Exemple #1
0
        public Face3D(List <Point3D> vertices)
        {
            _vertices = vertices;
            //for (int i = 0; i < vertices.Count; i++)
            //{
            //    LineSegment3D edge;
            //    if (i == vertices.Count - 1)
            //        edge = new LineSegment3D(vertices[i], vertices[0]);
            //    else
            //        edge = new LineSegment3D(vertices[i], vertices[i + 1]);
            //    _boundaryLines.Add(edge);
            //    if (i > 0 && i < vertices.Count)
            //    {
            //        if (_boundaryLines[i].baseLine.direction != _boundaryLines[i-1].baseLine.direction)
            //            _nonColinearEdgesIdx.Add(i-1);
            //    }
            //    if (i == vertices.Count -1 )
            //        if (_boundaryLines[i].baseLine.direction != _boundaryLines[0].baseLine.direction)
            //            _nonColinearEdgesIdx.Add(i);
            //}
            generateEdges(vertices, out _boundaryLines, out _nonColinearEdgesIdx);

            //_basePlane = new Plane3D(_vertices[0], _boundaryLines[_nonColinearEdgesIdx[0]].baseLine.direction, _boundaryLines[_nonColinearEdgesIdx[1]].baseLine.direction);
            // Use Newell's method to calculate normal because any vertices > 3 can be concave
            Vector3D faceNormal = normalByNewellMethod(_vertices);

            _basePlane = new Plane3D(_vertices[0], faceNormal);

            containingBB = new BoundingBox3D(_vertices);
        }
Exemple #2
0
        /// <summary>
        /// This is to support initialization of Face3D with holes. The list contains multiple lists, the first one should be the outer list and the rest are the inner lists
        /// Currently support of holes is still very scant, just be able to capture the data. Everything else (operations) are only working for the outer loop without consideration of the holes
        /// </summary>
        /// <param name="vertices"></param>
        public Face3D(List <List <Point3D> > vertices)
        {
            // Initialize the outer boundary information
            _vertices = vertices[0];
            generateEdges(vertices[0], out _boundaryLines, out _nonColinearEdgesIdx);

            //_basePlane = new Plane3D(_vertices[0], _boundaryLines[_nonColinearEdgesIdx[0]].baseLine.direction, _boundaryLines[_nonColinearEdgesIdx[1]].baseLine.direction);

            // Use Newell's method to calculate normal because any vertices > 3 can be concave
            Vector3D faceNormal = normalByNewellMethod(_vertices);

            _basePlane = new Plane3D(_vertices[0], faceNormal);

            containingBB = new BoundingBox3D(_vertices);

            // Now add the inner boundary informations
            for (int i = 1; i < vertices.Count; i++)
            {
                List <Point3D>       innerLoop           = new List <Point3D>();
                List <LineSegment3D> innerBound          = new List <LineSegment3D>();
                List <int>           nonColinearBoundIdx = new List <int>();

                _innerVertices.Add(vertices[i]);
                generateEdges(vertices[i], out innerBound, out nonColinearBoundIdx);
                _innerBoundaries.Add(innerBound);
            }
        }
Exemple #3
0
        public static bool Overlaps(Plane3D P1, LineSegment3D LS)
        {
            double res      = Vector3D.DotProduct(P1.normalVector, LS.baseLine.direction);
            bool   pOnPlane = pointOnPlane(P1, LS.startPoint);

            // if the normals are the same and point in P2 is also point in P1, the two planes are overlapped
            return(MathUtils.equalTol(res, 0.0, MathUtils.defaultTol) && pOnPlane);
        }
Exemple #4
0
        public static bool Overlaps(Plane3D P1, Face3D F1)
        {
            bool parallel = Vector3D.Parallels(P1.normalVector, F1.basePlane.normalVector);
            bool pOnPlane = pointOnPlane(P1, F1.vertices[0]);

            // if the normals are the same and point in P2 is also point in P1, the two planes are overlapped
            return(parallel && pOnPlane);
        }
Exemple #5
0
        /// <summary>
        /// Test whether 2 planes overlapped
        /// </summary>
        /// <param name="P1"></param>
        /// <param name="P2"></param>
        /// <returns></returns>
        public static bool Overlaps(Plane3D P1, Plane3D P2)
        {
            bool parallel = Vector3D.Parallels(P1.normalVector, P2.normalVector);
            bool pOnPlane = pointOnPlane(P1, P2.point);

            // if the normals are the same and point in P2 is also point in P1, the two planes are overlapped
            return(parallel && pOnPlane);
        }
