Thanks to Joe Moore, Chris Perry and Mark Ogilvie for their responses.
I settled on the approach sugested by Mark.  

For those interested I have included the function implemented in my program
which is as follows: (Note I have an error trapping routine in the main
program in case no liniear objects are found within the upper tolerance
range)

Function calc(ByVal X as float,ByVal Y as Float,ByVal UpTol as float,ByVal
LowTol as float, ByVal RoadTab as String) as object
        'This Function takes a coordinate set and a table name and returns a
point object 
        'that is closest (or very near to) the closest point on the nearest
polyline.
        'Parameters passed are:
        'X              x (east)  coordinate of point
        'Y              y (north) coordinate of point
        'UpTol          Maximum distance to search from X,Y to find polyline
object
        'LowTol         Minimum tolerance to use to find nearest object
before accepting the first object
        '               this is required in-case there are two or more
objects exactly the same distance
        '               which could occur if X,Y corresponds to the
intersection of teo lines
        'RoadTab        The name of the polyline table to 'snap' the point
X,Y point too.

        Dim SearchArea,fndObj,LinObj as object
        Dim SearchRadius,SearchUp,SearchDown as Float
        dim fndline,fndnode,curline,curnode as integer
        Dim d2node,CurDist,xObj,yObj as float
        Dim NotFound as logical

        NotFound = False
        SearchUp = UpTol
        SearchDown = 0
        SearchRadius = SearchUp-2*(LowTol)
        Do
                SearchArea = converttoregion(CreateCircle(X,Y,SearchRadius))
                Select * from RoadTab where object intersects SearchArea
into fnd noselect
                do case tableinfo(fnd,tab_info_nrows)
                        case 0 'increase search radius
                                if SearchRadius=SearchUp then
                                        NotFound = True
                                        exit do
                                end if
                                SearchDown = SearchRadius
                                SearchRadius = (SearchUp+SearchDown)/2
                        Case 1 'one object found so keep going until within
tolerance exist 
                                while loop
                                        if abs(SearchRadius-SearchUp) <
LowTol then
                                                Exit Do
                                        else
                                                searchUp = SearchRadius
                                                SearchRadius =
(SearchUp+SearchDown)/2
                                        end if
                        case else 'multiple selection so decrease search
radius
                                if abs(SearchRadius-SearchUp) < LowTol then
                                        'if all are within tolerance then
exit and use first object
                                        exit do
                                end if
                                searchUp = SearchRadius
                                SearchRadius = (SearchUp+SearchDown)/2
                end case
        Loop 
        If Not NotFound then
                Fetch first from fnd
                LinObj = Converttopline(Fnd.obj)
                FndObj = IntersectNodes ( SearchArea,LinObj,INCL_CROSSINGS)
                xObj = ObjectNodeX(FndObj,1,1)
                yObj = ObjectNodeY(FndObj,1,1)
                Create point into variable fndobj (xObj,yObj)
                Calc = FndObj   
        End if
End Function

*************************  Original question and reponses follow
***********************************
My original question was:

I have a problem that I have been trying to get my head around and I hope
that someone out there has done  similar thing.

I have a series of point features (bus stops) that I would like to snap to
the nearest linear object (road centrelines) in another table.

I can identify the closest road but want to be able to determine where on
the polyline is the closest point to the bus stop so that I can shift the
bus stop object to lie exactly on the road centreline (not just snap to the
nearest node).

I hope this makes sense!

Any ideas??
----------------------------------------------------------------------------
---------------------

In reponse:

Joe Moore Wrote:

Hi Martin,

Funny you should ask, I actually wrote this in MapBasic. Unfortunatly, the
code is archived and it is difficult for me to get at. If you need the
actual code let know and I will get it. Here's the gist of how to do it...

Given points x1,y1,x2,y2 which make your closest street
             x3,y3       which is the off-street point

deltaY = y2-y1
deltaX = X2-X1

xAnswer = deltaX * deltaY (y3 - y1) + (deltaX * deltaX) * x3 + (deltaY *
deltaY) * x1
xAnswer = xAnswer / (deltaY * deltaY) + (deltaX * deltaX)
yAnswer = ((deltaY / deltaX) * xAnswer) + y1 - ((deltaY / deltaX) * x1)

Simple, yes! The concept is that you know the slope of the closest line.
You know the place that the point is closest to the line is at a line
perpendicular to the line. Just find the perpendicular line that goes
through your bus stop.

WARNINGS!!!!
You need to do special cases if deltaX or deltaY are zero (horizontal or
vertical lines) these cases are easy though, since you know that every
point on a horizontal line has the same X.

Watch out for cases where it is impossible to draw a perpendicular line
through the closest street and the point.

There will be rounding errors, but they should be minimal.


Here's the funny part... I wrote this to put school bus stops on a center
line :-)


Good luck, and I'll be happy to get that code for you if you need it.

Joe Moore
----------------------------------------------------------------------------
---------------------
Chris Perry Wrote:

        Martin,

        I'm sure there is a more sophisticated answer, but if you use the
all2pts to
        convert the polylines to nodes, then use SQL to select the points
within a
        buffer of the original bus stop. The list of points selected will be
in
        order closest - farthest.

        Hope this helps

        Chris Perry
        Manager Mapping Systems
        Parks Victoria
        Melbourne Australia
        Ph: 613 9816 6800
        Fax: 613 9816 7222
        [EMAIL PROTECTED]

----------------------------------------------------------------------------
---------------------
        Mark Ogilvie wrote:


        I have done something very like this. Although I don't have the
MapBasic
        code here right now (and you would probably have to heavily adapt it
for
        your particular situation anyway), here's the logic I used. By the
way, I
        wrote this programme for another upper North Island District
Council. I work
        for Compudigm (a NZ GIS consulting company based in Wellington), and
we did
        it under contract to the council. I guess if you wanted to you may
be able
        to arrange with either the council or maybe Compudigm to get the
code.

        1: Draw/construct a small (1m?) circle around the bus stop. If the
circle
        doesn't intersect the road at more than one point draw a bigger
circle. Keep
        drawing bigger circles (up to a maximum, say 50m?) until you find a
circle
        that intersects the road at two or more points.

        2: Take the two intersection points and construct a line between
them. This
        line is either parallel or very nearly parallel to the road.

        3: Construct the perpendicular bisector to this line. This line will
cut the
        road at a point *very* nearly the closest point to the bus stop. To
retrieve
        that point you will probably need to turn the perp_bisector into a
really
        long line (e.g. 50km) and close it off in a large triangle-shaped
region, so
        you can use IntersectNodes to determine the intersection point.

        4: You now have a point on the road, either the nearest point or
very close
        to the nearest point to the bus stop. If you want to shift this
point to the
        nearest node, that's reasonably straight forward, but I can't
remember
        exactly how I did it now.

        As usual, a good part of the work (half?) was in building the
        semi-intelligent user interface, tuned to the client's work process,
around
        the core engine which did all the work.


        Cheers
        Mark Ogilvie


Thanks again to all that helped.

===================================
Martin Roundill
GIS Manager
Waitakere City Council
Private Bag 93109
Henderson
Waitakere City
New Zealand
Ph +64 9 836 8000 ext 8344
Fax +64 9 836 8001
email [EMAIL PROTECTED]
===================================


----------------------------------------------------------------------
To unsubscribe from this list, send e-mail to [EMAIL PROTECTED] and put
"unsubscribe MAPINFO-L" in the message body, or contact [EMAIL PROTECTED]

Reply via email to