rays 0.1.47 → 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 (69) hide show
  1. checksums.yaml +4 -4
  2. data/.doc/ext/rays/bitmap.cpp +287 -46
  3. data/.doc/ext/rays/camera.cpp +2 -2
  4. data/.doc/ext/rays/defs.cpp +32 -8
  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 +73 -3
  8. data/.doc/ext/rays/polygon.cpp +131 -97
  9. data/.doc/ext/rays/polyline.cpp +89 -10
  10. data/.doc/ext/rays/rays.cpp +80 -0
  11. data/.doc/ext/rays/{noise.cpp → util.cpp} +2 -2
  12. data/ChangeLog.md +23 -0
  13. data/VERSION +1 -1
  14. data/ext/rays/bitmap.cpp +288 -46
  15. data/ext/rays/camera.cpp +2 -2
  16. data/ext/rays/defs.cpp +32 -8
  17. data/ext/rays/defs.h +56 -3
  18. data/ext/rays/font.cpp +56 -4
  19. data/ext/rays/native.cpp +2 -4
  20. data/ext/rays/painter.cpp +80 -3
  21. data/ext/rays/polygon.cpp +134 -99
  22. data/ext/rays/polyline.cpp +95 -9
  23. data/ext/rays/rays.cpp +80 -0
  24. data/ext/rays/{noise.cpp → util.cpp} +2 -2
  25. data/include/rays/defs.h +24 -26
  26. data/include/rays/font.h +17 -3
  27. data/include/rays/painter.h +14 -0
  28. data/include/rays/polygon.h +56 -37
  29. data/include/rays/polyline.h +17 -2
  30. data/include/rays/ruby/polygon.h +0 -11
  31. data/include/rays/ruby/rays.h +4 -0
  32. data/include/rays/{noise.h → util.h} +2 -2
  33. data/lib/rays/color.rb +1 -1
  34. data/lib/rays/font.rb +1 -1
  35. data/lib/rays/image.rb +1 -1
  36. data/lib/rays/painter.rb +12 -1
  37. data/lib/rays/point.rb +1 -1
  38. data/lib/rays/polygon.rb +44 -35
  39. data/lib/rays/polyline.rb +54 -8
  40. data/lib/rays.rb +0 -1
  41. data/rays.gemspec +1 -1
  42. data/src/font.cpp +24 -2
  43. data/src/font.h +8 -1
  44. data/src/ios/font.mm +88 -27
  45. data/src/osx/font.mm +90 -28
  46. data/src/osx/helper.h +2 -2
  47. data/src/osx/helper.mm +2 -2
  48. data/src/painter.cpp +155 -85
  49. data/src/painter.h +11 -3
  50. data/src/polygon.cpp +404 -315
  51. data/src/polyline.cpp +138 -27
  52. data/src/polyline.h +3 -5
  53. data/src/shader.cpp +36 -4
  54. data/src/shader.h +1 -1
  55. data/src/texture.cpp +2 -2
  56. data/src/{noise.cpp → util.cpp} +1 -1
  57. data/src/win32/font.cpp +1 -1
  58. data/test/test_bitmap.rb +12 -5
  59. data/test/test_color.rb +4 -0
  60. data/test/test_font.rb +20 -2
  61. data/test/test_image.rb +18 -18
  62. data/test/test_point.rb +1 -1
  63. data/test/test_polygon.rb +52 -45
  64. data/test/test_polyline.rb +191 -72
  65. metadata +9 -15
  66. data/.doc/ext/rays/polygon_line.cpp +0 -97
  67. data/ext/rays/polygon_line.cpp +0 -100
  68. data/lib/rays/polygon_line.rb +0 -33
  69. data/test/test_polygon_line.rb +0 -164
