Explode and Select Window in C#

Explode and Select Window in C#

alexisgacia
Advocate Advocate
1,225 Views
12 Replies
Message 1 of 13

Explode and Select Window in C#

alexisgacia
Advocate
Advocate

Hi,

 

Is it possible to select exploded objects using the select window?

 

I'm trying to explode and select certain area base on the selected objects. Then those selected object will be save and the rest will be ignored.

 

Thanks in advance.

0 Likes
1,226 Views
12 Replies
Replies (12)
Message 2 of 13

hosneyalaa
Advisor
Advisor

Hi 

Anther way ,  Example of Explode Region

 

 

var region = (Region)tr.GetObject(id, OpenMode.ForWrite, false, true);

                            var objects = new DBObjectCollection();

                            region.Explode(objects);

                            foreach (Entity ent in objects)

                            {

                               

                            }

 

 

 

 

 

0 Likes
Message 3 of 13

alexisgacia
Advocate
Advocate

Hi @hosneyalaa ,

 

Thank you for the reply.

 

What I mean is like this.

var region = (Region)tr.GetObject(id, OpenMode.ForWrite, false, true);
var objects = new DBObjectCollection();
region.Explode(objects);

// Here I will select base window mPt1 and mPt2. I tried this but it didnt get the objects from the exploded

PromptSelectionResult mBoxSelect = ed.SelectWindow(mPt1, mPt2);

foreach (ObjectId oInBoxId  in mBoxSelect.Value.GetObjectIds())
{                            
  ..
}

 

0 Likes
Message 4 of 13

hosneyalaa
Advisor
Advisor

hi @alexisgacia 

my language is not good

 

Can you share an Autocad drawing?
Explain if you want to reach

0 Likes
Message 5 of 13

alexisgacia
Advocate
Advocate

I'm trying to identify the label inside the sheet. Using the boundary of the line, I will able to select the object and Identify the label that I marked. In this case (063, 064, 067, 068, 069)

 

alexisgacia_1-1661850603719.png

 

 

0 Likes
Message 6 of 13

hosneyalaa
Advisor
Advisor

hi @alexisgacia 

reading code  from gile

you have to add reference to acdbmgdbrep.dll and Import Autodesk.AutoCAD.BoundaryRepresentation namespace

 

 

  https://forums.autodesk.com/t5/net/spatial-query-in-autocad-2010/m-p/5304535/highlight/true#M42041

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

            PromptEntityOptions peo = new PromptEntityOptions("\nSelect a polyline: ");
            peo.SetRejectMessage("Only a polyline !");
            peo.AddAllowedClass(typeof(Polyline), true);
            PromptEntityResult per = ed.GetEntity(peo);
            if (per.Status != PromptStatus.OK)
                return;

            using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction())
            {
                Polyline pline = (Polyline)tr.GetObject(per.ObjectId, OpenMode.ForRead);
                if (!pline.Closed)
                {
                    ed.WriteMessage("\nPolyline must be closed.");
                    return;
                }
                DBObjectCollection curves = new DBObjectCollection();
                curves.Add(pline);
                try
                {
                    using (DBObjectCollection regions = Region.CreateFromCurves(curves))
                    using (Region region = (Region)regions[0])
                    {
                        PromptPointOptions ppo = new PromptPointOptions("\nPick a point <quit>: ");
                        ppo.AllowNone = true;
                        while (true)
                        {
                            PromptPointResult ppr = ed.GetPoint(ppo);
                            if (ppr.Status != PromptStatus.OK)
                                break;
                            Application.ShowAlertDialog(
                                GetPointContainment(region, ppr.Value).ToString());
                        }
                    }
                }
                catch (System.Exception exn)
                {
                    ed.WriteMessage("\nError: " + exn.Message);
                }
            }
        }

        private PointContainment GetPointContainment(Region region, Point3d point)
        {
            PointContainment result = PointContainment.Outside;
            using (Brep brep = new Brep(region))
            {
                if (brep != null)
                {
                    using (BrepEntity ent = brep.GetPointContainment(point, out result))
                    {
                        if (ent is Autodesk.AutoCAD.BoundaryRepresentation.Face)
                        {
                            result = PointContainment.Inside;
                        }
                    }
                }
            }
            return result;
        }

 

 

