Пример #1
0
        public override void Check(IEnumerable <ObjectId> selectedObjectIds)
        {
            if (!selectedObjectIds.Any())
            {
                return;
            }

            // 1. Create a kd tree
            var database    = Database;
            var allVertices = new List <CurveVertex>();

            using (var transaction = database.TransactionManager.StartTransaction())
            {
                foreach (var objectId in selectedObjectIds)
                {
                    var curve = transaction.GetObject(objectId, OpenMode.ForRead) as Curve;
                    if (curve == null)
                    {
                        continue;
                    }
                    var vertices = CurveUtils.GetDistinctVertices(curve, transaction);
                    allVertices.AddRange(vertices.Select(it => new CurveVertex(it, objectId)));
                }
                transaction.Commit();
            }
            var kdTree = new CurveVertexKdTree <CurveVertex>(allVertices, it => it.Point.ToArray(), ignoreZ: true);

            // 3. Filter out points that on same curve
            var visited = new HashSet <CurveVertex>();

            using (var tolerance = new SafeToleranceOverride(1E-5, 1E-5))
                foreach (var curveVertex in allVertices)
                {
                    if (visited.Contains(curveVertex))
                    {
                        continue;
                    }

                    var nears     = kdTree.NearestNeighbours(curveVertex.Point.ToArray(), _tolerance);
                    var qualified = new List <CurveVertex>();
                    qualified.Add(curveVertex);
                    foreach (var near in nears)
                    {
                        visited.Add(near);
                        if (near.Point == curveVertex.Point)
                        {
                            continue;
                        }
                        qualified.Add(near);
                    }
                    if (qualified.Count > 1)
                    {
                        _nearVertices.Add(qualified);
                    }
                }
        }
Пример #2
0
        /// <summary>
        /// New check - start the settings dialog and check.
        /// </summary>
        /// <returns></returns>
        public bool NewMapCleanCheckWithDialog()
        {
            var dialog       = DialogService.Instance.CreateDialog <ActionsSettingDialog>(null, _actionsSettingViewModel);
            var dialogResult = dialog.ShowDialog();

            if (dialogResult == null || !dialogResult.Value)
            {
                return(false);
            }

            // Clear all check results first.
            ClearCheckResults(raiseEvent: true);

            // Will check all curves in model space.
            OnlyCheckPolyline = false;
            var selectedIds = PrepareObjectIdsForCheck();

            if (selectedIds == null || !selectedIds.Any())
            {
                DialogService.Instance.ShowMessageBox(_actionsSettingViewModel, "图形区没有实体可检查", "提示:",
                                                      MessageBoxButton.OK, MessageBoxImage.Information, MessageBoxResult.OK);
                return(false);
            }

            // If breaking objects, we need to break all crosing objects first.
            if (_actionsSettingViewModel.ActionSelectVM.BreakCrossingObjects)
            {
                using (var toleranceSWitcher = new SafeToleranceOverride())
                {
                    var algorithm = new BreakCrossingObjectsQuadTree(Document.Editor);
                    algorithm.Check(selectedIds);

                    Document.Editor.WriteMessage("\n共找到{0}个交叉对象,开始打断...", algorithm.CrossingInfos.Count());
                    algorithm.Fix(eraseOld: true);
                    Document.Editor.WriteMessage("\n打断所有交叉对象成功!\n");
                }
            }

            // Create actions
            _executingActions.Clear();
            foreach (var action in _actionsSettingViewModel.ActionSelectVM.CheckedItems)
            {
                _executingActions.Add(action.ActionType);
            }

            // After objects are broken, need to update selectedIds.
            if (_actionsSettingViewModel.ActionSelectVM.BreakCrossingObjects)
            {
                selectedIds = PrepareObjectIdsForCheck();
            }

            NewCheckWithPrompt(selectedIds, "拓扑错误");
            return(true);
        }
