rays 0.1.13 → 0.1.18

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/.doc/ext/rays/camera.cpp +171 -0
  3. data/.doc/ext/rays/color.cpp +2 -3
  4. data/.doc/ext/rays/color_space.cpp +22 -14
  5. data/.doc/ext/rays/font.cpp +30 -0
  6. data/.doc/ext/rays/image.cpp +1 -1
  7. data/.doc/ext/rays/native.cpp +4 -4
  8. data/.doc/ext/rays/painter.cpp +83 -0
  9. data/.doc/ext/rays/point.cpp +14 -0
  10. data/.doc/ext/rays/polygon.cpp +33 -7
  11. data/.doc/ext/rays/polyline.cpp +12 -6
  12. data/.doc/ext/rays/rays.cpp +105 -1
  13. data/LICENSE +21 -0
  14. data/Rakefile +3 -0
  15. data/VERSION +1 -1
  16. data/ext/rays/bitmap.cpp +1 -1
  17. data/ext/rays/camera.cpp +186 -0
  18. data/ext/rays/color.cpp +2 -3
  19. data/ext/rays/color_space.cpp +22 -14
  20. data/ext/rays/extconf.rb +1 -1
  21. data/ext/rays/font.cpp +35 -2
  22. data/ext/rays/image.cpp +2 -2
  23. data/ext/rays/native.cpp +4 -4
  24. data/ext/rays/painter.cpp +94 -3
  25. data/ext/rays/point.cpp +16 -0
  26. data/ext/rays/polygon.cpp +34 -6
  27. data/ext/rays/polyline.cpp +11 -5
  28. data/ext/rays/rays.cpp +105 -1
  29. data/include/rays/camera.h +74 -0
  30. data/include/rays/color_space.h +4 -2
  31. data/include/rays/defs.h +33 -0
  32. data/include/rays/exception.h +6 -2
  33. data/include/rays/image.h +1 -1
  34. data/include/rays/painter.h +38 -0
  35. data/include/rays/polygon.h +35 -1
  36. data/include/rays/polyline.h +7 -1
  37. data/include/rays/ruby/camera.h +41 -0
  38. data/include/rays/ruby/rays.h +8 -0
  39. data/lib/rays.rb +2 -2
  40. data/lib/rays/camera.rb +24 -0
  41. data/lib/rays/image.rb +1 -1
  42. data/lib/rays/painter.rb +23 -1
  43. data/lib/rays/polygon.rb +8 -0
  44. data/rays.gemspec +2 -2
  45. data/src/color_space.cpp +2 -2
  46. data/src/image.cpp +1 -1
  47. data/src/ios/bitmap.h +23 -0
  48. data/src/ios/bitmap.mm +32 -11
  49. data/src/ios/camera.mm +517 -0
  50. data/src/ios/font.mm +2 -2
  51. data/src/ios/helper.h +2 -2
  52. data/src/osx/bitmap.h +23 -0
  53. data/src/osx/bitmap.mm +28 -10
  54. data/src/osx/camera.mm +452 -0
  55. data/src/osx/font.mm +2 -2
  56. data/src/painter.cpp +100 -10
  57. data/src/polygon.cpp +203 -37
  58. data/src/polyline.cpp +4 -2
  59. data/src/polyline.h +3 -1
  60. data/test/test_font.rb +5 -0
  61. data/test/test_painter.rb +65 -5
  62. data/test/test_painter_shape.rb +48 -3
  63. data/test/test_point.rb +8 -0
  64. data/test/test_polyline.rb +26 -0
  65. metadata +20 -9
@@ -238,6 +238,18 @@ VALUE inspect(VALUE self)
238
238
  return value(Xot::stringf("#<Rays::Point %s>", THIS->inspect().c_str()));
239
239
  }
240
240
 
