/***************************************************/ public static Point PointAtParameter(this PolyCurve curve, double parameter) { if (parameter == 0) { return(curve.StartPoint()); } else if (parameter == 1) { return(curve.EndPoint()); } double cLength = parameter * curve.Length(); foreach (ICurve c in curve.SubParts()) { double l = c.ILength(); if (l >= cLength) { return(c.IPointAtParameter(cLength / l)); } cLength -= l; } return(null); }
/***************************************************/ public static List <Point> DiscontinuityPoints(this PolyCurve curve, double distanceTolerance = Tolerance.Distance, double angleTolerance = Tolerance.Angle) { List <Point> result = new List <Point>(); List <ICurve> curves = curve.SubParts().Where(c => !(c is Circle || c is Ellipse)).ToList(); bool closed = curve.IsClosed(distanceTolerance); if (curves.Count == 0) { return(result); } int j; for (int i = 0; i < curves.Count; i++) { j = (i - 1 + curves.Count) % curves.Count; if (i > 0 || closed) { if (!curves[j].IEndDir().IsEqual(curves[i].IStartDir(), distanceTolerance)) { result.Add(curves[i].IStartPoint()); } } else { result.Add(curves[i].IStartPoint()); } } if (!closed) { result.Add(curve.EndPoint()); } return(result); }
/***************************************************/ public static List <PolyCurve> SplitAtPoints(this PolyCurve curve, List <Point> points, double tolerance = Tolerance.Distance) { if (points.Count == 0) { return new List <PolyCurve> { curve.DeepClone() } } ; List <PolyCurve> result = new List <PolyCurve>(); List <ICurve> tmpResult = new List <ICurve>(); List <Point> subPoints = new List <Point>(); List <Point> onCurvePoints = new List <Point>(); foreach (Point p in points) { if (p.IsOnCurve(curve, tolerance)) { onCurvePoints.Add(p); } } onCurvePoints = onCurvePoints.CullDuplicates(tolerance); if (onCurvePoints.Count == 0) { return new List <PolyCurve> { curve.DeepClone() } } ; onCurvePoints = onCurvePoints.SortAlongCurve(curve); foreach (ICurve crv in curve.SubParts()) { if (crv is Arc) { foreach (Point point in onCurvePoints) { if (point.IIsOnCurve(crv, tolerance)) { subPoints.Add(point); } } tmpResult.AddRange((crv as Arc).SplitAtPoints(subPoints)); subPoints.Clear(); } else if (crv is Line) { foreach (Point point in onCurvePoints) { if (point.IIsOnCurve(crv, tolerance)) { subPoints.Add(point); } } tmpResult.AddRange((crv as Line).SplitAtPoints(subPoints)); subPoints.Clear(); } else if (crv is Circle) { List <PolyCurve> tResult = new List <PolyCurve>(); foreach (Arc arc in (crv as Circle).SplitAtPoints(onCurvePoints, tolerance)) { tResult.Add(new PolyCurve { Curves = new List <ICurve> { arc } }); } result.AddRange(tResult); } else { Reflection.Compute.RecordError($"SplitAtPoints is not implemented for PolyCurves consisting of ICurves of type: {crv.GetType().Name}."); return(null); } } int i = 0; int j = 0; if (curve.IStartPoint().IsEqual(onCurvePoints[0])) { onCurvePoints.Add(onCurvePoints[0]); onCurvePoints.RemoveAt(0); } while (i <= onCurvePoints.Count) { List <ICurve> subResultList = new List <ICurve>(); while (j < tmpResult.Count) { subResultList.Add(tmpResult[j]); if (i < onCurvePoints.Count) { if (tmpResult[j].IEndPoint().IsEqual(onCurvePoints[i]) || (curve.IIsClosed(tolerance) && !curve.IIsClockwise(curve.INormal(), tolerance) && tmpResult[j].IStartPoint().IsEqual(onCurvePoints[i]))) { j++; break; } else if (tmpResult[j].IEndPoint().IsEqual(curve.EndPoint()) || (curve.IIsClosed(tolerance) && !curve.IIsClockwise(curve.INormal(), tolerance) && tmpResult[j].IEndPoint().IsEqual(curve.StartPoint()))) { j++; break; } } j++; } if (subResultList.Count > 0) { result.Add(new PolyCurve { Curves = subResultList.ToList() }); } i++; } if (curve.IsClosed(tolerance) && !(curve.SubParts()[0] is Circle)) { if (!curve.StartPoint().IsEqual(onCurvePoints[onCurvePoints.Count - 1])) { List <ICurve> subResultList = new List <ICurve>(); foreach (ICurve subCrv in result[result.Count - 1].ISubParts()) { subResultList.Add(subCrv); } foreach (ICurve subCrv in result[0].ISubParts()) { subResultList.Add(subCrv); } result.RemoveAt(0); result.RemoveAt(result.Count - 1); result.Add(new PolyCurve { Curves = subResultList.ToList() }); } } return(result); }
/***************************************************/ /**** Public Methods ****/ /***************************************************/ public static PolyCurve SortCurves(this PolyCurve curve, double tolerance = Tolerance.Distance) { if (curve.Curves.Count < 2) { return(curve.DeepClone()); } List <ICurve> pending = curve.Curves.Select(x => x.DeepClone()).ToList(); PolyCurve result = new PolyCurve { Curves = new List <ICurve> { pending[0] } }; pending.RemoveAt(0); double sqTol = tolerance * tolerance; while (pending.Count > 0) { Point start1 = result.StartPoint(); Point end1 = result.EndPoint(); bool foundNext = false; for (int i = 0; i < pending.Count; i++) { Point start2 = pending[i].IStartPoint(); Point end2 = pending[i].IEndPoint(); if (end1.SquareDistance(start2) < sqTol) { result.Curves.Add(pending[i]); pending.RemoveAt(i); foundNext = true; break; } else if (end1.SquareDistance(end2) < sqTol) { result.Curves.Add(pending[i].IFlip()); pending.RemoveAt(i); foundNext = true; break; } else if (start1.SquareDistance(end2) < sqTol) { result.Curves.Insert(0, pending[i]); pending.RemoveAt(i); foundNext = true; break; } else if (start1.SquareDistance(start2) < sqTol) { result.Curves.Insert(0, pending[i].IFlip()); pending.RemoveAt(i); foundNext = true; break; } } if (!foundNext) { throw new Exception("PolyCurve with unconnected subcurves cannot have them sorted"); } } return(result); }