public static void RemoveOnStraightPt(Polyline poly, double straightTolerance) { List <Point3d> removed = new List <Point3d>(); bool isClosed = poly.IsClosed; if (isClosed) { poly.RemoveAt(poly.Count - 1); } int pointCount = poly.Count; for (int i = 0; i < pointCount; i++) { if (i == 0 && !isClosed) { removed.Add(poly[i]); continue; } Vector3d preVector = poly[(pointCount + i - 1) % pointCount] - poly[i]; Vector3d postVector = poly[(pointCount + i + 1) % pointCount] - poly[i]; if (preVector.Length < 0.005) { continue; } if (i == pointCount - 1 && !isClosed) { removed.Add(poly[i]); break; } var tempConvexity = VectorTools.CheckConvexity(preVector, postVector, straightTolerance); if ((tempConvexity == Convexity.Convex || tempConvexity == Convexity.Concave) || postVector.Length < 0.005) { removed.Add(poly[i]); } } poly.Clear(); poly.AddRange(removed); if (isClosed) { poly.Add(poly.First); } }
public static Rectangle3d DrawP2PRect(Point3d pointStart, Point3d pointEnd, double perpThickness, double alignThickness) { Rectangle3d p2pRect = new Rectangle3d(); Vector3d alignP2P = new Line(pointStart, pointEnd).UnitTangent; Vector3d perpP2P = VectorTools.RotateVectorXY(alignP2P, Math.PI / 2.0); Point3d corner1 = pointStart - alignP2P * alignThickness / 2.0 + perpP2P * perpThickness / 2.0; Point3d corner2 = pointEnd + alignP2P * alignThickness / 2.0 - perpP2P * perpThickness / 2.0; Plane p2pPlane = new Plane(pointStart, alignP2P, perpP2P); p2pRect = new Rectangle3d(p2pPlane, corner1, corner2); return(p2pRect); }
/// <summary> /// 반시계 방향 기준으로 경계 안에 그릴 수 있는 최장의 선을 반환합니다. 기준점이 경계를 벗어나는 경우는 PCXStrict와 동일합니다. /// </summary> public static Line PCXLongest(Point3d basePt, Polyline boundary, Vector3d direction) { double onCurveTolerance = 0.5; double samePtTolerance = 0.005; double parallelTolerance = 0.005; Point3d longestEnd = basePt; //Get all crossing points. List <Point3d> allCrossPts = GetAllCrossPoints(basePt, boundary, direction, onCurveTolerance); allCrossPts.Sort((a, b) => (basePt.DistanceTo(a).CompareTo(basePt.DistanceTo(b)))); //Set compare points. List <Point3d> boundaryPt = new List <Point3d>(boundary); if (boundary.IsClosed) { boundaryPt.RemoveAt(boundaryPt.Count - 1); } //Find end point of longest line. foreach (Point3d i in allCrossPts) { longestEnd = i; //seive1: Remove same as basePt. if (i.DistanceTo(basePt) < samePtTolerance) { continue; } //seive2: End if not vertex. int vertexIndex = boundaryPt.FindIndex(n => n.DistanceTo(i) < samePtTolerance); bool isVertex = vertexIndex != -1; if (!isVertex) { break; } //seive3: End if not concave(& anti-parallel). Vector3d toPre = boundaryPt[(boundaryPt.Count + vertexIndex - 1) % boundaryPt.Count] - boundaryPt[vertexIndex]; Vector3d toPost = boundaryPt[(boundaryPt.Count + vertexIndex + 1) % boundaryPt.Count] - boundaryPt[vertexIndex]; Convexity cnv = VectorTools.CheckConvexity(toPre, toPost, parallelTolerance); if (cnv == Convexity.Convex || cnv == Convexity.Parallel) { break; } //seive4: Continue if not between. if (!VectorTools.IsBetweenVector(toPre, toPost, -direction)) { continue; } //seive5: End if pre or post is not parallel to direction. bool isPreDirParallel = Math.Abs(toPre * direction / (toPre.Length * direction.Length)) > 1 - parallelTolerance; bool isPostDirParallel = Math.Abs(toPost * direction / (toPost.Length * direction.Length)) > 1 - parallelTolerance; if (isPreDirParallel || isPostDirParallel) { continue; } //seive6: Continue if passable. Vector3d perpToDir = direction; perpToDir.Rotate(Math.PI / 2, Vector3d.ZAxis); double preDirDot = toPre * perpToDir; double postDirDot = toPost * perpToDir; if (preDirDot * postDirDot > 0) { continue; } break; } return(new Line(basePt, longestEnd)); }