Пример #1
0
        private IEnumerable <CurveVertex> GetConnectedVertices(CurveVertex vertex,
                                                               IDictionary <CurveVertex, SEdge <CurveVertex> > vertexPredecessors,
                                                               List <CurveVertex> connectedVertices, HashSet <CurveVertex> visited)
        {
            var result = new List <CurveVertex>();
            IEnumerable <SEdge <CurveVertex> > outEdges = null;

            _graph.TryGetOutEdges(vertex, out outEdges);
            if (outEdges != null)
            {
                foreach (var outEdge in outEdges)
                {
                    if (visited.Contains(outEdge.Target))
                    {
                        continue;
                    }

                    connectedVertices.Add(outEdge.Target);
                    visited.Add(outEdge.Target);
                    result.Add(outEdge.Target);
                }
            }

            SEdge <CurveVertex> inEdge;

            vertexPredecessors.TryGetValue(vertex, out inEdge);
            if (!inEdge.Equals(default(SEdge <CurveVertex>)) && !visited.Contains(inEdge.Source))
            {
                connectedVertices.Add(inEdge.Source);
                visited.Add(inEdge.Source);
                result.Add(inEdge.Source);
            }
            return(result);
        }
        private IEnumerable <IntersectionInfo> GetApparentIntersections(CurveVertex current, IEnumerable <CurveVertex> danglingVertices,
                                                                        HashSet <CurveVertex> visitedVertices, Transaction transaction)
        {
            visitedVertices.Add(current);
            var result = new List <IntersectionInfo>();
            var ids    = Editor.SelectEntitiesAtPoint(SelectionFilterUtils.OnlySelectCurve(), current.Point, _tolerance);

            foreach (var id in ids)
            {
                // Check whether danglingVertices contains this id.
                var vertices = danglingVertices.Where(it => it.Id == id);
                if (!vertices.Any())
                {
                    continue;
                }

                // Check each vertex of this id.
                foreach (var vertex in vertices)
                {
                    if (vertex == current)
                    {
                        continue;
                    }

                    if (visitedVertices.Contains(vertex))
                    {
                        continue;
                    }

                    var distance = (vertex.Point - current.Point).Length;
                    if (distance.Larger(_tolerance * 2))
                    {
                        continue;
                    }

                    // Calcuate the intersection info of these two vertices.
                    var info = CalcApparentIntersection(current, vertex, transaction);
                    if (info != null)
                    {
                        result.Add(info);
                    }
                }
            }

            return(result);
        }
Пример #3
0
        private bool CheckDangling(CurveVertex vertex, IEnumerable <ObjectId> allIds,
                                   HashSet <ObjectId> visitedIds, Stack <CurveVertex> candidates,
                                   Dictionary <ObjectId, CurveVertex[]> curveVertices, CurveVertexKdTree <CurveVertex> kdTree)
        {
            bool isDangling = true;

            // Get entities which vertex is on.
            var neighbors   = kdTree.NearestNeighbours(vertex.Point.ToArray(), radius: 0.1);
            var adjacentIds = neighbors.Select(it => it.Id);

            foreach (ObjectId adjacentId in adjacentIds)
            {
                if (adjacentId == vertex.Id)
                {
                    continue;
                }

                // Check adjacent vertices
                if (!curveVertices.ContainsKey(adjacentId))
                {
                    continue;
                }

                var vertices = curveVertices[adjacentId];
                foreach (var adjVertex in vertices)
                {
                    // If it connect to vertex, isDangling is false.
                    if (adjVertex.Point == vertex.Point)
                    {
                        isDangling = false;
                    }
                    else if (!visitedIds.Contains(adjacentId) &&
                             (_forDrawing || allIds.Contains(adjacentId)))
                    {
                        candidates.Push(adjVertex);
                    }
                }

                // Mark it as visited.
                visitedIds.Add(adjacentId);
            }
            return(isDangling);
        }
