rays 0.1.47 → 0.1.48

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/.doc/ext/rays/bitmap.cpp +287 -46
  3. data/.doc/ext/rays/camera.cpp +2 -2
  4. data/.doc/ext/rays/defs.cpp +32 -8
  5. data/.doc/ext/rays/font.cpp +50 -2
  6. data/.doc/ext/rays/native.cpp +2 -4
  7. data/.doc/ext/rays/painter.cpp +73 -3
  8. data/.doc/ext/rays/polygon.cpp +131 -97
  9. data/.doc/ext/rays/polyline.cpp +89 -10
  10. data/.doc/ext/rays/rays.cpp +80 -0
  11. data/.doc/ext/rays/{noise.cpp → util.cpp} +2 -2
  12. data/ChangeLog.md +23 -0
  13. data/VERSION +1 -1
  14. data/ext/rays/bitmap.cpp +288 -46
  15. data/ext/rays/camera.cpp +2 -2
  16. data/ext/rays/defs.cpp +32 -8
  17. data/ext/rays/defs.h +56 -3
  18. data/ext/rays/font.cpp +56 -4
  19. data/ext/rays/native.cpp +2 -4
  20. data/ext/rays/painter.cpp +80 -3
  21. data/ext/rays/polygon.cpp +134 -99
  22. data/ext/rays/polyline.cpp +95 -9
  23. data/ext/rays/rays.cpp +80 -0
  24. data/ext/rays/{noise.cpp → util.cpp} +2 -2
  25. data/include/rays/defs.h +24 -26
  26. data/include/rays/font.h +17 -3
  27. data/include/rays/painter.h +14 -0
  28. data/include/rays/polygon.h +56 -37
  29. data/include/rays/polyline.h +17 -2
  30. data/include/rays/ruby/polygon.h +0 -11
  31. data/include/rays/ruby/rays.h +4 -0
  32. data/include/rays/{noise.h → util.h} +2 -2
  33. data/lib/rays/color.rb +1 -1
  34. data/lib/rays/font.rb +1 -1
  35. data/lib/rays/image.rb +1 -1
  36. data/lib/rays/painter.rb +12 -1
  37. data/lib/rays/point.rb +1 -1
  38. data/lib/rays/polygon.rb +44 -35
  39. data/lib/rays/polyline.rb +54 -8
  40. data/lib/rays.rb +0 -1
  41. data/rays.gemspec +1 -1
  42. data/src/font.cpp +24 -2
  43. data/src/font.h +8 -1
  44. data/src/ios/font.mm +88 -27
  45. data/src/osx/font.mm +90 -28
  46. data/src/osx/helper.h +2 -2
  47. data/src/osx/helper.mm +2 -2
  48. data/src/painter.cpp +155 -85
  49. data/src/painter.h +11 -3
  50. data/src/polygon.cpp +404 -315
  51. data/src/polyline.cpp +138 -27
  52. data/src/polyline.h +3 -5
  53. data/src/shader.cpp +36 -4
  54. data/src/shader.h +1 -1
  55. data/src/texture.cpp +2 -2
  56. data/src/{noise.cpp → util.cpp} +1 -1
  57. data/src/win32/font.cpp +1 -1
  58. data/test/test_bitmap.rb +12 -5
  59. data/test/test_color.rb +4 -0
  60. data/test/test_font.rb +20 -2
  61. data/test/test_image.rb +18 -18
  62. data/test/test_point.rb +1 -1
  63. data/test/test_polygon.rb +52 -45
  64. data/test/test_polyline.rb +191 -72
  65. metadata +9 -15
  66. data/.doc/ext/rays/polygon_line.cpp +0 -97
  67. data/ext/rays/polygon_line.cpp +0 -100
  68. data/lib/rays/polygon_line.rb +0 -33
  69. data/test/test_polygon_line.rb +0 -164
