mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 01:11:40 +00:00
Removed IfcPolyLine as a parent curve for IfcCurveSegment.
This commit is contained in:
@@ -72,7 +72,6 @@ double translate_if_param_value(const IfcSchema::IfcCurve* crv, IfcSchema::IfcCu
|
||||
// vector of parent curve types that are supported for IfcCurveSegment.ParentCurve
|
||||
typedef boost::mpl::vector<
|
||||
IfcSchema::IfcLine
|
||||
, IfcSchema::IfcPolyline
|
||||
, IfcSchema::IfcCircle
|
||||
, IfcSchema::IfcPolynomialCurve
|
||||
#ifdef SCHEMA_HAS_IfcClothoid
|
||||
@@ -524,145 +523,7 @@ class curve_segment_evaluator {
|
||||
}
|
||||
}
|
||||
|
||||
void operator()(const IfcSchema::IfcPolyline* pl)
|
||||
{
|
||||
if (segment_type_ == ST_HORIZONTAL || segment_type_ == ST_VERTICAL) {
|
||||
struct Range {
|
||||
double u_start;
|
||||
double u_end;
|
||||
std::function<bool(double, double, double)> compare;
|
||||
bool operator<(const Range& r) const { return u_start < r.u_start; }
|
||||
};
|
||||
|
||||
using Function = std::function<Eigen::Matrix4d(double u)>;
|
||||
std::map<Range, Function> fns;
|
||||
|
||||
auto p = pl->Points();
|
||||
if (p->size() < 2) {
|
||||
Logger::Error(std::runtime_error("invalid polyline - must have at least 2 points")); // this should never happen, but just in case it does
|
||||
}
|
||||
|
||||
auto std_compare = [](double u_start, double u, double u_end) { return u_start <= u && u < u_end; };
|
||||
auto end_compare = [](double u_start, double u, double u_end) { return u_start <= u && u <= (u_end + 0.001); };
|
||||
|
||||
auto begin = p->begin();
|
||||
auto iter = begin;
|
||||
auto end = p->end();
|
||||
auto last = std::prev(end);
|
||||
auto p1 = *(iter++);
|
||||
|
||||
if (segment_type_ == ST_HORIZONTAL) {
|
||||
if (p1->Coordinates().size() != 2) {
|
||||
Logger::Warning("Expected IfcPolyline.Points to be 2D", pl);
|
||||
}
|
||||
} else {
|
||||
if (p1->Coordinates().size() != 3) {
|
||||
Logger::Warning("Expected IfcPolyline.Points to be 3D", pl);
|
||||
}
|
||||
}
|
||||
|
||||
auto u = 0.0;
|
||||
for (; iter != end; iter++) {
|
||||
auto p2 = *iter;
|
||||
|
||||
auto p1x = p1->Coordinates()[0];
|
||||
auto p1y = p1->Coordinates()[1];
|
||||
auto p1z = segment_type_ == ST_HORIZONTAL ? 0.0 : p1->Coordinates()[2];
|
||||
|
||||
auto p2x = p2->Coordinates()[0];
|
||||
auto p2y = p2->Coordinates()[1];
|
||||
auto p2z = segment_type_ == ST_HORIZONTAL ? 0.0 : p2->Coordinates()[2];
|
||||
|
||||
auto dx = p2x - p1x;
|
||||
auto dy = p2y - p1y;
|
||||
auto dz = p2z - p1z;
|
||||
auto l = sqrt(dx * dx + dy * dy + dz*dz);
|
||||
|
||||
|
||||
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;
|
||||
Logger::Warning(os.str(), pl);
|
||||
continue; // go to next point
|
||||
}
|
||||
|
||||
auto lh = sqrt(dx * dx + dy * dy); // horizontal length
|
||||
auto ds = dz / lh;
|
||||
|
||||
dx /= l;
|
||||
dy /= l;
|
||||
dz /= l;
|
||||
|
||||
std::function<double(double)> convert_u;
|
||||
if (segment_type_ == ST_HORIZONTAL) {
|
||||
convert_u = [](double u) { return u; };
|
||||
} else {
|
||||
convert_u = [ds](double u) { return u * ds; };
|
||||
}
|
||||
|
||||
auto fn = [p1x, p1y, p1z, dx, dy, dz, convert_u](double u) {
|
||||
u = convert_u(u);
|
||||
|
||||
auto x = p1x + u * dx;
|
||||
auto y = p1y + u * dy;
|
||||
auto z = p1z + u * dz;
|
||||
// rotation around z
|
||||
Eigen::Matrix4d yaw = Eigen::Matrix4d::Identity();
|
||||
yaw.col(0) = Eigen::Vector4d(dx, dy, 0, 0);
|
||||
yaw.col(1) = Eigen::Vector4d(-dy, dx, 0, 0);
|
||||
|
||||
// rotation around y
|
||||
Eigen::Matrix4d pitch = Eigen::Matrix4d::Identity();
|
||||
pitch.col(0) = Eigen::Vector4d(dx, 0, dz, 0);
|
||||
pitch.col(2) = Eigen::Vector4d(-dz, 0, dx, 0);
|
||||
|
||||
// rotaton around x
|
||||
Eigen::Matrix4d roll = Eigen::Matrix4d::Identity();
|
||||
roll.col(1) = Eigen::Vector4d(0, dy, -dz, 0);
|
||||
roll.col(2) = Eigen::Vector4d(0, dz, dy, 0);
|
||||
|
||||
// translation
|
||||
Eigen::Matrix4d position = Eigen::Matrix4d::Identity();
|
||||
position.col(3) = Eigen::Vector4d(x, y, z, 1);
|
||||
|
||||
return yaw * pitch * roll * position;
|
||||
};
|
||||
|
||||
fns.insert(std::make_pair(Range{u, u + l, iter == last ? end_compare : std_compare}, fn));
|
||||
|
||||
p1 = p2;
|
||||
u = u + l;
|
||||
}
|
||||
|
||||
projected_length_ = length_;
|
||||
|
||||
parent_curve_fn_ = [fns](double u) {
|
||||
auto iter = std::find_if(fns.cbegin(), fns.cend(), [=](const auto& fn) {
|
||||
auto [u_start, u_end, compare] = fn.first;
|
||||
return compare(u_start, u, u_end);
|
||||
});
|
||||
|
||||
if (iter == fns.end()) {
|
||||
throw std::runtime_error("invalid distance from start"); // this should never happen, but just in case it does, throw an exception so the problem gets automatically detected
|
||||
}
|
||||
|
||||
const auto& [u_start, u_end, compare] = iter->first;
|
||||
const auto& fn = iter->second;
|
||||
Eigen::Matrix4d m = fn(u - u_start); // (u - u_start) is distance from start of this segment of the polyline
|
||||
return m;
|
||||
};
|
||||
|
||||
parent_curve_placement_ = (*parent_curve_fn_)(0.0);
|
||||
} else if (segment_type_ == ST_CANT) {
|
||||
Logger::Warning(std::runtime_error("Use of IfcPolyline for cant is not supported"));
|
||||
parent_curve_fn_ = [](double /*u*/) -> Eigen::Matrix4d { return Eigen::Matrix4d::Identity(); };
|
||||
} else {
|
||||
Logger::Warning(std::runtime_error("Unexpected segment type encountered"));
|
||||
parent_curve_fn_ = [](double /*u*/) -> Eigen::Matrix4d { return Eigen::Matrix4d::Identity(); };
|
||||
}
|
||||
}
|
||||
|
||||
void operator()(const IfcSchema::IfcLine* l) {
|
||||
void operator()(const IfcSchema::IfcLine* l) {
|
||||
projected_length_ = length_;
|
||||
|
||||
auto c = l->Pnt()->Coordinates();
|
||||
|
||||
Reference in New Issue
Block a user