From 2f5475d50ab83210742e45b1c07ac51305c55437 Mon Sep 17 00:00:00 2001 From: aramis_acg Date: Sat, 20 Oct 2012 23:18:48 +0000 Subject: [PATCH] - Ifc: [Quadrulation] use generalized matrix multiplication for projections. Add table to map from contours to the openings they originated from and from openings to the points that were generated from it. git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@1313 67173fc5-114c-0410-ac8e-9d2fd5bffc1f --- code/IFCGeometry.cpp | 76 +++++++++++++++++++++++++------------------- code/IFCUtil.h | 7 ++++ 2 files changed, 51 insertions(+), 32 deletions(-) diff --git a/code/IFCGeometry.cpp b/code/IFCGeometry.cpp index b21ecb74d..bbd81b5bd 100644 --- a/code/IFCGeometry.cpp +++ b/code/IFCGeometry.cpp @@ -67,7 +67,7 @@ namespace Assimp { #define one_vec (IfcVector2(static_cast(1.0),static_cast(1.0))) - bool TryAddOpenings_Quadrulate(const std::vector& openings, + bool TryAddOpenings_Quadrulate(std::vector& openings, const std::vector& nors, TempMesh& curmesh); @@ -1004,10 +1004,7 @@ void QuadrifyPart(const IfcVector2& pmin, const IfcVector2& pmax, XYSortedField& void InsertWindowContours(const std::vector< BoundingBox >& bbs, const std::vector< std::vector >& contours, const std::vector& openings, - const IfcMatrix3& minv, - const IfcVector2& scale, - const IfcVector2& offset, - IfcFloat coord, + const IfcMatrix4& minv, TempMesh& curmesh) { ai_assert(contours.size() == bbs.size()); @@ -1083,7 +1080,7 @@ void InsertWindowContours(const std::vector< BoundingBox >& bbs, if ((contour[a] - edge).SquareLength() > diag*diag*0.7) { continue; } - const IfcVector3 v3 = minv * IfcVector3(offset.x + contour[a].x * scale.x, offset.y + contour[a].y * scale.y, coord); + const IfcVector3 v3 = minv * IfcVector3(contour[a].x, contour[a].y, 0.0f); curmesh.verts.push_back(v3); } @@ -1105,7 +1102,7 @@ void InsertWindowContours(const std::vector< BoundingBox >& bbs, corner.y = bb.second.y; } - const IfcVector3 v3 = minv * IfcVector3(offset.x + corner.x * scale.x, offset.y + corner.y * scale.y,coord); + const IfcVector3 v3 = minv * IfcVector3(corner.x, corner.y, 0.0f); curmesh.verts.push_back(v3); } else if (cnt == 1) { @@ -1213,10 +1210,7 @@ void CleanupWindowContours(std::vector< std::vector >& contours) // ------------------------------------------------------------------------------------------------ void CleanupOuterContour(const std::vector& contour_flat, TempMesh& curmesh, - const IfcMatrix3& minv, - const IfcVector2& scale, - const IfcVector2& offset, - IfcFloat coord, + const IfcMatrix4& minv, const std::vector& outflat) { std::vector vold; @@ -1263,9 +1257,9 @@ void CleanupOuterContour(const std::vector& contour_flat, TempMesh& iold.push_back(ex.outer.size()); BOOST_FOREACH(const ClipperLib::IntPoint& point, ex.outer) { vold.push_back( minv * IfcVector3( - offset.x + from_int64(point.X) * scale.x, - offset.y + from_int64(point.Y) * scale.y, - coord)); + from_int64(point.X), + from_int64(point.Y), + 0.0f)); } } @@ -1284,7 +1278,7 @@ void CleanupOuterContour(const std::vector& contour_flat, TempMesh& iold.resize(outflat.size()/4,4); BOOST_FOREACH(const IfcVector2& vproj, outflat) { - const IfcVector3 v3 = minv * IfcVector3(offset.x + vproj.x * scale.x, offset.y + vproj.y * scale.y,coord); + const IfcVector3 v3 = minv * IfcVector3(vproj.x, vproj.y, static_cast(0.0)); vold.push_back(v3); } } @@ -1295,16 +1289,16 @@ void CleanupOuterContour(const std::vector& contour_flat, TempMesh& } // ------------------------------------------------------------------------------------------------ -bool TryAddOpenings_Quadrulate(const std::vector& openings, +bool TryAddOpenings_Quadrulate(std::vector& openings, const std::vector& nors, TempMesh& curmesh) { std::vector& out = curmesh.verts; + std::vector > contours_to_openings; // Try to derive a solid base plane within the current surface for use as // working coordinate system. - const IfcMatrix3& m = DerivePlaneCoordinateSpace(curmesh); - const IfcMatrix3& minv = IfcMatrix3(m).Inverse(); + IfcMatrix4 m = IfcMatrix4(DerivePlaneCoordinateSpace(curmesh)); const IfcVector3& nor = IfcVector3(m.c1, m.c2, m.c3); IfcFloat coord = -1; @@ -1334,10 +1328,8 @@ bool TryAddOpenings_Quadrulate(const std::vector& openings, contour_flat.push_back(IfcVector2(vv.x,vv.y)); } - // With the current code in DerivePlaneCoordinateSpace, - // vmin,vmax should always be the 0...1 rectangle (+- numeric inaccuracies) - // but here we really need this to be accurate, so normalize again. - + // Further improve the projection by mapping the entire working set into + // [0,1] range vmax -= vmin; BOOST_FOREACH(IfcVector2& vv, contour_flat) { vv.x = (vv.x - vmin.x) / vmax.x; @@ -1348,15 +1340,26 @@ bool TryAddOpenings_Quadrulate(const std::vector& openings, vv = std::min(vv,one_vec); } - // project all openings into the coordinate system defined by the p+sv*tu plane - // and compute bounding boxes for them + IfcMatrix4 mult; + mult.a1 = static_cast(1.0) / vmax.x; + mult.b2 = static_cast(1.0) / vmax.y; + + mult.a4 = -vmin.x * mult.a1; + mult.b4 = -vmin.y * mult.b2; + mult.c4 = -coord; + m = mult * m; + + // Obtain inverse transform for getting back + const IfcMatrix4& minv = IfcMatrix4(m).Inverse(); + + // Compute bounding boxes for the projections of all openings std::vector< BoundingBox > bbs; std::vector< std::vector > contours; size_t c = 0; - BOOST_FOREACH(const TempOpening& t,openings) { - std::vector profile_verts = t.profileMesh->verts; - std::vector profile_vertcnts = t.profileMesh->vertcnt; + BOOST_FOREACH(TempOpening& opening,openings) { + std::vector profile_verts = opening.profileMesh->verts; + std::vector profile_vertcnts = opening.profileMesh->vertcnt; if(profile_verts.size() <= 2) { continue; } @@ -1385,8 +1388,8 @@ bool TryAddOpenings_Quadrulate(const std::vector& openings, IfcVector2 vv(v.x, v.y); // rescale - vv.x = (vv.x - vmin.x) / vmax.x; - vv.y = (vv.y - vmin.y) / vmax.y; + //vv.x = (vv.x - vmin.x) / vmax.x; + //vv.y = (vv.y - vmin.y) / vmax.y; vv = std::max(vv,IfcVector2()); vv = std::min(vv,one_vec); @@ -1403,6 +1406,7 @@ bool TryAddOpenings_Quadrulate(const std::vector& openings, } BoundingBox bb = BoundingBox(vpmin,vpmax); + std::vector joined_openings(1, &opening); // see if this BB intersects any other, in which case we could not use the Quadrify() // algorithm and would revert to Poly2Tri only. @@ -1445,6 +1449,10 @@ bool TryAddOpenings_Quadrulate(const std::vector& openings, bb.first = std::min(bb.first, ibb.first); bb.second = std::max(bb.second, ibb.second); + std::vector& t = contours_to_openings[std::distance(bbs.begin(),it)]; + joined_openings.insert(joined_openings.end(), t.begin(), t.end()); + + contours_to_openings.erase(contours_to_openings.begin() + std::distance(bbs.begin(),it)); contours.erase(contours.begin() + std::distance(bbs.begin(),it)); it = bbs.erase(it); continue; @@ -1454,6 +1462,10 @@ bool TryAddOpenings_Quadrulate(const std::vector& openings, } if(!contour.empty()) { + contours_to_openings.push_back(std::vector( + joined_openings.begin(), + joined_openings.end())); + contours.push_back(contour); bbs.push_back(bb); } @@ -1476,10 +1488,10 @@ bool TryAddOpenings_Quadrulate(const std::vector& openings, QuadrifyPart(IfcVector2(0.f,0.f),IfcVector2(1.f,1.f),field,bbs,outflat); ai_assert(!(outflat.size() % 4)); - CleanupOuterContour(contour_flat, curmesh, minv, vmax, vmin, coord, outflat); + CleanupOuterContour(contour_flat, curmesh, minv,outflat); CleanupWindowContours(contours); - InsertWindowContours(bbs,contours,openings, minv,vmax, vmin, coord, curmesh); - + InsertWindowContours(bbs,contours,openings, minv,curmesh); + //CloseWindows(contours, minv,contours_to_openings, curmesh); return true; } diff --git a/code/IFCUtil.h b/code/IFCUtil.h index fb9d21eb2..517e5d3c1 100644 --- a/code/IFCUtil.h +++ b/code/IFCUtil.h @@ -80,6 +80,13 @@ struct TempOpening IfcVector3 extrusionDir; boost::shared_ptr profileMesh; + // list of points generated for this opening. This is used to + // create connections between two opposing holes created + // from a single opening instance (two because walls tend to + // have two sides). If !empty(), the other side of the wall + // has already been processed. + std::vector wallPoints; + // ------------------------------------------------------------------------------ TempOpening() : solid()