コード例 #1
0
 /// <summary>
 /// Method used to add a face properly for internal methods
 /// </summary>
 /// <param name="v1">a face vertex</param>
 /// <param name="v2">a face vertex</param>
 /// <param name="v3">a face vertex</param>
 /// <returns></returns>
 private void AddFaceFromSplit(Vertex v1, Vertex v2, Vertex v3,
                               Stack <CsgFace> facesFromSplit)
 {
     if (!(v1.Equals(v2) || v1.Equals(v3) || v2.Equals(v3)))
     {
         CsgFace face = new CsgFace(v1, v2, v3);
         if (face.GetArea() > EqualityTolerance)
         {
             bool exists = false;
             foreach (var test in facesFromSplit)
             {
                 if (test.Equals(face))
                 {
                     exists = true;
                     break;
                 }
             }
             if (!exists)
             {
                 Faces.Insert(face, face.GetBound());
                 facesFromSplit.Push(face);
             }
         }
     }
 }
コード例 #2
0
        /// <summary>
        /// Face breaker for VERTEX-FACE-FACE / FACE-FACE-VERTEX
        /// </summary>
        /// <param name="faceIndex">face index in the faces array</param>
        /// <param name="newPos">new vertex position</param>
        /// <param name="endVertex">vertex used for the split</param>
        private bool BreakFaceInThree(CsgFace face, Vector3 newPos, Stack <CsgFace> facesFromSplit)
        {
            //       O
            //      -*-
            //     - * -
            //    -  *  -
            //   -   X   -
            //  -  *   *  -
            // O-*--------*O
            Vertex vertex = AddVertex(newPos, FaceStatus.Boundary);

            if (face.v1.Position == vertex.Position ||
                face.v2.Position == vertex.Position ||
                face.v2.Position == vertex.Position)                    // it is not new
            {
                // if the vertex we are adding is any of the existing vertices then don't add any
                return(false);
            }

            AddFaceFromSplit(face.v1, face.v2, vertex, facesFromSplit);
            AddFaceFromSplit(face.v2, face.v3, vertex, facesFromSplit);
            AddFaceFromSplit(face.v3, face.v1, vertex, facesFromSplit);

            Faces.Remove(face);

            return(true);
        }
