예제 #1
0
파일: Line.cs 프로젝트: dlannan/csg-toolkit
        //----------------------------------CONSTRUCTORS---------------------------------//
        /**
         * Constructor for a line. The line created is the intersection between two planes
         *
         * @param face1 face representing one of the planes
         * @param face2 face representing one of the planes
         */
        public Line(Face face1, Face face2)
        {
            Vector3d normalFace1 = face1.getNormal();
            Vector3d normalFace2 = face2.getNormal();

            //direction: cross product of the faces normals
            direction = new Vector3d();
            direction.cross(normalFace1, normalFace2);

            //if direction lenght is not zero (the planes aren't parallel )...
            if (!(direction.length() < TOL))
            {
                //getting a line point, zero is set to a coordinate whose direction
                //component isn't zero (line intersecting its origin plan)
                point = new Point3d();
                double d1 = -(normalFace1.x * face1.v1.x + normalFace1.y * face1.v1.y + normalFace1.z * face1.v1.z);
                double d2 = -(normalFace2.x * face2.v1.x + normalFace2.y * face2.v1.y + normalFace2.z * face2.v1.z);
                if (Math.Abs(direction.x) > TOL)
                {
                    point.x = 0;
                    point.y = (d2 * normalFace1.z - d1 * normalFace2.z) / direction.x;
                    point.z = (d1 * normalFace2.y - d2 * normalFace1.y) / direction.x;
                }
                else if (Math.Abs(direction.y) > TOL)
                {
                    point.x = (d1 * normalFace2.z - d2 * normalFace1.z) / direction.y;
                    point.y = 0;
                    point.z = (d2 * normalFace1.x - d1 * normalFace2.x) / direction.y;
                }
                else
                {
                    point.x = (d2 * normalFace1.y - d1 * normalFace2.y) / direction.z;
                    point.y = (d1 * normalFace2.x - d2 * normalFace1.x) / direction.z;
                    point.z = 0;
                }
            }

            direction.normalize();
        }
예제 #2
0
        //---------------------------------CONSTRUCTORS---------------------------------//
        /**
         * Constructs a Segment based on elements obtained from the two planes relations
         *
         * @param line resulting from the two planes intersection
         * @param face face that intersects with the plane
         * @param sign1 position of the face vertex1 relative to the plane (-1 behind, 1 front, 0 on)
         * @param sign2 position of the face vertex1 relative to the plane (-1 behind, 1 front, 0 on)
         * @param sign3 position of the face vertex1 relative to the plane (-1 behind, 1 front, 0 on)
         */
        public Segment(Line line, Face face, int sign1, int sign2, int sign3)
        {
            this.line = line;
            index = 0;

            //VERTEX is an end
            if (sign1 == 0)
            {
                setVertex(face.v1);
                //other vertices on the same side - VERTEX-VERTEX VERTEX
                if (sign2 == sign3)
                {
                    setVertex(face.v1);
                }
            }

            //VERTEX is an end
            if (sign2 == 0)
            {
                setVertex(face.v2);
                //other vertices on the same side - VERTEX-VERTEX VERTEX
                if (sign1 == sign3)
                {
                    setVertex(face.v2);
                }
            }

            //VERTEX is an end
            if (sign3 == 0)
            {
                setVertex(face.v3);
                //other vertices on the same side - VERTEX-VERTEX VERTEX
                if (sign1 == sign2)
                {
                    setVertex(face.v3);
                }
            }

            //There are undefined ends - one or more edges cut the planes intersection line
            if (getNumEndsSet() != 2)
            {
                //EDGE is an end
                if ((sign1 == 1 && sign2 == -1) || (sign1 == -1 && sign2 == 1))
                {
                    setEdge(face.v1, face.v2);
                }
                //EDGE is an end
                if ((sign2 == 1 && sign3 == -1) || (sign2 == -1 && sign3 == 1))
                {
                    setEdge(face.v2, face.v3);
                }
                //EDGE is an end
                if ((sign3 == 1 && sign1 == -1) || (sign3 == -1 && sign1 == 1))
                {
                    setEdge(face.v3, face.v1);
                }
            }
        }