Exemple #6
0
        public static bool Parallels(Plane3D P1, LineSegment3D LS)
        {
            double res = Vector3D.DotProduct(P1.normalVector, LS.baseLine.direction);

            if (MathUtils.equalTol(res, 0.0, MathUtils.defaultTol))
            {
                return(true);
            }
            return(false);
        }
Exemple #7
0
        public static List <Face3D> exclFacesOutsideOfBound(List <Face3D> faces, BoundingBox3D bound, UInt16 axes)
        {
            Plane3D lowerBoundX = new Plane3D(bound.LLB, new Vector3D(1.0, 0.0, 0.0));
            Plane3D lowerBoundY = new Plane3D(bound.LLB, new Vector3D(0.0, 1.0, 0.0));
            Plane3D lowerBoundZ = new Plane3D(bound.LLB, new Vector3D(0.0, 0.0, 1.0));
            Plane3D upperBoundX = new Plane3D(bound.URT, new Vector3D(1.0, 0.0, 0.0));
            Plane3D upperBoundY = new Plane3D(bound.URT, new Vector3D(0.0, 1.0, 0.0));
            Plane3D upperBoundZ = new Plane3D(bound.URT, new Vector3D(0.0, 0.0, 1.0));

            List <Face3D> reducedList = faces;

            // filter each direction
            if ((axes & 0x100) == 0x100)
            {
                // filter X direction
                if (reducedList.Count > 0)
                {
                    reducedList = exclFacesLeftOfAxis(reducedList, lowerBoundX);
                }
                if (reducedList.Count > 0)
                {
                    reducedList = exclFacesRightOfAxis(reducedList, upperBoundX);
                }
            }

            if ((axes & 0x010) == 0x010)
            {
                // filter Y direction
                if (reducedList.Count > 0)
                {
                    reducedList = exclFacesLeftOfAxis(reducedList, lowerBoundY);
                }
                if (reducedList.Count > 0)
                {
                    reducedList = exclFacesRightOfAxis(reducedList, upperBoundY);
                }
            }

            if ((axes & 0x001) == 0x001)
            {
                // filter Z direction
                if (reducedList.Count > 0)
                {
                    reducedList = exclFacesLeftOfAxis(reducedList, lowerBoundZ);
                }
                if (reducedList.Count > 0)
                {
                    reducedList = exclFacesRightOfAxis(reducedList, upperBoundZ);
                }
            }

            return(reducedList);
        }
