Announcements
Due to scheduled maintenance, the Autodesk Community will be inaccessible from 10:00PM PDT on Oct 16th for approximately 1 hour. We appreciate your patience during this time.
.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Create the outermost border for the curves (BOUNDARY)

23 REPLIES 23
SOLVED
Reply
Message 1 of 24
quyenpv
1526 Views, 23 Replies

Create the outermost border for the curves (BOUNDARY)

Hello!
I want to create an outermost border for curves in a selection, some work well and some polylines don't. I've tried everything but can't fix it, hope you can help me fix it 

 

 

Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.BoundaryRepresentation
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.Geometry
Imports Autodesk.AutoCAD.Runtime
Imports CadDb = Autodesk.AutoCAD.DatabaseServices

Public Module M_Boundary
    Public Class OutLiner
        Private _dwg As Document

        Public Sub New(dwg As Document)
            _dwg = dwg
        End Sub

        Public Sub DrawOutline(entIds As IEnumerable(Of ObjectId))
            Using polyline = GetOutline(entIds)
                Using tran = _dwg.TransactionManager.StartTransaction()
                    Dim space = DirectCast(tran.GetObject(_dwg.Database.CurrentSpaceId, OpenMode.ForWrite), BlockTableRecord)
                    space.AppendEntity(TryCast(polyline, Entity))
                    tran.AddNewlyCreatedDBObject(TryCast(polyline, Entity), True)
                    tran.Commit()
                End Using
            End Using
        End Sub

        Public Function GetOutline(entIds As IEnumerable(Of ObjectId)) As Entity
            Dim regions = New List(Of Region)()

            Using tran = _dwg.TransactionManager.StartTransaction()
                For Each entId In entIds
                    Dim entity = TryCast(tran.GetObject(entId, OpenMode.ForRead), Entity)
                    If entity IsNot Nothing Then
                        Dim entityRegion As List(Of Region) = Nothing
                        Select Case entity.GetType()
                            Case GetType(Polyline)
                                entityRegion = GetRegionFromPolyline(TryCast(entity, Polyline))
                            Case GetType(Circle)
                                entityRegion = GetRegionFromCircle(TryCast(entity, Circle))
                            Case GetType(Arc)
                                entityRegion = GetRegionFromArc(TryCast(entity, Arc))
                            Case GetType(Ellipse)
                                entityRegion = GetRegionFromEllipse(TryCast(entity, Ellipse))
                            Case GetType(Line)
                                entityRegion = GetRegionFromLine(TryCast(entity, Line))
                            Case Else
                                ' Unsupported type
                                Continue For
                        End Select
                        If entityRegion IsNot Nothing Then
                            regions.AddRange(entityRegion)
                        End If
                    End If
                Next

                tran.Commit()
            End Using


            Using region = MergeRegions(regions)
                If region IsNot Nothing Then
                    Dim brep = New Brep(region)
                    Dim points = New List(Of Point2d)()
                    Dim faceCount = brep.Faces.Count()
                    Dim face = brep.Faces.First()
                    For Each iloop In face.Loops
                        If iloop.LoopType = LoopType.LoopExterior Then
                            For Each vertex In iloop.Vertices
                                points.Add(New Point2d(vertex.Point.X, vertex.Point.Y))
                            Next
                            Exit For
                        End If
                    Next

                    Return CreatePolyline(points)
                Else
                    Return Nothing
                End If
            End Using
        End Function
        'Private Function GetRegionFromPolyline(poly As CadDb.Polyline) As List(Of Region)
        '    Return GetRegionFromCurve(poly)
        'End Function
        Private Function GetRegionFromPolyline(poly As CadDb.Polyline) As List(Of Region)
            Dim regions = New List(Of Region)()
            Dim sourceCol = New DBObjectCollection()

            ' Create a list of all points in the polyline
            Dim points = New List(Of Point3d)()
            For i = 0 To poly.NumberOfVertices - 1
                points.Add(poly.GetPoint3dAt(i))
            Next

            ' Calculate the centroid of points
            Dim centroid = New Point3d(points.Average(Function(p) p.X), points.Average(Function(p) p.Y), points.Average(Function(p) p.Z))

            ' Sort points by angle
            points.Sort(Function(p1, p2) Math.Atan2(p1.Y - centroid.Y, p1.X - centroid.X).CompareTo(Math.Atan2(p2.Y - centroid.Y, p2.X - centroid.X)))

            ' Create a new closed polyline from the sorted points
            Dim sortedPoly = New CadDb.Polyline()
            For i As Integer = 0 To points.Count - 1
                sortedPoly.AddVertexAt(i, New Point2d(points(i).X, points(i).Y), 0, 0, 0)
            Next
            sortedPoly.Closed = True

            ' Add the polyline to the source collection
            sourceCol.Add(sortedPoly)

            ' Create regions from the source collection
            Dim dbObjs = Region.CreateFromCurves(sourceCol)
            For Each obj In dbObjs
                If TypeOf obj Is Region Then regions.Add(TryCast(obj, Region))
            Next

            Return regions
        End Function


        Public Function GetRegionFromCircle(circle As CadDb.Circle) As List(Of Region)
            Dim regions = New List(Of Region)()
            Dim sourceCol = New DBObjectCollection()
            Dim dbObj = New CadDb.Polyline()
            Dim numPoints As Integer = 100 ' increase this for higher precision
            For i = 0 To numPoints
                Dim param = 2 * Math.PI * i / numPoints
                Dim point = New Point2d(circle.Center.X + circle.Radius * Math.Cos(param), circle.Center.Y + circle.Radius * Math.Sin(param))
                dbObj.AddVertexAt(i, point, 0.0, 0.3, 0.3)
            Next
            dbObj.Closed = True
            sourceCol.Add(dbObj)
            Dim dbObjs = Region.CreateFromCurves(sourceCol)
            For Each obj In dbObjs
                If TypeOf obj Is Region Then regions.Add(TryCast(obj, Region))
            Next

            Return regions
        End Function
        Public Function GetRegionFromLine(line As CadDb.Line) As List(Of Region)
            Dim regions = New List(Of Region)()
            Dim sourceCol = New DBObjectCollection()

            ' Create a parallel line
            Dim offsetVector = (line.EndPoint - line.StartPoint).RotateBy(Math.PI / 2, New Vector3d(0, 0, 1)) * 0.1

            Dim parallelLine = DirectCast(line.GetOffsetCurves(offsetVector.Length)(0), CadDb.Line)


            ' Create a polyline from the two lines
            Dim poly = New CadDb.Polyline()
            poly.AddVertexAt(0, New Point2d(line.StartPoint.X, line.StartPoint.Y), 0.0, 0.3, 0.3)
            poly.AddVertexAt(1, New Point2d(line.EndPoint.X, line.EndPoint.Y), 0.0, 0.3, 0.3)
            poly.AddVertexAt(2, New Point2d(parallelLine.EndPoint.X, parallelLine.EndPoint.Y), 0.0, 0.3, 0.3)
            poly.AddVertexAt(3, New Point2d(parallelLine.StartPoint.X, parallelLine.StartPoint.Y), 0.0, 0.3, 0.3)

            poly.Closed = True
            sourceCol.Add(poly)

            Dim dbObjs = Region.CreateFromCurves(sourceCol)
            For Each obj In dbObjs
                If TypeOf obj Is Region Then regions.Add(TryCast(obj, Region))
            Next

            Return regions
        End Function
        Private Function GetRegionFromEllipse(ellipse As CadDb.Ellipse) As List(Of Region)
            Dim regions = New List(Of Region)()

            Using tran = _dwg.TransactionManager.StartTransaction()
                Dim tempEllipse = ellipse.Clone()
                tempEllipse.TransformBy(Matrix3d.Displacement(ellipse.Center.GetVectorTo(Point3d.Origin)))
                tran.AddNewlyCreatedDBObject(tempEllipse, True)
                Dim outlineId = tempEllipse.GetOffsetCurves(0.001)(0)
                Dim outline = tran.GetObject(outlineId, OpenMode.ForWrite)
                tran.AddNewlyCreatedDBObject(outline, True)

                If TypeOf outline Is CadDb.Polyline Then
                    regions.AddRange(GetRegionFromPolyline(TryCast(outline, CadDb.Polyline)))
                ElseIf TypeOf outline Is CadDb.Arc Then
                    regions.AddRange(GetRegionFromArc(TryCast(outline, CadDb.Arc)))
                End If

                outline.Erase()
                tempEllipse.Erase()
                tran.Commit()
            End Using

            Return regions
        End Function



        Public Function GetRegionFromArc(arc As CadDb.Arc) As List(Of Region)
            Dim regions = New List(Of Region)()
            Dim sourceCol = New DBObjectCollection()
            Dim dbObj = New CadDb.Polyline()
            Dim numPoints As Integer = 100 ' increase this for higher precision
            For i = 0 To numPoints
                Dim param = arc.StartAngle + (arc.EndAngle - arc.StartAngle) * i / numPoints
                Dim point = New Point2d(arc.Center.X + arc.Radius * Math.Cos(param), arc.Center.Y + arc.Radius * Math.Sin(param))
                dbObj.AddVertexAt(i, point, 0.0, 0.3, 0.3)
            Next
            dbObj.AddVertexAt(numPoints + 1, New Point2d(arc.Center.X, arc.Center.Y), 0.0, 0.3, 0.3) ' add center point
            dbObj.Closed = True
            sourceCol.Add(dbObj)
            Dim dbObjs = Region.CreateFromCurves(sourceCol)
            For Each obj In dbObjs
                If TypeOf obj Is Region Then regions.Add(TryCast(obj, Region))
            Next

            Return regions
        End Function

        Private Function GetRegionFromCurve(curve As CadDb.Curve) As List(Of Region)
            Dim regions = New List(Of Region)()
            Dim sourceCol = New DBObjectCollection()
            Dim dbObj = DirectCast(curve.Clone(), CadDb.Curve)
            sourceCol.Add(dbObj)
            Dim dbObjs = Region.CreateFromCurves(sourceCol)
            For Each obj In dbObjs
                If TypeOf obj Is Region Then regions.Add(TryCast(obj, Region))
            Next

            Return regions
        End Function

        Private Function MergeRegions(regions As List(Of Region)) As Region
            If regions.Count = 0 Then Return Nothing
            If regions.Count = 1 Then Return regions(0)
            Dim region = regions(0)
            For i = 1 To regions.Count - 1
                Dim rg = regions(i)
                region.BooleanOperation(BooleanOperationType.BoolUnite, rg)
                rg.Dispose()
            Next

            Return region
        End Function

        Private Function CreatePolyline(points As List(Of Point2d)) As CadDb.Polyline
            Dim poly = New CadDb.Polyline(points.Count())
            For i = 0 To points.Count - 1
                poly.AddVertexAt(i, points(i), 0.0, 0.1, 0.1)
            Next
            poly.SetDatabaseDefaults(_dwg.Database)
            poly.ColorIndex = 1
            poly.Closed = True
            Return poly
        End Function
    End Class

    <CommandMethod("Outline")>
    Public Sub RunMyCommand()
        Dim dwg = Application.DocumentManager.MdiActiveDocument
        Dim ed = dwg.Editor

        Try
            Dim ids = SelectEntities(ed)
            If ids IsNot Nothing Then
                Dim liner = New OutLiner(dwg)
                liner.DrawOutline(ids)
            Else
                ed.WriteMessage(vbLf & "*Cancel*")
            End If
        Catch ex As System.Exception
            ed.WriteMessage(vbLf & "Command failed:" & vbLf & "{0}", ex.Message)
            ed.WriteMessage(vbLf & "*Cancel*")
        End Try
    End Sub

    Private Function SelectEntities(ed As Editor) As ObjectId()
        ' Allow selection of all types of entities.
        Dim res = ed.GetSelection()
        If res.Status = PromptStatus.OK Then
            Return res.Value.GetObjectIds()
        Else
            Return Nothing
        End If
    End Function