data/src/polygon.cpp CHANGED
@@ -50,66 +50,62 @@ namespace Rays
50
50
  {
51
51
 
52
52
 
53
- class Triangulator
53
+ class Triangles
54
54
  {
55
55
 
56
56
  public:
57
57
 
58
- Triangulator (size_t npoints)
58
+ Triangles (size_t npoints)
59
59
  {
60
60
  points.reserve(npoints);
61
61
  }
62
62
 
63
- size_t begin (bool hole = false)
63
+ void append (const Polyline& polyline)
64
64
  {
65
- segments.emplace_back(points.size(), 0, hole);
66
- return segments.back().begin;
67
- }
68
-
69
- void end (size_t n)
70
- {
71
- if (segments.empty())
72
- invalid_state_error(__FILE__, __LINE__);
65
+ if (polyline.empty()) return;
73
66
 
74
- auto& seg = segments.back();
75
- if (n != seg.begin)
67
+ const Point* points_ = polyline.points();
68
+ const Color* colors_ = polyline.colors();
69
+ const Coord3* texcoords_ = polyline.texcoords();
70
+ if (!points_)
76
71
  argument_error(__FILE__, __LINE__);
77
72
 
78
- seg.end = points.size();
79
-
80
- if (seg.empty()) segments.pop_back();
81
- }
82
-
83
- void append (const Point& point)
84
- {
85
- points.emplace_back(point);
86
- }
73
+ if (
74
+ !points.empty() &&
75
+ (!colors_ != !pcolors || !texcoords_ != !ptexcoords))
76
+ {
77
+ argument_error(__FILE__, __LINE__);
78
+ }
87
79
 
88
- void triangulate ()
89
- {
90
- if (segments.empty()) return;
80
+ segments.emplace_back(points.size(), 0, polyline.hole());
81
+ points.insert(points.end(), points_, points_ + polyline.size());
82
+ segments.back().end = points.size();
91
83
 
92
- PolylineList polylines;
93
- size_t index_offset = 0;
94
- for (const auto& seg : segments)
84
+ if (colors_)
95
85
  {
96
- Polyline polyline(&points[0] + seg.begin, seg.end - seg.begin);
97
- if (!seg.hole)
86
+ if (!pcolors)
98
87
  {
99
- triangulate(polylines, index_offset);
100
- polylines.clear();
101
- index_offset = seg.begin;
88
+ pcolors.reset(new decltype(pcolors)::element_type());
89
+ pcolors->reserve(points.capacity());
102
90
  }
103
- polylines.emplace_back(polyline);
91
+ pcolors->insert(pcolors->end(), colors_, colors_ + polyline.size());
104
92
  }
105
- triangulate(polylines, index_offset);
106
93
 
107
- segments.clear();
108
- segments.shrink_to_fit();
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
+ }
109
104
  }
110
105
 
111
- bool get_triangles (Polygon::TrianglePointList* triangles) const
106
+ bool get (Polygon::TrianglePointList* triangles) const
112
107
  {
108
+ triangulate();
113
109
  if (indices.empty()) return false;
114
110
 
115
111
  triangles->reserve(triangles->size() + indices.size());
@@ -118,6 +114,30 @@ namespace Rays
118
114
  return true;
119
115
  }
120
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
+ }
140
+
121
141
  private:
122
142
 
123
143
  struct Segment
@@ -165,13 +185,40 @@ namespace Rays
165
185
 
166
186
  typedef std::vector<Polyline> PolylineList;
167
187
 
168
- std::vector<Segment> segments;
169
-
170
188
  std::vector<Point> points;
171
189
 
172
- std::vector<uint32_t> indices;
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();
219
+ }
173
220
 
174
- void triangulate (const PolylineList& polylines, size_t index_offset)
221
+ void triangulate (const PolylineList& polylines, size_t index_offset) const
175
222
  {
176
223
  if (polylines.empty()) return;
177
224
 
@@ -180,17 +227,17 @@ namespace Rays
180
227
  indices.emplace_back(index_offset + index);
181
228
  }
182
229
 
183
- };// Triangulator
230
+ };// Triangles
184
231
 
185
232
 
186
233
  struct Polygon::Data