Exemple #8
0
        /// <summary>
        /// Test whether two planes intersect
        /// </summary>
        /// <param name="P1">Plane 1</param>
        /// <param name="P2">Plane 2</param>
        /// <param name="intersectingLine">Resulting intersection line</param>
        /// <returns></returns>
        public static bool PPintersect(Plane3D P1, Plane3D P2, out Line3D intersectingLine)
        {
            intersectingLine = new Line3D();
            if (Vector3D.Parallels(P1.normalVector, P2.normalVector))
            {
                return(false);   // Planes are parallel to each other
            }
            intersectingLine.direction = Vector3D.CrossProduct(P1.normalVector, P2.normalVector);

            // To find the point on the line, we can use 3 plane intersection with the 3rd plane with the normal as a cross product of P1 and P2 to guarantee 1 point intersection. It passes through the origin
            Vector3D n3 = Vector3D.CrossProduct(P1.normalVector, P2.normalVector);
            double   da = 1 / (Vector3D.DotProduct(P1.normalVector, Vector3D.CrossProduct(P2.normalVector, n3)));
            Vector3D vp = (-P1.parConstant * (Vector3D.CrossProduct(P2.normalVector, n3)) - P2.parConstant * (Vector3D.CrossProduct(n3, P1.normalVector))) * da;

            intersectingLine.point.X = vp.X;
            intersectingLine.point.Y = vp.Y;
            intersectingLine.point.Z = vp.Z;

            //if ((Math.Abs(intersectingLine.direction.Z) > Math.Abs(intersectingLine.direction.X))  && (Math.Abs(intersectingLine.direction.Z) > Math.Abs(intersectingLine.direction.Y)))
            //{// Z=0
            //    intersectingLine.point.Y = (P1.normalVector.X * P2.parConstant - P2.normalVector.X * P1.parConstant)
            //                                    / (P1.normalVector.Y * P2.normalVector.X - P1.normalVector.X * P2.normalVector.Y);
            //    if (!MathUtils.equalTol(P1.normalVector.X, 0.0, MathUtils.defaultTol))
            //        intersectingLine.point.X = (-P1.parConstant - P1.normalVector.Y * intersectingLine.point.Y) / P1.normalVector.X;
            //    else
            //        intersectingLine.point.X = (-P2.parConstant - P2.normalVector.Y * intersectingLine.point.Y) / P2.normalVector.X;
            //    intersectingLine.point.Z = 0.0;
            //}
            //else if ((Math.Abs(intersectingLine.direction.Y) > Math.Abs(intersectingLine.direction.X)) && (Math.Abs(intersectingLine.direction.Y) > Math.Abs(intersectingLine.direction.Z)))
            //{// Y=0
            //    intersectingLine.point.Z = (P1.normalVector.X * P2.parConstant - P2.normalVector.X * P1.parConstant)
            //                                    / (P1.normalVector.Z * P2.normalVector.X - P1.normalVector.X * P2.normalVector.Z);
            //    if (!MathUtils.equalTol(P1.normalVector.X, 0.0, MathUtils.defaultTol))
            //        intersectingLine.point.X = (-P1.parConstant - P1.normalVector.Z * intersectingLine.point.Z) / P1.normalVector.X;
            //    else
            //        intersectingLine.point.X = (-P2.parConstant - P2.normalVector.Z * intersectingLine.point.Z) / P2.normalVector.X;
            //    intersectingLine.point.Y = 0.0;
            //}
            //else
            //{// X=0
            //    intersectingLine.point.Y = (P1.normalVector.Z * P2.parConstant - P2.normalVector.Z * P1.parConstant)
            //                                    / (P1.normalVector.Y * P2.normalVector.Z - P1.normalVector.Z * P2.normalVector.Y);
            //    if (!MathUtils.equalTol(P1.normalVector.Z, 0.0, MathUtils.defaultTol))
            //        intersectingLine.point.Z = (-P1.parConstant - P1.normalVector.Y * intersectingLine.point.Y) / P1.normalVector.Z;
            //    else
            //        intersectingLine.point.Z = (-P2.parConstant - P2.normalVector.Y * intersectingLine.point.Y) / P2.normalVector.Z;
            //    intersectingLine.point.X = 0.0;
            //}
            return(true);
        }
Exemple #9
0
        public static bool validateFace(List <List <Point3D> > vertexLists)
        {
            if (vertexLists.Count < 1)
            {
                return(false);
            }

            foreach (List <Point3D> pList in vertexLists)
            {
                // Face has less than minimum 3 vertices
                if (pList.Count < 3)
                {
                    return(false);
                }

                List <LineSegment3D> boundaryLines;
                List <int>           nonColinearEdgesIdx;

                // There is no enough non-colinear edges to form a valid Face
                generateEdges(pList, out boundaryLines, out nonColinearEdgesIdx);
                if (nonColinearEdgesIdx.Count < 2)
                {
                    return(false);
                }

                //Plane3D basePlane = new Plane3D(pList[0], boundaryLines[nonColinearEdgesIdx[0]].baseLine.direction, boundaryLines[nonColinearEdgesIdx[1]].baseLine.direction);
                // Use Newell's method to calculate normal because any vertices > 3 can be concave
                Vector3D faceNormal = normalByNewellMethod(pList);
                Plane3D  basePlane  = new Plane3D(pList[0], faceNormal);

                // If we can't get a normal, then the face is most likely not valid
                if (double.IsNaN(basePlane.normalVector.X) || double.IsNaN(basePlane.normalVector.Y) || double.IsNaN(basePlane.normalVector.Z))
                {
                    return(false);
                }
                if (basePlane.normalVector.X == 0.0 && basePlane.normalVector.Y == 0.0 && basePlane.normalVector.Z == 0.0)
                {
                    return(false);
                }

                // Skip the check for point on plane as it may not be as critical and it is too sensitive to tolerance
                //foreach (Point3D p in pList)
                //{
                //    // Test all points are on the plane
                //    if (!Plane3D.pointOnPlane(basePlane, p))
                //        return false;
                //}
            }
            return(true);
        }
