mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-18 06:21:40 +00:00
Merge branch 'v0.8.0' into feat/IfcFixedReferenceSweptAreaSolid
This commit is contained in:
@@ -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();
|
||||
@@ -776,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 {
|
||||
@@ -832,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);
|
||||
@@ -1015,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>());
|
||||
@@ -1159,6 +1183,7 @@ class curve_segment_evaluator {
|
||||
[](double /*u*/) -> Eigen::Matrix4d { return Eigen::Matrix4d::Identity(); });
|
||||
}
|
||||
}
|
||||
#endif
|
||||
};
|
||||
} // namespace
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user