//public static bool IsInclude(Curve sourceCurve, Curve targetCurve, Transaction transaction) //{ // var sourceVertices = CurveUtils.GetDistinctVertices(sourceCurve, transaction).ToList(); // var sourceVertices2d = sourceVertices.Select(it => new Point2d(it.X, it.Y)).ToList(); // if (sourceVertices2d[0] != sourceVertices2d[sourceVertices2d.Count - 1]) // sourceVertices2d.Add(sourceVertices2d[0]); // var sourcePolygon = sourceVertices2d.ToArray(); // var targetVertices = CurveUtils.GetDistinctVertices(targetCurve, transaction).ToList(); // foreach (var targetVertex in targetVertices) // { // var point2D = new Point2d(targetVertex.X, targetVertex.Y); // if (!ComputerGraphics.IsInPolygon(sourcePolygon, point2D, sourcePolygon.Length - 1)) // return false; // } // // There is a case, a polyon's all vertices are on another concave polygon, but the former is not in the latter. // // So we need to use the former's edge middle points to check. // if (targetVertices[0] != targetVertices[targetVertices.Count - 1]) // targetVertices.Add(targetVertices[0]); // var middlePoints = GetAllMiddlePoints(targetVertices); // foreach (var middlePoint in middlePoints) // { // var point2D = new Point2d(middlePoint.X, middlePoint.Y); // if (!ComputerGraphics.IsInPolygon(sourcePolygon, point2D, sourcePolygon.Length - 1)) // return false; // } // return true; //} public static bool IsInclude(Curve sourceCurve, Curve targetCurve, Transaction transaction) { var sourceVertices = CurveUtils.GetDistinctVertices(sourceCurve, transaction); var targetVertices = CurveUtils.GetDistinctVertices(targetCurve, transaction); return(IsInclude(sourceVertices, targetVertices)); }
private bool AreDuplicateEntities(CurveCrossingInfo crossInfo) { if (crossInfo.SourceId == crossInfo.TargetId) { return(false); } // Check whether all the intersection points are curve's vertices. var sourceVertices = CurveUtils.GetDistinctVertices(crossInfo.SourceId, _transaction); var targetVertices = CurveUtils.GetDistinctVertices(crossInfo.TargetId, _transaction); var sourceCount = sourceVertices.Count(); var targetCount = targetVertices.Count(); if (sourceCount != targetCount) { return(false); } if (sourceCount != crossInfo.IntersectPoints.Length) { return(false); } foreach (var point in crossInfo.IntersectPoints) { if (!sourceVertices.Contains(point) || !targetVertices.Contains(point)) { return(false); } } return(true); }
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); }
private IEnumerable <Point3d> CheckSharpCorners(ObjectId curveId, Transaction transaction) { var result = new List <Point3d>(); var distinctVertices = CurveUtils.GetDistinctVertices(curveId, transaction); // 保证首尾点不相同 if (distinctVertices[0] == distinctVertices[distinctVertices.Count - 1]) { distinctVertices.RemoveAt(distinctVertices.Count - 1); } for (int i = 0; i < distinctVertices.Count; i++) { var current = distinctVertices[i]; var prev = distinctVertices[(i - 1 + distinctVertices.Count) % distinctVertices.Count]; var next = distinctVertices[(i + 1) % distinctVertices.Count]; var prevDir = prev - current; var nextDir = next - current; var angle = prevDir.GetAngleTo(nextDir); if (angle.SmallerOrEqual(Tolerance / 180.0 * Math.PI)) { result.Add(current); } } return(result); }
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); } } }
public override void Check(IEnumerable <ObjectId> selectedObjectIds) { if (!selectedObjectIds.Any()) { return; } var group = CalculateIntersectionKdTree(selectedObjectIds, true, Editor); // Check each intersection whether it's a missing vertex. var database = Editor.Document.Database; 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(); } //foreach (var info in _missingVertexInfos) //{ // Editor.WriteMessage("\n{0}:", info.PolylineId.Handle.ToString()); // foreach (var point in info.Positions) // { // Editor.WriteMessage(" {0} ", point.ToString()); // } // Editor.WriteMessage("\n"); //} }
/// <summary> /// Build a linked list for vertices. /// </summary> /// <param name="curve"></param> /// <param name="transaction"></param> /// <param name="isLoop">Indicate whether the curve is a loop</param> /// <returns></returns> public static LinkedPoint GetLinkedPoints(Curve curve, Transaction transaction, bool isLoop) { var vertices = CurveUtils.GetDistinctVertices(curve, transaction); // Make sure the first point is not equal to the last one. if (vertices.Count > 1 && vertices[0] == vertices[vertices.Count - 1]) { vertices.RemoveAt(vertices.Count - 1); } return(GetLinkedPoints(vertices, isLoop)); }
public static void TestConvexHull() { var currentDoc = Application.DocumentManager.MdiActiveDocument; var editor = currentDoc.Editor; var database = currentDoc.Database; // Only select polyline and polyline 2d. ObjectId polylineId = ObjectId.Null; while (true) { var options = new PromptEntityOptions("\n选择一条曲线:"); var result = editor.GetEntity(options); if (result.Status == PromptStatus.OK) { polylineId = result.ObjectId; break; } if (result.Status == PromptStatus.Cancel) { break; } editor.WriteMessage("\n选择无效"); } if (polylineId.IsNull) { return; } using (var transaction = database.TransactionManager.StartTransaction()) { IEnumerable <Point3d> points = CurveUtils.GetDistinctVertices(polylineId, transaction); var convex = new ConvexHull <Point3d>(points, it => it.X, it => it.Y, (x, y) => new Point3d(x, y, 0), (a, b) => a == b); convex.CalcConvexHull(); var hullPoints = convex.GetResultsAsArrayOfPoint(); var polyline = new Autodesk.AutoCAD.DatabaseServices.Polyline(); for (int i = 0; i < hullPoints.Length; i++) { polyline.AddVertexAt(i, new Point2d(hullPoints[i].X, hullPoints[i].Y), 0, 1, 1); } polyline.ColorIndex = 2; var modelspaceId = SymbolUtilityServices.GetBlockModelSpaceId(database); var modelspace = transaction.GetObject(modelspaceId, OpenMode.ForWrite) as BlockTableRecord; modelspace.AppendEntity(polyline); transaction.AddNewlyCreatedDBObject(polyline, true); transaction.Commit(); } }
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(); } }
CurveVertexKdTree <CurveVertex> CreatePolygonKdTree(IEnumerable <ObjectId> objectIds, Transaction transaction) { var vertices = new List <CurveVertex>(); foreach (var objectId in objectIds) { var points = CurveUtils.GetDistinctVertices(objectId, transaction); if (points[0] == points[points.Count - 1]) { points.RemoveAt(points.Count - 1); } vertices.AddRange(points.Select(it => new CurveVertex(it, objectId))); } var kdTree = new CurveVertexKdTree <CurveVertex>(vertices, it => it.Point.ToArray(), ignoreZ: true); return(kdTree); }
private CurveVertexKdTree <CurveVertex> BuildCurveVertexKdTree2(IEnumerable <ObjectId> allIds, Transaction transaction) { var allVertices = new List <CurveVertex>(); foreach (var id in allIds) { var points = CurveUtils.GetDistinctVertices(id, transaction); if (!points.Any()) { continue; } var vertices = points.Select(it => new CurveVertex(it, id)); allVertices.AddRange(vertices); } var kdTree = new CurveVertexKdTree <CurveVertex>(allVertices, it => it.Point.ToArray(), ignoreZ: true); return(kdTree); }
private void BuildCurveVertexKdTree(IEnumerable <ObjectId> allIds, Transaction transaction, out Dictionary <ObjectId, CurveVertex[]> curveVertices, out CurveVertexKdTree <CurveVertex> kdTree) { curveVertices = new Dictionary <ObjectId, CurveVertex[]>(); var allVertices = new List <CurveVertex>(); foreach (var id in allIds) { var points = CurveUtils.GetDistinctVertices(id, transaction); if (!points.Any()) { continue; } var vertices = points.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 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(); } }
/// <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; }
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); }
public override void Check(IEnumerable <ObjectId> selectedObjectIds) { if (selectedObjectIds == null || !selectedObjectIds.Any()) { return; } var regions = new List <IsolatedRegion>(); using (var transaction = Database.TransactionManager.StartTransaction()) { // Create a kdtree, for near searching var kdTree = CreatePolygonKdTree(selectedObjectIds, transaction); var visited = new HashSet <ObjectId>(); foreach (var objectId in selectedObjectIds) { if (visited.Contains(objectId)) { continue; } // 防止二次访问,造成无限循环 visited.Add(objectId); var contour = CurveUtils.GetDistinctVertices(objectId, transaction); var idsGroup = new List <ObjectId>() { objectId }; var unionableIds = new List <ObjectId>() { objectId }; while (unionableIds.Count > 0) { var newUnionableIds = new List <ObjectId>(); foreach (var unionableId in unionableIds) { // Get near polygon Ids var nearIds = GetNearPolygonIds(kdTree, unionableId, visited, transaction); foreach (var nearId in nearIds) { var nearPoints = CurveUtils.GetDistinctVertices(nearId, transaction); List <Point3d> unionPolygon = null; var unionable = AnalyzePolygonsUnionable(contour, nearPoints, out unionPolygon); if (unionable) { newUnionableIds.Add(nearId); visited.Add(nearId); idsGroup.Add(nearId); contour = unionPolygon; } } } unionableIds = newUnionableIds; } regions.Add(new IsolatedRegion() { Contour = contour, CurveIds = idsGroup }); } transaction.Commit(); } _isolatedRegions = regions; }
private PolygonIntersect?AnalyzePolygonIntersection(ObjectId sourceId, ObjectId targetId, Transaction transaction) { var sourceCurve = transaction.GetObject(sourceId, OpenMode.ForRead) as Curve; var targetCurve = transaction.GetObject(targetId, OpenMode.ForRead) as Curve; if (!IsCurveClosed(sourceCurve) || !IsCurveClosed(targetCurve)) { return(null); } // Use clipper to calculate the intersection var precision = 0.000001; var subject = new List <List <IntPoint> >(1); var clipper = new List <List <IntPoint> >(1); var result = new List <List <IntPoint> >(); var sourceVertices = CurveUtils.GetDistinctVertices(sourceCurve, transaction); var targetVertices = CurveUtils.GetDistinctVertices(targetCurve, transaction); var subjectPath = sourceVertices.Select(it => new IntPoint(it.X / precision, it.Y / precision)).ToList(); var clipperPath = targetVertices.Select(it => new IntPoint(it.X / precision, it.Y / precision)).ToList(); subject.Add(subjectPath); clipper.Add(clipperPath); var cpr = new Clipper(); cpr.AddPaths(subject, PolyType.ptSubject, true); cpr.AddPaths(clipper, PolyType.ptClip, true); cpr.Execute(ClipType.ctIntersection, result, PolyFillType.pftNonZero, PolyFillType.pftNonZero); if (result.Count <= 0) { //Editor.WriteMessage("有相交,但Clipper没有计算出相交部分"); return(null); } var intersectPaths = new List <Polyline>(); foreach (var path in result) { var points = path.Select(it => new Point3d(it.X * precision, it.Y * precision, 0.0)).ToArray(); var polyline = CreatePolygon(points); // If the polygon's area is very small, just ignore, or it will bother user. var intersectArea = polyline.Area; if (intersectArea.Smaller(0.001)) { polyline.Dispose(); continue; } else if (TargetAreaRatio != null) { var targetArea = targetCurve.Area; if ((intersectArea / targetArea).Smaller(TargetAreaRatio.Value)) { polyline.Dispose(); continue; } } intersectPaths.Add(polyline); } if (intersectPaths.Count <= 0) { return(null); } // 将包含的情况排除 if (intersectPaths.Count == 1) { var intersectPoints = CurveUtils.GetDistinctVertices(intersectPaths[0], null); var qualified = IsIntersectQualified(sourceId, sourceVertices, targetId, targetVertices, intersectPoints, transaction); if (!qualified) { intersectPaths[0].Dispose(); intersectPaths.Clear(); return(null); } } return(new PolygonIntersect() { SourceId = sourceId, TargetId = targetId, Intersections = intersectPaths }); }