IfcConvert and IfcGeomIterator filtering improvements#188
Conversation
… by type and name, w.i.p.
…fication external to the Iterator.
…include|exclude>=arg <Name|GlobalId>. The plan is to support arbitrary arguments in the future.
….Tag, not yet for IfcProxy.Tag).
…pport for IfcProxy.Tag (untested, did not find suitable test input yet).
… filter::traverse_match: dynamic_cast instead of static_cast as the decomposing entity is not guaranteed to be IfcProduct
…code generation + fix getObject()
|
Ideally I'd like to see Iterator refactored a bit more. It currently reminds a bit of Java-style iterators, but is lacking certain things. I think something like this would be nice: No filtering: IfcGeom::Iterator it(...);
while(it.has_next()) {
// next() renamed to create_next() here to imply it does work and is not simply a getter
auto geom = it.create_next();
// write geom
}Filtering: IfcGeom::Iterator it(...);
while(it.has_next()) {
auto next_prod = it.peek_next_product();
if (filter_matches(next_prod)) {
auto geom = it.create_next();
// write geom
} else {
it.skip_next();
}
} |
|
While still at it, I could also throw in specifying the ID usage of serialized element (Unique ID or any of the currently supported inclusion/exclusion argument names (GlobalId, Name, Description, Tag), https://sourceforge.net/p/ifcopenshell/discussion/1782717/thread/0ff477aa/#70f4 |
|
While I quite like your suggestion, how about making it more STL-like? (We should also really then consider renaming it to something else than iterator.) IfcGeom::Iterator model(...);
auto filtered_model = ...;
for(auto it = filtered_model.begin(); it != filtered_model.end(); ++it) {
auto geom = *it; // <- when dereferenced the geometry is interpreted? Is that too unconventional?
}
// range based for also fine of course
// or
for(auto it = model.begin(); it != model.end(); next_matching(filters, it)) {
auto geom = *it;
}
// And then perhaps sth like:
ColladaSerializer s(...);
std::copy(model.begin(), model.end(), s.begin());Not sure really, just thinking out loud. For example, would it be nice to
Yeah, sorry, I mixed up things in my head when typing that reply, I implied that that was already being worked on. I'm inclined to say let's first factor out this |
|
Yeah, that was surprising also to me, at first I even thought it was a bug in my code! Let me ponder for a minute what would be the most convenient way for specifying traversal on a per filter basis, it really comes down simply to boost::program_options parsing and handling as the per filter traversal code is already possible. |
|
Maybe |
…d --exclude+ options that control traversal on per filter basis.
|
OK! I Should be good to go. I think I'm going to postpone the work with specifying "arbitrary" element ID for now. |
|
Couple more minor commits incoming if you don't mind. |
|
Oh, and regarding your iterator ideas, those look quite good too, I especially like the look of |
|
One more pending thing: I just found out that IfcConvert crashes (null ptr access in TokenFunc::asStringRef) when trying to read an empty IFC file, so I'll see if that's easy to fix quickly. |
| void IfcSpfHeader::readSemicolon() { | ||
| if (!TokenFunc::isOperator(_lexer->Next(), ';')) { | ||
| Token next = _lexer->Next(); | ||
| if (next.lexer != 0 && !TokenFunc::isOperator(next, ';')) { |
There was a problem hiding this comment.
I did not look into this really in-depth as noticed the IfcSpfLexer* lexer; //TODO: remove it from here comment. Can be refactored properly when time permits.
There was a problem hiding this comment.
Thanks for this, I had a look as well. This only protects the header parser. I think that in the data section this issue less likely to manifest itself, as there eof is detected and non complete instances are not registered in the map. Still, I think it might be better to resolve it in asStringRef() to reduce the likelihood of hard segfaults, by simply throwing an exception there it seems the issue is addressed as well (also, the check on lexer is a bit cryptic, better check on type == NONE).
I suggest the following instead at the start of asStringRef():
if (t.type == Token_NONE) {
throw IfcParse::IfcException("Null token encountered, premature end of file?");
}There was a problem hiding this comment.
OK, thanks, will do as suggested.
fb38af3 to
14ca901
Compare
|
OK, cleanup up the the fix. |
|
Works well, many thanks. There are some small things in the ifcconvert help text that needs updating, I will commit that right way. |

--<include|exclude> --<enties|layers|guids|names> <value1 value2 ...>syntax changed to--<include|exclude>=<entities|layers|arg> (<GlobalId|Name|Description|Tag>) <value1 value2 ...>