- Ifc: since overlapping opening bounding boxes cause lots of trouble, we now try to avoid them in a subset of all cases. This is possible whenever two openings overlap in a way that their bounding boxes can easily be made disjunct by differentiating the polygons.

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@1335 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
pull/12/head
aramis_acg 2012-11-17 02:04:53 +00:00
parent 6d3cedc0b1
commit e3e8c92546
1 changed files with 77 additions and 5 deletions

View File

@ -1089,6 +1089,8 @@ void MergeWindowContours (const std::vector<IfcVector2>& a,
const std::vector<IfcVector2>& b,
ClipperLib::ExPolygons& out)
{
out.clear();
ClipperLib::Clipper clipper;
ClipperLib::Polygon clip;
@ -1115,6 +1117,40 @@ void MergeWindowContours (const std::vector<IfcVector2>& a,
clipper.Execute(ClipperLib::ctUnion, out,ClipperLib::pftNonZero,ClipperLib::pftNonZero);
}
// ------------------------------------------------------------------------------------------------
// Subtract a from b
void MakeDisjunctWindowContours (const std::vector<IfcVector2>& a,
const std::vector<IfcVector2>& b,
ClipperLib::ExPolygons& out)
{
out.clear();
ClipperLib::Clipper clipper;
ClipperLib::Polygon clip;
BOOST_FOREACH(const IfcVector2& pip, a) {
clip.push_back(ClipperLib::IntPoint( to_int64(pip.x), to_int64(pip.y) ));
}
if (ClipperLib::Orientation(clip)) {
std::reverse(clip.begin(), clip.end());
}
clipper.AddPolygon(clip, ClipperLib::ptClip);
clip.clear();
BOOST_FOREACH(const IfcVector2& pip, b) {
clip.push_back(ClipperLib::IntPoint( to_int64(pip.x), to_int64(pip.y) ));
}
if (ClipperLib::Orientation(clip)) {
std::reverse(clip.begin(), clip.end());
}
clipper.AddPolygon(clip, ClipperLib::ptSubject);
clipper.Execute(ClipperLib::ctDifference, out,ClipperLib::pftNonZero,ClipperLib::pftNonZero);
}
// ------------------------------------------------------------------------------------------------
void CleanupWindowContours(ContourVector& contours)
{
@ -1580,17 +1616,53 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
if (ibb.first.x <= bb.second.x && ibb.second.x >= bb.first.x &&
ibb.first.y <= bb.second.y && ibb.second.y >= bb.first.y) {
// Take these two contours and try to merge them. If they overlap (which
// should not happen, but in fact happens-in-the-real-world [tm] ),
// resume using a single contour and a single bounding box.
const std::vector<IfcVector2>& other = contours[std::distance(bbs.begin(),it)];
ClipperLib::ExPolygons poly;
// First check whether subtracting the old contour (to which ibb belongs)
// from the new contour (to which bb belongs) yields an updated bb which
// no longer overlaps ibb
MakeDisjunctWindowContours(other, temp_contour, poly);
if(poly.size() == 1) {
IfcVector2 newbb_min, newbb_max;
MinMaxChooser<IfcVector2>()(newbb_min, newbb_max);
BOOST_FOREACH(const ClipperLib::IntPoint& point, poly[0].outer) {
IfcVector2 vv = IfcVector2( from_int64(point.X), from_int64(point.Y));
// sanity rounding
vv = std::max(vv,IfcVector2());
vv = std::min(vv,one_vec);
newbb_min = std::min(newbb_min,vv);
newbb_max = std::max(newbb_max,vv);
}
if (!(ibb.first.x <= newbb_max.x && ibb.second.x >= newbb_min.x &&
ibb.first.y <= newbb_max.y && ibb.second.y >= newbb_min.y)) {
// Good guy bounding box
bb = BoundingBox(newbb_min,newbb_max);
temp_contour.clear();
BOOST_FOREACH(const ClipperLib::IntPoint& point, poly[0].outer) {
const IfcVector2& vv = IfcVector2( from_int64(point.X), from_int64(point.Y));
temp_contour.push_back(vv);
}
continue;
}
}
// Take these two overlapping contours and try to merge them. If they
// overlap (which should not happen, but in fact happens-in-the-real-
// world [tm] ), resume using a single contour and a single bounding box.
MergeWindowContours(temp_contour, other, poly);
// TODO: Commented because it causes more visible artifacts than
// it solves.
if (false && poly.size() > 1) {
if (poly.size() > 1) {
IFCImporter::LogWarn("cannot use quadrify algorithm to generate wall openings due to "
"bounding box overlaps, using poly2tri fallback method");
return TryAddOpenings_Poly2Tri(openings, nors, curmesh);