Exemple #10
0
        /// <summary>
        /// This function return reduced list of faces that is entirely on the RIGHT of the specified Axis (only work on Axis parallel to X, or Y, or Z)
        /// The funcion is used for optimizing intersection test between the polyhedron and the Axis-align bounding box (e.g. Octree cell)
        /// </summary>
        /// <param name="axisLoc">The axis location. Must be X only, or Y only, or Z only</param>
        /// <returns></returns>
        public static List <Face3D> exclFacesLeftOfAxis(List <Face3D> faces, Plane3D axisPl)
        {
            List <Face3D> facesRightOfAxis = new List <Face3D>();

            // Only deal with one axis set, either A, Y or Z, otherwise null List will be returned
            if ((axisPl.normalVector.Y == 0.0 && axisPl.normalVector.Z == 0.0) || (axisPl.normalVector.X == 0.0 && axisPl.normalVector.Y == 0.0) || (axisPl.normalVector.X == 0.0 && axisPl.normalVector.Z == 0.0))
            {
                for (int i = 0; i < faces.Count; i++)
                {
                    bool left = true;

                    // Test all face boundaries are beyond the axis location specified
                    for (int j = 0; j < faces[i].boundaries.Count; j++)
                    {
                        // It is sufficient to stop checking if any point of any of the boundaries lies behind the Axis location
                        if (axisPl.normalVector.X != 0.0)
                        {
                            if (!(faces[i].boundaries[j].startPoint.X < axisPl.point.X && faces[i].boundaries[j].endPoint.X < axisPl.point.X))
                            {
                                left = false;
                                break;
                            }
                        }
                        else if (axisPl.normalVector.Y != 0.0)
                        {
                            if (!(faces[i].boundaries[j].startPoint.Y < axisPl.point.Y && faces[i].boundaries[j].endPoint.Y < axisPl.point.Y))
                            {
                                left = false;
                                break;
                            }
                        }
                        if (axisPl.normalVector.Z != 0.0)
                        {
                            if (!(faces[i].boundaries[j].startPoint.Z < axisPl.point.Z && faces[i].boundaries[j].endPoint.Z < axisPl.point.Z))
                            {
                                left = false;
                                break;
                            }
                        }
                    }
                    if (left == false)
                    {
                        facesRightOfAxis.Add(faces[i]);
                    }
                }
            }
            return(facesRightOfAxis);
        }
Exemple #11
0
        /// <summary>
        /// Calculating an intersection between a Face and a LineSegment
        /// </summary>
        /// <param name="F1">the Face3D</param>
        /// <param name="LS">the Line Segment</param>
        /// <param name="intPoint">the intersection point</param>
        /// <returns></returns>
        public static bool intersect(Face3D F1, LineSegment3D LS, out List <Point3D> intPoints)
        {
            intPoints = new List <Point3D>();
            Point3D intPt = new Point3D();

            // There are 2 possible cases: 1. Line punching the face, 2. Line lies on the same plane as the face
            // Test whether the line is on the same plane
            if (MathUtils.equalTol(Vector3D.DotProduct(F1.basePlane.normalVector, LS.baseLine.direction), 0.0, MathUtils.defaultTol))
            {
                // test whether at least one point of the segment is on the plane
                if (!Plane3D.pointOnPlane(F1.basePlane, LS.startPoint))
                {
                    return(false);       // line is parallel with the plane, no intersection
                }
                LineSegmentIntersectEnum mode = LineSegmentIntersectEnum.Undefined;
                for (int i = 0; i < F1.boundaries.Count; i++)
                {
                    bool st = LineSegment3D.intersect(F1.boundaries[i], LS, out intPt, out mode);
                    if (st)
                    {
                        intPoints.Add(intPt);
                    }
                }
                if (intPoints.Count > 0)
                {
                    return(true);
                }
                return(false);
            }
            else
            {
                bool res = Plane3D.PLintersect(F1.basePlane, LS, out intPt);
                if (res == false)
                {
                    return(false);                          // intersection occurs beyond the line segment
                }
                // There is intersection point, test whether the point in within (inside the boundary of the face boundaries
                res = inside(F1, intPt);
                if (res)
                {
                    intPoints.Add(intPt);
                    return(true);
                }
            }
            return(false);
        }
Exemple #12
0
        /// <summary>
        /// Plane and a line intersection
        /// </summary>
        /// <param name="P1">Plane</param>
        /// <param name="L1">Line</param>
        /// <param name="intersectingPoint">Point of intersection</param>
        /// <returns></returns>
        public static bool PLintersect(Plane3D P1, Line3D L1, out Point3D intersectingPoint)
        {
            intersectingPoint = new Point3D();
            double denom = Vector3D.DotProduct(P1.normalVector, L1.direction);

            if (MathUtils.equalTol(denom, 0.0, MathUtils.defaultTol))
            {
                return(false);   // Normal and the lines are perpendicular to each other: line is parallel to the plane, no intersection
            }
            double r = Vector3D.DotProduct(P1.normalVector, new Vector3D(P1.point.X - L1.point.X, P1.point.Y - L1.point.Y, P1.point.Z - L1.point.Z))
                       / denom;

            intersectingPoint.X = L1.point.X + r * L1.direction.X;
            intersectingPoint.Y = L1.point.Y + r * L1.direction.Y;
            intersectingPoint.Z = L1.point.Z + r * L1.direction.Z;
            return(true);
        }
