Merge remote-tracking branch 'origin/v0.8.0' into tfk-rocksdb-storage

This commit is contained in:
Thomas Krijnen
2025-08-26 10:17:57 +02:00
1179 changed files with 47255 additions and 16166 deletions
+1 -1
View File
@@ -27,7 +27,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcAxis1Placement* inst) {
try {
taxonomy::point3::ptr v = taxonomy::cast<taxonomy::point3>(map(inst->Location()));
P = *v->components_;
} catch (const std::runtime_error&) {
} catch (const std::exception&) {
Logger::Warning("Placement with invalid Location:", inst);
}
const bool hasAxis = inst->Axis();
+1 -1
View File
@@ -28,7 +28,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcAxis2Placement2D* inst) {
try {
taxonomy::point3::ptr v = taxonomy::cast<taxonomy::point3>(map(inst->Location()));
P = *v->components_;
} catch (const std::runtime_error&) {
} catch (const std::exception&) {
Logger::Warning("Placement with invalid Location:", inst);
}
const bool hasRef = !!inst->RefDirection();
+1 -1
View File
@@ -28,7 +28,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcAxis2Placement3D* inst) {
try {
taxonomy::point3::ptr v = taxonomy::cast<taxonomy::point3>(map(inst->Location()));
o = *v->components_;
} catch (const std::runtime_error&) {
} catch (const std::exception&) {
Logger::Warning("Placement with invalid Location:", inst);
}
const bool hasAxis = !!inst->Axis();
+80 -52
View File
@@ -55,8 +55,10 @@ double translate_to_length_measure(const IfcSchema::IfcCurve* crv, double param_
return fabs(clothoid->ClothoidConstant()*sqrt(PI))*param_value;
} else if (auto circ = crv->as<IfcSchema::IfcCircle>()) {
return circ->Radius() * param_value;
#ifdef SCHEMA_HAS_IfcPolynomialCurve
} else if (auto poly = crv->as<IfcSchema::IfcPolynomialCurve>()) {
return param_value;
#endif
} else {
throw std::runtime_error("Unsupported curve measure type");
}
@@ -75,7 +77,9 @@ double translate_if_param_value(const IfcSchema::IfcCurve* crv, IfcSchema::IfcCu
typedef boost::mpl::vector<
IfcSchema::IfcLine
, IfcSchema::IfcCircle
#ifdef SCHEMA_HAS_IfcPolynomialCurve
, IfcSchema::IfcPolynomialCurve
#endif
#ifdef SCHEMA_HAS_IfcClothoid
, IfcSchema::IfcClothoid
#endif
@@ -198,8 +202,12 @@ class curve_segment_evaluator {
inst_(inst),
length_unit_(length_unit),
parent_curve_(inst->ParentCurve()) {
#ifdef SCHEMA_IfcSegment_HAS_UsingCurves
auto composite_curves = inst->UsingCurves();
#else
aggregate_of<IfcSchema::IfcCompositeCurve>::ptr composite_curves;
throw std::runtime_error("Schema not supported");
#endif
// Find the next segment after inst
const IfcSchema::IfcCurveSegment* next_inst = nullptr;
@@ -245,17 +253,23 @@ class curve_segment_evaluator {
segment_type_ = is_horizontal ? ST_HORIZONTAL : is_vertical ? ST_VERTICAL : is_cant ? ST_CANT : ST_HORIZONTAL;
#ifdef SCHEMA_IfcCurveSegment_HAS_SegmentStart
start_ = translate_if_param_value(inst->ParentCurve(), inst->SegmentStart()) * length_unit;
#else
throw std::runtime_error("Schema not supported");
#endif
length_ = translate_if_param_value(inst->ParentCurve(), inst->SegmentLength()) * length_unit;
projected_length_ = length_; // initialize with something reasonable
if (inst) {
#ifdef SCHEMA_IfcCurveSegment_HAS_Placement
curve_segment_placement_ = taxonomy::cast<taxonomy::matrix4>(mapping_->map(inst->Placement()))->ccomponents();
#endif
}
if (next_inst) {
#ifdef SCHEMA_IfcCurveSegment_HAS_Placement
next_segment_placement_ = taxonomy::cast<taxonomy::matrix4>(mapping_->map(next_inst->Placement()))->ccomponents();
#endif
} else {
// there is not a next segment, however IfcGradientCurve and IfcSegmentReferenceCurve have an
// optional EndPoint which services the same purpose as the zero-length last segment.
@@ -264,7 +278,9 @@ class curve_segment_evaluator {
auto& cc = *(composite_curves)->begin();
if (segment_type_ == ST_VERTICAL) {
auto gradient_curve = cc->as<IfcSchema::IfcGradientCurve>();
#ifdef SCHEMA_IfcCurveSegment_HAS_Placement
end_point = gradient_curve->EndPoint();
#endif
} else if (segment_type_ == ST_CANT) {
auto segmented_reference_curve = cc->as<IfcSchema::IfcSegmentedReferenceCurve>();
end_point = segmented_reference_curve->EndPoint();
@@ -448,14 +464,17 @@ class curve_segment_evaluator {
// defines the parent_curve_fn_ functor for cant segments.
void set_cant_spiral_function(std::function<double(double)> Superelevation, std::function<double(double)> SuperelevationSlope, std::function<double(double)> Cant) {
auto dy = (*curve_segment_placement_)(1, 2); // placement dy
auto dz = (*curve_segment_placement_)(2, 2); // placement dz
// compute start cross slope angle, measured relative to (0,0,1)
auto dy = (*curve_segment_placement_)(1, 2); // Axis.dy
auto dz = (*curve_segment_placement_)(2, 2); // Axis.dz
auto start_angle = atan2(dz, dy);
// compute end cross slope angle, measured relative to (0,0,1)
dy = (next_segment_placement_.has_value() ? (*next_segment_placement_)(1, 2) : 0.0);
dz = (next_segment_placement_.has_value() ? (*next_segment_placement_)(2, 2) : 1.0);
auto end_angle = atan2(dz, dy);
// angular change of railhead cross slope over the length of the segment
auto delta_angle = end_angle - start_angle;
auto start_cant = Cant(0.0 /*start_*/);
auto end_cant = Cant(/* start_ + */ length_);
@@ -529,7 +548,7 @@ class curve_segment_evaluator {
if (segment_type_ == ST_CANT) {
boost::optional<std::function<double(double)>> super, slope;
std::tie(super, slope) = get_superelevation_functions();
auto cant = [A, L](double t) -> double { return A ? L * A * t / fabs(pow(A, 3)) : 0.0; };
auto cant = [A, L](double t) -> double { return A ? L * L * A * t / fabs(pow(A, 3)) : 0.0; };
if (!super.has_value()) {
super = cant;
@@ -579,9 +598,9 @@ class curve_segment_evaluator {
std::tie(super, slope) = get_superelevation_functions();
auto cant = [constant_term, cosine_term, L](double t) -> double {
auto a0 = constant_term.has_value() ? L / constant_term.value() : 0.0;
auto a1 = (L / cosine_term) * cos(PI * t / L);
return a0 + a1;
auto a0 = constant_term.has_value() ? 1 / constant_term.value() : 0.0;
auto a1 = (1 / cosine_term) * cos(PI * t / L);
return L*L*(a0 + a1);
};
if (!super.has_value()) {
@@ -627,7 +646,7 @@ class curve_segment_evaluator {
if (segment_type_ == ST_HORIZONTAL) {
auto theta = [constant_term, linear_term, sine_term, L](double t) -> double {
auto a0 = constant_term.has_value() ? t / constant_term.value() : 0.0;
auto a1 = linear_term.has_value() ? sign(linear_term.value()) * pow(t / linear_term.value(), 2.0) / 2.0 : 0.0;
auto a1 = linear_term.has_value() ? (linear_term.value() / fabs(linear_term.value())) * pow(t / linear_term.value(), 2.0) / 2.0 : 0.0;
auto a2 = -1.0 * (L / (2 * PI * sine_term)) * (cos(2 * PI * t / L) - 1.0);
return a0 + a1 + a2;
};
@@ -635,7 +654,7 @@ class curve_segment_evaluator {
auto fn_y = [theta](double t) -> double { return sin(theta(t)); };
auto curvature = [constant_term, linear_term, sine_term, L](double t) -> double {
auto a0 = constant_term.has_value() ? L / constant_term.value() : 0.0;
auto a1 = linear_term.has_value() ? sign(linear_term.value()) * pow(L / linear_term.value(), 2.0)*(t/L) : 0.0;
auto a1 = linear_term.has_value() ? (linear_term.value() / fabs(linear_term.value())) * pow(L / linear_term.value(), 2.0) * (t / L) : 0.0;
auto a2 = (L / sine_term) * sin(2 * PI * t / L);
return a0 + a1 + a2;
};
@@ -646,10 +665,10 @@ class curve_segment_evaluator {
std::tie(super, slope) = get_superelevation_functions();
auto cant = [constant_term, linear_term, sine_term, L](double t) -> double {
auto a0 = constant_term.has_value() ? L / constant_term.value() : 0.0;
auto a1 = linear_term.has_value() ? sign(linear_term.value()) * pow(L / linear_term.value(), 2.0) * (t / L) : 0.0;
auto a2 = (L / sine_term) * sin(2 * PI * t / L);
return a0 + a1 + a2;
auto a0 = constant_term.has_value() ? 1 / constant_term.value() : 0.0;
auto a1 = linear_term.has_value() ? (linear_term.value()/fabs(linear_term.value())) * pow(1 / linear_term.value(), 2.0) * t : 0.0;
auto a2 = (1 / sine_term) * sin(2 * PI * t / L);
return L*L*(a0 + a1 + a2);
};
if (!super.has_value()) {
@@ -681,14 +700,14 @@ class curve_segment_evaluator {
void polynomial_spiral(boost::optional<double> A0, boost::optional<double> A1, boost::optional<double> A2, boost::optional<double> A3, boost::optional<double> A4, boost::optional<double> A5, boost::optional<double> A6, boost::optional<double> A7) {
auto theta = [A0, A1, A2, A3, A4, A5, A6, A7, start = start_ * length_unit_, lu = length_unit_](double t) -> double {
auto a0 = A0.has_value() ? t / (A0.value() * lu) : 0.0;
auto a1 = A1.has_value() ? A1.value() * lu * std::pow(t, 2) / (2 * fabs(std::pow(A1.value() * lu, 3))) : 0.0;
auto a2 = A2.has_value() ? std::pow(t, 3) / (3 * std::pow(A2.value() * lu, 3)) : 0.0;
auto a3 = A3.has_value() ? A3.value() * lu * std::pow(t, 4) / (4 * fabs(std::pow(A3.value() * lu, 5))) : 0.0;
auto a4 = A4.has_value() ? std::pow(t, 5) / (5 * std::pow(A4.value() * lu, 5)) : 0.0;
auto a5 = A5.has_value() ? A5.value() * lu * std::pow(t, 6) / (6 * fabs(std::pow(A5.value() * lu, 7))) : 0.0;
auto a6 = A6.has_value() ? std::pow(t, 7) / (7 * std::pow(A6.value() * lu, 7)) : 0.0;
auto a7 = A7.has_value() ? A7.value() * lu * std::pow(t, 8) / (8 * fabs(std::pow(A7.value() * lu, 9))) : 0.0;
auto a0 = A0.get_value_or(0.0) != 0.0 ? t / (A0.value() * lu) : 0.0;
auto a1 = A1.get_value_or(0.0) != 0.0 ? A1.value() * lu * std::pow(t, 2) / (2 * fabs(std::pow(A1.value() * lu, 3))) : 0.0;
auto a2 = A2.get_value_or(0.0) != 0.0 ? std::pow(t, 3) / (3 * std::pow(A2.value() * lu, 3)) : 0.0;
auto a3 = A3.get_value_or(0.0) != 0.0 ? A3.value() * lu * std::pow(t, 4) / (4 * fabs(std::pow(A3.value() * lu, 5))) : 0.0;
auto a4 = A4.get_value_or(0.0) != 0.0 ? std::pow(t, 5) / (5 * std::pow(A4.value() * lu, 5)) : 0.0;
auto a5 = A5.get_value_or(0.0) != 0.0 ? A5.value() * lu * std::pow(t, 6) / (6 * fabs(std::pow(A5.value() * lu, 7))) : 0.0;
auto a6 = A6.get_value_or(0.0) != 0.0 ? std::pow(t, 7) / (7 * std::pow(A6.value() * lu, 7)) : 0.0;
auto a7 = A7.get_value_or(0.0) != 0.0 ? A7.value() * lu * std::pow(t, 8) / (8 * fabs(std::pow(A7.value() * lu, 9))) : 0.0;
return a0 + a1 + a2 + a3 + a4 + a5 + a6 + a7;
};
@@ -699,14 +718,14 @@ class curve_segment_evaluator {
// this is same as cant function in polynomial_cant_spiral
auto curvature = [A0, A1, A2, A3, A4, A5, A6, A7, start = start_, L = length_, lu = length_unit_, length = length_](double t) -> double {
t += start;
auto a0 = A0.has_value() ? 1 / (A0.value() * lu) : 0.0;
auto a1 = A1.has_value() ? A1.value() * lu * t / fabs(std::pow(A1.value() * lu, 3)) : 0.0;
auto a2 = A2.has_value() ? std::pow(t, 2) / std::pow(A2.value() * lu, 3) : 0.0;
auto a3 = A3.has_value() ? A3.value() * lu * std::pow(t, 3) / fabs(std::pow(A3.value() * lu, 5)) : 0.0;
auto a4 = A4.has_value() ? std::pow(t, 4) / std::pow(A4.value() * lu, 5) : 0.0;
auto a5 = A5.has_value() ? A5.value() * lu * std::pow(t, 5) / fabs(std::pow(A5.value() * lu, 7)) : 0.0;
auto a6 = A6.has_value() ? std::pow(t, 6) / std::pow(A6.value() * lu, 7) : 0.0;
auto a7 = A7.has_value() ? A7.value() * lu * std::pow(t, 7) / fabs(std::pow(A7.value() * lu, 9)) : 0.0;
auto a0 = A0.get_value_or(0.0) != 0.0 ? 1 / (A0.value() * lu) : 0.0;
auto a1 = A1.get_value_or(0.0) != 0.0 ? A1.value() * lu * t / fabs(std::pow(A1.value() * lu, 3)) : 0.0;
auto a2 = A2.get_value_or(0.0) != 0.0 ? std::pow(t, 2) / std::pow(A2.value() * lu, 3) : 0.0;
auto a3 = A3.get_value_or(0.0) != 0.0 ? A3.value() * lu * std::pow(t, 3) / fabs(std::pow(A3.value() * lu, 5)) : 0.0;
auto a4 = A4.get_value_or(0.0) != 0.0 ? std::pow(t, 4) / std::pow(A4.value() * lu, 5) : 0.0;
auto a5 = A5.get_value_or(0.0) != 0.0 ? A5.value() * lu * std::pow(t, 5) / fabs(std::pow(A5.value() * lu, 7)) : 0.0;
auto a6 = A6.get_value_or(0.0) != 0.0 ? std::pow(t, 6) / std::pow(A6.value() * lu, 7) : 0.0;
auto a7 = A7.get_value_or(0.0) != 0.0 ? A7.value() * lu * std::pow(t, 7) / fabs(std::pow(A7.value() * lu, 9)) : 0.0;
return L * (a0 + a1 + a2 + a3 + a4 + a5 + a6 + a7);
};
@@ -721,15 +740,15 @@ class curve_segment_evaluator {
auto cant = [A0, A1, A2, A3, A4, A5, A6, A7, start = start_, L = length_, lu = length_unit_, length = length_](double t) -> double {
t += start;
auto a0 = A0.has_value() ? 1 / (A0.value() * lu) : 0.0;
auto a1 = A1.has_value() ? A1.value() * lu * t / fabs(std::pow(A1.value() * lu, 3)) : 0.0;
auto a2 = A2.has_value() ? std::pow(t, 2) / std::pow(A2.value() * lu, 3) : 0.0;
auto a3 = A3.has_value() ? A3.value() * lu * std::pow(t, 3) / fabs(std::pow(A3.value() * lu, 5)) : 0.0;
auto a4 = A4.has_value() ? std::pow(t, 4) / std::pow(A4.value() * lu, 5) : 0.0;
auto a5 = A5.has_value() ? A5.value() * lu * std::pow(t, 5) / fabs(std::pow(A5.value() * lu, 7)) : 0.0;
auto a6 = A6.has_value() ? std::pow(t, 6) / std::pow(A6.value() * lu, 7) : 0.0;
auto a7 = A7.has_value() ? A7.value() * lu * std::pow(t, 7) / fabs(std::pow(A7.value() * lu, 9)) : 0.0;
return L * (a0 + a1 + a2 + a3 + a4 + a5 + a6 + a7);
auto a0 = A0.get_value_or(0.0) != 0.0 ? 1 / (A0.value() * lu) : 0.0;
auto a1 = A1.get_value_or(0.0) != 0.0 ? A1.value() * lu * t / fabs(std::pow(A1.value() * lu, 3)) : 0.0;
auto a2 = A2.get_value_or(0.0) != 0.0 ? std::pow(t, 2) / std::pow(A2.value() * lu, 3) : 0.0;
auto a3 = A3.get_value_or(0.0) != 0.0 ? A3.value() * lu * std::pow(t, 3) / fabs(std::pow(A3.value() * lu, 5)) : 0.0;
auto a4 = A4.get_value_or(0.0) != 0.0 ? std::pow(t, 4) / std::pow(A4.value() * lu, 5) : 0.0;
auto a5 = A5.get_value_or(0.0) != 0.0 ? A5.value() * lu * std::pow(t, 5) / fabs(std::pow(A5.value() * lu, 7)) : 0.0;
auto a6 = A6.get_value_or(0.0) != 0.0 ? std::pow(t, 6) / std::pow(A6.value() * lu, 7) : 0.0;
auto a7 = A7.get_value_or(0.0) != 0.0 ? A7.value() * lu * std::pow(t, 7) / fabs(std::pow(A7.value() * lu, 9)) : 0.0;
return L * L * (a0 + a1 + a2 + a3 + a4 + a5 + a6 + a7);
};
if (!super.has_value()) {
@@ -739,14 +758,14 @@ class curve_segment_evaluator {
if (!slope.has_value()) {
slope = [A1, A2, A3, A4, A5, A6, A7, start = start_, L = length_, lu = length_unit_, length = length_](double t) -> double {
t += start;
auto a1 = A1.has_value() ? A1.value() * lu / fabs(std::pow(A1.value() * lu, 3)) : 0.0;
auto a2 = A2.has_value() ? 2 * t / std::pow(A2.value() * lu, 3) : 0.0;
auto a3 = A3.has_value() ? 3 * A3.value() * lu * std::pow(t, 2) / fabs(std::pow(A3.value() * lu, 5)) : 0.0;
auto a4 = A4.has_value() ? 4 * std::pow(t, 3) / std::pow(A4.value() * lu, 5) : 0.0;
auto a5 = A5.has_value() ? 5 * A5.value() * lu * std::pow(t, 4) / fabs(std::pow(A5.value() * lu, 7)) : 0.0;
auto a6 = A6.has_value() ? 6 * std::pow(t, 5) / std::pow(A6.value() * lu, 7) : 0.0;
auto a7 = A7.has_value() ? 7 * A7.value() * lu * std::pow(t, 6) / fabs(std::pow(A7.value() * lu, 9)) : 0.0;
return L * (a1 + a2 + a3 + a4 + a5 + a6 + a7);
auto a1 = A1.get_value_or(0.0) != 0.0 ? A1.value() * lu / fabs(std::pow(A1.value() * lu, 3)) : 0.0;
auto a2 = A2.get_value_or(0.0) != 0.0 ? 2 * t / std::pow(A2.value() * lu, 3) : 0.0;
auto a3 = A3.get_value_or(0.0) != 0.0 ? 3 * A3.value() * lu * std::pow(t, 2) / fabs(std::pow(A3.value() * lu, 5)) : 0.0;
auto a4 = A4.get_value_or(0.0) != 0.0 ? 4 * std::pow(t, 3) / std::pow(A4.value() * lu, 5) : 0.0;
auto a5 = A5.get_value_or(0.0) != 0.0 ? 5 * A5.value() * lu * std::pow(t, 4) / fabs(std::pow(A5.value() * lu, 7)) : 0.0;
auto a6 = A6.get_value_or(0.0) != 0.0 ? 6 * std::pow(t, 5) / std::pow(A6.value() * lu, 7) : 0.0;
auto a7 = A7.get_value_or(0.0) != 0.0 ? 7 * A7.value() * lu * std::pow(t, 6) / fabs(std::pow(A7.value() * lu, 9)) : 0.0;
return L * L * (a1 + a2 + a3 + a4 + a5 + a6 + a7);
};
}
@@ -773,9 +792,13 @@ class curve_segment_evaluator {
auto A0 = c->ConstantTerm();
auto A1 = c->LinearTerm();
auto A2 = c->QuadraticTerm();
auto A3 = c->CubicTerm();
boost::optional<double> A4, A5, A6, A7;
boost::optional<double> A3, A4, A5, A6, A7;
#ifdef SCHEMA_IfcThirdOrderPolynomialSpiral_HAS_CubicTerm
A3 = c->CubicTerm();
#else
A3 = c->QubicTerm();
#endif
if (segment_type_ == ST_CANT) {
polynomial_cant_spiral(A0, A1, A2, A3, A4, A5, A6, A7);
} else {
@@ -829,7 +852,10 @@ class curve_segment_evaluator {
if (segment_type_ == ST_HORIZONTAL) {
convert_u = [](double u) { return u; };
} else {
auto curve_segment_placement = taxonomy::cast<taxonomy::matrix4>(mapping_->map(inst_->Placement()))->ccomponents();
Eigen::Matrix4d curve_segment_placement;
#ifdef SCHEMA_IfcCurveSegment_HAS_Placement
curve_segment_placement = taxonomy::cast<taxonomy::matrix4>(mapping_->map(inst_->Placement()))->ccomponents();
#endif
auto csStartX = curve_segment_placement(0, 3);
auto csStartY = curve_segment_placement(1, 3);
auto csStartDx = curve_segment_placement(0, 0);
@@ -1012,6 +1038,7 @@ class curve_segment_evaluator {
}
}
#ifdef SCHEMA_HAS_IfcPolynomialCurve
void operator()(const IfcSchema::IfcPolynomialCurve* pc) {
// see https://forums.buildingsmart.org/t/ifcpolynomialcurve-clarification/4716 for discussion on IfcPolynomialCurve
auto coeffX = pc->CoefficientsX().get_value_or(std::vector<double>());
@@ -1156,6 +1183,7 @@ class curve_segment_evaluator {
[](double /*u*/) -> Eigen::Matrix4d { return Eigen::Matrix4d::Identity(); });
}
}
#endif
};
} // namespace
@@ -38,7 +38,8 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcFixedReferenceSweptAreaSolid
function_item_evaluator evaluator(settings_,fn);
double start = 0;
double end = fn->length();
#ifdef SCHEMA_HAS_IfcDirectrixCurveSweptAreaSolid
// IfcPointByDistanceExpression is introduced in rc2, the code below doesn't work on rc1 because startparam is optional<double>
#if defined(SCHEMA_HAS_IfcDirectrixCurveSweptAreaSolid) && defined(SCHEMA_HAS_IfcPointByDistanceExpression)
// IfcDirectrixCurveSweptAreaSolid introduced in 4.3 changed attribute type
// from optional IfcParamValue to optional IfcCurveMeasureSelect.
// Invocation of mapping on pre-4.3 models can never result in a piecewise_function.
+6 -1
View File
@@ -53,7 +53,12 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcGradientCurve* inst) {
// Get starting position of gradient curve, which is relative to the base curve
// The gradient curve can start before or after the start of the base curve
auto first_segment = *(segments->begin());
auto p = taxonomy::cast<taxonomy::matrix4>(map(first_segment->as<IfcSchema::IfcCurveSegment>()->Placement()));
taxonomy::matrix4::ptr p;
#ifdef SCHEMA_IfcCurveSegment_HAS_Placement
p = taxonomy::cast<taxonomy::matrix4>(map(first_segment->as<IfcSchema::IfcCurveSegment>()->Placement()));
#else
throw std::runtime_error("Unsupported schema");
#endif
const Eigen::Matrix4d& m = p->ccomponents();
double gradient_start = m(0, 3); // start of vertical (row 0, col 3) - "Distance Along" horizontal curve
@@ -39,15 +39,29 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcOffsetCurveByDistances* inst
auto first_offset_value = *(offset_values->begin());
auto basis_curve = inst->BasisCurve();
auto curve = taxonomy::dcast<taxonomy::function_item>(map(basis_curve));
if (!curve) {
// // IfcOffsetCurveByDistances can be based on another IfcOffsetCurveByDistances, an IfcGradientCurve, or an IfcCompositeCurve
// // When based on IfcOffsetCurveByDistances, it creates a chain of curves that we must navigate down to the base curve.
// // The source curve is IfcGradientCurve or IfcCompositeCurve. This loop drills down to the base curve.
// while (auto offset_curve = basis_curve->as<IfcSchema::IfcOffsetCurveByDistances>()) {
// basis_curve = offset_curve;
// }
//
//#if defined SCHEMA_HAS_IfcGradientCurve
// if (auto gc = basis_curve->as<IfcSchema::IfcGradientCurve>()) {
// basis_curve = gc->BaseCurve();
// }
//#endif
auto basis_curve_fn = taxonomy::dcast<taxonomy::function_item>(map(basis_curve));
if (!basis_curve_fn) {
// Only implement on alignment curves
Logger::Warning("IfcOffsetCurveByDistances is only implemented for BasisCurves curves based on taxonomy::function_item", inst);
return nullptr;
}
double start = curve->start();
double basis_curve_length = curve->length();
double start = basis_curve_fn->start();
double basis_curve_length = basis_curve_fn->length();
taxonomy::piecewise_function::spans_t offset_spans;
@@ -56,6 +70,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcOffsetCurveByDistances* inst
#else
double first_distance = *first_offset_value->DistanceAlong()->as<IfcSchema::IfcLengthMeasure>();
#endif
first_distance *= length_unit_;
if (first_distance < 0.0) {
Logger::Warning("IfcOffsetCurveByDistance first offset value is before the start of the curve.");
@@ -83,35 +98,54 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcOffsetCurveByDistances* inst
auto prev = std::prev(next);
auto end = offset_values->end();
for (; next != end; prev++, next++) {
#if defined SCHEMA_HAS_IfcPointByDistanceExpression
if ((*prev)->BasisCurve() != basis_curve || (*next)->BasisCurve() != basis_curve) {
Logger::Error("All offsets from a IfcOffsetCurveByDistances must refer to the same BasisCurve");
}
#endif
#if defined SCHEMA_HAS_IfcDistanceExpression
double dn = (*next)->DistanceAlong();
double dp = (*prev)->DistanceAlong();
double dn = (*next)->DistanceAlong();
#else
double dn = *(*next)->DistanceAlong()->as<IfcSchema::IfcLengthMeasure>();
double dp = *(*prev)->DistanceAlong()->as<IfcSchema::IfcLengthMeasure>();
double dn = *(*next)->DistanceAlong()->as<IfcSchema::IfcLengthMeasure>();
#endif
if ((dp < 0.0 || basis_curve_length < dp)
or
(dn < 0.0 || basis_curve_length < dn)
or
(dn < dp)
)
dp *= length_unit_;
dn *= length_unit_;
if (dn < dp) // next is before previous
{
Logger::Warning("IfcOffsetCurveByDistance offset value is out of bounds.");
continue;
}
double l = (dn - dp)*length_unit_;
double l = (dn - dp);
double yn = (*next)->OffsetLateral().get_value_or(0.0) * length_unit_;
double yp = (*prev)->OffsetLateral().get_value_or(0.0) * length_unit_;
double zn = (*next)->OffsetVertical().get_value_or(0.0) * length_unit_;
double zp = (*prev)->OffsetVertical().get_value_or(0.0) * length_unit_;
if ( (dp < 0.0 && dn < 0.0) || (basis_curve_length < dp && basis_curve_length < dn) ) {
// both points are either before the start of the curve or after the end of the curve. ignore them.
continue;
}
if (dp < 0.0) {
// previous is before the start of the curve
// compute y and z offsets at the start of the curve
auto yp_at_start = yp - (yn - yp) * dp / l;
auto zp_at_start = zp - (zn - zp) * dp / l;
dp = 0.0;
yp = yp_at_start;
zp = zp_at_start;
}
if (basis_curve_length < dn) {
// next is after the end of the curve
// compute y and z offsets at the end of the curve
auto yn_at_end = yn - (yn - yp) * (dn - basis_curve_length) / l;
auto zn_at_end = zn - (zn - zp) * (dn - basis_curve_length) / l;
dn = basis_curve_length;
yn = yn_at_end;
zn = zn_at_end;
}
auto fn = [yp, yn, zp, zn, l](double u) -> Eigen::Matrix4d {
Eigen::Matrix4d m = Eigen::Matrix4d::Identity();
@@ -128,10 +162,6 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcOffsetCurveByDistances* inst
#else
double last_distance = *(*prev)->DistanceAlong()->as<IfcSchema::IfcLengthMeasure>() * length_unit_;
#endif
if (basis_curve_length < last_distance) {
Logger::Warning("IfcOffsetCurveByDistance last offset value is after the end of the curve.");
}
if (last_distance < basis_curve_length) {
// Last offset is defined before the end of the curve so the lateral and vertical offsets
@@ -152,7 +182,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcOffsetCurveByDistances* inst
auto offsets = taxonomy::make<taxonomy::piecewise_function>(start,offset_spans);
auto fn = taxonomy::make<taxonomy::offset_function>(curve, offsets);
auto fn = taxonomy::make<taxonomy::offset_function>(basis_curve_fn, offsets);
return fn;
}
@@ -55,7 +55,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcSectionedSolidHorizontal* in
for (auto& cs : *css) {
faces.push_back(std::move(taxonomy::cast<taxonomy::face>(map(cs))));
}
#ifdef SCHEMA_HAS_IfcPointByDistanceExpression
#if defined(SCHEMA_HAS_IfcPointByDistanceExpression) && !defined(SCHEMA_IfcSectionedSurface_HAS_FixedAxisVertical)
for (auto& csp : *csps) {
auto pbde = csp->Location()->as<IfcSchema::IfcPointByDistanceExpression>(true);
+2 -1
View File
@@ -55,7 +55,8 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcSectionedSurface* inst) {
for (auto& cs : *css) {
faces.push_back(std::move(taxonomy::cast<taxonomy::geom_item>(map(cs))));
}
#ifdef SCHEMA_HAS_IfcPointByDistanceExpression
// IfcSectionedSurface::FixedAxisVertical removed in rc4, where CrossSectionPositions was IfcPointByDistanceExpression instead of IfcAxis2PlacementLinear
#if defined(SCHEMA_HAS_IfcPointByDistanceExpression) && !defined(SCHEMA_IfcSectionedSurface_HAS_FixedAxisVertical)
for (auto& csp : *csps) {
auto pbde = csp->Location()->as<IfcSchema::IfcPointByDistanceExpression>(true);
@@ -53,8 +53,13 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcSegmentedReferenceCurve* ins
// Get starting position of cant curve, relative to the gradient curve.
// The cant curve can start before or after the start of the gradient curve
auto first_segment = *(segments->begin());
auto p = taxonomy::cast<taxonomy::matrix4>(map(first_segment->as<IfcSchema::IfcCurveSegment>()->Placement()));
const Eigen::Matrix4d& m = p->ccomponents();
taxonomy::matrix4::ptr p;
#ifdef SCHEMA_IfcCurveSegment_HAS_Placement
p = taxonomy::cast<taxonomy::matrix4>(map(first_segment->as<IfcSchema::IfcCurveSegment>()->Placement()));
#else
throw std::runtime_error("Unsupported schema");
#endif
const Eigen::Matrix4d& m = p->ccomponents();
double cant_start = m(0, 3); // start of cant curve
auto cant = taxonomy::make<taxonomy::piecewise_function>(cant_start,spans);
+7 -1
View File
@@ -556,6 +556,10 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcMaterial* material) {
}
}
// When material does not have a representation we don't create a style from it
return nullptr;
/*
taxonomy::style::ptr material_style = taxonomy::make<taxonomy::style>();
material_style->instance = material;
if (settings_.get<settings::UseMaterialNames>().get()) {
@@ -566,6 +570,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcMaterial* material) {
material_style->name = oss.str();
}
return material_style;
*/
// @todo
// IfcGeom::SurfaceStyle material_style = IfcGeom::SurfaceStyle(material->data().id(), material->Name());
@@ -874,7 +879,8 @@ void mapping::initialize_units_() {
if (settings_.get<ModelRotation>().has()) {
auto vs = settings_.get<ModelRotation>().get();
if (vs.size() == 4) {
auto m3 = Eigen::Quaterniond(vs[0], vs[1], vs[2], vs[3]).normalized().matrix();
// @nb W, X, Y, Z
auto m3 = Eigen::Quaterniond(vs[3], vs[0], vs[1], vs[2]).normalized().matrix();
Eigen::Matrix4d m4 = Eigen::Matrix4d::Identity();
m4 << m3;
offset_and_rotation_ *= m4;