0

ArcObjects with ArcGis 10.1

I have constructed a polyline in WGS84 that has straight segments and curved segments. The line is heavily geodesically densified. Now I have to step through every 100 meters and perform additionally calculations at these points.

IConstructPoint.ConstructAlong looks promising but the distance is spat ref units which for WGS84 is degrees so that rules that out.

The best I have been able to do is as follows: Step through every vertex in the line (which is way more than needed) and:

1. use IPolyline.QueryPointAndDistance to get the distance along the line in spat ref units.
2. Get a subcurve at that distance using IPolycurve2.GetSubcurve
3. Finally use IGeometryServer3.GetLengthsGeodesic of the subcurve to get the length in meters.

Seems like a lot of overhead. There must be a way to get a point every x meters along the line. Most of the functions I have looked at are based on length in spat ref units which is not what I am looking for.

Applicable code is as follows:

Dim pntAlongLine As IPoint = New Point
Dim distAlongLineToPnt As Double = 0, distFromPntToLine As Double = 0, IsToRightOfLine As Boolean
pPolyline.QueryPointAndDistance(esriSegmentExtension.esriNoExtension, pntOnLine, False, pntAlongLine, distAlongLineToPnt, distFromPntToLine, IsToRightOfLine)

'get a subcurve
Dim pPolyCurve As IPolycurve2 = CType(pPolyline, IPolycurve2)
Dim outCurve As ICurve = Nothing
pPolyCurve.GetSubcurve(0, distAlongLineToPnt, False, outCurve)

'create a polyline array with one element
Dim pPolylineArray As IPolylineArray = New PolylineArray
pPolylineArray.Add(pPolyline)

'create a linear meter unit
Dim pSpatRefFact As New SpatialReferenceEnvironment
Dim pLinearUnitMeters As ILinearUnit = CType(pSpatRefFact.CreateUnit(esriSRUnitType.esriSRUnit_Meter), ILinearUnit)

'setup a Geometry server
Dim pGeometryServer As IGeometryServer3 = CType(New GeometryServer, IGeometryServer3)
Dim pDoubleArray As IDoubleArray
pDoubleArray = pGeometryServer.GetLengthsGeodesic(pSpatRef, pPolylineArray, pLinearUnitMeters)

'the reference array will have geodesic distances for each polyline. in this case we passed in only one line.
distInMeters = pDoubleArray.Element(0)

This code is dependent on each vertex in the line but what I would really like is a point every 100 meters along the line.

  • Is project first an option? – FelixIP Sep 18 '17 at 1:09
  • Rather than a numbered list, can you present a code snippet that can more precisely illustrate what you have tried and where you are stuck, please? – PolyGeo Sep 18 '17 at 1:13
  • I added my code. – sinDizzy Sep 18 '17 at 1:48
  • 2
    To construct a point in metres the linear unit must be metres, simply project the polyline to a suitable projected coordinate system (in memory) construct your point(s) with IConstructPoint.ConstructAlong, project the point(s) to WGS84 and discard the projected polyline. – Michael Stimson Sep 18 '17 at 2:26
  • Let me ask the follow-up. What would be a suitable projected spatial reference? The polyline can be anywhere in the world, but length max is in the neighborhood of ~25NM. – sinDizzy Sep 18 '17 at 14:32
0

Solution: As suggested by several folks I reprojected the polyline to a spatial reference with meters as map units. I chose Azimuthal Equidistant.

            'create a World Azimuthal Equidistant spatial reference.
            Dim pProjCsTemp As IProjectedCoordinateSystem = pSpatRefFact.CreateProjectedCoordinateSystem(esriSRProjCSType.esriSRProjCS_World_AzimuthalEquidistant)
            Dim pProjCs As IProjectedCoordinateSystem4 = CType(pProjCsTemp, IProjectedCoordinateSystem4)
            Dim pSpatRefAzEq As ISpatialReference3 = CType(pProjCs, ISpatialReference3)
            If pProjCs.CoordinateUnit.Name <> pLinearUnitMeters.Name Then
                Throw New Exception("The unit of the Projected Coordinate System is not meters.")
            End If

            'make a clone of the main polyline and then project it to Azimuthal Equidistan. set projection parameters to center of polyline.
            Dim pClone As IClone = CType(pPolyline, IClone)
            Dim pCloneLine As IPolyline = CType(pClone.Clone, IPolyline)
            Dim pGeom As IGeometry = pCloneLine
            Dim pEnv As IEnvelope = pGeom.Envelope

            Dim centLon As Double = (pEnv.XMin + pEnv.XMax) / 2
            pProjCs.CentralMeridian(True) = centLon
            Dim centLat As Double = (pEnv.YMin + pEnv.YMax) / 2
            pProjCs.LatitudeOfOrigin = centLat

            'tell the projected coordinate system that it has changed.
            pProjCs.Changed()

            pCloneLine.Project(pSpatRefAzEq)

Now I can use IConstructPoint with map units of meters as needed:

            'a point on the line. we use the cloned line since we can use meters in the Azimuthal Equidistant projection.
            Dim pCPoint As IConstructPoint = New Point
            pCPoint.ConstructAlong(pCloneLine, esriSegmentExtension.esriNoExtension, distAlongInMeters, False)
            Dim pPointCtrlAlongC As IPoint = CType(pCPoint, IPoint)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.