mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-17 05:52:33 +00:00
Linearizing the use of IfcGeomIterator by integrating it into IfcConvert in full, atm it does not build.
This commit is contained in:
+588
-89
@@ -49,6 +49,10 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <future>
|
||||||
|
#include <thread>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
#if USE_VLD
|
#if USE_VLD
|
||||||
#include <vld.h>
|
#include <vld.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -75,6 +79,29 @@ const std::string TEMP_FILE_EXTENSION = ".tmp";
|
|||||||
|
|
||||||
namespace po = boost::program_options;
|
namespace po = boost::program_options;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct IfcproductRepresentation
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
IfcSchema::IfcRepresentation *representation;
|
||||||
|
IfcSchema::IfcProduct *product;
|
||||||
|
IfcGeom::Element<real_t> *geom_object;
|
||||||
|
IfcGeom::BRepElement<real_t> *element;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Bounds
|
||||||
|
{
|
||||||
|
gp_XYZ min;
|
||||||
|
gp_XYZ max;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool reuse_ok_(SerializerSettings settings, const IfcSchema::IfcProduct::list::ptr &products, IfcGeom::Kernel kernel);
|
||||||
|
void create_element(SerializerSettings &settings,IfcproductRepresentation &rep);
|
||||||
|
Bounds compute_bounds(IfcParse::IfcFile* ifc_file, IfcGeom::Kernel kernel);
|
||||||
|
|
||||||
|
|
||||||
void print_version()
|
void print_version()
|
||||||
{
|
{
|
||||||
cout_ << "IfcOpenShell " << IfcSchema::Identifier << " IfcConvert " << IFCOPENSHELL_VERSION << " (OCC " << OCC_VERSION_STRING_EXT << ")\n";
|
cout_ << "IfcOpenShell " << IfcSchema::Identifier << " IfcConvert " << IFCOPENSHELL_VERSION << " (OCC " << OCC_VERSION_STRING_EXT << ")\n";
|
||||||
@@ -115,6 +142,7 @@ void print_options(const po::options_description& options)
|
|||||||
cout_ << std::endl;
|
cout_ << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T change_extension(const T& fn, const T& ext) {
|
T change_extension(const T& fn, const T& ext) {
|
||||||
typename T::size_type dot = fn.find_last_of('.');
|
typename T::size_type dot = fn.find_last_of('.');
|
||||||
@@ -177,7 +205,7 @@ int wmain(int argc, wchar_t** argv) {
|
|||||||
_setmode(_fileno(stdout), _O_U16TEXT);
|
_setmode(_fileno(stdout), _O_U16TEXT);
|
||||||
_setmode(_fileno(stderr), _O_U16TEXT);
|
_setmode(_fileno(stderr), _O_U16TEXT);
|
||||||
#else
|
#else
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
typedef po::command_line_parser command_line_parser;
|
typedef po::command_line_parser command_line_parser;
|
||||||
typedef char char_t;
|
typedef char char_t;
|
||||||
#endif
|
#endif
|
||||||
@@ -560,12 +588,18 @@ int main(int argc, char** argv) {
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!entity_filter.values.empty()) { entity_filter.update_description(); Logger::Notice(entity_filter.description); }
|
if (!entity_filter.values.empty()) {
|
||||||
if (!layer_filter.values.empty()) { layer_filter.update_description(); Logger::Notice(layer_filter.description); }
|
entity_filter.update_description(); Logger::Notice(entity_filter.description); }
|
||||||
if (!guid_filter.values.empty()) { guid_filter.update_description(); Logger::Notice(guid_filter.description); }
|
if (!layer_filter.values.empty()) {
|
||||||
if (!name_filter.values.empty()) { name_filter.update_description(); Logger::Notice(name_filter.description); }
|
layer_filter.update_description(); Logger::Notice(layer_filter.description); }
|
||||||
if (!desc_filter.values.empty()) { desc_filter.update_description(); Logger::Notice(desc_filter.description); }
|
if (!guid_filter.values.empty()) {
|
||||||
if (!tag_filter.values.empty()) { tag_filter.update_description(); Logger::Notice(tag_filter.description); }
|
guid_filter.update_description(); Logger::Notice(guid_filter.description); }
|
||||||
|
if (!name_filter.values.empty()) {
|
||||||
|
name_filter.update_description(); Logger::Notice(name_filter.description); }
|
||||||
|
if (!desc_filter.values.empty()) {
|
||||||
|
desc_filter.update_description(); Logger::Notice(desc_filter.description); }
|
||||||
|
if (!tag_filter.values.empty()) {
|
||||||
|
tag_filter.update_description(); Logger::Notice(tag_filter.description); }
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
if (output_extension == DAE || output_extension == STP || output_extension == IGS) {
|
if (output_extension == DAE || output_extension == STP || output_extension == IGS) {
|
||||||
@@ -600,8 +634,6 @@ int main(int argc, char** argv) {
|
|||||||
settings.set(IfcGeom::IteratorSettings::SEARCH_FLOOR, use_element_hierarchy);
|
settings.set(IfcGeom::IteratorSettings::SEARCH_FLOOR, use_element_hierarchy);
|
||||||
settings.set(IfcGeom::IteratorSettings::SITE_LOCAL_PLACEMENT, site_local_placement);
|
settings.set(IfcGeom::IteratorSettings::SITE_LOCAL_PLACEMENT, site_local_placement);
|
||||||
settings.set(IfcGeom::IteratorSettings::BUILDING_LOCAL_PLACEMENT, building_local_placement);
|
settings.set(IfcGeom::IteratorSettings::BUILDING_LOCAL_PLACEMENT, building_local_placement);
|
||||||
|
|
||||||
|
|
||||||
settings.set(SerializerSettings::USE_ELEMENT_NAMES, use_element_names);
|
settings.set(SerializerSettings::USE_ELEMENT_NAMES, use_element_names);
|
||||||
settings.set(SerializerSettings::USE_ELEMENT_GUIDS, use_element_guids);
|
settings.set(SerializerSettings::USE_ELEMENT_GUIDS, use_element_guids);
|
||||||
settings.set(SerializerSettings::USE_MATERIAL_NAMES, use_material_names);
|
settings.set(SerializerSettings::USE_MATERIAL_NAMES, use_material_names);
|
||||||
@@ -610,17 +642,25 @@ int main(int argc, char** argv) {
|
|||||||
settings.set_deflection_tolerance(deflection_tolerance);
|
settings.set_deflection_tolerance(deflection_tolerance);
|
||||||
settings.precision = precision;
|
settings.precision = precision;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Set up serializer
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
boost::shared_ptr<GeometrySerializer> serializer; /**< @todo use std::unique_ptr when possible */
|
boost::shared_ptr<GeometrySerializer> serializer; /**< @todo use std::unique_ptr when possible */
|
||||||
if (output_extension == OBJ) {
|
|
||||||
|
if (output_extension == OBJ)
|
||||||
|
{
|
||||||
// Do not use temp file for MTL as it's such a small file.
|
// Do not use temp file for MTL as it's such a small file.
|
||||||
const path_t mtl_filename = change_extension(output_filename, MTL);
|
const path_t mtl_filename = change_extension(output_filename, MTL);
|
||||||
if (!use_world_coords) {
|
if (!use_world_coords)
|
||||||
|
{
|
||||||
Logger::Notice("Using world coords when writing WaveFront OBJ files");
|
Logger::Notice("Using world coords when writing WaveFront OBJ files");
|
||||||
settings.set(IfcGeom::IteratorSettings::USE_WORLD_COORDS, true);
|
settings.set(IfcGeom::IteratorSettings::USE_WORLD_COORDS, true);
|
||||||
}
|
}
|
||||||
serializer = boost::make_shared<WaveFrontOBJSerializer>(IfcUtil::path::to_utf8(output_temp_filename), IfcUtil::path::to_utf8(mtl_filename), settings);
|
serializer = boost::make_shared<WaveFrontOBJSerializer>(IfcUtil::path::to_utf8(output_temp_filename), IfcUtil::path::to_utf8(mtl_filename), settings);
|
||||||
#ifdef WITH_OPENCOLLADA
|
#ifdef WITH_OPENCOLLADA
|
||||||
} else if (output_extension == DAE) {
|
} else if (output_extension == DAE)
|
||||||
|
{
|
||||||
serializer = boost::make_shared<ColladaSerializer>(IfcUtil::path::to_utf8(output_temp_filename), settings);
|
serializer = boost::make_shared<ColladaSerializer>(IfcUtil::path::to_utf8(output_temp_filename), settings);
|
||||||
#endif
|
#endif
|
||||||
} else if (output_extension == STP) {
|
} else if (output_extension == STP) {
|
||||||
@@ -684,20 +724,196 @@ int main(int argc, char** argv) {
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// initialize geometry
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
serializer->setFile(&ifc_file);
|
||||||
|
|
||||||
IfcGeom::Iterator<real_t> context_iterator(settings, &ifc_file, filter_funcs);
|
IfcGeom::Iterator<real_t> context_iterator(settings, &ifc_file, filter_funcs);
|
||||||
if (!context_iterator.initialize()) {
|
IfcGeom::Kernel kernel;
|
||||||
/// @todo It would be nice to know and print separate error prints for a case where we found no entities
|
std::string unit_name = "METER" ;
|
||||||
/// and for a case we found no entities that satisfy our filtering criteria.
|
double unit_magnitude = 1.f;
|
||||||
|
IfcSchema::IfcRepresentation::list::ptr ok_mapped_representations;
|
||||||
|
IfcSchema::IfcRepresentation::list::ptr representations =
|
||||||
|
IfcSchema::IfcRepresentation::list::ptr(new IfcSchema::IfcRepresentation::list);
|
||||||
|
IfcSchema::IfcRepresentation::list::it representation_iterator;
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
// TriangulationElement<P>* current_triangulation =0 ;
|
||||||
|
// BRepElement<P>* current_shape_model = 0;
|
||||||
|
// SerializedElement<P>* current_serialization = 0;
|
||||||
|
kernel.setValue(IfcGeom::Kernel::GV_MAX_FACES_TO_SEW, settings.get(IfcGeom::IteratorSettings::SEW_SHELLS) ? 1000 : -1);
|
||||||
|
kernel.setValue(IfcGeom::Kernel::GV_DIMENSIONALITY, (settings.get(IfcGeom::IteratorSettings::INCLUDE_CURVES)
|
||||||
|
? (settings.get(IfcGeom::IteratorSettings::EXCLUDE_SOLIDS_AND_SURFACES) ? -1. : 0.) : +1.));
|
||||||
|
if (settings.get(IfcGeom::IteratorSettings::BUILDING_LOCAL_PLACEMENT)) {
|
||||||
|
if (settings.get(IfcGeom::IteratorSettings::SITE_LOCAL_PLACEMENT)) {
|
||||||
|
Logger::Message(Logger::LOG_WARNING, "building-local-placement takes precedence over site-local-placement");
|
||||||
|
}
|
||||||
|
kernel.set_conversion_placement_rel_to(IfcSchema::Type::IfcBuilding);
|
||||||
|
} else if (settings.get(IfcGeom::IteratorSettings::SITE_LOCAL_PLACEMENT)) {
|
||||||
|
kernel.set_conversion_placement_rel_to(IfcSchema::Type::IfcSite);
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize()
|
||||||
|
// initunits()
|
||||||
|
IfcSchema::IfcProject::list::ptr projects = ifc_file.entitiesByType<IfcSchema::IfcProject>();
|
||||||
|
std::set<std::string> allowed_context_types;
|
||||||
|
std::set<std::string> context_types;
|
||||||
|
double lowest_precision_encountered = std::numeric_limits<double>::infinity();
|
||||||
|
bool any_precision_encountered = false;
|
||||||
|
|
||||||
|
if (projects->size() == 1) {
|
||||||
|
IfcSchema::IfcProject* project = *projects->begin();
|
||||||
|
std::pair<std::string, double> length_unit = kernel.initializeUnits(project->UnitsInContext());
|
||||||
|
unit_name = length_unit.first;
|
||||||
|
unit_magnitude = length_unit.second;
|
||||||
|
} else {
|
||||||
|
Logger::Error("A single IfcProject is expected (encountered " + boost::lexical_cast<std::string>(projects->size()) + "); unable to read unit information.");
|
||||||
|
}
|
||||||
|
|
||||||
|
allowed_context_types.insert("model");
|
||||||
|
allowed_context_types.insert("plan");
|
||||||
|
allowed_context_types.insert("notdefined");
|
||||||
|
if (!settings.get(IfcGeom::IteratorSettings::EXCLUDE_SOLIDS_AND_SURFACES)) {
|
||||||
|
// 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");
|
||||||
|
// Some earlier (?) versions DDS-CAD output their own ContextTypes
|
||||||
|
context_types.insert("model view");
|
||||||
|
context_types.insert("detail view");
|
||||||
|
}
|
||||||
|
if (settings.get(IfcGeom::IteratorSettings::INCLUDE_CURVES)) {
|
||||||
|
context_types.insert("plan");
|
||||||
|
}
|
||||||
|
|
||||||
|
representations = IfcSchema::IfcRepresentation::list::ptr(new IfcSchema::IfcRepresentation::list);
|
||||||
|
ok_mapped_representations = IfcSchema::IfcRepresentation::list::ptr(new IfcSchema::IfcRepresentation::list);
|
||||||
|
|
||||||
|
IfcSchema::IfcGeometricRepresentationContext::list::it it;
|
||||||
|
IfcSchema::IfcGeometricRepresentationSubContext::list::it jt;
|
||||||
|
IfcSchema::IfcGeometricRepresentationContext::list::ptr contexts =
|
||||||
|
ifc_file.entitiesByType<IfcSchema::IfcGeometricRepresentationContext>();
|
||||||
|
|
||||||
|
IfcSchema::IfcGeometricRepresentationContext::list::ptr filtered_contexts (new IfcSchema::IfcGeometricRepresentationContext::list);
|
||||||
|
|
||||||
|
for (it = contexts->begin(); it != contexts->end(); ++it) {
|
||||||
|
IfcSchema::IfcGeometricRepresentationContext* context = *it;
|
||||||
|
if (context->is(IfcSchema::Type::IfcGeometricRepresentationSubContext)) {
|
||||||
|
// Continue, as the list of subcontexts will be considered
|
||||||
|
// by the parent's context inverse attributes.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (context->hasContextType()) {
|
||||||
|
std::string context_type = context->ContextType();
|
||||||
|
boost::to_lower(context_type);
|
||||||
|
if (allowed_context_types.find(context_type) == allowed_context_types.end()) {
|
||||||
|
Logger::Message(Logger::LOG_ERROR, std::string("ContextType '") + context->ContextType() + "' not allowed:", context->entity);
|
||||||
|
} // == allowed_context_types.end()
|
||||||
|
if (context_types.find(context_type) != context_types.end()) {
|
||||||
|
filtered_contexts->push(context);
|
||||||
|
} // != context_types.end()
|
||||||
|
} // hasContextType()
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
Logger::Error(e);
|
||||||
|
}
|
||||||
|
} // end iterating contexts
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
if (filtered_contexts->size() == 0) {
|
||||||
|
for (it = contexts->begin(); it != contexts->end(); ++it) {
|
||||||
|
IfcSchema::IfcGeometricRepresentationContext* context = *it;
|
||||||
|
if (!context->is(IfcSchema::Type::IfcGeometricRepresentationSubContext)) {
|
||||||
|
filtered_contexts->push(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (it = filtered_contexts->begin(); it != filtered_contexts->end(); ++it) {
|
||||||
|
IfcSchema::IfcGeometricRepresentationContext* context = *it;
|
||||||
|
|
||||||
|
representations->push(context->RepresentationsInContext());
|
||||||
|
try {
|
||||||
|
if (context->hasPrecision() && context->Precision() < lowest_precision_encountered) {
|
||||||
|
lowest_precision_encountered = context->Precision();
|
||||||
|
any_precision_encountered = true;
|
||||||
|
}
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
Logger::Error(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
|
} // end iterating filtered_contexts
|
||||||
|
|
||||||
|
if (any_precision_encountered) {
|
||||||
|
// Some arbitrary factor that has proven to work better for the models in the set of test files.
|
||||||
|
lowest_precision_encountered *= 10.;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
kernel.setValue(IfcGeom::Kernel::GV_PRECISION, 1.e-5);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (representations->size() == 0) {
|
||||||
|
Logger::Message(Logger::LOG_ERROR, "No representations encountered in relevant contexts, using all");
|
||||||
|
representations = ifc_file.entitiesByType<IfcSchema::IfcRepresentation>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (representations->size() == 0) {
|
||||||
|
Logger::Message(Logger::LOG_ERROR, "No representations encountered, aborting");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// representation_iterator = representations->begin();
|
||||||
|
// ifcproducts.reset();
|
||||||
|
|
||||||
|
// if (!create()) {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// done = 0;
|
||||||
|
// total = representations->size();
|
||||||
|
|
||||||
|
// return true;
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
Logger::Error(e);
|
||||||
Logger::Error("No geometrical entities found");
|
Logger::Error("No geometrical entities found");
|
||||||
IfcUtil::path::delete_file(IfcUtil::path::to_utf8(output_temp_filename));
|
IfcUtil::path::delete_file(IfcUtil::path::to_utf8(output_temp_filename));
|
||||||
write_log(!quiet);
|
write_log(!quiet);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
serializer->setFile(context_iterator.getFile());
|
//replaces:
|
||||||
|
// if (!context_iterator.initialize()) {
|
||||||
|
// /// @todo It would be nice to know and print separate error prints for a case where we found no entities
|
||||||
|
// /// and for a case we found no entities that satisfy our filtering criteria.
|
||||||
|
// Logger::Error("No geometrical entities found");
|
||||||
|
// IfcUtil::path::delete_file(IfcUtil::path::to_utf8(output_temp_filename));
|
||||||
|
// write_log(!quiet);
|
||||||
|
// return EXIT_FAILURE;
|
||||||
|
// }
|
||||||
|
|
||||||
if (convert_back_units) {
|
if (convert_back_units) {
|
||||||
serializer->setUnitNameAndMagnitude(context_iterator.getUnitName(), static_cast<float>(context_iterator.getUnitMagnitude()));
|
// serializer->setUnitNameAndMagnitude(context_iterator.getUnitName(), static_cast<float>(context_iterator.getUnitMagnitude()));
|
||||||
|
serializer->setUnitNameAndMagnitude(unit_name, static_cast<float>(unit_magnitude));
|
||||||
} else {
|
} else {
|
||||||
serializer->setUnitNameAndMagnitude("METER", 1.0f);
|
serializer->setUnitNameAndMagnitude("METER", 1.0f);
|
||||||
}
|
}
|
||||||
@@ -705,7 +921,7 @@ int main(int argc, char** argv) {
|
|||||||
serializer->writeHeader();
|
serializer->writeHeader();
|
||||||
|
|
||||||
int old_progress = quiet ? 0 : -1;
|
int old_progress = quiet ? 0 : -1;
|
||||||
|
Bounds model_bounds;
|
||||||
if (is_tesselated && (center_model || model_offset)) {
|
if (is_tesselated && (center_model || model_offset)) {
|
||||||
double* offset = serializer->settings().offset;
|
double* offset = serializer->settings().offset;
|
||||||
if (center_model) {
|
if (center_model) {
|
||||||
@@ -715,10 +931,10 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!quiet) Logger::Status("Computing bounds...");
|
if (!quiet) Logger::Status("Computing bounds...");
|
||||||
context_iterator.compute_bounds();
|
model_bounds = compute_bounds( &ifc_file, kernel );
|
||||||
if (!quiet) Logger::Status("Done!");
|
if (!quiet) Logger::Status("Done!");
|
||||||
|
|
||||||
gp_XYZ center = (context_iterator.bounds_min() + context_iterator.bounds_max()) * 0.5;
|
gp_XYZ center = (model_bounds.min + model_bounds.max) * 0.5;
|
||||||
offset[0] = -center.X();
|
offset[0] = -center.X();
|
||||||
offset[1] = -center.Y();
|
offset[1] = -center.Y();
|
||||||
offset[2] = -center.Z();
|
offset[2] = -center.Z();
|
||||||
@@ -752,50 +968,218 @@ int main(int argc, char** argv) {
|
|||||||
// available.
|
// available.
|
||||||
size_t num_created = 0;
|
size_t num_created = 0;
|
||||||
|
|
||||||
do {
|
|
||||||
IfcGeom::Element<real_t> *geom_object = context_iterator.get();
|
|
||||||
|
|
||||||
if (is_tesselated)
|
////////////////////////////////////////////////////////////
|
||||||
|
// start initializing elements for threading
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
std::vector<IfcproductRepresentation> IfcproductRepresentations;
|
||||||
|
|
||||||
|
// do {
|
||||||
|
// IfcGeom::Element<real_t> *geom_object = context_iterator.get();
|
||||||
|
|
||||||
|
// if (is_tesselated)
|
||||||
|
// {
|
||||||
|
// serializer->write(static_cast<const IfcGeom::TriangulationElement<real_t>*>(geom_object));
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// serializer->write(static_cast<const IfcGeom::BRepElement<real_t>*>(geom_object));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (!no_progress) {
|
||||||
|
// if (quiet) {
|
||||||
|
// const int progress = context_iterator.progress();
|
||||||
|
// for (; old_progress < progress; ++old_progress) {
|
||||||
|
// std::cout << ".";
|
||||||
|
// if (stderr_progress)
|
||||||
|
// std::cerr << ".";
|
||||||
|
// }
|
||||||
|
// std::cout << std::flush;
|
||||||
|
// if (stderr_progress)
|
||||||
|
// std::cerr << std::flush;
|
||||||
|
// } else {
|
||||||
|
// const int progress = context_iterator.progress() / 2;
|
||||||
|
// if (old_progress != progress) Logger::ProgressBar(progress);
|
||||||
|
// old_progress = progress;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } while (++num_created, context_iterator.next());
|
||||||
|
|
||||||
|
// if (!no_progress && quiet) {
|
||||||
|
// for (; old_progress < 100; ++old_progress) {
|
||||||
|
// std::cout << ".";
|
||||||
|
// if (stderr_progress)
|
||||||
|
// std::cerr << ".";
|
||||||
|
// }
|
||||||
|
// std::cout << std::flush;
|
||||||
|
// if (stderr_progress)
|
||||||
|
// std::cerr << std::flush;
|
||||||
|
// } else {
|
||||||
|
// Logger::Status("\rDone creating geometry (" + boost::lexical_cast<std::string>(num_created) +
|
||||||
|
// " objects) ");
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Copy/Paste from IfcInfo, fine-tooth comb over vars
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/////// find products associated with representations (... ?)
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
IfcSchema::IfcProduct::list::ptr ifcproducts;
|
||||||
|
IfcSchema::IfcProduct::list::it ifcproduct_iterator;
|
||||||
|
std::vector<IfcGeom::filter_t> filters_;
|
||||||
|
|
||||||
|
IfcGeom::layer_filter layer_filter;
|
||||||
|
IfcGeom::entity_filter entity_filter;
|
||||||
|
IfcGeom::string_arg_filter guid_filter(IfcSchema::Type::IfcRoot, 0);
|
||||||
|
IfcGeom::string_arg_filter name_filter(IfcSchema::Type::IfcRoot, 2);
|
||||||
|
IfcGeom::string_arg_filter desc_filter(IfcSchema::Type::IfcRoot, 3);
|
||||||
|
IfcGeom::string_arg_filter tag_filter(IfcSchema::Type::IfcProxy, 8,
|
||||||
|
IfcSchema::Type::IfcElement,
|
||||||
|
7);
|
||||||
|
filters_.emplace_back(boost::ref(layer_filter));
|
||||||
|
filters_.emplace_back(boost::ref(entity_filter));
|
||||||
|
filters_.emplace_back(boost::ref(guid_filter));
|
||||||
|
filters_.emplace_back(boost::ref(name_filter));
|
||||||
|
filters_.emplace_back(boost::ref(desc_filter));
|
||||||
|
filters_.emplace_back(boost::ref(tag_filter));
|
||||||
|
bool geometry_reuse_ok_for_current_representation_;
|
||||||
|
|
||||||
|
// functor
|
||||||
|
struct filter_match
|
||||||
{
|
{
|
||||||
serializer->write(static_cast<const IfcGeom::TriangulationElement<real_t>*>(geom_object));
|
filter_match(IfcSchema::IfcProduct *prod) : product(prod) {}
|
||||||
|
bool operator()(const IfcGeom::filter_t &filter) const { return filter(product); }
|
||||||
|
IfcSchema::IfcProduct *product;
|
||||||
|
};
|
||||||
|
|
||||||
|
Logger::Status("starting to iterate over representations ");
|
||||||
|
|
||||||
|
start = std::chrono::system_clock::now();
|
||||||
|
int index_count = 0;
|
||||||
|
for (representation_iterator = representations->begin();
|
||||||
|
representation_iterator != representations->end(); representation_iterator++)
|
||||||
|
{
|
||||||
|
IfcSchema::IfcRepresentation *representation = *representation_iterator;
|
||||||
|
ifcproducts.reset();
|
||||||
|
ifcproducts = IfcSchema::IfcProduct::list::ptr(new IfcSchema::IfcProduct::list);
|
||||||
|
IfcSchema::IfcProduct::list::ptr unfiltered_products =
|
||||||
|
kernel.products_represented_by(representation);
|
||||||
|
geometry_reuse_ok_for_current_representation_ = reuse_ok_(settings, unfiltered_products);
|
||||||
|
IfcSchema::IfcRepresentationMap::list::ptr maps = representation->RepresentationMap();
|
||||||
|
if (!geometry_reuse_ok_for_current_representation_ && maps->size() == 1)
|
||||||
|
{
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
// NOTE(sander): is this equivalent to _nextShape() ?
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool representation_processed_as_mapped_item = false;
|
||||||
|
IfcSchema::IfcRepresentation *representation_mapped_to =
|
||||||
|
kernel.representation_mapped_to(representation);
|
||||||
|
if (representation_mapped_to)
|
||||||
|
{
|
||||||
|
// Check if this representation has (or will be) processed as part its mapped
|
||||||
|
// representation
|
||||||
|
bool contains = ok_mapped_representations->contains(representation_mapped_to);
|
||||||
|
bool reuse = reuse_ok_(settings, kernel.products_represented_by(representation_mapped_to));
|
||||||
|
representation_processed_as_mapped_item = contains || reuse;
|
||||||
|
}
|
||||||
|
if (representation_processed_as_mapped_item)
|
||||||
|
{
|
||||||
|
ok_mapped_representations->push(representation_mapped_to);
|
||||||
|
// _nextShape();
|
||||||
|
// continue;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Filter the products based on the set of entities and/or names being included or excluded
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
} // end for unfiltered_products
|
||||||
|
|
||||||
|
for (ifcproduct_iterator = ifcproducts->begin(); ifcproduct_iterator != ifcproducts->end();
|
||||||
|
ifcproduct_iterator++)
|
||||||
|
{
|
||||||
|
IfcproductRepresentation ir;
|
||||||
|
ir.index = index_count;
|
||||||
|
ir.product = *ifcproduct_iterator;
|
||||||
|
ir.representation = representation;
|
||||||
|
IfcproductRepresentations.push_back(ir);
|
||||||
|
index_count++;
|
||||||
|
} // end for ifcproducts
|
||||||
|
|
||||||
|
} // for representation in representations
|
||||||
|
end = std::chrono::system_clock::now();
|
||||||
|
elapsed_seconds = end - start;
|
||||||
|
Logger::Status("iterated over representations: " + std::to_string(elapsed_seconds.count()));
|
||||||
|
Logger::Status("count: " + std::to_string(index_count));
|
||||||
|
|
||||||
|
const unsigned int conc_threads = std::thread::hardware_concurrency();
|
||||||
|
std::cout << "amount of threads available for use on this machine: " << conc_threads << std::endl;
|
||||||
|
std::vector<std::future<void>> threadpool;
|
||||||
|
count = 0;
|
||||||
|
for (int j = 0; j < (int)IfcproductRepresentations.size();)
|
||||||
|
{
|
||||||
|
IfcproductRepresentation &r = IfcproductRepresentations[j];
|
||||||
|
if (threadpool.size() < conc_threads)
|
||||||
|
{
|
||||||
|
std::future<void> fu = std::async(std::launch::async, create_element, std::ref(settings), std::ref(r));
|
||||||
|
threadpool.emplace_back(std::move(fu));
|
||||||
|
j++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
serializer->write(static_cast<const IfcGeom::BRepElement<real_t>*>(geom_object));
|
bool waiting = true;
|
||||||
|
while (waiting)
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
threadpool.erase(threadpool.begin() + i);
|
||||||
|
waiting = false;
|
||||||
|
} // if
|
||||||
|
} // for
|
||||||
|
} // while
|
||||||
|
} // else
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!no_progress) {
|
for (std::future<void> &fu : threadpool)
|
||||||
if (quiet) {
|
{
|
||||||
const int progress = context_iterator.progress();
|
fu.get();
|
||||||
for (; old_progress < progress; ++old_progress) {
|
|
||||||
std::cout << ".";
|
|
||||||
if (stderr_progress)
|
|
||||||
std::cerr << ".";
|
|
||||||
}
|
}
|
||||||
std::cout << std::flush;
|
|
||||||
if (stderr_progress)
|
|
||||||
std::cerr << std::flush;
|
|
||||||
} else {
|
|
||||||
const int progress = context_iterator.progress() / 2;
|
|
||||||
if (old_progress != progress) Logger::ProgressBar(progress);
|
|
||||||
old_progress = progress;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (++num_created, context_iterator.next());
|
|
||||||
|
|
||||||
if (!no_progress && quiet) {
|
|
||||||
for (; old_progress < 100; ++old_progress) {
|
|
||||||
std::cout << ".";
|
////////////////////////////////////////////////////////////
|
||||||
if (stderr_progress)
|
//
|
||||||
std::cerr << ".";
|
////////////////////////////////////////////////////////////
|
||||||
}
|
|
||||||
std::cout << std::flush;
|
|
||||||
if (stderr_progress)
|
|
||||||
std::cerr << std::flush;
|
|
||||||
} else {
|
|
||||||
Logger::Status("\rDone creating geometry (" + boost::lexical_cast<std::string>(num_created) +
|
|
||||||
" objects) ");
|
|
||||||
}
|
|
||||||
|
|
||||||
serializer->finalize();
|
serializer->finalize();
|
||||||
// Make sure the dtor is explicitly run here (e.g. output files are closed before renaming them).
|
// Make sure the dtor is explicitly run here (e.g. output files are closed before renaming them).
|
||||||
@@ -818,10 +1202,10 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return successful ? EXIT_SUCCESS : EXIT_FAILURE;
|
return successful ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string format_duration(time_t start, time_t end)
|
std::string format_duration(time_t start, time_t end)
|
||||||
{
|
{
|
||||||
int seconds = (int)difftime(end, start);
|
int seconds = (int)difftime(end, start);
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
int minutes = seconds / 60;
|
int minutes = seconds / 60;
|
||||||
@@ -838,9 +1222,9 @@ std::string format_duration(time_t start, time_t end)
|
|||||||
ss << "s";
|
ss << "s";
|
||||||
}
|
}
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_log(bool header) {
|
void write_log(bool header) {
|
||||||
path_t log = log_stream.str();
|
path_t log = log_stream.str();
|
||||||
if (!log.empty()) {
|
if (!log.empty()) {
|
||||||
if (header) {
|
if (header) {
|
||||||
@@ -848,10 +1232,10 @@ void write_log(bool header) {
|
|||||||
}
|
}
|
||||||
cout_ << log << std::endl;
|
cout_ << log << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool init_input_file(const std::string &filename, IfcParse::IfcFile &ifc_file, bool no_progress, bool mmap)
|
bool init_input_file(const std::string &filename, IfcParse::IfcFile &ifc_file, bool no_progress, bool mmap)
|
||||||
{
|
{
|
||||||
time_t start, end;
|
time_t start, end;
|
||||||
|
|
||||||
// Prevent IfcFile::Init() prints by setting output to null temporarily
|
// Prevent IfcFile::Init() prints by setting output to null temporarily
|
||||||
@@ -873,10 +1257,10 @@ bool init_input_file(const std::string &filename, IfcParse::IfcFile &ifc_file, b
|
|||||||
else { Logger::Status("Parsing input file took " + format_duration(start, end)); }
|
else { Logger::Status("Parsing input file took " + format_duration(start, end)); }
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool append_filter(const std::string& type, const std::vector<std::string>& values, geom_filter& filter)
|
bool append_filter(const std::string& type, const std::vector<std::string>& values, geom_filter& filter)
|
||||||
{
|
{
|
||||||
geom_filter temp;
|
geom_filter temp;
|
||||||
parse_filter(temp, values);
|
parse_filter(temp, values);
|
||||||
// Merge values only if type and arg match.
|
// Merge values only if type and arg match.
|
||||||
@@ -888,15 +1272,15 @@ bool append_filter(const std::string& type, const std::vector<std::string>& valu
|
|||||||
filter.values.insert(temp.values.begin(), temp.values.end());
|
filter.values.insert(temp.values.begin(), temp.values.end());
|
||||||
filter.arg = temp.arg;
|
filter.arg = temp.arg;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t read_filters_from_file(
|
size_t read_filters_from_file(
|
||||||
const std::string& filename,
|
const std::string& filename,
|
||||||
inclusion_filter& include_filter,
|
inclusion_filter& include_filter,
|
||||||
inclusion_traverse_filter& include_traverse_filter,
|
inclusion_traverse_filter& include_traverse_filter,
|
||||||
exclusion_filter& exclude_filter,
|
exclusion_filter& exclude_filter,
|
||||||
exclusion_traverse_filter& exclude_traverse_filter)
|
exclusion_traverse_filter& exclude_traverse_filter)
|
||||||
{
|
{
|
||||||
std::ifstream filter_file(IfcUtil::path::from_utf8(filename).c_str());
|
std::ifstream filter_file(IfcUtil::path::from_utf8(filename).c_str());
|
||||||
|
|
||||||
if (!filter_file.is_open()) {
|
if (!filter_file.is_open()) {
|
||||||
@@ -944,10 +1328,10 @@ size_t read_filters_from_file(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return num_filters;
|
return num_filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse_filter(geom_filter &filter, const std::vector<std::string>& values)
|
void parse_filter(geom_filter &filter, const std::vector<std::string>& values)
|
||||||
{
|
{
|
||||||
if (values.size() == 0) {
|
if (values.size() == 0) {
|
||||||
throw po::validation_error(po::validation_error::at_least_one_value_required);
|
throw po::validation_error(po::validation_error::at_least_one_value_required);
|
||||||
}
|
}
|
||||||
@@ -966,46 +1350,46 @@ void parse_filter(geom_filter &filter, const std::vector<std::string>& values)
|
|||||||
throw po::validation_error(po::validation_error::invalid_option_value);
|
throw po::validation_error(po::validation_error::invalid_option_value);
|
||||||
}
|
}
|
||||||
filter.values.insert(values.begin() + (filter.type == geom_filter::ENTITY_ARG ? 2 : 1), values.end());
|
filter.values.insert(values.begin() + (filter.type == geom_filter::ENTITY_ARG ? 2 : 1), values.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
void validate(boost::any& v, const std::vector<std::string>& values, inclusion_filter*, int)
|
void validate(boost::any& v, const std::vector<std::string>& values, inclusion_filter*, int)
|
||||||
{
|
{
|
||||||
/// @todo For now only single --include, --include+, --exclude, or --exclude+ supported. Support having multiple.
|
/// @todo For now only single --include, --include+, --exclude, or --exclude+ supported. Support having multiple.
|
||||||
po::validators::check_first_occurrence(v);
|
po::validators::check_first_occurrence(v);
|
||||||
inclusion_filter filter;
|
inclusion_filter filter;
|
||||||
parse_filter(filter, values);
|
parse_filter(filter, values);
|
||||||
v = filter;
|
v = filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
void validate(boost::any& v, const std::vector<std::string>& values, inclusion_traverse_filter*, int)
|
void validate(boost::any& v, const std::vector<std::string>& values, inclusion_traverse_filter*, int)
|
||||||
{
|
{
|
||||||
po::validators::check_first_occurrence(v);
|
po::validators::check_first_occurrence(v);
|
||||||
inclusion_traverse_filter filter;
|
inclusion_traverse_filter filter;
|
||||||
parse_filter(filter, values);
|
parse_filter(filter, values);
|
||||||
v = filter;
|
v = filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
void validate(boost::any& v, const std::vector<std::string>& values, exclusion_filter*, int)
|
void validate(boost::any& v, const std::vector<std::string>& values, exclusion_filter*, int)
|
||||||
{
|
{
|
||||||
po::validators::check_first_occurrence(v);
|
po::validators::check_first_occurrence(v);
|
||||||
exclusion_filter filter;
|
exclusion_filter filter;
|
||||||
parse_filter(filter, values);
|
parse_filter(filter, values);
|
||||||
v = filter;
|
v = filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
void validate(boost::any& v, const std::vector<std::string>& values, exclusion_traverse_filter*, int)
|
void validate(boost::any& v, const std::vector<std::string>& values, exclusion_traverse_filter*, int)
|
||||||
{
|
{
|
||||||
po::validators::check_first_occurrence(v);
|
po::validators::check_first_occurrence(v);
|
||||||
exclusion_traverse_filter filter;
|
exclusion_traverse_filter filter;
|
||||||
parse_filter(filter, values);
|
parse_filter(filter, values);
|
||||||
v = filter;
|
v = filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @todo Clean up this filter initialization code further.
|
/// @todo Clean up this filter initialization code further.
|
||||||
/// @return References to the used filter functors, if none an error occurred.
|
/// @return References to the used filter functors, if none an error occurred.
|
||||||
std::vector<IfcGeom::filter_t> setup_filters(const std::vector<geom_filter>& filters, const std::string& output_extension)
|
std::vector<IfcGeom::filter_t> setup_filters(const std::vector<geom_filter>& filters, const std::string& output_extension)
|
||||||
{
|
{
|
||||||
std::vector<IfcGeom::filter_t> filter_funcs;
|
std::vector<IfcGeom::filter_t> filter_funcs;
|
||||||
BOOST_FOREACH(const geom_filter& f, filters) {
|
BOOST_FOREACH(const geom_filter& f, filters) {
|
||||||
if (f.type == geom_filter::ENTITY_TYPE) {
|
if (f.type == geom_filter::ENTITY_TYPE) {
|
||||||
@@ -1067,4 +1451,119 @@ std::vector<IfcGeom::filter_t> setup_filters(const std::vector<geom_filter>& fil
|
|||||||
if (!tag_filter.values.empty()) { filter_funcs.push_back(boost::ref(tag_filter)); }
|
if (!tag_filter.values.empty()) { filter_funcs.push_back(boost::ref(tag_filter)); }
|
||||||
|
|
||||||
return filter_funcs;
|
return filter_funcs;
|
||||||
|
}
|
||||||
|
bool reuse_ok_(SerializerSettings settings, const IfcSchema::IfcProduct::list::ptr &products, IfcGeom::Kernel kernel)
|
||||||
|
{
|
||||||
|
// IfcGeom::Kernel kernel;
|
||||||
|
|
||||||
|
// 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(IfcGeom::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(IfcGeom::IteratorSettings::DISABLE_OPENING_SUBTRACTIONS) &&
|
||||||
|
kernel.find_openings(product)->size())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (settings.get(IfcGeom::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)
|
||||||
|
{
|
||||||
|
if (assoc->RelatingMaterial()->is(IfcSchema::Type::IfcMaterialLayerSetUsage))
|
||||||
|
{
|
||||||
|
// 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));
|
||||||
|
if (associated_single_materials.size() > 1)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return associated_single_materials.size() == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void create_element(SerializerSettings &settings, IfcproductRepresentation &rep)
|
||||||
|
{
|
||||||
|
Logger::Status("processing item #: " + std::to_string(rep.index));
|
||||||
|
IfcGeom::Kernel kernel;
|
||||||
|
IfcSchema::IfcRepresentation *representation= rep.representation;
|
||||||
|
IfcSchema::IfcProduct *product = rep.product;
|
||||||
|
// IfcGeom::BRepElement<real_t> *element;
|
||||||
|
rep.element =
|
||||||
|
kernel.create_brep_for_representation_and_product<real_t>(settings, representation, product);
|
||||||
|
//if(geometry_reuse_ok_for_current_representation_)
|
||||||
|
// {
|
||||||
|
// // element = kernel.create_brep_for_processed_representation(settings, representation,
|
||||||
|
// // product,
|
||||||
|
// // current_shape_model);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//@todo MOVE this include
|
||||||
|
#include <gp_GTrsf.hxx>
|
||||||
|
|
||||||
|
Bounds compute_bounds(IfcParse::IfcFile* ifc_file, IfcGeom::Kernel kernel)
|
||||||
|
{
|
||||||
|
gp_XYZ bounds_min_;
|
||||||
|
gp_XYZ bounds_max_;
|
||||||
|
Bounds bounds;
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
IfcSchema::IfcProduct::list::ptr products = ifc_file->entitiesByType<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()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bounds.min = bounds_min_;
|
||||||
|
bounds.max = bounds_max_;
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -92,8 +92,8 @@
|
|||||||
|
|
||||||
namespace IfcGeom {
|
namespace IfcGeom {
|
||||||
|
|
||||||
template <typename P>
|
template <typename P>
|
||||||
class Iterator {
|
class Iterator {
|
||||||
private:
|
private:
|
||||||
Iterator(const Iterator&); // N/I
|
Iterator(const Iterator&); // N/I
|
||||||
Iterator& operator=(const Iterator&); // N/I
|
Iterator& operator=(const Iterator&); // N/I
|
||||||
@@ -763,7 +763,7 @@ namespace IfcGeom {
|
|||||||
|
|
||||||
free_shapes();
|
free_shapes();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user