rays 0.1.46 → 0.1.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.doc/ext/rays/bitmap.cpp +499 -0
  3. data/.doc/ext/rays/camera.cpp +2 -2
  4. data/.doc/ext/rays/defs.cpp +35 -11
  5. data/.doc/ext/rays/font.cpp +50 -2
  6. data/.doc/ext/rays/native.cpp +2 -4
  7. data/.doc/ext/rays/painter.cpp +111 -6
  8. data/.doc/ext/rays/polygon.cpp +152 -41
  9. data/.doc/ext/rays/polyline.cpp +89 -10
  10. data/.doc/ext/rays/rays.cpp +91 -11
  11. data/.doc/ext/rays/{noise.cpp → util.cpp} +2 -2
  12. data/.github/workflows/test.yml +0 -1
  13. data/ChangeLog.md +38 -0
  14. data/Rakefile +4 -4
  15. data/VERSION +1 -1
  16. data/ext/rays/bitmap.cpp +501 -0
  17. data/ext/rays/camera.cpp +2 -2
  18. data/ext/rays/defs.cpp +35 -11
  19. data/ext/rays/defs.h +56 -3
  20. data/ext/rays/font.cpp +56 -4
  21. data/ext/rays/native.cpp +2 -4
  22. data/ext/rays/painter.cpp +125 -11
  23. data/ext/rays/polygon.cpp +161 -41
  24. data/ext/rays/polyline.cpp +95 -9
  25. data/ext/rays/rays.cpp +91 -11
  26. data/ext/rays/{noise.cpp → util.cpp} +2 -2
  27. data/include/rays/defs.h +24 -0
  28. data/include/rays/font.h +17 -3
  29. data/include/rays/matrix.h +2 -0
  30. data/include/rays/painter.h +29 -1
  31. data/include/rays/polygon.h +57 -33
  32. data/include/rays/polyline.h +20 -1
  33. data/include/rays/ruby/polygon.h +0 -11
  34. data/include/rays/ruby/rays.h +4 -0
  35. data/include/rays/{noise.h → util.h} +2 -2
  36. data/lib/rays/color.rb +1 -1
  37. data/lib/rays/font.rb +1 -1
  38. data/lib/rays/image.rb +1 -1
  39. data/lib/rays/painter.rb +13 -2
  40. data/lib/rays/point.rb +1 -1
  41. data/lib/rays/polygon.rb +54 -16
  42. data/lib/rays/polyline.rb +54 -8
  43. data/lib/rays.rb +0 -1
  44. data/rays.gemspec +2 -2
  45. data/src/color_space.cpp +2 -2
  46. data/src/font.cpp +24 -2
  47. data/src/font.h +8 -1
  48. data/src/ios/font.mm +88 -27
  49. data/src/matrix.cpp +8 -0
  50. data/src/osx/font.mm +90 -28
  51. data/src/osx/helper.h +2 -2
  52. data/src/osx/helper.mm +2 -2
  53. data/src/painter.cpp +227 -90
  54. data/src/painter.h +11 -3
  55. data/src/polygon.cpp +588 -205
  56. data/src/polyline.cpp +154 -28
  57. data/src/polyline.h +3 -5
  58. data/src/shader.cpp +36 -4
  59. data/src/shader.h +1 -1
  60. data/src/texture.cpp +2 -2
  61. data/src/{noise.cpp → util.cpp} +1 -1
  62. data/src/win32/font.cpp +1 -1
  63. data/test/test_bitmap.rb +16 -2
  64. data/test/test_color.rb +4 -0
  65. data/test/test_font.rb +20 -2
  66. data/test/test_image.rb +18 -18
  67. data/test/test_point.rb +1 -1
  68. data/test/test_polygon.rb +52 -45
  69. data/test/test_polyline.rb +191 -72
  70. metadata +11 -17
  71. data/.doc/ext/rays/polygon_line.cpp +0 -97
  72. data/ext/rays/polygon_line.cpp +0 -100
  73. data/lib/rays/polygon_line.rb +0 -33
  74. data/test/test_polygon_line.rb +0 -164