data/src/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,43 +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, fill = 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_, bool fill_, 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
- if (begin > end)
26
- argument_error(__FILE__, __LINE__);
36
+ ColorList* colors = colors_ ? &this->colors() : NULL;
37
+ TexCoordList* texcoords = texcoords_ ? &this->texcoords() : NULL;
38
+ int size = (int) size_;
27
39
 
28
- points.clear();
29
40
  loop = loop_;
30
41
  fill = fill_;
42
+ hole = hole_;
43
+ if (!is_valid())
44
+ argument_error(__FILE__, __LINE__, "hole polyline must be looped");
31
45
 
32
- size_t size = end - begin;
33
- if (size <= 0) return;
34
-
46
+ points.clear();
35
47
  points.reserve(size);
36
- for (auto it = begin; it != end; ++it)
37
- 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
+ }
38
90
  }
39
91
 
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;
102
+ }
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
40
121
  };// Polyline::Data
41
122
 
42
123
 
43
- void
44
- Polyline_create (
45
- Polyline* polyline, const Path& path, bool loop, bool hole)
124
+ Polyline
125
+ Polyline_create (const Path& path, bool loop, bool hole)
46
126
  {
47
127
  Path cleaned;
48
128
  ClipperLib::CleanPolygon(path, cleaned);
49
129
 
50
- auto fun = [](const IntPoint& point) {return from_clipper(point);};
51
- if (hole)
52
- polyline->self->reset(cleaned.rbegin(), cleaned.rend(), loop, loop, fun);
53
- else
54
- polyline->self->reset(cleaned. begin(), cleaned. end(), loop, loop, fun);
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;
55
135
  }
56
136
 
57
137
  template <typename I>
@@ -66,8 +146,6 @@ namespace Rays
66
146
  void
67
147
  Polyline_get_path (Path* path, const Polyline& polyline, bool hole)
68
148
  {
69
- assert(path);
70
-
71
149
  const auto& points = polyline.self->points;
72
150
  if (hole)
73
151
  reset_path(path, points.rbegin(), points.rend());
@@ -80,17 +158,23 @@ namespace Rays
80
158
  {
81
159
  }
82
160
 
83
- 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)
84
165
  {
85
166
  self->reset(
86
- points, points + size, loop, loop,
167
+ points, colors, texcoords, size, loop, loop, hole,
87
168
  [](const Point& p) {return p;});
88
169
  }
89
170
 
90
- Polyline::Polyline (const Point* points, size_t size, bool loop, bool fill)
171
+ Polyline::Polyline (
172
+ const Point* points, size_t size, bool loop, bool fill,
173
+ const Color* colors, const Coord3* texcoords,
174
+ bool hole)
91
175
  {
92
176
  self->reset(
93
- points, points + size, loop, fill,
177
+ points, colors, texcoords, size, loop, fill, hole,
94
178
  [](const Point& p) {return p;});
95
179
  }
96
180
 
@@ -130,6 +214,33 @@ namespace Rays
130
214
  return self->fill;
131
215
  }
132
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
+
133
244
  size_t
134
245
  Polyline::size () const
135
246
  {
@@ -162,7 +273,7 @@ namespace Rays
162
273
 
163
274
  Polyline::operator bool () const
164
275
  {
165
- return true;
276
+ return self->is_valid();
166
277
  }
167
278
 
168
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 hole = 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 hole = 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)
@@ -32,10 +32,17 @@ class TestBitmap < Test::Unit::TestCase
32
32
  end
33
33
 
34
34
  def test_pixels()
35
- colors = %w[#f00 #0f0 #00f #ff0].map {|s| color s}
36
- bmp = bitmap 2, 2
37
- bmp[0, 0], bmp[1, 0], bmp[0, 1], bmp[1, 1] = colors
35
+ bmp = bitmap 2, 2, Rays::RGBA
36
+ assert_equal [0] * 4, bmp.pixels
37
+
38
+ bmp.pixels = [0xffff0000, 0xff00ff00, 0xff0000ff, 0xffffff00]
38
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
39
46
  end
40
47
 
41
48
  def test_at()
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_nothing_raised {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_nothing_raised {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