Get closest value?

I have a map and its build where i have
some mapblocks that holds Image,size,x,y and more
and when i press form i get my MouseX,MouseY
and now i need to get what Block im closest to:
if i have blocks with values: 1,14,23,99 and i have value
15 how do i get what block im closest to? becuse a case of would suck..

LVL 2
brainwareAsked:
Who is Participating?
 
mirek071497Commented:
Ohh - mayby you need only the algorithm which say what line is the nearest ?
so no easiest question ! ;)

look here.
You have line segment from point A1(ax1,ay1) to point B1(bx1,bx2)
first you must find the line for this points.
I think so you can use line equation like this :
y := a1*x+b1

so you must compute the a1 and b1

a1 := (by1-ay1)/(bx1-ax1)
b1 := ay1 - ax1*(by1-ay1)/(bx1-ax1)

now you must find line which is perpendicular to this one. Ok this line is :

y := -a1*x +b2

You don't know the b2, but the line need to go throught your point X1,Y1

so you can compute the b2 and :

b2 := Y1+a1*X1

now you must find the point of intersection of this lines. Nothing easiest.You must find Point X0,Y0 which is in both lines.
so you have

X0 := (X1-b1+Y1*a1)/(2*a1)
Y0 := (X1-b1+Y1*a1)/2 + b1

ok now we have 2 examples
1. the point X0.Y0 is on the line segment
2. the point X0.Y0 is outside the line segment

we must know at which example we are so you can easy check this, but for easiest way we can make an assumption so the ax1<bx1 and if not than you can check this on start of proc and than exchange points
In this assumption we have :

if (X0>ax1) and (X0<ax2) then point1 else point2;

so for point1 we need to calculate the length of the line segment from point X1,Y1 to point X0,Y0

the leght is l:= Sqrt((X1-X0)*(X1-X0)+(Y1-Y0)*(Y1-Y0));

for the second point2 we need calculate the distance between point X1.Y1 and points A1 and B1 and get the lowest value

so :
l1 := Sqrt((X1-ax1)*(X1-ax1)+(Y1-ay1)*(Y1-ay1));
l2 := Sqrt((X1-ax2)*(X1-ax2)+(Y1-ay2)*(Y1-ay2));
if l1<l2 then l := l1 else l := l2;

It is easy - right ? ;)

ok now we can prepare the final proc for getting the l

if ax1>ax2 then { exchange points - easy and I don't write this }
a1 := (by1-ay1)/(bx1-ax1);
b1 := ay1 - ax1*(by1-ay1)/(bx1-ax1);
X0 := (X1-b1+Y1*a1)/(2*a1);
Y0 := (X1-b1+Y1*a1)/2 + b1;
if (X0>ax1) and (X0<ax2) then
  begin
    l:= Sqrt((X1-X0)*(X1-X0)+(Y1-Y0)*(Y1-Y0));
  end
else
  begin
    l1 := Sqrt((X1-ax1)*(X1-ax1)+(Y1-ay1)*(Y1-ay1));
    l2 := Sqrt((X1-ax2)*(X1-ax2)+(Y1-ay2)*(Y1-ay2));
    if l1<l2 then l := l1 else l := l2;
  end;

this is all, however you must trap examples when the a := 0 ! because in this examples you can get devide by 0 error !

Regards
mirek.
0
 
mirek071497Commented:
Hmmm - this is bigger problem than you probably think.
I was write some years ago map program and I have the same problem.
I was resolve this in that way :
1.first I made a list of polygons which contains the block.
2.if list is niil then I return the polygon which contain line which is nearest to my point.
3. if list is not nill than I was mady some different algorithm which depends on the additional layer parameters, however in global idea you must find the polygon which countain the nearest line to your point.

The problem is however bigger - why ? ok
You probably have big map and you can't compare to each line !
I was solve this by deviding the whole map to smalest squares and I first finding square for my point and then from list of objects which is assigned to the square I was create the search described later.
0
 
viktornetCommented:
Here is something I just wrote, but you try it since I haven't tried it on Delphi.////

function GetClosestRect ( x1, y1, x2, y2, Pt : TPoint ) : boolean;
begin
  Result := ( Pt.x > x1 ) and ( Pt.y > y1 ) and ( Pt.x < x2 ) and ( Pt.y < y2 );  
end;

Example Call:
var
  MyRect : TRect;
begin
  if GetClosestRect( 1, 14, 23, 99, 15 ) then//15 is the point you want to check is closest..
    MyRect := Rect(1, 14, 23, 99);
end;

You can create same procedure but using a TRect type instead of x1,y1,x2,y2......

Hope this helps....

Regards,
Viktor Ivanov
0
Introducing Cloud Class® training courses

Tech changes fast. You can learn faster. That’s why we’re bringing professional training courses to Experts Exchange. With a subscription, you can access all the Cloud Class® courses to expand your education, prep for certifications, and get top-notch instructions.

 
viktornetCommented:
A very easy way is to do what you want is to use the function PtInRect()

if PtInRect(Rect, Point) then
  MyRect := Rect;

Regards,
Viktor Ivanov

0
 
mirek071497Commented:
Yes -victornet, but what when the point is outside rect ? ;)
0
 
viktornetCommented:
Not exactly sure,....maybe your solution is better..but here is something he might try......this is only for the width,,,,you do it for both width and height...

var
  Rect, MyRect : TRect;
  pt : TPoint;
  i : Integer;
begin
  GetCursorPos(pt);
  for i := 0 to (Width div Rect.Right) do
  begin
    Rect :=Rect (i*Rect.Right, 0, (i*Rect.Right)+Rect.Right, 100);
    if PtInRect(Rect, pt) then
      MyRect := Rect;
  end;
end;

0
 
mirek071497Commented:
so you say that the brainware need to try with many rect to see if the other point is in the rect ?!!!!
0
 
viktornetCommented:
Not exactly...What I say is that you way is an original way to do that, and he is suppose to use yours, but he can try mine as well if he wants to... Just trying to give other pointers....he might learn something new from other example ;-)

Regards,
Viktor Ivanov
0
 
brainwareAuthor Commented:
Not what i was looking for..
But i got help from SPACEBRAIN that was so nice to drop by my home.
Whatever i think you 100% mis-understod question..

I wanted to check what value that was closest, but found a new way insted..

0
 
mirek071497Commented:

so what you was asking for ? I can't understand :( and why you accept my answe ?
0
 
brainwareAuthor Commented:
I acepted it, so if u where some points wanting #"/)" as mabye not..
i would not get my head pulled off...

But ill save the code and try it out, it looks like somthing that was worth this anyway..

So Thanks anyway.. .) I think i can use it for other purpose.

Mvh.
Michael V. Andersen
0
 
brainwareAuthor Commented:
Old Question but anyway.. what i tryed to do was get Block that was Clicked on in game-map, i was properly tired :))

whatever you algo is nice tho.. understand it and already know where i can use it :))
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.