data/src/polyline.cpp CHANGED
@@ -1,7 +1,8 @@
1
1
  #include "polyline.h"
2
2
 
3
3
 
4
- #include <assert.h>
4
+ #include <memory>
5
+ #include "rays/color.h"
5
6
  #include "rays/debug.h"
6
7
 
7
8
 
@@ -15,42 +16,122 @@ namespace Rays
15
16
  struct Polyline::Data
16
17
  {
17
18
 
19
+ typedef std::vector<Color> ColorList;
20
+
21
+ typedef std::vector<Coord3> TexCoordList;
22
+
18
23
  PointList points;
19
24
 
20
- bool loop = false;
25
+ std::unique_ptr<ColorList> pcolors;
26
+
27
+ std::unique_ptr<TexCoordList> ptexcoords;
21
28
 
22
- template <typename I, typename FUN>
23
- void reset (I begin, I end, bool loop_, FUN to_point_fun)
29
+ bool loop = false, fill = false, hole = false;
30
+
31
+ void reset (
32
+ const auto* points_, const Color* colors_, const Coord3* texcoords_,
33
+ size_t size_, bool loop_, bool fill_, bool hole_,
34
+ auto to_point_fun)
24
35
  {
25
- size_t size = end - begin;
26
- if (0 < size && size < 3 && loop_)
27
- argument_error(__FILE__, __LINE__);
36
+ ColorList* colors = colors_ ? &this->colors() : NULL;
37
+ TexCoordList* texcoords = texcoords_ ? &this->texcoords() : NULL;
38
+ int size = (int) size_;
39
+
40
+ loop = loop_;
41
+ fill = fill_;
42
+ hole = hole_;
43
+ if (!is_valid())
44
+ argument_error(__FILE__, __LINE__, "hole polyline must be looped");
28
45
 
29
46
  points.clear();
30
47
  points.reserve(size);
31
- for (auto it = begin; it != end; ++it)
32
- points.emplace_back(to_point_fun(*it));
48
+ if (hole)
49
+ {
50
+ for (int i = size - 1; i >= 0; --i)
51
+ points.emplace_back(to_point_fun(points_[i]));
52
+ }
53
+ else
54
+ {
55
+ for (int i = 0; i < size; ++i)
56
+ points.emplace_back(to_point_fun(points_[i]));
57
+ }
58
+
59
+ if (colors)
60
+ {
61
+ colors->clear();
62
+ colors->reserve(size);
63
+ if (hole)
64
+ {
65
+ for (int i = size - 1; i >= 0; --i)
66
+ colors->emplace_back(colors_[i]);
67
+ }
68
+ else
69
+ {
70
+ for (int i = 0; i < size; ++i)
71
+ colors->emplace_back(colors_[i]);
72
+ }
73
+ }
74
+
75
+ if (texcoords)
76
+ {
77
+ texcoords->clear();
78
+ texcoords->reserve(size);
79
+ if (hole)
80
+ {
81
+ for (int i = size - 1; i >= 0; --i)
82
+ texcoords->emplace_back(texcoords_[i]);
83
+ }
84
+ else
85
+ {
86
+ for (int i = 0; i < size; ++i)
87
+ texcoords->emplace_back(texcoords_[i]);
88
+ }
89
+ }
90
+ }
33
91
 
34
- loop = loop_ && size > 0;
92
+ ColorList& colors ()
93
+ {
94
+ if (!pcolors) pcolors.reset(new ColorList());
95
+ return *pcolors;
96
+ }
97
+
98
+ TexCoordList& texcoords ()
99
+ {
100
+ if (!ptexcoords) ptexcoords.reset(new TexCoordList());
101
+ return *ptexcoords;
35
102
  }
36
103
 
104
+ bool is_valid () const
105
+ {
106
+ return loop || !hole;
107
+ }
108
+
109
+ private:
110
+ #if 0
111
+ void reset_values (size_t size_, bool hole, auto fun)
112
+ {
113
+ int size = (int) size_;
114
+
115
+ if (hole)
116
+ for (int i = size - 1; i >= 0; --i) fun((size_t) i);
117
+ else
118
+ for (int i = 0; i < size; ++i) fun((size_t) i);
119
+ }
120
+ #endif
37
121
  };// Polyline::Data
