siren2 0.1.2

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 (97) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.travis.yml +5 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE +21 -0
  6. data/README.md +36 -0
  7. data/Rakefile +18 -0
  8. data/bin/console +14 -0
  9. data/bin/setup +8 -0
  10. data/ext/siren2/extconf.rb +66 -0
  11. data/ext/siren2/inc/bndbox.h +51 -0
  12. data/ext/siren2/inc/bo.h +20 -0
  13. data/ext/siren2/inc/brep.h +17 -0
  14. data/ext/siren2/inc/common.h +98 -0
  15. data/ext/siren2/inc/curve.h +65 -0
  16. data/ext/siren2/inc/curve/bscurve.h +22 -0
  17. data/ext/siren2/inc/curve/bzcurve.h +17 -0
  18. data/ext/siren2/inc/curve/circle.h +29 -0
  19. data/ext/siren2/inc/curve/ellipse.h +15 -0
  20. data/ext/siren2/inc/curve/hyperbola.h +15 -0
  21. data/ext/siren2/inc/curve/line.h +17 -0
  22. data/ext/siren2/inc/curve/offsetcurve.h +15 -0
  23. data/ext/siren2/inc/curve/parabola.h +15 -0
  24. data/ext/siren2/inc/filler.h +26 -0
  25. data/ext/siren2/inc/heal.h +19 -0
  26. data/ext/siren2/inc/io/iges.h +19 -0
  27. data/ext/siren2/inc/io/step.h +18 -0
  28. data/ext/siren2/inc/io/stl.h +13 -0
  29. data/ext/siren2/inc/offset.h +35 -0
  30. data/ext/siren2/inc/shape.h +140 -0
  31. data/ext/siren2/inc/shape/chunk.h +26 -0
  32. data/ext/siren2/inc/shape/compound.h +22 -0
  33. data/ext/siren2/inc/shape/edge.h +50 -0
  34. data/ext/siren2/inc/shape/face.h +67 -0
  35. data/ext/siren2/inc/shape/shell.h +21 -0
  36. data/ext/siren2/inc/shape/solid.h +41 -0
  37. data/ext/siren2/inc/shape/vertex.h +23 -0
  38. data/ext/siren2/inc/shape/wire.h +31 -0
  39. data/ext/siren2/inc/siren.h +39 -0
  40. data/ext/siren2/inc/surface/dummy +0 -0
  41. data/ext/siren2/inc/topalgo.h +52 -0
  42. data/ext/siren2/inc/trans.h +48 -0
  43. data/ext/siren2/inc/vec.h +65 -0
  44. data/ext/siren2/src/bndbox.cpp +343 -0
  45. data/ext/siren2/src/bo.cpp +66 -0
  46. data/ext/siren2/src/brep.cpp +69 -0
  47. data/ext/siren2/src/common.cpp +18 -0
  48. data/ext/siren2/src/curve.cpp +75 -0
  49. data/ext/siren2/src/curve/bscurve.cpp +118 -0
  50. data/ext/siren2/src/curve/bzcurve.cpp +55 -0
  51. data/ext/siren2/src/curve/circle.cpp +146 -0
  52. data/ext/siren2/src/curve/ellipse.cpp +17 -0
  53. data/ext/siren2/src/curve/hyperbola.cpp +17 -0
  54. data/ext/siren2/src/curve/line.cpp +24 -0
  55. data/ext/siren2/src/curve/offsetcurve.cpp +17 -0
  56. data/ext/siren2/src/curve/parabola.cpp +17 -0
  57. data/ext/siren2/src/filler.cpp +191 -0
  58. data/ext/siren2/src/heal.cpp +92 -0
  59. data/ext/siren2/src/io/iges.cpp +85 -0
  60. data/ext/siren2/src/io/step.cpp +47 -0
  61. data/ext/siren2/src/io/stl.cpp +22 -0
  62. data/ext/siren2/src/offset.cpp +256 -0
  63. data/ext/siren2/src/shape.cpp +617 -0
  64. data/ext/siren2/src/shape/chunk.cpp +65 -0
  65. data/ext/siren2/src/shape/compound.cpp +96 -0
  66. data/ext/siren2/src/shape/edge.cpp +254 -0
  67. data/ext/siren2/src/shape/face.cpp +366 -0
  68. data/ext/siren2/src/shape/shell.cpp +41 -0
  69. data/ext/siren2/src/shape/solid.cpp +256 -0
  70. data/ext/siren2/src/shape/vertex.cpp +68 -0
  71. data/ext/siren2/src/shape/wire.cpp +100 -0
  72. data/ext/siren2/src/siren.cpp +80 -0
  73. data/ext/siren2/src/surface/dummy +0 -0
  74. data/ext/siren2/src/topalgo.cpp +246 -0
  75. data/ext/siren2/src/trans.cpp +330 -0
  76. data/ext/siren2/src/vec.cpp +454 -0
  77. data/lib/io/dxf.rb +68 -0
  78. data/lib/io/plot.rb +38 -0
  79. data/lib/io/ply.rb +57 -0
  80. data/lib/io/stl.rb +35 -0
  81. data/lib/io/svg.rb +44 -0
  82. data/lib/kernel/array.rb +133 -0
  83. data/lib/kernel/float.rb +15 -0
  84. data/lib/shape.rb +157 -0
  85. data/lib/shape/compound.rb +11 -0
  86. data/lib/shape/edge.rb +15 -0
  87. data/lib/shape/face.rb +7 -0
  88. data/lib/shape/shell.rb +21 -0
  89. data/lib/shape/solid.rb +10 -0
  90. data/lib/shape/vertex.rb +7 -0
  91. data/lib/shape/wire.rb +14 -0
  92. data/lib/shapes.rb +52 -0
  93. data/lib/siren.rb +166 -0
  94. data/lib/siren2/version.rb +3 -0
  95. data/lib/vec.rb +81 -0
  96. data/siren2.gemspec +28 -0
  97. metadata +195 -0