Пример #4
0
        private IntersectionInfo CreateRealIntersectionInfo(BspSplitInfo info, Point2d point, ObjectId targetId, HashSet <CurveVertex> vertexIntersects)
        {
            var extendType = CurveIntersectUtils.ParamToExtendTypeForLine(info.SourceParam);

            if (extendType != ExtendType.None)
            {
                return(null);
            }

            // Self intersection
            if ((info.SourceParam.EqualsWithTolerance(0.0) || info.SourceParam.EqualsWithTolerance(1.0)) &&
                info.SourceSegment.EntityId == targetId)
            {
                // Need to take care of a special case:
                // Polyline AEB and CED intersect at E point
                //     A\  D
                //       \ |
                //        \|_________B
                //      C / E

                var vertexIntersect = new CurveVertex(new Point3d(point.X, point.Y, 0.0), info.SourceSegment.EntityId);
                // More than two intersects, then it's a self intersection.
                if (vertexIntersects.Contains(vertexIntersect))
                {
                    var intersection = new IntersectionInfo(info.SourceSegment.EntityId, ExtendType.None, targetId,
                                                            ExtendType.None, new Point3d(point.X, point.Y, 0.0));

                    return(intersection);
                }

                vertexIntersects.Add(vertexIntersect);
                return(null);
            }
            else
            {
                var intersection = new IntersectionInfo(info.SourceSegment.EntityId, ExtendType.None, targetId,
                                                        ExtendType.None, new Point3d(point.X, point.Y, 0.0));

                return(intersection);
            }
        }
Пример #5
0
        private IEnumerable <CurveVertex> GetCurveVertices(ObjectId id, HashSet <ObjectId> visitedIds)
        {
            var points = CurveUtils.GetCurveEndPoints(id, _transaction);

            if (points.Length <= 0)
            {
                return(new CurveVertex[0]);
            }

            // Remove the duplicate point
            // Note: if a curve has 2 same end points, means its a self-loop.
            var     distinctPoints = new List <Point3d>();
            Point3d current        = points[0];

            distinctPoints.Add(current);
            for (int i = 1; i < points.Length; i++)
            {
                if (points[i] != current)
                {
                    current = points[i];
                    distinctPoints.Add(current);
                }
            }
            if (distinctPoints.Count <= 1)
            {
                return(new CurveVertex[0]);
            }

            // Create vertices for the curve
            var vertices = new CurveVertex[distinctPoints.Count];

            for (int i = 0; i < distinctPoints.Count; i++)
            {
                vertices[i] = new CurveVertex(distinctPoints[i], id);
            }
            return(vertices);
        }
