ArcGIS Engine – How to Get Part of Polyline Based on Two Points

arcgis-10.0arcgis-enginenetpolyline-creation

Currently I have a layer with polylines; in another layer, I allowed the user to create 2 points on the polyline.

I want to know if there is a function for the polyline feature that I can use to get the clipped portion of the polyline based on the 2 user-added points. Thanks.

Best Answer

enter image description here

The testmethod only works with arcmap, but the other methods should work with arcengine.

private void TestGetsubCurve()
{
    IPoint pnt1 = null;
    IPoint pnt2 = null;
    IPolyline polyLine = null;
    var gc = ArcMap.Document.FocusMap as IGraphicsContainer;
    gc.Reset();
    IElement elem;
    while((elem = gc.Next())!= null)
    {
        if (elem.Geometry is IPoint && pnt1 == null)
            pnt1 = elem.Geometry as IPoint;
        else if (elem.Geometry is IPoint && pnt2 == null)
            pnt2 = elem.Geometry as IPoint;
        else if (elem.Geometry is IPolyline)
            polyLine = elem.Geometry as IPolyline;
    }
    if (pnt1 == null || pnt2 == null || polyLine == null)
    {
        Debug.Print("missing some geometry");
        return;
    }
    var subCurve = GetSubCurve(polyLine, pnt1, pnt2);
    elem = new LineElementClass();
    ((ILineElement)elem).Symbol = ((IDocumentDefaultSymbols)ArcMap.Document).LineSymbol;
    elem.Geometry = subCurve;
    gc.AddElement(elem, 0);
    ((IActiveView)ArcMap.Document.FocusMap).Refresh();
}

private IPolyline GetSubCurve(IPolyline inpolyLine, IPoint pnt1, IPoint pnt2)
{
    double d1 = GetDistAlong(inpolyLine,pnt1);
    double d2 = GetDistAlong(inpolyLine, pnt2);

    var c = inpolyLine as ICurve;
    ICurve outCurve;
    c.GetSubcurve(d1, d2, false, out outCurve);
    if (c == null || c.IsEmpty)
        throw new Exception("unable to get subcurve");
    var outPolyline = outCurve as IPolyline;
    if (outPolyline == null)
    {
        // this didn't happen in testing, but one never knows ...
        outPolyline = new PolylineClass() as IPolyline;
        var sc = outPolyline as ISegmentCollection;
        sc.AddSegment((ISegment)outCurve);
        ((IGeometry)sc).SpatialReference = outCurve.SpatialReference;
    }
    return outPolyline;
}

private double GetDistAlong(IPolyline polyLine, IPoint pnt)
{
    var outPnt = new PointClass() as IPoint;
    double distAlong = double.NaN;
    double distFrom = double.NaN;
    bool bRight = false;
    polyLine.QueryPointAndDistance(esriSegmentExtension.esriNoExtension, pnt, false, outPnt,
        ref distAlong, ref distFrom, ref bRight);
    return distAlong;
}