コード例 #3
0
ファイル: CsgFace.cs プロジェクト: TenYearsADream/agg-sharp
        public bool Equals(CsgFace 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
        /// <summary>
        /// Face breaker for VERTEX-FACE-EDGE / EDGE-FACE-VERTEX
        /// </summary>
        /// <param name="faceIndex">face index in the faces array</param>
        /// <param name="newPos">new vertex position</param>
        /// <param name="endVertex">vertex used for splitting</param>
        private bool BreakFaceInTwo(CsgFace face, Vector3 newPos, Vertex endVertex, Stack <CsgFace> facesFromSplit)
        {
            //       O
            //      - -
            //     -   -
            //    -     -
            //   -       -
            //  -         -
            // O-----------O

            // TODO: make sure we are not creating extra Vertices and not cleaning them up
            Vertex vertex = AddVertex(newPos, FaceStatus.Boundary);

            if (endVertex.Equals(face.v1))
            {
                // don't add it if it is the same as the face we have
                if (!face.v1.Equals(vertex) &&
                    !face.v2.Equals(vertex))
                {
                    AddFaceFromSplit(face.v1, vertex, face.v3, facesFromSplit);
                    AddFaceFromSplit(vertex, face.v2, face.v3, facesFromSplit);
                    Faces.Remove(face);

                    return(true);
                }
            }
            else if (endVertex.Equals(face.v2))
            {
                // don't add it if it is the same as the face we have
                if (!face.v2.Equals(vertex) &&
                    !face.v3.Equals(vertex))
                {
                    AddFaceFromSplit(face.v2, vertex, face.v1, facesFromSplit);
                    AddFaceFromSplit(vertex, face.v3, face.v1, facesFromSplit);
                    Faces.Remove(face);

                    return(true);
                }
            }
            else
            {
                // don't add it if it is the same as the face we have
                if (!face.v1.Equals(vertex) &&
                    !face.v3.Equals(vertex))
                {
                    AddFaceFromSplit(face.v3, vertex, face.v2, facesFromSplit);
                    AddFaceFromSplit(vertex, face.v1, face.v2, facesFromSplit);
                    Faces.Remove(face);

                    return(true);
                }
            }

            return(false);
        }
コード例 #5
0
ファイル: CsgFace.cs プロジェクト: TenYearsADream/agg-sharp
        /// <summary>
        /// Clones the face object
        /// </summary>
        /// <returns>cloned face object</returns>
        public CsgFace Clone()
        {
            CsgFace clone = new CsgFace();

            clone.v1     = v1.Clone();
            clone.v2     = v2.Clone();
            clone.v3     = v3.Clone();
            clone.center = center;
            clone.Status = Status;
            return(clone);
        }
コード例 #6
0
        /// <summary>
        /// Face breaker for EDGE-FACE-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="startVertex">vertex used for the new faces creation</param>
        /// <param name="endVertex">vertex used for the new faces creation</param>
        private bool BreakFaceInThree(CsgFace face, Vector3 newPos1, Vector3 newPos2, Vertex startVertex, Vertex endVertex, Stack <CsgFace> facesFromSplit)
        {
            //       O
            //      - -
            //     -   -
            //    -     -
            //   -       -
            //  -         -
            // O-----------O
            Vertex vertex1 = AddVertex(newPos1, FaceStatus.Boundary);
            Vertex vertex2 = AddVertex(newPos2, FaceStatus.Boundary);

            if (startVertex.Equals(face.v1) && endVertex.Equals(face.v2))
            {
                AddFaceFromSplit(face.v1, vertex1, vertex2, facesFromSplit);
                AddFaceFromSplit(face.v1, vertex2, face.v3, facesFromSplit);
                AddFaceFromSplit(vertex1, face.v2, vertex2, facesFromSplit);
            }
            else if (startVertex.Equals(face.v2) && endVertex.Equals(face.v1))
            {
                AddFaceFromSplit(face.v1, vertex2, vertex1, facesFromSplit);
                AddFaceFromSplit(face.v1, vertex1, face.v3, facesFromSplit);
                AddFaceFromSplit(vertex2, face.v2, vertex1, facesFromSplit);
            }
            else if (startVertex.Equals(face.v2) && endVertex.Equals(face.v3))
            {
                AddFaceFromSplit(face.v2, vertex1, vertex2, facesFromSplit);
                AddFaceFromSplit(face.v2, vertex2, face.v1, facesFromSplit);
                AddFaceFromSplit(vertex1, face.v3, vertex2, facesFromSplit);
            }
            else if (startVertex.Equals(face.v3) && endVertex.Equals(face.v2))
            {
                AddFaceFromSplit(face.v2, vertex2, vertex1, facesFromSplit);
                AddFaceFromSplit(face.v2, vertex1, face.v1, facesFromSplit);
                AddFaceFromSplit(vertex2, face.v3, vertex1, facesFromSplit);
            }
            else if (startVertex.Equals(face.v3) && endVertex.Equals(face.v1))
            {
                AddFaceFromSplit(face.v3, vertex1, vertex2, facesFromSplit);
                AddFaceFromSplit(face.v3, vertex2, face.v2, facesFromSplit);
                AddFaceFromSplit(vertex1, face.v1, vertex2, facesFromSplit);
            }
            else
            {
                AddFaceFromSplit(face.v3, vertex2, vertex1, facesFromSplit);
                AddFaceFromSplit(face.v3, vertex1, face.v2, facesFromSplit);
                AddFaceFromSplit(vertex2, face.v1, vertex1, facesFromSplit);
            }

            Faces.Remove(face);

            return(true);
        }
コード例 #7
0
        /// <summary>
        /// Face breaker for FACE-FACE-FACE
        /// </summary>
        /// <param name="faceIndex">face index in the faces array</param>
        /// <param name="facePos1">new vertex position</param>
        /// <param name="facePos2">new vertex position</param>
        /// <param name="linedVertex">linedVertex what vertex is more lined with the intersection found</param>
        private bool BreakFaceInFive(CsgFace face, Vector3 facePos1, Vector3 facePos2, int linedVertex, Stack <CsgFace> facesFromSplit)
        {
            //       O
            //      - -
            //     -   -
            //    -     -
            //   -    X  -
            //  -  X      -
            // O-----------O
            Vertex faceVertex1       = AddVertex(facePos1, FaceStatus.Boundary);
            bool   faceVertex1Exists = faceVertex1 != vertices[vertices.Count - 1];

            Vertex faceVertex2       = AddVertex(facePos2, FaceStatus.Boundary);
            bool   faceVertex2Exists = faceVertex2 != vertices[vertices.Count - 1];

            if (faceVertex1Exists && faceVertex2Exists)
            {
                vertices.RemoveAt(vertices.Count - 1);
                vertices.RemoveAt(vertices.Count - 1);
                return(false);
            }

            if (linedVertex == 1)
            {
                AddFaceFromSplit(face.v2, face.v3, faceVertex1, facesFromSplit);
                AddFaceFromSplit(face.v2, faceVertex1, faceVertex2, facesFromSplit);
                AddFaceFromSplit(face.v3, faceVertex2, faceVertex1, facesFromSplit);
                AddFaceFromSplit(face.v2, faceVertex2, face.v1, facesFromSplit);
                AddFaceFromSplit(face.v3, face.v1, faceVertex2, facesFromSplit);
            }
            else if (linedVertex == 2)
            {
                AddFaceFromSplit(face.v3, face.v1, faceVertex1, facesFromSplit);
                AddFaceFromSplit(face.v3, faceVertex1, faceVertex2, facesFromSplit);
                AddFaceFromSplit(face.v1, faceVertex2, faceVertex1, facesFromSplit);
                AddFaceFromSplit(face.v3, faceVertex2, face.v2, facesFromSplit);
                AddFaceFromSplit(face.v1, face.v2, faceVertex2, facesFromSplit);
            }
            else
            {
                AddFaceFromSplit(face.v1, face.v2, faceVertex1, facesFromSplit);
                AddFaceFromSplit(face.v1, faceVertex1, faceVertex2, facesFromSplit);
                AddFaceFromSplit(face.v2, faceVertex2, faceVertex1, facesFromSplit);
                AddFaceFromSplit(face.v1, faceVertex2, face.v3, facesFromSplit);
                AddFaceFromSplit(face.v2, face.v3, faceVertex2, facesFromSplit);
            }

            Faces.Remove(face);

            return(true);
        }
コード例 #8
0
        /// <summary>
        /// Face breaker for EDGE-FACE-FACE / FACE-FACE-EDGE
        /// </summary>
        /// <param name="faceIndex">face index in the faces array</param>
        /// <param name="edgePos">new vertex position</param>
        /// <param name="facePos">new vertex position</param>
        /// <param name="endVertex">vertex used for the split</param>
        private bool BreakFaceInFour(CsgFace face, Vector3 edgePos, Vector3 facePos, Vertex endVertex, Stack <CsgFace> facesFromSplit)
        {
            //         2
            //        -*-
            //       - * -
            //      -  *  E
            //     -   * * -
            //    -    F    -
            //   -   *   *   -
            //  - *         * -
            // 3---------------1
            Vertex edgeVertex = AddVertex(edgePos, FaceStatus.Boundary);
            bool   edgeExists = edgeVertex != vertices[vertices.Count - 1];
            Vertex faceVertex = AddVertex(facePos, FaceStatus.Boundary);
            bool   faceExists = faceVertex != vertices[vertices.Count - 1];

            if (faceExists && edgeExists)
            {
                vertices.RemoveAt(vertices.Count - 1);
                vertices.RemoveAt(vertices.Count - 1);
                return(false);
            }

            // check that we are not adding back in the same face we are removing
            if (endVertex.Equals(face.v1))
            {
                AddFaceFromSplit(face.v1, edgeVertex, faceVertex, facesFromSplit);
                AddFaceFromSplit(edgeVertex, face.v2, faceVertex, facesFromSplit);
                AddFaceFromSplit(face.v2, face.v3, faceVertex, facesFromSplit);
                AddFaceFromSplit(face.v3, face.v1, faceVertex, facesFromSplit);
            }
            else if (endVertex.Equals(face.v2))
            {
                AddFaceFromSplit(face.v2, edgeVertex, faceVertex, facesFromSplit);
                AddFaceFromSplit(edgeVertex, face.v3, faceVertex, facesFromSplit);
                AddFaceFromSplit(face.v3, face.v1, faceVertex, facesFromSplit);
                AddFaceFromSplit(face.v1, face.v2, faceVertex, facesFromSplit);
            }
            else
            {
                AddFaceFromSplit(face.v3, edgeVertex, faceVertex, facesFromSplit);
                AddFaceFromSplit(edgeVertex, face.v1, faceVertex, facesFromSplit);
                AddFaceFromSplit(face.v1, face.v2, faceVertex, facesFromSplit);
                AddFaceFromSplit(face.v2, face.v3, faceVertex, facesFromSplit);
            }

            Faces.Remove(face);

            return(true);
        }
コード例 #9
0
        private CsgFace AddFace(Vertex v1, Vertex v2, Vertex v3)
        {
            if (!(v1.Equals(v2) || v1.Equals(v3) || v2.Equals(v3)))
            {
                CsgFace face = new CsgFace(v1, v2, v3);
                if (face.GetArea() > EqualityTolerance)
                {
                    Faces.Insert(face, face.GetBound());

                    return(face);
                }
            }

            return(null);
        }
コード例 #10
0
        /// <summary>
        /// Face breaker for VERTEX-EDGE-EDGE / EDGE-EDGE-VERTEX
        /// </summary>
        /// <param name="faceIndex">face index in the faces array</param>
        /// <param name="newPos">new vertex position</param>
        /// <param name="splitEdge">edge that will be split</param>
        private bool BreakFaceInTwo(CsgFace face, Vector3 newPos, int splitEdge, Stack <CsgFace> facesFromSplit)
        {
            //       O
            //      -*-
            //     - * -
            //    -  *  -
            //   -   *   -
            //  -    *    -
            // O-----X-----O
            Vertex vertex = AddVertex(newPos, FaceStatus.Boundary);

            if (vertex != vertices[vertices.Count - 1])
            {
                // The added vertex is one of the existing vertices. So we would only add the same face we are removing.
                return(false);
            }

            if (splitEdge == 1)
            {
                AddFaceFromSplit(face.v1, vertex, face.v3, facesFromSplit);
                AddFaceFromSplit(vertex, face.v2, face.v3, facesFromSplit);
            }
            else if (splitEdge == 2)
            {
                if (!face.v3.Equals(vertex))
                {
                    AddFaceFromSplit(face.v2, vertex, face.v1, facesFromSplit);
                }
                AddFaceFromSplit(vertex, face.v3, face.v1, facesFromSplit);
            }
            else
            {
                AddFaceFromSplit(face.v3, vertex, face.v2, facesFromSplit);
                AddFaceFromSplit(vertex, face.v1, face.v2, facesFromSplit);
            }

            Faces.Remove(face);

            return(true);
        }
コード例 #11
0
        /// <summary>
        /// Constructor for a line.The line created is the intersection between two planes
        /// </summary>
        /// <param name="face1">face representing one of the planes</param>
        /// <param name="face2">face representing one of the planes</param>
        public Line(CsgFace face1, CsgFace face2)
        {
            Vector3 normalFace1 = face1.Normal;
            Vector3 normalFace2 = face2.Normal;

            //direction: cross product of the faces normals
            Direction = Vector3Ex.Cross(normalFace1, normalFace2);

            //if direction length is not zero (the planes aren't parallel )...
            if (!(Direction.Length < EqualityTolerance))
            {
                //getting a line point, zero is set to a coordinate whose direction
                //component isn't zero (line intersecting its origin plan)
                startPoint = new Vector3();
                double d1 = -(normalFace1.X * face1.v1.Position.X + normalFace1.Y * face1.v1.Position.Y + normalFace1.Z * face1.v1.Position.Z);
                double d2 = -(normalFace2.X * face2.v1.Position.X + normalFace2.Y * face2.v1.Position.Y + normalFace2.Z * face2.v1.Position.Z);
                if (Math.Abs(Direction.X) > EqualityTolerance)
                {
                    startPoint.X = 0;
                    startPoint.Y = (d2 * normalFace1.Z - d1 * normalFace2.Z) / Direction.X;
                    startPoint.Z = (d1 * normalFace2.Y - d2 * normalFace1.Y) / Direction.X;
                }
                else if (Math.Abs(Direction.Y) > EqualityTolerance)
                {
                    startPoint.X = (d1 * normalFace2.Z - d2 * normalFace1.Z) / Direction.Y;
                    startPoint.Y = 0;
                    startPoint.Z = (d2 * normalFace1.X - d1 * normalFace2.X) / Direction.Y;
                }
                else
                {
                    startPoint.X = (d2 * normalFace1.Y - d1 * normalFace2.Y) / Direction.Z;
                    startPoint.Y = (d1 * normalFace2.X - d2 * normalFace1.X) / Direction.Z;
                    startPoint.Z = 0;
                }
            }

            Direction.Normalize();
        }
コード例 #12
0
        /// <summary>
        /// Split an individual face
        /// </summary>
        /// <param name="faceIndex">face index in 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 bool SplitFace(CsgFace face, Segment segment1, Segment segment2, Stack <CsgFace> facesFromSplit)
        {
            Vector3    startPos, endPos;
            SegmentEnd startType, endType, middleType;
            double     startDist, endDist;

            Vertex startVertex = segment1.StartVertex;
            Vertex endVertex   = segment1.EndVertex;

            //starting point: deeper starting point
            if (segment2.StartDistance > segment1.StartDistance + EqualityTolerance)
            {
                startDist = segment2.StartDistance;
                startType = segment1.MiddleType;
                startPos  = segment2.StartPosition;
            }
            else
            {
                startDist = segment1.StartDistance;
                startType = segment1.StartType;
                startPos  = segment1.StartPosition;
            }

            //ending point: deepest ending point
            if (segment2.EndDistance < segment1.EndDistance - EqualityTolerance)
            {
                endDist = segment2.EndDistance;
                endType = segment1.MiddleType;
                endPos  = segment2.EndPosition;
            }
            else
            {
                endDist = segment1.EndDistance;
                endType = segment1.EndType;
                endPos  = segment1.EndPosition;
            }
            middleType = segment1.MiddleType;

            if (startType == SegmentEnd.Vertex)
            {
                //set vertex to BOUNDARY if it is start type
                startVertex.Status = FaceStatus.Boundary;
            }

            if (endType == SegmentEnd.Vertex)
            {
                //set vertex to BOUNDARY if it is end type
                endVertex.Status = FaceStatus.Boundary;
            }

            if (startType == SegmentEnd.Vertex && endType == SegmentEnd.Vertex)
            {
                //VERTEX-_______-VERTEX
                return(false);
            }
            else if (middleType == SegmentEnd.Edge)
            {
                //______-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;
                }

                if (startType == SegmentEnd.Vertex)
                {
                    //VERTEX-EDGE-EDGE
                    return(BreakFaceInTwo(face, endPos, splitEdge, facesFromSplit));
                }
                else if (endType == SegmentEnd.Vertex)
                {
                    //EDGE-EDGE-VERTEX
                    return(BreakFaceInTwo(face, startPos, splitEdge, facesFromSplit));
                }
                else if (startDist == endDist)
                {
                    // EDGE-EDGE-EDGE
                    return(BreakFaceInTwo(face, endPos, splitEdge, facesFromSplit));
                }
                else
                {
                    if ((startVertex == face.v1 && endVertex == face.v2) || (startVertex == face.v2 && endVertex == face.v3) || (startVertex == face.v3 && endVertex == face.v1))
                    {
                        return(BreakFaceInThree(face, startPos, endPos, splitEdge, facesFromSplit));
                    }
                    else
                    {
                        return(BreakFaceInThree(face, endPos, startPos, splitEdge, facesFromSplit));
                    }
                }
            }
            //______-FACE-______
            else if (startType == SegmentEnd.Vertex && endType == SegmentEnd.Edge)
            {
                //VERTEX-FACE-EDGE
                return(BreakFaceInTwo(face, endPos, endVertex, facesFromSplit));
            }
            else if (startType == SegmentEnd.Edge && endType == SegmentEnd.Vertex)
            {
                //EDGE-FACE-VERTEX
                return(BreakFaceInTwo(face, startPos, startVertex, facesFromSplit));
            }
            else if (startType == SegmentEnd.Vertex && endType == SegmentEnd.Face)
            {
                //VERTEX-FACE-FACE
                return(BreakFaceInThree(face, endPos, facesFromSplit));
            }
            else if (startType == SegmentEnd.Face && endType == SegmentEnd.Vertex)
            {
                //FACE-FACE-VERTEX
                return(BreakFaceInThree(face, startPos, facesFromSplit));
            }
            else if (startType == SegmentEnd.Edge && endType == SegmentEnd.Edge)
            {
                //EDGE-FACE-EDGE
                return(BreakFaceInThree(face, startPos, endPos, startVertex, endVertex, facesFromSplit));
            }
            else if (startType == SegmentEnd.Edge && endType == SegmentEnd.Face)
            {
                //EDGE-FACE-FACE
                return(BreakFaceInFour(face, startPos, endPos, startVertex, facesFromSplit));
            }
            else if (startType == SegmentEnd.Face && endType == SegmentEnd.Edge)
            {
                //FACE-FACE-EDGE
                return(BreakFaceInFour(face, endPos, startPos, endVertex, facesFromSplit));
            }
            else if (startType == SegmentEnd.Face &&
                     endType == SegmentEnd.Face)
            {
                //FACE-FACE-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)
                {
                    return(BreakFaceInThree(face, startPos, facesFromSplit));
                }

                //gets the vertex more lined with the intersection segment
                double dot1 = Math.Abs(Vector3.Dot(segmentVector, (endPos - face.v1.Position).GetNormal()));
                double dot2 = Math.Abs(Vector3.Dot(segmentVector, (endPos - face.v2.Position).GetNormal()));
                double dot3 = Math.Abs(Vector3.Dot(segmentVector, (endPos - face.v3.Position).GetNormal()));

                int     linedVertex;
                Vector3 linedVertexPos;
                if (dot1 > dot2 &&
                    dot1 > dot3)
                {
                    linedVertex    = 1;
                    linedVertexPos = face.v1.Position;
                }
                else if (dot2 > dot3 &&
                         dot2 > dot1)
                {
                    linedVertex    = 2;
                    linedVertexPos = face.v2.Position;
                }
                else
                {
                    linedVertex    = 3;
                    linedVertexPos = face.v3.Position;
                }

                // Now find which of the intersection endpoints is nearest to that vertex.
                if ((linedVertexPos - startPos).Length > (linedVertexPos - endPos).Length)
                {
                    return(BreakFaceInFive(face, startPos, endPos, linedVertex, facesFromSplit));
                }
                else
                {
                    return(BreakFaceInFive(face, endPos, startPos, linedVertex, facesFromSplit));
                }
            }

            return(false);
        }
