rays 0.1.47 → 0.1.49

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) 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/color.cpp +11 -0
  5. data/.doc/ext/rays/defs.cpp +32 -8
  6. data/.doc/ext/rays/font.cpp +50 -2
  7. data/.doc/ext/rays/image.cpp +3 -3
  8. data/.doc/ext/rays/matrix.cpp +65 -7
  9. data/.doc/ext/rays/native.cpp +2 -4
  10. data/.doc/ext/rays/painter.cpp +117 -9
  11. data/.doc/ext/rays/point.cpp +1 -11
  12. data/.doc/ext/rays/polygon.cpp +133 -97
  13. data/.doc/ext/rays/polyline.cpp +89 -10
  14. data/.doc/ext/rays/rays.cpp +80 -0
  15. data/.doc/ext/rays/{noise.cpp → util.cpp} +2 -2
  16. data/ChangeLog.md +46 -0
  17. data/VERSION +1 -1
  18. data/ext/rays/bitmap.cpp +288 -46
  19. data/ext/rays/camera.cpp +2 -2
  20. data/ext/rays/color.cpp +13 -1
  21. data/ext/rays/defs.cpp +32 -8
  22. data/ext/rays/defs.h +56 -3
  23. data/ext/rays/font.cpp +56 -4
  24. data/ext/rays/image.cpp +3 -3
  25. data/ext/rays/matrix.cpp +69 -7
  26. data/ext/rays/native.cpp +2 -4
  27. data/ext/rays/painter.cpp +132 -13
  28. data/ext/rays/point.cpp +1 -12
  29. data/ext/rays/polygon.cpp +136 -99
  30. data/ext/rays/polyline.cpp +95 -9
  31. data/ext/rays/rays.cpp +80 -0
  32. data/ext/rays/{noise.cpp → util.cpp} +2 -2
  33. data/include/rays/color.h +3 -1
  34. data/include/rays/defs.h +24 -26
  35. data/include/rays/font.h +17 -3
  36. data/include/rays/image.h +1 -1
  37. data/include/rays/matrix.h +24 -0
  38. data/include/rays/painter.h +24 -0
  39. data/include/rays/polygon.h +68 -43
  40. data/include/rays/polyline.h +17 -2
  41. data/include/rays/ruby/polygon.h +0 -11
  42. data/include/rays/ruby/rays.h +4 -0
  43. data/include/rays/{noise.h → util.h} +2 -2
  44. data/lib/rays/color.rb +7 -1
  45. data/lib/rays/font.rb +1 -1
  46. data/lib/rays/image.rb +11 -1
  47. data/lib/rays/matrix.rb +16 -0
  48. data/lib/rays/painter.rb +18 -7
  49. data/lib/rays/point.rb +5 -1
  50. data/lib/rays/polygon.rb +44 -35
  51. data/lib/rays/polyline.rb +54 -8
  52. data/lib/rays.rb +0 -1
  53. data/rays.gemspec +2 -2
  54. data/src/color.cpp +11 -2
  55. data/src/font.cpp +37 -18
  56. data/src/font.h +6 -5
  57. data/src/image.cpp +58 -14
  58. data/src/ios/font.mm +89 -32
  59. data/src/ios/helper.h +2 -2
  60. data/src/ios/helper.mm +2 -2
  61. data/src/matrix.cpp +45 -0
  62. data/src/osx/font.mm +93 -33
  63. data/src/osx/helper.h +2 -2
  64. data/src/osx/helper.mm +2 -2
  65. data/src/painter.cpp +246 -114
  66. data/src/painter.h +11 -3
  67. data/src/polygon.cpp +431 -332
  68. data/src/polyline.cpp +138 -27
  69. data/src/polyline.h +3 -5
  70. data/src/shader.cpp +36 -4
  71. data/src/shader.h +1 -1
  72. data/src/texture.cpp +23 -4
  73. data/src/texture.h +2 -0
  74. data/src/{noise.cpp → util.cpp} +1 -1
  75. data/src/win32/font.cpp +1 -1
  76. data/test/test_bitmap.rb +12 -5
  77. data/test/test_color.rb +25 -4
  78. data/test/test_font.rb +23 -2
  79. data/test/test_image.rb +44 -18
  80. data/test/test_matrix.rb +22 -0
  81. data/test/test_painter.rb +27 -0
  82. data/test/test_point.rb +1 -1
  83. data/test/test_polygon.rb +52 -45
  84. data/test/test_polyline.rb +191 -72
  85. metadata +12 -18
  86. data/.doc/ext/rays/polygon_line.cpp +0 -97
  87. data/ext/rays/polygon_line.cpp +0 -100
  88. data/lib/rays/polygon_line.rb +0 -33
  89. 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;
