Example #1
0
        /***************************************************/

        public static Plane Plane(Point p1, Point p2, Point p3)
        {
            Vector normal = Query.CrossProduct(p2 - p1, p3 - p1).Normalise();

            return(new Plane {
                Origin = p1.Clone(), Normal = normal
            });
        }
Example #2
0
        /***************************************************/

        public static Vector Normal(this Mesh mesh, Face face, double tolerance = Tolerance.Distance)
        {
            List <Point> vertices = mesh.Vertices;

            Point  p1    = vertices[(face.A)];
            Point  p2    = vertices[(face.B)];
            Point  p3    = vertices[(face.C)];
            Vector v1    = p2 - p1;
            Vector v2    = p3 - p1;
            double sqTol = tolerance * tolerance;

            return(v1.SquareLength() <= sqTol || v2.SquareLength() <= sqTol ? null : Query.CrossProduct(p2 - p1, p3 - p1));
        }
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);
        }
        /***************************************************/

        public static List <Point> MeshIntersections(this Line curve, Mesh mesh, double tolerance = Tolerance.Distance)
        {
            // Outputs
            List <Point> points = new List <Point>();

            // Preprocessing Mesh
            Mesh         tMesh   = mesh.Triangulate();
            List <Face>  faces   = tMesh.Faces;
            List <Point> meshPts = tMesh.Vertices;

            for (int i = 0; i < faces.Count; i++)
            {
                // Mesh Points
                Point p1 = meshPts[faces[i].A];
                Point p2 = meshPts[faces[i].B];
                Point p3 = meshPts[faces[i].C];

                // Ray direction
                Vector d = curve.PointAtParameter(1) - curve.PointAtParameter(0);

                // Vectors from p1 to p2/p3 (edges)
                Vector e1, e2;

                Vector p, q, t;
                double det, invDet, u, v;

                //Find vectors for two edges sharing vertex/point p1
                e1 = p2 - p1;
                e2 = p3 - p1;

                // calculating determinant
                p = Query.CrossProduct(d, e2);

                //Calculate determinat
                det = e1 * p;

                //if determinant is near zero, ray lies in plane of triangle otherwise not
                if (det > -tolerance && det < tolerance)
                {
                    continue;
                }

                invDet = 1.0f / det;

                //calculate distance from p1 to ray origin
                t = curve.PointAtParameter(0) - p1;

                //Calculate u parameter
                u = t * p * invDet;

                //Check for ray hit
                if (u < 0 || u > 1)
                {
                    continue;
                }

                //Prepare to test v parameter
                q = Query.CrossProduct(t, e1);

                //Calculate v parameter
                v = d * q * invDet;

                //Check for ray hit
                if (v < 0 || u + v > 1)
                {
                    continue;
                }

                if ((e2 * q * invDet) > Double.Epsilon)
                {
                    points.Add((1 - u - v) * p1 + u * p2 + v * p3);                             //ray does intersect
                }
            }
            return(points);
        }