187
234
  {
188
235
 
189
- LineList lines;
236
+ PolylineList polylines;
190
237
 
191
- mutable std::unique_ptr<Bounds> pbounds;
238
+ mutable std::unique_ptr<Bounds> pbounds;
192
239
 
193
- mutable std::unique_ptr<Triangulator> ptriangulator;
240
+ mutable std::unique_ptr<Triangles> ptriangles;
194
241
 
195
242
  virtual ~Data ()
196
243
  {
@@ -200,14 +247,14 @@ namespace Rays
200
247
  {
201
248
  if (!pbounds)
202
249
  {
203
- if (lines.empty())
250
+ if (polylines.empty())
204
251
  pbounds.reset(new Bounds(-1, -1, -1));
205
252
  else
206
253
  {
207
- pbounds.reset(new Bounds(lines[0][0], 0));
208
- for (const auto& line : lines)
254
+ pbounds.reset(new Bounds(polylines[0][0], 0));
255
+ for (const auto& polyline : polylines)
209
256
  {
210
- for (const auto& point : line)
257
+ for (const auto& point : polyline)
211
258
  *pbounds |= point;
212
259
  }
213
260
  }
@@ -215,48 +262,24 @@ namespace Rays
215
262
  return *pbounds;
216
263
  }
217
264
 
218
- void append (const Polyline& polyline, bool hole = false)
265
+ void append (const Polyline& polyline)
219
266
  {
220
267
  if (polyline.empty())
221
268
  return;
222
269
 
223
- lines.emplace_back(polyline, hole);
224
- pbounds.reset();
225
- }
226
-
227
- void append (const Line& line)
228
- {
229
- if (line.empty())
230
- return;
231
-
232
- lines.emplace_back(line);
233
- pbounds.reset();
270
+ polylines.emplace_back(polyline);
234
271
  }
235
272
 
236
273
  bool triangulate (TrianglePointList* triangles) const
237
274
  {
238
- assert(triangles);
239
-
240
- if (!ptriangulator)
241
- {
242
- ptriangulator.reset(new Triangulator(count_points_for_triangulation()));
243
- auto& t = *ptriangulator;
244
-
245
- for (const auto& line : lines)
246
- {
247
- size_t n = t.begin(line.hole());
248
- for (const auto& point : line)
249
- t.append(point);
250
- t.end(n);
251
- }
252
- t.triangulate();
253
- }
254
-
255
275
  triangles->clear();
256
- return ptriangulator->get_triangles(triangles);
276
+ return this->triangles().get(triangles);
257
277
  }
258
278
 
259
- virtual void fill (Painter* painter, const Color& color) const = 0;
279
+ virtual void fill (Painter* painter, const Color& color) const
280
+ {
281
+ triangles().draw(painter, color);
282
+ }
260
283
 
261
284
  virtual void stroke (
262
285
  const Polygon& polygon, Painter* painter, const Color& color) const
@@ -275,20 +298,31 @@ namespace Rays
275
298
 
276
299
  private:
277
300
 
301
+ Triangles& triangles () const
302
+ {
303
+ if (!ptriangles)
304
+ {
305
+ ptriangles.reset(new Triangles(count_points_for_triangulation()));
306
+ for (const auto& polyline : polylines)
307
+ ptriangles->append(polyline);
308
+ }
309
+ return *ptriangles;
310
+ }
311
+
278
312
  size_t count_points_for_triangulation () const
279
313
  {
280
314
  size_t count = 0;
281
- for (const auto& line : lines)
315
+ for (const auto& polyline : polylines)
282
316
  {
283
- if (can_triangulate(line))
284
- count += line.size();
317
+ if (can_triangulate(polyline))
318
+ count += polyline.size();
285
319
  }
286
320
  return count;
287
321
  }
288
322
 
289
- bool can_triangulate (const Line& line) const
323
+ bool can_triangulate (const Polyline& polyline) const
290
324
  {
291
- return (line.fill() || line.hole()) && line.size() >= 3;
325
+ return (polyline.fill() || polyline.hole()) && polyline.size() >= 3;
292
326
  }
293
327
 
294
328
  void stroke_with_width (
@@ -349,11 +383,11 @@ namespace Rays
349
383
  {
350
384
  assert(painter && color);
351
385
 
352
- for (const auto& line : lines)
386
+ for (const auto& polyline : polylines)
353
387
  {
354
- Painter_draw_polygon(
355
- painter, line.loop() ? GL_LINE_LOOP : GL_LINE_STRIP, color,
356
- &line[0], line.size());
388
+ Painter_draw(
389
+ painter, polyline.loop() ? GL_LINE_LOOP : GL_LINE_STRIP, color,
390
+ &polyline[0], polyline.size());
357
391
  }
358
392
  }
359
393
 
@@ -419,14 +453,14 @@ namespace Rays
419
453
  assert(clipper);
420
454
 
421
455
  clip::Path path;
422
- for (const auto& line : polygon)
456
+ for (const auto& polyline : polygon)
423
457
  {
424
- if (!line) continue;
458
+ if (!polyline) continue;
425
459
 
426
- Polyline_get_path(&path, line, line.hole());
460
+ Polyline_get_path(&path, polyline, polyline.hole());
427
461
  if (path.empty()) continue;
428
462
 
429
- clipper->AddPath(path, type, line.loop());
463
+ clipper->AddPath(path, type, polyline.loop());
430
464
  }
431
465
  }
432
466
 
@@ -465,7 +499,7 @@ namespace Rays
465
499
  static bool
466
500
  add_polyline_to_offsetter (
467
501
  clip::ClipperOffset* offsetter, const Polyline& polyline,
468
- CapType cap, JoinType join, bool hole, bool fill)
502
+ CapType cap, JoinType join, bool fill, bool hole)
469
503
  {
470
504
  assert(offsetter);
471
505
 
@@ -486,10 +520,10 @@ namespace Rays
486
520
  assert(offsetter);
487
521
 
488
522
  bool added = false;
489
- for (const auto& line : polygon.self->lines)
523
+ for (const auto& polyline : polygon.self->polylines)
490
524
  {
491
525
  added |= add_polyline_to_offsetter(
492
- offsetter, line, cap, join, line.hole(), true);
526
+ offsetter, polyline, cap, join, true, polyline.hole());
493
527
  }
494
528
  return added;
495
529
  }
@@ -502,12 +536,11 @@ namespace Rays
502
536
  if (node.Contour.empty() || node.IsHole())
503
537
  return false;
504
538
 
505
- Polyline polyline;
506
- Polyline_create(&polyline, node.Contour, !node.IsOpen(), false);
539
+ Polyline polyline = Polyline_create(node.Contour, !node.IsOpen());
507
540
  if (!polyline)
508
541
  return false;
509
542
 
510
- polygon->self->append(polyline, false);
543
+ polygon->self->append(polyline);
511
544
  return true;
512
545
  }
513
546
 
@@ -521,12 +554,11 @@ namespace Rays
521
554
  if (!child->IsHole())
522
555
  return;
523
556
 
524
- Polyline polyline;
525
- Polyline_create(&polyline, child->Contour, !child->IsOpen(), true);
557
+ Polyline polyline = Polyline_create(child->Contour, !child->IsOpen(), true);
526
558
  if (!polyline)
527
559
  continue;
528
560
 
529
- polygon->self->append(polyline, true);
561
+ polygon->self->append(polyline);
530
562
  }
531
563
  }
532
564
 
@@ -605,26 +637,6 @@ namespace Rays
605
637
  }
606
638
 
607
639
 
608
- struct PolygonData : public Polygon::Data
609
- {
610
-
611
- mutable Polygon::TrianglePointList triangles;
612
-
613
- void fill (Painter* painter, const Color& color) const
614
- {
615
- if (triangles.empty())
616
- {
617
- if (!triangulate(&triangles))
618
- return;
619
- }
620
-
621
- Painter_draw_polygon(
622
- painter, GL_TRIANGLES, color, &triangles[0], triangles.size());
623
- }
624
-
625
- };// PolygonData
626
-
627
-
628
640
  struct RectData : public Polygon::Data
629
641
  {
630
642
 
@@ -652,11 +664,11 @@ namespace Rays
652
664
 
653
665
  void fill (Painter* painter, const Color& color) const
654
666
  {
655
- if (lines.size() != 1)
667
+ if (polylines.size() != 1)
656
668
  invalid_state_error(__FILE__, __LINE__);
657
669
 
658
- const auto& outline = lines[0];
659
- Painter_draw_polygon(
670
+ const auto& outline = polylines[0];
671
+ Painter_draw(
660
672
  painter, GL_TRIANGLE_FAN, color, &outline[0], outline.size());
661
673
  }
662
674
 
@@ -787,10 +799,10 @@ namespace Rays
787
799
  };// RectData
788
800
 
789
801
 
790
- struct EllipseData : public PolygonData
802
+ struct EllipseData : public Polygon::Data
791
803
  {
792
804
 
793
- typedef PolygonData Super;
805
+ typedef Polygon::Data Super;
794
806
 
795
807
  GLenum mode = 0;
796
808
 
@@ -813,7 +825,7 @@ namespace Rays
813
825
 
814
826
  void fill (Painter* painter, const Color& color) const
815
827
  {
816
- if (lines.size() <= 0)
828
+ if (polylines.size() <= 0)
817
829
  invalid_state_error(__FILE__, __LINE__);
818
830
 
819
831
  if (mode == 0)
@@ -822,11 +834,11 @@ namespace Rays
822
834
  return;
823
835
  }
824
836
 
825
- if (lines.size() >= 2)
837
+ if (polylines.size() >= 2)
826
838
  invalid_state_error(__FILE__, __LINE__);
827
839
 
828
- const auto& outline = lines[0];
829
- 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());
830
842
  }
831
843
 
832
844
  private:
@@ -881,7 +893,7 @@ namespace Rays
881
893
  hole_x, hole_y, hole_size.x, hole_size.y,
882
894
  radian_from, radian_to, nsegment, seg));
883
895
  }
884
- append(Polyline(&points[0], points.size(), true), true);
896
+ append(Polyline(&points[0], points.size(), true, NULL, NULL, true));
885
897
  }
886
898
  }
887
899
 
@@ -946,50 +958,51 @@ namespace Rays
946
958
  };// EllipseData
947
959
 
948
960
 
949
- static const char*
950
- get_draw_mode_name (DrawMode mode)
961
+ Polygon
962
+ create_point (coord x, coord y)
951
963
  {
952
- switch (mode)
953
- {
954
- case DRAW_POINTS: return "DRAW_POINTS";
955
- case DRAW_LINES: return "DRAW_LINES";
956
- case DRAW_LINE_STRIP: return "DRAW_LINE_STRIP";
957
- case DRAW_TRIANGLES: return "DRAW_TRIANGLES";
958
- case DRAW_TRIANGLE_STRIP: return "DRAW_TRIANGLE_STRIP";
959
- case DRAW_TRIANGLE_FAN: return "DRAW_TRIANGLE_FAN";
960
- case DRAW_QUADS: return "DRAW_QUADS";
961
- case DRAW_QUAD_STRIP: return "DRAW_QUAD_STRIP";
962
- case DRAW_POLYGON: return "DRAW_POLYGON";
963
- default: argument_error(__FILE__, __LINE__, "unknown draw mode");
964
- }
964
+ return create_point(Point(x, y));
965
965
  }
966
966
 
967
- static void
968
- create_polygon (Polygon* polygon, const Point* points, size_t size, bool loop)
967
+ Polygon
968
+ create_point (const Point& point)
969
969
  {
970
- polygon->self->append(Polyline(points, size, loop, true));
970
+ return create_points(&point, 1);
971
971
  }
972
972
 
973
- static void
974
- create_points (Polygon* polygon, const Point* points, size_t size)
973
+ Polygon
974
+ create_points (const Point* points, size_t size)
975
975
  {
976
+ Polygon p;
976
977
  for (size_t i = 0; i < size; ++i)
977
- polygon->self->append(Polyline(&points[i], 1, false, false));
978
+ p.self->append(Polyline(&points[i], 1, false, false));
979
+ return p;
978
980
  }
979
981
 
980
- static void
981
- create_lines (Polygon* polygon, const Point* points, size_t size)
982
+ Polygon
983
+ create_line (coord x1, coord y1, coord x2, coord y2)
982
984
  {
983
- for (size_t i = 0; i + 1 < size; i += 2)
984
- polygon->self->append(Polyline(&points[i], 2, false, false));
985
+ const Point points[] = {
986
+ Point(x1, y1),
987
+ Point(x2, y2)
988
+ };
989
+ return create_line(points, 2);
985
990
  }
986
991
 
