Mosfet80 clipper update (#5220)

* remove deprecated sprinf

* Update clipper
Updated Clipper to V6.4.2

* Fix the build

* Fix the build

* Disable hunter build

* Fix: Fix hided var.

* Fix invalid use of hunter enabled macro.

* Fix misconfig for hunter

* Disable removing contrib folder

* Update BlenderTessellator.h

* Remove Hunter-based includes

* Refactorings

* Remove final

* Update IFCCurve.cpp

* Update IFCCurve.cpp

---------

Co-authored-by: andrea <realeandrea@yahoo.it>
Co-authored-by: Kim Kulling <kim.kullingk@draeger.com>
pull/5225/head
Kim Kulling 2023-09-09 19:29:15 +02:00 committed by GitHub
parent 3cf7d28bc4
commit aa1996e143
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 4320 additions and 3238 deletions

View File

@ -74,12 +74,6 @@ jobs:
repository: cpp-pm/polly repository: cpp-pm/polly
path: cmake/polly path: cmake/polly
- name: Remove contrib directory for Hunter builds
if: contains(matrix.name, 'hunter')
uses: JesseTG/rm@v1.0.3
with:
path: contrib
- name: Cache DX SDK - name: Cache DX SDK
id: dxcache id: dxcache
if: contains(matrix.name, 'windows') if: contains(matrix.name, 'windows')

View File

@ -52,7 +52,6 @@ IF(ASSIMP_HUNTER_ENABLED)
URL "https://github.com/cpp-pm/hunter/archive/v0.24.17.tar.gz" URL "https://github.com/cpp-pm/hunter/archive/v0.24.17.tar.gz"
SHA1 "e6396699e414120e32557fe92db097b7655b760b" SHA1 "e6396699e414120e32557fe92db097b7655b760b"
) )
add_definitions(-DASSIMP_USE_HUNTER) add_definitions(-DASSIMP_USE_HUNTER)
ENDIF() ENDIF()
@ -201,12 +200,9 @@ SET (ASSIMP_VERSION ${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VER
SET (ASSIMP_SOVERSION 5) SET (ASSIMP_SOVERSION 5)
SET( ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used for uploading the sources" ) SET( ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used for uploading the sources" )
if(NOT ASSIMP_HUNTER_ENABLED)
# Enable C++17 support globally
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_C_STANDARD 99) set(CMAKE_C_STANDARD 99)
endif()
IF(NOT ASSIMP_IGNORE_GIT_HASH) IF(NOT ASSIMP_IGNORE_GIT_HASH)
# Get the current working branch # Get the current working branch
@ -254,8 +250,7 @@ IF( UNIX )
# Use GNUInstallDirs for Unix predefined directories # Use GNUInstallDirs for Unix predefined directories
INCLUDE(GNUInstallDirs) INCLUDE(GNUInstallDirs)
# Ensure that we do not run into issues like http://www.tcm.phy.cam.ac.uk/sw/inodes64.html on 32 bit linux # Ensure that we do not run into issues like http://www.tcm.phy.cam.ac.uk/sw/inodes64.html on 32 bit linux
IF( ${OPERATING_SYSTEM} MATCHES "Android") IF(NOT ${OPERATING_SYSTEM} MATCHES "Android")
ELSE()
IF ( CMAKE_SIZEOF_VOID_P EQUAL 4) # only necessary for 32-bit linux IF ( CMAKE_SIZEOF_VOID_P EQUAL 4) # only necessary for 32-bit linux
ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64 ) ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64 )
ENDIF() ENDIF()
@ -265,7 +260,6 @@ ENDIF()
# Grouped compiler settings ######################################## # Grouped compiler settings ########################################
IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT MINGW) IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT MINGW)
IF(NOT ASSIMP_HUNTER_ENABLED) IF(NOT ASSIMP_HUNTER_ENABLED)
SET(CMAKE_CXX_STANDARD 17)
SET(CMAKE_POSITION_INDEPENDENT_CODE ON) SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
ENDIF() ENDIF()
@ -302,7 +296,6 @@ ELSEIF(MSVC)
SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG:FULL /PDBALTPATH:%_PDB% /OPT:REF /OPT:ICF") SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG:FULL /PDBALTPATH:%_PDB% /OPT:REF /OPT:ICF")
ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
IF(NOT ASSIMP_HUNTER_ENABLED) IF(NOT ASSIMP_HUNTER_ENABLED)
SET(CMAKE_CXX_STANDARD 17)
SET(CMAKE_POSITION_INDEPENDENT_CODE ON) SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
ENDIF() ENDIF()
SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long ${CMAKE_CXX_FLAGS}" ) SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long ${CMAKE_CXX_FLAGS}" )
@ -332,12 +325,12 @@ IF ( IOS AND NOT ASSIMP_HUNTER_ENABLED)
ELSE() ELSE()
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode -O3") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode -O3")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -O3") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -O3")
# Experimental for pdb generation
ENDIF() ENDIF()
ENDIF() ENDIF()
IF (ASSIMP_COVERALLS) IF (ASSIMP_COVERALLS)
MESSAGE(STATUS "Coveralls enabled") MESSAGE(STATUS "Coveralls enabled")
INCLUDE(Coveralls) INCLUDE(Coveralls)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
@ -345,12 +338,14 @@ ENDIF()
IF (ASSIMP_ASAN) IF (ASSIMP_ASAN)
MESSAGE(STATUS "AddressSanitizer enabled") MESSAGE(STATUS "AddressSanitizer enabled")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")
ENDIF() ENDIF()
IF (ASSIMP_UBSAN) IF (ASSIMP_UBSAN)
MESSAGE(STATUS "Undefined Behavior sanitizer enabled") MESSAGE(STATUS "Undefined Behavior sanitizer enabled")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined,shift,shift-exponent,integer-divide-by-zero,unreachable,vla-bound,null,return,signed-integer-overflow,bounds,float-divide-by-zero,float-cast-overflow,nonnull-attribute,returns-nonnull-attribute,bool,enum,vptr,pointer-overflow,builtin -fno-sanitize-recover=all") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined,shift,shift-exponent,integer-divide-by-zero,unreachable,vla-bound,null,return,signed-integer-overflow,bounds,float-divide-by-zero,float-cast-overflow,nonnull-attribute,returns-nonnull-attribute,bool,enum,vptr,pointer-overflow,builtin -fno-sanitize-recover=all")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined,shift,shift-exponent,integer-divide-by-zero,unreachable,vla-bound,null,return,signed-integer-overflow,bounds,float-divide-by-zero,float-cast-overflow,nonnull-attribute,returns-nonnull-attribute,bool,enum,vptr,pointer-overflow,builtin -fno-sanitize-recover=all") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined,shift,shift-exponent,integer-divide-by-zero,unreachable,vla-bound,null,return,signed-integer-overflow,bounds,float-divide-by-zero,float-cast-overflow,nonnull-attribute,returns-nonnull-attribute,bool,enum,vptr,pointer-overflow,builtin -fno-sanitize-recover=all")
ENDIF() ENDIF()
@ -697,7 +692,6 @@ ELSE()
COMPONENT ${LIBASSIMP_COMPONENT} COMPONENT ${LIBASSIMP_COMPONENT}
INCLUDES DESTINATION include INCLUDES DESTINATION include
) )
ENDIF() ENDIF()
ENDIF() ENDIF()
ENDIF() ENDIF()

View File

