Selaa lähdekoodia

- Ifc: further improvements to opening caps algorithm.

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@1329 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
aramis_acg 13 vuotta sitten
vanhempi
commit
3f38d91e88
1 muutettua tiedostoa jossa 58 lisäystä ja 12 poistoa
  1. 58 12
      code/IFCGeometry.cpp

+ 58 - 12
code/IFCGeometry.cpp

@@ -1282,15 +1282,25 @@ void CloseWindows(const ContourVector& contours, const IfcMatrix4& minv,
 
 			// XXX this algorithm is really a bit inefficient - both in terms
 			// of constant factor and of asymptotic runtime.
-			size_t vstart;
-			for (ContourVector::value_type::const_iterator cit = cbegin; cit != cend; ++cit) {
+			size_t vstart = curmesh.verts.size();
+			bool outer_border = false;
+			IfcVector2 last_proj_point;
+
+			const IfcFloat border_epsilon_upper = static_cast<IfcFloat>(1-1e-4);
+			const IfcFloat border_epsilon_lower = static_cast<IfcFloat>(1e-4);
 
+			bool start_is_outer_border = false;
+
+			for (ContourVector::value_type::const_iterator cit = cbegin; cit != cend; ++cit) {
 				const IfcVector2& proj_point = *cit;
-				const IfcVector3& world_point = minv * IfcVector3(proj_point.x,proj_point.y,0.0f);
 
+				// Locate the closest opposite point. This should be a good heuristic to
+				// connect only the points that are really intended to be connected.
 				IfcFloat best = static_cast<IfcFloat>(1e10);
 				IfcVector3 bestv;
 
+				const IfcVector3& world_point = minv * IfcVector3(proj_point.x,proj_point.y,0.0f);
+
 				BOOST_FOREACH(const TempOpening* opening, refs) {
 					BOOST_FOREACH(const IfcVector3& other, opening->wallPoints) {
 						const IfcFloat sqdist = (world_point - other).SquareLength();
@@ -1301,23 +1311,59 @@ void CloseWindows(const ContourVector& contours, const IfcMatrix4& minv,
 					}
 				}
 
-				if (cit == cbegin) {
-					vstart = curmesh.verts.size();
-				}
+				// Check if this connection is along the outer boundary of the projection
+				// plane. In such a case we better drop it because such 'edges' should
+				// not have any geometry to close them (think of door openings).
+				bool drop_this_edge = false;
+				if (proj_point.x <= border_epsilon_lower || proj_point.x >= border_epsilon_upper ||
+					proj_point.y <= border_epsilon_lower || proj_point.y >= border_epsilon_upper) {
 
-				curmesh.verts.push_back(world_point);
-				curmesh.verts.push_back(bestv);
+					if (outer_border) {
+						ai_assert(cit != cbegin);
+						if (fabs((proj_point.x - last_proj_point.x) * (proj_point.y - last_proj_point.y)) < 1e-5f) {
+							drop_this_edge = true;
 
-				curmesh.vertcnt.push_back(4);
+							curmesh.verts.pop_back();
+							curmesh.verts.pop_back();
+						}
+					}
+					else if (cit == cbegin) {
+						start_is_outer_border = true;
+					}
+					outer_border = true;
+				}
+				else {
+					outer_border = false;
+				}
 
-				if (cit != cbegin) {
+				last_proj_point = proj_point;
 
+				if (!drop_this_edge) {
 					curmesh.verts.push_back(bestv);
 					curmesh.verts.push_back(world_point);
 
+					curmesh.vertcnt.push_back(4);
+				}
+
+				if (cit != cbegin) {
+					curmesh.verts.push_back(world_point);
+					curmesh.verts.push_back(bestv);
+
 					if (cit == cend - 1) {
-						curmesh.verts.push_back(curmesh.verts[vstart]);
-						curmesh.verts.push_back(curmesh.verts[vstart+1]);
+
+						// Check if the final connection (last to first element) is itself
+						// a border edge that needs to be dropped.
+						if (start_is_outer_border && outer_border &&
+							fabs((proj_point.x - (*cbegin).x) * (proj_point.y - (*cbegin).y)) < 1e-5f) {
+
+							curmesh.vertcnt.pop_back();
+							curmesh.verts.pop_back();
+							curmesh.verts.pop_back();
+						}
+						else {
+							curmesh.verts.push_back(curmesh.verts[vstart]);
+							curmesh.verts.push_back(curmesh.verts[vstart+1]);
+						}
 					}
 				}
 			}