987
- static void
988
- create_line_strip (
989
- Polygon* polygon, const Point* points, size_t size, bool loop)
992
+ Polygon
993
+ create_line (const Point& p1, const Point& p2)
994
+ {
995
+ const Point points[] = {p1, p2};
996
+ return create_line(points, 2);
997
+ }
998
+
999
+ Polygon
1000
+ create_line (const Point* points, size_t size, bool loop)
990
1001
  {
991
- if (!loop || size < 3)
992
- polygon->self->append(Polyline(points, size, loop, false));
1002
+ Polygon p;(points, size, loop);
1003
+ //if (!loop || size < 3)
1004
+ p.self->append(Polyline(points, size, loop, false));
1005
+ #if 0
993
1006
  else
994
1007
  {
995
1008
  std::vector<Point> array;
@@ -998,105 +1011,133 @@ namespace Rays
998
1011
  array.emplace_back(points[0]);
999
1012
  polygon->self->append(Polyline(&array[0], array.size(), true, false));
1000
1013
  }
1014
+ #endif
1015
+ return p;
1001
1016
  }
1002
1017
 
1003
- static void
1018
+ Polygon
1019
+ create_line (const Polyline& polyline)
1020
+ {
1021
+ return Polygon(polyline);
1022
+ }
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
1004
1050
  create_triangles (
1005
- Polygon* polygon, const Point* points, size_t size, bool loop)
1051
+ const Point* points, size_t size, bool loop,
1052
+ const Color* colors, const Coord3* texcoords)
1006
1053
  {
1054
+ Polygon p;
1007
1055
  for (size_t i = 0; i + 2 < size; i += 3)
1008
- polygon->self->append(Polyline(&points[i], 3, loop, true));
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;
1009
1063
  }
1010
1064
 
1011
- static void
1012
- create_triangle_strip (Polygon* polygon, const Point* points, size_t size)
1065
+ Polygon
1066
+ create_triangle_strip (
1067
+ const Point* points, size_t size,
1068
+ const Color* colors, const Coord3* texcoords)
1013
1069
  {
1014
- if (size < 3) return;
1070
+ Polygon p;
1071
+ if (size < 3) return p;
1015
1072
 
1016
1073
  size_t last = size - 1;
1017
1074
  size_t in_last = last % 2 == 0 ? last - 1 : last;
1018
1075
  size_t out_last = last % 2 == 0 ? last : last - 1;
1019
1076
 
1020
- std::vector<Point> array;
1021
- array.emplace_back(points[0]);
1077
+ std::vector<Point> points_;
1078
+ points_.reserve(size);
1079
+ points_.emplace_back(points[0]);
1022
1080
  for (size_t i = 1; i <= in_last; i += 2)
1023
- array.emplace_back(points[i]);
1081
+ points_.emplace_back(points[i]);
1024
1082
  for (size_t i = out_last; i >= 2; i -= 2)
1025
- array.emplace_back(points[i]);
1083
+ points_.emplace_back(points[i]);
1026
1084
 
1027
- polygon->self->append(Polyline(&array[0], array.size(), true));
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));
1028
1113
  if (size >= 4)
1029
- polygon->self->append(Polyline(&points[1], size - 2));
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;
1030
1121
  }
1031
1122
 
