public static Polyline Extend(this Polyline curve, double start = 0.0, double end = 0.0, bool tangentExtensions = false, double tolerance = Tolerance.Distance) { if (curve.IsClosed(tolerance)) { Reflection.Compute.RecordNote("Cannot Trim or Extend closed curves."); return(curve); } if (start + end + curve.Length() < tolerance) { Reflection.Compute.RecordError("Negative extend values are smaller than curve length."); return(null); } Polyline result = new Polyline(); List <Line> lines = curve.SubParts(); if (start < 0 && -start > lines[0].ILength()) { double startCut = -lines[0].ILength(); while (startCut > start && lines.Count > 1) { lines.RemoveAt(0); startCut -= lines[0].ILength(); } startCut += lines[0].ILength(); if (lines.Count > 1) { lines[0] = lines[0].Extend(start - startCut, 0, false, tolerance); } else { lines[0] = lines[0].Extend(start - startCut, end, tangentExtensions, tolerance); result = Create.Polyline(lines); return(result); } } else { lines[0] = lines[0].Extend(start, 0, tangentExtensions, tolerance); } if (end < 0 && -end > lines[lines.Count - 1].ILength()) { double endCut = -lines[lines.Count - 1].ILength(); while (endCut > end) { lines.RemoveAt(lines.Count - 1); endCut -= lines[lines.Count - 1].ILength(); } endCut += lines[lines.Count - 1].ILength(); lines[lines.Count - 1] = lines[lines.Count - 1].Extend(0, end - endCut, tangentExtensions, tolerance); } else { lines[lines.Count - 1] = lines[lines.Count - 1].Extend(0, end, tangentExtensions, tolerance); } result = Create.Polyline(lines); return(result); }
/***************************************************/ public static bool IsContaining(this Polyline curve, List <Point> points, bool acceptOnEdge = true, double tolerance = Tolerance.Distance) { // Todo: // check boundingBox/proximity at the beginning! // project to 2D & rewrite methods to 2D to improve performance // - to be replaced with a general method for a nurbs curve? // - could be done with a ray instead of an infinite line! if (curve.IsClosed(tolerance)) { Plane p = curve.FitPlane(tolerance); double sqTol = tolerance * tolerance; if (p == null) { if (acceptOnEdge) { foreach (Point pt in points) { if (curve.ClosestPoint(pt).SquareDistance(pt) > sqTol) { return(false); } } return(true); } else { return(false); } } else { List <Line> subParts = curve.SubParts(); List <Vector> edgeDirections = subParts.Select(c => c.Direction()).ToList(); foreach (Point pt in points) { Point pPt = pt.Project(p); if (pPt.SquareDistance(pt) <= sqTol) { Point end = p.Origin; Vector direction = (end - pPt).Normalise(); while (direction.SquareLength() <= 0.5 || edgeDirections.Any(e => 1 - Math.Abs(e.DotProduct(direction)) <= Tolerance.Angle)) { end = end.Translate(Create.RandomVectorInPlane(p, true)); direction = (end - pPt).Normalise(); } Line ray = new Line { Start = pPt, End = end }; ray.Infinite = true; List <Point> intersects = new List <Point>(); List <Point> extraIntersects = new List <Point>(); Func <double, double, double> ToFactor = (t, n) => (1 - t * t) / (1 - n * n); Line current = subParts[1]; double prevTolFactor = ToFactor(subParts[0].Direction().DotProduct(direction), current.Direction().DotProduct(direction)); for (int i = 1; i < subParts.Count + 1; i++) { Line next = subParts[(i + 1) % subParts.Count]; double nextTolFactor = ToFactor(next.Direction().DotProduct(direction), current.Direction().DotProduct(direction)); Point iPt = current.LineIntersection(ray, false, tolerance); if (iPt != null) { double signedAngle = direction.SignedAngle(current.Direction(), p.Normal); if ((current.Start.SquareDistance(iPt) <= sqTol * prevTolFactor)) // Will we get a point on the previous line { if (signedAngle > Tolerance.Angle) { intersects.Add(iPt); } else { extraIntersects.Add(iPt); } } else if ((current.End.SquareDistance(iPt) <= sqTol * nextTolFactor)) // Will we get a point on the next line { if (signedAngle < -Tolerance.Angle) { intersects.Add(iPt); } else { extraIntersects.Add(iPt); } } else { intersects.Add(iPt); } } prevTolFactor = 1 / nextTolFactor; current = next; } if (intersects.Count == 0) { return(false); } if ((pPt.ClosestPoint(intersects.Union(extraIntersects)).SquareDistance(pPt) <= sqTol)) { if (acceptOnEdge) { continue; } else { return(false); } } intersects.Add(pPt); intersects = intersects.SortCollinear(tolerance); for (int j = 0; j < intersects.Count; j++) { if (j % 2 == 0 && intersects[j] == pPt) { return(false); } } } else { return(false); } } return(true); } } return(false); }
/***************************************************/ public static Cartesian Mirror(this Cartesian coordinateSystem, Plane p) { return(Create.CartesianCoordinateSystem(coordinateSystem.Origin.Mirror(p), coordinateSystem.X.Mirror(p), coordinateSystem.Y.Mirror(p))); }
/***************************************************/ public static ICurve Project(this Ellipse ellipse, Plane p) { TransformMatrix project = Create.ProjectionMatrix(p, p.Normal); return(ellipse.Transform(project)); }
/***************************************************/ public static List <IntegrationSlice> IntegrationSlices(List <ICurve> edges, Vector direction, double increment = 0.001, double tolerance = Tolerance.Distance) { List <IntegrationSlice> slices = new List <IntegrationSlice>(); if (edges.Count == 0) { return(slices); } List <double> cutAt = new List <double>(); List <double> sliceSegments = new List <double>(); Plane p = new Plane { Origin = oM.Geometry.Point.Origin, Normal = direction }; for (int i = 0; i < edges.Count; i++) { for (int j = 0; j < edges[i].IControlPoints().Count; j++) { cutAt.Add(Query.DotProduct(Create.Vector(edges[i].IControlPoints()[j]), p.Normal)); } } cutAt.Sort(); cutAt = cutAt.Distinct <double>().ToList(); double currentValue = Query.DotProduct(Create.Vector(Query.Bounds(new PolyCurve { Curves = edges }).Min), p.Normal); double max = Query.DotProduct(Create.Vector(Query.Bounds(new PolyCurve { Curves = edges }).Max), p.Normal); int index = 0; while (currentValue < max) { if (cutAt.Count > index && currentValue > cutAt[index]) { sliceSegments.Add(cutAt[index]); index++; } else { sliceSegments.Add(currentValue); currentValue += increment; } } sliceSegments.Add(max); for (int i = 0; i < sliceSegments.Count - 1; i++) { if (sliceSegments[i] == sliceSegments[i + 1]) { continue; } currentValue = (sliceSegments[i] + sliceSegments[i + 1]) / 2; slices.Add(Query.SliceAt(edges, currentValue, -sliceSegments[i] + sliceSegments[i + 1], p, tolerance)); } return(slices); }
public static T Orient <T>(this T geometry, Cartesian csFrom, Cartesian csTo) where T : IGeometry { TransformMatrix orientationMatrix = Create.OrientationMatrix(csFrom, csTo); return((T)ITransform(geometry, orientationMatrix)); }
/***************************************************/ public static bool IsContaining(this Polyline curve, List <Point> points, bool acceptOnEdge = true, double tolerance = Tolerance.Distance) { // Todo: // check boundingBox/proximity at the beginning! // project to 2D & rewrite methods to 2D to improve performance // - to be replaced with a general method for a nurbs curve? // - could be done with a ray instead of an infinite line! if (curve.IsClosed(tolerance)) { Plane p = curve.FitPlane(tolerance); double sqTol = tolerance * tolerance; if (p == null) { if (acceptOnEdge) { foreach (Point pt in points) { if (curve.ClosestPoint(pt).SquareDistance(pt) > sqTol) { return(false); } } return(true); } else { return(false); } } else { foreach (Point pt in points) { Point pPt = pt.Project(p); if (pPt.SquareDistance(pt) <= sqTol) { Point end = p.Origin; if (pPt.SquareDistance(end) <= sqTol) { end = end.Translate(Create.RandomVectorInPlane(p, true)); } Line ray = new Line { Start = pPt, End = end }; ray.Infinite = true; Vector rayDir = ray.Direction(); List <Line> subParts = curve.SubParts(); List <Point> intersects = new List <Point>(); List <Point> extraIntersects = new List <Point>(); foreach (Line subPart in subParts) { Point iPt = subPart.LineIntersection(ray, false, tolerance); if (iPt != null) { double signedAngle = rayDir.SignedAngle(subPart.Direction(), p.Normal); if ((subPart.Start.SquareDistance(iPt) <= sqTol)) { if (signedAngle > Tolerance.Angle) { intersects.Add(iPt); } else { extraIntersects.Add(iPt); } } else if ((subPart.End.SquareDistance(iPt) <= sqTol)) { if (signedAngle < -Tolerance.Angle) { intersects.Add(iPt); } else { extraIntersects.Add(iPt); } } else { intersects.Add(iPt); } } } if (intersects.Count == 0) { return(false); } if ((pPt.ClosestPoint(intersects.Union(extraIntersects)).SquareDistance(pPt) <= sqTol)) { if (acceptOnEdge) { continue; } else { return(false); } } intersects.Add(pPt); intersects = intersects.SortCollinear(tolerance); for (int j = 0; j < intersects.Count; j++) { if (j % 2 == 0 && intersects[j] == pPt) { return(false); } } } else { return(false); } } return(true); } } return(false); }
/***************************************************/ /**** Public Methods - Others ****/ /***************************************************/ public static Mesh Rotate(this Mesh mesh, Point origin, Vector axis, double rad) { TransformMatrix rotationMatrix = Create.RotationMatrix(origin, axis, rad); return(Transform(mesh, rotationMatrix)); }
/***************************************************/ public static ICurve Rotate(this Ellipse curve, Point origin, Vector axis, double rad) { TransformMatrix rotationMatrix = Create.RotationMatrix(origin, axis, rad); return(Transform(curve, rotationMatrix)); }
/***************************************************/ public static NurbsCurve ToNurbsCurve(this Line line) { return(Create.NurbsCurve(new List <Point> { line.Start, line.End }, new double[] { 1, 1 }, new double[] { 0, 1 })); }
/***************************************************/ public static Basis Rotate(this Basis basis, double rad, Vector axis) { return(Create.Basis(basis.X.Rotate(rad, axis), basis.Y.Rotate(rad, axis))); }
/***************************************************/ public static Plane Rotate(this Plane plane, Point origin, Vector axis, double rad) { TransformMatrix rotationMatrix = Create.RotationMatrix(origin, axis, rad); return(Transform(plane, rotationMatrix)); }
/***************************************************/ public static CompositeGeometry Rotate(this CompositeGeometry group, Point origin, Vector axis, double rad) { TransformMatrix rotationMatrix = Create.RotationMatrix(origin, axis, rad); return(Transform(group, rotationMatrix)); }
/***************************************************/ public static bool IsContaining(this PolyCurve curve, List <Point> points, bool acceptOnEdge = true, double tolerance = Tolerance.Distance) { // Todo: // - to be replaced with a general method for a nurbs curve? // - this is very problematic for edge cases (cutting line going through a sharp corner, to be superseded? BoundingBox box = curve.Bounds(); if (points.Any(x => !box.IsContaining(x, true, tolerance))) { return(false); } if (!curve.IsClosed(tolerance)) { return(false); } if (curve.Curves.Count == 1 && curve.Curves[0] is Circle) { return(IsContaining(curve.Curves[0] as Circle, points, acceptOnEdge, tolerance)); } Plane p = curve.FitPlane(tolerance); double sqTol = tolerance * tolerance; if (p == null) { if (acceptOnEdge) { foreach (Point pt in points) { if (curve.ClosestPoint(pt).SquareDistance(pt) > sqTol) { return(false); } } return(true); } else { return(false); } } List <ICurve> subParts = curve.SubParts(); List <Vector> edgeDirections = subParts.Where(s => s is Line).Select(c => (c as Line).Direction()).ToList(); foreach (Point pt in points) { Point pPt = pt.Project(p); if (pPt.SquareDistance(pt) > sqTol) // not on the same plane { return(false); } Point end = p.Origin; // Avrage of control points Vector direction = (end - pPt).Normalise(); // Gets a line cutting through the curves and the point while (direction.SquareLength() <= 0.5 || edgeDirections.Any(e => 1 - Math.Abs(e.DotProduct(direction)) <= Tolerance.Angle)) // not zeroa or parallel to edges { end = end.Translate(Create.RandomVectorInPlane(p, true)); direction = (end - pPt).Normalise(); } Line ray = new Line { Start = pPt, End = end }; ray.Infinite = true; List <Point> intersects = new List <Point>(); List <Point> extraIntersects = new List <Point>(); foreach (ICurve subPart in subParts) { List <Point> iPts = subPart.ILineIntersections(ray, false, tolerance); // LineIntersection ignores the `false` foreach (Point iPt in iPts) { double signedAngle = direction.SignedAngle(subPart.ITangentAtPoint(iPt, tolerance), p.Normal); if ((subPart.IStartPoint().SquareDistance(iPt) <= sqTol)) // Keep intersections from beeing counted twice? { if (signedAngle >= -Tolerance.Angle) // tangent is to the left of the direction { intersects.Add(iPt); } else { extraIntersects.Add(iPt); } } else if ((subPart.IEndPoint().SquareDistance(iPt) <= sqTol)) { if (signedAngle <= Tolerance.Angle) // tangent is to the rigth of the direction { intersects.Add(iPt); } else { extraIntersects.Add(iPt); } } else if (Math.Abs(signedAngle) <= Tolerance.Angle) // They are parallel { extraIntersects.Add(iPt); } else { intersects.Add(iPt); } } } if (intersects.Count == 0) // did not intersect the curve (strange) { return(false); } if ((pPt.ClosestPoint(intersects.Union(extraIntersects)).SquareDistance(pPt) <= sqTol)) // if any intersection point is the point { if (acceptOnEdge) { continue; } else { return(false); } } intersects.Add(pPt); intersects = intersects.SortCollinear(tolerance); for (int j = 0; j < intersects.Count; j++) // Even indecies on a colinerar sort is outside the region { if (j % 2 == 0 && intersects[j] == pPt) { return(false); } } } return(true); }
/***************************************************/ public static bool IsContaining(this PolyCurve curve, List <Point> points, bool acceptOnEdge = true, double tolerance = Tolerance.Distance) { // Todo: // - to be replaced with a general method for a nurbs curve? // - this is very problematic for edge cases (cutting line going through a sharp corner, to be superseded? if (curve.IsClosed(tolerance)) { Plane p = curve.FitPlane(tolerance); double sqTol = tolerance * tolerance; if (p == null) { if (acceptOnEdge) { foreach (Point pt in points) { if (curve.ClosestPoint(pt).SquareDistance(pt) > sqTol) { return(false); } } return(true); } else { return(false); } } else { foreach (Point pt in points) { Point pPt = pt.Project(p); if (pPt.SquareDistance(pt) <= sqTol) { Point end = p.Origin; if (pPt.SquareDistance(end) <= sqTol) { end = end.Translate(Create.RandomVectorInPlane(p, true)); } Line ray = new Line { Start = pPt, End = end }; ray.Infinite = true; Vector rayDir = ray.Direction(); List <ICurve> subParts = curve.SubParts(); List <Point> intersects = new List <Point>(); List <Point> extraIntersects = new List <Point>(); foreach (ICurve subPart in subParts) { List <Point> iPts = subPart.ILineIntersections(ray, false, tolerance); foreach (Point iPt in iPts) { double signedAngle = rayDir.SignedAngle(subPart.ITangentAtPoint(iPt, tolerance), p.Normal); if ((subPart.IStartPoint().SquareDistance(iPt) <= sqTol)) { if (signedAngle >= -Tolerance.Angle) { intersects.Add(iPt); } else { extraIntersects.Add(iPt); } } else if ((subPart.IEndPoint().SquareDistance(iPt) <= sqTol)) { if (signedAngle <= Tolerance.Angle) { intersects.Add(iPt); } else { extraIntersects.Add(iPt); } } else if (Math.Abs(signedAngle) <= Tolerance.Angle) { extraIntersects.Add(iPt); } else { intersects.Add(iPt); } } } if (intersects.Count == 0) { return(false); } if ((pPt.ClosestPoint(intersects.Union(extraIntersects)).SquareDistance(pPt) <= sqTol)) { if (acceptOnEdge) { continue; } else { return(false); } } intersects.Add(pPt); intersects = intersects.SortCollinear(tolerance); for (int j = 0; j < intersects.Count; j++) { if (j % 2 == 0 && intersects[j] == pPt) { return(false); } } } else { return(false); } } return(true); } } return(false); }
/***************************************************/ private static PolyCurve Fillet(this ICurve curve1, ICurve curve2, bool tangentExtensions, bool keepCurve1StartPoint, bool keepCurve2StartPoint, double tolerance = Tolerance.Distance) { //TODO: //Write a proper fillet method, test and make it public if (!((curve1 is Line || curve1 is Arc) && (curve2 is Line || curve2 is Arc))) //for now works only with combinations of lines and arcs { Reflection.Compute.RecordError("Private method fillet is implemented only for PolyCurves consisting of Lines or Arcs."); return(null); } List <PolyCurve> joinCurves = Compute.IJoin(new List <ICurve> { curve1, curve2 }, tolerance).ToList(); if (joinCurves.Count == 1) { return(joinCurves[0]); } List <ICurve> resultCurves = new List <ICurve>(); bool C1SP = keepCurve1StartPoint; bool C2SP = keepCurve2StartPoint; List <Point> intersections = curve1.ICurveIntersections(curve2, tolerance); if (intersections.Count > 2) { Reflection.Compute.RecordError("Invalid number of intersections between curves. Two lines/arcs can have no more than two intersections."); } else if (intersections.Count == 2 || intersections.Count == 1) { Point intersection = intersections[0]; if (intersections.Count == 2) { double maxdist = double.MaxValue; if (C1SP) { foreach (Point p in intersections) { double dist = p.SquareDistance(curve1.IStartPoint()); if (dist < maxdist) { intersection = p; maxdist = dist; } } } else { foreach (Point p in intersections) { double dist = p.SquareDistance(curve1.IEndPoint()); if (dist < maxdist) { intersection = p; maxdist = dist; } } } } else { intersection = intersections[0]; } if (C1SP && C2SP) { resultCurves.AddRange(curve1.ExtendToPoint(curve1.IStartPoint(), intersection, tangentExtensions, tolerance)); resultCurves.AddRange(curve2.ExtendToPoint(curve2.IStartPoint(), intersection, tangentExtensions, tolerance)); resultCurves[1] = resultCurves[1].IFlip(); } else if (C1SP && !C2SP) { resultCurves.AddRange(curve1.ExtendToPoint(curve1.IStartPoint(), intersection, tangentExtensions, tolerance)); resultCurves.AddRange(curve2.ExtendToPoint(intersection, curve2.IEndPoint(), tangentExtensions, tolerance)); } else if (!C1SP && C2SP) { resultCurves.AddRange(curve1.ExtendToPoint(intersection, curve1.IEndPoint(), tangentExtensions, tolerance)); resultCurves.AddRange(curve2.ExtendToPoint(curve2.IStartPoint(), intersection, tangentExtensions, tolerance)); resultCurves[0] = resultCurves[0].IFlip(); resultCurves[1] = resultCurves[1].IFlip(); } else { resultCurves.AddRange(curve1.ExtendToPoint(intersection, curve1.IEndPoint(), tangentExtensions, tolerance)); resultCurves.AddRange(curve2.ExtendToPoint(intersection, curve2.IEndPoint(), tangentExtensions, tolerance)); resultCurves[0] = resultCurves[0].IFlip(); } } else { if (curve1 is Line && curve2 is Line) { Point intersection = (curve1 as Line).LineIntersection(curve2 as Line, true, tolerance); if (C1SP && C2SP) { if ((curve1.IStartPoint().Distance((curve2 as Line), true) < curve1.IEndPoint().Distance((curve2 as Line), true) && !intersection.IIsOnCurve(curve1)) || (curve2.IStartPoint().Distance((curve1 as Line), true) < curve2.IEndPoint().Distance((curve1 as Line), true) && !intersection.IIsOnCurve(curve2))) { Reflection.Compute.RecordWarning("Couldn't provide correct fillet for given input"); return(null); } resultCurves.AddRange(curve1.ExtendToPoint(curve1.IStartPoint(), intersection, tangentExtensions, tolerance)); resultCurves.AddRange(curve2.ExtendToPoint(curve2.IStartPoint(), intersection, tangentExtensions, tolerance)); resultCurves[1] = resultCurves[1].IFlip(); } else if (C1SP && !C2SP) { if ((curve1.IStartPoint().Distance((curve2 as Line), true) < curve1.IEndPoint().Distance((curve2 as Line), true) && !intersection.IIsOnCurve(curve1)) || (curve2.IStartPoint().Distance((curve1 as Line), true) > curve2.IEndPoint().Distance((curve1 as Line), true) && !intersection.IIsOnCurve(curve2))) { Reflection.Compute.RecordWarning("Couldn't provide correct fillet for given input"); return(null); } resultCurves.AddRange(curve1.ExtendToPoint(curve1.IStartPoint(), intersection, tangentExtensions, tolerance)); resultCurves.AddRange(curve2.ExtendToPoint(intersection, curve2.IEndPoint(), tangentExtensions, tolerance)); } else if (!C1SP && C2SP) { if ((curve1.IStartPoint().Distance((curve2 as Line), true) > curve1.IEndPoint().Distance((curve2 as Line), true) && !intersection.IIsOnCurve(curve1)) || (curve2.IStartPoint().Distance((curve1 as Line), true) < curve2.IEndPoint().Distance((curve1 as Line), true) && !intersection.IIsOnCurve(curve2))) { Reflection.Compute.RecordWarning("Couldn't provide correct fillet for given input"); return(null); } resultCurves.AddRange(curve1.ExtendToPoint(intersection, curve1.IEndPoint(), tangentExtensions, tolerance)); resultCurves.AddRange(curve2.ExtendToPoint(curve2.IStartPoint(), intersection, tangentExtensions, tolerance)); resultCurves[0] = resultCurves[0].IFlip(); resultCurves[1] = resultCurves[1].IFlip(); } else { if ((curve1.IStartPoint().Distance((curve2 as Line), true) > curve1.IEndPoint().Distance((curve2 as Line), true) && !intersection.IIsOnCurve(curve1)) || (curve2.IStartPoint().Distance((curve1 as Line), true) > curve2.IEndPoint().Distance((curve1 as Line), true) && !intersection.IIsOnCurve(curve2))) { Reflection.Compute.RecordWarning("Couldn't provide correct fillet for given input"); return(null); } resultCurves.AddRange(curve1.ExtendToPoint(intersection, curve1.IEndPoint(), tangentExtensions, tolerance)); resultCurves.AddRange(curve2.ExtendToPoint(intersection, curve2.IEndPoint(), tangentExtensions, tolerance)); resultCurves[0] = resultCurves[0].IFlip(); } } else { Point intersection; if (!tangentExtensions) { PolyCurve pCurve1 = new PolyCurve(); PolyCurve pCurve2 = new PolyCurve(); if (curve1 is Arc) { pCurve1.Curves.Add(new Circle { Centre = (curve1 as Arc).Centre(), Normal = (curve1 as Arc).Normal(), Radius = (curve1 as Arc).Radius }); } else { pCurve1.Curves.Add(new Line { Start = (curve1 as Line).Start, End = (curve1 as Line).End, Infinite = true }); } if (curve2 is Arc) { pCurve2.Curves.Add(new Circle { Centre = (curve2 as Arc).Centre(), Normal = (curve2 as Arc).Normal(), Radius = (curve2 as Arc).Radius }); } else { pCurve2.Curves.Add(new Line { Start = (curve2 as Line).Start, End = (curve2 as Line).End, Infinite = true }); } List <Point> curveIntersections = pCurve1.CurveIntersections(pCurve2, tolerance); if (curveIntersections.Count == 0) { Reflection.Compute.RecordError("Curves' extensions do not intersect"); return(null); } if (C1SP && C2SP) { intersection = curveIntersections.ClosestPoint(curve1.IEndPoint()); resultCurves.AddRange(curve1.ExtendToPoint(curve1.IStartPoint(), intersection, tangentExtensions, tolerance)); resultCurves.AddRange(curve2.ExtendToPoint(curve2.IStartPoint(), intersection, tangentExtensions, tolerance)); resultCurves[1] = resultCurves[1].IFlip(); } else if (C1SP && !C2SP) { intersection = curveIntersections.ClosestPoint(curve1.IEndPoint()); resultCurves.AddRange(curve1.ExtendToPoint(curve1.IStartPoint(), intersection, tangentExtensions, tolerance)); resultCurves.AddRange(curve2.ExtendToPoint(intersection, curve2.IEndPoint(), tangentExtensions, tolerance)); } else if (!C1SP && C2SP) { intersection = curveIntersections.ClosestPoint(curve1.IStartPoint()); resultCurves.AddRange(curve1.ExtendToPoint(intersection, curve1.IEndPoint(), tangentExtensions, tolerance)); resultCurves.AddRange(curve2.ExtendToPoint(curve2.IStartPoint(), intersection, tangentExtensions, tolerance)); resultCurves[0] = resultCurves[0].IFlip(); resultCurves[1] = resultCurves[1].IFlip(); } else { intersection = curveIntersections.ClosestPoint(curve1.IStartPoint()); resultCurves.AddRange(curve1.ExtendToPoint(intersection, curve1.IEndPoint(), tangentExtensions, tolerance)); resultCurves.AddRange(curve2.ExtendToPoint(intersection, curve2.IEndPoint(), tangentExtensions, tolerance)); resultCurves[0] = resultCurves[0].IFlip(); } } else { if (C1SP && C2SP) { Line tanLine1 = Create.Line(curve1.IEndPoint(), curve1.IEndDir() / tolerance); tanLine1.Infinite = false; PolyCurve pCurve1 = new PolyCurve { Curves = { curve1, tanLine1 } }; Line tanLine2 = Create.Line(curve2.IEndPoint(), curve2.IEndDir() / tolerance); tanLine2.Infinite = false; PolyCurve pCurve2 = new PolyCurve { Curves = { curve2, tanLine2 } }; List <Point> curveIntersecions = pCurve1.CurveIntersections(pCurve2, tolerance); if (curveIntersecions.Count > 0) { intersection = curveIntersecions.ClosestPoint(curve1.IEndPoint()); } else { Reflection.Compute.RecordWarning("Couldn't create fillet"); return(null); } PolyCurve subResult1 = new PolyCurve { Curves = curve1.ExtendToPoint(curve1.IStartPoint(), intersection, tangentExtensions, tolerance).ToList() }; PolyCurve subResult2 = new PolyCurve { Curves = curve2.ExtendToPoint(curve2.IStartPoint(), intersection, tangentExtensions, tolerance).ToList() }; subResult2 = subResult2.Flip(); resultCurves.AddRange(subResult1.Curves); resultCurves.AddRange(subResult2.Curves); } else if (C1SP && !C2SP) { Line tanLine1 = Create.Line(curve1.IEndPoint(), curve1.IEndDir() / tolerance); tanLine1.Infinite = false; PolyCurve pCurve1 = new PolyCurve { Curves = { curve1, tanLine1 } }; Line tanLine2 = Create.Line(curve2.IStartPoint(), curve2.IStartDir().Reverse() / tolerance); tanLine2.Infinite = false; PolyCurve pCurve2 = new PolyCurve { Curves = { tanLine2, curve2 } }; List <Point> curveIntersecions = pCurve1.ICurveIntersections(pCurve2, tolerance); if (curveIntersecions.Count > 0) { intersection = curveIntersecions.ClosestPoint(curve1.IEndPoint()); } else { Reflection.Compute.RecordWarning("Couldn't create fillet"); return(null); } resultCurves.AddRange(curve1.ExtendToPoint(curve1.IStartPoint(), intersection, tangentExtensions, tolerance)); resultCurves.AddRange(curve2.ExtendToPoint(intersection, curve2.IEndPoint(), tangentExtensions, tolerance)); } else if (!C1SP && C2SP) { Line tanLine1 = Create.Line(curve1.IStartPoint(), curve1.IStartDir().Reverse() / tolerance); tanLine1.Infinite = false; PolyCurve pCurve1 = new PolyCurve { Curves = { tanLine1, curve1 } }; Line tanLine2 = Create.Line(curve2.IEndPoint(), curve2.IEndDir() / tolerance); tanLine2.Infinite = false; PolyCurve pCurve2 = new PolyCurve { Curves = { curve2, tanLine2 } }; List <Point> curveIntersecions = pCurve1.ICurveIntersections(pCurve2, tolerance); if (curveIntersecions.Count > 0) { intersection = curveIntersecions.ClosestPoint(curve1.IStartPoint()); } else { Reflection.Compute.RecordWarning("Couldn't create fillet"); return(null); } PolyCurve subResult1 = new PolyCurve { Curves = curve1.ExtendToPoint(intersection, curve1.IEndPoint(), tangentExtensions, tolerance).ToList() }; PolyCurve subResult2 = new PolyCurve { Curves = curve2.ExtendToPoint(curve2.IStartPoint(), intersection, tangentExtensions, tolerance).ToList() }; subResult1 = subResult1.Flip(); subResult2 = subResult2.Flip(); resultCurves.AddRange(subResult1.Curves); resultCurves.AddRange(subResult2.Curves); } else { Line tanLine1 = Create.Line(curve1.IStartPoint(), curve1.IStartDir().Reverse() / tolerance); tanLine1.Infinite = false; PolyCurve pCurve1 = new PolyCurve { Curves = { tanLine1, curve1 } }; Line tanLine2 = Create.Line(curve2.IStartPoint(), curve2.IStartDir().Reverse() / tolerance); tanLine2.Infinite = false; PolyCurve pCurve2 = new PolyCurve { Curves = { tanLine2, curve2 } }; List <Point> curveIntersecions = pCurve1.ICurveIntersections(pCurve2, tolerance); if (curveIntersecions.Count > 0) { intersection = curveIntersecions.ClosestPoint(curve1.IStartPoint()); } else { Reflection.Compute.RecordWarning("Couldn't create fillet"); return(null); } PolyCurve subResult1 = new PolyCurve { Curves = curve1.ExtendToPoint(intersection, curve1.IEndPoint(), tangentExtensions, tolerance).ToList() }; PolyCurve subResult2 = new PolyCurve { Curves = curve2.ExtendToPoint(intersection, curve2.IEndPoint(), tangentExtensions, tolerance).ToList() }; subResult1 = subResult1.Flip(); resultCurves.AddRange(subResult1.Curves); resultCurves.AddRange(subResult2.Curves); } } } } for (int i = resultCurves.Count - 1; i >= 0; i--) { if (resultCurves[i] is PolyCurve) { PolyCurve temp = (PolyCurve)resultCurves[i]; resultCurves.RemoveAt(i); resultCurves.InsertRange(i, temp.Curves); } } PolyCurve result = new PolyCurve { Curves = resultCurves }; return(result); }
/***************************************************/ public static PolySurface Rotate(this PolySurface surface, Point origin, Vector axis, double rad) { TransformMatrix rotationMatrix = Create.RotationMatrix(origin, axis, rad); return(Transform(surface, rotationMatrix)); }