예제 #3
0
파일: Face.cs 프로젝트: dlannan/csg-toolkit
        /**
         * Checks if a face is equal to another. To be equal, they have to have equal
         * vertices in the same order
         *
         * @param anObject the other face to be tested
         * @return true if they are equal, false otherwise.
         */
        public bool equals(Face face)
        {
            bool cond1 = v1.equals(face.v1) && v2.equals(face.v2) && v3.equals(face.v3);
            bool cond2 = v1.equals(face.v2) && v2.equals(face.v3) && v3.equals(face.v1);
            bool cond3 = v1.equals(face.v3) && v2.equals(face.v1) && v3.equals(face.v2);

            return cond1 || cond2 || cond3;
        }
예제 #4
0
파일: Face.cs 프로젝트: dlannan/csg-toolkit
 //-----------------------------------OVERRIDES----------------------------------//
 /**
  * Clones the face object
  *
  * @return cloned face object
  */
 public Face Clone()
 {
     Face clone = new Face();
     clone.v1 = v1.Clone();
     clone.v2 = v2.Clone();
     clone.v3 = v3.Clone();
     clone.status = status;
     return clone;
 }
예제 #5
0
        /**
         * Split an individual face
         *
         * @param facePos face position on the array of faces
         * @param segment1 segment representing the intersection of the face with the plane
         * of another face
         * @return segment2 segment representing the intersection of other face with the
         * plane of the current face plane
         */
        private void splitFace(int facePos, Segment segment1, Segment segment2)
        {
            Vertex  startPosVertex, endPosVertex;
            Point3d startPos, endPos;
            int     startType, endType, middleType;
            double  startDist, endDist;

            Face   face        = getFace(facePos);
            Vertex startVertex = segment1.getStartVertex();
            Vertex endVertex   = segment1.getEndVertex();

            //starting point: deeper starting point
            if (segment2.getStartDistance() > segment1.getStartDistance() + TOL)
            {
                startDist = segment2.getStartDistance();
                startType = segment1.getIntermediateType();
                startPos  = segment2.getStartPosition();
            }
            else
            {
                startDist = segment1.getStartDistance();
                startType = segment1.getStartType();
                startPos  = segment1.getStartPosition();
            }

            //ending point: deepest ending point
            if (segment2.getEndDistance() < segment1.getEndDistance() - TOL)
            {
                endDist = segment2.getEndDistance();
                endType = segment1.getIntermediateType();
                endPos  = segment2.getEndPosition();
            }
            else
            {
                endDist = segment1.getEndDistance();
                endType = segment1.getEndType();
                endPos  = segment1.getEndPosition();
            }
            middleType = segment1.getIntermediateType();

            //set vertex to BOUNDARY if it is start type
            if (startType == Segment.VERTEX)
            {
                startVertex.setStatus(Vertex.BOUNDARY);
            }

            //set vertex to BOUNDARY if it is end type
            if (endType == Segment.VERTEX)
            {
                endVertex.setStatus(Vertex.BOUNDARY);
            }

            //VERTEX-_______-VERTEX
            if (startType == Segment.VERTEX && endType == Segment.VERTEX)
            {
                return;
            }

            //______-EDGE-______
            else if (middleType == Segment.EDGE)
            {
                //gets the edge
                int splitEdge;
                if ((startVertex == face.v1 && endVertex == face.v2) || (startVertex == face.v2 && endVertex == face.v1))
                {
                    splitEdge = 1;
                }
                else if ((startVertex == face.v2 && endVertex == face.v3) || (startVertex == face.v3 && endVertex == face.v2))
                {
                    splitEdge = 2;
                }
                else
                {
                    splitEdge = 3;
                }

                //VERTEX-EDGE-EDGE
                if (startType == Segment.VERTEX)
                {
                    breakFaceInTwo(facePos, endPos, splitEdge);
                    return;
                }

                //EDGE-EDGE-VERTEX
                else if (endType == Segment.VERTEX)
                {
                    breakFaceInTwo(facePos, startPos, splitEdge);
                    return;
                }

                // EDGE-EDGE-EDGE
                else if (startDist == endDist)
                {
                    breakFaceInTwo(facePos, endPos, splitEdge);
                }
                else
                {
                    if ((startVertex == face.v1 && endVertex == face.v2) || (startVertex == face.v2 && endVertex == face.v3) || (startVertex == face.v3 && endVertex == face.v1))
                    {
                        breakFaceInThree(facePos, startPos, endPos, splitEdge);
                    }
                    else
                    {
                        breakFaceInThree(facePos, endPos, startPos, splitEdge);
                    }
                }
                return;
            }

            //______-FACE-______

            //VERTEX-FACE-EDGE
            else if (startType == Segment.VERTEX && endType == Segment.EDGE)
            {
                breakFaceInTwo(facePos, endPos, endVertex);
            }
            //EDGE-FACE-VERTEX
            else if (startType == Segment.EDGE && endType == Segment.VERTEX)
            {
                breakFaceInTwo(facePos, startPos, startVertex);
            }
            //VERTEX-FACE-FACE
            else if (startType == Segment.VERTEX && endType == Segment.FACE)
            {
                breakFaceInThree(facePos, endPos, startVertex);
            }
            //FACE-FACE-VERTEX
            else if (startType == Segment.FACE && endType == Segment.VERTEX)
            {
                breakFaceInThree(facePos, startPos, endVertex);
            }
            //EDGE-FACE-EDGE
            else if (startType == Segment.EDGE && endType == Segment.EDGE)
            {
                breakFaceInThree(facePos, startPos, endPos, startVertex, endVertex);
            }
            //EDGE-FACE-FACE
            else if (startType == Segment.EDGE && endType == Segment.FACE)
            {
                breakFaceInFour(facePos, startPos, endPos, startVertex);
            }
            //FACE-FACE-EDGE
            else if (startType == Segment.FACE && endType == Segment.EDGE)
            {
                breakFaceInFour(facePos, endPos, startPos, endVertex);
            }
            //FACE-FACE-FACE
            else if (startType == Segment.FACE && endType == Segment.FACE)
            {
                Vector3d segmentVector = new Vector3d(startPos.x - endPos.x, startPos.y - endPos.y, startPos.z - endPos.z);

                //if the intersection segment is a point only...
                if (Math.Abs(segmentVector.x) < TOL && Math.Abs(segmentVector.y) < TOL && Math.Abs(segmentVector.z) < TOL)
                {
                    breakFaceInThree(facePos, startPos);
                    return;
                }

                //gets the vertex more lined with the intersection segment
                int      linedVertex;
                Point3d  linedVertexPos;
                Vector3d vertexVector = new Vector3d(endPos.x - face.v1.x, endPos.y - face.v1.y, endPos.z - face.v1.z);
                vertexVector.normalize();
                double dot1 = Math.Abs(segmentVector.dot(vertexVector));
                vertexVector = new Vector3d(endPos.x - face.v2.x, endPos.y - face.v2.y, endPos.z - face.v2.z);
                vertexVector.normalize();
                double dot2 = Math.Abs(segmentVector.dot(vertexVector));
                vertexVector = new Vector3d(endPos.x - face.v3.x, endPos.y - face.v3.y, endPos.z - face.v3.z);
                vertexVector.normalize();
                double dot3 = Math.Abs(segmentVector.dot(vertexVector));
                if (dot1 > dot2 && dot1 > dot3)
                {
                    linedVertex    = 1;
                    linedVertexPos = face.v1.getPosition();
                }
                else if (dot2 > dot3 && dot2 > dot1)
                {
                    linedVertex    = 2;
                    linedVertexPos = face.v2.getPosition();
                }
                else
                {
                    linedVertex    = 3;
                    linedVertexPos = face.v3.getPosition();
                }

                // Now find which of the intersection endpoints is nearest to that vertex.
                if (linedVertexPos.distance(startPos) > linedVertexPos.distance(endPos))
                {
                    breakFaceInFive(facePos, startPos, endPos, linedVertex);
                }
                else
                {
                    breakFaceInFive(facePos, endPos, startPos, linedVertex);
                }
            }
        }
