I want to Open Block Editor, Select all Lines ,and Join them to Create Polyline, and then save and Close Block Editor.

I want to Open Block Editor, Select all Lines ,and Join them to Create Polyline, and then save and Close Block Editor.

official.jaydeo
Enthusiast Enthusiast
318 Views
1 Reply
Message 1 of 2

I want to Open Block Editor, Select all Lines ,and Join them to Create Polyline, and then save and Close Block Editor.

official.jaydeo
Enthusiast
Enthusiast

I want to join all the lines inside the blocks to Create Polyline, like we do manually by editing a block Definition , type JOIN command select all lines, and then save Block Definition 

I am currently using following code but getting error at JoinEntities Line

i cannot use start and endpoints of Lines as Irregular Polyline may get Generated, as i have 100s of Lines to Join

@_gile @ActivistInvestor 

 [CommandMethod("cb")]
        public void JoinLinesInBlocks()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;

                foreach (ObjectId btrId in bt)
                {
                    BlockTableRecord btr = tr.GetObject(btrId, OpenMode.ForRead) as BlockTableRecord;

                    if (!btr.IsLayout)
                    {
                        BlockTableRecord blockDef = tr.GetObject(btrId, OpenMode.ForRead) as BlockTableRecord;

                        Entity[] entityCollection;

                        // Collect line entities in the block reference
                        int i = 0;
                        foreach (ObjectId entId in blockDef)
                        {
                           
                            Entity entity = tr.GetObject(entId, OpenMode.ForRead) as Entity;
                            if (entity is Line || entity is Arc || entity is Polyline)
                            {
                                entityCollection[i] = entity; i++;
                            }
                        }

                        // Check if there are at least two entities to create a polyline
                        if (entityCollection.Count() > 1)
                        {
                            // Create a new polyline
                            Polyline polyline = new Polyline();
                            blockDef.UpgradeOpen();

                            // Join entities to create a polyline
                            polyline.JoinEntities(entityCollection);

                            // Save the modified block
                            blockDef.AppendEntity(polyline);
                            tr.AddNewlyCreatedDBObject(polyline, true);
                        }
                    }
                }

                // Commit the transaction
                tr.Commit();
            }
        }

 

 

0 Likes
319 Views
1 Reply
Reply (1)
Message 2 of 2

_gile
Consultant
Consultant

Hi,

To join lines and arcs into a polyline, the entity on which the JoinEntities method is called must be a polyline.

You can try with something like this:

Edit: More robust version

 

public static void MJoinToPolylines(IEnumerable<Curve> source, Transaction tr)
{
    if (source is null) throw new ArgumentNullException(nameof(source));
    if (tr is null) throw new ArgumentNullException(nameof(tr));

    var curves = source
        .Where (c => c is Arc || c is Line || c is Polyline)
        .ToList();
    if (curves.Count == 0)
        return;
    var owner = (BlockTableRecord)tr.GetObject(curves[0].OwnerId, OpenMode.ForWrite);

    while (0 < curves.Count)
    {
        Polyline polyline = null;
        Curve curve = curves[0];
        switch (curve)
        {
            case Polyline pline:
                polyline = (Polyline)pline.Clone();
                break;
            case Line line:
                var plane = new Plane(Point3d.Origin, Vector3d.ZAxis);
                polyline = new Polyline();
                polyline.AddVertexAt(0, line.StartPoint.Convert2d(plane), 0.0, 0.0, 0.0);
                polyline.AddVertexAt(1, line.EndPoint.Convert2d(plane), 0.0, 0.0, 0.0);
                break;
            case Arc arc:
                plane = new Plane(Point3d.Origin, Vector3d.ZAxis);
                polyline = new Polyline();
                double angle = arc.EndAngle - arc.StartAngle;
                if (angle < 0)
                    angle += Math.PI * 2;
                double bulge = Math.Tan(angle / 4);
                polyline.AddVertexAt(0, arc.StartPoint.Convert2d(plane), bulge, 0.0, 0.0);
                polyline.AddVertexAt(1, arc.EndPoint.Convert2d(plane), 0.0, 0.0, 0.0);
                break;
        }
        curves.Remove(curve);
        if (polyline != null)
        {
            owner.AppendEntity(polyline);
            tr.AddNewlyCreatedDBObject(polyline, true);
            try
            {
                var indices = polyline.JoinEntities(curves.ToArray());
                if (!curve.IsWriteEnabled) tr.GetObject(curve.ObjectId, OpenMode.ForWrite);
                curve.Erase();
                foreach (Curve c in indices.Cast<int>()
                                           .Select(i => curves[i])
                                           .ToArray())
                {
                    curves.Remove(c);
                    if (!c.IsWriteEnabled) tr.GetObject(c.ObjectId, OpenMode.ForWrite);
                    c.Erase();
                }
            }
            catch
            {
                polyline.Erase();
            }
        }
    }
}

 

 

Your command:

 

        [CommandMethod("cb")]
        public void JoinLinesInBlocks()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;
            using (var tr = db.TransactionManager.StartTransaction())
            {
                var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                var validClassNames = new List<string> { "AcDbArc", "AcDbLine", "AcDbPolyline" };
                foreach (ObjectId btrId in bt)
                {
                    var btr = (BlockTableRecord)tr.GetObject(btrId, OpenMode.ForRead);
                    if (!btr.IsLayout)
                    {
                        var curves = btr
                            .Cast<ObjectId>()
                            .Where(id => validClassNames.Contains(id.ObjectClass.Name))
                            .Select(id => (Curve)tr.GetObject(id, OpenMode.ForRead));
                        MJoinToPolylines(curves, tr);
                    }
                }
                tr.Commit();
            }
        }

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes