Fix the build

pull/5220/head
Kim Kulling 2023-09-06 13:45:17 +02:00
parent 4de723d497
commit 9834a6aa7d
2 changed files with 104 additions and 156 deletions

View File

@ -38,13 +38,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
/** @file IFCOpenings.cpp /// @file IFCOpenings.cpp
* @brief Implements a subset of Ifc CSG operations for pouring /// @brief Implements a subset of Ifc CSG operations for pouring
* holes for windows and doors into walls. /// holes for windows and doors into walls.
*/
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER #ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
#include "IFCUtil.h" #include "IFCUtil.h"
#include "Common/PolyTools.h" #include "Common/PolyTools.h"
#include "PostProcessing/ProcessHelper.h" #include "PostProcessing/ProcessHelper.h"
@ -53,9 +52,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# include <poly2tri/poly2tri.h> # include <poly2tri/poly2tri.h>
# include <polyclipping/clipper.hpp> # include <polyclipping/clipper.hpp>
#else #else
# include "../contrib/poly2tri/poly2tri/poly2tri.h" # include "contrib/poly2tri/poly2tri/poly2tri.h"
# include "../contrib/clipper/clipper.hpp" # include "contrib/clipper/clipper.hpp"
#endif #endif // ASSIMP_USE_HUNTER
#include <deque> #include <deque>
#include <forward_list> #include <forward_list>
@ -63,32 +62,33 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <utility> #include <utility>
namespace Assimp { namespace Assimp {
namespace IFC { namespace IFC {
using ClipperLib::ulong64; using ClipperLib::ulong64;
// XXX use full -+ range ...
const ClipperLib::long64 max_ulong64 = 1518500249; // clipper.cpp / hiRange var
//#define to_int64(p) (static_cast<ulong64>( std::max( 0., std::min( static_cast<IfcFloat>((p)), 1.) ) * max_ulong64 )) // XXX use full -+ range ...
#define to_int64(p) (static_cast<ulong64>(static_cast<IfcFloat>((p) ) * max_ulong64 )) const ClipperLib::long64 max_ulong64 = 1518500249; // clipper.cpp / hiRange var
#define from_int64(p) (static_cast<IfcFloat>((p)) / max_ulong64)
#define one_vec (IfcVector2(static_cast<IfcFloat>(1.0),static_cast<IfcFloat>(1.0)))
inline ulong64 to_int64(IfcFloat p) {
return (static_cast<ulong64>(static_cast<IfcFloat>((p) ) * max_ulong64 ));
}
// fallback method to generate wall openings inline IfcFloat from_int64(ulong64 p) {
bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings, return (static_cast<IfcFloat>((p)) / max_ulong64);
TempMesh& curmesh); }
const IfcVector2 one_vec(IfcVector2(static_cast<IfcFloat>(1.0),static_cast<IfcFloat>(1.0)));
typedef std::pair< IfcVector2, IfcVector2 > BoundingBox; // fallback method to generate wall openings
typedef std::map<IfcVector2,size_t,XYSorter> XYSortedField; bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings, TempMesh& curmesh);
using BoundingBox = std::pair< IfcVector2, IfcVector2 >;
using XYSortedField = std::map<IfcVector2,size_t,XYSorter>;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void QuadrifyPart(const IfcVector2& pmin, const IfcVector2& pmax, XYSortedField& field, void QuadrifyPart(const IfcVector2& pmin, const IfcVector2& pmax, XYSortedField& field,
const std::vector< BoundingBox >& bbs, const std::vector< BoundingBox >& bbs,
std::vector<IfcVector2>& out) std::vector<IfcVector2>& out) {
{
if (!(pmin.x-pmax.x) || !(pmin.y-pmax.y)) { if (!(pmin.x-pmax.x) || !(pmin.y-pmax.y)) {
return; return;
} }
@ -142,19 +142,12 @@ void QuadrifyPart(const IfcVector2& pmin, const IfcVector2& pmax, XYSortedField&
} }
if (bb.second.y > ylast) { if (bb.second.y > ylast) {
found = true; found = true;
const IfcFloat ys = std::max(bb.first.y,pmin.y), ye = std::min(bb.second.y,pmax.y); const IfcFloat ys = std::max(bb.first.y,pmin.y), ye = std::min(bb.second.y,pmax.y);
if (ys - ylast > 0.0f) { if (ys - ylast > 0.0f) {
QuadrifyPart( IfcVector2(xs,ylast), IfcVector2(xe,ys) ,field,bbs,out); QuadrifyPart( IfcVector2(xs,ylast), IfcVector2(xe,ys) ,field,bbs,out);
} }
// the following are the window vertices
/*wnd.push_back(IfcVector2(xs,ys));
wnd.push_back(IfcVector2(xs,ye));
wnd.push_back(IfcVector2(xe,ye));
wnd.push_back(IfcVector2(xe,ys));*/
ylast = ye; ylast = ye;
} }
} }
@ -176,23 +169,17 @@ void QuadrifyPart(const IfcVector2& pmin, const IfcVector2& pmax, XYSortedField&
} }
} }
typedef std::vector<IfcVector2> Contour; using Contour = std::vector<IfcVector2>;
typedef std::vector<bool> SkipList; // should probably use int for performance reasons using SkipList = std::vector<bool>; // should probably use int for performance reasons
struct ProjectedWindowContour struct ProjectedWindowContour {
{
Contour contour; Contour contour;
BoundingBox bb; BoundingBox bb;
SkipList skiplist; SkipList skiplist;
bool is_rectangular; bool is_rectangular;
ProjectedWindowContour(const Contour& contour, const BoundingBox& bb, bool is_rectangular)
ProjectedWindowContour(const Contour& contour, const BoundingBox& bb, bool is_rectangular) : contour(contour), bb(bb) , is_rectangular(is_rectangular) {}
: contour(contour)
, bb(bb)
, is_rectangular(is_rectangular)
{}
bool IsInvalid() const { bool IsInvalid() const {
return contour.empty(); return contour.empty();
@ -207,19 +194,17 @@ struct ProjectedWindowContour
} }
}; };
typedef std::vector< ProjectedWindowContour > ContourVector; using ContourVector = std::vector<ProjectedWindowContour>;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool BoundingBoxesOverlapping( const BoundingBox &ibb, const BoundingBox &bb ) static bool BoundingBoxesOverlapping( const BoundingBox &ibb, const BoundingBox &bb ) {
{
// count the '=' case as non-overlapping but as adjacent to each other // count the '=' case as non-overlapping but as adjacent to each other
return ibb.first.x < bb.second.x && ibb.second.x > bb.first.x && return ibb.first.x < bb.second.x && ibb.second.x > bb.first.x &&
ibb.first.y < bb.second.y && ibb.second.y > bb.first.y; ibb.first.y < bb.second.y && ibb.second.y > bb.first.y;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool IsDuplicateVertex(const IfcVector2& vv, const std::vector<IfcVector2>& temp_contour) static bool IsDuplicateVertex(const IfcVector2& vv, const std::vector<IfcVector2>& temp_contour) {
{
// sanity check for duplicate vertices // sanity check for duplicate vertices
for(const IfcVector2& cp : temp_contour) { for(const IfcVector2& cp : temp_contour) {
if ((cp-vv).SquareLength() < 1e-5f) { if ((cp-vv).SquareLength() < 1e-5f) {
@ -230,14 +215,13 @@ bool IsDuplicateVertex(const IfcVector2& vv, const std::vector<IfcVector2>& temp
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ExtractVerticesFromClipper(const ClipperLib::Polygon& poly, std::vector<IfcVector2>& temp_contour, void ExtractVerticesFromClipper(const ClipperLib::Path& poly, std::vector<IfcVector2>& temp_contour,
bool filter_duplicates = false) bool filter_duplicates = false) {
{
temp_contour.clear(); temp_contour.clear();
for(const ClipperLib::IntPoint& point : poly) { for(const ClipperLib::IntPoint& point : poly) {
IfcVector2 vv = IfcVector2( from_int64(point.X), from_int64(point.Y)); IfcVector2 vv = IfcVector2( from_int64(point.X), from_int64(point.Y));
vv = std::max(vv,IfcVector2()); vv = std::max(vv, IfcVector2());
vv = std::min(vv,one_vec); vv = std::min(vv, one_vec);
if (!filter_duplicates || !IsDuplicateVertex(vv, temp_contour)) { if (!filter_duplicates || !IsDuplicateVertex(vv, temp_contour)) {
temp_contour.push_back(vv); temp_contour.push_back(vv);
@ -246,13 +230,12 @@ void ExtractVerticesFromClipper(const ClipperLib::Polygon& poly, std::vector<Ifc
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
BoundingBox GetBoundingBox(const ClipperLib::Polygon& poly) BoundingBox GetBoundingBox(const ClipperLib::Path& poly) {
{
IfcVector2 newbb_min, newbb_max; IfcVector2 newbb_min, newbb_max;
MinMaxChooser<IfcVector2>()(newbb_min, newbb_max); MinMaxChooser<IfcVector2>()(newbb_min, newbb_max);
for(const ClipperLib::IntPoint& point : poly) { for (const ClipperLib::IntPoint& point : poly) {
IfcVector2 vv = IfcVector2( from_int64(point.X), from_int64(point.Y)); IfcVector2 vv = IfcVector2(from_int64(point.X), from_int64(point.Y));
// sanity rounding // sanity rounding
vv = std::max(vv,IfcVector2()); vv = std::max(vv,IfcVector2());
@ -265,12 +248,9 @@ BoundingBox GetBoundingBox(const ClipperLib::Polygon& poly)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void InsertWindowContours(const ContourVector& contours, void InsertWindowContours(const ContourVector& contours, const std::vector<TempOpening>& /*openings*/, TempMesh& curmesh) {
const std::vector<TempOpening>& /*openings*/,
TempMesh& curmesh)
{
// fix windows - we need to insert the real, polygonal shapes into the quadratic holes that we have now // fix windows - we need to insert the real, polygonal shapes into the quadratic holes that we have now
for(size_t i = 0; i < contours.size();++i) { for (size_t i = 0; i < contours.size(); ++i) {
const BoundingBox& bb = contours[i].bb; const BoundingBox& bb = contours[i].bb;
const std::vector<IfcVector2>& contour = contours[i].contour; const std::vector<IfcVector2>& contour = contours[i].contour;
if(contour.empty()) { if(contour.empty()) {
@ -287,8 +267,7 @@ void InsertWindowContours(const ContourVector& contours,
const std::set<IfcVector2,XYSorter>::const_iterator end = verts.end(); const std::set<IfcVector2,XYSorter>::const_iterator end = verts.end();
if (verts.find(bb.first)!=end && verts.find(bb.second)!=end if (verts.find(bb.first)!=end && verts.find(bb.second)!=end
&& verts.find(IfcVector2(bb.first.x,bb.second.y))!=end && verts.find(IfcVector2(bb.first.x,bb.second.y))!=end
&& verts.find(IfcVector2(bb.second.x,bb.first.y))!=end && verts.find(IfcVector2(bb.second.x,bb.first.y))!=end ) {
) {
continue; continue;
} }
} }
@ -313,8 +292,7 @@ void InsertWindowContours(const ContourVector& contours,
if (std::fabs(v.x-bb.first.x)<epsilon) { if (std::fabs(v.x-bb.first.x)<epsilon) {
edge.x = bb.first.x; edge.x = bb.first.x;
hit = true; hit = true;
} } else if (std::fabs(v.x-bb.second.x)<epsilon) {
else if (std::fabs(v.x-bb.second.x)<epsilon) {
edge.x = bb.second.x; edge.x = bb.second.x;
hit = true; hit = true;
} }
@ -322,8 +300,7 @@ void InsertWindowContours(const ContourVector& contours,
if (std::fabs(v.y-bb.first.y)<epsilon) { if (std::fabs(v.y-bb.first.y)<epsilon) {
edge.y = bb.first.y; edge.y = bb.first.y;
hit = true; hit = true;
} } else if (std::fabs(v.y-bb.second.y)<epsilon) {
else if (std::fabs(v.y-bb.second.y)<epsilon) {
edge.y = bb.second.y; edge.y = bb.second.y;
hit = true; hit = true;
} }
@ -347,26 +324,22 @@ void InsertWindowContours(const ContourVector& contours,
} }
if (edge != contour[last_hit]) { if (edge != contour[last_hit]) {
IfcVector2 corner = edge; IfcVector2 corner = edge;
if (std::fabs(contour[last_hit].x-bb.first.x)<epsilon) { if (std::fabs(contour[last_hit].x-bb.first.x)<epsilon) {
corner.x = bb.first.x; corner.x = bb.first.x;
} } else if (std::fabs(contour[last_hit].x-bb.second.x)<epsilon) {
else if (std::fabs(contour[last_hit].x-bb.second.x)<epsilon) {
corner.x = bb.second.x; corner.x = bb.second.x;
} }
if (std::fabs(contour[last_hit].y-bb.first.y)<epsilon) { if (std::fabs(contour[last_hit].y-bb.first.y)<epsilon) {
corner.y = bb.first.y; corner.y = bb.first.y;
} } else if (std::fabs(contour[last_hit].y-bb.second.y)<epsilon) {
else if (std::fabs(contour[last_hit].y-bb.second.y)<epsilon) {
corner.y = bb.second.y; corner.y = bb.second.y;
} }
curmesh.mVerts.emplace_back(corner.x, corner.y, 0.0f); curmesh.mVerts.emplace_back(corner.x, corner.y, 0.0f);
} } else if (cnt == 1) {
else if (cnt == 1) {
// avoid degenerate polygons (also known as lines or points) // avoid degenerate polygons (also known as lines or points)
curmesh.mVerts.erase(curmesh.mVerts.begin()+old,curmesh.mVerts.end()); curmesh.mVerts.erase(curmesh.mVerts.begin()+old,curmesh.mVerts.end());
} }
@ -378,8 +351,7 @@ void InsertWindowContours(const ContourVector& contours,
if (n == very_first_hit) { if (n == very_first_hit) {
break; break;
} }
} } else {
else {
very_first_hit = n; very_first_hit = n;
} }
@ -390,14 +362,11 @@ void InsertWindowContours(const ContourVector& contours,
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void MergeWindowContours (const std::vector<IfcVector2>& a, void MergeWindowContours (const std::vector<IfcVector2>& a, const std::vector<IfcVector2>& b, ClipperLib::Paths& out) {
const std::vector<IfcVector2>& b,
ClipperLib::ExPolygons& out)
{
out.clear(); out.clear();
ClipperLib::Clipper clipper; ClipperLib::Clipper clipper;
ClipperLib::Polygon clip; ClipperLib::Path clip;
for(const IfcVector2& pip : a) { for(const IfcVector2& pip : a) {
clip.emplace_back(to_int64(pip.x), to_int64(pip.y)); clip.emplace_back(to_int64(pip.x), to_int64(pip.y));
@ -407,7 +376,7 @@ void MergeWindowContours (const std::vector<IfcVector2>& a,
std::reverse(clip.begin(), clip.end()); std::reverse(clip.begin(), clip.end());
} }
clipper.AddPolygon(clip, ClipperLib::ptSubject); clipper.AddPath(clip, ClipperLib::ptSubject, true);
clip.clear(); clip.clear();
for(const IfcVector2& pip : b) { for(const IfcVector2& pip : b) {
@ -418,7 +387,7 @@ void MergeWindowContours (const std::vector<IfcVector2>& a,
std::reverse(clip.begin(), clip.end()); std::reverse(clip.begin(), clip.end());
} }
clipper.AddPolygon(clip, ClipperLib::ptSubject); clipper.AddPath(clip, ClipperLib::ptSubject, true);
clipper.Execute(ClipperLib::ctUnion, out,ClipperLib::pftNonZero,ClipperLib::pftNonZero); clipper.Execute(ClipperLib::ctUnion, out,ClipperLib::pftNonZero,ClipperLib::pftNonZero);
} }
@ -426,12 +395,12 @@ void MergeWindowContours (const std::vector<IfcVector2>& a,
// Subtract a from b // Subtract a from b
void MakeDisjunctWindowContours (const std::vector<IfcVector2>& a, void MakeDisjunctWindowContours (const std::vector<IfcVector2>& a,
const std::vector<IfcVector2>& b, const std::vector<IfcVector2>& b,
ClipperLib::ExPolygons& out) ClipperLib::Paths& out)
{ {
out.clear(); out.clear();
ClipperLib::Clipper clipper; ClipperLib::Clipper clipper;
ClipperLib::Polygon clip; ClipperLib::Path clip;
for(const IfcVector2& pip : a) { for(const IfcVector2& pip : a) {
clip.emplace_back(to_int64(pip.x), to_int64(pip.y)); clip.emplace_back(to_int64(pip.x), to_int64(pip.y));
@ -441,7 +410,7 @@ void MakeDisjunctWindowContours (const std::vector<IfcVector2>& a,
std::reverse(clip.begin(), clip.end()); std::reverse(clip.begin(), clip.end());
} }
clipper.AddPolygon(clip, ClipperLib::ptClip); clipper.AddPath(clip, ClipperLib::ptClip, true);
clip.clear(); clip.clear();
for(const IfcVector2& pip : b) { for(const IfcVector2& pip : b) {
@ -452,30 +421,28 @@ void MakeDisjunctWindowContours (const std::vector<IfcVector2>& a,
std::reverse(clip.begin(), clip.end()); std::reverse(clip.begin(), clip.end());
} }
clipper.AddPolygon(clip, ClipperLib::ptSubject); clipper.AddPath(clip, ClipperLib::ptSubject, true);
clipper.Execute(ClipperLib::ctDifference, out,ClipperLib::pftNonZero,ClipperLib::pftNonZero); clipper.Execute(ClipperLib::ctDifference, out,ClipperLib::pftNonZero,ClipperLib::pftNonZero);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void CleanupWindowContour(ProjectedWindowContour& window) void CleanupWindowContour(ProjectedWindowContour& window) {
{
std::vector<IfcVector2> scratch; std::vector<IfcVector2> scratch;
std::vector<IfcVector2>& contour = window.contour; std::vector<IfcVector2>& contour = window.contour;
ClipperLib::Polygon subject; ClipperLib::Path subject;
ClipperLib::Clipper clipper; ClipperLib::Clipper clipper;
ClipperLib::ExPolygons clipped; ClipperLib::Paths clipped;
for(const IfcVector2& pip : contour) { for(const IfcVector2& pip : contour) {
subject.emplace_back(to_int64(pip.x), to_int64(pip.y)); subject.emplace_back(to_int64(pip.x), to_int64(pip.y));
} }
clipper.AddPolygon(subject,ClipperLib::ptSubject); clipper.AddPath(subject,ClipperLib::ptSubject, true);
clipper.Execute(ClipperLib::ctUnion,clipped,ClipperLib::pftNonZero,ClipperLib::pftNonZero); clipper.Execute(ClipperLib::ctUnion,clipped,ClipperLib::pftNonZero,ClipperLib::pftNonZero);
// This should yield only one polygon or something went wrong // This should yield only one polygon or something went wrong
if (clipped.size() != 1) { if (clipped.size() != 1) {
// Empty polygon? drop the contour altogether // Empty polygon? drop the contour altogether
if(clipped.empty()) { if(clipped.empty()) {
IFCImporter::LogError("error during polygon clipping, window contour is degenerate"); IFCImporter::LogError("error during polygon clipping, window contour is degenerate");
@ -487,7 +454,7 @@ void CleanupWindowContour(ProjectedWindowContour& window)
IFCImporter::LogError("error during polygon clipping, window contour is not convex"); IFCImporter::LogError("error during polygon clipping, window contour is not convex");
} }
ExtractVerticesFromClipper(clipped[0].outer, scratch); ExtractVerticesFromClipper(clipped[0], scratch);
// Assume the bounding box doesn't change during this operation // Assume the bounding box doesn't change during this operation
} }
@ -499,16 +466,14 @@ void CleanupWindowContours(ContourVector& contours)
for(ProjectedWindowContour& window : contours) { for(ProjectedWindowContour& window : contours) {
CleanupWindowContour(window); CleanupWindowContour(window);
} }
} } catch (const char* sx) {
catch (const char* sx) {
IFCImporter::LogError("error during polygon clipping, window shape may be wrong: (Clipper: " IFCImporter::LogError("error during polygon clipping, window shape may be wrong: (Clipper: "
+ std::string(sx) + ")"); + std::string(sx) + ")");
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void CleanupOuterContour(const std::vector<IfcVector2>& contour_flat, TempMesh& curmesh) void CleanupOuterContour(const std::vector<IfcVector2>& contour_flat, TempMesh& curmesh) {
{
std::vector<IfcVector3> vold; std::vector<IfcVector3> vold;
std::vector<unsigned int> iold; std::vector<unsigned int> iold;
@ -518,11 +483,11 @@ void CleanupOuterContour(const std::vector<IfcVector2>& contour_flat, TempMesh&
// Fix the outer contour using polyclipper // Fix the outer contour using polyclipper
try { try {
ClipperLib::Polygon subject; ClipperLib::Path subject;
ClipperLib::Clipper clipper; ClipperLib::Clipper clipper;
ClipperLib::ExPolygons clipped; ClipperLib::Paths clipped;
ClipperLib::Polygon clip; ClipperLib::Path clip;
clip.reserve(contour_flat.size()); clip.reserve(contour_flat.size());
for(const IfcVector2& pip : contour_flat) { for(const IfcVector2& pip : contour_flat) {
clip.emplace_back(to_int64(pip.x), to_int64(pip.y)); clip.emplace_back(to_int64(pip.x), to_int64(pip.y));
@ -551,18 +516,15 @@ void CleanupOuterContour(const std::vector<IfcVector2>& contour_flat, TempMesh&
std::reverse(subject.begin(), subject.end()); std::reverse(subject.begin(), subject.end());
} }
clipper.AddPolygon(subject,ClipperLib::ptSubject); clipper.AddPath(subject,ClipperLib::ptSubject, true);
clipper.AddPolygon(clip,ClipperLib::ptClip); clipper.AddPath(clip,ClipperLib::ptClip, true);
clipper.Execute(ClipperLib::ctIntersection,clipped,ClipperLib::pftNonZero,ClipperLib::pftNonZero); clipper.Execute(ClipperLib::ctIntersection,clipped,ClipperLib::pftNonZero,ClipperLib::pftNonZero);
for(const ClipperLib::ExPolygon& ex : clipped) { for(const ClipperLib::Path& ex : clipped) {
iold.push_back(static_cast<unsigned int>(ex.outer.size())); iold.push_back(static_cast<unsigned int>(ex.size()));
for(const ClipperLib::IntPoint& point : ex.outer) { for(const ClipperLib::IntPoint& point : ex) {
vold.emplace_back( vold.emplace_back(from_int64(point.X), from_int64(point.Y), 0.0f);
from_int64(point.X),
from_int64(point.Y),
0.0f);
} }
} }
@ -571,8 +533,7 @@ void CleanupOuterContour(const std::vector<IfcVector2>& contour_flat, TempMesh&
clipper.Clear(); clipper.Clear();
} }
} }
} } catch (const char* sx) {
catch (const char* sx) {
IFCImporter::LogError("Ifc: error during polygon clipping, wall contour line may be wrong: (Clipper: " IFCImporter::LogError("Ifc: error during polygon clipping, wall contour line may be wrong: (Clipper: "
+ std::string(sx) + ")"); + std::string(sx) + ")");
@ -593,8 +554,7 @@ typedef std::vector<std::pair<
> ContourRefVector; > ContourRefVector;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool BoundingBoxesAdjacent(const BoundingBox& bb, const BoundingBox& ibb) bool BoundingBoxesAdjacent(const BoundingBox& bb, const BoundingBox& ibb) {
{
// TODO: I'm pretty sure there is a much more compact way to check this // TODO: I'm pretty sure there is a much more compact way to check this
const IfcFloat epsilon = Math::getEpsilon<float>(); const IfcFloat epsilon = Math::getEpsilon<float>();
return (std::fabs(bb.second.x - ibb.first.x) < epsilon && bb.first.y <= ibb.second.y && bb.second.y >= ibb.first.y) || return (std::fabs(bb.second.x - ibb.first.x) < epsilon && bb.first.y <= ibb.second.y && bb.second.y >= ibb.first.y) ||
@ -648,8 +608,7 @@ bool IntersectingLineSegments(const IfcVector2& n0, const IfcVector2& n1,
if (std::fabs(s1) == inf && std::fabs(n0_to_m1.x) < smalle) { if (std::fabs(s1) == inf && std::fabs(n0_to_m1.x) < smalle) {
s1 = 0.; s1 = 0.;
} }
} } else {
else {
s0 = n0_to_m0.y / n0_to_n1.y; s0 = n0_to_m0.y / n0_to_n1.y;
s1 = n0_to_m1.y / n0_to_n1.y; s1 = n0_to_m1.y / n0_to_n1.y;
@ -1318,7 +1277,7 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
} }
const std::vector<IfcVector2>& other = (*it).contour; const std::vector<IfcVector2>& other = (*it).contour;
ClipperLib::ExPolygons poly; ClipperLib::Paths poly;
// First check whether subtracting the old contour (to which ibb belongs) // First check whether subtracting the old contour (to which ibb belongs)
// from the new contour (to which bb belongs) yields an updated bb which // from the new contour (to which bb belongs) yields an updated bb which
@ -1326,12 +1285,12 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
MakeDisjunctWindowContours(other, temp_contour, poly); MakeDisjunctWindowContours(other, temp_contour, poly);
if(poly.size() == 1) { if(poly.size() == 1) {
const BoundingBox newbb = GetBoundingBox(poly[0].outer); const BoundingBox newbb = GetBoundingBox(poly[0]);
if (!BoundingBoxesOverlapping(ibb, newbb )) { if (!BoundingBoxesOverlapping(ibb, newbb )) {
// Good guy bounding box // Good guy bounding box
bb = newbb ; bb = newbb ;
ExtractVerticesFromClipper(poly[0].outer, temp_contour, false); ExtractVerticesFromClipper(poly[0], temp_contour, false);
continue; continue;
} }
} }
@ -1343,15 +1302,13 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
if (poly.size() > 1) { if (poly.size() > 1) {
return TryAddOpenings_Poly2Tri(openings, curmesh); return TryAddOpenings_Poly2Tri(openings, curmesh);
} } else if (poly.empty()) {
else if (poly.size() == 0) {
IFCImporter::LogWarn("ignoring duplicate opening"); IFCImporter::LogWarn("ignoring duplicate opening");
temp_contour.clear(); temp_contour.clear();
break; break;
} } else {
else {
IFCImporter::LogVerboseDebug("merging overlapping openings"); IFCImporter::LogVerboseDebug("merging overlapping openings");
ExtractVerticesFromClipper(poly[0].outer, temp_contour, false); ExtractVerticesFromClipper(poly[0], temp_contour, false);
// Generate the union of the bounding boxes // Generate the union of the bounding boxes
bb.first = std::min(bb.first, ibb.first); bb.first = std::min(bb.first, ibb.first);
@ -1494,7 +1451,6 @@ static void logSegment(std::pair<IfcVector2,IfcVector2> segment) {
std::vector<std::vector<IfcVector2>> GetContoursInPlane3D(const std::shared_ptr<TempMesh>& mesh,IfcMatrix3 planeSpace, std::vector<std::vector<IfcVector2>> GetContoursInPlane3D(const std::shared_ptr<TempMesh>& mesh,IfcMatrix3 planeSpace,
IfcFloat planeOffset) { IfcFloat planeOffset) {
{ {
std::stringstream msg; std::stringstream msg;
msg << "GetContoursInPlane3D: planeSpace is \n"; msg << "GetContoursInPlane3D: planeSpace is \n";
@ -1552,15 +1508,12 @@ std::vector<std::vector<IfcVector2>> GetContoursInPlane3D(const std::shared_ptr<
if(std::fabs(vn.z - planeOffset) < close) { if(std::fabs(vn.z - planeOffset) < close) {
// on the plane // on the plane
intersection = vn; intersection = vn;
} } else if((vn.z > planeOffset) != (vp.z > planeOffset)) {
else if((vn.z > planeOffset) != (vp.z > planeOffset))
{
// passes through the plane // passes through the plane
auto vdir = vn - vp; auto vdir = vn - vp;
auto scale = (planeOffset - vp.z) / vdir.z; auto scale = (planeOffset - vp.z) / vdir.z;
intersection = vp + scale * vdir; intersection = vp + scale * vdir;
} } else {
else {
// nowhere near - move on // nowhere near - move on
continue; continue;
} }
@ -1575,15 +1528,13 @@ std::vector<std::vector<IfcVector2>> GetContoursInPlane3D(const std::shared_ptr<
logSegment(s); logSegment(s);
lineSegments.push_back(s); lineSegments.push_back(s);
// next firstpoint should be this one // next firstpoint should be this one
} } else {
else {
// store the first intersection point // store the first intersection point
firstPoint.x = intersection.x; firstPoint.x = intersection.x;
firstPoint.y = intersection.y; firstPoint.y = intersection.y;
gotFirstPoint = true; gotFirstPoint = true;
} }
} } else {
else {
// now got the second point, so store the pair // now got the second point, so store the pair
IfcVector2 secondPoint(intersection.x,intersection.y); IfcVector2 secondPoint(intersection.x,intersection.y);
auto s = std::pair<IfcVector2,IfcVector2>(firstPoint,secondPoint); auto s = std::pair<IfcVector2,IfcVector2>(firstPoint,secondPoint);
@ -1771,15 +1722,13 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,
// If this happens then the projection must have been wrong. // If this happens then the projection must have been wrong.
ai_assert(vmax.Length()); ai_assert(vmax.Length());
ClipperLib::ExPolygons clipped; ClipperLib::Paths clipped;
ClipperLib::Polygons holes_union; ClipperLib::Paths holes_union;
IfcVector3 wall_extrusion; IfcVector3 wall_extrusion;
bool first = true; bool first = true;
try { try {
ClipperLib::Clipper clipper_holes; ClipperLib::Clipper clipper_holes;
for(const TempOpening& t : openings) { for(const TempOpening& t : openings) {
@ -1787,7 +1736,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,
for(auto& contour : contours) { for(auto& contour : contours) {
// scale to clipping space // scale to clipping space
ClipperLib::Polygon hole; ClipperLib::Path hole;
for(IfcVector2& pip : contour) { for(IfcVector2& pip : contour) {
pip.x = (pip.x - vmin.x) / vmax.x; pip.x = (pip.x - vmin.x) / vmax.x;
pip.y = (pip.y - vmin.y) / vmax.y; pip.y = (pip.y - vmin.y) / vmax.y;
@ -1806,7 +1755,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,
ClipperLib::OffsetPolygons(pol_temp,pol_temp2,5.0); ClipperLib::OffsetPolygons(pol_temp,pol_temp2,5.0);
hole = pol_temp2[0];*/ hole = pol_temp2[0];*/
clipper_holes.AddPolygon(hole,ClipperLib::ptSubject); clipper_holes.AddPath(hole,ClipperLib::ptSubject, true);
{ {
std::stringstream msg; std::stringstream msg;
msg << "- added polygon "; msg << "- added polygon ";
@ -1829,7 +1778,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,
// Now that we have the big union of all holes, subtract it from the outer contour // Now that we have the big union of all holes, subtract it from the outer contour
// to obtain the final polygon to feed into the triangulator. // to obtain the final polygon to feed into the triangulator.
{ {
ClipperLib::Polygon poly; ClipperLib::Path poly;
for(IfcVector2& pip : contour_flat) { for(IfcVector2& pip : contour_flat) {
pip.x = (pip.x - vmin.x) / vmax.x; pip.x = (pip.x - vmin.x) / vmax.x;
pip.y = (pip.y - vmin.y) / vmax.y; pip.y = (pip.y - vmin.y) / vmax.y;
@ -1841,16 +1790,15 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,
std::reverse(poly.begin(), poly.end()); std::reverse(poly.begin(), poly.end());
} }
clipper_holes.Clear(); clipper_holes.Clear();
clipper_holes.AddPolygon(poly,ClipperLib::ptSubject); clipper_holes.AddPath(poly,ClipperLib::ptSubject, true);
clipper_holes.AddPolygons(holes_union,ClipperLib::ptClip); clipper_holes.AddPaths(holes_union,ClipperLib::ptClip, true);
clipper_holes.Execute(ClipperLib::ctDifference,clipped, clipper_holes.Execute(ClipperLib::ctDifference,clipped,
ClipperLib::pftNonZero, ClipperLib::pftNonZero,
ClipperLib::pftNonZero); ClipperLib::pftNonZero);
} }
} } catch (const char* sx) {
catch (const char* sx) {
IFCImporter::LogError("Ifc: error during polygon clipping, skipping openings for this face: (Clipper: " IFCImporter::LogError("Ifc: error during polygon clipping, skipping openings for this face: (Clipper: "
+ std::string(sx) + ")"); + std::string(sx) + ")");
@ -1864,13 +1812,13 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,
old_vertcnt.swap(curmesh.mVertcnt); old_vertcnt.swap(curmesh.mVertcnt);
std::vector< std::vector<p2t::Point*> > contours; std::vector< std::vector<p2t::Point*> > contours;
for(ClipperLib::ExPolygon& clip : clipped) { for(ClipperLib::Path &clip : clipped) {
contours.clear(); contours.clear();
// Build the outer polygon contour line for feeding into poly2tri // Build the outer polygon contour line for feeding into poly2tri
std::vector<p2t::Point*> contour_points; std::vector<p2t::Point*> contour_points;
for(ClipperLib::IntPoint& point : clip.outer) { for(ClipperLib::IntPoint& point : clip) {
contour_points.push_back( new p2t::Point(from_int64(point.X), from_int64(point.Y)) ); contour_points.push_back( new p2t::Point(from_int64(point.X), from_int64(point.Y)) );
} }
@ -1890,7 +1838,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,
// Build the poly2tri inner contours for all holes we got from ClipperLib // Build the poly2tri inner contours for all holes we got from ClipperLib
for(ClipperLib::Polygon& opening : clip.holes) { for(ClipperLib::Path& opening : holes_union) {
contours.emplace_back(); contours.emplace_back();
std::vector<p2t::Point*>& contour = contours.back(); std::vector<p2t::Point*>& contour = contours.back();
@ -1945,12 +1893,11 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,
return result; return result;
} }
} // ! IFC
} // ! IFC
} // ! Assimp } // ! Assimp
#undef to_int64 #undef to_int64
#undef from_int64 #undef from_int64
#undef one_vec #undef one_vec
#endif #endif // ASSIMP_BUILD_NO_IFC_IMPORTER

View File

@ -718,7 +718,8 @@ void DisposeOutPts(OutPt*& pp)
inline void InitEdge(TEdge* e, TEdge* eNext, TEdge* ePrev, const IntPoint& Pt) inline void InitEdge(TEdge* e, TEdge* eNext, TEdge* ePrev, const IntPoint& Pt)
{ {
std::memset(e, 0, sizeof(TEdge)); *e = {};
//std::memset(e, 0, sizeof(TEdge));
e->Next = eNext; e->Next = eNext;
e->Prev = ePrev; e->Prev = ePrev;
e->Curr = Pt; e->Curr = Pt;
@ -4329,10 +4330,10 @@ double DistanceFromLineSqrd(
const IntPoint& pt, const IntPoint& ln1, const IntPoint& ln2) const IntPoint& pt, const IntPoint& ln1, const IntPoint& ln2)
{ {
//The equation of a line in general form (Ax + By + C = 0) //The equation of a line in general form (Ax + By + C = 0)
//given 2 points (x¹,y¹) & (x²,y²) is ... //given 2 points (x<EFBFBD>,y<>) & (x<>,y<>) is ...
//(y¹ - y²)x + (x² - x¹)y + (y² - y¹)x¹ - (x² - x¹)y¹ = 0 //(y<EFBFBD> - y<>)x + (x<> - x<>)y + (y<> - y<>)x<> - (x<> - x<>)y<> = 0
//A = (y¹ - y²); B = (x² - x¹); C = (y² - y¹)x¹ - (x² - x¹)y¹ //A = (y<EFBFBD> - y<>); B = (x<> - x<>); C = (y<> - y<>)x<> - (x<> - x<>)y<>
//perpendicular distance of point (x³,y³) = (Ax³ + By³ + C)/Sqrt(A² + B²) //perpendicular distance of point (x<EFBFBD>,y<>) = (Ax<41> + By<42> + C)/Sqrt(A<> + B<>)
//see http://en.wikipedia.org/wiki/Perpendicular_distance //see http://en.wikipedia.org/wiki/Perpendicular_distance
double A = double(ln1.Y - ln2.Y); double A = double(ln1.Y - ln2.Y);
double B = double(ln2.X - ln1.X); double B = double(ln2.X - ln1.X);