0 Likes
Message 7 of 13

hosneyalaa
Advisor
Advisor

OR  can you using

 

                    TypedValue[] tvs = new TypedValue[]

                        {new TypedValue(0, "text")

                              };

                    SelectionFilter filter = new SelectionFilter(tvs);

                    PromptSelectionResult result = ed.SelectCrossingWindow(p1, p2, filter);

                    if (result.Status != PromptStatus.OK) return;

 

 

Screenshot 2022-08-29 101349.png 

0 Likes
Message 8 of 13

Jeff_M
Consultant
Consultant

@alexisgacia The Explode method does not add the objects to the database so selection won't find anything. If you post a small dwg along with the code you are using to the select the region(s) we could probably get this sorted out for you.

Jeff_M, also a frequent Swamper
EESignature
0 Likes
Message 9 of 13

hosneyalaa
Advisor
Advisor
0 Likes
Message 10 of 13

alexisgacia
Advocate
Advocate

Hi @Jeff_M and @hosneyalaa,

 

Good day.

 

I attached the DWG File as reference. 

 

alexisgacia_0-1661935635259.png

 

User Steps:

Select BlockReference as BlockSheet

Select Target Entities (Circle, Line, Polyline, SPLine)

 

Desired Output:

Circle (Cyan): 053, 054, 060 & 061

Line(Green): 067

SPLine(Yellow): 056, 057, 061, 062 & 063

Polyline(White): 069, 070, 072, 073 & 074

 

Block <BlockSheet>: Contains Polyline and Text

Polyline ("A-TITL-TXT2" & "Z_DWG_SHT")

TEST ("Z_DWG_SHT_NO")

 

My idea on the process:

Explode the BlockSheet to SheetCollection

Remove any objects except objects having layer ("Z_DWG_SHT" & "Z_DWG_SHT_NO")

Loop through to Selected Entities 

(SelectCrossing or Alternative function) using boundingbox of the entity as Crv1 to identify the objects in SheetCollection.

(SelectCrossing or Alternative function) Using the boundary of the entity as Sheet having layer "Z_DWG_SHT" from the sheetCollection to check if Crv1 exist in the selection

Once Crv1 exist grab the Text with layer "Z_DWG_SHT_NO"

 

Currently I don't have an alternative function that can SelectCrossing in the Collection. 

 

Below is the sample code that I did

