diff --git a/src/ifcopenshell-python/ifcopenshell/geom/main.py b/src/ifcopenshell-python/ifcopenshell/geom/main.py index 8421a389b7..32fcaae008 100644 --- a/src/ifcopenshell-python/ifcopenshell/geom/main.py +++ b/src/ifcopenshell-python/ifcopenshell/geom/main.py @@ -72,13 +72,30 @@ _iterator = ifcopenshell_wrapper.iterator_double_precision # Make sure people are able to use python's platform agnostic paths class iterator(_iterator): - def __init__(self, settings, file_or_filename, num_threads = 1): + def __init__(self, settings, file_or_filename, num_threads = 1, include = None, exclude = None): self.settings = settings if isinstance(file_or_filename, file): file_or_filename = file_or_filename.wrapped_data else: file_or_filename = os.path.abspath(file_or_filename) - _iterator.__init__(self, settings, file_or_filename, num_threads) + + if include is not None and exclude is not None: + raise ValueError("include and exclude cannot be specified simultaneously") + + if include is not None or exclude is not None: + # Couldn't get the typemaps properly applied using %extend so we + # replicate the SWIG-generated __init__ call on the output of a + # free function. + # @todo verify this works with SWIG 4 + self.this = ifcopenshell_wrapper.\ + construct_iterator_double_precision_with_include_exclude( + self.settings, + file_or_filename, + include if exclude is None else exclude, + include is not None, + num_threads) + else: + _iterator.__init__(self, settings, file_or_filename, num_threads) if has_occ: def get(self): @@ -165,8 +182,8 @@ def create_shape(settings, inst, repr=None): )) -def iterate(settings, filename): - it = iterator(settings, filename) +def iterate(settings, file_or_filename, num_threads = 1, include = None, exclude = None): + it = iterator(settings, file_or_filename, num_threads, include, exclude) if it.initialize(): while True: yield it.get() diff --git a/src/ifcwrap/IfcGeomWrapper.i b/src/ifcwrap/IfcGeomWrapper.i index 4850a1071d..5bc968dab6 100644 --- a/src/ifcwrap/IfcGeomWrapper.i +++ b/src/ifcwrap/IfcGeomWrapper.i @@ -160,6 +160,30 @@ struct ShapeRTTI : public boost::static_visitor %} } + +// I couldn't get the vector typemap to be applied when %extending Iterator constructor. +// anyway it does not matter as SWIG generates C code without actual constructors +%inline %{ + template + IfcGeom::Iterator* construct_iterator_with_include_exclude_(IfcGeom::IteratorSettings settings, IfcParse::IfcFile* file, std::vector elems, bool include, int num_threads) { + std::set elems_set(elems.begin(), elems.end()); + IfcGeom::entity_filter ef{ include, false, elems_set }; + return new IfcGeom::Iterator(settings, file, {ef}, num_threads); + } + + IfcGeom::Iterator* construct_iterator_single_precision_with_include_exclude(IfcGeom::IteratorSettings settings, IfcParse::IfcFile* file, std::vector elems, bool include, int num_threads) { + return construct_iterator_with_include_exclude_(settings, file, elems, include, num_threads); + } + + IfcGeom::Iterator* construct_iterator_double_precision_with_include_exclude(IfcGeom::IteratorSettings settings, IfcParse::IfcFile* file, std::vector elems, bool include, int num_threads) { + return construct_iterator_with_include_exclude_(settings, file, elems, include, num_threads); + } +%} + +%ignore construct_iterator_with_include_exclude_; +%newobject construct_iterator_single_precision_with_include_exclude; +%newobject construct_iterator_double_precision_with_include_exclude; + %extend IfcGeom::Iterator { static int mantissa_size() { return std::numeric_limits::digits;