Arcobjects: set measures based on the polyline length

149 Views Asked by At

I am currently linear referencing a set of roads. Using IMSegmatation2.SetMsAsDistance2 works fine for single-part polylines but for multi-part polylines I want to set the M values as the length along the polyline to the point, not the shortest distance between the point and the start point of the polyline. The SetMsAsDistance2 function sets the Measures on parallel lines as equal. I want them to be different.

Apart from setting an M value for each polyline vertex does anyone know of a method that sets the M as the length along the polyline?

1

There are 1 best solutions below

0
On

The solution is to use the IMSegmentation3.SetAndInterpolateMsBetween function. Note that the solution assumes that the geometries that make up the feature are in the right order. It assigns measures geometry-by-geometry.

The code for this is:

    public static void measuresAdd_NonDuplicating(ref IFeature pFeat, bool bHasZ, bool bIgnoreGaps, out string sError)
    {
        // Add non-duplicating measures to the feature
        sError = "";
        IMSegmentation3 pSeg;
        IGeometryCollection pGeomColl;
        //IGeometryCollection pNewGeomColl; // Use if geometries are to be re-ordered.
        IGeometry pGeom;
        IPolyline4 pPoly;
        IQueryFilter pQ;
        IMAware pMAware;
        IZAware pZAware;
        double dStartMeasure;
        double dToMeasure;
        double dMeasure;
        double dLen;

        try
        {


                if (pFeat.ShapeCopy.IsEmpty == false)
                {
                    pGeomColl = (IGeometryCollection)new PolylineClass();
                    pGeomColl = (IGeometryCollection)pFeat.ShapeCopy;
                    if (pGeomColl.GeometryCount == 1)
                    {
                        // Single line geometry. Duplication not an issue.
                        pMAware = (IMAware)pFeat.ShapeCopy;
                        pMAware.MAware = true;
                        pSeg = (IMSegmentation3)pMAware;
                        pPoly = geometryToPolyline((IGeometry)pFeat.ShapeCopy, out sError);
                        if (sError.Length > 0)
                        {
                            sError = "measuresAdd_NonDuplicating\r\n" + sError;
                            return;
                        }
                        pSeg.SetMsAsDistance2(pPoly.FromPoint, 1, 0, bIgnoreGaps);
                        pFeat.Shape = (IGeometry)pSeg;
                        pFeat.Store();
                    }
                    else
                    {
                        // For re-ordering geometries. Not currently used.
                        //pNewGeomColl = (IGeometryCollection)new Polyline();
                        //IZAware pZawareNew = (IZAware)pNewGeomColl;
                        //pZawareNew.ZAware = bHasZ;
                        //IMAware pMAwareNew = (IMAware)pNewGeomColl;
                        //pMAwareNew.MAware = true;

                        dStartMeasure = 0;
                        dMeasure = 0;
                        // MultiGeometry. Place them in order and set the measures on each part increasing.
                        // Currently assumes the existing order is correct.
                        for (int i = 0; i < pGeomColl.GeometryCount; i++)
                        {
                            pGeom = pGeomColl.Geometry[i];

                            pPoly = geometryToPolyline(pGeom, out sError);
                            if (sError.Length > 0)
                            {
                                sError = "measuresAdd_NonDuplicating\r\n" + sError;
                                return;
                            }
                            // Measure Values
                            dStartMeasure = dMeasure;
                            if (i > 0) dStartMeasure += 0.01;
                            dLen = pPoly.Length;
                            dToMeasure = dMeasure + dLen;
                            // Set Measures
                            pMAware = (IMAware)pPoly;
                            pMAware.MAware = true;
                            pZAware = (IZAware)pPoly;
                            pZAware.ZAware = bHasZ;
                            pSeg = (IMSegmentation3)pPoly;
                            pSeg.SetAndInterpolateMsBetween(dStartMeasure, dToMeasure);

                            // If geometries are re-ordered into a connecting network
                            //IGeometryCollection pXGeomColl = new PolylineClass();
                            //pMAware = (IMAware)pXGeomColl;
                            //pMAware.MAware = true;
                            //pZAware = (IZAware)pXGeomColl;
                            //pZAware.ZAware = bHasZ;
                            //pXGeomColl = (IGeometryCollection)pPoly;
                            //for (int j = 0; j < pXGeomColl.GeometryCount; j++)
                            //    pNewGeomColl.AddGeometry(pXGeomColl.Geometry[j]);

                            dMeasure += dLen;

                        }

                        pFeat.Shape = (IGeometry)pGeomColl;
                    }
            }

        }
        catch (Exception ex)
        {
            System.Diagnostics.StackTrace pStack = new System.Diagnostics.StackTrace(ex, true);
            System.Diagnostics.StackFrame pFrame = pStack.GetFrame(pStack.FrameCount - 1);
            int iLineNo = pFrame.GetFileLineNumber();

            sError = "ERROR: measuresAdd_NonDuplicating; Line: " + iLineNo + "\n" + ex.ToString();
        }


    }