private void _SelectObjectsFromExploded(object sender, EventArgs e)
        {
            Autodesk.Civil.ApplicationServices.CivilDocument civilDoc = Autodesk.Civil.ApplicationServices.CivilApplication.ActiveDocument;
            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;
            listBox1.Items.Clear();
            string mSheetBlockName = "SheetBlock";
            string mSheetLayerName = "Z_DWG_SHT";
            string mLabelLayerLName = "Z_DWG_SHT_NO";

            cSelection mSel = new cSelection();
            ObjectId mSheetBlockId = mSel.Select_SingeEntity("Select Sheet Block");

            // Set up our selection to only select 2D solids
            var pso = new PromptSelectionOptions();
            pso.MessageForAdding = "\nSelect Curve";

            //var sf = new SelectionFilter(new TypedValue[] { new TypedValue((int)DxfCode.Start, "3DSOLID") });

            //var psr = ed.GetSelection(pso, sf);
            var psr = ed.GetSelection(pso);

            if (psr.Status != PromptStatus.OK) return;
            using (doc.LockDocument())
            {
                DBObjectCollection mSheets = new DBObjectCollection();
                DBObjectCollection mValidSheets = new DBObjectCollection();
                BlockReference oSheet = null;

                doc.TransactionManager.EnableGraphicsFlush(true);
                using (Transaction tr = doc.TransactionManager.StartTransaction())
                {
                    var oBlk = tr.GetObject(mSheetBlockId, OpenMode.ForWrite);

                    if (oBlk is BlockReference)
                    {
                        oSheet = oBlk as BlockReference;
                        if (oSheet.Name.ToUpper() != mSheetBlockName.ToUpper())
                        {
                            ed.WriteMessage("\nSelected block is not recognize as Block Sheet.");
                            return;
                        }


                        // Create Temp Sheets
                        oSheet.Explode(mSheets);
                        mValidSheets = GetValidSheets(tr, mSheets);

                    }
                    tr.Commit();
                }
                using (Transaction tr = doc.TransactionManager.StartTransaction())
                {
                    if(oSheet != null) 
                    { 
                        foreach (ObjectId oID in psr.Value.GetObjectIds())
                        {
                            var o = tr.GetObject(oID, OpenMode.ForRead);

                            if (o is Curve)
                            { 
                                Curve mCurve = o as Curve;

                                CreateLine(tr, mCurve.GeometricExtents.MinPoint, mCurve.GeometricExtents.MaxPoint);

                                string mSheetCnt = GetSheetNumber(mValidSheets, mCurve);
                                listBox1.Items.Add(mSheetCnt);
                            }
                        }

                        // Clear Temporary Sheets
                        foreach (Entity ent in mValidSheets) 
                        {
                            Entity ForDel = tr.GetObject(ent.ObjectId, OpenMode.ForWrite) as Entity;
                            ForDel.Erase(); 
                        }
                    }
                    else
                    {
                        ed.WriteMessage("\nInvalid Block Selected.");
                    }

                    tr.Commit();
                }
            }


        }
 
        DBObjectCollection GetValidSheets(Transaction tr, DBObjectCollection mSheets, string LayerSheet="Z_DWG_SHT", string LayerSheetNo= "Z_DWG_SHT_NO")
        {
            BlockTable acBlkTbl = tr.GetObject(Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Database.BlockTableId, OpenMode.ForRead) as BlockTable;
            BlockTableRecord acBlkTblRec = tr.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
            DBObjectCollection mValidSheets = new DBObjectCollection();
            foreach (Entity oEnt in mSheets) 
            {
                if (oEnt.Layer == LayerSheet || oEnt.Layer == LayerSheetNo)
                {
                    mValidSheets.Add(oEnt);

                    acBlkTblRec.AppendEntity(oEnt);
                    tr.AddNewlyCreatedDBObject(oEnt, true);
                }
            }
            return mValidSheets;
        }
                 string GetSheetNumber(DBObjectCollection mSheets, Curve mCurve, string LayerSheet = "Z_DWG_SHT", string LayerSheetNo = "Z_DWG_SHT_NO")
        {
            dynamic acadApp = Application.AcadApplication;

            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;
            string mSheetCnt = "";
             
            PromptSelectionResult mRes = ed.SelectCrossingWindow(mCurve.GeometricExtents.MaxPoint, mCurve.GeometricExtents.MinPoint);
             

            using (SelectionSet ss = mRes.Value)
            {
                if (ss is null) return "No Selection";
                foreach (ObjectId oId in ss.GetObjectIds())
                {
                    Entity obj = oId.GetObject(OpenMode.ForRead) as Entity;
                    //if (mSheets.Contains(obj))
                    //System.Diagnostics.Debug.Print(obj.GetType().Name + " - " + obj.Layer);
                    listBox1.Items.Add(" - " + obj.GetType().Name + " - " + obj.Layer);
                    if(CollectionHas(mSheets, obj))
                    {
                        if (obj.Layer == LayerSheet)    // Sheet Box
                        {
                            // Select using box
                            PromptSelectionResult mBoxSelect = ed.SelectCrossingWindow(obj.GeometricExtents.MaxPoint, obj.GeometricExtents.MinPoint);

                            bool HasCurveId = false;
                            bool HasSheetCnt = false;
                            Entity oSheetCnt = null;
                            foreach (ObjectId oInBoxId  in mBoxSelect.Value.GetObjectIds())
                            {
                                if (mCurve.ObjectId == oInBoxId) HasCurveId = true;

                                Entity oBoxObj = oInBoxId.GetObject(OpenMode.ForRead) as Entity;

                                if(oBoxObj.Layer == LayerSheetNo)
                                {
                                    HasSheetCnt = true;
                                    oSheetCnt = oBoxObj;
                                }

                            }

                            // If curve and sheetcnt exist add the sheet number
                            if (HasSheetCnt && HasCurveId) 
                            {
                                if (oSheetCnt is DBText) mSheetCnt = mSheetCnt +", " + ((DBText)oSheetCnt).TextString;
                                if (oSheetCnt is MText) mSheetCnt = mSheetCnt + ", " + ((MText)oSheetCnt).Text;
                            }
                        }

                    }
                } 
            }

            return mSheetCnt;
        }

 

 

