diff --git a/src/ifcgeom/schema/mapping.cpp b/src/ifcgeom/schema/mapping.cpp index ecfef11143..d057166367 100644 --- a/src/ifcgeom/schema/mapping.cpp +++ b/src/ifcgeom/schema/mapping.cpp @@ -841,3 +841,71 @@ std::map mapping::get_layers(IfcUtil::IfcB } return layers; } + +#include "../../ifcparse/IfcSIPrefix.h" + +void mapping::initialize_units_() { + // Set default units, set length to meters, angles to undefined + length_unit_ = 1.; + angle_unit_ = -1.; + length_unit_name_ = "METER"; + + auto unit_assignments = file_->instances_by_type(); + if (unit_assignments->size() != 1) { + Logger::Warning("Not a single unit assignment in file"); + } + auto unit_assignment = *unit_assignments->begin(); + + bool length_unit_encountered = false, angle_unit_encountered = false; + + try { + IfcEntityList::ptr units = unit_assignment->Units(); + if (!units || !units->size()) { + Logger::Warning("No unit information found"); + } else { + for (IfcEntityList::it it = units->begin(); it != units->end(); ++it) { + IfcUtil::IfcBaseClass* base = *it; + if (base->declaration().is(IfcSchema::IfcNamedUnit::Class())) { + IfcSchema::IfcNamedUnit* named_unit = base->as(); + if (named_unit->UnitType() == IfcSchema::IfcUnitEnum::IfcUnit_LENGTHUNIT || + named_unit->UnitType() == IfcSchema::IfcUnitEnum::IfcUnit_PLANEANGLEUNIT) { + std::string current_unit_name; + const double current_unit_magnitude = IfcParse::get_SI_equivalent(named_unit); + if (current_unit_magnitude != 0.) { + if (named_unit->declaration().is(IfcSchema::IfcConversionBasedUnit::Class())) { + IfcSchema::IfcConversionBasedUnit* u = (IfcSchema::IfcConversionBasedUnit*)base; + current_unit_name = u->Name(); + } else if (named_unit->declaration().is(IfcSchema::IfcSIUnit::Class())) { + IfcSchema::IfcSIUnit* si_unit = named_unit->as(); + if (si_unit->hasPrefix()) { + current_unit_name = IfcSchema::IfcSIPrefix::ToString(si_unit->Prefix()); + } + current_unit_name += IfcSchema::IfcSIUnitName::ToString(si_unit->Name()); + } + if (named_unit->UnitType() == IfcSchema::IfcUnitEnum::IfcUnit_LENGTHUNIT) { + length_unit_name_ = current_unit_name; + length_unit_ = current_unit_magnitude; + length_unit_encountered = true; + } else { + angle_unit_ = current_unit_magnitude; + angle_unit_encountered = true; + } + } + } + } + } + } + } catch (const IfcParse::IfcException& ex) { + std::stringstream ss; + ss << "Failed to determine unit information '" << ex.what() << "'"; + Logger::Message(Logger::LOG_ERROR, ss.str()); + } + + if (!length_unit_encountered) { + Logger::Warning("No length unit encountered"); + } + + if (!angle_unit_encountered) { + Logger::Warning("No plane angle unit encountered"); + } +} diff --git a/src/ifcgeom/schema/mapping.h b/src/ifcgeom/schema/mapping.h index 4083966f0d..150196122c 100644 --- a/src/ifcgeom/schema/mapping.h +++ b/src/ifcgeom/schema/mapping.h @@ -16,8 +16,14 @@ namespace geometry { class POSTFIX_SCHEMA(mapping) : public abstract_mapping { private: IfcParse::IfcFile* file_; + double length_unit_, angle_unit_; + std::string length_unit_name_; + + void initialize_units_(); public: - POSTFIX_SCHEMA(mapping)(IfcParse::IfcFile* file) : file_(file) {} + POSTFIX_SCHEMA(mapping)(IfcParse::IfcFile* file) : file_(file) { + initialize_units_(); + } virtual ifcopenshell::geometry::taxonomy::item* map(const IfcUtil::IfcBaseClass*); virtual void get_representations(std::vector& tasks, std::vector& filters, settings& s); virtual std::map get_layers(IfcUtil::IfcBaseEntity*);