241
+ static
242
+ VALUE dot(VALUE self, VALUE p1, VALUE p2)
243
+ {
244
+ return value(Rays::dot(to<Rays::Point>(p1), to<Rays::Point>(p2)));
245
+ }
246
+
247
+ static
248
+ VALUE cross(VALUE self, VALUE p1, VALUE p2)
249
+ {
250
+ return value(Rays::cross(to<Rays::Point>(p1), to<Rays::Point>(p2)));
251
+ }
252
+
241
253
 
242
254
  static Class cPoint;
243
255
 
@@ -271,6 +283,8 @@ Init_point ()
271
283
  cPoint.define_method("[]=", set_at);
272
284
  cPoint.define_method("[]", get_at);
273
285
  rb_define_method(cPoint, "inspect", RUBY_METHOD_FUNC(inspect), 0);
286
+ rb_define_module_function(cPoint, "dot", RUBY_METHOD_FUNC(dot), 2);
287
+ rb_define_module_function(cPoint, "cross", RUBY_METHOD_FUNC(cross), 2);
274
288
  }
275
289
 
276
290
 
@@ -26,7 +26,7 @@ VALUE setup(VALUE self, VALUE args, VALUE loop)
26
26
  {
27
27
  CHECK;
28
28
 
29
- if (loop)
29
+ if (args[0].is_kind_of(Rays::polyline_class()))
30
30
  *THIS = to<Rays::Polygon>(args.size(), args.as_array());
31
31
  else
32
32
  {
@@ -37,12 +37,18 @@ VALUE setup(VALUE self, VALUE args, VALUE loop)
37
37
  }
38
38
 
39
39
  static
40
- VALUE expand(VALUE self, VALUE width)
40
+ VALUE expand(VALUE self)
41
41
  {
42
42
  CHECK;
43
+ check_arg_count(__FILE__, __LINE__, "Polygon#expand", argc, 1, 2, 3, 4);
44
+
45
+ coord width = to<coord> (argv[0]);
46
+ Rays::CapType cap = argc >= 2 ? to<Rays::CapType> (argv[1]) : Rays::CAP_DEFAULT;
47
+ Rays::JoinType join = argc >= 3 ? to<Rays::JoinType>(argv[2]) : Rays::JOIN_DEFAULT;
48
+ coord ml = argc >= 4 ? to<coord> (argv[3]) : Rays::JOIN_DEFAULT_MITER_LIMIT;
43
49
 
44
50
  Rays::Polygon polygon;
45
- THIS->expand(&polygon, to<coord>(width));
51
+ THIS->expand(&polygon, width, cap, join, ml);
46
52
  return value(polygon);
47
53
  }
48
54
 
@@ -68,7 +74,7 @@ VALUE empty(VALUE self)
68
74
  }
69
75
 
70
76
  static
71
- VALUE at(VALUE self, VALUE index)
77
+ VALUE get_at(VALUE self, VALUE index)
72
78
  {
73
79
  CHECK;
74
80
 
@@ -87,7 +93,7 @@ VALUE each(VALUE self)
87
93
  {
88
94
  CHECK;
89
95
 
90
- Value ret;
96
+ Value ret = Qnil;
91
97
  for (const auto& line : *THIS)
92
98
  ret = rb_yield(value(line));
93
99
  return ret;
@@ -205,6 +211,24 @@ VALUE create_ellipse(VALUE self, VALUE
205
211
  return value(Rays::create_ellipse(x, y, w, h, hole_size, from, to_, nseg));
206
212
  }
207
213
 
214
+ static
215
+ VALUE create_curve(VALUE self, VALUE args, VALUE loop)
216
+ {
217
+ std::vector<Rays::Point> points;
218
+ get_line_args(&points, args.size(), args.as_array());
219
+
220
+ return value(Rays::create_curve(&points[0], points.size(), loop));
221
+ }
222
+
223
+ static
224
+ VALUE create_bezier(VALUE self, VALUE args, VALUE loop)
225
+ {
226
+ std::vector<Rays::Point> points;
227
+ get_line_args(&points, args.size(), args.as_array());
228
+
229
+ return value(Rays::create_bezier(&points[0], points.size(), loop));
230
+ }
231
+
208
232
 
209
233
  static Class cPolygon;
210
234
 
@@ -216,11 +240,11 @@ Init_polygon ()
216
240
  cPolygon = rb_define_class_under(mRays, "Polygon", rb_cObject);
217
241
  rb_define_alloc_func(cPolygon, alloc);
218
242
  rb_define_private_method(cPolygon, "setup", RUBY_METHOD_FUNC(setup), 2);
219
- rb_define_method(cPolygon, "expand", RUBY_METHOD_FUNC(expand), 1);
243
+ rb_define_method(cPolygon, "expand", RUBY_METHOD_FUNC(expand), -1);
220
244
  rb_define_method(cPolygon, "bounds", RUBY_METHOD_FUNC(bounds), 0);
221
245
  rb_define_method(cPolygon, "size", RUBY_METHOD_FUNC(size), 0);
222
246
  cPolygon.define_method("empty?", empty);
223
- cPolygon.define_method("[]", at);
247
+ cPolygon.define_method("[]", get_at);
224
248
  rb_define_method(cPolygon, "each", RUBY_METHOD_FUNC(each), 0);
225
249
  cPolygon.define_method("+", op_or);
226
250
  cPolygon.define_method("-", op_sub);
@@ -229,6 +253,8 @@ Init_polygon ()
229
253
  cPolygon.define_method("^", op_xor);
230
254
  rb_define_singleton_method(cPolygon, "create_rect", RUBY_METHOD_FUNC(create_rect), 7);
231
255
  rb_define_singleton_method(cPolygon, "create_ellipse", RUBY_METHOD_FUNC(create_ellipse), 7);
256
+ rb_define_singleton_method(cPolygon, "create_curve", RUBY_METHOD_FUNC(create_curve), 2);
257
+ rb_define_singleton_method(cPolygon, "create_bezier", RUBY_METHOD_FUNC(create_bezier), 2);
232
258
  }
233
259
 
234
260
 
@@ -32,12 +32,18 @@ VALUE setup(VALUE self, VALUE points, VALUE loop)
32
32
  }
33
33
 
34
34
  static
35
- VALUE expand(VALUE self, VALUE width)
35
+ VALUE expand(VALUE self)
36
36
  {
37
37
  CHECK;
38
+ check_arg_count(__FILE__, __LINE__, "Polyline#expand", argc, 1, 2, 3, 4);
39
+
40
+ coord width = to<coord> (argv[0]);
41
+ Rays::CapType cap = argc >= 2 ? to<Rays::CapType> (argv[1]) : Rays::CAP_DEFAULT;
42
+ Rays::JoinType join = argc >= 3 ? to<Rays::JoinType>(argv[2]) : Rays::JOIN_DEFAULT;
43
+ coord ml = argc >= 4 ? to<coord> (argv[3]) : Rays::JOIN_DEFAULT_MITER_LIMIT;
38
44
 
39
45
  Rays::Polygon polygon;
40
- THIS->expand(&polygon, to<coord>(width));
46
+ THIS->expand(&polygon, width, cap, join, ml);
41
47
  return value(polygon);
42
48
  }
43
49
 
@@ -70,7 +76,7 @@ VALUE empty(VALUE self)
70
76
  }
71
77
 
72
78
  static