コード例 #13
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(CsgFace face, Vector3 newPos1, Vector3 newPos2, int splitEdge, Stack <CsgFace> facesFromSplit)
        {
            //       O
            //      - -
            //     -   X
            //    -  *  -
            //   - *   **X
            //  -* ****   -
            // X-----------O

            Vertex vertex1 = AddVertex(newPos1, FaceStatus.Boundary);
            Vertex vertex2 = AddVertex(newPos2, FaceStatus.Boundary);

            if (splitEdge == 1)             // vertex 3
            {
                bool willMakeExistingFace = (vertex1 == face.v1 && vertex2 == face.v2) || (vertex1 == face.v2 || vertex2 == face.v1);
                if (!willMakeExistingFace)
                {
                    AddFaceFromSplit(face.v1, vertex1, face.v3, facesFromSplit);
                    AddFaceFromSplit(vertex1, vertex2, face.v3, facesFromSplit);
                    AddFaceFromSplit(vertex2, face.v2, face.v3, facesFromSplit);
                    Faces.Remove(face);

                    return(true);
                }
            }
            else if (splitEdge == 2)             // vertex 1
            {
                bool willMakeExistingFace = (vertex1 == face.v2 && vertex2 == face.v3) || (vertex1 == face.v3 || vertex2 == face.v2);
                if (!willMakeExistingFace)
                {
                    AddFaceFromSplit(face.v2, vertex1, face.v1, facesFromSplit);
                    AddFaceFromSplit(vertex1, vertex2, face.v1, facesFromSplit);
                    AddFaceFromSplit(vertex2, face.v3, face.v1, facesFromSplit);
                    Faces.Remove(face);

                    return(true);
                }
            }
            else             // vertex 2
            {
                bool willMakeExistingFace = (vertex1 == face.v1 && vertex2 == face.v3) || (vertex1 == face.v3 || vertex2 == face.v1);
                if (!willMakeExistingFace)
                {
                    AddFaceFromSplit(face.v3, vertex1, face.v2, facesFromSplit);
                    AddFaceFromSplit(vertex1, vertex2, face.v2, facesFromSplit);
                    AddFaceFromSplit(vertex2, face.v1, face.v2, facesFromSplit);
                    Faces.Remove(face);

                    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);
        }
コード例 #14
0
ファイル: CsgFace.cs プロジェクト: TenYearsADream/agg-sharp
        /// <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(CsgObject3D obj)
        {
            var random = new Random();

            //creating a ray starting at the face baricenter going to the normal direction
            Ray ray = new Ray(center, Normal);

            //Line ray = new Line(GetNormal(), center);
            ray.PerturbDirection(random);

            bool    success;
            double  distance;
            Vector3 intersectionPoint;
            CsgFace closestFace = null;
            double  closestDistance;

            do
            {
                success         = true;
                closestDistance = Double.MaxValue;
                //for each face from the other solid...
                //foreach (Face face in obj.Faces.AllObjects())
                obj.Faces.AlongRay(ray);
                foreach (var face in obj.Faces.QueryResults)
                {
                    double hitDistance;
                    bool   front;

                    //if ray intersects the plane...
                    if (face.Plane.RayHitPlane(ray, out hitDistance, out front))
                    {
                        double dotProduct = Vector3.Dot(face.Normal, ray.directionNormal);
                        distance                  = hitDistance;
                        intersectionPoint         = ray.origin + ray.directionNormal * hitDistance;
                        ray.maxDistanceToConsider = hitDistance;

                        //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(random);
                            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 until now
                                    closestDistance = distance;
                                    closestFace     = face;
                                }
                            }
                        }
                    }
                }
            } while (success == false);

            if (closestFace == null)
            {
                //none face found: outside face
                Status = FaceStatus.Outside;
            }
            else             //face found: test dot product
            {
                double dotProduct = Vector3.Dot(closestFace.Normal, ray.directionNormal);

                //distance = 0: coplanar faces
                if (Math.Abs(closestDistance) < EqualityTolerance)
                {
                    if (dotProduct > EqualityTolerance)
                    {
                        Status = FaceStatus.Same;
                    }
                    else if (dotProduct < -EqualityTolerance)
                    {
                        Status = FaceStatus.Opposite;
                    }
                }
                else if (dotProduct > EqualityTolerance)
                {
                    //dot product > 0 (same direction): inside face
                    Status = FaceStatus.Inside;
                }
                else if (dotProduct < -EqualityTolerance)
                {
                    //dot product < 0 (opposite direction): outside face
                    Status = FaceStatus.Outside;
                }
            }
        }
コード例 #15
0
        /// <summary>
        /// Constructs a Segment based on elements obtained from the two planes relations
        /// </summary>
        /// <param name="line"></param>
        /// <param name="face"></param>
        /// <param name="side1"></param>
        /// <param name="side2"></param>
        /// <param name="side3"></param>
        public Segment(Line line, CsgFace face, PlaneSide side1, PlaneSide side2, PlaneSide side3)
        {
            this.line = line;
            index     = 0;

            //VERTEX is an end
            if (side1 == PlaneSide.On)
            {
                SetVertex(face.v1);
                //other vertices on the same side - VERTEX-VERTEX VERTEX
                if (side2 == side3)
                {
                    SetVertex(face.v1);
                }
            }

            //VERTEX is an end
            if (side2 == PlaneSide.On)
            {
                SetVertex(face.v2);
                //other vertices on the same side - VERTEX-VERTEX VERTEX
                if (side1 == side3)
                {
                    SetVertex(face.v2);
                }
            }

            //VERTEX is an end
            if (side3 == PlaneSide.On)
            {
                SetVertex(face.v3);
                //other vertices on the same side - VERTEX-VERTEX VERTEX
                if (side1 == side2)
                {
                    SetVertex(face.v3);
                }
            }

            //There are undefined ends - one or more edges cut the planes intersection line
            if (GetNumEndsSet() != 2)
            {
                //EDGE is an end
                if ((side1 == PlaneSide.Front && side2 == PlaneSide.Back) ||
                    (side1 == PlaneSide.Back && side2 == PlaneSide.Front))
                {
                    SetEdge(face.v1, face.v2);
                }
                //EDGE is an end
                if ((side2 == PlaneSide.Front && side3 == PlaneSide.Back) ||
                    (side2 == PlaneSide.Back && side3 == PlaneSide.Front))
                {
                    SetEdge(face.v2, face.v3);
                }
                //EDGE is an end
                if ((side3 == PlaneSide.Front && side1 == PlaneSide.Back) ||
                    (side3 == PlaneSide.Back && side1 == PlaneSide.Front))
                {
                    SetEdge(face.v3, face.v1);
                }
            }
        }