private List <InitialPt> FindFootOfPerp(Line perpBase, Vector3d perpDirection, AngleTagVertex perpStart, bool perpInvert) { List <InitialPt> footOfPerps = new List <InitialPt>(); if (!VectorTools.IsBetweenVector(perpStart.PreVec, perpStart.PostVec, perpDirection)) { return(footOfPerps); } Line crossLay = new Line(perpStart.Pt, perpStart.Pt + perpDirection); Point3d crossOnBase = CCXTools.GetCrossPt(perpBase, crossLay); if (crossOnBase == Point3d.Unset || boundCrv.Contains(crossOnBase) == PointContainment.Outside) { return(footOfPerps); } Polyline perpLinePoly = new Polyline { crossOnBase, perpStart.Pt }; Vector3d perpVec = perpStart.Pt - crossOnBase; if (perpInvert) { perpVec = -perpVec; } if (!CCXTools.IsIntersectCrv(perpLinePoly, boundary, false)) { footOfPerps.Add(new InitialPt(crossOnBase, perpBase.UnitTangent, perpVec)); } return(footOfPerps); }
/// <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)); }