0 Likes
Message 11 of 13

alexisgacia
Advocate
Advocate

Hi,

 

I changed my code with the new one below.

 

What I did here is to detect the intersection between Curve and the Sheet, If not check again if Curve.Startpoint is in the Sheet.

 

private void _SelectObjectsFromExploded(object sender, EventArgs e)
        {
            Autodesk.Civil.ApplicationServices.CivilDocument civilDoc = Autodesk.Civil.ApplicationServices.CivilApplication.ActiveDocument;
            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;
            listBox1.Items.Clear();
            string mSheetBlockName = "SheetBlock";
            string mSheetLayerName = "Z_DWG_SHT";
            string mLabelLayerLName = "Z_DWG_SHT_NO";

            cSelection mSel = new cSelection();
            ObjectId mSheetBlockId = mSel.Select_SingeEntity("Select Sheet Block");

            // Set up our selection to only select 2D solids
            var pso = new PromptSelectionOptions();
            pso.MessageForAdding = "\nSelect Curve";

            //var sf = new SelectionFilter(new TypedValue[] { new TypedValue((int)DxfCode.Start, "3DSOLID") });

            //var psr = ed.GetSelection(pso, sf);
            var psr = ed.GetSelection(pso);

            if (psr.Status != PromptStatus.OK) return;
            using (doc.LockDocument())
            {
                DBObjectCollection mSheets = new DBObjectCollection();
                DBObjectCollection mValidSheets = new DBObjectCollection();
                BlockReference oSheet = null;

                doc.TransactionManager.EnableGraphicsFlush(true);
                using (Transaction tr = doc.TransactionManager.StartTransaction())
                {
                    var oBlk = tr.GetObject(mSheetBlockId, OpenMode.ForWrite);


                    // Preparing all sheets having valid layers
                    if (oBlk is BlockReference)
                    {
                        oSheet = oBlk as BlockReference;
                        if (oSheet.Name.ToUpper() != mSheetBlockName.ToUpper())
                        {
                            ed.WriteMessage("\nSelected block is not recognize as Block Sheet.");
                            return;
                        }

                        // Create Temp Sheets
                        oSheet.Explode(mSheets);
                        mValidSheets = GetValidSheetsOnly(tr, mSheets);

                    }
                      

                    // Check all selected Entities
                    if(oSheet != null) 
                    { 
                        foreach (ObjectId oID in psr.Value.GetObjectIds())
                        {
                            var o = tr.GetObject(oID, OpenMode.ForRead);

                            if (o is Curve)
                            { 
                                Curve mCurve = o as Curve;

                                //CreateLine(tr, mCurve.GeometricExtents.MinPoint, mCurve.GeometricExtents.MaxPoint);

                                string mSheetCnt = GetSheetNumberFromCollection(mValidSheets, mCurve);
                                listBox1.Items.Add(mSheetCnt);
                            }
                        }

                        // Clear Temporary Sheets
                        foreach (Entity ent in mValidSheets) 
                        {
                            //Entity ForDel = tr.GetObject(ent.ObjectId, OpenMode.ForWrite) as Entity;
                            //ForDel.Erase(); 
                            if(!ent.IsDisposed)ent.Dispose();
                        }
                    }
                    else
                    {
                        ed.WriteMessage("\nInvalid Block Selected.");
                    }

                    tr.Commit();
                }
            }


        }

