Skip to content

Commit c086858

Browse files
Performance (#4)
1 parent e6e154e commit c086858

12 files changed

+581
-243
lines changed

CMakeLists.txt

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,24 @@ set( HEADERS
4646
include/ifcpp/Geometry/Extruder.h
4747
include/ifcpp/Geometry/Helpers.h
4848
include/ifcpp/Geometry/StyleConverter.h
49+
include/ifcpp/Geometry/Style.h
50+
include/ifcpp/Geometry/VisualObject.h
4951
${IFC_HEADERS} )
5052

5153

52-
53-
add_library( ${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS} )
54-
target_include_directories( ${PROJECT_NAME} PUBLIC include )
54+
add_library( ifcpp_lib STATIC ${SOURCES} ${HEADERS} )
55+
target_include_directories( ifcpp_lib PUBLIC include )
5556
if( MSVC )
56-
target_compile_options( ${PROJECT_NAME} PRIVATE "/bigobj" )
57+
set_source_files_properties( src/Ifc/Factories/EntityFactory.cpp PROPERTIES COMPILE_FLAGS /bigobj )
58+
set_source_files_properties( src/Ifc/Factories/TypeFactory.cpp PROPERTIES COMPILE_FLAGS /bigobj )
59+
endif()
60+
61+
62+
add_library( ${PROJECT_NAME} INTERFACE )
63+
target_link_libraries( ${PROJECT_NAME} INTERFACE ifcpp_lib )
64+
65+
find_package( OpenMP )
66+
if( OpenMP_CXX_FOUND )
67+
add_definitions( -DENABLE_OPENMP )
68+
target_link_libraries( ${PROJECT_NAME} INTERFACE OpenMP::OpenMP_CXX )
5769
endif()

README.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
It is fork off [IfcPlusPlus](https://github.com/ifcquery/ifcplusplus)
1+
Forked from [IfcPlusPlus](https://github.com/ifcquery/ifcplusplus)
22

3-
The approach to geometry generation has been redesigned, especially working with cycles (making holes without premature triangulation), as well as the "adapter" layer, with which it is possible to easily use different libraries for triangulation and CSG.
3+
The approach to geometry generation has been redesigned, especially working with loops (making holes without premature triangulation), as well as the "adapter" layer, with which it is possible to easily use different libraries for triangulation and CSG.
44

55
Take a look into [usage example](https://github.com/ExternPointer/ifcpp-example)
6-
7-
// TODO: Styles

include/ifcpp/Geometry/CAdapter.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@ concept CAdapter = CVector<typename TAdapter::TVector> &&
1919
std::vector<typename TAdapter::TMesh> meshes, std::vector<typename TAdapter::TPolyline> polylines, Matrix<typename TAdapter::TVector> matrix,
2020
std::vector<typename TAdapter::TVector> loop, std::vector<typename TAdapter::TMesh> operand1, std::vector<typename TAdapter::TMesh> operand2,
2121
std::vector<std::shared_ptr<Style>> styles ) {
22-
{ adapter.CreatePolyline( vertices ) } -> std::same_as<typename TAdapter::TPolyline>;
2322
{ adapter.CreateTriangle( vertices, indices ) } -> std::same_as<typename TAdapter::TTriangle>;
23+
{ adapter.CreatePolyline( vertices ) } -> std::same_as<typename TAdapter::TPolyline>;
2424
{ adapter.CreateMesh( triangles ) } -> std::same_as<typename TAdapter::TMesh>;
25+
{ adapter.CreatePolyline( polylines[0] ) } -> std::same_as<typename TAdapter::TPolyline>;
26+
{ adapter.CreateMesh( meshes[0] ) } -> std::same_as<typename TAdapter::TMesh>;
2527
{ adapter.CreateEntity( ifcObjectDifinition, meshes, polylines ) } -> std::same_as<typename TAdapter::TEntity>;
2628
{ adapter.Transform( &meshes, matrix ) } -> std::same_as<void>;
2729
{ adapter.Transform( &polylines, matrix ) } -> std::same_as<void>;

include/ifcpp/Geometry/CurveConverter.h

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
#pragma once
22

3+
#include <map>
4+
5+
#include "ifcpp/Model/OpenMPIncludes.h"
6+
37
#include "ifcpp/Geometry/CAdapter.h"
48
#include "ifcpp/Geometry/GeomUtils.h"
59
#include "ifcpp/Geometry/Matrix.h"
@@ -49,6 +53,11 @@ class CurveConverter {
4953
std::shared_ptr<SplineConverter<TVector>> m_splineConverter;
5054
std::shared_ptr<Parameters> m_parameters;
5155

56+
std::map<std::shared_ptr<IfcCurve>, TCurve> m_curveToPointsMap;
57+
#ifdef ENABLE_OPENMP
58+
Mutex m_curveToPointsMapMutex;
59+
#endif
60+
5261
public:
5362
CurveConverter( const std::shared_ptr<PrimitiveTypesConverter<TVector>>& primitivesConverter, const std::shared_ptr<GeomUtils<TVector>>& geomUtils,
5463
const std::shared_ptr<SplineConverter<TVector>> splineConverter, const std::shared_ptr<Parameters>& parameters )
@@ -58,16 +67,33 @@ class CurveConverter {
5867
, m_parameters( parameters ) {
5968
}
6069

70+
void ResetCaches() {
71+
#ifdef ENABLE_OPENMP
72+
ScopedLock lock( this->m_curveToPointsMapMutex );
73+
#endif
74+
this->m_curveToPointsMap = {};
75+
}
76+
6177
TCurve ConvertCurve( const std::shared_ptr<IfcCurve>& curve ) {
6278
// ENTITY IfcCurve ABSTRACT SUPERTYPE OF (ONEOF(IfcBoundedCurve, IfcConic, IfcLine, IfcOffsetCurve2D, IfcOffsetCurve3D, IfcPCurve))
6379

80+
{
81+
#ifdef ENABLE_OPENMP
82+
ScopedLock lock( this->m_curveToPointsMapMutex );
83+
#endif
84+
if( this->m_curveToPointsMap.contains( curve ) ) {
85+
return this->m_curveToPointsMap[ curve ];
86+
}
87+
}
88+
89+
TCurve result;
90+
6491
const auto boundedCurve = dynamic_pointer_cast<IfcBoundedCurve>( curve );
6592
if( boundedCurve ) {
6693
// ENTITY IfcBoundedCurve ABSTRACT SUPERTYPE OF (ONEOF(IfcCompositeCurve, IfcPolyline, IfcTrimmedCurve, IfcBSplineCurve))
6794

6895
const auto compositeCurve = dynamic_pointer_cast<IfcCompositeCurve>( boundedCurve );
6996
if( compositeCurve ) {
70-
TCurve result;
7197
for( const auto& segment: compositeCurve->m_Segments ) {
7298
TCurve segmentPoints;
7399
const auto compositeCurveSegment = dynamic_pointer_cast<IfcCompositeCurveSegment>( segment );
@@ -83,12 +109,12 @@ class CurveConverter {
83109
// TODO: Log error
84110
}
85111
}
86-
return this->m_geomUtils->SimplifyCurve( result );
112+
result = this->m_geomUtils->SimplifyCurve( result );
87113
}
88114

89115
const auto polyLine = dynamic_pointer_cast<IfcPolyline>( curve );
90116
if( polyLine ) {
91-
return this->m_geomUtils->SimplifyCurve( this->m_primitivesConverter->ConvertPoints( polyLine->m_Points ) );
117+
result = this->m_geomUtils->SimplifyCurve( this->m_primitivesConverter->ConvertPoints( polyLine->m_Points ) );
92118
}
93119

94120
const auto trimmedCurve = dynamic_pointer_cast<IfcTrimmedCurve>( boundedCurve );
@@ -111,19 +137,17 @@ class CurveConverter {
111137
radius1 = radius2 = (float)circle->m_Radius->m_value;
112138
}
113139

114-
TCurve result;
115140
int n = this->m_parameters->m_numVerticesPerCircle; // TODO: should be calculated from radius
116141
n = std::max( n, this->m_parameters->m_minNumVerticesPerArc );
117142
bool senseAgreement = !trimmedCurve->m_SenseAgreement || trimmedCurve->m_SenseAgreement->m_value;
118-
auto [ startAngle, openingAngle ] =
119-
this->GetTrimmingsForCircle( trimmedCurve->m_Trim1, trimmedCurve->m_Trim2, placement.GetTransformed( AVector::New() ), senseAgreement );
143+
auto [ startAngle, openingAngle ] = this->GetTrimmingsForCircle( trimmedCurve->m_Trim1, trimmedCurve->m_Trim2,
144+
placement.GetTransformed( AVector::New() ), senseAgreement );
120145
if( radius1 > this->m_parameters->m_epsilon && radius2 > this->m_parameters->m_epsilon ) {
121146
result = this->m_geomUtils->BuildEllipse( radius1, radius2, startAngle, openingAngle, n );
122147
} else {
123148
result.push_back( AVector::New() );
124149
}
125150
placement.TransformLoop( &result );
126-
return result;
127151
}
128152

129153
const auto line = dynamic_pointer_cast<IfcLine>( trimmedCurve->m_BasisCurve );
@@ -132,7 +156,7 @@ class CurveConverter {
132156
const auto direction = AVector::Normalized( this->m_primitivesConverter->ConvertVector( line->m_Dir ) );
133157
bool senseAgreement = !trimmedCurve->m_SenseAgreement || trimmedCurve->m_SenseAgreement->m_value;
134158
const auto [ l, r ] = this->GetTrimmingsForLine( trimmedCurve->m_Trim1, trimmedCurve->m_Trim2, origin, direction, senseAgreement );
135-
return {
159+
result = {
136160
origin + direction * l,
137161
origin + direction * r,
138162
};
@@ -142,13 +166,12 @@ class CurveConverter {
142166

143167
const auto bsplineCurve = dynamic_pointer_cast<IfcBSplineCurve>( boundedCurve );
144168
if( bsplineCurve ) {
145-
return this->m_splineConverter->ConvertBSplineCurve( bsplineCurve );
169+
result = this->m_splineConverter->ConvertBSplineCurve( bsplineCurve );
146170
}
147171

148172
const auto indexedPolyCurve = dynamic_pointer_cast<IfcIndexedPolyCurve>( boundedCurve );
149173
if( indexedPolyCurve ) {
150174
std::vector<TVector> points;
151-
TCurve result;
152175
const auto pointList2d = dynamic_pointer_cast<IfcCartesianPointList2D>( indexedPolyCurve->m_Points );
153176
if( pointList2d ) {
154177
points = this->m_primitivesConverter->ConvertPoints( pointList2d->m_CoordList );
@@ -178,7 +201,6 @@ class CurveConverter {
178201
}
179202
}
180203
}
181-
return result;
182204
}
183205
}
184206

@@ -199,7 +221,6 @@ class CurveConverter {
199221
radius1 = radius2 = (float)circle->m_Radius->m_value;
200222
}
201223

202-
TCurve result;
203224
int n = this->m_parameters->m_numVerticesPerCircle; // TODO: should be calculated from radius
204225
n = std::max( n, this->m_parameters->m_minNumVerticesPerArc );
205226
if( radius1 > this->m_parameters->m_epsilon && radius2 > this->m_parameters->m_epsilon ) {
@@ -208,14 +229,13 @@ class CurveConverter {
208229
result.push_back( AVector::New() );
209230
}
210231
placement.TransformLoop( &result );
211-
return result;
212232
}
213233

214234
const auto line = dynamic_pointer_cast<IfcLine>( curve );
215235
if( line && line->m_Pnt && line->m_Dir ) {
216236
const auto origin = this->m_primitivesConverter->ConvertPoint( line->m_Pnt );
217237
const auto direction = AVector::Normalized( this->m_primitivesConverter->ConvertVector( line->m_Dir ) );
218-
return {
238+
result = {
219239
origin - direction * this->m_parameters->m_modelMaxSize * 0.5f,
220240
origin + direction * this->m_parameters->m_modelMaxSize * 0.5f,
221241
};
@@ -224,23 +244,28 @@ class CurveConverter {
224244
const auto offset_curve_2d = dynamic_pointer_cast<IfcOffsetCurve2D>( curve );
225245
if( offset_curve_2d ) {
226246
// TODO: implement
227-
return {};
247+
result = {};
228248
}
229249

230250
const auto offset_curve_3d = dynamic_pointer_cast<IfcOffsetCurve3D>( curve );
231251
if( offset_curve_3d ) {
232252
// TODO: implement
233-
return {};
253+
result = {};
234254
}
235255

236256
const auto pcurve = dynamic_pointer_cast<IfcPcurve>( curve );
237257
if( pcurve ) {
238258
// TODO: implement
239-
return {};
259+
result = {};
240260
}
241261

242-
// TODO: Log error
243-
return {};
262+
{
263+
#ifdef ENABLE_OPENMP
264+
ScopedLock lock( this->m_curveToPointsMapMutex );
265+
#endif
266+
this->m_curveToPointsMap[ curve ] = result;
267+
}
268+
return result;
244269
}
245270

246271
TCurve TrimCurve( const TCurve& curve, const TVector& t1, const TVector& t2 ) {
@@ -291,7 +316,7 @@ class CurveConverter {
291316
return { l, M_PI * 2 - l + r };
292317
}
293318
if( !senseAgreement && l < r ) {
294-
return { l, -l - (M_PI * 2 - r)};
319+
return { l, -l - ( M_PI * 2 - r ) };
295320
}
296321
if( !senseAgreement && l > r ) {
297322
return { l, l - r };

include/ifcpp/Geometry/Extruder.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,9 @@ class Extruder {
8888
for( int i = 1; i < sweepPoints.size() - 1; i++ ) {
8989
fDirs.push_back( AVector::Normalized( AVector::Normalized( sweepPoints[ i ] - sweepPoints[ i - 1 ] ) +
9090
AVector::Normalized( sweepPoints[ i + 1 ] - sweepPoints[ i ] ) ) );
91-
float angle = std::acosf( AVector::Dot( AVector::Normalized( sweepPoints[ i ] - sweepPoints[ i - 1 ] ),
91+
float angle = acosf( AVector::Dot( AVector::Normalized( sweepPoints[ i ] - sweepPoints[ i - 1 ] ),
9292
AVector::Normalized( sweepPoints[ i ] - sweepPoints[ i + 1 ] ) ) );
93-
k.push_back( 1.0f / std::sinf( angle / 2.0f ) );
93+
k.push_back( 1.0f / sinf( angle / 2.0f ) );
9494
}
9595
fDirs.push_back( AVector::Normalized( sweepPoints[ sweepPoints.size() - 1 ] - sweepPoints[ sweepPoints.size() - 2 ] ) );
9696
k.push_back( 1.0f );

include/ifcpp/Geometry/GeomUtils.h

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -159,22 +159,21 @@ class GeomUtils {
159159
std::copy( std::begin( toAppend ), std::end( toAppend ), std::back_inserter( *loop ) );
160160
}
161161
std::vector<TVector> CombineLoops( std::vector<std::vector<TVector>> loops ) {
162-
while( !loops.empty() && loops[ 0 ].size() < 3 ) {
163-
loops.erase( std::begin( loops ) );
162+
for( int i = 0; i < loops.size(); i++ ) {
163+
if( loops[i].size() < 3 ) {
164+
loops.erase( loops.begin() + i );
165+
i--;
166+
}
164167
}
165-
166168
if( loops.empty() ) {
167169
return {};
168170
}
169171

170-
auto planeNormal = this->ComputePolygonNormal( loops[ 0 ] );
171-
const Plane<TVector> p( loops[ 0 ][ 0 ], planeNormal );
172-
173-
174-
for( auto& l: loops ) {
175-
l = p.GetProjection( l );
176-
}
177-
172+
// auto planeNormal = this->ComputePolygonNormal( loops[ 0 ] );
173+
// const Plane<TVector> p( loops[ 0 ][ 0 ], planeNormal );
174+
// for( auto& l: loops ) {
175+
// l = p.GetProjection( l );
176+
// }
178177

179178
for( auto& l: loops ) {
180179
if( !l.empty() ) {
@@ -234,7 +233,7 @@ class GeomUtils {
234233
result.insert( std::begin( result ) + inResultIdx, result[ inResultIdx ] );
235234
result.insert( std::begin( result ) + inResultIdx + 1, std::begin( loopToInsert ), std::end( loopToInsert ) );
236235
}
237-
result = p.GetUnProjected( result );
236+
//result = p.GetUnProjected( result );
238237
return this->SimplifyLoop( result );
239238
}
240239
std::vector<TVector> IncorporateHoles( const std::vector<TVector>& outer, std::vector<std::vector<TVector>> inners ) {
@@ -339,7 +338,7 @@ class GeomUtils {
339338
const auto center_p0_normalized = AVector::Normalized( center_p0 );
340339
const auto center_p2_normalized = AVector::Normalized( center_p2 );
341340

342-
const float openingAngle = std::acos( AVector::Dot( center_p0_normalized, center_p2_normalized ) );
341+
const float openingAngle = acosf( AVector::Dot( center_p0_normalized, center_p2_normalized ) );
343342
int n = (int)( this->m_parameters->m_numVerticesPerCircle * openingAngle / ( M_PI * 2.0f ) );
344343
n = std::max( n, this->m_parameters->m_minNumVerticesPerArc );
345344

@@ -370,7 +369,7 @@ class GeomUtils {
370369
if( AVector::Len2( normal ) > AVector::Len2( planeNormal ) ) {
371370
planeNormal = normal;
372371
}
373-
if( AVector::Len2( planeNormal ) > this->m_parameters->m_epsilon ) {
372+
if( AVector::Len2( planeNormal ) > this->m_parameters->m_epsilon * this->m_parameters->m_epsilon ) {
374373
goto BREAK;
375374
}
376375
}
@@ -384,6 +383,11 @@ class GeomUtils {
384383
loop = p.GetProjection( loop );
385384
loop.push_back( loop[ 0 ] );
386385

386+
BoundingBox<TVector> bbox( loop );
387+
for( auto& v: loop ) {
388+
v = v - bbox.m_min;
389+
}
390+
387391
float s = 0.0f;
388392
for( int i = 1; i < loop.size(); i++ ) {
389393
const auto& v1 = loop[ i - 1 ];

0 commit comments

Comments
 (0)