Exemple #13
0
        /// <summary>
        /// This function return reduced list of faces that is entirely on the LEFT of the specified Axis (only work on Axis parallel to X, or Y, or Z)
        /// The funcion is used for optimizing intersection test between the polyhedron and the Axis-align bounding box (e.g. Octree cell)
        /// </summary>
        /// <param name="axisLoc">The axis location. Must be either X only, or Y only, or Z only</param>
        /// <returns></returns>
        public static List <Face3D> inclFacesBeyondAxis(List <Face3D> faces, Plane3D axisPl)
        {
            List <Face3D> facesBeyond = new List <Face3D>();

            // Only deal with one axis set, either X, Y or Z, otherwise null List will be returned
            if ((axisPl.normalVector.Y == 0.0 && axisPl.normalVector.Z == 0.0) || (axisPl.normalVector.X == 0.0 && axisPl.normalVector.Y == 0.0) || (axisPl.normalVector.X == 0.0 && axisPl.normalVector.Z == 0.0))
            {
                for (int i = 0; i < faces.Count; i++)
                {
                    for (int j = 0; j < faces[i].boundaries.Count; j++)
                    {
                        // Sufficient to test whether there is any of the end point of the segment is beyond the Axis location
                        if (axisPl.normalVector.X != 0.0)
                        {
                            if (faces[i].boundaries[j].startPoint.X >= axisPl.point.X || faces[i].boundaries[j].endPoint.X >= axisPl.point.X)
                            {
                                facesBeyond.Add(faces[i]);
                                break;
                            }
                        }
                        else if (axisPl.normalVector.Y != 0.0)
                        {
                            if (faces[i].boundaries[j].startPoint.Y >= axisPl.point.Y || faces[i].boundaries[j].endPoint.Y >= axisPl.point.Y)
                            {
                                facesBeyond.Add(faces[i]);
                                break;
                            }
                        }
                        if (axisPl.normalVector.Z != 0.0)
                        {
                            if (faces[i].boundaries[j].startPoint.Z >= axisPl.point.Z || faces[i].boundaries[j].endPoint.Z >= axisPl.point.Z)
                            {
                                facesBeyond.Add(faces[i]);
                                break;
                            }
                        }
                    }
                }
            }
            return(facesBeyond);
        }
Exemple #14
0
        /// <summary>
        /// Test whether a Face (bounded plane) intersects with a plane
        /// </summary>
        /// <param name="P1">Plane</param>
        /// <param name="F1">Face</param>
        /// <param name="intersectingLine">Resulting intercting linesegment (bounded)</param>
        /// <returns></returns>
        public static bool PPintersect(Plane3D P1, Face3D F1, out LineSegment3D intersectingLine)
        {
            Line3D        intLine = new Line3D();
            LineSegment3D ls      = new LineSegment3D(new Point3D(0.0, 0.0, 0.0), new Point3D(1.0, 1.0, 1.0));

            intersectingLine = ls;

            // Intersect operation: get the intersection (unbounded) line
            if (!PPintersect(P1, F1.basePlane, out intLine))
            {
                return(false);
            }

            // Now needs to check get the segment by getting intersecting points between the line and the Face boundaries
            List <Point3D> intPts = new List <Point3D>();
            // Use line segment that is large enough to ensure it covers the extent of the face
            //double extent = Point3D.distance(F1.boundingBox.LLB, F1.boundingBox.URT) * 10;        // Bug: NOT big enough for some cases!, use worldBB extent
            double extent;

            if (Octree.WorldBB == null)
            {
                extent = 1000000000;
            }
            else
            {
                extent = Octree.WorldBB.extent * 10;
            }
            LineSegment3D intLS = new LineSegment3D(new Point3D(intLine.point - (intLine.direction * extent)), new Point3D(intLine.point + (intLine.direction * extent)));

            bool res = Face3D.intersect(F1, intLS, out intPts);

            if (res)
            {
                intersectingLine.startPoint = intPts[0];
                intersectingLine.endPoint   = intPts[intPts.Count - 1];
                return(true);
            }
            return(false);
        }