173
195
 
174
- void triangulate (const PolylineList& polylines, size_t index_offset)
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
+ }
220
+
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
 
@@ -397,7 +431,7 @@ namespace Rays
397
431
  #endif
398
432
 
399
433
  static uint
400
- get_nsegment (
434
+ get_nsegment_for_angle (
401
435
  uint nsegment, uint nsegment_min, float angle_from, float angle_to)
402
436
  {
403
437
  float angle = angle_to - angle_from;
@@ -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
 
@@ -688,7 +700,7 @@ namespace Rays
688
700
  left_top != 0 || right_top != 0 ||
689
701
  left_bottom != 0 || right_bottom != 0);
690
702
 
691
- nsegment = get_nsegment(nsegment, 1, 0, 90);
703
+ nsegment = get_nsegment_for_angle(nsegment, 1, 0, 90);
692
704
 
693
705
  fix_rounds(
694
706
  &left_top, &right_top,
@@ -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:
@@ -851,7 +863,7 @@ namespace Rays
851
863
  {
852
864
  assert(width != 0 && height != 0);
853
865
 
854
- nsegment = get_nsegment(nsegment, 3, 0, 360);
866
+ nsegment = get_nsegment_for_angle(nsegment, 3, 0, 360);
855
867
 
856
868
  bool has_hole = hole_size != 0;
857
869
  float radian_from = Xot::deg2rad(0);
@@ -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
 
@@ -892,7 +904,7 @@ namespace Rays
892
904
  {
893
905
  assert(width != 0 && height != 0 && angle_from != angle_to);
894
906
 
895
- nsegment = get_nsegment(nsegment, 3, angle_from, angle_to);
907
+ nsegment = get_nsegment_for_angle(nsegment, 3, angle_from, angle_to);
896
908
 
897
909
  bool has_hole = hole_size != 0;
898
910
  float radian_from = Xot::deg2rad(angle_from);
@@ -946,50 +958,59 @@ 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
+ static const coord DELTA = 0.01;
977
+
978
+ Polygon p;
976
979
  for (size_t i = 0; i < size; ++i)
977
- polygon->self->append(Polyline(&points[i], 1, false, false));
980
+ {
981
+ // Polyline(&points[i], 1, false, false).expand() ignores CapType
982
+
983
+ coord x = points[i].x, y = points[i].y;
984
+ Point array[] = {{x, y}, {x + DELTA, y + DELTA}};
985
+ p.self->append(Polyline(array, 2, false, false));
986
+ }
987
+ return p;
978
988
  }
979
989
 
980
- static void
981
- create_lines (Polygon* polygon, const Point* points, size_t size)
990
+ Polygon
991
+ create_line (coord x1, coord y1, coord x2, coord y2)
982
992
  {
983
- for (size_t i = 0; i + 1 < size; i += 2)
984
- polygon->self->append(Polyline(&points[i], 2, false, false));
993
+ const Point points[] = {
994
+ Point(x1, y1),
995
+ Point(x2, y2)
996
+ };
997
+ return create_line(points, 2);
985
998
  }
986
999
 
987
- static void
988
- create_line_strip (
989
- Polygon* polygon, const Point* points, size_t size, bool loop)
1000
+ Polygon
1001
+ create_line (const Point& p1, const Point& p2)
990
1002
  {
991
- if (!loop || size < 3)
992
- polygon->self->append(Polyline(points, size, loop, false));
1003
+ const Point points[] = {p1, p2};
1004
+ return create_line(points, 2);
1005
+ }
1006
+
1007
+ Polygon
1008
+ create_line (const Point* points, size_t size, bool loop)
1009
+ {
1010
+ Polygon p;(points, size, loop);
1011
+ //if (!loop || size < 3)
1012
+ p.self->append(Polyline(points, size, loop, false));
1013
+ #if 0
993
1014
  else
994
1015
  {
995
1016
  std::vector<Point> array;
@@ -998,105 +1019,133 @@ namespace Rays
998
1019
  array.emplace_back(points[0]);
999
1020
  polygon->self->append(Polyline(&array[0], array.size(), true, false));
1000
1021
  }
1022
+ #endif
1023
+ return p;
1001
1024
  }
1002
1025
 
1003
- static void
1026
+ Polygon
1027
+ create_line (const Polyline& polyline)
1028
+ {
1029
+ return Polygon(polyline);
1030
+ }
1031
+
1032
+ Polygon
1033
+ create_lines (const Point* points, size_t size)
1034
+ {
1035
+ Polygon p;
1036
+ for (size_t i = 0; i + 1 < size; i += 2)
1037
+ p.self->append(Polyline(&points[i], 2, false, false));
1038
+ return p;
1039
+ }
1040
+
1041
+ Polygon
1042
+ create_triangle (
1043
+ coord x1, coord y1, coord x2, coord y2, coord x3, coord y3, bool loop)
1044
+ {
1045
+ const Point points[] = {Point(x1, y1), Point(x2, y2), Point(x3, y3)};
1046
+ return create_triangles(points, 3, loop);
1047
+ }
1048
+
1049
+ Polygon
1050
+ create_triangle (
1051
+ const Point& p1, const Point& p2, const Point& p3, bool loop)
1052
+ {
1053
+ const Point points[] = {p1, p2, p3};
1054
+ return create_triangles(points, 3, loop);
1055
+ }
1056
+
1057
+ Polygon
1004
1058
  create_triangles (
1005
- Polygon* polygon, const Point* points, size_t size, bool loop)
1059
+ const Point* points, size_t size, bool loop,
1060
+ const Color* colors, const Coord3* texcoords)
1006
1061
  {
1062
+ Polygon p;
1007
1063
  for (size_t i = 0; i + 2 < size; i += 3)
1008
- polygon->self->append(Polyline(&points[i], 3, loop, true));
1064
+ {
1065
+ p.self->append(Polyline(
1066
+ &points[i], 3, loop, true,
1067
+ colors ? &colors[i] : NULL,
1068
+ texcoords ? &texcoords[i] : NULL));
1069
+ }
1070
+ return p;
1009
1071
  }
1010
1072
 
1011
- static void
1012
- create_triangle_strip (Polygon* polygon, const Point* points, size_t size)
1073
+ Polygon
1074
+ create_triangle_strip (
1075
+ const Point* points, size_t size,
1076
+ const Color* colors, const Coord3* texcoords)
1013
1077
  {
1014
- if (size < 3) return;
1078
+ Polygon p;
1079
+ if (size < 3) return p;
1015
1080
 
1016
1081
  size_t last = size - 1;
1017
1082
  size_t in_last = last % 2 == 0 ? last - 1 : last;
1018
1083
  size_t out_last = last % 2 == 0 ? last : last - 1;
1019
1084
 
1020
- std::vector<Point> array;
1021
- array.emplace_back(points[0]);
1085
+ std::vector<Point> points_;
1086
+ points_.reserve(size);
1087
+ points_.emplace_back(points[0]);
1022
1088
  for (size_t i = 1; i <= in_last; i += 2)
1023
- array.emplace_back(points[i]);
1089
+ points_.emplace_back(points[i]);
1024
1090
  for (size_t i = out_last; i >= 2; i -= 2)
1025
- array.emplace_back(points[i]);
1091
+ points_.emplace_back(points[i]);
1092
+
1093
+ std::unique_ptr<std::vector<Color>> pcolors_;
1094
+ if (colors)
1095
+ {
1096
+ pcolors_.reset(new decltype(pcolors_)::element_type());
1097
+ pcolors_->reserve(size);
1098
+ pcolors_->emplace_back(colors[0]);
1099
+ for (size_t i = 1; i <= in_last; i += 2)
1100
+ pcolors_->emplace_back(colors[i]);
1101
+ for (size_t i = out_last; i >= 2; i -= 2)
1102
+ pcolors_->emplace_back(colors[i]);
1103
+ }
1104
+
1105
+ std::unique_ptr<std::vector<Coord3>> ptexcoords_;
1106
+ if (texcoords)
1107
+ {
1108
+ ptexcoords_.reset(new decltype(ptexcoords_)::element_type());
1109
+ ptexcoords_->reserve(size);
1110
+ ptexcoords_->emplace_back(texcoords[0]);
1111
+ for (size_t i = 1; i <= in_last; i += 2)
1112
+ ptexcoords_->emplace_back(texcoords[i]);
1113
+ for (size_t i = out_last; i >= 2; i -= 2)
1114
+ ptexcoords_->emplace_back(texcoords[i]);
1115
+ }
1026
1116
 
1027
- polygon->self->append(Polyline(&array[0], array.size(), true));
1117
+ p.self->append(Polyline(
1118
+ &points_[0], points_.size(), true,
1119
+ pcolors_ ? &(*pcolors_)[0] : NULL,
1120
+ ptexcoords_ ? &(*ptexcoords_)[0] : NULL));
1028
1121
  if (size >= 4)
1029
- polygon->self->append(Polyline(&points[1], size - 2));
1122
+ {
1123
+ p.self->append(Polyline(
1124
+ &points[1], size - 2, false,
1125
+ colors ? &colors[1] : NULL,
1126
+ texcoords ? &texcoords[1] : NULL));
1127
+ }
1128
+ return p;
1030
1129
  }
1031
1130
 
1032
- static void
1033
- create_triangle_fan (Polygon* polygon, const Point* points, size_t size)
1131
+ Polygon
1132
+ create_triangle_fan (
1133
+ const Point* points, size_t size,
1134
+ const Color* colors, const Coord3* texcoords)
1034
1135
  {
1035
- create_polygon(polygon, points, size, true);
1136
+ Polygon p(points, size, true, colors, texcoords);
1036
1137
 
1037
1138
  Point array[2];
1038
1139
  array[0] = points[0];
1039
1140
  for (size_t i = 2; i < size - 1; ++i)
1040
1141
  {
1041
1142
  array[1] = points[i];
1042
- polygon->self->append(Polyline(&array[0], 2));
1143
+ p.self->append(Polyline(
1144
+ &array[0], 2, false,
1145
+ colors ? &colors[0] : NULL,
1146
+ texcoords ? &texcoords[0] : NULL));
1043
1147
  }
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);
1148
+ return p;
1100
1149
  }
1101
1150
 
1102
1151
  Polygon
@@ -1148,6 +1197,96 @@ namespace Rays
1148
1197
  nsegment);
