Handle missing or invalid unit and precision information more gracefully during IfcGeomObject initialization

This commit is contained in:
aothms
2014-03-22 12:56:08 +00:00
parent ba0ba1973a
commit ffe1eddb00
+49 -30
View File
@@ -598,28 +598,36 @@ double UnitPrefixToValue( IfcSchema::IfcSIPrefix::IfcSIPrefix v ) {
} }
void IfcGeomObjects::InitPrecision() { void IfcGeomObjects::InitPrecision() {
IfcSchema::IfcGeometricRepresentationContext::list rep_contexts = ifc_file->EntitiesByType<IfcSchema::IfcGeometricRepresentationContext>(); IfcGeom::SetValue(IfcGeom::GV_PRECISION, 0.00001);
// Currently, IfcGeometricRepresentationContext aren't used as much as they should be
// in the evaluation of shape representations, hence, we try to find the one with the try {
// lowest precision. Typically, a value of 1e-5 is encountered. This value is applied IfcSchema::IfcGeometricRepresentationContext::list rep_contexts = ifc_file->EntitiesByType<IfcSchema::IfcGeometricRepresentationContext>();
// to all TopoDS_Shapes generated by one of the IfcGeom::convert() functions. // Currently, IfcGeometricRepresentationContext aren't used as much as they should be
// TODO: Many of the empirically found tolerances should probably be substituted by // in the evaluation of shape representations, hence, we try to find the one with the
// one that is defined in the model file. // lowest precision. Typically, a value of 1e-5 is encountered. This value is applied
double lowest_precision_encountered = std::numeric_limits<double>::infinity(); // to all TopoDS_Shapes generated by one of the IfcGeom::convert() functions.
bool any_precision_encountered = false; // TODO: Many of the empirically found tolerances should probably be substituted by
for (IfcSchema::IfcGeometricRepresentationContext::it it = rep_contexts->begin(); it != rep_contexts->end(); ++it) { // one that is defined in the model file.
IfcSchema::IfcGeometricRepresentationContext* rep_context = *it; double lowest_precision_encountered = std::numeric_limits<double>::infinity();
if (rep_context->is(IfcSchema::Type::IfcGeometricRepresentationSubContext)) continue; bool any_precision_encountered = false;
if (rep_context->hasPrecision()) { for (IfcSchema::IfcGeometricRepresentationContext::it it = rep_contexts->begin(); it != rep_contexts->end(); ++it) {
const double precision = rep_context->Precision(); IfcSchema::IfcGeometricRepresentationContext* rep_context = *it;
if (precision < lowest_precision_encountered) { if (rep_context->is(IfcSchema::Type::IfcGeometricRepresentationSubContext)) continue;
any_precision_encountered = true; if (rep_context->hasPrecision()) {
lowest_precision_encountered = precision; const double precision = rep_context->Precision();
if (precision < lowest_precision_encountered) {
any_precision_encountered = true;
lowest_precision_encountered = precision;
}
} }
} }
} if (any_precision_encountered) {
if (any_precision_encountered) { IfcGeom::SetValue(IfcGeom::GV_PRECISION, lowest_precision_encountered);
IfcGeom::SetValue(IfcGeom::GV_PRECISION, lowest_precision_encountered); }
} catch (const IfcParse::IfcException& ex) {
std::stringstream ss;
ss << "Failed to determine precision value '" << ex.what() << "'";
Logger::Message(Logger::LOG_ERROR, ss.str());
} }
} }
@@ -633,23 +641,32 @@ void IfcGeomObjects::InitUnits() {
IfcSchema::IfcUnitAssignment::list unit_assignments = ifc_file->EntitiesByType<IfcSchema::IfcUnitAssignment>(); IfcSchema::IfcUnitAssignment::list unit_assignments = ifc_file->EntitiesByType<IfcSchema::IfcUnitAssignment>();
IfcUtil::IfcAbstractSelect::list units = IfcUtil::IfcAbstractSelect::list(); IfcUtil::IfcAbstractSelect::list units = IfcUtil::IfcAbstractSelect::list();
if ( unit_assignments->Size() ) { try {
IfcSchema::IfcUnitAssignment::ptr unit_assignment = *unit_assignments->begin(); if ( unit_assignments->Size() ) {
units = unit_assignment->Units(); IfcSchema::IfcUnitAssignment::ptr unit_assignment = *unit_assignments->begin();
} units = unit_assignment->Units();
if ( ! units ) { }
} catch (const IfcParse::IfcException&) {}
if (!units) {
// No units eh... Since tolerances and deflection are specified internally in meters // No units eh... Since tolerances and deflection are specified internally in meters
// we will try to find another indication of the model size. // we will try to find another indication of the model size.
IfcSchema::IfcExtrudedAreaSolid::list extrusions = ifc_file->EntitiesByType<IfcSchema::IfcExtrudedAreaSolid>(); IfcSchema::IfcExtrudedAreaSolid::list extrusions = ifc_file->EntitiesByType<IfcSchema::IfcExtrudedAreaSolid>();
if ( ! extrusions->Size() ) return; if ( ! extrusions->Size() ) return;
double max_height = -1.0f; double max_height = -1.0f;
for ( IfcSchema::IfcExtrudedAreaSolid::it it = extrusions->begin(); it != extrusions->end(); ++ it ) { for ( IfcSchema::IfcExtrudedAreaSolid::it it = extrusions->begin(); it != extrusions->end(); ++ it ) {
const double depth = (*it)->Depth(); try {
if ( depth > max_height ) max_height = depth; const double depth = (*it)->Depth();
if ( depth > max_height ) max_height = depth;
} catch (const IfcParse::IfcException&) {}
}
if ( max_height > 100.0f ) {
IfcGeom::SetValue(IfcGeom::GV_LENGTH_UNIT,0.001);
Logger::Message(Logger::LOG_NOTICE, "Guessed length unit to be in millimeters based on extrusion depth");
} }
if ( max_height > 100.0f ) IfcGeom::SetValue(IfcGeom::GV_LENGTH_UNIT,0.001);
return; return;
} }
try { try {
for ( IfcUtil::IfcAbstractSelect::it it = units->begin(); it != units->end(); ++ it ) { for ( IfcUtil::IfcAbstractSelect::it it = units->begin(); it != units->end(); ++ it ) {
std::string current_unit_name = ""; std::string current_unit_name = "";
@@ -691,8 +708,10 @@ void IfcGeomObjects::InitUnits() {
} }
} }
} }
} catch ( IfcParse::IfcException ex ) { } catch (const IfcParse::IfcException& ex) {
Logger::Message(Logger::LOG_ERROR,ex.what()); std::stringstream ss;
ss << "Failed to determine unit information '" << ex.what() << "'";
Logger::Message(Logger::LOG_ERROR, ss.str());
} }
} }