Explorar o código

- Ifc: better handling of degenerate primitives occuring in clipping operations.

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@1317 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
aramis_acg %!s(int64=13) %!d(string=hai) anos
pai
achega
7ed1400c68
Modificáronse 1 ficheiros con 32 adicións e 16 borrados
  1. 32 16
      code/IFCGeometry.cpp

+ 32 - 16
code/IFCGeometry.cpp

@@ -546,40 +546,48 @@ void ProcessSweptDiskSolid(const IfcSweptDiskSolid solid, TempMesh& result, Conv
 }
 
 // ------------------------------------------------------------------------------------------------
-IfcMatrix3 DerivePlaneCoordinateSpace(const TempMesh& curmesh) {
-
+IfcMatrix3 DerivePlaneCoordinateSpace(const TempMesh& curmesh, bool& ok) 
+{
 	const std::vector<IfcVector3>& out = curmesh.verts;
 	IfcMatrix3 m;
 
+	ok = true;
+
 	const size_t s = out.size();
 	assert(curmesh.vertcnt.size() == 1 && curmesh.vertcnt.back() == s);
 
 	const IfcVector3 any_point = out[s-1];
 	IfcVector3 nor; 
 
-	// The input polygon is arbitrarily shaped, so we might need some tries
-	// until we find a suitable normal (and it does not even need to be
-	// right in all cases, Newell's algorithm would be the correct one ... ).
+	// The input polygon is arbitrarily shaped, therefore we might need some tries
+	// until we find a suitable normal. Note that Newells algorithm would give
+	// a more robust result, but this variant also gives us a suitable first
+	// axis for the 2D coordinate space on the polygon plane, exploiting the
+	// fact that the input polygon is nearly always a quad.
+	bool done = false;
 	size_t base = s-curmesh.vertcnt.back(), i, j;
-	for (i = base; i < s-1; ++i) {
+	for (i = base; !done && i < s-1; !done && ++i) {
 		for (j = i+1; j < s; ++j) {
 			nor = -((out[i]-any_point)^(out[j]-any_point));
 			if(fabs(nor.Length()) > 1e-8f) {
-				goto out;
+				done = true;
+				break;
 			}
 		}
 	}
 
-	assert(0);
-
-out:
+	if(!done) {
+		ok = false;
+		return m;
+	}
 
 	nor.Normalize();
 
 	IfcVector3 r = (out[i]-any_point);
 	r.Normalize();
 
-	// reconstruct orthonormal basis
+	// Reconstruct orthonormal basis
+	// XXX use Gram Schmidt for increased robustness
 	IfcVector3 u = r ^ nor;
 	u.Normalize();
 
@@ -599,7 +607,8 @@ out:
 }
 
 // ------------------------------------------------------------------------------------------------
-bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std::vector<IfcVector3>& nors, TempMesh& curmesh)
+bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std::vector<IfcVector3>& nors, 
+	TempMesh& curmesh)
 {
 	std::vector<IfcVector3>& out = curmesh.verts;
 
@@ -607,7 +616,12 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std:
 
 	// Try to derive a solid base plane within the current surface for use as 
 	// working coordinate system. 
-	const IfcMatrix3& m = DerivePlaneCoordinateSpace(curmesh);
+	bool ok;
+	const IfcMatrix3& m = DerivePlaneCoordinateSpace(curmesh, ok);
+	if (!ok) {
+		return false;
+	}
+
 	const IfcMatrix3 minv = IfcMatrix3(m).Inverse();
 	const IfcVector3& nor = IfcVector3(m.c1, m.c2, m.c3);
 
@@ -1397,7 +1411,11 @@ bool TryAddOpenings_Quadrulate(std::vector<TempOpening>& openings,
 
 	// Try to derive a solid base plane within the current surface for use as 
 	// working coordinate system. 
-	IfcMatrix4 m = IfcMatrix4(DerivePlaneCoordinateSpace(curmesh));
+	bool ok;
+	IfcMatrix4 m = IfcMatrix4(DerivePlaneCoordinateSpace(curmesh,ok));
+	if(!ok) {
+		return false;
+	}
 	const IfcVector3& nor = IfcVector3(m.c1, m.c2, m.c3);
 
 	IfcFloat coord = -1;
@@ -1924,8 +1942,6 @@ void ProcessBooleanExtrudedAreaSolidDifference(const IfcExtrudedAreaSolid* as, T
 		vit += pcount;
 	}
 
-	
-
 	IFCImporter::LogDebug("generating CSG geometry by geometric difference to a solid (IfcExtrudedAreaSolid)");
 }