73
- VALUE at(VALUE self, VALUE index)
79
+ VALUE get_at(VALUE self, VALUE index)
74
80
  {
75
81
  CHECK;
76
82
 
@@ -89,7 +95,7 @@ VALUE each(VALUE self)
89
95
  {
90
96
  CHECK;
91
97
 
92
- Value ret;
98
+ Value ret = Qnil;
93
99
  for (const auto& point : *THIS)
94
100
  ret = rb_yield(value(point));
95
101
  return ret;
@@ -106,12 +112,12 @@ Init_polyline ()
106
112
  cPolyline = rb_define_class_under(mRays, "Polyline", rb_cObject);
107
113
  rb_define_alloc_func(cPolyline, alloc);
108
114
  rb_define_private_method(cPolyline, "setup", RUBY_METHOD_FUNC(setup), 2);
109
- rb_define_method(cPolyline, "expand", RUBY_METHOD_FUNC(expand), 1);
115
+ rb_define_method(cPolyline, "expand", RUBY_METHOD_FUNC(expand), -1);
110
116
  rb_define_method(cPolyline, "bounds", RUBY_METHOD_FUNC(bounds), 0);
111
117
  cPolyline.define_method("loop?", loop);
112
118
  rb_define_method(cPolyline, "size", RUBY_METHOD_FUNC(size), 0);
113
119
  cPolyline.define_method("empty?", empty);
114
- cPolyline.define_method("[]", at);
120
+ cPolyline.define_method("[]", get_at);
115
121
  rb_define_method(cPolyline, "each", RUBY_METHOD_FUNC(each), 0);
116
122
  }
117
123
 
@@ -1,7 +1,35 @@
1
- #include "rays/rays.h"
1
+ #include "rays/ruby/rays.h"
2
+
3
+
4
+ #include <vector>
2
5
  #include "defs.h"
3
6
 
4
7
 
8
+ RUCY_DEFINE_CONVERT_TO(Rays::CapType)
9
+ RUCY_DEFINE_CONVERT_TO(Rays::JoinType)
10
+
11
+
12
+ template <typename T>
13
+ struct EnumType
14
+ {
15
+ const char* name;
16
+ const char* short_name;
17
+ T type;
18
+ };
19
+
20
+ static std::vector<EnumType<Rays::CapType>> CAP_TYPES({
21
+ {"CAP_BUTT", "BUTT", Rays::CAP_BUTT},
22
+ {"CAP_ROUND", "ROUND", Rays::CAP_ROUND},
23
+ {"CAP_SQUARE", "SQUARE", Rays::CAP_SQUARE},
24
+ });
25
+
26
+ static std::vector<EnumType<Rays::JoinType>> JOIN_TYPES({
27
+ {"JOIN_MITER", "MITER", Rays::JOIN_MITER},
28
+ {"JOIN_ROUND", "ROUND", Rays::JOIN_ROUND},
29
+ {"JOIN_SQUARE", "SQUARE", Rays::JOIN_SQUARE},
30
+ });
31
+
32
+
5
33
  static
6
34
  VALUE init(VALUE self)
7
35
  {
@@ -23,11 +51,87 @@ void
23
51
  Init_rays ()
24
52
  {
25
53
  mRays = rb_define_module("Rays");
54
+
26
55
  mRays.define_singleton_method("init!", init);
27
56
  mRays.define_singleton_method("fin!", fin);
57
+
58
+ for (auto it = CAP_TYPES.begin(); it != CAP_TYPES.end(); ++it)
59
+ mRays.define_const(it->name, it->type);
60
+
61
+ for (auto it = JOIN_TYPES.begin(); it != JOIN_TYPES.end(); ++it)
62
+ mRays.define_const(it->name, it->type);
28
63
  }
29
64
 
30
65
 
66
+ namespace Rucy
67
+ {
68
+
69
+
70
+ template <> Rays::CapType
71
+ value_to<Rays::CapType> (int argc, const Value* argv, bool convert)
72
+ {
73
+ assert(argc > 0 && argv);
74
+
75
+ if (convert)
76
+ {
77
+ if (argv->is_s() || argv->is_sym())
78
+ {
79
+ const char* str = argv->c_str();
80
+ for (auto it = CAP_TYPES.begin(); it != CAP_TYPES.end(); ++it)
81
+ {
82
+ if (
83
+ strcasecmp(str, it->name) == 0 ||
84
+ strcasecmp(str, it->short_name) == 0)
85
+ {
86
+ return it->type;
87
+ }
88
+ }
89
+ argument_error(__FILE__, __LINE__, "invalid cap type -- %s", str);
90
+ }
91
+ }
92
+
93
+ int type = value_to<int>(*argv, convert);
94
+ if (type < 0 || Rays::CAP_MAX <= type)
95
+ argument_error(__FILE__, __LINE__, "invalid cap type -- %d", type);
96
+
97
+ return (Rays::CapType) type;
98
+ }
99
+
100
+
101
+ template <> Rays::JoinType
102
+ value_to<Rays::JoinType> (int argc, const Value* argv, bool convert)
103
+ {
104
+ assert(argc > 0 && argv);
105
+
106
+ if (convert)
107
+ {
108
+ if (argv->is_s() || argv->is_sym())
109
+ {
110
+ const char* str = argv->c_str();
111
+ for (auto it = JOIN_TYPES.begin(); it != JOIN_TYPES.end(); ++it)
112
+ {
113
+ if (
114
+ strcasecmp(str, it->name) == 0 ||
115
+ strcasecmp(str, it->short_name) == 0)
116
+ {
117
+ return it->type;
118
+ }
119
+ }
120
+ argument_error(__FILE__, __LINE__, "invalid join type -- %s", str);
121
+ }
122
+ }
123
+
124
+ int type = value_to<int>(*argv, convert);
125
+ if (type < 0 || Rays::JOIN_MAX <= type)
126
+ argument_error(__FILE__, __LINE__, "invalid join type -- %d", type);
127
+
128
+ return (Rays::JoinType) type;
129
+ }
130
+
131
+
132
+ }// Rucy
133
+
134
+
31
135
  namespace Rays
32
136
  {
33
137
 
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2019 xord.org
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/Rakefile CHANGED
@@ -29,6 +29,9 @@ use_external_library 'https://github.com/greenm01/poly2tri',
29
29
  incdir: 'poly2tri',
30
30
  srcdir: 'poly2tri'
31
31
 
32
+ use_external_library 'https://github.com/andrewwillmott/splines-lib.git',
33
+ excludes: 'Test\.cpp'
34
+
32
35
  build_native_library
33
36
  build_ruby_extension
34
37
  test_ruby_extension
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.13
1
+ 0.1.18
@@ -110,7 +110,7 @@ Init_bitmap ()
110
110
  cBitmap.define_alloc_func(alloc);
111
111
  cBitmap.define_private_method("initialize", initialize);
112
112
  cBitmap.define_private_method("initialize_copy", initialize_copy);
113
- cBitmap.define_method("width", width);
113
+ cBitmap.define_method("width", width);
114
114
  cBitmap.define_method("height", height);
115
115
  cBitmap.define_method("color_space", color_space);
116
116
  cBitmap.define_method("[]=", set_at);
@@ -0,0 +1,186 @@
1
+ #include "rays/ruby/camera.h"
2
+
3
+
4
+ #include "rays/ruby/image.h"
5
+ #include "defs.h"
6
+
7
+
8
+ RUCY_DEFINE_VALUE_FROM_TO(Rays::Camera)
9
+
10
+ #define THIS to<Rays::Camera*>(self)
11
+
12
+ #define CHECK RUCY_CHECK_OBJECT(Rays::Camera, self)
13
+
14
+
15
+ static
16
+ RUCY_DEF_ALLOC(alloc, klass)
17
+ {
18
+ return new_type<Rays::Camera>(klass);
19
+ }
20
+ RUCY_END
21
+
22
+ static
23
+ RUCY_DEF5(setup, device_name, min_width, min_height, resize, crop)
24
+ {
25
+ RUCY_CHECK_OBJ(Rays::Camera, self);
26
+
27
+ *THIS = Rays::Camera(
28
+ device_name ? to<const char*>(device_name) : NULL,
29
+ to<int>(min_width), to<int>(min_height),
30
+ to<bool>(resize), to<bool>(crop));
31
+ return self;
32
+ }
33
+ RUCY_END
34
+
35
+ static
36
+ RUCY_DEF0(start)
37
+ {
38
+ CHECK;
39
+ return value(THIS->start());
40
+ }
41
+ RUCY_END
42
+
43
+ static
44
+ RUCY_DEF0(stop)
45
+ {
46
+ CHECK;
47
+ THIS->stop();
48
+ }
49
+ RUCY_END
50
+
51
+ static
52
+ RUCY_DEF0(is_active)
53
+ {
54
+ CHECK;
55
+ return value(THIS->is_active());
56
+ }
57
+ RUCY_END
58
+
59
+ static
60
+ RUCY_DEF1(set_min_width, width)
61
+ {
62
+ CHECK;
63
+ THIS->set_min_width(to<int>(width));
64
+ return value(THIS->min_width());
65
+ }
66
+ RUCY_END
67
+
68
+ static
69
+ RUCY_DEF0(min_width)
70
+ {
71
+ CHECK;
72
+ return value(THIS->min_width());
73
+ }
74
+ RUCY_END
75
+
76
+ static
77
+ RUCY_DEF1(set_min_height, height)
78
+ {
79
+ CHECK;
80
+ THIS->set_min_height(to<int>(height));
81
+ return value(THIS->min_height());
82
+ }
83
+ RUCY_END
84
+
85
+ static
86
+ RUCY_DEF0(min_height)
87
+ {
88
+ CHECK;
89
+ return value(THIS->min_height());
90
+ }
91
+ RUCY_END
92
+
93
+ static
94
+ RUCY_DEF1(set_resize, resize)
95
+ {
96
+ CHECK;
97
+ THIS->set_resize(to<bool>(resize));
98
+ return value(THIS->is_resize());
99
+ }
100
+ RUCY_END
101
+
102
+ static
103
+ RUCY_DEF0(is_resize)
104
+ {
105
+ CHECK;
106
+ return value(THIS->is_resize());
107
+ }
108
+ RUCY_END
109
+
110
+ static
111
+ RUCY_DEF1(set_crop, crop)
112
+ {
113
+ CHECK;
114
+ THIS->set_crop(to<bool>(crop));
115
+ return value(THIS->is_crop());
116
+ }
117
+ RUCY_END
118
+
119
+ static
120
+ RUCY_DEF0(is_crop)
121
+ {
122
+ CHECK;
123
+ return value(THIS->is_crop());
124
+ }
125
+ RUCY_END
126
+
127
+ static
128
+ RUCY_DEF0(image)
129
+ {
130
+ CHECK;
131
+ const Rays::Image* img = THIS->image();
132
+ return img ? value(*img) : nil();
133
+ }
134
+ RUCY_END
135
+
136
+ static
137
+ RUCY_DEF0(device_names)
138
+ {
139
+ auto names = Rays::get_camera_device_names();
140
+
141
+ std::vector<Value> v;
142
+ for (auto it = names.begin(), end = names.end(); it != end; ++it)
143
+ v.emplace_back(value(it->c_str()));
144
+ return value(v.size(), &v[0]);
145
+ }
146
+ RUCY_END
147
+
148
+
149
+ static Class cCamera;
150
+
151
+ void
152
+ Init_camera ()
153
+ {
154
+ Module mRays = define_module("Rays");
155
+
156
+ cCamera = mRays.define_class("Camera");
157
+ cCamera.define_alloc_func(alloc);
158
+ cCamera.define_private_method("setup", setup);
159
+ cCamera.define_method("start", start);
160
+ cCamera.define_method("stop", stop);
161
+ cCamera.define_method("active?", is_active);
162
+ cCamera.define_method("min_width=", set_min_width);
163
+ cCamera.define_method("min_width", min_width);
164
+ cCamera.define_method("min_height=", set_min_height);
165
+ cCamera.define_method("min_height", min_height);
166
+ cCamera.define_method("resize=", set_resize);
167
+ cCamera.define_method("resize?", is_resize);
168
+ cCamera.define_method("crop=", set_crop);
169
+ cCamera.define_method("crop?", is_crop);
170
+ cCamera.define_method("image", image);
171
+ cCamera.define_module_function("device_names", device_names);
172
+ }
173
+
174
+
175
+ namespace Rays
176
+ {
177
+
178
+
179
+ Class
180
+ camera_class ()
181
+ {
182
+ return cCamera;
183
+ }
184
+
185
+
186
+ }// Rays