| 822 | |
| 823 | |
| 824 | boost::optional<function_item::ptr> ifcopenshell::geometry::taxonomy::loop_to_function_item_upgrade_impl(ptr item) { |
| 825 | boost::optional<function_item::ptr> function_item_; |
| 826 | auto loop_ = dcast<loop>(item); |
| 827 | if (loop_) { |
| 828 | if (loop_->function_item.is_initialized()) { |
| 829 | function_item_ = loop_->function_item; |
| 830 | } else { |
| 831 | // piecewise_function is a specialization of function_item - callers don't need to know this detail |
| 832 | piecewise_function::spans_t spans; |
| 833 | spans.reserve(loop_->children.size()); |
| 834 | for (auto& edge_ : loop_->children) { |
| 835 | if (edge_->basis && edge_->basis->kind() == CIRCLE) { |
| 836 | const circle::ptr circ = std::static_pointer_cast<circle>(edge_->basis); |
| 837 | |
| 838 | auto* s_pnt = boost::get<point3::ptr>(&edge_->start); |
| 839 | auto* e_pnt = boost::get<point3::ptr>(&edge_->end); |
| 840 | auto* s_param = boost::get<double>(&edge_->start); |
| 841 | auto* e_param = boost::get<double>(&edge_->end); |
| 842 | |
| 843 | if (!s_pnt && !s_param) { |
| 844 | return boost::none; |
| 845 | } |
| 846 | if (!e_pnt && !e_param) { |
| 847 | return boost::none; |
| 848 | } |
| 849 | |
| 850 | double s = s_pnt ? project_onto_curve(circ, **s_pnt) : *s_param; |
| 851 | double e = e_pnt ? project_onto_curve(circ, **e_pnt) : *e_param; |
| 852 | |
| 853 | auto l = std::fabs(s - e) * circ->radius; |
| 854 | std::function<Eigen::Matrix4d(double)> fn = [circ, s](double u) { |
| 855 | point3 P; |
| 856 | direction3 d; |
| 857 | evaluate_curve(circ, u / circ->radius + s, P); |
| 858 | evaluate_curve_d1(circ, u / circ->radius + s, d); |
| 859 | return matrix4(P.ccomponents(), circ->matrix->ccomponents().col(2).head<3>(), d.ccomponents()).components(); |
| 860 | }; |
| 861 | spans.emplace_back(taxonomy::make<taxonomy::functor_item>(l, fn)); |
| 862 | } else if (edge_->start.which() == 1 && edge_->end.which() == 1) { |
| 863 | if (edge_->basis && edge_->basis->kind() != LINE) { |
| 864 | Logger::Message(Logger::Severity::LOG_WARNING, "Basis curve not supported - edge is treated as a straight line edge"); |
| 865 | } |
| 866 | const auto& s = boost::get<point3::ptr>(edge_->start)->ccomponents(); |
| 867 | const auto& e = boost::get<point3::ptr>(edge_->end)->ccomponents(); |
| 868 | Eigen::Vector3d v = e - s; |
| 869 | auto l = v.norm(); // the norm of a vector is a measure of its length |
| 870 | v.normalize(); // normalize the vector so that it is a unit direction vector |
| 871 | std::function<Eigen::Matrix4d(double)> fn = [s, v](double u) { |
| 872 | Eigen::Vector3d o(s + u * v), axis(0, 0, 1), refDirection(v); |
| 873 | auto Y = axis.cross(refDirection).normalized(); |
| 874 | axis = refDirection.cross(Y).normalized(); |
| 875 | return make<matrix4>(o, axis, refDirection)->components(); |
| 876 | }; |
| 877 | spans.emplace_back(taxonomy::make<taxonomy::functor_item>(l, fn)); |
| 878 | } else { |
| 879 | Logger::Message(Logger::Severity::LOG_ERROR, "Basis curve not supported"); |
| 880 | return boost::none; |
| 881 | } |
nothing calls this directly
no test coverage detected