siren2 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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
+