Example #1
0
        /***************************************************/
        /**** 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
            });
        }
Example #2
0
        /***************************************************/

        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));
        }
Example #3
0
        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);
        }
Example #4
0
        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(),
            });
        }
Example #5
0
        /***************************************************/

        public static Cartesian Mirror(this Cartesian coordinateSystem, Plane p)
        {
            return(Create.CartesianCoordinateSystem(coordinateSystem.Origin.Mirror(p), coordinateSystem.X.Mirror(p), coordinateSystem.Y.Mirror(p)));
        }