mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-20 12:12:15 +00:00
Handle missing or invalid unit and precision information more gracefully during IfcGeomObject initialization
This commit is contained in:
@@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user