End Module

 

quyenpv1_0-1691756419626.pngquyenpv1_1-1691756443145.pngquyenpv1_2-1691756646564.png

 

23 REPLIES 23
Message 2 of 24
_gile
in reply to: quyenpv

Hi,

This code (inspired by this one) seems to work as expected (at least with your drawing example).

 

using Autodesk.AutoCAD.ApplicationServices.Core;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;

using System;
using System.Collections.Generic;
using System.Linq;

namespace MergeCurvesSample
{
    public class Commands
    {
        struct Segment
        {
            public Point2d StartPt { get; set; }
            public Point2d EndPt { get; set; }
            public double Bulge { get; set; }
        }

        private static IEnumerable<Polyline> MergeCurves(IEnumerable<Curve> curves)
        {
            var splitCurves = new List<Curve>();
            var curveSegments = new DBObjectCollection();
            foreach (Curve curve in curves)
            {
                if (curve is Arc || curve is Circle || curve is Line || curve is Polyline)
                {
                    foreach (Curve c in GetSplitSegments(curve, curves))
                    {
                        splitCurves.Add(c);
                        curveSegments.Add(c);
                    }
                }
            }
            var regions = Region.CreateFromCurves(curveSegments);
            foreach (Curve c in splitCurves)
            {
                c.Dispose();
            }

            if (regions.Count == 0) yield break;

            Region reg = (Region)regions[0];
            for (int i = 1; i < regions.Count; i++)
            {
                reg.BooleanOperation(BooleanOperationType.BoolUnite, (Region)regions[i]);
                regions[i].Dispose();
            }

            var segments = new DBObjectCollection();
            reg.Explode(segments);
            reg.Dispose();

            var segs = new List<Segment>();
            var plane = new Plane(Point3d.Origin, Vector3d.ZAxis);
            for (int i = 0; i < segments.Count; i++)
            {
                if (segments[i] is Region r)
                {
                    r.Explode(segments);
                    continue;
                }
                Curve crv = (Curve)segments[i];
                Point3d start = crv.StartPoint;
                Point3d end = crv.EndPoint;
                double bulge = 0.0;
                if (crv is Arc arc)
                {
                    double angle = arc.Center.GetVectorTo(start).GetAngleTo(arc.Center.GetVectorTo(end), arc.Normal);
                    bulge = Math.Tan(angle / 4.0);
                }
                segs.Add(new Segment { StartPt = start.Convert2d(plane), EndPt = end.Convert2d(plane), Bulge = bulge });
            }

            foreach (DBObject o in segments) o.Dispose();

            while (segs.Count > 0)
            {
                var pline = new Polyline();
                pline.AddVertexAt(0, segs[0].StartPt, segs[0].Bulge, 0.0, 0.0);
                Point2d pt = segs[0].EndPt;
                segs.RemoveAt(0);
                int vtx = 1;
                while (true)
                {
                    int i = segs.FindIndex((s) => s.StartPt.IsEqualTo(pt) || s.EndPt.IsEqualTo(pt));
                    if (i < 0) break;
                    Segment seg = segs[i];
                    if (seg.EndPt.IsEqualTo(pt))
                        seg = new Segment { StartPt = seg.EndPt, EndPt = seg.StartPt, Bulge = -seg.Bulge };
                    pline.AddVertexAt(vtx, seg.StartPt, seg.Bulge, 0.0, 0.0);
                    pt = seg.EndPt;
                    segs.RemoveAt(i);
                    vtx++;
                }
                pline.Closed = true;
                yield return pline;
            }
        }