Пример #6
0
        private bool CheckDangling(CurveVertex vertex, IEnumerable <ObjectId> allIds, HashSet <ObjectId> visitedIds, Stack <CurveVertex> candidates)
        {
            bool isDangling = true;

            // Get entities which vertex is on.
            var adjacentIds = SelectCurves(vertex.Point);

            foreach (ObjectId adjacentId in adjacentIds)
            {
                if (adjacentId == vertex.Id)
                {
                    continue;
                }

                // Check adjacent vertices
                var vertices = GetCurveVertices(adjacentId, visitedIds);

                foreach (var adjVertex in vertices)
                {
                    // If it connect to vertex, isDangling is false.
                    if (adjVertex.Point == vertex.Point)
                    {
                        isDangling = false;
                    }
                    else if (!visitedIds.Contains(adjacentId) &&
                             (_forDrawing || allIds.Contains(adjacentId)))
                    {
                        candidates.Push(adjVertex);
                    }
                }

                // Mark it as visited.
                visitedIds.Add(adjacentId);
            }
            return(isDangling);
        }
        private IntersectionInfo CalcApparentIntersection(CurveVertex source, CurveVertex target, Transaction transaction)
        {
            var sourceEntity = transaction.GetObject(source.Id, OpenMode.ForRead);
            var targetEntity = transaction.GetObject(target.Id, OpenMode.ForRead);

            // Source curve
            var desiredSourceExtend = CurveUtils.GetExtendType((Curve)sourceEntity, source.Point);
            var sourceLine          = sourceEntity as Line;
            var sourceArc           = sourceEntity as Arc;
            var sourcePolyline      = sourceEntity as Autodesk.AutoCAD.DatabaseServices.Polyline;
            var sourcePolyline2d    = sourceEntity as Polyline2d;

            if (sourcePolyline != null)
            {
                sourceLine = CurveUtils.CutOutLineFromPolyLine(sourcePolyline, source.Point);
            }
            else if (sourcePolyline2d != null)
            {
                sourceLine = CurveUtils.CutOutLineFromPolyline2d(sourcePolyline2d, source.Point, transaction);
            }

            // Target curve
            var desiredTargetExtend = CurveUtils.GetExtendType((Curve)targetEntity, target.Point);
            var targetLine          = targetEntity as Line;
            var targetArc           = targetEntity as Arc;
            var targetPolyline      = targetEntity as Autodesk.AutoCAD.DatabaseServices.Polyline;
            var targetPolyline2d    = targetEntity as Polyline2d;

            if (targetPolyline != null)
            {
                targetLine = CurveUtils.CutOutLineFromPolyLine(targetPolyline, target.Point);
            }
            else if (targetPolyline2d != null)
            {
                targetLine = CurveUtils.CutOutLineFromPolyline2d(targetPolyline2d, target.Point, transaction);
            }

            // Calculate intersection.
            var results = new List <IntersectionInfo>();

            if (sourceLine != null && targetLine != null)
            {
                // Line && Line
                var info = CurveIntersectUtils.InsersectLines(sourceLine, targetLine);
                if (info != null)
                {
                    info.SourceId = source.Id;
                    info.TargetId = target.Id;
                    results.Add(info);
                }
            }
            else if (sourceLine != null && targetArc != null)
            {
                // Line && Arc
                var infos = CurveIntersectUtils.IntersectLineArc(sourceLine, targetArc, coerceArcExtendType: desiredTargetExtend);
                foreach (var info in infos)
                {
                    info.SourceId = source.Id;
                    info.TargetId = target.Id;
                }
                results.AddRange(infos);
            }
            else if (sourceArc != null && targetLine != null)
            {
                // Arc && Line
                var infos = CurveIntersectUtils.IntersectLineArc(targetLine, sourceArc, coerceArcExtendType: desiredSourceExtend);
                foreach (var info in infos)
                {
                    // Exchange entend type.
                    var newInfo = new IntersectionInfo(source.Id, info.TargetExtendType, target.Id,
                                                       info.SourceExtendType, info.IntersectPoint);

                    results.Add(newInfo);
                }
            }
            else if (sourceArc != null && targetArc != null)
            {
                // Arc && Arc
                var infos = CurveIntersectUtils.IntersectArcs(sourceArc, desiredSourceExtend, targetArc,
                                                              desiredTargetExtend);
                foreach (var info in infos)
                {
                    info.SourceId = source.Id;
                    info.TargetId = target.Id;
                }

                results.AddRange(infos);
            }

            IntersectionInfo result = null;

            foreach (var info in results)
            {
                var valid = CheckIntersectionInfo(info, desiredSourceExtend, source.Point, desiredTargetExtend, target.Point, _tolerance);
                if (valid)
                {
                    result = info;
                    break;
                }
            }
            return(result);
        }