1149
1198
  }
1150
1199
 
1200
+ Polygon
1201
+ create_quad (
1202
+ coord x1, coord y1, coord x2, coord y2,
1203
+ coord x3, coord y3, coord x4, coord y4,
1204
+ bool loop)
1205
+ {
1206
+ Point points[] = {Point(x1, y1), Point(x2, y2), Point(x3, y3), Point(x4, y4)};
1207
+ return create_quads(points, 4, loop);
1208
+ }
1209
+
1210
+ Polygon
1211
+ create_quad (
1212
+ const Point& p1, const Point& p2, const Point& p3, const Point& p4,
1213
+ bool loop)
1214
+ {
1215
+ Point points[] = {p1, p2, p3, p4};
1216
+ return create_quads(points, 4, loop);
1217
+ }
1218
+
1219
+ Polygon
1220
+ create_quads (
1221
+ const Point* points, size_t size, bool loop,
1222
+ const Color* colors, const Coord3* texcoords)
1223
+ {
1224
+ Polygon p;
1225
+ for (size_t i = 0; i + 3 < size; i += 4)
1226
+ {
1227
+ p.self->append(Polyline(
1228
+ &points[i], 4, loop, true,
1229
+ colors ? &colors[i] : NULL,
1230
+ texcoords ? &texcoords[i] : NULL));
1231
+ }
1232
+ return p;
1233
+ }
1234
+
1235
+ Polygon
1236
+ create_quad_strip (
1237
+ const Point* points, size_t size,
1238
+ const Color* colors, const Coord3* texcoords)
1239
+ {
1240
+ Polygon p;
1241
+ if (size < 4) return p;
1242
+
1243
+ if (size % 2 != 0) --size;
1244
+ size_t in_last = size - 2;
1245
+ size_t out_last = size - 1;
1246
+
1247
+ std::vector<Point> points_;
1248
+ points_.reserve(size);
1249
+ for (size_t i = 0; i <= in_last; i += 2)
1250
+ points_.emplace_back(points[i]);
1251
+ for (int i = (int) out_last; i >= 1; i -= 2)
1252
+ points_.emplace_back(points[i]);
1253
+
1254
+ std::unique_ptr<std::vector<Color>> pcolors_;
1255
+ if (colors)
1256
+ {
1257
+ pcolors_.reset(new decltype(pcolors_)::element_type());
1258
+ pcolors_->reserve(size);
1259
+ for (size_t i = 0; i <= in_last; i += 2)
1260
+ pcolors_->emplace_back(colors[i]);
1261
+ for (int i = (int) out_last; i >= 1; i -= 2)
1262
+ pcolors_->emplace_back(colors[i]);
1263
+ }
1264
+
1265
+ std::unique_ptr<std::vector<Coord3>> ptexcoords_;
1266
+ if (texcoords)
1267
+ {
1268
+ ptexcoords_.reset(new decltype(ptexcoords_)::element_type());
1269
+ ptexcoords_->reserve(size);
1270
+ for (size_t i = 0; i <= in_last; i += 2)
1271
+ ptexcoords_->emplace_back(texcoords[i]);
1272
+ for (int i = (int) out_last; i >= 1; i -= 2)
1273
+ ptexcoords_->emplace_back(texcoords[i]);
1274
+ }
1275
+
1276
+ p.self->append(Polyline(
1277
+ &points_[0], points_.size(), true,
1278
+ pcolors_ ? &(*pcolors_)[0] : NULL,
1279
+ ptexcoords_ ? &(*ptexcoords_)[0] : NULL));
1280
+ for (size_t i = 2; i < in_last; i += 2)
1281
+ {
1282
+ p.self->append(Polyline(
1283
+ &points[i], 2, false,
1284
+ colors ? &colors[i] : NULL,
1285
+ texcoords ? &texcoords[i] : NULL));
1286
+ }
1287
+ return p;
1288
+ }
1289
+
1151
1290
  Polygon
