/***************************************************/ /**** Public Methods - Curves ****/ /***************************************************/ public static Arc Flip(this Arc curve) { Cartesian system = Create.CartesianCoordinateSystem(curve.CoordinateSystem.Origin, curve.CoordinateSystem.X, -curve.CoordinateSystem.Y); return(new Arc { CoordinateSystem = system, StartAngle = -curve.EndAngle, EndAngle = -curve.StartAngle, Radius = curve.Radius }); }
/***************************************************/ public static Cartesian Transform(this Cartesian coordinateSystem, TransformMatrix transform) { Point origin = coordinateSystem.Origin.Transform(transform); Vector x = coordinateSystem.X.Transform(transform); Plane plane = Create.Plane(origin, x); Vector y = coordinateSystem.Y.Transform(transform).Project(plane); return(Create.CartesianCoordinateSystem(origin, x, y)); }
public static Arc RoundCoordinates(this Arc arc, int decimalPlaces = 6) { // do the rounding Point start = arc.StartPoint().RoundCoordinates(decimalPlaces); Point end = arc.EndPoint().RoundCoordinates(decimalPlaces); double angle = arc.Angle(); double dist = start.Distance(end); if (dist == 0) { // translate the origin as one of the points were, and set both angles to that ones angle return(new Arc() { CoordinateSystem = arc.CoordinateSystem.Translate(start - arc.StartPoint()), Radius = arc.Radius, StartAngle = arc.StartAngle, EndAngle = arc.StartAngle, }); } // recalculate the radius based on not changing the total angle // Consider a equal legged triangle with endpoints at the arc's endpoints // we know the "top" angle and the "base" length and are solving for the last two sides length double radius = Math.Sqrt( Math.Pow(dist / (2 * Math.Tan(angle / 2)), 2) + // "Height" Math.Pow(dist / 2, 2) // "half the base" ); // Align the normal to the new endpoints Vector normal = arc.CoordinateSystem.Z.CrossProduct(end - start).CrossProduct(start - end).Normalise(); Circle startCircle = new Circle() { Normal = normal, Centre = start, Radius = radius }; Circle endCircle = new Circle() { Normal = normal, Centre = end, Radius = radius }; List <Point> intersections = startCircle.CurveIntersections(endCircle).OrderBy(x => x.SquareDistance(arc.CoordinateSystem.Origin)).ToList(); Point newOrigin = null; // 180degrees arc where the points got rounded away from eachother if (intersections.Count == 0) { newOrigin = (start + end) / 2; radius = newOrigin.Distance(start); } else { // Ensure that the new centre is at the same side of the start/end points Vector unitNormal = normal.Normalise(); unitNormal *= angle > Math.PI ? -1 : 1; foreach (Point pt in intersections) { Vector temp = (start - pt).CrossProduct(end - pt).Normalise(); if ((temp + unitNormal).SquareLength() >= 1) { newOrigin = pt; break; } } } Vector newX = (start - newOrigin).Normalise(); oM.Geometry.CoordinateSystem.Cartesian coordClone = Create.CartesianCoordinateSystem(newOrigin, newX, Query.CrossProduct(normal, newX)); double endAngle = (start - newOrigin).Angle(end - newOrigin); endAngle = angle > Math.PI ? 2 * Math.PI - endAngle : endAngle; Arc result = new Arc() { CoordinateSystem = coordClone, Radius = radius, StartAngle = 0, EndAngle = endAngle, }; return(result); }
public static Output <double, double, Vector, Vector> PrincipalCurvatureAtParameter(this NurbsSurface surface, double u, double v) { // Vector entries for a "Hessian" with regard to u and v Vector dU2 = DerivativeAtParameter(surface, u, v, 2, 0); Vector dUV = DerivativeAtParameter(surface, u, v, 1, 1); Vector dV2 = DerivativeAtParameter(surface, u, v, 0, 2); // Get the local space, dU and dV are the basis vectors for the Hessian above. Vector dU = DerivativeAtParameter(surface, u, v, 1, 0); Vector dV = DerivativeAtParameter(surface, u, v, 0, 1); Vector normal = dU.CrossProduct(dV).Normalise(); // We reduce the vector valued Hessian to a scalar valued Hessian, where the value (of the imagined original function) is the distance from the point we evaluate along the normal // | a b | // | c d | double a = dU2.DotProduct(normal); double b = dUV.DotProduct(normal); double c = b; double d = dV2.DotProduct(normal); // That's the Hessian for a system where the derivative vectors are the local coordinate systems xy-axis, i.e very poorly scaled and skewed for most purposes double phi = dU.SignedAngle(dV, normal); // Change of basis matrix, to get the transform for the Hessian to the world space // | e f | // | g h | double e = 1 / dU.Length(); double g = 0; double h = 1 / (Math.Sin(phi) * dV.Length()); double f = -(Math.Cos(phi) * dV.Length()) * h * e; // A^T * Hess(x) * A gives the Hessian in the world space scaled/skewed system, i.e a system we care about double a1 = a * e * e + b * g * e + c * e * g + d * g * g; double b1 = e * a * f + e * b * h + g * c * f + g * d * h; double c1 = f * a * e + b * g * f + c * e * h + d * g * h; double d1 = a * f * f + b * h * f + c * f * h + d * h * h; // Eigenvalues of the Hessian gives the min and max curvature of the function double p = (a1 + d1) * 0.5; double sqrt = Math.Sqrt((a1 + d1) * (a1 + d1) * 0.25 - (a1 * d1 - b1 * c1)); if (double.IsNaN(sqrt)) { sqrt = 0; } double eigenMin = (p - sqrt); double eigenMax = (p + sqrt); // The eigenvectors of the Hessian are the principled directions Vector eigMin = new Vector(); Vector eigMax = new Vector(); if (Math.Abs(c1) > Tolerance.Distance) { eigMin.X = eigenMin - d1; eigMin.Y = c1; eigMax.X = eigenMax - d1; eigMax.Y = c1; } else if (Math.Abs(b1) > Tolerance.Distance) { eigMin.X = b1; eigMin.Y = eigenMin - a1; eigMax.X = b1; eigMax.Y = eigenMax - a1; } else { eigMin.X = 1; eigMax.Y = 1; } // Orient to world space, as in we've been working on the origin with the normal as z-axis, this places the vectors back to the surface. // would be nice to suppress the warning in some manner as it is very much intended. TransformMatrix matrix = Create.OrientationMatrixGlobalToLocal(Create.CartesianCoordinateSystem(new Point(), dU, dV)); return(new Output <double, double, Vector, Vector>() { Item1 = eigenMin, Item2 = eigenMax, Item3 = eigMin.Transform(matrix).Normalise(), Item4 = eigMax.Transform(matrix).Normalise(), }); }
/***************************************************/ public static Cartesian Mirror(this Cartesian coordinateSystem, Plane p) { return(Create.CartesianCoordinateSystem(coordinateSystem.Origin.Mirror(p), coordinateSystem.X.Mirror(p), coordinateSystem.Y.Mirror(p))); }