예제 #1
0
        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();
            }
        }
예제 #2
0
            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);
                }
            }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }