Ejemplo n.º 1
0
        /// <summary>
        /// Split faces so that none face is intercepted by a face of other object
        /// </summary>
        /// <param name="compareObject">the other object 3d used to make the split</param>
        public void SplitFaces(Object3D compareObject)
        {
            Line    line;
            Face    thisFace, compareFace;
            Segment segment1;
            Segment segment2;
            double  v1DistToCompareFace, distFace1Vert2, distFace1Vert3, distFace2Vert1, distFace2Vert2, distFace2Vert3;
            int     signFace1Vert1, signFace1Vert2, signFace1Vert3, signFace2Vert1, signFace2Vert2, signFace2Vert3;
            int     numFacesBefore = this.GetNumFaces();
            int     numFacesStart  = this.GetNumFaces();

            //if the objects bounds overlap...
            if (this.GetBound().Overlap(compareObject.GetBound()))
            {
                //for each object1 face...
                for (int thisFaceIndex = 0; thisFaceIndex < this.GetNumFaces(); thisFaceIndex++)
                {
                    //if object1 face bound and object2 bound overlap ...
                    thisFace = GetFace(thisFaceIndex);

                    if (thisFace.GetBound().Overlap(compareObject.GetBound()))
                    {
                        //for each object2 face...
                        for (int compareFaceIndex = 0; compareFaceIndex < compareObject.GetNumFaces(); compareFaceIndex++)
                        {
                            //if object1 face bound and object2 face bound overlap...
                            compareFace = compareObject.GetFace(compareFaceIndex);
                            if (thisFace.GetBound().Overlap(compareFace.GetBound()))
                            {
                                //PART I - DO TWO POLIGONS INTERSECT?
                                //POSSIBLE RESULTS: INTERSECT, NOT_INTERSECT, COPLANAR

                                //distance from the face1 vertices to the face2 plane
                                v1DistToCompareFace = ComputeDistance(thisFace.v1, compareFace);
                                distFace1Vert2      = ComputeDistance(thisFace.v2, compareFace);
                                distFace1Vert3      = ComputeDistance(thisFace.v3, compareFace);

                                //distances signs from the face1 vertices to the face2 plane
                                signFace1Vert1 = (v1DistToCompareFace > EqualityTolerance ? 1 : (v1DistToCompareFace < -EqualityTolerance ? -1 : 0));
                                signFace1Vert2 = (distFace1Vert2 > EqualityTolerance ? 1 : (distFace1Vert2 < -EqualityTolerance ? -1 : 0));
                                signFace1Vert3 = (distFace1Vert3 > EqualityTolerance ? 1 : (distFace1Vert3 < -EqualityTolerance ? -1 : 0));

                                //if all the signs are zero, the planes are coplanar
                                //if all the signs are positive or negative, the planes do not intersect
                                //if the signs are not equal...
                                if (!(signFace1Vert1 == signFace1Vert2 && signFace1Vert2 == signFace1Vert3))
                                {
                                    //distance from the face2 vertices to the face1 plane
                                    distFace2Vert1 = ComputeDistance(compareFace.v1, thisFace);
                                    distFace2Vert2 = ComputeDistance(compareFace.v2, thisFace);
                                    distFace2Vert3 = ComputeDistance(compareFace.v3, thisFace);

                                    //distances signs from the face2 vertices to the face1 plane
                                    signFace2Vert1 = (distFace2Vert1 > EqualityTolerance ? 1 : (distFace2Vert1 < -EqualityTolerance ? -1 : 0));
                                    signFace2Vert2 = (distFace2Vert2 > EqualityTolerance ? 1 : (distFace2Vert2 < -EqualityTolerance ? -1 : 0));
                                    signFace2Vert3 = (distFace2Vert3 > EqualityTolerance ? 1 : (distFace2Vert3 < -EqualityTolerance ? -1 : 0));

                                    //if the signs are not equal...
                                    if (!(signFace2Vert1 == signFace2Vert2 && signFace2Vert2 == signFace2Vert3))
                                    {
                                        line = new Line(thisFace, compareFace);

                                        //intersection of the face1 and the plane of face2
                                        segment1 = new Segment(line, thisFace, signFace1Vert1, signFace1Vert2, signFace1Vert3);

                                        //intersection of the face2 and the plane of face1
                                        segment2 = new Segment(line, compareFace, signFace2Vert1, signFace2Vert2, signFace2Vert3);

                                        //if the two segments intersect...
                                        if (segment1.Intersect(segment2))
                                        {
                                            //PART II - SUBDIVIDING NON-COPLANAR POLYGONS
                                            int  lastNumFaces = GetNumFaces();
                                            bool splitOccured = this.SplitFace(thisFaceIndex, segment1, segment2);

                                            //prevent from infinite loop (with a loss of faces...)
                                            if (GetNumFaces() > numFacesStart * 100)
                                            {
                                                //System.out.println("possible infinite loop situation: terminating faces split");
                                                //return;
                                                int a = 0;
                                            }

                                            //if the face in the position isn't the same, there was a break
                                            if (splitOccured &&
                                                thisFace != GetFace(thisFaceIndex))
                                            {
                                                //if the generated solid is equal the origin...
                                                if (thisFace.Equals(GetFace(GetNumFaces() - 1)))
                                                {
                                                    //return it to its position and jump it
                                                    if (thisFaceIndex != (GetNumFaces() - 1))
                                                    {
                                                        faces.RemoveAt(GetNumFaces() - 1);
                                                        faces.Insert(thisFaceIndex, thisFace);
                                                    }
                                                    else
                                                    {
                                                        continue;
                                                    }
                                                }
                                                //else: test next face
                                                else
                                                {
                                                    thisFaceIndex--;
                                                    break;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Split faces so that no face is intercepted by a face of other object
        /// </summary>
        /// <param name="compareObject">the other object 3d used to make the split</param>
        public void SplitFaces(CsgObject3D compareObject, CancellationToken cancellationToken,
                               Action <CsgFace, CsgFace> splitFaces = null,
                               Action <List <CsgFace> > results     = null)
        {
            Stack <CsgFace> newFacesFromSplitting = new Stack <CsgFace>();

            int numFacesStart = this.Faces.Count;

            //if the objects bounds overlap...
            //for each object1 face...
            var bounds = compareObject.GetBound();

            Faces.SearchBounds(bounds);
            foreach (var thisFaceIn in Faces.QueryResults)             // put it in an array as we will be adding new faces to it
            {
                newFacesFromSplitting.Push(thisFaceIn);
                // make sure we process every face that we have added during splitting before moving on to the next face
                while (newFacesFromSplitting.Count > 0)
                {
                    var faceToSplit = newFacesFromSplitting.Pop();

                    // stop processing if operation has been canceled
                    cancellationToken.ThrowIfCancellationRequested();

                    //if object1 face bound and object2 bound overlap ...
                    //for each object2 face...
                    compareObject.Faces.SearchBounds(faceToSplit.GetBound());
                    foreach (var cuttingFace in compareObject.Faces.QueryResults)
                    {
                        //if object1 face bound and object2 face bound overlap...
                        //PART I - DO TWO POLIGONS INTERSECT?
                        //POSSIBLE RESULTS: INTERSECT, NOT_INTERSECT, COPLANAR

                        //distance from the face1 vertices to the face2 plane
                        double v1DistToCuttingFace = cuttingFace.DistanceFromPlane(faceToSplit.v1);
                        double v2DistToCuttingFace = cuttingFace.DistanceFromPlane(faceToSplit.v2);
                        double v3DistToCuttingFace = cuttingFace.DistanceFromPlane(faceToSplit.v3);

                        //distances signs from the face1 vertices to the face2 plane
                        PlaneSide sideFace1Vert1 = (v1DistToCuttingFace > EqualityTolerance ? PlaneSide.Front : (v1DistToCuttingFace < -EqualityTolerance ? PlaneSide.Back : PlaneSide.On));
                        PlaneSide sideFace1Vert2 = (v2DistToCuttingFace > EqualityTolerance ? PlaneSide.Front : (v2DistToCuttingFace < -EqualityTolerance ? PlaneSide.Back : PlaneSide.On));
                        PlaneSide sideFace1Vert3 = (v3DistToCuttingFace > EqualityTolerance ? PlaneSide.Front : (v3DistToCuttingFace < -EqualityTolerance ? PlaneSide.Back : PlaneSide.On));

                        //if all the signs are zero, the planes are coplanar
                        //if all the signs are positive or negative, the planes do not intersect
                        //if the signs are not equal...
                        if (!(sideFace1Vert1 == sideFace1Vert2 && sideFace1Vert2 == sideFace1Vert3))
                        {
                            //distance from the face2 vertices to the face1 plane
                            double faceToSplitTo1 = faceToSplit.DistanceFromPlane(cuttingFace.v1);
                            double faceToSplitTo2 = faceToSplit.DistanceFromPlane(cuttingFace.v2);
                            double faceToSplitTo3 = faceToSplit.DistanceFromPlane(cuttingFace.v3);

                            //distances signs from the face2 vertices to the face1 plane
                            PlaneSide signFace2Vert1 = (faceToSplitTo1 > EqualityTolerance ? PlaneSide.Front : (faceToSplitTo1 < -EqualityTolerance ? PlaneSide.Back : PlaneSide.On));
                            PlaneSide signFace2Vert2 = (faceToSplitTo2 > EqualityTolerance ? PlaneSide.Front : (faceToSplitTo2 < -EqualityTolerance ? PlaneSide.Back : PlaneSide.On));
                            PlaneSide signFace2Vert3 = (faceToSplitTo3 > EqualityTolerance ? PlaneSide.Front : (faceToSplitTo3 < -EqualityTolerance ? PlaneSide.Back : PlaneSide.On));

                            //if the signs are not equal...
                            if (!(signFace2Vert1 == signFace2Vert2 && signFace2Vert2 == signFace2Vert3))
                            {
                                var line = new Line(faceToSplit, cuttingFace);

                                //intersection of the face1 and the plane of face2
                                var segment1 = new Segment(line, faceToSplit, sideFace1Vert1, sideFace1Vert2, sideFace1Vert3);

                                //intersection of the face2 and the plane of face1
                                var segment2 = new Segment(line, cuttingFace, signFace2Vert1, signFace2Vert2, signFace2Vert3);

                                //if the two segments intersect...
                                if (segment1.Intersect(segment2))
                                {
                                    //PART II - SUBDIVIDING NON-COPLANAR POLYGONS
                                    Stack <CsgFace> facesFromSplit = new Stack <CsgFace>();

                                    if (this.SplitFace(faceToSplit, segment1, segment2, facesFromSplit) &&
                                        facesFromSplit.Count > 0 &&
                                        !(facesFromSplit.Count == 1 && facesFromSplit.Peek().Equals(faceToSplit)))
                                    {
                                        foreach (var face in facesFromSplit)
                                        {
                                            newFacesFromSplitting.Push(face);
                                        }

                                        // send debugging information if registered
                                        splitFaces?.Invoke(faceToSplit, cuttingFace);
                                        results?.Invoke(facesFromSplit.ToList());

                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Split faces so that none face is intercepted by a face of other object
        /// </summary>
        /// <param name="obj">the other object 3d used to make the split</param>
        public void SplitFaces(Object3D obj)
        {
            Line    line;
            Face    face1, face2;
            Segment segment1;
            Segment segment2;
            double  distFace1Vert1, distFace1Vert2, distFace1Vert3, distFace2Vert1, distFace2Vert2, distFace2Vert3;
            int     signFace1Vert1, signFace1Vert2, signFace1Vert3, signFace2Vert1, signFace2Vert2, signFace2Vert3;
            int     numFacesBefore = NumFaces;
            int     numFacesStart  = NumFaces;

            //if the objects bounds overlap...
            if (_Bound.Overlap(obj._Bound))
            {
                //for each object1 face...
                for (int i = 0; i < NumFaces; i++)
                {
                    //if object1 face bound and object2 bound overlap ...
                    face1 = GetFace(i);

                    if (face1.GetBound().Overlap(obj._Bound))
                    {
                        //for each object2 face...
                        for (int j = 0; j < obj.NumFaces; j++)
                        {
                            //if object1 face bound and object2 face bound overlap...
                            face2 = obj.GetFace(j);
                            if (face1.GetBound().Overlap(face2.GetBound()))
                            {
                                //PART I - DO TWO POLIGONS INTERSECT?
                                //POSSIBLE RESULTS: INTERSECT, NOT_INTERSECT, COPLANAR

                                //distance from the face1 vertices to the face2 plane
                                distFace1Vert1 = ComputeDistance(face1.V1, face2);
                                distFace1Vert2 = ComputeDistance(face1.V2, face2);
                                distFace1Vert3 = ComputeDistance(face1.V3, face2);

                                //distances signs from the face1 vertices to the face2 plane
                                signFace1Vert1 = (distFace1Vert1 > EqualityTolerance ? 1 : (distFace1Vert1 < -EqualityTolerance ? -1 : 0));
                                signFace1Vert2 = (distFace1Vert2 > EqualityTolerance ? 1 : (distFace1Vert2 < -EqualityTolerance ? -1 : 0));
                                signFace1Vert3 = (distFace1Vert3 > EqualityTolerance ? 1 : (distFace1Vert3 < -EqualityTolerance ? -1 : 0));

                                //if all the signs are zero, the planes are coplanar
                                //if all the signs are positive or negative, the planes do not intersect
                                //if the signs are not equal...
                                if (!(signFace1Vert1 == signFace1Vert2 && signFace1Vert2 == signFace1Vert3))
                                {
                                    //distance from the face2 vertices to the face1 plane
                                    distFace2Vert1 = ComputeDistance(face2.V1, face1);
                                    distFace2Vert2 = ComputeDistance(face2.V2, face1);
                                    distFace2Vert3 = ComputeDistance(face2.V3, face1);

                                    //distances signs from the face2 vertices to the face1 plane
                                    signFace2Vert1 = (distFace2Vert1 > EqualityTolerance ? 1 : (distFace2Vert1 < -EqualityTolerance ? -1 : 0));
                                    signFace2Vert2 = (distFace2Vert2 > EqualityTolerance ? 1 : (distFace2Vert2 < -EqualityTolerance ? -1 : 0));
                                    signFace2Vert3 = (distFace2Vert3 > EqualityTolerance ? 1 : (distFace2Vert3 < -EqualityTolerance ? -1 : 0));

                                    //if the signs are not equal...
                                    if (!(signFace2Vert1 == signFace2Vert2 && signFace2Vert2 == signFace2Vert3))
                                    {
                                        line = new Line(face1, face2);

                                        //intersection of the face1 and the plane of face2
                                        segment1 = new Segment(line, face1, signFace1Vert1, signFace1Vert2, signFace1Vert3);

                                        //intersection of the face2 and the plane of face1
                                        segment2 = new Segment(line, face2, signFace2Vert1, signFace2Vert2, signFace2Vert3);

                                        //if the two segments intersect...
                                        if (segment1.Intersect(segment2))
                                        {
                                            //PART II - SUBDIVIDING NON-COPLANAR POLYGONS
                                            int lastNumFaces = NumFaces;
                                            SplitFace(i, segment1, segment2);

                                            //prevent from infinite loop (with a loss of faces...)
                                            //if(numFacesStart*20<getNumFaces())
                                            //{
                                            //  System.out.println("possible infinite loop situation: terminating faces split");
                                            //  return;
                                            //}

                                            //if the face in the position isn't the same, there was a break
                                            if (face1 != GetFace(i))
                                            {
                                                //if the generated solid is equal the origin...
                                                if (face1.Equals(GetFace(NumFaces - 1)))
                                                {
                                                    //return it to its position and jump it
                                                    if (i != (NumFaces - 1))
                                                    {
                                                        Faces.RemoveAt(NumFaces - 1);
                                                        Faces.Insert(i, face1);
                                                    }
                                                    else
                                                    {
                                                        continue;
                                                    }
                                                }
                                                //else: test next face
                                                else
                                                {
                                                    i--;
                                                    break;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }