how to split a polyline at its self intersection points

how to split a polyline at its self intersection points

Anonymous
Not applicable
9,844 Views
9 Replies
Message 1 of 10

how to split a polyline at its self intersection points

Anonymous
Not applicable

hi,

 

I'm trying to split a polyline that have some intersection points at its intersection points. So, if a polyline have two self intersection point, then it will become three different polyline. I attach the example of a polyline that I want to split. I wonder, does the get split curve method can help me to do this ? or any other idea how can I do this ?

 

I'm new to .net programming so I still don't know how some methods works

thanks

0 Likes
9,845 Views
9 Replies
Replies (9)
Message 2 of 10

adam.nagy
Autodesk Support
Autodesk Support

Hi,

 

Yes, GetSplitCurves() could be useful as it can split the polyline, however you have to provide the additional logic that will be able to turn the polyline you attached into 3 closed loop polylines. Depending on which vertex is the start/end point of the polyline you'll get different results.

 

Another thing that might be useful for you to know is that there is a boundary tracing function available since AutoCAD 2011. In AutoCAD 2011 only in the ARX API (I think), but in 2012 it is also available under Editor.TraceBoundary(). If you specify a point that fals inside a loop then it will give you the poly loop around that point. In previous versions you could use the -BOUNDARY command instead.

 

In both cases though first you'd probably have to figure out the intersection points. So you would need to iterate through each segment of the poly and try to intersect it with all the other segments. Depending on the return value of Polyline.GetSegmentType() you would need to call either GetLineSegmentAt or GetArcSegmentAt. These segments then provide an IntersectWith function that you can use.

 

I hope this helps.

 

Cheers,

Adam Nagy

Autodesk Developer Network 



Adam Nagy
Autodesk Platform Services
Message 3 of 10

Anonymous
Not applicable

hi,

 

yes, I found out that there is no simple way to do that, that I have to provide the additional logic to split the polyline

I'm still working on it

 

thanks for your answer !

 

0 Likes
Message 4 of 10

Anonymous
Not applicable

Thank Adam for the post.

0 Likes
Message 5 of 10

Anonymous
Not applicable

Hi

 

Did you find anything regarding your concers ?

 I have to do exact same. if possible can you share code.

 

Thanks in advanse.

0 Likes
Message 6 of 10

SENL1362
Advisor
Advisor

Simplified version, not tested for special types of intersections.

After splitting Create Region is added to show results.

 

 

        [CommandMethod("SPAI")]
        public static void SplitPolylineAtIntersection()
        {
            Document doc = null;
            Database db = null;
            Editor ed = null;


            try
            {
                doc = AcadApp.DocumentManager.MdiActiveDocument;
                if (doc == null)
                    throw new System.Exception("No MdiActiveDocument");
                db = doc.Database;
                ed = doc.Editor;

                var plPeo = new PromptEntityOptions("Select Poly");
                var per = ed.GetEntity(plPeo);
                if (per.Status != PromptStatus.OK)
                    return;
                var plId = per.ObjectId;




                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    var ms = (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForWrite);
                    var pl = tr.GetObject(plId, OpenMode.ForRead) as Polyline;

                    var plSegs = new DBObjectCollection();
                    pl.Explode(plSegs);

                    //Test each Poly Segment for intersection with the other segments.
                    //These segments will be splitted at the intersections and tested again
                    int i = -1;
                    while (++i < plSegs.Count)
                    {
                        var segi = plSegs[i] as Curve;
                        if (segi == null) continue;

                        int j = -1;
                        while (++j < plSegs.Count)
                        {
                            if (j == i) continue;
                            var segj = plSegs[j] as Curve;
                            if (segj == null) continue;

                            //Test Segment[i] against Segment[j]
                            Point3dCollection intsPnts = new Point3dCollection();
                            segi.IntersectWith(segj, Intersect.OnBothOperands, intsPnts, IntPtr.Zero, IntPtr.Zero);
                            if (intsPnts.Count > 0)
                            {
                                var splCurves = segi.GetSplitCurves(intsPnts);
                                if (splCurves.Count > 1)  //don't add curves splitted at the start or end
                                {
                                    foreach (DBObject splCurve in splCurves)
                                    {
                                        plSegs.Add(splCurve);
                                        //for testing purposes add segments to database
                                        ms.AppendEntity((Entity)splCurve);
                                        tr.AddNewlyCreatedDBObject(splCurve, true);
                                    }
                                    plSegs[i] = null;
                                    break; //exit while j, next i
                                }
                            }
                        }
                    }
                    pl.UpgradeOpen();
                    pl.Erase();

                    //for testing purposes add remaning segments to database
                    // add the not splitted segments to the Database
                    foreach (DBObject plseg in plSegs)
                    {
                        if (plseg == null) continue;
                        if (plseg.ObjectId.IsNull)
                        {
                            ms.AppendEntity((Entity)plseg);
                            tr.AddNewlyCreatedDBObject(plseg, true);
                        }
                    }

                    //Create regions from splitted segments
                    // then create closed polylines from these regions
                    var regions=Region.CreateFromCurves(plSegs);

                    //for testing purposes add regions to database
                    foreach (DBObject region in regions)
                    {
                        ms.AppendEntity((Entity)region);
                        tr.AddNewlyCreatedDBObject(region, true);
                    }

                    tr.Commit();
                }
            }
            catch (System.Exception ex)
            {
                if (ed != null)
                    ed.WriteMessage("\n Error in SplitPolylineAtIntersection: {0}", ex.Message);
            }
        }

Screenshot_1.png

 

Screenshot_2.png

 

 

 

 

 

 

 

 

 

 

0 Likes
Message 7 of 10

BKSpurgeon
Collaborator
Collaborator

I would add the following to Adam's post: http://through-the-interface.typepad.com/through_the_interface/2010/06/tracing-a-boundary-defined-by...

 

which is a good example of the trace boundary implmentation.

 

best rgds,

BK

0 Likes
Message 8 of 10

BKSpurgeon
Collaborator
Collaborator

I do not complete understand what you are trying to do, but if you are happy to click three different times, within each of the separate triangles, then trace boundary sounds ok. but if you want a programatically complete solution, perhaps investigate the code kindly posted by the other user.

 

best rgds

 

BK

0 Likes
Message 9 of 10

silke.foernzler
Explorer
Explorer

The above algorithm for splitting polylines works quite nice... until the polyline contains arc segments that will be splitted.

To handle this problem, just add the following lines of code after the call to 'IntersectWith()':

 

for (int k = intsPnts.Count-1; k >= 0; k--)
{
   Point3d pt = intsPnts[k];
   if (FuzzyEquals(pt, segi.StartPoint) || FuzzyEquals(pt, segi.EndPoint))
      intsPnts.RemoveAt(k);
}

 

Best regards,

Silke

0 Likes
Message 10 of 10

Anonymous
Not applicable

why so complicated? just use "bo" (boundary) command, use generate pline and pick a point and pick inner points in every polygon you want a region.

0 Likes