- Ifc: further improvements to opening caps algorithm.

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@1329 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
pull/6/merge
aramis_acg 2012-11-03 00:43:28 +00:00
parent 1553bd91f6
commit 3f38d91e88
1 changed files with 59 additions and 13 deletions

View File

@ -1282,15 +1282,25 @@ void CloseWindows(const ContourVector& contours, const IfcMatrix4& minv,
// XXX this algorithm is really a bit inefficient - both in terms // XXX this algorithm is really a bit inefficient - both in terms
// of constant factor and of asymptotic runtime. // of constant factor and of asymptotic runtime.
size_t vstart; 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) { for (ContourVector::value_type::const_iterator cit = cbegin; cit != cend; ++cit) {
const IfcVector2& proj_point = *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); IfcFloat best = static_cast<IfcFloat>(1e10);
IfcVector3 bestv; 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 TempOpening* opening, refs) {
BOOST_FOREACH(const IfcVector3& other, opening->wallPoints) { BOOST_FOREACH(const IfcVector3& other, opening->wallPoints) {
const IfcFloat sqdist = (world_point - other).SquareLength(); const IfcFloat sqdist = (world_point - other).SquareLength();
@ -1301,23 +1311,59 @@ void CloseWindows(const ContourVector& contours, const IfcMatrix4& minv,
} }
} }
if (cit == cbegin) { // Check if this connection is along the outer boundary of the projection
vstart = curmesh.verts.size(); // 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) {
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.verts.pop_back();
curmesh.verts.pop_back();
}
}
else if (cit == cbegin) {
start_is_outer_border = true;
}
outer_border = true;
}
else {
outer_border = false;
} }
curmesh.verts.push_back(world_point); last_proj_point = proj_point;
curmesh.verts.push_back(bestv);
curmesh.vertcnt.push_back(4);
if (cit != cbegin) {
if (!drop_this_edge) {
curmesh.verts.push_back(bestv); curmesh.verts.push_back(bestv);
curmesh.verts.push_back(world_point); 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) { 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]);
}
} }
} }
} }