We are having some difficulty parsing Ifc files whenever entities are specified by embedded entities in the following manner:
IFCPROPERTYSINGLEVALUE('z-Direction Offset Value',$,IFCLENGTHMEASURE(-0.5208333333333334),$);
This type of specification appears to be very common particularly with property sets yet always seems to produce the 'Token Is Not an Identifier' error.
Are we doing something wrong or is the Parser in its current form unable to handle these structures?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The parser is able to handle these statements, but dealing with them in the client side code is indeed a little tricky. Cleanly representing these select types (as they are called in the ifc express schema) in C++ proved to be a bit difficult, it is due for a major rewrite. For now you can use the following code. The trick is to use the IfcArgumentSelect class which will help you extract the underlying C++ datatype from the IfcLengthMeasure. You can either an if-else or a try-catch block to determine the C++ type.
usingnamespaceIfc2x3;if(property_single_value->hasNominalValue()){IfcValuevalue=property_single_value->NominalValue();IfcArgumentSelect::ptrvalue_select=dynamic_cast<IfcArgumentSelect::ptr>(value);if(value_select){// Either by schemaif(value->is(Type::IfcLengthMeasure)){doublel=*value_select->wrappedValue();std::cout<<l<<std::endl;}elseif(value->is(Type::IfcBoolean)){boolb=*value_select->wrappedValue();std::cout<<(b?"True":"False")<<std::endl;}// Or by blind lucktry{doubledouble_val=*value_select->wrappedValue();std::cout<<Type::ToString(value->type())<<": "<<double_val;}catch(IfcException&e){// Apparently not a number, maybe it is a string?std::stringstring_val=*value_select->wrappedValue();std::cout<<Type::ToString(value->type())<<": "<<string_val;}}}
Hope that helps, if things still don't work out, please post some code so we can be of better assistance.
Kind regards,
Thomas
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks to your code, I narrowed down the problem a bit further. The entities causing the problem were in fact only those containing embedded IFCINTEGER entities eg #17546 = IFCPROPERTYSINGLEVALUE ('Red', $, IFCINTEGER (0), $);. This seemed odd because IFCBOOLEAN embeds and other types were OK. Perhaps it is related to the fact that Integer starts with an I?
A collegaue of mine modified the routine as shown below and we are now able to process all the properties.
int TokenFunc::asInt(Token t) {
//Ankur-
/*
if ( ! isIdentifier(t) ) throw IfcException("Token is not an identifier");
const std::string str = asString(t);
return atoi(str.c_str()+1);
/*/
const std::string str = asString(t);
if ( ! isIdentifier(t) ) {
return atoi(str.c_str());
}
else {
return atoi(str.c_str()+1);
}
}
Not sure if that is the right fix but thought you should know anyway!
Regards
Dave Mills
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Ah, I understand now, the int cast in C++ expects to encounter a # before the number, because it was intended to deal with the #123 identifiers and references. I'll see to it that your fix gets applied. Sorry for this nasty bug in IfcOpenShell. I appreciate that you and your colleague took the time to investigate the issue and report back.
Kind regards,
Thomas
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
We are having some difficulty parsing Ifc files whenever entities are specified by embedded entities in the following manner:
IFCPROPERTYSINGLEVALUE('z-Direction Offset Value',$,IFCLENGTHMEASURE(-0.5208333333333334),$);
This type of specification appears to be very common particularly with property sets yet always seems to produce the 'Token Is Not an Identifier' error.
Are we doing something wrong or is the Parser in its current form unable to handle these structures?
Hi,
The parser is able to handle these statements, but dealing with them in the client side code is indeed a little tricky. Cleanly representing these select types (as they are called in the ifc express schema) in C++ proved to be a bit difficult, it is due for a major rewrite. For now you can use the following code. The trick is to use the IfcArgumentSelect class which will help you extract the underlying C++ datatype from the IfcLengthMeasure. You can either an if-else or a try-catch block to determine the C++ type.
Hope that helps, if things still don't work out, please post some code so we can be of better assistance.
Kind regards,
Thomas
Hi Thomas,
Thanks for the quick repsonse. I will let you kinow how we get on with the code above.
Regards
Dave Mills
Hi Thomas,
Thanks to your code, I narrowed down the problem a bit further. The entities causing the problem were in fact only those containing embedded IFCINTEGER entities eg #17546 = IFCPROPERTYSINGLEVALUE ('Red', $, IFCINTEGER (0), $);. This seemed odd because IFCBOOLEAN embeds and other types were OK. Perhaps it is related to the fact that Integer starts with an I?
A collegaue of mine modified the routine as shown below and we are now able to process all the properties.
int TokenFunc::asInt(Token t) {
//Ankur-
/*
if ( ! isIdentifier(t) ) throw IfcException("Token is not an identifier");
const std::string str = asString(t);
return atoi(str.c_str()+1);
/*/
const std::string str = asString(t);
if ( ! isIdentifier(t) ) {
return atoi(str.c_str());
}
else {
return atoi(str.c_str()+1);
}
}
Not sure if that is the right fix but thought you should know anyway!
Regards
Dave Mills
Hi Dave,
Ah, I understand now, the int cast in C++ expects to encounter a # before the number, because it was intended to deal with the #123 identifiers and references. I'll see to it that your fix gets applied. Sorry for this nasty bug in IfcOpenShell. I appreciate that you and your colleague took the time to investigate the issue and report back.
Kind regards,
Thomas