diff --git a/src/ifcconvert/IfcConvert.cpp b/src/ifcconvert/IfcConvert.cpp index 797d7dbe88..4f0916c454 100644 --- a/src/ifcconvert/IfcConvert.cpp +++ b/src/ifcconvert/IfcConvert.cpp @@ -391,7 +391,7 @@ int main(int argc, char** argv) std::string output_extension = output_filename.substr(output_filename.size()-4); boost::to_lower(output_extension); - Logger::SetOutput(&std::cout, &log_stream); + if (output_extension == ".xml") { int exit_code = 1; try { @@ -412,7 +412,7 @@ int main(int argc, char** argv) return exit_code; } - SerializerSettings settings; + SerializerSettings 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); @@ -428,7 +428,6 @@ int main(int argc, char** argv) settings.set(IfcGeom::IteratorSettings::APPLY_LAYERSETS, enable_layerset_slicing); settings.set(IfcGeom::IteratorSettings::NO_NORMALS, no_normals); settings.set(IfcGeom::IteratorSettings::GENERATE_UVS, generate_uvs); - settings.set(IfcGeom::IteratorSettings::TRAVERSE, traverse); settings.set(SerializerSettings::USE_ELEMENT_NAMES, use_element_names); settings.set(SerializerSettings::USE_ELEMENT_GUIDS, use_element_guids); @@ -483,34 +482,16 @@ int main(int argc, char** argv) IfcGeom::Iterator context_iterator(settings, input_filename); - try { - if (include_entities) { - context_iterator.includeEntities(entities); - } else { - context_iterator.excludeEntities(entities); - } - } catch (const IfcParse::IfcException& e) { - std::cout << "[Error] " << e.what() << std::endl; - return 1; - } - - if (include_names) { - context_iterator.include_entity_names(names); - } else { - context_iterator.exclude_entity_names(names); + try { + context_iterator.filter_entities(include_entities, entities, traverse); + } catch (const IfcParse::IfcException& e) { + std::cout << "[Error] " << e.what() << std::endl; + return 1; } - if (include_guids) { - context_iterator.include_entity_guids(guids); - } else { - context_iterator.exclude_entity_guids(guids); - } - - if (include_layers) { - context_iterator.include_layer_names(layers); - } else { - context_iterator.exclude_layer_names(layers); - } + context_iterator.filter_entity_names(include_names, names, traverse); + context_iterator.filter_entity_guids(include_guids, guids, traverse); + context_iterator.filter_layer_names(include_layers, layers, traverse); if (!serializer->ready()) { write_log(); @@ -570,7 +551,7 @@ int main(int argc, char** argv) // geometrical entities are available. None of these functions throw // exceptions, neither for parsing errors or geometrical errors. Upon // calling next() the entity to be returned has already been processed, a - // true return value guarantees that a successfully processed product is + // non-null return value guarantees that a successfully processed product is // available. size_t num_created = 0; diff --git a/src/ifcgeom/IfcGeomIterator.h b/src/ifcgeom/IfcGeomIterator.h index 88da0d6afb..b5e58bcf8d 100644 --- a/src/ifcgeom/IfcGeomIterator.h +++ b/src/ifcgeom/IfcGeomIterator.h @@ -120,8 +120,8 @@ namespace IfcGeom { int total; std::string unit_name; - // double? - P unit_magnitude; + double unit_magnitude; + gp_XYZ bounds_min_; gp_XYZ bounds_max_; @@ -131,13 +131,21 @@ namespace IfcGeom { IfcSchema::IfcProject* project = *projects->begin(); std::pair length_unit = kernel.initializeUnits(project->UnitsInContext()); unit_name = length_unit.first; - unit_magnitude = static_cast

(length_unit.second); + unit_magnitude = length_unit.second; } } - struct wildcard_filter + struct filter { + /// Should the product be included (true) or excluded (false). bool include; + /// If traversal requested, traverse to the parents to see if they satisfy the criteria. E.g. we might be looking for + /// children of a storey named "Level 20", or children of entities that have no representation, e.g. IfcCurtainWall. + bool traverse; + }; + + struct wildcard_filter : public filter + { std::set values; void populate(const std::set& patterns) @@ -167,9 +175,8 @@ namespace IfcGeom { wildcard_filter guid_filter_; wildcard_filter layer_filter_; - struct entity_filter + struct entity_filter : public filter { - bool include; std::set values; void populate(const std::set& types) @@ -180,9 +187,7 @@ namespace IfcGeom { try { ty = IfcSchema::Type::FromString(boost::to_upper_copy(type)); } catch (const IfcParse::IfcException&) { - std::stringstream ss; - ss << "'" << type << "' does not name a valid IFC entity"; - throw IfcParse::IfcException(ss.str()); + throw IfcParse::IfcException("'" + type + "' does not name a valid IFC entity"); } values.insert(ty); // TODO: Add child classes so that containment in set can be in O(log n) @@ -295,9 +300,9 @@ namespace IfcGeom { kernel.setValue(IfcGeom::Kernel::GV_PRECISION, 1.e-5); } - if (representations->size() == 0) { - Logger::Message(Logger::LOG_ERROR, "No geometries found"); - return false; + if (representations->size() == 0) { + Logger::Message(Logger::LOG_ERROR, "No geometries found"); + return false; } representation_iterator = representations->begin(); @@ -346,66 +351,43 @@ namespace IfcGeom { const std::string& getUnitName() const { return unit_name; } - P getUnitMagnitude() const { return unit_magnitude; } + /// @note Double always as per IFC specification. + double getUnitMagnitude() const { return unit_magnitude; } std::string getLog() const { return Logger::GetLog(); } IfcParse::IfcFile* getFile() const { return ifc_file; } /// @note Entity names are handled case-insensitively. - void includeEntities(const std::set& entities) + void filter_entities(bool include, const std::set& entities, bool traverse) { entity_filter_.populate(entities); - entity_filter_.include = true; - } - - /// @copydoc includeEntities() - void excludeEntities(const std::set& entities) - { - entity_filter_.populate(entities); - entity_filter_.include = false; + entity_filter_.include = include; + entity_filter_.traverse = traverse; } /// @note Arbitrary names or wildcard expressions are handled case-sensitively. - void include_entity_names(const std::set& names) + void filter_entity_names(bool include, const std::set& names, bool traverse) { name_filter_.populate(names); - name_filter_.include = true; - } - - /// @copydoc include_entity_names() - void exclude_entity_names(const std::set& names) - { - name_filter_.populate(names); - name_filter_.include = false; + name_filter_.include = include; + name_filter_.traverse = traverse; } /// @note GUIDs (wildcard expressions allowed) are handled case-sensitively. - void include_entity_guids(const std::set& guids) + void filter_entity_guids(bool include, const std::set& guids, bool traverse) { guid_filter_.populate(guids); - guid_filter_.include = true; - } - - /// @copydoc include_entity_guids() - void exclude_entity_guids(const std::set& guids) - { - guid_filter_.populate(guids); - guid_filter_.include = false; + guid_filter_.include = include; + guid_filter_.traverse = traverse; } /// @note Arbitrary names or wildcard expressions are handled case-sensitively. - void include_layer_names(const std::set& names) + void filter_layer_names(bool include, const std::set& names, bool traverse) { layer_filter_.populate(names); - layer_filter_.include = true; - } - - /// @copydoc include_layer_names() - void exclude_layer_names(const std::set& names) - { - layer_filter_.populate(names); - layer_filter_.include = false; + layer_filter_.include = include; + layer_filter_.traverse = traverse; } const gp_XYZ& bounds_min() const { return bounds_min_; } @@ -428,14 +410,17 @@ namespace IfcGeom { std::set mapped_representations_processed; - BRepElement

* create_shape_model_for_next_entity() { + struct shape_model { BRepElement

* element; IfcSchema::IfcProduct* product; }; + + shape_model create_shape_model_for_next_entity() { + shape_model ret = {0}; for (;;) { IfcSchema::IfcRepresentation* representation; // Have we reached the end of our list of representations? if ( representation_iterator == representations->end() ) { representations.reset(); - return 0; + return ret; } representation = *representation_iterator; @@ -578,9 +563,6 @@ namespace IfcGeom { } // Filter the products based on the set of entities and/or names being included or excluded for processing. - // If traversal requested, traverse to the parents to see if they satisfy the criteria. E.g. we might be looking for - // children of a storey named "Level 20", or children of entities that have no representation, e.g. IfcCurtainWall. - const bool traverse = settings.get(IteratorSettings::TRAVERSE); for (IfcSchema::IfcProduct::list::it jt = unfiltered_products->begin(); jt != unfiltered_products->end(); ++jt) { IfcSchema::IfcProduct* prod = *jt; /// @todo Horrible copy-pasta, refactor. @@ -594,7 +576,7 @@ namespace IfcGeom { } } - if (type_found != entity_filter_.include && traverse) { + if (type_found != entity_filter_.include && entity_filter_.traverse) { foreach(IfcSchema::Type::Enum type, entity_filter_.values) { IfcSchema::IfcProduct* parent, *current = prod; while ((parent = static_cast(kernel.get_decomposing_entity(current))) != 0) { @@ -620,7 +602,7 @@ namespace IfcGeom { } } - if (name_found != name_filter_.include && traverse) { + if (name_found != name_filter_.include && name_filter_.traverse) { foreach(const boost::regex& r, name_filter_.values) { IfcSchema::IfcProduct* parent, *current = prod; while ((parent = static_cast(kernel.get_decomposing_entity(current))) != 0) { @@ -647,7 +629,7 @@ namespace IfcGeom { } } - if (guid_found != guid_filter_.include && traverse) { + if (guid_found != guid_filter_.include && guid_filter_.traverse) { foreach(const boost::regex& r, guid_filter_.values) { IfcSchema::IfcProduct* parent, *current = prod; while ((parent = static_cast(kernel.get_decomposing_entity(current))) != 0) { @@ -680,7 +662,7 @@ namespace IfcGeom { } } - if (layer_found != layer_filter_.include && traverse) { + if (layer_found != layer_filter_.include && layer_filter_.traverse) { foreach(const boost::regex& r, layer_filter_.values) { for (lit = layers.begin(); lit != layers.end(); ++lit) { IfcSchema::IfcProduct* parent, *current = prod; @@ -714,26 +696,25 @@ namespace IfcGeom { continue; } - IfcSchema::IfcProduct* product = *ifcproduct_iterator; + ret.product = *ifcproduct_iterator; + + Logger::SetProduct(ret.product); - Logger::SetProduct(product); - - BRepElement

* element; if (ifcproduct_iterator == ifcproducts->begin() || !settings.get(IteratorSettings::USE_WORLD_COORDS)) { - element = kernel.create_brep_for_representation_and_product

(settings, representation, product); + ret.element = kernel.create_brep_for_representation_and_product

(settings, representation, ret.product); } else { - element = kernel.create_brep_for_processed_representation(settings, representation, product, current_shape_model); + ret.element = kernel.create_brep_for_processed_representation(settings, representation, ret.product, current_shape_model); } Logger::SetProduct(boost::none); - if ( !element ) { + if (!ret.element) { _nextShape(); continue; } - return element; - } + return ret; + } } void free_shapes() { @@ -748,7 +729,19 @@ namespace IfcGeom { public: - bool next() { + /// Returns what would be the product for the next shape representation + IfcSchema::IfcProduct* peek_next() const + { + if (ifcproducts && ifcproduct_iterator + 1 != ifcproducts->end()){ + return *(ifcproduct_iterator + 1); + } else { + return 0; + } + } + + /// Moves to the next shape representation and returns the associated product. + /// Use get() to retrieve the created geometry. + IfcSchema::IfcProduct* next() { // Increment the iterator over the list of products using the current // shape representation if (ifcproducts) { @@ -811,10 +804,8 @@ namespace IfcGeom { return ifc_object; } - bool create() { - bool success = true; - - IfcGeom::BRepElement

* next_shape_model = 0; + IfcSchema::IfcProduct* create() { + shape_model next_shape_model = {0}; IfcGeom::SerializedElement

* next_serialization = 0; IfcGeom::TriangulationElement

* next_triangulation = 0; @@ -822,37 +813,33 @@ namespace IfcGeom { next_shape_model = create_shape_model_for_next_entity(); } catch (...) {} - if (next_shape_model) { + if (next_shape_model.element) { if (settings.get(IteratorSettings::USE_BREP_DATA)) { try { - next_serialization = new SerializedElement

(*next_shape_model); + next_serialization = new SerializedElement

(*next_shape_model.element); } catch (...) { Logger::Message(Logger::LOG_ERROR, "Getting a serialized element from model failed."); - success = false; } } else if (!settings.get(IteratorSettings::DISABLE_TRIANGULATION)) { try { if (ifcproduct_iterator == ifcproducts->begin() || settings.get(IteratorSettings::USE_WORLD_COORDS)) { - next_triangulation = new TriangulationElement

(*next_shape_model); + next_triangulation = new TriangulationElement

(*next_shape_model.element); } else { - next_triangulation = new TriangulationElement

(*next_shape_model, current_triangulation->geometry_pointer()); + next_triangulation = new TriangulationElement

(*next_shape_model.element, current_triangulation->geometry_pointer()); } } catch (...) { Logger::Message(Logger::LOG_ERROR, "Getting a triangulation element from model failed."); - success = false; } } - } else { - success = false; } free_shapes(); - current_shape_model = next_shape_model; + current_shape_model = next_shape_model.element; current_serialization = next_serialization; current_triangulation = next_triangulation; - return success; + return next_shape_model.product; } private: void _initialize() { diff --git a/src/ifcgeom/IfcGeomIteratorSettings.h b/src/ifcgeom/IfcGeomIteratorSettings.h index 087a7808eb..b8ffa97b55 100644 --- a/src/ifcgeom/IfcGeomIteratorSettings.h +++ b/src/ifcgeom/IfcGeomIteratorSettings.h @@ -78,9 +78,6 @@ namespace IfcGeom GENERATE_UVS = 1 << 12, /// Specifies whether to slice representations according to associated IfcLayerSets. APPLY_LAYERSETS = 1 << 13, - /// Marks that include/exclude filtering should be applied also to the decomposition - /// and/or containment (IsDecomposedBy, HasOpenings, FillsVoid, ContainedInStructure) - /// of the filtered entity. TRAVERSE = 1 << 14, /// Number of different setting flags. NUM_SETTINGS = 14 diff --git a/src/ifcgeomserver/IfcGeomServer.cpp b/src/ifcgeomserver/IfcGeomServer.cpp index e1ec526770..03850784ce 100644 --- a/src/ifcgeomserver/IfcGeomServer.cpp +++ b/src/ifcgeomserver/IfcGeomServer.cpp @@ -516,7 +516,7 @@ int main () { } case NEXT: { Next n; n.read(std::cin); - has_more = iterator->next(); + has_more = iterator->next() != 0; if (!has_more) { delete iterator; iterator = 0;