Begin to implement IfcConvert enhancements discussed in #20. Remove C++-specific getters and setters and use the same set() and get() functions in in both C++ and Python. Enhance output of IfcConvert, especially in error situations (spamming a hundred lines of options always hides the original error message), utilize Boost's foreach macro to provide cleaner iteration code.

This commit is contained in:
Stinkfist0
2016-03-07 22:37:36 +02:00
parent e35cefac52
commit 0da0e63687
14 changed files with 426 additions and 311 deletions
+194 -94
View File
@@ -26,16 +26,6 @@
* *
********************************************************************************/
#include <fstream>
#include <sstream>
#include <set>
#include <time.h>
#include <boost/program_options.hpp>
#include <boost/algorithm/string.hpp>
#include "../ifcgeom/IfcGeomIterator.h"
#include "../ifcconvert/ColladaSerializer.h"
#include "../ifcconvert/IgesSerializer.h"
#include "../ifcconvert/StepSerializer.h"
@@ -43,35 +33,68 @@
#include "../ifcconvert/XmlSerializer.h"
#include "../ifcconvert/SvgSerializer.h"
#include "../ifcgeom/IfcGeomIterator.h"
#include <IGESControl_Controller.hxx>
#include <Standard_Version.hxx>
#include <boost/program_options.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/optional/optional_io.hpp>
#include <fstream>
#include <sstream>
#include <set>
#include <time.h>
typedef double real_t; /**< @todo Will be configurable */
#define INF std::numeric_limits<real_t>::infinity()
real_t bounds_min[3] = { INF, INF, INF };
real_t bounds_max[3] = { -INF, -INF, -INF };
#if USE_VLD
#include <vld.h>
#endif
static std::string DEFAULT_EXTENSION = "obj";
const std::string DEFAULT_EXTENSION = "obj";
void printVersion() {
std::cerr << "IfcOpenShell IfcConvert " << IFCOPENSHELL_VERSION << std::endl;
void print_version()
{
/// @todo Why cerr used for info prints? Change to cout.
std::cerr << "IfcOpenShell " << IfcSchema::Identifier << " IfcConvert " << IFCOPENSHELL_VERSION << std::endl;
}
void printUsage(const boost::program_options::options_description& generic_options, const boost::program_options::options_description& geom_options) {
printVersion();
std::cerr << "Usage: IfcConvert [options] <input.ifc> [<output>]" << std::endl
<< std::endl
<< "Converts the geometry in an IFC file into one of the following formats:" << std::endl
<< " .obj WaveFront OBJ (a .mtl file is also created)" << std::endl;
#ifdef WITH_OPENCOLLADA
std::cerr << " .dae Collada Digital Asset Exchange" << std::endl;
void print_usage()
{
std::cerr << "Usage: IfcConvert [options] <input.ifc> [<output>]" << "\n"
<< "\n"
<< "Converts the geometry in an IFC file into one of the following formats:" << "\n"
<< " .obj WaveFront OBJ (a .mtl file is also created)" << "\n"
#ifdef WITH_OPENCOLLADA
<< " .dae Collada Digital Assets Exchange" << "\n"
#endif
std::cerr << " .stp STEP Standard for the Exchange of Product Data" << std::endl
<< " .igs IGES Initial Graphics Exchange Specification" << std::endl
<< " .xml XML Property definitions and decomposition tree" << std::endl
<< " .svg SVG Scalable Vector Graphics (2d floor plan)" << std::endl
<< std::endl
<< "Command line options" << std::endl << generic_options << std::endl
<< "Advanced options" << std::endl << geom_options << std::endl;
<< " .stp STEP Standard for the Exchange of Product Data" << "\n"
<< " .igs IGES Initial Graphics Exchange Specification" << "\n"
<< " .xml XML Property definitions and decomposition tree" << "\n"
<< " .svg SVG Scalable Vector Graphics (2D floor plan)" << "\n"
<< "\n"
<< "If no output filename given, <input>." + DEFAULT_EXTENSION + " will be used as the output file.\n"
<< "\n"
<< "Run 'IfcConvert --help' for more information." << std::endl;
}
void print_options(
const boost::optional<boost::program_options::options_description>& generic_options,
const boost::optional<boost::program_options::options_description>& geom_options,
const boost::optional<boost::program_options::options_description>& serialization_options)
{
if (generic_options)
std::cerr << "\nCommand line options\n" << generic_options;
if (geom_options)
std::cerr << "\nGeometry options\n" << geom_options;
if (serialization_options)
std::cerr << "\nSerialization options\n" << serialization_options;
std::cerr << std::endl;
}
std::string change_extension(const std::string& fn, const std::string& ext) {
@@ -89,7 +112,7 @@ void write_log();
int main(int argc, char** argv) {
boost::program_options::options_description generic_options;
generic_options.add_options()
("help", "display usage information")
("help,h", "display usage information")
("version", "display version information")
("verbose,v", "more verbose output");
@@ -98,8 +121,8 @@ int main(int argc, char** argv) {
("input-file", boost::program_options::value<std::string>(), "input IFC file")
("output-file", boost::program_options::value<std::string>(), "output geometry file");
std::string bounds;
std::vector<std::string> entity_vector;
std::vector<std::string> entity_vector/*, names*/;
//double deflection_tolerance;
boost::program_options::options_description geom_options;
geom_options.add_options()
("plan",
@@ -142,20 +165,48 @@ int main(int argc, char** argv) {
("disable-opening-subtractions",
"Specifies whether to disable the boolean subtraction of "
"IfcOpeningElement Representations from their RelatingElements.")
("bounds", boost::program_options::value<std::string>(&bounds),
"Specifies the bounding rectangle, for example 512x512, to which the "
"output will be scaled. Only used when converting to SVG.")
("include",
"Specifies that the entities listed after --entities are to be included")
"Specifies that the entities listed after --entities or --names are to be included")
("exclude",
"Specifies that the entities listed after --entities are to be excluded")
("entities", boost::program_options::value< std::vector<std::string> >(&entity_vector)->multitoken(),
"Specifies that the entities listed after --entities or --names are to be excluded")
("entities", boost::program_options::value< std::vector<std::string> >(&entity_vector)->multitoken(),
"A list of entities that should be included in or excluded from the "
"geometrical output, depending on whether --ignore or --include is "
"specified. Defaults to IfcOpeningElement and IfcSpace to be excluded.");
"geometrical output, depending on whether --exclude or --include is specified. "
" Defaults to IfcOpeningElement and IfcSpace to be excluded. "
"The names are handled case-insensitively. Cannot be placed right before input file argument.")
/*("names", boost::program_options::value< std::vector<std::string> >(&names)->multitoken(),
"A list of names or wildcard patterns that should be included in or excluded from the "
"geometrical output, depending on whether --exclude or --include is specified. "
"The names are handled case-sensitively. Cannot be placed right before input file argument.")
("no-normals",
"Disables computation of normals. Saves time and file size and is useful "
"in instances where you're going to recompute normals for the exported "
"model in other modelling application in any case.")
("deflection-tolerance", boost::program_options::value<double>(&deflection_tolerance),
"Sets the deflection tolerance of the mesher, 1e-3 by default if not specified.")*/;
std::string bounds;
boost::program_options::options_description serializer_options;
serializer_options.add_options()
("bounds", boost::program_options::value<std::string>(&bounds),
"Specifies the bounding rectangle, for example 512x512, to which the "
"output will be scaled. Only used when converting to SVG.")
/*("use-names",
"Use entity names instead of unique IDs for naming objects and materials "
"upon serialization. Applicable for .obj and .dae output.")
("use-guids",
"Use entity GUIDs instead of unique IDs for naming objects upon serialization. "
"Overrides possible usage of --use-names for objects but not for materials."
"Applicable for .obj and .dae output.")
("center-model",
"Centers the models upon serialization by applying the center point of "
"the scene bounds as an offset. Applicable only for .dae output currently.")
("generate-uvs",
"Generates UVs (texture coordinates) by using simple box projection. Requires normals. Not guaranteed to work "
"properly if used with --weld-vertices. Applicable only for .dae output currently.")*/;
boost::program_options::options_description cmdline_options;
cmdline_options.add(generic_options).add(fileio_options).add(geom_options);
cmdline_options.add(generic_options).add(fileio_options).add(geom_options).add(serializer_options);
boost::program_options::positional_options_description positional_options;
positional_options.add("input-file", 1);
@@ -167,21 +218,30 @@ int main(int argc, char** argv) {
options(cmdline_options).positional(positional_options).run(), vmap);
} catch (const boost::program_options::unknown_option& e) {
std::cerr << "[Error] Unknown option '" << e.get_option_name() << "'" << std::endl << std::endl;
// Usage information will be emitted below
print_usage();
return 1;
} catch (...) {
// Catch other errors such as invalid command line syntax
print_usage();
return 1;
}
boost::program_options::notify(vmap);
if (vmap.count("version")) {
printVersion();
return 0;
} else if (vmap.count("help") || !vmap.count("input-file")) {
printUsage(generic_options, geom_options);
return vmap.count("help") ? 0 : 1;
print_version();
if (vmap.count("version")) {
return 0;
} else if (vmap.count("help")) {
print_usage();
print_options(generic_options, geom_options, serializer_options);
return 0;
} else if (!vmap.count("input-file")) {
std::cerr << "[Error] Input file not specified" << std::endl;
print_usage();
return 1;
} else if (vmap.count("include") && vmap.count("exclude")) {
std::cerr << "[Error] --include and --ignore can not be specified together" << std::endl;
printUsage(generic_options, geom_options);
std::cerr << "[Error] --include and --exclude can not be specified together" << std::endl;
print_options(boost::none, geom_options, boost::none);
return 1;
}
@@ -197,6 +257,12 @@ int main(int argc, char** argv) {
bool include_entities = vmap.count("include") != 0;
const bool include_plan = vmap.count("plan") != 0;
const bool include_model = vmap.count("model") != 0 || (!include_plan);
//const bool use_names = vmap.count("use-names") != 0;
//const bool use_guids = vmap.count("use-guids") != 0 ;
//const bool no_normals = vmap.count("no-normals") != 0 ;
//const bool center_model = vmap.count("center-model") != 0 ;
//const bool generate_uvs = vmap.count("generate-uvs") != 0 ;
//const bool deflection_tolerance_specified = vmap.count("deflection-tolerance") != 0 ;
boost::optional<int> bounding_width, bounding_height;
if (vmap.count("bounds") == 1) {
int w, h;
@@ -205,18 +271,14 @@ int main(int argc, char** argv) {
bounding_height = h;
} else {
std::cerr << "[Error] Invalid use of --bounds" << std::endl;
printUsage(generic_options, geom_options);
print_options(boost::none, boost::none, serializer_options);
return 1;
}
}
// Gets the set ifc types to be ignored from the command line.
std::set<std::string> entities;
for (std::vector<std::string>::const_iterator it = entity_vector.begin(); it != entity_vector.end(); ++it) {
const std::string& mixed_case_type = *it;
entities.insert(boost::to_lower_copy(mixed_case_type));
}
std::set<std::string> entities(entity_vector.begin(), entity_vector.end());
const std::string input_filename = vmap["input-file"].as<std::string>();
// If no output filename is specified a Wavefront OBJ file will be output
// to maintain backwards compatibility with the obsolete IfcObj executable.
@@ -225,7 +287,8 @@ int main(int argc, char** argv) {
: change_extension(input_filename, DEFAULT_EXTENSION);
if (output_filename.size() < 5) {
printUsage(generic_options, geom_options);
std::cerr << "[Error] Invalid or unsupported output file given " << output_filename << std::endl;
print_usage();
return 1;
}
@@ -234,12 +297,12 @@ int main(int argc, char** argv) {
// If no entities are specified these are the defaults to skip from output
if (entity_vector.empty()) {
entities.insert("IfcSpace");
/// @todo Document in --help that SVG uses "--include --entities IfcSpace" by default.
if (output_extension == ".svg") {
entities.insert("ifcspace");
include_entities = true;
} else {
entities.insert("ifcopeningelement");
entities.insert("ifcspace");
entities.insert("IfcOpeningElement");
}
}
@@ -264,7 +327,7 @@ int main(int argc, char** argv) {
}
IfcGeom::IteratorSettings settings;
/// @todo Make APPLY_DEFAULT_MATERIALS configurable? Quickly tested setting this to false and using obj exporter caused the program to crash and burn.
settings.set(IfcGeom::IteratorSettings::APPLY_DEFAULT_MATERIALS, true);
settings.set(IfcGeom::IteratorSettings::USE_WORLD_COORDS, use_world_coords);
settings.set(IfcGeom::IteratorSettings::WELD_VERTICES, weld_vertices);
@@ -276,6 +339,13 @@ int main(int argc, char** argv) {
settings.set(IfcGeom::IteratorSettings::DISABLE_OPENING_SUBTRACTIONS, disable_opening_subtractions);
settings.set(IfcGeom::IteratorSettings::INCLUDE_CURVES, include_plan);
settings.set(IfcGeom::IteratorSettings::EXCLUDE_SOLIDS_AND_SURFACES, !include_model);
//settings.set(IfcConvertSettings::USE_NAMES, use_names);
//settings.set(IfcConvertSettings::USE_GUIDS, use_guids);
//settings.set(IfcGeom::IteratorSettings::NO_NORMALS, no_normals);
//settings.set(IfcConvertSettings::CENTER_MODEL, center_model);
//settings.set(IfcConvertSettings::GENERATE_UVS, generate_uvs);
//if (deflection_tolerance_specified)
// settings.set_deflection_tolerance(deflection_tolerance);
GeometrySerializer* serializer;
if (output_extension == ".obj") {
@@ -300,15 +370,12 @@ int main(int argc, char** argv) {
settings.set(IfcGeom::IteratorSettings::DISABLE_TRIANGULATION, true);
serializer = new SvgSerializer(output_filename);
if (bounding_width && bounding_height) {
((SvgSerializer*) serializer)->setBoundingRectangle(
static_cast<double>(*bounding_width),
static_cast<double>(*bounding_height)
);
static_cast<SvgSerializer*>(serializer)->setBoundingRectangle(*bounding_width, *bounding_height);
}
} else {
Logger::Message(Logger::LOG_ERROR, "Unknown output filename extension");
write_log();
printUsage(generic_options, geom_options);
print_usage();
return 1;
}
@@ -316,16 +383,18 @@ int main(int argc, char** argv) {
if (weld_vertices) {
Logger::Message(Logger::LOG_NOTICE, "Weld vertices setting ignored when writing STEP or IGES files");
}
settings.disable_triangulation() = true;
settings.set(IfcGeom::IteratorSettings::DISABLE_TRIANGULATION, true);
}
IfcGeom::Iterator<double> context_iterator(settings, input_filename);
IfcGeom::Iterator<real_t> context_iterator(settings, input_filename);
try {
if (include_entities) {
context_iterator.includeEntities(entities);
//context_iterator.include_entity_names(names);
} else {
context_iterator.excludeEntities(entities);
//context_iterator.exclude_entity_names(names);
}
} catch (const IfcParse::IfcException& e) {
std::cout << "[Error] " << e.what() << std::endl;
@@ -347,21 +416,18 @@ int main(int argc, char** argv) {
return 1;
}
serializer->setFile(context_iterator.getFile());
if (convert_back_units) {
serializer->setUnitNameAndMagnitude(context_iterator.getUnitName(), static_cast<const float>(context_iterator.getUnitMagnitude()));
serializer->setUnitNameAndMagnitude(context_iterator.getUnitName(), static_cast<float>(context_iterator.getUnitMagnitude()));
} else {
serializer->setUnitNameAndMagnitude("METER", 1.0f);
}
serializer->writeHeader();
std::set<std::string> materials;
int old_progress = -1;
Logger::Status("Creating geometry...");
std::vector<IfcGeom::Element<real_t>* > geometries;
// The functions IfcGeom::Iterator::get() and IfcGeom::Iterator::next()
// wrap an iterator of all geometrical products in the Ifc file.
// IfcGeom::Iterator::get() returns an IfcGeom::TriangulationElement or
@@ -373,30 +439,65 @@ int main(int argc, char** argv) {
// true return value guarantees that a successfully processed product is
// available.
do {
const IfcGeom::Element<double>* geom_object = context_iterator.get();
if (serializer->isTesselated()) {
serializer->write(static_cast<const IfcGeom::TriangulationElement<double>*>(geom_object));
} else {
serializer->write(static_cast<const IfcGeom::BRepElement<double>*>(geom_object));
}
const int progress = context_iterator.progress() / 2;
if (old_progress!= progress) Logger::ProgressBar(progress);
old_progress = progress;
} while (context_iterator.next());
IfcGeom::Element<real_t> *geom_object = context_iterator.get(true); // true == take ownership, we will clean up ourselves
geometries.push_back(geom_object);
const int progress = context_iterator.progress() / 2;
if (old_progress != progress) Logger::ProgressBar(progress);
old_progress = progress;
//if (center_model) {
// const std::vector<real_t>& pos = geom_object->transformation().matrix().data();
// bounds_min[0] = std::min(bounds_min[0], pos[9]);
// bounds_min[1] = std::min(bounds_min[1], pos[10]);
// bounds_min[2] = std::min(bounds_min[2], pos[11]);
// bounds_max[0] = std::max(bounds_max[0], pos[9]);
// bounds_max[1] = std::max(bounds_max[1], pos[10]);
// bounds_max[2] = std::max(bounds_max[2], pos[11]);
//}
} while (context_iterator.next());
Logger::Status("\rDone creating geometry (" + boost::lexical_cast<std::string>(geometries.size()) +
" objects) ");
//if (center_model) {
// settings.offset[0] = -(bounds_min[0] + bounds_max[0]) * real_t(0.5);
// settings.offset[1] = -(bounds_min[1] + bounds_max[1]) * real_t(0.5);
// settings.offset[2] = -(bounds_min[2] + bounds_max[2]) * real_t(0.5);
// //printf("Bounds min. (%g, %g, %g)\n", bounds_min[0], bounds_min[1], bounds_min[2]);
// //printf("Bounds max. (%g, %g, %g)\n", bounds_max[0], bounds_max[1], bounds_max[2]);
// printf("Using model offset (%g, %g, %g)\n", settings.offset[0], settings.offset[1], settings.offset[2]); //TODO Logger::Message(Logger::LOG_NOTICE, ...);
//}
Logger::Status("Serializing geometry...");
//serializer->setSettings(settings);
if (serializer->isTesselated()) { // isTesselated() doesn't change at run-time
foreach(const IfcGeom::Element<real_t>* geom, geometries) {
serializer->write(static_cast<const IfcGeom::TriangulationElement<real_t>*>(geom));
delete geom;
}
} else {
foreach(const IfcGeom::Element<real_t>* geom, geometries) {
serializer->write(static_cast<const IfcGeom::BRepElement<real_t>*>(geom));
delete geom;
}
}
serializer->finalize();
delete serializer;
Logger::Status("\rDone creating geometry ");
Logger::Status("\rDone serializing geometry ");
delete serializer;
write_log();
time(&end);
int dif = (int) difftime (end,start);
printf ("\nConversion took %d seconds\n", dif );
int seconds = (int)difftime(end, start);
if (seconds < 60)
printf("\nConversion took %d seconds\n", seconds); // TODO Logger::Message(Logger::LOG_NOTICE, ...);
else
printf("\nConversion took %d minute(s) %d seconds\n", seconds/60, seconds%60); // TODO Logger::Message(Logger::LOG_NOTICE, ...);
return 0;
}
@@ -404,7 +505,6 @@ int main(int argc, char** argv) {
void write_log() {
std::string log = log_stream.str();
if (!log.empty()) {
std::cerr << std::endl << "Log:" << std::endl;
std::cerr << log << std::endl;
std::cerr << "\n" << "Log:\n" << log << std::endl;
}
}
}
@@ -43,7 +43,7 @@ void OpenCascadeBasedSerializer::write(const IfcGeom::BRepElement<double>* o) {
const gp_Trsf& o_trsf = o->transformation().data();
gtrsf.PreMultiply(o_trsf);
if (o->geometry().settings().convert_back_units()) {
if (o->geometry().settings().get(IfcGeom::IteratorSettings::CONVERT_BACK_UNITS)) {
gp_Trsf scale;
scale.SetScaleFactor(1.0 / o->geometry().settings().unit_magnitude());
gtrsf.PreMultiply(scale);
+5 -6
View File
@@ -21,7 +21,6 @@
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/foreach.hpp>
#include <boost/version.hpp>
#include "XmlSerializer.h"
@@ -256,16 +255,16 @@ void XmlSerializer::finalize() {
ptree root, header, decomposition, properties;
// Write the SPF header as XML nodes.
BOOST_FOREACH(const std::string& s, file->header().file_description().description()) {
foreach(const std::string& s, file->header().file_description().description()) {
header.add_child("file_description.description", ptree(s));
}
BOOST_FOREACH(const std::string& s, file->header().file_name().author()) {
foreach(const std::string& s, file->header().file_name().author()) {
header.add_child("file_name.author", ptree(s));
}
BOOST_FOREACH(const std::string& s, file->header().file_name().organization()) {
foreach(const std::string& s, file->header().file_name().organization()) {
header.add_child("file_name.organization", ptree(s));
}
BOOST_FOREACH(const std::string& s, file->header().file_schema().schema_identifiers()) {
foreach(const std::string& s, file->header().file_schema().schema_identifiers()) {
header.add_child("file_schema.schema_identifiers", ptree(s));
}
header.put("file_description.implementation_level", file->header().file_description().implementation_level());
@@ -298,4 +297,4 @@ void XmlSerializer::finalize() {
boost::property_tree::xml_writer_settings<char> settings('\t', 1);
#endif
boost::property_tree::write_xml(xml_filename, root, std::locale(), settings);
}
}
+1 -1
View File
@@ -44,7 +44,7 @@ namespace IfcGeom {
for(int i = 1; i < 5; ++i) {
for (int j = 1; j < 4; ++j) {
const double trsf_value = trsf.Value(j,i);
const double matrix_value = i == 4 && settings.convert_back_units()
const double matrix_value = i == 4 && settings.get(IteratorSettings::CONVERT_BACK_UNITS)
? trsf_value / settings.unit_magnitude()
: trsf_value;
_data.push_back(static_cast<P>(matrix_value));
+4 -4
View File
@@ -1103,11 +1103,11 @@ IfcGeom::BRepElement<P>* IfcGeom::Kernel::create_brep_for_representation_and_pro
const std::string product_type = IfcSchema::Type::ToString(product->type());
ElementSettings element_settings(settings, getValue(GV_LENGTH_UNIT), product_type);
if ( !settings.disable_opening_subtractions() && openings && openings->size() ) {
if (!settings.get(IfcGeom::IteratorSettings::DISABLE_OPENING_SUBTRACTIONS) && openings && openings->size()) {
IfcGeom::IfcRepresentationShapeItems opened_shapes;
try {
#if OCC_VERSION_HEX < 0x60900
const bool faster_booleans = settings.faster_booleans();
const bool faster_booleans = settings.get(IteratorSettings::FASTER_BOOLEANS);
#else
const bool faster_booleans = true;
#endif
@@ -1123,14 +1123,14 @@ IfcGeom::BRepElement<P>* IfcGeom::Kernel::create_brep_for_representation_and_pro
} catch(...) {
Logger::Message(Logger::LOG_ERROR,"Error processing openings for:",product->entity);
}
if ( settings.use_world_coords() ) {
if (settings.get(IteratorSettings::USE_WORLD_COORDS)) {
for ( IfcGeom::IfcRepresentationShapeItems::iterator it = opened_shapes.begin(); it != opened_shapes.end(); ++ it ) {
it->prepend(trsf);
}
trsf = gp_Trsf();
}
shape = new IfcGeom::Representation::BRep(element_settings, representation->entity->id(), opened_shapes);
} else if ( settings.use_world_coords() ) {
} else if (settings.get(IteratorSettings::USE_WORLD_COORDS)) {
for ( IfcGeom::IfcRepresentationShapeItems::iterator it = shapes.begin(); it != shapes.end(); ++ it ) {
it->prepend(trsf);
}
+54 -28
View File
@@ -86,6 +86,9 @@ namespace IfcGeom {
template <typename P>
class Iterator {
private:
Iterator(const Iterator&); // N/I
Iterator& operator=(const Iterator&); // N/I
Kernel kernel;
IteratorSettings settings;
@@ -121,6 +124,7 @@ namespace IfcGeom {
}
}
std::set<boost::regex> names_to_include_or_exclude; // regex containing a name or a wildcard expression
std::set<IfcSchema::Type::Enum> entities_to_include_or_exclude;
bool include_entities_in_processing;
@@ -148,7 +152,7 @@ namespace IfcGeom {
} catch (...) {}
std::set<std::string> context_types;
if (!settings.exclude_solids_and_surfaces()) {
if (!settings.get(IteratorSettings::EXCLUDE_SOLIDS_AND_SURFACES)) {
// Really this should only be 'Model', as per
// the standard 'Design' is deprecated. So,
// just for backwards compatibility:
@@ -157,7 +161,7 @@ namespace IfcGeom {
// DDS likes to output 'model view'
context_types.insert("model view");
}
if (settings.include_curves()) {
if (settings.get(IteratorSettings::INCLUDE_CURVES)) {
context_types.insert("plan");
}
@@ -250,36 +254,46 @@ namespace IfcGeom {
return true;
}
int progress() {
return 100 * done / total;
}
int progress() const { return 100 * done / total; }
const std::string& getUnitName() {
return unit_name;
}
const std::string& getUnitName() const { return unit_name; }
const P getUnitMagnitude() {
return unit_magnitude;
}
P getUnitMagnitude() const { return unit_magnitude; }
const std::string getLog() {
return Logger::GetLog();
}
std::string getLog() const { return Logger::GetLog(); }
IfcParse::IfcFile* getFile() {
return ifc_file;
}
IfcParse::IfcFile* getFile() const { return ifc_file; }
/// @note Entity names are handled case-insensitively.
void includeEntities(const std::set<std::string>& entities) {
populate_set(entities);
include_entities_in_processing = true;
}
/// @note Entity names are handled case-insensitively.
void excludeEntities(const std::set<std::string>& entities) {
populate_set(entities);
include_entities_in_processing = false;
}
// Arbitrary names or wildcard expressions are handled case-sensitively.
void include_entity_names(const std::vector<std::string>& names)
{
names_to_include_or_exclude.clear();
foreach(const std::string &name, names)
names_to_include_or_exclude.insert(IfcUtil::wildcard_string_to_regex(name));
include_entities_in_processing = true;
}
// Arbitrary names or wildcard expressions are handled case-sensitively.
void exclude_entity_names(const std::vector<std::string>& names)
{
names_to_include_or_exclude.clear();
foreach(const std::string &name, names)
names_to_include_or_exclude.insert(IfcUtil::wildcard_string_to_regex(name));
include_entities_in_processing = false;
}
private:
// Move to the next IfcRepresentation
void _nextShape() {
@@ -330,6 +344,14 @@ namespace IfcGeom {
break;
}
}
foreach(const boost::regex& r, names_to_include_or_exclude) {
if (boost::regex_match((*it)->Name(), r)) {
found = true;
break;
}
}
if (found == include_entities_in_processing) {
ifcproducts->push(*jt);
}
@@ -382,13 +404,17 @@ namespace IfcGeom {
return create();
}
Element<P>* get() {
// TODO: Test settings and throw
if (current_triangulation) return current_triangulation;
else if (current_serialization) return current_serialization;
else if (current_shape_model) return current_shape_model;
else return 0;
}
/// Gets or takes the representation of the current geometrical entity.
/// @param take_ownership Pass in 'true' as if wishing to maintain the element lifetime yourself.
Element<P>* get(bool take_ownership = false)
{
// TODO: Test settings and throw
Element<P>* ret = 0;
if (current_triangulation) { ret = current_triangulation; if (take_ownership) current_triangulation = 0; }
else if (current_serialization) { ret = current_serialization; if (take_ownership) current_serialization = 0; }
else if (current_shape_model) { ret = current_shape_model; if (take_ownership) current_shape_model = 0; }
return ret;
}
const Element<P>* getObject(int id) {
@@ -430,12 +456,12 @@ namespace IfcGeom {
current_shape_model = create_shape_model_for_next_entity();
} catch (...) {}
if (!current_shape_model) return false;
if (settings.use_brep_data()) {
if (settings.get(IteratorSettings::USE_BREP_DATA)) {
try {
current_serialization = new SerializedElement<P>(*current_shape_model);
} catch (...) {}
return !!current_serialization;
} else if (!settings.disable_triangulation()) {
} else if (!settings.get(IteratorSettings::DISABLE_TRIANGULATION)) {
try {
current_triangulation = new TriangulationElement<P>(*current_shape_model);
} catch (...) {}
@@ -457,8 +483,8 @@ namespace IfcGeom {
unit_name = "METER";
unit_magnitude = 1.f;
kernel.setValue(IfcGeom::Kernel::GV_MAX_FACES_TO_SEW, settings.sew_shells() ? 1000 : -1);
kernel.setValue(IfcGeom::Kernel::GV_DIMENSIONALITY, (settings.include_curves() ? (settings.exclude_solids_and_surfaces() ? -1. : 0.) : +1.));
kernel.setValue(IfcGeom::Kernel::GV_MAX_FACES_TO_SEW, settings.get(IteratorSettings::SEW_SHELLS) ? 1000 : -1);
kernel.setValue(IfcGeom::Kernel::GV_DIMENSIONALITY, (settings.get(IteratorSettings::INCLUDE_CURVES) ? (settings.get(IteratorSettings::EXCLUDE_SOLIDS_AND_SURFACES) ? -1. : 0.) : +1.));
}
bool owns_ifc_file;
+116 -146
View File
@@ -20,160 +20,130 @@
#ifndef IFCGEOMITERATORSETTINGS_H
#define IFCGEOMITERATORSETTINGS_H
#include <string>
#include "../ifcparse/IfcException.h"
namespace IfcGeom {
namespace IfcGeom
{
class IteratorSettings
{
public:
/// Enumeration of setting identifiers. These settings define the
/// behaviour of various aspects of IfcOpenShell.
enum Setting
{
/// Specifies whether vertices are welded, meaning that the coordinates
/// vector will only contain unique xyz-triplets. This results in a
/// manifold mesh which is useful for modelling applications, but might
/// result in unwanted shading artifacts in rendering applications.
WELD_VERTICES = 1,
/// Specifies whether to apply the local placements of building elements
/// directly to the coordinates of the representation mesh rather than
/// to represent the local placement in the 4x3 matrix, which will in that
/// case be the identity matrix.
USE_WORLD_COORDS = 1 << 1,
/// Internally IfcOpenShell measures everything in meters. This settings
/// specifies whether to convert IfcGeomObjects back to the units in which
/// the geometry in the IFC file is specified.
CONVERT_BACK_UNITS = 1 << 2,
/// Specifies whether to use the Open Cascade BREP format for representation
/// items rather than to create triangle meshes. This is useful is IfcOpenShell
/// is used as a library in an application that is also built on Open Cascade.
USE_BREP_DATA = 1 << 3,
/// Specifies whether to sew IfcConnectedFaceSets (open and closed shells) to
/// TopoDS_Shells or whether to keep them as a loose collection of faces.
SEW_SHELLS = 1 << 4,
/// Specifies whether to compose IfcOpeningElements into a single compound
/// in order to speed up the processing of opening subtractions.
FASTER_BOOLEANS = 1 << 5,
/// Disables the subtraction of IfcOpeningElement representations from
/// the related building element representations.
DISABLE_OPENING_SUBTRACTIONS = 1 << 6,
/// Disables the triangulation of the topological representations. Useful if
/// the client application understands Open Cascade's native format.
DISABLE_TRIANGULATION = 1 << 7,
/// Applies default materials to entity instances without a surface style.
APPLY_DEFAULT_MATERIALS = 1 << 8,
/// Specifies whether to include subtypes of IfcCurve.
INCLUDE_CURVES = 1 << 9,
/// Specifies whether to exclude subtypes of IfcSolidModel and IfcSurface.
EXCLUDE_SOLIDS_AND_SURFACES = 1 << 10,
/// Disables computation of normals. Saves time and file size and is useful
/// in instances where you're going to recompute normals for the exported
/// model in other modelling application in any case.
//NO_NORMALS = 1 << 11,
/// Use entity names instead of unique IDs for naming objects and materials.
/// Applicable for .obj and .dae output.
//USE_NAMES = 1 << 12,
/// Use entity GUIDs instead of unique IDs for naming objects.
/// Overrides possible usage of --use-names for objects but not for materials.
/// Applicable for .obj and .dae output.
//USE_GUIDS = 1 << 13,
/// Centers the models upon serialization by the applying the center point of
/// the scene bounds as an offset. Applicable only for .dae output currently.
//CENTER_MODEL = 1 << 14,
/// Generates UVs by using simple box projection. Requires normals.
/// Applicable only for .dae output currently.
//GENERATE_UVS = 1 << 15,
//NUM_SETTINGS = 15
};
/// Used to store logical OR combination of setting flags.
typedef unsigned SettingField;
class IteratorSettings {
public:
// Enumeration of setting identifiers. These settings define the
// behaviour of various aspects of IfcOpenShell.
IteratorSettings()
: settings_(WELD_VERTICES) // OR options that default to true here
, deflection_tolerance_(1.e-3)
{
memset(offset, 0, sizeof(offset));
}
// Specifies whether vertices are welded, meaning that the coordinates
// vector will only contain unique xyz-triplets. This results in a
// manifold mesh which is useful for modelling applications, but might
// result in unwanted shading artifacts in rendering applications.
static const int WELD_VERTICES = 1;
// Specifies whether to apply the local placements of building elements
// directly to the coordinates of the representation mesh rather than
// to represent the local placement in the 4x3 matrix, which will in that
// case be the identity matrix.
static const int USE_WORLD_COORDS = 2;
// Internally IfcOpenShell measures everything in meters. This settings
// specifies whether to convert IfcGeomObjects back to the units in which
// the geometry in the IFC file is specified.
static const int CONVERT_BACK_UNITS = 3;
// Specifies whether to use the Open Cascade BREP format for representation
// items rather than to create triangle meshes. This is useful is IfcOpenShell
// is used as a library in an application that is also built on Open Cascade.
static const int USE_BREP_DATA = 4;
// Specifies whether to sew IfcConnectedFaceSets (open and closed shells) to
// TopoDS_Shells or whether to keep them as a loose collection of faces.
static const int SEW_SHELLS = 5;
// Specifies whether to compose IfcOpeningElements into a single compound
// in order to speed up the processing of opening subtractions.
static const int FASTER_BOOLEANS = 6;
// Disables the subtraction of IfcOpeningElement representations from
// the related building element representations.
static const int DISABLE_OPENING_SUBTRACTIONS = 8;
// Disables the triangulation of the topological representations. Useful if
// the client application understands Open Cascade's native format.
static const int DISABLE_TRIANGULATION = 9;
// Applies default materials to entity instances without a surface style.
static const int APPLY_DEFAULT_MATERIALS = 10;
// Specifies whether to include subtypes of IfcCurve.
static const int INCLUDE_CURVES = 11;
// Specifies whether to exclude subtypes of IfcSolidModel and IfcSurface.
static const int EXCLUDE_SOLIDS_AND_SURFACES = 12;
/// Optional offset that is applied to serialized objects, (0,0,0) by default.
double offset[3];
// End of settings enumeration.
/// Note that this is independent of the IFC length unit, one millimeter by default.
double deflection_tolerance() const { return deflection_tolerance_; }
/// @todo Sanity check for the value
void set_deflection_tolerance(double value) { deflection_tolerance_ = value; }
private:
bool _weld_vertices, _use_world_coords, _convert_back_units, _use_brep_data, _sew_shells, _faster_booleans, _disable_opening_subtractions, _disable_triangulation, _apply_default_materials, _include_curves, _exclude_solids_and_surfaces;
double _deflection_tolerance;
public:
IteratorSettings()
: _weld_vertices(true)
, _use_world_coords(false)
, _convert_back_units(false)
, _use_brep_data(false)
, _sew_shells(false)
, _faster_booleans(false)
, _disable_opening_subtractions(false)
, _disable_triangulation(false)
, _apply_default_materials(false)
, _include_curves(false)
, _exclude_solids_and_surfaces(false)
// TODO: Make deflection tolerance into a command line argument
// For now, stick to one millimeter. Note that this is independent of the IFC length unit.
, _deflection_tolerance(1.e-3)
{}
bool get(SettingField setting) const
{
/// @todo If unknown setting value/combination: throw IfcParse::IfcException("Invalid IteratorSetting")?
return (settings_ & setting) != 0;
}
const bool& weld_vertices() const { return _weld_vertices; }
bool& weld_vertices() { return _weld_vertices; }
const bool& use_world_coords() const { return _use_world_coords; }
bool& use_world_coords() { return _use_world_coords; }
const bool& convert_back_units() const { return _convert_back_units; }
bool& convert_back_units() { return _convert_back_units; }
const bool& use_brep_data() const { return _use_brep_data; }
bool& use_brep_data() { return _use_brep_data; }
const bool& sew_shells() const { return _sew_shells; }
bool& sew_shells() { return _sew_shells; }
const bool& faster_booleans() const { return _faster_booleans; }
bool& faster_booleans() { return _faster_booleans; }
const bool& disable_opening_subtractions() const { return _disable_opening_subtractions; }
bool& disable_opening_subtractions() { return _disable_opening_subtractions; }
const bool& disable_triangulation() const { return _disable_triangulation; }
bool& disable_triangulation() { return _disable_triangulation; }
const bool& apply_default_materials() const { return _apply_default_materials; }
bool& apply_default_materials() { return _apply_default_materials; }
const bool& include_curves() const { return _include_curves; }
bool& include_curves() { return _include_curves; }
const bool& exclude_solids_and_surfaces() const { return _exclude_solids_and_surfaces; }
bool& exclude_solids_and_surfaces() { return _exclude_solids_and_surfaces; }
const double& deflection_tolerance() const { return _deflection_tolerance; }
double& deflection_tolerance() { return _deflection_tolerance; }
void set(int setting, bool value) {
switch (setting) {
case USE_WORLD_COORDS:
_use_world_coords = value;
break;
case WELD_VERTICES:
_weld_vertices = value;
break;
case CONVERT_BACK_UNITS:
_convert_back_units = value;
break;
case USE_BREP_DATA:
_use_brep_data = value;
break;
case FASTER_BOOLEANS:
_faster_booleans = value;
break;
case SEW_SHELLS:
_sew_shells = value;
break;
case DISABLE_OPENING_SUBTRACTIONS:
_disable_opening_subtractions = value;
break;
case DISABLE_TRIANGULATION:
_disable_triangulation = value;
break;
case APPLY_DEFAULT_MATERIALS:
_apply_default_materials = value;
break;
case INCLUDE_CURVES:
_include_curves = value;
break;
case EXCLUDE_SOLIDS_AND_SURFACES:
_exclude_solids_and_surfaces = value;
break;
default: throw IfcParse::IfcException("Invalid IteratorSetting");
}
}
};
class ElementSettings : public IteratorSettings {
private:
double _unit_magnitude;
std::string _element_type;
public:
ElementSettings(const IteratorSettings& settings,
double unit_magnitude,
const std::string& element_type)
: IteratorSettings(settings)
, _unit_magnitude(unit_magnitude)
, _element_type(element_type)
{}
void set(SettingField setting, bool value)
{
/// @todo If unknown setting value/combination: throw IfcParse::IfcException("Invalid IteratorSetting")?
if (value) {
settings_ |= setting;
} else {
settings_ &= ~setting;
}
}
const double& unit_magnitude() const { return _unit_magnitude; }
const std::string& element_type() const { return _element_type; }
};
protected:
SettingField settings_;
double deflection_tolerance_;
};
class ElementSettings : public IteratorSettings
{
public:
ElementSettings(const IteratorSettings& settings,
double unit_magnitude,
const std::string& element_type)
: IteratorSettings(settings)
, unit_magnitude_(unit_magnitude)
, element_type_(element_type)
{
}
double unit_magnitude() const { return unit_magnitude_; }
const std::string& element_type() const { return element_type_; }
private:
double unit_magnitude_;
std::string element_type_;
};
}
#endif
#endif
+1 -1
View File
@@ -38,7 +38,7 @@ IfcGeom::Representation::Serialization::Serialization(const BRep& brep)
for (IfcGeom::IfcRepresentationShapeItems::const_iterator it = brep.begin(); it != brep.end(); ++ it) {
const TopoDS_Shape& s = it->Shape();
gp_GTrsf trsf = it->Placement();
if (settings().convert_back_units()) {
if (settings().get(IteratorSettings::CONVERT_BACK_UNITS)) {
gp_Trsf scale;
scale.SetScaleFactor(1.0 / settings().unit_magnitude());
trsf.PreMultiply(scale);
+7 -6
View File
@@ -132,7 +132,7 @@ namespace IfcGeom {
}
}
if (settings().apply_default_materials() && surface_style_id == -1) {
if (settings().get(IteratorSettings::APPLY_DEFAULT_MATERIALS) && surface_style_id == -1) {
Material material(IfcGeom::get_default_style(settings().element_type()));
std::vector<Material>::const_iterator mit = std::find(_materials.begin(), _materials.end(), material);
if (mit == _materials.end()) {
@@ -182,7 +182,7 @@ namespace IfcGeom {
std::map<int,int> dict;
// Vertex normals are only calculated if vertices are not welded
const bool calculate_normals = !settings().weld_vertices();
const bool calculate_normals = !settings().get(IteratorSettings::WELD_VERTICES);
for( int i = 1; i <= nodes.Length(); ++ i ) {
coords.push_back(nodes(i).Transformed(loc).XYZ());
@@ -278,11 +278,12 @@ namespace IfcGeom {
private:
// Welds vertices that belong to different faces
int addVertex(int material_index, const gp_XYZ& p) {
const P X = static_cast<P>(settings().convert_back_units() ? (p.X() / settings().unit_magnitude()) : p.X());
const P Y = static_cast<P>(settings().convert_back_units() ? (p.Y() / settings().unit_magnitude()) : p.Y());
const P Z = static_cast<P>(settings().convert_back_units() ? (p.Z() / settings().unit_magnitude()) : p.Z());
const bool convert = settings().get(IteratorSettings::CONVERT_BACK_UNITS);
const P X = static_cast<P>(convert ? (p.X() / settings().unit_magnitude()) : p.X());
const P Y = static_cast<P>(convert ? (p.Y() / settings().unit_magnitude()) : p.Y());
const P Z = static_cast<P>(convert ? (p.Z() / settings().unit_magnitude()) : p.Z());
int i = (int) _verts.size() / 3;
if (settings().weld_vertices()) {
if (settings().get(IteratorSettings::WELD_VERTICES)) {
const VertexKey key = std::make_pair(material_index, std::make_pair(X, std::make_pair(Y, Z)));
typename VertexKeyMap::const_iterator it = welds.find(key);
if ( it != welds.end() ) return it->second;
+4 -4
View File
@@ -318,10 +318,10 @@ int main () {
memcpy(data, m.string().c_str(), len);
IfcGeom::IteratorSettings settings;
settings.use_world_coords() = false;
settings.weld_vertices() = false;
settings.convert_back_units() = true;
settings.include_curves() = true;
settings.set(IfcGeom::IteratorSettings::USE_WORLD_COORDS, false);
settings.set(IfcGeom::IteratorSettings::WELD_VERTICES, false);
settings.set(IfcGeom::IteratorSettings::CONVERT_BACK_UNITS, true);
settings.set(IfcGeom::IteratorSettings::INCLUDE_CURVES, true);
iterator = new IfcGeom::Iterator<float>(settings, data, (int)len);
has_more = iterator->initialize();
+3 -3
View File
@@ -214,9 +214,9 @@ static Mtl* ComposeMultiMaterial(std::map<std::vector<std::string>, Mtl*>& multi
int IFCImp::DoImport(const TCHAR *name, ImpInterface *impitfc, Interface *itfc, BOOL /*suppressPrompts*/) {
IfcGeom::IteratorSettings settings;
settings.use_world_coords() = false;
settings.weld_vertices() = true;
settings.sew_shells() = true;
settings.set(IfcGeom::IteratorSettings::USE_WORLD_COORDS, false);
settings.set(IfcGeom::IteratorSettings::WELD_VERTICES, true);
settings.set(IfcGeom::IteratorSettings::SEW_SHELLS, true);
#ifdef _UNICODE
int fn_buffer_size = WideCharToMultiByte(CP_UTF8, 0, name, -1, 0, 0, 0, 0);
+16 -4
View File
@@ -17,12 +17,14 @@
* *
********************************************************************************/
#include "IfcUtil.h"
#include "../ifcparse/IfcException.h"
#include <boost/algorithm/string/replace.hpp>
#include <iostream>
#include <algorithm>
#include "../ifcparse/IfcException.h"
#include "IfcUtil.h"
void IfcEntityList::push(IfcUtil::IfcBaseClass* l) {
if (l) {
@@ -143,4 +145,14 @@ bool IfcUtil::valid_binary_string(const std::string& s) {
if (*it != '0' && *it != '1') return false;
}
return true;
}
}
boost::regex IfcUtil::wildcard_string_to_regex(std::string str)
{
std::string special_chars = "\\^.$|()[]*+";
foreach(char c, special_chars) {
std::string char_str(1, c);
boost::replace_all(str, char_str, "\\"+ char_str);
}
return boost::regex(str);
}
+10 -3
View File
@@ -26,15 +26,20 @@
#include <sstream>
#include <algorithm>
#include <boost/shared_ptr.hpp>
#include <boost/dynamic_bitset.hpp>
#ifdef USE_IFC4
#include "../ifcparse/Ifc4enum.h"
#else
#include "../ifcparse/Ifc2x3enum.h"
#endif
#include <boost/shared_ptr.hpp>
#include <boost/dynamic_bitset.hpp>
#include <boost/regex.hpp>
#include <boost/foreach.hpp>
#define foreach BOOST_FOREACH
#define rforeach BOOST_REVERSE_FOREACH
class Argument;
class IfcEntityList;
class IfcEntityListList;
@@ -110,6 +115,8 @@ namespace IfcUtil {
};
bool valid_binary_string(const std::string& s);
boost::regex wildcard_string_to_regex(std::string str);
}
template <class T>
+10 -10
View File
@@ -244,8 +244,8 @@ struct ShapeRTTI : public boost::static_visitor<PyObject*>
IfcSchema::IfcProject* project = *projects->begin();
IfcGeom::Kernel kernel;
kernel.setValue(IfcGeom::Kernel::GV_MAX_FACES_TO_SEW, settings.sew_shells() ? 1000 : -1);
kernel.setValue(IfcGeom::Kernel::GV_DIMENSIONALITY, (settings.include_curves() ? (settings.exclude_solids_and_surfaces() ? -1. : 0.) : +1.));
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.));
std::pair<std::string, double> length_unit = kernel.initializeUnits(project->UnitsInContext());
if (instance->is(IfcSchema::Type::IfcProduct)) {
@@ -269,13 +269,13 @@ struct ShapeRTTI : public boost::static_visitor<PyObject*>
// First, try to find a representation based on the settings
for (IfcSchema::IfcRepresentation::list::it it = reps->begin(); it != reps->end(); ++it) {
IfcSchema::IfcRepresentation* rep = *it;
if (!settings.exclude_solids_and_surfaces()) {
if (!settings.get(IfcGeom::IteratorSettings::EXCLUDE_SOLIDS_AND_SURFACES)) {
if (rep->RepresentationIdentifier() == "Body") {
ifc_representation = rep;
break;
}
}
if (settings.include_curves()) {
if (settings.get(IfcGeom::IteratorSettings::INCLUDE_CURVES)) {
if (rep->RepresentationIdentifier() == "Plan" || rep->RepresentationIdentifier() == "Axis") {
ifc_representation = rep;
break;
@@ -293,12 +293,12 @@ struct ShapeRTTI : public boost::static_visitor<PyObject*>
// TODO: Remove redundancy with IfcGeomIterator.h
if (context->hasContextType()) {
std::set<std::string> context_types;
if (!settings.exclude_solids_and_surfaces()) {
if (!settings.get(IfcGeom::IteratorSettings::EXCLUDE_SOLIDS_AND_SURFACES)) {
context_types.insert("model");
context_types.insert("design");
context_types.insert("model view");
}
if (settings.include_curves()) {
if (settings.get(IfcGeom::IteratorSettings::INCLUDE_CURVES)) {
context_types.insert("plan");
}
@@ -347,11 +347,11 @@ struct ShapeRTTI : public boost::static_visitor<PyObject*>
if (!brep) {
throw IfcParse::IfcException("Failed to process shape");
}
if (settings.use_brep_data()) {
if (settings.get(IfcGeom::IteratorSettings::USE_BREP_DATA)) {
IfcGeom::SerializedElement<double>* serialization = new IfcGeom::SerializedElement<double>(*brep);
delete brep;
return serialization;
} else if (!settings.disable_triangulation()) {
} else if (!settings.get(IfcGeom::IteratorSettings::DISABLE_TRIANGULATION)) {
IfcGeom::TriangulationElement<double>* triangulation = new IfcGeom::TriangulationElement<double>(*brep);
delete brep;
return triangulation;
@@ -366,9 +366,9 @@ struct ShapeRTTI : public boost::static_visitor<PyObject*>
IfcGeom::ElementSettings element_settings(settings, kernel.getValue(IfcGeom::Kernel::GV_LENGTH_UNIT), IfcSchema::Type::ToString(instance->type()));
IfcGeom::Representation::BRep brep(element_settings, instance->entity->id(), shapes);
try {
if (settings.use_brep_data()) {
if (settings.get(IfcGeom::IteratorSettings::USE_BREP_DATA)) {
return new IfcGeom::Representation::Serialization(brep);
} else if (!settings.disable_triangulation()) {
} else if (!settings.get(IfcGeom::IteratorSettings::DISABLE_TRIANGULATION)) {
return new IfcGeom::Representation::Triangulation<double>(brep);
}
} catch (...) {