rays 0.1.47 → 0.1.49

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 (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