rays 0.1.46 → 0.1.48

Sign up to get free protection for your applications and to get access to all the features.
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