From f507994299b0fbbb2277295bb5a0857b6bdf4ac7 Mon Sep 17 00:00:00 2001 From: aramis_acg Date: Wed, 19 Dec 2012 02:24:06 +0000 Subject: [PATCH] - Ifc: vastly improved algorithm for fixing up window caps. git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@1345 67173fc5-114c-0410-ac8e-9d2fd5bffc1f --- code/IFCGeometry.cpp | 243 ++-- workspaces/vc9/assimp.vcproj | 2594 +++++++++++++++++----------------- 2 files changed, 1457 insertions(+), 1380 deletions(-) diff --git a/code/IFCGeometry.cpp b/code/IFCGeometry.cpp index 09505d813..03b8d4f80 100644 --- a/code/IFCGeometry.cpp +++ b/code/IFCGeometry.cpp @@ -956,11 +956,13 @@ void QuadrifyPart(const IfcVector2& pmin, const IfcVector2& pmax, XYSortedField& } typedef std::vector Contour; +typedef std::vector SkipList; // should probably use int for performance reasons struct ProjectedWindowContour { Contour contour; BoundingBox bb; + SkipList skiplist; ProjectedWindowContour(const Contour& contour, const BoundingBox& bb) @@ -976,6 +978,10 @@ struct ProjectedWindowContour void FlagInvalid() { contour.clear(); } + + void PrepareSkiplist() { + skiplist.resize(contour.size(),false); + } }; typedef std::vector< ProjectedWindowContour > ContourVector; @@ -1382,47 +1388,65 @@ bool IntersectingLineSegments(const IfcVector2& n0, const IfcVector2& n1, IfcVector2& out0, IfcVector2& out1) { const IfcVector2& m0_to_m1 = m1 - m0; - const IfcVector2& m0_to_n1 = n1 - m0; const IfcVector2& n0_to_n1 = n1 - n0; + + const IfcVector2& n0_to_m0 = m0 - n0; + const IfcVector2& n1_to_m1 = m1 - n1; + const IfcVector2& n0_to_m1 = m1 - n0; - const IfcFloat m0_to_m1_len = m0_to_m1.SquareLength(); - const IfcFloat m0_to_n1_len = m0_to_n1.SquareLength(); - const IfcFloat n0_to_n1_len = n0_to_n1.SquareLength(); - const IfcFloat n0_to_m1_len = n0_to_m1.SquareLength(); + const IfcFloat e = 1e-5f; - if (m0_to_m1_len < m0_to_n1_len) { + if (!(n0_to_m0.SquareLength() < e*e || fabs(n0_to_m0 * n0_to_n1) / (n0_to_m0.Length() * n0_to_n1.Length()) > 1-1e-5 )) { return false; } - if (n0_to_n1_len < n0_to_m1_len) { + if (!(n1_to_m1.SquareLength() < e*e || fabs(n1_to_m1 * n0_to_n1) / (n1_to_m1.Length() * n0_to_n1.Length()) > 1-1e-5 )) { return false; } - const IfcFloat epsilon = 1e-5f; - if (fabs((m0_to_m1 * n0_to_n1) - sqrt(m0_to_m1_len) * sqrt(n0_to_n1_len)) > epsilon) { + IfcFloat s0; + IfcFloat s1; + if(fabs(n0_to_n1.x) > e) { + ai_assert(fabs(n0_to_m0.x) > e); + s0 = n0_to_m0.x / n0_to_n1.x; + s1 = n0_to_m1.x / n0_to_n1.x; + } + else { + ai_assert(fabs(n0_to_n1.y) > e); + s0 = n0_to_m0.y / n0_to_n1.y; + s1 = n0_to_m1.y / n0_to_n1.y; + } + + if (s1 < s0) { + std::swap(s1,s0); + } + + s0 = std::max(0.0,s0); + s1 = std::max(0.0,s1); + + s0 = std::min(1.0,s0); + s1 = std::min(1.0,s1); + + if (fabs(s1-s0) < e) { return false; } - if (fabs((m0_to_m1 * m0_to_n1) - sqrt(m0_to_m1_len) * sqrt(m0_to_n1_len)) > epsilon) { - return false; - } - - // XXX this condition is probably redundant (or at least a check against > 0 is sufficient) - if (fabs((n0_to_n1 * n0_to_m1) - sqrt(n0_to_n1_len) * sqrt(n0_to_m1_len)) > epsilon) { - return false; - } - - // determine intersection points + out0 = n0 + s0 * n0_to_n1; + out1 = n0 + s1 * n0_to_n1; return true; } // ------------------------------------------------------------------------------------------------ -void FindAdjacentContours(const ContourVector::const_iterator current, const ContourVector& contours) +void FindAdjacentContours(ContourVector::iterator current, const ContourVector& contours) { const BoundingBox& bb = (*current).bb; + // What is to be done here is to populate the skip lists for the contour + // and to add necessary padding points when needed. + SkipList& skiplist = (*current).skiplist; + // First step to find possible adjacent contours is to check for adjacent bounding // boxes. If the bounding boxes are not adjacent, the contours lines cannot possibly be. for (ContourVector::const_iterator it = contours.begin(), end = contours.end(); it != end; ++it) { @@ -1446,7 +1470,7 @@ void FindAdjacentContours(const ContourVector::const_iterator current, const Con // world Ifc files it will not matter since most windows that // are adjacent to each others are rectangular anyway. - const Contour& ncontour = (*current).contour; + Contour& ncontour = (*current).contour; const Contour& mcontour = (*it).contour; for (size_t n = 0, nend = ncontour.size(); n < nend; ++n) { @@ -1454,12 +1478,28 @@ void FindAdjacentContours(const ContourVector::const_iterator current, const Con const IfcVector2& n1 = ncontour[(n+1) % ncontour.size()]; for (size_t m = 0, mend = mcontour.size(); m < nend; ++m) { - const IfcVector2& m0 = ncontour[m]; - const IfcVector2& m1 = ncontour[(m+1) % mcontour.size()]; + const IfcVector2& m0 = mcontour[m]; + const IfcVector2& m1 = mcontour[(m+1) % mcontour.size()]; IfcVector2 isect0, isect1; if (IntersectingLineSegments(n0,n1, m0, m1, isect0, isect1)) { - // Find intersection range + + if ((isect0 - n0).SquareLength() > 1e-5) { + ++n; + + ncontour.insert(ncontour.begin() + n, isect0); + skiplist.insert(skiplist.begin() + n, true); + } + else { + skiplist[n] = true; + } + + if ((isect1 - n1).SquareLength() > 1e-5) { + ++n; + + ncontour.insert(ncontour.begin() + n, isect1); + skiplist.insert(skiplist.begin() + n, false); + } } } } @@ -1468,7 +1508,59 @@ void FindAdjacentContours(const ContourVector::const_iterator current, const Con } // ------------------------------------------------------------------------------------------------ -void CloseWindows(const ContourVector& contours, +void FindBorderContours(ContourVector::iterator current) +{ + const IfcFloat border_epsilon_upper = static_cast(1-1e-4); + const IfcFloat border_epsilon_lower = static_cast(1e-4); + const IfcFloat dot_point_epsilon = static_cast(1e-5); + + bool outer_border = false; + bool start_on_outer_border = false; + + SkipList& skiplist = (*current).skiplist; + IfcVector2 last_proj_point; + + const Contour::const_iterator cbegin = (*current).contour.begin(), cend = (*current).contour.end(); + + for (Contour::const_iterator cit = cbegin; cit != cend; ++cit) { + const IfcVector2& proj_point = *cit; + + // 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). + 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)) < dot_point_epsilon) { + skiplist[std::distance(cbegin, cit) - 1] = true; + } + } + else if (cit == cbegin) { + start_on_outer_border = true; + } + + outer_border = true; + } + else { + outer_border = false; + } + + last_proj_point = proj_point; + } + + // handle first segment + if (outer_border && start_on_outer_border) { + const IfcVector2& proj_point = *cbegin; + if (fabs((proj_point.x - last_proj_point.x) * (proj_point.y - last_proj_point.y)) < dot_point_epsilon) { + skiplist[0] = true; + } + } +} + +// ------------------------------------------------------------------------------------------------ +void CloseWindows(ContourVector& contours, const IfcMatrix4& minv, OpeningRefVector contours_to_openings, TempMesh& curmesh) @@ -1483,7 +1575,7 @@ void CloseWindows(const ContourVector& contours, // The code is based on the assumption that this happens symmetrically // on both sides of the wall. If it doesn't (which would be a bug anyway) // wrong geometry may be generated. - for (ContourVector::const_iterator it = contours.begin(), end = contours.end(); it != end; ++it) { + for (ContourVector::iterator it = contours.begin(), end = contours.end(); it != end; ++it) { if ((*it).IsInvalid()) { continue; } @@ -1498,8 +1590,18 @@ void CloseWindows(const ContourVector& contours, } ContourRefVector adjacent_contours; - FindAdjacentContours(it, contours); + // prepare a skiplist for this contour. The skiplist is used to + // eliminate unwanted contour lines for adjacent windows and + // those bordering the outer frame. + (*it).PrepareSkiplist(); + + FindAdjacentContours(it, contours); + FindBorderContours(it); + + ai_assert((*it).skiplist.size() == (*it).contour.size()); + + SkipList::const_iterator skipbegin = (*it).skiplist.begin(), skipend = (*it).skiplist.end(); const Contour::const_iterator cbegin = (*it).contour.begin(), cend = (*it).contour.end(); if (has_other_side) { @@ -1509,16 +1611,13 @@ void CloseWindows(const ContourVector& contours, // XXX this algorithm is really a bit inefficient - both in terms // of constant factor and of asymptotic runtime. size_t vstart = curmesh.verts.size(); - bool outer_border = false; - IfcVector2 last_proj_point; - IfcVector3 last_diff; + std::vector::const_iterator skipit = skipbegin; - const IfcFloat border_epsilon_upper = static_cast(1-1e-4); - const IfcFloat border_epsilon_lower = static_cast(1e-4); + IfcVector3 start0; + IfcVector3 start1; - bool start_is_outer_border = false; - - for (Contour::const_iterator cit = cbegin; cit != cend; ++cit) { + bool drop_this_edge = false; + for (Contour::const_iterator cit = cbegin; cit != cend; ++cit, drop_this_edge = *skipit++) { const IfcVector2& proj_point = *cit; // Locate the closest opposite point. This should be a good heuristic to @@ -1538,64 +1637,42 @@ void CloseWindows(const ContourVector& contours, } } - // 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) { - - 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; - } - - last_proj_point = proj_point; - IfcVector3 diff = bestv - world_point; diff.Normalize(); - if (!drop_this_edge) { - curmesh.verts.push_back(bestv); - curmesh.verts.push_back(world_point); + if (drop_this_edge) { + curmesh.verts.pop_back(); + curmesh.verts.pop_back(); + } + else { + curmesh.verts.push_back(cit == cbegin ? world_point : bestv); + curmesh.verts.push_back(cit == cbegin ? bestv : world_point); curmesh.vertcnt.push_back(4); } - last_diff = diff; + if (cit == cbegin) { + start0 = world_point; + start1 = bestv; + continue; + } - if (cit != cbegin) { - curmesh.verts.push_back(world_point); - curmesh.verts.push_back(bestv); + curmesh.verts.push_back(world_point); + curmesh.verts.push_back(bestv); - if (cit == cend - 1) { + if (cit == cend - 1) { + drop_this_edge = *skipit; - // 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]); - } + // Check if the final connection (last to first element) is itself + // a border edge that needs to be dropped. + if (drop_this_edge) { + curmesh.vertcnt.pop_back(); + curmesh.verts.pop_back(); + curmesh.verts.pop_back(); + } + else { + curmesh.verts.push_back(start1); + curmesh.verts.push_back(start0); } } } diff --git a/workspaces/vc9/assimp.vcproj b/workspaces/vc9/assimp.vcproj index 5a1b92338..0b026dbff 100644 --- a/workspaces/vc9/assimp.vcproj +++ b/workspaces/vc9/assimp.vcproj @@ -82,68 +82,6 @@ Name="VCPostBuildEventTool" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -2219,14 +2211,6 @@ UsePrecompiledHeader="0" /> - - - @@ -2251,6 +2235,22 @@ UsePrecompiledHeader="0" /> + + + + + + @@ -2385,14 +2385,6 @@ PrecompiledHeaderThrough="AssimpPCH.h" /> - - - @@ -2420,14 +2412,6 @@ PrecompiledHeaderThrough="AssimpPCH.h" /> - - - @@ -2455,6 +2439,22 @@ PrecompiledHeaderThrough="AssimpPCH.h" /> + + + + + + @@ -2762,14 +2762,6 @@ UsePrecompiledHeader="0" /> - - - @@ -2778,14 +2770,6 @@ UsePrecompiledHeader="0" /> - - - @@ -2794,14 +2778,6 @@ UsePrecompiledHeader="0" /> - - - @@ -2810,14 +2786,6 @@ UsePrecompiledHeader="0" /> - - - @@ -2826,14 +2794,6 @@ UsePrecompiledHeader="0" /> - - - @@ -2842,14 +2802,6 @@ UsePrecompiledHeader="0" /> - - - @@ -2859,7 +2811,7 @@ /> + + + + + + + + + + + + + + + + + + - - - @@ -2922,14 +2914,6 @@ UsePrecompiledHeader="0" /> - - - @@ -2938,14 +2922,6 @@ UsePrecompiledHeader="0" /> - - - @@ -2954,14 +2930,6 @@ UsePrecompiledHeader="0" /> - - - @@ -2970,14 +2938,6 @@ UsePrecompiledHeader="0" /> - - - @@ -2986,14 +2946,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3003,7 +2955,7 @@ /> + + + + + + + + + + + + + + + + + + - - - @@ -3054,14 +3046,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3070,14 +3054,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3086,14 +3062,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3102,14 +3070,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3118,14 +3078,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3135,7 +3087,7 @@ /> + + + + + + + + + + + + + + + + + + - - - @@ -3194,14 +3186,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3210,14 +3194,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3226,14 +3202,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3242,14 +3210,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3258,14 +3218,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3275,7 +3227,7 @@ /> + + + + + + + + + + + + + + + + + + - - - @@ -3334,14 +3326,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3350,14 +3334,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3366,14 +3342,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3382,14 +3350,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3398,14 +3358,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3415,7 +3367,7 @@ /> + + + + + + + + + + + + + + + + + + - - - @@ -3470,14 +3462,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3486,14 +3470,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3502,14 +3478,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3518,14 +3486,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3534,14 +3494,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3551,7 +3503,7 @@ /> + + + + + + + + + + + + + + + + + + - - - @@ -3606,14 +3598,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3622,14 +3606,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3638,14 +3614,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3654,14 +3622,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3670,14 +3630,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3687,7 +3639,7 @@ /> + + + + + + + + + + + + + + + + + + - - - @@ -3742,14 +3734,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3758,14 +3742,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3774,14 +3750,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3790,14 +3758,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3806,14 +3766,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3823,7 +3775,7 @@ /> + + + + + + + + + + + + + + + + + + - - - @@ -3890,14 +3882,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3906,14 +3890,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3922,14 +3898,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3938,14 +3906,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3954,14 +3914,6 @@ UsePrecompiledHeader="0" /> - - - @@ -3971,7 +3923,7 @@ /> + + + + + + + + + + + + + + + + + + - - - @@ -4030,14 +4022,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4046,14 +4030,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4062,14 +4038,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4078,14 +4046,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4094,14 +4054,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4111,7 +4063,7 @@ /> + + + + + + + + + + + + + + + + + + - - - @@ -4170,14 +4162,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4186,14 +4170,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4202,14 +4178,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4218,14 +4186,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4234,14 +4194,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4251,7 +4203,7 @@ /> + + + + + + + + + + + + + + + + + + - - - @@ -4306,14 +4298,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4322,14 +4306,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4338,14 +4314,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4354,14 +4322,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4370,14 +4330,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4387,7 +4339,7 @@ /> + + + + + + + + + + + + + + + + + + - - - @@ -4446,14 +4438,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4462,14 +4446,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4478,14 +4454,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4494,14 +4462,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4510,14 +4470,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4527,7 +4479,7 @@ /> + + + + + + + + + + + + + + + + + + - - - @@ -4582,14 +4574,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4598,14 +4582,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4614,14 +4590,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4630,14 +4598,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4646,14 +4606,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4663,7 +4615,7 @@ /> + + + + + + + + + + + + + + + + + + - - - @@ -4718,14 +4710,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4734,14 +4718,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4750,14 +4726,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4766,14 +4734,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4782,14 +4742,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4799,7 +4751,7 @@ /> + + + + + + + + + + + + + + + + + + - - - @@ -4862,14 +4854,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4878,14 +4862,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4894,14 +4870,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4910,14 +4878,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4926,14 +4886,6 @@ UsePrecompiledHeader="0" /> - - - @@ -4943,7 +4895,7 @@ /> + + + + + + + + + + + + + + + + + +