Fri, 01 Jul 2022 16:46:43 +0300
Fix right click to delete not really working properly
Instead of removing the point that had been added, it would remove
the point that is being drawn, which would cause it to overwrite the
previous point using the new point, causing a bit of a delay
223
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
1 | #pragma once |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
2 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
3 | #include <algorithm> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
4 | #include <cassert> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
5 | #include <cmath> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
6 | #include <cstddef> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
7 | #include <limits> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
8 | #include <memory> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
9 | #include <utility> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
10 | #include <vector> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
11 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
12 | namespace mapbox { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
13 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
14 | namespace util { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
15 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
16 | template <std::size_t I, typename T> struct nth { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
17 | inline static typename std::tuple_element<I, T>::type |
250
2837b549e616
I felt that the compiler was too kind to me, so I enabled a big pile of warnings
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
223
diff
changeset
|
18 | get(const T& t) { return std::get<I>(t); } |
223
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
19 | }; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
20 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
21 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
22 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
23 | namespace detail { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
24 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
25 | template <typename N = uint32_t> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
26 | class Earcut { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
27 | public: |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
28 | std::vector<N> indices; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
29 | std::size_t vertices = 0; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
30 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
31 | template <typename Polygon> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
32 | void operator()(const Polygon& points); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
33 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
34 | private: |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
35 | struct Node { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
36 | Node(N index, double x_, double y_) : i(index), x(x_), y(y_) {} |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
37 | Node(const Node&) = delete; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
38 | Node& operator=(const Node&) = delete; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
39 | Node(Node&&) = delete; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
40 | Node& operator=(Node&&) = delete; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
41 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
42 | const N i; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
43 | const double x; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
44 | const double y; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
45 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
46 | // previous and next vertice nodes in a polygon ring |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
47 | Node* prev = nullptr; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
48 | Node* next = nullptr; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
49 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
50 | // z-order curve value |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
51 | int32_t z = 0; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
52 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
53 | // previous and next nodes in z-order |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
54 | Node* prevZ = nullptr; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
55 | Node* nextZ = nullptr; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
56 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
57 | // indicates whether this is a steiner point |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
58 | bool steiner = false; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
59 | }; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
60 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
61 | template <typename Ring> Node* linkedList(const Ring& points, const bool clockwise); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
62 | Node* filterPoints(Node* start, Node* end = nullptr); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
63 | void earcutLinked(Node* ear, int pass = 0); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
64 | bool isEar(Node* ear); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
65 | bool isEarHashed(Node* ear); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
66 | Node* cureLocalIntersections(Node* start); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
67 | void splitEarcut(Node* start); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
68 | template <typename Polygon> Node* eliminateHoles(const Polygon& points, Node* outerNode); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
69 | Node* eliminateHole(Node* hole, Node* outerNode); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
70 | Node* findHoleBridge(Node* hole, Node* outerNode); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
71 | bool sectorContainsSector(const Node* m, const Node* p); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
72 | void indexCurve(Node* start); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
73 | Node* sortLinked(Node* list); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
74 | int32_t zOrder(const double x_, const double y_); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
75 | Node* getLeftmost(Node* start); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
76 | bool pointInTriangle(double ax, double ay, double bx, double by, double cx, double cy, double px, double py) const; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
77 | bool isValidDiagonal(Node* a, Node* b); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
78 | double area(const Node* p, const Node* q, const Node* r) const; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
79 | bool equals(const Node* p1, const Node* p2); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
80 | bool intersects(const Node* p1, const Node* q1, const Node* p2, const Node* q2); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
81 | bool onSegment(const Node* p, const Node* q, const Node* r); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
82 | int sign(double val); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
83 | bool intersectsPolygon(const Node* a, const Node* b); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
84 | bool locallyInside(const Node* a, const Node* b); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
85 | bool middleInside(const Node* a, const Node* b); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
86 | Node* splitPolygon(Node* a, Node* b); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
87 | template <typename Point> Node* insertNode(std::size_t i, const Point& p, Node* last); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
88 | void removeNode(Node* p); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
89 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
90 | bool hashing; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
91 | double minX, maxX; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
92 | double minY, maxY; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
93 | double inv_size = 0; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
94 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
95 | template <typename T, typename Alloc = std::allocator<T>> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
96 | class ObjectPool { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
97 | public: |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
98 | ObjectPool() { } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
99 | ObjectPool(std::size_t blockSize_) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
100 | reset(blockSize_); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
101 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
102 | ~ObjectPool() { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
103 | clear(); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
104 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
105 | template <typename... Args> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
106 | T* construct(Args&&... args) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
107 | if (currentIndex >= blockSize) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
108 | currentBlock = alloc_traits::allocate(alloc, blockSize); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
109 | allocations.emplace_back(currentBlock); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
110 | currentIndex = 0; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
111 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
112 | T* object = ¤tBlock[currentIndex++]; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
113 | alloc_traits::construct(alloc, object, std::forward<Args>(args)...); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
114 | return object; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
115 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
116 | void reset(std::size_t newBlockSize) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
117 | for (auto allocation : allocations) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
118 | alloc_traits::deallocate(alloc, allocation, blockSize); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
119 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
120 | allocations.clear(); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
121 | blockSize = std::max<std::size_t>(1, newBlockSize); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
122 | currentBlock = nullptr; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
123 | currentIndex = blockSize; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
124 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
125 | void clear() { reset(blockSize); } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
126 | private: |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
127 | T* currentBlock = nullptr; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
128 | std::size_t currentIndex = 1; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
129 | std::size_t blockSize = 1; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
130 | std::vector<T*> allocations; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
131 | Alloc alloc; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
132 | typedef typename std::allocator_traits<Alloc> alloc_traits; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
133 | }; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
134 | ObjectPool<Node> nodes; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
135 | }; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
136 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
137 | template <typename N> template <typename Polygon> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
138 | void Earcut<N>::operator()(const Polygon& points) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
139 | // reset |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
140 | indices.clear(); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
141 | vertices = 0; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
142 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
143 | if (points.empty()) return; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
144 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
145 | double x; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
146 | double y; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
147 | int threshold = 80; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
148 | std::size_t len = 0; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
149 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
150 | for (size_t i = 0; threshold >= 0 && i < points.size(); i++) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
151 | threshold -= static_cast<int>(points[i].size()); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
152 | len += points[i].size(); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
153 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
154 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
155 | //estimate size of nodes and indices |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
156 | nodes.reset(len * 3 / 2); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
157 | indices.reserve(len + points[0].size()); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
158 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
159 | Node* outerNode = linkedList(points[0], true); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
160 | if (!outerNode || outerNode->prev == outerNode->next) return; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
161 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
162 | if (points.size() > 1) outerNode = eliminateHoles(points, outerNode); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
163 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
164 | // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
165 | hashing = threshold < 0; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
166 | if (hashing) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
167 | Node* p = outerNode->next; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
168 | minX = maxX = outerNode->x; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
169 | minY = maxY = outerNode->y; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
170 | do { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
171 | x = p->x; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
172 | y = p->y; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
173 | minX = std::min<double>(minX, x); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
174 | minY = std::min<double>(minY, y); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
175 | maxX = std::max<double>(maxX, x); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
176 | maxY = std::max<double>(maxY, y); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
177 | p = p->next; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
178 | } while (p != outerNode); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
179 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
180 | // minX, minY and size are later used to transform coords into integers for z-order calculation |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
181 | inv_size = std::max<double>(maxX - minX, maxY - minY); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
182 | inv_size = inv_size != .0 ? (1. / inv_size) : .0; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
183 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
184 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
185 | earcutLinked(outerNode); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
186 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
187 | nodes.clear(); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
188 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
189 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
190 | // create a circular doubly linked list from polygon points in the specified winding order |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
191 | template <typename N> template <typename Ring> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
192 | typename Earcut<N>::Node* |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
193 | Earcut<N>::linkedList(const Ring& points, const bool clockwise) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
194 | using Point = typename Ring::value_type; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
195 | double sum = 0; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
196 | const std::size_t len = points.size(); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
197 | std::size_t i, j; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
198 | Node* last = nullptr; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
199 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
200 | // calculate original winding order of a polygon ring |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
201 | for (i = 0, j = len > 0 ? len - 1 : 0; i < len; j = i++) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
202 | const auto& p1 = points[i]; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
203 | const auto& p2 = points[j]; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
204 | const double p20 = util::nth<0, Point>::get(p2); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
205 | const double p10 = util::nth<0, Point>::get(p1); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
206 | const double p11 = util::nth<1, Point>::get(p1); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
207 | const double p21 = util::nth<1, Point>::get(p2); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
208 | sum += (p20 - p10) * (p11 + p21); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
209 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
210 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
211 | // link points into circular doubly-linked list in the specified winding order |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
212 | if (clockwise == (sum > 0)) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
213 | for (i = 0; i < len; i++) last = insertNode(vertices + i, points[i], last); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
214 | } else { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
215 | for (i = len; i-- > 0;) last = insertNode(vertices + i, points[i], last); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
216 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
217 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
218 | if (last && equals(last, last->next)) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
219 | removeNode(last); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
220 | last = last->next; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
221 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
222 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
223 | vertices += len; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
224 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
225 | return last; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
226 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
227 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
228 | // eliminate colinear or duplicate points |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
229 | template <typename N> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
230 | typename Earcut<N>::Node* |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
231 | Earcut<N>::filterPoints(Node* start, Node* end) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
232 | if (!end) end = start; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
233 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
234 | Node* p = start; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
235 | bool again; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
236 | do { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
237 | again = false; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
238 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
239 | if (!p->steiner && (equals(p, p->next) || area(p->prev, p, p->next) == 0)) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
240 | removeNode(p); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
241 | p = end = p->prev; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
242 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
243 | if (p == p->next) break; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
244 | again = true; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
245 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
246 | } else { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
247 | p = p->next; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
248 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
249 | } while (again || p != end); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
250 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
251 | return end; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
252 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
253 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
254 | // main ear slicing loop which triangulates a polygon (given as a linked list) |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
255 | template <typename N> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
256 | void Earcut<N>::earcutLinked(Node* ear, int pass) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
257 | if (!ear) return; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
258 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
259 | // interlink polygon nodes in z-order |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
260 | if (!pass && hashing) indexCurve(ear); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
261 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
262 | Node* stop = ear; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
263 | Node* prev; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
264 | Node* next; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
265 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
266 | int iterations = 0; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
267 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
268 | // iterate through ears, slicing them one by one |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
269 | while (ear->prev != ear->next) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
270 | iterations++; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
271 | prev = ear->prev; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
272 | next = ear->next; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
273 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
274 | if (hashing ? isEarHashed(ear) : isEar(ear)) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
275 | // cut off the triangle |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
276 | indices.emplace_back(prev->i); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
277 | indices.emplace_back(ear->i); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
278 | indices.emplace_back(next->i); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
279 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
280 | removeNode(ear); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
281 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
282 | // skipping the next vertice leads to less sliver triangles |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
283 | ear = next->next; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
284 | stop = next->next; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
285 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
286 | continue; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
287 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
288 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
289 | ear = next; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
290 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
291 | // if we looped through the whole remaining polygon and can't find any more ears |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
292 | if (ear == stop) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
293 | // try filtering points and slicing again |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
294 | if (!pass) earcutLinked(filterPoints(ear), 1); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
295 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
296 | // if this didn't work, try curing all small self-intersections locally |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
297 | else if (pass == 1) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
298 | ear = cureLocalIntersections(filterPoints(ear)); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
299 | earcutLinked(ear, 2); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
300 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
301 | // as a last resort, try splitting the remaining polygon into two |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
302 | } else if (pass == 2) splitEarcut(ear); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
303 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
304 | break; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
305 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
306 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
307 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
308 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
309 | // check whether a polygon node forms a valid ear with adjacent nodes |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
310 | template <typename N> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
311 | bool Earcut<N>::isEar(Node* ear) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
312 | const Node* a = ear->prev; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
313 | const Node* b = ear; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
314 | const Node* c = ear->next; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
315 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
316 | if (area(a, b, c) >= 0) return false; // reflex, can't be an ear |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
317 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
318 | // now make sure we don't have other points inside the potential ear |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
319 | Node* p = ear->next->next; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
320 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
321 | while (p != ear->prev) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
322 | if (pointInTriangle(a->x, a->y, b->x, b->y, c->x, c->y, p->x, p->y) && |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
323 | area(p->prev, p, p->next) >= 0) return false; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
324 | p = p->next; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
325 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
326 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
327 | return true; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
328 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
329 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
330 | template <typename N> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
331 | bool Earcut<N>::isEarHashed(Node* ear) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
332 | const Node* a = ear->prev; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
333 | const Node* b = ear; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
334 | const Node* c = ear->next; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
335 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
336 | if (area(a, b, c) >= 0) return false; // reflex, can't be an ear |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
337 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
338 | // triangle bbox; min & max are calculated like this for speed |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
339 | const double minTX = std::min<double>(a->x, std::min<double>(b->x, c->x)); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
340 | const double minTY = std::min<double>(a->y, std::min<double>(b->y, c->y)); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
341 | const double maxTX = std::max<double>(a->x, std::max<double>(b->x, c->x)); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
342 | const double maxTY = std::max<double>(a->y, std::max<double>(b->y, c->y)); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
343 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
344 | // z-order range for the current triangle bbox; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
345 | const int32_t minZ = zOrder(minTX, minTY); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
346 | const int32_t maxZ = zOrder(maxTX, maxTY); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
347 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
348 | // first look for points inside the triangle in increasing z-order |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
349 | Node* p = ear->nextZ; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
350 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
351 | while (p && p->z <= maxZ) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
352 | if (p != ear->prev && p != ear->next && |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
353 | pointInTriangle(a->x, a->y, b->x, b->y, c->x, c->y, p->x, p->y) && |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
354 | area(p->prev, p, p->next) >= 0) return false; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
355 | p = p->nextZ; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
356 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
357 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
358 | // then look for points in decreasing z-order |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
359 | p = ear->prevZ; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
360 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
361 | while (p && p->z >= minZ) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
362 | if (p != ear->prev && p != ear->next && |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
363 | pointInTriangle(a->x, a->y, b->x, b->y, c->x, c->y, p->x, p->y) && |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
364 | area(p->prev, p, p->next) >= 0) return false; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
365 | p = p->prevZ; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
366 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
367 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
368 | return true; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
369 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
370 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
371 | // go through all polygon nodes and cure small local self-intersections |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
372 | template <typename N> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
373 | typename Earcut<N>::Node* |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
374 | Earcut<N>::cureLocalIntersections(Node* start) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
375 | Node* p = start; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
376 | do { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
377 | Node* a = p->prev; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
378 | Node* b = p->next->next; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
379 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
380 | // a self-intersection where edge (v[i-1],v[i]) intersects (v[i+1],v[i+2]) |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
381 | if (!equals(a, b) && intersects(a, p, p->next, b) && locallyInside(a, b) && locallyInside(b, a)) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
382 | indices.emplace_back(a->i); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
383 | indices.emplace_back(p->i); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
384 | indices.emplace_back(b->i); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
385 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
386 | // remove two nodes involved |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
387 | removeNode(p); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
388 | removeNode(p->next); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
389 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
390 | p = start = b; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
391 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
392 | p = p->next; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
393 | } while (p != start); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
394 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
395 | return filterPoints(p); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
396 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
397 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
398 | // try splitting polygon into two and triangulate them independently |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
399 | template <typename N> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
400 | void Earcut<N>::splitEarcut(Node* start) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
401 | // look for a valid diagonal that divides the polygon into two |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
402 | Node* a = start; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
403 | do { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
404 | Node* b = a->next->next; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
405 | while (b != a->prev) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
406 | if (a->i != b->i && isValidDiagonal(a, b)) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
407 | // split the polygon in two by the diagonal |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
408 | Node* c = splitPolygon(a, b); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
409 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
410 | // filter colinear points around the cuts |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
411 | a = filterPoints(a, a->next); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
412 | c = filterPoints(c, c->next); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
413 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
414 | // run earcut on each half |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
415 | earcutLinked(a); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
416 | earcutLinked(c); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
417 | return; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
418 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
419 | b = b->next; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
420 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
421 | a = a->next; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
422 | } while (a != start); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
423 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
424 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
425 | // link every hole into the outer loop, producing a single-ring polygon without holes |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
426 | template <typename N> template <typename Polygon> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
427 | typename Earcut<N>::Node* |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
428 | Earcut<N>::eliminateHoles(const Polygon& points, Node* outerNode) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
429 | const size_t len = points.size(); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
430 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
431 | std::vector<Node*> queue; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
432 | for (size_t i = 1; i < len; i++) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
433 | Node* list = linkedList(points[i], false); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
434 | if (list) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
435 | if (list == list->next) list->steiner = true; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
436 | queue.push_back(getLeftmost(list)); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
437 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
438 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
439 | std::sort(queue.begin(), queue.end(), [](const Node* a, const Node* b) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
440 | return a->x < b->x; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
441 | }); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
442 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
443 | // process holes from left to right |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
444 | for (size_t i = 0; i < queue.size(); i++) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
445 | outerNode = eliminateHole(queue[i], outerNode); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
446 | outerNode = filterPoints(outerNode, outerNode->next); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
447 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
448 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
449 | return outerNode; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
450 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
451 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
452 | // find a bridge between vertices that connects hole with an outer ring and and link it |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
453 | template <typename N> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
454 | typename Earcut<N>::Node* |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
455 | Earcut<N>::eliminateHole(Node* hole, Node* outerNode) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
456 | Node* bridge = findHoleBridge(hole, outerNode); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
457 | if (!bridge) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
458 | return outerNode; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
459 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
460 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
461 | Node* bridgeReverse = splitPolygon(bridge, hole); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
462 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
463 | // filter collinear points around the cuts |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
464 | Node* filteredBridge = filterPoints(bridge, bridge->next); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
465 | filterPoints(bridgeReverse, bridgeReverse->next); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
466 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
467 | // Check if input node was removed by the filtering |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
468 | return outerNode == bridge ? filteredBridge : outerNode; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
469 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
470 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
471 | // David Eberly's algorithm for finding a bridge between hole and outer polygon |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
472 | template <typename N> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
473 | typename Earcut<N>::Node* |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
474 | Earcut<N>::findHoleBridge(Node* hole, Node* outerNode) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
475 | Node* p = outerNode; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
476 | double hx = hole->x; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
477 | double hy = hole->y; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
478 | double qx = -std::numeric_limits<double>::infinity(); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
479 | Node* m = nullptr; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
480 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
481 | // find a segment intersected by a ray from the hole's leftmost Vertex to the left; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
482 | // segment's endpoint with lesser x will be potential connection Vertex |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
483 | do { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
484 | if (hy <= p->y && hy >= p->next->y && p->next->y != p->y) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
485 | double x = p->x + (hy - p->y) * (p->next->x - p->x) / (p->next->y - p->y); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
486 | if (x <= hx && x > qx) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
487 | qx = x; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
488 | if (x == hx) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
489 | if (hy == p->y) return p; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
490 | if (hy == p->next->y) return p->next; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
491 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
492 | m = p->x < p->next->x ? p : p->next; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
493 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
494 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
495 | p = p->next; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
496 | } while (p != outerNode); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
497 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
498 | if (!m) return 0; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
499 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
500 | if (hx == qx) return m; // hole touches outer segment; pick leftmost endpoint |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
501 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
502 | // look for points inside the triangle of hole Vertex, segment intersection and endpoint; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
503 | // if there are no points found, we have a valid connection; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
504 | // otherwise choose the Vertex of the minimum angle with the ray as connection Vertex |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
505 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
506 | const Node* stop = m; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
507 | double tanMin = std::numeric_limits<double>::infinity(); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
508 | double tanCur = 0; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
509 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
510 | p = m; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
511 | double mx = m->x; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
512 | double my = m->y; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
513 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
514 | do { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
515 | if (hx >= p->x && p->x >= mx && hx != p->x && |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
516 | pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p->x, p->y)) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
517 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
518 | tanCur = std::abs(hy - p->y) / (hx - p->x); // tangential |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
519 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
520 | if (locallyInside(p, hole) && |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
521 | (tanCur < tanMin || (tanCur == tanMin && (p->x > m->x || sectorContainsSector(m, p))))) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
522 | m = p; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
523 | tanMin = tanCur; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
524 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
525 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
526 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
527 | p = p->next; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
528 | } while (p != stop); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
529 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
530 | return m; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
531 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
532 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
533 | // whether sector in vertex m contains sector in vertex p in the same coordinates |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
534 | template <typename N> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
535 | bool Earcut<N>::sectorContainsSector(const Node* m, const Node* p) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
536 | return area(m->prev, m, p->prev) < 0 && area(p->next, m, m->next) < 0; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
537 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
538 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
539 | // interlink polygon nodes in z-order |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
540 | template <typename N> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
541 | void Earcut<N>::indexCurve(Node* start) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
542 | assert(start); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
543 | Node* p = start; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
544 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
545 | do { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
546 | p->z = p->z ? p->z : zOrder(p->x, p->y); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
547 | p->prevZ = p->prev; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
548 | p->nextZ = p->next; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
549 | p = p->next; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
550 | } while (p != start); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
551 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
552 | p->prevZ->nextZ = nullptr; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
553 | p->prevZ = nullptr; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
554 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
555 | sortLinked(p); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
556 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
557 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
558 | // Simon Tatham's linked list merge sort algorithm |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
559 | // http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
560 | template <typename N> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
561 | typename Earcut<N>::Node* |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
562 | Earcut<N>::sortLinked(Node* list) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
563 | assert(list); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
564 | Node* p; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
565 | Node* q; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
566 | Node* e; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
567 | Node* tail; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
568 | int i, numMerges, pSize, qSize; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
569 | int inSize = 1; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
570 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
571 | for (;;) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
572 | p = list; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
573 | list = nullptr; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
574 | tail = nullptr; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
575 | numMerges = 0; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
576 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
577 | while (p) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
578 | numMerges++; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
579 | q = p; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
580 | pSize = 0; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
581 | for (i = 0; i < inSize; i++) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
582 | pSize++; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
583 | q = q->nextZ; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
584 | if (!q) break; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
585 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
586 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
587 | qSize = inSize; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
588 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
589 | while (pSize > 0 || (qSize > 0 && q)) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
590 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
591 | if (pSize == 0) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
592 | e = q; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
593 | q = q->nextZ; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
594 | qSize--; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
595 | } else if (qSize == 0 || !q) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
596 | e = p; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
597 | p = p->nextZ; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
598 | pSize--; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
599 | } else if (p->z <= q->z) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
600 | e = p; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
601 | p = p->nextZ; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
602 | pSize--; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
603 | } else { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
604 | e = q; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
605 | q = q->nextZ; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
606 | qSize--; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
607 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
608 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
609 | if (tail) tail->nextZ = e; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
610 | else list = e; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
611 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
612 | e->prevZ = tail; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
613 | tail = e; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
614 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
615 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
616 | p = q; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
617 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
618 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
619 | tail->nextZ = nullptr; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
620 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
621 | if (numMerges <= 1) return list; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
622 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
623 | inSize *= 2; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
624 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
625 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
626 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
627 | // z-order of a Vertex given coords and size of the data bounding box |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
628 | template <typename N> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
629 | int32_t Earcut<N>::zOrder(const double x_, const double y_) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
630 | // coords are transformed into non-negative 15-bit integer range |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
631 | int32_t x = static_cast<int32_t>(32767.0 * (x_ - minX) * inv_size); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
632 | int32_t y = static_cast<int32_t>(32767.0 * (y_ - minY) * inv_size); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
633 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
634 | x = (x | (x << 8)) & 0x00FF00FF; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
635 | x = (x | (x << 4)) & 0x0F0F0F0F; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
636 | x = (x | (x << 2)) & 0x33333333; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
637 | x = (x | (x << 1)) & 0x55555555; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
638 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
639 | y = (y | (y << 8)) & 0x00FF00FF; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
640 | y = (y | (y << 4)) & 0x0F0F0F0F; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
641 | y = (y | (y << 2)) & 0x33333333; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
642 | y = (y | (y << 1)) & 0x55555555; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
643 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
644 | return x | (y << 1); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
645 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
646 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
647 | // find the leftmost node of a polygon ring |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
648 | template <typename N> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
649 | typename Earcut<N>::Node* |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
650 | Earcut<N>::getLeftmost(Node* start) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
651 | Node* p = start; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
652 | Node* leftmost = start; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
653 | do { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
654 | if (p->x < leftmost->x || (p->x == leftmost->x && p->y < leftmost->y)) |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
655 | leftmost = p; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
656 | p = p->next; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
657 | } while (p != start); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
658 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
659 | return leftmost; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
660 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
661 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
662 | // check if a point lies within a convex triangle |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
663 | template <typename N> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
664 | bool Earcut<N>::pointInTriangle(double ax, double ay, double bx, double by, |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
665 | double cx, double cy, double px, double py) const { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
666 | return (cx - px) * (ay - py) - (ax - px) * (cy - py) >= 0 && |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
667 | (ax - px) * (by - py) - (bx - px) * (ay - py) >= 0 && |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
668 | (bx - px) * (cy - py) - (cx - px) * (by - py) >= 0; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
669 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
670 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
671 | // check if a diagonal between two polygon nodes is valid (lies in polygon interior) |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
672 | template <typename N> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
673 | bool Earcut<N>::isValidDiagonal(Node* a, Node* b) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
674 | // dones't intersect other edges |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
675 | return a->next->i != b->i && a->prev->i != b->i && !intersectsPolygon(a, b) && |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
676 | // locally visible |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
677 | ((locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b) && |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
678 | // does not create opposite-facing sectors |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
679 | (area(a->prev, a, b->prev) != 0.0 || area(a, b->prev, b) != 0.0)) || |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
680 | // special zero-length case |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
681 | (equals(a, b) && area(a->prev, a, a->next) > 0 && area(b->prev, b, b->next) > 0)); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
682 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
683 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
684 | // signed area of a triangle |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
685 | template <typename N> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
686 | double Earcut<N>::area(const Node* p, const Node* q, const Node* r) const { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
687 | return (q->y - p->y) * (r->x - q->x) - (q->x - p->x) * (r->y - q->y); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
688 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
689 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
690 | // check if two points are equal |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
691 | template <typename N> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
692 | bool Earcut<N>::equals(const Node* p1, const Node* p2) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
693 | return p1->x == p2->x && p1->y == p2->y; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
694 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
695 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
696 | // check if two segments intersect |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
697 | template <typename N> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
698 | bool Earcut<N>::intersects(const Node* p1, const Node* q1, const Node* p2, const Node* q2) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
699 | int o1 = sign(area(p1, q1, p2)); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
700 | int o2 = sign(area(p1, q1, q2)); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
701 | int o3 = sign(area(p2, q2, p1)); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
702 | int o4 = sign(area(p2, q2, q1)); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
703 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
704 | if (o1 != o2 && o3 != o4) return true; // general case |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
705 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
706 | if (o1 == 0 && onSegment(p1, p2, q1)) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1 |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
707 | if (o2 == 0 && onSegment(p1, q2, q1)) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1 |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
708 | if (o3 == 0 && onSegment(p2, p1, q2)) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2 |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
709 | if (o4 == 0 && onSegment(p2, q1, q2)) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2 |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
710 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
711 | return false; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
712 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
713 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
714 | // for collinear points p, q, r, check if point q lies on segment pr |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
715 | template <typename N> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
716 | bool Earcut<N>::onSegment(const Node* p, const Node* q, const Node* r) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
717 | return q->x <= std::max<double>(p->x, r->x) && |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
718 | q->x >= std::min<double>(p->x, r->x) && |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
719 | q->y <= std::max<double>(p->y, r->y) && |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
720 | q->y >= std::min<double>(p->y, r->y); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
721 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
722 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
723 | template <typename N> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
724 | int Earcut<N>::sign(double val) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
725 | return (0.0 < val) - (val < 0.0); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
726 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
727 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
728 | // check if a polygon diagonal intersects any polygon segments |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
729 | template <typename N> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
730 | bool Earcut<N>::intersectsPolygon(const Node* a, const Node* b) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
731 | const Node* p = a; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
732 | do { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
733 | if (p->i != a->i && p->next->i != a->i && p->i != b->i && p->next->i != b->i && |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
734 | intersects(p, p->next, a, b)) return true; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
735 | p = p->next; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
736 | } while (p != a); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
737 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
738 | return false; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
739 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
740 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
741 | // check if a polygon diagonal is locally inside the polygon |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
742 | template <typename N> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
743 | bool Earcut<N>::locallyInside(const Node* a, const Node* b) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
744 | return area(a->prev, a, a->next) < 0 ? |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
745 | area(a, b, a->next) >= 0 && area(a, a->prev, b) >= 0 : |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
746 | area(a, b, a->prev) < 0 || area(a, a->next, b) < 0; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
747 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
748 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
749 | // check if the middle Vertex of a polygon diagonal is inside the polygon |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
750 | template <typename N> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
751 | bool Earcut<N>::middleInside(const Node* a, const Node* b) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
752 | const Node* p = a; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
753 | bool inside = false; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
754 | double px = (a->x + b->x) / 2; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
755 | double py = (a->y + b->y) / 2; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
756 | do { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
757 | if (((p->y > py) != (p->next->y > py)) && p->next->y != p->y && |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
758 | (px < (p->next->x - p->x) * (py - p->y) / (p->next->y - p->y) + p->x)) |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
759 | inside = !inside; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
760 | p = p->next; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
761 | } while (p != a); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
762 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
763 | return inside; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
764 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
765 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
766 | // link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
767 | // polygon into two; if one belongs to the outer ring and another to a hole, it merges it into a |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
768 | // single ring |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
769 | template <typename N> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
770 | typename Earcut<N>::Node* |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
771 | Earcut<N>::splitPolygon(Node* a, Node* b) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
772 | Node* a2 = nodes.construct(a->i, a->x, a->y); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
773 | Node* b2 = nodes.construct(b->i, b->x, b->y); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
774 | Node* an = a->next; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
775 | Node* bp = b->prev; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
776 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
777 | a->next = b; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
778 | b->prev = a; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
779 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
780 | a2->next = an; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
781 | an->prev = a2; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
782 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
783 | b2->next = a2; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
784 | a2->prev = b2; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
785 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
786 | bp->next = b2; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
787 | b2->prev = bp; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
788 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
789 | return b2; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
790 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
791 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
792 | // create a node and util::optionally link it with previous one (in a circular doubly linked list) |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
793 | template <typename N> template <typename Point> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
794 | typename Earcut<N>::Node* |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
795 | Earcut<N>::insertNode(std::size_t i, const Point& pt, Node* last) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
796 | Node* p = nodes.construct(static_cast<N>(i), util::nth<0, Point>::get(pt), util::nth<1, Point>::get(pt)); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
797 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
798 | if (!last) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
799 | p->prev = p; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
800 | p->next = p; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
801 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
802 | } else { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
803 | assert(last); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
804 | p->next = last->next; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
805 | p->prev = last; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
806 | last->next->prev = p; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
807 | last->next = p; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
808 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
809 | return p; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
810 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
811 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
812 | template <typename N> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
813 | void Earcut<N>::removeNode(Node* p) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
814 | p->next->prev = p->prev; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
815 | p->prev->next = p->next; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
816 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
817 | if (p->prevZ) p->prevZ->nextZ = p->nextZ; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
818 | if (p->nextZ) p->nextZ->prevZ = p->prevZ; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
819 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
820 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
821 | |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
822 | template <typename N = uint32_t, typename Polygon> |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
823 | std::vector<N> earcut(const Polygon& poly) { |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
824 | mapbox::detail::Earcut<N> earcut; |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
825 | earcut(poly); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
826 | return std::move(earcut.indices); |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
827 | } |
ce81db996275
Use Mapbox's ear clipping algorithm to handle drawing any simple polygon
Teemu Piippo <teemu.s.piippo@gmail.com>
parents:
diff
changeset
|
828 | } |