1032
- static void
1033
- create_triangle_fan (Polygon* polygon, const Point* points, size_t size)
1123
+ Polygon
1124
+ create_triangle_fan (
1125
+ const Point* points, size_t size,
1126
+ const Color* colors, const Coord3* texcoords)
1034
1127
  {
1035
- create_polygon(polygon, points, size, true);
1128
+ Polygon p(points, size, true, colors, texcoords);
1036
1129
 
1037
1130
  Point array[2];
1038
1131
  array[0] = points[0];
1039
1132
  for (size_t i = 2; i < size - 1; ++i)
1040
1133
  {
1041
1134
  array[1] = points[i];
1042
- polygon->self->append(Polyline(&array[0], 2));
1135
+ p.self->append(Polyline(
1136
+ &array[0], 2, false,
1137
+ colors ? &colors[0] : NULL,
1138
+ texcoords ? &texcoords[0] : NULL));
1043
1139
  }
1044
- }
1045
-
1046
- static void
1047
- create_quads (Polygon* polygon, const Point* points, size_t size, bool loop)
1048
- {
1049
- for (size_t i = 0; i + 3 < size; i += 4)
1050
- polygon->self->append(Polyline(&points[i], 4, loop, true));
1051
- }
1052
-
1053
- static void
1054
- create_quad_strip (Polygon* polygon, const Point* points, size_t size)
1055
- {
1056
- if (size < 4) return;
1057
-
1058
- if (size % 2 != 0) --size;
1059
- size_t in_last = size - 2;
1060
- size_t out_last = size - 1;
1061
-
1062
- std::vector<Point> array;
1063
- for (size_t i = 0; i <= in_last; i += 2)
1064
- array.emplace_back(points[i]);
1065
- for (int i = (int) out_last; i >= 1; i -= 2)
1066
- array.emplace_back(points[i]);
1067
-
1068
- polygon->self->append(Polyline(&array[0], array.size(), true));
1069
- for (size_t i = 2; i < in_last; i += 2)
1070
- polygon->self->append(Polyline(&points[i], 2));
1071
- }
1072
-
1073
- Polygon
1074
- create_line (coord x1, coord y1, coord x2, coord y2)
1075
- {
1076
- const Point points[] = {
1077
- Point(x1, y1),
1078
- Point(x2, y2)
1079
- };
1080
- return create_line(points, 2);
1081
- }
1082
-
1083
- Polygon
1084
- create_line (const Point& p1, const Point& p2)
1085
- {
1086
- const Point points[] = {p1, p2};
1087
- return create_line(points, 2);
1088
- }
1089
-
1090
- Polygon
1091
- create_line (const Point* points, size_t size, bool loop)
1092
- {
1093
- return Polygon(points, size, loop);
1094
- }
1095
-
1096
- Polygon
1097
- create_line (const Polyline& polyline)
1098
- {
1099
- return Polygon(polyline);
1140
+ return p;
1100
1141
  }
1101
1142
 
1102
1143
  Polygon
@@ -1148,6 +1189,96 @@ namespace Rays
1148
1189
  nsegment);
1149
1190
  }
1150
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
+
1151
1282
  Polygon