Пример #8
0
        private IntersectionInfo GetUnderShootIntersection(CurveVertex vertex, Transaction transaction, double tolerance)
        {
            var curve         = transaction.GetObject(vertex.Id, OpenMode.ForRead);
            var desiredExtend = CurveUtils.GetExtendType((Curve)curve, vertex.Point);

            var line       = curve as Line;
            var arc        = curve as Arc;
            var polyline   = curve as Polyline;
            var polyline2d = curve as Polyline2d;

            if (polyline != null)
            {
                line = CurveUtils.CutOutLineFromPolyLine(polyline, vertex.Point);
            }
            else if (polyline2d != null)
            {
                line = CurveUtils.CutOutLineFromPolyline2d(polyline2d, vertex.Point, transaction);
            }

            // Construct a polygon to get adjacent entities.
            Point3dCollection polygon = null;

            if (line != null)
            {
                var direction = line.EndPoint - line.StartPoint;
                if (desiredExtend == ExtendType.ExtendStart)
                {
                    direction = -1.0 * direction;
                }
                polygon = BuildSelectionPolygonForLine(vertex.Point, direction, tolerance);
            }
            else if (arc != null)
            {
                polygon = BuildSelectionPolygonForArc(vertex.Point, tolerance);
            }

            // Zoom window
            var minPt   = new Point3d(vertex.Point.X - tolerance, vertex.Point.Y - tolerance, 0.0);
            var maxPt   = new Point3d(vertex.Point.X + tolerance, vertex.Point.Y + tolerance, 0.0);
            var extents = new Extents3d(minPt, maxPt);

            Editor.ZoomToWin(extents, factor: 2.0);

            var selectionResult = Editor.SelectCrossingPolygon(polygon, SelectionFilterUtils.OnlySelectCurve());

            if (selectionResult.Status != PromptStatus.OK || selectionResult.Value == null)
            {
                return(null);
            }

            // Check each adjacent entity whether they are intersected.
            var intersectionInfos = new List <IntersectionInfo>();
            var adjacentIds       = selectionResult.Value.GetObjectIds();

            foreach (ObjectId objId in adjacentIds)
            {
                var targetCurve = transaction.GetObject(objId, OpenMode.ForRead) as Curve;
                if (targetCurve == null)
                {
                    continue;
                }

                // Calculate the intersection
                IntersectionInfo info = null;
                if (line != null)
                {
                    info = IntersectLineAndCurve(line, targetCurve, vertex.Point, desiredExtend);
                }
                else if (arc != null)
                {
                    info = IntersectArcAndCurve(arc, targetCurve, vertex.Point, desiredExtend);
                }

                if (info != null && info.SourceExtendType == desiredExtend)
                {
                    info.SourceId = vertex.Id;
                    info.TargetId = objId;

                    intersectionInfos.Add(info);
                }
            }

            // Get nearest point.
            if (intersectionInfos.Count <= 0)
            {
                return(null);
            }

            var nearest     = intersectionInfos[0];
            var nearsetDist = (intersectionInfos[0].IntersectPoint - vertex.Point).Length;

            for (int i = 1; i < intersectionInfos.Count; i++)
            {
                var dist = (intersectionInfos[i].IntersectPoint - vertex.Point).Length;
                if (dist < nearsetDist)
                {
                    nearsetDist = dist;
                    nearest     = intersectionInfos[i];
                }
            }

            if (nearsetDist.Larger(tolerance))
            {
                return(null);
            }

            return(nearest);
        }
