diff --git a/src/ifcconvert/XmlSerializer.cpp b/src/ifcconvert/XmlSerializer.cpp index 0eb92c7a2e..b7c9bf3408 100644 --- a/src/ifcconvert/XmlSerializer.cpp +++ b/src/ifcconvert/XmlSerializer.cpp @@ -27,6 +27,8 @@ #include +#include "../ifcparse/IfcSIPrefix.h" + using boost::property_tree::ptree; using namespace IfcSchema; @@ -78,9 +80,6 @@ boost::optional format_attribute(const Argument* argument, IfcUtil: unit_name = unit->Name(); } - // TODO add toLower() and toUpper() string helper functions for the project - std::transform(unit_name.begin(), unit_name.end(), unit_name.begin(), ::tolower); - value = unit_name; } break; } @@ -252,7 +251,7 @@ void XmlSerializer::finalize() { } IfcProject* project = *projects->begin(); - ptree root, header, decomposition, properties; + ptree root, header, units, decomposition, properties; // Write the SPF header as XML nodes. foreach(const std::string& s, file->header().file_description().description()) { @@ -285,7 +284,20 @@ void XmlSerializer::finalize() { format_properties(pset->HasProperties(), node); } + // Write all assigned units as XML nodes. + IfcEntityList::ptr unit_assignments = project->UnitsInContext()->Units(); + for (IfcEntityList::it it = unit_assignments->begin(); it != unit_assignments->end(); ++it) { + if ((*it)->is(IfcSchema::Type::IfcNamedUnit)) { + IfcSchema::IfcNamedUnit* named_unit = (*it)->as(); + ptree& node = format_entity_instance(named_unit, units); + node.put(".SI_equivalent", IfcParse::get_SI_equivalent(named_unit)); + } else if ((*it)->is(IfcSchema::Type::IfcMonetaryUnit)) { + format_entity_instance((*it)->as(), units); + } + } + root.add_child("ifc.header", header); + root.add_child("ifc.units", units); root.add_child("ifc.properties", properties); root.add_child("ifc.decomposition", decomposition); diff --git a/src/ifcgeom/IfcGeomFunctions.cpp b/src/ifcgeom/IfcGeomFunctions.cpp index 95168585e5..4bcc8413c9 100644 --- a/src/ifcgeom/IfcGeomFunctions.cpp +++ b/src/ifcgeom/IfcGeomFunctions.cpp @@ -1293,43 +1293,36 @@ std::pair IfcGeom::Kernel::initializeUnits(IfcSchema::IfcUn if (!units || !units->size()) { Logger::Message(Logger::LOG_ERROR, "No unit information found"); } else { - for ( IfcEntityList::it it = units->begin(); it != units->end(); ++ it ) { + for (IfcEntityList::it it = units->begin(); it != units->end(); ++it) { std::string current_unit_name = ""; IfcUtil::IfcBaseClass* base = *it; IfcSchema::IfcSIUnit* unit = 0; - double value = 1.f; - if ( base->is(IfcSchema::Type::IfcConversionBasedUnit) ) { - IfcSchema::IfcConversionBasedUnit* u = (IfcSchema::IfcConversionBasedUnit*)base; - current_unit_name = u->Name(); - IfcSchema::IfcMeasureWithUnit* u2 = u->ConversionFactor(); - IfcSchema::IfcUnit* u3 = u2->UnitComponent(); - if ( u3->is(IfcSchema::Type::IfcSIUnit) ) { - unit = (IfcSchema::IfcSIUnit*) u3; - } - IfcSchema::IfcValue* v = u2->ValueComponent(); - // Quick hack to get the numeric value from an IfcValue: - const double f = *v->entity->getArgument(0); - value *= f; - } else if ( base->is(IfcSchema::Type::IfcSIUnit) ) { - unit = (IfcSchema::IfcSIUnit*)base; - } - if ( unit ) { - if ( unit->hasPrefix() ) { - value *= IfcParse::IfcSIPrefixToValue(unit->Prefix()); - } - IfcSchema::IfcUnitEnum::IfcUnitEnum type = unit->UnitType(); - if ( type == IfcSchema::IfcUnitEnum::IfcUnit_LENGTHUNIT ) { - setValue(IfcGeom::Kernel::GV_LENGTH_UNIT,value); - if (current_unit_name.empty()) { - if (unit->hasPrefix()) { - current_unit_name = IfcSchema::IfcSIPrefix::ToString(unit->Prefix()); + if (base->is(IfcSchema::Type::IfcNamedUnit)) { + 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->is(IfcSchema::Type::IfcConversionBasedUnit)) { + IfcSchema::IfcConversionBasedUnit* u = (IfcSchema::IfcConversionBasedUnit*)base; + current_unit_name = u->Name(); + } else if (named_unit->is(IfcSchema::Type::IfcSIUnit)) { + IfcSchema::IfcSIUnit* si_unit = named_unit->as(); + if (si_unit->hasPrefix()) { + current_unit_name = IfcSchema::IfcSIPrefix::ToString(si_unit->Prefix()) + unit_name; + } + current_unit_name += IfcSchema::IfcSIUnitName::ToString(si_unit->Name()); + } + if (named_unit->UnitType() == IfcSchema::IfcUnitEnum::IfcUnit_LENGTHUNIT) { + unit_name = current_unit_name; + unit_magnitude = current_unit_magnitude; + setValue(IfcGeom::Kernel::GV_LENGTH_UNIT, current_unit_magnitude); + } else { + setValue(IfcGeom::Kernel::GV_PLANEANGLE_UNIT, current_unit_magnitude); } - current_unit_name += IfcSchema::IfcSIUnitName::ToString(unit->Name()); } - unit_magnitude = value; - unit_name = current_unit_name; - } else if ( type == IfcSchema::IfcUnitEnum::IfcUnit_PLANEANGLEUNIT ) { - setValue(IfcGeom::Kernel::GV_PLANEANGLE_UNIT, value); } } } diff --git a/src/ifcparse/IfcSIPrefix.cpp b/src/ifcparse/IfcSIPrefix.cpp index e3edd16ed7..632760b5ee 100644 --- a/src/ifcparse/IfcSIPrefix.cpp +++ b/src/ifcparse/IfcSIPrefix.cpp @@ -36,4 +36,31 @@ double IfcParse::IfcSIPrefixToValue(IfcSchema::IfcSIPrefix::IfcSIPrefix v) { else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_FEMTO ) return 1.e-15; else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_ATTO ) return 1.e-18; else return 1.; +} + +double IfcParse::get_SI_equivalent(IfcSchema::IfcNamedUnit* named_unit) { + double scale = 1.; + IfcSchema::IfcSIUnit* si_unit = 0; + + if (named_unit->is(IfcSchema::Type::IfcConversionBasedUnit)) { + IfcSchema::IfcConversionBasedUnit* conv_unit = named_unit->as(); + IfcSchema::IfcMeasureWithUnit* factor = conv_unit->ConversionFactor(); + IfcSchema::IfcUnit* component = factor->UnitComponent(); + if (component->is(IfcSchema::Type::IfcSIUnit)) { + si_unit = component->as(); + IfcSchema::IfcValue* v = factor->ValueComponent(); + scale = *v->entity->getArgument(0); + } + } else if (named_unit->is(IfcSchema::Type::IfcSIUnit)) { + si_unit = named_unit->as(); + } + if (si_unit) { + if (si_unit->hasPrefix()) { + scale *= IfcSIPrefixToValue(si_unit->Prefix()); + } + } else { + scale = 0.; + } + + return scale; } \ No newline at end of file diff --git a/src/ifcparse/IfcSIPrefix.h b/src/ifcparse/IfcSIPrefix.h index 1c62b31bdd..c90a602eb5 100644 --- a/src/ifcparse/IfcSIPrefix.h +++ b/src/ifcparse/IfcSIPrefix.h @@ -23,7 +23,9 @@ #include "../ifcparse/IfcParse.h" namespace IfcParse { - double IfcSIPrefixToValue(IfcSchema::IfcSIPrefix::IfcSIPrefix v); + double IfcSIPrefixToValue(IfcSchema::IfcSIPrefix::IfcSIPrefix); + + double get_SI_equivalent(IfcSchema::IfcNamedUnit*); } #endif \ No newline at end of file