1152
1291
  create_ellipse (
1153
1292
  coord x, coord y, coord width, coord height,
@@ -1222,11 +1361,13 @@ namespace Rays
1222
1361
  create_spline (
1223
1362
  SplineType type,
1224
1363
  const Point* points, size_t size, bool loop,
1225
- uint nsegment = 16)
1364
+ uint nsegment = 0)
1226
1365
  {
1227
1366
  if (size % 4 != 0)
1228
1367
  argument_error(__FILE__, __LINE__);
1229
1368
 
1369
+ if (nsegment <= 0) nsegment = 16;
1370
+
1230
1371
  size_t count = size / 4;
1231
1372
  auto spline_fun = get_spline_fun(type);
1232
1373
 
@@ -1253,7 +1394,7 @@ namespace Rays
1253
1394
  create_curve (
1254
1395
  coord x1, coord y1, coord x2, coord y2,
1255
1396
  coord x3, coord y3, coord x4, coord y4,
1256
- bool loop)
1397
+ bool loop, uint nsegment)
1257
1398
  {
1258
1399
  const Point points[] = {
1259
1400
  Point(x1, y1),
@@ -1261,29 +1402,29 @@ namespace Rays
1261
1402
  Point(x3, y3),
1262
1403
  Point(x4, y4)
1263
1404
  };
1264
- return create_spline(CATMULLROM, points, 4, loop);
1405
+ return create_spline(CATMULLROM, points, 4, loop, nsegment);
1265
1406
  }
