📄 polyhedralboundedsolid.java
字号:
public void doExtraInformation(Ray inRay, double inT, GeometryIntersectionInformation outData) { outData.clone(lastInfo); } /** Needed for supplying the Geometry.getMinMax operation */ private void calculateMinMaxPositions() { if ( minMax == null ) { minMax = new double[6]; double minX = Double.MAX_VALUE; double minY = Double.MAX_VALUE; double minZ = Double.MAX_VALUE; double maxX = Double.MIN_VALUE; double maxY = Double.MIN_VALUE; double maxZ = Double.MIN_VALUE; int i; for ( i = 0; i < verticesList.size(); i++ ) { _PolyhedralBoundedSolidVertex v; v = verticesList.get(i); double x = v.position.x; double y = v.position.y; double z = v.position.z; if ( x < minX ) minX = x; if ( y < minY ) minY = y; if ( z < minZ ) minZ = z; if ( x > maxX ) maxX = x; if ( y > maxY ) maxY = y; if ( z > maxZ ) maxZ = z; } minMax[0] = minX; minMax[1] = minY; minMax[2] = minZ; minMax[3] = maxX; minMax[4] = maxY; minMax[5] = maxZ; } } /** Check the general interface contract in superclass method Geometry.getMinMax. */ public double[] getMinMax() { if ( minMax == null ) { calculateMinMaxPositions(); } return minMax; } /** Checks that: 1. There are at least 3 points in set (no no-surface case) 2. There are at least 2 different points in the set (no all-equal bad case) 3. There are at least a third point, no colinear with the first 2 4. All points in this set lies within a small tolerance over the surface of the plane If all four steps succeed, this method returns true. Otherwise returns false. */ private boolean validateFacePointsAreCoplanar(ArrayList<Vector3D> points) { //- 1. Test no-surface case --------------------------------------- if ( points.size() < 3 ) { System.out.println("Reason 1"); return false; } //- 2. Test all-equal case ---------------------------------------- Vector3D p0, p1, p2; p0 = points.get(0); p1 = null; boolean test = false; int i; for ( i = 1; i < points.size(); i++ ) { p1 = points.get(i); if ( VSDK.vectorDistance(p0, p1) > 10 * VSDK.EPSILON ) { test = true; break; } } if ( !test ) { System.out.println("Reason 2"); return false; } //- 3. Test co-linear case ---------------------------------------- Vector3D a, b, n; double aDotB; InfinitePlane facePlane = null; int j, k; for ( i = 0; i < points.size(); i++ ) { for ( j = 0; j < points.size(); j++ ) { for ( k = 0; k < points.size(); k++ ) { if ( i == j || i == k || j == k ) { continue; } p0 = points.get(i); p1 = points.get(j); p2 = points.get(k); if ( VSDK.vectorDistance(p0, p2) > 10 * VSDK.EPSILON && VSDK.vectorDistance(p1, p2) > 10 * VSDK.EPSILON ) { a = p2.substract(p0); b = p1.substract(p0); a.normalize(); b.normalize(); aDotB = Math.abs(a.dotProduct(b)); if ( aDotB < 1 - 2*VSDK.EPSILON ) { n = a.crossProduct(b); n.normalize(); facePlane = new InfinitePlane(n, p0); } break; } } } } if ( facePlane == null ) { System.out.println("Reason 3"); return false; } //- 4. Check if all points are near face plane -------------------- for ( i = 1; i < points.size(); i++ ) { p0 = points.get(i); if ( facePlane.doContainmentTest(p0, VSDK.EPSILON) != LIMIT ) { return false; } } //----------------------------------------------------------------- return true; } /** Returns true if the model was validated (using `validateModel` method) and validation succeed after any geometrical or topological operation. */ public boolean isValid() { return modelIsValid; } private ArrayList<Vector3D> extractPointsFromFace(_PolyhedralBoundedSolidFace face) { boolean test = true; ArrayList<Vector3D> points; points = new ArrayList<Vector3D>(); int j; for ( j = 0; j < face.boundariesList.size(); j++ ) { _PolyhedralBoundedSolidLoop loop; _PolyhedralBoundedSolidHalfEdge he, heStart; loop = face.boundariesList.get(j); he = loop.boundaryStartHalfEdge; if ( he == null ) { //msg += " - Loop without starting halfedge\n"; test = false; break; } heStart = he; do { he = he.next(); if ( he == null ) { // Loop is not closed! //msg += " - Not closed loop\n"; test = false; break; } points.add(he.startingVertex.position); } while( he != heStart ); } if ( !test ) { return null; } return points; } /** Given a face inside current solid, this method returns true if face is planar, false otherwise. */ public boolean validateFaceIsPlanar(_PolyhedralBoundedSolidFace face) { ArrayList<Vector3D> points = extractPointsFromFace(face); if ( (points != null) && validateFacePointsAreCoplanar(points) ) { return true; } return false; } /** After section [MANT1988].12.4.2 and program [MANT1988].12.9. */ public void loopGlue(int faceid) { //----------------------------------------------------------------- _PolyhedralBoundedSolidFace face; face = findFace(faceid); //----------------------------------------------------------------- _PolyhedralBoundedSolidHalfEdge h1, h2, h1next; h1 = face.boundariesList.get(0).boundaryStartHalfEdge; h2 = face.boundariesList.get(1).boundaryStartHalfEdge; while ( !h1.vertexPositionMatch(h2, 10*VSDK.EPSILON) ) { h2 = h2.next(); } lmekr(h1, h2); lkev(h1.previous(), h2.previous()); while ( h1.next() != h2 ) { h1next = h1.next(); lmef(h1.next(), h1.previous(), maxFaceId+1); lkev(h1.next(), (h1.next()).mirrorHalfEdge()); lkef(h1.mirrorHalfEdge(), h1); h1 = h1next; } lkef(h1.mirrorHalfEdge(), h1); } /** Given `this` and `other` solids, this method erases the `other` solid while appending its parts to current one as a new shell. This method follows section [MANT1988].12.4.1 and program [MANT1988].12.8. */ public void merge(PolyhedralBoundedSolid other) { //----------------------------------------------------------------- int offsetFacesId = getMaxFaceId(); int offsetVertexId = getMaxVertexId(); _PolyhedralBoundedSolidFace f; _PolyhedralBoundedSolidVertex v; //----------------------------------------------------------------- while ( other.polygonsList.size() > 0 ) { f = other.polygonsList.get(0); f.id += offsetFacesId; if ( f.id > maxFaceId ) maxFaceId = f.id; polygonsList.add(f); other.polygonsList.remove(0); } while ( other.edgesList.size() > 0 ) { edgesList.add(other.edgesList.get(0)); other.edgesList.remove(0); } while ( other.verticesList.size() > 0 ) { v = other.verticesList.get(0); v.id += offsetVertexId; if ( v.id > maxVertexId ) maxVertexId = v.id; verticesList.add(v); other.verticesList.remove(0); } } private boolean validateTopologicalIntegrity() { int i, j, k; _PolyhedralBoundedSolidEdge e; _PolyhedralBoundedSolidHalfEdge h1, h2; _PolyhedralBoundedSolidFace f; _PolyhedralBoundedSolidLoop l; //----------------------------------------------------------------- for ( i = 0; i < edgesList.size(); i++ ) { e = edgesList.get(i); h1 = e.rightHalf; h2 = e.leftHalf; if ( h1 == null || h2 == null ) { VSDK.reportMessage(this, VSDK.WARNING, "validateTopologicalIntegrity", "Edge with null halfedge!"); return false; } if ( h1.parentLoop.parentFace.parentSolid != h2.parentLoop.parentFace.parentSolid ) { VSDK.reportMessage(this, VSDK.WARNING, "validateTopologicalIntegrity", "Edge belonging to two different solids!"); return false; } } //----------------------------------------------------------------- int edgeCount[]; edgeCount = new int[edgesList.size()]; for ( i = 0; i < edgeCount.length; i++ ) { edgeCount[i] = 0; } for ( i = 0; i < polygonsList.size(); i++ ) { f = polygonsList.get(i); for ( j = 0; j < f.boundariesList.size(); j++ ) { _PolyhedralBoundedSolidHalfEdge he, heStart; l = f.boundariesList.get(j); he = l.boundaryStartHalfEdge; if ( he == null ) { VSDK.reportMessage(this, VSDK.WARNING, "validateTopologicalIntegrity", "Loop without starting halfedge!"); return false; } heStart = he; do { he = he.next(); if ( he == null ) { // Loop is not closed! VSDK.reportMessage(this, VSDK.WARNING, "validateTopologicalIntegrity", "Not closed loop!"); return false; } //----- for ( k = 0; k < edgeCount.length; k++ ) { if ( he.parentEdge == edgesList.get(k) ) { edgeCount[k]++; break; } } //----- } while( he != heStart ); } } for ( i = 0; i < edgeCount.length; i++ ) { if ( edgeCount[i] != 2 ) { VSDK.reportMessage(this, VSDK.WARNING, "validateTopologicalIntegrity", "Edges with different halfedges than 2!"); return false; } } //----------------------------------------------------------------- return true; } /** For all given halfedges, this edge asign valid emanating half edges on valid vertexes. If all the operations in current implementation are perfectly done, this method should not be needed. */ private void remakeEmanatingHalfedgesReferences()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -