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.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.doc/ext/rays/bitmap.cpp +499 -0
  3. data/.doc/ext/rays/camera.cpp +2 -2
  4. data/.doc/ext/rays/defs.cpp +35 -11
  5. data/.doc/ext/rays/font.cpp +50 -2
  6. data/.doc/ext/rays/native.cpp +2 -4
  7. data/.doc/ext/rays/painter.cpp +111 -6
  8. data/.doc/ext/rays/polygon.cpp +152 -41
  9. data/.doc/ext/rays/polyline.cpp +89 -10
  10. data/.doc/ext/rays/rays.cpp +91 -11
  11. data/.doc/ext/rays/{noise.cpp → util.cpp} +2 -2
  12. data/.github/workflows/test.yml +0 -1
  13. data/ChangeLog.md +38 -0
  14. data/Rakefile +4 -4
  15. data/VERSION +1 -1
  16. data/ext/rays/bitmap.cpp +501 -0
  17. data/ext/rays/camera.cpp +2 -2
  18. data/ext/rays/defs.cpp +35 -11
  19. data/ext/rays/defs.h +56 -3
  20. data/ext/rays/font.cpp +56 -4
  21. data/ext/rays/native.cpp +2 -4
  22. data/ext/rays/painter.cpp +125 -11
  23. data/ext/rays/polygon.cpp +161 -41
  24. data/ext/rays/polyline.cpp +95 -9
  25. data/ext/rays/rays.cpp +91 -11
  26. data/ext/rays/{noise.cpp → util.cpp} +2 -2
  27. data/include/rays/defs.h +24 -0
  28. data/include/rays/font.h +17 -3
  29. data/include/rays/matrix.h +2 -0
  30. data/include/rays/painter.h +29 -1
  31. data/include/rays/polygon.h +57 -33
  32. data/include/rays/polyline.h +20 -1
  33. data/include/rays/ruby/polygon.h +0 -11
  34. data/include/rays/ruby/rays.h +4 -0
  35. data/include/rays/{noise.h → util.h} +2 -2
  36. data/lib/rays/color.rb +1 -1
  37. data/lib/rays/font.rb +1 -1
  38. data/lib/rays/image.rb +1 -1
  39. data/lib/rays/painter.rb +13 -2
  40. data/lib/rays/point.rb +1 -1
  41. data/lib/rays/polygon.rb +54 -16
  42. data/lib/rays/polyline.rb +54 -8
  43. data/lib/rays.rb +0 -1
  44. data/rays.gemspec +2 -2
  45. data/src/color_space.cpp +2 -2
  46. data/src/font.cpp +24 -2
  47. data/src/font.h +8 -1
  48. data/src/ios/font.mm +88 -27
  49. data/src/matrix.cpp +8 -0
  50. data/src/osx/font.mm +90 -28
  51. data/src/osx/helper.h +2 -2
  52. data/src/osx/helper.mm +2 -2
  53. data/src/painter.cpp +227 -90
  54. data/src/painter.h +11 -3
  55. data/src/polygon.cpp +588 -205
  56. data/src/polyline.cpp +154 -28
  57. data/src/polyline.h +3 -5
  58. data/src/shader.cpp +36 -4
  59. data/src/shader.h +1 -1
  60. data/src/texture.cpp +2 -2
  61. data/src/{noise.cpp → util.cpp} +1 -1
  62. data/src/win32/font.cpp +1 -1
  63. data/test/test_bitmap.rb +16 -2
  64. data/test/test_color.rb +4 -0
  65. data/test/test_font.rb +20 -2
  66. data/test/test_image.rb +18 -18
  67. data/test/test_point.rb +1 -1
  68. data/test/test_polygon.rb +52 -45
  69. data/test/test_polyline.rb +191 -72
  70. metadata +11 -17
  71. data/.doc/ext/rays/polygon_line.cpp +0 -97
  72. data/ext/rays/polygon_line.cpp +0 -100
  73. data/lib/rays/polygon_line.rb +0 -33
  74. 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 <poly2tri.h>
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 Rays
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
- static inline Point
31
- from_poly2tri (const p2t::Point& point)
32
- {
33
- return Point(point.x, point.y);
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
- struct Polygon::Data
44
+ }// util
45
+
46
+ }// mapbox
47
+
48
+
49
+ namespace Rays
50
+ {
51
+
52
+
53
+ class Triangles
38
54
  {
39
55
 
40
- LineList lines;
56
+ public:
41
57
 
42
- virtual ~Data ()
43
- {
44
- }
58
+ Triangles (size_t npoints)
59
+ {
60
+ points.reserve(npoints);
61
+ }
45
62
 
46
- void append (const Polyline& polyline, bool hole = false)
47
- {
48
- if (polyline.empty())
49
- return;
63
+ void append (const Polyline& polyline)
64
+ {
65
+ if (polyline.empty()) return;
50
66
 
51
- lines.emplace_back(Line(polyline, hole));
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
- void append (const Line& line)
55
- {
56
- if (line.empty())
57
- return;
73
+ if (
74
+ !points.empty() &&
75
+ (!colors_ != !pcolors || !texcoords_ != !ptexcoords))
76
+ {
77
+ argument_error(__FILE__, __LINE__);
78
+ }
58
79
 
59
- lines.emplace_back(line);
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
- bool triangulate (TrianglePointList* triangles) const
63
- {
64
- assert(triangles);
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
- triangles->clear();
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
- if (!can_triangulate())
69
- return false;
106
+ bool get (Polygon::TrianglePointList* triangles) const
107
+ {
108
+ triangulate();
109
+ if (indices.empty()) return false;
70
110
 
71
- size_t npoint = count_points();
72
- if (npoint <= 0)
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
- std::unique_ptr<p2t::CDT> cdt;
76
- std::vector<p2t::Point> points;
77
- std::vector<p2t::Point*> pointers;
141
+ private:
78
142
 
79
- points.reserve(npoint);
80
- for (const auto& line : lines)
143
+ struct Segment
81
144
  {
82
- pointers.clear();
83
- pointers.reserve(line.size());
84
- for (const auto& point : line)
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
- if (!line.hole())
155
+ bool empty () const
91
156
  {
92
- if (cdt) triangulate(triangles, cdt.get());
93
- cdt.reset(new p2t::CDT(pointers));
157
+ return begin == end;
94
158
  }
95
- else if (cdt)
96
- cdt->AddHole(pointers);
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
- if (cdt) triangulate(triangles, cdt.get());
221
+ void triangulate (const PolylineList& polylines, size_t index_offset) const
222
+ {
223
+ if (polylines.empty()) return;
100
224
 
101
- return true;
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
- virtual void fill (Painter* painter, const Color& color) const = 0;
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
- stroke_with_width(polygon, painter, color, stroke_width);
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
- bool can_triangulate () const
301
+ Triangles& triangles () const
121
302
  {
122
- for (const auto& line : lines)
303
+ if (!ptriangles)
123
304
  {
124
- if (line.loop() && !line.hole() && !line.empty())
125
- return true;
305
+ ptriangles.reset(new Triangles(count_points_for_triangulation()));
306
+ for (const auto& polyline : polylines)
307
+ ptriangles->append(polyline);
126
308
  }
127
- return false;
309
+ return *ptriangles;
128
310
  }
129
311
 
130
- size_t count_points () const
312
+ size_t count_points_for_triangulation () const
131
313
  {
132
314
  size_t count = 0;
133
- for (const auto& line : lines)
134
- count += line.size();
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
- void triangulate (TrianglePointList* triangles, p2t::CDT* cdt) const
323
+ bool can_triangulate (const Polyline& polyline) const
139
324
  {
140
- assert(triangles && cdt);
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
- Polygon stroke;
176
- if (!polyline.expand(&stroke, stroke_width / 2, cap, join, ml))
177
- continue;
351
+ if (!has_loop) return;
178
352
 
179
- Polygon_fill(stroke, painter, color);
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
- if (has_loop)
360
+ for (const auto& polyline : outline)
183
361
  {
184
- Polygon hole;
185
- if (polygon.expand(&hole, -stroke_width, cap, join, ml))
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& line : lines)
386
+ for (const auto& polyline : polylines)
195
387
  {
196
- Painter_draw_polygon(
197
- painter, line.loop() ? GL_LINE_LOOP : GL_LINE_STRIP, color,
198
- &line[0], line.size());
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& line : polygon)
456
+ for (const auto& polyline : polygon)
265
457
  {
266
- if (!line) continue;
458
+ if (!polyline) continue;
267
459
 
268
- Polyline_get_path(&path, line, line.hole());
460
+ Polyline_get_path(&path, polyline, polyline.hole());
269
461
  if (path.empty()) continue;
270
462
 
271
- clipper->AddPath(path, type, line.loop());
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 hole, bool fill)
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& line : polygon.self->lines)
523
+ for (const auto& polyline : polygon.self->polylines)
332
524
  {
333
525
  added |= add_polyline_to_offsetter(
334
- offsetter, line, cap, join, line.hole(), true);
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, false);
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, true);
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 (lines.size() != 1)
667
+ if (polylines.size() != 1)
498
668
  invalid_state_error(__FILE__, __LINE__);
499
669
 
500
- const auto& outline = lines[0];
501
- Painter_draw_polygon(
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 PolygonData
802
+ struct EllipseData : public Polygon::Data
633
803
  {
634
804
 
635
- typedef PolygonData Super;
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 (lines.size() <= 0)
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 (lines.size() >= 2)
837
+ if (polylines.size() >= 2)
668
838
  invalid_state_error(__FILE__, __LINE__);
669
839
 
670
- const auto& outline = lines[0];
671
- Painter_draw_polygon(painter, mode, color, &outline[0], outline.size());
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), 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(Point(x + width / 2, y + height / 2));
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
- return Polygon(points, size, loop);
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 (const Point* points, size_t size, bool loop)
1068
- : self(new PolygonData())
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 Line* lines, size_t size)
1082
- : self(new PolygonData())
1496
+ Polygon::Polygon (const Polyline* polylines, size_t size)
1083
1497
  {
1084
- if (!lines || size <= 0) return;
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(lines[i]);
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
- if (empty()) return Bounds(-1, -1, -1);
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->lines.size();
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& line : self->lines)
1542
+ for (const auto& polyline : self->polylines)
1133
1543
  {
1134
- if (!line.empty())
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->lines.begin();
1555
+ return self->polylines.begin();
1146
1556
  }
1147
1557
 
1148
1558
  Polygon::const_iterator
1149
1559
  Polygon::end () const
1150
1560
  {
1151
- return self->lines.end();
1561
+ return self->polylines.end();
1152
1562
  }
1153
1563
 
1154
- const Polygon::Line&
1564
+ const Polyline&
1155
1565
  Polygon::operator [] (size_t index) const
1156
1566
  {
1157
- return self->lines[index];
1567
+ return self->polylines[index];
1158
1568
  }
1159
1569
 
1160
1570
  Polygon::operator bool () const
1161
1571
  {
1162
- if (self->lines.empty())
1572
+ if (self->polylines.empty())
1163
1573
  return true;
1164
1574
 
1165
- for (const auto& line : self->lines)
1575
+ for (const auto& polyline : self->polylines)
1166
1576
  {
1167
- if (line) return true;
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
- return lhs | rhs;
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