예제 #6
0
        /// <summary>
        /// Split an individual face
        /// </summary>
        /// <param name="facePos">face position on the array of faces</param>
        /// <param name="segment1">segment representing the intersection of the face with the plane</param>
        /// <param name="segment2">segment representing the intersection of other face with the plane of the current face plane</param>
        private void SplitFace(int facePos, Segment segment1, Segment segment2)
        {
            Vector3 startPos, endPos;
            int startType, endType, middleType;
            double startDist, endDist;

            Face face = GetFace(facePos);
            Vertex startVertex = segment1.GetStartVertex();
            Vertex endVertex = segment1.GetEndVertex();

            //starting point: deeper starting point
            if (segment2.StartDist > segment1.StartDist + EqualityTolerance)
            {
                startDist = segment2.StartDist;
                startType = segment1.GetIntermediateType();
                startPos = segment2.GetStartPosition();
            }
            else
            {
                startDist = segment1.StartDist;
                startType = segment1.GetStartType();
                startPos = segment1.GetStartPosition();
            }

            //ending point: deepest ending point
            if (segment2.GetEndDistance() < segment1.GetEndDistance() - EqualityTolerance)
            {
                endDist = segment2.GetEndDistance();
                endType = segment1.GetIntermediateType();
                endPos = segment2.GetEndPosition();
            }
            else
            {
                endDist = segment1.GetEndDistance();
                endType = segment1.GetEndType();
                endPos = segment1.GetEndPosition();
            }
            middleType = segment1.GetIntermediateType();

            //set vertex to BOUNDARY if it is start type
            if (startType == Segment.VERTEX)
            {
                startVertex.SetStatus(Status.BOUNDARY);
            }

            //set vertex to BOUNDARY if it is end type
            if (endType == Segment.VERTEX)
            {
                endVertex.SetStatus(Status.BOUNDARY);
            }

            //VERTEX-_______-VERTEX
            if (startType == Segment.VERTEX && endType == Segment.VERTEX)
            {
                return;
            }

            //______-EDGE-______
            else if (middleType == Segment.EDGE)
            {
                //gets the edge
                int splitEdge;
                if ((startVertex == face.v1 && endVertex == face.v2) || (startVertex == face.v2 && endVertex == face.v1))
                {
                    splitEdge = 1;
                }
                else if ((startVertex == face.v2 && endVertex == face.v3) || (startVertex == face.v3 && endVertex == face.v2))
                {
                    splitEdge = 2;
                }
                else
                {
                    splitEdge = 3;
                }

                //VERTEX-EDGE-EDGE
                if (startType == Segment.VERTEX)
                {
                    BreakFaceInTwo(facePos, endPos, splitEdge);
                    return;
                }

                //EDGE-EDGE-VERTEX
                else if (endType == Segment.VERTEX)
                {
                    BreakFaceInTwo(facePos, startPos, splitEdge);
                    return;
                }

                // EDGE-EDGE-EDGE
                else if (startDist == endDist)
                {
                    BreakFaceInTwo(facePos, endPos, splitEdge);
                }
                else
                {
                    if ((startVertex == face.v1 && endVertex == face.v2) || (startVertex == face.v2 && endVertex == face.v3) || (startVertex == face.v3 && endVertex == face.v1))
                    {
                        BreakFaceInThree(facePos, startPos, endPos, splitEdge);
                    }
                    else
                    {
                        BreakFaceInThree(facePos, endPos, startPos, splitEdge);
                    }
                }
                return;
            }

            //______-FACE-______

            //VERTEX-FACE-EDGE
            else if (startType == Segment.VERTEX && endType == Segment.EDGE)
            {
                BreakFaceInTwo(facePos, endPos, endVertex);
            }
            //EDGE-FACE-VERTEX
            else if (startType == Segment.EDGE && endType == Segment.VERTEX)
            {
                BreakFaceInTwo(facePos, startPos, startVertex);
            }
            //VERTEX-FACE-FACE
            else if (startType == Segment.VERTEX && endType == Segment.FACE)
            {
                BreakFaceInThree(facePos, endPos, startVertex);
            }
            //FACE-FACE-VERTEX
            else if (startType == Segment.FACE && endType == Segment.VERTEX)
            {
                BreakFaceInThree(facePos, startPos, endVertex);
            }
            //EDGE-FACE-EDGE
            else if (startType == Segment.EDGE && endType == Segment.EDGE)
            {
                BreakFaceInThree(facePos, startPos, endPos, startVertex, endVertex);
            }
            //EDGE-FACE-FACE
            else if (startType == Segment.EDGE && endType == Segment.FACE)
            {
                BreakFaceInFour(facePos, startPos, endPos, startVertex);
            }
            //FACE-FACE-EDGE
            else if (startType == Segment.FACE && endType == Segment.EDGE)
            {
                BreakFaceInFour(facePos, endPos, startPos, endVertex);
            }
            //FACE-FACE-FACE
            else if (startType == Segment.FACE && endType == Segment.FACE)
            {
                Vector3 segmentVector = new Vector3(startPos.x - endPos.x, startPos.y - endPos.y, startPos.z - endPos.z);

                //if the intersection segment is a point only...
                if (Math.Abs(segmentVector.x) < EqualityTolerance && Math.Abs(segmentVector.y) < EqualityTolerance && Math.Abs(segmentVector.z) < EqualityTolerance)
                {
                    BreakFaceInThree(facePos, startPos);
                    return;
                }

                //gets the vertex more lined with the intersection segment
                int linedVertex;
                Vector3 linedVertexPos;
                Vector3 vertexVector = new Vector3(endPos.x - face.v1.Position.x, endPos.y - face.v1.Position.y, endPos.z - face.v1.Position.z);
                vertexVector.Normalize();
                double dot1 = Math.Abs(Vector3.Dot(segmentVector, vertexVector));
                vertexVector = new Vector3(endPos.x - face.v2.Position.x, endPos.y - face.v2.Position.y, endPos.z - face.v2.Position.z);
                vertexVector.Normalize();
                double dot2 = Math.Abs(Vector3.Dot(segmentVector, vertexVector));
                vertexVector = new Vector3(endPos.x - face.v3.Position.x, endPos.y - face.v3.Position.y, endPos.z - face.v3.Position.z);
                vertexVector.Normalize();
                double dot3 = Math.Abs(Vector3.Dot(segmentVector, vertexVector));
                if (dot1 > dot2 && dot1 > dot3)
                {
                    linedVertex = 1;
                    linedVertexPos = face.v1.GetPosition();
                }
                else if (dot2 > dot3 && dot2 > dot1)
                {
                    linedVertex = 2;
                    linedVertexPos = face.v2.GetPosition();
                }
                else
                {
                    linedVertex = 3;
                    linedVertexPos = face.v3.GetPosition();
                }

                // Now find which of the intersection endpoints is nearest to that vertex.
                if ((linedVertexPos - startPos).Length > (linedVertexPos - endPos).Length)
                {
                    BreakFaceInFive(facePos, startPos, endPos, linedVertex);
                }
                else
                {
                    BreakFaceInFive(facePos, endPos, startPos, linedVertex);
                }
            }
        }
예제 #7
0
        /// <summary>
        /// Face breaker for EDGE-EDGE-EDGE
        /// </summary>
        /// <param name="faceIndex">face index in the faces array</param>
        /// <param name="newPos1">new vertex position</param>
        /// <param name="newPos2">new vertex position</param>
        /// <param name="splitEdge">edge that will be split</param>
        private bool BreakFaceInThree(int faceIndex, Vector3 newPos1, Vector3 newPos2, int splitEdge)
        {
            //       O
            //      - -
            //     -   X
            //    -  *  -
            //   - *   **X
            //  -* ****   -
            // X-----------O

            Vertex vertex1 = AddVertex(newPos1, Status.BOUNDARY);
            Vertex vertex2 = AddVertex(newPos2, Status.BOUNDARY);

            if (splitEdge == 1)             // vertex 3
            {
                Face face = faces[faceIndex];
                bool willMakeExistingFace = (vertex1 == face.v1 && vertex2 == face.v2) || (vertex1 == face.v2 || vertex2 == face.v1);
                if (!willMakeExistingFace)
                {
                    faces.RemoveAt(faceIndex);
                    AddFace(face.v1, vertex1, face.v3);
                    AddFace(vertex1, vertex2, face.v3);
                    AddFace(vertex2, face.v2, face.v3);
                    return(true);
                }
            }
            else if (splitEdge == 2)             // vertex 1
            {
                Face face = faces[faceIndex];
                bool willMakeExistingFace = (vertex1 == face.v2 && vertex2 == face.v3) || (vertex1 == face.v3 || vertex2 == face.v2);
                if (!willMakeExistingFace)
                {
                    faces.RemoveAt(faceIndex);
                    AddFace(face.v2, vertex1, face.v1);
                    AddFace(vertex1, vertex2, face.v1);
                    AddFace(vertex2, face.v3, face.v1);
                    return(true);
                }
            }
            else             // vertex 2
            {
                Face face = faces[faceIndex];
                bool willMakeExistingFace = (vertex1 == face.v1 && vertex2 == face.v3) || (vertex1 == face.v3 || vertex2 == face.v1);
                if (!willMakeExistingFace)
                {
                    faces.RemoveAt(faceIndex);
                    AddFace(face.v3, vertex1, face.v2);
                    AddFace(vertex1, vertex2, face.v2);
                    AddFace(vertex2, face.v1, face.v2);
                    return(true);
                }
            }

            if (vertex2 == vertices[vertices.Count - 1])
            {
                vertices.RemoveAt(vertices.Count - 1);
            }
            if (vertex1 == vertices[vertices.Count - 1])
            {
                vertices.RemoveAt(vertices.Count - 1);
            }
            return(false);
        }
