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); }
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); }
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); } }
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); }
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); }
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); }
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); }
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); }
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); }