rays 0.1.47 → 0.1.48

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