//------------------------------------OTHERS------------------------------------// /** * Checks if two segments intersect * * @param segment the other segment to check the intesection * @return true if the segments intersect, false otherwise */ public bool intersect(Segment segment) { if (endDist < segment.startDist + TOL || segment.endDist < startDist + TOL) { return false; } else { return true; } }
/** * 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); } } }
//-----------------------------------OVERRIDES----------------------------------// /** * Clones the Segment object * * @return cloned Segment object */ public Segment Clone() { Segment clone = new Segment(); clone.line = line.Clone(); clone.index = index; clone.startDist = startDist; clone.endDist = endDist; clone.startDist = startType; clone.middleType = middleType; clone.endType = endType; clone.startVertex = startVertex.Clone(); clone.endVertex = endVertex.Clone(); clone.startPos = startPos.Clone(); clone.endPos = endPos.Clone(); return clone; }
//-------------------------FACES_SPLITTING_METHODS------------------------------// /** * Split faces so that none face is intercepted by a face of other object * * @param object the other object 3d used to make the split */ public void splitFaces(Object3D obj) { Line line; Face face1, face2; Segment[] segments; Segment segment1; Segment segment2; double distFace1Vert1, distFace1Vert2, distFace1Vert3, distFace2Vert1, distFace2Vert2, distFace2Vert3; int signFace1Vert1, signFace1Vert2, signFace1Vert3, signFace2Vert1, signFace2Vert2, signFace2Vert3; int numFacesBefore = getNumFaces(); int numFacesStart = getNumFaces(); int facesIgnored = 0; //if the objects bounds overlap... if (getBound().overlap(obj.getBound())) { //for each object1 face... for (int i = 0; i < getNumFaces(); i++) { //if object1 face bound and object2 bound overlap ... face1 = getFace(i); if (face1.getBound().overlap(obj.getBound())) { //for each object2 face... for (int j = 0; j < obj.getNumFaces(); 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 > TOL ? 1 : (distFace1Vert1 < -TOL ? -1 : 0)); signFace1Vert2 = (distFace1Vert2 > TOL ? 1 : (distFace1Vert2 < -TOL ? -1 : 0)); signFace1Vert3 = (distFace1Vert3 > TOL ? 1 : (distFace1Vert3 < -TOL ? -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 > TOL ? 1 : (distFace2Vert1 < -TOL ? -1 : 0)); signFace2Vert2 = (distFace2Vert2 > TOL ? 1 : (distFace2Vert2 < -TOL ? -1 : 0)); signFace2Vert3 = (distFace2Vert3 > TOL ? 1 : (distFace2Vert3 < -TOL ? -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 = getNumFaces(); this.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(getNumFaces() - 1))) { //return it to its position and jump it if (i != (getNumFaces() - 1)) { faces.RemoveAt(getNumFaces() - 1); faces.Insert(i, face1); } else { continue; } } //else: test next face else { i--; break; } } } } } } } } } } }