| 3 | using namespace ifcopenshell::geometry; |
| 4 | |
| 5 | taxonomy::loop::ptr ifcopenshell::geometry::fillet_loop(taxonomy::loop::ptr loop, double radius) { |
| 6 | std::vector<profile_point_with_edges_3d> pps(loop->children.size()); |
| 7 | for (int b = 0; b < loop->children.size(); ++b) { |
| 8 | int c = (b - 1) % loop->children.size(); |
| 9 | pps[b] = { |
| 10 | boost::get<taxonomy::point3::ptr>(loop->children[c]->start)->ccomponents(), |
| 11 | radius, loop->children[c], loop->children[b] |
| 12 | }; |
| 13 | } |
| 14 | size_t i = pps.size(); |
| 15 | while (i--) { |
| 16 | const auto& p = pps[i]; |
| 17 | if (p.radius && *p.radius > 0.) { |
| 18 | |
| 19 | auto p0 = boost::get<taxonomy::point3::ptr>(p.previous->start)->ccomponents(); |
| 20 | auto p1a = boost::get<taxonomy::point3::ptr>(p.previous->end)->ccomponents(); |
| 21 | auto p2 = boost::get<taxonomy::point3::ptr>(p.next->end)->ccomponents(); |
| 22 | auto p1b = boost::get<taxonomy::point3::ptr>(p.next->start)->ccomponents(); |
| 23 | |
| 24 | auto ba_ = p0 - p1a; |
| 25 | auto bc_ = p2 - p1b; |
| 26 | |
| 27 | auto ba = ba_.normalized(); |
| 28 | auto bc = bc_.normalized(); |
| 29 | |
| 30 | const double angle = std::acos(ba.dot(bc)); |
| 31 | const double inset = *p.radius / std::tan(angle / 2.); |
| 32 | |
| 33 | boost::get<taxonomy::point3::ptr>(p.previous->end)->components() += ba * inset; |
| 34 | boost::get<taxonomy::point3::ptr>(p.next->start)->components() += bc * inset; |
| 35 | |
| 36 | auto e = taxonomy::make<taxonomy::edge>(); |
| 37 | e->start = p.previous->end; |
| 38 | e->end = p.next->start; |
| 39 | |
| 40 | // @todo untested from here. |
| 41 | |
| 42 | auto ab = ba.cross(bc); |
| 43 | |
| 44 | auto O = boost::get<taxonomy::point3::ptr>(p.previous->end)->ccomponents().head<3>() + ab * *p.radius; |
| 45 | |
| 46 | auto c = taxonomy::make<taxonomy::circle>(); |
| 47 | c->matrix = taxonomy::make<taxonomy::matrix4>(O, ab); |
| 48 | c->radius = *p.radius; |
| 49 | e->basis = c; |
| 50 | |
| 51 | loop->children.insert(std::find(loop->children.begin(), loop->children.end(), p.next), e); |
| 52 | } |
| 53 | }; |
| 54 | return loop; |
| 55 | } |
| 56 | |
| 57 | void ifcopenshell::geometry::remove_duplicate_points_from_loop(std::vector<taxonomy::point3::ptr>& polygon, bool closed, double tol) { |
| 58 | tol *= tol; |