@@ -0,0 +1,22 @@
1
+ #include "io/stl.h"
2
+
3
+ bool siren_stl_install()
4
+ {
5
+ rb_define_method(sr_mSiren, "load_stl", RUBY_METHOD_FUNC(siren_stl_load), -1);
6
+ return true;
7
+ }
8
+
9
+ VALUE siren_stl_load(int argc, VALUE* argv, VALUE self)
10
+ {
11
+ VALUE path;
12
+ rb_scan_args(argc, argv, "1", &path);
13
+
14
+ TopoDS_Shape shape;
15
+ StlAPI::Read(shape, (Standard_CString)RSTRING_PTR(path));
16
+
17
+ if (shape.IsNull()) {
18
+ rb_raise(Qnil, "Failed to load STL from %S.", (wchar_t*)RSTRING_PTR(path));
19
+ }
20
+
21
+ return siren_shape_new(shape);
22
+ }
@@ -0,0 +1,256 @@
1
+ #include "offset.h"
2
+
3
+ bool siren_offset_install()
4
+ {
5
+ #if 0
6
+ // Class method
7
+ rb_define_class_method(sr_mSiren, "sweep_vec", RUBY_METHOD_FUNC(siren_offset_sweep_vec), MRB_ARGS_REQ(2));
8
+ rb_define_class_method(sr_mSiren, "sweep_path", RUBY_METHOD_FUNC(siren_offset_sweep_path), MRB_ARGS_REQ(2) | MRB_ARGS_OPT(4));
9
+ rb_define_class_method(sr_mSiren, "loft", RUBY_METHOD_FUNC(siren_offset_loft), MRB_ARGS_REQ(1) | MRB_ARGS_OPT(3));
10
+ rb_define_class_method(sr_mSiren, "offset_geomsurf", RUBY_METHOD_FUNC(siren_offset_offset_geomsurf), MRB_ARGS_REQ(2) | MRB_ARGS_OPT(1));
11
+ rb_define_class_method(sr_mSiren, "offset", RUBY_METHOD_FUNC(siren_offset_offset), MRB_ARGS_REQ(3) | MRB_ARGS_OPT(5));
12
+ rb_define_class_method(sr_mSiren, "offset_shape", RUBY_METHOD_FUNC(siren_offset_offset_shape), MRB_ARGS_REQ(3) | MRB_ARGS_OPT(4));
13
+ rb_define_class_method(sr_mSiren, "pipe", RUBY_METHOD_FUNC(siren_offset_pipe), MRB_ARGS_REQ(2) | MRB_ARGS_OPT(2));
14
+ #endif
15
+ // For mix-in
16
+ rb_define_method(sr_mSiren, "sweep_vec", RUBY_METHOD_FUNC(siren_offset_sweep_vec), -1);
17
+ rb_define_method(sr_mSiren, "sweep_path", RUBY_METHOD_FUNC(siren_offset_sweep_path), -1);
18
+ rb_define_method(sr_mSiren, "loft", RUBY_METHOD_FUNC(siren_offset_loft), -1);
19
+ rb_define_method(sr_mSiren, "offset_geomsurf", RUBY_METHOD_FUNC(siren_offset_offset_geomsurf), -1);
20
+ rb_define_method(sr_mSiren, "offset", RUBY_METHOD_FUNC(siren_offset_offset), -1);
21
+ rb_define_method(sr_mSiren, "offset_shape", RUBY_METHOD_FUNC(siren_offset_offset_shape), -1);
22
+ rb_define_method(sr_mSiren, "pipe", RUBY_METHOD_FUNC(siren_offset_pipe), -1);
23
+ return true;
24
+ }
25
+
26
+ VALUE siren_offset_sweep_vec(int argc, VALUE* argv, VALUE self)
27
+ {
28
+ VALUE target, vec;
29
+ rb_scan_args(argc, argv, "2", &target, &vec);
30
+
31
+ TopoDS_Shape* profile = siren_shape_get(target);
32
+
33
+ gp_Pnt sp = gp_Pnt(0., 0., 0.).Transformed(profile->Location());
34
+ gp_Pnt tp = siren_ary_to_pnt(vec).Transformed(profile->Location());
35
+
36
+ TopoDS_Edge pe = BRepBuilderAPI_MakeEdge(sp, tp);
37
+ TopoDS_Wire path = BRepBuilderAPI_MakeWire(pe);
38
+
39
+ BRepOffsetAPI_MakePipe mp(path, *profile);
40
+ mp.Build();
41
+
42
+ return siren_shape_new(mp.Shape());
43
+ }
44
+
45
+ VALUE siren_offset_sweep_path(int argc, VALUE* argv, VALUE self)
46
+ {
47
+ VALUE target, pathwire;
48
+ VALUE cont, corr;
49
+ VALUE scale_first, scale_last;
50
+ rb_scan_args(argc, argv, "24", &target, &pathwire, &cont, &corr, &scale_first, &scale_last);
51
+
52
+ TopoDS_Shape* shape_profile = siren_shape_get(target);
53
+ TopoDS_Shape* shape_path = siren_shape_get(pathwire);
54
+
55
+ TopoDS_Wire path;
56
+
57
+ if (shape_path->ShapeType() == TopAbs_EDGE) {
58
+ path = BRepBuilderAPI_MakeWire(TopoDS::Edge(*shape_path));
59
+ }
60
+ else if (shape_path->ShapeType() == TopAbs_WIRE) {
61
+ path = TopoDS::Wire(*shape_path);
62
+ }
63
+ else {
64
+ rb_raise(Qnil, "Type of path is not Edge or Wire.");
65
+ }
66
+
67
+ VALUE result = Qnil;
68
+
69
+ if (argc >= 3 && argc <= 6) {
70
+
71
+ Standard_Boolean withContact = (Standard_Boolean)cont;
72
+ Standard_Boolean withCorrection = (Standard_Boolean)corr;
73
+
74
+ BRepOffsetAPI_MakePipeShell ps(path);
75
+
76
+ // get params
77
+ Standard_Real fparam, lparam;
78
+ {
79
+ BRepAdaptor_CompCurve cc(path);
80
+ fparam = cc.FirstParameter();
81
+ lparam = cc.LastParameter();
82
+ }
83
+
84
+ if (argc < 6) {
85
+ scale_last = 1.0;
86
+ if (argc < 5) {
87
+ scale_first = 1.0;
88
+ }
89
+ }
90
+
91
+ //opencascade::handle<Law_Linear> law = new Law_Linear();
92
+ //law->Set(fparam, scale_first, lparam, scale_last);
93
+
94
+ opencascade::handle<Law_S> law = new Law_S();
95
+ law->Set(fparam, scale_first, lparam, scale_last);
96
+
97
+ //opencascade::handle<Law_Composite> law = new Law_Composite(fparam, lparam, 1.0e-6);
98
+
99
+ // get start point
100
+ TopoDS_Vertex pfirst; {
101
+ TopoDS_Vertex plast;
102
+ TopExp::Vertices(path, pfirst, plast);
103
+ }
104
+
105
+ ps.SetLaw(
106
+ *shape_profile, // セクションプロファイル
107
+ law, // 掃引規則
108
+ pfirst, // 開始点
109
+ withContact, // translate profile to start point
110
+ withCorrection // Change normal of profile by curveture
111
+ );
112
+
113
+ ps.Build();
114
+ result = siren_shape_new(ps.Shape());
115
+ }
116
+ else {
117
+ BRepOffsetAPI_MakePipe mp(path, *shape_profile);
118
+ mp.Build();
119
+ result = siren_shape_new(mp.Shape());
120
+ }
121
+ return result;
122
+ }
123
+
124
+ VALUE siren_offset_loft(int argc, VALUE* argv, VALUE self)
125
+ {
126
+ VALUE objs;
127
+ VALUE smooth, is_solid, is_ruled;
128
+ rb_scan_args(argc, argv, "13", &objs, &smooth, &is_solid, &is_ruled);
129
+ int lsize = RARRAY_LEN(objs);
130
+
131
+ if (lsize < 2) {
132
+ rb_raise(Qnil, "Number of shapes must be over 2 wires.");
133
+ }
134
+
135
+ Standard_Boolean is_sm, is_s, is_r;
136
+ is_sm = argc < 2 ? Standard_True : (Standard_Boolean)smooth;
137
+ is_s = argc < 3 ? Standard_False : (Standard_Boolean)is_solid;
138
+ is_r = argc < 4 ? Standard_True : (Standard_Boolean)is_ruled;
139
+
140
+ BRepOffsetAPI_ThruSections ts(is_s, is_r);
141
+
142
+ for (int i=0; i<lsize; i++) {
143
+ VALUE line = RARRAY_AREF(objs, i);
144
+ TopoDS_Shape* shape = siren_shape_get(line);
145
+ TopoDS_Wire w = TopoDS::Wire(*shape);
146
+ ts.AddWire(w);
147
+ }
148
+
149
+ ts.SetSmoothing(is_sm);
150
+ ts.Build();
151
+
152
+ return siren_shape_new(ts.Shape());
153
+ }
154
+
155
+ VALUE siren_offset_offset_geomsurf(int argc, VALUE* argv, VALUE self)
156
+ {
157
+ VALUE target;
158
+ VALUE offset, tol;
159
+ rb_scan_args(argc, argv, "21", &target, &offset, &tol);
160
+ if (argc < 3)
161
+ tol = 1.0;
162
+
163
+ TopoDS_Shape* shape = siren_shape_get(target);
164
+
165
+ TopoDS_Compound comp;
166
+ BRep_Builder B;
167
+ B.MakeCompound(comp);
168
+
169
+ TopExp_Explorer exp(*shape, TopAbs_FACE);
170
+
171
+ for (; exp.More(); exp.Next()) {
172
+ TopoDS_Face face = TopoDS::Face(exp.Current());
173
+ opencascade::handle<Geom_Surface> gs = BRep_Tool::Surface(face);
174
+ opencascade::handle<Geom_OffsetSurface> gos = new Geom_OffsetSurface(gs, offset);
175
+ TopoDS_Face newface = BRepBuilderAPI_MakeFace(gos, tol);
176
+ B.Add(comp, newface);
177
+ }
178
+
179
+ return siren_shape_new(comp);
180
+ }
181
+
182
+ VALUE siren_offset_offset(int argc, VALUE* argv, VALUE self)
183
+ {
184
+ VALUE target;
185
+ VALUE offset, tol;
186
+ VALUE mode = (int)BRepOffset_Skin;
187
+ VALUE intersect = false, self_intersect = false;
188
+ VALUE join = (int)GeomAbs_Arc;
189
+ VALUE thickening = false;
190
+ rb_scan_args(argc, argv, "35", &target, &offset, &tol, &mode,
191
+ &intersect, &self_intersect, &join, &thickening);
192
+
193
+ TopoDS_Shape* shape = siren_shape_get(target);
194
+
195
+ BRepOffset_MakeOffset api;
196
+ api.Initialize(*shape, offset, tol, (BRepOffset_Mode)mode,
197
+ intersect, self_intersect, (GeomAbs_JoinType)join, thickening);
198
+ api.MakeOffsetShape();
199
+ if (api.IsDone()) {
200
+ return siren_shape_new(api.Shape());
201
+ }
202
+ else {
203
+ switch (api.Error()) {
204
+ default: break;
205
+ }
206
+ }
207
+ return Qnil;
208
+ }
209
+
210
+ VALUE siren_offset_offset_shape(int argc, VALUE* argv, VALUE self)
211
+ {
212
+ VALUE target;
213
+ VALUE offset, tol;
214
+ VALUE mode = (int)BRepOffset_Skin;
215
+ VALUE intersect = false, self_intersect = false;
216
+ VALUE join = (int)GeomAbs_Arc;
217
+ rb_scan_args(argc, argv, "34", &target, &offset, &tol, &mode,
218
+ &intersect, &self_intersect, &join);
219
+
220
+ TopoDS_Shape* shape = siren_shape_get(target);
221
+
222
+ TopoDS_Shape result = BRepOffsetAPI_MakeOffsetShape(*shape, offset, tol, (BRepOffset_Mode)mode,
223
+ intersect, self_intersect, (GeomAbs_JoinType)join);
224
+
225
+ return siren_shape_new(result);
226
+ }
227
+
228
+ VALUE siren_offset_pipe(int argc, VALUE* argv, VALUE self)
229
+ {
230
+ VALUE profile, path;
231
+ VALUE mode;
232
+ VALUE force_approx_c1;
233
+ rb_scan_args(argc, argv, "22", &profile, &path, &mode, &force_approx_c1);
234
+
235
+ TopoDS_Shape* shape_profile = siren_shape_get(profile);
236
+ TopoDS_Shape* shape_path = siren_shape_get(path);
237
+
238
+ if (shape_path->ShapeType() != TopAbs_WIRE) {
239
+ rb_raise(Qnil, "Type of path is not Edge or Wire.");
240
+ }
241
+
242
+ TopoDS_Wire wire = TopoDS::Wire(*shape_path);
243
+
244
+ if (argc == 2) {
245
+ BRepOffsetAPI_MakePipe mp(wire, *shape_profile);
246
+ mp.Build();
247
+ return siren_shape_new(mp.Shape());
248
+ }
249
+ if (argc == 3) {
250
+ force_approx_c1 = Qfalse;
251
+ }
252
+
253
+ BRepOffsetAPI_MakePipe mp(wire, *shape_profile, (GeomFill_Trihedron)mode, force_approx_c1 == Qtrue);
254
+ mp.Build();
255
+ return siren_shape_new(mp.Shape());
256
+ }
@@ -0,0 +1,617 @@
1
+ /*
2
+ * Document-class: Shape
3
+ *
4
+ */
5
+
6
+ #include "shape.h"
7
+
8
+ VALUE sr_cShape;
9
+
10
+ VALUE siren_shape_allocate(VALUE klass)
11
+ {
12
+ void* p = ruby_xmalloc(sizeof(TopoDS_Shape));
13
+ new(p) TopoDS_Shape();
14
+ return Data_Wrap_Struct(klass, NULL, siren_shape_final, p);
15
+ }
16
+
17
+ TopoDS_Shape* siren_shape_get(VALUE obj)
18
+ {
19
+ TopoDS_Shape* m;
20
+ Data_Get_Struct(obj, TopoDS_Shape, m);
21
+ return m;
22
+ }
23
+
24
+ VALUE siren_shape_new(const TopoDS_Shape& shape)
25
+ {
26
+ VALUE klass;
27
+ switch (shape.ShapeType()) {
28
+ case TopAbs_VERTEX: klass = sr_cVertex; break;
29
+ case TopAbs_EDGE: klass = sr_cEdge; break;
30
+ case TopAbs_WIRE: klass = sr_cWire; break;
31
+ case TopAbs_FACE: klass = sr_cFace; break;
32
+ case TopAbs_SHELL: klass = sr_cShell; break;
33
+ case TopAbs_SOLID: klass = sr_cSolid; break;
34
+ #ifdef SR_ENABLE_CHUNK
35
+ case TopAbs_COMPSOLID: klass = sr_cCompSolid; break;
36
+ #endif
37
+ case TopAbs_COMPOUND: klass = sr_cCompound; break;
38
+ default:
39
+ rb_raise(Qnil, "Failed to make Shape object.");
40
+ break;
41
+ }
42
+ auto val = siren_shape_allocate(klass);
43
+ auto ps = siren_shape_get(val);
44
+ *ps = shape;
45
+ return val;
46
+ }
47
+
48
+ bool siren_shape_install()
49
+ {
50
+ sr_cShape = rb_define_class_under(sr_mSiren, "Shape", rb_cObject);
51
+ rb_define_alloc_func(sr_cShape, siren_shape_allocate);
52
+ rb_define_method(sr_cShape, "initialize", RUBY_METHOD_FUNC(siren_shape_init), -1);
53
+ rb_define_method(sr_cShape, "null?", RUBY_METHOD_FUNC(siren_shape_is_null), -1);
54
+ rb_define_method(sr_cShape, "pos", RUBY_METHOD_FUNC(siren_shape_pos), -1);
55
+ rb_define_method(sr_cShape, "trans", RUBY_METHOD_FUNC(siren_shape_trans), -1);
56
+ rb_define_method(sr_cShape, "trans=", RUBY_METHOD_FUNC(siren_shape_set_trans), -1);
57
+ rb_define_method(sr_cShape, "bndbox", RUBY_METHOD_FUNC(siren_shape_bndbox), -1);
58
+ rb_define_method(sr_cShape, "translate!", RUBY_METHOD_FUNC(siren_shape_translate_bang), -1);
59
+ rb_define_method(sr_cShape, "rotate!", RUBY_METHOD_FUNC(siren_shape_rotate_bang), -1);
60
+ rb_define_method(sr_cShape, "scale!", RUBY_METHOD_FUNC(siren_shape_scale_bang), -1);
61
+ rb_define_method(sr_cShape, "mirror!", RUBY_METHOD_FUNC(siren_shape_mirror_bang), -1);
62
+ rb_define_method(sr_cShape, "move!", RUBY_METHOD_FUNC(siren_shape_move_bang), -1);
63
+ rb_define_method(sr_cShape, "translate", RUBY_METHOD_FUNC(siren_shape_translate), -1);
64
+ rb_define_method(sr_cShape, "rotate", RUBY_METHOD_FUNC(siren_shape_rotate), -1);
65
+ rb_define_method(sr_cShape, "scale", RUBY_METHOD_FUNC(siren_shape_scale), -1);
66
+ rb_define_method(sr_cShape, "mirror", RUBY_METHOD_FUNC(siren_shape_mirror), -1);
67
+ rb_define_method(sr_cShape, "move", RUBY_METHOD_FUNC(siren_shape_move), -1);
68
+ rb_define_method(sr_cShape, "hashcode", RUBY_METHOD_FUNC(siren_shape_hashcode), -1);
69
+ rb_define_method(sr_cShape, "partner?", RUBY_METHOD_FUNC(siren_shape_is_partner), -1);
70
+ rb_define_method(sr_cShape, "same?", RUBY_METHOD_FUNC(siren_shape_is_same), -1);
71
+ rb_define_method(sr_cShape, "equal?", RUBY_METHOD_FUNC(siren_shape_is_equal), -1);
72
+ rb_define_method(sr_cShape, "<=>", RUBY_METHOD_FUNC(siren_shape_is_equal), -1);
73
+ rb_define_method(sr_cShape, "explore", RUBY_METHOD_FUNC(siren_shape_explore), -1);
74
+ rb_define_method(sr_cShape, "subshapes", RUBY_METHOD_FUNC(siren_shape_subshapes), -1);
75
+ rb_define_method(sr_cShape, "section", RUBY_METHOD_FUNC(siren_shape_section), -1);
76
+ rb_define_method(sr_cShape, "reverse", RUBY_METHOD_FUNC(siren_shape_reverse), -1);
77
+ rb_define_method(sr_cShape, "reverse!", RUBY_METHOD_FUNC(siren_shape_reverse_bang), -1);
78
+ #ifdef SR_ENABLE_SHHEALING
79
+ rb_define_method(sr_cShape, "outerwire", RUBY_METHOD_FUNC(siren_heal_outerwire), -1);
80
+ rb_define_method(sr_cShape, "fix", RUBY_METHOD_FUNC(siren_heal_fix), -1);
81
+ #endif
82
+ /* from BRepTools */
83
+ rb_define_method(sr_cShape, "update!", RUBY_METHOD_FUNC(siren_shape_update_bang), -1);
84
+ rb_define_method(sr_cShape, "clean!", RUBY_METHOD_FUNC(siren_shape_clean_bang), -1);
85
+ /* frag accessors */
86
+ rb_define_method(sr_cShape, "lock?", RUBY_METHOD_FUNC(siren_shape_is_lock), -1);
87
+ rb_define_method(sr_cShape, "lock", RUBY_METHOD_FUNC(siren_shape_is_lock), -1);
88
+ rb_define_method(sr_cShape, "lock=", RUBY_METHOD_FUNC(siren_shape_set_lock), -1);
89
+ rb_define_method(sr_cShape, "modify?", RUBY_METHOD_FUNC(siren_shape_is_modify), -1);
90
+ rb_define_method(sr_cShape, "modify", RUBY_METHOD_FUNC(siren_shape_is_modify), -1);
91
+ rb_define_method(sr_cShape, "modify=", RUBY_METHOD_FUNC(siren_shape_set_modify), -1);
92
+ rb_define_method(sr_cShape, "check?", RUBY_METHOD_FUNC(siren_shape_is_check), -1);
93
+ rb_define_method(sr_cShape, "check", RUBY_METHOD_FUNC(siren_shape_is_check), -1);
94
+ rb_define_method(sr_cShape, "check=", RUBY_METHOD_FUNC(siren_shape_set_check), -1);
95
+ rb_define_method(sr_cShape, "orientable?", RUBY_METHOD_FUNC(siren_shape_is_orientable), -1);
96
+ rb_define_method(sr_cShape, "orientable", RUBY_METHOD_FUNC(siren_shape_is_orientable), -1);
97
+ rb_define_method(sr_cShape, "orientable=", RUBY_METHOD_FUNC(siren_shape_set_orientable), -1);
98
+ rb_define_method(sr_cShape, "close?", RUBY_METHOD_FUNC(siren_shape_is_close), -1);
99
+ rb_define_method(sr_cShape, "close", RUBY_METHOD_FUNC(siren_shape_is_close), -1);
100
+ rb_define_method(sr_cShape, "close=", RUBY_METHOD_FUNC(siren_shape_set_close), -1);
101
+ rb_define_method(sr_cShape, "infinite?", RUBY_METHOD_FUNC(siren_shape_is_infinite), -1);
102
+ rb_define_method(sr_cShape, "infinite", RUBY_METHOD_FUNC(siren_shape_is_infinite), -1);
103
+ rb_define_method(sr_cShape, "infinite=", RUBY_METHOD_FUNC(siren_shape_set_infinite), -1);
104
+ rb_define_method(sr_cShape, "convex?", RUBY_METHOD_FUNC(siren_shape_is_convex), -1);
105
+ rb_define_method(sr_cShape, "convex", RUBY_METHOD_FUNC(siren_shape_is_convex), -1);
106
+ rb_define_method(sr_cShape, "convex=", RUBY_METHOD_FUNC(siren_shape_set_convex), -1);
107
+ rb_define_method(sr_cShape, "next_trans", RUBY_METHOD_FUNC(siren_shape_next_trans), -1);
108
+ rb_define_method(sr_cShape, "first_datum", RUBY_METHOD_FUNC(siren_shape_first_datum), -1);
109
+
110
+ siren_vertex_install();
111
+ siren_edge_install();
112
+ siren_wire_install();
113
+ siren_face_install();
114
+ siren_shell_install();
115
+ siren_solid_install();
116
+ #ifdef SR_ENABLE_CHUNK
117
+ siren_chunk_install();
118
+ #endif
119
+ siren_compound_install();
120
+
121
+ return true;
122
+ }
123
+
124
+ VALUE siren_shape_init(int argc, VALUE* argv, VALUE self)
125
+ {
126
+ rb_raise(rb_eNoMethodError, "private method `new' called for Shape:Class");
127
+ return Qnil;
128
+ }
129
+
130
+ void siren_shape_final( void* p)
131
+ {
132
+ TopoDS_Shape* s = static_cast<TopoDS_Shape*>(p);
133
+ s->Nullify();
134
+ ruby_xfree(s);
135
+ }
136
+
137
+ VALUE siren_shape_is_null(int argc, VALUE* argv, VALUE self)
138
+ {
139
+ TopoDS_Shape* shape = siren_shape_get(self);
140
+ return shape->IsNull() ? Qtrue : Qfalse;
141
+ }
142
+
143
+ VALUE siren_shape_pos(int argc, VALUE* argv, VALUE self)
144
+ {
145
+ TopoDS_Shape* shape = siren_shape_get(self);
146
+ gp_XYZ pos = shape->Location().Transformation().TranslationPart();
147
+ return siren_pnt_to_ary(gp_Pnt(pos.X(), pos.Y(), pos.Z()));
148
+ }
149
+
150
+ VALUE siren_shape_trans(int argc, VALUE* argv, VALUE self)
151
+ {
152
+ TopoDS_Shape* shape = siren_shape_get(self);
153
+ TopLoc_Location loc = shape->Location();
154
+ return siren_trans_new(loc.Transformation());
155
+ }
156
+
157
+ VALUE siren_shape_next_trans(int argc, VALUE* argv, VALUE self)
158
+ {
159
+ TopoDS_Shape* shape = siren_shape_get(self);
160
+ TopLoc_Location loc = shape->Location().NextLocation();
161
+ return siren_trans_new(loc.Transformation());
162
+ }
163
+
164
+ VALUE siren_shape_first_datum(int argc, VALUE* argv, VALUE self)
165
+ {
166
+ TopoDS_Shape* shape = siren_shape_get(self);
167
+ TopLoc_Location loc = shape->Location();
168
+ opencascade::handle<TopLoc_Datum3D> datum = loc.FirstDatum();
169
+ gp_Trsf t = datum->Transformation();
170
+ return siren_trans_new(t);
171
+ }
172
+
173
+ VALUE siren_shape_set_trans(int argc, VALUE* argv, VALUE self)
174
+ {
175
+ VALUE obj;
176
+ rb_scan_args(argc, argv, "1", &obj);
177
+ gp_Trsf* trans = siren_trans_get(obj);
178
+ TopLoc_Location loc(*trans);
179
+ siren_shape_get(self)->Location(loc);
180
+ return self;
181
+ }
182
+
183
+ VALUE siren_shape_bndbox(int argc, VALUE* argv, VALUE self)
184
+ {
185
+ TopoDS_Shape* shape = siren_shape_get(self);
186
+ return siren_bndbox_new(*shape);
187
+ }
188
+
189
+ VALUE siren_shape_translate_bang(int argc, VALUE* argv, VALUE self)
190
+ {
191
+ VALUE vec;
192
+ rb_scan_args(argc, argv, "1", &vec);
193
+ gp_Trsf trsf;
194
+ trsf.SetTranslation(siren_ary_to_vec(vec));
195
+ siren_shape_get(self)->Move(trsf);
196
+ return self;
197
+ }
198
+
199
+ VALUE siren_shape_rotate_bang(int argc, VALUE* argv, VALUE self)
200
+ {
201
+ VALUE op, norm;
202
+ VALUE ang;
203
+ rb_scan_args(argc, argv, "3", &op, &norm, &ang);
204
+ gp_Trsf trsf;
205
+ trsf.SetRotation(siren_ary_to_ax1(op, norm), ang);
206
+ siren_shape_get(self)->Move(trsf);
207
+ return self;
208
+ }
209
+
210
+ VALUE siren_shape_scale_bang(int argc, VALUE* argv, VALUE self)
211
+ {
212
+ VALUE op;
213
+ VALUE factor;
214
+ rb_scan_args(argc, argv, "2", &op, &factor);
215
+ gp_Trsf trsf;
216
+ trsf.SetScale(siren_ary_to_pnt(op), factor);
217
+ siren_shape_get(self)->Move(trsf);
218
+ return self;
219
+ }
220
+
221
+ VALUE siren_shape_mirror_bang(int argc, VALUE* argv, VALUE self)
222
+ {
223
+ VALUE op, norm;
224
+ rb_scan_args(argc, argv, "2", &op, &norm);
225
+ gp_Trsf trsf;
226
+ trsf.SetMirror(siren_ary_to_ax2(op, norm));
227
+ siren_shape_get(self)->Move(trsf);
228
+ return self;
229
+ }
230
+
231
+ VALUE siren_shape_move_bang(int argc, VALUE* argv, VALUE self)
232
+ {
233
+ VALUE trans;
234
+ rb_scan_args(argc, argv, "1", &trans);
235
+ gp_Trsf* t = siren_trans_get(trans);
236
+ siren_shape_get(self)->Move(*t);
237
+ return self;
238
+ }
239
+
240
+ VALUE siren_shape_translate(int argc, VALUE* argv, VALUE self)
241
+ {
242
+ VALUE vec;
243
+ rb_scan_args(argc, argv, "1", &vec);
244
+ gp_Trsf trsf;
245
+ trsf.SetTranslation(siren_ary_to_vec(vec));
246
+ return siren_shape_new(siren_shape_get(self)->Moved(trsf));
247
+ }
248
+
249
+ VALUE siren_shape_rotate(int argc, VALUE* argv, VALUE self)
250
+ {
251
+ VALUE op, norm;
252
+ VALUE ang;
253
+ rb_scan_args(argc, argv, "3", &op, &norm, &ang);
254
+ gp_Trsf trsf;
255
+ trsf.SetRotation(siren_ary_to_ax1(op, norm), ang);
256
+ return siren_shape_new(siren_shape_get(self)->Moved(trsf));
257
+ }
258
+
259
+ VALUE siren_shape_scale(int argc, VALUE* argv, VALUE self)
260
+ {
261
+ VALUE op;
262
+ VALUE factor;
263
+ rb_scan_args(argc, argv, "2", &op, &factor);
264
+ gp_Trsf trsf;
265
+ trsf.SetScale(siren_ary_to_pnt(op), factor);
266
+ return siren_shape_new(siren_shape_get(self)->Moved(trsf));
267
+ }
268
+
269
+ VALUE siren_shape_mirror(int argc, VALUE* argv, VALUE self)
270
+ {
271
+ VALUE op, norm;
272
+ rb_scan_args(argc, argv, "2", &op, &norm);
273
+ gp_Trsf trsf;
274
+ trsf.SetMirror(siren_ary_to_ax2(op, norm));
275
+ return siren_shape_new(siren_shape_get(self)->Moved(trsf));
276
+ }
277
+
278
+ VALUE siren_shape_move(int argc, VALUE* argv, VALUE self)
279
+ {
280
+ VALUE trans;
281
+ rb_scan_args(argc, argv, "1", &trans);
282
+ gp_Trsf* t = siren_trans_get(trans);
283
+ return siren_shape_new(siren_shape_get(self)->Moved(*t));
284
+ }
285
+
286
+ VALUE siren_shape_hashcode(int argc, VALUE* argv, VALUE self)
287
+ {
288
+ VALUE upper;
289
+ rb_scan_args(argc, argv, "1", &upper);
290
+ TopoDS_Shape* shape = siren_shape_get(self);
291
+ return INT2FIX(shape->HashCode(upper));
292
+ }
293
+
294
+ VALUE siren_shape_is_partner(int argc, VALUE* argv, VALUE self)
295
+ {
296
+ VALUE other;
297
+ rb_scan_args(argc, argv, "1", &other);
298
+ TopoDS_Shape* shape_self = siren_shape_get(self);
299
+ TopoDS_Shape* shape_other = siren_shape_get(other);
300
+ return shape_self->IsPartner(*shape_other) ? Qtrue : Qfalse;
301
+ }
302
+
303
+ VALUE siren_shape_is_same(int argc, VALUE* argv, VALUE self)
304
+ {
305
+ VALUE other;
306
+ rb_scan_args(argc, argv, "1", &other);
307
+ TopoDS_Shape* shape_self = siren_shape_get(self);
308
+ TopoDS_Shape* shape_other = siren_shape_get(other);
309
+ return shape_self->IsSame(*shape_other) ? Qtrue : Qfalse;
310
+ }
311
+
312
+ VALUE siren_shape_is_equal(int argc, VALUE* argv, VALUE self)
313
+ {
314
+ VALUE other;
315
+ rb_scan_args(argc, argv, "1", &other);
316
+ TopoDS_Shape* shape_self = siren_shape_get(self);
317
+ TopoDS_Shape* shape_other = siren_shape_get(other);
318
+ return shape_self->IsEqual(*shape_other) ? Qtrue : Qfalse;
319
+ }
320
+
321
+ VALUE siren_shape_explore(int argc, VALUE* argv, VALUE self)
322
+ {
323
+ VALUE klass;
324
+ VALUE klassf;
325
+ VALUE block;
326
+ rb_scan_args(argc, argv, "12", &klass, &klassf, &block);
327
+
328
+ VALUE mtype;
329
+ TopAbs_ShapeEnum type = TopAbs_COMPOUND;
330
+ if (rb_funcall(klass, rb_intern("=="), 1, sr_cCompound) == Qtrue) {
331
+ type = TopAbs_COMPOUND;
332
+ }
333
+ #ifdef SR_ENABLE_CHUNK
334
+ else if (rb_funcall(klass, rb_intern("=="), 1, sr_cChunk) == Qtrue) {
335
+ type = TopAbs_COMPSOLID;
336
+ }
337
+ #endif
338
+ else if (rb_funcall(klass, rb_intern("=="), 1, sr_cSolid) == Qtrue) {
339
+ type = TopAbs_SOLID;
340
+ }
341
+ else if (rb_funcall(klass, rb_intern("=="), 1, sr_cShell) == Qtrue) {
342
+ type = TopAbs_SHELL;
343
+ }
344
+ else if (rb_funcall(klass, rb_intern("=="), 1, sr_cFace) == Qtrue) {
345
+ type = TopAbs_FACE;
346
+ }
347
+ else if (rb_funcall(klass, rb_intern("=="), 1, sr_cWire) == Qtrue) {
348
+ type = TopAbs_WIRE;
349
+ }
350
+ else if (rb_funcall(klass, rb_intern("=="), 1, sr_cEdge) == Qtrue) {
351
+ type = TopAbs_EDGE;
352
+ }
353
+ else if (rb_funcall(klass, rb_intern("=="), 1, sr_cVertex) == Qtrue) {
354
+ type = TopAbs_VERTEX;
355
+ }
356
+ else {
357
+ rb_raise(Qnil, "Type error.");
358
+ }
359
+
360
+ TopExp_Explorer ex;
361
+ if (argc == 1) {
362
+ ex.Init(*siren_shape_get(self), type);
363
+ }
364
+ else {
365
+ VALUE mfilter;
366
+ TopAbs_ShapeEnum avoid = TopAbs_COMPOUND;
367
+ if (rb_funcall(klassf, rb_intern("=="), 1, sr_cCompound) == Qtrue) {
368
+ avoid = TopAbs_COMPOUND;
369
+ }
370
+ #ifdef SR_ENABLE_CHUNK
371
+ else if (rb_funcall(klassf, rb_intern("=="), 1, sr_cChunk) == Qtrue) {
372
+ avoid = TopAbs_COMPSOLID;
373
+ }
374
+ #endif
375
+ else if (rb_funcall(klassf, rb_intern("=="), 1, sr_cSolid) == Qtrue) {
376
+ avoid = TopAbs_SOLID;
377
+ }
378
+ else if (rb_funcall(klassf, rb_intern("=="), 1, sr_cShell) == Qtrue) {
379
+ avoid = TopAbs_SHELL;
380
+ }
381
+ else if (rb_funcall(klassf, rb_intern("=="), 1, sr_cFace) == Qtrue) {
382
+ avoid = TopAbs_FACE;
383
+ }
384
+ else if (rb_funcall(klassf, rb_intern("=="), 1, sr_cWire) == Qtrue) {
385
+ avoid = TopAbs_WIRE;
386
+ }
387
+ else if (rb_funcall(klassf, rb_intern("=="), 1, sr_cEdge) == Qtrue) {
388
+ avoid = TopAbs_EDGE;
389
+ }
390
+ else if (rb_funcall(klassf, rb_intern("=="), 1, sr_cVertex) == Qtrue) {
391
+ avoid = TopAbs_VERTEX;
392
+ }
393
+ else {
394
+ rb_raise(Qnil, "Type error.");
395
+ }
396
+ ex.Init(*siren_shape_get(self), type, avoid);
397
+ }
398
+
399
+ if (!NIL_P(block)) {
400
+ for (; ex.More(); ex.Next()) {
401
+ VALUE argv[2];
402
+ argv[0] = siren_shape_new(ex.Current());
403
+ argv[1] = INT2FIX(ex.Depth());
404
+ #if 0
405
+ rb_yield_argv(block, 2, argv);
406
+ #else
407
+ // where is a block?
408
+ rb_yield_values2(2, argv);
409
+ #endif
410
+ }
411
+ return self;
412
+ }
413
+ VALUE ar = rb_ary_new();
414
+ for (; ex.More(); ex.Next()) {
415
+ #if 0
416
+ VALUE ai = rb_gc_arena_save();
417
+ #endif
418
+ rb_ary_push(ar, siren_shape_new(ex.Current()));
419
+ #if 0
420
+ rb_gc_arena_restore(ai);
421
+ #endif
422
+ }
423
+ return ar;
424
+ }
425
+
426
+ VALUE siren_shape_subshapes(int argc, VALUE* argv, VALUE self)
427
+ {
428
+ VALUE ori, loc;
429
+ rb_scan_args(argc, argv, "02", &ori, &loc);
430
+ if (argc == 0) {
431
+ ori = Qtrue;
432
+ loc = Qtrue;
433
+ }
434
+ if (argc == 1) {
435
+ loc = Qtrue;
436
+ }
437
+ VALUE ar = rb_ary_new();
438
+ TopoDS_Shape* shape = siren_shape_get(self);
439
+ if (!shape || shape->IsNull()) {
440
+ return ar;
441
+ }
442
+ TopoDS_Iterator it(*shape, ori == Qtrue, loc == Qtrue);
443
+ for (; it.More(); it.Next()) {
444
+ #if 0
445
+ VALUE ai = rb_gc_arena_save();
446
+ #endif
447
+ rb_ary_push(ar, siren_shape_new(it.Value()));
448
+ #if 0
449
+ rb_gc_arena_restore(ai);
450
+ #endif
451
+ }
452
+ return ar;
453
+ }
454
+
455
+ VALUE siren_shape_section(int argc, VALUE* argv, VALUE self)
456
+ {
457
+ VALUE other;
458
+ rb_scan_args(argc, argv, "1", &other);
459
+
460
+ TopoDS_Shape* S1 = siren_shape_get(self);
461
+ TopoDS_Shape* S2 = siren_shape_get(other);
462
+
463
+ BRepAlgoAPI_Section api(*S1, *S2, Standard_False);
464
+ // api.ComputePCurveOn1(Standard_True);
465
+ api.Approximation(Standard_True);
466
+ api.Build();
467
+
468
+ if (!api.IsDone()) {
469
+ rb_raise(Qnil, "Failed to intersection.");
470
+ }
471
+
472
+ return siren_shape_new(api.Shape());
473
+ }
474
+
475
+ VALUE siren_shape_reverse(int argc, VALUE* argv, VALUE self)
476
+ {
477
+ TopoDS_Shape* shape = siren_shape_get(self);
478
+ return siren_shape_new(shape->Reversed());
479
+ }
480
+
481
+ VALUE siren_shape_reverse_bang(int argc, VALUE* argv, VALUE self)
482
+ {
483
+ TopoDS_Shape* shape = siren_shape_get(self);
484
+ shape->Reverse();
485
+ return Qnil;
486
+ }
487
+
488
+ VALUE siren_shape_update_bang(int argc, VALUE* argv, VALUE self)
489
+ {
490
+ TopoDS_Shape* shape = siren_shape_get(self);
491
+ BRepTools::Update(*shape);
492
+ return self;
493
+ }
494
+
495
+ VALUE siren_shape_clean_bang(int argc, VALUE* argv, VALUE self)
496
+ {
497
+ TopoDS_Shape* shape = siren_shape_get(self);
498
+ // Removes all the triangulations of the faces of <shape>
499
+ // and removes all polygons on triangulations of the edges.
500
+ BRepTools::Clean(*shape);
501
+ return self;
502
+ }
503
+
504
+ VALUE siren_shape_is_lock(int argc, VALUE* argv, VALUE self)
505
+ {
506
+ return siren_shape_get(self)->Locked() == Standard_True ?
507
+ Qtrue : Qfalse;
508
+ }
509
+
510
+ VALUE siren_shape_set_lock(int argc, VALUE* argv, VALUE self)
511
+ {
512
+ VALUE flag;
513
+ rb_scan_args(argc, argv, "1", &flag);
514
+ siren_shape_get(self)->Locked((Standard_Boolean)(flag == Qtrue));
515
+ return self;
516
+ }
517
+
518
+ VALUE siren_shape_is_modify(int argc, VALUE* argv, VALUE self)
519
+ {
520
+ return siren_shape_get(self)->Modified() == Standard_True ?
521
+ Qtrue : Qfalse;
522
+ }
523
+
524
+ VALUE siren_shape_set_modify(int argc, VALUE* argv, VALUE self)
525
+ {
526
+ VALUE flag;
527
+ rb_scan_args(argc, argv, "1", &flag);
528
+ siren_shape_get(self)->Modified((Standard_Boolean)(flag == Qtrue));
529
+ return self;
530
+ }
531
+
532
+ VALUE siren_shape_is_check(int argc, VALUE* argv, VALUE self)
533
+ {
534
+ return siren_shape_get(self)->Checked() == Standard_True ?
535
+ Qtrue : Qfalse;
536
+ }
537
+
538
+ VALUE siren_shape_set_check(int argc, VALUE* argv, VALUE self)
539
+ {
540
+ VALUE flag;
541
+ rb_scan_args(argc, argv, "1", &flag);
542
+ siren_shape_get(self)->Checked((Standard_Boolean)(flag == Qtrue));
543
+ return self;
544
+ }
545
+
546
+ VALUE siren_shape_is_orientable(int argc, VALUE* argv, VALUE self)
547
+ {
548
+ return siren_shape_get(self)->Orientable() == Standard_True ?
549
+ Qtrue : Qfalse;
550
+ }
551
+
552
+ VALUE siren_shape_set_orientable(int argc, VALUE* argv, VALUE self)
553
+ {
554
+ VALUE flag;
555
+ rb_scan_args(argc, argv, "1", &flag);
556
+ siren_shape_get(self)->Orientable((Standard_Boolean)(flag == Qtrue));
557
+ return self;
558
+ }
559
+
560
+ VALUE siren_shape_is_close(int argc, VALUE* argv, VALUE self)
561
+ {
562
+ return siren_shape_get(self)->Closed() == Standard_True ?
563
+ Qtrue : Qfalse;
564
+ }
565
+
566
+ VALUE siren_shape_set_close(int argc, VALUE* argv, VALUE self)
567
+ {
568
+ VALUE flag;
569
+ rb_scan_args(argc, argv, "1", &flag);
570
+ siren_shape_get(self)->Closed((Standard_Boolean)(flag == Qtrue));
571
+ return self;
572
+ }
573
+
574
+ VALUE siren_shape_is_infinite(int argc, VALUE* argv, VALUE self)
575
+ {
576
+ return siren_shape_get(self)->Infinite() == Standard_True ?
577
+ Qtrue : Qfalse;
578
+ }
579
+
580
+ VALUE siren_shape_set_infinite(int argc, VALUE* argv, VALUE self)
581
+ {
582
+ VALUE flag;
583
+ rb_scan_args(argc, argv, "1", &flag);
584
+ siren_shape_get(self)->Infinite((Standard_Boolean)(flag == Qtrue));
585
+ return self;
586
+ }
587
+
588
+ VALUE siren_shape_is_convex(int argc, VALUE* argv, VALUE self)
589
+ {
590
+ return siren_shape_get(self)->Convex() == Standard_True ?
591
+ Qtrue : Qfalse;
592
+ }
593
+
594
+ VALUE siren_shape_set_convex(int argc, VALUE* argv, VALUE self)
595
+ {
596
+ VALUE flag;
597
+ rb_scan_args(argc, argv, "1", &flag);
598
+ siren_shape_get(self)->Convex((Standard_Boolean)(flag == Qtrue));
599
+ return self;
600
+ }
601
+
602
+ bool siren_shape_p(const VALUE& target)
603
+ {
604
+ return rb_funcall(target, rb_intern("is_a?"), 1, sr_cShape) == Qtrue;
605
+ }
606
+
607
+ void siren_shape_check(const VALUE& target)
608
+ {
609
+ if (!siren_shape_p(target)) {
610
+ VALUE type = rb_funcall(target, rb_intern("class"), 0);
611
+ VALUE type_str = rb_funcall(type, rb_intern("to_s"), 0);
612
+ VALUE etype_str = rb_funcall(sr_cShape, rb_intern("to_s"), 0);
613
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)",
614
+ RSTRING_PTR(type_str), RSTRING_PTR(etype_str));
615
+ }
616
+ }
617
+