diff --git a/src/ifcgeom/IfcGeomObjects.cpp b/src/ifcgeom/IfcGeomObjects.cpp index 5878d1c509..dd6627f316 100644 --- a/src/ifcgeom/IfcGeomObjects.cpp +++ b/src/ifcgeom/IfcGeomObjects.cpp @@ -598,28 +598,36 @@ double UnitPrefixToValue( IfcSchema::IfcSIPrefix::IfcSIPrefix v ) { } void IfcGeomObjects::InitPrecision() { - IfcSchema::IfcGeometricRepresentationContext::list rep_contexts = ifc_file->EntitiesByType(); - // 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 - // lowest precision. Typically, a value of 1e-5 is encountered. This value is applied - // to all TopoDS_Shapes generated by one of the IfcGeom::convert() functions. - // TODO: Many of the empirically found tolerances should probably be substituted by - // one that is defined in the model file. - double lowest_precision_encountered = std::numeric_limits::infinity(); - bool any_precision_encountered = false; - for (IfcSchema::IfcGeometricRepresentationContext::it it = rep_contexts->begin(); it != rep_contexts->end(); ++it) { - IfcSchema::IfcGeometricRepresentationContext* rep_context = *it; - if (rep_context->is(IfcSchema::Type::IfcGeometricRepresentationSubContext)) continue; - if (rep_context->hasPrecision()) { - const double precision = rep_context->Precision(); - if (precision < lowest_precision_encountered) { - any_precision_encountered = true; - lowest_precision_encountered = precision; + IfcGeom::SetValue(IfcGeom::GV_PRECISION, 0.00001); + + try { + IfcSchema::IfcGeometricRepresentationContext::list rep_contexts = ifc_file->EntitiesByType(); + // 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 + // lowest precision. Typically, a value of 1e-5 is encountered. This value is applied + // to all TopoDS_Shapes generated by one of the IfcGeom::convert() functions. + // TODO: Many of the empirically found tolerances should probably be substituted by + // one that is defined in the model file. + double lowest_precision_encountered = std::numeric_limits::infinity(); + bool any_precision_encountered = false; + for (IfcSchema::IfcGeometricRepresentationContext::it it = rep_contexts->begin(); it != rep_contexts->end(); ++it) { + IfcSchema::IfcGeometricRepresentationContext* rep_context = *it; + if (rep_context->is(IfcSchema::Type::IfcGeometricRepresentationSubContext)) continue; + if (rep_context->hasPrecision()) { + const double precision = rep_context->Precision(); + if (precision < lowest_precision_encountered) { + any_precision_encountered = true; + lowest_precision_encountered = precision; + } } } - } - if (any_precision_encountered) { - IfcGeom::SetValue(IfcGeom::GV_PRECISION, lowest_precision_encountered); + if (any_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(); IfcUtil::IfcAbstractSelect::list units = IfcUtil::IfcAbstractSelect::list(); - if ( unit_assignments->Size() ) { - IfcSchema::IfcUnitAssignment::ptr unit_assignment = *unit_assignments->begin(); - units = unit_assignment->Units(); - } - if ( ! units ) { + try { + if ( unit_assignments->Size() ) { + IfcSchema::IfcUnitAssignment::ptr unit_assignment = *unit_assignments->begin(); + units = unit_assignment->Units(); + } + } catch (const IfcParse::IfcException&) {} + + if (!units) { // No units eh... Since tolerances and deflection are specified internally in meters // we will try to find another indication of the model size. IfcSchema::IfcExtrudedAreaSolid::list extrusions = ifc_file->EntitiesByType(); if ( ! extrusions->Size() ) return; double max_height = -1.0f; for ( IfcSchema::IfcExtrudedAreaSolid::it it = extrusions->begin(); it != extrusions->end(); ++ it ) { - const double depth = (*it)->Depth(); - if ( depth > max_height ) max_height = depth; + try { + 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; } + try { for ( IfcUtil::IfcAbstractSelect::it it = units->begin(); it != units->end(); ++ it ) { std::string current_unit_name = ""; @@ -691,8 +708,10 @@ void IfcGeomObjects::InitUnits() { } } } - } catch ( IfcParse::IfcException ex ) { - Logger::Message(Logger::LOG_ERROR,ex.what()); + } catch (const IfcParse::IfcException& ex) { + std::stringstream ss; + ss << "Failed to determine unit information '" << ex.what() << "'"; + Logger::Message(Logger::LOG_ERROR, ss.str()); } }