I have closed polylines - few rectangles, some of them are inside another (picture).
Now I would like to:
1. Calculate areas of each closed polyline.
2. Calculate areas of each closed polyline subtract area of inside polyline.
Everything seems to work if I have only 1 polyline or 2 (first inside second). If I have more, I'm always getting zero.
Here is my code (ClipLines is a list of closed polylines):
private static void CalculateClips(List<ClipsLines> cls) { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; DBObjectCollection dbCl = new DBObjectCollection(); DBObjectCollection myRegionColl = new DBObjectCollection(); using (Transaction tr = db.TransactionManager.StartTransaction()) { try { foreach (ClipsLines cl in cls) { DBObject obj = tr.GetObject(cl.id, OpenMode.ForRead); dbCl.Add(obj); } myRegionColl = Region.CreateFromCurves(dbCl); for (int i = 0; i < myRegionColl.Count; i++) { Region r1 = myRegionColl[i] as Region; double mainRegArea = r1.Area; for (int j = 0; j < myRegionColl.Count; j++) { if (i != j) { Region r2 = myRegionColl[j] as Region; r1.BooleanOperation(BooleanOperationType.BoolSubtract, r2); if (r1.Area > 0) mainRegArea -= r1.Area; } } doc.Editor.WriteMessage("\nReg1: " + mainRegArea); } tr.Commit(); } catch (Autodesk.AutoCAD.Runtime.Exception ex) { tr.Abort(); utilities.ErrorMessage("\nClips calculating exception!\n" + ex.Message); } } }
I've written this code:
double[] areas = new double[clipsLines.Count]; for (int i = 0; i < clipsLines.Count; i++) { DBObject obj1 = tr.GetObject(clipsLines[i].id, OpenMode.ForRead); Polyline l = (Polyline)obj1 as Polyline; double correctionArea = 0.0; for (int j = 0; j < clipsLines.Count; j++) { if (i != j) { DBObjectCollection dbCl = new DBObjectCollection(); DBObject obj2 = tr.GetObject(clipsLines[j].id, OpenMode.ForRead); dbCl.Add(obj1); dbCl.Add(obj2); DBObjectCollection myRegionColl = new DBObjectCollection(); myRegionColl = Region.CreateFromCurves(dbCl); Region r1 = myRegionColl[0] as Region; Region r2 = myRegionColl[1] as Region; double firstArea = r1.Area; r1.BooleanOperation(BooleanOperationType.BoolIntersect, r2); if (r1.Area - firstArea == 0) correctionArea += (r1.Area); } } areas[i] = l.Area - correctionArea;
For few polylines it works pretty good, but if I have more, AutoCAD is crashing down.
Hello,
Try disposing those regions explicitly.
The crash could be related the topics discussed in these posts :
Try this code, tested on A2010,
see comments within
[CommandMethod("Rea")] public static void testUnionContours() { Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument; Editor ed = doc.Editor; Database db = doc.Database; // Argument to choose operation mode bool doUnion = false;// to subtract regions if many regions inside the biggest one, otherwise set to true List<Region> regLst = new List<Region>(); List<Polyline> delPline = new List<Polyline>(); //start a transaction using (Transaction tr = db.TransactionManager.StartTransaction()) { TypedValue[] tvs = new TypedValue[] {new TypedValue(0, "lwpolyline"), new TypedValue(70, 1) }; SelectionFilter filter = new SelectionFilter(tvs); PromptSelectionOptions pso = new PromptSelectionOptions(); pso.MessageForRemoval = "\nSelect closed polylines only: "; pso.MessageForAdding = "\nSelect closed polylines: "; PromptSelectionResult result = ed.GetSelection(filter); if (result.Status != PromptStatus.OK) return; // if (result.Value.Count != 2) return; try { SelectionSet sset = result.Value; ObjectId[] ids = sset.GetObjectIds(); BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite, false); Region objreg1 = new Region(); // Region objreg2 = new Region(); for (int n = 0; n < ids.Count(); n++) { DBObject obj = tr.GetObject(ids[n], OpenMode.ForRead) as DBObject; Polyline pline1 = obj as Polyline; if (pline1 == null) return; // Add the polyline to the List to rerase them all at the end of execution delPline.Add(pline1); // Add the polyline to the array DBObjectCollection objArray1 = new DBObjectCollection(); objArray1.Add(pline1); // create the 1 st region DBObjectCollection objRegions1 = new DBObjectCollection(); objRegions1 = Region.CreateFromCurves(objArray1); objreg1 = objRegions1[0] as Region; btr.AppendEntity(objreg1); tr.AddNewlyCreatedDBObject(objreg1, true); objreg1.ColorIndex = 1;//optional // Add the region to the List for the future work regLst.Add(objreg1); } ed.WriteMessage("\nCount regions:\t{0}\n", regLst.Count); //________________________________________________________// // Sort regions by areas Region[] items = regLst.ToArray(); Array.Sort(items, (Region x, Region y) => y.Area.CompareTo(x.Area)); // Get the biggest region first Region mainReg = items[0]; ed.WriteMessage("\nMain region area:\t{0:f3}\n", items[0].Area); if (!mainReg.IsWriteEnabled) mainReg.UpgradeOpen(); // Start iteration from the second region int i = 1; do { Region reg1 = items[i]; Region reg2 = items[i + 1]; if ((reg1 == null) || (reg2 == null)) { break; } else { // Subtract region 1 from region 2 if (reg1.Area > reg2.Area) { // Subtract the smaller region from the larger one // reg1.BooleanOperation(BooleanOperationType.BoolUnite, reg2); if (!doUnion) { mainReg.BooleanOperation(BooleanOperationType.BoolSubtract, reg1); } else { mainReg.BooleanOperation(BooleanOperationType.BoolUnite, reg1); } } else { // Subtract the smaller region from the larger one reg2.BooleanOperation(BooleanOperationType.BoolUnite, reg1); if (!doUnion) { mainReg.BooleanOperation(BooleanOperationType.BoolSubtract, reg2); } else { mainReg.BooleanOperation(BooleanOperationType.BoolUnite, reg2); } } } // Increment counter i++; } while (i < items.Length - 1); mainReg.ColorIndex = 121; //__________________________________________________________// //Erase polylines , optional foreach (Polyline poly in delPline) { if (poly != null) { if (!poly.IsWriteEnabled) poly.UpgradeOpen(); poly.Erase(); if (!poly.IsDisposed) poly.Dispose(); } } tr.Commit(); } catch (Autodesk.AutoCAD.Runtime.Exception ex) { ed.WriteMessage("\nBoolean operation exception!\n" + ex.Message + "n" + ex.StackTrace); } finally { ed.WriteMessage(new Autodesk.AutoCAD.Runtime.ErrorStatus().ToString());//optional, might be removed } } }
~'J'~