Ignore objects in a selection set based on coordinates

Ignore objects in a selection set based on coordinates

Anonymous
Not applicable
1,000 Views
2 Replies
Message 1 of 3

Ignore objects in a selection set based on coordinates

Anonymous
Not applicable

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. 

 

Cheers

Vince

 

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
    {
        [CommandMethod("test3d")]
        public void test()
        {
            
           
           
            // Go to if layer name doesn't exist
            Step1:

            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";
                            acLyrTbl1.UpgradeOpen();
                            

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

                        ///////////////////////////////////////////////////////////////////////////
                        Step2:

                        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)
                                return;
                            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();
                            regs.Add(circ);

                            // 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");
                                return;
                            }
                            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();

                            circ.Erase();

                        }
                        tr.Commit();
                    
                    }

                }
            }
        }
    

 

0 Likes
1,001 Views
2 Replies
Replies (2)
Message 2 of 3

_gile
Consultant
Consultant

Hi,

 

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;
                ed.SetImpliedSelection(psr.Value);
                tr.Commit();
            }
        }

        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)))
                        e.Remove(i);
                }
            }
        }

 

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 3 of 3

Anonymous
Not applicable

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
Vince

 

 

 

0 Likes