        private static DBObjectCollection GetSplitSegments(Curve curve, IEnumerable<Curve> curves)
        {
            var points = new Point3dCollection();
            foreach (var c in curves)
            {
                curve.IntersectWith(c, Intersect.OnBothOperands, points, IntPtr.Zero, IntPtr.Zero);
            }

            if (points.Count == 0) return new DBObjectCollection { (Curve)curve.Clone() };

            var parameters = points
                .Cast<Point3d>()
                .Select(p => curve.GetParameterAtPoint(p))
                .OrderBy(p => p)
                .ToArray();
            return curve.GetSplitCurves(new DoubleCollection(parameters));
        }

        [CommandMethod("TEST")]
        public static void Test()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;

            var filter = new SelectionFilter(new[]
            {
                new TypedValue(0, "ARC,CIRCLE,LINE,LWPOLYLINE")
            });
            var selection = ed.GetSelection(filter);
            if (selection.Status != PromptStatus.OK)
                return;

            using (var tr = db.TransactionManager.StartTransaction())
            {
                var curves = selection.Value.GetObjectIds()
                    .Select(id => (Curve)tr.GetObject(id, OpenMode.ForRead));
                var curSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                foreach (var pline in MergeCurves(curves))
                {
                    curSpace.AppendEntity(pline);
                    tr.AddNewlyCreatedDBObject(pline, true);
                }
                tr.Commit();
            }
        }
    }
}

 

 

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 3 of 24
quyenpv
in reply to: quyenpv