Пример #9
0
        private IEnumerable <SEdge <CurveVertex> > VisitCurve(CurveVertex?sourceVertex, ObjectId id, IEnumerable <ObjectId> allIds,
                                                              HashSet <ObjectId> visitedIds, Stack <KeyValuePair <ObjectId, CurveVertex> > candidates, Transaction transaction)
        {
            var points = CurveUtils.GetCurveEndPoints(id, transaction);

            // If none of the curve's end points is equal to the point, just return.
            // It means this curve is not a qualified one because it's not connected to sourceVertex.
            // Then it will be handled later because it belongs to another loop.
            if (sourceVertex != null && points.Length > 0 && !points.Contains(sourceVertex.Value.Point))
            {
                bool contains = false;
                foreach (var point in points)
                {
                    if (point.IsEqualTo(sourceVertex.Value.Point))
                    {
                        contains = true;
                    }
                }

                if (!contains)
                {
                    return(new SEdge <CurveVertex> [0]);
                }
            }

            // Mark it as visited.
            visitedIds.Add(id);
            // If there is no end points on the entity, just return.
            if (points.Length <= 0)
            {
                return(new SEdge <CurveVertex> [0]);
            }

            // Remove the duplicate point
            // Note: if a curve has 2 same end points, means its a self-loop.
            var     distinctPoints = new List <Point3d>();
            Point3d current        = points[0];

            distinctPoints.Add(current);
            for (int i = 1; i < points.Length; i++)
            {
                if (points[i] != current)
                {
                    current = points[i];
                    distinctPoints.Add(current);
                }
            }

            // Create vertices for the curve
            var vertices = new CurveVertex[distinctPoints.Count];

            for (int i = 0; i < distinctPoints.Count; i++)
            {
                vertices[i] = new CurveVertex(distinctPoints[i], id);
            }

            var result = new List <SEdge <CurveVertex> >();

            // Push vertex and adjacent curve into candidates
            foreach (var vertex in vertices)
            {
                if (sourceVertex != null && sourceVertex.Value.Point.IsEqualTo(vertex.Point))
                {
                    continue;
                }

                var adjacentIds = SelectCurves(vertex.Point);
                foreach (ObjectId adjacentId in adjacentIds)
                {
                    // If it has been visited.
                    if (visitedIds.Contains(adjacentId))
                    {
                        var originVertex = new CurveVertex(vertex.Point, adjacentId);
                        // If this curve has been pushed into the candidates stack before, there must exist a loop.
                        // So we create a back edge to the original vertex.
                        // NOTE: Use candidates.Contains(new KeyValuePair<ObjectId, CurveVertex>(id, originVertex))
                        // will cause a problem if two point are very close to each other
                        // such as (10.5987284839403,10.2186528623464,0) and (10.5987284839408,10.2186528623464,0)
                        var existing = candidates.FirstOrDefault(it => it.Key == id && it.Value == originVertex);
                        if (!existing.Equals(default(KeyValuePair <ObjectId, CurveVertex>)))
                        {
                            // Create edge back to the old vertex.
                            result.Add(new SEdge <CurveVertex>(vertex, existing.Value));
                        }
                        //if (candidates.Contains(new KeyValuePair<ObjectId, CurveVertex>(id, originVertex)))
                        //{
                        //    // Create edge back to the old vertex.
                        //    result.Add(new SEdge<CurveVertex>(vertex, originVertex));
                        //}
                        continue;
                    }

                    // If it's not in the collection of selected ids.
                    if (!allIds.Contains(adjacentId))
                    {
                        continue;
                    }

                    candidates.Push(new KeyValuePair <ObjectId, CurveVertex>(adjacentId, vertex));
                }
            }

            // Create edges
            int start = 0;

            if (sourceVertex != null)
            {
                for (int i = 0; i < vertices.Length; i++)
                {
                    if (vertices[i].Point.IsEqualTo(sourceVertex.Value.Point))
                    {
                        start = i;
                        // Add edge from sourceVertex to nearest point.
                        result.Add(new SEdge <CurveVertex>(sourceVertex.Value, vertices[start]));
                        break;
                    }
                }
            }

            if (vertices.Length == 1)
            {
                // Allan 2015/05/06: Self loop won't be handled - to improve performance.

                //// Self loop, create dummy vertex to let it to be a real loop
                //var dummy = new CurveVertex(vertices[0].Point + new Vector3d(1, 1, 1), id);
                //result.Add(new SEdge<CurveVertex>(vertices[0], dummy));
                //result.Add(new SEdge<CurveVertex>(dummy, vertices[0]));
            }
            else
            {
                // Must start from the vertex whose poitn is equal to source vertex's point.
                // Up
                var previousVertex = vertices[start];
                for (int i = start + 1; i < vertices.Length; i++)
                {
                    // Create a middle point to fix a bug - to avoid a line's two vertices are both in loop,
                    // but actually the line is not in a loop, for example
                    //        /\             /\
                    //       /  \           /  \
                    //      /____\A_______B/____\
                    // Point A and point B are both in a loop, but line AB is not in a loop.
                    // If I add a dummy point C in the middle of AB, then our graph could easily
                    // to determine C is not in a loop.
                    var middlePoint  = previousVertex.Point + (vertices[i].Point - previousVertex.Point) / 2.0;
                    var middleVertex = new CurveVertex(middlePoint, id);
                    result.Add(new SEdge <CurveVertex>(previousVertex, middleVertex));
                    result.Add(new SEdge <CurveVertex>(middleVertex, vertices[i]));
                    previousVertex = vertices[i];
                }
                // Down
                previousVertex = vertices[start];
                for (int i = start - 1; i >= 0; i--)
                {
                    var middlePoint  = previousVertex.Point + (vertices[i].Point - previousVertex.Point) / 2.0;
                    var middleVertex = new CurveVertex(middlePoint, id);
                    result.Add(new SEdge <CurveVertex>(previousVertex, middleVertex));
                    result.Add(new SEdge <CurveVertex>(middleVertex, vertices[i]));

                    previousVertex = vertices[i];
                }
            }

            return(result);
        }