38
122
 
39
123
 
40
- void
41
- Polyline_create (
42
- Polyline* polyline, const Path& path, bool loop, bool reverse)
124
+ Polyline
125
+ Polyline_create (const Path& path, bool loop, bool hole)
43
126
  {
44
- assert(polyline);
45
-
46
127
  Path cleaned;
47
128
  ClipperLib::CleanPolygon(path, cleaned);
48
129
 
49
- auto to_point = [](const IntPoint& point) {return from_clipper(point);};
50
- if (reverse)
51
- polyline->self->reset(cleaned.rbegin(), cleaned.rend(), loop, to_point);
52
- else
53
- polyline->self->reset(cleaned. begin(), cleaned. end(), loop, to_point);
130
+ Polyline pl;
131
+ pl.self->reset(
132
+ &cleaned[0], NULL, NULL, cleaned.size(), loop, loop, hole,
133
+ [](const IntPoint& point) {return from_clipper(point);});
134
+ return pl;
54
135
  }
55
136
 
56
137
  template <typename I>
@@ -63,12 +144,10 @@ namespace Rays
63
144
  }
64
145
 
65
146
  void
66
- Polyline_get_path (Path* path, const Polyline& polyline, bool reverse)
147
+ Polyline_get_path (Path* path, const Polyline& polyline, bool hole)
67
148
  {
68
- assert(path);
69
-
70
149
  const auto& points = polyline.self->points;
71
- if (reverse)
150
+ if (hole)
72
151
  reset_path(path, points.rbegin(), points.rend());
73
152
  else
74
153
  reset_path(path, points. begin(), points. end());
@@ -79,9 +158,24 @@ namespace Rays
79
158
  {
80
159
  }
81
160
 
82
- Polyline::Polyline (const Point* points, size_t size, bool loop)
161
+ Polyline::Polyline (
162
+ const Point* points, size_t size, bool loop,
163
+ const Color* colors, const Coord3* texcoords,
164
+ bool hole)
83
165
  {
84
- self->reset(points, points + size, loop, [](const Point& p) {return p;});
166
+ self->reset(
167
+ points, colors, texcoords, size, loop, loop, hole,
168
+ [](const Point& p) {return p;});
169
+ }
170
+
171
+ Polyline::Polyline (
172
+ const Point* points, size_t size, bool loop, bool fill,
173
+ const Color* colors, const Coord3* texcoords,
174
+ bool hole)
175
+ {
176
+ self->reset(
177
+ points, colors, texcoords, size, loop, fill, hole,
178
+ [](const Point& p) {return p;});
85
179
  }
86
180
 
87
181
  Polyline::~Polyline ()
@@ -114,6 +208,39 @@ namespace Rays
114
208
  return self->loop;
115
209
  }
116
210
 
211
+ bool
212
+ Polyline::fill () const
213
+ {
214
+ return self->fill;
215
+ }
216
+
217
+ bool
218
+ Polyline::hole () const
219
+ {
220
+ return self->hole;
221
+ }
222
+
223
+ const Point*
224
+ Polyline::points () const
225
+ {
226
+ const auto& v = self->points;
227
+ return !v.empty() ? &v[0] : NULL;
228
+ }
229
+
230
+ const Color*
231
+ Polyline::colors () const
232
+ {
233
+ const auto& pv = self->pcolors;
234
+ return pv && !pv->empty() ? &(*pv)[0] : NULL;
235
+ }
236
+
237
+ const Coord3*
238
+ Polyline::texcoords () const
239
+ {
240
+ const auto& pv = self->ptexcoords;
241
+ return pv && !pv->empty() ? &(*pv)[0] : NULL;
242
+ }
243
+
117
244
  size_t
118
245
  Polyline::size () const
119
246
  {
@@ -146,8 +273,7 @@ namespace Rays
146
273
 
147
274
  Polyline::operator bool () const
148
275
  {
149
- size_t s = size();
150
- return !((s == 1 || s == 2) && self->loop);
276
+ return self->is_valid();
151
277
  }
152
278
 
153
279
  bool
data/src/polyline.h CHANGED
@@ -50,13 +50,11 @@ namespace Rays
50
50
  }
51
51
 
52
52
 
53
- void Polyline_create (
54
- Polyline* polyline, const ClipperLib::Path& path, bool loop,
55
- bool reverse = false);
53
+ Polyline Polyline_create (
54
+ const ClipperLib::Path& path, bool loop, bool hole = false);
56
55
 
57
56
  void Polyline_get_path (
58
- ClipperLib::Path* path, const Polyline& polyline,
59
- bool reverse = false);
57
+ ClipperLib::Path* path, const Polyline& polyline, bool hole = false);
60
58
 
61
59
  bool Polyline_expand (
62
60
  Polygon* result, const Polyline& polyline,
data/src/shader.cpp CHANGED
@@ -97,7 +97,30 @@ namespace Rays
97
97
  }
98
98
 
99
99
  static Shader
100
- make_default_shader_for_texture ()
100
+ make_default_shader_for_texture_clamp ()
101
+ {
102
+ const ShaderBuiltinVariableNames& names =
103
+ ShaderEnv_get_builtin_variable_names(DEFAULT_ENV);
104
+ return Shader(
105
+ "varying vec4 " + V_TEXCOORD + ";\n"
106
+ "varying vec4 " + V_COLOR + ";\n"
107
+ "uniform vec3 " + U_TEXCOORD_MIN + ";\n"
108
+ "uniform vec3 " + U_TEXCOORD_MAX + ";\n"
109
+ "uniform vec3 " + U_TEXCOORD_OFFSET + ";\n"
110
+ "uniform sampler2D " + U_TEXTURE + ";\n"
111
+ "void main ()\n"
112
+ "{\n"
113
+ " vec2 texcoord__ = clamp(" +
114
+ V_TEXCOORD + ".xy, " +
115
+ U_TEXCOORD_MIN + ".xy, " +
116
+ U_TEXCOORD_MAX + ".xy - " + U_TEXCOORD_OFFSET + ".xy);\n"
117
+ " vec4 color__ = texture2D(" + U_TEXTURE + ", texcoord__);\n"
118
+ " gl_FragColor = " + V_COLOR + " * color__;\n"
119
+ "}\n");
120
+ }
121
+
122
+ static Shader
123
+ make_default_shader_for_texture_repeat ()
101
124
  {
102
125
  const ShaderBuiltinVariableNames& names =
103
126
  ShaderEnv_get_builtin_variable_names(DEFAULT_ENV);
@@ -160,10 +183,19 @@ namespace Rays
160
183
  }
161
184
 
162
185
  const Shader&
163
- Shader_get_default_shader_for_texture ()
186
+ Shader_get_default_shader_for_texture (TexCoordWrap wrap)
164
187
  {
165
- static const Shader SHADER = make_default_shader_for_texture();
166
- return SHADER;
188
+ switch (wrap)
189
+ {
190
+ case TEXCOORD_REPEAT:
191
+ static const Shader REPEAT = make_default_shader_for_texture_repeat();
192
+ return REPEAT;
193
+
194
+ case TEXCOORD_CLAMP:
195
+ default:
196
+ static const Shader CLAMP = make_default_shader_for_texture_clamp();
197
+ return CLAMP;
198
+ }
167
199
  }
168
200
 
169
201
  const Shader&
data/src/shader.h CHANGED
@@ -57,7 +57,7 @@ namespace Rays
57
57
 