1266
1407
 
1267
1408
  Polygon
1268
1409
  create_curve (
1269
1410
  const Point& p1, const Point& p2, const Point& p3, const Point& p4,
1270
- bool loop)
1411
+ bool loop, uint nsegment)
1271
1412
  {
1272
1413
  const Point points[] = {p1, p2, p3, p4};
1273
- return create_spline(CATMULLROM, points, 4, loop);
1414
+ return create_spline(CATMULLROM, points, 4, loop, nsegment);
1274
1415
  }
1275
1416
 
1276
1417
  Polygon
1277
- create_curve (const Point* points, size_t size, bool loop)
1418
+ create_curve (const Point* points, size_t size, bool loop, uint nsegment)
1278
1419
  {
1279
- return create_spline(CATMULLROM, points, size, loop);
1420
+ return create_spline(CATMULLROM, points, size, loop, nsegment);
1280
1421
  }
1281
1422
 
1282
1423
  Polygon
1283
1424
  create_bezier (
1284
1425
  coord x1, coord y1, coord x2, coord y2,
1285
1426
  coord x3, coord y3, coord x4, coord y4,
1286
- bool loop)
1427
+ bool loop, uint nsegment)
1287
1428
  {
1288
1429
  const Point points[] = {
1289
1430
  Point(x1, y1),
@@ -1291,22 +1432,22 @@ namespace Rays
1291
1432
  Point(x3, y3),
1292
1433
  Point(x4, y4)
1293
1434
  };
1294
- return create_spline(BEZIER, points, 4, loop);
1435
+ return create_spline(BEZIER, points, 4, loop, nsegment);
1295
1436
  }
