Ejemplo n.º 1
0
        /// <summary>
        /// Testing intersection between a line segment and a polyhedron and return ALL intersection points
        /// </summary>
        /// <param name="polyH">Polyhedron</param>
        /// <param name="lineS">Line segment</param>
        /// <param name="intPoints">List of intersection points</param>
        /// <returns></returns>
        public static bool intersect(Polyhedron polyH, LineSegment3D lineS, out List <Point3D> intPoints)
        {
            List <Point3D> iPoints = new List <Point3D>();

            intPoints = iPoints;

            List <Point3D> corners = new List <Point3D>();

            corners.Add(lineS.startPoint);
            corners.Add(lineS.endPoint);
            BoundingBox3D bound       = new BoundingBox3D(corners);
            List <Face3D> reducedList = Face3D.exclFacesOutsideOfBound(polyH.Faces, bound, 0x111);

            if (reducedList.Count == 0)
            {
                return(false);                       // no faces left, either they are all on the left or they are all on the right
            }
            // Now test whether there is any intersection. It needs to complete the test with entire faces to collect the intersection points
            for (int i = 0; i < reducedList.Count; i++)
            {
                List <Point3D> iPts = new List <Point3D>();
                if (Face3D.intersect(reducedList[i], lineS, out iPts))
                {
                    for (int j = 0; j < iPts.Count; j++)
                    {
                        iPoints.Add(iPts[j]);
                    }
                }
            }
            if (iPoints.Count > 0)
            {
                return(true);
            }
            return(false);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Touch check between 2 faces. Currently only returns true/false. Should be improved with a new face that overlap between the 2 input faces
        /// </summary>
        /// <param name="F1">Face 1</param>
        /// <param name="F2">Face 2</param>
        /// <returns></returns>
        public static bool touch(Face3D F1, Face3D F2)
        {
            if (Vector3D.Parallels(F1._basePlane.normalVector, F2._basePlane.normalVector))
            {
                // test for any point inside another face
                for (int i = 0; i < F2._vertices.Count; i++)
                {
                    if (Face3D.inside(F1, F2._vertices[i]))
                    {
                        return(true);
                    }
                }
                for (int i = 0; i < F1._vertices.Count; i++)
                {
                    if (Face3D.inside(F2, F1._vertices[i]))
                    {
                        return(true);
                    }
                }
                // if still not returning true, test whether the edges intersect
                List <Point3D> intPoints = new List <Point3D>();
                for (int i = 0; i < F2.boundaries.Count; ++i)
                {
                    if (Face3D.intersect(F1, F2.boundaries[i], out intPoints))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Testing a point inside a polyhedron is similar with the 2D version of a point inside a polygon by testing intersection between a ray starting from the point.
        /// If the number of intersection is odd the point is inside. In 3D the intersection is against the Faces
        /// </summary>
        /// <param name="polyH"></param>
        /// <param name="aPoint"></param>
        /// <returns></returns>
        public static bool inside(Polyhedron polyH, Point3D aPoint)
        {
            double extent = 0;

            if (Octree.WorldBB == null)
            {
                extent = Point3D.distance(polyH.boundingBox.LLB, polyH.boundingBox.URT);
            }
            else
            {
                extent = Octree.WorldBB.extent;
            }

            // define a ray using linesegment from the point toward and along +X-axis with 2*the extent of the World BB to ensure ray is always long enough
            LineSegment3D  ray         = new LineSegment3D(aPoint, new Point3D(aPoint.X + 2 * extent, aPoint.Y, aPoint.Z));
            List <Face3D>  reducedList = Face3D.inclFacesBeyondAxis(polyH.Faces, new Plane3D(aPoint, new Vector3D(1.0, 0.0, 0.0))); // beyond YZ plane
            List <Point3D> corners     = new List <Point3D>();

            corners.Add(aPoint);
            corners.Add(aPoint);
            BoundingBox3D bound = new BoundingBox3D(corners);

            if (reducedList.Count > 0)
            {
                reducedList = Face3D.exclFacesOutsideOfBound(reducedList, bound, 0x011); // reduce list on Y and Z both direction
            }
            if (reducedList.Count == 0)
            {
                return(false);                       // no faces left, either they are all on the left or they are all on the right
            }
            int iCount = 0;

            for (int i = 0; i < reducedList.Count; i++)
            {
                List <Point3D> intPts = new List <Point3D>();
                if (Face3D.intersect(reducedList[i], ray, out intPts))
                {
                    iCount++;
                }
            }
            if ((iCount % 2) == 1)
            {
                return(true);
            }
            return(false);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// To determine that a line segment is inside (completely inside) of a polyhedron, it must satisfy the following:
        /// 1. both end points are inside the polyhedron
        /// 2. There no intersection between the segment and the polyhedron
        /// </summary>
        /// <param name="polyH"></param>
        /// <param name="lineS"></param>
        /// <returns></returns>
        public static bool inside(Polyhedron polyH, LineSegment3D lineS)
        {
            // reducing the face candidate list is less expensive than inside test, do it first
            Point3D leftX  = new Point3D();
            Point3D rightX = new Point3D();

            leftX.X  = lineS.startPoint.X < lineS.endPoint.X ? lineS.startPoint.X : lineS.endPoint.X;
            rightX.X = lineS.startPoint.X < lineS.endPoint.X ? lineS.endPoint.X : lineS.startPoint.X;
            List <Face3D> reducedList = Face3D.inclFacesBeyondAxis(polyH.Faces, new Plane3D(leftX, new Vector3D(1.0, 0.0, 0.0)));
            // reducedList = Face3D.exclFacesBeyondAxis(reducedList, rightX);   // cannot remove this otherwise inside test for StartPoint may not be correct!!!
            List <Point3D> corners = new List <Point3D>();

            corners.Add(lineS.startPoint);
            corners.Add(lineS.endPoint);
            BoundingBox3D bound = new BoundingBox3D(corners);

            if (reducedList.Count > 0)
            {
                reducedList = Face3D.exclFacesOutsideOfBound(reducedList, bound, 0x011); // reduce list on Y and Z both direction
            }
            if (reducedList.Count == 0)
            {
                return(false);                       // no faces left, either they are all on the left or they are all on the right
            }
            // inside test for both segment ends. Test one by one so that we can exit when any one of them are not inside
            if (!inside(polyH, lineS.startPoint))
            {
                return(false);
            }
            if (!inside(polyH, lineS.endPoint))
            {
                return(false);
            }

            // Now test whether there is any intersection. If there is, the segment is not completely inside
            for (int i = 0; i < reducedList.Count; i++)
            {
                List <Point3D> iPoints = new List <Point3D>();
                if (Face3D.intersect(reducedList[i], lineS, out iPoints))
                {
                    return(false);
                }
            }
            return(true);
        }
Ejemplo n.º 5
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);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Test intersection between a polyhedron and a face. There is optmization applied for axis-aligned face (useful for Octree cells as they are all axis aligned)
        /// </summary>
        /// <param name="polyH">The Polyhedron</param>
        /// <param name="face">The face to test the intersection</param>
        /// <returns>true=intersected; false otherwise</returns>
        public static bool intersect(Polyhedron polyH, Face3D face)
        {
            List <Face3D> faceList = new List <Face3D>();
            BoundingBox3D bound    = new BoundingBox3D(face.vertices);

            faceList = Face3D.exclFacesOutsideOfBound(polyH.Faces, bound, 0x111);

            if (faceList.Count == 0)
            {
                return(false);                   // There is no face remaining to test, return false
            }
            for (int i = 0; i < faceList.Count; i++)
            {
                FaceIntersectEnum mode;
                LineSegment3D     intL = new LineSegment3D(new Point3D(), new Point3D());
                bool status            = Face3D.intersect(face, faceList[i], out intL, out mode);
                if (status == true)
                {
                    return(true);                   // return true as soon as an intersection is detected
                }
            }
            return(false);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Testing intersection between a line segment and a polyhedron only. It stops at the first intersection
        /// </summary>
        /// <param name="polyH">polyhedron</param>
        /// <param name="lineS">Line segment</param>
        /// <returns></returns>
        public static bool intersect(Polyhedron polyH, LineSegment3D lineS)
        {
            List <Point3D> corners = new List <Point3D>();

            corners.Add(lineS.startPoint);
            corners.Add(lineS.endPoint);
            BoundingBox3D bound       = new BoundingBox3D(corners);
            List <Face3D> reducedList = Face3D.exclFacesOutsideOfBound(polyH.Faces, bound, 0x111);

            if (reducedList.Count == 0)
            {
                return(false);                       // no faces left, either they are all on the left or they are all on the right
            }
            // Now test whether there is any intersection.
            for (int i = 0; i < reducedList.Count; i++)
            {
                List <Point3D> iPoints = new List <Point3D>();
                if (Face3D.intersect(reducedList[i], lineS, out iPoints))
                {
                    return(true);
                }
            }
            return(false);
        }