This isn't one of MapInfo's standard algorithms, so (unless I'm missing 
something obvious) the task is not trivial.  It could be done by looping 
through the nodes in the polyline using MapBasic code and doing some math 
-- find the line that is perpendicular to the given line segment and 
passes through each point that you're trying to move; check and see if the 
intersection point actually falls on the line segment; if so, put the 
point there.  Otherwise, move on to the next line segment.  You might need 
to check that the same point can't be moved a shorter distance to fall 
onto another line segment that you haven't looked at yet..

Some points won't show up on any line segment with this method -- e.g. 
points diagonally outside the corners of squares -- so you might take a 
second pass through and move all 'unclaimed' points to the nearest node on 
the polyline.  That would take care of all the cases pretty well, I think.

--------------------------------------

A method that would avoid some of the math (but still requires MapBasic, 
of course, for the looping structures) would be to use the CreateCircle() 
or Buffer() functions to create a circle around each point -- the radius 
being the distance that you're searching with.  Then use Overlap() to 
return the part of the polyline that the circle overlaps.

If a polyline with only two nodes is returned, you can average the 
coordinates of the two ends of the line to get the location on the line 
closest to the point!  In MapBasic this would use ObjectInfo(), 
ObjectNodeX(), and ObjectNodeY().  If a discontinuous polyline (several 
separate segments with two nodes each) is returned, calculate the center 
of each line segment, then pick the one whose Distance() is closest to the 
point in question.

If a segment in the polyline returned by Overlap() contains more than two 
nodes, though, you'll need to create another circle with a smaller radius 
and try the above method again -- a binary search will get you down to a 
very small overlap area pretty quickly.  You could calculate distances to 
each node in the returned polyline, then subtract a smidgen -- and use 
_that_ distance as your revised buffer/circle distance.  If the node you 
have found is _not_ the closest point, then this new circle will still 
overlap the polyline -- but it will probably overlap by a much smaller 
margin.  If there is no overlap, you've found your closest point.

Alternatively -- if you don't require that the point be moved to the 
line_exactly_ at right angles -- simply pick the node in the returned 
polyline that is the shortest Distance() from the point in question.

Recursively applying the above rough algorithm should find the correct 
location pretty quickly.


Dave G.
MapInfo Technical Support
(518) 285-7283
[EMAIL PROTECTED]
MapInfo Products Knowledgebase:
http://testdrive.mapinfo.com/kbase_by_product

Reply via email to