rays 0.1.46 → 0.1.48
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 +499 -0
- data/.doc/ext/rays/camera.cpp +2 -2
- data/.doc/ext/rays/defs.cpp +35 -11
- data/.doc/ext/rays/font.cpp +50 -2
- data/.doc/ext/rays/native.cpp +2 -4
- data/.doc/ext/rays/painter.cpp +111 -6
- data/.doc/ext/rays/polygon.cpp +152 -41
- data/.doc/ext/rays/polyline.cpp +89 -10
- data/.doc/ext/rays/rays.cpp +91 -11
- data/.doc/ext/rays/{noise.cpp → util.cpp} +2 -2
- data/.github/workflows/test.yml +0 -1
- data/ChangeLog.md +38 -0
- data/Rakefile +4 -4
- data/VERSION +1 -1
- data/ext/rays/bitmap.cpp +501 -0
- data/ext/rays/camera.cpp +2 -2
- data/ext/rays/defs.cpp +35 -11
- data/ext/rays/defs.h +56 -3
- data/ext/rays/font.cpp +56 -4
- data/ext/rays/native.cpp +2 -4
- data/ext/rays/painter.cpp +125 -11
- data/ext/rays/polygon.cpp +161 -41
- data/ext/rays/polyline.cpp +95 -9
- data/ext/rays/rays.cpp +91 -11
- data/ext/rays/{noise.cpp → util.cpp} +2 -2
- data/include/rays/defs.h +24 -0
- data/include/rays/font.h +17 -3
- data/include/rays/matrix.h +2 -0
- data/include/rays/painter.h +29 -1
- data/include/rays/polygon.h +57 -33
- data/include/rays/polyline.h +20 -1
- data/include/rays/ruby/polygon.h +0 -11
- data/include/rays/ruby/rays.h +4 -0
- data/include/rays/{noise.h → util.h} +2 -2
- data/lib/rays/color.rb +1 -1
- data/lib/rays/font.rb +1 -1
- data/lib/rays/image.rb +1 -1
- data/lib/rays/painter.rb +13 -2
- data/lib/rays/point.rb +1 -1
- data/lib/rays/polygon.rb +54 -16
- data/lib/rays/polyline.rb +54 -8
- data/lib/rays.rb +0 -1
- data/rays.gemspec +2 -2
- data/src/color_space.cpp +2 -2
- data/src/font.cpp +24 -2
- data/src/font.h +8 -1
- data/src/ios/font.mm +88 -27
- data/src/matrix.cpp +8 -0
- data/src/osx/font.mm +90 -28
- data/src/osx/helper.h +2 -2
- data/src/osx/helper.mm +2 -2
- data/src/painter.cpp +227 -90
- data/src/painter.h +11 -3
- data/src/polygon.cpp +588 -205
- data/src/polyline.cpp +154 -28
- data/src/polyline.h +3 -5
- data/src/shader.cpp +36 -4
- data/src/shader.h +1 -1
- data/src/texture.cpp +2 -2
- data/src/{noise.cpp → util.cpp} +1 -1
- data/src/win32/font.cpp +1 -1
- data/test/test_bitmap.rb +16 -2
- data/test/test_color.rb +4 -0
- data/test/test_font.rb +20 -2
- data/test/test_image.rb +18 -18
- data/test/test_point.rb +1 -1
- data/test/test_polygon.rb +52 -45
- data/test/test_polyline.rb +191 -72
- metadata +11 -17
- data/.doc/ext/rays/polygon_line.cpp +0 -97
- data/ext/rays/polygon_line.cpp +0 -100
- data/lib/rays/polygon_line.rb +0 -33
- data/test/test_polygon_line.rb +0 -164
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,91 +17,269 @@
|
|
17
17
|
namespace clip = ClipperLib;
|
18
18
|
|
19
19
|
|
20
|
-
namespace
|
20
|
+
namespace mapbox
|
21
21
|
{
|
22
22
|
|
23
|
-
|
24
|
-
static inline p2t::Point
|
25
|
-
to_poly2tri (const Point& point)
|
23
|
+
namespace util
|
26
24
|
{
|
27
|
-
return p2t::Point(point.x, point.y);
|
28
|
-
}
|
29
25
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
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
|
+
};
|
35
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
|
+
};
|
36
43
|
|
37
|
-
|
44
|
+
}// util
|
45
|
+
|
46
|
+
}// mapbox
|
47
|
+
|
48
|
+
|
49
|
+
namespace Rays
|
50
|
+
{
|
51
|
+
|
52
|
+
|
53
|
+
class Triangles
|
38
54
|
{
|
39
55
|
|
40
|
-
|
56
|
+
public:
|
41
57
|
|
42
|
-
|
43
|
-
|
44
|
-
|
58
|
+
Triangles (size_t npoints)
|
59
|
+
{
|
60
|
+
points.reserve(npoints);
|
61
|
+
}
|
45
62
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
return;
|
63
|
+
void append (const Polyline& polyline)
|
64
|
+
{
|
65
|
+
if (polyline.empty()) return;
|
50
66
|
|
51
|
-
|
52
|
-
|
67
|
+
const Point* points_ = polyline.points();
|
68
|
+
const Color* colors_ = polyline.colors();
|
69
|
+
const Coord3* texcoords_ = polyline.texcoords();
|
70
|
+
if (!points_)
|
71
|
+
argument_error(__FILE__, __LINE__);
|
53
72
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
73
|
+
if (
|
74
|
+
!points.empty() &&
|
75
|
+
(!colors_ != !pcolors || !texcoords_ != !ptexcoords))
|
76
|
+
{
|
77
|
+
argument_error(__FILE__, __LINE__);
|
78
|
+
}
|
58
79
|
|
59
|
-
|
60
|
-
|
80
|
+
segments.emplace_back(points.size(), 0, polyline.hole());
|
81
|
+
points.insert(points.end(), points_, points_ + polyline.size());
|
82
|
+
segments.back().end = points.size();
|
61
83
|
|
62
|
-
|
63
|
-
|
64
|
-
|
84
|
+
if (colors_)
|
85
|
+
{
|
86
|
+
if (!pcolors)
|
87
|
+
{
|
88
|
+
pcolors.reset(new decltype(pcolors)::element_type());
|
89
|
+
pcolors->reserve(points.capacity());
|
90
|
+
}
|
91
|
+
pcolors->insert(pcolors->end(), colors_, colors_ + polyline.size());
|
92
|
+
}
|
65
93
|
|
66
|
-
|
94
|
+
if (texcoords_)
|
95
|
+
{
|
96
|
+
if (!ptexcoords)
|
97
|
+
{
|
98
|
+
ptexcoords.reset(new decltype(ptexcoords)::element_type());
|
99
|
+
ptexcoords->reserve(points.capacity());
|
100
|
+
}
|
101
|
+
ptexcoords->insert(
|
102
|
+
ptexcoords->end(), texcoords_, texcoords_ + polyline.size());
|
103
|
+
}
|
104
|
+
}
|
67
105
|
|
68
|
-
|
69
|
-
|
106
|
+
bool get (Polygon::TrianglePointList* triangles) const
|
107
|
+
{
|
108
|
+
triangulate();
|
109
|
+
if (indices.empty()) return false;
|
70
110
|
|
71
|
-
|
72
|
-
|
111
|
+
triangles->reserve(triangles->size() + indices.size());
|
112
|
+
for (const auto& index : indices)
|
113
|
+
triangles->emplace_back(points[index]);
|
73
114
|
return true;
|
115
|
+
}
|
116
|
+
|
117
|
+
void draw (Painter* painter, const Color& color) const
|
118
|
+
{
|
119
|
+
triangulate();
|
120
|
+
if (indices.empty()) return;
|
121
|
+
|
122
|
+
if (pcolors)
|
123
|
+
{
|
124
|
+
Painter_draw(
|
125
|
+
painter, GL_TRIANGLES,
|
126
|
+
&points[0], points.size(),
|
127
|
+
&indices[0], indices.size(),
|
128
|
+
&(*pcolors)[0],
|
129
|
+
ptexcoords ? &(*ptexcoords)[0] : NULL);
|
130
|
+
}
|
131
|
+
else
|
132
|
+
{
|
133
|
+
Painter_draw(
|
134
|
+
painter, GL_TRIANGLES, color,
|
135
|
+
&points[0], points.size(),
|
136
|
+
&indices[0], indices.size(),
|
137
|
+
ptexcoords ? &(*ptexcoords)[0] : NULL);
|
138
|
+
}
|
139
|
+
}
|
74
140
|
|
75
|
-
|
76
|
-
std::vector<p2t::Point> points;
|
77
|
-
std::vector<p2t::Point*> pointers;
|
141
|
+
private:
|
78
142
|
|
79
|
-
|
80
|
-
for (const auto& line : lines)
|
143
|
+
struct Segment
|
81
144
|
{
|
82
|
-
|
83
|
-
|
84
|
-
|
145
|
+
|
146
|
+
size_t begin, end;
|
147
|
+
|
148
|
+
bool hole;
|
149
|
+
|
150
|
+
Segment (size_t begin, size_t end, bool hole = false)
|
151
|
+
: begin(begin), end(end), hole(hole)
|
85
152
|
{
|
86
|
-
points.emplace_back(to_poly2tri(point));
|
87
|
-
pointers.emplace_back(&points.back());
|
88
153
|
}
|
89
154
|
|
90
|
-
|
155
|
+
bool empty () const
|
91
156
|
{
|
92
|
-
|
93
|
-
cdt.reset(new p2t::CDT(pointers));
|
157
|
+
return begin == end;
|
94
158
|
}
|
95
|
-
|
96
|
-
|
159
|
+
|
160
|
+
};// Segment
|
161
|
+
|
162
|
+
class Polyline
|
163
|
+
{
|
164
|
+
|
165
|
+
const Point* points;
|
166
|
+
|
167
|
+
size_t size_;
|
168
|
+
|
169
|
+
public:
|
170
|
+
|
171
|
+
typedef Point value_type;
|
172
|
+
|
173
|
+
Polyline (const Point* points, size_t size)
|
174
|
+
: points(points), size_(size)
|
175
|
+
{
|
176
|
+
}
|
177
|
+
|
178
|
+
size_t size () const {return size_;}
|
179
|
+
|
180
|
+
bool empty () const {return size_ == 0;}
|
181
|
+
|
182
|
+
const Point& operator [] (size_t i) const {return points[i];}
|
183
|
+
|
184
|
+
};// Polyline
|
185
|
+
|
186
|
+
typedef std::vector<Polyline> PolylineList;
|
187
|
+
|
188
|
+
std::vector<Point> points;
|
189
|
+
|
190
|
+
std::unique_ptr<std::vector<Color>> pcolors;
|
191
|
+
|
192
|
+
std::unique_ptr<std::vector<Coord3>> ptexcoords;
|
193
|
+
|
194
|
+
mutable std::vector<Segment> segments;
|
195
|
+
|
196
|
+
mutable std::vector<uint32_t> indices;
|
197
|
+
|
198
|
+
void triangulate () const
|
199
|
+
{
|
200
|
+
if (segments.empty()) return;
|
201
|
+
|
202
|
+
PolylineList polylines;
|
203
|
+
size_t index_offset = 0;
|
204
|
+
for (const auto& seg : segments)
|
205
|
+
{
|
206
|
+
Polyline polyline(&points[0] + seg.begin, seg.end - seg.begin);
|
207
|
+
if (!seg.hole)
|
208
|
+
{
|
209
|
+
triangulate(polylines, index_offset);
|
210
|
+
polylines.clear();
|
211
|
+
index_offset = seg.begin;
|
212
|
+
}
|
213
|
+
polylines.emplace_back(polyline);
|
214
|
+
}
|
215
|
+
triangulate(polylines, index_offset);
|
216
|
+
|
217
|
+
segments.clear();
|
218
|
+
segments.shrink_to_fit();
|
97
219
|
}
|
98
220
|
|
99
|
-
|
221
|
+
void triangulate (const PolylineList& polylines, size_t index_offset) const
|
222
|
+
{
|
223
|
+
if (polylines.empty()) return;
|
100
224
|
|
101
|
-
|
225
|
+
auto result = mapbox::earcut<uint32_t>(polylines);
|
226
|
+
for (const auto& index : result)
|
227
|
+
indices.emplace_back(index_offset + index);
|
228
|
+
}
|
229
|
+
|
230
|
+
};// Triangles
|
231
|
+
|
232
|
+
|
233
|
+
struct Polygon::Data
|
234
|
+
{
|
235
|
+
|
236
|
+
PolylineList polylines;
|
237
|
+
|
238
|
+
mutable std::unique_ptr<Bounds> pbounds;
|
239
|
+
|
240
|
+
mutable std::unique_ptr<Triangles> ptriangles;
|
241
|
+
|
242
|
+
virtual ~Data ()
|
243
|
+
{
|
102
244
|
}
|
103
245
|
|
104
|
-
|
246
|
+
const Bounds& bounds () const
|
247
|
+
{
|
248
|
+
if (!pbounds)
|
249
|
+
{
|
250
|
+
if (polylines.empty())
|
251
|
+
pbounds.reset(new Bounds(-1, -1, -1));
|
252
|
+
else
|
253
|
+
{
|
254
|
+
pbounds.reset(new Bounds(polylines[0][0], 0));
|
255
|
+
for (const auto& polyline : polylines)
|
256
|
+
{
|
257
|
+
for (const auto& point : polyline)
|
258
|
+
*pbounds |= point;
|
259
|
+
}
|
260
|
+
}
|
261
|
+
}
|
262
|
+
return *pbounds;
|
263
|
+
}
|
264
|
+
|
265
|
+
void append (const Polyline& polyline)
|
266
|
+
{
|
267
|
+
if (polyline.empty())
|
268
|
+
return;
|
269
|
+
|
270
|
+
polylines.emplace_back(polyline);
|
271
|
+
}
|
272
|
+
|
273
|
+
bool triangulate (TrianglePointList* triangles) const
|
274
|
+
{
|
275
|
+
triangles->clear();
|
276
|
+
return this->triangles().get(triangles);
|
277
|
+
}
|
278
|
+
|
279
|
+
virtual void fill (Painter* painter, const Color& color) const
|
280
|
+
{
|
281
|
+
triangles().draw(painter, color);
|
282
|
+
}
|
105
283
|
|
106
284
|
virtual void stroke (
|
107
285
|
const Polygon& polygon, Painter* painter, const Color& color) const
|
@@ -110,47 +288,46 @@ namespace Rays
|
|
110
288
|
|
111
289
|
coord stroke_width = painter->stroke_width();
|
112
290
|
if (stroke_width > 0)
|
113
|
-
|
291
|
+
{
|
292
|
+
stroke_with_width(
|
293
|
+
polygon, painter, color, stroke_width, painter->stroke_outset());
|
294
|
+
}
|
114
295
|
else
|
115
296
|
stroke_without_width(painter, color);
|
116
297
|
}
|
117
298
|
|
118
299
|
private:
|
119
300
|
|
120
|
-
|
301
|
+
Triangles& triangles () const
|
121
302
|
{
|
122
|
-
|
303
|
+
if (!ptriangles)
|
123
304
|
{
|
124
|
-
|
125
|
-
|
305
|
+
ptriangles.reset(new Triangles(count_points_for_triangulation()));
|
306
|
+
for (const auto& polyline : polylines)
|
307
|
+
ptriangles->append(polyline);
|
126
308
|
}
|
127
|
-
return
|
309
|
+
return *ptriangles;
|
128
310
|
}
|
129
311
|
|
130
|
-
size_t
|
312
|
+
size_t count_points_for_triangulation () const
|
131
313
|
{
|
132
314
|
size_t count = 0;
|
133
|
-
for (const auto&
|
134
|
-
|
315
|
+
for (const auto& polyline : polylines)
|
316
|
+
{
|
317
|
+
if (can_triangulate(polyline))
|
318
|
+
count += polyline.size();
|
319
|
+
}
|
135
320
|
return count;
|
136
321
|
}
|
137
322
|
|
138
|
-
|
323
|
+
bool can_triangulate (const Polyline& polyline) const
|
139
324
|
{
|
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
|
-
}
|
325
|
+
return (polyline.fill() || polyline.hole()) && polyline.size() >= 3;
|
149
326
|
}
|
150
327
|
|
151
328
|
void stroke_with_width (
|
152
329
|
const Polygon& polygon, Painter* painter,
|
153
|
-
const Color& color, coord stroke_width) const
|
330
|
+
const Color& color, coord stroke_width, float stroke_outset) const
|
154
331
|
{
|
155
332
|
assert(painter && color && stroke_width > 0);
|
156
333
|
|
@@ -163,39 +340,54 @@ namespace Rays
|
|
163
340
|
bool has_loop = false;
|
164
341
|
for (const auto& polyline : polygon)
|
165
342
|
{
|
166
|
-
if (!polyline || polyline.empty())
|
167
|
-
continue;
|
168
|
-
|
169
343
|
if (polyline.loop())
|
170
344
|
{
|
171
345
|
has_loop = true;
|
172
346
|
continue;
|
173
347
|
}
|
348
|
+
stroke_polyline(polyline, painter, color, stroke_width, cap, join, ml);
|
349
|
+
}
|
174
350
|
|
175
|
-
|
176
|
-
if (!polyline.expand(&stroke, stroke_width / 2, cap, join, ml))
|
177
|
-
continue;
|
351
|
+
if (!has_loop) return;
|
178
352
|
|
179
|
-
|
180
|
-
|
353
|
+
coord inset = (-0.5 + stroke_outset) * stroke_width;
|
354
|
+
Polygon outline;
|
355
|
+
if (inset == 0)
|
356
|
+
outline = polygon;
|
357
|
+
else if (!polygon.expand(&outline, inset, cap, join, ml))
|
358
|
+
return;
|
181
359
|
|
182
|
-
|
360
|
+
for (const auto& polyline : outline)
|
183
361
|
{
|
184
|
-
|
185
|
-
|
186
|
-
Polygon_fill(polygon - hole, painter, color);
|
362
|
+
if (polyline.loop())
|
363
|
+
stroke_polyline(polyline, painter, color, stroke_width, cap, join, ml);
|
187
364
|
}
|
188
365
|
}
|
189
366
|
|
367
|
+
void stroke_polyline (
|
368
|
+
const Polyline& polyline, Painter* painter,
|
369
|
+
const Color& color, coord stroke_width,
|
370
|
+
CapType cap, JoinType join, coord miter_limit) const
|
371
|
+
{
|
372
|
+
assert(stroke_width > 0);
|
373
|
+
|
374
|
+
if (!polyline || polyline.empty())
|
375
|
+
return;
|
376
|
+
|
377
|
+
Polygon stroke;
|
378
|
+
if (polyline.expand(&stroke, stroke_width / 2, cap, join, miter_limit))
|
379
|
+
Polygon_fill(stroke, painter, color);
|
380
|
+
}
|
381
|
+
|
190
382
|
void stroke_without_width (Painter* painter, const Color& color) const
|
191
383
|
{
|
192
384
|
assert(painter && color);
|
193
385
|
|
194
|
-
for (const auto&
|
386
|
+
for (const auto& polyline : polylines)
|
195
387
|
{
|
196
|
-
|
197
|
-
painter,
|
198
|
-
&
|
388
|
+
Painter_draw(
|
389
|
+
painter, polyline.loop() ? GL_LINE_LOOP : GL_LINE_STRIP, color,
|
390
|
+
&polyline[0], polyline.size());
|
199
391
|
}
|
200
392
|
}
|
201
393
|
|
@@ -261,14 +453,14 @@ namespace Rays
|
|
261
453
|
assert(clipper);
|
262
454
|
|
263
455
|
clip::Path path;
|
264
|
-
for (const auto&
|
456
|
+
for (const auto& polyline : polygon)
|
265
457
|
{
|
266
|
-
if (!
|
458
|
+
if (!polyline) continue;
|
267
459
|
|
268
|
-
Polyline_get_path(&path,
|
460
|
+
Polyline_get_path(&path, polyline, polyline.hole());
|
269
461
|
if (path.empty()) continue;
|
270
462
|
|
271
|
-
clipper->AddPath(path, type,
|
463
|
+
clipper->AddPath(path, type, polyline.loop());
|
272
464
|
}
|
273
465
|
}
|
274
466
|
|
@@ -307,7 +499,7 @@ namespace Rays
|
|
307
499
|
static bool
|
308
500
|
add_polyline_to_offsetter (
|
309
501
|
clip::ClipperOffset* offsetter, const Polyline& polyline,
|
310
|
-
CapType cap, JoinType join, bool
|
502
|
+
CapType cap, JoinType join, bool fill, bool hole)
|
311
503
|
{
|
312
504
|
assert(offsetter);
|
313
505
|
|
@@ -328,10 +520,10 @@ namespace Rays
|
|
328
520
|
assert(offsetter);
|
329
521
|
|
330
522
|
bool added = false;
|
331
|
-
for (const auto&
|
523
|
+
for (const auto& polyline : polygon.self->polylines)
|
332
524
|
{
|
333
525
|
added |= add_polyline_to_offsetter(
|
334
|
-
offsetter,
|
526
|
+
offsetter, polyline, cap, join, true, polyline.hole());
|
335
527
|
}
|
336
528
|
return added;
|
337
529
|
}
|
@@ -344,12 +536,11 @@ namespace Rays
|
|
344
536
|
if (node.Contour.empty() || node.IsHole())
|
345
537
|
return false;
|
346
538
|
|
347
|
-
Polyline polyline;
|
348
|
-
Polyline_create(&polyline, node.Contour, !node.IsOpen(), false);
|
539
|
+
Polyline polyline = Polyline_create(node.Contour, !node.IsOpen());
|
349
540
|
if (!polyline)
|
350
541
|
return false;
|
351
542
|
|
352
|
-
polygon->self->append(polyline
|
543
|
+
polygon->self->append(polyline);
|
353
544
|
return true;
|
354
545
|
}
|
355
546
|
|
@@ -363,12 +554,11 @@ namespace Rays
|
|
363
554
|
if (!child->IsHole())
|
364
555
|
return;
|
365
556
|
|
366
|
-
Polyline polyline;
|
367
|
-
Polyline_create(&polyline, child->Contour, !child->IsOpen(), true);
|
557
|
+
Polyline polyline = Polyline_create(child->Contour, !child->IsOpen(), true);
|
368
558
|
if (!polyline)
|
369
559
|
continue;
|
370
560
|
|
371
|
-
polygon->self->append(polyline
|
561
|
+
polygon->self->append(polyline);
|
372
562
|
}
|
373
563
|
}
|
374
564
|
|
@@ -447,26 +637,6 @@ namespace Rays
|
|
447
637
|
}
|
448
638
|
|
449
639
|
|
450
|
-
struct PolygonData : public Polygon::Data
|
451
|
-
{
|
452
|
-
|
453
|
-
mutable Polygon::TrianglePointList triangles;
|
454
|
-
|
455
|
-
void fill (Painter* painter, const Color& color) const
|
456
|
-
{
|
457
|
-
if (triangles.empty())
|
458
|
-
{
|
459
|
-
if (!triangulate(&triangles))
|
460
|
-
return;
|
461
|
-
}
|
462
|
-
|
463
|
-
Painter_draw_polygon(
|
464
|
-
painter, GL_TRIANGLES, color, &triangles[0], triangles.size());
|
465
|
-
}
|
466
|
-
|
467
|
-
};// PolygonData
|
468
|
-
|
469
|
-
|
470
640
|
struct RectData : public Polygon::Data
|
471
641
|
{
|
472
642
|
|
@@ -494,11 +664,11 @@ namespace Rays
|
|
494
664
|
|
495
665
|
void fill (Painter* painter, const Color& color) const
|
496
666
|
{
|
497
|
-
if (
|
667
|
+
if (polylines.size() != 1)
|
498
668
|
invalid_state_error(__FILE__, __LINE__);
|
499
669
|
|
500
|
-
const auto& outline =
|
501
|
-
|
670
|
+
const auto& outline = polylines[0];
|
671
|
+
Painter_draw(
|
502
672
|
painter, GL_TRIANGLE_FAN, color, &outline[0], outline.size());
|
503
673
|
}
|
504
674
|
|
@@ -629,10 +799,10 @@ namespace Rays
|
|
629
799
|
};// RectData
|
630
800
|
|
631
801
|
|
632
|
-
struct EllipseData : public
|
802
|
+
struct EllipseData : public Polygon::Data
|
633
803
|
{
|
634
804
|
|
635
|
-
typedef
|
805
|
+
typedef Polygon::Data Super;
|
636
806
|
|
637
807
|
GLenum mode = 0;
|
638
808
|
|
@@ -655,7 +825,7 @@ namespace Rays
|
|
655
825
|
|
656
826
|
void fill (Painter* painter, const Color& color) const
|
657
827
|
{
|
658
|
-
if (
|
828
|
+
if (polylines.size() <= 0)
|
659
829
|
invalid_state_error(__FILE__, __LINE__);
|
660
830
|
|
661
831
|
if (mode == 0)
|
@@ -664,11 +834,11 @@ namespace Rays
|
|
664
834
|
return;
|
665
835
|
}
|
666
836
|
|
667
|
-
if (
|
837
|
+
if (polylines.size() >= 2)
|
668
838
|
invalid_state_error(__FILE__, __LINE__);
|
669
839
|
|
670
|
-
const auto& outline =
|
671
|
-
|
840
|
+
const auto& outline = polylines[0];
|
841
|
+
Painter_draw(painter, mode, color, &outline[0], outline.size());
|
672
842
|
}
|
673
843
|
|
674
844
|
private:
|
@@ -723,7 +893,7 @@ namespace Rays
|
|
723
893
|
hole_x, hole_y, hole_size.x, hole_size.y,
|
724
894
|
radian_from, radian_to, nsegment, seg));
|
725
895
|
}
|
726
|
-
append(Polyline(&points[0], points.size(), true
|
896
|
+
append(Polyline(&points[0], points.size(), true, NULL, NULL, true));
|
727
897
|
}
|
728
898
|
}
|
729
899
|
|
@@ -746,7 +916,7 @@ namespace Rays
|
|
746
916
|
|
747
917
|
if (!has_hole)
|
748
918
|
{
|
749
|
-
points.emplace_back(
|
919
|
+
points.emplace_back(x + width / 2, y + height / 2);
|
750
920
|
mode = GL_TRIANGLE_FAN;
|
751
921
|
}
|
752
922
|
|
@@ -788,6 +958,27 @@ namespace Rays
|
|
788
958
|
};// EllipseData
|
789
959
|
|
790
960
|
|
961
|
+
Polygon
|
962
|
+
create_point (coord x, coord y)
|
963
|
+
{
|
964
|
+
return create_point(Point(x, y));
|
965
|
+
}
|
966
|
+
|
967
|
+
Polygon
|
968
|
+
create_point (const Point& point)
|
969
|
+
{
|
970
|
+
return create_points(&point, 1);
|
971
|
+
}
|
972
|
+
|
973
|
+
Polygon
|
974
|
+
create_points (const Point* points, size_t size)
|
975
|
+
{
|
976
|
+
Polygon p;
|
977
|
+
for (size_t i = 0; i < size; ++i)
|
978
|
+
p.self->append(Polyline(&points[i], 1, false, false));
|
979
|
+
return p;
|
980
|
+
}
|
981
|
+
|
791
982
|
Polygon
|
792
983
|
create_line (coord x1, coord y1, coord x2, coord y2)
|
793
984
|
{
|
@@ -808,7 +999,20 @@ namespace Rays
|
|
808
999
|
Polygon
|
809
1000
|
create_line (const Point* points, size_t size, bool loop)
|
810
1001
|
{
|
811
|
-
|
1002
|
+
Polygon p;(points, size, loop);
|
1003
|
+
//if (!loop || size < 3)
|
1004
|
+
p.self->append(Polyline(points, size, loop, false));
|
1005
|
+
#if 0
|
1006
|
+
else
|
1007
|
+
{
|
1008
|
+
std::vector<Point> array;
|
1009
|
+
array.reserve(size + 1);
|
1010
|
+
array.insert(array.begin(), points, points + size);
|
1011
|
+
array.emplace_back(points[0]);
|
1012
|
+
polygon->self->append(Polyline(&array[0], array.size(), true, false));
|
1013
|
+
}
|
1014
|
+
#endif
|
1015
|
+
return p;
|
812
1016
|
}
|
813
1017
|
|
814
1018
|
Polygon
|
@@ -817,6 +1021,125 @@ namespace Rays
|
|
817
1021
|
return Polygon(polyline);
|
818
1022
|
}
|
819
1023
|
|
1024
|
+
Polygon
|
1025
|
+
create_lines (const Point* points, size_t size)
|
1026
|
+
{
|
1027
|
+
Polygon p;
|
1028
|
+
for (size_t i = 0; i + 1 < size; i += 2)
|
1029
|
+
p.self->append(Polyline(&points[i], 2, false, false));
|
1030
|
+
return p;
|
1031
|
+
}
|
1032
|
+
|
1033
|
+
Polygon
|
1034
|
+
create_triangle (
|
1035
|
+
coord x1, coord y1, coord x2, coord y2, coord x3, coord y3, bool loop)
|
1036
|
+
{
|
1037
|
+
const Point points[] = {Point(x1, y1), Point(x2, y2), Point(x3, y3)};
|
1038
|
+
return create_triangles(points, 3, loop);
|
1039
|
+
}
|
1040
|
+
|
1041
|
+
Polygon
|
1042
|
+
create_triangle (
|
1043
|
+
const Point& p1, const Point& p2, const Point& p3, bool loop)
|
1044
|
+
{
|
1045
|
+
const Point points[] = {p1, p2, p3};
|
1046
|
+
return create_triangles(points, 3, loop);
|
1047
|
+
}
|
1048
|
+
|
1049
|
+
Polygon
|
1050
|
+
create_triangles (
|
1051
|
+
const Point* points, size_t size, bool loop,
|
1052
|
+
const Color* colors, const Coord3* texcoords)
|
1053
|
+
{
|
1054
|
+
Polygon p;
|
1055
|
+
for (size_t i = 0; i + 2 < size; i += 3)
|
1056
|
+
{
|
1057
|
+
p.self->append(Polyline(
|
1058
|
+
&points[i], 3, loop, true,
|
1059
|
+
colors ? &colors[i] : NULL,
|
1060
|
+
texcoords ? &texcoords[i] : NULL));
|
1061
|
+
}
|
1062
|
+
return p;
|
1063
|
+
}
|
1064
|
+
|
1065
|
+
Polygon
|
1066
|
+
create_triangle_strip (
|
1067
|
+
const Point* points, size_t size,
|
1068
|
+
const Color* colors, const Coord3* texcoords)
|
1069
|
+
{
|
1070
|
+
Polygon p;
|
1071
|
+
if (size < 3) return p;
|
1072
|
+
|
1073
|
+
size_t last = size - 1;
|
1074
|
+
size_t in_last = last % 2 == 0 ? last - 1 : last;
|
1075
|
+
size_t out_last = last % 2 == 0 ? last : last - 1;
|
1076
|
+
|
1077
|
+
std::vector<Point> points_;
|
1078
|
+
points_.reserve(size);
|
1079
|
+
points_.emplace_back(points[0]);
|
1080
|
+
for (size_t i = 1; i <= in_last; i += 2)
|
1081
|
+
points_.emplace_back(points[i]);
|
1082
|
+
for (size_t i = out_last; i >= 2; i -= 2)
|
1083
|
+
points_.emplace_back(points[i]);
|
1084
|
+
|
1085
|
+
std::unique_ptr<std::vector<Color>> pcolors_;
|
1086
|
+
if (colors)
|
1087
|
+
{
|
1088
|
+
pcolors_.reset(new decltype(pcolors_)::element_type());
|
1089
|
+
pcolors_->reserve(size);
|
1090
|
+
pcolors_->emplace_back(colors[0]);
|
1091
|
+
for (size_t i = 1; i <= in_last; i += 2)
|
1092
|
+
pcolors_->emplace_back(colors[i]);
|
1093
|
+
for (size_t i = out_last; i >= 2; i -= 2)
|
1094
|
+
pcolors_->emplace_back(colors[i]);
|
1095
|
+
}
|
1096
|
+
|
1097
|
+
std::unique_ptr<std::vector<Coord3>> ptexcoords_;
|
1098
|
+
if (texcoords)
|
1099
|
+
{
|
1100
|
+
ptexcoords_.reset(new decltype(ptexcoords_)::element_type());
|
1101
|
+
ptexcoords_->reserve(size);
|
1102
|
+
ptexcoords_->emplace_back(texcoords[0]);
|
1103
|
+
for (size_t i = 1; i <= in_last; i += 2)
|
1104
|
+
ptexcoords_->emplace_back(texcoords[i]);
|
1105
|
+
for (size_t i = out_last; i >= 2; i -= 2)
|
1106
|
+
ptexcoords_->emplace_back(texcoords[i]);
|
1107
|
+
}
|
1108
|
+
|
1109
|
+
p.self->append(Polyline(
|
1110
|
+
&points_[0], points_.size(), true,
|
1111
|
+
pcolors_ ? &(*pcolors_)[0] : NULL,
|
1112
|
+
ptexcoords_ ? &(*ptexcoords_)[0] : NULL));
|
1113
|
+
if (size >= 4)
|
1114
|
+
{
|
1115
|
+
p.self->append(Polyline(
|
1116
|
+
&points[1], size - 2, false,
|
1117
|
+
colors ? &colors[1] : NULL,
|
1118
|
+
texcoords ? &texcoords[1] : NULL));
|
1119
|
+
}
|
1120
|
+
return p;
|
1121
|
+
}
|
1122
|
+
|
1123
|
+
Polygon
|
1124
|
+
create_triangle_fan (
|
1125
|
+
const Point* points, size_t size,
|
1126
|
+
const Color* colors, const Coord3* texcoords)
|
1127
|
+
{
|
1128
|
+
Polygon p(points, size, true, colors, texcoords);
|
1129
|
+
|
1130
|
+
Point array[2];
|
1131
|
+
array[0] = points[0];
|
1132
|
+
for (size_t i = 2; i < size - 1; ++i)
|
1133
|
+
{
|
1134
|
+
array[1] = points[i];
|
1135
|
+
p.self->append(Polyline(
|
1136
|
+
&array[0], 2, false,
|
1137
|
+
colors ? &colors[0] : NULL,
|
1138
|
+
texcoords ? &texcoords[0] : NULL));
|
1139
|
+
}
|
1140
|
+
return p;
|
1141
|
+
}
|
1142
|
+
|
820
1143
|
Polygon
|
821
1144
|
create_rect (
|
822
1145
|
coord x, coord y, coord width, coord height,
|
@@ -866,6 +1189,96 @@ namespace Rays
|
|
866
1189
|
nsegment);
|
867
1190
|
}
|
868
1191
|
|
1192
|
+
Polygon
|
1193
|
+
create_quad (
|
1194
|
+
coord x1, coord y1, coord x2, coord y2,
|
1195
|
+
coord x3, coord y3, coord x4, coord y4,
|
1196
|
+
bool loop)
|
1197
|
+
{
|
1198
|
+
Point points[] = {Point(x1, y1), Point(x2, y2), Point(x3, y3), Point(x4, y4)};
|
1199
|
+
return create_quads(points, 4, loop);
|
1200
|
+
}
|
1201
|
+
|
1202
|
+
Polygon
|
1203
|
+
create_quad (
|
1204
|
+
const Point& p1, const Point& p2, const Point& p3, const Point& p4,
|
1205
|
+
bool loop)
|
1206
|
+
{
|
1207
|
+
Point points[] = {p1, p2, p3, p4};
|
1208
|
+
return create_quads(points, 4, loop);
|
1209
|
+
}
|
1210
|
+
|
1211
|
+
Polygon
|
1212
|
+
create_quads (
|
1213
|
+
const Point* points, size_t size, bool loop,
|
1214
|
+
const Color* colors, const Coord3* texcoords)
|
1215
|
+
{
|
1216
|
+
Polygon p;
|
1217
|
+
for (size_t i = 0; i + 3 < size; i += 4)
|
1218
|
+
{
|
1219
|
+
p.self->append(Polyline(
|
1220
|
+
&points[i], 4, loop, true,
|
1221
|
+
colors ? &colors[i] : NULL,
|
1222
|
+
texcoords ? &texcoords[i] : NULL));
|
1223
|
+
}
|
1224
|
+
return p;
|
1225
|
+
}
|
1226
|
+
|
1227
|
+
Polygon
|
1228
|
+
create_quad_strip (
|
1229
|
+
const Point* points, size_t size,
|
1230
|
+
const Color* colors, const Coord3* texcoords)
|
1231
|
+
{
|
1232
|
+
Polygon p;
|
1233
|
+
if (size < 4) return p;
|
1234
|
+
|
1235
|
+
if (size % 2 != 0) --size;
|
1236
|
+
size_t in_last = size - 2;
|
1237
|
+
size_t out_last = size - 1;
|
1238
|
+
|
1239
|
+
std::vector<Point> points_;
|
1240
|
+
points_.reserve(size);
|
1241
|
+
for (size_t i = 0; i <= in_last; i += 2)
|
1242
|
+
points_.emplace_back(points[i]);
|
1243
|
+
for (int i = (int) out_last; i >= 1; i -= 2)
|
1244
|
+
points_.emplace_back(points[i]);
|
1245
|
+
|
1246
|
+
std::unique_ptr<std::vector<Color>> pcolors_;
|
1247
|
+
if (colors)
|
1248
|
+
{
|
1249
|
+
pcolors_.reset(new decltype(pcolors_)::element_type());
|
1250
|
+
pcolors_->reserve(size);
|
1251
|
+
for (size_t i = 0; i <= in_last; i += 2)
|
1252
|
+
pcolors_->emplace_back(colors[i]);
|
1253
|
+
for (int i = (int) out_last; i >= 1; i -= 2)
|
1254
|
+
pcolors_->emplace_back(colors[i]);
|
1255
|
+
}
|
1256
|
+
|
1257
|
+
std::unique_ptr<std::vector<Coord3>> ptexcoords_;
|
1258
|
+
if (texcoords)
|
1259
|
+
{
|
1260
|
+
ptexcoords_.reset(new decltype(ptexcoords_)::element_type());
|
1261
|
+
ptexcoords_->reserve(size);
|
1262
|
+
for (size_t i = 0; i <= in_last; i += 2)
|
1263
|
+
ptexcoords_->emplace_back(texcoords[i]);
|
1264
|
+
for (int i = (int) out_last; i >= 1; i -= 2)
|
1265
|
+
ptexcoords_->emplace_back(texcoords[i]);
|
1266
|
+
}
|
1267
|
+
|
1268
|
+
p.self->append(Polyline(
|
1269
|
+
&points_[0], points_.size(), true,
|
1270
|
+
pcolors_ ? &(*pcolors_)[0] : NULL,
|
1271
|
+
ptexcoords_ ? &(*ptexcoords_)[0] : NULL));
|
1272
|
+
for (size_t i = 2; i < in_last; i += 2)
|
1273
|
+
{
|
1274
|
+
p.self->append(Polyline(
|
1275
|
+
&points[i], 2, false,
|
1276
|
+
colors ? &colors[i] : NULL,
|
1277
|
+
texcoords ? &texcoords[i] : NULL));
|
1278
|
+
}
|
1279
|
+
return p;
|
1280
|
+
}
|
1281
|
+
|
869
1282
|
Polygon
|
870
1283
|
create_ellipse (
|
871
1284
|
coord x, coord y, coord width, coord height,
|
@@ -1060,31 +1473,36 @@ namespace Rays
|
|
1060
1473
|
|
1061
1474
|
|
1062
1475
|
Polygon::Polygon ()
|
1063
|
-
: self(new PolygonData())
|
1064
1476
|
{
|
1065
1477
|
}
|
1066
1478
|
|
1067
|
-
Polygon::Polygon (
|
1068
|
-
|
1479
|
+
Polygon::Polygon (
|
1480
|
+
const Point* points, size_t size, bool loop,
|
1481
|
+
const Color* colors, const Coord3* texcoords)
|
1069
1482
|
{
|
1070
1483
|
if (!points || size <= 0) return;
|
1071
1484
|
|
1072
|
-
self->append(Polyline(points, size, loop));
|
1485
|
+
self->append(Polyline(points, size, loop, true, colors, texcoords));
|
1073
1486
|
}
|
1074
1487
|
|
1075
1488
|
Polygon::Polygon (const Polyline& polyline)
|
1076
|
-
: self(new PolygonData())
|
1077
1489
|
{
|
1490
|
+
if (polyline.hole())
|
1491
|
+
argument_error(__FILE__, __LINE__);
|
1492
|
+
|
1078
1493
|
self->append(polyline);
|
1079
1494
|
}
|
1080
1495
|
|
1081
|
-
Polygon::Polygon (const
|
1082
|
-
: self(new PolygonData())
|
1496
|
+
Polygon::Polygon (const Polyline* polylines, size_t size)
|
1083
1497
|
{
|
1084
|
-
if (!
|
1498
|
+
if (!polylines || size <= 0)
|
1499
|
+
return;
|
1500
|
+
|
1501
|
+
if (polylines[0].hole())
|
1502
|
+
argument_error(__FILE__, __LINE__);
|
1085
1503
|
|
1086
1504
|
for (size_t i = 0; i < size; ++i)
|
1087
|
-
self->append(
|
1505
|
+
self->append(polylines[i]);
|
1088
1506
|
}
|
1089
1507
|
|
1090
1508
|
Polygon::Polygon (Data* data)
|
@@ -1107,21 +1525,13 @@ namespace Rays
|
|
1107
1525
|
Bounds
|
1108
1526
|
Polygon::bounds () const
|
1109
1527
|
{
|
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;
|
1528
|
+
return self->bounds();
|
1119
1529
|
}
|
1120
1530
|
|
1121
1531
|
size_t
|
1122
1532
|
Polygon::size () const
|
1123
1533
|
{
|
1124
|
-
return self->
|
1534
|
+
return self->polylines.size();
|
1125
1535
|
}
|
1126
1536
|
|
1127
1537
|
bool
|
@@ -1129,9 +1539,9 @@ namespace Rays
|
|
1129
1539
|
{
|
1130
1540
|
if (deep)
|
1131
1541
|
{
|
1132
|
-
for (const auto&
|
1542
|
+
for (const auto& polyline : self->polylines)
|
1133
1543
|
{
|
1134
|
-
if (!
|
1544
|
+
if (!polyline.empty())
|
1135
1545
|
return false;
|
1136
1546
|
}
|
1137
1547
|
}
|
@@ -1142,29 +1552,29 @@ namespace Rays
|
|
1142
1552
|
Polygon::const_iterator
|
1143
1553
|
Polygon::begin () const
|
1144
1554
|
{
|
1145
|
-
return self->
|
1555
|
+
return self->polylines.begin();
|
1146
1556
|
}
|
1147
1557
|
|
1148
1558
|
Polygon::const_iterator
|
1149
1559
|
Polygon::end () const
|
1150
1560
|
{
|
1151
|
-
return self->
|
1561
|
+
return self->polylines.end();
|
1152
1562
|
}
|
1153
1563
|
|
1154
|
-
const
|
1564
|
+
const Polyline&
|
1155
1565
|
Polygon::operator [] (size_t index) const
|
1156
1566
|
{
|
1157
|
-
return self->
|
1567
|
+
return self->polylines[index];
|
1158
1568
|
}
|
1159
1569
|
|
1160
1570
|
Polygon::operator bool () const
|
1161
1571
|
{
|
1162
|
-
if (self->
|
1572
|
+
if (self->polylines.empty())
|
1163
1573
|
return true;
|
1164
1574
|
|
1165
|
-
for (const auto&
|
1575
|
+
for (const auto& polyline : self->polylines)
|
1166
1576
|
{
|
1167
|
-
if (
|
1577
|
+
if (polyline) return true;
|
1168
1578
|
}
|
1169
1579
|
|
1170
1580
|
return false;
|
@@ -1182,10 +1592,23 @@ namespace Rays
|
|
1182
1592
|
return self->triangulate(triangles);
|
1183
1593
|
}
|
1184
1594
|
|
1595
|
+
Polygon
|
1596
|
+
operator + (const Polygon& lhs, const Polyline& rhs)
|
1597
|
+
{
|
1598
|
+
std::vector<Polyline> polylines;
|
1599
|
+
for (const auto& polyline : lhs)
|
1600
|
+
polylines.emplace_back(polyline);
|
1601
|
+
polylines.emplace_back(rhs);
|
1602
|
+
return Polygon(&polylines[0], polylines.size());
|
1603
|
+
}
|
1604
|
+
|
1185
1605
|
Polygon
|
1186
1606
|
operator + (const Polygon& lhs, const Polygon& rhs)
|
1187
1607
|
{
|
1188
|
-
|
1608
|
+
std::vector<Polyline> polylines;
|
1609
|
+
for (const auto& polyline : lhs) polylines.emplace_back(polyline);
|
1610
|
+
for (const auto& polyline : rhs) polylines.emplace_back(polyline);
|
1611
|
+
return Polygon(&polylines[0], polylines.size());
|
1189
1612
|
}
|
1190
1613
|
|
1191
1614
|
Polygon
|
@@ -1221,44 +1644,4 @@ namespace Rays
|
|
1221
1644
|
}
|
1222
1645
|
|
1223
1646
|
|
1224
|
-
Polygon::Line::Line ()
|
1225
|
-
: Super(), hole_(false)
|
1226
|
-
{
|
1227
|
-
}
|
1228
|
-
|
1229
|
-
Polygon::Line::Line (const Point* points, size_t size, bool loop, bool hole)
|
1230
|
-
: Super(points, size, loop), hole_(hole)
|
1231
|
-
{
|
1232
|
-
if (!*this)
|
1233
|
-
argument_error(__FILE__, __LINE__);
|
1234
|
-
}
|
1235
|
-
|
1236
|
-
Polygon::Line::Line (const Polyline& polyline, bool hole)
|
1237
|
-
: Super(polyline), hole_(hole)
|
1238
|
-
{
|
1239
|
-
if (!*this)
|
1240
|
-
argument_error(__FILE__, __LINE__);
|
1241
|
-
}
|
1242
|
-
|
1243
|
-
bool
|
1244
|
-
Polygon::Line::hole () const
|
1245
|
-
{
|
1246
|
-
return hole_;
|
1247
|
-
}
|
1248
|
-
|
1249
|
-
Polygon::Line::operator bool () const
|
1250
|
-
{
|
1251
|
-
if (!Super::operator bool())
|
1252
|
-
return false;
|
1253
|
-
|
1254
|
-
return loop() || !hole();
|
1255
|
-
}
|
1256
|
-
|
1257
|
-
bool
|
1258
|
-
Polygon::Line::operator ! () const
|
1259
|
-
{
|
1260
|
-
return !operator bool();
|
1261
|
-
}
|
1262
|
-
|
1263
|
-
|
1264
1647
|
}// Rays
|