Пример #10
0
        CurveVertex?GetRootVertex(IDictionary <CurveVertex, SEdge <CurveVertex> > predecessors, CurveVertex vertex)
        {
            CurveVertex?target = vertex;
            CurveVertex?source = null;

            while (target != null)
            {
                if (predecessors.ContainsKey(target.Value))
                {
                    source = predecessors[target.Value].Source;
                    target = source;
                }
                else
                {
                    target = null;
                }
            }
            return(source);
        }
Пример #11
0
        public static Dictionary <ObjectId, List <Point3d> > GetCrotchPoints(Database database,
                                                                             IEnumerable <ObjectId> parcelIds)
        {
            var result = new Dictionary <ObjectId, List <Point3d> >();
            // Create a kd tree.
            var allVertices = new List <CurveVertex>();

            using (var transaction = database.TransactionManager.StartTransaction())
            {
                foreach (var objId in parcelIds)
                {
                    var curve = transaction.GetObject(objId, OpenMode.ForRead) as Curve;
                    if (curve == null)
                    {
                        continue;
                    }
                    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);

            // 搜索三岔口
            //using (var tolerance = new ToleranceOverrule(null))
            using (var transaction = database.TransactionManager.StartTransaction())
            {
                foreach (var parcelId in parcelIds)
                {
                    var curve = transaction.GetObject(parcelId, OpenMode.ForRead) as Curve;
                    if (curve == null)
                    {
                        continue;
                    }

                    var ptLink     = LinkedPoint.GetLinkedPoints(curve, transaction, isLoop: true);
                    var ptTraverse = ptLink;
                    // Use records to improve performance.
                    var records = new Dictionary <LinkedPoint, IEnumerable <CurveVertex> >();
                    while (ptTraverse != null)
                    {
                        var prev = ptTraverse.Prev;
                        var next = ptTraverse.Next;
                        if (!records.ContainsKey(prev))
                        {
                            records[prev] = kdTree.NearestNeighbours(prev.Point.ToArray(), radius: 0.001);
                        }
                        if (!records.ContainsKey(ptTraverse))
                        {
                            records[ptTraverse] = kdTree.NearestNeighbours(ptTraverse.Point.ToArray(), radius: 0.001);
                        }
                        if (!records.ContainsKey(next))
                        {
                            records[next] = kdTree.NearestNeighbours(next.Point.ToArray(), radius: 0.001);
                        }

                        foreach (var vertex in records[ptTraverse])
                        {
                            if (result.ContainsKey(parcelId) && result[parcelId].Contains(vertex.Point))
                            {
                                continue;
                            }

                            if (vertex.Id == parcelId || vertex.Point != ptTraverse.Point)
                            {
                                continue;
                            }
                            var prevVertex = new CurveVertex(prev.Point, vertex.Id);
                            var nextVertex = new CurveVertex(next.Point, vertex.Id);
                            if (records[prev].Contains(prevVertex) && records[next].Contains(nextVertex))
                            {
                                continue;
                            }

                            List <Point3d> list = null;
                            if (result.ContainsKey(parcelId))
                            {
                                list = result[parcelId];
                            }
                            else
                            {
                                list             = new List <Point3d>();
                                result[parcelId] = list;
                            }
                            list.Add(ptTraverse.Point);
                        }

                        ptTraverse = ptTraverse.Next;
                        if (ptTraverse == ptLink)
                        {
                            break;
                        }
                    }
                }
                transaction.Commit();
            }

            return(result);
        }