private IEnumerable <CurveCrossingInfo> SearchDuplicateEntities2(ObjectId curveId, CurveVertexKdTree <CurveVertex> kdTree,
                                                                         HashSet <KeyValuePair <ObjectId, ObjectId> > visited, Transaction transaction)
        {
            var result = new List <CurveCrossingInfo>();
            var curve  = transaction.GetObject(curveId, OpenMode.ForRead) as Curve;

            if (curve == null)
            {
                return(new List <CurveCrossingInfo>());
            }
            var extents      = curve.GeometricExtents;
            var nearVertices = kdTree.BoxedRange(extents.MinPoint.ToArray(), extents.MaxPoint.ToArray());

            foreach (var nearVertex in nearVertices)
            {
                if (nearVertex.Id == curveId ||
                    visited.Contains(new KeyValuePair <ObjectId, ObjectId>(curveId, nearVertex.Id)) ||
                    visited.Contains(new KeyValuePair <ObjectId, ObjectId>(nearVertex.Id, curveId)))
                {
                    continue;
                }
                var sourceVertices = CurveUtils.GetDistinctVertices(curve, transaction);
                var targetVertices = CurveUtils.GetDistinctVertices(nearVertex.Id, transaction);
                var identical      = PolygonIncludeSearcher.AreIdenticalCoordinates(sourceVertices, targetVertices);
                if (identical)
                {
                    result.Add(new CurveCrossingInfo(curveId, nearVertex.Id, sourceVertices.ToArray()));
                }
                visited.Add(new KeyValuePair <ObjectId, ObjectId>(curveId, nearVertex.Id));
            }
            return(result);
        }