1296
1437
 
1297
1438
  Polygon
1298
1439
  create_bezier (
1299
1440
  const Point& p1, const Point& p2, const Point& p3, const Point& p4,
1300
- bool loop)
1441
+ bool loop, uint nsegment)
1301
1442
  {
1302
1443
  const Point points[] = {p1, p2, p3, p4};
1303
- return create_spline(BEZIER, points, 4, loop);
1444
+ return create_spline(BEZIER, points, 4, loop, nsegment);
1304
1445
  }
1305
1446
 
1306
1447
  Polygon
1307
- create_bezier (const Point* points, size_t size, bool loop)
1448
+ create_bezier (const Point* points, size_t size, bool loop, uint nsegment)
1308
1449
  {
1309
- return create_spline(BEZIER, points, size, loop);
1450
+ return create_spline(BEZIER, points, size, loop, nsegment);
1310
1451
  }
1311
1452
 
1312
1453
  void
@@ -1342,54 +1483,36 @@ namespace Rays
1342
1483
 
1343
1484
 
1344
1485
  Polygon::Polygon ()
1345
- : self(new PolygonData())
1346
1486
  {
1347
1487
  }
1348
1488
 
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())
1489
+ Polygon::Polygon (
1490
+ const Point* points, size_t size, bool loop,
1491
+ const Color* colors, const Coord3* texcoords)
1359
1492
  {
1360
1493
  if (!points || size <= 0) return;
1361
1494
 
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
- }
1495
+ self->append(Polyline(points, size, loop, true, colors, texcoords));
1378
1496
  }
1379
1497
 
1380
1498
  Polygon::Polygon (const Polyline& polyline)
1381
- : self(new PolygonData())
1382
1499
  {
1500
+ if (polyline.hole())
1501
+ argument_error(__FILE__, __LINE__);
1502
+
1383
1503
  self->append(polyline);
1384
1504
  }
