| 22 | using namespace ifcopenshell::geometry; |
| 23 | |
| 24 | taxonomy::ptr mapping::map_impl(const IfcSchema::IfcCompositeCurve* inst) { |
| 25 | auto loop = taxonomy::make<taxonomy::loop>(); |
| 26 | taxonomy::piecewise_function::spans_t spans; |
| 27 | |
| 28 | #ifdef SCHEMA_HAS_IfcSegment |
| 29 | // 4x3 |
| 30 | IfcSchema::IfcSegment::list::ptr segments = inst->Segments(); |
| 31 | #else |
| 32 | IfcSchema::IfcCompositeCurveSegment::list::ptr segments = inst->Segments(); |
| 33 | #endif |
| 34 | |
| 35 | for (auto& segment : *segments) { |
| 36 | if (segment->as<IfcSchema::IfcCompositeCurveSegment>() && segment->as<IfcSchema::IfcCompositeCurveSegment>()->ParentCurve()->as<IfcSchema::IfcLine>()) { |
| 37 | Logger::Notice("Infinite IfcLine used as ParentCurve of segment, treating as a segment", segment); |
| 38 | double u0 = 0.0; |
| 39 | double u1 = segment->as<IfcSchema::IfcCompositeCurveSegment>()->ParentCurve()->as<IfcSchema::IfcLine>()->Dir()->Magnitude() * length_unit_; |
| 40 | if (u1 < settings_.get<settings::Precision>().get()) { |
| 41 | Logger::Warning("Segment length below tolerance", segment); |
| 42 | } |
| 43 | |
| 44 | auto e = taxonomy::make<taxonomy::edge>(); |
| 45 | e->basis = map(segment->as<IfcSchema::IfcCompositeCurveSegment>()->ParentCurve()); |
| 46 | e->start = u0; |
| 47 | e->end = u1; |
| 48 | e->curve_sense.reset(segment->as<IfcSchema::IfcCompositeCurveSegment>()->SameSense()); |
| 49 | |
| 50 | loop->children.push_back(e); |
| 51 | } |
| 52 | else if (segment->as<IfcSchema::IfcCompositeCurveSegment>()) { |
| 53 | auto crv = map(segment->as<IfcSchema::IfcCompositeCurveSegment>()->ParentCurve()); |
| 54 | if (crv) { |
| 55 | if (!segment->as<IfcSchema::IfcCompositeCurveSegment>()->SameSense()) { |
| 56 | crv->reverse(); |
| 57 | } |
| 58 | if (crv->kind() == taxonomy::EDGE) { |
| 59 | auto ecrv = taxonomy::cast<taxonomy::edge>(crv); |
| 60 | loop->children.push_back(ecrv); |
| 61 | } else if (crv->kind() == taxonomy::LOOP) { |
| 62 | for (auto& s : taxonomy::cast<taxonomy::loop>(crv)->children) { |
| 63 | loop->children.push_back(s); |
| 64 | } |
| 65 | } else if ((crv->kind() == taxonomy::CIRCLE || crv->kind() == taxonomy::ELLIPSE) && segments->size() == 1) { |
| 66 | // A circle or ellipse segment is a full circle/ellipse, only possible when it is the only segment |
| 67 | std::shared_ptr<taxonomy::edge> e = std::make_shared<taxonomy::edge>(); |
| 68 | e->basis = crv; |
| 69 | e->start = 0.0; |
| 70 | e->end = 2.0 * boost::math::constants::pi<double>(); |
| 71 | loop->children.push_back(e); |
| 72 | } else { |
| 73 | Logger::Warning("Unexpected segment type", segment); |
| 74 | return nullptr; |
| 75 | } |
| 76 | } |
| 77 | } |
| 78 | #ifdef SCHEMA_HAS_IfcCurveSegment |
| 79 | else if (segment->as<IfcSchema::IfcCurveSegment>()) { |
| 80 | // @todo check that we don't get a mixture of implicit and explicit definitions |
| 81 | auto crv = map(segment->as<IfcSchema::IfcCurveSegment>()); |