diff --git a/src/ifcgeom/mapping/IfcCurveSegment.cpp b/src/ifcgeom/mapping/IfcCurveSegment.cpp index ec16e5e852..ce4eb990c8 100644 --- a/src/ifcgeom/mapping/IfcCurveSegment.cpp +++ b/src/ifcgeom/mapping/IfcCurveSegment.cpp @@ -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 compare; - bool operator<(const Range& r) const { return u_start < r.u_start; } - }; - - using Function = std::function; - std::map 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().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 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();