1152
1283
  create_ellipse (
1153
1284
  coord x, coord y, coord width, coord height,
@@ -1342,54 +1473,36 @@ namespace Rays
1342
1473
 
1343
1474
 
1344
1475
  Polygon::Polygon ()
1345
- : self(new PolygonData())
1346
1476
  {
1347
1477
  }
1348
1478
 
1349
- Polygon::Polygon (const Point* points, size_t size, bool loop)
1350
- : self(new PolygonData())
1351
- {
1352
- if (!points || size <= 0) return;
1353
-
1354
- create_polygon(this, points, size, loop);
1355
- }
1356
-
1357
- Polygon::Polygon (DrawMode mode, const Point* points, size_t size, bool loop)
1358
- : self(new PolygonData())
1479
+ Polygon::Polygon (
1480
+ const Point* points, size_t size, bool loop,
1481
+ const Color* colors, const Coord3* texcoords)
1359
1482
  {
1360
1483
  if (!points || size <= 0) return;
1361
1484
 
1362
- switch (mode)
1363
- {
1364
- case DRAW_POINTS: create_points( this, points, size); break;
1365
- case DRAW_LINES: create_lines( this, points, size); break;
1366
- case DRAW_LINE_STRIP: create_line_strip( this, points, size, loop); break;
1367
- case DRAW_TRIANGLES: create_triangles( this, points, size, loop); break;
1368
- case DRAW_TRIANGLE_STRIP: create_triangle_strip(this, points, size); break;
1369
- case DRAW_TRIANGLE_FAN: create_triangle_fan( this, points, size); break;
1370
- case DRAW_QUADS: create_quads( this, points, size, loop); break;
1371
- case DRAW_QUAD_STRIP: create_quad_strip( this, points, size); break;
1372
- case DRAW_POLYGON: create_polygon( this, points, size, loop); break;
1373
- default:
1374
- argument_error(
1375
- __FILE__, __LINE__,
1376
- Xot::stringf("unknown draw mode '%s'", get_draw_mode_name(mode)));
1377
- }
1485
+ self->append(Polyline(points, size, loop, true, colors, texcoords));
1378
1486
  }
1379
1487
 
1380
1488
  Polygon::Polygon (const Polyline& polyline)
1381
- : self(new PolygonData())
1382
1489
  {
1490
+ if (polyline.hole())
1491
+ argument_error(__FILE__, __LINE__);
1492
+
1383
1493
  self->append(polyline);
1384
1494
  }
1385
1495
 
1386
- Polygon::Polygon (const Line* lines, size_t size)
1387
- : self(new PolygonData())
1496
+ Polygon::Polygon (const Polyline* polylines, size_t size)
1388
1497
  {
1389
- if (!lines || size <= 0) return;
1498
+ if (!polylines || size <= 0)
1499
+ return;
1500
+
1501
+ if (polylines[0].hole())
1502
+ argument_error(__FILE__, __LINE__);
1390
1503
 
1391
1504
  for (size_t i = 0; i < size; ++i)
1392
- self->append(lines[i]);
1505
+ self->append(polylines[i]);
1393
1506
  }
1394
1507
 
1395
1508
  Polygon::Polygon (Data* data)
@@ -1418,7 +1531,7 @@ namespace Rays
1418
1531
  size_t
1419
1532
  Polygon::size () const
1420
1533
  {
1421
- return self->lines.size();
1534
+ return self->polylines.size();
1422
1535
  }
1423
1536
 
1424
1537
  bool
@@ -1426,9 +1539,9 @@ namespace Rays
1426
1539
  {
1427
1540
  if (deep)
1428
1541
  {
1429
- for (const auto& line : self->lines)
1542
+ for (const auto& polyline : self->polylines)
1430
1543
  {
1431
- if (!line.empty())
1544
+ if (!polyline.empty())
1432
1545
  return false;
1433
1546
  }
1434
1547
  }
@@ -1439,29 +1552,29 @@ namespace Rays
1439
1552
  Polygon::const_iterator
1440
1553
  Polygon::begin () const
1441
1554
  {
1442
- return self->lines.begin();
1555
+ return self->polylines.begin();
1443
1556
  }
1444
1557
 
1445
1558
  Polygon::const_iterator
1446
1559
  Polygon::end () const
1447
1560
  {
1448
- return self->lines.end();
1561
+ return self->polylines.end();
1449
1562
  }
1450
1563
 
1451
- const Polygon::Line&
1564
+ const Polyline&
1452
1565
  Polygon::operator [] (size_t index) const
1453
1566
  {
1454
- return self->lines[index];
1567
+ return self->polylines[index];
1455
1568
  }
1456
1569
 
1457
1570
  Polygon::operator bool () const
1458
1571
  {
1459
- if (self->lines.empty())
1572
+ if (self->polylines.empty())
1460
1573
  return true;
1461
1574
 
1462
- for (const auto& line : self->lines)
1575
+ for (const auto& polyline : self->polylines)
1463
1576
  {
1464
- if (line) return true;
1577
+ if (polyline) return true;
1465
1578
  }
1466
1579
 
1467
1580
  return false;
@@ -1479,10 +1592,23 @@ namespace Rays
1479
1592
  return self->triangulate(triangles);
1480
1593
  }
1481
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
+
1482
1605
  Polygon
1483
1606
  operator + (const Polygon& lhs, const Polygon& rhs)
1484
1607
  {
1485
- 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());
1486
1612
  }
1487
1613
 
1488
1614
  Polygon
@@ -1518,41 +1644,4 @@ namespace Rays
1518
1644
  }
1519
1645
 
1520
1646
 
1521
- Polygon::Line::Line ()
1522
- : Super(), hole_(false)
1523
- {
1524
- }
1525
-
1526
- Polygon::Line::Line (const Point* points, size_t size, bool loop, bool hole)
1527
- : Super(points, size, loop), hole_(hole)
1528
- {
1529
- if (!*this)
1530
- argument_error(__FILE__, __LINE__);
1531
- }
1532
-
1533
- Polygon::Line::Line (const Polyline& polyline, bool hole)
1534
- : Super(polyline), hole_(hole)
1535
- {
1536
- if (!*this)
1537
- argument_error(__FILE__, __LINE__);
1538
- }
1539
-
1540
- bool
1541
- Polygon::Line::hole () const
1542
- {
1543
- return hole_;
1544
- }
1545
-
1546
- Polygon::Line::operator bool () const
1547
- {
1548
- return Super::operator bool() && (loop() || !hole());
1549
- }
1550
-
1551
- bool
1552
- Polygon::Line::operator ! () const
1553
- {
1554
- return !operator bool();
1555
- }
1556
-
1557
-
1558
1647
  }// Rays