Exemple #15
0
        public void Reverse()
        {
            // First reverse the vertex list, and then regenerate the rest
            _vertices.Reverse();

            _boundaryLines.Clear();
            _nonColinearEdgesIdx.Clear();

            for (int i = 0; i < vertices.Count; i++)
            {
                LineSegment3D edge;
                if (i == vertices.Count - 1)
                {
                    edge = new LineSegment3D(vertices[i], vertices[0]);
                }
                else
                {
                    edge = new LineSegment3D(vertices[i], vertices[i + 1]);
                }
                _boundaryLines.Add(edge);
                if (i > 0 && i < vertices.Count)
                {
                    if (_boundaryLines[i].baseLine.direction != _boundaryLines[i - 1].baseLine.direction)
                    {
                        _nonColinearEdgesIdx.Add(i - 1);
                    }
                }
                if (i == vertices.Count - 1)
                {
                    if (_boundaryLines[i].baseLine.direction != _boundaryLines[0].baseLine.direction)
                    {
                        _nonColinearEdgesIdx.Add(i);
                    }
                }
            }
            _basePlane   = new Plane3D(vertices[0], _boundaryLines[_nonColinearEdgesIdx[0]].baseLine.direction, _boundaryLines[_nonColinearEdgesIdx[1]].baseLine.direction);
            containingBB = new BoundingBox3D(vertices);
        }
Exemple #16
0
 /// <summary>
 /// Test whether a point P1 lies on the plane PL1
 /// </summary>
 /// <param name="PL1">Plane</param>
 /// <param name="P1">Point</param>
 /// <param name="distance">return the distance. Needed to check whether the point is actually on the plabe: distance=0</param>
 /// <returns></returns>
 public static bool pointOnPlane(Plane3D PL1, Point3D P1, out double distance)
 {
     distance = distPoint2Plane(PL1, P1);
     return(MathUtils.equalTol(distance, 0.0));
 }
