private void BuildCurveVertexKdTree(IEnumerable <ObjectId> allIds, Transaction transaction, out Dictionary <ObjectId, CurveVertex[]> curveVertices, out CurveVertexKdTree <CurveVertex> kdTree) { kdTree = null; curveVertices = new Dictionary <ObjectId, CurveVertex[]>(); var allVertices = new List <CurveVertex>(); foreach (var id in allIds) { var points = CurveUtils.GetCurveEndPoints(id, transaction); if (points.Length <= 0) { continue; } var distinctPoints = GetDistinctPoints(points); // If distinctPoints.Length == 1, means it's self-loop if (distinctPoints.Length <= 1) { continue; } var vertices = distinctPoints.Select(it => new CurveVertex(it, id)); curveVertices[id] = vertices.ToArray(); allVertices.AddRange(vertices); } kdTree = new CurveVertexKdTree <CurveVertex>(allVertices, it => it.Point.ToArray(), ignoreZ: true); }
public UnclosedPolygonCheckResult(ObjectId sourceId) : base(ActionType.UnclosedPolygon, new ObjectId[] { sourceId }) { using (var transaction = sourceId.Database.TransactionManager.StartTransaction()) { _markPoints = CurveUtils.GetCurveEndPoints(sourceId, transaction); transaction.Commit(); } }
private IEnumerable <CurveCrossingInfo> FilterCrossInfos(IEnumerable <CurveCrossingInfo> crossInfos, out IEnumerable <CurveCrossingInfo> duplicateEntities) { duplicateEntities = new List <CurveCrossingInfo>(); var result = new List <CurveCrossingInfo>(); foreach (var curveCrossingInfo in crossInfos) { // Filter out duplicate entities if (AreDuplicateEntities(curveCrossingInfo)) { ((List <CurveCrossingInfo>)duplicateEntities).Add(curveCrossingInfo); continue; } var sourcePoints = CurveUtils.GetCurveEndPoints(curveCrossingInfo.SourceId, _transaction); var targetPoints = new Point3d[0]; if (curveCrossingInfo.TargetId != curveCrossingInfo.SourceId) { targetPoints = CurveUtils.GetCurveEndPoints(curveCrossingInfo.TargetId, _transaction); } sourcePoints = DistinctEndPoints(sourcePoints); targetPoints = DistinctEndPoints(targetPoints); var points = new List <Point3d>(); foreach (var point3D in curveCrossingInfo.IntersectPoints) { // Whether point3D is end point of each cuve //// If sourcePoints.Length is 1 or 0, means it's a loop, loop need to be splitted. //if (sourcePoints.Length >= 2 && sourcePoints.Contains(point3D) && // targetPoints.Length >= 2 && targetPoints.Contains(point3D)) // continue; // If curveCrossingInfo.SourceId == curveCrossingInfo.TargetId, it's a self intersection. if (sourcePoints.Contains(point3D) && targetPoints.Contains(point3D) && curveCrossingInfo.SourceId != curveCrossingInfo.TargetId) { continue; } points.Add(point3D); } if (points.Count > 0) { var newCrossingInfo = new CurveCrossingInfo(curveCrossingInfo.SourceId, curveCrossingInfo.TargetId, points.ToArray()); result.Add(newCrossingInfo); } } return(result); }
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 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); }