Exemple #1
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 #2
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);
        }