Exemple #17
0
        /// <summary>
        /// Test a point is inside a face
        /// </summary>
        /// <param name="F1"></param>
        /// <param name="P1"></param>
        /// <returns></returns>
        public static bool inside(Face3D F1, Point3D P1)
        {
            if (!Plane3D.pointOnPlane(F1.basePlane, P1))
            {
                return(false);                                          // Point is not on a plane
            }
            // test Point inside a Face
            // Need to project the plane to 2D (XY-, YZ-, or XZ- plane). It should work well with convex face (esp. triangles and rectangles we will deal with mostly)
            double maxDim     = Double.MinValue;
            int    DimttoZero = 0;

            // First test whether the plane is already axis-aligned (in this case we can just remove the appropriate axis)
            if (MathUtils.equalTol(F1.basePlane.normalVector.Y, 0.0, MathUtils.defaultTol) && MathUtils.equalTol(F1.basePlane.normalVector.Z, 0.0, MathUtils.defaultTol))
            {
                DimttoZero = 0;     // Ignore X, project to Y-Z plane
            }
            else if (MathUtils.equalTol(F1.basePlane.normalVector.X, 0.0, MathUtils.defaultTol) && MathUtils.equalTol(F1.basePlane.normalVector.Z, 0.0, MathUtils.defaultTol))
            {
                DimttoZero = 1;     // Ignore Y, project to X-Z plane
            }
            else if (MathUtils.equalTol(F1.basePlane.normalVector.X, 0.0, MathUtils.defaultTol) && MathUtils.equalTol(F1.basePlane.normalVector.Y, 0.0, MathUtils.defaultTol))
            {
                DimttoZero = 2;     // Ignore Z, project to X-Y plane
            }
            else
            {
                if (maxDim < Math.Abs(F1.basePlane.normalVector.X))
                {
                    maxDim     = Math.Abs(F1.basePlane.normalVector.X);
                    DimttoZero = 0;
                }
                if (maxDim < Math.Abs(F1.basePlane.normalVector.Y))
                {
                    maxDim     = Math.Abs(F1.basePlane.normalVector.Y);
                    DimttoZero = 1;
                }
                if (maxDim < Math.Abs(F1.basePlane.normalVector.Z))
                {
                    maxDim     = Math.Abs(F1.basePlane.normalVector.Z);
                    DimttoZero = 2;
                }
            }

            // We ignore the largest component, which means the least impact to the projection plane
            List <Point3D> projVert = new List <Point3D>();
            Point3D        projIntP = new Point3D(P1.X, P1.Y, P1.Z);
            Point3D        rayEndP  = new Point3D(P1.X, P1.Y, P1.Z);

            if (DimttoZero == 0)
            {
                for (int i = 0; i < F1.vertices.Count; i++)
                {
                    projVert.Add(new Point3D(0.0, F1.vertices[i].Y, F1.vertices[i].Z));
                }
                projIntP.X = 0.0;
                rayEndP.X  = 0.0;
                if (Octree.WorldBB == null)
                {
                    rayEndP.Y += Point3D.distance(F1.containingBB.URT, F1.containingBB.LLB) * 1000;
                }
                else
                {
                    rayEndP.Y += Octree.WorldBB.extent * 2;
                }
            }
            else if (DimttoZero == 1)
            {
                for (int i = 0; i < F1.vertices.Count; i++)
                {
                    projVert.Add(new Point3D(F1.vertices[i].X, 0.0, F1.vertices[i].Z));
                }
                projIntP.Y = 0.0;
                rayEndP.Y  = 0.0;
                //rayEndP.Z += Point3D.distance(F1.containingBB.URT, F1.containingBB.LLB) * 2;
                if (Octree.WorldBB == null)
                {
                    rayEndP.X += Point3D.distance(F1.containingBB.URT, F1.containingBB.LLB) * 2;    // Use X axis for the ray
                }
                else
                {
                    rayEndP.X += Octree.WorldBB.extent * 2;
                }
            }
            else if (DimttoZero == 2)
            {
                for (int i = 0; i < F1.vertices.Count; i++)
                {
                    projVert.Add(new Point3D(F1.vertices[i].X, F1.vertices[i].Y, 0.0));
                }
                projIntP.Z = 0.0;
                rayEndP.Z  = 0.0;
                if (Octree.WorldBB == null)
                {
                    rayEndP.X += Point3D.distance(F1.containingBB.URT, F1.containingBB.LLB) * 2;
                }
                else
                {
                    rayEndP.X += Octree.WorldBB.extent * 2;
                }
            }
            Face3D projFace = new Face3D(projVert);

            // define a ray from the intersection point along the X-axis of the projected plane by using long enough line segment beginning from the point, using
            //    max extent of the face containingBB *2
            LineSegment3D ray = new LineSegment3D(projIntP, rayEndP);

            // Now do intersection between the ray and all the segments of the face. Odd number indicates the point is inside
            // 4 rules to follow:
            //    1. If the segment is upward, exclude the endpoint for intersection (only consider the startpoint)
            //    2. If the segment is downward, exclude the startpoint for intersection (only considers the end point)
            //    3. Ignore the segment that is horizontal (parallel to the ray)
            //    4. ray is always strictly to the right of the Point
            int     intCount             = 0;
            Point3D iP                   = new Point3D();
            LineSegmentIntersectEnum mod = LineSegmentIntersectEnum.Undefined;

            for (int i = 0; i < projFace.boundaries.Count; i++)
            {
                if (ray.baseLine.direction == projFace.boundaries[i].baseLine.direction)
                {
                    continue;   //ignore segment that is parallel to the ray (rule #3)
                }
                Point3D pointToExclude = new Point3D();
                if (DimttoZero == 0 || DimttoZero == 1)
                {
                    // for both X-Z and Y-Z plane (Z as vertical axis)
                    if (projFace.boundaries[i].startPoint.Z <= ray.startPoint.Z && projFace.boundaries[i].endPoint.Z > ray.startPoint.Z)
                    {
                        pointToExclude = projFace.boundaries[i].endPoint;       // Rule #1
                    }
                    else if (projFace.boundaries[i].startPoint.Z > ray.startPoint.Z && projFace.boundaries[i].endPoint.Z <= ray.startPoint.Z)
                    {
                        pointToExclude = projFace.boundaries[i].startPoint;     // Rule #2
                    }
                }
                else
                {
                    // for X-Y plane (Y as vertical axis)
                    if (projFace.boundaries[i].startPoint.Y <= ray.startPoint.Y && projFace.boundaries[i].endPoint.Y > ray.startPoint.Y)
                    {
                        pointToExclude = projFace.boundaries[i].endPoint;       // Rule #1
                    }
                    else if (projFace.boundaries[i].startPoint.Y > ray.startPoint.Y && projFace.boundaries[i].endPoint.Y <= ray.startPoint.Y)
                    {
                        pointToExclude = projFace.boundaries[i].startPoint;     // Rule #2
                    }
                }

                // In the evaluation of the number of intersection between a ray and a face, we will ignore the intersection point that is equal to the rule #2 or #3
                if (LineSegment3D.intersect(ray, projFace.boundaries[i], out iP, out mod) && (iP != pointToExclude))
                {
                    intCount++;
                }
            }
            if (intCount % 2 == 1)
            {
                return(true);
            }
            return(false);
        }
