📄 polyhedralboundedsolid.java
字号:
{ int i, j; for ( i = 0; i < verticesList.size(); i++ ) { verticesList.get(i).emanatingHalfEdge = null; } for ( i = 0; i < polygonsList.size(); i++ ) { _PolyhedralBoundedSolidFace face = polygonsList.get(i); for ( j = 0; j < face.boundariesList.size(); j++ ) { _PolyhedralBoundedSolidLoop loop; _PolyhedralBoundedSolidHalfEdge he, heStart; loop = face.boundariesList.get(j); he = loop.boundaryStartHalfEdge; if ( he == null ) { continue; } heStart = he; do { he.startingVertex.emanatingHalfEdge = he; he = he.next(); if ( he == null ) { break; } } while( he != heStart ); } } for ( i = 0; i < verticesList.size(); i++ ) { if ( verticesList.get(i).emanatingHalfEdge == null ) { verticesList.locateWindowAtElem(verticesList.get(i)); verticesList.removeElemAtWindow(); i--; } } } /** This method runs a set of validity tests to check te integrity of the data structure. If all of the tests goes well, this method returns true. If any of the test fails, this method return false. Current methods (already implemented): - All loops have an starting halfedge - All loops are closed - All faces contains its corresponding containing plane equation Current methods (not implemented yet): - All faces are co-planar - For faces with more than one loop, the loops are not intersecting nor self-intersecting - Topology test: euler formula gives a closed representation (no holes, no missing faces and no non-manifold solids like Klain bottles) - Geometric integrity: there are no intersecting faces */ public boolean validateModel() { int i; String msg = ""; boolean test = true; modelIsValid = false; remakeEmanatingHalfedgesReferences(); //----------------------------------------------------------------- for ( i = 0; i < polygonsList.size(); i++ ) { _PolyhedralBoundedSolidFace face = polygonsList.get(i); if ( validateFaceIsPlanar(face) ) { face.calculatePlane(); } else { msg += " - Face [" + face.id + "] is not coplanar\n"; test = false; } } //----------------------------------------------------------------- if ( !validateTopologicalIntegrity() ) { msg += " - Topological integrity test failed.\n"; test = false; } //----------------------------------------------------------------- if ( test ) { modelIsValid = true; } else { VSDK.reportMessage(this, VSDK.WARNING, "validateModel", "Validation test failed!:\n" + msg); } return test; } //= TEXTUAL QUERY OPERATIONS ====================================== private String intPreSpaces(int val, int fieldSize) { DecimalFormat f = new DecimalFormat("0"); String cad; cad = f.format(val, new StringBuffer(""), new FieldPosition(0)).toString(); int remain = fieldSize - cad.length(); for ( ; remain > 0; remain-- ) { cad = " " + cad; } return cad; } /** Check the general interface contract in superclass method Geometry.computeQuantitativeInvisibility. */ public int computeQuantitativeInvisibility(Vector3D origin, Vector3D p) { int qi = 0; int i; Vector3D d = p.substract(origin); Vector3D pi; double t0 = d.length(); d.normalize(); int pos; Ray ray = new Ray(origin, d); GeometryIntersectionInformation info; info = new GeometryIntersectionInformation(); for ( i = 0; i < polygonsList.size(); i++ ) { _PolyhedralBoundedSolidFace face = polygonsList.get(i); if ( face.containingPlane.doIntersection(ray) ) { if ( ray.t < t0-VSDK.EPSILON ) { ray.direction.normalize(); pi = ray.origin.add(ray.direction.multiply(ray.t)); pos = face.testPointInside(pi, VSDK.EPSILON); if ( pos == Geometry.INSIDE || pos == Geometry.LIMIT ) { face.containingPlane.doExtraInformation(ray, 0.0, info); if ( info.n.dotProduct(d) < 0.0 ) { qi ++; } } } } } return qi; } /** Utility routine used to compare floating values inside the boundary representation winged edge data structure, following procedure `comp` from program [MANT1988].13.2. */ public static int compareValue(double a, double b, double tolerance) { double delta; delta = Math.abs(a - b); if ( delta < tolerance ) { return 0; } else if ( a > b ) { return 1; } return -1; } /** This method get current solid in an "inverted" (geometrical sense) solid. Works on half edge data structure by inverting the order of each loop. This is an answer to problem [MANT1988].15.6. Current implementation does NOT correct face normals. Explicit model validation is encouraged after the application of this method. */ public void revert() { int i; for ( i = 0; i < polygonsList.size(); i++ ) { polygonsList.get(i).revert(); } } /** Removes all "inessential" edges of current solid (i.e. edges that separates two coplanar faces, or that occurs just in a single face). This is an answer to problem [MANT1988].15.2. For some operations on solid polyhedra such as boolean set operations, it is required that faces of solids be "maximal", i.e. that all coplanar neighbor faces have been combined, and all "inessential" edges have been removed, as noted on section [MANT1988].15.5. @todo current method does not fix faces that lies entirely over other faces. */ public void maximizeFaces() { int i; _PolyhedralBoundedSolidEdge e; InfinitePlane a, b; Vector3D p0, p1, p2; remakeEmanatingHalfedgesReferences(); //- Eliminate null edges ------------------------------------------ for ( i = 0; i < edgesList.size(); i++ ) { e = edgesList.get(i); p1 = e.rightHalf.startingVertex.position; p2 = e.leftHalf.startingVertex.position; if ( VSDK.vectorDistance(p1, p2) < 10*VSDK.EPSILON ) { lkev(e.rightHalf, e.leftHalf); // As this breaks the edge sequence, start again! maximizeFaces(); return; } } //- Join coplanar faces ------------------------------------------- for ( i = 0; i < edgesList.size(); i++ ) { e = edgesList.get(i); a = e.rightHalf.parentLoop.parentFace.containingPlane; b = e.leftHalf.parentLoop.parentFace.containingPlane; if ( e.rightHalf.parentLoop.parentFace == e.leftHalf.parentLoop.parentFace ) { lkemr(e.rightHalf, e.leftHalf); // As this breaks the face set, start again! maximizeFaces(); return; } else if ( a.overlapsWith(b, VSDK.EPSILON) ) { lkef(e.rightHalf, e.leftHalf); // As this breaks the face set, start again! maximizeFaces(); return; } } //- Eliminate vertices between colinear edges --------------------- _PolyhedralBoundedSolidHalfEdge he, heStart; _PolyhedralBoundedSolidVertex v; int nedges; for ( i = 0; i < verticesList.size(); i++ ) { v = verticesList.get(i); heStart = v.emanatingHalfEdge; if ( heStart == null ) { continue; } he = heStart; nedges = 0; do { nedges++; if ( nedges > 2 ) break; he = he.mirrorHalfEdge().next(); } while ( he != heStart ); if ( nedges == 2 ) { p0 = heStart.startingVertex.position; p1 = heStart.next().startingVertex.position.substract(p0); p2 = heStart.previous().startingVertex.position.substract(p0); if ( p1.crossProduct(p2).length() < VSDK.EPSILON ) { if ( p1.dotProduct(p2) < 0 ) { lkev(heStart, heStart.mirrorHalfEdge()); // As this breaks the edge sequence, start again! maximizeFaces(); return; } } } } //- Eliminate rings with a single vertex -------------------------- int j; for ( i = 0; i < polygonsList.size(); i++ ) { _PolyhedralBoundedSolidFace face = polygonsList.get(i); for ( j = 1; j < face.boundariesList.size(); j++ ) { _PolyhedralBoundedSolidLoop loop; loop = face.boundariesList.get(j); he = loop.boundaryStartHalfEdge; if ( he.parentEdge == null || loop.halfEdgesList.size() == 1 ) { System.out.println("Please delete face " + face.id + " and null point from " + he); } } } // Here should be a code searching for faces inside faces ... remakeEmanatingHalfedgesReferences(); } /** Modifies ids for current solid's vertices, edges, faces and halfedges to make them consecutive from 1. Note that ids does not impact current solid geometry or topology, as they are use only for debugging and furter construction / modification support. User of this class should keep in mind id changes when using this method. */ public void compactIds() { int i, j; for ( i = 0; i < verticesList.size(); i++ ) { verticesList.get(i).id = i+1; } maxVertexId = i; for ( i = 0; i < edgesList.size(); i++ ) { edgesList.get(i).id = i+1; } int k = 1; for ( i = 0; i < polygonsList.size(); i++ ) { _PolyhedralBoundedSolidFace face = polygonsList.get(i); face.id = i+1; for ( j = 0; j < face.boundariesList.size(); j++ ) { _PolyhedralBoundedSolidLoop loop; _PolyhedralBoundedSolidHalfEdge he, heStart; loop = face.boundariesList.get(j); he = loop.boundaryStartHalfEdge; if ( he == null ) { continue; } heStart = he; do { he.id = k; k++; he = he.next(); if ( he == null ) { break; } } while( he != heStart ); } } maxFaceId = i; } public String toString() { String msg = ""; int i, j; msg += "= POLYHEDRAL BOUNDED SOLID STRUCTURE ==========================================\n"; msg += "Solid with " + verticesList.size() + " vertices:\n"; for ( i = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -