private static void SearchWalls(List <LineSegment3d> outLines, List <LineSegment3d> allLines) { WallInfor wallInfo = null; using (var tolerance = new Utils.SafeToleranceOverride()) { wallInfo = WallRecognizer.getWallinfors(outLines, allLines); } if (wallInfo == null) { return; } // Test Code! var visited = new HashSet <WallInfor>(); var database = Application.DocumentManager.MdiActiveDocument.Database; using (var transaction = database.TransactionManager.StartTransaction()) { var modelspaceId = SymbolUtilityServices.GetBlockModelSpaceId(database); var modelspace = (BlockTableRecord)transaction.GetObject(modelspaceId, OpenMode.ForWrite); var color = Color.FromColorIndex(ColorMethod.ByAci, 4); // Cyan ObjectId layerId = LayerUtils.AddNewLayer(database, "temp-poly2", "Continuous", color); var currentInfo = wallInfo; var count = 0; while (currentInfo != null && currentInfo.outline != null) { if (visited.Contains(currentInfo)) { break; } var line = new Line(currentInfo.outline.StartPoint, currentInfo.outline.EndPoint); line.Color = color; line.LayerId = layerId; modelspace.AppendEntity(line); transaction.AddNewlyCreatedDBObject(line, add: true); foreach (var innerSeg in currentInfo.innerlines) { var innerLine = new Line(innerSeg.StartPoint, innerSeg.EndPoint); innerLine.Color = color; innerLine.LayerId = layerId; modelspace.AppendEntity(innerLine); transaction.AddNewlyCreatedDBObject(innerLine, add: true); } visited.Add(currentInfo); count++; currentInfo = currentInfo.next; if (currentInfo == wallInfo) { break; } } transaction.Commit(); } }
static void AddHolesToParcel(ObjectId parcelId, ObjectId groupId, ObjectId[] holeIds) { Database database = parcelId.Database; // 将扣除的孔洞等图形放到孔洞图层,以绿色醒目显示 var layerId = LayerUtils.GetLayerByName(database, "孔洞"); if (!layerId.IsValid) { layerId = LayerUtils.AddNewLayer(database, "孔洞", "Continuous", /*GREEN*/ 3); } // 看看选择的地块是不是真的在地块里面了 var availableHoles = new List <ObjectId>(); using (var tr = database.TransactionManager.StartTransaction()) { var reader = new DwgReader(); var curve = tr.GetObject(parcelId, OpenMode.ForRead) as Curve; if (curve != null && curve.Closed) { var polygon1 = reader.ReadCurveAsPolygon(tr, curve); foreach (var holeId in holeIds) { var hole = tr.GetObject(holeId, OpenMode.ForRead) as Curve; // 只添加地块为封闭的 if (hole == null || !hole.Closed) { continue; } // 继续,看看是不是在地块中间,不在就跳过 var polygon2 = reader.ReadCurveAsPolygon(tr, hole); if (!polygon1.Contains(polygon2)) { continue; } // 如果是,添加地块 hole.UpgradeOpen(); CadUtils.SetCassFlag(hole, CassFlagIsland); hole.LayerId = layerId; availableHoles.Add(holeId); // 如果组不是空,直接加入组 if (!groupId.IsNull) { GroupUtils.AppendEntityIntoGroup(database, groupId, holeId); } } } tr.Commit(); } // 如果没有group,创建group if (groupId.IsNull) { var ids = new ObjectIdCollection() { parcelId }; foreach (var availableHole in availableHoles) { ids.Add(availableHole); } GroupUtils.CreateNewGroup(database, "*A", ids); } }
private static ApartmentContourInfo GetApartmentContour(IEnumerable <ObjectId> linearIds) { var info = ApartmentContour.CalcContour(Application.DocumentManager.MdiActiveDocument, linearIds); var database = Application.DocumentManager.MdiActiveDocument.Database; // Test code ! using (var transaction = database.TransactionManager.StartTransaction()) { var contourSegments = info.Contour; var innerSegments = info.InternalSegments; // find out windows on wall, usually there are 4 or 3 parallel line segments for a window like below. // ----------------------- // ----------------------- // ----------------------- // ----------------------- const double maxWallWidth = 600; // todo Tolerance tol = new Tolerance(0.001, 0.001); List <LineSegment3d> sideWindowSegments = new List <LineSegment3d>(); List <List <LineSegment3d> > windowGroup = new List <List <LineSegment3d> >(); for (var i = 0; i < innerSegments.Count; i++) { var thisSeg = innerSegments[i]; //var startPt = innerSegments[i].StartPoint; //var endPt = innerSegments[i].EndPoint; // do check if the start and end points are on the wall //var cIndex = contourSegments.FindIndex((seg) => { // if (seg.IsOn(startPt, tol) && seg.IsOn(endPt, tol)) // return true; // return false; //}); // find out if the line segment is on the outer contour wall //var cIndex = contourSegments.FindIndex((seg) => //{ // if (seg.IsParallelTo(innerSegments[i], tol)) // { // var dist = seg.GetDistanceTo(thisSeg.MidPoint); // if (dist < maxWallWidth) // return true; // } // return false; //}); //if (cIndex != -1) { // find out all other parallel and equal length segments with this one var startPt = thisSeg.StartPoint; var endPt = thisSeg.EndPoint; double thisLength = thisSeg.Length; Vector3d direction = thisSeg.Direction.RotateBy(Math.PI / 2, Vector3d.ZAxis); Line3d startLine = new Line3d(startPt, direction); Line3d endLine = new Line3d(endPt, direction); List <LineSegment3d> parEqualSegs = new List <LineSegment3d>(); for (var j = 0; j < innerSegments.Count; j++) { if (i == j || innerSegments[j] == null) { continue; // itself } if (thisSeg.IsParallelTo(innerSegments[j]) && (startLine.IsOn(innerSegments[j].StartPoint, tol) && endLine.IsOn(innerSegments[j].EndPoint, tol)) || (startLine.IsOn(innerSegments[j].EndPoint, tol) && endLine.IsOn(innerSegments[j].StartPoint, tol))) { parEqualSegs.Add(innerSegments[j]); } } if (parEqualSegs.Count > 1) { Line3d helper1 = new Line3d(thisSeg.MidPoint, thisSeg.Direction); Line3d helper2 = new Line3d(thisSeg.MidPoint, direction); var intersects = helper1.IntersectWith(helper2); var basePt = intersects[0]; //direction = (thisSeg.MidPoint - basePt).GetNormal(); // sort them by direction parEqualSegs.Add(thisSeg); parEqualSegs.Sort((seg1, seg2) => { Vector3d vector1 = seg1.MidPoint - basePt; Vector3d vector2 = seg2.MidPoint - basePt; if (Math.Abs(vector1.DotProduct(direction) - vector2.DotProduct(direction)) < 0.001) { return(0); } else if (vector1.DotProduct(direction) > vector2.DotProduct(direction)) { return(1); } return(-1); }); List <LineSegment3d> thisWindow = new List <LineSegment3d>(); double distance = parEqualSegs[1].MidPoint.DistanceTo(parEqualSegs[0].MidPoint); if (distance < maxWallWidth / 2) { thisWindow.Add(parEqualSegs[0]); thisWindow.Add(parEqualSegs[1]); for (var k = 2; k < parEqualSegs.Count; k++) { var dist = parEqualSegs[k].MidPoint.DistanceTo(parEqualSegs[k - 1].MidPoint); if (thisWindow.Count > 4 || Math.Abs(dist - distance) > 100) { // we have find out 4 parallel lines or the distance is not equal to previous one break; } thisWindow.Add(parEqualSegs[k]); } if (thisWindow.Count > 2) { // this will be treaded as a valid window windowGroup.Add(thisWindow); } } } } } innerSegments.RemoveAll((seg) => { var index = windowGroup.FindIndex((window) => { return(window.Contains(seg)); }); if (index != -1) { return(true); } return(false); }); // end window var modelspaceId = SymbolUtilityServices.GetBlockModelSpaceId(database); var modelspace = (BlockTableRecord)transaction.GetObject(modelspaceId, OpenMode.ForWrite); var color1 = Color.FromColorIndex(ColorMethod.ByAci, 1); // 1: red ObjectId layerId = LayerUtils.AddNewLayer(database, "temp-poly", "Continuous", color1); for (var i = 0; i < windowGroup.Count; i++) { var window = windowGroup[i]; for (var j = 0; j < window.Count; j++) { var start = window[j].StartPoint; var end = window[j].EndPoint; var line = new Line(start, end); line.Color = color1; line.LayerId = layerId; modelspace.AppendEntity(line); transaction.AddNewlyCreatedDBObject(line, add: true); } } var color = Color.FromColorIndex(ColorMethod.ByAci, 3); // Green var polyline = new Polyline(); for (var i = 0; i < contourSegments.Count; i++) { var segment = contourSegments[i]; var start = segment.StartPoint; polyline.AddVertexAt(i, new Point2d(start.X, start.Y), 0, 0, 0); } polyline.Closed = true; polyline.Color = color; polyline.LayerId = layerId; modelspace.AppendEntity(polyline); transaction.AddNewlyCreatedDBObject(polyline, add: true); foreach (var segment in innerSegments) { var line = new Line(segment.StartPoint, segment.EndPoint); line.Color = color; line.LayerId = layerId; modelspace.AppendEntity(line); transaction.AddNewlyCreatedDBObject(line, add: true); } transaction.Commit(); } return(info); }
public static ApartmentContourInfo CalcContour(Document doc, IEnumerable <ObjectId> objectIdsList) { var newCreatedIds = new List <ObjectId>(); IEnumerable <ObjectId> curveIds = new List <ObjectId>(); IEnumerable <ObjectId> splitSourceIds = new List <ObjectId>(); List <ObjectId> duplicateIds = new List <ObjectId>(); using (var waitCursor = new WaitCursorSwitcher()) using (var tolerance = new SafeToleranceOverride()) { // 1. Break down all lines doc.Editor.WriteMessage("\n打断所有交叉线...\n"); var breakCrossingAlgorithm = new BreakCrossingObjectsQuadTree(doc.Editor); breakCrossingAlgorithm.Check(objectIdsList); var breakIdPairs = breakCrossingAlgorithm.Fix(eraseOld: false).ToList(); splitSourceIds = breakIdPairs.Select(it => it.Key); var checkIds = objectIdsList.Except(splitSourceIds).ToList(); foreach (var idPair in breakIdPairs) { newCreatedIds.AddRange(idPair.Value); checkIds.AddRange(idPair.Value); } // 2. Erase the duplcate curves doc.Editor.WriteMessage("\n排除重复线...\n"); var duplicateEraserAlgorithm = new DuplicateEntityEraserKdTree(doc.Editor, 0.0005); duplicateEraserAlgorithm.Check(checkIds); var crossingInfos = duplicateEraserAlgorithm.CrossingInfos; if (crossingInfos != null) { foreach (var curveCrossingInfo in crossingInfos) { checkIds.Remove(curveCrossingInfo.TargetId); duplicateIds.Add(curveCrossingInfo.TargetId); } // Deal with the source duplicate var groups = crossingInfos.GroupBy(it => it.TargetId); foreach (var g in groups) { if (g.Count() <= 1) { continue; } bool first = true; foreach (var curveCrossingInfo in g) { if (first) { first = false; continue; } checkIds.Remove(curveCrossingInfo.SourceId); duplicateIds.Add(curveCrossingInfo.SourceId); } } } // 3. Extend undershoot doc.Editor.WriteMessage("\n调整未及点...\n"); var extendUndershoots = new ExtendUnderShoots(doc.Editor, 0.001); extendUndershoots.Check(checkIds); var splittedIds = extendUndershoots.Fix(breakTarget: true); foreach (var pair in splittedIds) { checkIds.Remove(pair.Key); checkIds.AddRange(pair.Value); // Also recorded in newCreatedIds which will be removed at the end. if (newCreatedIds.Contains(pair.Key)) { newCreatedIds.Remove(pair.Key); newCreatedIds.AddRange(pair.Value); } } // 4. 排除0面积闭合线 doc.Editor.WriteMessage("\n排除零面积闭合线...\n"); var zeroAreaLoopIds = CurveUtils.GetZeroAreaLoop(checkIds, doc.Database); foreach (var zeroAreaLoopId in zeroAreaLoopIds) { checkIds.Remove(zeroAreaLoopId); duplicateIds.Add(zeroAreaLoopId); } // 5. 删除0长度对象 doc.Editor.WriteMessage("\n排除零长度对象...\n"); var zeroLengthEraser = new ZeroLengthEraser(doc.Editor); zeroLengthEraser.Check(checkIds); foreach (ObjectId zeroLengthId in zeroLengthEraser.ZerolengthObjectIdCollection) { checkIds.Remove(zeroLengthId); duplicateIds.Add(zeroLengthId); } curveIds = checkIds; //// Test code //using (var transaction = doc.Database.TransactionManager.StartTransaction()) //{ // var color = Color.FromColorIndex(ColorMethod.ByAci, 3); // Green // ObjectId layerId = LayerUtils.AddNewLayer(doc.Database, "temp-poly", "Continuous", color); // foreach (var polygonId in polygonIds) // { // var entity = (Entity)transaction.GetObject(polygonId, OpenMode.ForWrite); // entity.Color = color; // entity.LayerId = layerId; // } // transaction.Commit(); //} //return new List<Point2d>(); } // 2. Make polygons. doc.Editor.WriteMessage("开始分析外墙轮廓..."); var resultIds = new List <ObjectId>(); if (curveIds.Any()) { var color = Color.FromColorIndex(ColorMethod.ByAci, 3); // Green ObjectId layerId = LayerUtils.AddNewLayer(doc.Database, "temp-poly", "Continuous", color); using (var tolerance = new SafeToleranceOverride()) using (var waitCursor = new WaitCursorSwitcher()) { //var polygons = MinimalLoopSearcher2.Search(curveIds, doc); //using (var transaction = doc.Database.TransactionManager.StartTransaction()) //{ // var modelspaceId = SymbolUtilityServices.GetBlockModelSpaceId(doc.Database); // var modelspace = (BlockTableRecord)transaction.GetObject(modelspaceId, OpenMode.ForWrite); // foreach (var polyline in polygons) // { // polyline.Color = color; // polyline.LayerId = layerId; // var id = modelspace.AppendEntity(polyline); // resultIds.Add(id); // transaction.AddNewlyCreatedDBObject(polyline, true); // } // transaction.Commit(); //} resultIds = NtsUtils.PolygonizeLineStrings(doc.Database, curveIds, "temp-poly", color, 0.0001); } } // 3. Union all polygons var database = doc.Database; var partitioner = new DrawingPartitioner(database); partitioner.Check(resultIds); // 4. Get largest are polygon which is the apartment's contour var polylines = new List <Polyline>(); foreach (var region in partitioner.IsolatedRegions) { var polyline = new Polyline(region.Contour.Count); int i = 0; foreach (var point in region.Contour) { polyline.AddVertexAt(i++, new Point2d(point.X, point.Y), 0, 0, 0); } polyline.Closed = true; polylines.Add(polyline); } polylines.Sort((poly1, poly2) => { if (poly1.Area > poly2.Area) { return(-1); } return(1); }); if (polylines.Count >= 2) { var first = polylines[0]; var second = polylines[1]; // Exclude the situation if the largest polyline is a drawing frame. if (IsRectangle(first) && HaveSomeTextsOnBottom(first, database) && PolygonIncludeSearcher.IsInclude(first, second, null)) { polylines.RemoveAt(0); } } Polyline largestPolyline = polylines.FirstOrDefault(); var resultPoints = new List <Point2d>(); if (largestPolyline != null) { resultPoints = CurveUtils.GetDistinctVertices2D(largestPolyline, null); if (resultPoints[0] != resultPoints[resultPoints.Count - 1]) { resultPoints.Add(resultPoints[0]); } var clockwise = ComputerGraphics.ClockWise2(resultPoints.ToArray()); if (clockwise) { resultPoints.Reverse(); } //// Test code ! //using (var transaction = database.TransactionManager.StartTransaction()) //{ // var modelspaceId = SymbolUtilityServices.GetBlockModelSpaceId(database); // var modelspace = (BlockTableRecord)transaction.GetObject(modelspaceId, OpenMode.ForWrite); // var color = Color.FromColorIndex(ColorMethod.ByAci, 3); // Green // ObjectId layerId = LayerUtils.AddNewLayer(doc.Database, "temp-poly", "Continuous", color); // largestPolyline.Color = color; // largestPolyline.LayerId = layerId; // modelspace.AppendEntity(largestPolyline); // transaction.AddNewlyCreatedDBObject(largestPolyline, add: true); // foreach (var polyline in polylines) // { // if (polyline == largestPolyline) // continue; // polyline.Color = color; // polyline.LayerId = layerId; // modelspace.AppendEntity(polyline); // transaction.AddNewlyCreatedDBObject(polyline, add: true); // } // transaction.Commit(); //} } // Get contour linesegments from resultPoints var contourSegments = new List <LineSegment3d>(); var innerSegments = new List <LineSegment3d>(); if (resultPoints.Count > 0) { for (var i = 0; i < resultPoints.Count - 1; i++) { var start = new Point3d(resultPoints[i].X, resultPoints[i].Y, 0); var end = new Point3d(resultPoints[i + 1].X, resultPoints[i + 1].Y, 0); var segment = new LineSegment3d(start, end); contourSegments.Add(segment); } // Get inner linesegments using (var tr = doc.Database.TransactionManager.StartTransaction()) { var contourArray = resultPoints.ToArray(); foreach (var objId in curveIds) { var point2ds = CurveUtils.GetDistinctVertices2D(objId, tr); for (var i = 0; i < point2ds.Count - 1; i++) { var start = point2ds[i]; var end = point2ds[i + 1]; if (start.IsEqualTo(end)) { continue; } // TODO: no need to calculate again for startInPoly. var startInPoly = ComputerGraphics.IsInPolygon2(start, contourArray); var endInPoly = ComputerGraphics.IsInPolygon2(end, contourArray); if ((startInPoly == 0 && endInPoly == 0) || (startInPoly == -1 && endInPoly == -1)) { continue; } var segment = new LineSegment3d(new Point3d(start.X, start.Y, 0), new Point3d(end.X, end.Y, 0)); innerSegments.Add(segment); } } tr.Commit(); } } // 5. Delete the polygons of resultIds using (var tr = doc.Database.TransactionManager.StartTransaction()) { foreach (var objId in resultIds) { if (objId.IsErased) { continue; } var dbObj = tr.GetObject(objId, OpenMode.ForWrite); dbObj.Erase(); } //////////////////////////////////////////////////////////////////////////////////////// tr.Commit(); } // Delete the splited curves using (var tr = doc.Database.TransactionManager.StartTransaction()) { foreach (var newCreatedId in newCreatedIds) { if (newCreatedId.IsErased) { continue; } var dbObj = tr.GetObject(newCreatedId, OpenMode.ForWrite); dbObj.Erase(); } //////////////////////////////////////////////////////////////////////////////////////// tr.Commit(); } var result = new ApartmentContourInfo() { Contour = contourSegments, InternalSegments = innerSegments }; return(result); }