| 24 | #include "../profile_helper.h" |
| 25 | |
| 26 | taxonomy::ptr mapping::map_impl(const IfcSchema::IfcPolyline* inst) { |
| 27 | IfcSchema::IfcCartesianPoint::list::ptr points = inst->Points(); |
| 28 | |
| 29 | // Parse and store the points in a sequence |
| 30 | std::vector<taxonomy::point3::ptr> polygon; |
| 31 | polygon.reserve(points->size()); |
| 32 | std::transform(points->begin(), points->end(), std::back_inserter(polygon), [this](const IfcSchema::IfcCartesianPoint* p) { |
| 33 | return taxonomy::cast<taxonomy::point3>(map(p)); |
| 34 | }); |
| 35 | |
| 36 | auto eps = this->settings_.get<settings::Precision>().get(); |
| 37 | |
| 38 | const bool closed_by_proximity = polygon.size() >= 3 && (polygon.front()->ccomponents() - polygon.back()->ccomponents()).norm() < eps; |
| 39 | if (closed_by_proximity) { |
| 40 | polygon.resize(polygon.size() - 1); |
| 41 | } |
| 42 | |
| 43 | // Remove points that are too close to one another |
| 44 | auto previous_size = polygon.size(); |
| 45 | remove_duplicate_points_from_loop(polygon, closed_by_proximity, eps); |
| 46 | if (polygon.size() != previous_size) { |
| 47 | Logger::Warning("Removed " + std::to_string(previous_size - polygon.size()) + " (near) duplicate points from:", inst); |
| 48 | } |
| 49 | |
| 50 | if (polygon.size() < 2) { |
| 51 | // We somehow need to signal we fail this curve on purpose not to trigger an error. |
| 52 | Logger::Warning("Invalid polyline with " + std::to_string(polygon.size()) + " points:", inst); |
| 53 | return nullptr; |
| 54 | } |
| 55 | |
| 56 | if (closed_by_proximity) { |
| 57 | polygon.push_back(polygon.front()); |
| 58 | } |
| 59 | |
| 60 | return polygon_from_points(polygon); |
| 61 | } |