예제 #8
0
        /**
         * Classifies the face based on the ray trace technique
         *
         * @param object object3d used to compute the face status
         */
        public void rayTraceClassify(Object3D obj)
        {
            //creating a ray starting starting at the face baricenter going to the normal direction
            Point3d p0 = new Point3d();

            p0.x = (v1.x + v2.x + v3.x) / 3d;
            p0.y = (v1.y + v2.y + v3.y) / 3d;
            p0.z = (v1.z + v2.z + v3.z) / 3d;
            Line ray = new Line(getNormal(), p0);

            bool    success;
            double  dotProduct, distance;
            Point3d intersectionPoint;
            Face    closestFace = null;
            double  closestDistance;

            do
            {
                success         = true;
                closestDistance = Double.MaxValue;
                //for each face from the other solid...
                for (int i = 0; i < obj.getNumFaces(); i++)
                {
                    Face face = obj.getFace(i);
                    dotProduct        = face.getNormal().dot(ray.getDirection());
                    intersectionPoint = ray.computePlaneIntersection(face.getNormal(), face.v1.getPosition());

                    //if ray intersects the plane...
                    if (intersectionPoint != null)
                    {
                        distance = ray.computePointToPointDistance(intersectionPoint);

                        //if ray lies in plane...
                        if (Math.Abs(distance) < TOL && Math.Abs(dotProduct) < TOL)
                        {
                            //disturb the ray in order to not lie into another plane
                            ray.perturbDirection();
                            success = false;
                            break;
                        }

                        //if ray starts in plane...
                        if (Math.Abs(distance) < TOL && Math.Abs(dotProduct) > TOL)
                        {
                            //if ray intersects the face...
                            if (face.hasPoint(intersectionPoint))
                            {
                                //faces coincide
                                closestFace     = face;
                                closestDistance = 0;
                                break;
                            }
                        }

                        //if ray intersects plane...
                        else if (Math.Abs(dotProduct) > TOL && distance > TOL)
                        {
                            if (distance < closestDistance)
                            {
                                //if ray intersects the face;
                                if (face.hasPoint(intersectionPoint))
                                {
                                    //this face is the closest face untill now
                                    closestDistance = distance;
                                    closestFace     = face;
                                }
                            }
                        }
                    }
                }
            } while(success == false);

            //none face found: outside face
            if (closestFace == null)
            {
                status = OUTSIDE;
            }
            //face found: test dot product
            else
            {
                dotProduct = closestFace.getNormal().dot(ray.getDirection());

                //distance = 0: coplanar faces
                if (Math.Abs(closestDistance) < TOL)
                {
                    if (dotProduct > TOL)
                    {
                        status = SAME;
                    }
                    else if (dotProduct < -TOL)
                    {
                        status = OPPOSITE;
                    }
                }

                //dot product > 0 (same direction): inside face
                else if (dotProduct > TOL)
                {
                    status = INSIDE;
                }

                //dot product < 0 (opposite direction): outside face
                else if (dotProduct < -TOL)
                {
                    status = OUTSIDE;
                }
            }
        }
