| 643 | } |
| 644 | |
| 645 | ifcopenshell::geometry::taxonomy::direction3::ptr IfcGeom::Iterator::remove_offset_() { |
| 646 | |
| 647 | using namespace ifcopenshell::geometry::taxonomy; |
| 648 | using namespace ifcopenshell::geometry::settings; |
| 649 | |
| 650 | if (!settings_.get<MaxOffset>().has()) { |
| 651 | return nullptr; |
| 652 | } |
| 653 | |
| 654 | if (!settings_.get<NoParallelMapping>().get()) { |
| 655 | throw std::runtime_error("remove_offset() can only be called with defer-processing-first-element and no-parallel-mapping settings"); |
| 656 | } |
| 657 | |
| 658 | auto collect_offset = [&](const item::ptr& itm, const std::vector<std::pair<IfcUtil::IfcBaseEntity*, matrix4::ptr>>& pr) -> std::pair<double, Eigen::Vector3d> { |
| 659 | std::function<std::pair<double, Eigen::Vector3d>(const item::ptr&, Eigen::Matrix4d)> traverse; |
| 660 | traverse = [&](const item::ptr& node, Eigen::Matrix4d m4) -> std::pair<double, Eigen::Vector3d> { |
| 661 | if (auto shl = std::dynamic_pointer_cast<shell>(node)) { |
| 662 | auto p = shl->centroid(); |
| 663 | Eigen::Vector4d v; |
| 664 | v << p->components()(0), p->components()(1), p->components()(2), 1.0; |
| 665 | Eigen::Vector3d translation_part = (m4 * v).head<3>(); |
| 666 | double translation_amnt = translation_part.norm(); |
| 667 | if (translation_amnt > settings_.get<MaxOffset>().get()) { |
| 668 | return { translation_amnt, translation_part }; |
| 669 | } else { |
| 670 | return { 0.0, Eigen::Vector3d::Zero() }; |
| 671 | } |
| 672 | } else { |
| 673 | if (auto gi = std::dynamic_pointer_cast<geom_item>(node)) { |
| 674 | if (gi->matrix) { |
| 675 | m4 = m4 * gi->matrix->ccomponents(); |
| 676 | } |
| 677 | } |
| 678 | Eigen::Vector3d translation_part = m4.block<3, 1>(0, 3); |
| 679 | double translation_amnt = translation_part.norm(); |
| 680 | if (translation_amnt > settings_.get<MaxOffset>().get()) { |
| 681 | return { translation_amnt, translation_part }; |
| 682 | } else if (auto col = std::dynamic_pointer_cast<collection>(node)) { |
| 683 | std::vector<std::pair<double, Eigen::Vector3d>> child_transforms; |
| 684 | for (const auto& child : col->children) { |
| 685 | child_transforms.push_back(traverse(child, m4)); |
| 686 | } |
| 687 | if (!child_transforms.empty()) { |
| 688 | return *std::max_element(child_transforms.begin(), child_transforms.end(), |
| 689 | [](const auto& a, const auto& b) { return a.first < b.first; }); |
| 690 | } |
| 691 | } |
| 692 | return { 0.0, Eigen::Vector3d::Zero() }; |
| 693 | } |
| 694 | }; |
| 695 | |
| 696 | Eigen::Matrix4d m4 = Eigen::Matrix4d::Identity(); |
| 697 | if (pr.size() == 1 && pr[0].second) { |
| 698 | m4 = pr[0].second->ccomponents(); |
| 699 | } |
| 700 | return traverse(itm, m4); |
| 701 | }; |
| 702 | |