| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | #include "tesselate.h" | 
| 2 |  |  |  |  |  |  | #include "mapbox/earcut.hpp" | 
| 3 |  |  |  |  |  |  | #include | 
| 4 |  |  |  |  |  |  | #include | 
| 5 |  |  |  |  |  |  |  | 
| 6 |  |  |  |  |  |  | using coord_t = geos::geom::Coordinate; | 
| 7 |  |  |  |  |  |  |  | 
| 8 |  |  |  |  |  |  | namespace mapbox { | 
| 9 |  |  |  |  |  |  | namespace util { | 
| 10 |  |  |  |  |  |  |  | 
| 11 |  |  |  |  |  |  | template <> | 
| 12 |  |  |  |  |  |  | struct nth<0, coord_t> { | 
| 13 | 24 |  |  |  |  |  | inline static auto get(const coord_t &t) { | 
| 14 | 24 |  |  |  |  |  | return t.x; | 
| 15 |  |  |  |  |  |  | }; | 
| 16 |  |  |  |  |  |  | }; | 
| 17 |  |  |  |  |  |  | template <> | 
| 18 |  |  |  |  |  |  | struct nth<1, coord_t> { | 
| 19 | 24 |  |  |  |  |  | inline static auto get(const coord_t &t) { | 
| 20 | 24 |  |  |  |  |  | return t.y; | 
| 21 |  |  |  |  |  |  | }; | 
| 22 |  |  |  |  |  |  | }; | 
| 23 |  |  |  |  |  |  |  | 
| 24 |  |  |  |  |  |  | } // namespace util | 
| 25 |  |  |  |  |  |  | } // namespace mapbox | 
| 26 |  |  |  |  |  |  |  | 
| 27 |  |  |  |  |  |  | namespace panda { namespace Geos { | 
| 28 |  |  |  |  |  |  |  | 
| 29 | 1 |  |  |  |  |  | geos::geom::GeometryCollection* tesselate(geos::geom::Polygon& input) { | 
| 30 |  |  |  |  |  |  | using seq_holder_t = std::unique_ptr; | 
| 31 |  |  |  |  |  |  | using result_t = std::vector; | 
| 32 |  |  |  |  |  |  | using poly_sequence_t = std::vector; | 
| 33 |  |  |  |  |  |  |  | 
| 34 | 1 | 50 |  |  |  |  | auto shell = input.getExteriorRing(); | 
| 35 | 2 | 50 |  |  |  |  | auto shell_coords = seq_holder_t{shell->getCoordinates()}; | 
| 36 | 2 |  |  |  |  |  | std::vector polygon; | 
| 37 | 2 |  |  |  |  |  | poly_sequence_t linearized; | 
| 38 |  |  |  |  |  |  |  | 
| 39 |  |  |  |  |  |  | /* outer ring/shell */ | 
| 40 | 1 | 50 |  |  |  |  | assert(shell_coords->size() > 1); | 
|  |  | 50 |  |  |  |  |  | 
| 41 | 2 |  |  |  |  |  | poly_sequence_t shell_seq; | 
| 42 | 5 | 50 |  |  |  |  | for (size_t i = 0; i < shell_coords->size() - 1; ++i) { | 
|  |  | 100 |  |  |  |  |  | 
| 43 | 4 | 50 |  |  |  |  | auto& coord = shell_coords->getAt(i); | 
| 44 | 4 | 50 |  |  |  |  | shell_seq.push_back(coord); | 
| 45 | 4 | 50 |  |  |  |  | linearized.push_back(coord); | 
| 46 |  |  |  |  |  |  | } | 
| 47 | 1 | 50 |  |  |  |  | polygon.push_back(shell_seq); | 
| 48 |  |  |  |  |  |  |  | 
| 49 |  |  |  |  |  |  | /* inner rings/holes */ | 
| 50 | 1 | 50 |  |  |  |  | auto holes_num = input.getNumInteriorRing(); | 
| 51 | 2 | 100 |  |  |  |  | for (size_t i = 0; i < holes_num; ++i) { | 
| 52 | 1 | 50 |  |  |  |  | auto* hole = input.getInteriorRingN(i); | 
| 53 | 2 | 50 |  |  |  |  | auto hole_coords = seq_holder_t{hole->getCoordinates()}; | 
| 54 | 1 | 50 |  |  |  |  | assert(hole_coords->size() > 1); | 
|  |  | 50 |  |  |  |  |  | 
| 55 | 2 |  |  |  |  |  | poly_sequence_t seq; | 
| 56 | 5 | 50 |  |  |  |  | for (size_t j = 0; j < hole_coords->size() - 1; ++j) { | 
|  |  | 100 |  |  |  |  |  | 
| 57 | 4 | 50 |  |  |  |  | auto& coord = hole_coords->getAt(j); | 
| 58 | 4 | 50 |  |  |  |  | seq.push_back(coord); | 
| 59 | 4 | 50 |  |  |  |  | linearized.push_back(coord); | 
| 60 |  |  |  |  |  |  | } | 
| 61 | 1 | 50 |  |  |  |  | polygon.push_back(seq); | 
| 62 |  |  |  |  |  |  | } | 
| 63 |  |  |  |  |  |  |  | 
| 64 |  |  |  |  |  |  | /* run tesselation */ | 
| 65 |  |  |  |  |  |  | using N = uint32_t; | 
| 66 | 2 | 50 |  |  |  |  | std::vector indices = mapbox::earcut(polygon); | 
| 67 | 1 |  |  |  |  |  | auto vertices = indices.size(); | 
| 68 | 1 | 50 |  |  |  |  | if (!vertices) throw "no tesselation (invalid polygon?)"; | 
| 69 | 1 | 50 |  |  |  |  | assert(vertices % 3 == 0); | 
| 70 |  |  |  |  |  |  |  | 
| 71 |  |  |  |  |  |  | /* construct triangles as polygones */ | 
| 72 | 1 |  |  |  |  |  | auto factory = input.getFactory(); | 
| 73 | 1 | 50 |  |  |  |  | auto seq_factory = factory->getCoordinateSequenceFactory(); | 
| 74 | 1 | 50 |  |  |  |  | auto triangles = new result_t(); | 
| 75 | 9 | 100 |  |  |  |  | for(size_t i = 0; i < indices.size(); i += 3) { | 
| 76 | 8 |  |  |  |  |  | auto& c_A = linearized[indices[i + 0]]; | 
| 77 | 8 |  |  |  |  |  | auto& c_B = linearized[indices[i + 1]]; | 
| 78 | 8 |  |  |  |  |  | auto& c_C = linearized[indices[i + 2]]; | 
| 79 | 16 | 50 |  |  |  |  | auto seq = seq_holder_t{seq_factory->create(4, 2)}; | 
| 80 | 8 | 50 |  |  |  |  | seq->setAt(c_A, 0); | 
| 81 | 8 | 50 |  |  |  |  | seq->setAt(c_B, 1); | 
| 82 | 8 | 50 |  |  |  |  | seq->setAt(c_C, 2); | 
| 83 | 8 | 50 |  |  |  |  | seq->setAt(c_A, 3); /* close the poly */ | 
| 84 |  |  |  |  |  |  |  | 
| 85 | 8 | 50 |  |  |  |  | auto shell = factory->createLinearRing(seq.release()); | 
| 86 | 8 | 50 |  |  |  |  | auto holes = new std::vector(); | 
| 87 | 8 | 50 |  |  |  |  | auto poly = factory->createPolygon(shell, holes); | 
| 88 | 8 | 50 |  |  |  |  | triangles->push_back(poly); | 
|  |  | 50 |  |  |  |  |  | 
| 89 |  |  |  |  |  |  | } | 
| 90 |  |  |  |  |  |  |  | 
| 91 | 2 | 50 |  |  |  |  | return factory->createGeometryCollection(triangles); | 
| 92 |  |  |  |  |  |  | } | 
| 93 |  |  |  |  |  |  |  | 
| 94 |  |  |  |  |  |  |  | 
| 95 | 184 | 50 |  |  |  |  | }} | 
|  |  | 50 |  |  |  |  |  |