Pages: [1] 2
  Print  
Author Topic: distance_to_object  (Read 2703 times)
Offline (Male) RetroX
Posted on: December 20, 2010, 09:02:53 PM

Master of all things Linux
Contributor
Location: US
Joined: Apr 2008
Posts: 1055
MSN Messenger - classixretrox@gmail.com
View Profile Email
Code: [Select]
#include <limits>
double distance_to_object_point(int object)
{
  enigma::object_collisions* const inst1 = ((enigma::object_collisions*)enigma::instance_event_iterator->inst);
  double distance = std::numeric_limits<double>::infinity();
  double tempdist;
  for (enigma::inst_iter *it = enigma::fetch_inst_iter_by_int(object); it != NULL; it = it->next)
  {
    const enigma::object_collisions* inst2 = (enigma::object_collisions*)it->inst;
    if (inst1 == inst2) continue;
    tempdist = point_distance(inst1->x, inst1->y, inst2->x, inst2->y);
    if (tempdist < distance)
    {
      distance = tempdist;
    }
  }
  return (distance == std::numeric_limits<double>::infinity() ? 0 : distance);
}

inline double dist_ranges(double left1, double right1, double left2, double right2)
{
double right = min(right1, right2), left = max(left1, left2);
return (left > right ? left - right : 0);
}

double distance_to_object_bbox(int object)
{
  enigma::object_collisions* const inst1 = ((enigma::object_collisions*)enigma::instance_event_iterator->inst);
  const double left1  = inst1->x + inst1->bbox_left,  top1    = inst1->y + inst1->bbox_top,
               right1 = inst1->x + inst1->bbox_right, bottom1 = inst1->y + inst1->bbox_bottom;
  double distance = std::numeric_limits<double>::infinity();
  double tempdist;
  for (enigma::inst_iter *it = enigma::fetch_inst_iter_by_int(object); it != NULL; it = it->next)
  {
    const enigma::object_collisions* inst2 = (enigma::object_collisions*)it->inst;
    if (inst1 == inst2) continue;
const double left2  = inst2->x + inst1->bbox_left,  top2    = inst2->y + inst1->bbox_top,
right2 = inst2->x + inst1->bbox_right, bottom2 = inst2->y + inst1->bbox_bottom;
    tempdist = hypot(dist_ranges(left1, right1, left2, right2),
                     dist_ranges(top1, bottom1, top2, bottom2));
    if (tempdist < distance)
    {
      distance = tempdist;
    }
  }
  return (distance == std::numeric_limits<double>::infinity() ? 0 : distance);
}