Exemple #18
0
        /// <summary>
        /// Calculating intersection beween 2 Faces. The outcome of the intersection should be a LineSegment
        /// </summary>
        /// <param name="F1">First Face</param>
        /// <param name="F2">Second Face</param>
        /// <param name="intersectionLine">The resulting intersection line. Zero if no intersection</param>
        /// <param name="mode">The mode of the intersection: No intersection/parallel, partially intersect, no actual intersection/undefined</param>
        /// <returns></returns>
        public static bool intersect(Face3D F1, Face3D F2, out LineSegment3D intersectionLine, out FaceIntersectEnum mode)
        {
            intersectionLine = new LineSegment3D(new Point3D(0, 0, 0), new Point3D(0, 0, 0));
            mode             = FaceIntersectEnum.Undefined;

            if (F1._basePlane.normalVector == F2._basePlane.normalVector)
            {
                // test points inside another face
                for (int i = 0; i < F2._vertices.Count; i++)
                {
                    if (!Face3D.inside(F1, F2._vertices[i]))
                    {
                        continue;
                    }
                    mode = FaceIntersectEnum.Overlap;
                    return(true);
                }
                mode = FaceIntersectEnum.NoIntersectionParallel;
                return(false);
            }

            LineSegment3D ls1;
            LineSegment3D ls2;
            bool          res1 = Plane3D.PPintersect(F1._basePlane, F2, out ls1);
            bool          res2 = Plane3D.PPintersect(F2._basePlane, F1, out ls2);

            if (!res1 || !res2)
            {
                return(false);       // the faces do not intersect
            }
            // Special case if the intersection occurs only at a single point
            if (ls1.startPoint == ls1.endPoint && ls2.startPoint == ls2.endPoint)
            {
                if (ls1.startPoint.Equals(ls2.startPoint))
                {
                    mode = FaceIntersectEnum.IntersectPartial;
                    return(true);
                }
                return(false);
            }
            else if (ls1.startPoint.Equals(ls1.endPoint))
            {
                // a single point intersection: ls1 is 0 length linesegnment = point
                if (LineSegment3D.isInSegment(ls2, ls1.startPoint))
                {
                    mode = FaceIntersectEnum.IntersectPartial;
                    return(true);
                }
                return(false);
            }
            else if (ls2.startPoint.Equals(ls2.endPoint))
            {
                // a single point intersection: ls1 is 0 length linesegnment = point
                if (LineSegment3D.isInSegment(ls1, ls2.startPoint))
                {
                    mode = FaceIntersectEnum.IntersectPartial;
                    return(true);
                }
                return(false);
            }

            LineSegment3D          ovSegment;
            LineSegmentOverlapEnum ovstat = LineSegmentOverlapEnum.Undefined;
            bool lint = LineSegment3D.overlap(ls1, ls2, out ovSegment, out ovstat);

            if (lint)
            {
                intersectionLine = ovSegment;
                mode             = FaceIntersectEnum.IntersectPartial;
                return(true);
            }
            return(false);
        }
Exemple #19
0
 public static bool Parallels(Plane3D P1, Face3D F1)
 {
     return(Vector3D.Parallels(P1.normalVector, F1.basePlane.normalVector));
 }
Exemple #20
0
 /// <summary>
 /// Test whether a point P1 lies on the plane PL1
 /// </summary>
 /// <param name="PL1">Plane</param>
 /// <param name="P1">Point</param>
 /// <returns></returns>
 public static bool pointOnPlane(Plane3D PL1, Point3D P1)
 {
     return(MathUtils.equalTol(distPoint2Plane(PL1, P1), 0.0));
 }
Exemple #21
0
 /// <summary>
 /// Distance from a point to a plane
 /// </summary>
 /// <param name="PL1">Plane</param>
 /// <param name="P1">Point</param>
 /// <returns></returns>
 public static double distPoint2Plane(Plane3D PL1, Point3D P1)
 {
     return(Vector3D.DotProduct(PL1.normalVector, new Vector3D(P1.X - PL1.point.X, P1.Y - PL1.point.Y, P1.Z - PL1.point.Z)));
 }
Exemple #22
0
 public static bool Parallels(Plane3D P1, Plane3D P2)
 {
     return(Vector3D.Parallels(P1.normalVector, P2.normalVector));
 }