diff --git a/src/ifcconvert/IfcConvert.cpp b/src/ifcconvert/IfcConvert.cpp index 50a3dbf4a7..58b24592f9 100644 --- a/src/ifcconvert/IfcConvert.cpp +++ b/src/ifcconvert/IfcConvert.cpp @@ -122,7 +122,7 @@ void write_log(); struct geom_filter { geom_filter() : type(UNUSED) {} - enum filter_type { UNUSED, ENTITY_TYPE, ENTITY_ARG, LAYER_NAME }; + enum filter_type { UNUSED, ENTITY_TYPE, LAYER_NAME, ENTITY_ARG }; filter_type type; std::string arg; std::set values; @@ -151,9 +151,8 @@ int main(int argc, char** argv) exclusion_filter exclude_filter; supported_args.push_back(NAME_ARG); supported_args.push_back(GUID_ARG); - /// @todo - //supported_args.push_back(DESC_ARG); - //supported_args.push_back(TAG_ARG); + supported_args.push_back(DESC_ARG); + supported_args.push_back(TAG_ARG); po::options_description geom_options("Geometry options"); geom_options.add_options() @@ -207,7 +206,7 @@ int main(int argc, char** argv) "2) 'layers': the entities that are assigned to presentation layers of which names " "match the given values should be included.\n" "3) 'arg ': the following list of values for that specific argument should be included. " - "Currently supported arguments are GlobalId and Name.\n\n" + "Currently supported arguments are GlobalId, Name, Description, and Tag.\n\n" "The values for 'layers' and 'arg' are handled case-sensitively (wildcards supported)." "--include and --exclude cannot be placed right before input file argument and " "only single of each argument supported for now. See also --exclude and --traverse.") @@ -389,6 +388,7 @@ int main(int argc, char** argv) // Set up filters. Entity filter is used always by default. + std::vector filters; /// @todo Clean up this filter initialization code IfcGeom::entity_filter entity_filter; entity_filter.traverse = traverse; @@ -418,25 +418,8 @@ int main(int argc, char** argv) std::cout << "[Error] " << e.what() << std::endl; return 1; } - - IfcGeom::arg_filter name_filter; - name_filter.traverse = traverse; - if (include_filter.arg == NAME_ARG) { - name_filter.include = true; - name_filter.populate(include_filter.values); - } else if (exclude_filter.arg == NAME_ARG) { - name_filter.include = false; - name_filter.populate(exclude_filter.values); - } - - IfcGeom::arg_filter guid_filter; - guid_filter.traverse = traverse; - if (include_filter.arg == GUID_ARG) { - guid_filter.include = true; - guid_filter.populate(include_filter.values); - } else if (exclude_filter.arg == GUID_ARG) { - guid_filter.include = false; - guid_filter.populate(include_filter.values); + if (!entity_filter.values.empty()) { + filters.push_back(boost::ref(entity_filter)); } IfcGeom::layer_filter layer_filter; @@ -448,6 +431,71 @@ int main(int argc, char** argv) layer_filter.include = false; layer_filter.populate(exclude_filter.values); } + if (!layer_filter.values.empty()) { + filters.push_back(boost::ref(layer_filter)); + } + + // IfcRoot.GlobalId + IfcGeom::arg_filter guid_filter; + guid_filter.traverse = traverse; + if (include_filter.arg == GUID_ARG) { + guid_filter.include = true; + guid_filter.populate(include_filter.values); + } else if (exclude_filter.arg == GUID_ARG) { + guid_filter.include = false; + guid_filter.populate(include_filter.values); + } + if (!guid_filter.values.empty()) { + filters.push_back(boost::ref(guid_filter)); + } + + // Note: skipping IfcRoot OwnerHistory, argument index 1 + + // IfcRoot.Name + IfcGeom::arg_filter name_filter; + name_filter.traverse = traverse; + if (include_filter.arg == NAME_ARG) { + name_filter.include = true; + name_filter.populate(include_filter.values); + } else if (exclude_filter.arg == NAME_ARG) { + name_filter.include = false; + name_filter.populate(exclude_filter.values); + } + if (!name_filter.values.empty()) { + filters.push_back(boost::ref(name_filter)); + } + + // IfcRoot.Description + IfcGeom::arg_filter desc_filter; + desc_filter.traverse = traverse; + if (include_filter.arg == DESC_ARG) { + desc_filter.include = true; + desc_filter.populate(include_filter.values); + } else if (exclude_filter.arg == DESC_ARG) { + desc_filter.include = false; + desc_filter.populate(exclude_filter.values); + } + if (!desc_filter.values.empty()) { + filters.push_back(boost::ref(desc_filter)); + } + + /// @todo IfcProxy.Tag + //IfcGeom::arg_filter tag_filter; + // IfcElement.Tag + IfcGeom::arg_filter tag_filter; + tag_filter.traverse = traverse; + if (include_filter.arg == TAG_ARG) { + tag_filter.include = true; + tag_filter.populate(include_filter.values); + } else if (exclude_filter.arg == TAG_ARG) { + tag_filter.include = false; + tag_filter.populate(exclude_filter.values); + } + if (!tag_filter.values.empty()) { + filters.push_back(boost::ref(tag_filter)); + } + + ///@ todo Logger::Message(Logger::LOG_NOTICE, "Filtering by X, Y and Z.") if (output_extension == ".xml") { int exit_code = 1; @@ -537,21 +585,6 @@ int main(int argc, char** argv) settings.set(IfcGeom::IteratorSettings::DISABLE_TRIANGULATION, true); } - IfcGeom::Iterator context_iterator(settings, input_filename); - - if (!guid_filter.values.empty()) { - context_iterator.filters().push_back(boost::ref(guid_filter)); - } - if (!name_filter.values.empty()) { - context_iterator.filters().push_back(boost::ref(name_filter)); - } - if (!entity_filter.values.empty()) { - context_iterator.filters().push_back(boost::ref(entity_filter)); - } - if (!layer_filter.values.empty()) { - context_iterator.filters().push_back(boost::ref(layer_filter)); - } - if (!serializer->ready()) { write_log(); return 1; @@ -559,7 +592,8 @@ int main(int argc, char** argv) time_t start,end; time(&start); - + + IfcGeom::Iterator context_iterator(settings, input_filename, filters); if (!context_iterator.initialize()) { /// @todo It would be nice to know and print separate error prints for a case where we failed to parse /// the file and for a case where we found no entities that satisfy our filtering criteria. diff --git a/src/ifcgeom/IfcGeomFilter.h b/src/ifcgeom/IfcGeomFilter.h index 8c42bacc66..13fd9dec10 100644 --- a/src/ifcgeom/IfcGeomFilter.h +++ b/src/ifcgeom/IfcGeomFilter.h @@ -24,7 +24,11 @@ #define IFCGEOMFILTER_H #include "IfcGeom.h" + +#include #include +#include +#include namespace IfcGeom { @@ -100,13 +104,13 @@ namespace IfcGeom /// @todo Maybe not use template class for this after all. Attribute name would be better /// than index, but IfcBaseClass doesn't have getArgument(name) (IfcLateBoundEntity would have though). - template + template struct arg_filter : public wildcard_filter { arg_filter() { #ifndef NDEBUG - ClassType dummy(0); + IfcType dummy(0); assert(ArgIndex < dummy.getArgumentCount()); #endif } @@ -114,7 +118,7 @@ namespace IfcGeom : wildcard_filter(include, traverse, patterns) { #ifndef NDEBUG - ClassType dummy(0); + IfcType dummy(0); assert(ArgIndex < dummy.getArgumentCount()); #endif populate(patterns); @@ -122,8 +126,8 @@ namespace IfcGeom ArgType value(IfcSchema::IfcProduct* prod) const { - Argument *arg = prod->entity->getArgument(ArgIndex); - return !arg->isNull() ? *arg : ArgType(); + Argument *arg = prod->is(IfcType::Class()) ? prod->entity->getArgument(ArgIndex) : 0; + return arg && !arg->isNull() ? *arg : ArgType(); } bool operator()(IfcSchema::IfcProduct* prod) const diff --git a/src/ifcgeom/IfcGeomIterator.h b/src/ifcgeom/IfcGeomIterator.h index 648a5ca4c6..855d36b405 100644 --- a/src/ifcgeom/IfcGeomIterator.h +++ b/src/ifcgeom/IfcGeomIterator.h @@ -145,7 +145,18 @@ namespace IfcGeom { } } + /// @todo public/private sections all over the place: move all public to the beginning of the class public: + Iterator(const IteratorSettings& settings, const std::string& filename, std::vector& filters) + : settings(settings) + , ifc_file(new IfcParse::IfcFile) + , owns_ifc_file(true) + , filters_(filters) + { + ifc_file->Init(filename); + _initialize(); + } + bool initialize() { try { initUnits(); @@ -307,8 +318,8 @@ namespace IfcGeom { IfcParse::IfcFile* getFile() const { return ifc_file; } - const std::vector &filters() const { return filters_; } - std::vector &filters() { return filters_; } + const std::vector& filters() const { return filters_; } + std::vector& filters() { return filters_; } const gp_XYZ& bounds_min() const { return bounds_min_; } const gp_XYZ& bounds_max() const { return bounds_max_; }