rays 0.1.46 → 0.1.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.doc/ext/rays/bitmap.cpp +258 -0
- data/.doc/ext/rays/defs.cpp +3 -3
- data/.doc/ext/rays/painter.cpp +38 -3
- data/.doc/ext/rays/polygon.cpp +81 -4
- data/.doc/ext/rays/rays.cpp +11 -11
- data/.github/workflows/test.yml +0 -1
- data/ChangeLog.md +15 -0
- data/Rakefile +4 -4
- data/VERSION +1 -1
- data/ext/rays/bitmap.cpp +259 -0
- data/ext/rays/defs.cpp +3 -3
- data/ext/rays/painter.cpp +45 -8
- data/ext/rays/polygon.cpp +89 -4
- data/ext/rays/rays.cpp +11 -11
- data/include/rays/defs.h +26 -0
- data/include/rays/matrix.h +2 -0
- data/include/rays/painter.h +15 -1
- data/include/rays/polygon.h +6 -1
- data/include/rays/polyline.h +4 -0
- data/lib/rays/painter.rb +1 -1
- data/lib/rays/polygon.rb +36 -7
- data/rays.gemspec +2 -2
- data/src/color_space.cpp +2 -2
- data/src/matrix.cpp +8 -0
- data/src/painter.cpp +72 -5
- data/src/polygon.cpp +385 -91
- data/src/polyline.cpp +33 -18
- data/src/polyline.h +2 -2
- data/test/test_bitmap.rb +7 -0
- data/test/test_polygon.rb +2 -2
- data/test/test_polygon_line.rb +5 -5
- data/test/test_polyline.rb +7 -7
- metadata +6 -6
data/src/polygon.cpp
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
#include <math.h>
|
5
5
|
#include <assert.h>
|
6
6
|
#include <utility>
|
7
|
-
#include <
|
7
|
+
#include <earcut.hpp>
|
8
8
|
#include <Splines.h>
|
9
9
|
#include <xot/util.h>
|
10
10
|
#include "rays/color.h"
|
@@ -17,21 +17,170 @@
|
|
17
17
|
namespace clip = ClipperLib;
|
18
18
|
|
19
19
|
|
20
|
+
namespace mapbox
|
21
|
+
{
|
22
|
+
|
23
|
+
namespace util
|
24
|
+
{
|
25
|
+
|
26
|
+
template<>
|
27
|
+
struct nth<0, Rays::Point>
|
28
|
+
{
|
29
|
+
inline static auto get (const Rays::Point& p)
|
30
|
+
{
|
31
|
+
return p.x;
|
32
|
+
}
|
33
|
+
};
|
34
|
+
|
35
|
+
template<>
|
36
|
+
struct nth<1, Rays::Point>
|
37
|
+
{
|
38
|
+
inline static auto get (const Rays::Point& p)
|
39
|
+
{
|
40
|
+
return p.y;
|
41
|
+
}
|
42
|
+
};
|
43
|
+
|
44
|
+
}// util
|
45
|
+
|
46
|
+
}// mapbox
|
47
|
+
|
48
|
+
|
20
49
|
namespace Rays
|
21
50
|
{
|
22
51
|
|
23
52
|
|
24
|
-
|
25
|
-
to_poly2tri (const Point& point)
|
53
|
+
class Triangulator
|
26
54
|
{
|
27
|
-
return p2t::Point(point.x, point.y);
|
28
|
-
}
|
29
55
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
56
|
+
public:
|
57
|
+
|
58
|
+
Triangulator (size_t npoints)
|
59
|
+
{
|
60
|
+
points.reserve(npoints);
|
61
|
+
}
|
62
|
+
|
63
|
+
size_t begin (bool hole = false)
|
64
|
+
{
|
65
|
+
segments.emplace_back(points.size(), 0, hole);
|
66
|
+
return segments.back().begin;
|
67
|
+
}
|
68
|
+
|
69
|
+
void end (size_t n)
|
70
|
+
{
|
71
|
+
if (segments.empty())
|
72
|
+
invalid_state_error(__FILE__, __LINE__);
|
73
|
+
|
74
|
+
auto& seg = segments.back();
|
75
|
+
if (n != seg.begin)
|
76
|
+
argument_error(__FILE__, __LINE__);
|
77
|
+
|
78
|
+
seg.end = points.size();
|
79
|
+
|
80
|
+
if (seg.empty()) segments.pop_back();
|
81
|
+
}
|
82
|
+
|
83
|
+
void append (const Point& point)
|
84
|
+
{
|
85
|
+
points.emplace_back(point);
|
86
|
+
}
|
87
|
+
|
88
|
+
void triangulate ()
|
89
|
+
{
|
90
|
+
if (segments.empty()) return;
|
91
|
+
|
92
|
+
PolylineList polylines;
|
93
|
+
size_t index_offset = 0;
|
94
|
+
for (const auto& seg : segments)
|
95
|
+
{
|
96
|
+
Polyline polyline(&points[0] + seg.begin, seg.end - seg.begin);
|
97
|
+
if (!seg.hole)
|
98
|
+
{
|
99
|
+
triangulate(polylines, index_offset);
|
100
|
+
polylines.clear();
|
101
|
+
index_offset = seg.begin;
|
102
|
+
}
|
103
|
+
polylines.emplace_back(polyline);
|
104
|
+
}
|
105
|
+
triangulate(polylines, index_offset);
|
106
|
+
|
107
|
+
segments.clear();
|
108
|
+
segments.shrink_to_fit();
|
109
|
+
}
|
110
|
+
|
111
|
+
bool get_triangles (Polygon::TrianglePointList* triangles) const
|
112
|
+
{
|
113
|
+
if (indices.empty()) return false;
|
114
|
+
|
115
|
+
triangles->reserve(triangles->size() + indices.size());
|
116
|
+
for (const auto& index : indices)
|
117
|
+
triangles->emplace_back(points[index]);
|
118
|
+
return true;
|
119
|
+
}
|
120
|
+
|
121
|
+
private:
|
122
|
+
|
123
|
+
struct Segment
|
124
|
+
{
|
125
|
+
|
126
|
+
size_t begin, end;
|
127
|
+
|
128
|
+
bool hole;
|
129
|
+
|
130
|
+
Segment (size_t begin, size_t end, bool hole = false)
|
131
|
+
: begin(begin), end(end), hole(hole)
|
132
|
+
{
|
133
|
+
}
|
134
|
+
|
135
|
+
bool empty () const
|
136
|
+
{
|
137
|
+
return begin == end;
|
138
|
+
}
|
139
|
+
|
140
|
+
};// Segment
|
141
|
+
|
142
|
+
class Polyline
|
143
|
+
{
|
144
|
+
|
145
|
+
const Point* points;
|
146
|
+
|
147
|
+
size_t size_;
|
148
|
+
|
149
|
+
public:
|
150
|
+
|
151
|
+
typedef Point value_type;
|
152
|
+
|
153
|
+
Polyline (const Point* points, size_t size)
|
154
|
+
: points(points), size_(size)
|
155
|
+
{
|
156
|
+
}
|
157
|
+
|
158
|
+
size_t size () const {return size_;}
|
159
|
+
|
160
|
+
bool empty () const {return size_ == 0;}
|
161
|
+
|
162
|
+
const Point& operator [] (size_t i) const {return points[i];}
|
163
|
+
|
164
|
+
};// Polyline
|
165
|
+
|
166
|
+
typedef std::vector<Polyline> PolylineList;
|
167
|
+
|
168
|
+
std::vector<Segment> segments;
|
169
|
+
|
170
|
+
std::vector<Point> points;
|
171
|
+
|
172
|
+
std::vector<uint32_t> indices;
|
173
|
+
|
174
|
+
void triangulate (const PolylineList& polylines, size_t index_offset)
|
175
|
+
{
|
176
|
+
if (polylines.empty()) return;
|
177
|
+
|
178
|
+
auto result = mapbox::earcut<uint32_t>(polylines);
|
179
|
+
for (const auto& index : result)
|
180
|
+
indices.emplace_back(index_offset + index);
|
181
|
+
}
|
182
|
+
|
183
|
+
};// Triangulator
|
35
184
|
|
36
185
|
|
37
186
|
struct Polygon::Data
|
@@ -39,16 +188,40 @@ namespace Rays
|
|
39
188
|
|
40
189
|
LineList lines;
|
41
190
|
|
191
|
+
mutable std::unique_ptr<Bounds> pbounds;
|
192
|
+
|
193
|
+
mutable std::unique_ptr<Triangulator> ptriangulator;
|
194
|
+
|
42
195
|
virtual ~Data ()
|
43
196
|
{
|
44
197
|
}
|
45
198
|
|
199
|
+
const Bounds& bounds () const
|
200
|
+
{
|
201
|
+
if (!pbounds)
|
202
|
+
{
|
203
|
+
if (lines.empty())
|
204
|
+
pbounds.reset(new Bounds(-1, -1, -1));
|
205
|
+
else
|
206
|
+
{
|
207
|
+
pbounds.reset(new Bounds(lines[0][0], 0));
|
208
|
+
for (const auto& line : lines)
|
209
|
+
{
|
210
|
+
for (const auto& point : line)
|
211
|
+
*pbounds |= point;
|
212
|
+
}
|
213
|
+
}
|
214
|
+
}
|
215
|
+
return *pbounds;
|
216
|
+
}
|
217
|
+
|
46
218
|
void append (const Polyline& polyline, bool hole = false)
|
47
219
|
{
|
48
220
|
if (polyline.empty())
|
49
221
|
return;
|
50
222
|
|
51
|
-
lines.emplace_back(
|
223
|
+
lines.emplace_back(polyline, hole);
|
224
|
+
pbounds.reset();
|
52
225
|
}
|
53
226
|
|
54
227
|
void append (const Line& line)
|
@@ -57,48 +230,30 @@ namespace Rays
|
|
57
230
|
return;
|
58
231
|
|
59
232
|
lines.emplace_back(line);
|
233
|
+
pbounds.reset();
|
60
234
|
}
|
61
235
|
|
62
236
|
bool triangulate (TrianglePointList* triangles) const
|
63
237
|
{
|
64
238
|
assert(triangles);
|
65
239
|
|
66
|
-
|
67
|
-
|
68
|
-
if (!can_triangulate())
|
69
|
-
return false;
|
70
|
-
|
71
|
-
size_t npoint = count_points();
|
72
|
-
if (npoint <= 0)
|
73
|
-
return true;
|
74
|
-
|
75
|
-
std::unique_ptr<p2t::CDT> cdt;
|
76
|
-
std::vector<p2t::Point> points;
|
77
|
-
std::vector<p2t::Point*> pointers;
|
78
|
-
|
79
|
-
points.reserve(npoint);
|
80
|
-
for (const auto& line : lines)
|
240
|
+
if (!ptriangulator)
|
81
241
|
{
|
82
|
-
|
83
|
-
|
84
|
-
for (const auto& point : line)
|
85
|
-
{
|
86
|
-
points.emplace_back(to_poly2tri(point));
|
87
|
-
pointers.emplace_back(&points.back());
|
88
|
-
}
|
242
|
+
ptriangulator.reset(new Triangulator(count_points_for_triangulation()));
|
243
|
+
auto& t = *ptriangulator;
|
89
244
|
|
90
|
-
|
245
|
+
for (const auto& line : lines)
|
91
246
|
{
|
92
|
-
|
93
|
-
|
247
|
+
size_t n = t.begin(line.hole());
|
248
|
+
for (const auto& point : line)
|
249
|
+
t.append(point);
|
250
|
+
t.end(n);
|
94
251
|
}
|
95
|
-
|
96
|
-
cdt->AddHole(pointers);
|
252
|
+
t.triangulate();
|
97
253
|
}
|
98
254
|
|
99
|
-
|
100
|
-
|
101
|
-
return true;
|
255
|
+
triangles->clear();
|
256
|
+
return ptriangulator->get_triangles(triangles);
|
102
257
|
}
|
103
258
|
|
104
259
|
virtual void fill (Painter* painter, const Color& color) const = 0;
|
@@ -110,47 +265,35 @@ namespace Rays
|
|
110
265
|
|
111
266
|
coord stroke_width = painter->stroke_width();
|
112
267
|
if (stroke_width > 0)
|
113
|
-
|
268
|
+
{
|
269
|
+
stroke_with_width(
|
270
|
+
polygon, painter, color, stroke_width, painter->stroke_outset());
|
271
|
+
}
|
114
272
|
else
|
115
273
|
stroke_without_width(painter, color);
|
116
274
|
}
|
117
275
|
|
118
276
|
private:
|
119
277
|
|
120
|
-
|
278
|
+
size_t count_points_for_triangulation () const
|
121
279
|
{
|
280
|
+
size_t count = 0;
|
122
281
|
for (const auto& line : lines)
|
123
282
|
{
|
124
|
-
if (
|
125
|
-
|
283
|
+
if (can_triangulate(line))
|
284
|
+
count += line.size();
|
126
285
|
}
|
127
|
-
return false;
|
128
|
-
}
|
129
|
-
|
130
|
-
size_t count_points () const
|
131
|
-
{
|
132
|
-
size_t count = 0;
|
133
|
-
for (const auto& line : lines)
|
134
|
-
count += line.size();
|
135
286
|
return count;
|
136
287
|
}
|
137
288
|
|
138
|
-
|
289
|
+
bool can_triangulate (const Line& line) const
|
139
290
|
{
|
140
|
-
|
141
|
-
|
142
|
-
cdt->Triangulate();
|
143
|
-
|
144
|
-
for (auto* triangle : cdt->GetTriangles())
|
145
|
-
{
|
146
|
-
for (int i = 0; i < 3; ++i)
|
147
|
-
triangles->emplace_back(from_poly2tri(*triangle->GetPoint(i)));
|
148
|
-
}
|
291
|
+
return (line.fill() || line.hole()) && line.size() >= 3;
|
149
292
|
}
|
150
293
|
|
151
294
|
void stroke_with_width (
|
152
295
|
const Polygon& polygon, Painter* painter,
|
153
|
-
const Color& color, coord stroke_width) const
|
296
|
+
const Color& color, coord stroke_width, float stroke_outset) const
|
154
297
|
{
|
155
298
|
assert(painter && color && stroke_width > 0);
|
156
299
|
|
@@ -163,30 +306,45 @@ namespace Rays
|
|
163
306
|
bool has_loop = false;
|
164
307
|
for (const auto& polyline : polygon)
|
165
308
|
{
|
166
|
-
if (!polyline || polyline.empty())
|
167
|
-
continue;
|
168
|
-
|
169
309
|
if (polyline.loop())
|
170
310
|
{
|
171
311
|
has_loop = true;
|
172
312
|
continue;
|
173
313
|
}
|
314
|
+
stroke_polyline(polyline, painter, color, stroke_width, cap, join, ml);
|
315
|
+
}
|
174
316
|
|
175
|
-
|
176
|
-
if (!polyline.expand(&stroke, stroke_width / 2, cap, join, ml))
|
177
|
-
continue;
|
317
|
+
if (!has_loop) return;
|
178
318
|
|
179
|
-
|
180
|
-
|
319
|
+
coord inset = (-0.5 + stroke_outset) * stroke_width;
|
320
|
+
Polygon outline;
|
321
|
+
if (inset == 0)
|
322
|
+
outline = polygon;
|
323
|
+
else if (!polygon.expand(&outline, inset, cap, join, ml))
|
324
|
+
return;
|
181
325
|
|
182
|
-
|
326
|
+
for (const auto& polyline : outline)
|
183
327
|
{
|
184
|
-
|
185
|
-
|
186
|
-
Polygon_fill(polygon - hole, painter, color);
|
328
|
+
if (polyline.loop())
|
329
|
+
stroke_polyline(polyline, painter, color, stroke_width, cap, join, ml);
|
187
330
|
}
|
188
331
|
}
|
189
332
|
|
333
|
+
void stroke_polyline (
|
334
|
+
const Polyline& polyline, Painter* painter,
|
335
|
+
const Color& color, coord stroke_width,
|
336
|
+
CapType cap, JoinType join, coord miter_limit) const
|
337
|
+
{
|
338
|
+
assert(stroke_width > 0);
|
339
|
+
|
340
|
+
if (!polyline || polyline.empty())
|
341
|
+
return;
|
342
|
+
|
343
|
+
Polygon stroke;
|
344
|
+
if (polyline.expand(&stroke, stroke_width / 2, cap, join, miter_limit))
|
345
|
+
Polygon_fill(stroke, painter, color);
|
346
|
+
}
|
347
|
+
|
190
348
|
void stroke_without_width (Painter* painter, const Color& color) const
|
191
349
|
{
|
192
350
|
assert(painter && color);
|
@@ -746,7 +904,7 @@ namespace Rays
|
|
746
904
|
|
747
905
|
if (!has_hole)
|
748
906
|
{
|
749
|
-
points.emplace_back(
|
907
|
+
points.emplace_back(x + width / 2, y + height / 2);
|
750
908
|
mode = GL_TRIANGLE_FAN;
|
751
909
|
}
|
752
910
|
|
@@ -788,6 +946,130 @@ namespace Rays
|
|
788
946
|
};// EllipseData
|
789
947
|
|
790
948
|
|
949
|
+
static const char*
|
950
|
+
get_draw_mode_name (DrawMode mode)
|
951
|
+
{
|
952
|
+
switch (mode)
|
953
|
+
{
|
954
|
+
case DRAW_POINTS: return "DRAW_POINTS";
|
955
|
+
case DRAW_LINES: return "DRAW_LINES";
|
956
|
+
case DRAW_LINE_STRIP: return "DRAW_LINE_STRIP";
|
957
|
+
case DRAW_TRIANGLES: return "DRAW_TRIANGLES";
|
958
|
+
case DRAW_TRIANGLE_STRIP: return "DRAW_TRIANGLE_STRIP";
|
959
|
+
case DRAW_TRIANGLE_FAN: return "DRAW_TRIANGLE_FAN";
|
960
|
+
case DRAW_QUADS: return "DRAW_QUADS";
|
961
|
+
case DRAW_QUAD_STRIP: return "DRAW_QUAD_STRIP";
|
962
|
+
case DRAW_POLYGON: return "DRAW_POLYGON";
|
963
|
+
default: argument_error(__FILE__, __LINE__, "unknown draw mode");
|
964
|
+
}
|
965
|
+
}
|
966
|
+
|
967
|
+
static void
|
968
|
+
create_polygon (Polygon* polygon, const Point* points, size_t size, bool loop)
|
969
|
+
{
|
970
|
+
polygon->self->append(Polyline(points, size, loop, true));
|
971
|
+
}
|
972
|
+
|
973
|
+
static void
|
974
|
+
create_points (Polygon* polygon, const Point* points, size_t size)
|
975
|
+
{
|
976
|
+
for (size_t i = 0; i < size; ++i)
|
977
|
+
polygon->self->append(Polyline(&points[i], 1, false, false));
|
978
|
+
}
|
979
|
+
|
980
|
+
static void
|
981
|
+
create_lines (Polygon* polygon, const Point* points, size_t size)
|
982
|
+
{
|
983
|
+
for (size_t i = 0; i + 1 < size; i += 2)
|
984
|
+
polygon->self->append(Polyline(&points[i], 2, false, false));
|
985
|
+
}
|
986
|
+
|
987
|
+
static void
|
988
|
+
create_line_strip (
|
989
|
+
Polygon* polygon, const Point* points, size_t size, bool loop)
|
990
|
+
{
|
991
|
+
if (!loop || size < 3)
|
992
|
+
polygon->self->append(Polyline(points, size, loop, false));
|
993
|
+
else
|
994
|
+
{
|
995
|
+
std::vector<Point> array;
|
996
|
+
array.reserve(size + 1);
|
997
|
+
array.insert(array.begin(), points, points + size);
|
998
|
+
array.emplace_back(points[0]);
|
999
|
+
polygon->self->append(Polyline(&array[0], array.size(), true, false));
|
1000
|
+
}
|
1001
|
+
}
|
1002
|
+
|
1003
|
+
static void
|
1004
|
+
create_triangles (
|
1005
|
+
Polygon* polygon, const Point* points, size_t size, bool loop)
|
1006
|
+
{
|
1007
|
+
for (size_t i = 0; i + 2 < size; i += 3)
|
1008
|
+
polygon->self->append(Polyline(&points[i], 3, loop, true));
|
1009
|
+
}
|
1010
|
+
|
1011
|
+
static void
|
1012
|
+
create_triangle_strip (Polygon* polygon, const Point* points, size_t size)
|
1013
|
+
{
|
1014
|
+
if (size < 3) return;
|
1015
|
+
|
1016
|
+
size_t last = size - 1;
|
1017
|
+
size_t in_last = last % 2 == 0 ? last - 1 : last;
|
1018
|
+
size_t out_last = last % 2 == 0 ? last : last - 1;
|
1019
|
+
|
1020
|
+
std::vector<Point> array;
|
1021
|
+
array.emplace_back(points[0]);
|
1022
|
+
for (size_t i = 1; i <= in_last; i += 2)
|
1023
|
+
array.emplace_back(points[i]);
|
1024
|
+
for (size_t i = out_last; i >= 2; i -= 2)
|
1025
|
+
array.emplace_back(points[i]);
|
1026
|
+
|
1027
|
+
polygon->self->append(Polyline(&array[0], array.size(), true));
|
1028
|
+
if (size >= 4)
|
1029
|
+
polygon->self->append(Polyline(&points[1], size - 2));
|
1030
|
+
}
|
1031
|
+
|
1032
|
+
static void
|
1033
|
+
create_triangle_fan (Polygon* polygon, const Point* points, size_t size)
|
1034
|
+
{
|
1035
|
+
create_polygon(polygon, points, size, true);
|
1036
|
+
|
1037
|
+
Point array[2];
|
1038
|
+
array[0] = points[0];
|
1039
|
+
for (size_t i = 2; i < size - 1; ++i)
|
1040
|
+
{
|
1041
|
+
array[1] = points[i];
|
1042
|
+
polygon->self->append(Polyline(&array[0], 2));
|
1043
|
+
}
|
1044
|
+
}
|
1045
|
+
|
1046
|
+
static void
|
1047
|
+
create_quads (Polygon* polygon, const Point* points, size_t size, bool loop)
|
1048
|
+
{
|
1049
|
+
for (size_t i = 0; i + 3 < size; i += 4)
|
1050
|
+
polygon->self->append(Polyline(&points[i], 4, loop, true));
|
1051
|
+
}
|
1052
|
+
|
1053
|
+
static void
|
1054
|
+
create_quad_strip (Polygon* polygon, const Point* points, size_t size)
|
1055
|
+
{
|
1056
|
+
if (size < 4) return;
|
1057
|
+
|
1058
|
+
if (size % 2 != 0) --size;
|
1059
|
+
size_t in_last = size - 2;
|
1060
|
+
size_t out_last = size - 1;
|
1061
|
+
|
1062
|
+
std::vector<Point> array;
|
1063
|
+
for (size_t i = 0; i <= in_last; i += 2)
|
1064
|
+
array.emplace_back(points[i]);
|
1065
|
+
for (int i = (int) out_last; i >= 1; i -= 2)
|
1066
|
+
array.emplace_back(points[i]);
|
1067
|
+
|
1068
|
+
polygon->self->append(Polyline(&array[0], array.size(), true));
|
1069
|
+
for (size_t i = 2; i < in_last; i += 2)
|
1070
|
+
polygon->self->append(Polyline(&points[i], 2));
|
1071
|
+
}
|
1072
|
+
|
791
1073
|
Polygon
|
792
1074
|
create_line (coord x1, coord y1, coord x2, coord y2)
|
793
1075
|
{
|
@@ -1069,7 +1351,30 @@ namespace Rays
|
|
1069
1351
|
{
|
1070
1352
|
if (!points || size <= 0) return;
|
1071
1353
|
|
1072
|
-
|
1354
|
+
create_polygon(this, points, size, loop);
|
1355
|
+
}
|
1356
|
+
|
1357
|
+
Polygon::Polygon (DrawMode mode, const Point* points, size_t size, bool loop)
|
1358
|
+
: self(new PolygonData())
|
1359
|
+
{
|
1360
|
+
if (!points || size <= 0) return;
|
1361
|
+
|
1362
|
+
switch (mode)
|
1363
|
+
{
|
1364
|
+
case DRAW_POINTS: create_points( this, points, size); break;
|
1365
|
+
case DRAW_LINES: create_lines( this, points, size); break;
|
1366
|
+
case DRAW_LINE_STRIP: create_line_strip( this, points, size, loop); break;
|
1367
|
+
case DRAW_TRIANGLES: create_triangles( this, points, size, loop); break;
|
1368
|
+
case DRAW_TRIANGLE_STRIP: create_triangle_strip(this, points, size); break;
|
1369
|
+
case DRAW_TRIANGLE_FAN: create_triangle_fan( this, points, size); break;
|
1370
|
+
case DRAW_QUADS: create_quads( this, points, size, loop); break;
|
1371
|
+
case DRAW_QUAD_STRIP: create_quad_strip( this, points, size); break;
|
1372
|
+
case DRAW_POLYGON: create_polygon( this, points, size, loop); break;
|
1373
|
+
default:
|
1374
|
+
argument_error(
|
1375
|
+
__FILE__, __LINE__,
|
1376
|
+
Xot::stringf("unknown draw mode '%s'", get_draw_mode_name(mode)));
|
1377
|
+
}
|
1073
1378
|
}
|
1074
1379
|
|
1075
1380
|
Polygon::Polygon (const Polyline& polyline)
|
@@ -1107,15 +1412,7 @@ namespace Rays
|
|
1107
1412
|
Bounds
|
1108
1413
|
Polygon::bounds () const
|
1109
1414
|
{
|
1110
|
-
|
1111
|
-
|
1112
|
-
Bounds b(self->lines[0][0], 0);
|
1113
|
-
for (const auto& line : *this)
|
1114
|
-
{
|
1115
|
-
for (const auto& point : line)
|
1116
|
-
b |= point;
|
1117
|
-
}
|
1118
|
-
return b;
|
1415
|
+
return self->bounds();
|
1119
1416
|
}
|
1120
1417
|
|
1121
1418
|
size_t
|
@@ -1248,10 +1545,7 @@ namespace Rays
|
|
1248
1545
|
|
1249
1546
|
Polygon::Line::operator bool () const
|
1250
1547
|
{
|
1251
|
-
|
1252
|
-
return false;
|
1253
|
-
|
1254
|
-
return loop() || !hole();
|
1548
|
+
return Super::operator bool() && (loop() || !hole());
|
1255
1549
|
}
|
1256
1550
|
|
1257
1551
|
bool
|
data/src/polyline.cpp
CHANGED
@@ -17,21 +17,24 @@ namespace Rays
|
|
17
17
|
|
18
18
|
PointList points;
|
19
19
|
|
20
|
-
bool loop = false;
|
20
|
+
bool loop = false, fill = false;
|
21
21
|
|
22
22
|
template <typename I, typename FUN>
|
23
|
-
void reset (I begin, I end, bool loop_, FUN to_point_fun)
|
23
|
+
void reset (I begin, I end, bool loop_, bool fill_, FUN to_point_fun)
|
24
24
|
{
|
25
|
-
|
26
|
-
if (0 < size && size < 3 && loop_)
|
25
|
+
if (begin > end)
|
27
26
|
argument_error(__FILE__, __LINE__);
|
28
27
|
|
29
28
|
points.clear();
|
29
|
+
loop = loop_;
|
30
|
+
fill = fill_;
|
31
|
+
|
32
|
+
size_t size = end - begin;
|
33
|
+
if (size <= 0) return;
|
34
|
+
|
30
35
|
points.reserve(size);
|
31
36
|
for (auto it = begin; it != end; ++it)
|
32
37
|
points.emplace_back(to_point_fun(*it));
|
33
|
-
|
34
|
-
loop = loop_ && size > 0;
|
35
38
|
}
|
36
39
|
|
37
40
|
};// Polyline::Data
|
@@ -39,18 +42,16 @@ namespace Rays
|
|
39
42
|
|
40
43
|
void
|
41
44
|
Polyline_create (
|
42
|
-
Polyline* polyline, const Path& path, bool loop, bool
|
45
|
+
Polyline* polyline, const Path& path, bool loop, bool hole)
|
43
46
|
{
|
44
|
-
assert(polyline);
|
45
|
-
|
46
47
|
Path cleaned;
|
47
48
|
ClipperLib::CleanPolygon(path, cleaned);
|
48
49
|
|
49
|
-
auto
|
50
|
-
if (
|
51
|
-
polyline->self->reset(cleaned.rbegin(), cleaned.rend(), loop,
|
50
|
+
auto fun = [](const IntPoint& point) {return from_clipper(point);};
|
51
|
+
if (hole)
|
52
|
+
polyline->self->reset(cleaned.rbegin(), cleaned.rend(), loop, loop, fun);
|
52
53
|
else
|
53
|
-
polyline->self->reset(cleaned. begin(), cleaned. end(), loop,
|
54
|
+
polyline->self->reset(cleaned. begin(), cleaned. end(), loop, loop, fun);
|
54
55
|
}
|
55
56
|
|
56
57
|
template <typename I>
|
@@ -63,12 +64,12 @@ namespace Rays
|
|
63
64
|
}
|
64
65
|
|
65
66
|
void
|
66
|
-
Polyline_get_path (Path* path, const Polyline& polyline, bool
|
67
|
+
Polyline_get_path (Path* path, const Polyline& polyline, bool hole)
|
67
68
|
{
|
68
69
|
assert(path);
|
69
70
|
|
70
71
|
const auto& points = polyline.self->points;
|
71
|
-
if (
|
72
|
+
if (hole)
|
72
73
|
reset_path(path, points.rbegin(), points.rend());
|
73
74
|
else
|
74
75
|
reset_path(path, points. begin(), points. end());
|
@@ -81,7 +82,16 @@ namespace Rays
|
|
81
82
|
|
82
83
|
Polyline::Polyline (const Point* points, size_t size, bool loop)
|
83
84
|
{
|
84
|
-
self->reset(
|
85
|
+
self->reset(
|
86
|
+
points, points + size, loop, loop,
|
87
|
+
[](const Point& p) {return p;});
|
88
|
+
}
|
89
|
+
|
90
|
+
Polyline::Polyline (const Point* points, size_t size, bool loop, bool fill)
|
91
|
+
{
|
92
|
+
self->reset(
|
93
|
+
points, points + size, loop, fill,
|
94
|
+
[](const Point& p) {return p;});
|
85
95
|
}
|
86
96
|
|
87
97
|
Polyline::~Polyline ()
|
@@ -114,6 +124,12 @@ namespace Rays
|
|
114
124
|
return self->loop;
|
115
125
|
}
|
116
126
|
|
127
|
+
bool
|
128
|
+
Polyline::fill () const
|
129
|
+
{
|
130
|
+
return self->fill;
|
131
|
+
}
|
132
|
+
|
117
133
|
size_t
|
118
134
|
Polyline::size () const
|
119
135
|
{
|
@@ -146,8 +162,7 @@ namespace Rays
|
|
146
162
|
|
147
163
|
Polyline::operator bool () const
|
148
164
|
{
|
149
|
-
|
150
|
-
return !((s == 1 || s == 2) && self->loop);
|
165
|
+
return true;
|
151
166
|
}
|
152
167
|
|
153
168
|
bool
|