How to get a segment of a polyline at a certain location?

1759
5
Jump to solution
01-28-2014 02:57 PM
SuiHuang
Occasional Contributor II
Hi Everybody:

    Given a polyline and a point on it, how can I find the segment of that polyline on that point? I checked the ISegmentCollection interface but couldn't find a way to do it. How can I do it?

***********************************************
The reason I want to find the polyline segment for a given point
***********************************************
I am trying to write a function to decide whether a given 3D point feature is on a given 3D polyline feature. After making sure the point is exactly contained by the polyline, I want to allow some Z-coordinate tolerance, which is decided according to the segment length of the polyline at that location:
-- The segment is long, which means the distance between polyline vertices is large, then allow a larger tolerance
-- The segment is short, indicating closer distance between polyline vertices, then allow smaller tolerance

Is there alternative way different from finding the segment? I want to find the local vertex density instead of an overall one for a long polyline (which can be calculated by length divided by number of vertices).

    Thank you!
0 Kudos
1 Solution

Accepted Solutions
NeilClemmons
Regular Contributor III
Take a look at the IHitTest interface.  It can tell you if a point is on the line as well as the segment index of the segment in the line's segment collection.  If the line is multi-part, it will also tell you the part index in the line's geometry collection.

View solution in original post

0 Kudos
5 Replies
SuiHuang
Occasional Contributor II
A simple idea I have now is to enumerate through all the segments, but that doesn't seem to be efficient...
0 Kudos
RichardFairhurst
MVP Honored Contributor
If these were Routes you could get the measure of the point and find the segment that bounded that measure from the segment end point M values.  You would have to decide what rule you want to follow if the measure was on a vertex.

You also might be interested in my Add-On tool that can generate 3D route measures on a projected Polyline MZ feature class linked in this thread.  Just convert your lines to a new Polyline M Z feature class and the tool can assign the measures for you.  The Locate Features Along a Route tool can then create a measure event table from your points that would report the 3D distance traveled along the line.

My tool just walks through the ISegmentCollection interface to examine each segment's FromPoint or ToPoint (pSegment.FromPoint.X,.Y,.Z or pSegment.ToPoint.X,.Y,.Z) to derive and set the M values (pSegment.FromPoint.M or pSegment.ToPoint.M).  That is the interface I would use to find the segment the point fell on based on the M value of the point on the line and the M values at each segment end.

The ICurve.QueryPointAndDistance may also prove useful to get the 2D distance along the curve of the point and its interpolated M and Z values on the line.  The IMSegmentation interface may also be useful (GetMsAtDistance) if you go with this option.

If for some reason you ever need to set one of the coordinates on a segment follow this typical code snippet (you cannot set the coordinate directly to the segment without a temporary point object):

  pInPoint = New Point  ' Create a new point
  pInPoint.SpatialReference = pSpatialRef  ' Previously obtained Spatial Reference from input lines
  pInPoint = pSegment.ToPoint '  Set the new point to the point of interest from the segment
  pInPoint.M = distAlong  ' in other parts of my code distAlong keeps track of accumulated 3D distances along the line
  pSegment.ToPoint = pInPoint  ' replace the point of interest with the modified M coordinate
0 Kudos
RichardFairhurst
MVP Honored Contributor
Here is a code snippet to illustrate the basics of walking through the ISegmentCollection interface to modify the FromPoint of the segment end (VB.Net):

SegCount = pSegColl.SegmentCount
For j = 0 To SegCount - 1
  pSegment = pSegColl.Segment(j)
  pInPoint = New Point  'If you needed to modify the segment points do the next steps
  pInPoint.SpatialReference = pSpatialRef
  pInPoint = pSegment.FromPoint
  ' Do something with the segment point
  pSegment.FromPoint = pInPoint
  pSegColl.SegmentsChanged()  ' Send out Segment Changed Message event
  pInPoint = Nothing ' Clean up Point Object
Next j


If you are only reading the segments you can just examine the pSegment.FromPoint.X,.Y,.M, or .Z values directly instead of assigning them to a new point to modify them.
0 Kudos
NeilClemmons
Regular Contributor III
Take a look at the IHitTest interface.  It can tell you if a point is on the line as well as the segment index of the segment in the line's segment collection.  If the line is multi-part, it will also tell you the part index in the line's geometry collection.
0 Kudos
SuiHuang
Occasional Contributor II
Thank you! IHitTest interface works and I used it to find the segment.

Take a look at the IHitTest interface.  It can tell you if a point is on the line as well as the segment index of the segment in the line's segment collection.  If the line is multi-part, it will also tell you the part index in the line's geometry collection.
0 Kudos