Drastic settings refactoring

This commit is contained in:
Thomas Krijnen
2023-11-15 10:32:20 +01:00
parent d2a2e0d7a0
commit 65e874c67f
80 changed files with 1057 additions and 723 deletions
+1 -1
View File
@@ -40,7 +40,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcCShapeProfileDef* inst) {
f2 = f1 + d1;
}
const double tol = conv_settings_.getValue(ConversionSettings::GV_PRECISION);
const double tol = settings_.get<settings::Precision>().get();
if ( x < tol || y < tol || d1 < tol || d2 < tol) {
Logger::Message(Logger::LOG_NOTICE," Skipping zero sized profile:", inst);
+1 -1
View File
@@ -25,7 +25,7 @@ using namespace ifcopenshell::geometry;
taxonomy::ptr mapping::map_impl(const IfcSchema::IfcCircle* inst) {
const double r = inst->Radius() * length_unit_;
if (r < conv_settings_.getValue(ConversionSettings::GV_PRECISION)) {
if (r < settings_.get<settings::Precision>().get()) {
Logger::Message(Logger::LOG_ERROR, "Radius not greater than zero for:", inst);
return nullptr;
}
+1 -1
View File
@@ -37,7 +37,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcCompositeCurve* inst) {
Logger::Notice("Infinite IfcLine used as ParentCurve of segment, treating as a segment", segment);
double u0 = 0.0;
double u1 = segment->as<IfcSchema::IfcCompositeCurveSegment>()->ParentCurve()->as<IfcSchema::IfcLine>()->Dir()->Magnitude() * length_unit_;
if (u1 < conv_settings_.getValue(ConversionSettings::GV_PRECISION)) {
if (u1 < settings_.get<settings::Precision>().get()) {
Logger::Warning("Segment length below tolerance", segment);
}
+1 -1
View File
@@ -632,7 +632,7 @@ class curve_segment_evaluator {
auto dy = p2y - p1y;
auto l = sqrt(dx * dx + dy * dy);
if (l < mapping_->conversion_settings().getValue(ConversionSettings::GV_PRECISION))
if (l < mapping_->settings().get<ifcopenshell::geometry::settings::Precision>().get())
{
std::ostringstream os;
os << "Coincident IfcPolyline.Points are not expected. Skipping point " << std::distance(iter, begin) << std::endl;
+1 -1
View File
@@ -24,7 +24,7 @@ using namespace ifcopenshell::geometry;
taxonomy::ptr mapping::map_impl(const IfcSchema::IfcEllipse* inst) {
double x = inst->SemiAxis1() * length_unit_;
double y = inst->SemiAxis2() * length_unit_;
const double tol = conv_settings_.getValue(ConversionSettings::GV_PRECISION);
const double tol = settings_.get<settings::Precision>().get();
if (x < tol || y < tol) {
Logger::Message(Logger::LOG_ERROR, "Radius not greater than zero for:", inst);
return nullptr;
+1 -1
View File
@@ -24,7 +24,7 @@ using namespace ifcopenshell::geometry;
taxonomy::ptr mapping::map_impl(const IfcSchema::IfcEllipseProfileDef* inst) {
double rx = inst->SemiAxis1() * length_unit_;
double ry = inst->SemiAxis2() * length_unit_;
const double tol = conv_settings_.getValue(ConversionSettings::GV_PRECISION);
const double tol = settings_.get<settings::Precision>().get();
if (rx < tol || ry < tol) {
Logger::Message(Logger::LOG_ERROR, "Radius not greater than zero for:", inst);
return nullptr;
+1 -1
View File
@@ -26,7 +26,7 @@ using namespace ifcopenshell::geometry;
taxonomy::ptr mapping::map_impl(const IfcSchema::IfcExtrudedAreaSolid* inst) {
const double height = inst->Depth() * length_unit_;
if (height < conv_settings_.getValue(ConversionSettings::GV_PRECISION)) {
if (height < settings_.get<settings::Precision>().get()) {
Logger::Message(Logger::LOG_ERROR, "Non-positive extrusion height encountered for:", inst);
#ifndef PERMISSIVE_EXTRUSION
return nullptr;
@@ -26,7 +26,7 @@ using namespace ifcopenshell::geometry;
#define mapping POSTFIX_SCHEMA(mapping)
taxonomy::ptr mapping::map_impl(const IfcSchema::IfcExtrudedAreaSolidTapered* inst) {
const double height = inst->Depth() * length_unit_;
if (height < conv_settings_.getValue(ConversionSettings::GV_PRECISION)) {
if (height < settings_.get<settings::Precision>().get()) {
Logger::Message(Logger::LOG_ERROR, "Non-positive extrusion height encountered for:", inst);
return nullptr;
}
+1 -1
View File
@@ -78,7 +78,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcIShapeProfileDef* inst) {
fe2 = fe1;
}
const double tol = conv_settings_.getValue(ConversionSettings::GV_PRECISION);
const double tol = settings_.get<settings::Precision>().get();
if (x1 < tol || x2 < tol || y < tol || d1 < tol || ft1 < tol || ft2 < tol) {
Logger::Message(Logger::LOG_NOTICE, "Skipping zero sized profile:", inst);
+1 -1
View File
@@ -42,7 +42,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcLShapeProfileDef* inst) {
f2 = *inst->EdgeRadius() * length_unit_;
}
const double tol = conv_settings_.getValue(ConversionSettings::GV_PRECISION);
const double tol = settings_.get<settings::Precision>().get();
if ( x < tol || y < tol || d < tol) {
Logger::Message(Logger::LOG_NOTICE, "Skipping zero sized profile:", inst);
+1 -1
View File
@@ -41,7 +41,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcPolyLoop* inst) {
}
// @todo Remove points that are too close to one another
const double eps = conv_settings_.getValue(ConversionSettings::GV_PRECISION);
const double eps = settings_.get<settings::Precision>().get();
// util::remove_duplicate_points_from_loop(polygon, true, eps);
int count = polygon.size();
+1 -1
View File
@@ -33,7 +33,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcPolyline* inst) {
return taxonomy::cast<taxonomy::point3>(map(p));
});
const bool closed_by_proximity = polygon.size() >= 3 && (*polygon.front()->components_ - *polygon.back()->components_).norm() < conv_settings_.getValue(ConversionSettings::GV_PRECISION);
const bool closed_by_proximity = polygon.size() >= 3 && (*polygon.front()->components_ - *polygon.back()->components_).norm() < settings_.get<settings::Precision>().get();
if (closed_by_proximity) {
polygon.resize(polygon.size() - 1);
polygon.push_back(polygon.front());
@@ -34,7 +34,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcRectangleHollowProfileDef* i
const double r1 = fr1 ? (*inst->OuterFilletRadius()) * length_unit_ : 0.;
const double r2 = fr2 ? (*inst->InnerFilletRadius()) * length_unit_ : 0.;
const double tol = conv_settings_.getValue(ConversionSettings::GV_PRECISION);
const double tol = settings_.get<settings::Precision>().get();
if (x < tol || y < tol) {
Logger::Message(Logger::LOG_NOTICE, "Skipping zero sized profile:", inst);
@@ -27,7 +27,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcRectangleProfileDef* inst) {
const double x = inst->XDim() / 2.0f * length_unit_;
const double y = inst->YDim() / 2.0f * length_unit_;
const double tol = conv_settings_.getValue(ConversionSettings::GV_PRECISION);
const double tol = settings_.get<settings::Precision>().get();
if (x < tol || y < tol) {
Logger::Message(Logger::LOG_NOTICE, "Skipping zero sized profile:", inst);
+2 -1
View File
@@ -22,7 +22,8 @@
using namespace ifcopenshell::geometry;
taxonomy::ptr mapping::map_impl(const IfcSchema::IfcRepresentation* inst) {
const bool use_body = !this->settings_.get(IfcGeom::IteratorSettings::INCLUDE_CURVES);
// @todo
const bool use_body = !this->settings_.get<settings::IncludeCurves>().get();
auto items = map_to_collection(this, inst->Items());
if (items == nullptr) {
@@ -28,7 +28,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcRoundedRectangleProfileDef*
const double y = inst->YDim() / 2.0f * length_unit_;
const double r = inst->RoundingRadius() * length_unit_;
const double tol = conv_settings_.getValue(ConversionSettings::GV_PRECISION);
const double tol = settings_.get<settings::Precision>().get();
if (x < tol || y < tol) {
Logger::Message(Logger::LOG_NOTICE, "Skipping zero sized profile:", inst);
+1 -1
View File
@@ -62,7 +62,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcSweptDiskSolid* inst) {
ep = inst->EndParam();
#endif
const double tol = conv_settings_.getValue(ConversionSettings::GV_PRECISION);
const double tol = settings_.get<settings::Precision>().get();
#ifdef SCHEMA_HAS_IfcSweptDiskSolidPolygonal
if (inst->as<IfcSchema::IfcSweptDiskSolidPolygonal>()) {
+1 -1
View File
@@ -37,7 +37,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcTShapeProfileDef* inst) {
const double flangeSlope = hasFlangeSlope ? (*inst->FlangeSlope() * angle_unit_) : 0.;
const double webSlope = hasWebSlope ? (*inst->WebSlope() * angle_unit_) : 0.;
const double tol = conv_settings_.getValue(ConversionSettings::GV_PRECISION);
const double tol = settings_.get<settings::Precision>().get();
if (x < tol || y < tol || d1 < tol || d2 < tol) {
Logger::Message(Logger::LOG_NOTICE, "Skipping zero sized profile:", inst);
@@ -33,7 +33,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcTrapeziumProfileDef* inst) {
// The trapezium x center should not be midway of BottomXDim but rather at the center of the overall bounding box.
const double x_offset = ((std::min(dx, 0.) + std::max(w + dx, x1 * 2.)) / 2.) - x1;
const double tol = conv_settings_.getValue(ConversionSettings::GV_PRECISION);
const double tol = settings_.get<settings::Precision>().get();
if (x1 < tol || w < tol || y < tol) {
Logger::Message(Logger::LOG_NOTICE, "Skipping zero sized profile:", inst);
+2 -2
View File
@@ -70,7 +70,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcTrimmedCurve* inst) {
}
}
const double tol = conv_settings_.getValue(ConversionSettings::GV_PRECISION);
const double tol = settings_.get<settings::Precision>().get();
trim_cartesian &= has_pnts[0] && has_pnts[1];
bool trim_cartesian_failed = !trim_cartesian;
@@ -126,7 +126,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcTrimmedCurve* inst) {
}
// @todo is 100. not too much? Check with the original issue.
const double precision_markup = conv_settings_.getValue(ConversionSettings::GV_PRECISION_FACTOR) == 1. ? 1. : 100.;
const double precision_markup = settings_.get<settings::PrecisionFactor>().get() == 1. ? 1. : 100.;
if (isConic && std::fabs(fmod(flts[1] - flts[0], pi * 2.)) < precision_markup * tol / (2 * pi * radius)) {
flts[0] = 0.;
+1 -1
View File
@@ -51,7 +51,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcUShapeProfileDef* inst) {
dy2 = x * tan(slope);
}
const double tol = conv_settings_.getValue(ConversionSettings::GV_PRECISION);
const double tol = settings_.get<settings::Precision>().get();
if (x < tol || y < tol || d1 < tol || d2 < tol) {
Logger::Message(Logger::LOG_NOTICE, "Skipping zero sized profile:", inst);
+1 -1
View File
@@ -42,7 +42,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcZShapeProfileDef* inst) {
f2 = *inst->EdgeRadius() * length_unit_;
}
const double tol = conv_settings_.getValue(ConversionSettings::GV_PRECISION);
const double tol = settings_.get<settings::Precision>().get();
if (x < tol || y < tol || dx < tol || dy < tol) {
Logger::Message(Logger::LOG_NOTICE, "Skipping zero sized profile:", inst);
+20 -75
View File
@@ -32,7 +32,7 @@ using namespace IfcGeom;
namespace {
struct POSTFIX_SCHEMA(factory_t) {
abstract_mapping* operator()(IfcParse::IfcFile* file, IteratorSettings& settings) const {
abstract_mapping* operator()(IfcParse::IfcFile* file, Settings& settings) const {
ifcopenshell::geometry::POSTFIX_SCHEMA(mapping)* m = new ifcopenshell::geometry::POSTFIX_SCHEMA(mapping)(file, settings);
return m;
}
@@ -114,7 +114,7 @@ namespace {
bool mapping::reuse_ok_(const IfcSchema::IfcProduct::list::ptr& products) {
// With world coords enabled, object transformations are directly applied to
// the BRep. There is no way to re-use the geometry for multiple products.
if (settings_.get(IfcGeom::IteratorSettings::USE_WORLD_COORDS)) {
if (settings_.get<settings::UseWorldCoords>().get()) {
return false;
}
@@ -127,11 +127,11 @@ bool mapping::reuse_ok_(const IfcSchema::IfcProduct::list::ptr& products) {
for (IfcSchema::IfcProduct::list::it it = products->begin(); it != products->end(); ++it) {
IfcSchema::IfcProduct* product = *it;
if (!settings_.get(IfcGeom::IteratorSettings::DISABLE_OPENING_SUBTRACTIONS) && find_openings(product)->size()) {
if (!settings_.get<settings::DisableOpeningSubtractions>().get() && find_openings(product)->size()) {
return false;
}
if (settings_.get(IfcGeom::IteratorSettings::APPLY_LAYERSETS)) {
if (settings_.get<settings::ApplyLayerSets>().get()) {
IfcSchema::IfcRelAssociates::list::ptr associations = product->HasAssociations();
for (IfcSchema::IfcRelAssociates::list::it jt = associations->begin(); jt != associations->end(); ++jt) {
IfcSchema::IfcRelAssociatesMaterial* assoc = (*jt)->as<IfcSchema::IfcRelAssociatesMaterial>();
@@ -188,7 +188,7 @@ aggregate_of_instance::ptr mapping::find_openings(const IfcUtil::IfcBaseEntity*
void mapping::get_representations(std::vector<geometry_conversion_task>& tasks, std::vector<filter_t>& filters) {
IfcSchema::IfcRepresentation::list::ptr representations(new IfcSchema::IfcRepresentation::list);
if (settings_.context_ids().empty()) {
if (!settings_.get<settings::ContextIds>().has()) {
addRepresentationsFromDefaultContexts(representations);
} else {
addRepresentationsFromContextIds(representations);
@@ -664,8 +664,8 @@ void mapping::initialize_units_() {
}
void mapping::initialize_settings() {
conv_settings_.setValue(ConversionSettings::GV_LENGTH_UNIT, length_unit_);
conv_settings_.setValue(ConversionSettings::GV_PLANEANGLE_UNIT, angle_unit_);
settings_.get<settings::LengthUnit>().value = length_unit_;
settings_.get<settings::PlaneUnit>().value = angle_unit_;
// Set precision from file
double lowest_precision_encountered = std::numeric_limits<double>::infinity();
@@ -679,12 +679,13 @@ void mapping::initialize_settings() {
IfcSchema::IfcGeometricRepresentationContext* context = *it;
// See if there is a context_id filter and whether the context is selected
if (!settings_.context_ids().empty()) {
if (settings_.context_ids().find(context->data().id()) == settings_.context_ids().end()) {
if (settings_.get<settings::ContextIds>().has()) {
auto cids = settings_.get<settings::ContextIds>().get();
if (cids.find(context->data().id()) == cids.end()) {
bool selected_sub_context = false;
auto subs = context->HasSubContexts();
for (auto& sub : *subs) {
if (settings_.context_ids().find(context->data().id()) != settings_.context_ids().end()) {
if (cids.find(context->data().id()) != cids.end()) {
selected_sub_context = true;
break;
}
@@ -695,9 +696,10 @@ void mapping::initialize_settings() {
}
}
if (context->Precision() && (*context->Precision() * length_unit_ * 10.) < lowest_precision_encountered) {
auto fp = settings_.get<settings::PrecisionFactor>().get();
if (context->Precision() && (*context->Precision() * length_unit_ * fp) < lowest_precision_encountered) {
// Some arbitrary factor that has proven to work better for the models in the set of test files.
lowest_precision_encountered = *context->Precision() * length_unit_ * 10.;
lowest_precision_encountered = *context->Precision() * length_unit_ * fp;
any_precision_encountered = true;
}
}
@@ -713,7 +715,7 @@ void mapping::initialize_settings() {
}
}
conv_settings_.setValue(ConversionSettings::GV_PRECISION, precision_to_set);
settings_.get<Precision>().value = precision_to_set;
}
bool mapping::get_layerset_information(const IfcUtil::IfcBaseInterface* p, layerset_information& info, int &)
@@ -920,7 +922,7 @@ IfcSchema::IfcRepresentation* mapping::find_representation(const IfcSchema::IfcP
}
void mapping::addRepresentationsFromContextIds(IfcSchema::IfcRepresentation::list::ptr& representations) {
for (auto context_id : settings_.context_ids()) {
for (auto context_id : settings_.get<settings::ContextIds>().get()) {
IfcSchema::IfcGeometricRepresentationContext* context;
try {
context = file_->instance_by_id(context_id)->as<IfcSchema::IfcGeometricRepresentationContext>();
@@ -944,7 +946,7 @@ void mapping::addRepresentationsFromDefaultContexts(IfcSchema::IfcRepresentation
allowed_context_types.insert("notdefined");
std::set<std::string> context_types;
if (!settings_.get(IfcGeom::IteratorSettings::EXCLUDE_SOLIDS_AND_SURFACES)) {
if (settings_.get<settings::IncludeSurfaces>().get()) {
// Really this should only be 'Model', as per
// the standard 'Design' is deprecated. So,
// just for backwards compatibility:
@@ -954,7 +956,7 @@ void mapping::addRepresentationsFromDefaultContexts(IfcSchema::IfcRepresentation
context_types.insert("model view");
context_types.insert("detail view");
}
if (settings_.get(IfcGeom::IteratorSettings::INCLUDE_CURVES)) {
if (settings_.get<settings::IncludeCurves>().get()) {
context_types.insert("plan");
}
@@ -1020,63 +1022,6 @@ void mapping::addRepresentationsFromDefaultContexts(IfcSchema::IfcRepresentation
}
}
void mapping::apply_settings() {
conv_settings_.setValue(ConversionSettings::GV_MAX_FACES_TO_ORIENT, settings_.get(IfcGeom::IteratorSettings::SEW_SHELLS) ? std::numeric_limits<double>::infinity() : -1);
conv_settings_.setValue(ConversionSettings::GV_DIMENSIONALITY, (settings_.get(IfcGeom::IteratorSettings::INCLUDE_CURVES)
? (settings_.get(IfcGeom::IteratorSettings::EXCLUDE_SOLIDS_AND_SURFACES) ? -1. : 0.) : +1.));
conv_settings_.setValue(ConversionSettings::GV_LAYERSET_FIRST,
settings_.get(IfcGeom::IteratorSettings::LAYERSET_FIRST)
? +1.0
: -1.0
);
conv_settings_.setValue(ConversionSettings::GV_NO_WIRE_INTERSECTION_CHECK,
settings_.get(IfcGeom::IteratorSettings::NO_WIRE_INTERSECTION_CHECK)
? +1.0
: -1.0
);
conv_settings_.setValue(ConversionSettings::GV_NO_WIRE_INTERSECTION_TOLERANCE,
settings_.get(IfcGeom::IteratorSettings::NO_WIRE_INTERSECTION_TOLERANCE)
? +1.0
: -1.0
);
conv_settings_.setValue(ConversionSettings::GV_PRECISION_FACTOR,
settings_.get(IfcGeom::IteratorSettings::STRICT_TOLERANCE)
? 1.0
: 10.0
);
conv_settings_.setValue(ConversionSettings::GV_DISABLE_BOOLEAN_RESULT,
settings_.get(IfcGeom::IteratorSettings::DISABLE_BOOLEAN_RESULT)
? +1.0
: -1.0
);
conv_settings_.setValue(ConversionSettings::GV_DEBUG_BOOLEAN,
settings_.get(IfcGeom::IteratorSettings::DEBUG_BOOLEAN)
? +1.0
: -1.0
);
conv_settings_.setValue(ConversionSettings::GV_BOOLEAN_ATTEMPT_2D,
settings_.get(IfcGeom::IteratorSettings::BOOLEAN_ATTEMPT_2D)
? +1.0
: -1.0
);
if (settings_.get(IfcGeom::IteratorSettings::BUILDING_LOCAL_PLACEMENT)) {
if (settings_.get(IfcGeom::IteratorSettings::SITE_LOCAL_PLACEMENT)) {
Logger::Message(Logger::LOG_WARNING, "building-local-placement takes precedence over site-local-placement");
}
placement_rel_to_type_ = &IfcSchema::IfcBuilding::Class();
} else if (settings_.get(IfcGeom::IteratorSettings::SITE_LOCAL_PLACEMENT)) {
placement_rel_to_type_ = &IfcSchema::IfcSite::Class();
}
// @todo
// conv_settings_.set_offset(settings_.offset);
// conv_settings_.set_rotation(settings_.rotation);
}
IfcUtil::IfcBaseEntity* mapping::representation_of(const IfcUtil::IfcBaseEntity* product) {
// @todo correct, but very inefficient
IfcSchema::IfcRepresentation::list::ptr representations(new IfcSchema::IfcRepresentation::list);
@@ -1084,7 +1029,7 @@ IfcUtil::IfcBaseEntity* mapping::representation_of(const IfcUtil::IfcBaseEntity*
IfcSchema::IfcRepresentation::list::ptr intersection(new IfcSchema::IfcRepresentation::list);
IfcSchema::IfcRepresentation::list::ptr intersection_no_box(new IfcSchema::IfcRepresentation::list);
if (settings_.context_ids().empty()) {
if (!settings_.get<settings::ContextIds>().has()) {
addRepresentationsFromDefaultContexts(representations);
} else {
addRepresentationsFromContextIds(representations);
@@ -1100,7 +1045,7 @@ IfcUtil::IfcBaseEntity* mapping::representation_of(const IfcUtil::IfcBaseEntity*
}
}
if (intersection->size() == 0 && settings_.context_ids().empty() && settings_.get(IfcGeom::IteratorSettings::INCLUDE_CURVES) && settings_.get(IfcGeom::IteratorSettings::EXCLUDE_SOLIDS_AND_SURFACES)) {
if (intersection->size() == 0 && settings_.get<settings::ContextIds>().has() && settings_.get<settings::IncludeCurves>().get() && !settings_.get<settings::IncludeSurfaces>().get()) {
for (auto& r : *of_product) {
if (r->RepresentationIdentifier() && *r->RepresentationIdentifier() == "Axis") {
intersection->push(r);
+1 -4
View File
@@ -31,9 +31,8 @@ namespace geometry {
void addRepresentationsFromContextIds(IfcSchema::IfcRepresentation::list::ptr&);
void addRepresentationsFromDefaultContexts(IfcSchema::IfcRepresentation::list::ptr&);
public:
POSTFIX_SCHEMA(mapping)(IfcParse::IfcFile* file, IfcGeom::IteratorSettings& settings) : abstract_mapping(settings), file_(file), placement_rel_to_type_(0), placement_rel_to_instance_(0) {
POSTFIX_SCHEMA(mapping)(IfcParse::IfcFile* file, Settings& settings) : abstract_mapping(settings), file_(file), placement_rel_to_type_(0), placement_rel_to_instance_(0) {
initialize_units_();
apply_settings();
}
virtual ifcopenshell::geometry::taxonomy::ptr map(const IfcUtil::IfcBaseInterface*);
virtual void get_representations(std::vector<geometry_conversion_task>& tasks, std::vector<filter_t>& filters);
@@ -42,8 +41,6 @@ namespace geometry {
virtual double get_length_unit() const { return length_unit_; }
virtual aggregate_of_instance::ptr find_openings(const IfcUtil::IfcBaseEntity*);
virtual IfcUtil::IfcBaseEntity* representation_of(const IfcUtil::IfcBaseEntity* product);
void apply_settings();
virtual const IfcUtil::IfcBaseEntity* get_single_material_association(const IfcUtil::IfcBaseEntity* product);
IfcSchema::IfcRepresentation* representation_mapped_to(const IfcSchema::IfcRepresentation* representation);