/// <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; } } } } } } } } } } }
/// <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; } } } } } } } }
/// <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; } } } } } } } } } } }