Пример #3
0
        public static Dictionary <ObjectId, List <Point3d> > CalculateIntersection(IEnumerable <ObjectId> objectIds,
                                                                                   bool includeInline, Database database)
        {
            IEnumerable <IntersectionInfo> intersections = null;
            // 调低计算精度,否则有些交叉因为精度问题算不出来
            var oldTolerance = DoubleExtensions.STolerance;

            DoubleExtensions.STolerance = 1e-05;
            using (var tolerance = new SafeToleranceOverride(DoubleExtensions.STolerance))
                using (var transaction = database.TransactionManager.StartTransaction())
                {
                    // Build curve bsp tree and search all intersections
                    var curve2dBspBuilder = new Curve2dBspBuilder(objectIds, transaction);
                    intersections = curve2dBspBuilder.SearchRealIntersections(includeInline: includeInline);
                    transaction.Commit();
                }
            // 恢复默认的计算精度值
            DoubleExtensions.STolerance = oldTolerance;

            // Group intersections by object id.
            var group = new Dictionary <ObjectId, List <Point3d> >();

            foreach (var intersection in intersections)
            {
                if (!group.ContainsKey(intersection.SourceId))
                {
                    group[intersection.SourceId] = new List <Point3d>();
                }
                var points = group[intersection.SourceId];
                if (!points.Contains(intersection.IntersectPoint))
                {
                    points.Add(intersection.IntersectPoint);
                }

                if (intersection.SourceId == intersection.TargetId)
                {
                    continue;
                }

                if (!group.ContainsKey(intersection.TargetId))
                {
                    group[intersection.TargetId] = new List <Point3d>();
                }
                points = group[intersection.TargetId];
                if (!points.Contains(intersection.IntersectPoint))
                {
                    points.Add(intersection.IntersectPoint);
                }
            }
            return(group);
        }
Пример #4
0
        protected override IEnumerable <CheckResult> CheckImpl(IEnumerable <ObjectId> selectedObjectIds)
        {
            var results  = new List <ZeroAreaLoopCheckResult>();
            var database = Document.Database;

            using (var switcher = new SafeToleranceOverride())
            {
                using (var transaction = database.TransactionManager.StartTransaction())
                {
                    foreach (var selectedObjectId in selectedObjectIds)
                    {
                        var dbObj = transaction.GetObject(selectedObjectId, OpenMode.ForRead);
                        var curve = dbObj as Curve;
                        if (curve == null || curve is Xline) // Xline will cause exception
                        {
                            continue;
                        }

                        bool isClosed   = false;
                        var  polyline   = curve as Polyline;
                        var  polyline2d = curve as Polyline2d;
                        if (polyline != null)
                        {
                            isClosed = polyline.Closed;
                        }
                        else if (polyline2d != null)
                        {
                            isClosed = polyline2d.Closed;
                        }

                        if (!isClosed)
                        {
                            var startPoint = curve.StartPoint;
                            var endPoint   = curve.EndPoint;
                            if (startPoint.IsEqualTo(endPoint))
                            {
                                isClosed = true;
                            }
                        }

                        if (isClosed && curve.Area.EqualsWithTolerance(0.0, 0.00001))
                        {
                            var checkResult = new ZeroAreaLoopCheckResult(selectedObjectId, curve.StartPoint);
                            results.Add(checkResult);
                        }
                    }
                    transaction.Commit();
                }
            }
            return(results);
        }
Пример #5
0
        public override void Check(IEnumerable <ObjectId> selectedObjectIds)
        {
            if (!selectedObjectIds.Any())
            {
                return;
            }

            var database = Editor.Document.Database;
            var group    = CalculateIntersection(selectedObjectIds, true, database);

            // Check each intersection whether it's a missing vertex.
            // TODO: 用一个比较低的精度去比较一个交点是否是顶点
            using (var tolerance = new SafeToleranceOverride(_tolerance, _tolerance))
                using (var transaction = database.TransactionManager.StartTransaction())
                {
                    foreach (var pair in group)
                    {
                        var curve = transaction.GetObject(pair.Key, OpenMode.ForRead) as Curve;
                        if (curve == null)
                        {
                            continue;
                        }

                        var vertices         = CurveUtils.GetDistinctVertices(curve, transaction);
                        var noneVertexPoints = new List <Point3d>();
                        foreach (var point in pair.Value)
                        {
                            var ret = CheckPointIsVertex(vertices, point, transaction);
                            if (!ret)
                            {
                                noneVertexPoints.Add(point);
                            }
                        }

                        if (noneVertexPoints.Count > 0)
                        {
                            _missingVertexInfos.Add(new MissingVertexInfo()
                            {
                                PolylineId = pair.Key,
                                Positions  = noneVertexPoints
                            });
                        }
                    }
                    transaction.Commit();
                }
        }