Great, excellent, wonderfull! Thank you very much
1. Can you add more ellipse objects if you want?
2. If you want to create internal boundary Boundary of qq307501169 

 

Message 4 of 24
_gile
in reply to: quyenpv


@quyenpv  a écrit :

1. Can you add more ellipse objects if you want?


Polyline can only contain linear and circular arc segments. If you want to convert true ellipses to polyline approximations, you can use the Ellipse.ToPolyline method from the GeometryExtensions library.

 


@quyenpv  a écrit :

2. If you want to create internal boundary Boundary of qq307501169 


I thaught you wanted to learn .NET programmation. I won't do your work for you.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 5 of 24
quyenpv
in reply to: quyenpv

Thank you!
Based on your suggestion, I did it
I'm learning VB.Net for real, but it's not to ask him to do the work that should be mine, but I really can't find a solution, so I need help.
Based on the above suggestion, I understood that I had to transform ellipse and arc into polyline to create boundary
Once again thank you very much! I wish you good health

Message 6 of 24
quyenpv
in reply to: quyenpv

@_gile 

Right now I can only process the ellipse and the arc still can't. Can you help me with suggestions?

quyenpv1_0-1691779475827.pngquyenpv1_1-1691779491210.png

 

Message 7 of 24
_gile
in reply to: quyenpv