예제 #9
0
파일: Face.cs 프로젝트: sunjini/Net3dBool
        /// <summary>
        /// Classifies the face based on the ray trace technique
        /// </summary>
        /// <param name="obj">object3d used to compute the face status</param>
        public void RayTraceClassify(Object3D obj)
        {
            //creating a ray starting at the face baricenter going to the normal direction
            Line ray = new Line(GetNormal(), Center);

            bool     success;
            double   distance;
            Vector3d intersectionPoint;
            Face     closestFace = null;
            double   closestDistance;

            do
            {
                success         = true;
                closestDistance = double.MaxValue;
                //for each face from the other solid...
                for (int faceIndex = 0; faceIndex < obj.NumFaces; faceIndex++)
                {
                    Face face = obj.GetFace(faceIndex);
                    intersectionPoint = ray.ComputePlaneIntersection(face.GetPlane());

                    //if ray intersects the plane...
                    if (intersectionPoint.X != double.PositiveInfinity)
                    {
                        double dotProduct = Vector3d.Dot(face.GetNormal(), ray.Direction);
                        distance = ray.ComputePointToPointDistance(intersectionPoint);

                        //if ray lies in plane...
                        if (Math.Abs(distance) < EqualityTolerance && Math.Abs(dotProduct) < EqualityTolerance)
                        {
                            //disturb the ray in order to not lie into another plane
                            ray.PerturbDirection();
                            success = false;
                            break;
                        }

                        //if ray starts in plane...
                        if (Math.Abs(distance) < EqualityTolerance && Math.Abs(dotProduct) > EqualityTolerance)
                        {
                            //if ray intersects the face...
                            if (face.ContainsPoint(intersectionPoint))
                            {
                                //faces coincide
                                closestFace     = face;
                                closestDistance = 0;
                                break;
                            }
                        }

                        //if ray intersects plane...
                        else if (Math.Abs(dotProduct) > EqualityTolerance && distance > EqualityTolerance)
                        {
                            if (distance < closestDistance)
                            {
                                //if ray intersects the face;
                                if (face.ContainsPoint(intersectionPoint))
                                {
                                    //this face is the closest face untill now
                                    closestDistance = distance;
                                    closestFace     = face;
                                }
                            }
                        }
                    }
                }
            } while (success == false);


            if (closestFace == null)
            {
                //none face found: outside face
                Status = Status.OUTSIDE;
            }
            else //face found: test dot product
            {
                double dotProduct = Vector3d.Dot(closestFace.GetNormal(), ray.Direction);

                //distance = 0: coplanar faces
                if (Math.Abs(closestDistance) < EqualityTolerance)
                {
                    if (dotProduct > EqualityTolerance)
                    {
                        Status = Status.SAME;
                    }
                    else if (dotProduct < -EqualityTolerance)
                    {
                        Status = Status.OPPOSITE;
                    }
                }
                else if (dotProduct > EqualityTolerance)
                {
                    //dot product > 0 (same direction): inside face
                    Status = Status.INSIDE;
                }
                else if (dotProduct < -EqualityTolerance)
                {
                    //dot product < 0 (opposite direction): outside face
                    Status = Status.OUTSIDE;
                }
            }
        }
예제 #10
0
 /**
  * Computes closest distance from a vertex to a plane
  *
  * @param vertex vertex used to compute the distance
  * @param face face representing the plane where it is contained
  * @return the closest distance from the vertex to the plane
  */
 private double computeDistance(Vertex vertex, Face face)
 {
     Vector3d normal = face.getNormal();
     double a = normal.x;
     double b = normal.y;
     double c = normal.z;
     double d = -(a * face.v1.x + b * face.v1.y + c * face.v1.z);
     return a * vertex.x + b * vertex.y + c * vertex.z + d;
 }
예제 #11
0
 //------------------------------------ADDS----------------------------------------//
 /**
  * Method used to add a face properly for internal methods
  *
  * @param v1 a face vertex
  * @param v2 a face vertex
  * @param v3 a face vertex
  */
 private Face addFace(Vertex v1, Vertex v2, Vertex v3)
 {
     if (!(v1.equals(v2) || v1.equals(v3) || v2.equals(v3)))
     {
         Face face = new Face(v1, v2, v3);
         if (face.getArea() > TOL)
         {
             faces.Add(face);
             return face;
         }
         else
         {
             return null;
         }
     }
     else
     {
         return null;
     }
 }