Пример #6
0
        public bool CheckAndFixAll(IEnumerable <ObjectId> ids)
        {
            var  watch  = Stopwatch.StartNew();
            bool result = false;

            using (var switcher = new SafeToleranceOverride())
            {
                result = CheckAndFixAllImpl(ids);
            }
            watch.Stop();
            var elapseMs = watch.ElapsedMilliseconds;

            if (Document != null)
            {
                Document.Editor.WriteMessage("\n本次检查用时{0}毫秒\n", elapseMs);
            }
            return(result);
        }
Пример #7
0
 public MapClean.Status Fix(CheckResult checkResult, out List <ObjectId> resultIds)
 {
     if (checkResult.SourceIds != null)
     {
         foreach (var sourceId in checkResult.SourceIds)
         {
             if (!sourceId.IsValid || sourceId.IsErased)
             {
                 resultIds = new List <ObjectId>();
                 return(Status.Invalid);
             }
         }
     }
     using (var siwtcher = new SafeToleranceOverride())
     {
         return(FixImpl(checkResult, out resultIds));
     }
 }
Пример #8
0
        public IEnumerable <CheckResult> Check(IEnumerable <ObjectId> selectedObjectIds)
        {
            var watch = Stopwatch.StartNew();

            IEnumerable <CheckResult> result = null;

            using (var waitCursor = new WaitCursorSwitcher())
                using (var switcher = new SafeToleranceOverride())
                {
                    result = CheckImpl(selectedObjectIds);
                }

            watch.Stop();
            var elapseMs = watch.ElapsedMilliseconds;

            if (Document != null)
            {
                Document.Editor.WriteMessage("\n本次检查用时{0}毫秒\n", elapseMs);
            }

            return(result);
        }
Пример #9
0
        public static void TestSearchMinimumPolygons()
        {
            var drawingDb = Application.DocumentManager.MdiActiveDocument.Database;
            var editor    = Application.DocumentManager.MdiActiveDocument.Editor;

            editor.WriteMessage("\n选择一条或几条闭合曲线:\n");
            var result = editor.GetSelection();

            if (result.Status != PromptStatus.OK)
            {
                return;
            }
            var polylineids = result.Value.GetObjectIds();

            using (var tolerance = new SafeToleranceOverride(null, null))
                using (var transaction = drawingDb.TransactionManager.StartTransaction())
                {
                    var polylines = new List <Polyline>();
                    foreach (var polylineid in polylineids)
                    {
                        var polyline = transaction.GetObject(polylineid, OpenMode.ForRead) as Polyline;
                        polylines.Add(polyline.Clone() as Polyline);
                    }
                    Dictionary <Curve, List <Curve> > replaced = null;
                    var polygons     = MinimalLoopSearcher2.SearchMinimalPolygons(polylines, out replaced);
                    var modelspaceId = SymbolUtilityServices.GetBlockModelSpaceId(drawingDb);
                    var modelspace   = transaction.GetObject(modelspaceId, OpenMode.ForWrite) as BlockTableRecord;
                    foreach (var polyline in polygons)
                    {
                        polyline.Layer = "dk";
                        polyline.Color = Color.FromColorIndex(ColorMethod.ByAci, 3);
                        modelspace.AppendEntity(polyline);
                        transaction.AddNewlyCreatedDBObject(polyline, true);
                    }
                    transaction.Commit();
                }
        }
Пример #10
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);
        }