Exemple #2
0
        public static IEnumerable <KeyValuePair <CurveSegment, CurveSegment> > SearchNearSegments(IEnumerable <ObjectId> selectedObjectIds, double tolerance)
        {
            var segments = GetAllCurveSegments(selectedObjectIds, tolerance, onlyForClosedPolygon: true);
            var vertices = new List <CollisionVertex>();

            foreach (var segment in segments)
            {
                var collisionVertices = segment.MiniBoundingBox.Select(it => new CollisionVertex()
                {
                    Point   = new Point3d(it.X, it.Y, 0.0),
                    Segment = segment
                });
                vertices.AddRange(collisionVertices);
            }

            // Create kd tree
            var kdTree = new CurveVertexKdTree <CollisionVertex>(vertices, it => it.Point.ToArray(), ignoreZ: true);
            // Use kd tree to check collision bounding box's intersection
            var segmentPairs = new HashSet <KeyValuePair <CurveSegment, CurveSegment> >();

            foreach (var segment in segments)
            {
                var extents = segment.GetExtents();
                if (extents == null)
                {
                    continue;
                }
                var minPoint     = extents.Value.MinPoint;
                var maxPoint     = extents.Value.MaxPoint;
                var nearVertices = kdTree.BoxedRange(new double[] { minPoint.X, minPoint.Y, 0.0 },
                                                     new double[] { maxPoint.X, maxPoint.Y, 0.0 });
                foreach (var collisionVertex in nearVertices)
                {
                    if (collisionVertex.Segment.EntityId == segment.EntityId ||
                        segmentPairs.Contains(new KeyValuePair <CurveSegment, CurveSegment>(segment, collisionVertex.Segment)) ||
                        segmentPairs.Contains(new KeyValuePair <CurveSegment, CurveSegment>(collisionVertex.Segment, segment)))
                    {
                        continue;
                    }

                    var boundingBox = segment.MiniBoundingBox.ToList();
                    boundingBox.Add(segment.MiniBoundingBox[0]);
                    if (!ComputerGraphics.IsInPolygon(boundingBox.ToArray(), new Point2d(collisionVertex.Point.X, collisionVertex.Point.Y), 4))
                    {
                        continue;
                    }

                    segmentPairs.Add(new KeyValuePair <CurveSegment, CurveSegment>(segment, collisionVertex.Segment));
                }
            }

            return(segmentPairs);
        }
        IEnumerable <ObjectId> GetNearPolygonIds(CurveVertexKdTree <CurveVertex> kdTree,
                                                 ObjectId polygonId, HashSet <ObjectId> visitedIds, Transaction transaction)
        {
            var result  = new HashSet <ObjectId>();
            var curve   = (Curve)transaction.GetObject(polygonId, OpenMode.ForRead);
            var extents = curve.GeometricExtents;
            var dir     = (extents.MaxPoint - extents.MinPoint).GetNormal();
            // 向外扩张0.1
            var minPoint     = extents.MinPoint - dir * 0.1;
            var maxPoint     = extents.MaxPoint + dir * 0.1;
            var nearVertices = kdTree.BoxedRange(minPoint.ToArray(), maxPoint.ToArray());

            foreach (var curveVertex in nearVertices)
            {
                // 不要包含本身
                if (curveVertex.Id == polygonId || visitedIds.Contains(curveVertex.Id))
                {
                    continue;
                }

                result.Add(curveVertex.Id);
            }
            return(result);
        }
        public override void Check(IEnumerable <ObjectId> selectedObjectIds)
        {
            if (!selectedObjectIds.Any())
            {
                return;
            }

            var allVertices = new List <CurveVertex>();
            var curveIds    = new List <ObjectId>();

            using (var transaction = this.Database.TransactionManager.StartTransaction())
            {
                foreach (var objId in selectedObjectIds)
                {
                    var curve = transaction.GetObject(objId, OpenMode.ForRead) as Curve;
                    if (curve == null)
                    {
                        continue;
                    }
                    if (!IsCurveClosed(curve))
                    {
                        continue;
                    }

                    curveIds.Add(objId);
                    var vertices = CurveUtils.GetDistinctVertices(curve, transaction);
                    allVertices.AddRange(vertices.Select(it => new CurveVertex(it, objId)));
                }
                transaction.Commit();
            }
            var kdTree = new CurveVertexKdTree <CurveVertex>(allVertices, it => it.Point.ToArray(), ignoreZ: true);

            // Use kd tree to check include.
            var analyzed = new HashSet <KeyValuePair <ObjectId, ObjectId> >();

            using (var transaction = this.Database.TransactionManager.StartTransaction())
            {
                foreach (var objectId in curveIds)
                {
                    var curve        = transaction.GetObject(objectId, OpenMode.ForRead) as Curve;
                    var extents      = curve.GeometricExtents;
                    var nearVertices = kdTree.BoxedRange(extents.MinPoint.ToArray(), extents.MaxPoint.ToArray());

                    foreach (var curveVertex in nearVertices)
                    {
                        if (curveVertex.Id == objectId ||
                            analyzed.Contains(new KeyValuePair <ObjectId, ObjectId>(objectId, curveVertex.Id)))
                        {
                            continue;
                        }

                        analyzed.Add(new KeyValuePair <ObjectId, ObjectId>(objectId, curveVertex.Id));
                        var targetCurve = transaction.GetObject(curveVertex.Id, OpenMode.ForRead) as Curve;
                        if (IsInclude(curve, targetCurve, transaction))
                        {
                            _includePolygons.Add(new KeyValuePair <ObjectId, ObjectId>(objectId, curveVertex.Id));
                        }
                    }
                }
                transaction.Commit();
            }
        }
        private IEnumerable <IntersectionInfo> GetUnderShootIntersections2(IEnumerable <ObjectId> selectedObjectIds,
                                                                           IEnumerable <CurveVertex> danglingVertices, double tolerance, Transaction transaction)
        {
            if (danglingVertices == null || !danglingVertices.Any())
            {
                return(new List <IntersectionInfo>());
            }

            var intersectMap      = new Dictionary <CurveVertex, List <CurveVertex> >();
            var desireExtendTypes = new Dictionary <CurveVertex, ExtendType>();

            foreach (var vertex in danglingVertices)
            {
                var curve         = transaction.GetObject(vertex.Id, OpenMode.ForRead);
                var desiredExtend = CurveUtils.GetExtendType((Curve)curve, vertex.Point);
                desireExtendTypes[vertex] = desiredExtend;
            }

            // 创建一个kdtree
            var kdTree = new CurveVertexKdTree <CurveVertex>(danglingVertices, it => it.Point.ToArray(), ignoreZ: true);

            foreach (var objectId in selectedObjectIds)
            {
                var curve = transaction.GetObject(objectId, OpenMode.ForRead) as Curve;
                if (curve == null)
                {
                    continue;
                }

                // 预检
                var curveExtents = curve.GeometricExtents;
                var vertices     = kdTree.BoxedRange(curveExtents.MinPoint.ToArray(), curveExtents.MaxPoint.ToArray());
                if (vertices == null || !vertices.Any())
                {
                    continue;
                }

                var segments             = CurveUtils.GetSegment2dsOfCurve(curve, transaction);
                var segmentsForCollision = segments.Select(it => new CurveSegmentForCollision()
                {
                    LineSegment     = it,
                    EntityId        = objectId,
                    MiniBoundingBox = CurveSegmentForCollision.CreateCollisionBoundingBox(it, tolerance)
                });
                foreach (var curveSegmentForCollision in segmentsForCollision)
                {
                    var extents = curveSegmentForCollision.GetExtents();
                    if (extents == null)
                    {
                        continue;
                    }
                    var minPoint     = extents.Value.MinPoint;
                    var maxPoint     = extents.Value.MaxPoint;
                    var nearVertices = kdTree.BoxedRange(new double[] { minPoint.X, minPoint.Y, 0.0 },
                                                         new double[] { maxPoint.X, maxPoint.Y, 0.0 });

                    if (!nearVertices.Any())
                    {
                        continue;
                    }

                    var boundingBox = curveSegmentForCollision.MiniBoundingBox.ToList();
                    boundingBox.Add(curveSegmentForCollision.MiniBoundingBox[0]);
                    foreach (var curveVertex in nearVertices)
                    {
                        if (!ComputerGraphics.IsInPolygon(boundingBox.ToArray(), new Point2d(curveVertex.Point.X, curveVertex.Point.Y), 4))
                        {
                            continue;
                        }

                        var danglingCurve   = (Curve)transaction.GetObject(curveVertex.Id, OpenMode.ForRead);
                        var danglingSegment = GetExtendLineSegment(danglingCurve, curveVertex.Point, transaction);
                        var danglineLine    = new Line2d(danglingSegment.StartPoint, danglingSegment.EndPoint);
                        var intersectPoints = danglineLine.IntersectWith(curveSegmentForCollision.LineSegment);
                        if (intersectPoints == null || intersectPoints.Length <= 0)
                        {
                            continue;
                        }

                        var intersectPoint2D = intersectPoints[0];
                        var param            = danglingSegment.GetParameterOf(intersectPoint2D);
                        var extendType       = CurveIntersectUtils.ParamToExtendTypeForLine(param);
                        if (extendType != desireExtendTypes[curveVertex])
                        {
                            continue;
                        }

                        var intersectPoint = new Point3d(intersectPoint2D.X, intersectPoint2D.Y, 0);
                        var dist           = (intersectPoint - curveVertex.Point).Length;
                        if (dist.Larger(tolerance))
                        {
                            continue;
                        }

                        List <CurveVertex> intersectList;
                        intersectMap.TryGetValue(curveVertex, out intersectList);
                        if (intersectList == null)
                        {
                            intersectList             = new List <CurveVertex>();
                            intersectMap[curveVertex] = intersectList;
                        }

                        intersectList.Add(new CurveVertex(intersectPoint, curveSegmentForCollision.EntityId));
                    }
                }
            }

            // 分析交点
            var result = new List <IntersectionInfo>();

            foreach (var pair in intersectMap)
            {
                var vertex         = pair.Key;
                var extendVertices = pair.Value;
                var nearest        = extendVertices[0];
                var nearsetDist    = (nearest.Point - vertex.Point).Length;
                for (int i = 1; i < extendVertices.Count; i++)
                {
                    var dist = (extendVertices[i].Point - vertex.Point).Length;
                    if (dist < nearsetDist)
                    {
                        nearsetDist = dist;
                        nearest     = extendVertices[i];
                    }
                }

                result.Add(new IntersectionInfo(vertex.Id, desireExtendTypes[vertex], nearest.Id, ExtendType.None, nearest.Point));
            }
            return(result);
        }
        /// <summary>
        /// 检查和sourceIds相交的objectIds
        /// </summary>
        /// <param name="objectIds"></param>
        /// <param name="sourceIds"></param>
        public void Check(IEnumerable <ObjectId> objectIds, IEnumerable <ObjectId> sourceIds)
        {
            if (!objectIds.Any() || !sourceIds.Any())
            {
                return;
            }

            var database = Editor.Document.Database;
            // Build a kd tree for searching intersection
            var allVertices     = new List <CurveVertex>();
            var closedSourceIds = new List <ObjectId>();

            using (var transaction = database.TransactionManager.StartTransaction())
            {
                foreach (var objectId in objectIds)
                {
                    var curve = transaction.GetObject(objectId, OpenMode.ForRead) as Curve;
                    if (curve == null)
                    {
                        continue;
                    }
                    if (!IsCurveClosed(curve))
                    {
                        continue;
                    }

                    var vertices = CurveUtils.GetDistinctVertices(curve, transaction);
                    allVertices.AddRange(vertices.Select(it => new CurveVertex(it, objectId)));
                    curve.Dispose();
                }

                foreach (var sourceId in sourceIds)
                {
                    var curve = transaction.GetObject(sourceId, OpenMode.ForRead) as Curve;
                    if (curve == null)
                    {
                        continue;
                    }
                    if (!IsCurveClosed(curve))
                    {
                        continue;
                    }

                    closedSourceIds.Add(sourceId);
                    curve.Dispose();
                }
                transaction.Commit();
            }

            // Create a kdTree
            var kdTree = new CurveVertexKdTree <CurveVertex>(allVertices, it => it.Point.ToArray(), ignoreZ: true);

            // Use kd tree to check intersect.
            var intersects = new List <PolygonIntersect>();
            var analyzed   = new HashSet <KeyValuePair <ObjectId, ObjectId> >();

            using (var transaction = database.TransactionManager.StartTransaction())
            {
                foreach (var objectId in closedSourceIds)
                {
                    var curve        = transaction.GetObject(objectId, OpenMode.ForRead) as Curve;
                    var extents      = curve.GeometricExtents;
                    var nearVertices = kdTree.BoxedRange(extents.MinPoint.ToArray(), extents.MaxPoint.ToArray());

                    foreach (var curveVertex in nearVertices)
                    {
                        if (curveVertex.Id == objectId ||
                            analyzed.Contains(new KeyValuePair <ObjectId, ObjectId>(objectId, curveVertex.Id)))
                        {
                            continue;
                        }

                        analyzed.Add(new KeyValuePair <ObjectId, ObjectId>(objectId, curveVertex.Id));
                        var polygonIntersect = AnalyzePolygonIntersection(objectId, curveVertex.Id, transaction);
                        if (polygonIntersect != null)
                        {
                            var sourceId = polygonIntersect.Value.SourceId;
                            var targetId = polygonIntersect.Value.TargetId;
                            var existing = intersects.FirstOrDefault(it => it.SourceId == sourceId && it.TargetId == targetId ||
                                                                     it.SourceId == targetId && it.TargetId == sourceId);
                            if (existing.Equals(default(PolygonIntersect)))
                            {
                                intersects.Add(polygonIntersect.Value);
                            }
                        }
                    }
                }
                transaction.Commit();
            }
            _intersects = intersects;
        }