public static Point3d?GetOrthoNormalPoint(this Polyline pline, Point3d point, Plane plane, bool nullForOutOfRange = true) { point = point.OrthoProject(pline.GetPlane()); List <Point3d> res = new List <Point3d>(); var segments = pline.GetSegments(); int i = 0; foreach (var s in segments) { if (point.IsEqualTo(s.StartPoint, Tolerance.Global)) { return(point); } Vector3d vector = point - s.StartPoint; Vector3d segmVector = s.EndPoint - s.StartPoint; double cos = segmVector.GetCos2d(vector); double length = s.GetLength(s.GetParameterOf(s.StartPoint), s.GetParameterOf(s.EndPoint), Tolerance.Global.EqualPoint); /////////////////////////////////////////////// if (!nullForOutOfRange) { if (i == 0 && cos < 0d) { return(s.StartPoint); } if (i == segments.Count() - 1 && cos > 0 && cos * vector.Length > segmVector.Length) { return(s.EndPoint); } i++; } /////////////////////////////////////////////// if (cos >= 0d && cos * vector.Length <= segmVector.Length) { if (s is CircularArc3d) { CircularArc3d arc3d = (CircularArc3d)s; Arc arc = arc3d.ConvertToArc(); Point3d? normalPoint = arc.GetOrthoNormalPoint(point, nullForOutOfRange); if (normalPoint.HasValue) { res.Add(normalPoint.Value); } } else if (s is LineSegment3d) { LineSegment3d line3d = (LineSegment3d)s; Line line = line3d.ConvertToLine(); Point3d? normalPoint = line.GetOrthoNormalPoint(point, plane, nullForOutOfRange); if (normalPoint.HasValue) { res.Add(normalPoint.Value); } } } } if (res.Count == 0) { return(null); } else { res.Sort((p1, p2) => Comparer <double> .Default.Compare((point - p1).Length, (point - p2).Length)); return(res[0]); } }