1385
1505
 
1386
- Polygon::Polygon (const Line* lines, size_t size)
1387
- : self(new PolygonData())
1506
+ Polygon::Polygon (const Polyline* polylines, size_t size)
1388
1507
  {
1389
- if (!lines || size <= 0) return;
1508
+ if (!polylines || size <= 0)
1509
+ return;
1510
+
1511
+ if (polylines[0].hole())
1512
+ argument_error(__FILE__, __LINE__);
1390
1513
 
1391
1514
  for (size_t i = 0; i < size; ++i)
1392
- self->append(lines[i]);
1515
+ self->append(polylines[i]);
1393
1516
  }
1394
1517
 
1395
1518
  Polygon::Polygon (Data* data)
@@ -1418,7 +1541,7 @@ namespace Rays
1418
1541
  size_t
1419
1542
  Polygon::size () const
1420
1543
  {
1421
- return self->lines.size();
1544
+ return self->polylines.size();
1422
1545
  }
1423
1546
 
1424
1547
  bool
@@ -1426,9 +1549,9 @@ namespace Rays
1426
1549
  {
1427
1550
  if (deep)
1428
1551
  {
1429
- for (const auto& line : self->lines)
1552
+ for (const auto& polyline : self->polylines)
1430
1553
  {
1431
- if (!line.empty())
1554
+ if (!polyline.empty())
1432
1555
  return false;
1433
1556
  }
1434
1557
  }
@@ -1439,29 +1562,29 @@ namespace Rays
1439
1562
  Polygon::const_iterator
1440
1563
  Polygon::begin () const
1441
1564
  {
1442
- return self->lines.begin();
1565
+ return self->polylines.begin();
1443
1566
  }
1444
1567
 
1445
1568
  Polygon::const_iterator
1446
1569
  Polygon::end () const
1447
1570
  {
1448
- return self->lines.end();
1571
+ return self->polylines.end();
1449
1572
  }
1450
1573
 
1451
- const Polygon::Line&
1574
+ const Polyline&
1452
1575
  Polygon::operator [] (size_t index) const
1453
1576
  {
1454
- return self->lines[index];
1577
+ return self->polylines[index];
1455
1578
  }
1456
1579
 
1457
1580
  Polygon::operator bool () const
1458
1581
  {
1459
- if (self->lines.empty())
1582
+ if (self->polylines.empty())
1460
1583
  return true;
1461
1584
 
1462
- for (const auto& line : self->lines)
1585
+ for (const auto& polyline : self->polylines)
1463
1586
  {
1464
- if (line) return true;
1587
+ if (polyline) return true;
1465
1588
  }
1466
1589
 
1467
1590
  return false;
@@ -1479,10 +1602,23 @@ namespace Rays
1479
1602
  return self->triangulate(triangles);
1480
1603
  }
1481
1604
 
1605
+ Polygon
1606
+ operator + (const Polygon& lhs, const Polyline& rhs)
1607
+ {
1608
+ std::vector<Polyline> polylines;
1609
+ for (const auto& polyline : lhs)
1610
+ polylines.emplace_back(polyline);
1611
+ polylines.emplace_back(rhs);
1612
+ return Polygon(&polylines[0], polylines.size());
1613
+ }
1614
+
1482
1615
  Polygon
1483
1616
  operator + (const Polygon& lhs, const Polygon& rhs)
1484
1617
  {
1485
- return lhs | rhs;
1618
+ std::vector<Polyline> polylines;
1619
+ for (const auto& polyline : lhs) polylines.emplace_back(polyline);
1620
+ for (const auto& polyline : rhs) polylines.emplace_back(polyline);
1621
+ return Polygon(&polylines[0], polylines.size());
1486
1622
  }
1487
1623
 
1488
1624
  Polygon
@@ -1518,41 +1654,4 @@ namespace Rays
1518
1654
  }
1519
1655
 
1520
1656
 
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
1657
  }// Rays