@ -102,10 +102,6 @@ void Structure::Convert<CollectionObject>(
ReadFieldPtr<ErrorPolicy_Fail>(dest.next, "*next", db); ReadFieldPtr<ErrorPolicy_Fail>(dest.next, "*next", db);
{ {
//std::shared_ptr<CollectionObject> prev;
//ReadFieldPtr<ErrorPolicy_Fail>(prev, "*prev", db);
//dest.prev = prev.get();
std::shared_ptr<Object> ob; std::shared_ptr<Object> ob;
ReadFieldPtr<ErrorPolicy_Igno>(ob, "*ob", db); ReadFieldPtr<ErrorPolicy_Igno>(ob, "*ob", db);
dest.ob = ob.get(); dest.ob = ob.get();

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team Copyright (c) 2006-2022, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -40,10 +39,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
/** @file BlenderTessellator.cpp /// @file BlenderTessellator.cpp
* @brief A simple tessellation wrapper /// @brief A simple tessellation wrapper
*/
#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER #ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team Copyright (c) 2006-2022, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -144,11 +143,7 @@ namespace Assimp
#if ASSIMP_BLEND_WITH_POLY_2_TRI #if ASSIMP_BLEND_WITH_POLY_2_TRI
#ifdef ASSIMP_USE_HUNTER #include "contrib/poly2tri/poly2tri/poly2tri.h"
# include <poly2tri/poly2tri.h>
#else
# include "../contrib/poly2tri/poly2tri/poly2tri.h"
#endif
namespace Assimp namespace Assimp
{ {

View File

@ -38,9 +38,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
/** @file IFCBoolean.cpp /// @file IFCBoolean.cpp
* @brief Implements a subset of Ifc boolean operations /// @brief Implements a subset of Ifc boolean operations
*/
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER #ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
@ -48,7 +47,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "Common/PolyTools.h" #include "Common/PolyTools.h"
#include "PostProcessing/ProcessHelper.h" #include "PostProcessing/ProcessHelper.h"
#include <iterator> #include <iterator>
#include <tuple> #include <tuple>
#include <utility> #include <utility>
@ -67,8 +65,9 @@ bool IntersectSegmentPlane(const IfcVector3 &p, const IfcVector3 &n, const IfcVe
// if segment ends on plane, do not report a hit. We stay on that side until a following segment starting at this // if segment ends on plane, do not report a hit. We stay on that side until a following segment starting at this
// point leaves the plane through the other side // point leaves the plane through the other side
if (std::abs(dotOne + dotTwo) < ai_epsilon) if (std::abs(dotOne + dotTwo) < ai_epsilon) {
return false; return false;
}
// if segment starts on the plane, report a hit only if the end lies on the *other* side // if segment starts on the plane, report a hit only if the end lies on the *other* side
if (std::abs(dotTwo) < ai_epsilon) { if (std::abs(dotTwo) < ai_epsilon) {
@ -82,13 +81,15 @@ bool IntersectSegmentPlane(const IfcVector3 &p, const IfcVector3 &n, const IfcVe
// ignore if segment is parallel to plane and far away from it on either side // ignore if segment is parallel to plane and far away from it on either side
// Warning: if there's a few thousand of such segments which slowly accumulate beyond the epsilon, no hit would be registered // Warning: if there's a few thousand of such segments which slowly accumulate beyond the epsilon, no hit would be registered
if (std::abs(dotOne) < ai_epsilon) if (std::abs(dotOne) < ai_epsilon) {
return false; return false;
}
// t must be in [0..1] if the intersection point is within the given segment // t must be in [0..1] if the intersection point is within the given segment
const IfcFloat t = dotTwo / dotOne; const IfcFloat t = dotTwo / dotOne;
if (t > 1.0 || t < 0.0) if (t > 1.0 || t < 0.0) {
return false; return false;
}
out = e0 + t * seg; out = e0 + t * seg;
return true; return true;
@ -110,12 +111,14 @@ void FilterPolygon(std::vector<IfcVector3> &resultpoly) {
FuzzyVectorCompare fz(epsilon); FuzzyVectorCompare fz(epsilon);
std::vector<IfcVector3>::iterator e = std::unique(resultpoly.begin(), resultpoly.end(), fz); std::vector<IfcVector3>::iterator e = std::unique(resultpoly.begin(), resultpoly.end(), fz);
if (e != resultpoly.end()) if (e != resultpoly.end()) {
resultpoly.erase(e, resultpoly.end()); resultpoly.erase(e, resultpoly.end());
}
if (!resultpoly.empty() && fz(resultpoly.front(), resultpoly.back())) if (!resultpoly.empty() && fz(resultpoly.front(), resultpoly.back())) {
resultpoly.pop_back(); resultpoly.pop_back();
} }
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void WritePolygon(std::vector<IfcVector3> &resultpoly, TempMesh &result) { void WritePolygon(std::vector<IfcVector3> &resultpoly, TempMesh &result) {
@ -291,8 +294,9 @@ bool IntersectsBoundaryProfile(const IfcVector3 &e0, const IfcVector3 &e1, const
} }
// Line segment ends at boundary -> ignore any hit, it will be handled by possibly following segments // Line segment ends at boundary -> ignore any hit, it will be handled by possibly following segments
if (endsAtSegment && !halfOpen) if (endsAtSegment && !halfOpen) {
continue; continue;
}
// Line segment starts at boundary -> generate a hit only if following that line would change the INSIDE/OUTSIDE // Line segment starts at boundary -> generate a hit only if following that line would change the INSIDE/OUTSIDE
// state. This should catch the case where a connected set of segments has a point directly on the boundary, // state. This should catch the case where a connected set of segments has a point directly on the boundary,
@ -301,16 +305,18 @@ bool IntersectsBoundaryProfile(const IfcVector3 &e0, const IfcVector3 &e1, const
if (startsAtSegment) { if (startsAtSegment) {
IfcVector3 inside_dir = IfcVector3(b.y, -b.x, 0.0) * windingOrder; IfcVector3 inside_dir = IfcVector3(b.y, -b.x, 0.0) * windingOrder;
bool isGoingInside = (inside_dir * e) > 0.0; bool isGoingInside = (inside_dir * e) > 0.0;
if (isGoingInside == isStartAssumedInside) if (isGoingInside == isStartAssumedInside) {
continue; continue;
}
// only insert the point into the list if it is sufficiently far away from the previous intersection point. // only insert the point into the list if it is sufficiently far away from the previous intersection point.
// This way, we avoid duplicate detection if the intersection is directly on the vertex between two segments. // This way, we avoid duplicate detection if the intersection is directly on the vertex between two segments.
if (!intersect_results.empty() && intersect_results.back().first == i - 1) { if (!intersect_results.empty() && intersect_results.back().first == i - 1) {
const IfcVector3 diff = intersect_results.back().second - e0; const IfcVector3 diff = intersect_results.back().second - e0;
if (IfcVector2(diff.x, diff.y).SquareLength() < 1e-10) if (IfcVector2(diff.x, diff.y).SquareLength() < 1e-10) {
continue; continue;
} }
}
intersect_results.emplace_back(i, e0); intersect_results.emplace_back(i, e0);
continue; continue;
} }
@ -322,9 +328,10 @@ bool IntersectsBoundaryProfile(const IfcVector3 &e0, const IfcVector3 &e1, const
// This way, we avoid duplicate detection if the intersection is directly on the vertex between two segments. // This way, we avoid duplicate detection if the intersection is directly on the vertex between two segments.
if (!intersect_results.empty() && intersect_results.back().first == i - 1) { if (!intersect_results.empty() && intersect_results.back().first == i - 1) {
const IfcVector3 diff = intersect_results.back().second - p; const IfcVector3 diff = intersect_results.back().second - p;
if (IfcVector2(diff.x, diff.y).SquareLength() < 1e-10) if (IfcVector2(diff.x, diff.y).SquareLength() < 1e-10) {
continue; continue;
} }
}
intersect_results.emplace_back(i, p); intersect_results.emplace_back(i, p);
} }
} }
@ -662,7 +669,8 @@ void ProcessPolygonalBoundedBooleanHalfSpaceDifference(const Schema_2x3::IfcPoly
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ProcessBooleanExtrudedAreaSolidDifference(const Schema_2x3::IfcExtrudedAreaSolid *as, TempMesh &result, void ProcessBooleanExtrudedAreaSolidDifference(const Schema_2x3::IfcExtrudedAreaSolid *as,
TempMesh &result,
const TempMesh &first_operand, const TempMesh &first_operand,
ConversionData &conv) { ConversionData &conv) {
ai_assert(as != nullptr); ai_assert(as != nullptr);
@ -763,4 +771,4 @@ void ProcessBoolean(const Schema_2x3::IfcBooleanResult &boolean, TempMesh &resul
} // namespace IFC } // namespace IFC
} // namespace Assimp } // namespace Assimp
#endif #endif // ASSIMP_BUILD_NO_IFC_IMPORTER

View File

@ -39,15 +39,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
/** @file IFCProfile.cpp /// @file IFCProfile.cpp
* @brief Read profile and curves entities from IFC files /// @brief Read profile and curves entities from IFC files
*/
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER #ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
#include "IFCUtil.h" #include "IFCUtil.h"
namespace Assimp { namespace Assimp {
namespace IFC { namespace IFC {
namespace { namespace {
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
@ -56,8 +56,7 @@ namespace {
class Conic : public Curve { class Conic : public Curve {
public: public:
// -------------------------------------------------- // --------------------------------------------------
Conic(const Schema_2x3::IfcConic& entity, ConversionData& conv) Conic(const Schema_2x3::IfcConic& entity, ConversionData& conv) : Curve(entity,conv) {
: Curve(entity,conv) {
IfcMatrix4 trafo; IfcMatrix4 trafo;
ConvertAxisPlacement(trafo,*entity.Position,conv); ConvertAxisPlacement(trafo,*entity.Position,conv);
@ -69,12 +68,12 @@ public:
} }
// -------------------------------------------------- // --------------------------------------------------
bool IsClosed() const { bool IsClosed() const override {
return true; return true;
} }
// -------------------------------------------------- // --------------------------------------------------
size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const { size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const override {
ai_assert( InRange( a ) ); ai_assert( InRange( a ) );
ai_assert( InRange( b ) ); ai_assert( InRange( b ) );
@ -88,7 +87,7 @@ public:
} }
// -------------------------------------------------- // --------------------------------------------------
ParamRange GetParametricRange() const { ParamRange GetParametricRange() const override {
return std::make_pair(static_cast<IfcFloat>( 0. ), static_cast<IfcFloat>( AI_MATH_TWO_PI / conv.angle_scale )); return std::make_pair(static_cast<IfcFloat>( 0. ), static_cast<IfcFloat>( AI_MATH_TWO_PI / conv.angle_scale ));
} }
@ -102,14 +101,13 @@ protected:
class Circle : public Conic { class Circle : public Conic {
public: public:
// -------------------------------------------------- // --------------------------------------------------
Circle(const Schema_2x3::IfcCircle& entity, ConversionData& conv) Circle(const Schema_2x3::IfcCircle& entity, ConversionData& conv) : Conic(entity,conv) , entity(entity) {}
: Conic(entity,conv)
, entity(entity)
{
}
// -------------------------------------------------- // --------------------------------------------------
IfcVector3 Eval(IfcFloat u) const { ~Circle() override = default;
// --------------------------------------------------
IfcVector3 Eval(IfcFloat u) const override {
u = -conv.angle_scale * u; u = -conv.angle_scale * u;
return location + static_cast<IfcFloat>(entity.Radius)*(static_cast<IfcFloat>(std::cos(u))*p[0] + return location + static_cast<IfcFloat>(entity.Radius)*(static_cast<IfcFloat>(std::cos(u))*p[0] +
static_cast<IfcFloat>(std::sin(u))*p[1]); static_cast<IfcFloat>(std::sin(u))*p[1]);
@ -132,7 +130,7 @@ public:
} }
// -------------------------------------------------- // --------------------------------------------------
IfcVector3 Eval(IfcFloat u) const { IfcVector3 Eval(IfcFloat u) const override {
u = -conv.angle_scale * u; u = -conv.angle_scale * u;
return location + static_cast<IfcFloat>(entity.SemiAxis1)*static_cast<IfcFloat>(std::cos(u))*p[0] + return location + static_cast<IfcFloat>(entity.SemiAxis1)*static_cast<IfcFloat>(std::cos(u))*p[0] +
static_cast<IfcFloat>(entity.SemiAxis2)*static_cast<IfcFloat>(std::sin(u))*p[1]; static_cast<IfcFloat>(entity.SemiAxis2)*static_cast<IfcFloat>(std::sin(u))*p[1];
@ -155,17 +153,17 @@ public:
} }
// -------------------------------------------------- // --------------------------------------------------
bool IsClosed() const { bool IsClosed() const override {
return false; return false;
} }
// -------------------------------------------------- // --------------------------------------------------
IfcVector3 Eval(IfcFloat u) const { IfcVector3 Eval(IfcFloat u) const override {
return p + u*v; return p + u*v;
} }
// -------------------------------------------------- // --------------------------------------------------
size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const { size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const override {
ai_assert( InRange( a ) ); ai_assert( InRange( a ) );
ai_assert( InRange( b ) ); ai_assert( InRange( b ) );
// two points are always sufficient for a line segment // two points are always sufficient for a line segment
@ -174,7 +172,7 @@ public:
// -------------------------------------------------- // --------------------------------------------------
void SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const { void SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const override {
ai_assert( InRange( a ) ); ai_assert( InRange( a ) );
ai_assert( InRange( b ) ); ai_assert( InRange( b ) );
@ -188,7 +186,7 @@ public:
} }
// -------------------------------------------------- // --------------------------------------------------
ParamRange GetParametricRange() const { ParamRange GetParametricRange() const override {
const IfcFloat inf = std::numeric_limits<IfcFloat>::infinity(); const IfcFloat inf = std::numeric_limits<IfcFloat>::infinity();
return std::make_pair(-inf,+inf); return std::make_pair(-inf,+inf);
@ -234,7 +232,7 @@ public:
} }
// -------------------------------------------------- // --------------------------------------------------
IfcVector3 Eval(IfcFloat u) const { IfcVector3 Eval(IfcFloat u) const override {
if (curves.empty()) { if (curves.empty()) {
return IfcVector3(); return IfcVector3();
} }
@ -254,7 +252,7 @@ public:
} }
// -------------------------------------------------- // --------------------------------------------------
size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const { size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const override {
ai_assert( InRange( a ) ); ai_assert( InRange( a ) );
ai_assert( InRange( b ) ); ai_assert( InRange( b ) );
size_t cnt = 0; size_t cnt = 0;
@ -275,7 +273,7 @@ public:
} }
// -------------------------------------------------- // --------------------------------------------------
void SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const { void SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const override {
ai_assert( InRange( a ) ); ai_assert( InRange( a ) );
ai_assert( InRange( b ) ); ai_assert( InRange( b ) );
@ -293,7 +291,7 @@ public:
} }
// -------------------------------------------------- // --------------------------------------------------
ParamRange GetParametricRange() const { ParamRange GetParametricRange() const override {
return std::make_pair(static_cast<IfcFloat>( 0. ),total); return std::make_pair(static_cast<IfcFloat>( 0. ),total);
} }
@ -373,27 +371,27 @@ public:
} }
// -------------------------------------------------- // --------------------------------------------------
IfcVector3 Eval(IfcFloat p) const { IfcVector3 Eval(IfcFloat p) const override {
ai_assert(InRange(p)); ai_assert(InRange(p));
return base->Eval( TrimParam(p) ); return base->Eval( TrimParam(p) );
} }
// -------------------------------------------------- // --------------------------------------------------
size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const { size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const override {
ai_assert( InRange( a ) ); ai_assert( InRange( a ) );
ai_assert( InRange( b ) ); ai_assert( InRange( b ) );
return base->EstimateSampleCount(TrimParam(a),TrimParam(b)); return base->EstimateSampleCount(TrimParam(a),TrimParam(b));
} }
// -------------------------------------------------- // --------------------------------------------------
void SampleDiscrete(TempMesh& out,IfcFloat a,IfcFloat b) const { void SampleDiscrete(TempMesh& out,IfcFloat a,IfcFloat b) const override {
ai_assert(InRange(a)); ai_assert(InRange(a));
ai_assert(InRange(b)); ai_assert(InRange(b));
return base->SampleDiscrete(out,TrimParam(a),TrimParam(b)); return base->SampleDiscrete(out,TrimParam(a),TrimParam(b));
} }
// -------------------------------------------------- // --------------------------------------------------
ParamRange GetParametricRange() const { ParamRange GetParametricRange() const override {
return std::make_pair(static_cast<IfcFloat>( 0. ),maxval); return std::make_pair(static_cast<IfcFloat>( 0. ),maxval);
} }
@ -431,7 +429,7 @@ public:
} }
// -------------------------------------------------- // --------------------------------------------------
IfcVector3 Eval(IfcFloat p) const { IfcVector3 Eval(IfcFloat p) const override {
ai_assert(InRange(p)); ai_assert(InRange(p));
const size_t b = static_cast<size_t>(std::floor(p)); const size_t b = static_cast<size_t>(std::floor(p));
@ -444,14 +442,14 @@ public:
} }
// -------------------------------------------------- // --------------------------------------------------
size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const { size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const override {
ai_assert(InRange(a)); ai_assert(InRange(a));
ai_assert(InRange(b)); ai_assert(InRange(b));
return static_cast<size_t>( std::ceil(b) - std::floor(a) ); return static_cast<size_t>( std::ceil(b) - std::floor(a) );
} }
// -------------------------------------------------- // --------------------------------------------------
ParamRange GetParametricRange() const { ParamRange GetParametricRange() const override {
return std::make_pair(static_cast<IfcFloat>( 0. ),static_cast<IfcFloat>(points.size()-1)); return std::make_pair(static_cast<IfcFloat>( 0. ),static_cast<IfcFloat>(points.size()-1));
} }
@ -516,7 +514,7 @@ size_t Curve::EstimateSampleCount(IfcFloat a, IfcFloat b) const {
ai_assert( InRange( a ) ); ai_assert( InRange( a ) );
ai_assert( InRange( b ) ); ai_assert( InRange( b ) );
// arbitrary default value, deriving classes should supply better suited values // arbitrary default value, deriving classes should supply better-suited values
return 16; return 16;
} }

View File

@ -38,24 +38,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
/** @file IFCGeometry.cpp /// @file IFCGeometry.cpp
* @brief Geometry conversion and synthesis for IFC /// @brief Geometry conversion and synthesis for IFC
*/
#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"
#include "contrib/poly2tri/poly2tri/poly2tri.h"
#ifdef ASSIMP_USE_HUNTER #include "contrib/clipper/clipper.hpp"
# include <poly2tri/poly2tri.h>
# include <polyclipping/clipper.hpp>
#else
# include "../contrib/poly2tri/poly2tri/poly2tri.h"
# include "../contrib/clipper/clipper.hpp"
#endif
#include <iterator> #include <iterator>
#include <memory> #include <memory>
@ -65,8 +56,7 @@ namespace Assimp {
namespace IFC { namespace IFC {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool ProcessPolyloop(const Schema_2x3::IfcPolyLoop& loop, TempMesh& meshout, ConversionData& /*conv*/) bool ProcessPolyloop(const Schema_2x3::IfcPolyLoop& loop, TempMesh& meshout, ConversionData& /*conv*/) {
{
size_t cnt = 0; size_t cnt = 0;
for(const Schema_2x3::IfcCartesianPoint& c : loop.Polygon) { for(const Schema_2x3::IfcCartesianPoint& c : loop.Polygon) {
IfcVector3 tmp; IfcVector3 tmp;
@ -91,8 +81,7 @@ bool ProcessPolyloop(const Schema_2x3::IfcPolyLoop& loop, TempMesh& meshout, Con
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ProcessPolygonBoundaries(TempMesh& result, const TempMesh& inmesh, size_t master_bounds = (size_t)-1) void ProcessPolygonBoundaries(TempMesh& result, const TempMesh& inmesh, size_t master_bounds = (size_t)-1) {
{
// handle all trivial cases // handle all trivial cases
if(inmesh.mVertcnt.empty()) { if(inmesh.mVertcnt.empty()) {
return; return;
@ -127,8 +116,7 @@ void ProcessPolygonBoundaries(TempMesh& result, const TempMesh& inmesh, size_t m
if (master_bounds != (size_t)-1) { if (master_bounds != (size_t)-1) {
ai_assert(master_bounds < inmesh.mVertcnt.size()); ai_assert(master_bounds < inmesh.mVertcnt.size());
outer_polygon_it = begin + master_bounds; outer_polygon_it = begin + master_bounds;
} } else {
else {
for(iit = begin; iit != end; ++iit) { for(iit = begin; iit != end; ++iit) {
// find the polygon with the largest area and take it as the outer bound. // find the polygon with the largest area and take it as the outer bound.
IfcVector3& n = normals[std::distance(begin,iit)]; IfcVector3& n = normals[std::distance(begin,iit)];
@ -139,6 +127,7 @@ void ProcessPolygonBoundaries(TempMesh& result, const TempMesh& inmesh, size_t m
} }
} }
} }
if (outer_polygon_it == end) { if (outer_polygon_it == end) {
return; return;
} }
@ -205,40 +194,20 @@ void ProcessConnectedFaceSet(const Schema_2x3::IfcConnectedFaceSet& fset, TempMe
if(const Schema_2x3::IfcPolyLoop* const polyloop = bound.Bound->ToPtr<Schema_2x3::IfcPolyLoop>()) { if(const Schema_2x3::IfcPolyLoop* const polyloop = bound.Bound->ToPtr<Schema_2x3::IfcPolyLoop>()) {
if(ProcessPolyloop(*polyloop, meshout,conv)) { if(ProcessPolyloop(*polyloop, meshout,conv)) {
// The outer boundary is better determined by checking which // The outer boundary is better determined by checking which
// polygon covers the largest area. // polygon covers the largest area.
//if(bound.ToPtr<IfcFaceOuterBound>()) {
// ob = cnt;
//}
//++cnt;
} }
} } else {
else {
IFCImporter::LogWarn("skipping unknown IfcFaceBound entity, type is ", bound.Bound->GetClassName()); IFCImporter::LogWarn("skipping unknown IfcFaceBound entity, type is ", bound.Bound->GetClassName());
continue; continue;
} }
// And this, even though it is sometimes TRUE and sometimes FALSE,
// does not really improve results.
/*if(!IsTrue(bound.Orientation)) {
size_t c = 0;
for(unsigned int& c : meshout.vertcnt) {
std::reverse(result.verts.begin() + cnt,result.verts.begin() + cnt + c);
cnt += c;
}
}*/
} }
ProcessPolygonBoundaries(result, meshout); ProcessPolygonBoundaries(result, meshout);
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ProcessRevolvedAreaSolid(const Schema_2x3::IfcRevolvedAreaSolid& solid, TempMesh& result, ConversionData& conv) void ProcessRevolvedAreaSolid(const Schema_2x3::IfcRevolvedAreaSolid& solid, TempMesh& result, ConversionData& conv) {
{
TempMesh meshout; TempMesh meshout;
// first read the profile description // first read the profile description
@ -265,7 +234,8 @@ void ProcessRevolvedAreaSolid(const Schema_2x3::IfcRevolvedAreaSolid& solid, Tem
return; return;
} }
const unsigned int cnt_segments = std::max(2u,static_cast<unsigned int>(conv.settings.cylindricalTessellation * std::fabs(max_angle)/AI_MATH_HALF_PI_F)); const unsigned int cnt_segments =
std::max(2u,static_cast<unsigned int>(conv.settings.cylindricalTessellation * std::fabs(max_angle)/AI_MATH_HALF_PI_F));
const IfcFloat delta = max_angle/cnt_segments; const IfcFloat delta = max_angle/cnt_segments;
has_area = has_area && std::fabs(max_angle) < AI_MATH_TWO_PI_F*0.99; has_area = has_area && std::fabs(max_angle) < AI_MATH_TWO_PI_F*0.99;
@ -324,8 +294,9 @@ void ProcessRevolvedAreaSolid(const Schema_2x3::IfcRevolvedAreaSolid& solid, Tem
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ProcessSweptDiskSolid(const Schema_2x3::IfcSweptDiskSolid &solid, TempMesh& result, ConversionData& conv) void ProcessSweptDiskSolid(const Schema_2x3::IfcSweptDiskSolid &solid,
{ TempMesh& result,
ConversionData& conv) {
const Curve* const curve = Curve::Convert(*solid.Directrix, conv); const Curve* const curve = Curve::Convert(*solid.Directrix, conv);
if(!curve) { if(!curve) {
IFCImporter::LogError("failed to convert Directrix curve (IfcSweptDiskSolid)"); IFCImporter::LogError("failed to convert Directrix curve (IfcSweptDiskSolid)");
@ -460,8 +431,7 @@ void ProcessSweptDiskSolid(const Schema_2x3::IfcSweptDiskSolid &solid, TempMesh&
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
IfcMatrix3 DerivePlaneCoordinateSpace(const TempMesh& curmesh, bool& ok, IfcVector3& norOut) IfcMatrix3 DerivePlaneCoordinateSpace(const TempMesh& curmesh, bool& ok, IfcVector3& norOut) {
{
const std::vector<IfcVector3>& out = curmesh.mVerts; const std::vector<IfcVector3>& out = curmesh.mVerts;
IfcMatrix3 m; IfcMatrix3 m;
@ -504,10 +474,6 @@ IfcMatrix3 DerivePlaneCoordinateSpace(const TempMesh& curmesh, bool& ok, IfcVect
IfcVector3 r = (out[idx]-any_point); IfcVector3 r = (out[idx]-any_point);
r.Normalize(); r.Normalize();
//if(d) {
// *d = -any_point * nor;
//}
// Reconstruct orthonormal basis // Reconstruct orthonormal basis
// XXX use Gram Schmidt for increased robustness // XXX use Gram Schmidt for increased robustness
IfcVector3 u = r ^ nor; IfcVector3 u = r ^ nor;
@ -531,8 +497,7 @@ IfcMatrix3 DerivePlaneCoordinateSpace(const TempMesh& curmesh, bool& ok, IfcVect
const auto closeDistance = ai_epsilon; const auto closeDistance = ai_epsilon;
bool areClose(Schema_2x3::IfcCartesianPoint pt1,Schema_2x3::IfcCartesianPoint pt2) { bool areClose(Schema_2x3::IfcCartesianPoint pt1,Schema_2x3::IfcCartesianPoint pt2) {
if(pt1.Coordinates.size() != pt2.Coordinates.size()) if(pt1.Coordinates.size() != pt2.Coordinates.size()) {
{
IFCImporter::LogWarn("unable to compare differently-dimensioned points"); IFCImporter::LogWarn("unable to compare differently-dimensioned points");
return false; return false;
} }
@ -540,11 +505,11 @@ bool areClose(Schema_2x3::IfcCartesianPoint pt1,Schema_2x3::IfcCartesianPoint pt
auto coord2 = pt2.Coordinates.begin(); auto coord2 = pt2.Coordinates.begin();
// we're just testing each dimension separately rather than doing euclidean distance, as we're // we're just testing each dimension separately rather than doing euclidean distance, as we're
// looking for very close coordinates // looking for very close coordinates
for(; coord1 != pt1.Coordinates.end(); coord1++,coord2++) for(; coord1 != pt1.Coordinates.end(); coord1++,coord2++) {
{ if(std::fabs(*coord1 - *coord2) > closeDistance) {
if(std::fabs(*coord1 - *coord2) > closeDistance)
return false; return false;
} }
}
return true; return true;
} }
@ -553,6 +518,7 @@ bool areClose(IfcVector3 pt1,IfcVector3 pt2) {
std::fabs(pt1.y - pt2.y) < closeDistance && std::fabs(pt1.y - pt2.y) < closeDistance &&
std::fabs(pt1.z - pt2.z) < closeDistance); std::fabs(pt1.z - pt2.z) < closeDistance);
} }
// Extrudes the given polygon along the direction, converts it into an opening or applies all openings as necessary. // Extrudes the given polygon along the direction, converts it into an opening or applies all openings as necessary.
void ProcessExtrudedArea(const Schema_2x3::IfcExtrudedAreaSolid& solid, const TempMesh& curve, void ProcessExtrudedArea(const Schema_2x3::IfcExtrudedAreaSolid& solid, const TempMesh& curve,
const IfcVector3& extrusionDir, TempMesh& result, ConversionData &conv, bool collect_openings) const IfcVector3& extrusionDir, TempMesh& result, ConversionData &conv, bool collect_openings)
@ -590,8 +556,9 @@ void ProcessExtrudedArea(const Schema_2x3::IfcExtrudedAreaSolid& solid, const Te
// reverse profile polygon if it's winded in the wrong direction in relation to the extrusion direction // reverse profile polygon if it's winded in the wrong direction in relation to the extrusion direction
IfcVector3 profileNormal = TempMesh::ComputePolygonNormal(in.data(), in.size()); IfcVector3 profileNormal = TempMesh::ComputePolygonNormal(in.data(), in.size());
if( profileNormal * dir < 0.0 ) if( profileNormal * dir < 0.0 ) {
std::reverse(in.begin(), in.end()); std::reverse(in.begin(), in.end());
}
std::vector<IfcVector3> nors; std::vector<IfcVector3> nors;
const bool openings = !!conv.apply_openings && conv.apply_openings->size(); const bool openings = !!conv.apply_openings && conv.apply_openings->size();
@ -678,8 +645,7 @@ void ProcessExtrudedArea(const Schema_2x3::IfcExtrudedAreaSolid& solid, const Te
if(n > 0) { if(n > 0) {
for(size_t i = 0; i < in.size(); ++i) for(size_t i = 0; i < in.size(); ++i)
out.push_back(in[i] + dir); out.push_back(in[i] + dir);
} } else {
else {
for(size_t i = in.size(); i--; ) for(size_t i = in.size(); i--; )
out.push_back(in[i]); out.push_back(in[i]);
} }
@ -721,9 +687,10 @@ void ProcessExtrudedArea(const Schema_2x3::IfcExtrudedAreaSolid& solid, const Te
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ProcessExtrudedAreaSolid(const Schema_2x3::IfcExtrudedAreaSolid& solid, TempMesh& result, void ProcessExtrudedAreaSolid(const Schema_2x3::IfcExtrudedAreaSolid& solid,
ConversionData& conv, bool collect_openings) TempMesh& result,
{ ConversionData& conv,
bool collect_openings) {
TempMesh meshout; TempMesh meshout;
// First read the profile description. // First read the profile description.
@ -761,24 +728,23 @@ void ProcessExtrudedAreaSolid(const Schema_2x3::IfcExtrudedAreaSolid& solid, Tem
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ProcessSweptAreaSolid(const Schema_2x3::IfcSweptAreaSolid& swept, TempMesh& meshout, void ProcessSweptAreaSolid(const Schema_2x3::IfcSweptAreaSolid& swept,
ConversionData& conv) TempMesh& meshout,
{ ConversionData& conv) {
if(const Schema_2x3::IfcExtrudedAreaSolid* const solid = swept.ToPtr<Schema_2x3::IfcExtrudedAreaSolid>()) { if(const Schema_2x3::IfcExtrudedAreaSolid* const solid = swept.ToPtr<Schema_2x3::IfcExtrudedAreaSolid>()) {
ProcessExtrudedAreaSolid(*solid,meshout,conv, !!conv.collect_openings); ProcessExtrudedAreaSolid(*solid,meshout,conv, !!conv.collect_openings);
} } else if(const Schema_2x3::IfcRevolvedAreaSolid* const rev = swept.ToPtr<Schema_2x3::IfcRevolvedAreaSolid>()) {
else if(const Schema_2x3::IfcRevolvedAreaSolid* const rev = swept.ToPtr<Schema_2x3::IfcRevolvedAreaSolid>()) {
ProcessRevolvedAreaSolid(*rev,meshout,conv); ProcessRevolvedAreaSolid(*rev,meshout,conv);
} } else {
else {
IFCImporter::LogWarn("skipping unknown IfcSweptAreaSolid entity, type is ", swept.GetClassName()); IFCImporter::LogWarn("skipping unknown IfcSweptAreaSolid entity, type is ", swept.GetClassName());
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool ProcessGeometricItem(const Schema_2x3::IfcRepresentationItem& geo, unsigned int matid, std::set<unsigned int>& mesh_indices, bool ProcessGeometricItem(const Schema_2x3::IfcRepresentationItem& geo,
ConversionData& conv) unsigned int matid,
{ std::set<unsigned int>& mesh_indices,
ConversionData& conv) {
bool fix_orientation = false; bool fix_orientation = false;
std::shared_ptr< TempMesh > meshtmp = std::make_shared<TempMesh>(); std::shared_ptr< TempMesh > meshtmp = std::make_shared<TempMesh>();
if(const Schema_2x3::IfcShellBasedSurfaceModel* shellmod = geo.ToPtr<Schema_2x3::IfcShellBasedSurfaceModel>()) { if(const Schema_2x3::IfcShellBasedSurfaceModel* shellmod = geo.ToPtr<Schema_2x3::IfcShellBasedSurfaceModel>()) {
@ -788,41 +754,32 @@ bool ProcessGeometricItem(const Schema_2x3::IfcRepresentationItem& geo, unsigned
const Schema_2x3::IfcConnectedFaceSet& fs = conv.db.MustGetObject(e).To<Schema_2x3::IfcConnectedFaceSet>(); const Schema_2x3::IfcConnectedFaceSet& fs = conv.db.MustGetObject(e).To<Schema_2x3::IfcConnectedFaceSet>();
ProcessConnectedFaceSet(fs, *meshtmp, conv); ProcessConnectedFaceSet(fs, *meshtmp, conv);
} } catch(std::bad_cast&) {
catch(std::bad_cast&) {
IFCImporter::LogWarn("unexpected type error, IfcShell ought to inherit from IfcConnectedFaceSet"); IFCImporter::LogWarn("unexpected type error, IfcShell ought to inherit from IfcConnectedFaceSet");
} }
} }
fix_orientation = true; fix_orientation = true;
} } else if(const Schema_2x3::IfcConnectedFaceSet* fset = geo.ToPtr<Schema_2x3::IfcConnectedFaceSet>()) {
else if(const Schema_2x3::IfcConnectedFaceSet* fset = geo.ToPtr<Schema_2x3::IfcConnectedFaceSet>()) {
ProcessConnectedFaceSet(*fset, *meshtmp, conv); ProcessConnectedFaceSet(*fset, *meshtmp, conv);
fix_orientation = true; fix_orientation = true;
} } else if(const Schema_2x3::IfcSweptAreaSolid* swept = geo.ToPtr<Schema_2x3::IfcSweptAreaSolid>()) {
else if(const Schema_2x3::IfcSweptAreaSolid* swept = geo.ToPtr<Schema_2x3::IfcSweptAreaSolid>()) {
ProcessSweptAreaSolid(*swept, *meshtmp, conv); ProcessSweptAreaSolid(*swept, *meshtmp, conv);
} } else if(const Schema_2x3::IfcSweptDiskSolid* disk = geo.ToPtr<Schema_2x3::IfcSweptDiskSolid>()) {
else if(const Schema_2x3::IfcSweptDiskSolid* disk = geo.ToPtr<Schema_2x3::IfcSweptDiskSolid>()) {
ProcessSweptDiskSolid(*disk, *meshtmp, conv); ProcessSweptDiskSolid(*disk, *meshtmp, conv);
} } else if(const Schema_2x3::IfcManifoldSolidBrep* brep = geo.ToPtr<Schema_2x3::IfcManifoldSolidBrep>()) {
else if(const Schema_2x3::IfcManifoldSolidBrep* brep = geo.ToPtr<Schema_2x3::IfcManifoldSolidBrep>()) {
ProcessConnectedFaceSet(brep->Outer, *meshtmp, conv); ProcessConnectedFaceSet(brep->Outer, *meshtmp, conv);
fix_orientation = true; fix_orientation = true;
} } else if(const Schema_2x3::IfcFaceBasedSurfaceModel* surf = geo.ToPtr<Schema_2x3::IfcFaceBasedSurfaceModel>()) {
else if(const Schema_2x3::IfcFaceBasedSurfaceModel* surf = geo.ToPtr<Schema_2x3::IfcFaceBasedSurfaceModel>()) {
for(const Schema_2x3::IfcConnectedFaceSet& fc : surf->FbsmFaces) { for(const Schema_2x3::IfcConnectedFaceSet& fc : surf->FbsmFaces) {
ProcessConnectedFaceSet(fc, *meshtmp, conv); ProcessConnectedFaceSet(fc, *meshtmp, conv);
} }
fix_orientation = true; fix_orientation = true;
} } else if(const Schema_2x3::IfcBooleanResult* boolean = geo.ToPtr<Schema_2x3::IfcBooleanResult>()) {
else if(const Schema_2x3::IfcBooleanResult* boolean = geo.ToPtr<Schema_2x3::IfcBooleanResult>()) {
ProcessBoolean(*boolean, *meshtmp, conv); ProcessBoolean(*boolean, *meshtmp, conv);
} } else if(geo.ToPtr<Schema_2x3::IfcBoundingBox>()) {
else if(geo.ToPtr<Schema_2x3::IfcBoundingBox>()) {
// silently skip over bounding boxes // silently skip over bounding boxes
return false; return false;
} } else {
else {
std::stringstream toLog; std::stringstream toLog;
toLog << "skipping unknown IfcGeometricRepresentationItem entity, type is " << geo.GetClassName() << " id is " << geo.GetID(); toLog << "skipping unknown IfcGeometricRepresentationItem entity, type is " << geo.GetClassName() << " id is " << geo.GetID();
IFCImporter::LogWarn(toLog.str().c_str()); IFCImporter::LogWarn(toLog.str().c_str());
@ -868,9 +825,7 @@ bool ProcessGeometricItem(const Schema_2x3::IfcRepresentationItem& geo, unsigned
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void AssignAddedMeshes(std::set<unsigned int>& mesh_indices,aiNode* nd, void AssignAddedMeshes(std::set<unsigned int>& mesh_indices,aiNode* nd, ConversionData& /*conv*/) {
ConversionData& /*conv*/)
{
if (!mesh_indices.empty()) { if (!mesh_indices.empty()) {
std::set<unsigned int>::const_iterator it = mesh_indices.cbegin(); std::set<unsigned int>::const_iterator it = mesh_indices.cbegin();
std::set<unsigned int>::const_iterator end = mesh_indices.cend(); std::set<unsigned int>::const_iterator end = mesh_indices.cend();
@ -886,9 +841,9 @@ void AssignAddedMeshes(std::set<unsigned int>& mesh_indices,aiNode* nd,
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool TryQueryMeshCache(const Schema_2x3::IfcRepresentationItem& item, bool TryQueryMeshCache(const Schema_2x3::IfcRepresentationItem& item,
std::set<unsigned int>& mesh_indices, unsigned int mat_index, std::set<unsigned int>& mesh_indices,
ConversionData& conv) unsigned int mat_index,
{ ConversionData& conv) {
ConversionData::MeshCacheIndex idx(&item, mat_index); ConversionData::MeshCacheIndex idx(&item, mat_index);
ConversionData::MeshCache::const_iterator it = conv.cached_meshes.find(idx); ConversionData::MeshCache::const_iterator it = conv.cached_meshes.find(idx);
if (it != conv.cached_meshes.end()) { if (it != conv.cached_meshes.end()) {
@ -900,18 +855,18 @@ bool TryQueryMeshCache(const Schema_2x3::IfcRepresentationItem& item,
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void PopulateMeshCache(const Schema_2x3::IfcRepresentationItem& item, void PopulateMeshCache(const Schema_2x3::IfcRepresentationItem& item,
const std::set<unsigned int>& mesh_indices, unsigned int mat_index, const std::set<unsigned int>& mesh_indices,
ConversionData& conv) unsigned int mat_index,
{ ConversionData& conv) {
ConversionData::MeshCacheIndex idx(&item, mat_index); ConversionData::MeshCacheIndex idx(&item, mat_index);
conv.cached_meshes[idx] = mesh_indices; conv.cached_meshes[idx] = mesh_indices;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool ProcessRepresentationItem(const Schema_2x3::IfcRepresentationItem& item, unsigned int matid, bool ProcessRepresentationItem(const Schema_2x3::IfcRepresentationItem& item,
unsigned int matid,
std::set<unsigned int>& mesh_indices, std::set<unsigned int>& mesh_indices,
ConversionData& conv) ConversionData& conv) {
{
// determine material // determine material
unsigned int localmatid = ProcessMaterials(item.GetID(), matid, conv, true); unsigned int localmatid = ProcessMaterials(item.GetID(), matid, conv, true);
@ -920,8 +875,9 @@ bool ProcessRepresentationItem(const Schema_2x3::IfcRepresentationItem& item, un
if(mesh_indices.size()) { if(mesh_indices.size()) {
PopulateMeshCache(item,mesh_indices,localmatid,conv); PopulateMeshCache(item,mesh_indices,localmatid,conv);
} }
} else {
return false;
} }
else return false;
} }
return true; return true;
} }
@ -930,4 +886,4 @@ bool ProcessRepresentationItem(const Schema_2x3::IfcRepresentationItem& item, un
} // ! IFC } // ! IFC
} // ! Assimp } // ! Assimp
#endif #endif // ASSIMP_BUILD_NO_IFC_IMPORTER

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team Copyright (c) 2006-2022, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -40,9 +39,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
/** @file IFCLoad.cpp /// @file IFCLoad.cpp
* @brief Implementation of the Industry Foundation Classes loader. /// @brief Implementation of the Industry Foundation Classes loader.
*/
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER #ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
@ -92,7 +90,6 @@ using namespace Assimp::IFC;
IfcUnitAssignment IfcUnitAssignment
IfcClosedShell IfcClosedShell
IfcDoor IfcDoor
*/ */
namespace { namespace {
@ -119,14 +116,6 @@ static const aiImporterDesc desc = {
"ifc ifczip step stp" "ifc ifczip step stp"
}; };
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
IFCImporter::IFCImporter() = default;
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
IFCImporter::~IFCImporter() = default;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool IFCImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { bool IFCImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
@ -256,7 +245,12 @@ void IFCImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
// tell the reader for which types we need to simulate STEPs reverse indices // tell the reader for which types we need to simulate STEPs reverse indices
static const char *const inverse_indices_to_track[] = { static const char *const inverse_indices_to_track[] = {
"ifcrelcontainedinspatialstructure", "ifcrelaggregates", "ifcrelvoidselement", "ifcreldefinesbyproperties", "ifcpropertyset", "ifcstyleditem" "ifcrelcontainedinspatialstructure",
"ifcrelaggregates",
"ifcrelvoidselement",
"ifcreldefinesbyproperties",
"ifcpropertyset",
"ifcstyleditem"
}; };
// feed the IFC schema into the reader and pre-parse all lines // feed the IFC schema into the reader and pre-parse all lines
@ -928,4 +922,4 @@ void MakeTreeRelative(ConversionData &conv) {
} // namespace } // namespace
#endif #endif // ASSIMP_BUILD_NO_IFC_IMPORTER

View File

@ -87,8 +87,8 @@ public:
int cylindricalTessellation; int cylindricalTessellation;
}; };
IFCImporter(); IFCImporter() = default;
~IFCImporter() override; ~IFCImporter() override = default;
// -------------------- // --------------------
bool CanRead(const std::string &pFile, bool CanRead(const std::string &pFile,

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team Copyright (c) 2006-2022, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -40,9 +39,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
/** @file IFCMaterial.cpp /// @file IFCMaterial.cpp
* @brief Implementation of conversion routines to convert IFC materials to aiMaterial /// @brief Implementation of conversion routines to convert IFC materials to aiMaterial
*/
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER #ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
@ -174,7 +172,6 @@ unsigned int ProcessMaterials(uint64_t id, unsigned int prevMatId, ConversionDat
aiString name; aiString name;
name.Set("<IFCDefault>"); name.Set("<IFCDefault>");
// ConvertColorToString( color, name);
// look if there's already a default material with this base color // look if there's already a default material with this base color
for( size_t a = 0; a < conv.materials.size(); ++a ) { for( size_t a = 0; a < conv.materials.size(); ++a ) {

View File

@ -38,24 +38,17 @@ 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"
#include "contrib/poly2tri/poly2tri/poly2tri.h"
#ifdef ASSIMP_USE_HUNTER #include "contrib/clipper/clipper.hpp"
# include <poly2tri/poly2tri.h>
# include <polyclipping/clipper.hpp>
#else
# include "../contrib/poly2tri/poly2tri/poly2tri.h"
# include "../contrib/clipper/clipper.hpp"
#endif
#include <deque> #include <deque>
#include <forward_list> #include <forward_list>
@ -66,29 +59,37 @@ namespace Assimp {
namespace IFC { namespace IFC {
using ClipperLib::ulong64; using ClipperLib::ulong64;
// XXX use full -+ range ... // XXX use full -+ range ...
const ClipperLib::long64 max_ulong64 = 1518500249; // clipper.cpp / hiRange var 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 )) AI_FORCE_INLINE ulong64 to_int64(IfcFloat p) {
#define to_int64(p) (static_cast<ulong64>(static_cast<IfcFloat>((p) ) * max_ulong64 )) return (static_cast<ulong64>(static_cast<IfcFloat>((p) ) * max_ulong64 ));
#define from_int64(p) (static_cast<IfcFloat>((p)) / max_ulong64) }
#define one_vec (IfcVector2(static_cast<IfcFloat>(1.0),static_cast<IfcFloat>(1.0)))
AI_FORCE_INLINE IfcFloat from_int64(ulong64 p) {
return (static_cast<IfcFloat>((p)) / max_ulong64);
}
AI_FORCE_INLINE void fillRectangle(const IfcVector2& pmin, const IfcVector2& pmax, std::vector<IfcVector2>& out) {
out.emplace_back(pmin.x, pmin.y);
out.emplace_back(pmin.x, pmax.y);
out.emplace_back(pmax.x, pmax.y);
out.emplace_back(pmax.x, pmin.y);
}
const IfcVector2 one_vec(IfcVector2(static_cast<IfcFloat>(1.0),static_cast<IfcFloat>(1.0)));
// fallback method to generate wall openings // fallback method to generate wall openings
bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings, bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings, TempMesh& curmesh);
TempMesh& curmesh);
typedef std::pair< IfcVector2, IfcVector2 > BoundingBox;
typedef std::map<IfcVector2,size_t,XYSorter> XYSortedField;
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;
} }
@ -114,10 +115,7 @@ void QuadrifyPart(const IfcVector2& pmin, const IfcVector2& pmax, XYSortedField&
if (!found) { if (!found) {
// the rectangle [pmin,pend] is opaque, fill it // the rectangle [pmin,pend] is opaque, fill it
out.push_back(pmin); fillRectangle(pmin, pmax, out);
out.emplace_back(pmin.x,pmax.y);
out.push_back(pmax);
out.emplace_back(pmax.x,pmin.y);
return; return;
} }
@ -142,19 +140,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 +167,19 @@ 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) : contour(contour), bb(bb) , is_rectangular(is_rectangular) {}
, bb(bb)
, is_rectangular(is_rectangular)
{}
~ProjectedWindowContour() = default;
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,9 +215,8 @@ 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));
@ -246,8 +230,7 @@ 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);
@ -265,10 +248,7 @@ 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;
@ -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,12 @@ void InsertWindowContours(const ContourVector& contours,
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void MergeWindowContours (const std::vector<IfcVector2>& a, void MergeWindowContours (const std::vector<IfcVector2>& a, const std::vector<IfcVector2>& b,
const std::vector<IfcVector2>& b, ClipperLib::Paths& out) {
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 +377,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 +388,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,13 +396,11 @@ 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 +409,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 +420,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,28 +453,25 @@ 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);
// Assume the bounding box doesn't change during this operation // Assume the bounding box doesn't change during this operation
ExtractVerticesFromClipper(clipped[0], scratch);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void CleanupWindowContours(ContourVector& contours) void CleanupWindowContours(ContourVector& contours) {
{
// Use PolyClipper to clean up window contours // Use PolyClipper to clean up window contours
try { try {
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;
@ -517,12 +480,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::Path subject;
ClipperLib::Polygon 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 +513,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 +530,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) + ")");
@ -584,17 +542,14 @@ void CleanupOuterContour(const std::vector<IfcVector2>& contour_flat, TempMesh&
std::swap(iold,curmesh.mVertcnt); std::swap(iold,curmesh.mVertcnt);
} }
typedef std::vector<TempOpening*> OpeningRefs; using OpeningRefs = std::vector<TempOpening*> ;
typedef std::vector<OpeningRefs > OpeningRefVector; using OpeningRefVector = std::vector<OpeningRefs >;
using ContourRefVector = std::vector<std::pair<
typedef std::vector<std::pair<
ContourVector::const_iterator, ContourVector::const_iterator,
Contour::const_iterator> Contour::const_iterator> >;
> 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) ||
@ -608,8 +563,7 @@ bool BoundingBoxesAdjacent(const BoundingBox& bb, const BoundingBox& ibb)
// output the intersection points on n0,n1 // output the intersection points on n0,n1
bool IntersectingLineSegments(const IfcVector2& n0, const IfcVector2& n1, bool IntersectingLineSegments(const IfcVector2& n0, const IfcVector2& n1,
const IfcVector2& m0, const IfcVector2& m1, const IfcVector2& m0, const IfcVector2& m1,
IfcVector2& out0, IfcVector2& out1) IfcVector2& out0, IfcVector2& out1) {
{
const IfcVector2 n0_to_n1 = n1 - n0; const IfcVector2 n0_to_n1 = n1 - n0;
const IfcVector2 n0_to_m0 = m0 - n0; const IfcVector2 n0_to_m0 = m0 - n0;
@ -648,8 +602,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;
@ -682,8 +635,7 @@ bool IntersectingLineSegments(const IfcVector2& n0, const IfcVector2& n1,
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void FindAdjacentContours(ContourVector::iterator current, const ContourVector& contours) void FindAdjacentContours(ContourVector::iterator current, const ContourVector& contours) {
{
const IfcFloat sqlen_epsilon = static_cast<IfcFloat>(Math::getEpsilon<float>()); const IfcFloat sqlen_epsilon = static_cast<IfcFloat>(Math::getEpsilon<float>());
const BoundingBox& bb = (*current).bb; const BoundingBox& bb = (*current).bb;
@ -698,13 +650,6 @@ void FindAdjacentContours(ContourVector::iterator current, const ContourVector&
continue; continue;
} }
// this left here to make clear we also run on the current contour
// to check for overlapping contour segments (which can happen due
// to projection artifacts).
//if(it == current) {
// continue;
//}
const bool is_me = it == current; const bool is_me = it == current;
const BoundingBox& ibb = (*it).bb; const BoundingBox& ibb = (*it).bb;
@ -740,8 +685,7 @@ void FindAdjacentContours(ContourVector::iterator current, const ContourVector&
ncontour.insert(ncontour.begin() + n, isect0); ncontour.insert(ncontour.begin() + n, isect0);
skiplist.insert(skiplist.begin() + n, true); skiplist.insert(skiplist.begin() + n, true);
} } else {
else {
skiplist[n] = true; skiplist[n] = true;
} }
@ -759,15 +703,13 @@ void FindAdjacentContours(ContourVector::iterator current, const ContourVector&
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AI_FORCE_INLINE bool LikelyBorder(const IfcVector2& vdelta) AI_FORCE_INLINE bool LikelyBorder(const IfcVector2& vdelta) {
{
const IfcFloat dot_point_epsilon = static_cast<IfcFloat>(Math::getEpsilon<float>()); const IfcFloat dot_point_epsilon = static_cast<IfcFloat>(Math::getEpsilon<float>());
return std::fabs(vdelta.x * vdelta.y) < dot_point_epsilon; return std::fabs(vdelta.x * vdelta.y) < dot_point_epsilon;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void FindBorderContours(ContourVector::iterator current) void FindBorderContours(ContourVector::iterator current) {
{
const IfcFloat border_epsilon_upper = static_cast<IfcFloat>(1-1e-4); const IfcFloat border_epsilon_upper = static_cast<IfcFloat>(1-1e-4);
const IfcFloat border_epsilon_lower = static_cast<IfcFloat>(1e-4); const IfcFloat border_epsilon_lower = static_cast<IfcFloat>(1e-4);
@ -787,20 +729,17 @@ void FindBorderContours(ContourVector::iterator current)
// not have any geometry to close them (think of door openings). // not have any geometry to close them (think of door openings).
if (proj_point.x <= border_epsilon_lower || proj_point.x >= border_epsilon_upper || 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) { proj_point.y <= border_epsilon_lower || proj_point.y >= border_epsilon_upper) {
if (outer_border) { if (outer_border) {
ai_assert(cit != cbegin); ai_assert(cit != cbegin);
if (LikelyBorder(proj_point - last_proj_point)) { if (LikelyBorder(proj_point - last_proj_point)) {
skiplist[std::distance(cbegin, cit) - 1] = true; skiplist[std::distance(cbegin, cit) - 1] = true;
} }
} } else if (cit == cbegin) {
else if (cit == cbegin) {
start_on_outer_border = true; start_on_outer_border = true;
} }
outer_border = true; outer_border = true;
} } else {
else {
outer_border = false; outer_border = false;
} }
@ -817,16 +756,14 @@ void FindBorderContours(ContourVector::iterator current)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AI_FORCE_INLINE bool LikelyDiagonal(IfcVector2 vdelta) AI_FORCE_INLINE bool LikelyDiagonal(IfcVector2 vdelta) {
{
vdelta.x = std::fabs(vdelta.x); vdelta.x = std::fabs(vdelta.x);
vdelta.y = std::fabs(vdelta.y); vdelta.y = std::fabs(vdelta.y);
return (std::fabs(vdelta.x-vdelta.y) < 0.8 * std::max(vdelta.x, vdelta.y)); return (std::fabs(vdelta.x-vdelta.y) < 0.8 * std::max(vdelta.x, vdelta.y));
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void FindLikelyCrossingLines(ContourVector::iterator current) void FindLikelyCrossingLines(ContourVector::iterator current) {
{
SkipList& skiplist = (*current).skiplist; SkipList& skiplist = (*current).skiplist;
IfcVector2 last_proj_point; IfcVector2 last_proj_point;
@ -854,8 +791,7 @@ void FindLikelyCrossingLines(ContourVector::iterator current)
size_t CloseWindows(ContourVector& contours, size_t CloseWindows(ContourVector& contours,
const IfcMatrix4& minv, const IfcMatrix4& minv,
OpeningRefVector& contours_to_openings, OpeningRefVector& contours_to_openings,
TempMesh& curmesh) TempMesh& curmesh) {
{
size_t closed = 0; size_t closed = 0;
// For all contour points, check if one of the assigned openings does // For all contour points, check if one of the assigned openings does
// already have points assigned to it. In this case, assume this is // already have points assigned to it. In this case, assume this is
@ -964,8 +900,7 @@ size_t CloseWindows(ContourVector& contours,
if (drop_this_edge) { if (drop_this_edge) {
curmesh.mVerts.pop_back(); curmesh.mVerts.pop_back();
curmesh.mVerts.pop_back(); curmesh.mVerts.pop_back();
} } else {
else {
curmesh.mVerts.push_back(((cit == cbegin) != reverseCountourFaces) ? world_point : bestv); curmesh.mVerts.push_back(((cit == cbegin) != reverseCountourFaces) ? world_point : bestv);
curmesh.mVerts.push_back(((cit == cbegin) != reverseCountourFaces) ? bestv : world_point); curmesh.mVerts.push_back(((cit == cbegin) != reverseCountourFaces) ? bestv : world_point);
@ -992,16 +927,13 @@ size_t CloseWindows(ContourVector& contours,
curmesh.mVertcnt.pop_back(); curmesh.mVertcnt.pop_back();
curmesh.mVerts.pop_back(); curmesh.mVerts.pop_back();
curmesh.mVerts.pop_back(); curmesh.mVerts.pop_back();
} } else {
else {
curmesh.mVerts.push_back(reverseCountourFaces ? start0 : start1); curmesh.mVerts.push_back(reverseCountourFaces ? start0 : start1);
curmesh.mVerts.push_back(reverseCountourFaces ? start1 : start0); curmesh.mVerts.push_back(reverseCountourFaces ? start1 : start0);
} }
} }
} }
} } else {
else {
const Contour::const_iterator cbegin = (*it).contour.begin(), cend = (*it).contour.end(); const Contour::const_iterator cbegin = (*it).contour.begin(), cend = (*it).contour.end();
for(TempOpening* opening : refs) { for(TempOpening* opening : refs) {
ai_assert(opening->wallPoints.empty()); ai_assert(opening->wallPoints.empty());
@ -1018,8 +950,7 @@ size_t CloseWindows(ContourVector& contours,
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Quadrify(const std::vector< BoundingBox >& bbs, TempMesh& curmesh) void Quadrify(const std::vector< BoundingBox >& bbs, TempMesh& curmesh) {
{
ai_assert(curmesh.IsEmpty()); ai_assert(curmesh.IsEmpty());
std::vector<IfcVector2> quads; std::vector<IfcVector2> quads;
@ -1045,8 +976,7 @@ void Quadrify(const std::vector< BoundingBox >& bbs, TempMesh& curmesh)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Quadrify(const ContourVector& contours, TempMesh& curmesh) void Quadrify(const ContourVector& contours, TempMesh& curmesh) {
{
std::vector<BoundingBox> bbs; std::vector<BoundingBox> bbs;
bbs.reserve(contours.size()); bbs.reserve(contours.size());
@ -1058,12 +988,17 @@ void Quadrify(const ContourVector& contours, TempMesh& curmesh)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
IfcMatrix4 ProjectOntoPlane(std::vector<IfcVector2>& out_contour, const TempMesh& in_mesh, IfcMatrix4 ProjectOntoPlane(std::vector<IfcVector2>& out_contour,
bool &ok, IfcVector3& nor_out) const TempMesh& in_mesh,
{ bool &ok,
IfcVector3& nor_out) {
const std::vector<IfcVector3>& in_verts = in_mesh.mVerts; const std::vector<IfcVector3>& in_verts = in_mesh.mVerts;
ok = true; if (in_verts.empty()){
ok = false;
return IfcMatrix4();
}
ok = true;
IfcMatrix4 m = IfcMatrix4(DerivePlaneCoordinateSpace(in_mesh, ok, nor_out)); IfcMatrix4 m = IfcMatrix4(DerivePlaneCoordinateSpace(in_mesh, ok, nor_out));
if(!ok) { if(!ok) {
return IfcMatrix4(); return IfcMatrix4();
@ -1076,7 +1011,6 @@ IfcMatrix4 ProjectOntoPlane(std::vector<IfcVector2>& out_contour, const TempMesh
IfcFloat zcoord = 0; IfcFloat zcoord = 0;
out_contour.reserve(in_verts.size()); out_contour.reserve(in_verts.size());
IfcVector3 vmin, vmax; IfcVector3 vmin, vmax;
MinMaxChooser<IfcVector3>()(vmin, vmax); MinMaxChooser<IfcVector3>()(vmin, vmax);
@ -1087,11 +1021,6 @@ IfcMatrix4 ProjectOntoPlane(std::vector<IfcVector2>& out_contour, const TempMesh
// (which are present, of course), this should be the same value for // (which are present, of course), this should be the same value for
// all polygon vertices (assuming the polygon is planar). // all polygon vertices (assuming the polygon is planar).
// XXX this should be guarded, but we somehow need to pick a suitable
// epsilon
// if(coord != -1.0f) {
// assert(std::fabs(coord - vv.z) < 1e-3f);
// }
zcoord += vv.z; zcoord += vv.z;
vmin = std::min(vv, vmin); vmin = std::min(vv, vmin);
vmax = std::max(vv, vmax); vmax = std::max(vv, vmax);
@ -1146,8 +1075,7 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
TempMesh& curmesh, TempMesh& curmesh,
bool check_intersection, bool check_intersection,
bool generate_connection_geometry, bool generate_connection_geometry,
const IfcVector3& wall_extrusion_axis) const IfcVector3& wall_extrusion_axis) {
{
OpeningRefVector contours_to_openings; OpeningRefVector contours_to_openings;
// Try to derive a solid base plane within the current surface for use as // Try to derive a solid base plane within the current surface for use as
@ -1183,8 +1111,7 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
IfcVector3 norm_extrusion_dir = opening.extrusionDir; IfcVector3 norm_extrusion_dir = opening.extrusionDir;
if (norm_extrusion_dir.SquareLength() > 1e-10) { if (norm_extrusion_dir.SquareLength() > 1e-10) {
norm_extrusion_dir.Normalize(); norm_extrusion_dir.Normalize();
} } else {
else {
norm_extrusion_dir = IfcVector3(); norm_extrusion_dir = IfcVector3();
} }
@ -1249,10 +1176,8 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
const IfcVector3 v = m * x; const IfcVector3 v = m * x;
IfcVector2 vv(v.x, v.y); IfcVector2 vv(v.x, v.y);
//if(check_intersection) {
dmin = std::min(dmin, v.z); dmin = std::min(dmin, v.z);
dmax = std::max(dmax, v.z); dmax = std::max(dmax, v.z);
//}
// sanity rounding // sanity rounding
vv = std::max(vv,IfcVector2()); vv = std::max(vv,IfcVector2());
@ -1261,8 +1186,7 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
if(side_flag) { if(side_flag) {
vpmin = std::min(vpmin,vv); vpmin = std::min(vpmin,vv);
vpmax = std::max(vpmax,vv); vpmax = std::max(vpmax,vv);
} } else {
else {
vpmin2 = std::min(vpmin2,vv); vpmin2 = std::min(vpmin2,vv);
vpmax2 = std::max(vpmax2,vv); vpmax2 = std::max(vpmax2,vv);
} }
@ -1310,28 +1234,25 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
// See if this BB intersects or is in close adjacency to any other BB we have so far. // See if this BB intersects or is in close adjacency to any other BB we have so far.
for (ContourVector::iterator it = contours.begin(); it != contours.end(); ) { for (ContourVector::iterator it = contours.begin(); it != contours.end(); ) {
const BoundingBox& ibb = (*it).bb; const BoundingBox& ibb = (*it).bb;
if (BoundingBoxesOverlapping(ibb, bb)) { if (BoundingBoxesOverlapping(ibb, bb)) {
if (!(*it).is_rectangular) { if (!(*it).is_rectangular) {
is_rectangle = false; is_rectangle = false;
} }
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
// no longer overlaps ibb // no longer overlaps ibb
MakeDisjunctWindowContours(other, temp_contour, poly); MakeDisjunctWindowContours(other, temp_contour, poly);
if(poly.size() == 1) { if(poly.size() == 1) {
const BoundingBox newbb = GetBoundingBox(poly[0]);
const BoundingBox newbb = GetBoundingBox(poly[0].outer);
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 +1264,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);
@ -1429,9 +1348,14 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
return true; return true;
} }
std::vector<IfcVector2> GetContourInPlane2D(const std::shared_ptr<TempMesh>& mesh,IfcMatrix3 planeSpace, std::vector<IfcVector2> GetContourInPlane2D(const std::shared_ptr<TempMesh>& mesh,
IfcVector3 planeNor,IfcFloat planeOffset, IfcMatrix3 planeSpace,
IfcVector3 extrusionDir,IfcVector3& wall_extrusion,bool& first,bool& ok) { IfcVector3 planeNor,
IfcFloat planeOffset,
IfcVector3 extrusionDir,
IfcVector3& wall_extrusion,
bool& first,
bool& ok) {
std::vector<IfcVector2> contour; std::vector<IfcVector2> contour;
const auto outernor = ((mesh->mVerts[2] - mesh->mVerts[0]) ^ (mesh->mVerts[1] - mesh->mVerts[0])).Normalize(); const auto outernor = ((mesh->mVerts[2] - mesh->mVerts[0]) ^ (mesh->mVerts[1] - mesh->mVerts[0])).Normalize();
@ -1494,7 +1418,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";
@ -1521,8 +1444,8 @@ std::vector<std::vector<IfcVector2>> GetContoursInPlane3D(const std::shared_ptr<
IFCImporter::LogInfo(msg.str().c_str()); IFCImporter::LogInfo(msg.str().c_str());
} }
if(nVertices <= 2) // not a plane, a point or line // not a plane, a point or line
{ if(nVertices <= 2) {
std::stringstream msg; std::stringstream msg;
msg << "GetContoursInPlane3D: found point or line when expecting plane (only " << nVertices << " vertices)"; msg << "GetContoursInPlane3D: found point or line when expecting plane (only " << nVertices << " vertices)";
IFCImporter::LogWarn(msg.str().c_str()); IFCImporter::LogWarn(msg.str().c_str());
@ -1552,15 +1475,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 +1495,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);
@ -1691,29 +1609,28 @@ std::vector<std::vector<IfcVector2>> GetContoursInPlane3D(const std::shared_ptr<
return contours; return contours;
} }
std::vector<std::vector<IfcVector2>> GetContoursInPlane(const std::shared_ptr<TempMesh>& mesh,IfcMatrix3 planeSpace, std::vector<std::vector<IfcVector2>> GetContoursInPlane(const std::shared_ptr<TempMesh>& mesh,
IfcVector3 planeNor,IfcFloat planeOffset, IfcMatrix3 planeSpace,
IfcVector3 extrusionDir,IfcVector3& wall_extrusion,bool& first) { IfcVector3 planeNor,
IfcFloat planeOffset,
if(mesh->mVertcnt.size() == 1) IfcVector3 extrusionDir,
{ IfcVector3& wall_extrusion,
bool& first) {
if(mesh->mVertcnt.size() == 1) {
bool ok; bool ok;
auto contour = GetContourInPlane2D(mesh,planeSpace,planeNor,planeOffset,extrusionDir,wall_extrusion,first,ok); auto contour = GetContourInPlane2D(mesh,planeSpace,planeNor,planeOffset,extrusionDir,wall_extrusion,first,ok);
if(ok) if(ok)
return std::vector<std::vector<IfcVector2>> {std::move(contour)}; return std::vector<std::vector<IfcVector2>> {std::move(contour)};
else else
return std::vector<std::vector<IfcVector2>> {}; return std::vector<std::vector<IfcVector2>> {};
} } else {
else
{
return GetContoursInPlane3D(mesh,planeSpace,planeOffset); return GetContoursInPlane3D(mesh,planeSpace,planeOffset);
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings, bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,
TempMesh& curmesh) TempMesh& curmesh) {
{
IFCImporter::LogWarn("forced to use poly2tri fallback method to generate wall openings"); IFCImporter::LogWarn("forced to use poly2tri fallback method to generate wall openings");
std::vector<IfcVector3>& out = curmesh.mVerts; std::vector<IfcVector3>& out = curmesh.mVerts;
@ -1746,14 +1663,6 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,
// keep Z offset in the plane coordinate system. Ignoring precision issues // keep Z offset in the plane coordinate system. Ignoring precision issues
// (which are present, of course), this should be the same value for // (which are present, of course), this should be the same value for
// all polygon vertices (assuming the polygon is planar). // all polygon vertices (assuming the polygon is planar).
// XXX this should be guarded, but we somehow need to pick a suitable
// epsilon
// if(coord != -1.0f) {
// assert(std::fabs(coord - vv.z) < 1e-3f);
// }
coord = vv.z; coord = vv.z;
vmin = std::min(IfcVector2(vv.x, vv.y), vmin); vmin = std::min(IfcVector2(vv.x, vv.y), vmin);
@ -1771,15 +1680,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 +1694,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;
@ -1797,16 +1704,9 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,
if(!ClipperLib::Orientation(hole)) { if(!ClipperLib::Orientation(hole)) {
std::reverse(hole.begin(),hole.end()); std::reverse(hole.begin(),hole.end());
// assert(ClipperLib::Orientation(hole));
} }
/*ClipperLib::Polygons pol_temp(1), pol_temp2(1); clipper_holes.AddPath(hole,ClipperLib::ptSubject, true);
pol_temp[0] = hole;
ClipperLib::OffsetPolygons(pol_temp,pol_temp2,5.0);
hole = pol_temp2[0];*/
clipper_holes.AddPolygon(hole,ClipperLib::ptSubject);
{ {
std::stringstream msg; std::stringstream msg;
msg << "- added polygon "; msg << "- added polygon ";
@ -1829,7 +1729,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 +1741,14 @@ 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 +1762,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)) );
} }
@ -1881,16 +1779,14 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,
// happen in production use if the input data is broken. An assertion would be // happen in production use if the input data is broken. An assertion would be
// inappropriate. // inappropriate.
cdt = new p2t::CDT(contour_points); cdt = new p2t::CDT(contour_points);
} } catch(const std::exception& e) {
catch(const std::exception& e) {
IFCImporter::LogError("Ifc: error during polygon triangulation, skipping some openings: (poly2tri: " IFCImporter::LogError("Ifc: error during polygon triangulation, skipping some openings: (poly2tri: "
+ std::string(e.what()) + ")"); + std::string(e.what()) + ")");
continue; continue;
} }
// 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();
@ -1905,8 +1801,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,
try { try {
// Note: See above // Note: See above
cdt->Triangulate(); cdt->Triangulate();
} } catch(const std::exception& e) {
catch(const std::exception& e) {
IFCImporter::LogError("Ifc: error during polygon triangulation, skipping some openings: (poly2tri: " IFCImporter::LogError("Ifc: error during polygon triangulation, skipping some openings: (poly2tri: "
+ std::string(e.what()) + ")"); + std::string(e.what()) + ")");
continue; continue;
@ -1945,7 +1840,6 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,
return result; return result;
} }
} // ! IFC } // ! IFC
} // ! Assimp } // ! Assimp
@ -1953,4 +1847,4 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,
#undef from_int64 #undef from_int64
#undef one_vec #undef one_vec
#endif #endif // ASSIMP_BUILD_NO_IFC_IMPORTER

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team Copyright (c) 2006-2022, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -40,9 +39,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
/** @file IFCProfile.cpp /// @file IFCProfile.cpp
* @brief Read profile and curves entities from IFC files /// @brief Read profile and curves entities from IFC files
*/
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER #ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
@ -52,8 +50,9 @@ namespace Assimp {
namespace IFC { namespace IFC {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ProcessPolyLine(const Schema_2x3::IfcPolyline& def, TempMesh& meshout, ConversionData& /*conv*/) void ProcessPolyLine(const Schema_2x3::IfcPolyline& def,
{ TempMesh& meshout,
ConversionData& /*conv*/) {
// this won't produce a valid mesh, it just spits out a list of vertices // this won't produce a valid mesh, it just spits out a list of vertices
IfcVector3 t; IfcVector3 t;
for(const Schema_2x3::IfcCartesianPoint& cp : def.Points) { for(const Schema_2x3::IfcCartesianPoint& cp : def.Points) {
@ -64,8 +63,9 @@ void ProcessPolyLine(const Schema_2x3::IfcPolyline& def, TempMesh& meshout, Conv
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool ProcessCurve(const Schema_2x3::IfcCurve& curve, TempMesh& meshout, ConversionData& conv) bool ProcessCurve(const Schema_2x3::IfcCurve& curve,
{ TempMesh& meshout,
ConversionData& conv) {
std::unique_ptr<const Curve> cv(Curve::Convert(curve,conv)); std::unique_ptr<const Curve> cv(Curve::Convert(curve,conv));
if (!cv) { if (!cv) {
IFCImporter::LogWarn("skipping unknown IfcCurve entity, type is ", curve.GetClassName()); IFCImporter::LogWarn("skipping unknown IfcCurve entity, type is ", curve.GetClassName());
@ -90,20 +90,23 @@ bool ProcessCurve(const Schema_2x3::IfcCurve& curve, TempMesh& meshout, Convers
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ProcessClosedProfile(const Schema_2x3::IfcArbitraryClosedProfileDef& def, TempMesh& meshout, ConversionData& conv) void ProcessClosedProfile(const Schema_2x3::IfcArbitraryClosedProfileDef& def,
{ TempMesh& meshout,
ConversionData& conv) {
ProcessCurve(def.OuterCurve,meshout,conv); ProcessCurve(def.OuterCurve,meshout,conv);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ProcessOpenProfile(const Schema_2x3::IfcArbitraryOpenProfileDef& def, TempMesh& meshout, ConversionData& conv) void ProcessOpenProfile(const Schema_2x3::IfcArbitraryOpenProfileDef& def,
{ TempMesh& meshout,
ConversionData& conv) {
ProcessCurve(def.Curve,meshout,conv); ProcessCurve(def.Curve,meshout,conv);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ProcessParametrizedProfile(const Schema_2x3::IfcParameterizedProfileDef& def, TempMesh& meshout, ConversionData& conv) void ProcessParametrizedProfile(const Schema_2x3::IfcParameterizedProfileDef& def,
{ TempMesh& meshout,
ConversionData& conv) {
if(const Schema_2x3::IfcRectangleProfileDef* const cprofile = def.ToPtr<Schema_2x3::IfcRectangleProfileDef>()) { if(const Schema_2x3::IfcRectangleProfileDef* const cprofile = def.ToPtr<Schema_2x3::IfcRectangleProfileDef>()) {
const IfcFloat x = cprofile->XDim*0.5f, y = cprofile->YDim*0.5f; const IfcFloat x = cprofile->XDim*0.5f, y = cprofile->YDim*0.5f;
@ -113,8 +116,7 @@ void ProcessParametrizedProfile(const Schema_2x3::IfcParameterizedProfileDef& de
meshout.mVerts.emplace_back(-x,-y, 0.f ); meshout.mVerts.emplace_back(-x,-y, 0.f );
meshout.mVerts.emplace_back( x,-y, 0.f ); meshout.mVerts.emplace_back( x,-y, 0.f );
meshout.mVertcnt.push_back(4); meshout.mVertcnt.push_back(4);
} } else if( const Schema_2x3::IfcCircleProfileDef* const circle = def.ToPtr<Schema_2x3::IfcCircleProfileDef>()) {
else if( const Schema_2x3::IfcCircleProfileDef* const circle = def.ToPtr<Schema_2x3::IfcCircleProfileDef>()) {
if(def.ToPtr<Schema_2x3::IfcCircleHollowProfileDef>()) { if(def.ToPtr<Schema_2x3::IfcCircleHollowProfileDef>()) {
// TODO // TODO
} }
@ -129,8 +131,7 @@ void ProcessParametrizedProfile(const Schema_2x3::IfcParameterizedProfileDef& de
} }
meshout.mVertcnt.push_back(static_cast<unsigned int>(segments)); meshout.mVertcnt.push_back(static_cast<unsigned int>(segments));
} } else if( const Schema_2x3::IfcIShapeProfileDef* const ishape = def.ToPtr<Schema_2x3::IfcIShapeProfileDef>()) {
else if( const Schema_2x3::IfcIShapeProfileDef* const ishape = def.ToPtr<Schema_2x3::IfcIShapeProfileDef>()) {
// construct simplified IBeam shape // construct simplified IBeam shape
const IfcFloat offset = (ishape->OverallWidth - ishape->WebThickness) / 2; const IfcFloat offset = (ishape->OverallWidth - ishape->WebThickness) / 2;
const IfcFloat inner_height = ishape->OverallDepth - ishape->FlangeThickness * 2; const IfcFloat inner_height = ishape->OverallDepth - ishape->FlangeThickness * 2;
@ -150,8 +151,7 @@ void ProcessParametrizedProfile(const Schema_2x3::IfcParameterizedProfileDef& de
meshout.mVerts.emplace_back(ishape->OverallWidth,0,0); meshout.mVerts.emplace_back(ishape->OverallWidth,0,0);
meshout.mVertcnt.push_back(12); meshout.mVertcnt.push_back(12);
} } else {
else {
IFCImporter::LogWarn("skipping unknown IfcParameterizedProfileDef entity, type is ", def.GetClassName()); IFCImporter::LogWarn("skipping unknown IfcParameterizedProfileDef entity, type is ", def.GetClassName());
return; return;
} }
@ -162,18 +162,14 @@ void ProcessParametrizedProfile(const Schema_2x3::IfcParameterizedProfileDef& de
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool ProcessProfile(const Schema_2x3::IfcProfileDef& prof, TempMesh& meshout, ConversionData& conv) bool ProcessProfile(const Schema_2x3::IfcProfileDef& prof, TempMesh& meshout, ConversionData& conv) {
{
if(const Schema_2x3::IfcArbitraryClosedProfileDef* const cprofile = prof.ToPtr<Schema_2x3::IfcArbitraryClosedProfileDef>()) { if(const Schema_2x3::IfcArbitraryClosedProfileDef* const cprofile = prof.ToPtr<Schema_2x3::IfcArbitraryClosedProfileDef>()) {
ProcessClosedProfile(*cprofile,meshout,conv); ProcessClosedProfile(*cprofile,meshout,conv);
} } else if(const Schema_2x3::IfcArbitraryOpenProfileDef* const copen = prof.ToPtr<Schema_2x3::IfcArbitraryOpenProfileDef>()) {
else if(const Schema_2x3::IfcArbitraryOpenProfileDef* const copen = prof.ToPtr<Schema_2x3::IfcArbitraryOpenProfileDef>()) {
ProcessOpenProfile(*copen,meshout,conv); ProcessOpenProfile(*copen,meshout,conv);
} } else if(const Schema_2x3::IfcParameterizedProfileDef* const cparam = prof.ToPtr<Schema_2x3::IfcParameterizedProfileDef>()) {
else if(const Schema_2x3::IfcParameterizedProfileDef* const cparam = prof.ToPtr<Schema_2x3::IfcParameterizedProfileDef>()) {
ProcessParametrizedProfile(*cparam,meshout,conv); ProcessParametrizedProfile(*cparam,meshout,conv);
} } else {
else {
IFCImporter::LogWarn("skipping unknown IfcProfileDef entity, type is ", prof.GetClassName()); IFCImporter::LogWarn("skipping unknown IfcProfileDef entity, type is ", prof.GetClassName());
return false; return false;
} }

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team Copyright (c) 2006-2022, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -40,9 +39,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
/** @file IFCUtil.cpp /// @file IFCUtil.cpp
* @brief Implementation of conversion routines for some common Ifc helper entities. /// @brief Implementation of conversion routines for some common Ifc helper entities.
*/
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER #ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
@ -66,8 +64,7 @@ void TempOpening::Transform(const IfcMatrix4& mat) {
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiMesh* TempMesh::ToMesh() aiMesh* TempMesh::ToMesh() {
{
ai_assert(mVerts.size() == std::accumulate(mVertcnt.begin(),mVertcnt.end(),size_t(0))); ai_assert(mVerts.size() == std::accumulate(mVertcnt.begin(),mVertcnt.end(),size_t(0)));
if (mVerts.empty()) { if (mVerts.empty()) {
@ -105,36 +102,31 @@ aiMesh* TempMesh::ToMesh()
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void TempMesh::Clear() void TempMesh::Clear() {
{
mVerts.clear(); mVerts.clear();
mVertcnt.clear(); mVertcnt.clear();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void TempMesh::Transform(const IfcMatrix4& mat) void TempMesh::Transform(const IfcMatrix4& mat) {
{
for(IfcVector3& v : mVerts) { for(IfcVector3& v : mVerts) {
v *= mat; v *= mat;
} }
} }
// ------------------------------------------------------------------------------ // ------------------------------------------------------------------------------
IfcVector3 TempMesh::Center() const IfcVector3 TempMesh::Center() const {
{ return mVerts.empty() ? IfcVector3(0.0f, 0.0f, 0.0f) : (std::accumulate(mVerts.begin(),mVerts.end(),IfcVector3()) / static_cast<IfcFloat>(mVerts.size()));
return (mVerts.size() == 0) ? IfcVector3(0.0f, 0.0f, 0.0f) : (std::accumulate(mVerts.begin(),mVerts.end(),IfcVector3()) / static_cast<IfcFloat>(mVerts.size()));
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void TempMesh::Append(const TempMesh& other) void TempMesh::Append(const TempMesh& other) {
{
mVerts.insert(mVerts.end(),other.mVerts.begin(),other.mVerts.end()); mVerts.insert(mVerts.end(),other.mVerts.begin(),other.mVerts.end());
mVertcnt.insert(mVertcnt.end(),other.mVertcnt.begin(),other.mVertcnt.end()); mVertcnt.insert(mVertcnt.end(),other.mVertcnt.begin(),other.mVertcnt.end());
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void TempMesh::RemoveDegenerates() void TempMesh::RemoveDegenerates() {
{
// The strategy is simple: walk the mesh and compute normals using // The strategy is simple: walk the mesh and compute normals using
// Newell's algorithm. The length of the normals gives the area // Newell's algorithm. The length of the normals gives the area
// of the polygons, which is close to zero for lines. // of the polygons, which is close to zero for lines.
@ -167,11 +159,9 @@ void TempMesh::RemoveDegenerates()
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
IfcVector3 TempMesh::ComputePolygonNormal(const IfcVector3* vtcs, size_t cnt, bool normalize) IfcVector3 TempMesh::ComputePolygonNormal(const IfcVector3* vtcs, size_t cnt, bool normalize) {
{
std::vector<IfcFloat> temp((cnt+2)*3); std::vector<IfcFloat> temp((cnt+2)*3);
for( size_t vofs = 0, i = 0; vofs < cnt; ++vofs ) for( size_t vofs = 0, i = 0; vofs < cnt; ++vofs ) {
{
const IfcVector3& v = vtcs[vofs]; const IfcVector3& v = vtcs[vofs];
temp[i++] = v.x; temp[i++] = v.x;
temp[i++] = v.y; temp[i++] = v.y;
@ -186,8 +176,7 @@ IfcVector3 TempMesh::ComputePolygonNormal(const IfcVector3* vtcs, size_t cnt, bo
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void TempMesh::ComputePolygonNormals(std::vector<IfcVector3>& normals, void TempMesh::ComputePolygonNormals(std::vector<IfcVector3>& normals,
bool normalize, bool normalize,
size_t ofs) const size_t ofs) const {
{
size_t max_vcount = 0; size_t max_vcount = 0;
std::vector<unsigned int>::const_iterator begin = mVertcnt.begin()+ofs, end = mVertcnt.end(), iit; std::vector<unsigned int>::const_iterator begin = mVertcnt.begin()+ofs, end = mVertcnt.end(), iit;
for(iit = begin; iit != end; ++iit) { for(iit = begin; iit != end; ++iit) {
@ -250,29 +239,27 @@ struct FindVector {
}; };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void TempMesh::FixupFaceOrientation() void TempMesh::FixupFaceOrientation() {
{
const IfcVector3 vavg = Center(); const IfcVector3 vavg = Center();
// create a list of start indices for all faces to allow random access to faces // create a list of start indices for all faces to allow random access to faces
std::vector<size_t> faceStartIndices(mVertcnt.size()); std::vector<size_t> faceStartIndices(mVertcnt.size());
for( size_t i = 0, a = 0; a < mVertcnt.size(); i += mVertcnt[a], ++a ) for( size_t i = 0, a = 0; a < mVertcnt.size(); i += mVertcnt[a], ++a ) {
faceStartIndices[a] = i; faceStartIndices[a] = i;
}
// list all faces on a vertex // list all faces on a vertex
std::map<IfcVector3, std::vector<size_t>, CompareVector> facesByVertex; std::map<IfcVector3, std::vector<size_t>, CompareVector> facesByVertex;
for( size_t a = 0; a < mVertcnt.size(); ++a ) for( size_t a = 0; a < mVertcnt.size(); ++a ) {
{ for( size_t b = 0; b < mVertcnt[a]; ++b ) {
for( size_t b = 0; b < mVertcnt[a]; ++b )
facesByVertex[mVerts[faceStartIndices[a] + b]].push_back(a); facesByVertex[mVerts[faceStartIndices[a] + b]].push_back(a);
} }
}
// determine neighbourhood for all polys // determine neighbourhood for all polys
std::vector<size_t> neighbour(mVerts.size(), SIZE_MAX); std::vector<size_t> neighbour(mVerts.size(), SIZE_MAX);
std::vector<size_t> tempIntersect(10); std::vector<size_t> tempIntersect(10);
for( size_t a = 0; a < mVertcnt.size(); ++a ) for( size_t a = 0; a < mVertcnt.size(); ++a ) {
{ for( size_t b = 0; b < mVertcnt[a]; ++b ) {
for( size_t b = 0; b < mVertcnt[a]; ++b )
{
size_t ib = faceStartIndices[a] + b, nib = faceStartIndices[a] + (b + 1) % mVertcnt[a]; size_t ib = faceStartIndices[a] + b, nib = faceStartIndices[a] + (b + 1) % mVertcnt[a];
const std::vector<size_t>& facesOnB = facesByVertex[mVerts[ib]]; const std::vector<size_t>& facesOnB = facesByVertex[mVerts[ib]];
const std::vector<size_t>& facesOnNB = facesByVertex[mVerts[nib]]; const std::vector<size_t>& facesOnNB = facesByVertex[mVerts[nib]];
@ -281,10 +268,12 @@ void TempMesh::FixupFaceOrientation()
std::vector<size_t>::iterator sectend = std::set_intersection( std::vector<size_t>::iterator sectend = std::set_intersection(
facesOnB.begin(), facesOnB.end(), facesOnNB.begin(), facesOnNB.end(), sectstart); facesOnB.begin(), facesOnB.end(), facesOnNB.begin(), facesOnNB.end(), sectstart);
if( std::distance(sectstart, sectend) != 2 ) if( std::distance(sectstart, sectend) != 2 ) {
continue; continue;
if( *sectstart == a ) }
if( *sectstart == a ) {
++sectstart; ++sectstart;
}
neighbour[ib] = *sectstart; neighbour[ib] = *sectstart;
} }
} }
@ -293,15 +282,14 @@ void TempMesh::FixupFaceOrientation()
// facing outwards. So we reverse this face to point outwards in relation to the center. Then we adapt neighbouring // facing outwards. So we reverse this face to point outwards in relation to the center. Then we adapt neighbouring
// faces to have the same winding until all faces have been tested. // faces to have the same winding until all faces have been tested.
std::vector<bool> faceDone(mVertcnt.size(), false); std::vector<bool> faceDone(mVertcnt.size(), false);
while( std::count(faceDone.begin(), faceDone.end(), false) != 0 ) while( std::count(faceDone.begin(), faceDone.end(), false) != 0 ) {
{
// find the farthest of the remaining faces // find the farthest of the remaining faces
size_t farthestIndex = SIZE_MAX; size_t farthestIndex = SIZE_MAX;
IfcFloat farthestDistance = -1.0; IfcFloat farthestDistance = -1.0;
for( size_t a = 0; a < mVertcnt.size(); ++a ) for( size_t a = 0; a < mVertcnt.size(); ++a ) {
{ if( faceDone[a] ) {
if( faceDone[a] )
continue; continue;
}
IfcVector3 faceCenter = std::accumulate(mVerts.begin() + faceStartIndices[a], IfcVector3 faceCenter = std::accumulate(mVerts.begin() + faceStartIndices[a],
mVerts.begin() + faceStartIndices[a] + mVertcnt[a], IfcVector3(0.0)) / IfcFloat(mVertcnt[a]); mVerts.begin() + faceStartIndices[a] + mVertcnt[a], IfcVector3(0.0)) / IfcFloat(mVertcnt[a]);
IfcFloat dst = (faceCenter - vavg).SquareLength(); IfcFloat dst = (faceCenter - vavg).SquareLength();
@ -315,8 +303,7 @@ void TempMesh::FixupFaceOrientation()
/ IfcFloat(mVertcnt[farthestIndex]); / IfcFloat(mVertcnt[farthestIndex]);
// We accept a bit of negative orientation without reversing. In case of doubt, prefer the orientation given in // We accept a bit of negative orientation without reversing. In case of doubt, prefer the orientation given in
// the file. // the file.
if( (farthestNormal * (farthestCenter - vavg).Normalize()) < -0.4 ) if( (farthestNormal * (farthestCenter - vavg).Normalize()) < -0.4 ) {
{
size_t fsi = faceStartIndices[farthestIndex], fvc = mVertcnt[farthestIndex]; size_t fsi = faceStartIndices[farthestIndex], fvc = mVertcnt[farthestIndex];
std::reverse(mVerts.begin() + fsi, mVerts.begin() + fsi + fvc); std::reverse(mVerts.begin() + fsi, mVerts.begin() + fsi + fvc);
std::reverse(neighbour.begin() + fsi, neighbour.begin() + fsi + fvc); std::reverse(neighbour.begin() + fsi, neighbour.begin() + fsi + fvc);
@ -333,19 +320,18 @@ void TempMesh::FixupFaceOrientation()
todo.push_back(farthestIndex); todo.push_back(farthestIndex);
// go over its neighbour faces recursively and adapt their winding order to match the farthest face // go over its neighbour faces recursively and adapt their winding order to match the farthest face
while( !todo.empty() ) while( !todo.empty() ) {
{
size_t tdf = todo.back(); size_t tdf = todo.back();
size_t vsi = faceStartIndices[tdf], vc = mVertcnt[tdf]; size_t vsi = faceStartIndices[tdf], vc = mVertcnt[tdf];
todo.pop_back(); todo.pop_back();
// check its neighbours // check its neighbours
for( size_t a = 0; a < vc; ++a ) for( size_t a = 0; a < vc; ++a ) {
{
// ignore neighbours if we already checked them // ignore neighbours if we already checked them
size_t nbi = neighbour[vsi + a]; size_t nbi = neighbour[vsi + a];
if( nbi == SIZE_MAX || faceDone[nbi] ) if( nbi == SIZE_MAX || faceDone[nbi] ) {
continue; continue;
}
const IfcVector3& vp = mVerts[vsi + a]; const IfcVector3& vp = mVerts[vsi + a];
size_t nbvsi = faceStartIndices[nbi], nbvc = mVertcnt[nbi]; size_t nbvsi = faceStartIndices[nbi], nbvc = mVertcnt[nbi];
@ -388,31 +374,7 @@ void TempMesh::RemoveAdjacentDuplicates() {
IfcVector3 vmin,vmax; IfcVector3 vmin,vmax;
ArrayBounds(&*base, cnt ,vmin,vmax); ArrayBounds(&*base, cnt ,vmin,vmax);
const IfcFloat epsilon = (vmax-vmin).SquareLength() / static_cast<IfcFloat>(1e9); const IfcFloat epsilon = (vmax-vmin).SquareLength() / static_cast<IfcFloat>(1e9);
//const IfcFloat dotepsilon = 1e-9;
//// look for vertices that lie directly on the line between their predecessor and their
//// successor and replace them with either of them.
//for(size_t i = 0; i < cnt; ++i) {
// IfcVector3& v1 = *(base+i), &v0 = *(base+(i?i-1:cnt-1)), &v2 = *(base+(i+1)%cnt);
// const IfcVector3& d0 = (v1-v0), &d1 = (v2-v1);
// const IfcFloat l0 = d0.SquareLength(), l1 = d1.SquareLength();
// if (!l0 || !l1) {
// continue;
// }
// const IfcFloat d = (d0/std::sqrt(l0))*(d1/std::sqrt(l1));
// if ( d >= 1.f-dotepsilon ) {
// v1 = v0;
// }
// else if ( d < -1.f+dotepsilon ) {
// v2 = v1;
// continue;
// }
//}
// drop any identical, adjacent vertices. this pass will collect the dropouts // drop any identical, adjacent vertices. this pass will collect the dropouts
// of the previous pass as a side-effect. // of the previous pass as a side-effect.
@ -440,78 +402,58 @@ void TempMesh::RemoveAdjacentDuplicates() {
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void TempMesh::Swap(TempMesh& other) void TempMesh::Swap(TempMesh& other) {
{
mVertcnt.swap(other.mVertcnt); mVertcnt.swap(other.mVertcnt);
mVerts.swap(other.mVerts); mVerts.swap(other.mVerts);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool IsTrue(const ::Assimp::STEP::EXPRESS::BOOLEAN& in) bool IsTrue(const ::Assimp::STEP::EXPRESS::BOOLEAN& in) {
{
return (std::string)in == "TRUE" || (std::string)in == "T"; return (std::string)in == "TRUE" || (std::string)in == "T";
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
IfcFloat ConvertSIPrefix(const std::string& prefix) IfcFloat ConvertSIPrefix(const std::string& prefix) {
{
if (prefix == "EXA") { if (prefix == "EXA") {
return 1e18f; return 1e18f;
} } else if (prefix == "PETA") {
else if (prefix == "PETA") {
return 1e15f; return 1e15f;
} } else if (prefix == "TERA") {
else if (prefix == "TERA") {
return 1e12f; return 1e12f;
} } else if (prefix == "GIGA") {
else if (prefix == "GIGA") {
return 1e9f; return 1e9f;
} } else if (prefix == "MEGA") {
else if (prefix == "MEGA") {
return 1e6f; return 1e6f;
} } else if (prefix == "KILO") {
else if (prefix == "KILO") {
return 1e3f; return 1e3f;
} } else if (prefix == "HECTO") {
else if (prefix == "HECTO") {
return 1e2f; return 1e2f;
} } else if (prefix == "DECA") {
else if (prefix == "DECA") {
return 1e-0f; return 1e-0f;
} } else if (prefix == "DECI") {
else if (prefix == "DECI") {
return 1e-1f; return 1e-1f;
} } else if (prefix == "CENTI") {
else if (prefix == "CENTI") {
return 1e-2f; return 1e-2f;
} } else if (prefix == "MILLI") {
else if (prefix == "MILLI") {
return 1e-3f; return 1e-3f;
} } else if (prefix == "MICRO") {
else if (prefix == "MICRO") {
return 1e-6f; return 1e-6f;
} } else if (prefix == "NANO") {
else if (prefix == "NANO") {
return 1e-9f; return 1e-9f;
} } else if (prefix == "PICO") {
else if (prefix == "PICO") {
return 1e-12f; return 1e-12f;
} } else if (prefix == "FEMTO") {
else if (prefix == "FEMTO") {
return 1e-15f; return 1e-15f;
} } else if (prefix == "ATTO") {
else if (prefix == "ATTO") {
return 1e-18f; return 1e-18f;
} } else {
else {
IFCImporter::LogError("Unrecognized SI prefix: ", prefix); IFCImporter::LogError("Unrecognized SI prefix: ", prefix);
return 1; return 1;
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ConvertColor(aiColor4D& out, const Schema_2x3::IfcColourRgb& in) void ConvertColor(aiColor4D& out, const Schema_2x3::IfcColourRgb& in) {
{
out.r = static_cast<float>( in.Red ); out.r = static_cast<float>( in.Red );
out.g = static_cast<float>( in.Green ); out.g = static_cast<float>( in.Green );
out.b = static_cast<float>( in.Blue ); out.b = static_cast<float>( in.Blue );
@ -519,8 +461,10 @@ void ConvertColor(aiColor4D& out, const Schema_2x3::IfcColourRgb& in)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ConvertColor(aiColor4D& out, const Schema_2x3::IfcColourOrFactor& in,ConversionData& conv,const aiColor4D* base) void ConvertColor(aiColor4D& out,
{ const Schema_2x3::IfcColourOrFactor& in,
ConversionData& conv,
const aiColor4D* base) {
if (const ::Assimp::STEP::EXPRESS::REAL* const r = in.ToPtr<::Assimp::STEP::EXPRESS::REAL>()) { if (const ::Assimp::STEP::EXPRESS::REAL* const r = in.ToPtr<::Assimp::STEP::EXPRESS::REAL>()) {
out.r = out.g = out.b = static_cast<float>(*r); out.r = out.g = out.b = static_cast<float>(*r);
if(base) { if(base) {
@ -528,20 +472,18 @@ void ConvertColor(aiColor4D& out, const Schema_2x3::IfcColourOrFactor& in,Conver
out.g *= static_cast<float>( base->g ); out.g *= static_cast<float>( base->g );
out.b *= static_cast<float>( base->b ); out.b *= static_cast<float>( base->b );
out.a = static_cast<float>( base->a ); out.a = static_cast<float>( base->a );
} else {
out.a = 1.0;
} }
else out.a = 1.0; } else if (const Schema_2x3::IfcColourRgb* const rgb = in.ResolveSelectPtr<Schema_2x3::IfcColourRgb>(conv.db)) {
}
else if (const Schema_2x3::IfcColourRgb* const rgb = in.ResolveSelectPtr<Schema_2x3::IfcColourRgb>(conv.db)) {
ConvertColor(out,*rgb); ConvertColor(out,*rgb);
} } else {
else {
IFCImporter::LogWarn("skipping unknown IfcColourOrFactor entity"); IFCImporter::LogWarn("skipping unknown IfcColourOrFactor entity");
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ConvertCartesianPoint(IfcVector3& out, const Schema_2x3::IfcCartesianPoint& in) void ConvertCartesianPoint(IfcVector3& out, const Schema_2x3::IfcCartesianPoint& in) {
{
out = IfcVector3(); out = IfcVector3();
for(size_t i = 0; i < in.Coordinates.size(); ++i) { for(size_t i = 0; i < in.Coordinates.size(); ++i) {
out[static_cast<unsigned int>(i)] = in.Coordinates[i]; out[static_cast<unsigned int>(i)] = in.Coordinates[i];
@ -549,15 +491,13 @@ void ConvertCartesianPoint(IfcVector3& out, const Schema_2x3::IfcCartesianPoint&
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ConvertVector(IfcVector3& out, const Schema_2x3::IfcVector& in) void ConvertVector(IfcVector3& out, const Schema_2x3::IfcVector& in) {
{
ConvertDirection(out,in.Orientation); ConvertDirection(out,in.Orientation);
out *= in.Magnitude; out *= in.Magnitude;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ConvertDirection(IfcVector3& out, const Schema_2x3::IfcDirection& in) void ConvertDirection(IfcVector3& out, const Schema_2x3::IfcDirection& in) {
{
out = IfcVector3(); out = IfcVector3();
for(size_t i = 0; i < in.DirectionRatios.size(); ++i) { for(size_t i = 0; i < in.DirectionRatios.size(); ++i) {
out[static_cast<unsigned int>(i)] = in.DirectionRatios[i]; out[static_cast<unsigned int>(i)] = in.DirectionRatios[i];
@ -571,8 +511,7 @@ void ConvertDirection(IfcVector3& out, const Schema_2x3::IfcDirection& in)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void AssignMatrixAxes(IfcMatrix4& out, const IfcVector3& x, const IfcVector3& y, const IfcVector3& z) void AssignMatrixAxes(IfcMatrix4& out, const IfcVector3& x, const IfcVector3& y, const IfcVector3& z) {
{
out.a1 = x.x; out.a1 = x.x;
out.b1 = x.y; out.b1 = x.y;
out.c1 = x.z; out.c1 = x.z;
@ -587,8 +526,7 @@ void AssignMatrixAxes(IfcMatrix4& out, const IfcVector3& x, const IfcVector3& y,
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ConvertAxisPlacement(IfcMatrix4& out, const Schema_2x3::IfcAxis2Placement3D& in) void ConvertAxisPlacement(IfcMatrix4& out, const Schema_2x3::IfcAxis2Placement3D& in) {
{
IfcVector3 loc; IfcVector3 loc;
ConvertCartesianPoint(loc,in.Location); ConvertCartesianPoint(loc,in.Location);
@ -612,8 +550,7 @@ void ConvertAxisPlacement(IfcMatrix4& out, const Schema_2x3::IfcAxis2Placement3D
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ConvertAxisPlacement(IfcMatrix4& out, const Schema_2x3::IfcAxis2Placement2D& in) void ConvertAxisPlacement(IfcMatrix4& out, const Schema_2x3::IfcAxis2Placement2D& in) {
{
IfcVector3 loc; IfcVector3 loc;
ConvertCartesianPoint(loc,in.Location); ConvertCartesianPoint(loc,in.Location);
@ -629,34 +566,28 @@ void ConvertAxisPlacement(IfcMatrix4& out, const Schema_2x3::IfcAxis2Placement2D
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ConvertAxisPlacement(IfcVector3& axis, IfcVector3& pos, const Schema_2x3::IfcAxis1Placement& in) void ConvertAxisPlacement(IfcVector3& axis, IfcVector3& pos, const Schema_2x3::IfcAxis1Placement& in) {
{
ConvertCartesianPoint(pos,in.Location); ConvertCartesianPoint(pos,in.Location);
if (in.Axis) { if (in.Axis) {
ConvertDirection(axis,in.Axis.Get()); ConvertDirection(axis,in.Axis.Get());
} } else {
else {
axis = IfcVector3(0.f,0.f,1.f); axis = IfcVector3(0.f,0.f,1.f);
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ConvertAxisPlacement(IfcMatrix4& out, const Schema_2x3::IfcAxis2Placement& in, ConversionData& conv) void ConvertAxisPlacement(IfcMatrix4& out, const Schema_2x3::IfcAxis2Placement& in, ConversionData& conv) {
{
if(const Schema_2x3::IfcAxis2Placement3D* pl3 = in.ResolveSelectPtr<Schema_2x3::IfcAxis2Placement3D>(conv.db)) { if(const Schema_2x3::IfcAxis2Placement3D* pl3 = in.ResolveSelectPtr<Schema_2x3::IfcAxis2Placement3D>(conv.db)) {
ConvertAxisPlacement(out,*pl3); ConvertAxisPlacement(out,*pl3);
} } else if(const Schema_2x3::IfcAxis2Placement2D* pl2 = in.ResolveSelectPtr<Schema_2x3::IfcAxis2Placement2D>(conv.db)) {
else if(const Schema_2x3::IfcAxis2Placement2D* pl2 = in.ResolveSelectPtr<Schema_2x3::IfcAxis2Placement2D>(conv.db)) {
ConvertAxisPlacement(out,*pl2); ConvertAxisPlacement(out,*pl2);
} } else {
else {
IFCImporter::LogWarn("skipping unknown IfcAxis2Placement entity"); IFCImporter::LogWarn("skipping unknown IfcAxis2Placement entity");
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ConvertTransformOperator(IfcMatrix4& out, const Schema_2x3::IfcCartesianTransformationOperator& op) void ConvertTransformOperator(IfcMatrix4& out, const Schema_2x3::IfcCartesianTransformationOperator& op) {
{
IfcVector3 loc; IfcVector3 loc;
ConvertCartesianPoint(loc,op.LocalOrigin); ConvertCartesianPoint(loc,op.LocalOrigin);
@ -677,14 +608,12 @@ void ConvertTransformOperator(IfcMatrix4& out, const Schema_2x3::IfcCartesianTra
IfcMatrix4::Translation(loc,locm); IfcMatrix4::Translation(loc,locm);
AssignMatrixAxes(out,x,y,z); AssignMatrixAxes(out,x,y,z);
IfcVector3 vscale; IfcVector3 vscale;
if (const Schema_2x3::IfcCartesianTransformationOperator3DnonUniform* nuni = op.ToPtr<Schema_2x3::IfcCartesianTransformationOperator3DnonUniform>()) { if (const Schema_2x3::IfcCartesianTransformationOperator3DnonUniform* nuni = op.ToPtr<Schema_2x3::IfcCartesianTransformationOperator3DnonUniform>()) {
vscale.x = nuni->Scale?op.Scale.Get():1.f; vscale.x = nuni->Scale?op.Scale.Get():1.f;
vscale.y = nuni->Scale2?nuni->Scale2.Get():1.f; vscale.y = nuni->Scale2?nuni->Scale2.Get():1.f;
vscale.z = nuni->Scale3?nuni->Scale3.Get():1.f; vscale.z = nuni->Scale3?nuni->Scale3.Get():1.f;
} } else {
else {
const IfcFloat sc = op.Scale?op.Scale.Get():1.f; const IfcFloat sc = op.Scale?op.Scale.Get():1.f;
vscale = IfcVector3(sc,sc,sc); vscale = IfcVector3(sc,sc,sc);
} }
@ -695,8 +624,7 @@ void ConvertTransformOperator(IfcMatrix4& out, const Schema_2x3::IfcCartesianTra
out = locm * out * s; out = locm * out * s;
} }
} // ! IFC } // ! IFC
} // ! Assimp } // ! Assimp
#endif #endif // ASSIMP_BUILD_NO_IFC_IMPORTER

View File

@ -927,22 +927,22 @@ ELSE()
ENDIF() ENDIF()
# polyclipping # polyclipping
IF(ASSIMP_HUNTER_ENABLED) #IF(ASSIMP_HUNTER_ENABLED)
hunter_add_package(polyclipping) # hunter_add_package(polyclipping)
find_package(polyclipping CONFIG REQUIRED) # find_package(polyclipping CONFIG REQUIRED)
ELSE() #ELSE()
SET( Clipper_SRCS SET( Clipper_SRCS
../contrib/clipper/clipper.hpp ../contrib/clipper/clipper.hpp
../contrib/clipper/clipper.cpp ../contrib/clipper/clipper.cpp
) )
SOURCE_GROUP( Contrib\\Clipper FILES ${Clipper_SRCS}) SOURCE_GROUP( Contrib\\Clipper FILES ${Clipper_SRCS})
ENDIF() #ENDIF()
# poly2tri # poly2tri
IF(ASSIMP_HUNTER_ENABLED) #IF(ASSIMP_HUNTER_ENABLED)
hunter_add_package(poly2tri) # hunter_add_package(poly2tri)
find_package(poly2tri CONFIG REQUIRED) # find_package(poly2tri CONFIG REQUIRED)
ELSE() #ELSE()
SET( Poly2Tri_SRCS SET( Poly2Tri_SRCS
../contrib/poly2tri/poly2tri/common/shapes.cc ../contrib/poly2tri/poly2tri/common/shapes.cc
../contrib/poly2tri/poly2tri/common/shapes.h ../contrib/poly2tri/poly2tri/common/shapes.h
@ -957,7 +957,7 @@ ELSE()
../contrib/poly2tri/poly2tri/sweep/sweep_context.h ../contrib/poly2tri/poly2tri/sweep/sweep_context.h
) )
SOURCE_GROUP( Contrib\\Poly2Tri FILES ${Poly2Tri_SRCS}) SOURCE_GROUP( Contrib\\Poly2Tri FILES ${Poly2Tri_SRCS})
ENDIF() #ENDIF()
# minizip/unzip # minizip/unzip
IF(ASSIMP_HUNTER_ENABLED) IF(ASSIMP_HUNTER_ENABLED)
@ -1267,9 +1267,9 @@ TARGET_INCLUDE_DIRECTORIES ( assimp PUBLIC
IF(ASSIMP_HUNTER_ENABLED) IF(ASSIMP_HUNTER_ENABLED)
TARGET_LINK_LIBRARIES(assimp TARGET_LINK_LIBRARIES(assimp
PUBLIC PUBLIC
polyclipping::polyclipping #polyclipping::polyclipping
openddlparser::openddl_parser openddlparser::openddl_parser
poly2tri::poly2tri #poly2tri::poly2tri
minizip::minizip minizip::minizip
ZLIB::zlib ZLIB::zlib
RapidJSON::rapidjson RapidJSON::rapidjson

View File

@ -1,7 +1,3 @@
The Clipper code library, the "Software" (that includes Delphi, C++ & C#
source code, accompanying samples and documentation), has been released
under the following license, terms and conditions:
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003
http://www.boost.org/LICENSE_1_0.txt http://www.boost.org/LICENSE_1_0.txt
@ -26,4 +22,3 @@ SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,10 @@
/******************************************************************************* /*******************************************************************************
* * * *
* Author : Angus Johnson * * Author : Angus Johnson *
* Version : 4.8.8 * * Version : 6.4.2 *
* Date : 30 August 2012 * * Date : 27 February 2017 *
* Website : http://www.angusj.com * * Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2012 * * Copyright : Angus Johnson 2010-2017 *
* * * *
* License: * * License: *
* Use, modification & distribution is subject to Boost Software License Ver 1. * * Use, modification & distribution is subject to Boost Software License Ver 1. *
@ -34,11 +34,30 @@
#ifndef clipper_hpp #ifndef clipper_hpp
#define clipper_hpp #define clipper_hpp
#define CLIPPER_VERSION "6.4.2"
//use_int32: When enabled 32bit ints are used instead of 64bit ints. This
//improve performance but coordinate values are limited to the range +/- 46340
//#define use_int32
//use_xyz: adds a Z member to IntPoint. Adds a minor cost to perfomance.
//#define use_xyz
//use_lines: Enables line clipping. Adds a very minor cost to performance.
#define use_lines
//use_deprecated: Enables temporary support for the obsolete functions
//#define use_deprecated
#include <vector> #include <vector>
#include <list>
#include <set>
#include <stdexcept> #include <stdexcept>
#include <cstring> #include <cstring>
#include <cstdlib> #include <cstdlib>
#include <ostream> #include <ostream>
#include <functional>
#include <queue>
namespace ClipperLib { namespace ClipperLib {
@ -50,129 +69,150 @@ enum PolyType { ptSubject, ptClip };
//see http://glprogramming.com/red/chapter11.html //see http://glprogramming.com/red/chapter11.html
enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative }; enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative };
typedef signed long long long64; #ifdef use_int32
typedef int cInt;
static cInt const loRange = 0x7FFF;
static cInt const hiRange = 0x7FFF;
#else
typedef signed long long cInt;
static cInt const loRange = 0x3FFFFFFF;
static cInt const hiRange = 0x3FFFFFFFFFFFFFFFLL;
typedef signed long long long64; //used by Int128 class
typedef unsigned long long ulong64; typedef unsigned long long ulong64;
#endif
struct IntPoint { struct IntPoint {
public: cInt X;
long64 X; cInt Y;
long64 Y; #ifdef use_xyz
IntPoint(long64 x = 0, long64 y = 0): X(x), Y(y) {}; cInt Z;
friend std::ostream& operator <<(std::ostream &s, IntPoint &p); IntPoint(cInt x = 0, cInt y = 0, cInt z = 0): X(x), Y(y), Z(z) {};
#else
IntPoint(cInt x = 0, cInt y = 0): X(x), Y(y) {};
#endif
friend inline bool operator== (const IntPoint& a, const IntPoint& b)
{
return a.X == b.X && a.Y == b.Y;
}
friend inline bool operator!= (const IntPoint& a, const IntPoint& b)
{
return a.X != b.X || a.Y != b.Y;
}
}; };
//------------------------------------------------------------------------------
typedef std::vector< IntPoint > Polygon; typedef std::vector< IntPoint > Path;
typedef std::vector< Polygon > Polygons; typedef std::vector< Path > Paths;
std::ostream& operator <<(std::ostream &s, Polygon &p); inline Path& operator <<(Path& poly, const IntPoint& p) {poly.push_back(p); return poly;}
std::ostream& operator <<(std::ostream &s, Polygons &p); inline Paths& operator <<(Paths& polys, const Path& p) {polys.push_back(p); return polys;}
struct ExPolygon { std::ostream& operator <<(std::ostream &s, const IntPoint &p);
Polygon outer; std::ostream& operator <<(std::ostream &s, const Path &p);
Polygons holes; std::ostream& operator <<(std::ostream &s, const Paths &p);
struct DoublePoint
{
double X;
double Y;
DoublePoint(double x = 0, double y = 0) : X(x), Y(y) {}
DoublePoint(IntPoint ip) : X((double)ip.X), Y((double)ip.Y) {}
}; };
typedef std::vector< ExPolygon > ExPolygons; //------------------------------------------------------------------------------
#ifdef use_xyz
typedef void (*ZFillCallback)(IntPoint& e1bot, IntPoint& e1top, IntPoint& e2bot, IntPoint& e2top, IntPoint& pt);
#endif
enum InitOptions {ioReverseSolution = 1, ioStrictlySimple = 2, ioPreserveCollinear = 4};
enum JoinType {jtSquare, jtRound, jtMiter}; enum JoinType {jtSquare, jtRound, jtMiter};
enum EndType {etClosedPolygon, etClosedLine, etOpenButt, etOpenSquare, etOpenRound};
bool Orientation(const Polygon &poly); class PolyNode;
double Area(const Polygon &poly); typedef std::vector< PolyNode* > PolyNodes;
void OffsetPolygons(const Polygons &in_polys, Polygons &out_polys,
double delta, JoinType jointype = jtSquare, double MiterLimit = 2);
void SimplifyPolygon(const Polygon &in_poly, Polygons &out_polys, PolyFillType fillType = pftEvenOdd);
void SimplifyPolygons(const Polygons &in_polys, Polygons &out_polys, PolyFillType fillType = pftEvenOdd);
void SimplifyPolygons(Polygons &polys, PolyFillType fillType = pftEvenOdd);
void ReversePolygon(Polygon& p); class PolyNode
void ReversePolygons(Polygons& p); {
public:
//used internally ... PolyNode();
enum EdgeSide { esNeither = 0, esLeft = 1, esRight = 2, esBoth = 3 }; virtual ~PolyNode(){};
enum IntersectProtects { ipNone = 0, ipLeft = 1, ipRight = 2, ipBoth = 3 }; Path Contour;
PolyNodes Childs;
struct TEdge { PolyNode* Parent;
long64 xbot; PolyNode* GetNext() const;
long64 ybot; bool IsHole() const;
long64 xcurr; bool IsOpen() const;
long64 ycurr; int ChildCount() const;
long64 xtop; private:
long64 ytop; //PolyNode& operator =(PolyNode& other);
double dx; unsigned Index; //node index in Parent.Childs
long64 tmpX; bool m_IsOpen;
PolyType polyType; JoinType m_jointype;
EdgeSide side; EndType m_endtype;
int windDelta; //1 or -1 depending on winding direction PolyNode* GetNextSiblingUp() const;
int windCnt; void AddChild(PolyNode& child);
int windCnt2; //winding count of the opposite polytype friend class Clipper; //to access Index
int outIdx; friend class ClipperOffset;
TEdge *next;
TEdge *prev;
TEdge *nextInLML;
TEdge *nextInAEL;
TEdge *prevInAEL;
TEdge *nextInSEL;
TEdge *prevInSEL;
}; };
struct IntersectNode { class PolyTree: public PolyNode
TEdge *edge1; {
TEdge *edge2; public:
IntPoint pt; ~PolyTree(){ Clear(); };
IntersectNode *next; PolyNode* GetFirst() const;
void Clear();
int Total() const;
private:
//PolyTree& operator =(PolyTree& other);
PolyNodes AllNodes;
friend class Clipper; //to access AllNodes
}; };
struct LocalMinima { bool Orientation(const Path &poly);
long64 Y; double Area(const Path &poly);
TEdge *leftBound; int PointInPolygon(const IntPoint &pt, const Path &path);
TEdge *rightBound;
LocalMinima *next;
};
struct Scanbeam { void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType = pftEvenOdd);
long64 Y; void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType = pftEvenOdd);
Scanbeam *next; void SimplifyPolygons(Paths &polys, PolyFillType fillType = pftEvenOdd);
};
struct OutPt; //forward declaration void CleanPolygon(const Path& in_poly, Path& out_poly, double distance = 1.415);
void CleanPolygon(Path& poly, double distance = 1.415);
void CleanPolygons(const Paths& in_polys, Paths& out_polys, double distance = 1.415);
void CleanPolygons(Paths& polys, double distance = 1.415);
struct OutRec { void MinkowskiSum(const Path& pattern, const Path& path, Paths& solution, bool pathIsClosed);
int idx; void MinkowskiSum(const Path& pattern, const Paths& paths, Paths& solution, bool pathIsClosed);
bool isHole; void MinkowskiDiff(const Path& poly1, const Path& poly2, Paths& solution);
OutRec *FirstLeft;
OutRec *AppendLink;
OutPt *pts;
OutPt *bottomPt;
OutPt *bottomFlag;
EdgeSide sides;
};
struct OutPt { void PolyTreeToPaths(const PolyTree& polytree, Paths& paths);
int idx; void ClosedPathsFromPolyTree(const PolyTree& polytree, Paths& paths);
IntPoint pt; void OpenPathsFromPolyTree(PolyTree& polytree, Paths& paths);
OutPt *next;
OutPt *prev;
};
struct JoinRec { void ReversePath(Path& p);
IntPoint pt1a; void ReversePaths(Paths& p);
IntPoint pt1b;
int poly1Idx;
IntPoint pt2a;
IntPoint pt2b;
int poly2Idx;
};
struct HorzJoinRec { struct IntRect { cInt left; cInt top; cInt right; cInt bottom; };
TEdge *edge;
int savedIdx;
};
struct IntRect { long64 left; long64 top; long64 right; long64 bottom; }; //enums that are used internally ...
enum EdgeSide { esLeft = 1, esRight = 2};
//forward declarations (for stuff used internally) ...
struct TEdge;
struct IntersectNode;
struct LocalMinimum;
struct OutPt;
struct OutRec;
struct Join;
typedef std::vector < OutRec* > PolyOutList; typedef std::vector < OutRec* > PolyOutList;
typedef std::vector < TEdge* > EdgeList; typedef std::vector < TEdge* > EdgeList;
typedef std::vector < JoinRec* > JoinList; typedef std::vector < Join* > JoinList;
typedef std::vector < HorzJoinRec* > HorzJoinList; typedef std::vector < IntersectNode* > IntersectList;
//------------------------------------------------------------------------------
//ClipperBase is the ancestor to the Clipper class. It should not be //ClipperBase is the ancestor to the Clipper class. It should not be
//instantiated directly. This class simply abstracts the conversion of sets of //instantiated directly. This class simply abstracts the conversion of sets of
@ -182,110 +222,170 @@ class ClipperBase
public: public:
ClipperBase(); ClipperBase();
virtual ~ClipperBase(); virtual ~ClipperBase();
bool AddPolygon(const Polygon &pg, PolyType polyType); virtual bool AddPath(const Path &pg, PolyType PolyTyp, bool Closed);
bool AddPolygons( const Polygons &ppg, PolyType polyType); bool AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed);
virtual void Clear(); virtual void Clear();
IntRect GetBounds(); IntRect GetBounds();
bool PreserveCollinear() {return m_PreserveCollinear;};
void PreserveCollinear(bool value) {m_PreserveCollinear = value;};
protected: protected:
void DisposeLocalMinimaList(); void DisposeLocalMinimaList();
TEdge* AddBoundsToLML(TEdge *e); TEdge* AddBoundsToLML(TEdge *e, bool IsClosed);
void PopLocalMinima();
virtual void Reset(); virtual void Reset();
void InsertLocalMinima(LocalMinima *newLm); TEdge* ProcessBound(TEdge* E, bool IsClockwise);
LocalMinima *m_CurrentLM; void InsertScanbeam(const cInt Y);
LocalMinima *m_MinimaList; bool PopScanbeam(cInt &Y);
bool LocalMinimaPending();
bool PopLocalMinima(cInt Y, const LocalMinimum *&locMin);
OutRec* CreateOutRec();
void DisposeAllOutRecs();
void DisposeOutRec(PolyOutList::size_type index);
void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2);
void DeleteFromAEL(TEdge *e);
void UpdateEdgeIntoAEL(TEdge *&e);
typedef std::vector<LocalMinimum> MinimaList;
MinimaList::iterator m_CurrentLM;
MinimaList m_MinimaList;
bool m_UseFullRange; bool m_UseFullRange;
EdgeList m_edges; EdgeList m_edges;
bool m_PreserveCollinear;
bool m_HasOpenPaths;
PolyOutList m_PolyOuts;
TEdge *m_ActiveEdges;
typedef std::priority_queue<cInt> ScanbeamList;
ScanbeamList m_Scanbeam;
}; };
//------------------------------------------------------------------------------
class Clipper : public virtual ClipperBase class Clipper : public virtual ClipperBase
{ {
public: public:
Clipper(); Clipper(int initOptions = 0);
~Clipper();
bool Execute(ClipType clipType, bool Execute(ClipType clipType,
Polygons &solution, Paths &solution,
PolyFillType subjFillType = pftEvenOdd, PolyFillType fillType = pftEvenOdd);
PolyFillType clipFillType = pftEvenOdd);
bool Execute(ClipType clipType, bool Execute(ClipType clipType,
ExPolygons &solution, Paths &solution,
PolyFillType subjFillType = pftEvenOdd, PolyFillType subjFillType,
PolyFillType clipFillType = pftEvenOdd); PolyFillType clipFillType);
void Clear(); bool Execute(ClipType clipType,
PolyTree &polytree,
PolyFillType fillType = pftEvenOdd);
bool Execute(ClipType clipType,
PolyTree &polytree,
PolyFillType subjFillType,
PolyFillType clipFillType);
bool ReverseSolution() { return m_ReverseOutput; }; bool ReverseSolution() { return m_ReverseOutput; };
void ReverseSolution(bool value) {m_ReverseOutput = value;}; void ReverseSolution(bool value) {m_ReverseOutput = value;};
bool StrictlySimple() {return m_StrictSimple;};
void StrictlySimple(bool value) {m_StrictSimple = value;};
//set the callback function for z value filling on intersections (otherwise Z is 0)
#ifdef use_xyz
void ZFillFunction(ZFillCallback zFillFunc);
#endif
protected: protected:
void Reset(); virtual bool ExecuteInternal();
virtual bool ExecuteInternal(bool fixHoleLinkages);
private: private:
PolyOutList m_PolyOuts;
JoinList m_Joins; JoinList m_Joins;
HorzJoinList m_HorizJoins; JoinList m_GhostJoins;
IntersectList m_IntersectList;
ClipType m_ClipType; ClipType m_ClipType;
Scanbeam *m_Scanbeam; typedef std::list<cInt> MaximaList;
TEdge *m_ActiveEdges; MaximaList m_Maxima;
TEdge *m_SortedEdges; TEdge *m_SortedEdges;
IntersectNode *m_IntersectNodes;
bool m_ExecuteLocked; bool m_ExecuteLocked;
PolyFillType m_ClipFillType; PolyFillType m_ClipFillType;
PolyFillType m_SubjFillType; PolyFillType m_SubjFillType;
bool m_ReverseOutput; bool m_ReverseOutput;
void DisposeScanbeamList(); bool m_UsingPolyTree;
bool m_StrictSimple;
#ifdef use_xyz
ZFillCallback m_ZFill; //custom callback
#endif
void SetWindingCount(TEdge& edge); void SetWindingCount(TEdge& edge);
bool IsEvenOddFillType(const TEdge& edge) const; bool IsEvenOddFillType(const TEdge& edge) const;
bool IsEvenOddAltFillType(const TEdge& edge) const; bool IsEvenOddAltFillType(const TEdge& edge) const;
void InsertScanbeam(const long64 Y); void InsertLocalMinimaIntoAEL(const cInt botY);
long64 PopScanbeam(); void InsertEdgeIntoAEL(TEdge *edge, TEdge* startEdge);
void InsertLocalMinimaIntoAEL(const long64 botY);
void InsertEdgeIntoAEL(TEdge *edge);
void AddEdgeToSEL(TEdge *edge); void AddEdgeToSEL(TEdge *edge);
bool PopEdgeFromSEL(TEdge *&edge);
void CopyAELToSEL(); void CopyAELToSEL();
void DeleteFromSEL(TEdge *e); void DeleteFromSEL(TEdge *e);
void DeleteFromAEL(TEdge *e);
void UpdateEdgeIntoAEL(TEdge *&e);
void SwapPositionsInSEL(TEdge *edge1, TEdge *edge2); void SwapPositionsInSEL(TEdge *edge1, TEdge *edge2);
bool IsContributing(const TEdge& edge) const; bool IsContributing(const TEdge& edge) const;
bool IsTopHorz(const long64 XPos); bool IsTopHorz(const cInt XPos);
void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2); void DoMaxima(TEdge *e);
void DoMaxima(TEdge *e, long64 topY);
void ProcessHorizontals(); void ProcessHorizontals();
void ProcessHorizontal(TEdge *horzEdge); void ProcessHorizontal(TEdge *horzEdge);
void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
void AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); OutPt* AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
OutRec* GetOutRec(int idx);
void AppendPolygon(TEdge *e1, TEdge *e2); void AppendPolygon(TEdge *e1, TEdge *e2);
void DoEdge1(TEdge *edge1, TEdge *edge2, const IntPoint &pt); void IntersectEdges(TEdge *e1, TEdge *e2, IntPoint &pt);
void DoEdge2(TEdge *edge1, TEdge *edge2, const IntPoint &pt); OutPt* AddOutPt(TEdge *e, const IntPoint &pt);
void DoBothEdges(TEdge *edge1, TEdge *edge2, const IntPoint &pt); OutPt* GetLastOutPt(TEdge *e);
void IntersectEdges(TEdge *e1, TEdge *e2, bool ProcessIntersections(const cInt topY);
const IntPoint &pt, IntersectProtects protects); void BuildIntersectList(const cInt topY);
OutRec* CreateOutRec();
void AddOutPt(TEdge *e, const IntPoint &pt);
void DisposeBottomPt(OutRec &outRec);
void DisposeAllPolyPts();
void DisposeOutRec(PolyOutList::size_type index);
bool ProcessIntersections(const long64 botY, const long64 topY);
void AddIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt);
void BuildIntersectList(const long64 botY, const long64 topY);
void ProcessIntersectList(); void ProcessIntersectList();
void ProcessEdgesAtTopOfScanbeam(const long64 topY); void ProcessEdgesAtTopOfScanbeam(const cInt topY);
void BuildResult(Polygons& polys); void BuildResult(Paths& polys);
void BuildResultEx(ExPolygons& polys); void BuildResult2(PolyTree& polytree);
void SetHoleState(TEdge *e, OutRec *OutRec); void SetHoleState(TEdge *e, OutRec *outrec);
void DisposeIntersectNodes(); void DisposeIntersectNodes();
bool FixupIntersections(); bool FixupIntersectionOrder();
void FixupOutPolygon(OutRec &outRec); void FixupOutPolygon(OutRec &outrec);
void FixupOutPolyline(OutRec &outrec);
bool IsHole(TEdge *e); bool IsHole(TEdge *e);
void FixHoleLinkage(OutRec *outRec); bool FindOwnerFromSplitRecs(OutRec &outRec, OutRec *&currOrfl);
void CheckHoleLinkages1(OutRec *outRec1, OutRec *outRec2); void FixHoleLinkage(OutRec &outrec);
void CheckHoleLinkages2(OutRec *outRec1, OutRec *outRec2); void AddJoin(OutPt *op1, OutPt *op2, const IntPoint offPt);
void AddJoin(TEdge *e1, TEdge *e2, int e1OutIdx = -1, int e2OutIdx = -1);
void ClearJoins(); void ClearJoins();
void AddHorzJoin(TEdge *e, int idx); void ClearGhostJoins();
void ClearHorzJoins(); void AddGhostJoin(OutPt *op, const IntPoint offPt);
void JoinCommonEdges(bool fixHoleLinkages); bool JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2);
void JoinCommonEdges();
void DoSimplePolygons();
void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec);
void FixupFirstLefts2(OutRec* InnerOutRec, OutRec* OuterOutRec);
void FixupFirstLefts3(OutRec* OldOutRec, OutRec* NewOutRec);
#ifdef use_xyz
void SetZ(IntPoint& pt, TEdge& e1, TEdge& e2);
#endif
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
class ClipperOffset
{
public:
ClipperOffset(double miterLimit = 2.0, double roundPrecision = 0.25);
~ClipperOffset();
void AddPath(const Path& path, JoinType joinType, EndType endType);
void AddPaths(const Paths& paths, JoinType joinType, EndType endType);
void Execute(Paths& solution, double delta);
void Execute(PolyTree& solution, double delta);
void Clear();
double MiterLimit;
double ArcTolerance;
private:
Paths m_destPolys;
Path m_srcPoly;
Path m_destPoly;
std::vector<DoublePoint> m_normals;
double m_delta, m_sinA, m_sin, m_cos;
double m_miterLim, m_StepsPerRad;
IntPoint m_lowest;
PolyNode m_polyNodes;
void FixOrientations();
void DoOffset(double delta);
void OffsetPoint(int j, int& k, JoinType jointype);
void DoSquare(int j, int k);
void DoMiter(int j, int k, double r);
void DoRound(int j, int k);
};
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
class clipperException : public std::exception class clipperException : public std::exception

View File

@ -0,0 +1,74 @@
MiniZip - Copyright (c) 1998-2010 - by Gilles Vollant - version 1.1 64 bits from Mathias Svensson
Introduction
---------------------
MiniZip 1.1 is built from MiniZip 1.0 by Gilles Vollant ( http://www.winimage.com/zLibDll/minizip.html )
When adding ZIP64 support into minizip it would result into risk of breaking compatibility with minizip 1.0.
All possible work was done for compatibility.
Background
---------------------
When adding ZIP64 support Mathias Svensson found that Even Rouault have added ZIP64
support for unzip.c into minizip for a open source project called gdal ( http://www.gdal.org/ )
That was used as a starting point. And after that ZIP64 support was added to zip.c
some refactoring and code cleanup was also done.
Changed from MiniZip 1.0 to MiniZip 1.1
---------------------------------------
* Added ZIP64 support for unzip ( by Even Rouault )
* Added ZIP64 support for zip ( by Mathias Svensson )
* Reverted some changed that Even Rouault did.
* Bunch of patches received from Gulles Vollant that he received for MiniZip from various users.
* Added unzip patch for BZIP Compression method (patch create by Daniel Borca)
* Added BZIP Compress method for zip
* Did some refactoring and code cleanup
Credits
Gilles Vollant - Original MiniZip author
Even Rouault - ZIP64 unzip Support
Daniel Borca - BZip Compression method support in unzip
Mathias Svensson - ZIP64 zip support
Mathias Svensson - BZip Compression method support in zip
Resources
ZipLayout http://result42.com/projects/ZipFileLayout
Command line tool for Windows that shows the layout and information of the headers in a zip archive.
Used when debugging and validating the creation of zip files using MiniZip64
ZIP App Note http://www.pkware.com/documents/casestudies/APPNOTE.TXT
Zip File specification
Notes.
* To be able to use BZip compression method in zip64.c or unzip64.c the BZIP2 lib is needed and HAVE_BZIP2 need to be defined.
License
----------------------------------------------------------
Condition of use and distribution are the same than zlib :
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
----------------------------------------------------------