58
58
  const Shader& Shader_get_default_shader_for_shape ();
59
59
 
60
- const Shader& Shader_get_default_shader_for_texture ();
60
+ const Shader& Shader_get_default_shader_for_texture (TexCoordWrap wrap);
61
61
 
62
62
  const Shader& Shader_get_shader_for_text ();
63
63
 
data/src/texture.cpp CHANGED
@@ -197,8 +197,8 @@ namespace Rays
197
197
  if (glIsTexture(self->id) == GL_FALSE)
198
198
  opengl_error(__FILE__, __LINE__, "failed to create texture.");
199
199
 
200
- //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
201
- //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
200
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
201
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
202
202
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
203
203
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);//GL_LINEAR);
204
204
 
@@ -1,4 +1,4 @@
1
- #include "rays/noise.h"
1
+ #include "rays/util.h"
2
2
 
3
3
 
4
4
  #include <glm/gtc/noise.hpp>
data/src/win32/font.cpp CHANGED
@@ -57,7 +57,7 @@ namespace Rays
57
57
 
58
58
 
59
59
  const Font&
60
- default_font ()
60
+ get_default_font ()
61
61
  {
62
62
  static const Font FONT(NULL);
63
63
  return FONT;
data/test/test_bitmap.rb CHANGED
@@ -6,8 +6,8 @@ class TestBitmap < Test::Unit::TestCase
6
6
  W = 32
7
7
  H = 16
8
8
 
9
- def bitmap(w = W, h = H)
10
- Rays::Bitmap.new w, h
9
+ def bitmap(w = W, h = H, *args)
10
+ Rays::Bitmap.new w, h, *args
11
11
  end
12
12
 
13
13
  def color(*args)
@@ -31,6 +31,20 @@ class TestBitmap < Test::Unit::TestCase
31
31
  assert_equal color(1, 0, 0, 0), o[0, 0]
32
32
  end
33
33
 
34
+ def test_pixels()
35
+ bmp = bitmap 2, 2, Rays::RGBA
36
+ assert_equal [0] * 4, bmp.pixels
37
+
38
+ bmp.pixels = [0xffff0000, 0xff00ff00, 0xff0000ff, 0xffffff00]
39
+ assert_equal [0xffff0000, 0xff00ff00, 0xff0000ff, 0xffffff00], bmp.pixels
40
+
41
+ bmp = bitmap 2, 2, Rays::RGBA_float
42
+ assert_equal [0,0,0,0] * 4, bmp.pixels
43
+
44
+ bmp.pixels = [1,0,0,1, 0,1,0,1, 0,0,1,1, 1,1,0,1]
45
+ assert_equal [1,0,0,1, 0,1,0,1, 0,0,1,1, 1,1,0,1], bmp.pixels
46
+ end
47
+
34
48
  def test_at()
35
49
  o = bitmap
36
50
  assert_equal color(0, 0, 0, 0), o[0, 0]
data/test/test_color.rb CHANGED
@@ -149,4 +149,8 @@ class TestColor < Test::Unit::TestCase
149
149
  assert_equal_color color(1, 0, 0, 1), hsv(1, 1, 1, 1)
150
150
  end
151
151
 
152
+ def test_inspect()
153
+ assert_equal "#<Rays::Color 1.0 2.0 3.0 1.0>", color(1, 2, 3).inspect
154
+ end
155
+
152
156
  end# TestColor
data/test/test_font.rb CHANGED
@@ -3,8 +3,10 @@ require_relative 'helper'
3
3
 
4
4
  class TestFont < Test::Unit::TestCase
5
5
 
6
+ R = Rays
7
+
6
8
  def font(*args)
7
- Rays::Font.new(*args)
9
+ R::Font.new(*args)
8
10
  end
9
11
 
10
12
  def test_name()
@@ -13,7 +15,19 @@ class TestFont < Test::Unit::TestCase
13
15
 
14
16
  def test_size()
15
17
  assert_kind_of Numeric, font.size
16
- assert_equal 32, font(nil, 32).size
18
+
19
+ f = font('Arial', 10)
20
+ assert_equal 10, f.size
21
+
22
+ name = f.name
23
+ f.size = 11
24
+ assert_equal 11, f.size
25
+ assert_equal name, f.name
26
+
27
+ f11 = f.dup
28
+ f.size = 12
29
+ assert_equal 12, f .size
30
+ assert_equal 11, f11.size
17
31
  end
18
32
 
19
33
  def test_width()
@@ -27,4 +41,8 @@ class TestFont < Test::Unit::TestCase
27
41
  assert_equal f.height, f.ascent + f.descent + f.leading
28
42
  end
29
43
 
44
+ def test_families()
45
+ assert_not R::Font.families.empty?
46
+ end
47
+
30
48
  end# TestFont
data/test/test_image.rb CHANGED
@@ -11,7 +11,7 @@ class TestImage < Test::Unit::TestCase
11
11
  Rays::Image.load path
12
12
  end
13
13
 
14
- def color(r = 0, g = 0, b = 0, a = 0)
14
+ def color(r, g, b, a)
15
15
  Rays::Color.new r, g, b, a
16
16
  end
17
17
 
@@ -52,24 +52,24 @@ class TestImage < Test::Unit::TestCase
52
52
  end
53
53
 
54
54
  def test_paint()
55
- def paint(&block)
55
+ paint = -> &block {
56
56
  Rays::Image.new(10, 10).paint(&block)
57
- end
58
- def fill(&block)
59
- paint {|p| p.fill 1, 0, 0; p.stroke nil; block.call p}
60
- end
61
- def stroke(&block)
62
- paint {|p| p.fill nil; p.stroke 1, 0, 0; block.call p}
63
- end
64
- def drawn(&block)
65
- fill(&block).bitmap.to_a.reject {|o| o.transparent?}.uniq.size > 0
66
- end
67
-
68
- assert_equal color(0, 0, 0, 0), fill {|p| p.rect 1, 1, 8, 8}[0, 0]
69
- assert_equal color(1, 0, 0, 1), fill {|p| p.rect 1, 1, 8, 8}[1, 1]
70
- assert_equal color(1, 0, 0, 1), stroke {|p| p.line 0, 0, 1, 1}[0, 0]
71
-
72
- assert drawn {|p| p.text "a"}
57
+ }
58
+ fill = -> &block {
59
+ paint.call {|p| p.fill 1, 0, 0; p.stroke nil; block.call p}
60
+ }
61
+ stroke = -> &block {
62
+ paint.call {|p| p.fill nil; p.stroke 1, 0, 0; block.call p}
63
+ }
64
+ drawn = -> &block {
65
+ fill[&block].bitmap.to_a.reject {|o| o.transparent?}.uniq.size > 0
66
+ }
67
+
68
+ assert_equal color(0, 0, 0, 0), fill.call {|p| p.rect 1, 1, 8, 8}[0, 0]
69
+ assert_equal color(1, 0, 0, 1), fill.call {|p| p.rect 1, 1, 8, 8}[1, 1]
70
+ assert_equal color(1, 0, 0, 1), stroke.call {|p| p.line 0, 0, 1, 1}[0, 0]
71
+
72
+ assert drawn.call {|p| p.text "a"}
73
73
  end
74
74
 
75
75
  def test_save_load()
data/test/test_point.rb CHANGED
@@ -179,7 +179,7 @@ class TestPoint < Test::Unit::TestCase
179
179
  end
180
180
 
181
181
  def test_inspect()
182
- assert_equal "#<Rays::Point 1.0, 2.0, 3.0>", point(1, 2, 3).inspect
182
+ assert_equal "#<Rays::Point 1.0 2.0 3.0>", point(1, 2, 3).inspect
183
183
  end
184
184
 
185
185
  def test_dot()
data/test/test_polygon.rb CHANGED
@@ -13,12 +13,8 @@ class TestPolygon < Test::Unit::TestCase
13
13
  Rays::Polygon.new(*args, **kwargs)
14
14
  end
15
15
 
16
- def line(*args)
17
- Rays::Polygon::Line.new(*args)
18
- end
19
-
20
- def polyline(*args)
21
- Rays::Polyline.new(*args)
16
+ def polyline(*args, **kwargs)
17
+ Rays::Polyline.new(*args, **kwargs)
22
18
  end
23
19
 
24
20
  def point(*args)
@@ -44,20 +40,23 @@ class TestPolygon < Test::Unit::TestCase
44
40
  assert_equal [[[5, 6], [7, 8]]], polygon( [5, 6], [7, 8], loop: false).dump
45
41
  assert_equal [[[1, 1], [2, 2]]], polygon( [1], [2], loop: false).dump
46
42
  assert_equal [[[3, 3], [4, 4]]], polygon(point(3), point(4), loop: false).dump
47
- assert_nothing_raised {polygon( loop: true)}
48
- assert_nothing_raised {polygon( loop: false)}
49
- assert_raise(ArgumentError) {polygon(1, loop: true)}
50
- assert_raise(ArgumentError) {polygon(1, loop: false)}
51
- assert_raise(ArgumentError) {polygon(1, 2, loop: true)}
52
- assert_nothing_raised {polygon(1, 2, loop: false)}
53
- assert_raise(ArgumentError) {polygon(1, 2, 3, loop: true)}
54
- assert_raise(ArgumentError) {polygon(1, 2, 3, loop: false)}
55
- assert_raise(ArgumentError) {polygon(1, 2, 3, 4, loop: true)}
56
- assert_nothing_raised {polygon(1, 2, 3, 4, loop: false)}
57
- assert_raise(ArgumentError) {polygon(1, 2, 3, 4, 5, loop: true)}
58
- assert_raise(ArgumentError) {polygon(1, 2, 3, 4, 5, loop: false)}
59
- assert_nothing_raised {polygon(1, 2, 3, 4, 5, 6, loop: true)}
60
- assert_nothing_raised {polygon(1, 2, 3, 4, 5, 6, loop: false)}
43
+
44
+ assert_nothing_raised {polygon( loop: true)}
45
+ assert_nothing_raised {polygon( loop: false)}
46
+ assert_raise(ArgumentError) {polygon(1, loop: true)}
47
+ assert_raise(ArgumentError) {polygon(1, loop: false)}
48
+ assert_nothing_raised {polygon(1,2, loop: true)}
49
+ assert_nothing_raised {polygon(1,2, loop: false)}
50
+ assert_raise(ArgumentError) {polygon(1,2, 3, loop: true)}
51
+ assert_raise(ArgumentError) {polygon(1,2, 3, loop: false)}
52
+ assert_nothing_raised {polygon(1,2, 3,4, loop: true)}
53
+ assert_nothing_raised {polygon(1,2, 3,4, loop: false)}
54
+ assert_raise(ArgumentError) {polygon(1,2, 3,4, 5, loop: true)}
55
+ assert_raise(ArgumentError) {polygon(1,2, 3,4, 5, loop: false)}
56
+ assert_nothing_raised {polygon(1,2, 3,4, 5,6, loop: true)}
57
+ assert_nothing_raised {polygon(1,2, 3,4, 5,6, loop: false)}
58
+
59
+ assert_raise(ArgumentError) {polygon(polyline(1,2, 3,4, 5,6, loop: true, hole: true))}
61
60
  end
62
61
 
63
62
  def test_expand()
@@ -71,43 +70,26 @@ class TestPolygon < Test::Unit::TestCase
71
70
  }