string GetSheetNumberFromCollection(DBObjectCollection mSheets, Curve mCurve, string LayerSheet = "Z_DWG_SHT", string LayerSheetNo = "Z_DWG_SHT_NO")
        {
            dynamic acadApp = Application.AcadApplication;

            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;
            string mSheetCnt = "";

            // Get Sheets that Intersect the Curve or Containing the Curve
            DBObjectCollection TargetSheets = getIntersectCurveFromCollection(mSheets, mCurve);

            // Select Valid label then check if inside in 1 of the TargetSheets
            foreach(var oTrg in mSheets)
            {
                if(oTrg is DBText || oTrg is MText)
                {
                    Point3d mPosition = new Point3d();
                    bool IsValid = false;
                    string mSheetNo = "";
                    // Check Text Validity
                    if(oTrg is DBText)
                    {
                        mPosition = ((DBText)oTrg).Position;
                        if (((DBText)oTrg).Layer == "Z_DWG_SHT_NO") IsValid = true;
                        mSheetNo = ((DBText)oTrg).TextString;
                    }
                    else
                    {
                        mPosition = ((MText)oTrg).Location;
                        if (((MText)oTrg).Layer == "Z_DWG_SHT_NO") IsValid = true;
                        mSheetNo = ((MText)oTrg).Text;
                    }

                    // Check if Inside in 1 of the Sheet
                    foreach(var oSht in TargetSheets) 
                    {
                        if(oSht is Polyline)
                        {
                            Polyline mPL_Sheet = oSht as Polyline;
                            if (mPL_Sheet.Closed)
                            {
                                if(IsPointInside(mPosition, mPL_Sheet))
                                {
                                    mSheetCnt = mSheetCnt + "," + mSheetNo;
                                }
                            }
                        }
                    }
                }
            }
 
            return mSheetCnt;
        }

        DBObjectCollection getIntersectCurveFromCollection(DBObjectCollection oCol, Curve mCurve, string mValidLayerInCollection = "Z_DWG_SHT")
        {
            DBObjectCollection iSectObjs = new DBObjectCollection();
            foreach(var o in oCol)  // Loop all 
            {
                Point3dCollection iPts = new Point3dCollection();

                if(o is Curve)
                {
                    Curve mTrgCrv = o as Curve;

                    if (mTrgCrv.Layer == mValidLayerInCollection)
                    {                        
                        mTrgCrv.IntersectWith(mCurve, Intersect.OnBothOperands, iPts, IntPtr.Zero, IntPtr.Zero);
                        if (iPts.Count > 0) // Detected or intersecting objects
                        {
                            iSectObjs.Add(mTrgCrv);
                        }
                        else // Not intersecting
                        {
                            if (mTrgCrv.Closed && mTrgCrv is Polyline)
                            {
                                if(IsPointInside(mCurve.StartPoint, (Polyline)mTrgCrv))
                                {
                                    iSectObjs.Add(mTrgCrv);
                                }
                            }
                        }
                    }
                }
            }

            return iSectObjs;
        }
        private static bool IsPointInside(Point3d point, Polyline pline)
        {
            double tolerance = Tolerance.Global.EqualPoint;
            using (MPolygon mpg = new MPolygon())
            {
                mpg.AppendLoopFromBoundary(pline, true, tolerance);
                return mpg.IsPointInsideMPolygon(point, tolerance).Count == 1;
            }
        }

 

0 Likes
Message 12 of 13

Jeff_M
Consultant
Consultant

@alexisgacia Is the new code doing what you want? I got called away for a family emergency so have not had a chance to look into this further. Your new code is doing pretty much what I was going to attempt. The last step for the text would just loop through the text objects and see if the insertion point is inside the 'selected' sheets.

Jeff_M, also a frequent Swamper
EESignature
0 Likes
Message 13 of 13

alexisgacia
Advocate
Advocate

Hi @Jeff_M,

 

Good day.

 

Sorry for the late reply. It works well for me.

"The last step for the text would just loop through the text objects and see if the insertion point is inside the 'selected' sheets." Yes this is what I did.

 

Thank you very much.

 

0 Likes