2014-12-19 12:14:36 +00:00
/********************************************************************************
* *
* This file is part of IfcOpenShell. *
* *
* IfcOpenShell is free software: you can redistribute it and/or modify *
* it under the terms of the Lesser GNU General Public License as published by *
* the Free Software Foundation, either version 3.0 of the License, or *
* (at your option) any later version. *
* *
* IfcOpenShell is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* Lesser GNU General Public License for more details. *
* *
* You should have received a copy of the Lesser GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
/********************************************************************************
* *
* Geometrical data in an IFC file consists of shapes (IfcShapeRepresentation) *
* and instances (SUBTYPE OF IfcBuildingElement e.g. IfcWindow). *
* *
* IfcGeom::Representation::Triangulation is a class that represents a *
* triangulated IfcShapeRepresentation. *
* Triangulation.verts is a 1 dimensional vector of float defining the *
* cartesian coordinates of the vertices of the triangulated shape in the *
* format of [x1,y1,z1,..,xn,yn,zn] *
* Triangulation.faces is a 1 dimensional vector of int containing the *
* indices of the triangles referencing positions in Triangulation.verts *
* Triangulation.edges is a 1 dimensional vector of int in {0,1} that dictates*
* the visibility of the edges that span the faces in Triangulation.faces *
* *
* IfcGeom::Element represents the actual IfcBuildingElements. *
* IfcGeomObject.name is the GUID of the element *
* IfcGeomObject.type is the datatype of the element e.g. IfcWindow *
* IfcGeomObject.mesh is a pointer to an IfcMesh *
* IfcGeomObject.transformation.matrix is a 4x3 matrix that defines the *
* orientation and translation of the mesh in relation to the world origin *
* *
2015-04-22 09:15:48 +00:00
* IfcGeom::Iterator::initialize() *
2014-12-19 12:14:36 +00:00
* finds the most suitable representation contexts. Returns true iff *
* at least a single representation will process successfully *
* *
* IfcGeom::Iterator::get() *
* returns a pointer to the current IfcGeom::Element *
* *
* IfcGeom::Iterator::next() *
* returns true iff a following entity is available for a successive call to *
* IfcGeom::Iterator::get() *
* *
* IfcGeom::Iterator::progress() *
* returns an int in [0..100] that indicates the overall progress *
* *
********************************************************************************/
# ifndef IFCGEOMITERATOR_H
# define IFCGEOMITERATOR_H
# include <map>
# include <set>
# include <vector>
2014-12-19 12:36:06 +00:00
# include <limits>
2014-12-19 12:14:36 +00:00
# include <algorithm>
2019-07-09 16:00:29 +02:00
# include <atomic>
2014-12-19 12:14:36 +00:00
2019-07-03 12:10:27 +02:00
# include <future>
# include <thread>
# include <chrono>
2015-09-13 15:00:21 +02:00
# include <boost/algorithm/string.hpp>
2014-12-19 12:14:36 +00:00
# include <gp_Mat.hxx>
# include <gp_Mat2d.hxx>
# include <gp_GTrsf.hxx>
# include <gp_GTrsf2d.hxx>
# include <gp_Trsf.hxx>
# include <gp_Trsf2d.hxx>
2015-01-05 14:11:42 +00:00
# include "../ifcparse/IfcFile.h"
2014-12-19 12:14:36 +00:00
# include "../ifcgeom/IfcGeom.h"
# include "../ifcgeom/IfcGeomElement.h"
2017-12-20 17:09:42 +01:00
# include "../ifcgeom_schema_agnostic/IfcGeomMaterial.h"
2014-12-19 12:14:36 +00:00
# include "../ifcgeom/IfcGeomIteratorSettings.h"
# include "../ifcgeom/IfcRepresentationShapeItem.h"
2018-09-07 14:08:56 +02:00
# include "../ifcgeom_schema_agnostic/IfcGeomFilter.h"
2017-12-20 17:09:42 +01:00
# include "../ifcgeom_schema_agnostic/IteratorImplementation.h"
2017-12-19 20:24:00 +01:00
2019-07-19 15:55:22 +02:00
# include <atomic>
2016-07-11 21:36:12 +03:00
// The infamous min & max Win32 #defines can leak here from OCE depending on the build configuration
# ifdef min
# undef min
# endif
# ifdef max
# undef max
# endif
2019-07-03 12:10:27 +02:00
namespace {
template < typename P , typename PP = P >
struct geometry_conversion_task {
int index ;
IfcSchema : : IfcRepresentation * representation ;
IfcSchema : : IfcProduct : : list : : ptr products ;
std : : vector < IfcGeom : : BRepElement < P , PP > * > breps ;
std : : vector < IfcGeom : : Element < P , PP > * > elements ;
} ;
2019-07-09 16:00:29 +02:00
template < typename P , typename PP = P >
IfcGeom : : Element < P , PP > * process_based_on_settings (
const IfcGeom : : IteratorSettings & settings ,
IfcGeom : : BRepElement < P , PP > * elem ,
IfcGeom : : TriangulationElement < P , PP > * previous = nullptr )
{
if ( settings . get ( IfcGeom : : IteratorSettings : : USE_BREP_DATA ) ) {
try {
return new IfcGeom : : SerializedElement < P , PP > ( * elem ) ;
} catch ( . . . ) {
Logger : : Message ( Logger : : LOG_ERROR , " Getting a serialized element from model failed. " ) ;
return nullptr ;
}
} else if ( ! settings . get ( IfcGeom : : IteratorSettings : : DISABLE_TRIANGULATION ) ) {
try {
if ( ! previous ) {
return new IfcGeom : : TriangulationElement < P , PP > ( * elem ) ;
} else {
return new IfcGeom : : TriangulationElement < P , PP > ( * elem , previous - > geometry_pointer ( ) ) ;
}
} catch ( . . . ) {
Logger : : Message ( Logger : : LOG_ERROR , " Getting a triangulation element from model failed. " ) ;
return nullptr ;
}
} else {
return elem ;
}
}
2019-07-03 12:10:27 +02:00
template < typename P , typename PP = P >
void create_element (
IfcGeom : : MAKE_TYPE_NAME ( Kernel ) * kernel ,
const IfcGeom : : IteratorSettings & settings ,
geometry_conversion_task < P , PP > * rep )
{
IfcSchema : : IfcRepresentation * representation = rep - > representation ;
IfcSchema : : IfcProduct * product = * rep - > products - > begin ( ) ;
2019-07-09 16:00:29 +02:00
auto brep = kernel - > create_brep_for_representation_and_product < P , PP > ( settings , representation , product ) ;
if ( ! brep ) {
return ;
}
auto elem = process_based_on_settings ( settings , brep ) ;
if ( ! elem ) {
return ;
}
rep - > breps = { brep } ;
rep - > elements = { elem } ;
2019-07-03 12:10:27 +02:00
for ( auto it = rep - > products - > begin ( ) + 1 ; it ! = rep - > products - > end ( ) ; + + it ) {
2019-07-09 16:00:29 +02:00
auto brep2 = kernel - > create_brep_for_processed_representation < P , PP > ( settings , representation , * it , brep ) ;
if ( brep2 ) {
2020-01-07 14:17:55 +01:00
auto elem2 = process_based_on_settings ( settings , brep2 , dynamic_cast < IfcGeom : : TriangulationElement < P , PP > * > ( elem ) ) ;
2019-07-09 16:00:29 +02:00
if ( elem2 ) {
rep - > breps . push_back ( brep2 ) ;
rep - > elements . push_back ( elem2 ) ;
}
}
2019-07-03 12:10:27 +02:00
}
}
}
2014-12-19 12:14:36 +00:00
namespace IfcGeom {
2018-07-07 21:14:27 +02:00
template < typename P , typename PP >
class MAKE_TYPE_NAME ( IteratorImplementation_ ) : public IteratorImplementation < P , PP > {
2014-12-19 12:14:36 +00:00
private :
2017-12-19 20:24:00 +01:00
2019-07-19 15:55:22 +02:00
std : : atomic < int > progress_ ;
2019-07-03 12:10:27 +02:00
std : : vector < geometry_conversion_task < P , PP > > tasks_ ;
std : : vector < IfcGeom : : Element < P , PP > * > all_processed_elements_ ;
2019-07-09 16:00:29 +02:00
std : : vector < IfcGeom : : BRepElement < P , PP > * > all_processed_native_elements_ ;
2019-07-03 12:10:27 +02:00
typename std : : vector < IfcGeom : : Element < P , PP > * > : : const_iterator task_result_iterator_ ;
2019-07-09 16:00:29 +02:00
typename std : : vector < IfcGeom : : BRepElement < P , PP > * > : : const_iterator native_task_result_iterator_ ;
2019-07-03 12:10:27 +02:00
2017-12-19 20:24:00 +01:00
MAKE_TYPE_NAME ( IteratorImplementation_ ) ( const MAKE_TYPE_NAME ( IteratorImplementation_ ) & ) ; // N/I
MAKE_TYPE_NAME ( IteratorImplementation_ ) & operator = ( const MAKE_TYPE_NAME ( IteratorImplementation_ ) & ) ; // N/I
2016-03-07 22:37:36 +02:00
2017-12-20 16:38:55 +01:00
MAKE_TYPE_NAME ( Kernel ) kernel ;
2014-12-19 12:14:36 +00:00
2020-03-18 11:59:11 +01:00
IteratorSettings settings ;
2014-12-19 12:14:36 +00:00
IfcParse : : IfcFile * ifc_file ;
2020-03-18 11:59:11 +01:00
std : : vector < filter_t > filters_ ;
bool owns_ifc_file ;
int num_threads_ ;
2014-12-19 12:14:36 +00:00
2015-01-05 14:11:42 +00:00
// A container and iterator for IfcRepresentations
2014-12-19 12:14:36 +00:00
IfcSchema : : IfcRepresentation : : list : : ptr representations ;
2015-01-05 14:11:42 +00:00
IfcSchema : : IfcRepresentation : : list : : it representation_iterator ;
2014-12-19 12:14:36 +00:00
// The object is fetched beforehand to be sure that get() returns a valid element
2018-07-07 21:14:27 +02:00
TriangulationElement < P , PP > * current_triangulation ;
BRepElement < P , PP > * current_shape_model ;
SerializedElement < P , PP > * current_serialization ;
2014-12-19 12:14:36 +00:00
2015-01-05 14:11:42 +00:00
// A container and iterator for IfcBuildingElements for the current IfcRepresentation referenced by *representation_iterator
2015-02-05 11:55:25 +00:00
IfcSchema : : IfcProduct : : list : : ptr ifcproducts ;
2014-12-19 12:14:36 +00:00
IfcSchema : : IfcProduct : : list : : it ifcproduct_iterator ;
2018-04-12 16:42:46 +03:00
IfcSchema : : IfcRepresentation : : list : : ptr ok_mapped_representations ;
2014-12-19 12:14:36 +00:00
int done ;
int total ;
std : : string unit_name ;
2017-02-03 19:15:37 +02:00
double unit_magnitude ;
2016-03-17 23:25:53 +02:00
gp_XYZ bounds_min_ ;
gp_XYZ bounds_max_ ;
2014-12-19 12:14:36 +00:00
2017-02-07 17:34:23 +02:00
struct filter_match
{
filter_match ( IfcSchema : : IfcProduct * prod ) : product ( prod ) { }
bool operator ( ) ( const filter_t & filter ) const { return filter ( product ) ; }
IfcSchema : : IfcProduct * product ;
} ;
2014-12-19 12:14:36 +00:00
void initUnits ( ) {
2017-12-19 20:24:00 +01:00
IfcSchema : : IfcProject : : list : : ptr projects = ifc_file - > instances_by_type < IfcSchema : : IfcProject > ( ) ;
2015-01-10 22:13:52 +00:00
if ( projects - > size ( ) = = 1 ) {
2015-01-05 14:11:42 +00:00
IfcSchema : : IfcProject * project = * projects - > begin ( ) ;
std : : pair < std : : string , double > length_unit = kernel . initializeUnits ( project - > UnitsInContext ( ) ) ;
unit_name = length_unit . first ;
2017-02-03 19:15:37 +02:00
unit_magnitude = length_unit . second ;
2018-09-07 14:25:46 +02:00
} else {
2018-12-29 12:34:32 +01:00
Logger : : Warning ( " A single IfcProject is expected (encountered " + boost : : lexical_cast < std : : string > ( projects - > size ( ) ) + " ); unable to read unit information. " ) ;
2014-12-19 12:14:36 +00:00
}
}
2017-02-16 19:49:46 +02:00
/// @todo public/private sections all over the place: move all public to the beginning of the class
2014-12-19 12:14:36 +00:00
public :
2017-12-19 20:24:00 +01:00
typedef P Precision ;
2018-07-07 21:14:27 +02:00
typedef PP PlacementPrecision ;
2017-12-19 20:24:00 +01:00
2020-07-22 12:25:24 +02:00
boost : : optional < bool > initialization_outcome_ ;
2015-04-22 09:15:48 +00:00
bool initialize ( ) {
2020-07-22 12:25:24 +02:00
if ( initialization_outcome_ ) {
return * initialization_outcome_ ;
}
2014-12-19 12:14:36 +00:00
try {
initUnits ( ) ;
2017-08-01 16:45:11 +02:00
} catch ( const std : : exception & e ) {
Logger : : Error ( e ) ;
}
2014-12-19 12:14:36 +00:00
2016-08-04 11:47:14 +02:00
std : : set < std : : string > allowed_context_types ;
allowed_context_types . insert ( " model " ) ;
allowed_context_types . insert ( " plan " ) ;
allowed_context_types . insert ( " notdefined " ) ;
2014-12-19 12:14:36 +00:00
std : : set < std : : string > context_types ;
2016-03-07 22:37:36 +02:00
if ( ! settings . get ( IteratorSettings : : EXCLUDE_SOLIDS_AND_SURFACES ) ) {
2015-04-22 09:15:48 +00:00
// Really this should only be 'Model', as per
// the standard 'Design' is deprecated. So,
// just for backwards compatibility:
context_types . insert ( " model " ) ;
context_types . insert ( " design " ) ;
2016-08-02 15:53:41 +02:00
// Some earlier (?) versions DDS-CAD output their own ContextTypes
2015-04-22 09:15:48 +00:00
context_types . insert ( " model view " ) ;
2016-08-02 15:53:41 +02:00
context_types . insert ( " detail view " ) ;
2015-04-22 09:15:48 +00:00
}
2016-03-07 22:37:36 +02:00
if ( settings . get ( IteratorSettings : : INCLUDE_CURVES ) ) {
2015-04-22 09:15:48 +00:00
context_types . insert ( " plan " ) ;
}
2014-12-19 12:14:36 +00:00
double lowest_precision_encountered = std : : numeric_limits < double > : : infinity ( ) ;
bool any_precision_encountered = false ;
representations = IfcSchema : : IfcRepresentation : : list : : ptr ( new IfcSchema : : IfcRepresentation : : list ) ;
2018-04-12 16:42:46 +03:00
ok_mapped_representations = IfcSchema : : IfcRepresentation : : list : : ptr ( new IfcSchema : : IfcRepresentation : : list ) ;
2014-12-19 12:14:36 +00:00
IfcSchema : : IfcGeometricRepresentationContext : : list : : it it ;
IfcSchema : : IfcGeometricRepresentationSubContext : : list : : it jt ;
IfcSchema : : IfcGeometricRepresentationContext : : list : : ptr contexts =
2017-12-19 20:24:00 +01:00
ifc_file - > instances_by_type < IfcSchema : : IfcGeometricRepresentationContext > ( ) ;
2014-12-19 12:14:36 +00:00
IfcSchema : : IfcGeometricRepresentationContext : : list : : ptr filtered_contexts ( new IfcSchema : : IfcGeometricRepresentationContext : : list ) ;
for ( it = contexts - > begin ( ) ; it ! = contexts - > end ( ) ; + + it ) {
IfcSchema : : IfcGeometricRepresentationContext * context = * it ;
2017-12-18 15:25:09 +01:00
if ( context - > declaration ( ) . is ( IfcSchema : : IfcGeometricRepresentationSubContext : : Class ( ) ) ) {
2014-12-19 12:14:36 +00:00
// Continue, as the list of subcontexts will be considered
// by the parent's context inverse attributes.
continue ;
}
2015-11-30 23:41:27 +01:00
try {
if ( context - > hasContextType ( ) ) {
std : : string context_type = context - > ContextType ( ) ;
boost : : to_lower ( context_type ) ;
2016-08-04 11:47:14 +02:00
if ( allowed_context_types . find ( context_type ) = = allowed_context_types . end ( ) ) {
2018-12-29 12:34:32 +01:00
Logger : : Warning ( std : : string ( " ContextType ' " ) + context - > ContextType ( ) + " ' not allowed: " , context ) ;
2016-08-04 11:47:14 +02:00
}
2015-11-30 23:41:27 +01:00
if ( context_types . find ( context_type ) ! = context_types . end ( ) ) {
filtered_contexts - > push ( context ) ;
}
2015-01-22 10:38:35 +00:00
}
2017-08-01 16:45:11 +02:00
} catch ( const std : : exception & e ) {
Logger : : Error ( e ) ;
}
2014-12-19 12:14:36 +00:00
}
2015-05-22 13:13:16 +00:00
// In case no contexts are identified based on their ContextType, all contexts are
// considered. Note that sub contexts are excluded as they are considered later on.
2015-01-10 22:13:52 +00:00
if ( filtered_contexts - > size ( ) = = 0 ) {
2015-05-22 13:13:16 +00:00
for ( it = contexts - > begin ( ) ; it ! = contexts - > end ( ) ; + + it ) {
IfcSchema : : IfcGeometricRepresentationContext * context = * it ;
2017-12-18 15:25:09 +01:00
if ( ! context - > declaration ( ) . is ( IfcSchema : : IfcGeometricRepresentationSubContext : : Class ( ) ) ) {
2015-05-22 13:13:16 +00:00
filtered_contexts - > push ( context ) ;
}
}
2014-12-19 12:14:36 +00:00
}
for ( it = filtered_contexts - > begin ( ) ; it ! = filtered_contexts - > end ( ) ; + + it ) {
IfcSchema : : IfcGeometricRepresentationContext * context = * it ;
representations - > push ( context - > RepresentationsInContext ( ) ) ;
2015-11-30 23:41:27 +01:00
try {
if ( context - > hasPrecision ( ) & & context - > Precision ( ) < lowest_precision_encountered ) {
lowest_precision_encountered = context - > Precision ( ) ;
any_precision_encountered = true ;
}
2017-08-01 16:45:11 +02:00
} catch ( const std : : exception & e ) {
Logger : : Error ( e ) ;
}
2014-12-19 12:14:36 +00:00
IfcSchema : : IfcGeometricRepresentationSubContext : : list : : ptr sub_contexts = context - > HasSubContexts ( ) ;
for ( jt = sub_contexts - > begin ( ) ; jt ! = sub_contexts - > end ( ) ; + + jt ) {
representations - > push ( ( * jt ) - > RepresentationsInContext ( ) ) ;
}
// There is no need for full recursion as the following is governed by the schema:
// WR31: The parent context shall not be another geometric representation sub context.
}
if ( any_precision_encountered ) {
2015-01-06 14:09:28 +00:00
// Some arbitrary factor that has proven to work better for the models in the set of test files.
2021-02-06 10:26:17 -06:00
lowest_precision_encountered * = kernel . getValue ( IfcGeom : : Kernel : : GV_PRECISION_FACTOR ) ;
2015-01-06 14:09:28 +00:00
lowest_precision_encountered * = unit_magnitude ;
if ( lowest_precision_encountered < 1.e-7 ) {
Logger : : Message ( Logger : : LOG_WARNING , " Precision lower than 0.0000001 meter not enforced " ) ;
kernel . setValue ( IfcGeom : : Kernel : : GV_PRECISION , 1.e-7 ) ;
} else {
kernel . setValue ( IfcGeom : : Kernel : : GV_PRECISION , lowest_precision_encountered ) ;
}
2014-12-19 12:14:36 +00:00
} else {
kernel . setValue ( IfcGeom : : Kernel : : GV_PRECISION , 1.e-5 ) ;
}
2017-02-03 19:15:37 +02:00
if ( representations - > size ( ) = = 0 ) {
2018-12-29 12:34:32 +01:00
Logger : : Warning ( " No representations encountered in relevant contexts, using all " ) ;
2018-10-30 14:32:28 +01:00
representations = ifc_file - > instances_by_type < IfcSchema : : IfcRepresentation > ( ) ;
2016-05-13 12:59:00 +02:00
}
2014-12-19 12:14:36 +00:00
2018-10-30 12:15:35 +01:00
if ( representations - > size ( ) = = 0 ) {
2018-12-29 12:34:32 +01:00
Logger : : Warning ( " No representations encountered, aborting " ) ;
2020-07-22 12:25:24 +02:00
initialization_outcome_ = false ;
} else {
representation_iterator = representations - > begin ( ) ;
ifcproducts . reset ( ) ;
2014-12-19 12:14:36 +00:00
2020-07-22 12:25:24 +02:00
done = 0 ;
total = representations - > size ( ) ;
2014-12-19 12:14:36 +00:00
2020-07-22 12:25:24 +02:00
if ( num_threads_ ! = 1 ) {
collect ( ) ;
process_concurrently ( ) ;
2020-05-31 17:07:41 +02:00
2020-07-22 12:25:24 +02:00
initialization_outcome_ = ! all_processed_elements_ . empty ( ) ;
} else {
initialization_outcome_ = create ( ) ;
2019-07-03 12:10:27 +02:00
}
}
2020-07-22 12:25:24 +02:00
return * initialization_outcome_ ;
2018-08-20 14:36:53 +03:00
}
2019-07-03 12:10:27 +02:00
void collect ( ) {
int i = 0 ;
IfcSchema : : IfcProduct : : list * previous = nullptr ;
2020-03-30 10:53:08 +02:00
while ( auto rp = try_get_next_task ( ) ) {
2019-07-03 12:10:27 +02:00
// Note that get_next_task() mutates the state of the iterator
// we use that capture all products that can be processed as
// part of this representation and then keep iterating until
// the underlying list of products changes.
if ( ifcproducts . get ( ) ! = previous ) {
previous = ifcproducts . get ( ) ;
2020-03-30 10:53:08 +02:00
if ( ifcproducts - > size ( ) ) {
geometry_conversion_task < P , PP > t ;
t . index = i + + ;
t . representation = * representation_iterator ;
t . products = ifcproducts ;
tasks_ . emplace_back ( t ) ;
}
}
if ( rp - > which ( ) = = 1 ) {
Logger : : Error ( boost : : get < IfcParse : : IfcException > ( * rp ) ) ;
2019-07-03 12:10:27 +02:00
}
_nextShape ( ) ;
}
}
void process_concurrently ( ) {
2019-07-09 16:00:29 +02:00
size_t conc_threads = num_threads_ ;
if ( conc_threads > tasks_ . size ( ) ) {
conc_threads = tasks_ . size ( ) ;
2019-07-03 12:10:27 +02:00
}
std : : vector < MAKE_TYPE_NAME ( Kernel ) * > kernel_pool ;
kernel_pool . reserve ( conc_threads ) ;
for ( unsigned i = 0 ; i < conc_threads ; + + i ) {
kernel_pool . push_back ( new MAKE_TYPE_NAME ( Kernel ) ( kernel ) ) ;
}
std : : vector < std : : future < void > > threadpool ;
2019-07-09 16:00:58 +02:00
int old_progress = - 1 ;
int processed = 0 ;
Logger : : ProgressBar ( 0 ) ;
2019-07-03 12:10:27 +02:00
for ( auto & rep : tasks_ ) {
2019-07-09 16:00:58 +02:00
MAKE_TYPE_NAME ( Kernel ) * K = nullptr ;
if ( threadpool . size ( ) < kernel_pool . size ( ) ) {
K = kernel_pool [ threadpool . size ( ) ] ;
}
2019-07-03 12:10:27 +02:00
while ( threadpool . size ( ) = = conc_threads ) {
for ( int i = 0 ; i < ( int ) threadpool . size ( ) ; i + + ) {
std : : future < void > & fu = threadpool [ i ] ;
std : : future_status status ;
status = fu . wait_for ( std : : chrono : : seconds ( 0 ) ) ;
if ( status = = std : : future_status : : ready ) {
fu . get ( ) ;
2019-07-09 16:00:58 +02:00
processed + = 1 ;
2019-07-19 15:55:22 +02:00
progress_ = processed * 50 / tasks_ . size ( ) ;
if ( progress_ ! = old_progress ) {
Logger : : ProgressBar ( progress_ ) ;
old_progress = progress_ ;
2019-07-09 16:00:58 +02:00
}
2019-07-03 12:10:27 +02:00
std : : swap ( threadpool [ i ] , threadpool . back ( ) ) ;
threadpool . pop_back ( ) ;
std : : swap ( kernel_pool [ i ] , kernel_pool . back ( ) ) ;
K = kernel_pool . back ( ) ;
break ;
} // if
} // for
} // while
std : : future < void > fu = std : : async ( std : : launch : : async , create_element < P , PP > , K , std : : ref ( settings ) , & rep ) ;
threadpool . emplace_back ( std : : move ( fu ) ) ;
}
for ( std : : future < void > & fu : threadpool ) {
fu . get ( ) ;
2019-07-09 16:00:58 +02:00
processed + = 1 ;
2019-07-19 15:55:22 +02:00
progress_ = processed * 50 / tasks_ . size ( ) ;
if ( progress_ ! = old_progress ) {
Logger : : ProgressBar ( progress_ ) ;
old_progress = progress_ ;
2019-07-09 16:00:58 +02:00
}
2019-07-03 12:10:27 +02:00
}
for ( auto & rep : tasks_ ) {
all_processed_elements_ . insert ( all_processed_elements_ . end ( ) , rep . elements . begin ( ) , rep . elements . end ( ) ) ;
2019-07-09 16:00:29 +02:00
all_processed_native_elements_ . insert ( all_processed_native_elements_ . end ( ) , rep . breps . begin ( ) , rep . breps . end ( ) ) ;
2019-07-03 12:10:27 +02:00
}
task_result_iterator_ = all_processed_elements_ . begin ( ) ;
2019-07-09 16:00:29 +02:00
native_task_result_iterator_ = all_processed_native_elements_ . begin ( ) ;
2019-07-09 16:00:58 +02:00
Logger : : Status ( " \r Done creating geometry ( " + boost : : lexical_cast < std : : string > ( all_processed_elements_ . size ( ) ) +
" objects) " ) ;
2019-07-03 12:10:27 +02:00
}
2018-08-20 14:36:53 +03:00
/// Computes model's bounding box (bounds_min and bounds_max).
/// @note Can take several minutes for large files.
2020-02-12 11:38:08 +01:00
void compute_bounds ( bool with_geometry )
2018-08-20 14:36:53 +03:00
{
2016-03-17 23:25:53 +02:00
for ( int i = 1 ; i < 4 ; + + i ) {
bounds_min_ . SetCoord ( i , std : : numeric_limits < double > : : infinity ( ) ) ;
bounds_max_ . SetCoord ( i , - std : : numeric_limits < double > : : infinity ( ) ) ;
}
2020-02-12 11:38:08 +01:00
if ( with_geometry ) {
size_t num_created = 0 ;
do {
IfcGeom : : Element < P , PP > * geom_object = get ( ) ;
const IfcGeom : : TriangulationElement < P , PP > * o = static_cast < const IfcGeom : : TriangulationElement < P , PP > * > ( geom_object ) ;
const IfcGeom : : Representation : : Triangulation < P > & mesh = o - > geometry ( ) ;
const gp_XYZ & pos = o - > transformation ( ) . data ( ) . TranslationPart ( ) ;
for ( typename std : : vector < P > : : const_iterator it = mesh . verts ( ) . begin ( ) ; it ! = mesh . verts ( ) . end ( ) ; ) {
const P x = * ( it + + ) ;
const P y = * ( it + + ) ;
const P z = * ( it + + ) ;
bounds_min_ . SetX ( std : : min ( bounds_min_ . X ( ) , pos . X ( ) + x ) ) ;
bounds_min_ . SetY ( std : : min ( bounds_min_ . Y ( ) , pos . Y ( ) + y ) ) ;
bounds_min_ . SetZ ( std : : min ( bounds_min_ . Z ( ) , pos . Z ( ) + z ) ) ;
bounds_max_ . SetX ( std : : max ( bounds_max_ . X ( ) , pos . X ( ) + x ) ) ;
bounds_max_ . SetY ( std : : max ( bounds_max_ . Y ( ) , pos . Y ( ) + y ) ) ;
bounds_max_ . SetZ ( std : : max ( bounds_max_ . Z ( ) , pos . Z ( ) + z ) ) ;
}
} while ( + + num_created , next ( ) ) ;
} else {
IfcSchema : : IfcProduct : : list : : ptr products = ifc_file - > instances_by_type < IfcSchema : : IfcProduct > ( ) ;
for ( IfcSchema : : IfcProduct : : list : : it iter = products - > begin ( ) ; iter ! = products - > end ( ) ; + + iter ) {
IfcSchema : : IfcProduct * product = * iter ;
if ( product - > hasObjectPlacement ( ) ) {
// Use a fresh trsf every time in order to prevent the result to be concatenated
gp_Trsf trsf ;
bool success = false ;
try {
success = kernel . convert ( product - > ObjectPlacement ( ) , trsf ) ;
} catch ( const std : : exception & e ) {
Logger : : Error ( e ) ;
} catch ( . . . ) {
Logger : : Error ( " Failed to construct placement " ) ;
}
if ( ! success ) {
continue ;
}
const gp_XYZ & pos = trsf . TranslationPart ( ) ;
bounds_min_ . SetX ( std : : min ( bounds_min_ . X ( ) , pos . X ( ) ) ) ;
bounds_min_ . SetY ( std : : min ( bounds_min_ . Y ( ) , pos . Y ( ) ) ) ;
bounds_min_ . SetZ ( std : : min ( bounds_min_ . Z ( ) , pos . Z ( ) ) ) ;
bounds_max_ . SetX ( std : : max ( bounds_max_ . X ( ) , pos . X ( ) ) ) ;
bounds_max_ . SetY ( std : : max ( bounds_max_ . Y ( ) , pos . Y ( ) ) ) ;
bounds_max_ . SetZ ( std : : max ( bounds_max_ . Z ( ) , pos . Z ( ) ) ) ;
}
}
}
2018-08-20 14:36:53 +03:00
}
2014-12-19 12:14:36 +00:00
2019-07-19 15:55:22 +02:00
int progress ( ) const {
if ( num_threads_ = = 1 ) {
return 100 * done / total ;
} else {
return progress_ ;
}
}
2014-12-19 12:14:36 +00:00
2016-03-07 22:37:36 +02:00
const std : : string & getUnitName ( ) const { return unit_name ; }
2014-12-19 12:14:36 +00:00
2017-02-03 19:15:37 +02:00
/// @note Double always as per IFC specification.
double getUnitMagnitude ( ) const { return unit_magnitude ; }
2014-12-19 12:14:36 +00:00
2016-03-07 22:37:36 +02:00
std : : string getLog ( ) const { return Logger : : GetLog ( ) ; }
2014-12-19 12:14:36 +00:00
2017-12-20 11:10:27 +01:00
IfcParse : : IfcFile * file ( ) const { return ifc_file ; }
2014-12-19 12:14:36 +00:00
2017-02-23 18:35:44 +02:00
const std : : vector < IfcGeom : : filter_t > & filters ( ) const { return filters_ ; }
std : : vector < IfcGeom : : filter_t > & filters ( ) { return filters_ ; }
2016-05-31 14:04:44 +03:00
2016-03-17 23:25:53 +02:00
const gp_XYZ & bounds_min ( ) const { return bounds_min_ ; }
const gp_XYZ & bounds_max ( ) const { return bounds_max_ ; }
2014-12-19 12:14:36 +00:00
private :
2015-01-05 14:11:42 +00:00
// Move to the next IfcRepresentation
2014-12-19 12:14:36 +00:00
void _nextShape ( ) {
2016-05-01 20:38:10 +02:00
// In order to conserve memory and reduce cache insertion times, the cache is
2018-09-06 12:23:07 -04:00
// cleared after an arbitrary number of processed representations. This has been
2016-05-01 20:38:10 +02:00
// benchmarked extensively: https://github.com/IfcOpenShell/IfcOpenShell/pull/47
static const int clear_interval = 64 ;
if ( done % clear_interval = = clear_interval - 1 ) {
kernel . purge_cache ( ) ;
2016-03-18 11:21:04 +01:00
}
2015-02-05 11:55:25 +00:00
ifcproducts . reset ( ) ;
2015-01-05 14:11:42 +00:00
+ + representation_iterator ;
2014-12-19 12:14:36 +00:00
+ + done ;
}
2017-06-28 15:24:49 +02:00
bool geometry_reuse_ok_for_current_representation_ ;
2017-10-06 15:36:51 +02:00
bool reuse_ok_ ( const IfcSchema : : IfcProduct : : list : : ptr & products ) {
// With world coords enabled, object transformations are directly applied to
// the BRep. There is no way to re-use the geometry for multiple products.
if ( settings . get ( IteratorSettings : : USE_WORLD_COORDS ) ) {
return false ;
}
std : : set < const IfcSchema : : IfcMaterial * > associated_single_materials ;
for ( IfcSchema : : IfcProduct : : list : : it it = products - > begin ( ) ; it ! = products - > end ( ) ; + + it ) {
IfcSchema : : IfcProduct * product = * it ;
if ( ! settings . get ( IteratorSettings : : DISABLE_OPENING_SUBTRACTIONS ) & & kernel . find_openings ( product ) - > size ( ) ) {
return false ;
}
if ( settings . get ( IteratorSettings : : APPLY_LAYERSETS ) ) {
IfcSchema : : IfcRelAssociates : : list : : ptr associations = product - > HasAssociations ( ) ;
for ( IfcSchema : : IfcRelAssociates : : list : : it jt = associations - > begin ( ) ; jt ! = associations - > end ( ) ; + + jt ) {
IfcSchema : : IfcRelAssociatesMaterial * assoc = ( * jt ) - > as < IfcSchema : : IfcRelAssociatesMaterial > ( ) ;
if ( assoc ) {
2017-12-18 15:25:09 +01:00
if ( assoc - > RelatingMaterial ( ) - > declaration ( ) . is ( IfcSchema : : IfcMaterialLayerSetUsage : : Class ( ) ) ) {
2017-10-06 15:36:51 +02:00
// TODO: Check whether single layer?
return false ;
}
}
}
}
// Note that this can be a nullptr (!), but the fact that set size should be one still holds
associated_single_materials . insert ( kernel . get_single_material_association ( product ) ) ;
2018-04-12 16:42:46 +03:00
if ( associated_single_materials . size ( ) > 1 ) return false ;
2017-10-06 15:36:51 +02:00
}
return associated_single_materials . size ( ) = = 1 ;
}
2020-03-30 10:53:08 +02:00
boost : : optional < boost : : variant < std : : pair < IfcSchema : : IfcRepresentation * , IfcSchema : : IfcProduct * > , IfcParse : : IfcException > > try_get_next_task ( ) {
boost : : variant <
std : : pair < IfcSchema : : IfcRepresentation * , IfcSchema : : IfcProduct * > ,
IfcParse : : IfcException
> r ;
try {
auto p = get_next_task ( ) ;
if ( p ) {
r = * p ;
} else {
return boost : : none ;
}
} catch ( IfcParse : : IfcException & e ) {
r = e ;
} catch ( . . . ) {
r = IfcParse : : IfcException ( " Unknown error " ) ;
}
return r ;
}
2019-07-03 12:10:27 +02:00
boost : : optional < std : : pair < IfcSchema : : IfcRepresentation * , IfcSchema : : IfcProduct * > > get_next_task ( ) {
2015-11-21 23:05:28 +02:00
for ( ; ; ) {
2015-01-05 14:11:42 +00:00
IfcSchema : : IfcRepresentation * representation ;
2014-12-19 12:14:36 +00:00
2019-07-03 12:10:27 +02:00
if ( representation_iterator = = representations - > end ( ) ) {
2014-12-19 12:14:36 +00:00
representations . reset ( ) ;
2019-07-03 12:10:27 +02:00
return boost : : none ; // reached the end of our list of representations
2014-12-19 12:14:36 +00:00
}
2015-01-05 14:11:42 +00:00
representation = * representation_iterator ;
2014-12-19 12:14:36 +00:00
2015-02-05 11:55:25 +00:00
if ( ! ifcproducts ) {
2018-08-23 10:33:43 +03:00
// Init. the list of filtered IfcProducts for this representation
2015-02-05 11:55:25 +00:00
ifcproducts = IfcSchema : : IfcProduct : : list : : ptr ( new IfcSchema : : IfcProduct : : list ) ;
2017-10-06 15:36:51 +02:00
IfcSchema : : IfcProduct : : list : : ptr unfiltered_products = kernel . products_represented_by ( representation ) ;
2019-07-03 12:10:27 +02:00
// Include only the desired products for processing.
for ( IfcSchema : : IfcProduct : : list : : it jt = unfiltered_products - > begin ( ) ; jt ! = unfiltered_products - > end ( ) ; + + jt ) {
IfcSchema : : IfcProduct * prod = * jt ;
if ( boost : : all ( filters_ , filter_match ( prod ) ) ) {
ifcproducts - > push ( prod ) ;
}
}
2018-08-21 13:52:09 +03:00
2019-07-03 12:10:27 +02:00
if ( ifcproducts - > size ( ) = = 0 ) {
_nextShape ( ) ;
continue ;
}
2015-02-05 11:55:25 +00:00
2019-07-03 12:10:27 +02:00
geometry_reuse_ok_for_current_representation_ = reuse_ok_ ( ifcproducts ) ;
2016-03-18 11:23:25 +01:00
2018-02-21 14:54:38 +01:00
IfcSchema : : IfcRepresentationMap : : list : : ptr maps = representation - > RepresentationMap ( ) ;
if ( ! geometry_reuse_ok_for_current_representation_ & & maps - > size ( ) = = 1 ) {
2017-10-06 15:36:51 +02:00
// unfiltered_products contains products represented by this representation by means of mapped items.
// For example because of openings applied to products, reuse might not be acceptable and then the
// products will be processed by means of their immediate representation and not the mapped representation.
2018-02-21 14:54:38 +01:00
// IfcRepresentationMaps are also used for IfcTypeProducts, so an additional check is performed whether the map
// is indeed used by IfcMappedItems.
IfcSchema : : IfcRepresentationMap * map = * maps - > begin ( ) ;
if ( map - > MapUsage ( ) - > size ( ) > 0 ) {
_nextShape ( ) ;
continue ;
}
2016-03-18 11:23:25 +01:00
}
2014-12-19 12:14:36 +00:00
2018-08-23 10:33:43 +03:00
// Check if this represenation has (or will be) processed as part its mapped representation
2016-03-18 11:23:25 +01:00
bool representation_processed_as_mapped_item = false ;
2019-07-03 12:10:27 +02:00
IfcSchema : : IfcRepresentation * representation_mapped_to = kernel . representation_mapped_to ( representation ) ;
2016-03-18 11:23:25 +01:00
if ( representation_mapped_to ) {
2019-07-03 12:10:27 +02:00
representation_processed_as_mapped_item = geometry_reuse_ok_for_current_representation_ & & (
ok_mapped_representations - > contains ( representation_mapped_to ) | | reuse_ok_ ( kernel . products_represented_by ( representation_mapped_to ) ) ) ;
2014-12-19 12:14:36 +00:00
}
2016-03-18 11:23:25 +01:00
if ( representation_processed_as_mapped_item ) {
2019-07-03 12:10:27 +02:00
ok_mapped_representations - > push ( representation_mapped_to ) ;
2014-12-19 12:14:36 +00:00
_nextShape ( ) ;
continue ;
}
2016-03-18 11:23:25 +01:00
2015-02-05 11:55:25 +00:00
ifcproduct_iterator = ifcproducts - > begin ( ) ;
2014-12-19 12:14:36 +00:00
}
2016-03-18 11:23:25 +01:00
2014-12-19 12:14:36 +00:00
// Have we reached the end of our list of IfcProducts?
2019-07-03 12:10:27 +02:00
if ( ifcproduct_iterator = = ifcproducts - > end ( ) ) {
2014-12-19 12:14:36 +00:00
_nextShape ( ) ;
continue ;
}
2017-02-07 17:34:23 +02:00
IfcSchema : : IfcProduct * product = * ifcproduct_iterator ;
2019-07-03 12:10:27 +02:00
return std : : make_pair ( representation , product ) ;
}
}
BRepElement < P , PP > * create_shape_model_for_next_entity ( ) {
for ( ; ; ) {
auto rp = get_next_task ( ) ;
if ( ! rp ) {
return nullptr ;
}
auto representation = rp - > first ;
auto product = rp - > second ;
Logger : : SetProduct ( product ) ;
2016-05-11 09:56:40 +01:00
2018-07-07 21:14:27 +02:00
BRepElement < P , PP > * element ;
2017-06-28 15:24:49 +02:00
if ( ifcproduct_iterator = = ifcproducts - > begin ( ) | | ! geometry_reuse_ok_for_current_representation_ ) {
2018-07-07 21:14:27 +02:00
element = kernel . create_brep_for_representation_and_product < P , PP > ( settings , representation , product ) ;
2016-03-18 11:23:25 +01:00
} else {
2017-02-07 17:34:23 +02:00
element = kernel . create_brep_for_processed_representation ( settings , representation , product , current_shape_model ) ;
2016-03-18 11:23:25 +01:00
}
2014-12-19 12:14:36 +00:00
2016-07-19 15:31:37 +01:00
Logger : : SetProduct ( boost : : none ) ;
2017-02-07 17:34:23 +02:00
if ( ! element ) {
2015-01-05 14:11:42 +00:00
_nextShape ( ) ;
continue ;
2014-12-19 12:14:36 +00:00
}
2017-02-07 17:34:23 +02:00
return element ;
2017-02-03 19:15:37 +02:00
}
2014-12-19 12:14:36 +00:00
}
2016-03-18 11:23:25 +01:00
void free_shapes ( ) {
2014-12-19 12:14:36 +00:00
// Free all possible representations of the current geometrical entity
delete current_triangulation ;
current_triangulation = 0 ;
2015-01-05 14:11:42 +00:00
delete current_serialization ;
current_serialization = 0 ;
delete current_shape_model ;
current_shape_model = 0 ;
2016-03-18 11:23:25 +01:00
}
2017-02-07 17:34:23 +02:00
public :
2017-02-03 19:15:37 +02:00
/// Returns what would be the product for the next shape representation
2017-02-07 17:34:23 +02:00
/// @todo Double-check and test the impl.
//IfcSchema::IfcProduct* peek_next() const
//{
// if (ifcproducts && ifcproduct_iterator + 1 != ifcproducts->end()){
// return *(ifcproduct_iterator + 1);
// } else {
// return 0;
// }
//}
/// @todo Would this be as simple as the following code?
//void skip_next() { if (ifcproducts) { ++ifcproduct_iterator; } }
/// Moves to the next shape representation, create its geometry, and returns the associated product.
2017-02-03 19:15:37 +02:00
/// Use get() to retrieve the created geometry.
2017-12-19 20:24:00 +01:00
IfcUtil : : IfcBaseClass * next ( ) {
2019-07-03 12:10:27 +02:00
if ( num_threads_ ! = 1 ) {
2019-07-09 16:00:29 +02:00
task_result_iterator_ + + ;
native_task_result_iterator_ + + ;
2019-07-03 12:10:27 +02:00
if ( task_result_iterator_ = = all_processed_elements_ . end ( ) ) {
return nullptr ;
} else {
return ( * task_result_iterator_ ) - > product ( ) ;
}
} else {
// Increment the iterator over the list of products using the current
// shape representation
if ( ifcproducts ) {
+ + ifcproduct_iterator ;
}
2014-12-19 12:14:36 +00:00
2019-07-03 12:10:27 +02:00
return create ( ) ;
}
2014-12-19 12:14:36 +00:00
}
2016-03-27 21:17:51 +02:00
/// Gets the representation of the current geometrical entity.
2018-07-07 21:14:27 +02:00
Element < P , PP > * get ( )
2016-03-07 22:37:36 +02:00
{
// TODO: Test settings and throw
2018-07-07 21:14:27 +02:00
Element < P , PP > * ret = 0 ;
2019-07-03 12:10:27 +02:00
if ( num_threads_ ! = 1 ) {
ret = * task_result_iterator_ ;
} else {
if ( current_triangulation ) {
ret = current_triangulation ;
} else if ( current_serialization ) {
ret = current_serialization ;
} else if ( current_shape_model ) {
ret = current_shape_model ;
}
}
2017-04-21 15:49:34 +02:00
2017-05-15 17:45:05 +02:00
// If we want to organize the element considering their hierarchy
2017-04-21 15:49:34 +02:00
if ( settings . get ( IteratorSettings : : SEARCH_FLOOR ) )
{
2017-05-15 17:45:05 +02:00
// We are going to build a vector with the element parents.
// First, create the parent vector
2018-07-07 21:14:27 +02:00
std : : vector < const IfcGeom : : Element < P , PP > * > parents ;
2017-05-15 17:45:05 +02:00
2017-04-21 16:02:13 +02:00
// if the element has a parent
2017-04-21 15:49:34 +02:00
if ( ret - > parent_id ( ) ! = - 1 )
{
2018-07-07 21:14:27 +02:00
const IfcGeom : : Element < P , PP > * parent_object = NULL ;
2017-04-21 15:49:34 +02:00
bool hasParent = true ;
2017-04-21 16:02:13 +02:00
// get the parent
2017-08-01 16:45:11 +02:00
try {
2017-12-20 11:10:27 +01:00
parent_object = get_object ( ret - > parent_id ( ) ) ;
2017-08-01 16:45:11 +02:00
} catch ( const std : : exception & e ) {
Logger : : Error ( e ) ;
2017-04-21 15:49:34 +02:00
hasParent = false ;
}
2017-05-15 17:45:05 +02:00
// Add the previously found parent to the vector
if ( hasParent ) parents . insert ( parents . begin ( ) , parent_object ) ;
// We need to find all the parents
2017-09-25 14:57:49 +02:00
while ( parent_object ! = NULL & & hasParent & & parent_object - > parent_id ( ) ! = - 1 )
2017-04-21 15:49:34 +02:00
{
2017-05-15 17:45:05 +02:00
// Find the next parent
2017-08-01 16:45:11 +02:00
try {
2017-12-20 11:10:27 +01:00
parent_object = get_object ( parent_object - > parent_id ( ) ) ;
2017-08-01 16:45:11 +02:00
} catch ( const std : : exception & e ) {
Logger : : Error ( e ) ;
2017-04-21 15:49:34 +02:00
hasParent = false ;
}
2017-05-15 17:45:05 +02:00
// Add the previously found parent to the vector
if ( hasParent ) parents . insert ( parents . begin ( ) , parent_object ) ;
hasParent = hasParent & & parent_object - > parent_id ( ) ! = - 1 ;
2017-04-21 15:49:34 +02:00
}
2017-05-15 17:45:05 +02:00
// when done push the parent list in the Element object
ret - > SetParents ( parents ) ;
2017-04-21 15:49:34 +02:00
}
}
2016-03-07 22:37:36 +02:00
return ret ;
}
2014-12-19 12:14:36 +00:00
2017-01-22 16:09:14 +01:00
/// Gets the native (Open Cascade) representation of the current geometrical entity.
2018-07-07 21:14:27 +02:00
BRepElement < P , PP > * get_native ( )
2017-01-22 16:09:14 +01:00
{
// TODO: Test settings and throw
2019-07-09 16:00:29 +02:00
if ( num_threads_ ! = 1 ) {
return * native_task_result_iterator_ ;
} else {
return current_shape_model ;
}
2017-01-22 16:09:14 +01:00
}
2018-07-07 21:14:27 +02:00
const Element < P , PP > * get_object ( int id ) {
2014-12-19 12:14:36 +00:00
gp_Trsf trsf ;
int parent_id = - 1 ;
std : : string instance_type , product_name , product_guid ;
2017-02-23 18:35:44 +02:00
IfcSchema : : IfcProduct * ifc_product = 0 ;
2017-09-25 14:57:49 +02:00
2014-12-19 12:14:36 +00:00
try {
2017-12-19 20:24:00 +01:00
IfcUtil : : IfcBaseClass * ifc_entity = ifc_file - > instance_by_id ( id ) ;
instance_type = ifc_entity - > declaration ( ) . name ( ) ;
2017-09-25 14:57:49 +02:00
2017-12-18 15:25:09 +01:00
if ( ifc_entity - > declaration ( ) . is ( IfcSchema : : IfcRoot : : Class ( ) ) ) {
2017-09-25 14:57:49 +02:00
IfcSchema : : IfcRoot * ifc_root = ifc_entity - > as < IfcSchema : : IfcRoot > ( ) ;
product_guid = ifc_root - > GlobalId ( ) ;
product_name = ifc_root - > hasName ( ) ? ifc_root - > Name ( ) : " " ;
}
2017-12-18 15:25:09 +01:00
if ( ifc_entity - > declaration ( ) . is ( IfcSchema : : IfcProduct : : Class ( ) ) ) {
2017-09-25 14:57:49 +02:00
ifc_product = ifc_entity - > as < IfcSchema : : IfcProduct > ( ) ;
2015-01-05 14:11:42 +00:00
parent_id = - 1 ;
2014-12-19 12:14:36 +00:00
try {
2018-09-19 14:05:19 +02:00
IfcSchema : : IfcObjectDefinition * parent_object = kernel . get_decomposing_entity ( ifc_product ) - > template as < IfcSchema : : IfcObjectDefinition > ( ) ;
2015-01-05 14:11:42 +00:00
if ( parent_object ) {
2017-12-11 15:07:40 +01:00
parent_id = parent_object - > data ( ) . id ( ) ;
2015-01-05 14:11:42 +00:00
}
2017-08-01 16:45:11 +02:00
} catch ( const std : : exception & e ) {
Logger : : Error ( e ) ;
} catch ( . . . ) {
Logger : : Error ( " Failed to find decomposing entity " ) ;
}
2014-12-19 12:14:36 +00:00
try {
kernel . convert ( ifc_product - > ObjectPlacement ( ) , trsf ) ;
2017-08-01 16:45:11 +02:00
} catch ( const std : : exception & e ) {
Logger : : Error ( e ) ;
} catch ( . . . ) {
Logger : : Error ( " Failed to construct placement " ) ;
}
}
} catch ( const std : : exception & e ) {
Logger : : Error ( e ) ;
} catch ( const Standard_Failure & e ) {
if ( e . GetMessageString ( ) & & strlen ( e . GetMessageString ( ) ) ) {
Logger : : Error ( e . GetMessageString ( ) ) ;
} else {
Logger : : Error ( " Unknown error returning product " ) ;
2014-12-19 12:14:36 +00:00
}
2017-08-01 16:45:11 +02:00
} catch ( . . . ) {
Logger : : Error ( " Unknown error returning product " ) ;
}
2014-12-19 12:14:36 +00:00
ElementSettings element_settings ( settings , unit_magnitude , instance_type ) ;
2017-05-15 17:45:05 +02:00
2018-07-07 21:14:27 +02:00
Element < P , PP > * ifc_object = new Element < P , PP > ( element_settings , id , parent_id , product_name , instance_type , product_guid , " " , trsf , ifc_product ) ;
2014-12-19 12:14:36 +00:00
return ifc_object ;
}
2017-12-19 20:24:00 +01:00
IfcUtil : : IfcBaseClass * create ( ) {
2018-07-07 21:14:27 +02:00
IfcGeom : : BRepElement < P , PP > * next_shape_model = 0 ;
IfcGeom : : SerializedElement < P , PP > * next_serialization = 0 ;
IfcGeom : : TriangulationElement < P , PP > * next_triangulation = 0 ;
2016-03-18 11:23:25 +01:00
2014-12-19 12:14:36 +00:00
try {
2016-03-18 11:23:25 +01:00
next_shape_model = create_shape_model_for_next_entity ( ) ;
2017-08-01 16:45:11 +02:00
} catch ( const std : : exception & e ) {
Logger : : Error ( e ) ;
} catch ( const Standard_Failure & e ) {
if ( e . GetMessageString ( ) & & strlen ( e . GetMessageString ( ) ) ) {
Logger : : Error ( e . GetMessageString ( ) ) ;
} else {
Logger : : Error ( " Unknown error creating geometry " ) ;
}
} catch ( . . . ) {
Logger : : Error ( " Unknown error creating geometry " ) ;
}
2016-03-18 11:23:25 +01:00
2017-02-07 17:34:23 +02:00
if ( next_shape_model ) {
2016-03-22 16:15:28 +01:00
if ( settings . get ( IteratorSettings : : USE_BREP_DATA ) ) {
2016-03-18 11:23:25 +01:00
try {
2018-07-07 21:14:27 +02:00
next_serialization = new SerializedElement < P , PP > ( * next_shape_model ) ;
2016-03-18 11:23:25 +01:00
} catch ( . . . ) {
2016-05-13 12:59:00 +02:00
Logger : : Message ( Logger : : LOG_ERROR , " Getting a serialized element from model failed. " ) ;
2016-03-18 11:23:25 +01:00
}
2016-03-22 16:15:28 +01:00
} else if ( ! settings . get ( IteratorSettings : : DISABLE_TRIANGULATION ) ) {
2016-03-18 11:23:25 +01:00
try {
2017-06-28 15:24:49 +02:00
if ( ifcproduct_iterator = = ifcproducts - > begin ( ) | | ! geometry_reuse_ok_for_current_representation_ ) {
2018-07-07 21:14:27 +02:00
next_triangulation = new TriangulationElement < P , PP > ( * next_shape_model ) ;
2016-03-18 11:23:25 +01:00
} else {
2018-07-07 21:14:27 +02:00
next_triangulation = new TriangulationElement < P , PP > ( * next_shape_model , current_triangulation - > geometry_pointer ( ) ) ;
2016-03-18 11:23:25 +01:00
}
} catch ( . . . ) {
2016-05-13 12:59:00 +02:00
Logger : : Message ( Logger : : LOG_ERROR , " Getting a triangulation element from model failed. " ) ;
2016-03-18 11:23:25 +01:00
}
}
2014-12-19 12:14:36 +00:00
}
2016-03-18 11:23:25 +01:00
free_shapes ( ) ;
2017-02-07 17:34:23 +02:00
current_shape_model = next_shape_model ;
2016-03-18 11:23:25 +01:00
current_serialization = next_serialization ;
current_triangulation = next_triangulation ;
2017-02-07 17:34:23 +02:00
return next_shape_model ? next_shape_model - > product ( ) : 0 ;
2014-12-19 12:14:36 +00:00
}
private :
2015-04-22 09:15:48 +00:00
void _initialize ( ) {
2014-12-19 12:14:36 +00:00
current_triangulation = 0 ;
current_shape_model = 0 ;
current_serialization = 0 ;
2015-02-19 20:17:53 +00:00
2014-12-19 12:14:36 +00:00
unit_name = " METER " ;
unit_magnitude = 1.f ;
2019-05-24 14:29:21 +02:00
kernel . setValue ( IfcGeom : : Kernel : : GV_MAX_FACES_TO_ORIENT , settings . get ( IteratorSettings : : SEW_SHELLS ) ? std : : numeric_limits < double > : : infinity ( ) : - 1 ) ;
2016-03-17 23:25:53 +02:00
kernel . setValue ( IfcGeom : : Kernel : : GV_DIMENSIONALITY , ( settings . get ( IteratorSettings : : INCLUDE_CURVES )
? ( settings . get ( IteratorSettings : : EXCLUDE_SOLIDS_AND_SURFACES ) ? - 1. : 0. ) : + 1. ) ) ;
2020-06-07 19:46:10 +02:00
kernel . setValue ( IfcGeom : : Kernel : : GV_LAYERSET_FIRST ,
settings . get ( IteratorSettings : : LAYERSET_FIRST )
? + 1.0
: - 1.0
) ;
2021-02-05 14:00:23 -06:00
kernel . setValue ( IfcGeom : : Kernel : : GV_NO_WIRE_INTERSECTION_CHECK ,
settings . get ( IteratorSettings : : NO_WIRE_INTERSECTION_CHECK )
? + 1.0
: - 1.0
) ;
2021-02-08 14:06:05 -06:00
kernel . setValue ( IfcGeom : : Kernel : : GV_NO_WIRE_INTERSECTION_TOLERANCE ,
settings . get ( IteratorSettings : : NO_WIRE_INTERSECTION_TOLERANCE )
? + 1.0
: - 1.0
) ;
2021-02-06 10:26:17 -06:00
kernel . setValue ( IfcGeom : : Kernel : : GV_PRECISION_FACTOR ,
settings . get ( IteratorSettings : : STRICT_TOLERANCE )
? 1.0
: 10.0
) ;
2021-02-05 14:00:23 -06:00
2020-11-24 16:58:05 +01:00
kernel . setValue ( IfcGeom : : Kernel : : GV_DISABLE_BOOLEAN_RESULT ,
settings . get ( IteratorSettings : : DISABLE_BOOLEAN_RESULT )
? + 1.0
: - 1.0
) ;
2020-06-07 19:46:10 +02:00
2018-02-14 15:17:37 +01:00
if ( settings . get ( IteratorSettings : : BUILDING_LOCAL_PLACEMENT ) ) {
if ( settings . get ( IteratorSettings : : SITE_LOCAL_PLACEMENT ) ) {
Logger : : Message ( Logger : : LOG_WARNING , " building-local-placement takes precedence over site-local-placement " ) ;
}
2018-07-07 17:15:54 +02:00
kernel . set_conversion_placement_rel_to ( & IfcSchema : : IfcBuilding : : Class ( ) ) ;
2018-02-14 15:17:37 +01:00
} else if ( settings . get ( IteratorSettings : : SITE_LOCAL_PLACEMENT ) ) {
2017-12-19 20:24:00 +01:00
kernel . set_conversion_placement_rel_to ( & IfcSchema : : IfcSite : : Class ( ) ) ;
2017-08-19 17:21:10 +02:00
}
2020-01-31 15:55:04 +01:00
kernel . set_offset ( settings . offset ) ;
kernel . set_rotation ( settings . rotation ) ;
2014-12-19 12:14:36 +00:00
}
2020-03-18 11:59:11 +01:00
2014-12-19 12:14:36 +00:00
public :
2019-07-19 15:55:22 +02:00
MAKE_TYPE_NAME ( IteratorImplementation_ ) ( const IteratorSettings & settings , IfcParse : : IfcFile * file , const std : : vector < IfcGeom : : filter_t > & filters , int num_threads )
2014-12-19 12:14:36 +00:00
: settings ( settings )
, ifc_file ( file )
2018-09-07 14:08:56 +02:00
, filters_ ( filters )
2015-06-20 14:23:59 +00:00
, owns_ifc_file ( false )
2019-07-03 12:10:27 +02:00
, num_threads_ ( num_threads )
2014-12-19 12:14:36 +00:00
{
2015-04-22 09:15:48 +00:00
_initialize ( ) ;
2014-12-19 12:14:36 +00:00
}
2017-12-19 20:24:00 +01:00
~ MAKE_TYPE_NAME ( IteratorImplementation_ ) ( ) {
2015-06-20 14:23:59 +00:00
if ( owns_ifc_file ) {
delete ifc_file ;
}
2014-12-19 12:14:36 +00:00
2019-12-14 13:23:40 +01:00
if ( ! settings . get ( IfcGeom : : IteratorSettings : : DISABLE_TRIANGULATION ) ) {
2019-07-09 16:34:35 +02:00
for ( auto & p : all_processed_native_elements_ ) {
delete p ;
}
}
for ( auto & p : all_processed_elements_ ) {
delete p ;
}
2016-03-18 11:23:25 +01:00
free_shapes ( ) ;
2014-12-19 12:14:36 +00:00
}
} ;
}
# endif