72
71
  end
73
72
 
74
- def test_transform_with_matrix()
75
- m = Rays::Matrix.translate 10, 10
76
- assert_equal_polygon rect(20, 20, 50, 50), rect(10, 10, 50, 50).transform(m)
77
-
78
- m = Rays::Matrix.scale 2
79
- assert_equal_polygon rect(20, 20, 40, 40), rect(10, 10, 20, 20).transform(m)
80
-
81
- m = Rays::Matrix.rotate 90
82
- assert_equal_polygon rect(-10, 0, 10, 10), rect(0, 0, 10, 10).transform(m)
83
- end
84
-
85
- def test_transform_block()
73
+ def test_transform()
86
74
  o = rect(0, 0, 100, 100) - rect(10, 10, 50, 50)
87
75
  assert_equal 2, o.size
88
76
 
89
- o.transform {|lines|
90
- lines.map {|l| l.transform Rays::Matrix.translate 10, 10}
77
+ o.transform {|polylines|
78
+ m = Rays::Matrix.translate 10, 10
79
+ polylines.map {|pl| pl.with points: pl.points.map {|p| m * p}}
91
80
  }.tap {|x|
92
81
  assert_equal_polygon (rect(10, 10, 100, 100) - rect(20, 20, 50, 50)), x
93
82
  }
94
83
 
95
- o.transform {|lines|
96
- lines.reject {|l| l.to_a.include? point(10, 10)}
84
+ o.transform {|polylines|
85
+ polylines.reject {|pl| pl.to_a.include? point(10, 10)}
97
86
  }.tap {|x|
98
87
  assert_equal 1, x.size
99
88
  assert_equal 2, o.size
100
89
  }
101
90
 
102
- o.transform {|lines|
103
- lines.reject {|l| l.to_a.include? point(10, 10)}
104
- }.tap {|x|
105
- assert_equal 1, x.size
106
- assert_equal 2, o.size
107
- }
108
-
109
- o.transform {|lines|
110
- lines + [line(1, 2, 3, 4, 5, 6)]
91
+ o.transform {|polylines|
92
+ polylines + [polyline(1, 2, 3, 4, 5, 6)]
111
93
  }.tap {|x|
112
94
  assert_equal 3, x.size
113
95
  assert_equal 2, o.size
@@ -156,6 +138,31 @@ class TestPolygon < Test::Unit::TestCase
156
138
  assert_raise(IndexError) {o[-4]}
157
139
  end
158
140
 
141
+ def test_add()
142
+ assert_equal_polygon(
143
+ polygon(*rect(0, 0, 10, 10).to_a, *rect(5, 0, 10, 10).to_a),
144
+ rect(0, 0, 10, 10) + rect(5, 0, 10, 10))
145
+
146
+ assert_equal_polygon(
147
+ polygon(*rect(0, 0, 10, 10).to_a, *rect(5, 0, 10, 10).to_a, *rect(10, 0, 10, 10).to_a),
148
+ rect(0, 0, 10, 10) + [rect(5, 0, 10, 10), rect(10, 0, 10, 10)])
149
+
150
+ o = rect(0, 0, 10, 10)
151
+ assert_equal_polygon(
152
+ polygon(*rect(0, 0, 10, 10).to_a, *rect(0, 0, 10, 10).to_a),
153
+ o + o)
154
+
155
+ assert_equal_polygon rect(0, 0, 10, 10), rect(0, 0, 10, 10) + polygon()
156
+ assert_equal_polygon rect(0, 0, 10, 10), polygon() + rect(0, 0, 10, 10)
157
+ assert_equal_polygon rect(0, 0, 10, 10), rect(0, 0, 10, 10) + []
158
+
159
+ assert_equal(
160
+ polygon(
161
+ polyline(0,0, 0,10, 10,10, 10,0, loop: true, fill: true),
162
+ polyline(1,1, 2,1, 2,2, 1,2, loop: true, fill: true, hole: true)),
163
+ polygon(0,0, 0,10, 10,10, 10,0) + polyline(1,1, 2,1, 2,2, 1,2, loop: true, hole: true))
164
+ end
165
+
159
166
  def test_sub()
160
167
  rect10 = rect 0, 0, 10, 10
161
168