Distinguished Contributor
Posts: 117
Registered: ‎11-02-2011
Message 1 of 3 (222 Views)

Ignore objects in a selection set based on coordinates

222 Views, 2 Replies
04-04-2013 09:23 AM

Hey Everyone,


I'm working on a command that lets me select polylines on a specific layer, then converts them to 3d solids. I'm having a slight issue where if a polyline has the same start and end coordinates (this happens in some of our drawings), then the command stops and I get an eDegenerateGeometry error. I want to modify my command so that it detects these objects, removes them from the selection set, and then notifies the users of their prescence so they can be removed manually. The last part i think I can handle, however I'm not sure how to modify either my filter or my routine to detect and ignore these objects. I'm assuming that since i'll want to record these objects to later notify the user, that i'd probably want to modify my routine. Any pointers or examples would be greatly appreciated. 





using System;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.DataExtraction;
using Autodesk.AutoCAD.Colors;
using System.Windows.Forms;

namespace Convert3D

    public class Convert3D
        public void test()
            // Go to if layer name doesn't exist

            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            string sreslayer = "";
            ////////////////////////// Get layer by selection //////////////////////////////
            Transaction trans = db.TransactionManager.StartTransaction();
            using (trans)
                PromptSelectionOptions sopts = new PromptSelectionOptions();
                sopts.MessageForAdding = "Select an object on the layer you would like to modify";
                PromptSelectionResult layerres = doc.Editor.GetSelection(sopts);

                if (layerres.Status == PromptStatus.OK)
                    foreach (ObjectId id in layerres.Value.GetObjectIds())
                        Entity acadent = (Entity)trans.GetObject(id, OpenMode.ForRead);

                        sreslayer = acadent.Layer;

                        ed.WriteMessage("The layer you have selected is " + sreslayer);


                // This time we do check whether the layer exists

                LayerTable lt = (LayerTable)trans.GetObject(db.LayerTableId, OpenMode.ForRead);

                if (!lt.Has(sreslayer))
                    ed.WriteMessage("\nLayer not found.");
                    ed.WriteMessage("\nTry Again.");
                    //If layername doesn't exist, re-run the command
                    goto Step1;
                    // Limits selection by layer and object type 
                    SelectionFilter filt = new SelectionFilter(new TypedValue[]{
                    new TypedValue(8,sreslayer), new TypedValue(0,"polyline")});

                    PromptSelectionResult res = ed.GetSelection(filt);
                    if (res.Status != PromptStatus.OK) return;
                    SelectionSet sset = res.Value;
                    Entity ent;

                    PromptDoubleOptions pdouble = new PromptDoubleOptions("\nEnter new diameter of pipe: ");
                    pdouble.AllowNegative = false;
                    pdouble.AllowZero = false;
                    PromptDoubleResult pres = ed.GetDouble(pdouble);

                    // radius of cylinder
                    double rad = pres.Value;

                    using (Transaction tr = doc.TransactionManager.StartTransaction())
                        //////////////////Creates a new 3d layer for the 3d solids///////////////
                        LayerTable acLyrTbl1 = tr.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable;
                        LayerTableRecord acLyrTblRec = new LayerTableRecord();
                        // Check if the layer exists, if not create it, if so, continue on
                        if (acLyrTbl1.Has(sreslayer+"-3D") == true)
                            goto Step2;
                        if (acLyrTbl1.Has(sreslayer) == true)
                            // Assign the layer a name
                            acLyrTblRec.Name = sreslayer+"-3D";

                            // Append the new layer to the Layer table and the transaction
                            tr.AddNewlyCreatedDBObject(acLyrTblRec, true);


                        BlockTableRecord btr = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
                        foreach (SelectedObject obj in sset)
                            ent = tr.GetObject(obj.ObjectId, OpenMode.ForRead) as Entity;
                            if (ent == null)
                            Polyline3d poly = ent as Polyline3d;
                            if (poly == null) return;
                            Point3d p1 = poly.GetPointAtParameter(poly.StartParam);
                            Point3d p2 = poly.GetPointAtParameter(poly.StartParam + 1.0);
                            Vector3d vec = (p2 - p1).GetNormal();
                            double height = p1.DistanceTo(p2);
                            Circle circ = new Circle(p1, vec, rad);

                            circ.Normal = vec;

                            ObjectId objId = btr.AppendEntity(circ);
                            // Set the layer in which to create the 3d solids
                            circ.Layer = sreslayer+"-3D";
                            tr.AddNewlyCreatedDBObject(circ, true);

                            // Get the boundary curves to create a region
                            DBObjectCollection regs = new DBObjectCollection();

                            // Create a region from the circle.

                            DBObjectCollection regions = new DBObjectCollection();
                            regions = Region.CreateFromCurves(regs);
                            if (regions.Count == 0)
                                ed.WriteMessage("\nFailed to create region\n");
                            Region reg = (Region)regions[0];

                            // Extrude the region to create a solid.

                            Solid3d sol = new Solid3d();
                            sol.Layer = sreslayer + "-3D";
                            sol.RecordHistory = true;// optional
                            sol.ShowHistory = false;// optional
                            sol.ExtrudeAlongPath(reg, poly as Curve, 0.0);
                            ObjectId solId = ObjectId.Null;
                            solId = btr.AppendEntity(sol);
                            tr.AddNewlyCreatedDBObject(sol, true);

                            if (!circ.IsWriteEnabled) circ.UpgradeOpen();





*Expert Elite*
Posts: 2,071
Registered: ‎04-29-2006
Message 2 of 3 (212 Views)

Re : Ignore objects in a selection set based on coordinates

04-04-2013 10:09 AM in reply to: vince1327



You can use the Editor.SelectionAdded event to filter during the selection.


        [CommandMethod("Test", CommandFlags.Modal)]
        public void Test()
            Document doc = AcAp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            using (Transaction tr = db.TransactionManager.StartTransaction())
                TypedValue[] filter = { new TypedValue(0, "LWPOLYLINE") };
                ed.SelectionAdded += ed_SelectionAdded;
                PromptSelectionResult psr = ed.GetSelection(new SelectionFilter(filter));
                ed.SelectionAdded -= ed_SelectionAdded;
                if (psr.Status != PromptStatus.OK) return;

        void ed_SelectionAdded(object sender, SelectionAddedEventArgs e)
            ObjectId[] ids = e.AddedObjects.GetObjectIds();
            for (int i = 0; i < ids.Length; i++)
                using (Polyline pline = (Polyline)ids[i].Open(OpenMode.ForRead))
                    if (pline.GetPoint2dAt(0).IsEqualTo(pline.GetPoint2dAt(pline.NumberOfVertices - 1)))



Gilles Chanteau
Distinguished Contributor
Posts: 117
Registered: ‎11-02-2011
Message 3 of 3 (202 Views)

Re: Ignore objects in a selection set based on coordinates

04-04-2013 11:46 AM in reply to: vince1327

Thanks for the example Gilles, I'll give it a shot



Is there any way that I can address this issue with an "if" statement here:


BlockTableRecord btr = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
foreach (SelectedObject obj in sset) {

Thanks Again




You are not logged in.

Log into access your profile, ask and answer questions, share ideas and more. Haven't signed up yet? Register

Are you familiar with the Autodesk Expert Elites? The Expert Elite program is made up of customers that help other customers by sharing knowledge and exemplifying an engaging style of collaboration. To learn more, please visit our Expert Elite website.

Need installation help?

Start with some of our most frequented solutions to get help installing your software.

Ask the Community