Tested and both work.  I don't know which method that GM uses, but here's two different algorithms.
« Last Edit: December 25, 2010, 10:54:31 AM by RetroX » Logged
My Box: Phenom II 3.4GHz X4 | ASUS ATI RadeonHD 5770, 1GB GDDR5 RAM | 1x4GB DDR3 SRAM | Arch Linux, x86_64 (Cube) / Windows 7 x64 (Blob)
Quote from: Fede-lasse
Why do all the pro-Microsoft people have troll avatars? :(
Post made December 22, 2010, 06:33:33 AM was deleted at the author's request.
Offline (Male) RetroX
Reply #2 Posted on: December 23, 2010, 02:41:32 PM

Master of all things Linux
Contributor
Location: US
Joined: Apr 2008
Posts: 1055
MSN Messenger - classixretrox@gmail.com
View Profile Email
Was it in C++ or GML?
Logged
My Box: Phenom II 3.4GHz X4 | ASUS ATI RadeonHD 5770, 1GB GDDR5 RAM | 1x4GB DDR3 SRAM | Arch Linux, x86_64 (Cube) / Windows 7 x64 (Blob)
Quote from: Fede-lasse
Why do all the pro-Microsoft people have troll avatars? :(
Offline (Male) Josh @ Dreamland
Reply #3 Posted on: December 23, 2010, 09:51:47 PM

Prince of all Goldfish
Developer
Location: Ohio, United States
Joined: Feb 2008
Posts: 2946

View Profile Email
Issue is, I don't know what GM does either. It does compensate for something like a bbox, but I'm not sure if it calculates the distance between the closest two points in the entirety of either mask, or if it calculates the distance between those along a straight line, or if it just defaults to bbox (which would be the only reasonable method), and if in that case it uses a rotated bbox or just a standard one... I'm in the dark on it. But I might accept Retro's bottom function. Provided, of course, that dist_ranges be made inline or into a macro.
Logged
"That is the single most cryptic piece of code I have ever seen." -Master PobbleWobble
"I disapprove of what you say, but I will defend to the death your right to say it." -Evelyn Beatrice Hall, Friends of Voltaire
Post made December 24, 2010, 01:41:27 PM was deleted at the author's request.
Offline (Male) RetroX
Reply #5 Posted on: December 25, 2010, 10:54:22 AM

Master of all things Linux
Contributor
Location: US
Joined: Apr 2008
Posts: 1055
MSN Messenger - classixretrox@gmail.com
View Profile Email
But I might accept Retro's bottom function. Provided, of course, that dist_ranges be made inline or into a macro.
I honestly don't know why I didn't make it inline.  I was probably rushing.  If you're going to use the bottom method, I'd still keep both labeled.
Code: [Select]
#define distance_to_object(x) distance_to_object_point(x)or
Code: [Select]
inline double distance_to_object(int object) { return distance_to_object_point(object); }
« Last Edit: December 25, 2010, 10:56:41 AM by RetroX » Logged
My Box: Phenom II 3.4GHz X4 | ASUS ATI RadeonHD 5770, 1GB GDDR5 RAM | 1x4GB DDR3 SRAM | Arch Linux, x86_64 (Cube) / Windows 7 x64 (Blob)
Quote from: Fede-lasse
Why do all the pro-Microsoft people have troll avatars? :(
Offline (Female) IsmAvatar
Reply #6 Posted on: December 26, 2010, 01:43:56 PM

LateralGM Developer
LGM Developer
Location: Pennsylvania/USA
Joined: Apr 2008
Posts: 891

View Profile Email
I'm pretty sure with() just gets converted into the iterator, so there's no speed benefit one way or the other.
Logged
Offline (Male) polygone
Reply #7 Posted on: December 26, 2010, 01:46:45 PM

Contributor
Location: England
Joined: Mar 2009
Posts: 809

View Profile
Thought that was probably the case, was just wondering why Retro looped through instead of using the with statement. So thought it might be due to speed.
« Last Edit: December 26, 2010, 01:52:22 PM by polygone » Logged
I honestly don't know wtf I'm talking about but hopefully I can muddle my way through.
Post made December 26, 2010, 01:51:05 PM was deleted at the author's request.
Offline (Female) IsmAvatar
Reply #9 Posted on: December 26, 2010, 01:56:36 PM

LateralGM Developer
LGM Developer
Location: Pennsylvania/USA
Joined: Apr 2008
Posts: 891

View Profile Email
For low-level functions that intend to go into the back-end, it's not uncommon for people to use straight C++ rather than EDL.
Logged
Offline (Male) polygone
Reply #10 Posted on: December 26, 2010, 02:00:05 PM

Contributor
Location: England
Joined: Mar 2009
Posts: 809

View Profile
OK I'll keep that in mind.
Logged
I honestly don't know wtf I'm talking about but hopefully I can muddle my way through.
Offline (Male) Josh @ Dreamland
Reply #11 Posted on: December 26, 2010, 06:16:01 PM

Prince of all Goldfish
Developer
Location: Ohio, United States
Joined: Feb 2008
Posts: 2946

View Profile Email
Not to mention, enigma::fetch_inst_iter_by_int(object) is literally as efficient as can be. It is, in fact, the function that composes with(). It is set up such that there is no way to make it any faster; the iterator it returns accounts for all aspects of instance iteration, including ID, object index with heredity, and keywords such as all, other, or noone.
Logged
"That is the single most cryptic piece of code I have ever seen." -Master PobbleWobble
"I disapprove of what you say, but I will defend to the death your right to say it." -Evelyn Beatrice Hall, Friends of Voltaire
Offline (Male) RetroX
Reply #12 Posted on: December 27, 2010, 06:06:53 PM

Master of all things Linux
Contributor
Location: US
Joined: Apr 2008
Posts: 1055
MSN Messenger - classixretrox@gmail.com
View Profile Email
Updated code:

Code: [Select]
/* ********************* */
// Place this in some math header or something.
inline double range_difference(double left1, double right1, double left2, double right2)
{
double right = min(right1, right2), left = max(left1, left2);
return (left > right ? left - right : 0);
}
/* ********************* */


#include <limits>

double distance_to_object_point(int object)
{
  enigma::object_collisions* const inst1 = ((enigma::object_collisions*)enigma::instance_event_iterator->inst);
  double distance = std::numeric_limits<double>::infinity();
  double tempdist;
  for (enigma::inst_iter *it = enigma::fetch_inst_iter_by_int(object); it != NULL; it = it->next)
  {
    const enigma::object_collisions* inst2 = (enigma::object_collisions*)it->inst;
    if (inst1 == inst2) continue;
    tempdist = point_distance(inst1->x, inst1->y, inst2->x, inst2->y);
    if (tempdist < distance)
    {
      distance = tempdist;
    }
  }
  return (distance == std::numeric_limits<double>::infinity() ? 0 : distance);
}

double distance_to_object_bbox(int object)
{
  enigma::object_collisions* const inst1 = ((enigma::object_collisions*)enigma::instance_event_iterator->inst);
  const double left1  = inst1->x + inst1->bbox_left,  top1    = inst1->y + inst1->bbox_top,
               right1 = inst1->x + inst1->bbox_right, bottom1 = inst1->y + inst1->bbox_bottom;
  double distance = std::numeric_limits<double>::infinity();
  double tempdist;
  for (enigma::inst_iter *it = enigma::fetch_inst_iter_by_int(object); it != NULL; it = it->next)
  {
    const enigma::object_collisions* inst2 = (enigma::object_collisions*)it->inst;
    if (inst1 == inst2) continue;
const double left2  = inst2->x + inst1->bbox_left,  top2    = inst2->y + inst1->bbox_top,
right2 = inst2->x + inst1->bbox_right, bottom2 = inst2->y + inst1->bbox_bottom;
    tempdist = hypot(range_difference(left1, right1, left2, right2),
                     range_difference(top1, bottom1, top2, bottom2));
    if (tempdist < distance)
    {
      distance = tempdist;
    }
  }
  return (distance == std::numeric_limits<double>::infinity() ? 0 : distance);
}


inline double distance_to_point_point(double x, double y)
{
  enigma::object_collisions* const inst1 = ((enigma::object_collisions*)enigma::instance_event_iterator->inst);
  return point_distance(inst1->x, inst1->y, x, y);
}

inline double distance_to_point_bbox(double x, double y)
{
  enigma::object_collisions* const inst1 = ((enigma::object_collisions*)enigma::instance_event_iterator->inst);
  const double left1  = inst1->x + inst1->bbox_left,  top1    = inst1->y + inst1->bbox_top,
               right1 = inst1->x + inst1->bbox_right, bottom1 = inst1->y + inst1->bbox_bottom;
  return hypot(abs(min(left1 - x, right1 -x),
               min(top1 - x, bottom1 -x)));
}


// Possible option in configuration to choose which method is used?
inline double distance_to_object(int object) { return distance_to_object_bbox(object); }
inline double distance_to_point(double x, double y) { return distance_to_point_bbox(x, y); }

I'm almost certain that someone will modify this before it's put into ENIGMA, but this is what I have.
« Last Edit: December 27, 2010, 10:48:11 PM by RetroX » Logged
My Box: Phenom II 3.4GHz X4 | ASUS ATI RadeonHD 5770, 1GB GDDR5 RAM | 1x4GB DDR3 SRAM | Arch Linux, x86_64 (Cube) / Windows 7 x64 (Blob)
Quote from: Fede-lasse
Why do all the pro-Microsoft people have troll avatars? :(
Offline (Female) IsmAvatar
Reply #13 Posted on: December 27, 2010, 06:18:57 PM

LateralGM Developer
LGM Developer
Location: Pennsylvania/USA
Joined: Apr 2008
Posts: 891

View Profile Email
If you make it complex enough and it works, nobody will bother touching it.
Logged
Offline (Male) polygone
Reply #14 Posted on: December 27, 2010, 06:46:35 PM

Contributor
Location: England
Joined: Mar 2009
Posts: 809

View Profile
I still prefer this:

Code: (EDL) [Select]
return (distance == std::numeric_limits<double>::infinity() ? -1 : distance);
Logged
I honestly don't know wtf I'm talking about but hopefully I can muddle my way through.
Pages: [1] 2
  Print