I edited the upper code so that all selected curves are splited at intersections.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 8 of 24
quyenpv
in reply to: quyenpv

@_gile With your newly updated code can handle the case

quyenpv1_0-1691804982208.png

But when arc intersects with ellipse and circle, it doesn't work

quyenpv1_1-1691805029094.png

 

Message 9 of 24
quyenpv
in reply to: _gile

@_gile With your newly updated code can handle the case, But when arc intersects with ellipse and circle, it doesn't work
Message 10 of 24
_gile
in reply to: quyenpv

It works for me.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 11 of 24
quyenpv
in reply to: _gile

Can you update the new processing code as shown in the video?

Message 12 of 24
_gile
in reply to: quyenpv


@quyenpv  a écrit :

Can you update the new processing code as shown in the video?


I ran the code as it was yesterday (reply #7).



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 13 of 24
kdub_nz
in reply to: quyenpv

@quyenpv,

 

Is it possible that your translation to VB.NET is faulty ??


// Called Kerry in my other life.

Everything will work just as you expect it to, unless your expectations are incorrect.
Sometimes the question is more important than the answer.

class keyThumper<T> : Lazy<T>;      another  Swamper

Message 14 of 24
quyenpv
in reply to: kdub_nz

Yes I'm thinking so
Message 15 of 24
kdub_nz
in reply to: quyenpv

That, I believe, is one of the hugest cause of errors in .NET programming
. . .  people making incorrect translations from C# to VB.net.

 

. . . but people generally don't want to listen when the suggestion is made to learn C# properly to save the hassle 🙂

 


// Called Kerry in my other life.

Everything will work just as you expect it to, unless your expectations are incorrect.
Sometimes the question is more important than the answer.

class keyThumper<T> : Lazy<T>;      another  Swamper

Message 16 of 24
quyenpv
in reply to: kdub_nz

Yes you are!
I see a very large C# community and a lot of documentation, I will learn and gradually switch to
Message 17 of 24
GiaBach
in reply to: _gile

Yes, that (reply 7#) didn't include any code.
And the origin (2#) only accepts Arc, Circle, Line, and Polyline objects.

 

            foreach (Curve curve in curves)
            {
                if (curve is Arc || curve is Circle || curve is Line || curve is Polyline)

 

Message 18 of 24
_gile
in reply to: GiaBach


@GiaBach  a écrit :

Yes, that (reply 7#) didn't include any code.


In reply #7 I announced the "upper code" (reply #2) had been edited.

 


@GiaBach  a écrit :

And the origin (2#) only accepts Arc, Circle, Line, and Polyline objects.

 

            foreach (Curve curve in curves)
            {
                if (curve is Arc || curve is Circle || curve is Line || curve is Polyline)

The code still accepts only arcs, circles, lines and polylines because polylines "can only contain linear and circular arc segments" as said in reply #4.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 19 of 24
_gile
in reply to: kdub_nz


@kdub_nz  a écrit :

@quyenpv,

 

Is it possible that your translation to VB.NET is faulty ??


This may be due to the for statement:

 

            for (int i = 0; i < segments.Count; i++)
            {
                if (segments[i] is Region r)
                {
                    r.Explode(segments);
                    continue;
                }
                Curve crv = (Curve)segments[i];
                Point3d start = crv.StartPoint;
                Point3d end = crv.EndPoint;
                double bulge = 0.0;
                if (crv is Arc arc)
                {
                    double angle = arc.Center.GetVectorTo(start).GetAngleTo(arc.Center.GetVectorTo(end), arc.Normal);
                    bulge = Math.Tan(angle / 4.0);
                }
                segs.Add(new Segment { StartPt = start.Convert2d(plane), EndPt = end.Convert2d(plane), Bulge = bulge });
            }

 

Because in C#, the loop condition is evaluated on each iteration, and in VB.NET, it is only evaluated on entry to the loop. In this loop if the entity is a region it is explode and the resulting entities are added to the segments collection.

In VB, this for statement have to be replaced by a while statement.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 20 of 24
_gile
in reply to: GiaBach

This version references the GeometryExtensions library to be able to directly work with Ellipses and Splines.

Due to the conversion of Ellipses and Splines into polyline approximations it needs a Tolerance.

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;

using Gile.AutoCAD.Geometry;

using System;
using System.Collections.Generic;
using System.Linq;

namespace MergeCurvesUsingGeometryExtensions
{
    public class Commands
    {
        private static IEnumerable<Polyline> MergeCurves(IEnumerable<Curve> curves, Tolerance tolerance)
        {
            var curveSegments = new DBObjectCollection();
            foreach (Curve curve in curves)
            {
                foreach (Curve c in GetSplitSegments(curve, curves))
                {
                    curveSegments.Add(c);
                }
            }
            var regions = Region.CreateFromCurves(curveSegments);
            foreach (Curve c in curveSegments)
            {
                c.Dispose();
            }

            if (regions.Count == 0) yield break;

            Region reg = (Region)regions[0];
            for (int i = 1; i < regions.Count; i++)
            {
                reg.BooleanOperation(BooleanOperationType.BoolUnite, (Region)regions[i]);
                regions[i].Dispose();
            }

            var segments = new DBObjectCollection();
            reg.Explode(segments);
            reg.Dispose();

            var plane = new Plane(Point3d.Origin, Vector3d.ZAxis);
            var polylineSegments = new PolylineSegmentCollection();
            for (int i = 0; i < segments.Count; i++)
            {
                var entity = (Entity)segments[i];
                switch (entity)
                {
                    case Region region:
                        region.Explode(segments);
                        break;
                    case Ellipse ellipse:
                        polylineSegments.AddRange(ellipse.ToPolyline());
                        break;
                    case Spline spline:
                        polylineSegments.AddRange((Polyline)spline.ToPolyline());
                        break;
                    case Line line:
                        polylineSegments.Add(new PolylineSegment(new LineSegment2d(
                            line.StartPoint.Convert2d(plane),
                            line.EndPoint.Convert2d(plane))));
                        break;
                    case Arc arc:
                        polylineSegments.Add(new PolylineSegment(new CircularArc2d(
                            arc.StartPoint.Convert2d(plane),
                            arc.GetPointAtParameter((arc.StartParam + arc.EndParam) * 0.5).Convert2d(plane),
                            arc.EndPoint.Convert2d(plane))));
                        break;
                    default:
                        break; ;
                }
            }
            foreach (var segmentCollection in polylineSegments.Join(tolerance))
            {
                yield return segmentCollection.ToPolyline();
            }
        }

        private static DBObjectCollection GetSplitSegments(Curve curve, IEnumerable<Curve> curves)
        {
            var points = new Point3dCollection();
            foreach (var c in curves)
            {
                curve.IntersectWith(c, Intersect.OnBothOperands, points, IntPtr.Zero, IntPtr.Zero);
            }

            if (points.Count == 0) return new DBObjectCollection { (Curve)curve.Clone() };

            var parameters = points
                .Cast<Point3d>()
                .Select(p => curve.GetParameterAtPoint(p))
                .OrderBy(p => p)
                .ToArray();
            return curve.GetSplitCurves(new DoubleCollection(parameters));
        }

        [CommandMethod("TEST")]
        public static void Test()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;

            var filter = new SelectionFilter(new[]
            {
                new TypedValue(-4, "<OR"),
                new TypedValue(0, "ARC,CIRCLE,ELLIPSE,LINE,LWPOLYLINE"),
                new TypedValue(-4, "<AND"),
                new TypedValue(0, "SPLINE"),
                new TypedValue(-4, "&"),
                new TypedValue(70, 8),
                new TypedValue(-4, "AND>"),
                new TypedValue(-4, "OR>")
            });
            var selection = ed.GetSelection(filter);
            if (selection.Status != PromptStatus.OK)
                return;

            using (var tr = db.TransactionManager.StartTransaction())
            {
                var curves = selection.Value.GetObjectIds()
                    .Select(id => (Curve)tr.GetObject(id, OpenMode.ForRead));
                var curSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                var tolerance = curves.Any(c => c is Ellipse || c is Spline) ?
                    new Tolerance(0.1, 0.5) :
                    Tolerance.Global;
                foreach (var pline in MergeCurves(curves, tolerance))
                {
                    curSpace.AppendEntity(pline);
                    tr.AddNewlyCreatedDBObject(pline, true);
                }
                tr.Commit();
            }
        }
    }
}

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

AutoCAD Inside the Factory


Autodesk Design & Make Report