- Ifc: experimental code to connect window holes, commented by default.
git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@1314 67173fc5-114c-0410-ac8e-9d2fd5bffc1fpull/6/merge
parent
2f5475d50a
commit
71fb04849c
|
@ -1000,9 +1000,11 @@ void QuadrifyPart(const IfcVector2& pmin, const IfcVector2& pmax, XYSortedField&
|
|||
}
|
||||
}
|
||||
|
||||
typedef std::vector< std::vector<IfcVector2> > ContourVector;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void InsertWindowContours(const std::vector< BoundingBox >& bbs,
|
||||
const std::vector< std::vector<IfcVector2> >& contours,
|
||||
const ContourVector& contours,
|
||||
const std::vector<TempOpening>& openings,
|
||||
const IfcMatrix4& minv,
|
||||
TempMesh& curmesh)
|
||||
|
@ -1013,6 +1015,9 @@ void InsertWindowContours(const std::vector< BoundingBox >& bbs,
|
|||
for(size_t i = 0; i < contours.size();++i) {
|
||||
const BoundingBox& bb = bbs[i];
|
||||
const std::vector<IfcVector2>& contour = contours[i];
|
||||
if(contour.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// check if we need to do it at all - many windows just fit perfectly into their quadratic holes,
|
||||
// i.e. their contours *are* already their bounding boxes.
|
||||
|
@ -1160,7 +1165,7 @@ void MergeWindowContours (const std::vector<IfcVector2>& a,
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void CleanupWindowContours(std::vector< std::vector<IfcVector2> >& contours)
|
||||
void CleanupWindowContours(ContourVector& contours)
|
||||
{
|
||||
std::vector<IfcVector2> scratch;
|
||||
|
||||
|
@ -1288,13 +1293,103 @@ void CleanupOuterContour(const std::vector<IfcVector2>& contour_flat, TempMesh&
|
|||
std::swap(iold,curmesh.vertcnt);
|
||||
}
|
||||
|
||||
typedef std::vector<TempOpening*> OpeningRefs;
|
||||
typedef std::vector<OpeningRefs > OpeningRefVector;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void CloseWindows(const ContourVector& contours, const IfcMatrix4& minv,
|
||||
OpeningRefVector contours_to_openings,
|
||||
TempMesh& curmesh)
|
||||
{
|
||||
// For all contour points, check if one of the assigned openings does
|
||||
// already have points assigned to it. In this case, assume this is
|
||||
// the second side of the wall and generate connections between
|
||||
// the two holes in order to close the window margin.
|
||||
|
||||
// All this gets complicated by the fact that contours may pertain to
|
||||
// multiple openings. The code is based on the assumption that this
|
||||
// relationship is identical on both sides of the wall. If this is
|
||||
// not the case, wrong geometry may be generated.
|
||||
for (ContourVector::const_iterator it = contours.begin(), end = contours.end(); it != end; ++it) {
|
||||
if ((*it).empty()) {
|
||||
continue;
|
||||
}
|
||||
OpeningRefs& refs = contours_to_openings[std::distance(contours.begin(), it)];
|
||||
|
||||
bool has_other_side = false;
|
||||
BOOST_FOREACH(const TempOpening* opening, refs) {
|
||||
if(!opening->wallPoints.empty()) {
|
||||
has_other_side = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const ContourVector::value_type::const_iterator cbegin = (*it).begin(), cend = (*it).end();
|
||||
|
||||
if (has_other_side) {
|
||||
// XXX this algorithm is really a bit inefficient - both in terms
|
||||
// of constant factor and of asymptotic runtime.
|
||||
std::vector<IfcVector3>::const_iterator vstart;
|
||||
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);
|
||||
|
||||
unsigned int i = 0;
|
||||
IfcFloat best = static_cast<IfcFloat>(1e10);
|
||||
IfcVector3 bestv;
|
||||
|
||||
BOOST_FOREACH(const TempOpening* opening, refs) {
|
||||
BOOST_FOREACH(const IfcVector3& other, opening->wallPoints) {
|
||||
const IfcFloat sqdist = (world_point - other).SquareLength();
|
||||
if (sqdist < best) {
|
||||
bestv = other;
|
||||
best = sqdist;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
curmesh.verts.push_back(world_point);
|
||||
curmesh.verts.push_back(bestv);
|
||||
|
||||
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(*(vstart));
|
||||
curmesh.verts.push_back(*(vstart+1));
|
||||
}
|
||||
}
|
||||
else {
|
||||
vstart = curmesh.verts.end() - 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
BOOST_FOREACH(TempOpening* opening, refs) {
|
||||
opening->wallPoints.reserve(opening->wallPoints.capacity() + (*it).size());
|
||||
for (ContourVector::value_type::const_iterator cit = cbegin; cit != cend; ++cit) {
|
||||
|
||||
const IfcVector2& proj_point = *cit;
|
||||
opening->wallPoints.push_back(minv * IfcVector3(proj_point.x,proj_point.y,0.0f));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool TryAddOpenings_Quadrulate(std::vector<TempOpening>& openings,
|
||||
const std::vector<IfcVector3>& nors,
|
||||
TempMesh& curmesh)
|
||||
{
|
||||
std::vector<IfcVector3>& out = curmesh.verts;
|
||||
std::vector<std::vector<TempOpening*> > contours_to_openings;
|
||||
OpeningRefVector contours_to_openings;
|
||||
|
||||
// Try to derive a solid base plane within the current surface for use as
|
||||
// working coordinate system.
|
||||
|
@ -1354,7 +1449,7 @@ bool TryAddOpenings_Quadrulate(std::vector<TempOpening>& openings,
|
|||
|
||||
// Compute bounding boxes for the projections of all openings
|
||||
std::vector< BoundingBox > bbs;
|
||||
std::vector< std::vector<IfcVector2> > contours;
|
||||
ContourVector contours;
|
||||
|
||||
size_t c = 0;
|
||||
BOOST_FOREACH(TempOpening& opening,openings) {
|
||||
|
@ -1387,10 +1482,7 @@ bool TryAddOpenings_Quadrulate(std::vector<TempOpening>& openings,
|
|||
const IfcVector3& v = m * x;
|
||||
IfcVector2 vv(v.x, v.y);
|
||||
|
||||
// rescale
|
||||
//vv.x = (vv.x - vmin.x) / vmax.x;
|
||||
//vv.y = (vv.y - vmin.y) / vmax.y;
|
||||
|
||||
// sanity rounding
|
||||
vv = std::max(vv,IfcVector2());
|
||||
vv = std::min(vv,one_vec);
|
||||
|
||||
|
@ -1491,7 +1583,12 @@ bool TryAddOpenings_Quadrulate(std::vector<TempOpening>& openings,
|
|||
CleanupOuterContour(contour_flat, curmesh, minv,outflat);
|
||||
CleanupWindowContours(contours);
|
||||
InsertWindowContours(bbs,contours,openings, minv,curmesh);
|
||||
//CloseWindows(contours, minv,contours_to_openings, curmesh);
|
||||
|
||||
// this should connect the window openings on both sides of the wall,
|
||||
// but it produces lots of artifacts which are not resolved yet.
|
||||
// Most of all, it makes all cases in which adjacent openings are
|
||||
// not correctly merged together glaringly obvious.
|
||||
//CloseWindows(contours, minv, contours_to_openings, curmesh);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1615,7 +1712,6 @@ void ProcessExtrudedAreaSolid(const IfcExtrudedAreaSolid& solid, TempMesh& resul
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if(openings && ((sides_with_openings != 2 && sides_with_openings) || (sides_with_v_openings != 2 && sides_with_v_openings))) {
|
||||
IFCImporter::LogWarn("failed to resolve all openings, presumably their topology is not supported by Assimp");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue