├── inc ├── surface │ └── dummy ├── io │ ├── stl.h │ ├── step.h │ └── iges.h ├── heal.h ├── brep.h ├── curve │ ├── ellipse.h │ ├── parabola.h │ ├── hyperbola.h │ ├── line.h │ ├── offsetcurve.h │ ├── bzcurve.h │ ├── bscurve.h │ └── circle.h ├── bo.h ├── shape │ ├── shell.h │ ├── chunk.h │ ├── vertex.h │ ├── compound.h │ ├── wire.h │ ├── solid.h │ ├── edge.h │ └── face.h ├── siren.h ├── filler.h ├── offset.h ├── curve.h ├── topalgo.h ├── trans.h ├── bndbox.h ├── common.h ├── vec.h └── shape.h ├── src ├── surface │ └── dummy ├── io │ ├── stl.cpp │ ├── step.cpp │ └── iges.cpp ├── common.cpp ├── curve │ ├── ellipse.cpp │ ├── parabola.cpp │ ├── hyperbola.cpp │ ├── offsetcurve.cpp │ ├── line.cpp │ ├── bzcurve.cpp │ ├── bscurve.cpp │ └── circle.cpp ├── siren.cpp ├── brep.cpp ├── bo.cpp ├── shape │ ├── shell.cpp │ ├── chunk.cpp │ ├── vertex.cpp │ ├── compound.cpp │ └── wire.cpp ├── curve.cpp ├── heal.cpp └── filler.cpp ├── .gitignore ├── test ├── shipmodel.rb ├── test-16.rb ├── transform-point.rb ├── extrema.rb ├── test-11.rb ├── test-19.rb ├── test-15.rb ├── test-17.rb ├── test-27.rb ├── test-25.rb ├── test-20.rb ├── halfspace.rb ├── test-13.rb ├── test-24.rb ├── bzcurve.rb ├── bscurve.rb ├── mruby-siren.rb ├── splitter.rb ├── curvature.rb ├── nurbssurf.rb ├── hull.rb ├── shimakaze.rb ├── siren-2d-drawer.html ├── hydrostatics.rb └── vec.rb ├── mrblib ├── shape │ ├── Edge.rb │ ├── Face.rb │ ├── Vertex.rb │ ├── Solid.rb │ ├── Wire.rb │ ├── Compound.rb │ └── Shell.rb ├── kernel │ ├── Float.rb │ └── Array.rb ├── io │ ├── plot.rb │ ├── stl.rb │ ├── svg.rb │ ├── ply.rb │ └── dxf.rb ├── Shapes.rb ├── Vec.rb ├── Shape.rb └── Siren.rb ├── doc ├── siren-reference.md └── thirdparty-license │ ├── opencascade.txt │ ├── mruby.txt │ ├── mingw32.txt │ └── freetype.txt ├── tool └── clean.sh ├── examples ├── view │ ├── config.js │ ├── siren-viewer.bat │ ├── builder.js │ ├── lib │ │ └── LICENSE │ ├── siren-viewer.css │ ├── brep2js.rb │ ├── viewer.js │ ├── siren-viewer.html │ ├── axis.js │ └── event.js ├── intersection.rb ├── tree.rb ├── make-hulllines.rb ├── least-squares-method-2d.rb ├── iges-curve2dxf-polyline.rb ├── fillet-pipe.rb ├── mqo2brep.rb └── make-hull.rb ├── viewer ├── README.md ├── lib │ └── LICENSE └── index.html ├── LICENSE ├── mrbgem.rake └── README.md /inc/surface/dummy: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/surface/dummy: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *~ 3 | -------------------------------------------------------------------------------- /test/shipmodel.rb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dyama/mruby-siren/HEAD/test/shipmodel.rb -------------------------------------------------------------------------------- /mrblib/shape/Edge.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Edge クラス拡張メソッド 3 | # 4 | class Siren::Edge 5 | 6 | end 7 | 8 | -------------------------------------------------------------------------------- /mrblib/shape/Face.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Face クラス拡張メソッド 3 | # 4 | class Siren::Face 5 | 6 | end 7 | 8 | -------------------------------------------------------------------------------- /doc/siren-reference.md: -------------------------------------------------------------------------------- 1 | Show github page: https://github.com/dyama/mruby-siren/wiki/Reference-manual 2 | -------------------------------------------------------------------------------- /mrblib/shape/Vertex.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Vertex クラス拡張メソッド 3 | # 4 | class Siren::Vertex 5 | 6 | end 7 | 8 | -------------------------------------------------------------------------------- /test/test-16.rb: -------------------------------------------------------------------------------- 1 | #!siren 2 | # coding: utf-8 3 | 4 | # ok 5 | p Siren.line [], [1] 6 | 7 | # clash 8 | p Siren.line [], [] 9 | 10 | -------------------------------------------------------------------------------- /test/transform-point.rb: -------------------------------------------------------------------------------- 1 | 2 | t = Trans::new 3 | t.translation! [5, 0, 0] 4 | t.rotation! Vec::zero, Vec::zdir, 15.0.to_rad 5 | 6 | p [10, 0, 0].trans(t) 7 | 8 | -------------------------------------------------------------------------------- /mrblib/shape/Solid.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Solid クラス拡張メソッド 3 | # 4 | class Siren::Solid 5 | 6 | def area 7 | self.shells.inject { |e| e.area } 8 | end 9 | 10 | end 11 | -------------------------------------------------------------------------------- /mrblib/shape/Wire.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Wire クラス拡張メソッド 3 | # 4 | class Siren::Wire 5 | 6 | def length 7 | self.edges.inject { |e| e.length } 8 | end 9 | 10 | end 11 | -------------------------------------------------------------------------------- /mrblib/shape/Compound.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Compound クラス拡張メソッド 3 | # 4 | class Siren::Compound 5 | 6 | def empty? 7 | self.subshapes.size == 0 8 | end 9 | 10 | end 11 | 12 | -------------------------------------------------------------------------------- /tool/clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # coding: utf-8 3 | 4 | SCRIPT_DIR=$(cd $(dirname $0); pwd) 5 | TARGET_DIR="$SCRIPT_DIR/.." 6 | find "$TARGET_DIR" -type f -name '*~' -exec rm {} \; 7 | 8 | -------------------------------------------------------------------------------- /test/extrema.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/siren 2 | # coding: utf-8 3 | 4 | # Test for extrema (get nearest point) 5 | 6 | include Siren 7 | 8 | a = infline [], Vec.x 9 | b = line [2, 0, 5], [2, 10, 5] 10 | p a.extrema b 11 | -------------------------------------------------------------------------------- /test/test-11.rb: -------------------------------------------------------------------------------- 1 | #!siren 2 | # coding: utf-8 3 | 4 | def test(&code) 5 | begin 6 | p code.call 7 | rescue => exc 8 | p exc 9 | end 10 | end 11 | 12 | Siren.wedge 13 | Siren.wedge 10, 10, 10, 0, 10, 0, 10 14 | -------------------------------------------------------------------------------- /mrblib/kernel/Float.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Float クラス拡張メソッド 3 | # 4 | class Float 5 | 6 | def to_deg 7 | self * 180.0 / Math::PI 8 | end 9 | 10 | def to_rad 11 | self * Math::PI / 180.0 12 | end 13 | 14 | end 15 | 16 | -------------------------------------------------------------------------------- /examples/view/config.js: -------------------------------------------------------------------------------- 1 | // configuration for siren viewer 2 | 3 | var material_face = new THREE.MeshPhongMaterial({color: 'slategray'}); 4 | material_face.side = THREE.DoubleSide; 5 | var material_edge = new THREE.LineBasicMaterial({linewidth: 2, color: 'red'}); 6 | 7 | -------------------------------------------------------------------------------- /test/test-19.rb: -------------------------------------------------------------------------------- 1 | #!siren 2 | # coding: utf-8 3 | 4 | def test(&code) 5 | begin 6 | p code.call 7 | rescue => exc 8 | p exc 9 | end 10 | end 11 | 12 | # ok 13 | test { Siren.sphere 1.0e-7} 14 | test { Siren.sphere 0 } 15 | 16 | # crash 17 | test { Siren.sphere -1.0e-7 } 18 | 19 | -------------------------------------------------------------------------------- /inc/io/stl.h: -------------------------------------------------------------------------------- 1 | #ifndef _STL_H_ 2 | #define _STL_H_ 3 | 4 | #include "siren.h" 5 | #include "vec.h" 6 | #include "shape.h" 7 | 8 | #include 9 | 10 | bool siren_stl_install(mrb_state* mrb, struct RClass* rclass); 11 | mrb_value siren_stl_load(mrb_state* mrb, mrb_value self); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /mrblib/shape/Shell.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Shell クラス拡張メソッド 3 | # 4 | class Siren::Shell 5 | 6 | def area 7 | self.faces.inject { |e| e.area } 8 | end 9 | 10 | def self.tol 11 | @@tol 12 | end 13 | 14 | def self.tol=(val) 15 | @@tol = val 16 | end 17 | 18 | @@tol = 1.0e-7 19 | 20 | end 21 | 22 | -------------------------------------------------------------------------------- /test/test-15.rb: -------------------------------------------------------------------------------- 1 | #!siren 2 | # coding: utf-8 3 | 4 | def test(&code) 5 | begin 6 | p code.call 7 | rescue => exc 8 | p exc 9 | end 10 | end 11 | 12 | # ok 13 | test { Siren.box [1, 2, 3] } 14 | test { Siren.box [1, 2, -3] } 15 | test { Siren.box [-1, -2, -3] } 16 | 17 | # crash 18 | test { Siren.box [0, 0, 0] } 19 | 20 | -------------------------------------------------------------------------------- /viewer/README.md: -------------------------------------------------------------------------------- 1 | How to use 2 | ---------- 3 | 4 | 1. Make a STL file in siren. 5 | 2. Put it named 'model.stl' to same directory with index.html. 6 | 3. Run Mozilla Firefox and open index.html. 7 | 8 | If your web blowser can not load the STL model, it denied by 9 | access to local resouce security policy. 10 | Then upload these files and open index.html via internet. 11 | 12 | -------------------------------------------------------------------------------- /test/test-17.rb: -------------------------------------------------------------------------------- 1 | #!siren 2 | # coding: utf-8 3 | 4 | def test(&code) 5 | begin 6 | p code.call 7 | rescue => exc 8 | p exc 9 | end 10 | end 11 | 12 | # ok 13 | test { Siren.curve [[], [1]] } 14 | test { Siren.curve [[], [1], []] } 15 | 16 | # crash 17 | test { Siren.curve [[], []] } 18 | test { Siren.curve [[1], [], []] } 19 | test { Siren.curve [[], [1], [1], []] } 20 | 21 | -------------------------------------------------------------------------------- /test/test-27.rb: -------------------------------------------------------------------------------- 1 | #!siren 2 | # coding: utf-8 3 | 4 | def test(&code) 5 | begin 6 | p code.call 7 | rescue => exc 8 | p exc 9 | end 10 | end 11 | 12 | test { 13 | a = Siren.box 14 | b = Siren.box 15 | a.translate! [0.5] 16 | a.fuse(b).volume 17 | } 18 | 19 | test { 20 | a = Siren.box 21 | b = Siren.box 22 | a.translate! [0.5] 23 | a.cut(b).volume 24 | } 25 | 26 | -------------------------------------------------------------------------------- /test/test-25.rb: -------------------------------------------------------------------------------- 1 | #!siren 2 | # coding: utf-8 3 | 4 | def test(&code) 5 | begin 6 | p code.call 7 | rescue => exc 8 | p exc 9 | end 10 | end 11 | 12 | # ok 13 | test { Siren.plane [0, 0, 0], [0, 0, 1], [0, 1, 0], -1, 1, -1, 1 } 14 | test { Siren.plane [2, 3, 4], [0, 1, 1], [1, 1, 0], -1, 1, -1, 1 } 15 | 16 | # crash 17 | test { Siren.plane [0, 0, 0], [0, 0, 1], [0, 0, 2], -1, 1, -1, 1 } 18 | -------------------------------------------------------------------------------- /examples/view/siren-viewer.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | title siren viewer 3 | SET "SCRIPTPATH=%~dp0" 4 | 5 | IF "%1"=="" ( 6 | echo No file specified. 7 | echo Please drop a BRep file to BAT file icon. 8 | pause 9 | ) else ( 10 | echo Convert BRep file to JavaScript code for three.js. 11 | %SCRIPTPATH%\..\..\siren %SCRIPTPATH%\brep2js.rb "%1" 12 | echo Opening WWW browser. 13 | start %SCRIPTPATH%\siren-viewer.html 14 | ) -------------------------------------------------------------------------------- /test/test-20.rb: -------------------------------------------------------------------------------- 1 | #!siren 2 | # coding: utf-8 3 | 4 | def test(&code) 5 | begin 6 | p code.call 7 | rescue => exc 8 | p exc 9 | end 10 | end 11 | 12 | # ok 13 | test { Siren.box [1, 2, 3] } 14 | test { Siren.box [1, 2, -3] } 15 | test { Siren.box [-1, -2, -3] } 16 | test { Siren.box [Float::NAN, 1, 1] } 17 | 18 | # crash 19 | test { Siren.box [1, "foobar", 1] } 20 | test { Siren.box [1, 2, nil] } 21 | 22 | -------------------------------------------------------------------------------- /examples/view/builder.js: -------------------------------------------------------------------------------- 1 | 2 | // MODEL(Face) 3 | for (var i = 0; i 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | mrb_value siren_heal_outerwire(mrb_state* mrb, mrb_value self); 17 | mrb_value siren_heal_fix(mrb_state* mrb, mrb_value self); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /inc/brep.h: -------------------------------------------------------------------------------- 1 | #ifndef _BREP_H_ 2 | #define _BREP_H_ 3 | 4 | #include "siren.h" 5 | #include "vec.h" 6 | #include "shape.h" 7 | 8 | #include 9 | #include 10 | 11 | bool siren_brep_install(mrb_state* mrb, struct RClass* rclass); 12 | 13 | mrb_value siren_brep_save(mrb_state* mrb, mrb_value self); 14 | mrb_value siren_brep_load(mrb_state* mrb, mrb_value self); 15 | mrb_value siren_brep_dump(mrb_state* mrb, mrb_value self); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /inc/curve/ellipse.h: -------------------------------------------------------------------------------- 1 | #ifndef _CURVE_ELLIPSE_H_ 2 | #define _CURVE_ELLIPSE_H_ 3 | 4 | #include "siren.h" 5 | 6 | #include 7 | 8 | static struct mrb_data_type siren_ellipse_type = { "Ellipse", siren_curve_final }; 9 | bool siren_ellipse_install(mrb_state* mrb, struct RClass* mod_siren); 10 | handle siren_ellipse_get(mrb_state* mrb, mrb_value self); 11 | mrb_value siren_ellipse_new(mrb_state* mrb, const handle* curve); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /examples/intersection.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/siren 2 | # coding: utf-8 3 | # 4 | # 交線 発生サンプル 5 | # 6 | 7 | include Siren 8 | 9 | tor = torus [0, 0, 0], Vec.zdir, 30, 10, Math::PI * 2 10 | pln = infplane [0, 0, 0], [0.5, 0.3, 0.8].to_v.normal 11 | int_curve = tor.section(pln) 12 | 13 | faces = [] 14 | int_curve.edges.each do |e| 15 | w = wire [e] 16 | faces << face(w, true) 17 | end 18 | 19 | comp = Compound.new faces 20 | save_brep comp, "int.brep" 21 | save_brep tor, "torus.brep" 22 | 23 | -------------------------------------------------------------------------------- /inc/curve/parabola.h: -------------------------------------------------------------------------------- 1 | #ifndef _CURVE_PARABOLA_H_ 2 | #define _CURVE_PARABOLA_H_ 3 | 4 | #include "siren.h" 5 | 6 | #include 7 | 8 | static struct mrb_data_type siren_parabola_type = { "Palabora", siren_curve_final }; 9 | bool siren_parabola_install(mrb_state* mrb, struct RClass* mod_siren); 10 | handle siren_parabola_get(mrb_state* mrb, mrb_value self); 11 | mrb_value siren_parabola_new(mrb_state* mrb, const handle* curve); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /inc/curve/hyperbola.h: -------------------------------------------------------------------------------- 1 | #ifndef _CURVE_HYPERBOLA_H_ 2 | #define _CURVE_HYPERBOLA_H_ 3 | 4 | #include "siren.h" 5 | 6 | #include 7 | 8 | static struct mrb_data_type siren_hyperbola_type = { "Hyperbola", siren_curve_final }; 9 | bool siren_hyperbola_install(mrb_state* mrb, struct RClass* mod_siren); 10 | handle siren_hyperbola_get(mrb_state* mrb, mrb_value self); 11 | mrb_value siren_hyperbola_new(mrb_state* mrb, const handle* curve); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /test/halfspace.rb: -------------------------------------------------------------------------------- 1 | include Siren 2 | 3 | xplane = infplane Vec.o, Vec.x 4 | yplane = infplane Vec.o, Vec.y 5 | zplane = infplane Vec.o, Vec.z 6 | 7 | # zplane = plane Vec.o, Vec.z, Vec.y, -50, 50, -50, 50 8 | # xplane = plane Vec.o, Vec.x, Vec.y, -50, 50, -50, 50 9 | 10 | a = halfspace xplane, Vec.x 11 | b = halfspace yplane, Vec.y 12 | c = halfspace zplane, Vec.z 13 | 14 | s = sphere 15 | r1 = a.common s 16 | r2 = b.common r1 17 | r3 = c.common r2 18 | 19 | save_brep r3, "/tmp/hoge.brep" 20 | 21 | -------------------------------------------------------------------------------- /inc/io/step.h: -------------------------------------------------------------------------------- 1 | #ifndef _STEP_H_ 2 | #define _STEP_H_ 3 | 4 | #include "siren.h" 5 | #include "vec.h" 6 | #include "shape.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | bool siren_step_install(mrb_state* mrb, struct RClass* rclass); 14 | 15 | mrb_value siren_step_save(mrb_state* mrb, mrb_value self); 16 | mrb_value siren_step_load(mrb_state* mrb, mrb_value self); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /inc/curve/line.h: -------------------------------------------------------------------------------- 1 | #ifndef _CURVE_LINE_H_ 2 | #define _CURVE_LINE_H_ 3 | 4 | #include "siren.h" 5 | 6 | #include 7 | 8 | static struct mrb_data_type siren_line_type = { "Line", siren_curve_final }; 9 | bool siren_line_install(mrb_state* mrb, struct RClass* mod_siren); 10 | handle siren_line_get(mrb_state* mrb, mrb_value self); 11 | mrb_value siren_line_new(mrb_state* mrb, const handle* curve); 12 | 13 | mrb_value siren_line_dir(mrb_state* mrb, mrb_value self); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /inc/curve/offsetcurve.h: -------------------------------------------------------------------------------- 1 | #ifndef _CURVE_OFFSETCURVE_H_ 2 | #define _CURVE_OFFSETCURVE_H_ 3 | 4 | #include "siren.h" 5 | 6 | #include 7 | 8 | static struct mrb_data_type siren_offsetcurve_type = { "OffsetCurve", siren_curve_final }; 9 | bool siren_offsetcurve_install(mrb_state* mrb, struct RClass* mod_siren); 10 | handle siren_offsetcurve_get(mrb_state* mrb, mrb_value self); 11 | mrb_value siren_offsetcurve_new(mrb_state* mrb, const handle* curve); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /test/test-13.rb: -------------------------------------------------------------------------------- 1 | #!siren 2 | # coding: utf-8 3 | 4 | def test(&code) 5 | begin 6 | p code.call 7 | rescue => exc 8 | p exc 9 | end 10 | end 11 | 12 | include Siren 13 | 14 | myface = plane [0, 0], Vec.z, Vec.x, 0, 3, 0, 3 15 | 16 | es = [] 17 | es << line([1, 0], [1, 2]) 18 | es << line([1, 1], [3, 1]) 19 | es << line([2, 1], [2, 3]) 20 | es << line([2, 2], [0, 2]) 21 | 22 | # es.each_with_index do |e, i| 23 | # res = myface.split e 24 | # puts "#{i}: #{e.to_s}" 25 | # end 26 | 27 | p myface.split es.to_comp 28 | -------------------------------------------------------------------------------- /test/test-24.rb: -------------------------------------------------------------------------------- 1 | #!siren 2 | # coding: utf-8 3 | 4 | def test(&code) 5 | begin 6 | p code.call 7 | rescue => exc 8 | p exc 9 | end 10 | end 11 | 12 | test { 13 | point = [2, 2, 2] 14 | myline = Siren.line [1, 1, 1], [3, 3, 3] 15 | p myline.param point 16 | myline = Siren.line [0, 0, 0], [3, 3, 3] 17 | p myline.param point 18 | } 19 | 20 | test { 21 | include Siren 22 | line1 = line [0, 0, 0], [3, 3, 3] 23 | p line1.param [2, 2, 2] 24 | line2 = line [1, 1, 1], [3, 3, 3] 25 | p line2.param [2, 2, 2] 26 | } 27 | -------------------------------------------------------------------------------- /test/bzcurve.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env siren 2 | # coding: utf-8 3 | 4 | include Siren 5 | 6 | poles = [[0, 0, 0], [1, 2, 0], [3, 2, 0], [4, 0, 0]] 7 | weights = [1.0, 1.2, 1.0, 1.0] 8 | 9 | if true 10 | e = bzcurve poles, weights, 0.1, 0.9 11 | p e 12 | p e.curve.class 13 | p e.length 14 | # p e.curve.degree 15 | # p e.curve.poles 16 | # p e.curve.weights 17 | else 18 | c = BzCurve.new poles, weights 19 | p c 20 | p c.class 21 | # p c.degree 22 | # p c.poles 23 | # p c.weights 24 | p Edge.new(c, 0, 1).terms 25 | end 26 | 27 | -------------------------------------------------------------------------------- /inc/io/iges.h: -------------------------------------------------------------------------------- 1 | #ifndef _IGES_H_ 2 | #define _IGES_H_ 3 | 4 | #include "siren.h" 5 | #include "vec.h" 6 | #include "shape.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | //#include 13 | 14 | bool siren_iges_install(mrb_state* mrb, struct RClass* rclass); 15 | 16 | mrb_value siren_iges_save(mrb_state* mrb, mrb_value self); 17 | mrb_value siren_iges_load(mrb_state* mrb, mrb_value self); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /inc/curve/bzcurve.h: -------------------------------------------------------------------------------- 1 | #ifndef _CURVE_BEZIERCURVE_H_ 2 | #define _CURVE_BEZIERCURVE_H_ 3 | 4 | #include "siren.h" 5 | 6 | #include 7 | 8 | static struct mrb_data_type siren_bzcurve_type = { "BzCurve", siren_curve_final }; 9 | bool siren_bzcurve_install(mrb_state* mrb, struct RClass* mod_siren); 10 | handle siren_bzcurve_get(mrb_state* mrb, mrb_value self); 11 | mrb_value siren_bzcurve_new(mrb_state* mrb, const handle* curve); 12 | 13 | mrb_value siren_bzcurve_init(mrb_state* mrb, mrb_value self); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /examples/tree.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/siren 2 | # coding: utf-8 3 | # 4 | # fractal tree 5 | # 6 | include Siren 7 | 8 | $start_len = 100.0 9 | 10 | def tree(cur_pt, dir, len) 11 | nxt_pt = cur_pt + dir * len 12 | edges = [ line(cur_pt, nxt_pt) ] 13 | len *= 0.75 14 | if len > $start_len / 10.0 15 | edges.concat tree(nxt_pt, dir.rotate(Vec.ydir, 30.0.to_rad), len) 16 | edges.concat tree(nxt_pt, dir.rotate(Vec.ydir, -30.0.to_rad), len) 17 | end 18 | return edges 19 | end 20 | 21 | lines = tree([0, 0, 0].to_v, Vec.zdir, $start_len) 22 | 23 | comp = lines.to_comp 24 | save_brep comp, "tree.brep" 25 | 26 | puts "done." 27 | 28 | -------------------------------------------------------------------------------- /inc/bo.h: -------------------------------------------------------------------------------- 1 | #ifndef _BO_H_ 2 | #define _BO_H_ 3 | 4 | #include "siren.h" 5 | #include "shape.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | bool siren_bo_install(mrb_state* mrb, struct RClass* mod_siren); 15 | mrb_value siren_bo_common (mrb_state* mrb, mrb_value self); 16 | mrb_value siren_bo_fuse (mrb_state* mrb, mrb_value self); 17 | mrb_value siren_bo_cut (mrb_state* mrb, mrb_value self); 18 | mrb_value siren_bo_projwire (mrb_state* mrb, mrb_value self); 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /inc/shape/shell.h: -------------------------------------------------------------------------------- 1 | #ifndef _SHAPE_SHELL_H_ 2 | #define _SHAPE_SHELL_H_ 3 | 4 | #include "siren.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | static struct mrb_data_type siren_shell_type = { "Shell", siren_shape_final }; 11 | bool siren_shell_install(mrb_state* mrb, struct RClass* mod_siren); 12 | TopoDS_Shell siren_shell_get(mrb_state* mrb, mrb_value self); 13 | mrb_value siren_shell_new(mrb_state* mrb, const TopoDS_Shape* src); 14 | mrb_value siren_shell_obj(mrb_state* mrb); 15 | struct RClass* siren_shell_rclass(mrb_state* mrb); 16 | 17 | mrb_value siren_shell_make(mrb_state* mrb, mrb_value self); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /doc/thirdparty-license/opencascade.txt: -------------------------------------------------------------------------------- 1 | Open CASCADE exception (version 1.0) to GNU LGPL version 2.1. 2 | 3 | The object code (i.e. not a source) form of a "work that uses the Library" 4 | can incorporate material from a header file that is part of the Library. 5 | As a special exception to the GNU Lesser General Public License version 2.1, 6 | you may distribute such object code incorporating material from header files 7 | provided with the Open CASCADE Technology libraries (including code of CDL 8 | generic classes) under terms of your choice, provided that you give 9 | prominent notice in supporting documentation to this code that it makes use 10 | of or is based on facilities provided by the Open CASCADE Technology software. 11 | -------------------------------------------------------------------------------- /test/bscurve.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env siren 2 | # coding: utf-8 3 | 4 | include Siren 5 | 6 | degree = 2 7 | # knots = [0, 0, 0, 1, 2, 2, 2] 8 | # use commpressed knot array 9 | knots = [0.0, 1.0, 2.0] 10 | mults = [3, 1, 3] 11 | poles = [[10, 0, 7], [7, 0, 7], [3, 0, 8], [0, 0, 7]] 12 | weights = [1.0, 1.2, 1.0, 1.0] 13 | 14 | if true 15 | e = bscurve degree, knots, mults, poles, weights, 0.1, 1.2 16 | p e 17 | p e.curve.class 18 | p e.curve.degree 19 | p e.curve.knots 20 | p e.curve.mults 21 | p e.curve.poles 22 | p e.curve.weights 23 | else 24 | c = BSCurve.new degree, knots, mults, poles, weights 25 | p c 26 | p c.class 27 | p c.degree 28 | p c.knots 29 | p c.mults 30 | p c.poles 31 | p c.weights 32 | p curve(c, 0, 1).terms 33 | end 34 | -------------------------------------------------------------------------------- /inc/shape/chunk.h: -------------------------------------------------------------------------------- 1 | #ifndef _SHAPE_CHUNK_H_ 2 | #define _SHAPE_CHUNK_H_ 3 | 4 | #ifdef SIREN_ENABLE_CHUNK 5 | 6 | #include "siren.h" 7 | 8 | #include 9 | #include 10 | 11 | static struct mrb_data_type siren_chunk_type = { "Chunk", siren_shape_final }; 12 | bool siren_chunk_install(mrb_state* mrb, struct RClass* mod_siren); 13 | TopoDS_CompSolid siren_chunk_get(mrb_state* mrb, mrb_value self); 14 | mrb_value siren_chunk_new(mrb_state* mrb, const TopoDS_Shape* src); 15 | mrb_value siren_chunk_obj(mrb_state* mrb); 16 | struct RClass* siren_chunk_rclass(mrb_state* mrb); 17 | 18 | mrb_value siren_chunk_init(mrb_state* mrb, mrb_value self); 19 | mrb_value siren_chunk_to_solid(mrb_state* mrb, mrb_value self); 20 | 21 | #endif 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /test/mruby-siren.rb: -------------------------------------------------------------------------------- 1 | #!mruby 2 | 3 | puts "--------------" 4 | puts "mruby-siren.rb" 5 | puts "--------------" 6 | 7 | sp = [5.0, 1.2, 3.8] 8 | tp = [8.0, 4.2, 3.8] 9 | a = Build.line sp, tp 10 | 11 | b = Build.vertex(1, 2, 3) 12 | 13 | pts = [] 14 | pts.push [1, 2, 3] 15 | pts.push [3, 3, 3] 16 | pts.push [2, 1, 3] 17 | 18 | c = Build.polyline pts 19 | 20 | cmp = Build.compound [a, b, c] 21 | 22 | cmp2 = nil 23 | if true 24 | BRepIO.save(cmp, "/tmp/hoge.brep") 25 | cmp2 = BRepIO.load("/tmp/hoge.brep"); 26 | else 27 | IGES.save([cmp], "/tmp/hoge.iges") 28 | cmp2 = IGES.load("/tmp/hoge.iges", true); 29 | end 30 | p cmp2.shapetype 31 | 32 | cmp2.explore ShapeType::EDGE do |edge, depth| 33 | p "depth:" + depth.to_s + " type:" + edge.shapetype.to_sname 34 | end 35 | 36 | -------------------------------------------------------------------------------- /src/io/stl.cpp: -------------------------------------------------------------------------------- 1 | #include "io/stl.h" 2 | 3 | bool siren_stl_install(mrb_state* mrb, struct RClass* mod_siren) 4 | { 5 | // Class method 6 | mrb_define_class_method(mrb, mod_siren, "load_stl", siren_stl_load, MRB_ARGS_REQ(1)); 7 | // For mix-in 8 | mrb_define_method (mrb, mod_siren, "load_stl", siren_stl_load, MRB_ARGS_REQ(1)); 9 | return true; 10 | } 11 | 12 | mrb_value siren_stl_load(mrb_state* mrb, mrb_value self) 13 | { 14 | mrb_value path; 15 | int argc = mrb_get_args(mrb, "S", &path); 16 | 17 | TopoDS_Shape shape; 18 | StlAPI::Read(shape, (Standard_CString)RSTRING_PTR(path)); 19 | 20 | if (shape.IsNull()) { 21 | mrb_raisef(mrb, E_ARGUMENT_ERROR, "Failed to load STL from %S.", path); 22 | } 23 | 24 | return siren_shape_new(mrb, shape); 25 | } 26 | 27 | -------------------------------------------------------------------------------- /inc/shape/vertex.h: -------------------------------------------------------------------------------- 1 | #ifndef _SHAPE_VERTEX_H_ 2 | #define _SHAPE_VERTEX_H_ 3 | 4 | #include "siren.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | static struct mrb_data_type siren_vertex_type = { "Vertex", siren_shape_final }; 11 | bool siren_vertex_install(mrb_state* mrb, struct RClass* mod_siren); 12 | TopoDS_Vertex siren_vertex_get(mrb_state* mrb, mrb_value self); 13 | mrb_value siren_vertex_new(mrb_state* mrb, const TopoDS_Shape* src); 14 | mrb_value siren_vertex_obj(mrb_state* mrb); 15 | struct RClass* siren_vertex_rclass(mrb_state* mrb); 16 | 17 | mrb_value siren_vertex_init(mrb_state* mrb, mrb_value self); 18 | mrb_value siren_vertex_xyz(mrb_state* mrb, mrb_value self); 19 | mrb_value siren_vertex_to_v(mrb_state* mrb, mrb_value self); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /inc/shape/compound.h: -------------------------------------------------------------------------------- 1 | #ifndef _SHAPE_COMPOUND_H_ 2 | #define _SHAPE_COMPOUND_H_ 3 | 4 | #include "siren.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | static struct mrb_data_type siren_compound_type = { "Compound", siren_shape_final }; 11 | bool siren_compound_install(mrb_state* mrb, struct RClass* mod_siren); 12 | TopoDS_Compound siren_compound_get(mrb_state* mrb, mrb_value self); 13 | mrb_value siren_compound_new(mrb_state* mrb, const TopoDS_Shape* src); 14 | mrb_value siren_compound_obj(mrb_state* mrb); 15 | struct RClass* siren_compound_rclass(mrb_state* mrb); 16 | 17 | mrb_value siren_compound_init(mrb_state* mrb, mrb_value self); 18 | mrb_value siren_compound_push(mrb_state* mrb, mrb_value self); 19 | mrb_value siren_compound_delete(mrb_state* mrb, mrb_value self); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /inc/curve/bscurve.h: -------------------------------------------------------------------------------- 1 | #ifndef _CURVE_BSPLINECURVE_H_ 2 | #define _CURVE_BSPLINECURVE_H_ 3 | 4 | #include "siren.h" 5 | 6 | #include 7 | 8 | static struct mrb_data_type siren_bscurve_type = { "BSCurve", siren_curve_final }; 9 | bool siren_bscurve_install(mrb_state* mrb, struct RClass* mod_siren); 10 | handle siren_bscurve_get(mrb_state* mrb, mrb_value self); 11 | mrb_value siren_bscurve_new(mrb_state* mrb, const handle* curve); 12 | 13 | mrb_value siren_bscurve_init(mrb_state* mrb, mrb_value self); 14 | mrb_value siren_bscurve_degree(mrb_state* mrb, mrb_value self); 15 | mrb_value siren_bscurve_knots(mrb_state* mrb, mrb_value self); 16 | mrb_value siren_bscurve_mults(mrb_state* mrb, mrb_value self); 17 | mrb_value siren_bscurve_poles(mrb_state* mrb, mrb_value self); 18 | mrb_value siren_bscurve_weights(mrb_state* mrb, mrb_value self); 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /mrblib/io/plot.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Gnuplot data file I/O method 3 | # 4 | module Siren 5 | 6 | def save_plot(shape, path, face_mode = false, deflect = 1.0, angle = 5.0.to_rad) 7 | File.open(path, "w") do |f| 8 | f.puts "# Created by siren - http://siren.xyz/" 9 | if face_mode 10 | shape.faces.map {|e| 11 | e.triangle(deflect, angle).map {|m| 12 | m[0,3] 13 | } 14 | }.flatten(1).each do |m| 15 | f.puts "%.f %.f %.f" % m[0] 16 | f.puts "%.f %.f %.f" % m[1] 17 | f.puts "%.f %.f %.f" % m[2] 18 | f.puts "" 19 | end 20 | else 21 | # Curve mode 22 | shape.edges.each do |e| 23 | e.to_pts(deflect).each do |pos| 24 | f.puts "%.f %.f %.f" % pos 25 | end 26 | f.puts "" 27 | end 28 | end 29 | end 30 | nil 31 | end 32 | 33 | def save_plot(*args) 34 | Siren.save_plot(*args) 35 | end 36 | 37 | end 38 | 39 | -------------------------------------------------------------------------------- /examples/make-hulllines.rb: -------------------------------------------------------------------------------- 1 | #!siren 2 | # coding: utf-8 3 | 4 | include Siren 5 | 6 | def make_hulllines(hs) 7 | b = hs.bndbox 8 | # Make water line 9 | wls = [] 10 | (0..b.max.z).each do |d| 11 | plane = infplane [0, 0, d], Vec.zdir 12 | line = hs.section plane 13 | break if line.edges.size == 0 14 | wls << line 15 | end 16 | # Make station line 17 | sls = [] 18 | stps = [ -0.190, -0.095, 0.0, 0.25, 0.5, 0.75, 1.0, 19 | 2.0, 2.5, 3.0, 4.0, 5.0, 6.0, 7.0, 7.5, 8.0, 8.5, 9.0, 20 | 9.25, 9.5, 9.75, 9.875, 10.0, 10.095] 21 | stps.each do |st| 22 | x = b.max.x * st / 10.0 23 | plane = infplane [x, 0, 0], Vec.xdir 24 | line = hs.section plane 25 | break if line.edges.size == 0 26 | sls << line 27 | end 28 | save_brep Compound.new(wls + sls), "hull-lines.brep" 29 | end 30 | 31 | if !File.exist? "face.brep" 32 | puts "face.brep がありません。" 33 | else 34 | hullsurf = load_brep "face.brep" 35 | make_hulllines hullsurf 36 | end 37 | 38 | -------------------------------------------------------------------------------- /inc/siren.h: -------------------------------------------------------------------------------- 1 | #ifndef _SIREN_H_ 2 | #define _SIREN_H_ 3 | 4 | // Configuration 5 | #define SIREN_ENABLE_GPROP 6 | #define SIREN_ENABLE_BO 7 | #define SIREN_ENABLE_OFFSET 8 | #define SIREN_ENABLE_SHHEALING 9 | #define SIREN_ENABLE_STL 10 | #define SIREN_ENABLE_IGES 11 | #define SIREN_ENABLE_STEP 12 | 13 | // #define SIREN_ENABLE_CHUNK 14 | 15 | // C++ libraries 16 | #include 17 | #include 18 | 19 | // placement new 20 | #include 21 | 22 | // mruby libraries 23 | #include "mruby.h" 24 | #include "mruby/array.h" 25 | #include "mruby/data.h" 26 | #include "mruby/string.h" 27 | #include "mruby/class.h" 28 | #include "mruby/variable.h" 29 | 30 | // OpenCASCADE libraries 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | using namespace opencascade; 40 | 41 | #include "common.h" 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /test/splitter.rb: -------------------------------------------------------------------------------- 1 | #!siren 2 | 3 | include Siren 4 | 5 | $f = plane Vec.o, Vec.x, Vec.y, 0, 3, 0, 3 6 | 7 | class Test4FaceSplitter < MTest::Unit::TestCase 8 | 9 | def test1 10 | es = [] 11 | es << line([1, 0], [1, 2]) 12 | es << line([1, 1], [3, 1]) 13 | es << line([2, 1], [2, 3]) 14 | es << line([2, 2], [0, 2]) 15 | w = wire es, 0.1 16 | p $f.split(w) 17 | end 18 | 19 | def test2 20 | es = [] 21 | es << line([1, 0], [1, 1]) 22 | es << line([1, 1], [1, 2]) 23 | es << line([1, 1], [2, 1]) 24 | es << line([2, 1], [3, 1]) 25 | es << line([2, 1], [2, 2]) 26 | es << line([2, 2], [2, 3]) 27 | es << line([2, 2], [1, 2]) 28 | es << line([1, 2], [0, 2]) 29 | w = wire es, 0.1 30 | p $f.split(w) 31 | end 32 | 33 | def test3 34 | w = polyline [[1, 1], [2, 1], [2, 2], [1, 2], [1, 1]] 35 | p $f.split(w) 36 | end 37 | 38 | def test4 39 | w = line([0, 1], [3, 3]) 40 | p $f.split(w) 41 | end 42 | 43 | end 44 | 45 | MTest::Unit.new.run 46 | 47 | -------------------------------------------------------------------------------- /inc/filler.h: -------------------------------------------------------------------------------- 1 | #ifndef _FILLER_H_ 2 | #define _FILLER_H_ 3 | 4 | #include "siren.h" 5 | 6 | #include 7 | 8 | bool siren_filler_install(mrb_state* mrb, struct RClass* rclass); 9 | void siren_filler_final(mrb_state* mrb, void* p); 10 | static struct mrb_data_type siren_filler_type = { "Filler", siren_filler_final }; 11 | 12 | BRepFill_Filling* siren_filler_get(mrb_state* mrb, mrb_value obj); 13 | 14 | mrb_value siren_filler_init(mrb_state* mrb, mrb_value self); 15 | mrb_value siren_filler_add_bound(mrb_state* mrb, mrb_value self); 16 | mrb_value siren_filler_add(mrb_state* mrb, mrb_value self); 17 | mrb_value siren_filler_build(mrb_state* mrb, mrb_value self); 18 | mrb_value siren_filler_is_done(mrb_state* mrb, mrb_value self); 19 | mrb_value siren_filler_face(mrb_state* mrb, mrb_value self); 20 | mrb_value siren_filler_g0error(mrb_state* mrb, mrb_value self); 21 | mrb_value siren_filler_g1error(mrb_state* mrb, mrb_value self); 22 | mrb_value siren_filler_g2error(mrb_state* mrb, mrb_value self); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /mrblib/io/stl.rb: -------------------------------------------------------------------------------- 1 | # 2 | # STL file I/O method 3 | # 4 | 5 | module Siren 6 | 7 | def self.save_stl(shape, path, ascii = true, deflect = 1.0, angle = 5.0.to_rad) 8 | File.open(path, "w") do |f| 9 | if ascii 10 | f.write "solid shape, STL ascii file built with siren. http://siren.xyz/\n" 11 | shape.faces.each do |face| 12 | face.triangle(deflect, angle).each do |mesh| 13 | f.write "facet normal %8e %8e %8e\n" % mesh[5] 14 | f.write " outer loop\n" 15 | f.write " vertex %8e %8e %8e\n" % mesh[0] 16 | f.write " vertex %8e %8e %8e\n" % mesh[1] 17 | f.write " vertex %8e %8e %8e\n" % mesh[2] 18 | f.write " endloop\n" 19 | f.write "endfacet\n" 20 | end 21 | end 22 | f.write "endsolid shape\n" 23 | else 24 | raise NotImplementedError 25 | end 26 | end 27 | nil 28 | end 29 | 30 | def save_stl(*args) 31 | Siren.save_stl(*args) 32 | end 33 | 34 | end 35 | 36 | -------------------------------------------------------------------------------- /inc/shape/wire.h: -------------------------------------------------------------------------------- 1 | #ifndef _SHAPE_WIRE_H_ 2 | #define _SHAPE_WIRE_H_ 3 | 4 | #include "siren.h" 5 | #include "shape.h" 6 | #include "topalgo.h" 7 | #include "vec.h" 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | // #include 14 | // #include 15 | #include 16 | #include 17 | #include 18 | 19 | static struct mrb_data_type siren_wire_type = { "Wire", siren_shape_final }; 20 | bool siren_wire_install(mrb_state* mrb, struct RClass* mod_siren); 21 | TopoDS_Wire siren_wire_get(mrb_state* mrb, mrb_value self); 22 | mrb_value siren_wire_new(mrb_state* mrb, const TopoDS_Shape* src); 23 | mrb_value siren_wire_obj(mrb_state* mrb); 24 | struct RClass* siren_wire_rclass(mrb_state* mrb); 25 | 26 | mrb_value siren_wire_make(mrb_state* mrb, mrb_value self); 27 | mrb_value siren_wire_ordered_edges(mrb_state* mrb, mrb_value self); 28 | mrb_value siren_wire_curves(mrb_state* mrb, mrb_value self); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /mrblib/Shapes.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Array クラス拡張メソッド 3 | # Shape 配列 4 | # 5 | class Array 6 | 7 | def to_polyline 8 | Siren.polyline self 9 | end 10 | 11 | def to_polygon 12 | Siren.polygon self 13 | end 14 | 15 | def to_wire(tol = 0.001) 16 | Siren.wire self, tol 17 | end 18 | 19 | def to_loft 20 | raise NotImplementedError 21 | end 22 | 23 | def to_revol 24 | raise NotImplementedError 25 | end 26 | 27 | def to_shell 28 | Siren.shell self 29 | end 30 | 31 | def to_solid 32 | Siren.solid self.to_shell 33 | end 34 | 35 | def to_comp 36 | Siren::Compound.new self 37 | end 38 | 39 | def vertices; self.map(&:vertices).flatten end 40 | def edges; self.map(&:edges).flatten end 41 | def wires; self.map(&:wires).flatten end 42 | def faces; self.map(&:faces).flatten end 43 | def shells; self.map(&:shells).flatten end 44 | def solids; self.map(&:solids).flatten end 45 | def compounds; self.map(&:compounds).flatten end 46 | 47 | def bndbox 48 | raise NotImplementedError 49 | end 50 | 51 | end 52 | 53 | -------------------------------------------------------------------------------- /inc/offset.h: -------------------------------------------------------------------------------- 1 | #ifndef _OFFSET_H_ 2 | #define _OFFSET_H_ 3 | 4 | #include "siren.h" 5 | #include "shape.h" 6 | #include "topalgo.h" 7 | 8 | // sweep_vec 9 | #include 10 | 11 | // sweep_path 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | // loft 18 | #include 19 | 20 | // offset 21 | #include 22 | #include 23 | #include 24 | 25 | bool siren_offset_install(mrb_state* mrb, struct RClass* rclass); 26 | 27 | mrb_value siren_offset_sweep_vec(mrb_state* mrb, mrb_value self); 28 | mrb_value siren_offset_sweep_path(mrb_state* mrb, mrb_value self); 29 | mrb_value siren_offset_loft(mrb_state* mrb, mrb_value self); 30 | mrb_value siren_offset_offset_geomsurf(mrb_state* mrb, mrb_value self); 31 | mrb_value siren_offset_offset(mrb_state* mrb, mrb_value self); 32 | mrb_value siren_offset_offset_shape(mrb_state* mrb, mrb_value self); 33 | mrb_value siren_offset_pipe(mrb_state* mrb, mrb_value self); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /doc/thirdparty-license/mruby.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 mruby developers 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a 4 | copy of this software and associated documentation files (the "Software"), 5 | to deal in the Software without restriction, including without limitation 6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | and/or sell copies of the Software, and to permit persons to whom the 8 | Software is furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | DEALINGS IN THE SOFTWARE. 20 | 21 | -------------------------------------------------------------------------------- /mrblib/io/svg.rb: -------------------------------------------------------------------------------- 1 | # 2 | # SVG file I/O method 3 | # 4 | 5 | module Siren 6 | 7 | def self.save_svg(shape, path, deflect = 1.0, angle = 5.0.to_rad) 8 | File.open(path, "w") do |f| 9 | df = 0.5 # Depth factor 10 | header = <<-EOF 11 | 12 | 13 | 14 | 15 | 22 | 23 | 24 | EOF 25 | f.write header 26 | shape.edges.each do |edge| 27 | pts = edge.to_pts(deflect) 28 | sp = pts.shift 29 | d = "M#{sp.y + sp.x * df},#{sp.z + sp.x * df}" 30 | pts.each {|pt| d << "L#{pt.y + pt.x * df},#{pt.z + pt.x * df}" } 31 | f.write " \n" 32 | end 33 | f.write " \n" 34 | f.write "\n" 35 | end 36 | nil 37 | end 38 | 39 | def save_svg(*args) 40 | Siren.save_svg(*args) 41 | end 42 | 43 | end 44 | 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 dyama 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. 22 | -------------------------------------------------------------------------------- /viewer/lib/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright © 2010-2016 three.js authors 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /examples/view/lib/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright © 2010-2016 three.js authors 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /doc/thirdparty-license/mingw32.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 MinGW.org project 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a 4 | copy of this software and associated documentation files (the "Software"), 5 | to deal in the Software without restriction, including without limitation 6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | and/or sell copies of the Software, and to permit persons to whom the 8 | Software is furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice, this permission notice and the below disclaimer 11 | shall be included in all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | DEALINGS IN THE SOFTWARE. 20 | 21 | -------------------------------------------------------------------------------- /examples/view/siren-viewer.css: -------------------------------------------------------------------------------- 1 | hr { 2 | border-width: 1px 0 0 0; 3 | border-style: solid; 4 | color: white; 5 | } 6 | input { 7 | border-width: 1 1 1 1; 8 | border-style: solid; 9 | border-color: #393939; 10 | border-radius: 3px; 11 | // padding: 2 2 2 2; 12 | margin: 1 1 1 1; 13 | } 14 | .panel { 15 | position:absolute; 16 | top:10px; 17 | left:10px; 18 | size:18pt; 19 | color:white; 20 | border-radius: 5px; 21 | background: rgba(99, 99, 99, 0.8); 22 | padding:5px; 23 | } 24 | .xyz { 25 | text-align: right; 26 | } 27 | .textbox { 28 | // background-color: #a5a5a5; 29 | background-color: #eaeaea; 30 | text-align: right; 31 | width: 60px; 32 | } 33 | .textbox:hover { 34 | background-color: white; 35 | } 36 | .button { 37 | color: white; 38 | background-color: #4f4f4f; 39 | } 40 | .button:hover { 41 | color: pink; 42 | background-color: #7f7f7f; 43 | } 44 | .log { 45 | position: absolute; 46 | left: 10px; 47 | bottom: 10px; 48 | size: 10pt; 49 | color:white; 50 | overflow: auto; 51 | width: 600px; 52 | height: 60px; 53 | border-radius: 5px; 54 | background: rgba(79, 79, 79, 0.8); 55 | padding:5px; 56 | } 57 | .alert { 58 | color: pink; 59 | } 60 | -------------------------------------------------------------------------------- /inc/curve/circle.h: -------------------------------------------------------------------------------- 1 | #ifndef _CURVE_CIRCLE_H_ 2 | #define _CURVE_CIRCLE_H_ 3 | 4 | #include "siren.h" 5 | 6 | #include 7 | 8 | static struct mrb_data_type siren_circle_type = { "Circle", siren_curve_final }; 9 | bool siren_circle_install(mrb_state* mrb, struct RClass* mod_siren); 10 | handle siren_circle_get(mrb_state* mrb, mrb_value self); 11 | mrb_value siren_circle_new(mrb_state* mrb, const handle* curve); 12 | 13 | mrb_value siren_circle_radius(mrb_state* mrb, mrb_value self); 14 | mrb_value siren_circle_radius_set(mrb_state* mrb, mrb_value self); 15 | mrb_value siren_circle_center(mrb_state* mrb, mrb_value self); 16 | mrb_value siren_circle_center_set(mrb_state* mrb, mrb_value self); 17 | mrb_value siren_circle_area(mrb_state* mrb, mrb_value self); 18 | mrb_value siren_circle_length(mrb_state* mrb, mrb_value self); 19 | mrb_value siren_circle_normal(mrb_state* mrb, mrb_value self); 20 | mrb_value siren_circle_normal_set(mrb_state* mrb, mrb_value self); 21 | mrb_value siren_circle_dir(mrb_state* mrb, mrb_value self); 22 | mrb_value siren_circle_dir_set(mrb_state* mrb, mrb_value self); 23 | mrb_value siren_circle_dist(mrb_state* mrb, mrb_value self); 24 | mrb_value siren_circle_distdist(mrb_state* mrb, mrb_value self); 25 | mrb_value siren_circle_contain(mrb_state* mrb, mrb_value self); 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /examples/least-squares-method-2d.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # coding: utf-8 3 | 4 | # 最小二乗法による直線 y = a * x + b の式の算出 5 | 6 | s1 = [[32.0, 24.0], 7 | [131.0, 62.0], 8 | [159.0, 110.0], 9 | [245.0, 146.0]] 10 | s2 = [[ 0.0, 0.0], 11 | [ 0.0, 10.0], 12 | [ 0.0, 20.0], 13 | [ 0.0, 30.0]] 14 | s3 = [[ 0.0, 0.0], 15 | [ 10.0, 0.0], 16 | [ 20.0, 0.0], 17 | [ 30.0, 0.0]] 18 | s = s1 19 | 20 | def s.sum(&b) 21 | self.inject(0.0) do |t, pnt| 22 | t + b.call(pnt[0], pnt[1]) 23 | end 24 | end 25 | 26 | n = s.size.to_f 27 | a = (n * s.sum{|x,y|x*y} - s.sum{|x,y|x} * s.sum{|x,y|y}) / 28 | (n * s.sum{|x,y|x**2} - (s.sum{|x,y|x})**2) 29 | b = (s.sum{|x,y|x**2} * s.sum{|x,y|y} - s.sum{|x,y|x*y} * s.sum{|x,y|x}) / 30 | (n * s.sum{|x,y|x**2} - (s.sum{|x,y|x})**2) 31 | 32 | puts "a: #{a}" 33 | puts "b: #{b}" 34 | 35 | line = nil 36 | if a == 0 && b == 0 37 | puts "horizontal" 38 | line = Siren.infline [0.0, s[0].y], Siren::Vec.xdir 39 | elsif a.nan? && b.nan? 40 | puts "vertical" 41 | line = Siren.infline [s[0].x, 0.0], Siren::Vec.ydir 42 | else 43 | p1 = [0.0, b] 44 | p2 = [100.0, a*100.0+b] 45 | dir = p2 - p1 46 | line = Siren.infline p1, dir 47 | end 48 | 49 | ps = s.map {|pt| Siren.vertex pt} 50 | ps << line 51 | comp = Siren::Compound.new ps 52 | Siren.save_brep comp, "sample-line.brep" 53 | 54 | -------------------------------------------------------------------------------- /test/curvature.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env siren 2 | # coding: utf-8 3 | 4 | # unit = 1m 5 | 6 | # 適当な構成点を与えて曲線を発生 7 | # (入出力ベクトルは省略) 8 | c = Build.curve([ 9 | [0, 0, 0], [0, 1, 0], 10 | [0, 2, 0.5], [0, 3, 1.8], 11 | [0, 4, 3.8], [0, 5, 5.5], 12 | [0, 6, 6.8], [0, 6.5, 8.2], 13 | [0, 6.8, 9.5], [0, 7, 11.2], 14 | ]) 15 | 16 | # トレランス、刻みピッチ、曲率ベクトルの大きさ係数 17 | t = 0.01 # 1cm 18 | pt = 0.2 19 | f = -3.0 20 | 21 | # 始終点の曲線パラメータを取得 22 | spr = c.param(c.sp, t) 23 | tpr = c.param(c.tp, t) 24 | 25 | cvs = [] 26 | pps = [] 27 | 28 | # 計算 29 | spr.floor.step(tpr.floor, pt) do |pr| 30 | # パラメータにおける三次元位置 31 | cp = c.to_xyz pr 32 | # パラメータにおける曲率ベクトル 33 | cv = c.curvature pr 34 | # ベクトル同士の和差、スカラ積は未実装・・・ 35 | # pp = cp + cv * f 36 | pp = [cp.x+cv.x*f, cp.y+cv.y*f, cp.z+cv.z*f] 37 | cvs.push Build.line(cp, pp) 38 | pps.push pp 39 | end 40 | 41 | # 以下、表示 42 | window = X11Window::new 43 | world = World.new `echo $DISPLAY`.chomp 44 | cam = Camera::new world, window.handle 45 | 46 | s_cvs = Skin.new Build.compound cvs 47 | s_cvs.color = ColorName::WHITE 48 | world.add s_cvs 49 | 50 | s_c = Skin.new c 51 | s_c.color = ColorName::RED 52 | world.add s_c 53 | 54 | s_pl = Skin.new Build.polyline(pps) 55 | s_pl.color = ColorName::GREEN 56 | world.add s_pl 57 | 58 | # 視点・視野設定 59 | cam.proj = OrientType::Xneg 60 | cam.fitz 61 | cam.fit 62 | 63 | # Enter が押されたら終了 64 | STDIN.gets 65 | -------------------------------------------------------------------------------- /examples/iges-curve2dxf-polyline.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/siren 2 | # coding: utf-8 3 | # 4 | # IGES curve to DXF polyline 5 | # 6 | 7 | # DXF データ要素の書式付き出力 8 | def ds(no, val) 9 | sprintf("%3d\n", no) + 10 | (val.is_a?(Float) ? sprintf("%14.6f\n", val) : "#{val}\n") 11 | end 12 | 13 | # Array クラス拡張 14 | class Array 15 | def to_dxf 16 | s = "" 17 | s += ds 10, self.x 18 | s += ds 20, self.y 19 | s += ds 30, self.z 20 | end 21 | end 22 | 23 | # Shape クラス拡張 24 | class Shape 25 | 26 | # レイヤー名 アクセサ 27 | def layer; @layer end 28 | def layer=(value); @layer=value end 29 | 30 | # DXF ポリライン出力 31 | def to_polyline 32 | s = "" 33 | # エッジ単位で処理 34 | self.edges do |edge| 35 | s += ds 0, "POLYLINE" 36 | s += ds 6, 3 37 | s += ds 8, @layer 38 | s += ds 66, 1 39 | s += ds 70, 8 40 | s += [].to_dxf 41 | # 点列化 42 | edge.to_pts.each do |pnt| 43 | s += ds 0, "VERTEX" 44 | s += ds 8, @layer 45 | s += pnt.to_dxf 46 | end 47 | s += ds 0, "SEQEND" 48 | s += ds 8, @layer 49 | end 50 | return s 51 | end 52 | end 53 | 54 | File.open("hammer.dxf", "w") do |f| 55 | f.write ds(0, "SECTION") 56 | f.write ds(2, "ENTITIES") 57 | # IGES の読み込み・DXF ポリラインの出力 58 | IGES.load("hammer.iges").each do |shape| 59 | shape.layer = "BASE" 60 | f.write shape.to_polyline 61 | end 62 | f.write ds(0, "ENDSEC") 63 | f.write ds(0, "EOF") 64 | end 65 | 66 | puts "done." 67 | 68 | -------------------------------------------------------------------------------- /src/common.cpp: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | /* this function copied from class.c */ 4 | mrb_value mrb_instance_alloc(mrb_state *mrb, mrb_value cv) 5 | { 6 | struct RClass *c = mrb_class_ptr(cv); 7 | struct RObject *o; 8 | enum mrb_vtype ttype = MRB_INSTANCE_TT(c); 9 | 10 | if (c->tt == MRB_TT_SCLASS) 11 | mrb_raise(mrb, E_TYPE_ERROR, "can't create instance of singleton class"); 12 | 13 | if (ttype == 0) ttype = MRB_TT_OBJECT; 14 | o = (struct RObject*)mrb_obj_alloc(mrb, ttype, c); 15 | return mrb_obj_value(o); 16 | } 17 | /* end of function */ 18 | 19 | void siren_ary_to_xyz(mrb_state* mrb, mrb_value ary, Standard_Real& x, Standard_Real& y, Standard_Real& z) 20 | { 21 | x = 0.0; y = 0.0; z = 0.0; 22 | int len = mrb_ary_len(mrb, ary); 23 | if (len > 0) { 24 | mrb_value val = mrb_ary_ref(mrb, ary, 0); 25 | if (mrb_float_p(val)) { 26 | x = mrb_float(val); 27 | } 28 | else if (mrb_fixnum_p(val)) { 29 | x = mrb_fixnum(val); 30 | } 31 | } 32 | if (len > 1) { 33 | mrb_value val = mrb_ary_ref(mrb, ary, 1); 34 | if (mrb_float_p(val)) { 35 | y = mrb_float(val); 36 | } 37 | else if (mrb_fixnum_p(val)) { 38 | y = mrb_fixnum(val); 39 | } 40 | } 41 | if (len > 2) { 42 | mrb_value val = mrb_ary_ref(mrb, ary, 2); 43 | if (mrb_float_p(val)) { 44 | z = mrb_float(val); 45 | } 46 | else if (mrb_fixnum_p(val)) { 47 | z = mrb_fixnum(val); 48 | } 49 | } 50 | return; 51 | } 52 | 53 | -------------------------------------------------------------------------------- /mrblib/Vec.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Vec クラス拡張メソッド 3 | # 4 | class Siren::Vec 5 | 6 | def self.zero 7 | Siren::Vec.new 0.0, 0.0, 0.0 8 | end 9 | 10 | def self.o 11 | Siren::Vec.new 0.0, 0.0, 0.0 12 | end 13 | 14 | def self.x 15 | Siren::Vec.new 1.0, 0.0, 0.0 16 | end 17 | 18 | def self.y 19 | Siren::Vec.new 0.0, 1.0, 0.0 20 | end 21 | 22 | def self.z 23 | Siren::Vec.new 0.0, 0.0, 1.0 24 | end 25 | 26 | def self.xy 27 | Siren::Vec.new 1.0, 1.0, 0.0 28 | end 29 | 30 | def self.xz 31 | Siren::Vec.new 1.0, 0.0, 1.0 32 | end 33 | 34 | def self.yx 35 | Siren::Vec.new 1.0, 1.0, 0.0 36 | end 37 | 38 | def self.yz 39 | Siren::Vec.new 0.0, 1.0, 1.0 40 | end 41 | 42 | def self.zx 43 | Siren::Vec.new 1.0, 0.0, 1.0 44 | end 45 | 46 | def self.zy 47 | Siren::Vec.new 0.0, 1.0, 1.0 48 | end 49 | 50 | def self.xyz 51 | Siren::Vec.new 1.0, 1.0, 1.0 52 | end 53 | 54 | def self.xdir 55 | Siren::Vec.x 56 | end 57 | 58 | def self.ydir 59 | Siren::Vec.y 60 | end 61 | 62 | def self.zdir 63 | Siren::Vec.z 64 | end 65 | 66 | ## 67 | # Return this object as a string. 68 | def to_s 69 | "#" % [self.object_id, self.x, self.y, self.z] 70 | end 71 | alias_method :inspect, :to_s 72 | 73 | ## 74 | # Return x, y and z values of this object as an array. 75 | def to_a 76 | [self.x, self.y, self.z] 77 | end 78 | alias_method :to_ary, :to_a 79 | alias_method :xyz, :to_a 80 | 81 | end 82 | -------------------------------------------------------------------------------- /examples/fillet-pipe.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/siren 2 | 3 | include Siren 4 | 5 | # 半径を指定して内接円弧を作成する 6 | def fillet(p1, p2, cp, r) 7 | 8 | ls1 = p1.to_v - cp.to_v 9 | ls2 = p2.to_v - cp.to_v 10 | cp = cp.to_v 11 | 12 | # 2直線のなす角度 13 | ang_rad = ls1.angle(ls2) 14 | if ang_rad.abs < 0.001 15 | return nil 16 | end 17 | 18 | # 交点から開始・終了点までの距離 19 | a = Math.tan(Math::PI / 2 - ang_rad / 2) * r 20 | 21 | # 始点 22 | startp = cp + (ls1.normal * a) 23 | 24 | # 終点 25 | termp = cp + (ls2.normal * a) 26 | 27 | # 2等分線ベクトル 28 | v = (startp - cp).normal + (termp - cp).normal 29 | v.normal! 30 | 31 | # 交点から中心点までの距離 32 | b = r / Math.cos(Math::PI / 2 - ang_rad / 2); 33 | 34 | # 中心点 35 | centerp = cp + (v * b); 36 | 37 | # 通過点 38 | thrup = centerp + (-v * r); 39 | 40 | return arc3p startp, thrup, termp 41 | end 42 | 43 | # パイプの径 44 | pipe_r = 1.0 45 | 46 | # エルボの径 47 | elbow_r = 2.0 48 | 49 | # パイプの経路 50 | pts = [[0, 0, 0], [10, 0, 0], [10, 10, 6], [15, 10, 10], [20, 15, 10]] 51 | 52 | 53 | # 経路パスを作成 54 | edges = [] 55 | pts.each_cons(3) do |ar| 56 | arc = fillet(ar[0], ar[2], ar[1], elbow_r) 57 | if edges.size == 0 58 | edges.push line(ar[0], arc.sp) 59 | else 60 | edges.push line(edges.last.tp, arc.sp) 61 | end 62 | edges.push arc 63 | end 64 | edges.push line(edges.last.tp, pts.last) 65 | path = wire edges, 0.01 66 | 67 | # 配管のモデル化 68 | profile = circle [], [1], pipe_r 69 | pipe = pipe profile, path, 0, true 70 | 71 | # 保存 72 | save_brep pipe, "pipe.brep" 73 | 74 | puts "done" 75 | 76 | -------------------------------------------------------------------------------- /src/curve/ellipse.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * ellipse.cpp 3 | * Implementation of singleton methods for ELLIPSE 4 | */ 5 | 6 | #include "curve.h" 7 | 8 | mrb_value siren_ellipse_new(mrb_state* mrb, const handle* curve) 9 | { 10 | struct RClass* mod_siren = mrb_module_get(mrb, "Siren"); 11 | mrb_value obj; 12 | obj = mrb_instance_alloc(mrb, mrb_const_get(mrb, mrb_obj_value(mod_siren), mrb_intern_lit(mrb, "Ellipse"))); 13 | void* p = mrb_malloc(mrb, sizeof(handle)); 14 | handle* hgcurve = new(p) handle(); 15 | *hgcurve = *curve; 16 | DATA_PTR(obj) = hgcurve; 17 | DATA_TYPE(obj) = &siren_ellipse_type; 18 | return obj; 19 | } 20 | 21 | handle siren_ellipse_get(mrb_state* mrb, mrb_value self) 22 | { 23 | handle hgc = *static_cast*>(mrb_get_datatype(mrb, self, &siren_ellipse_type)); 24 | if (hgc.IsNull()) { mrb_raise(mrb, E_RUNTIME_ERROR, "The geometry type is not Curve."); } 25 | handle ellipse = handle::DownCast(hgc); 26 | if (ellipse.IsNull()) { mrb_raise(mrb, E_RUNTIME_ERROR, "The geometry type is not Ellipse."); } 27 | return ellipse; 28 | } 29 | 30 | bool siren_ellipse_install(mrb_state* mrb, struct RClass* mod_siren) 31 | { 32 | struct RClass* cls_curve = siren_curve_rclass(mrb); 33 | struct RClass* cls_ellipse = mrb_define_class_under(mrb, mod_siren, "Ellipse", cls_curve); 34 | MRB_SET_INSTANCE_TT(cls_ellipse, MRB_TT_DATA); 35 | mrb_define_method(mrb, cls_ellipse, "initialize", siren_curve_init, MRB_ARGS_NONE()); 36 | return true; 37 | } 38 | -------------------------------------------------------------------------------- /src/curve/parabola.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * parabola.cpp 3 | * Implementation of singleton methods for PARABOLA 4 | */ 5 | 6 | #include "curve.h" 7 | 8 | mrb_value siren_parabola_new(mrb_state* mrb, const handle* curve) 9 | { 10 | struct RClass* mod_siren = mrb_module_get(mrb, "Siren"); 11 | mrb_value obj; 12 | obj = mrb_instance_alloc(mrb, mrb_const_get(mrb, mrb_obj_value(mod_siren), mrb_intern_lit(mrb, "Parabola"))); 13 | void* p = mrb_malloc(mrb, sizeof(handle)); 14 | handle* hgcurve = new(p) handle(); 15 | *hgcurve = *curve; 16 | DATA_PTR(obj) = hgcurve; 17 | DATA_TYPE(obj) = &siren_parabola_type; 18 | return obj; 19 | } 20 | 21 | handle siren_parabola_get(mrb_state* mrb, mrb_value self) 22 | { 23 | handle hgc = *static_cast*>(mrb_get_datatype(mrb, self, &siren_parabola_type)); 24 | if (hgc.IsNull()) { mrb_raise(mrb, E_RUNTIME_ERROR, "The geometry type is not Curve."); } 25 | handle parabola = handle::DownCast(hgc); 26 | if (parabola.IsNull()) { mrb_raise(mrb, E_RUNTIME_ERROR, "The geometry type is not Parabola."); } 27 | return parabola; 28 | } 29 | 30 | bool siren_parabola_install(mrb_state* mrb, struct RClass* mod_siren) 31 | { 32 | struct RClass* cls_curve = siren_curve_rclass(mrb); 33 | struct RClass* cls_parabola = mrb_define_class_under(mrb, mod_siren, "Parabola", cls_curve); 34 | MRB_SET_INSTANCE_TT(cls_parabola, MRB_TT_DATA); 35 | mrb_define_method(mrb, cls_parabola, "initialize", siren_curve_init, MRB_ARGS_NONE()); 36 | return true; 37 | } 38 | -------------------------------------------------------------------------------- /src/curve/hyperbola.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * hyperbola.cpp 3 | * Implementation of singleton methods for HYPERBOLA 4 | */ 5 | 6 | #include "curve.h" 7 | 8 | mrb_value siren_hyperbola_new(mrb_state* mrb, const handle* curve) 9 | { 10 | struct RClass* mod_siren = mrb_module_get(mrb, "Siren"); 11 | mrb_value obj; 12 | obj = mrb_instance_alloc(mrb, mrb_const_get(mrb, mrb_obj_value(mod_siren), mrb_intern_lit(mrb, "Hyperbola"))); 13 | void* p = mrb_malloc(mrb, sizeof(handle)); 14 | handle* hgcurve = new(p) handle(); 15 | *hgcurve = *curve; 16 | DATA_PTR(obj) = hgcurve; 17 | DATA_TYPE(obj) = &siren_hyperbola_type; 18 | return obj; 19 | } 20 | 21 | handle siren_hyperbola_get(mrb_state* mrb, mrb_value self) 22 | { 23 | handle hgc = *static_cast*>(mrb_get_datatype(mrb, self, &siren_hyperbola_type)); 24 | if (hgc.IsNull()) { mrb_raise(mrb, E_RUNTIME_ERROR, "The geometry type is not Curve."); } 25 | handle hyperbola = handle::DownCast(hgc); 26 | if (hyperbola.IsNull()) { mrb_raise(mrb, E_RUNTIME_ERROR, "The geometry type is not Hyperbola."); } 27 | return hyperbola; 28 | } 29 | 30 | bool siren_hyperbola_install(mrb_state* mrb, struct RClass* mod_siren) 31 | { 32 | struct RClass* cls_curve = siren_curve_rclass(mrb); 33 | struct RClass* cls_hyperbola = mrb_define_class_under(mrb, mod_siren, "Hyperbola", cls_curve); 34 | MRB_SET_INSTANCE_TT(cls_hyperbola, MRB_TT_DATA); 35 | mrb_define_method(mrb, cls_hyperbola, "initialize", siren_curve_init, MRB_ARGS_NONE()); 36 | return true; 37 | } 38 | -------------------------------------------------------------------------------- /mrblib/io/ply.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Stanford PLY file I/O method 3 | # 4 | module Siren 5 | 6 | def self.save_ply(shape, path, deflect = 1.0, angle = 5.0.to_rad) 7 | File.open(path, "w") do |f| 8 | fs = shape.faces.map {|e| 9 | e.triangle(deflect, angle).map {|m| 10 | m[0,3] 11 | } 12 | }.flatten(1) 13 | es = shape.edges(Siren::Face).map{|e| 14 | e.to_pts(deflect) 15 | } 16 | vs = [fs, es].flatten(2).sort.uniq 17 | f.puts "ply" 18 | f.puts "format ascii 1.0" 19 | f.puts "comment Created by siren - http://siren.xyz/" 20 | if vs.size > 0 21 | f.puts "element vertex %d" % vs.size 22 | f.puts "property float x" 23 | f.puts "property float y" 24 | f.puts "property float z" 25 | end 26 | if es.size > 0 27 | f.puts "element edge %d" % es.size 28 | f.puts "property uint vertex1" 29 | f.puts "property uint vertex2" 30 | end 31 | if fs.size > 0 32 | f.puts "element face %d" % fs.size 33 | f.puts "property list uchar uint vertex_indices" 34 | end 35 | f.puts "end_header" 36 | vs.each do |e| 37 | f.puts "%.f %.f %.f" % e 38 | end 39 | es.each do |e| 40 | sp = vs.index(e.first) 41 | tp = vs.index(e.last) 42 | f.puts "%d %d" % [sp, tp] 43 | end 44 | fs.each do |e| 45 | pts = e.map{|m| vs.index(m)} 46 | f.puts pts.size.to_s + " " + pts.join(" ") 47 | end 48 | nil 49 | end 50 | end 51 | 52 | def save_ply(*args) 53 | Siren.save_ply(*args) 54 | end 55 | 56 | end 57 | 58 | -------------------------------------------------------------------------------- /src/curve/offsetcurve.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * offsetcurve.cpp 3 | * Implementation of singleton methods for OFFSETCURVE 4 | */ 5 | 6 | #include "curve.h" 7 | 8 | mrb_value siren_offsetcurve_new(mrb_state* mrb, const handle* curve) 9 | { 10 | struct RClass* mod_siren = mrb_module_get(mrb, "Siren"); 11 | mrb_value obj; 12 | obj = mrb_instance_alloc(mrb, mrb_const_get(mrb, mrb_obj_value(mod_siren), mrb_intern_lit(mrb, "OffsetCurve"))); 13 | void* p = mrb_malloc(mrb, sizeof(handle)); 14 | handle* hgcurve = new(p) handle(); 15 | *hgcurve = *curve; 16 | DATA_PTR(obj) = hgcurve; 17 | DATA_TYPE(obj) = &siren_offsetcurve_type; 18 | return obj; 19 | } 20 | 21 | handle siren_offsetcurve_get(mrb_state* mrb, mrb_value self) 22 | { 23 | handle hgc = *static_cast*>(mrb_get_datatype(mrb, self, &siren_offsetcurve_type)); 24 | if (hgc.IsNull()) { mrb_raise(mrb, E_RUNTIME_ERROR, "The geometry type is not Curve."); } 25 | handle offsetcurve = handle::DownCast(hgc); 26 | if (offsetcurve.IsNull()) { mrb_raise(mrb, E_RUNTIME_ERROR, "The geometry type is not OffsetCurve."); } 27 | return offsetcurve; 28 | } 29 | 30 | bool siren_offsetcurve_install(mrb_state* mrb, struct RClass* mod_siren) 31 | { 32 | struct RClass* cls_curve = siren_curve_rclass(mrb); 33 | struct RClass* cls_offsetcurve = mrb_define_class_under(mrb, mod_siren, "offsetcurve", cls_curve); 34 | MRB_SET_INSTANCE_TT(cls_offsetcurve, MRB_TT_DATA); 35 | mrb_define_method(mrb, cls_offsetcurve, "initialize", siren_curve_init, MRB_ARGS_NONE()); 36 | return true; 37 | } 38 | -------------------------------------------------------------------------------- /mrblib/io/dxf.rb: -------------------------------------------------------------------------------- 1 | # 2 | # AutoCAD DXF file I/O method 3 | # 4 | module Siren 5 | 6 | def self.save_dxf(shape, path, deflect = 1.0, angle = 5.0.to_rad) 7 | File.open(path, "w") do |f| 8 | @ff = f 9 | def self.w(code, data) 10 | @ff.write "% 3d\n#{data}\n" % [code] 11 | end 12 | def self.wp(pt, ofs = 0) 13 | w 10 + ofs, pt.x 14 | w 20 + ofs, pt.y 15 | w 30 + ofs, pt.z 16 | end 17 | w 0, "SECTION" 18 | w 2, "ENTITIES" 19 | shape.vertices(Siren::Edge).each do |e| 20 | w 0, "POINT" 21 | w 8, "0" 22 | wp e.xyz 23 | end 24 | shape.edges(Siren::Face).each do |e| 25 | ps = e.to_pts(deflect) 26 | if ps.size == 2 27 | w 0, "LINE" 28 | w 8, "0" 29 | wp ps.first 30 | wp ps.last, 1 31 | else 32 | w 0, "POLYLINE" 33 | wp [0, 0, 0] 34 | w 8, "0" 35 | w 66, 1 36 | w 70, 8 # 3D=8,2D=0 37 | ps.each do |pt| 38 | w 0, "VERTEX" 39 | w 8, "0" 40 | wp pt 41 | end 42 | w 0, "SEQEND" 43 | end 44 | end 45 | shape.faces.each do |face| 46 | face.triangle(deflect, angle).each do |m| 47 | w 0, "3DFACE" 48 | w 8, "0" 49 | mm = m[0,3] 50 | wp mm[0] 51 | wp mm[1], 1 52 | wp mm[2], 2 53 | wp mm[0], 3 54 | w 70, 8 55 | end 56 | end 57 | w 0, "ENDSEC" 58 | w 0, "EOF" 59 | end 60 | nil 61 | end 62 | 63 | def save_dxf(*args) 64 | Siren.save_dxf(*args) 65 | end 66 | 67 | end 68 | 69 | -------------------------------------------------------------------------------- /src/io/step.cpp: -------------------------------------------------------------------------------- 1 | #include "io/step.h" 2 | 3 | #ifdef SIREN_ENABLE_STEP 4 | 5 | bool siren_step_install(mrb_state* mrb, struct RClass* mod_siren) 6 | { 7 | // Class method 8 | mrb_define_class_method(mrb, mod_siren, "save_step", siren_step_save, MRB_ARGS_REQ(2)); 9 | mrb_define_class_method(mrb, mod_siren, "load_step", siren_step_load, MRB_ARGS_REQ(1)); 10 | // For mix-in 11 | mrb_define_method (mrb, mod_siren, "save_step", siren_step_save, MRB_ARGS_REQ(2)); 12 | mrb_define_method (mrb, mod_siren, "load_step", siren_step_load, MRB_ARGS_REQ(1)); 13 | return true; 14 | } 15 | 16 | mrb_value siren_step_save(mrb_state* mrb, mrb_value self) 17 | { 18 | mrb_value s; 19 | mrb_value path; 20 | int argc = mrb_get_args(mrb, "oS", &s, &path); 21 | TopoDS_Shape* shape = siren_shape_get(mrb, s); 22 | STEPControl_Writer writer; 23 | if (writer.Transfer(*shape, STEPControl_AsIs, Standard_True) != IFSelect_RetDone) { 24 | mrb_raise(mrb, E_ARGUMENT_ERROR, "Failed to transfer Shape to STEP entity."); 25 | } 26 | if (writer.Write(RSTRING_PTR(path)) != IFSelect_RetDone) { 27 | mrb_raisef(mrb, E_RUNTIME_ERROR, "Failed to write STEP to %S.", path); 28 | } 29 | return mrb_nil_value(); 30 | } 31 | 32 | mrb_value siren_step_load(mrb_state* mrb, mrb_value self) 33 | { 34 | mrb_value path; 35 | int argc = mrb_get_args(mrb, "S", &path); 36 | STEPControl_Reader reader; 37 | if (!reader.ReadFile((Standard_CString)RSTRING_PTR(path))) { 38 | mrb_raisef(mrb, E_ARGUMENT_ERROR, "Failed to load STEP from %S.", path); 39 | } 40 | reader.NbRootsForTransfer(); 41 | reader.TransferRoots(); 42 | return siren_shape_new(mrb, reader.OneShape()); 43 | } 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /inc/curve.h: -------------------------------------------------------------------------------- 1 | #ifndef _CURVE_H_ 2 | #define _CURVE_H_ 3 | 4 | #include "siren.h" 5 | 6 | #include 7 | 8 | void siren_curve_final(mrb_state* mrb, void* p); 9 | static struct mrb_data_type siren_curve_type = { "Curve", siren_curve_final }; 10 | 11 | #include "curve/line.h" 12 | #include "curve/circle.h" 13 | #include "curve/ellipse.h" 14 | #include "curve/hyperbola.h" 15 | #include "curve/parabola.h" 16 | #include "curve/bzcurve.h" 17 | #include "curve/bscurve.h" 18 | #include "curve/offsetcurve.h" 19 | 20 | inline GeomAbs_CurveType siren_curve_geomtype_native(opencascade::handle hgc) 21 | { 22 | opencascade::handle type = hgc->DynamicType(); 23 | /* Geom_BoundedCurve */ 24 | if (STANDARD_TYPE(Geom_BezierCurve) == type) { return GeomAbs_BezierCurve; } 25 | if (STANDARD_TYPE(Geom_BSplineCurve) == type) { return GeomAbs_BSplineCurve; } 26 | /* Geom_Conic */ 27 | if (STANDARD_TYPE(Geom_Circle) == type) { return GeomAbs_Circle; } 28 | if (STANDARD_TYPE(Geom_Ellipse) == type) { return GeomAbs_Ellipse; } 29 | if (STANDARD_TYPE(Geom_Hyperbola) == type) { return GeomAbs_Hyperbola; } 30 | if (STANDARD_TYPE(Geom_Parabola) == type) { return GeomAbs_Parabola; } 31 | /* Line */ 32 | if (STANDARD_TYPE(Geom_Line) == type) { return GeomAbs_Line; } 33 | return GeomAbs_OtherCurve; 34 | } 35 | 36 | bool siren_curve_install(mrb_state* mrb, struct RClass* rclass); 37 | opencascade::handle* siren_curve_get(mrb_state* mrb, mrb_value obj); 38 | struct RClass* siren_curve_rclass(mrb_state* mrb); 39 | 40 | mrb_value siren_curve_new(mrb_state* mrb, const opencascade::handle* curve); 41 | mrb_value siren_curve_init(mrb_state* mrb, mrb_value self); 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /examples/mqo2brep.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env siren 2 | # vim:fileencoding=utf-8 3 | 4 | class MqObject 5 | attr_accessor :vertex, :face 6 | def build 7 | faces = face.map do |s| 8 | /V\(([^\)]+)\)/ =~ s 9 | nos = $1.split(/ */).map(&:to_i) 10 | if nos.last != nos.first 11 | nos << nos.first 12 | end 13 | pts = nos.map{|p| @vertex[p]} 14 | begin 15 | Siren.polygon pts, true 16 | rescue 17 | nil 18 | end 19 | end 20 | faces.select{|f| f != nil} 21 | end 22 | end 23 | 24 | models = [] 25 | 26 | ARGV.each do |path| 27 | File.open(path, "r") do |f| 28 | while line = f.gets 29 | line.gsub!(/^\s+/, "") 30 | if /^Object "([^"]*)"/ =~ line 31 | objname = $1 32 | curr = MqObject.new 33 | # puts "#{objname} found." 34 | 35 | while line = f.gets 36 | break if /^vertex/ =~ line.gsub(/^\s+/,"") 37 | end 38 | curr.vertex = Array.new 39 | while line = f.gets 40 | break if /^}/ =~ line.gsub!(/^\s+/,"") 41 | curr.vertex.push(line.split(/\s/).select{|val| val != nil }.map {|val| val.to_f }) 42 | end 43 | 44 | while line = f.gets 45 | break if /^face/ =~ line.gsub(/^\s+/,"") 46 | end 47 | curr.face = Array.new 48 | while line = f.gets 49 | break if /^}/ =~ line.gsub!(/^\s+/,"") 50 | curr.face.push(line.gsub(/ +/, " ").gsub(/\n/,"")) 51 | end 52 | 53 | models.push curr 54 | end 55 | end 56 | end 57 | end 58 | 59 | if models.size > 0 60 | fs = [] 61 | models.each do |m| 62 | fs += m.build 63 | end 64 | 65 | Siren.save_brep Siren::Compound.new(fs), "mqo.brep" 66 | puts "done" 67 | end 68 | 69 | -------------------------------------------------------------------------------- /inc/shape/solid.h: -------------------------------------------------------------------------------- 1 | #ifndef _SHAPE_SOLID_H_ 2 | #define _SHAPE_SOLID_H_ 3 | 4 | #include "siren.h" 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | static struct mrb_data_type siren_solid_type = { "Solid", siren_shape_final }; 18 | bool siren_solid_install(mrb_state* mrb, struct RClass* mod_siren); 19 | TopoDS_Solid siren_solid_get(mrb_state* mrb, mrb_value self); 20 | mrb_value siren_solid_new(mrb_state* mrb, const TopoDS_Shape* src); 21 | mrb_value siren_solid_obj(mrb_state* mrb); 22 | struct RClass* siren_solid_rclass(mrb_state* mrb); 23 | 24 | mrb_value siren_solid_init(mrb_state* mrb, mrb_value self); 25 | 26 | mrb_value siren_solid_box (mrb_state* mrb, mrb_value self); 27 | mrb_value siren_solid_box2p (mrb_state* mrb, mrb_value self); 28 | mrb_value siren_solid_boxax (mrb_state* mrb, mrb_value self); 29 | mrb_value siren_solid_sphere (mrb_state* mrb, mrb_value self); 30 | mrb_value siren_solid_cylinder (mrb_state* mrb, mrb_value self); 31 | mrb_value siren_solid_cone (mrb_state* mrb, mrb_value self); 32 | mrb_value siren_solid_torus (mrb_state* mrb, mrb_value self); 33 | mrb_value siren_solid_halfspace (mrb_state* mrb, mrb_value self); 34 | mrb_value siren_solid_prism (mrb_state* mrb, mrb_value self); 35 | mrb_value siren_solid_revol (mrb_state* mrb, mrb_value self); 36 | mrb_value siren_solid_revolution (mrb_state* mrb, mrb_value self); 37 | mrb_value siren_solid_wedge (mrb_state* mrb, mrb_value self); 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /test/nurbssurf.rb: -------------------------------------------------------------------------------- 1 | #!siren 2 | # coding: utf-8 3 | 4 | def test1 5 | udeg = 1 6 | uknots = [[0, 2], [1, 2]] 7 | vdeg = 2 8 | vknots = [[0, 3], [1, 1], [2, 3]] 9 | poles = [ 10 | [[Vec::new(0, 0, 0), 1.0], [Vec::new(10, 0, 5), 1.0]], 11 | [[Vec::new(0, 10, 2), 1.0], [Vec::new(10, 10, 3), 1.0]], 12 | [[Vec::new(0, 20, 10), 1.0], [Vec::new(10, 20, 20), 1.0]], 13 | [[Vec::new(0, 30, 0), 1.0], [Vec::new(10, 30, 0), 1.0]] 14 | ] 15 | 16 | surf = Build.nurbssurf udeg, uknots, vdeg, vknots, poles 17 | box = Prim.box Vec.new(5, 5, 5), Vec.new(2, 2, 1) 18 | es = Algo.section(surf, box) 19 | w = Build.wire es.explore(ShapeType::EDGE).map{|n|n} 20 | surf2 = Build.nurbssurf udeg, uknots, vdeg, vknots, poles, w 21 | 22 | if surf2 != nil && !surf2.null? 23 | BRepIO::save surf2, "/tmp/nurbssurf.brep" 24 | BRepIO::save box, "/tmp/box.brep" 25 | else 26 | puts "Failed to make NURBS surface." 27 | end 28 | end 29 | 30 | def test2 31 | udeg = 1 32 | uknots = [[0, 2], [1, 2]] 33 | vdeg = 1 34 | vknots = [[0, 2], [1, 2]] 35 | poles = [ 36 | [[Vec::new(0, 0, 0), 1.0], [Vec::new(10, 0, 0), 1.0]], 37 | [[Vec::new(0, 10, 0), 1.0], [Vec::new(10, 10, 0), 1.0]], 38 | [[Vec::new(0, 20, 0), 1.0], [Vec::new(10, 20, 0), 1.0]] 39 | ] 40 | 41 | w = Build.polyline [ 42 | Vec::new( 0, 0, 0), 43 | Vec::new( 0, 10, 0), 44 | Vec::new(10, 10, 0), 45 | Vec::new(10, 0, 0), 46 | Vec::new( 0, 0, 0), 47 | ] 48 | 49 | ww = w.translate(Vec::new(-5, -5, 0)) 50 | surf = Build.nurbssurf udeg, uknots, vdeg, vknots, poles, ww 51 | 52 | if surf != nil && !surf.null? 53 | BRepIO::save surf, "/tmp/nurbssurf.brep" 54 | BRepIO::save ww, "/tmp/wire.brep" 55 | puts "Done" 56 | else 57 | puts "Failed to make NURBS surface." 58 | end 59 | end 60 | 61 | test2 62 | 63 | -------------------------------------------------------------------------------- /inc/topalgo.h: -------------------------------------------------------------------------------- 1 | #ifndef _topalgo_H_ 2 | #define _topalgo_H_ 3 | 4 | #include "siren.h" 5 | #include "vec.h" 6 | #include "shape.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include // curve 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | 20 | // copy 21 | #include 22 | 23 | // NURBS curve 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | #include 30 | 31 | #include 32 | #include 33 | #include 34 | 35 | bool siren_topalgo_install(mrb_state* mrb, struct RClass* rclass); 36 | 37 | mrb_value siren_topalgo_copy (mrb_state* mrb, mrb_value self); 38 | 39 | mrb_value siren_topalgo_line (mrb_state* mrb, mrb_value self); 40 | mrb_value siren_topalgo_infline (mrb_state* mrb, mrb_value self); 41 | mrb_value siren_topalgo_polyline (mrb_state* mrb, mrb_value self); 42 | mrb_value siren_topalgo_interpolate(mrb_state* mrb, mrb_value self); 43 | mrb_value siren_topalgo_arc (mrb_state* mrb, mrb_value self); 44 | mrb_value siren_topalgo_arc3p (mrb_state* mrb, mrb_value self); 45 | mrb_value siren_topalgo_circle (mrb_state* mrb, mrb_value self); 46 | mrb_value siren_topalgo_circle3p (mrb_state* mrb, mrb_value self); 47 | 48 | mrb_value siren_topalgo_volume(mrb_state* mrb, mrb_value self); 49 | mrb_value siren_topalgo_cog(mrb_state* mrb, mrb_value self); 50 | mrb_value siren_topalgo_area(mrb_state* mrb, mrb_value self); 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /examples/view/brep2js.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/siren 2 | # coding: utf-8 3 | 4 | def brep2js(shape, path, edge_defl=0.01, face_defl=1.0, face_angle=5.0.to_rad) 5 | File.open(path, "w") do |f| 6 | f.write "var fs = [];\n" 7 | f.write "var es = [];\n" 8 | if shape.faces.size > 0 9 | i = 0 10 | f.write "{\n" 11 | f.write " var g = new THREE.Geometry();\n" 12 | shape.faces.each do |face| 13 | face.triangle(face_defl, face_angle).each do |m| 14 | f.write " g.vertices.push(new THREE.Vector3(#{m[0][0]}, #{m[0][1]}, #{m[0][2]}));\n" 15 | f.write " g.vertices.push(new THREE.Vector3(#{m[1][0]}, #{m[1][1]}, #{m[1][2]}));\n" 16 | f.write " g.vertices.push(new THREE.Vector3(#{m[2][0]}, #{m[2][1]}, #{m[2][2]}));\n" 17 | f.write " var face#{i} = new THREE.Face3(#{i}, #{i+1}, #{i+2});\n" 18 | f.write " face#{i}.normal = new THREE.Vector3(#{m[5][0]}, #{m[5][1]}, #{m[5][2]});\n" 19 | f.write " g.faces.push(face#{i});\n" 20 | i += 3 21 | end 22 | end 23 | f.write " fs.push(g);\n" 24 | f.write "}\n"; 25 | end 26 | shape.edges(Siren::Face).each do |edge| 27 | i = 0 28 | f.write "{\n" 29 | f.write " var g = new THREE.Geometry();\n" 30 | edge.to_pts(edge_defl).each do |pt| 31 | f.write " g.vertices.push(new THREE.Vector3(#{pt.x}, #{pt.y}, #{pt.z}));\n" 32 | end 33 | f.write " es.push(g);\n" 34 | f.write "}\n"; 35 | end 36 | end 37 | end 38 | 39 | model = nil 40 | if ARGV.size == 0 41 | puts "There is no specified file." 42 | else 43 | model = Siren.load_model ARGV[0] 44 | end 45 | 46 | if ARGV.size == 1 47 | brep2js model, File.expand_path(File.dirname(__FILE__)) + "/model.js" 48 | else 49 | brep2js model, File.expand_path(File.dirname(__FILE__)) + "/model.js", ARGV[1].to_f 50 | end 51 | 52 | -------------------------------------------------------------------------------- /inc/shape/edge.h: -------------------------------------------------------------------------------- 1 | #ifndef _SHAPE_EDGE_H_ 2 | #define _SHAPE_EDGE_H_ 3 | 4 | #include "siren.h" 5 | #include "curve.h" 6 | #include "shape.h" 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | // to_pts 16 | #include 17 | #include 18 | 19 | // param 20 | #include 21 | #include 22 | 23 | #include 24 | 25 | static struct mrb_data_type siren_edge_type = { "Edge", siren_shape_final }; 26 | bool siren_edge_install(mrb_state* mrb, struct RClass* mod_siren); 27 | TopoDS_Edge siren_edge_get(mrb_state* mrb, mrb_value self); 28 | mrb_value siren_edge_new(mrb_state* mrb, const TopoDS_Shape* src); 29 | mrb_value siren_edge_obj(mrb_state* mrb); 30 | struct RClass* siren_edge_rclass(mrb_state* mrb); 31 | 32 | mrb_value siren_edge_init(mrb_state* mrb, mrb_value self); 33 | mrb_value siren_edge_sp(mrb_state* mrb, mrb_value self); 34 | mrb_value siren_edge_tp(mrb_state* mrb, mrb_value self); 35 | mrb_value siren_edge_to_pts(mrb_state* mrb, mrb_value self); 36 | mrb_value siren_edge_param(mrb_state* mrb, mrb_value self); 37 | mrb_value siren_edge_to_xyz(mrb_state* mrb, mrb_value self); 38 | mrb_value siren_edge_curvature(mrb_state* mrb, mrb_value self); 39 | mrb_value siren_edge_tangent(mrb_state* mrb, mrb_value self); 40 | 41 | mrb_value siren_edge_terms(mrb_state* mrb, mrb_value self); 42 | mrb_value siren_edge_curve(mrb_state* mrb, mrb_value self); 43 | 44 | mrb_value siren_edge_split(mrb_state* mrb, mrb_value self); 45 | mrb_value siren_edge_trim(mrb_state* mrb, mrb_value self); 46 | mrb_value siren_edge_extrema(mrb_state* mrb, mrb_value self); 47 | 48 | mrb_value siren_edge_length(mrb_state* mrb, mrb_value self); 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /src/siren.cpp: -------------------------------------------------------------------------------- 1 | #include "siren.h" 2 | 3 | #include "vec.h" 4 | #include "curve.h" 5 | #include "shape.h" 6 | #include "topalgo.h" 7 | #include "brep.h" 8 | #include "trans.h" 9 | #include "bndbox.h" 10 | #include "filler.h" 11 | 12 | #ifdef SIREN_ENABLE_BO 13 | #include "bo.h" 14 | #endif 15 | 16 | #ifdef SIREN_ENABLE_SHHEALING 17 | #include "heal.h" 18 | #endif 19 | 20 | #ifdef SIREN_ENABLE_OFFSET 21 | #include "offset.h" 22 | #endif 23 | 24 | #ifdef SIREN_ENABLE_IGES 25 | #include "io/iges.h" 26 | #endif 27 | 28 | #ifdef SIREN_ENABLE_STL 29 | #include "io/stl.h" 30 | #endif 31 | 32 | #ifdef SIREN_ENABLE_STEP 33 | #include "io/step.h" 34 | #endif 35 | 36 | MRB_BEGIN_DECL 37 | 38 | struct RClass* mod_siren; 39 | 40 | // initializer 41 | void mrb_mruby_siren_gem_init(mrb_state* mrb) 42 | { 43 | // Siren module 44 | mod_siren = mrb_define_module(mrb, "Siren"); 45 | 46 | // Class 47 | siren_bndbox_install (mrb, mod_siren); 48 | siren_curve_install (mrb, mod_siren); 49 | siren_shape_install (mrb, mod_siren); 50 | siren_trans_install (mrb, mod_siren); 51 | siren_vec_install (mrb, mod_siren); 52 | 53 | // API class 54 | siren_filler_install (mrb, mod_siren); 55 | 56 | // Method 57 | siren_topalgo_install(mrb, mod_siren); 58 | siren_brep_install (mrb, mod_siren); 59 | #ifdef SIREN_ENABLE_OFFSET 60 | siren_offset_install (mrb, mod_siren); 61 | #endif 62 | #ifdef SIREN_ENABLE_BO 63 | siren_bo_install (mrb, mod_siren); 64 | #endif 65 | #ifdef SIREN_ENABLE_IGES 66 | siren_iges_install (mrb, mod_siren); 67 | #endif 68 | #ifdef SIREN_ENABLE_STL 69 | siren_stl_install (mrb, mod_siren); 70 | #endif 71 | #ifdef SIREN_ENABLE_STEP 72 | siren_step_install (mrb, mod_siren); 73 | #endif 74 | 75 | return; 76 | } 77 | 78 | // finalizer 79 | void mrb_mruby_siren_gem_final(mrb_state* mrb) 80 | { 81 | return; 82 | } 83 | 84 | MRB_END_DECL 85 | -------------------------------------------------------------------------------- /src/brep.cpp: -------------------------------------------------------------------------------- 1 | #include "brep.h" 2 | 3 | bool siren_brep_install(mrb_state* mrb, struct RClass* mod_siren) 4 | { 5 | // Class method 6 | mrb_define_class_method(mrb, mod_siren, "save_brep", siren_brep_save, MRB_ARGS_REQ(2)); 7 | mrb_define_class_method(mrb, mod_siren, "load_brep", siren_brep_load, MRB_ARGS_REQ(1)); 8 | mrb_define_class_method(mrb, mod_siren, "dump", siren_brep_dump, MRB_ARGS_REQ(1)); 9 | // For mix-in 10 | mrb_define_method (mrb, mod_siren, "save_brep", siren_brep_save, MRB_ARGS_REQ(2)); 11 | mrb_define_method (mrb, mod_siren, "load_brep", siren_brep_load, MRB_ARGS_REQ(1)); 12 | mrb_define_method (mrb, mod_siren, "dump", siren_brep_dump, MRB_ARGS_REQ(1)); 13 | return true; 14 | } 15 | 16 | mrb_value siren_brep_save(mrb_state* mrb, mrb_value self) 17 | { 18 | mrb_value target; 19 | mrb_value path; 20 | int argc = mrb_get_args(mrb, "oS", &target, &path); 21 | TopoDS_Shape* shape = siren_shape_get(mrb, target); 22 | try { 23 | std::ofstream fst(RSTRING_PTR(path), std::ios_base::out); 24 | BRepTools::Write(*shape, fst); 25 | } 26 | catch (...) { 27 | mrb_raisef(mrb, E_ARGUMENT_ERROR, "Failed to save BRep to %S.", path); 28 | } 29 | return mrb_nil_value(); 30 | } 31 | 32 | mrb_value siren_brep_load(mrb_state* mrb, mrb_value self) 33 | { 34 | mrb_value path; 35 | int argc = mrb_get_args(mrb, "S", &path); 36 | BRep_Builder B; 37 | TopoDS_Shape shape; 38 | try { 39 | std::ifstream fst(RSTRING_PTR(path), std::ios_base::in); 40 | BRepTools::Read(shape, fst, B); 41 | } 42 | catch (...) { 43 | mrb_raisef(mrb, E_ARGUMENT_ERROR, "Failed to load BRep from %S.", path); 44 | } 45 | return siren_shape_new(mrb, shape); 46 | } 47 | 48 | mrb_value siren_brep_dump(mrb_state* mrb, mrb_value self) 49 | { 50 | mrb_value target; 51 | int argc = mrb_get_args(mrb, "o", &target); 52 | TopoDS_Shape* shape = siren_shape_get(mrb, target); 53 | BRepTools::Dump(*shape, std::cout); 54 | return mrb_nil_value(); 55 | } 56 | 57 | -------------------------------------------------------------------------------- /examples/view/viewer.js: -------------------------------------------------------------------------------- 1 | // var view = document.getElementById("view"); 2 | // var w = view.clientWidth; 3 | // var h = view.clientHeight; 4 | var w = window.innerWidth; 5 | var h = window.innerHeight; 6 | var aspect = w / h; 7 | 8 | var models = []; 9 | 10 | var scene = new THREE.Scene(); 11 | 12 | // LIGHT 13 | var dlight = new THREE.DirectionalLight('white'); 14 | dlight.position.set(2, 7, 10); 15 | scene.add(dlight); 16 | 17 | var supportLight = new THREE.DirectionalLight('white'); 18 | supportLight.position.set(-0.5, -8, -1); 19 | scene.add(supportLight); 20 | 21 | // EVENT 22 | window.addEventListener('resize', function() { 23 | w = window.innerWidth; 24 | h = window.innerHeight; 25 | // w = view.clientWidth; 26 | // h = view.clientHeight; 27 | renderer.setSize(w, h); 28 | camera.aspect = aspect = w / h; 29 | camera.updateProjectionMatrix(); 30 | }, false); 31 | 32 | // CAMERA 33 | var camera = new THREE.PerspectiveCamera(65, aspect, 1, 500000); 34 | camera.position.set(-15, -25, 20); 35 | camera.lookAt(new THREE.Vector3(40, 0, 0)); 36 | camera.up.set(0, 0, 1); 37 | 38 | // RENDERER 39 | var renderer = new THREE.WebGLRenderer({alpha: false}); 40 | renderer.setSize(w, h); 41 | renderer.setClearColor(0x333333); 42 | document.body.appendChild(renderer.domElement); 43 | // view.appendChild(renderer.domElement); 44 | 45 | var fps = 30; 46 | var now; 47 | var then = Date.now(); 48 | var interval = 1000/fps; 49 | var delta; 50 | 51 | function render() { 52 | requestAnimationFrame(render); 53 | now = Date.now(); 54 | delta = now - then; 55 | if (delta > interval) { 56 | then = now - (delta % interval); 57 | control.update(); 58 | renderer.render(scene, camera); 59 | } 60 | } 61 | 62 | // OrbitControls 63 | var controls = new THREE.OrbitControls(camera, renderer.domElement); 64 | 65 | // TransformControls 66 | var control = new THREE.TransformControls( camera, renderer.domElement ); 67 | control.addEventListener( 'change', render ); 68 | scene.add(control); 69 | 70 | render(); 71 | 72 | -------------------------------------------------------------------------------- /src/curve/line.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * line.cpp 3 | * Implementation of singleton methods for LINE 4 | */ 5 | 6 | #include "curve.h" 7 | 8 | mrb_value siren_line_new(mrb_state* mrb, const handle* curve) 9 | { 10 | struct RClass* mod_siren = mrb_module_get(mrb, "Siren"); 11 | mrb_value obj; 12 | obj = mrb_instance_alloc(mrb, mrb_const_get(mrb, mrb_obj_value(mod_siren), mrb_intern_lit(mrb, "Line"))); 13 | void* p = mrb_malloc(mrb, sizeof(handle)); 14 | handle* hgcurve = new(p) handle(); 15 | *hgcurve = *curve; 16 | DATA_PTR(obj) = hgcurve; 17 | DATA_TYPE(obj) = &siren_line_type; 18 | return obj; 19 | } 20 | 21 | handle siren_line_get(mrb_state* mrb, mrb_value self) 22 | { 23 | handle hgc = *static_cast*>(mrb_get_datatype(mrb, self, &siren_line_type)); 24 | if (hgc.IsNull()) { mrb_raise(mrb, E_RUNTIME_ERROR, "The geometry type is not Curve."); } 25 | handle line = handle::DownCast(hgc); 26 | if (line.IsNull()) { mrb_raise(mrb, E_RUNTIME_ERROR, "The geometry type is not Line."); } 27 | return line; 28 | } 29 | 30 | bool siren_line_install(mrb_state* mrb, struct RClass* mod_siren) 31 | { 32 | struct RClass* cls_curve = siren_curve_rclass(mrb); 33 | struct RClass* cls_line = mrb_define_class_under(mrb, mod_siren, "Line", cls_curve); 34 | MRB_SET_INSTANCE_TT(cls_line, MRB_TT_DATA); 35 | mrb_define_method(mrb, cls_line, "initialize", siren_curve_init, MRB_ARGS_NONE()); 36 | 37 | mrb_define_method(mrb, cls_line, "dir", siren_line_dir, MRB_ARGS_NONE()); 38 | return true; 39 | } 40 | 41 | struct RClass* siren_line_rclass(mrb_state* mrb) 42 | { 43 | struct RClass* mod_siren = mrb_module_get(mrb, "Siren"); 44 | return mrb_class_ptr(mrb_const_get(mrb, mrb_obj_value(mod_siren), mrb_intern_lit(mrb, "Line"))); 45 | } 46 | 47 | mrb_value siren_line_dir(mrb_state* mrb, mrb_value self) 48 | { 49 | handle line = siren_line_get(mrb, self); 50 | return siren_dir_to_ary(mrb, line->Lin().Direction()); 51 | } 52 | 53 | -------------------------------------------------------------------------------- /examples/view/siren-viewer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | siren viewer 6 | 7 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | Primitive:
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | Edit:
28 |
29 |
30 |
31 | Property:
32 |
33 |
34 |
35 | OK. 36 |
37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /inc/shape/face.h: -------------------------------------------------------------------------------- 1 | #ifndef _SHAPE_FACE_H_ 2 | #define _SHAPE_FACE_H_ 3 | 4 | #include "siren.h" 5 | #include "shape.h" 6 | #include "vec.h" 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | #include 27 | 28 | // to_bezier 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | // split 38 | #include 39 | 40 | // triangle 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | static struct mrb_data_type siren_face_type = { "Face", siren_shape_final }; 47 | bool siren_face_install(mrb_state* mrb, struct RClass* mod_siren); 48 | TopoDS_Face siren_face_get(mrb_state* mrb, mrb_value self); 49 | mrb_value siren_face_new(mrb_state* mrb, const TopoDS_Shape* src); 50 | mrb_value siren_face_obj(mrb_state* mrb); 51 | struct RClass* siren_face_rclass(mrb_state* mrb); 52 | 53 | mrb_value siren_face_plane(mrb_state* mrb, mrb_value self); 54 | mrb_value siren_face_face(mrb_state* mrb, mrb_value self); 55 | mrb_value siren_face_infplane(mrb_state* mrb, mrb_value self); 56 | mrb_value siren_face_polygon(mrb_state* mrb, mrb_value self); 57 | mrb_value siren_face_bzsurf(mrb_state* mrb, mrb_value self); 58 | mrb_value siren_face_bssurf(mrb_state* mrb, mrb_value self); 59 | 60 | mrb_value siren_face_normal(mrb_state* mrb, mrb_value self); 61 | mrb_value siren_face_to_bezier(mrb_state* mrb, mrb_value self); 62 | mrb_value siren_face_split(mrb_state* mrb, mrb_value self); 63 | mrb_value siren_face_triangle(mrb_state* mrb, mrb_value self); 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /inc/trans.h: -------------------------------------------------------------------------------- 1 | #ifndef _TRANS_H_ 2 | #define _TRANS_H_ 3 | 4 | #include "common.h" 5 | #include "siren.h" 6 | #include "vec.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | bool siren_trans_install(mrb_state* mrb, struct RClass* rclass); 14 | void siren_trans_final(mrb_state* mrb, void* p); 15 | static struct mrb_data_type siren_trans_type = { "Trans", siren_trans_final }; 16 | gp_Trsf* siren_trans_get(mrb_state* mrb, mrb_value obj); 17 | struct RClass* siren_trans_rclass(mrb_state* mrb); 18 | mrb_value siren_trans_new(mrb_state* mrb, const gp_Trsf& src); 19 | 20 | mrb_value siren_trans_init(mrb_state* mrb, mrb_value self); 21 | mrb_value siren_trans_to_s(mrb_state* mrb, mrb_value self); 22 | mrb_value siren_trans_to_a(mrb_state* mrb, mrb_value self); 23 | mrb_value siren_trans_matrix(mrb_state* mrb, mrb_value self); 24 | mrb_value siren_trans_set_matrix(mrb_state* mrb, mrb_value self); 25 | mrb_value siren_trans_multiply(mrb_state* mrb, mrb_value self); 26 | mrb_value siren_trans_multiply_bang(mrb_state* mrb, mrb_value self); 27 | mrb_value siren_trans_power(mrb_state* mrb, mrb_value self); 28 | mrb_value siren_trans_power_bang(mrb_state* mrb, mrb_value self); 29 | mrb_value siren_trans_invert(mrb_state* mrb, mrb_value self); 30 | mrb_value siren_trans_invert_bang(mrb_state* mrb, mrb_value self); 31 | mrb_value siren_trans_is_negative(mrb_state* mrb, mrb_value self); 32 | mrb_value siren_trans_translate_bang(mrb_state* mrb, mrb_value self); 33 | mrb_value siren_trans_translatef(mrb_state* mrb, mrb_value self); 34 | mrb_value siren_trans_set_translatef(mrb_state* mrb, mrb_value self); 35 | mrb_value siren_trans_mirror_bang(mrb_state* mrb, mrb_value self); 36 | mrb_value siren_trans_rotate_bang(mrb_state* mrb, mrb_value self); 37 | //mrb_value siren_trans_rotatef(mrb_state* mrb, mrb_value self); 38 | //mrb_value siren_trans_set_rotatef(mrb_state* mrb, mrb_value self); 39 | mrb_value siren_trans_scale_bang(mrb_state* mrb, mrb_value self); 40 | mrb_value siren_trans_scalef(mrb_state* mrb, mrb_value self); 41 | mrb_value siren_trans_set_scalef(mrb_state* mrb, mrb_value self); 42 | mrb_value siren_trans_transform_bang(mrb_state* mrb, mrb_value self); 43 | mrb_value siren_trans_move_point(mrb_state* mrb, mrb_value self); 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /examples/view/axis.js: -------------------------------------------------------------------------------- 1 | 2 | function make_line(src, dst, colorHex, dashed) { 3 | var geom = new THREE.Geometry(), mat; 4 | if(dashed) { 5 | mat = new THREE.LineDashedMaterial({linewidth: 1, color: colorHex, dashSize: 1, gapSize: 1}); 6 | } 7 | else { 8 | mat = new THREE.LineBasicMaterial({linewidth: 1, color: colorHex}); 9 | } 10 | geom.vertices.push(src.clone()); 11 | geom.vertices.push(dst.clone()); 12 | geom.computeLineDistances(); 13 | return new THREE.Line(geom, mat, THREE.LineSegments); 14 | } 15 | 16 | // Axis 17 | (function () { 18 | var length = 10; 19 | var axes = new THREE.Object3D(); 20 | axes.add(make_line(new THREE.Vector3(0, 0, 0), new THREE.Vector3(length, 0, 0), 0xFF0000, false)); // +X 21 | axes.add(make_line(new THREE.Vector3(0, 0, 0), new THREE.Vector3(-length, 0, 0), 0xFF0000, true)); // -X 22 | axes.add(make_line(new THREE.Vector3(0, 0, 0), new THREE.Vector3(0, length, 0), 0x00FF00, false)); // +Y 23 | axes.add(make_line(new THREE.Vector3(0, 0, 0), new THREE.Vector3(0, -length, 0), 0x00FF00, true)); // -Y 24 | axes.add(make_line(new THREE.Vector3(0, 0, 0), new THREE.Vector3(0, 0, length), 0x0000FF, false)); // +Z 25 | axes.add(make_line(new THREE.Vector3(0, 0, 0), new THREE.Vector3(0, 0, -length), 0x0000FF, true)); // -Z 26 | scene.add(axes); 27 | })(); 28 | 29 | // Grid 30 | (function () { 31 | var grid = new THREE.Object3D(); 32 | var size_h = 10; 33 | var size_w = 10; 34 | var span = 10; 35 | 36 | var hlf_w = size_w / 2; 37 | var max_w = hlf_w * span; 38 | var min_w = hlf_w *-span; 39 | var hlf_h = size_h / 2; 40 | var max_h = hlf_h / 2 * span; 41 | var min_h = hlf_h / 2 *-span; 42 | 43 | var color = 0x5F5F5F; 44 | var color_strong = 0xA0A0A0; 45 | 46 | for (var i = 0; i <= size_w; i++) { 47 | grid.add(make_line( 48 | new THREE.Vector3(min_w, span * (i - hlf_w), 0), 49 | new THREE.Vector3(max_w, span * (i - hlf_w), 0), 50 | hlf_w == i ? color_strong : color, false)); 51 | } 52 | 53 | for (var i = 0; i <= size_h; i++) { 54 | grid.add(make_line( 55 | new THREE.Vector3(span * (i - hlf_h), min_w, 0), 56 | new THREE.Vector3(span * (i - hlf_h), max_w, 0), 57 | hlf_h == i ? color_strong : color, false)); 58 | } 59 | 60 | scene.add(grid); 61 | })(); 62 | -------------------------------------------------------------------------------- /src/bo.cpp: -------------------------------------------------------------------------------- 1 | #include "bo.h" 2 | 3 | bool siren_bo_install(mrb_state* mrb, struct RClass* mod_siren) 4 | { 5 | struct RClass* cls_shape = siren_shape_rclass(mrb); 6 | mrb_define_method(mrb, cls_shape, "common", siren_bo_common, MRB_ARGS_REQ(1)); 7 | mrb_define_method(mrb, cls_shape, "fuse", siren_bo_fuse, MRB_ARGS_REQ(1)); 8 | mrb_define_method(mrb, cls_shape, "cut", siren_bo_cut, MRB_ARGS_REQ(1)); 9 | mrb_define_method(mrb, cls_shape, "projwire", siren_bo_projwire, MRB_ARGS_REQ(2)); 10 | return true; 11 | } 12 | 13 | mrb_value siren_bo_common(mrb_state* mrb, mrb_value self) 14 | { 15 | mrb_value target; 16 | int argc = mrb_get_args(mrb, "o", &target); 17 | TopoDS_Shape* S1 = siren_shape_get(mrb, self); 18 | TopoDS_Shape* S2 = siren_shape_get(mrb, target); 19 | BRepAlgoAPI_Common api(*S1, *S2); 20 | api.Build(); 21 | if (api.ErrorStatus()) { 22 | return mrb_nil_value(); 23 | } 24 | return siren_shape_new(mrb, api.Shape()); 25 | } 26 | 27 | mrb_value siren_bo_fuse(mrb_state* mrb, mrb_value self) 28 | { 29 | mrb_value target; 30 | int argc = mrb_get_args(mrb, "o", &target); 31 | TopoDS_Shape* S1 = siren_shape_get(mrb, self); 32 | TopoDS_Shape* S2 = siren_shape_get(mrb, target); 33 | BRepAlgoAPI_Fuse api(*S1, *S2); 34 | api.Build(); 35 | if (api.ErrorStatus()) { 36 | return mrb_nil_value(); 37 | } 38 | return siren_shape_new(mrb, api.Shape()); 39 | } 40 | 41 | mrb_value siren_bo_cut(mrb_state* mrb, mrb_value self) 42 | { 43 | mrb_value target; 44 | int argc = mrb_get_args(mrb, "o", &target); 45 | TopoDS_Shape* S1 = siren_shape_get(mrb, self); 46 | TopoDS_Shape* S2 = siren_shape_get(mrb, target); 47 | BRepAlgoAPI_Cut api(*S1, *S2); 48 | api.Build(); 49 | if (api.ErrorStatus()) { 50 | return mrb_nil_value(); 51 | } 52 | return siren_shape_new(mrb, api.Shape()); 53 | } 54 | 55 | mrb_value siren_bo_projwire(mrb_state* mrb, mrb_value self) 56 | { 57 | mrb_value w, v; 58 | int argc = mrb_get_args(mrb, "oo", &w, &v); 59 | TopoDS_Shape* wire = siren_shape_get(mrb, w); 60 | TopoDS_Shape* shape = siren_shape_get(mrb, self); 61 | gp_Vec* vec = siren_vec_get(mrb, v); 62 | BRepProj_Projection api(*wire, *shape, *vec); 63 | if (!api.IsDone()) { 64 | return mrb_nil_value(); 65 | } 66 | return siren_shape_new(mrb, api.Shape()); 67 | } 68 | 69 | -------------------------------------------------------------------------------- /test/hull.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env siren 2 | # coding: utf-8 3 | 4 | # CSV offset table parser 5 | def get_table(ofsfile) 6 | t = {} 7 | ci = [] 8 | File::open(ofsfile, "r") do |f| 9 | f.each do |ln| 10 | ar = ln.chomp.split(",") 11 | if ar.first == "" # Colum header 12 | ar.slice(1..-1).each do |ord| 13 | t[ord.to_f] = {} 14 | ci.push ord.to_f 15 | end 16 | else 17 | ar.slice(1..-1).each_with_index do |val, i| 18 | t[ci[i]][ar.first.to_f] = val.to_f 19 | end 20 | end 21 | end 22 | end 23 | return t 24 | end 25 | 26 | def make_shell(tbl, lpp) 27 | cvs = [] 28 | tbl.each_pair do |k, v| 29 | pts = [] 30 | x = k * lpp * 0.1 31 | v.each_pair do |z, y| 32 | pts.push Vec::new(x, y, z) 33 | end 34 | #cvs.push Build::curve(pts) 35 | cvs.push Build::polyline(pts) 36 | end 37 | cvs.map!{|e| Build::wire [e] } 38 | Offset::loft(cvs, false, false, true) 39 | end 40 | 41 | def get_area(tbl, lpp) 42 | ar = tbl.to_a 43 | aex = ar.first.first * lpp * 0.1 44 | fex = ar.last.first * lpp * 0.1 45 | dmin = ar.first.last.to_a.first.first 46 | dmax = ar.first.last.to_a.last.first 47 | [aex, fex, dmin, dmax] 48 | end 49 | 50 | def make_top(tbl, lpp) 51 | pts = [] 52 | aex, fex, dmin, dmax = get_area(tbl, lpp) 53 | pts.push Vec::new(aex, 0, dmax) 54 | tbl.each_pair do |k, v| 55 | gnl = v.to_a.last 56 | pts.push Vec::new(k * lpp * 0.1, gnl.last, gnl.first) 57 | end 58 | pts.push Vec::new(fex, 0, dmax) 59 | Build::polygon pts 60 | end 61 | 62 | def make_center(tbl, lpp) 63 | aex, fex, dmin, dmax = get_area(tbl, lpp) 64 | Build::polygon [ 65 | Vec::new(aex, 0, dmin), 66 | Vec::new(aex, 0, dmax), 67 | Vec::new(fex, 0, dmax), 68 | Vec::new(fex, 0, dmin), 69 | ] 70 | end 71 | 72 | def make_section(xpos, curve) 73 | 74 | 75 | end 76 | 77 | lpp = 217.0 78 | table = get_table(ARGV[0]) 79 | top = make_top(table, lpp) 80 | center = make_center(table, lpp) 81 | shell = make_shell(table, lpp) 82 | 83 | # 以下、表示 84 | world = World.new `echo $DISPLAY`.chomp 85 | cam = Camera.new world, X11.test 86 | ss = Skin.new shell 87 | ss.color = ColorName::RED 88 | world.add ss 89 | st = Skin.new top 90 | st.color = ColorName::BLUE1 91 | world.add st 92 | sc = Skin.new center 93 | sc.color = ColorName::GREEN 94 | world.add sc 95 | # 視点・視野設定 96 | cam.proj = OrientType::XnegYnegZpos 97 | cam.fitz 98 | cam.fit 99 | # Enter が押されたら終了 100 | STDIN.gets 101 | 102 | -------------------------------------------------------------------------------- /mrbgem.rake: -------------------------------------------------------------------------------- 1 | ## 2 | # mruby-siren rake file 3 | # 4 | 5 | MRuby::Gem::Specification.new('mruby-siren') do |spec| 6 | 7 | # General spec 8 | spec.author = 'dyama' 9 | spec.summary = 'Lightweight 3D operation environment. See http://siren.xyz/' 10 | spec.license = 'MIT license' 11 | 12 | # siren configuration 13 | spec.add_dependency 'mruby-io' 14 | siren_incdir = "#{dir}/inc" 15 | siren_incpaths = [] 16 | siren_incpaths << siren_incdir 17 | siren_incpaths << Dir.glob("#{siren_incdir}/*/").map{|f| f.relative_path_from(dir)} 18 | 19 | # Open CASCADE Technology configuration 20 | # Check http://dev.opencascade.org/doc/refman/html/index.html 21 | thirdparty_libs = [] 22 | occt_libpaths = [] 23 | occt_incpaths = [] 24 | 25 | if occt_libpaths.size == 0 and occt_incpaths.size == 0 26 | os = RbConfig::CONFIG['host_os'].downcase 27 | case os 28 | when /linux|solaris|bsd/ 29 | occt_libpaths = [ '/opt/occ/710/lin64/gcc/lib' ] 30 | occt_incpaths = [ '/opt/occ/710/inc' ] 31 | when /darwin|mac os/ 32 | occt_libpaths = [ '/usr/local/opt/opencascade/lib' ] 33 | occt_incpaths = [ '/usr/local/opt/opencascade/include/opencascade' ] 34 | when /mswin|mingw/ 35 | occt_libpaths = [ '\occ\710\win64\gcc\lib' ] 36 | occt_incpaths = [ '\occ\710\inc' ] 37 | spec.cxx.flags << '-D_USE_MATH_DEFINES' 38 | spec.cxx.flags << '-D__NO_INLINE__' 39 | end 40 | end 41 | 42 | occt_libs = [ 43 | # Foundation classes 44 | 'TKernel', 'TKMath', 45 | # Modeling data 46 | 'TKG2d', 'TKG3d', 'TKGeomBase', 'TKBRep', 47 | # Modeling algorithms 48 | 'TKGeomAlgo', 'TKTopAlgo', 'TKBO', 'TKPrim', 49 | 'TKShHealing', 'TKHLR', 'TKMesh', 'TKBool', 50 | 'TKXMesh', 'TKFeat', 'TKFillet', 'TKOffset', 51 | # Data excange 52 | 'TKXSBase', 'TKSTL', 'TKIGES', 'TKSTEP', 53 | 'TKSTEP209', 'TKSTEPAttr', 'TKSTEPBase', 54 | ] 55 | 56 | # Linker option 57 | spec.linker.library_paths << occt_libpaths 58 | spec.linker.libraries << occt_libs << thirdparty_libs 59 | 60 | # Compiler option 61 | spec.cxx.flags << "-Wno-unused-function" 62 | spec.cxx.flags << "-Wno-unused-variable" 63 | spec.cxx.flags << "-Wno-unknown-pragmas" 64 | spec.cxx.flags << "-std=c++11" 65 | spec.cxx.include_paths << occt_incpaths 66 | spec.cxx.include_paths << siren_incpaths 67 | spec.objs << Dir.glob("#{dir}/src/*.{c,cpp}").map { |f| objfile(f.relative_path_from(dir).pathmap("#{build_dir}/%X")) } 68 | spec.objs << Dir.glob("#{dir}/src/*/*.{c,cpp}").map { |f| objfile(f.relative_path_from(dir).pathmap("#{build_dir}/%X")) } 69 | 70 | end 71 | 72 | -------------------------------------------------------------------------------- /mrblib/kernel/Array.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Array クラス拡張メソッド 3 | # 4 | class Array 5 | 6 | def to_v 7 | Siren::Vec.new self 8 | end 9 | 10 | def to(other) 11 | other.to_v - self.to_v 12 | end 13 | 14 | def from(other) 15 | self.to_v - other.to_v 16 | end 17 | 18 | def xyz 19 | self[0,3] 20 | end 21 | 22 | def xyz=(val) 23 | self[0,3] = val 24 | end 25 | 26 | def dist(other) 27 | (self.to_v - other.to_v).magnitude 28 | end 29 | 30 | def center(other) 31 | ((self.to_v + other.to_v) / 2.0).xyz 32 | end 33 | 34 | def equal?(other, lintol) 35 | dist(other) < lintol 36 | end 37 | 38 | def translate(t) 39 | if t.is_a? Siren::Vec 40 | v = t 41 | else 42 | v = t.to_v 43 | end 44 | (self.to_v + v).xyz 45 | end 46 | 47 | def translate!(t) 48 | self.xyz = translate(t) 49 | end 50 | 51 | def rotate(op, dir, angle) 52 | self.from(op).rotate(dir, angle).xyz.translate(op).xyz 53 | end 54 | 55 | def rotate!(op, dir, angle) 56 | self.xyz = rotate(op, dir, angle) 57 | end 58 | 59 | def scale(op, f) 60 | if (op.equal?(self, 1.0e-7)) 61 | self.xyz 62 | else 63 | (self.from(op).normal * f).xyz.translate(op).xyz 64 | end 65 | end 66 | 67 | def scale!(op, f) 68 | self.xyz = scale(op, f) 69 | end 70 | 71 | def mirror(op, dir = Siren::Vec.zero) 72 | if dir == Siren::Vec.zero 73 | op.translate(self.to(op)).xyz 74 | else 75 | self.from(op).mirror(dir).xyz.translate(op).xyz 76 | end 77 | end 78 | 79 | def mirror!(op, dir = Siren::Vec.zero) 80 | self.xyz = mirror(op, dir) 81 | end 82 | 83 | def trans(t) 84 | t.move_point self 85 | end 86 | 87 | def trans!(t) 88 | r = t.move_point self 89 | xyz = r.xyz 90 | end 91 | 92 | def x 93 | val = (self[0] ||= 0.0) 94 | if val.is_a?(Float) 95 | val 96 | elsif val.is_a?(Numeric) 97 | val.to_f 98 | else 99 | 0.0 100 | end 101 | end 102 | 103 | def y 104 | val = (self[1] ||= 0.0) 105 | if val.is_a?(Float) 106 | val 107 | elsif val.is_a?(Numeric) 108 | val.to_f 109 | else 110 | 0.0 111 | end 112 | end 113 | 114 | def z 115 | val = (self[2] ||= 0.0) 116 | if val.is_a?(Float) 117 | val 118 | elsif val.is_a?(Numeric) 119 | val.to_f 120 | else 121 | 0.0 122 | end 123 | end 124 | 125 | def x=(val); self[0] = val end 126 | def y=(val); self[1] = val end 127 | def z=(val); self[2] = val end 128 | 129 | def self.origin 130 | [0, 0, 0] 131 | end 132 | end 133 | 134 | -------------------------------------------------------------------------------- /src/io/iges.cpp: -------------------------------------------------------------------------------- 1 | #include "io/iges.h" 2 | 3 | #ifdef SIREN_ENABLE_IGES 4 | 5 | bool siren_iges_install(mrb_state* mrb, struct RClass* mod_siren) 6 | { 7 | // Class method 8 | mrb_define_class_method(mrb, mod_siren, "save_iges", siren_iges_save, MRB_ARGS_REQ(2)); 9 | mrb_define_class_method(mrb, mod_siren, "load_iges", siren_iges_load, MRB_ARGS_REQ(1)); 10 | // For mix-in 11 | mrb_define_method (mrb, mod_siren, "save_iges", siren_iges_save, MRB_ARGS_REQ(2)); 12 | mrb_define_method (mrb, mod_siren, "load_iges", siren_iges_load, MRB_ARGS_REQ(1)); 13 | return true; 14 | } 15 | 16 | mrb_value siren_iges_save(mrb_state* mrb, mrb_value self) 17 | { 18 | mrb_value target; 19 | mrb_value path; 20 | int argc = mrb_get_args(mrb, "oS", &target, &path); 21 | 22 | IGESControl_Controller::Init(); 23 | // IGESControl_Writer writer(Interface_Static::CVal("XSTEP.iges.unit"), 24 | // Interface_Static::IVal("XSTEP.iges.writebrep.mode")); 25 | IGESControl_Writer writer(Interface_Static::CVal("XSTEP.iges.unit"), 1); // the second argument "1" sets the OCCT => IGES conversion method to "BRep" 26 | 27 | writer.AddShape(*siren_shape_get(mrb, target)); 28 | writer.ComputeModel(); 29 | 30 | std::ofstream fst(RSTRING_PTR(path), std::ios_base::out); 31 | if (writer.Write(fst) == Standard_False) { 32 | mrb_raisef(mrb, E_ARGUMENT_ERROR, "Failed to save IGES to %S.", path); 33 | } 34 | 35 | return mrb_nil_value(); 36 | } 37 | 38 | mrb_value siren_iges_load(mrb_state* mrb, mrb_value self) 39 | { 40 | mrb_value path; 41 | mrb_bool as_ary = FALSE; 42 | int argc = mrb_get_args(mrb, "S|b", &path, &as_ary); 43 | 44 | IGESControl_Reader iges_reader; 45 | int stat = iges_reader.ReadFile((Standard_CString)RSTRING_PTR(path)); 46 | mrb_value result; 47 | 48 | if (stat == IFSelect_RetDone) { 49 | try { 50 | iges_reader.TransferRoots(); 51 | } 52 | catch (...) { 53 | mrb_raise(mrb, E_RUNTIME_ERROR, "Failed to TransferRoots() with an IGES."); 54 | } 55 | 56 | if (as_ary) { 57 | // Return array 58 | result = mrb_ary_new(mrb); 59 | for (int i=1; i <= iges_reader.NbShapes(); i++) { 60 | try { 61 | TopoDS_Shape shape = iges_reader.Shape(i); 62 | mrb_value mrshape = siren_shape_new(mrb, shape); 63 | mrb_ary_push(mrb, result, mrshape); 64 | } 65 | catch(...) { 66 | mrb_warn(mrb, "Failed to get entitiy at %d.", i); 67 | } 68 | } 69 | if (mrb_ary_len(mrb, result) < 1) { 70 | result = mrb_nil_value(); 71 | } 72 | } 73 | else { 74 | // As one shape 75 | result = siren_shape_new(mrb, iges_reader.OneShape()); 76 | } 77 | } 78 | else { 79 | mrb_raisef(mrb, E_ARGUMENT_ERROR, "Failed to load IGES from %S.", path); 80 | } 81 | return result; 82 | } 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /inc/bndbox.h: -------------------------------------------------------------------------------- 1 | #ifndef _BNDBOX_H_ 2 | #define _BNDBOX_H_ 3 | 4 | #include "siren.h" 5 | #include 6 | #include 7 | 8 | bool siren_bndbox_install(mrb_state* mrb, struct RClass* rclass); 9 | void siren_bndbox_final(mrb_state* mrb, void* p); 10 | static struct mrb_data_type siren_bndbox_type = { "BndBox", siren_bndbox_final }; 11 | mrb_value siren_bndbox_new(mrb_state* mrb, const TopoDS_Shape& shape); 12 | Bnd_Box* siren_bndbox_get(mrb_state* mrb, mrb_value obj); 13 | struct RClass* siren_bndbox_rclass(mrb_state* mrb); 14 | #define siren_is_bndbox(obj) (DATA_TYPE(obj) == &siren_bndbox_type) 15 | 16 | mrb_value siren_bndbox_init(mrb_state* mrb, mrb_value self); 17 | mrb_value siren_bndbox_to_s(mrb_state* mrb, mrb_value self); 18 | mrb_value siren_bndbox_min(mrb_state* mrb, mrb_value self); 19 | mrb_value siren_bndbox_max(mrb_state* mrb, mrb_value self); 20 | mrb_value siren_bndbox_add(mrb_state* mrb, mrb_value self); 21 | mrb_value siren_bndbox_is_out(mrb_state* mrb, mrb_value self); 22 | mrb_value siren_bndbox_center(mrb_state* mrb, mrb_value self); 23 | mrb_value siren_bndbox_xsize(mrb_state* mrb, mrb_value self); 24 | mrb_value siren_bndbox_ysize(mrb_state* mrb, mrb_value self); 25 | mrb_value siren_bndbox_zsize(mrb_state* mrb, mrb_value self); 26 | mrb_value siren_bndbox_is_void(mrb_state* mrb, mrb_value self); 27 | mrb_value siren_bndbox_is_whole(mrb_state* mrb, mrb_value self); 28 | mrb_value siren_bndbox_void_bang(mrb_state* mrb, mrb_value self); 29 | mrb_value siren_bndbox_whole_bang(mrb_state* mrb, mrb_value self); 30 | mrb_value siren_bndbox_is_xthin(mrb_state* mrb, mrb_value self); 31 | mrb_value siren_bndbox_is_ythin(mrb_state* mrb, mrb_value self); 32 | mrb_value siren_bndbox_is_zthin(mrb_state* mrb, mrb_value self); 33 | mrb_value siren_bndbox_is_openxmin(mrb_state* mrb, mrb_value self); 34 | mrb_value siren_bndbox_is_openxmax(mrb_state* mrb, mrb_value self); 35 | mrb_value siren_bndbox_is_openymin(mrb_state* mrb, mrb_value self); 36 | mrb_value siren_bndbox_is_openymax(mrb_state* mrb, mrb_value self); 37 | mrb_value siren_bndbox_is_openzmin(mrb_state* mrb, mrb_value self); 38 | mrb_value siren_bndbox_is_openzmax(mrb_state* mrb, mrb_value self); 39 | mrb_value siren_bndbox_openxmin_bang(mrb_state* mrb, mrb_value self); 40 | mrb_value siren_bndbox_openxmax_bang(mrb_state* mrb, mrb_value self); 41 | mrb_value siren_bndbox_openymin_bang(mrb_state* mrb, mrb_value self); 42 | mrb_value siren_bndbox_openymax_bang(mrb_state* mrb, mrb_value self); 43 | mrb_value siren_bndbox_openzmin_bang(mrb_state* mrb, mrb_value self); 44 | mrb_value siren_bndbox_openzmax_bang(mrb_state* mrb, mrb_value self); 45 | mrb_value siren_bndbox_set_gap(mrb_state* mrb, mrb_value self); 46 | mrb_value siren_bndbox_get_gap(mrb_state* mrb, mrb_value self); 47 | mrb_value siren_bndbox_dist(mrb_state* mrb, mrb_value self); 48 | mrb_value siren_bndbox_square(mrb_state* mrb, mrb_value self); 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /src/curve/bzcurve.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * bzcurve.cpp 3 | */ 4 | 5 | #include "curve.h" 6 | 7 | mrb_value siren_bzcurve_new(mrb_state* mrb, const handle* curve) 8 | { 9 | struct RClass* mod_siren = mrb_module_get(mrb, "Siren"); 10 | mrb_value obj; 11 | obj = mrb_instance_alloc(mrb, mrb_const_get(mrb, mrb_obj_value(mod_siren), mrb_intern_lit(mrb, "BzCurve"))); 12 | void* p = mrb_malloc(mrb, sizeof(handle)); 13 | handle* hgcurve = new(p) handle(); 14 | *hgcurve = *curve; 15 | DATA_PTR(obj) = hgcurve; 16 | DATA_TYPE(obj) = &siren_bzcurve_type; 17 | return obj; 18 | } 19 | 20 | handle siren_bzcurve_get(mrb_state* mrb, mrb_value self) 21 | { 22 | handle hgc = *static_cast*>(mrb_get_datatype(mrb, self, &siren_bzcurve_type)); 23 | if (hgc.IsNull()) { mrb_raise(mrb, E_RUNTIME_ERROR, "The geometry type is not Curve."); } 24 | handle bzcurve = handle::DownCast(hgc); 25 | if (bzcurve.IsNull()) { mrb_raise(mrb, E_RUNTIME_ERROR, "The geometry type is not BzCurve."); } 26 | return bzcurve; 27 | } 28 | 29 | bool siren_bzcurve_install(mrb_state* mrb, struct RClass* mod_siren) 30 | { 31 | struct RClass* cls_curve = siren_curve_rclass(mrb); 32 | struct RClass* cls_bzcurve = mrb_define_class_under(mrb, mod_siren, "BzCurve", cls_curve); 33 | MRB_SET_INSTANCE_TT(cls_bzcurve, MRB_TT_DATA); 34 | mrb_define_method(mrb, cls_bzcurve, "initialize", siren_bzcurve_init, MRB_ARGS_NONE()); 35 | // mrb_define_method(mrb, cls_bzcurve, "degree", siren_bzcurve_degree, MRB_ARGS_NONE()); 36 | return true; 37 | } 38 | 39 | mrb_value siren_bzcurve_init(mrb_state* mrb, mrb_value self) 40 | { 41 | mrb_value ps, ws; 42 | int argc = mrb_get_args(mrb, "A|A", &ps, &ws); 43 | bool has_weight = argc == 2; 44 | int plen = mrb_ary_len(mrb, ps); 45 | TColgp_Array1OfPnt poles(1, plen); 46 | TColStd_Array1OfReal weights(1, plen); 47 | // Start index of weights must be 1. Crash construction of Geom_BezierCurve 48 | // if another index specified. 49 | for (int i = 0; i < plen; i++) { 50 | poles.SetValue(i + 1, siren_ary_to_pnt(mrb, mrb_ary_ref(mrb, ps, i))); 51 | if (has_weight) { 52 | mrb_value w = mrb_ary_ref(mrb, ws, i); 53 | weights.SetValue(i + 1, mrb_float(w)); 54 | } 55 | } 56 | handle curve = nullptr; 57 | try { 58 | if (has_weight) { 59 | curve = new Geom_BezierCurve(poles, weights); 60 | } 61 | else { 62 | curve = new Geom_BezierCurve(poles); 63 | } 64 | } 65 | catch (...) { 66 | mrb_raise(mrb, E_ARGUMENT_ERROR, "Failed to make a BzCurve."); 67 | } 68 | void* p = mrb_malloc(mrb, sizeof(handle)); 69 | handle* hgcurve = new(p) handle(); 70 | *hgcurve = curve; 71 | DATA_PTR(self) = hgcurve; 72 | DATA_TYPE(self) = &siren_bzcurve_type; 73 | return self; 74 | } 75 | 76 | -------------------------------------------------------------------------------- /src/shape/shell.cpp: -------------------------------------------------------------------------------- 1 | #include "shape/shell.h" 2 | 3 | mrb_value siren_shell_new(mrb_state* mrb, const TopoDS_Shape* src) 4 | { 5 | mrb_value obj; 6 | struct RClass* cls_shape = siren_shape_rclass(mrb); 7 | struct RClass* mod_siren = mrb_module_get(mrb, "Siren"); 8 | obj = mrb_instance_alloc(mrb, mrb_const_get(mrb, mrb_obj_value(mod_siren), mrb_intern_lit(mrb, "Shell"))); 9 | void* p = mrb_malloc(mrb, sizeof(TopoDS_Shape)); 10 | TopoDS_Shape* inner = new(p) TopoDS_Shape(); 11 | *inner = *src; // Copy to inner native member 12 | DATA_PTR(obj) = const_cast(inner); 13 | DATA_TYPE(obj) = &siren_shell_type; 14 | return obj; 15 | } 16 | 17 | TopoDS_Shell siren_shell_get(mrb_state* mrb, mrb_value self) 18 | { 19 | TopoDS_Shape* shape = static_cast(mrb_get_datatype(mrb, self, &siren_shell_type)); 20 | TopoDS_Shell shell = TopoDS::Shell(*shape); 21 | if (shell.IsNull()) { mrb_raise(mrb, E_RUNTIME_ERROR, "The geometry type is not Shell."); } 22 | return shell; 23 | } 24 | 25 | bool siren_shell_install(mrb_state* mrb, struct RClass* mod_siren) 26 | { 27 | struct RClass* cls_shape = siren_shape_rclass(mrb); 28 | struct RClass* cls_shell = mrb_define_class_under(mrb, mod_siren, "Shell", cls_shape); 29 | MRB_SET_INSTANCE_TT(cls_shell, MRB_TT_DATA); 30 | mrb_define_method(mrb, cls_shell, "initialize", siren_shape_init, MRB_ARGS_NONE()); 31 | 32 | auto obj_shell = mrb_obj_ptr(siren_shell_obj(mrb)); 33 | mrb_define_singleton_method(mrb, obj_shell, "make", siren_shell_make, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(1)); 34 | mrb_define_singleton_method(mrb, obj_shell, "sew", siren_shell_make, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(1)); 35 | return true; 36 | } 37 | 38 | struct RClass* siren_shell_rclass(mrb_state* mrb) 39 | { 40 | struct RClass* mod_siren = mrb_module_get(mrb, "Siren"); 41 | return mrb_class_ptr(mrb_const_get(mrb, mrb_obj_value(mod_siren), mrb_intern_lit(mrb, "Shell"))); 42 | } 43 | 44 | mrb_value siren_shell_obj(mrb_state* mrb) 45 | { 46 | struct RClass* mod_siren = mrb_module_get(mrb, "Siren"); 47 | return mrb_const_get(mrb, mrb_obj_value(mod_siren), mrb_intern_lit(mrb, "Shell")); 48 | } 49 | 50 | mrb_value siren_shell_make(mrb_state* mrb, mrb_value self) 51 | { 52 | mrb_value ary; 53 | mrb_float tol; 54 | int argc = mrb_get_args(mrb, "A|f", &ary, &tol); 55 | BRepBuilderAPI_Sewing sewer; 56 | sewer.Init(); 57 | if (argc == 2 && tol >= 0) { 58 | sewer.SetTolerance(tol); 59 | } 60 | int len = mrb_ary_len(mrb, ary); 61 | for (int i=0; i < len; i++) { 62 | mrb_value item = mrb_ary_ref(mrb, ary, i); 63 | TopoDS_Shape* shape = siren_shape_get(mrb, item); 64 | if (shape->IsNull()) { 65 | continue; 66 | } 67 | TopExp_Explorer ex(*shape, TopAbs_FACE); 68 | for (; ex.More(); ex.Next()) { 69 | sewer.Add(ex.Current()); 70 | } 71 | } 72 | sewer.Perform(); 73 | return siren_shape_new(mrb, sewer.SewedShape()); 74 | } 75 | 76 | -------------------------------------------------------------------------------- /src/curve.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Document-class: Curve 3 | * 4 | */ 5 | 6 | #include "curve.h" 7 | 8 | mrb_value siren_curve_new(mrb_state* mrb, const opencascade::handle* curve) 9 | { 10 | GeomAbs_CurveType type = siren_curve_geomtype_native(*curve); 11 | struct RClass* mod_siren = mrb_module_get(mrb, "Siren"); 12 | switch (type) { 13 | case GeomAbs_Line: return siren_line_new(mrb, curve); break; 14 | case GeomAbs_Circle: return siren_circle_new(mrb, curve); break; 15 | case GeomAbs_Ellipse: return siren_ellipse_new(mrb, curve); break; 16 | case GeomAbs_Hyperbola: return siren_hyperbola_new(mrb, curve); break; 17 | case GeomAbs_Parabola: return siren_parabola_new(mrb, curve); break; 18 | case GeomAbs_BezierCurve: return siren_bzcurve_new(mrb, curve); break; 19 | case GeomAbs_BSplineCurve: return siren_bscurve_new(mrb, curve); break; 20 | case GeomAbs_OffsetCurve: return siren_offsetcurve_new(mrb, curve); break; 21 | default: break; 22 | } 23 | // rIght? 24 | mrb_value obj = mrb_instance_alloc(mrb, mrb_obj_value(siren_curve_rclass(mrb))); 25 | void* p = mrb_malloc(mrb, sizeof(opencascade::handle)); 26 | opencascade::handle* hgcurve = new(p) opencascade::handle(); 27 | *hgcurve = *curve; 28 | DATA_PTR(obj) = hgcurve; 29 | DATA_TYPE(obj) = &siren_curve_type; 30 | return obj; 31 | } 32 | 33 | bool siren_curve_install(mrb_state* mrb, struct RClass* mod_siren) 34 | { 35 | struct RClass* cls_curve = mrb_define_class_under(mrb, mod_siren, "Curve", mrb->object_class); 36 | MRB_SET_INSTANCE_TT(cls_curve, MRB_TT_DATA); 37 | mrb_define_method(mrb, cls_curve, "initialize", siren_curve_init, MRB_ARGS_NONE()); 38 | 39 | // Define derived classes for Siren::Curve 40 | siren_line_install(mrb, mod_siren); 41 | siren_circle_install(mrb, mod_siren); 42 | siren_ellipse_install(mrb, mod_siren); 43 | siren_hyperbola_install(mrb, mod_siren); 44 | siren_parabola_install(mrb, mod_siren); 45 | siren_bzcurve_install(mrb, mod_siren); 46 | siren_bscurve_install(mrb, mod_siren); 47 | siren_offsetcurve_install(mrb, mod_siren); 48 | 49 | return true; 50 | } 51 | 52 | mrb_value siren_curve_init(mrb_state* mrb, mrb_value self) 53 | { 54 | mrb_raise(mrb, E_NOMETHOD_ERROR, "private method `new' called for Curve:Class"); 55 | return mrb_nil_value(); 56 | } 57 | 58 | void siren_curve_final(mrb_state* mrb, void* p) 59 | { 60 | opencascade::handle* hgcurve = static_cast*>(p); 61 | if (!(*hgcurve).IsNull()) { 62 | (*hgcurve).Nullify(); 63 | } 64 | mrb_free(mrb, p); 65 | } 66 | 67 | opencascade::handle* siren_curve_get(mrb_state* mrb, mrb_value obj) 68 | { 69 | return static_cast*>(mrb_get_datatype(mrb, obj, &siren_curve_type)); 70 | } 71 | 72 | struct RClass* siren_curve_rclass(mrb_state* mrb) 73 | { 74 | struct RClass* mod_siren = mrb_module_get(mrb, "Siren"); 75 | return mrb_class_ptr(mrb_const_get(mrb, mrb_obj_value(mod_siren), mrb_intern_lit(mrb, "Curve"))); 76 | } 77 | 78 | -------------------------------------------------------------------------------- /test/shimakaze.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env siren 2 | # -*- mode:ruby; coding:utf-8 -*- 3 | # IJN destroyer Shimakaze 4 | # (c) dyama 2014 5 | 6 | $ap = [0, 0, 0] 7 | $yaxis = [0, 1, 0] 8 | 9 | # lines of Hull 10 | wl = [ 11 | [[1.0,0,6],[1,1,6],[3,2,6],[6,3,6],[10,4,6],[13,4.5,6],[20,5.0,6],[30,5.5,6],[40,5.5,6],[50,5.5,6],[60,5.5,6],[70,5.5,6],[80,5.5,6],[90,5.1,6.0],[100,4.5,6],[105,4.1-0.00,6],[110,3.5-0.00,6],[113,2.9-0.00,6],[116,2.0-0.00,6],[119-0.0,0.9-0.00,6],[120+0.9,0,6]], 12 | [[0.7,0,5],[1,1,5],[3,2,5],[6,3,5],[10,4,5],[13,4.5,5],[20,5.0,5],[30,5.5,5],[40,5.5,5],[50,5.5,5],[60,5.5,5],[70,5.5,5],[80,5.5,5],[90,5.1,5.0],[100,4.5,5],[105,4.1-0.10,5],[110,3.5-0.10,5],[113,2.9-0.10,5],[116,2.0-0.12,5],[119-0.2,0.9-0.10,5],[120+0.4,0,5]], 13 | [[0.5,0,4],[1,1,4],[3,2,4],[6,3,4],[10,4,4],[13,4.5,4],[20,5.0,4],[30,5.5,4],[40,5.5,4],[50,5.5,4],[60,5.5,4],[70,5.5,4],[80,5.5,4],[90,5.1,4,0],[100,4.5,4],[105,4.1-0.16,4],[110,3.5-0.16,4],[113,2.9-0.18,4],[116,2.0-0.23,4],[119-0.4,0.9-0.16,4],[120+0.0,0,4]], 14 | [[0.3,0,3],[1,1,3],[3,2,3],[6,3,3],[10,4,3],[13,4.5,3],[20,5.0,3],[30,5.5,3],[40,5.5,3],[50,5.5,3],[60,5.5,3],[70,5.5,3],[80,5.5,3],[90,5.1,3.0],[100,4.5,3],[105,4.1-0.20,3],[110,3.5-0.20,3],[113,2.9-0.24,3],[116,2.0-0.33,3],[119-0.6,0.9-0.20,3],[120-0.3,0,3]], 15 | [[0.2,0,2],[1,1,2],[3,2,2],[6,3,2],[10,4,2],[13,4.5,2],[20,5.0,2],[30,5.5,2],[40,5.5,2],[50,5.5,2],[60,5.5,2],[70,5.5,2],[80,5.5,2],[90,5.1,2.0],[100,4.5,2],[105,4.1-0.22,2],[110,3.5-0.22,2],[113,2.9-0.29,2],[116,2.0-0.42,2],[119-0.8,0.9-0.22,2],[120-0.5,0,2]], 16 | [[0.1,0,1],[1,1,1],[3,2,1],[6,3,1],[10,4,1],[13,4.5,1],[20,5.0,1],[30,5.5,1],[40,5.5,1],[50,5.5,1],[60,5.5,1],[70,5.5,1],[80,5.5,1],[90,5.1,1.0],[100,4.5,1],[105,4.1-0.23,1],[110,3.5-0.23,1],[113,2.9-0.33,1],[116,2.0-0.50,1],[119-1.0,0.9-0.23,1],[120-0.6,0,1]], 17 | [[0.0,0,0],[1,1,0],[3,2,0],[6,3,0],[10,4,0],[13,4.5,0],[20,5.0,0],[30,5.5,0],[40,5.5,0],[50,5.5,0],[60,5.5,0],[70,5.5,0],[80,5.5,0],[90,5.1,0.0],[100,4.5,0],[105,4.1-0.24,0],[110,3.5-0.24,0],[113,2.9-0.35,0],[116,2.0-0.56,0],[119-1.2,0.9-0.24,0],[120-0.7,0,0]] 18 | ] 19 | 20 | # 配列値をXYZ値を持つVec型に変換する 21 | def ar2vecs(ar) 22 | res = [] 23 | ar.each do |a| 24 | res.push Vec.new a[0], a[1], a[2] 25 | end 26 | return res 27 | end 28 | 29 | lines = [] 30 | wl.each do |n| 31 | m = ar2vecs n 32 | lines.push(Build.polyline(m)) 33 | end 34 | 35 | hullp = Offset.loft lines 36 | 37 | gunnel = ar2vecs(wl.first + [wl.first[0]]) 38 | topp = Build.polygon gunnel 39 | 40 | gunnel = ar2vecs(wl.last + [wl.last[0]]) 41 | btmp = Build.polygon gunnel 42 | 43 | pside = Build.sewing [hullp, topp, btmp] 44 | sside = Build.copy pside 45 | sside.mirror! Vec.new(0, 0, 0), Vec.new(0, 1, 0) 46 | 47 | hullshell = Build.sewing [pside, sside] 48 | hull = Build.solid hullshell 49 | 50 | # Upperdeck line 51 | n = -9 52 | a = 10 53 | ul = [[0,n,2.5],[83,n,2.5],[85,n,4.8],[100,n,4.8],[110,n,5.1],[116,n,5.5],[122,n,6], 54 | [122,n,a],[0,n,a],[0,n,2.5]] 55 | 56 | vecs = ar2vecs ul 57 | plate = Build.polygon vecs 58 | deckbox = Offset.sweep_vec plate, Vec.new(0, -n*2, 0) 59 | 60 | res = hull.cut deckbox 61 | 62 | BRepIO.save res, "/tmp/shimakaze.brep" 63 | puts "Done." 64 | 65 | -------------------------------------------------------------------------------- /src/shape/chunk.cpp: -------------------------------------------------------------------------------- 1 | #ifdef SIREN_ENABLE_CHUNK 2 | 3 | #include "shape/chunk.h" 4 | 5 | mrb_value siren_chunk_new(mrb_state* mrb, const TopoDS_Shape* src) 6 | { 7 | mrb_value obj; 8 | struct RClass* cls_shape = siren_shape_rclass(mrb); 9 | struct RClass* mod_siren = mrb_module_get(mrb, "Siren"); 10 | obj = mrb_instance_alloc(mrb, mrb_const_get(mrb, mrb_obj_value(mod_siren), mrb_intern_lit(mrb, "Chunk"))); 11 | void* p = mrb_malloc(mrb, sizeof(TopoDS_Shape)); 12 | TopoDS_Shape* inner = new(p) TopoDS_Shape(); 13 | *inner = *src; // Copy to inner native member 14 | DATA_PTR(obj) = const_cast(inner); 15 | DATA_TYPE(obj) = &siren_chunk_type; 16 | return obj; 17 | } 18 | 19 | TopoDS_CompSolid siren_chunk_get(mrb_state* mrb, mrb_value self) 20 | { 21 | TopoDS_Shape* shape = static_cast(mrb_get_datatype(mrb, self, &siren_chunk_type)); 22 | TopoDS_CompSolid chunk = TopoDS::CompSolid(*shape); 23 | if (chunk.IsNull()) { mrb_raise(mrb, E_RUNTIME_ERROR, "The geometry type is not Chunk."); } 24 | return chunk; 25 | } 26 | 27 | bool siren_chunk_install(mrb_state* mrb, struct RClass* mod_siren) 28 | { 29 | struct RClass* cls_shape = siren_shape_rclass(mrb); 30 | struct RClass* cls_chunk = mrb_define_class_under(mrb, mod_siren, "Chunk", cls_shape); 31 | MRB_SET_INSTANCE_TT(cls_chunk, MRB_TT_DATA); 32 | mrb_define_method(mrb, cls_chunk, "initialize", siren_chunk_init, MRB_ARGS_NONE()); 33 | mrb_define_method(mrb, cls_chunk, "to_solid", siren_chunk_to_solid, MRB_ARGS_NONE()); 34 | return true; 35 | } 36 | 37 | struct RClass* siren_chunk_rclass(mrb_state* mrb) 38 | { 39 | struct RClass* mod_siren = mrb_module_get(mrb, "Siren"); 40 | return mrb_class_ptr(mrb_const_get(mrb, mrb_obj_value(mod_siren), mrb_intern_lit(mrb, "Chunk"))); 41 | } 42 | 43 | mrb_value siren_chunk_obj(mrb_state* mrb) 44 | { 45 | struct RClass* mod_siren = mrb_module_get(mrb, "Siren"); 46 | return mrb_const_get(mrb, mrb_obj_value(mod_siren), mrb_intern_lit(mrb, "Chunk")); 47 | } 48 | 49 | mrb_value siren_chunk_init(mrb_state* mrb, mrb_value self) 50 | { 51 | mrb_value* a; 52 | mrb_int len; 53 | int argc = mrb_get_args(mrb, "*", &a, &len); 54 | 55 | TopoDS_CompSolid cs; 56 | TopoDS_Builder builder; 57 | builder.MakeCompSolid(cs); 58 | 59 | for (int i = 0; i < len; i++) { 60 | if (mrb_array_p(a[i])) { 61 | for (int j = 0; j < mrb_ary_len(mrb, a[i]); j++) { 62 | auto solid = siren_solid_get(mrb, mrb_ary_ref(mrb, a[i], j)); 63 | builder.Add(cs, solid); 64 | } 65 | } 66 | else { 67 | auto solid = siren_solid_get(mrb, a[i]); 68 | builder.Add(cs, solid); 69 | } 70 | } 71 | 72 | void* p = mrb_malloc(mrb, sizeof(TopoDS_Shape)); 73 | TopoDS_Shape* inner = new(p) TopoDS_Shape(); 74 | *inner = cs; // Copy to inner native member 75 | DATA_PTR(self) = const_cast(inner); 76 | DATA_TYPE(self) = &siren_chunk_type; 77 | return self; 78 | } 79 | 80 | mrb_value siren_chunk_to_solid(mrb_state* mrb, mrb_value self) 81 | { 82 | auto cs = siren_chunk_get(mrb, self); 83 | auto solid = BRepBuilderAPI_MakeSolid(cs); 84 | return siren_shape_new(mrb, solid); 85 | } 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /test/siren-2d-drawer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | siren 2d drawer 5 | 14 | 15 | 16 | 17 |
18 | 19 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /inc/common.h: -------------------------------------------------------------------------------- 1 | #ifndef _COMMON_H_ 2 | #define _COMMON_H_ 3 | 4 | #include "mruby.h" 5 | #include "shape.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | void siren_ary_to_xyz(mrb_state* mrb, mrb_value ary, Standard_Real& x, Standard_Real& y, Standard_Real& z); 15 | 16 | inline gp_Pnt siren_ary_to_pnt(mrb_state* mrb, mrb_value val) 17 | { 18 | Standard_Real x, y, z; 19 | siren_ary_to_xyz(mrb, val, x, y, z); 20 | return gp_Pnt(x, y, z); 21 | } 22 | 23 | inline gp_Vec siren_ary_to_vec(mrb_state* mrb, mrb_value val) 24 | { 25 | Standard_Real x, y, z; 26 | siren_ary_to_xyz(mrb, val, x, y, z); 27 | return gp_Vec(x, y, z); 28 | } 29 | 30 | inline gp_Dir siren_ary_to_dir(mrb_state* mrb, mrb_value val) 31 | { 32 | Standard_Real x, y, z; 33 | siren_ary_to_xyz(mrb, val, x, y, z); 34 | return gp_Dir(x, y, z); 35 | } 36 | 37 | inline gp_Ax1 siren_ary_to_ax1(mrb_state* mrb, mrb_value pos, mrb_value norm) 38 | { 39 | return gp_Ax1(siren_ary_to_pnt(mrb, pos), siren_ary_to_dir(mrb, norm)); 40 | } 41 | 42 | inline gp_Ax2 siren_ary_to_ax2(mrb_state* mrb, mrb_value pos, mrb_value norm, mrb_value vdir) 43 | { 44 | return gp_Ax2(siren_ary_to_pnt(mrb, pos), siren_ary_to_dir(mrb, norm), siren_ary_to_dir(mrb, vdir)); 45 | } 46 | 47 | inline gp_Ax2 siren_ary_to_ax2(mrb_state* mrb, mrb_value pos, mrb_value norm) 48 | { 49 | return gp_Ax2(siren_ary_to_pnt(mrb, pos), siren_ary_to_dir(mrb, norm)); 50 | } 51 | 52 | inline gp_Ax3 siren_ary_to_ax3(mrb_state* mrb, mrb_value pos, mrb_value norm, mrb_value vdir) 53 | { 54 | return gp_Ax3(siren_ary_to_pnt(mrb, pos), siren_ary_to_dir(mrb, norm), siren_ary_to_dir(mrb, vdir)); 55 | } 56 | 57 | inline gp_Ax3 siren_ary_to_ax3(mrb_state* mrb, mrb_value pos, mrb_value norm) 58 | { 59 | return gp_Ax3(siren_ary_to_pnt(mrb, pos), siren_ary_to_dir(mrb, norm)); 60 | } 61 | 62 | inline mrb_value siren_pnt_to_ary(mrb_state* mrb, const gp_Pnt& pnt) 63 | { 64 | mrb_value res[3]; 65 | res[0] = mrb_float_value(mrb, pnt.X()); 66 | res[1] = mrb_float_value(mrb, pnt.Y()); 67 | res[2] = mrb_float_value(mrb, pnt.Z()); 68 | return mrb_ary_new_from_values(mrb, 3, res); 69 | } 70 | 71 | inline mrb_value siren_dir_to_ary(mrb_state* mrb, const gp_Dir& dir) 72 | { 73 | mrb_value res[3]; 74 | res[0] = mrb_float_value(mrb, dir.X()); 75 | res[1] = mrb_float_value(mrb, dir.Y()); 76 | res[2] = mrb_float_value(mrb, dir.Z()); 77 | return mrb_ary_new_from_values(mrb, 3, res); 78 | } 79 | 80 | inline mrb_value siren_vec_to_ary(mrb_state* mrb, const gp_Vec& vec) 81 | { 82 | mrb_value res[3]; 83 | res[0] = mrb_float_value(mrb, vec.X()); 84 | res[1] = mrb_float_value(mrb, vec.Y()); 85 | res[2] = mrb_float_value(mrb, vec.Z()); 86 | return mrb_ary_new_from_values(mrb, 3, res); 87 | } 88 | 89 | inline mrb_value siren_pnt_new(mrb_state* mrb, double x, double y, double z) 90 | { 91 | mrb_value res[3]; 92 | res[0] = mrb_float_value(mrb, x); 93 | res[1] = mrb_float_value(mrb, y); 94 | res[2] = mrb_float_value(mrb, z); 95 | return mrb_ary_new_from_values(mrb, 3, res); 96 | } 97 | 98 | mrb_value mrb_instance_alloc(mrb_state *mrb, mrb_value cv); 99 | 100 | #endif 101 | -------------------------------------------------------------------------------- /inc/vec.h: -------------------------------------------------------------------------------- 1 | #ifndef _VEC_H_ 2 | #define _VEC_H_ 3 | 4 | #include "siren.h" 5 | 6 | bool siren_vec_install(mrb_state* mrb, struct RClass* rclass); 7 | void siren_vec_final(mrb_state* mrb, void* p); 8 | static struct mrb_data_type siren_vec_type = { "Vec", siren_vec_final }; 9 | gp_Vec* siren_vec_get(mrb_state* mrb, mrb_value obj); 10 | struct RClass* siren_vec_rclass(mrb_state* mrb); 11 | mrb_value siren_vec_new(mrb_state* mrb, double x, double y, double z); 12 | mrb_value siren_vec_new(mrb_state* mrb, const gp_Vec& vec); 13 | 14 | mrb_value siren_vec_init(mrb_state* mrb, mrb_value self); 15 | mrb_value siren_vec_x(mrb_state* mrb, mrb_value self); 16 | mrb_value siren_vec_x_set(mrb_state* mrb, mrb_value self); 17 | mrb_value siren_vec_y(mrb_state* mrb, mrb_value self); 18 | mrb_value siren_vec_y_set(mrb_state* mrb, mrb_value self); 19 | mrb_value siren_vec_z(mrb_state* mrb, mrb_value self); 20 | mrb_value siren_vec_z_set(mrb_state* mrb, mrb_value self); 21 | 22 | mrb_value siren_vec_is_equal(mrb_state* mrb, mrb_value self); 23 | mrb_value siren_vec_is_normal(mrb_state* mrb, mrb_value self); 24 | mrb_value siren_vec_is_reverse(mrb_state* mrb, mrb_value self); 25 | mrb_value siren_vec_is_parallel(mrb_state* mrb, mrb_value self); 26 | mrb_value siren_vec_angle(mrb_state* mrb, mrb_value self); 27 | mrb_value siren_vec_angleref(mrb_state* mrb, mrb_value self); 28 | mrb_value siren_vec_magnitude(mrb_state* mrb, mrb_value self); 29 | mrb_value siren_vec_square_mag(mrb_state* mrb, mrb_value self); 30 | mrb_value siren_vec_cross(mrb_state* mrb, mrb_value self); 31 | mrb_value siren_vec_cross_bang(mrb_state* mrb, mrb_value self); 32 | mrb_value siren_vec_cross_mag(mrb_state* mrb, mrb_value self); 33 | mrb_value siren_vec_cross_square_mag(mrb_state* mrb, mrb_value self); 34 | mrb_value siren_vec_cross_cross(mrb_state* mrb, mrb_value self); 35 | mrb_value siren_vec_cross_cross_bang(mrb_state* mrb, mrb_value self); 36 | mrb_value siren_vec_dot(mrb_state* mrb, mrb_value self); 37 | mrb_value siren_vec_dot_cross(mrb_state* mrb, mrb_value self); 38 | mrb_value siren_vec_normal(mrb_state* mrb, mrb_value self); 39 | mrb_value siren_vec_normal_bang(mrb_state* mrb, mrb_value self); 40 | mrb_value siren_vec_reverse(mrb_state* mrb, mrb_value self); 41 | mrb_value siren_vec_reverse_bang(mrb_state* mrb, mrb_value self); 42 | 43 | // mrb_value siren_vec_coord(mrb_state* mrb, mrb_value self); 44 | // mrb_value siren_vec_coord_set(mrb_state* mrb, mrb_value self); 45 | 46 | mrb_value siren_vec_mirror(mrb_state* mrb, mrb_value self); 47 | mrb_value siren_vec_mirror_bang(mrb_state* mrb, mrb_value self); 48 | mrb_value siren_vec_rotate(mrb_state* mrb, mrb_value self); 49 | mrb_value siren_vec_rotate_bang(mrb_state* mrb, mrb_value self); 50 | mrb_value siren_vec_scale(mrb_state* mrb, mrb_value self); 51 | mrb_value siren_vec_scale_bang(mrb_state* mrb, mrb_value self); 52 | mrb_value siren_vec_transform(mrb_state* mrb, mrb_value self); 53 | mrb_value siren_vec_transform_bang(mrb_state* mrb, mrb_value self); 54 | 55 | mrb_value siren_vec_negative(mrb_state* mrb, mrb_value self); 56 | 57 | mrb_value siren_vec_eq(mrb_state* mrb, mrb_value self); 58 | mrb_value siren_vec_plus(mrb_state* mrb, mrb_value self); 59 | mrb_value siren_vec_minus(mrb_state* mrb, mrb_value self); 60 | mrb_value siren_vec_multiply_scalar(mrb_state* mrb, mrb_value self); 61 | mrb_value siren_vec_devide_scalar(mrb_state* mrb, mrb_value self); 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | siren - Lightweight 3D operation environment 2 | ===================================== 3 | 4 | ![siren logo](http://siren.xyz/res/siren_logo.png) 5 | 6 | **siren** is lightweight 3D operation environment powered by Open CASCADE Technorogy. siren is integrated to mruby; lightweight Ruby interpreter environment, so it gives high-level 3D geometrical and topological operation with easy and simple scripting. 7 | For example, you can get volume of shape, intersection lines of some shapes, center of gravity and a result of boolean operation. It supports IGES, STEP file with NURBS surface and curve. 8 | 9 | You can get more information at siren official page. 10 | 11 | * siren official page: http://siren.xyz/ 12 | 13 | Example 14 | ------- 15 | 16 | # Make two boxes 17 | box1 = Siren.box [10, 10, 10] 18 | box2 = Siren.box [10, 10, 10] 19 | 20 | # Move box2 21 | box2.translate! [5, 5, 5] 22 | 23 | # Fuse two boxes 24 | box3 = box1.fuse box2 25 | 26 | # Print volume of box 27 | p box3.volume # => 1875 28 | 29 | box3.faces do |face| 30 | # Print area of face 31 | p face.area 32 | end 33 | 34 | You can find more examples code at the Github page. 35 | 36 | https://github.com/dyama/mruby-siren/wiki/Example 37 | 38 | Requirement 39 | ----------- 40 | 41 | * Microsoft Windows 42 | * Mac OS X 43 | * Linux 44 | 45 | Dependencies 46 | ------------ 47 | 48 | * mruby (Lightweight Ruby interpreter engine) 49 | * Official page: http://www.mruby.org/ 50 | * Source code: https://github.com/mruby/mruby 51 | * License: https://github.com/mruby/mruby/blob/master/MITL 52 | 53 | * Open CASCADE Technorogy 7.1.0 54 | * Official page: http://www.opencascade.org/ 55 | * Source code: http://www.opencascade.com/content/latest-release 56 | * License: http://www.opencascade.com/content/licensing 57 | 58 | How to build 59 | ------------ 60 | 1. Install OCCT libraries and headers on your system. 61 | 2. Clone mruby source code from github. 62 | 3. Add `conf.gem :github => "dyama/mruby-siren"` line to mrbgems/default.gembox. 63 | 4. Make mruby. 64 | 65 | If your OCCT installed path is not `/opt/occ`, you should change mrbgem.rake file in build/mrbgems/mruby-siren. 66 | Default install path is; 67 | 68 | * /opt/occ/710 ... for Linux 69 | * /usr/local/opt/opencascade ... for Mac OS X 70 | * \\occ\\710 .. for MinGW64 71 | 72 | Usage 73 | ----- 74 | 75 | * Run /bin/mirb. 76 | 77 | $ cd ~/mruby/bin 78 | $ ./mirb 79 | 80 | * Run /bin/mruby with siren script. 81 | 82 | $ cd ~/mruby/bin 83 | $ ./mruby script.rb 84 | 85 | * To specify the library path 86 | 87 | $ LD_LIBRARY_PATH=/opt/occ/710/lin64/gcc/lib ./mirb 88 | $ LD_LIBRARY_PATH=/opt/occ/710/lin64/gcc/lib ./mruby script.rb 89 | 90 | Or add the library path to /etc/ld.so.conf. 91 | 92 | Documentation 93 | ------------- 94 | 95 | * Official web page: http://siren.xyz/ 96 | * Tutorial: http://siren.xyz/tutorial.html 97 | * Wiki: https://github.com/dyama/mruby-siren/wiki. 98 | * Reference Manual: https://github.com/dyama/mruby-siren/wiki/Reference-manual 99 | * Examples: https://github.com/dyama/mruby-siren/wiki/Example 100 | 101 | Lincense 102 | -------- 103 | MIT License 104 | 105 | Show `LICENSE` file. 106 | 107 | Author 108 | ------ 109 | * dyama 110 | 111 | -------------------------------------------------------------------------------- /src/heal.cpp: -------------------------------------------------------------------------------- 1 | #include "heal.h" 2 | 3 | mrb_value siren_heal_outerwire(mrb_state* mrb, mrb_value self) 4 | { 5 | mrb_float tol = 1.0e-1; 6 | int argc = mrb_get_args(mrb, "|f", &tol); 7 | 8 | TopoDS_Shape* shape = siren_shape_get(mrb, self); 9 | 10 | mrb_value res = mrb_nil_value(); 11 | 12 | if (shape->ShapeType() == TopAbs_FACE) { 13 | TopoDS_Face face = TopoDS::Face(*shape); 14 | TopoDS_Wire wire = ShapeAnalysis::OuterWire(face); 15 | // ShapeAnalysis_FreeBounds 16 | // ::ConnectWiresToWires 17 | res = siren_shape_new(mrb, wire); 18 | } 19 | else { 20 | ShapeAnalysis_FreeBounds safb(*shape, tol); 21 | TopoDS_Compound comp = safb.GetClosedWires(); 22 | res = siren_shape_new(mrb, comp); 23 | } 24 | return res; 25 | } 26 | 27 | mrb_value siren_heal_fix(mrb_state* mrb, mrb_value self) 28 | { 29 | TopoDS_Shape* shape = siren_shape_get(mrb, self); 30 | mrb_value res = mrb_nil_value(); 31 | 32 | opencascade::handle sfs = new ShapeFix_Shape(); 33 | sfs->Init(*shape); 34 | sfs->SetPrecision(1.0); 35 | sfs->SetMinTolerance(1.0e-6); 36 | sfs->SetMaxTolerance(1.0e-1); 37 | 38 | switch (shape->ShapeType()) { 39 | case TopAbs_SOLID: 40 | sfs->FixSolidTool()->FixShellMode() = 1; 41 | case TopAbs_SHELL: 42 | sfs->FixShellTool()->FixFaceMode() = 1; 43 | sfs->FixShellTool()->FixOrientationMode() = 1; 44 | case TopAbs_FACE: 45 | sfs->FixFaceTool()->FixAddNaturalBoundMode() = 1; 46 | sfs->FixFaceTool()->FixIntersectingWiresMode() = 1; 47 | sfs->FixFaceTool()->FixLoopWiresMode() = 1; 48 | sfs->FixFaceTool()->FixOrientationMode() = 1; 49 | sfs->FixFaceTool()->FixPeriodicDegeneratedMode() = 1; 50 | sfs->FixFaceTool()->FixSmallAreaWireMode() = 1; 51 | sfs->FixFaceTool()->FixSplitFaceMode() = 1; 52 | sfs->FixFaceTool()->FixWireMode() = 1; 53 | case TopAbs_WIRE: 54 | //sfs->FixWireTool()->FixAddCurve3dMode() = 1; 55 | //sfs->FixWireTool()->FixAddPCurveMode() = 1; 56 | sfs->FixWireTool()->FixConnectedMode() = 1; 57 | sfs->FixWireTool()->FixDegeneratedMode() = 1; 58 | sfs->FixWireTool()->FixEdgeCurvesMode() = 1; 59 | //sfs->FixWireTool()->FixGaps2dMode() = 1; 60 | sfs->FixWireTool()->FixGaps3dMode() = 1; 61 | sfs->FixWireTool()->FixGapsByRangesMode() = 1; 62 | sfs->FixWireTool()->FixIntersectingEdgesMode() = 1; 63 | sfs->FixWireTool()->FixLackingMode() = 1; 64 | sfs->FixWireTool()->FixNonAdjacentIntersectingEdgesMode() = 1; 65 | sfs->FixWireTool()->FixNotchedEdgesMode() = 1; 66 | //sfs->FixWireTool()->FixRemoveCurve3dMode() = 1; 67 | //sfs->FixWireTool()->FixRemovePCurveMode() = 1; 68 | sfs->FixWireTool()->FixReorderMode() = 1; 69 | //sfs->FixWireTool()->FixReversed2dMode() = 1; 70 | sfs->FixWireTool()->FixSameParameterMode() = 1; 71 | sfs->FixWireTool()->FixSeamMode() = 1; 72 | sfs->FixWireTool()->FixSelfIntersectingEdgeMode() = 1; 73 | sfs->FixWireTool()->FixSelfIntersectionMode() = 1; 74 | sfs->FixWireTool()->FixShiftedMode() = 1; 75 | sfs->FixWireTool()->FixSmallMode() = 1; 76 | sfs->FixWireTool()->FixVertexToleranceMode() = 1; 77 | default: 78 | sfs->FixVertexPositionMode() = 1; 79 | } 80 | 81 | sfs->Perform(); 82 | 83 | TopoDS_Shape fixedshape = sfs->Shape(); 84 | if (!fixedshape.IsNull()) { 85 | res = siren_shape_new(mrb, fixedshape); 86 | } 87 | 88 | return res; 89 | } 90 | 91 | -------------------------------------------------------------------------------- /mrblib/Shape.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Shape クラス拡張メソッド 3 | # 4 | class Siren::Shape 5 | 6 | # Explorer wrapper methods 7 | 8 | def compounds(filter = nil) 9 | if filter.nil? 10 | self.explore(Siren::Compound) 11 | else 12 | self.explore(Siren::Compound, filter) 13 | end 14 | end 15 | 16 | def solids(filter = nil) 17 | if filter.nil? 18 | self.explore(Siren::Solid) 19 | else 20 | self.explore(Siren::Solid, filter) 21 | end 22 | end 23 | 24 | def shells(filter = nil) 25 | if filter.nil? 26 | self.explore(Siren::Shell) 27 | else 28 | self.explore(Siren::Shell, filter) 29 | end 30 | end 31 | 32 | def faces(filter = nil) 33 | if filter.nil? 34 | self.explore(Siren::Face) 35 | else 36 | self.explore(Siren::Face, filter) 37 | end 38 | end 39 | 40 | def wires(filter = nil) 41 | if filter.nil? 42 | self.explore(Siren::Wire) 43 | else 44 | self.explore(Siren::Wire, filter) 45 | end 46 | end 47 | 48 | def edges(filter = nil) 49 | if filter.nil? 50 | self.explore(Siren::Edge) 51 | else 52 | self.explore(Siren::Edge, filter) 53 | end 54 | end 55 | 56 | def vertices(filter = nil) 57 | if filter.nil? 58 | self.explore(Siren::Vertex) 59 | else 60 | self.explore(Siren::Vertex, filter) 61 | end 62 | end 63 | 64 | # Type check methods 65 | 66 | def compound? 67 | self.is_a? Siren::Compound 68 | end 69 | 70 | def solid? 71 | self.is_a? Siren::Solid 72 | end 73 | 74 | def shell? 75 | self.is_a? Siren::Shell 76 | end 77 | 78 | def face? 79 | self.is_a? Siren::Face 80 | end 81 | 82 | def wire? 83 | self.is_a? Siren::Wire 84 | end 85 | 86 | def edge? 87 | self.is_a? Siren::Edge 88 | end 89 | 90 | def vertex? 91 | self.is_a? Siren::Vertex 92 | end 93 | 94 | def dump_tree(current_depth = 0, &limit) 95 | hc = sprintf("%06X", self.hashcode(0xFFFFFF)) 96 | type = self.class.to_s 97 | puts " " * current_depth + "%s:0x%s" % [type, hc] 98 | if limit && limit.call(current_depth, self) 99 | # puts " " * current_depth + "..." 100 | return 101 | end 102 | current_depth += 1 103 | self.subshapes.each do |s| 104 | s.dump_tree(current_depth, &limit) 105 | end 106 | nil 107 | end 108 | 109 | def dump_compound 110 | self.dump_tree{|depth, child| child.compound?} 111 | end 112 | 113 | def dump_solid 114 | self.dump_tree{|depth, child| child.solid?} 115 | end 116 | 117 | def dump_shell 118 | self.dump_tree{|depth, child| child.sell?} 119 | end 120 | 121 | def dump_face 122 | self.dump_tree{|depth, child| child.face?} 123 | end 124 | 125 | def dump_wire 126 | self.dump_tree{|depth, child| child.wire?} 127 | end 128 | 129 | def dump_edge 130 | self.dump_tree{|depth, child| child.edge?} 131 | end 132 | 133 | def dump_vertex 134 | self.dump_tree{|depth, child| child.vertex?} 135 | end 136 | 137 | def clone(copy_geom = true) 138 | Siren.copy(self, copy_geom) 139 | end 140 | 141 | def to_a 142 | if self.compound? 143 | ar = [] 144 | self.subshapes.each do |s| 145 | if s.compound? 146 | ar << s.to_a 147 | else 148 | ar.push s 149 | end 150 | end 151 | return ar 152 | else 153 | return [self] 154 | end 155 | end 156 | 157 | end 158 | -------------------------------------------------------------------------------- /test/hydrostatics.rb: -------------------------------------------------------------------------------- 1 | 2 | # 1. Offset table csv to surface/solid model. 3 | # 2. Calculation hydrostatics table with solid model. 4 | 5 | ofsfile = "/tmp/TABLE.csv" 6 | lpp = 22.4 7 | 8 | no = "" 9 | sl = [] 10 | t = Hash.new 11 | 12 | puts "Parse offset table..." 13 | File.open(ofsfile, "r") do |f| 14 | f.each do |ln| 15 | if ln == nil then next end 16 | r = ln.chomp.split(/ *, */) 17 | case r[0] 18 | # Get ship no. 19 | when "!OFFSET" 20 | no = r[1].gsub(/\"/, "") 21 | # Get station line definitions 22 | when "SB" 23 | sl = r[2..-1].map{ |f| f = f.to_f } 24 | # Get offset data 25 | when /^SF\d{3}$/ 26 | w = r[1].to_f 27 | i = 0 28 | r[2..-1].map{ |f| f = f.to_f }.each do |n| 29 | if t[sl[i]] == nil then t[sl[i]] = Hash.new end 30 | if t[sl[i]][w] == nil then t[sl[i]][w] = Hash.new end 31 | t[sl[i]][w] = n 32 | i += 1 33 | end 34 | end 35 | end 36 | end 37 | 38 | puts "Make hullshape surface..." 39 | ws = Array.new 40 | t.each do |x, ln| 41 | x = x * lpp / 10 42 | pts = Array.new 43 | ln.each do |z, y| 44 | pts.push Vec.new(x, y, z) 45 | end 46 | ws.push Build.polyline(pts) 47 | end 48 | hullsurf = Offset.loft ws 49 | 50 | ae_line = t.sort_by{|k,v|k}.first 51 | fe_line = t.sort_by{|k,v|k}.last 52 | zmin = ae_line.last.sort_by{|k,v|k}.first.first 53 | zmax = ae_line.last.sort_by{|k,v|k}.last.first 54 | xmin = ae_line.first 55 | xmax = fe_line.first * lpp / 10 56 | 57 | puts "Make XZ plane on center line..." 58 | cl_plane = Build.polygon [ 59 | Vec.new(xmin, 0, zmin), Vec.new(xmin, 0, zmax), 60 | Vec.new(xmax, 0, zmax), Vec.new(xmax, 0, zmin), 61 | ] 62 | 63 | puts "Make XY plane on top..." 64 | pts = Array.new 65 | pts.push(Vec.new(xmin, 0, zmax)) 66 | t.each do |x, ln| 67 | pts.push(Vec.new((x * lpp / 10), ln.sort.last.last, zmax)) 68 | end 69 | pts.push(Vec.new(xmax, 0, zmax)) 70 | top_plane = Build.polygon pts 71 | 72 | # Make end plate 73 | def makeend(line) 74 | zmin = line.last.sort_by{|k,v|k}.first.first 75 | zmax = line.last.sort_by{|k,v|k}.last.first 76 | xpos = line.first 77 | pls = Array.new 78 | pts = nil 79 | line.last.sort_by{|k,v|k}.each_cons(2) do |cur,nex| 80 | cz = cur.first; cy = cur.last 81 | nz = nex.first; ny = nex.last 82 | if pts == nil 83 | # In out of polygon 84 | if cz == zmin && cy > 0 # Already started at first 85 | pts = Array.new 86 | pts.push Vec.new xpos, 0, zmin 87 | pts.push Vec.new xpos, cy, cz 88 | next 89 | end 90 | if cy == 0 && ny > 0 # Start polygon 91 | pts = Array.new 92 | pts.push Vec.new xpos, cy, cz 93 | next 94 | end 95 | else 96 | # In polygon 97 | pts.push Vec.new xpos, cy, cz 98 | if cy == 0 # Break from polygon 99 | pls.push Build.polygon pts 100 | pts = nil 101 | end 102 | end 103 | end 104 | if pts != nil 105 | pts.push Vec.new xpos, 0, zmax 106 | pls.push Build.polygon pts 107 | end 108 | return pls 109 | end 110 | 111 | puts "Make transom and F.E. plane..." 112 | pl_transom = makeend ae_line 113 | pl_foreend = makeend fe_line 114 | 115 | comp = Build.compound [hullsurf, cl_plane, top_plane] + pl_transom + pl_foreend 116 | BRepIO.save comp, "/tmp/#{no}.brep" 117 | 118 | #puts "Sewing faces to shell..." 119 | #shell = Build.sewing [hullsurf, cl_plane, top_plane] + pl_transom + pl_foreend 120 | 121 | #puts "Build solid from shell..." 122 | #hullsolid = Build.solid hullsolid 123 | # 124 | #puts "Save solid model to file..." 125 | #BRepIO.save hullsolid, "/tmp/#{no}.brep" 126 | 127 | puts "Done." 128 | 129 | -------------------------------------------------------------------------------- /mrblib/Siren.rb: -------------------------------------------------------------------------------- 1 | ## 2 | # 3 | # Siren module 4 | # 5 | 6 | module Siren 7 | 8 | def self.warn(*msg) 9 | return if $VERBOSE.nil? && msg.empty? 10 | $stderr.puts("siren: warning: " + msg.join) 11 | end 12 | 13 | def self.save_model(shape, path) 14 | e5 = path[-5, path.size].downcase 15 | e4 = path[-4, path.size].downcase 16 | if e5 == ".brep" || e4 == ".brp" 17 | Siren.save_brep shape, path 18 | elsif e5 == ".iges" || e4 == ".igs" 19 | Siren.save_iges shape, path 20 | elsif e5 == ".step" || e4 == ".stp" 21 | Siren.save_step shape, path 22 | elsif e4 == ".stl" 23 | Siren.save_stl shape, path 24 | elsif e4 == ".ply" 25 | Siren.save_ply shape, path 26 | elsif e4 == ".dxf" 27 | Siren.save_dxf shape, path 28 | elsif e4 == ".dat" 29 | Siren.save_plot shape, path 30 | else 31 | raise TypeError 32 | end 33 | end 34 | 35 | def save_model(shape, path) 36 | Siren.save_model(shape, path) 37 | end 38 | 39 | def self.load_model(path) 40 | e5 = path[-5, path.size].downcase 41 | e4 = path[-4, path.size].downcase 42 | if e5 == ".brep" || e4 == ".brp" 43 | Siren.load_brep path 44 | elsif e5 == ".iges" || e4 == ".igs" 45 | Siren.load_iges path 46 | elsif e5 == ".step" || e4 == ".stp" 47 | Siren.load_step path 48 | elsif e4 == ".stl" 49 | Siren.load_stl path 50 | else 51 | raise TypeError 52 | end 53 | end 54 | 55 | def load_model(path) 56 | Siren.load_model(path) 57 | end 58 | 59 | def self.bscurve(*args) 60 | c = nil 61 | if args.size == 4 62 | c = BSCurve.new(*args) 63 | else 64 | c = BSCurve.new(*(args[0..4])) 65 | end 66 | if args.size == 7 # with limit paramters 67 | Edge.new c, args[5], args[6] 68 | else 69 | Edge.new c 70 | end 71 | end 72 | 73 | def bscurve(*args) 74 | Siren.bscurve(*args) 75 | end 76 | 77 | def self.bzcurve(*args) 78 | c = nil 79 | if args.size <= 2 80 | c = BzCurve.new(*args) 81 | else 82 | c = BzCurve.new(*(args[0..1])) 83 | end 84 | if args.size == 4 # with limit parameters 85 | Edge.new c, args[-2], args[-1] 86 | else 87 | Edge.new c 88 | end 89 | end 90 | 91 | def bzcurve(*args) 92 | Siren.bzcurve(*args) 93 | end 94 | 95 | # Alias 96 | { 97 | Siren::Vertex => { 98 | :vertex => :new 99 | }, 100 | Siren::Wire => { 101 | :wire => :make, 102 | }, 103 | Siren::Face => { 104 | :plane => :plane, 105 | :face => :face, 106 | :infplane => :infplane, 107 | :polygon => :polygon, 108 | :bzsurf => :bzsurf, 109 | :bssurf => :bssurf, 110 | }, 111 | Siren::Shell => { 112 | :sew => :make, 113 | :shell => :make, 114 | }, 115 | Siren::Solid => { 116 | :box => :box, 117 | :box2p => :box2p, 118 | :boxax => :boxax, 119 | :sphere => :sphere, 120 | :cylinder => :cylinder, 121 | :cone => :cone, 122 | :torus => :torus, 123 | :halfspace => :halfspace, 124 | :prism => :prism, 125 | :revol => :revol, 126 | :revolution => :revolution, 127 | :wedge => :wedge, 128 | } 129 | }.each do |c, ms| 130 | ms.each do |ma, mo| 131 | # ma = Alias method name 132 | # mo = Original method name 133 | # puts "Export #{c}.#{mo} as Siren.#{ma}" 134 | self.define_singleton_method(ma) do |*args| 135 | c.send(mo, *args) 136 | end 137 | self.class_eval do 138 | self.define_method(ma) do |*args| 139 | c.send(mo, *args) 140 | end 141 | end 142 | end 143 | end 144 | 145 | end 146 | 147 | -------------------------------------------------------------------------------- /test/vec.rb: -------------------------------------------------------------------------------- 1 | #!siren 2 | # coding: utf-8 3 | # Test script for Siren::Vec class. 4 | 5 | include Siren 6 | 7 | class Test4VecClass < MTest::Unit::TestCase 8 | 9 | def test_constant 10 | assert [0, 0, 0], Vec::o.to_a 11 | assert [1, 0, 0], Vec::x.to_a 12 | assert [0, 1, 0], Vec::y.to_a 13 | assert [0, 0, 1], Vec::z.to_a 14 | assert [1, 1, 0], Vec::xy.to_a 15 | assert [1, 0, 1], Vec::xz.to_a 16 | assert [1, 1, 0], Vec::yx.to_a 17 | assert [0, 1, 1], Vec::yz.to_a 18 | assert [1, 0, 1], Vec::zx.to_a 19 | assert [0, 1, 1], Vec::zy.to_a 20 | assert [1, 1, 1], Vec::xyz.to_a 21 | assert [0, 0, 0], Vec::zero.to_a 22 | assert [1, 0, 0], Vec::xdir.to_a 23 | assert [0, 1, 0], Vec::ydir.to_a 24 | assert [0, 0, 1], Vec::zdir.to_a 25 | end 26 | 27 | def test_initialize 28 | assert_equal [0, 0, 0], Vec.new.to_a 29 | assert_equal [1, 0, 0], Vec.new(1).to_a 30 | assert_equal [1, 1, 0], Vec.new(1, 1).to_a 31 | assert_equal [1, 1, 1], Vec.new(1, 1, 1).to_a 32 | assert_equal [0, 0, 0], Vec.new([]).to_a 33 | assert_equal [1, 0, 0], Vec.new([1]).to_a 34 | assert_equal [1, 1, 0], Vec.new([1, 1]).to_a 35 | assert_equal [1, 1, 1], Vec.new([1, 1, 1]).to_a 36 | end 37 | 38 | def test_operater 39 | assert_equal [-1, 0, 0], (-Vec.new(1, 0, 0)).to_a 40 | assert_equal [1, 1, 2], (Vec.new(1, 1, 1) + Vec.new(0, 0, 1)).to_a 41 | assert_equal [1, 1, 0], (Vec.new(1, 1, 1) - Vec.new(0, 0, 1)).to_a 42 | assert_equal [2, 2, 2], (Vec.new(1, 1, 1) * 2).to_a 43 | assert_equal [-10, 0, 0], (-Vec::xdir * 10).to_a 44 | assert_equal [0.5, 0.5, 0.5], (Vec.new(1, 1, 1) / 2).to_a 45 | assert_true Vec.new(1, 0, 0) == Vec.new(1, 0, 0) 46 | assert_false Vec.new(1, 1, 0) == Vec.new(1, 0, 0) 47 | assert_false Vec.new(1, 0, 0) != Vec.new(1, 0, 0) 48 | assert_true Vec.new(1, 1, 0) != Vec.new(1, 0, 0) 49 | end 50 | 51 | def test_operater_2d 52 | assert_equal [-1, 0, 0], (-Vec.new(1, 0)).to_a 53 | assert_equal [1, 2, 0], (Vec.new(1, 1) + Vec.new(0, 1)).to_a 54 | assert_equal [1, 0, 0], (Vec.new(1, 1) - Vec.new(0, 1)).to_a 55 | assert_equal [2, 2, 0], (Vec.new(1, 1) * 2).to_a 56 | assert_equal [0.5, 0.5, 0], (Vec.new(1, 1) / 2).to_a 57 | assert_true Vec.new(1, 0, 0) == Vec.new(1, 0) 58 | assert_false Vec.new(1, 1, 0) == Vec.new(1, 0) 59 | assert_false Vec.new(1, 0, 0) != Vec.new(1, 0) 60 | assert_true Vec.new(1, 1, 0) != Vec.new(1, 0) 61 | end 62 | 63 | def test_xyz 64 | assert_equal 1, Vec.new(1, 2, 3).x 65 | assert_equal 2, Vec.new(1, 2, 3).y 66 | assert_equal 3, Vec.new(1, 2, 3).z 67 | vec = Vec.new(0, 0, 0) 68 | vec.x = 1 69 | assert_equal 1, vec.x 70 | vec.y = 2 71 | assert_equal 2, vec.y 72 | vec.z = 3 73 | assert_equal 3, vec.z 74 | assert_equal [1, 2, 3], vec.to_a 75 | end 76 | 77 | def test_ext_array 78 | assert_equal Vec.new(0, 0, 0), [].to_v 79 | assert_equal Vec.new(0, 0, 0), [0].to_v 80 | assert_equal Vec.new(0, 1, 0), [0, 1].to_v 81 | assert_equal Vec.new(0, 1, 2), [0, 1, 2].to_v 82 | assert_equal Vec.new(0, 1, 2), [0, 1, 2, 3].to_v 83 | assert_equal 0, [].x 84 | assert_equal 0, [].y 85 | assert_equal 0, [].z 86 | assert_equal 1, [1, 0, 0].x 87 | assert_equal 1, [0, 1, 0].y 88 | assert_equal 1, [0, 0, 1].z 89 | ary = [] 90 | ary.x = 1 91 | assert_equal 1, ary.x 92 | ary.y = 2 93 | assert_equal 2, ary.y 94 | ary.z = 3 95 | assert_equal 3, ary.z 96 | assert_equal [1, 2, 3], ary 97 | end 98 | 99 | def test_method 100 | assert_equal [1, 0, 0], Vec.new(100, 0, 0).normal.to_a 101 | # assert_equal [Math.sqrt(2) / 2, Math.sqrt(2) / 2, 0], Vec.new(100, 100, 0).normal.to_a 102 | end 103 | 104 | end 105 | 106 | 107 | MTest::Unit.new.run 108 | -------------------------------------------------------------------------------- /src/shape/vertex.cpp: -------------------------------------------------------------------------------- 1 | #include "shape/vertex.h" 2 | 3 | mrb_value siren_vertex_new(mrb_state* mrb, const TopoDS_Shape* src) 4 | { 5 | mrb_value obj; 6 | struct RClass* cls_shape = siren_shape_rclass(mrb); 7 | struct RClass* mod_siren = mrb_module_get(mrb, "Siren"); 8 | obj = mrb_instance_alloc(mrb, mrb_const_get(mrb, mrb_obj_value(mod_siren), mrb_intern_lit(mrb, "Vertex"))); 9 | void* p = mrb_malloc(mrb, sizeof(TopoDS_Shape)); 10 | TopoDS_Shape* inner = new(p) TopoDS_Shape(); 11 | *inner = *src; // Copy to inner native member 12 | DATA_PTR(obj) = const_cast(inner); 13 | DATA_TYPE(obj) = &siren_vertex_type; 14 | return obj; 15 | } 16 | 17 | TopoDS_Vertex siren_vertex_get(mrb_state* mrb, mrb_value self) 18 | { 19 | TopoDS_Shape* shape = static_cast(mrb_get_datatype(mrb, self, &siren_vertex_type)); 20 | TopoDS_Vertex vertex = TopoDS::Vertex(*shape); 21 | if (vertex.IsNull()) { mrb_raise(mrb, E_RUNTIME_ERROR, "The geometry type is not Vertex."); } 22 | return vertex; 23 | } 24 | 25 | bool siren_vertex_install(mrb_state* mrb, struct RClass* mod_siren) 26 | { 27 | struct RClass* cls_shape = siren_shape_rclass(mrb); 28 | struct RClass* cls_vertex = mrb_define_class_under(mrb, mod_siren, "Vertex", cls_shape); 29 | MRB_SET_INSTANCE_TT(cls_vertex, MRB_TT_DATA); 30 | mrb_define_method(mrb, cls_vertex, "initialize", siren_vertex_init, MRB_ARGS_NONE()); 31 | mrb_define_method(mrb, cls_vertex, "xyz", siren_vertex_xyz, MRB_ARGS_NONE()); 32 | mrb_define_method(mrb, cls_vertex, "to_a", siren_vertex_xyz, MRB_ARGS_NONE()); 33 | mrb_define_method(mrb, cls_vertex, "to_v", siren_vertex_to_v, MRB_ARGS_NONE()); 34 | return true; 35 | } 36 | 37 | struct RClass* siren_vertex_rclass(mrb_state* mrb) 38 | { 39 | struct RClass* mod_siren = mrb_module_get(mrb, "Siren"); 40 | return mrb_class_ptr(mrb_const_get(mrb, mrb_obj_value(mod_siren), mrb_intern_lit(mrb, "Vertex"))); 41 | } 42 | 43 | mrb_value siren_vertex_init(mrb_state* mrb, mrb_value self) 44 | { 45 | mrb_value* a; 46 | mrb_int len; 47 | int argc = mrb_get_args(mrb, "*", &a, &len); 48 | 49 | Standard_Real x = 0.0, y = 0.0, z = 0.0; 50 | if (len > 0 && mrb_array_p(a[0])) { 51 | gp_Pnt p = siren_ary_to_pnt(mrb, a[0]); 52 | x = p.X(); y = p.Y(); z = p.Z(); 53 | } 54 | else { 55 | if (len >= 1) { 56 | if (mrb_fixnum_p(a[0])) 57 | x = mrb_fixnum(a[0]); 58 | else if mrb_float_p(a[0]) 59 | x = mrb_float(a[0]); 60 | } 61 | if (len >= 2) { 62 | if (mrb_fixnum_p(a[1])) 63 | y = mrb_fixnum(a[1]); 64 | else if (mrb_float_p(a[1])) 65 | y = mrb_float(a[1]); 66 | } 67 | if (len >= 3) { 68 | if (mrb_fixnum_p(a[2])) 69 | z = mrb_fixnum(a[2]); 70 | else if (mrb_float_p(a[2])) 71 | z = mrb_float(a[2]); 72 | } 73 | } 74 | TopoDS_Vertex v = BRepBuilderAPI_MakeVertex(gp_Pnt(x, y, z)); 75 | 76 | void* p = mrb_malloc(mrb, sizeof(TopoDS_Shape)); 77 | TopoDS_Shape* inner = new(p) TopoDS_Shape(); 78 | *inner = v; // Copy to inner native member 79 | DATA_PTR(self) = const_cast(inner); 80 | DATA_TYPE(self) = &siren_vertex_type; 81 | return self; 82 | } 83 | 84 | mrb_value siren_vertex_xyz(mrb_state* mrb, mrb_value self) 85 | { 86 | TopoDS_Vertex vertex = siren_vertex_get(mrb, self); 87 | return siren_pnt_to_ary(mrb, BRep_Tool::Pnt(vertex)); 88 | } 89 | 90 | mrb_value siren_vertex_to_v(mrb_state* mrb, mrb_value self) 91 | { 92 | TopoDS_Vertex vertex = siren_vertex_get(mrb, self); 93 | gp_Pnt p = BRep_Tool::Pnt(vertex); 94 | return siren_vec_new(mrb, p.X(), p.Y(), p.Z()); 95 | } 96 | 97 | mrb_value siren_vertex_obj(mrb_state* mrb) 98 | { 99 | struct RClass* mod_siren = mrb_module_get(mrb, "Siren"); 100 | return mrb_const_get(mrb, mrb_obj_value(mod_siren), mrb_intern_lit(mrb, "Vertex")); 101 | } 102 | 103 | -------------------------------------------------------------------------------- /inc/shape.h: -------------------------------------------------------------------------------- 1 | #ifndef _SHAPE_H_ 2 | #define _SHAPE_H_ 3 | 4 | #include "siren.h" 5 | #include "vec.h" 6 | #include "bndbox.h" 7 | #include "trans.h" 8 | 9 | #ifdef SIREN_ENABLE_SHHEALING 10 | #include "heal.h" 11 | #endif 12 | 13 | void siren_shape_final(mrb_state* mrb, void* p); 14 | static struct mrb_data_type siren_shape_type = { "Shape", siren_shape_final }; 15 | 16 | #include "shape/vertex.h" 17 | #include "shape/edge.h" 18 | #include "shape/wire.h" 19 | #include "shape/face.h" 20 | #include "shape/shell.h" 21 | #include "shape/solid.h" 22 | #include "shape/chunk.h" 23 | #include "shape/compound.h" 24 | 25 | #include 26 | #include 27 | 28 | #include 29 | #include 30 | 31 | #include 32 | 33 | #include 34 | 35 | #include 36 | 37 | bool siren_shape_install(mrb_state* mrb, struct RClass* rclass); 38 | TopoDS_Shape* siren_shape_get(mrb_state* mrb, mrb_value obj); 39 | mrb_value siren_shape_new(mrb_state* mrb, const TopoDS_Shape& shape); 40 | struct RClass* siren_shape_rclass(mrb_state* mrb); 41 | #define siren_is_shape(obj) (DATA_TYPE(obj) == &siren_shape_type) 42 | 43 | mrb_value siren_shape_init(mrb_state* mrb, mrb_value self); 44 | mrb_value siren_shape_is_null(mrb_state* mrb, mrb_value self); 45 | mrb_value siren_shape_pos(mrb_state* mrb, mrb_value self); 46 | mrb_value siren_shape_trans(mrb_state* mrb, mrb_value self); 47 | mrb_value siren_shape_set_trans(mrb_state* mrb, mrb_value self); 48 | 49 | mrb_value siren_shape_bndbox(mrb_state* mrb, mrb_value self); 50 | 51 | mrb_value siren_shape_translate_bang(mrb_state* mrb, mrb_value self); 52 | mrb_value siren_shape_rotate_bang(mrb_state* mrb, mrb_value self); 53 | mrb_value siren_shape_scale_bang(mrb_state* mrb, mrb_value self); 54 | mrb_value siren_shape_mirror_bang(mrb_state* mrb, mrb_value self); 55 | mrb_value siren_shape_move_bang(mrb_state* mrb, mrb_value self); 56 | mrb_value siren_shape_translate(mrb_state* mrb, mrb_value self); 57 | mrb_value siren_shape_rotate(mrb_state* mrb, mrb_value self); 58 | mrb_value siren_shape_scale(mrb_state* mrb, mrb_value self); 59 | mrb_value siren_shape_mirror(mrb_state* mrb, mrb_value self); 60 | mrb_value siren_shape_move(mrb_state* mrb, mrb_value self); 61 | 62 | mrb_value siren_shape_hashcode(mrb_state* mrb, mrb_value self); 63 | 64 | mrb_value siren_shape_is_partner(mrb_state* mrb, mrb_value self); 65 | mrb_value siren_shape_is_same(mrb_state* mrb, mrb_value self); 66 | mrb_value siren_shape_is_equal(mrb_state* mrb, mrb_value self); 67 | 68 | mrb_value siren_shape_explore(mrb_state* mrb, mrb_value self); 69 | mrb_value siren_shape_subshapes(mrb_state* mrb, mrb_value self); 70 | 71 | mrb_value siren_shape_section(mrb_state* mrb, mrb_value self); 72 | 73 | mrb_value siren_shape_reverse(mrb_state* mrb, mrb_value self); 74 | mrb_value siren_shape_reverse_bang(mrb_state* mrb, mrb_value self); 75 | 76 | /* from BRepTools */ 77 | mrb_value siren_shape_update_bang(mrb_state* mrb, mrb_value self); 78 | mrb_value siren_shape_clean_bang(mrb_state* mrb, mrb_value self); 79 | 80 | /* flag accesors */ 81 | mrb_value siren_shape_is_lock(mrb_state* mrb, mrb_value self); 82 | mrb_value siren_shape_set_lock(mrb_state* mrb, mrb_value self); 83 | mrb_value siren_shape_is_modify(mrb_state* mrb, mrb_value self); 84 | mrb_value siren_shape_set_modify(mrb_state* mrb, mrb_value self); 85 | mrb_value siren_shape_is_check(mrb_state* mrb, mrb_value self); 86 | mrb_value siren_shape_set_check(mrb_state* mrb, mrb_value self); 87 | mrb_value siren_shape_is_orientable(mrb_state* mrb, mrb_value self); 88 | mrb_value siren_shape_set_orientable(mrb_state* mrb, mrb_value self); 89 | mrb_value siren_shape_is_close(mrb_state* mrb, mrb_value self); 90 | mrb_value siren_shape_set_close(mrb_state* mrb, mrb_value self); 91 | mrb_value siren_shape_is_infinite(mrb_state* mrb, mrb_value self); 92 | mrb_value siren_shape_set_infinite(mrb_state* mrb, mrb_value self); 93 | mrb_value siren_shape_is_convex(mrb_state* mrb, mrb_value self); 94 | mrb_value siren_shape_set_convex(mrb_state* mrb, mrb_value self); 95 | 96 | mrb_value siren_shape_next_trans(mrb_state* mrb, mrb_value self); 97 | mrb_value siren_shape_first_datum(mrb_state* mrb, mrb_value self); 98 | 99 | // mrb_value siren_shape_complement(mrb_state* mrb, mrb_value self); 100 | // mrb_value siren_shape_complement_bang(mrb_state* mrb, mrb_value self); 101 | // mrb_value siren_shape_compose(mrb_state* mrb, mrb_value self); 102 | // mrb_value siren_shape_compose_bang(mrb_state* mrb, mrb_value self); 103 | #endif 104 | -------------------------------------------------------------------------------- /src/shape/compound.cpp: -------------------------------------------------------------------------------- 1 | #include "shape/compound.h" 2 | 3 | mrb_value siren_compound_new(mrb_state* mrb, const TopoDS_Shape* src) 4 | { 5 | mrb_value obj; 6 | struct RClass* cls_shape = siren_shape_rclass(mrb); 7 | struct RClass* mod_siren = mrb_module_get(mrb, "Siren"); 8 | obj = mrb_instance_alloc(mrb, mrb_const_get(mrb, mrb_obj_value(mod_siren), mrb_intern_lit(mrb, "Compound"))); 9 | void* p = mrb_malloc(mrb, sizeof(TopoDS_Shape)); 10 | TopoDS_Shape* inner = new(p) TopoDS_Shape(); 11 | *inner = *src; // Copy to inner native member 12 | DATA_PTR(obj) = const_cast(inner); 13 | DATA_TYPE(obj) = &siren_compound_type; 14 | return obj; 15 | } 16 | 17 | TopoDS_Compound siren_compound_get(mrb_state* mrb, mrb_value self) 18 | { 19 | TopoDS_Shape* shape = static_cast(mrb_get_datatype(mrb, self, &siren_compound_type)); 20 | TopoDS_Compound compound = TopoDS::Compound(*shape); 21 | if (compound.IsNull()) { mrb_raise(mrb, E_RUNTIME_ERROR, "The geometry type is not Compound."); } 22 | return compound; 23 | } 24 | 25 | bool siren_compound_install(mrb_state* mrb, struct RClass* mod_siren) 26 | { 27 | struct RClass* cls_shape = siren_shape_rclass(mrb); 28 | struct RClass* cls_compound = mrb_define_class_under(mrb, mod_siren, "Compound", cls_shape); 29 | MRB_SET_INSTANCE_TT(cls_compound, MRB_TT_DATA); 30 | mrb_define_method(mrb, cls_compound, "initialize", siren_compound_init, MRB_ARGS_NONE()); 31 | mrb_define_method(mrb, cls_compound, "push", siren_compound_push, MRB_ARGS_NONE()); 32 | mrb_define_method(mrb, cls_compound, "<<", siren_compound_push, MRB_ARGS_NONE()); 33 | mrb_define_method(mrb, cls_compound, "delete", siren_compound_delete, MRB_ARGS_NONE()); 34 | return true; 35 | } 36 | 37 | struct RClass* siren_compound_rclass(mrb_state* mrb) 38 | { 39 | struct RClass* mod_siren = mrb_module_get(mrb, "Siren"); 40 | return mrb_class_ptr(mrb_const_get(mrb, mrb_obj_value(mod_siren), mrb_intern_lit(mrb, "Compound"))); 41 | } 42 | 43 | mrb_value siren_compound_obj(mrb_state* mrb) 44 | { 45 | struct RClass* mod_siren = mrb_module_get(mrb, "Siren"); 46 | return mrb_const_get(mrb, mrb_obj_value(mod_siren), mrb_intern_lit(mrb, "Compound")); 47 | } 48 | 49 | mrb_value siren_compound_init(mrb_state* mrb, mrb_value self) 50 | { 51 | mrb_value* a; 52 | mrb_int len; 53 | int argc = mrb_get_args(mrb, "*", &a, &len); 54 | 55 | TopoDS_Compound comp; 56 | BRep_Builder B; 57 | B.MakeCompound(comp); 58 | 59 | for (int i = 0; i < len; i++) { 60 | mrb_value arg = *(a + i); 61 | if (mrb_array_p(arg)) { 62 | mrb_value subary = mrb_funcall(mrb, arg, "flatten", 0); 63 | for (int j = 0; j < mrb_ary_len(mrb, subary); j++) { 64 | TopoDS_Shape* shape = siren_shape_get(mrb, mrb_ary_ref(mrb, subary, j)); 65 | B.Add(comp, *shape); 66 | } 67 | } 68 | else { 69 | TopoDS_Shape* shape = siren_shape_get(mrb, arg); 70 | B.Add(comp, *shape); 71 | } 72 | } 73 | 74 | void* p = mrb_malloc(mrb, sizeof(TopoDS_Shape)); 75 | TopoDS_Shape* inner = new(p) TopoDS_Shape(); 76 | *inner = comp; // Copy to inner native member 77 | DATA_PTR(self) = const_cast(inner); 78 | DATA_TYPE(self) = &siren_compound_type; 79 | return self; 80 | } 81 | 82 | mrb_value siren_compound_push(mrb_state* mrb, mrb_value self) 83 | { 84 | mrb_value* a; 85 | mrb_int len; 86 | int argc = mrb_get_args(mrb, "*", &a, &len); 87 | TopoDS_Compound comp = siren_compound_get(mrb, self); 88 | BRep_Builder B; 89 | for (int i = 0; i < len; i++) { 90 | mrb_value arg = *(a + i); 91 | if (mrb_array_p(arg)) { 92 | mrb_value subary = mrb_funcall(mrb, arg, "flatten", 0); 93 | for (int j = 0; j < mrb_ary_len(mrb, subary); j++) { 94 | TopoDS_Shape* shape = siren_shape_get(mrb, mrb_ary_ref(mrb, subary, j)); 95 | B.Add(comp, *shape); 96 | } 97 | } 98 | else { 99 | TopoDS_Shape* shape = siren_shape_get(mrb, arg); 100 | B.Add(comp, *shape); 101 | } 102 | } 103 | return self; 104 | } 105 | 106 | mrb_value siren_compound_delete(mrb_state* mrb, mrb_value self) 107 | { 108 | mrb_value* a; 109 | mrb_int len; 110 | int argc = mrb_get_args(mrb, "*", &a, &len); 111 | TopoDS_Compound comp = siren_compound_get(mrb, self); 112 | BRep_Builder B; 113 | for (int i = 0; i < len; i++) { 114 | mrb_value arg = *(a + i); 115 | if (mrb_array_p(arg)) { 116 | mrb_value subary = mrb_funcall(mrb, arg, "flatten", 0); 117 | for (int j = 0; j < mrb_ary_len(mrb, subary); j++) { 118 | TopoDS_Shape* shape = siren_shape_get(mrb, mrb_ary_ref(mrb, subary, j)); 119 | B.Remove(comp, *shape); 120 | } 121 | } 122 | else { 123 | TopoDS_Shape* shape = siren_shape_get(mrb, arg); 124 | B.Remove(comp, *shape); 125 | } 126 | } 127 | return self; 128 | } 129 | 130 | -------------------------------------------------------------------------------- /examples/make-hull.rb: -------------------------------------------------------------------------------- 1 | #!siren 2 | # coding: utf-8 3 | 4 | include Siren 5 | 6 | lpp = 158.0 7 | b = 27.0 * 1.2 8 | b2 = b / 2.0 9 | b4 = b / 4.0 10 | d = 14.4 11 | ae = -3.5 12 | loa = 166.575 + ae 13 | ms = lpp / 2.0 14 | pp_aft = ms - 20.035 15 | pp_fore = ms + 32.077 16 | pp_len = pp_fore - pp_aft; 17 | br = 1.8 18 | 19 | lines = [] 20 | faces = [] 21 | 22 | xtop_max = lpp + (loa - lpp) / 3.0 23 | 24 | # パラレルパート 25 | bilge = arc [0, b2-br, br], Vec.xdir, -Vec.zdir, br, 0.0.to_rad, 90.0.to_rad 26 | para_bl = line [0, 0], [0, b2-br] 27 | para_sl = line [0, b2, br], [0, b2, d] 28 | paraw = wire [para_bl, bilge, para_sl], 0.01 29 | parawa = copy paraw 30 | parawa.translate! [pp_aft] 31 | parawf = copy paraw 32 | parawf.translate! [pp_fore] 33 | para = loft [parawa, parawf] 34 | lines << parawa << parawf 35 | faces << para 36 | 37 | # アフトガンネルライン 38 | av = [(pp_aft - ae) / 4.0, b2].to_v - [ae, b4].to_v 39 | av.normal! 40 | ptsa = [ [ae, b4, d], [pp_aft - (pp_aft - ae) / 2.0, b2, d]] 41 | vcsa = [ av.to_a, [pp_len / 2.0, 0.0]] 42 | gunnela = interpolate(ptsa, vcsa) 43 | lines << gunnela 44 | 45 | # フォアガンネルライン 46 | fv = [xtop_max - pp_fore, 0].to_v - [(xtop_max - pp_fore) * 3.0 / 4.0, b2].to_v 47 | ptsf = [[pp_fore + (xtop_max - pp_fore) / 3.0, b2, d], [xtop_max, 0, d] ] 48 | vcsf = [ [pp_len / 2.0, 0.0], fv.to_a ] 49 | gunnelf = interpolate(ptsf, vcsf) 50 | lines << gunnelf 51 | 52 | # サイドデッドフラットライン 53 | sdfpa = [pp_aft - (pp_aft - ae) / 2.0, b2, d] 54 | sdfpf = [pp_fore + (xtop_max - pp_fore) / 3.0, b2, d] 55 | sdfla = interpolate [sdfpa, [pp_aft - (pp_aft-ae) / 3.0, b2, d / 2.0], [pp_aft, b2, br]], [[0,0,-1],nil,[1,0,0]] 56 | sdflf = interpolate [[pp_fore, b2, br], sdfpf], [[1,0,0],[0,0,1]] 57 | lines << sdfla << sdflf 58 | 59 | # ボトムデッドフラットライン 60 | blae = [-ae + -ae / 5.0, 0, 0] 61 | blfe = [lpp - (loa-lpp)/2.0, 0, 0] 62 | bdfla = interpolate [blae, [pp_aft, b2 - br, 0]], [[1,0,0],[1,0,0]] 63 | bdflf = interpolate [[pp_fore, b2 - br, 0], blfe], [[1,0,0],[1,-0.5,0]] 64 | lines << bdfla << bdflf 65 | 66 | # トランサム 67 | tsom_tl = line([ae, 0, d], [ae, b4, d]) 68 | tsom_bl = interpolate [[ae, 0, d * 2.0 / 3.0], [ae, b4, d]], [[0,1,0], [0,0,1]] 69 | lines << tsom_tl << tsom_bl 70 | 71 | # アフト プロファイル 72 | v1 = [-ae, 0, d / 2.0].to_v - [ae, 0, d * 2.0 / 3.0].to_v 73 | v1.normal! 74 | v2 = v1.rotate(Vec.ydir, 90.0.to_rad) 75 | v2.normal! 76 | tp = line [ae, 0, d],[ae, 0, d * 2.0 / 3.0] 77 | tp2 = line [ae, 0, d * 2.0 / 3.0], [-ae, 0, d / 2.0] 78 | tp3 = interpolate [[-ae, 0, d / 2.0], [-ae + -ae / 5.0, 0, d / 4.0]], [v1.to_a, v2.to_a] 79 | tp4 = line [-ae + -ae / 5.0, 0, d / 4.0], blae 80 | aft_profile = wire [tp, tp2, tp3, tp4], 0.01 81 | lines << aft_profile 82 | 83 | # フォア プロファイル 84 | p1 = blfe 85 | p2 = [loa, 0, d * 0.3] 86 | p3 = [lpp, 0, d / 4.0 * 2.5] 87 | p4 = [lpp, 0, d / 4.0 * 3.0] 88 | p5 = [xtop_max, 0, d] 89 | fore_profile = interpolate [p1, p2, [xtop_max,0,d/2.0], p3, p4, p5], [[1,0,0], [0,0,1], nil, [0,0,1], [0,0,1], (p5.to_v - p4.to_v).to_a] 90 | lines << fore_profile 91 | 92 | # ボトム面(アフト) 93 | bottom_aft_plane_contour = wire [bdfla, para_bl.translate([pp_aft]), line(blae, [pp_aft])] 94 | bottom_aft_plane = face bottom_aft_plane_contour, true 95 | faces << bottom_aft_plane 96 | 97 | # ボトム面(フォア) 98 | bottom_fore_plane_contour = wire [bdflf, para_bl.translate([pp_fore]), line(blfe, [pp_fore])] 99 | faces << face(bottom_fore_plane_contour, true) 100 | 101 | # サイド面(アフト) 102 | side_aft_plane_contour = wire [sdfla, para_sl.translate([pp_aft]), line([pp_aft,b2,d],sdfpa)] 103 | faces << face(side_aft_plane_contour, true) 104 | 105 | # サイド面(フォア) 106 | side_fore_plane_contour = wire [sdflf, para_sl.translate([pp_fore]), line([pp_fore,b2,d],sdfpf)] 107 | faces << face(side_fore_plane_contour, true) 108 | 109 | # トランサム面 110 | transom_plane_contour = wire [tsom_tl, tsom_bl, line([ae,0,d], [ae,0,d*2.0/3.0])], 0.01 111 | faces << face(transom_plane_contour, true) 112 | 113 | if false 114 | # 上甲板面 115 | updk_plane_contour = wire [tsom_tl, gunnela, line(sdfpa, sdfpf), gunnelf, line([xtop_max,0,d], [ae, 0, d]) ], 0.01 116 | faces << face(updk_plane_contour, true) 117 | 118 | # CL面 119 | cl_plane_contour = wire [aft_profile, line([ae, 0, d], [xtop_max, 0, d]), fore_profile, line(blfe, blae) ], 0.01 120 | faces << face(cl_plane_contour, true) 121 | end 122 | 123 | # アフト曲面 124 | fa = Filler.new 125 | [tsom_bl, gunnela, sdfla, bilge.translate([pp_aft]), bdfla, tp4, tp3, tp2].each do |edge| 126 | fa.add_bound edge, 0 127 | end 128 | fa.build 129 | if fa.done? 130 | faces << fa.face 131 | end 132 | 133 | # フォア曲面 134 | ff = Filler.new 135 | [bdflf, bilge.translate([pp_fore]), sdflf, gunnelf, fore_profile].each do |edge| 136 | ff.add_bound edge, 0 137 | end 138 | ff.build 139 | if ff.done? 140 | faces << ff.face 141 | end 142 | 143 | # shell = sewing faces, 0.01 144 | # solid = solid shell 145 | 146 | # 出力 147 | comp = Compound.new lines 148 | save_brep comp, "curves.brep" 149 | 150 | comp = Compound.new faces 151 | save_brep comp, "faces.brep" 152 | 153 | -------------------------------------------------------------------------------- /src/curve/bscurve.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * bscurve.cpp 3 | */ 4 | 5 | #include "curve.h" 6 | 7 | mrb_value siren_bscurve_new(mrb_state* mrb, const handle* curve) 8 | { 9 | struct RClass* mod_siren = mrb_module_get(mrb, "Siren"); 10 | mrb_value obj; 11 | obj = mrb_instance_alloc(mrb, mrb_const_get(mrb, mrb_obj_value(mod_siren), mrb_intern_lit(mrb, "BSCurve"))); 12 | void* p = mrb_malloc(mrb, sizeof(handle)); 13 | handle* hgcurve = new(p) handle(); 14 | *hgcurve = *curve; 15 | DATA_PTR(obj) = hgcurve; 16 | DATA_TYPE(obj) = &siren_bscurve_type; 17 | return obj; 18 | } 19 | 20 | handle siren_bscurve_get(mrb_state* mrb, mrb_value self) 21 | { 22 | handle hgc 23 | = *static_cast*>(mrb_get_datatype(mrb, self, &siren_bscurve_type)); 24 | if (hgc.IsNull()) { mrb_raise(mrb, E_RUNTIME_ERROR, "The geometry type is not Curve."); } 25 | handle bscurve = handle::DownCast(hgc); 26 | if (bscurve.IsNull()) { mrb_raise(mrb, E_RUNTIME_ERROR, "The geometry type is not BSCurve."); } 27 | return bscurve; 28 | } 29 | 30 | bool siren_bscurve_install(mrb_state* mrb, struct RClass* mod_siren) 31 | { 32 | struct RClass* cls_curve = siren_curve_rclass(mrb); 33 | struct RClass* cls_bscurve = mrb_define_class_under(mrb, mod_siren, "BSCurve", cls_curve); 34 | MRB_SET_INSTANCE_TT(cls_bscurve, MRB_TT_DATA); 35 | mrb_define_method(mrb, cls_bscurve, "initialize", siren_bscurve_init, MRB_ARGS_REQ(4) | MRB_ARGS_OPT(1)); 36 | mrb_define_method(mrb, cls_bscurve, "degree", siren_bscurve_degree, MRB_ARGS_NONE()); 37 | mrb_define_method(mrb, cls_bscurve, "knots", siren_bscurve_knots, MRB_ARGS_NONE()); 38 | mrb_define_method(mrb, cls_bscurve, "mults", siren_bscurve_mults, MRB_ARGS_NONE()); 39 | mrb_define_method(mrb, cls_bscurve, "poles", siren_bscurve_poles, MRB_ARGS_NONE()); 40 | mrb_define_method(mrb, cls_bscurve, "weights", siren_bscurve_weights, MRB_ARGS_NONE()); 41 | return true; 42 | } 43 | 44 | mrb_value siren_bscurve_init(mrb_state* mrb, mrb_value self) 45 | { 46 | mrb_int d; 47 | mrb_value ks, ms, ps, ws; 48 | int argc = mrb_get_args(mrb, "iAAA|A", &d, &ks, &ms, &ps, &ws); 49 | 50 | int plen = mrb_ary_len(mrb, ps); 51 | 52 | TColgp_Array1OfPnt poles(0, plen - 1); 53 | TColStd_Array1OfReal weights(0, plen - 1); 54 | for (int i=0; i < plen; i++) { 55 | poles.SetValue(i, siren_ary_to_pnt(mrb, mrb_ary_ref(mrb, ps, i))); 56 | if (argc >= 5) { 57 | mrb_value w = mrb_ary_ref(mrb, ws, i); 58 | weights.SetValue(i, mrb_float(w)); 59 | } 60 | else { 61 | weights.SetValue(i, 1.0); 62 | } 63 | } 64 | 65 | int klen = mrb_ary_len(mrb, ks); 66 | TColStd_Array1OfReal knots(0, klen - 1); 67 | TColStd_Array1OfInteger mults(0, klen - 1); 68 | 69 | for (int i=0; i < klen; i++) { 70 | mrb_value knot = mrb_ary_ref(mrb, ks, i); 71 | knots.SetValue(i, mrb_float(knot)); 72 | mrb_value mult = mrb_ary_ref(mrb, ms, i); 73 | mults.SetValue(i, (Standard_Integer)mrb_fixnum(mult)); 74 | } 75 | 76 | handle curve 77 | = new Geom_BSplineCurve(poles, weights, knots, mults, d, Standard_False); 78 | 79 | // initialize において self は既に mrb_instance_alloc されているので、 80 | // DATA_PTR と DATA_TYPE のみを設定する 81 | void* p = mrb_malloc(mrb, sizeof(handle)); 82 | handle* hgcurve = new(p) handle(); 83 | *hgcurve = curve; 84 | DATA_PTR(self) = hgcurve; 85 | DATA_TYPE(self) = &siren_bscurve_type; 86 | return self; 87 | } 88 | 89 | mrb_value siren_bscurve_degree(mrb_state* mrb, mrb_value self) 90 | { 91 | handle curve = siren_bscurve_get(mrb, self); 92 | return mrb_fixnum_value((int)curve->Degree()); 93 | } 94 | 95 | mrb_value siren_bscurve_knots(mrb_state* mrb, mrb_value self) 96 | { 97 | handle curve = siren_bscurve_get(mrb, self); 98 | mrb_value knots = mrb_ary_new(mrb); 99 | for (int i = 1; i <= curve->NbKnots(); i++) { 100 | mrb_ary_push(mrb, knots, mrb_float_value(mrb, curve->Knot(i))); 101 | } 102 | return knots; 103 | } 104 | 105 | mrb_value siren_bscurve_mults(mrb_state* mrb, mrb_value self) 106 | { 107 | handle curve = siren_bscurve_get(mrb, self); 108 | mrb_value mults = mrb_ary_new(mrb); 109 | for (int i = 1; i <= curve->NbKnots(); i++) { 110 | mrb_ary_push(mrb, mults, mrb_fixnum_value(curve->Multiplicity(i))); 111 | } 112 | return mults; 113 | } 114 | 115 | mrb_value siren_bscurve_poles(mrb_state* mrb, mrb_value self) 116 | { 117 | handle curve = siren_bscurve_get(mrb, self); 118 | mrb_value poles = mrb_ary_new(mrb); 119 | for (int i = 1; i <= curve->NbPoles(); i++) { 120 | mrb_value item = mrb_ary_new(mrb); 121 | mrb_ary_push(mrb, item, mrb_float_value(mrb, curve->Pole(i).X())); 122 | mrb_ary_push(mrb, item, mrb_float_value(mrb, curve->Pole(i).Y())); 123 | mrb_ary_push(mrb, item, mrb_float_value(mrb, curve->Pole(i).Z())); 124 | mrb_ary_push(mrb, poles, item); 125 | } 126 | return poles; 127 | } 128 | 129 | mrb_value siren_bscurve_weights(mrb_state* mrb, mrb_value self) 130 | { 131 | handle curve = siren_bscurve_get(mrb, self); 132 | mrb_value weights = mrb_ary_new(mrb); 133 | for (int i = 1; i <= curve->NbPoles(); i++) { 134 | mrb_ary_push(mrb, weights, mrb_float_value(mrb, curve->Weight(i))); 135 | } 136 | return weights; 137 | } 138 | 139 | -------------------------------------------------------------------------------- /src/shape/wire.cpp: -------------------------------------------------------------------------------- 1 | #include "shape/wire.h" 2 | 3 | mrb_value siren_wire_new(mrb_state* mrb, const TopoDS_Shape* src) 4 | { 5 | mrb_value obj; 6 | struct RClass* cls_shape = siren_shape_rclass(mrb); 7 | struct RClass* mod_siren = mrb_module_get(mrb, "Siren"); 8 | obj = mrb_instance_alloc(mrb, mrb_const_get(mrb, mrb_obj_value(mod_siren), mrb_intern_lit(mrb, "Wire"))); 9 | void* p = mrb_malloc(mrb, sizeof(TopoDS_Shape)); 10 | TopoDS_Shape* inner = new(p) TopoDS_Shape(); 11 | *inner = *src; // Copy to inner native member 12 | DATA_PTR(obj) = const_cast(inner); 13 | DATA_TYPE(obj) = &siren_wire_type; 14 | return obj; 15 | } 16 | 17 | TopoDS_Wire siren_wire_get(mrb_state* mrb, mrb_value self) 18 | { 19 | TopoDS_Shape* shape = static_cast(mrb_get_datatype(mrb, self, &siren_wire_type)); 20 | TopoDS_Wire wire = TopoDS::Wire(*shape); 21 | if (wire.IsNull()) { mrb_raise(mrb, E_RUNTIME_ERROR, "The geometry type is not Wire."); } 22 | return wire; 23 | } 24 | 25 | bool siren_wire_install(mrb_state* mrb, struct RClass* mod_siren) 26 | { 27 | struct RClass* cls_shape = siren_shape_rclass(mrb); 28 | struct RClass* cls_wire = mrb_define_class_under(mrb, mod_siren, "Wire", cls_shape); 29 | MRB_SET_INSTANCE_TT(cls_wire, MRB_TT_DATA); 30 | mrb_define_method(mrb, cls_wire, "initialize", siren_shape_init, MRB_ARGS_NONE()); 31 | mrb_define_method(mrb, cls_wire, "ordered_edges", siren_wire_ordered_edges, MRB_ARGS_NONE()); 32 | mrb_define_method(mrb, cls_wire, "curves", siren_wire_curves, MRB_ARGS_NONE()); 33 | 34 | auto obj_wire = mrb_obj_ptr(siren_wire_obj(mrb)); 35 | mrb_define_singleton_method(mrb, obj_wire, "make", siren_wire_make, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(1)); 36 | mrb_define_singleton_method(mrb, obj_wire, "join", siren_wire_make, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(1)); 37 | return true; 38 | } 39 | 40 | struct RClass* siren_wire_rclass(mrb_state* mrb) 41 | { 42 | struct RClass* mod_siren = mrb_module_get(mrb, "Siren"); 43 | return mrb_class_ptr(mrb_const_get(mrb, mrb_obj_value(mod_siren), mrb_intern_lit(mrb, "Wire"))); 44 | } 45 | 46 | mrb_value siren_wire_ordered_edges(mrb_state* mrb, mrb_value self) 47 | { 48 | TopoDS_Wire wire = siren_wire_get(mrb, self); 49 | mrb_value res = mrb_ary_new(mrb); 50 | for (BRepTools_WireExplorer exp(wire); exp.More(); exp.Next()) { 51 | TopoDS_Edge e = exp.Current(); 52 | mrb_ary_push(mrb, res, siren_shape_new(mrb, e)); 53 | } 54 | return res; 55 | } 56 | 57 | mrb_value siren_wire_curves(mrb_state* mrb, mrb_value self) 58 | { 59 | mrb_value res = mrb_ary_new(mrb); 60 | mrb_value edges = mrb_funcall(mrb, self, "edges", 0); 61 | for (int i = 0; i < mrb_ary_len(mrb, edges); i++) { 62 | mrb_value edge = mrb_ary_ref(mrb, edges, i); 63 | mrb_value curve = mrb_funcall(mrb, edge, "curve", 0); 64 | mrb_ary_push(mrb, res, curve); 65 | } 66 | return res; 67 | } 68 | 69 | mrb_value siren_wire_obj(mrb_state* mrb) 70 | { 71 | struct RClass* mod_siren = mrb_module_get(mrb, "Siren"); 72 | return mrb_const_get(mrb, mrb_obj_value(mod_siren), mrb_intern_lit(mrb, "Wire")); 73 | } 74 | 75 | mrb_value siren_wire_make(mrb_state* mrb, mrb_value self) 76 | { 77 | mrb_value objs; 78 | mrb_float tol; 79 | int argc = mrb_get_args(mrb, "A|f", &objs, &tol); 80 | BRepBuilderAPI_MakeWire api; 81 | #ifdef USE_WIRE_FIX 82 | ShapeFix_Wire sfw; 83 | handle wd = new ShapeExtend_WireData(); 84 | ShapeFix_ShapeTolerance FTol; 85 | int osize = mrb_ary_len(mrb, objs); 86 | for (int i = 0; i < osize ; i++) { 87 | mrb_value obj = mrb_ary_ref(mrb, objs, i); 88 | TopoDS_Shape* s = siren_shape_get(mrb, obj); 89 | if (s->IsNull()) { 90 | continue; 91 | } 92 | TopExp_Explorer exp(*s, TopAbs_EDGE); 93 | for (; exp.More(); exp.Next()) { 94 | wd->Add(TopoDS::Edge(exp.Current())); 95 | } 96 | } 97 | if (wd->NbEdges() == 0) { 98 | return mrb_nil_value(); 99 | } 100 | sfw.Load(wd); 101 | sfw.Perform(); 102 | for (int i = 1; i <= sfw.NbEdges(); i ++) { 103 | TopoDS_Edge e = sfw.WireData()->Edge(i); 104 | FTol.SetTolerance(e, argc == 1 ? 0.01 : tol, TopAbs_VERTEX); 105 | api.Add(e); 106 | } 107 | return siren_shape_new(mrb, api.Shape()); 108 | #else 109 | ShapeFix_ShapeTolerance fixtol; 110 | bool has_tol = argc == 2; 111 | for (int i = 0; i < mrb_ary_len(mrb, objs); i++) { 112 | TopoDS_Shape* shape = siren_shape_get(mrb, mrb_ary_ref(mrb, objs, i)); 113 | if (shape->ShapeType() == TopAbs_EDGE) { 114 | if (has_tol) { 115 | fixtol.SetTolerance(*shape, tol, TopAbs_VERTEX); 116 | } 117 | api.Add(TopoDS::Edge(*shape)); 118 | } 119 | else if (shape->ShapeType() == TopAbs_WIRE) { 120 | if (has_tol) { 121 | fixtol.SetTolerance(*shape, tol, TopAbs_VERTEX); 122 | fixtol.SetTolerance(*shape, tol, TopAbs_EDGE); 123 | } 124 | api.Add(TopoDS::Wire(*shape)); 125 | } 126 | } 127 | api.Build(); 128 | if (!api.IsDone()) { 129 | switch (api.Error()) { 130 | case BRepBuilderAPI_EmptyWire: 131 | mrb_raise(mrb, E_ARGUMENT_ERROR, "Failed to make a wire. (Empty wire)"); 132 | break; 133 | case BRepBuilderAPI_DisconnectedWire: 134 | mrb_raise(mrb, E_ARGUMENT_ERROR, "Failed to make a wire. (Disconnected wire)"); 135 | break; 136 | case BRepBuilderAPI_NonManifoldWire: 137 | mrb_raise(mrb, E_ARGUMENT_ERROR, "Failed to make a wire. (Non manifold wire)"); 138 | break; 139 | default: break; 140 | } 141 | } 142 | #endif 143 | return siren_wire_new(mrb, &api.Wire()); 144 | } 145 | -------------------------------------------------------------------------------- /src/filler.cpp: -------------------------------------------------------------------------------- 1 | #include "filler.h" 2 | 3 | BRepFill_Filling* siren_filler_get(mrb_state* mrb, mrb_value obj) 4 | { 5 | return static_cast(mrb_get_datatype(mrb, obj, &siren_filler_type)); 6 | } 7 | 8 | bool siren_filler_install(mrb_state* mrb, struct RClass* mod_siren) 9 | { 10 | struct RClass* cls_filler = mrb_define_class_under(mrb, mod_siren, "Filler", mrb->object_class); 11 | MRB_SET_INSTANCE_TT(cls_filler, MRB_TT_DATA); 12 | mrb_define_method(mrb, cls_filler, "initialize", siren_filler_init, MRB_ARGS_OPT(10)); 13 | mrb_define_method(mrb, cls_filler, "add_bound", siren_filler_add_bound, MRB_ARGS_REQ(2)); 14 | mrb_define_method(mrb, cls_filler, "add", siren_filler_add, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(1)); 15 | mrb_define_method(mrb, cls_filler, "build", siren_filler_build, MRB_ARGS_NONE()); 16 | mrb_define_method(mrb, cls_filler, "done?", siren_filler_is_done, MRB_ARGS_NONE()); 17 | mrb_define_method(mrb, cls_filler, "face", siren_filler_face, MRB_ARGS_NONE()); 18 | mrb_define_method(mrb, cls_filler, "g0error", siren_filler_g0error, MRB_ARGS_OPT(1)); 19 | mrb_define_method(mrb, cls_filler, "g1error", siren_filler_g1error, MRB_ARGS_OPT(1)); 20 | mrb_define_method(mrb, cls_filler, "g2error", siren_filler_g2error, MRB_ARGS_OPT(1)); 21 | return true; 22 | } 23 | 24 | mrb_value siren_filler_init(mrb_state* mrb, mrb_value self) 25 | { 26 | mrb_int degree, nbptsoncur, nbiter; 27 | mrb_bool anisotropie; 28 | mrb_float tol2d, tol3d, tolang, tolcurv; 29 | mrb_int maxdeg, maxsegs; 30 | int argc = mrb_get_args(mrb, "|iiibffffii", 31 | °ree, &nbptsoncur, &nbiter, &anisotropie, 32 | &tol2d, &tol3d, &tolang, &tolcurv, &maxdeg, &maxsegs); 33 | 34 | void* p = mrb_malloc(mrb, sizeof(BRepFill_Filling)); 35 | BRepFill_Filling* inner = nullptr; 36 | 37 | switch (argc) { 38 | case 1: 39 | inner = new(p) BRepFill_Filling(degree); 40 | break; 41 | case 2: 42 | inner = new(p) BRepFill_Filling(degree, nbptsoncur); 43 | break; 44 | case 3: 45 | inner = new(p) BRepFill_Filling(degree, nbptsoncur, nbiter); 46 | break; 47 | case 4: 48 | inner = new(p) BRepFill_Filling(degree, nbptsoncur, nbiter, anisotropie); 49 | break; 50 | case 5: 51 | inner = new(p) BRepFill_Filling(degree, nbptsoncur, nbiter, anisotropie, 52 | tol2d); 53 | break; 54 | case 6: 55 | inner = new(p) BRepFill_Filling(degree, nbptsoncur, nbiter, anisotropie, 56 | tol2d, tol3d); 57 | break; 58 | case 7: 59 | inner = new(p) BRepFill_Filling(degree, nbptsoncur, nbiter, anisotropie, 60 | tol2d, tol3d, tolang); 61 | break; 62 | case 8: 63 | inner = new(p) BRepFill_Filling(degree, nbptsoncur, nbiter, anisotropie, 64 | tol2d, tol3d, tolang, tolcurv); 65 | break; 66 | case 9: 67 | inner = new(p) BRepFill_Filling(degree, nbptsoncur, nbiter, anisotropie, 68 | tol2d, tol3d, tolang, tolcurv, maxdeg); 69 | break; 70 | case 10: 71 | inner = new(p) BRepFill_Filling(degree, nbptsoncur, nbiter, anisotropie, 72 | tol2d, tol3d, tolang, tolcurv, maxdeg, maxsegs); 73 | break; 74 | default: 75 | inner = new(p) BRepFill_Filling(); 76 | break; 77 | } 78 | 79 | DATA_PTR(self) = inner; 80 | DATA_TYPE(self) = &siren_filler_type; 81 | return self; 82 | } 83 | 84 | void siren_filler_final(mrb_state* mrb, void* p) 85 | { 86 | BRepFill_Filling* pp = static_cast(p); 87 | mrb_free(mrb, pp); 88 | } 89 | 90 | mrb_value siren_filler_add_bound(mrb_state* mrb, mrb_value self) 91 | { 92 | mrb_value edge; 93 | mrb_int order; 94 | int argc = mrb_get_args(mrb, "oi", &edge, &order); 95 | TopoDS_Shape* s = siren_shape_get(mrb, edge); 96 | TopoDS_Edge e = TopoDS::Edge(*s); 97 | siren_filler_get(mrb, self)->Add(e, (GeomAbs_Shape)order, 98 | /* IsBound= */ Standard_True); 99 | return mrb_nil_value(); 100 | } 101 | 102 | mrb_value siren_filler_add(mrb_state* mrb, mrb_value self) 103 | { 104 | mrb_value obj; 105 | mrb_int order; 106 | int argc = mrb_get_args(mrb, "o|i", &obj, &order); 107 | if (argc == 2) { 108 | TopoDS_Shape* s = siren_shape_get(mrb, obj); 109 | TopoDS_Edge e = TopoDS::Edge(*s); 110 | siren_filler_get(mrb, self)->Add(e, (GeomAbs_Shape)order, 111 | /* IsBound= */ Standard_False); 112 | } 113 | else { 114 | gp_Pnt pnt = siren_ary_to_pnt(mrb, obj); 115 | siren_filler_get(mrb, self)->Add(pnt); 116 | } 117 | return mrb_nil_value(); 118 | } 119 | 120 | mrb_value siren_filler_build(mrb_state* mrb, mrb_value self) 121 | { 122 | siren_filler_get(mrb, self)->Build(); 123 | return mrb_nil_value(); 124 | } 125 | 126 | mrb_value siren_filler_is_done(mrb_state* mrb, mrb_value self) 127 | { 128 | return siren_filler_get(mrb, self)->IsDone() == Standard_True ? 129 | mrb_true_value() : mrb_false_value(); 130 | } 131 | 132 | mrb_value siren_filler_face(mrb_state* mrb, mrb_value self) 133 | { 134 | TopoDS_Face f = siren_filler_get(mrb, self)->Face(); 135 | return siren_shape_new(mrb, f); 136 | } 137 | 138 | mrb_value siren_filler_g0error(mrb_state* mrb, mrb_value self) 139 | { 140 | mrb_int index; 141 | int argc = mrb_get_args(mrb, "|i", &index); 142 | Standard_Real value; 143 | if (argc) { 144 | value = siren_filler_get(mrb, self)->G0Error(index); 145 | } 146 | else { 147 | value = siren_filler_get(mrb, self)->G0Error(); 148 | } 149 | return mrb_float_value(mrb, value); 150 | } 151 | 152 | mrb_value siren_filler_g1error(mrb_state* mrb, mrb_value self) 153 | { 154 | mrb_int index; 155 | int argc = mrb_get_args(mrb, "|i", &index); 156 | Standard_Real value; 157 | if (argc) { 158 | value = siren_filler_get(mrb, self)->G1Error(index); 159 | } 160 | else { 161 | value = siren_filler_get(mrb, self)->G1Error(); 162 | } 163 | return mrb_float_value(mrb, value); 164 | } 165 | 166 | mrb_value siren_filler_g2error(mrb_state* mrb, mrb_value self) 167 | { 168 | mrb_int index; 169 | int argc = mrb_get_args(mrb, "|i", &index); 170 | Standard_Real value; 171 | if (argc) { 172 | value = siren_filler_get(mrb, self)->G2Error(index); 173 | } 174 | else { 175 | value = siren_filler_get(mrb, self)->G2Error(); 176 | } 177 | return mrb_float_value(mrb, value); 178 | } 179 | 180 | -------------------------------------------------------------------------------- /examples/view/event.js: -------------------------------------------------------------------------------- 1 | var shift = false; 2 | 3 | // Get objects by mouse position 4 | function get_objs(e) { 5 | var rect = e.target.getBoundingClientRect(); 6 | var mouseX = e.clientX - rect.left; 7 | var mouseY = e.clientY - rect.top; 8 | mouseX = (mouseX / w) * 2 - 1; 9 | mouseY = -(mouseY / h) * 2 + 1; 10 | var pos = new THREE.Vector3(mouseX, mouseY, 1); 11 | pos.unproject(camera); 12 | var ray = new THREE.Raycaster(camera.position, pos.sub(camera.position).normalize()); 13 | return ray.intersectObjects(models); 14 | } 15 | 16 | // Key events 17 | 18 | window.addEventListener('keydown', function(e) { 19 | down = e.keyCode; 20 | switch ( event.keyCode ) { 21 | case 81: // Q 22 | control.setSpace( control.space === "local" ? "world" : "local" ); 23 | break; 24 | case 16: // shift 25 | shift = true; 26 | break; 27 | case 17: // Ctrl 28 | control.setTranslationSnap( 100 ); 29 | control.setRotationSnap( THREE.Math.degToRad( 15 ) ); 30 | break; 31 | case 87: // W 32 | control.setMode( "translate" ); 33 | break; 34 | case 69: // E 35 | control.setMode( "rotate" ); 36 | break; 37 | case 82: // R 38 | control.setMode( "scale" ); 39 | break; 40 | case 187: 41 | case 107: // +, =, num+ 42 | control.setSize( control.size + 0.1 ); 43 | break; 44 | case 189: 45 | case 109: // -, _, num- 46 | control.setSize( Math.max( control.size - 0.1, 0.1 ) ); 47 | break; 48 | } 49 | }, false); 50 | 51 | window.addEventListener('keyup', function(e) { 52 | down = 0; 53 | switch ( event.keyCode ) { 54 | case 16: // shift 55 | shift = false; 56 | break; 57 | case 17: // Ctrl 58 | control.setTranslationSnap( null ); 59 | control.setRotationSnap( null ); 60 | break; 61 | } 62 | }, false); 63 | 64 | // Mouse events 65 | 66 | var down = false; 67 | var drag = false; 68 | 69 | window.addEventListener('mousedown', function(e) { 70 | down = true; 71 | }, false); 72 | 73 | window.addEventListener("mousemove", function(e) { 74 | drag = down; 75 | }, false); 76 | 77 | window.addEventListener('mouseup', function(e) { 78 | var panel = document.getElementById("panel"); 79 | if (e.clientX < panel.clientWidth && e.clientY < panel.clientHeight) { 80 | down = false; 81 | return; 82 | } 83 | if (!drag && down) { 84 | var objs = get_objs(e); 85 | if (!shift) { 86 | control.detach(); 87 | } 88 | if (objs.length > 0) { 89 | control.attach(objs[0].object); 90 | } 91 | } 92 | down = false; 93 | }, false); 94 | 95 | // Button events 96 | 97 | document.getElementById('plane').addEventListener('click', function(e) { 98 | var geom = new THREE.PlaneGeometry(10, 10, 1, 1); 99 | var mesh = new THREE.Mesh(geom, material_face); 100 | scene.add(mesh); 101 | models.push(mesh); 102 | control.detach(); 103 | control.attach(mesh); 104 | log('[plane] Done.'); 105 | }, false); 106 | 107 | document.getElementById('box').addEventListener('click', function(e) { 108 | var geom = new THREE.BoxGeometry(10, 10, 10); 109 | var mesh = new THREE.Mesh(geom, material_face); 110 | scene.add(mesh); 111 | models.push(mesh); 112 | control.detach(); 113 | control.attach(mesh); 114 | log('[box] Done.'); 115 | }, false); 116 | 117 | document.getElementById('cone').addEventListener('click', function(e) { 118 | var geom = new THREE.ConeGeometry(10, 30, 32); 119 | var mesh = new THREE.Mesh(geom, material_face); 120 | scene.add(mesh); 121 | models.push(mesh); 122 | control.detach(); 123 | control.attach(mesh); 124 | log('[cone] Done.'); 125 | }, false); 126 | 127 | document.getElementById('cylinder').addEventListener('click', function(e) { 128 | var geom = new THREE.CylinderGeometry(10, 10, 30, 32); 129 | var mesh = new THREE.Mesh(geom, material_face); 130 | scene.add(mesh); 131 | models.push(mesh); 132 | control.detach(); 133 | control.attach(mesh); 134 | log('[cylinder] Done.'); 135 | }, false); 136 | 137 | document.getElementById('sphere').addEventListener('click', function(e) { 138 | var geom = new THREE.SphereGeometry(10, 32, 32); 139 | var mesh = new THREE.Mesh(geom, material_face); 140 | scene.add(mesh); 141 | models.push(mesh); 142 | control.detach(); 143 | control.attach(mesh); 144 | log('[sphere] Done.'); 145 | }, false); 146 | 147 | document.getElementById('torus').addEventListener('click', function(e) { 148 | var geom = new THREE.TorusGeometry(20, 5, 16, 100); 149 | var mesh = new THREE.Mesh(geom, material_face); 150 | scene.add(mesh); 151 | models.push(mesh); 152 | control.detach(); 153 | control.attach(mesh); 154 | log('[torus] Done.'); 155 | }, false); 156 | 157 | document.getElementById('duplicate').addEventListener('click', function(e) { 158 | if (typeof(control.object) == 'undefined') { 159 | log('[duplicate] No selected object.', true); 160 | return; 161 | } 162 | var mesh = control.object.clone(); 163 | scene.add(mesh); 164 | models.push(mesh); 165 | control.detach(); 166 | control.attach(mesh); 167 | log('[duplicate] Done.'); 168 | }, true); 169 | 170 | document.getElementById('remove').addEventListener('click', function(e) { 171 | if (typeof(control.object) == 'undefined') { 172 | log('[remove] No selected object.', true); 173 | return; 174 | } 175 | var mesh = control.object; 176 | scene.remove(mesh); 177 | models = models.filter(function (e, i, a) { 178 | return e != mesh; 179 | }); 180 | control.detach(); 181 | mesh.geometry.dispose(); 182 | log('[remove] Done.'); 183 | }, true); 184 | 185 | document.getElementById('boundbox').addEventListener('click', function(e) { 186 | if (typeof(control.object) == 'undefined') { 187 | log('[boundbox] No selected object.', true); 188 | return; 189 | } 190 | var geom = control.object.geometry; 191 | geom.computeBoundingBox(); 192 | var bnd = geom.boundingBox; 193 | log('[boundbox] min:' + bnd.min.x + ',' + bnd.min.y + ',' + bnd.min.z); 194 | log('[boundbox] max:' + bnd.max.x + ',' + bnd.max.y + ',' + bnd.max.z); 195 | log('[boundsphere] R:' + geom.boundingSphere.radius); 196 | }, true); 197 | 198 | function log(msg, is_alert) { 199 | if (is_alert) { 200 | msg = '' + msg + ''; 201 | } 202 | var console = document.getElementById('log'); 203 | console.innerHTML = console.innerHTML + '
\n' + msg; 204 | console.scrollTop = console.scrollHeight; 205 | } 206 | 207 | -------------------------------------------------------------------------------- /src/curve/circle.cpp: -------------------------------------------------------------------------------- 1 | #include "curve.h" 2 | 3 | mrb_value siren_circle_new(mrb_state* mrb, const handle* curve) 4 | { 5 | struct RClass* mod_siren = mrb_module_get(mrb, "Siren"); 6 | mrb_value obj; 7 | obj = mrb_instance_alloc(mrb, mrb_const_get(mrb, mrb_obj_value(mod_siren), mrb_intern_lit(mrb, "Circle"))); 8 | void* p = mrb_malloc(mrb, sizeof(handle)); 9 | handle* hgcurve = new(p) handle(); 10 | *hgcurve = *curve; 11 | DATA_PTR(obj) = hgcurve; 12 | DATA_TYPE(obj) = &siren_circle_type; 13 | return obj; 14 | } 15 | 16 | handle siren_circle_get(mrb_state* mrb, mrb_value self) 17 | { 18 | handle hgc = *static_cast*>(mrb_get_datatype(mrb, self, &siren_circle_type)); 19 | if (hgc.IsNull()) { mrb_raise(mrb, E_RUNTIME_ERROR, "The geometry type is not Curve."); } 20 | handle circle = handle::DownCast(hgc); 21 | if (circle.IsNull()) { mrb_raise(mrb, E_RUNTIME_ERROR, "The geometry type is not Circle."); } 22 | return circle; 23 | } 24 | 25 | bool siren_circle_install(mrb_state* mrb, struct RClass* mod_siren) 26 | { 27 | struct RClass* cls_curve = siren_curve_rclass(mrb); 28 | struct RClass* cls_circle = mrb_define_class_under(mrb, mod_siren, "Circle", mrb->object_class); 29 | MRB_SET_INSTANCE_TT(cls_circle, MRB_TT_DATA); 30 | mrb_define_method(mrb, cls_circle, "initialize", siren_curve_init, MRB_ARGS_NONE()); 31 | 32 | mrb_define_method(mrb, cls_circle, "radius", siren_circle_radius, MRB_ARGS_NONE()); 33 | mrb_define_method(mrb, cls_circle, "radius=", siren_circle_radius_set, MRB_ARGS_REQ(1)); 34 | mrb_define_method(mrb, cls_circle, "center", siren_circle_center, MRB_ARGS_NONE()); 35 | mrb_define_method(mrb, cls_circle, "center=", siren_circle_center_set, MRB_ARGS_REQ(1)); 36 | mrb_define_method(mrb, cls_circle, "area", siren_circle_area, MRB_ARGS_NONE()); 37 | mrb_define_method(mrb, cls_circle, "length", siren_circle_length, MRB_ARGS_NONE()); 38 | mrb_define_method(mrb, cls_circle, "normal", siren_circle_normal, MRB_ARGS_NONE()); 39 | mrb_define_method(mrb, cls_circle, "normal=", siren_circle_normal_set, MRB_ARGS_REQ(1)); 40 | mrb_define_method(mrb, cls_circle, "dir", siren_circle_dir, MRB_ARGS_NONE()); 41 | mrb_define_method(mrb, cls_circle, "dir=", siren_circle_dir_set, MRB_ARGS_REQ(1)); 42 | mrb_define_method(mrb, cls_circle, "dist", siren_circle_dist, MRB_ARGS_REQ(1)); 43 | mrb_define_method(mrb, cls_circle, "distdist", siren_circle_distdist, MRB_ARGS_REQ(1)); 44 | mrb_define_method(mrb, cls_circle, "contain", siren_circle_contain, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(1)); 45 | return true; 46 | } 47 | 48 | mrb_value siren_circle_radius(mrb_state* mrb, mrb_value self) 49 | { 50 | Standard_Real r = siren_circle_get(mrb, self)->Radius(); 51 | return mrb_float_value(mrb, r); 52 | } 53 | 54 | mrb_value siren_circle_radius_set(mrb_state* mrb, mrb_value self) 55 | { 56 | mrb_float r; 57 | int argc = mrb_get_args(mrb, "f", &r); 58 | siren_circle_get(mrb, self)->SetRadius(r); 59 | return mrb_nil_value(); 60 | } 61 | 62 | mrb_value siren_circle_center(mrb_state* mrb, mrb_value self) 63 | { 64 | gp_Pnt center = siren_circle_get(mrb, self)->Circ().Location(); 65 | return siren_pnt_to_ary(mrb, center); 66 | } 67 | 68 | mrb_value siren_circle_center_set(mrb_state* mrb, mrb_value self) 69 | { 70 | mrb_value pos; 71 | int argc = mrb_get_args(mrb, "A", &pos); 72 | gp_Pnt p = siren_ary_to_pnt(mrb, pos); 73 | handle circle = siren_circle_get(mrb, self); 74 | gp_Circ circ = circle->Circ(); 75 | circ.SetLocation(p); 76 | circle->SetCirc(circ); 77 | return pos; 78 | } 79 | 80 | mrb_value siren_circle_area(mrb_state* mrb, mrb_value self) 81 | { 82 | handle circle = siren_circle_get(mrb, self); 83 | return mrb_float_value(mrb, circle->Circ().Area()); 84 | } 85 | 86 | mrb_value siren_circle_length(mrb_state* mrb, mrb_value self) 87 | { 88 | handle circle = siren_circle_get(mrb, self); 89 | return mrb_float_value(mrb, circle->Circ().Length()); 90 | } 91 | 92 | mrb_value siren_circle_normal(mrb_state* mrb, mrb_value self) 93 | { 94 | handle circle = siren_circle_get(mrb, self); 95 | // Returns the main axis of the circle. 96 | // It is the axis perpendicular to the plane of the circle, 97 | // passing through the "Location" point (center) of the circle. 98 | gp_Ax1 axis = circle->Circ().Axis(); 99 | return siren_dir_to_ary(mrb, axis.Direction()); 100 | } 101 | 102 | mrb_value siren_circle_normal_set(mrb_state* mrb, mrb_value self) 103 | { 104 | mrb_value norm; 105 | int argc = mrb_get_args(mrb, "A", &norm); 106 | gp_Dir dir = siren_ary_to_dir(mrb, norm); 107 | handle circle = siren_circle_get(mrb, self); 108 | gp_Circ circ = circle->Circ(); 109 | gp_Ax1 axis = circ.Axis(); 110 | axis.SetDirection(dir); 111 | circ.SetAxis(axis); 112 | circle->SetCirc(circ); 113 | return norm; 114 | } 115 | 116 | mrb_value siren_circle_dir(mrb_state* mrb, mrb_value self) 117 | { 118 | handle circle = siren_circle_get(mrb, self); 119 | gp_Ax1 axis = circle->Circ().XAxis(); 120 | return siren_dir_to_ary(mrb, axis.Direction()); 121 | } 122 | 123 | mrb_value siren_circle_dir_set(mrb_state* mrb, mrb_value self) 124 | { 125 | mrb_value val; 126 | int argc = mrb_get_args(mrb, "A", &val); 127 | gp_Dir dir = siren_ary_to_dir(mrb, val); 128 | handle circle = siren_circle_get(mrb, self); 129 | gp_Circ circ = circle->Circ(); 130 | gp_Ax2 axis; 131 | axis.SetAxis(circ.Axis()); 132 | axis.SetXDirection(dir); 133 | circ.SetPosition(axis); 134 | circle->SetCirc(circ); 135 | return val; 136 | } 137 | 138 | mrb_value siren_circle_dist(mrb_state* mrb, mrb_value self) 139 | { 140 | mrb_value pos; 141 | int argc = mrb_get_args(mrb, "A", &pos); 142 | gp_Pnt p = siren_ary_to_pnt(mrb, pos); 143 | handle circle = siren_circle_get(mrb, self); 144 | gp_Circ circ = circle->Circ(); 145 | return mrb_float_value(mrb, circ.Distance(p)); 146 | } 147 | 148 | mrb_value siren_circle_distdist(mrb_state* mrb, mrb_value self) 149 | { 150 | mrb_value pos; 151 | int argc = mrb_get_args(mrb, "A", &pos); 152 | gp_Pnt p = siren_ary_to_pnt(mrb, pos); 153 | handle circle = siren_circle_get(mrb, self); 154 | gp_Circ circ = circle->Circ(); 155 | return mrb_float_value(mrb, circ.SquareDistance(p)); 156 | } 157 | 158 | mrb_value siren_circle_contain(mrb_state* mrb, mrb_value self) 159 | { 160 | mrb_value pos; 161 | mrb_float lintol = 1.0e-7; 162 | int argc = mrb_get_args(mrb, "A|f", &pos, &lintol); 163 | gp_Pnt p = siren_ary_to_pnt(mrb, pos); 164 | handle circle = siren_circle_get(mrb, self); 165 | gp_Circ circ = circle->Circ(); 166 | return circ.Contains(p, lintol) ? mrb_true_value() : mrb_false_value(); 167 | } 168 | -------------------------------------------------------------------------------- /viewer/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | siren viewer 6 | 7 | 12 | 13 | 14 | 15 | 20 | 25 | 26 | 27 | 28 | 170 | 171 | -------------------------------------------------------------------------------- /doc/thirdparty-license/freetype.txt: -------------------------------------------------------------------------------- 1 | The FreeType Project LICENSE 2 | ---------------------------- 3 | 4 | 2006-Jan-27 5 | 6 | Copyright 1996-2002, 2006 by 7 | David Turner, Robert Wilhelm, and Werner Lemberg 8 | 9 | 10 | 11 | Introduction 12 | ============ 13 | 14 | The FreeType Project is distributed in several archive packages; 15 | some of them may contain, in addition to the FreeType font engine, 16 | various tools and contributions which rely on, or relate to, the 17 | FreeType Project. 18 | 19 | This license applies to all files found in such packages, and 20 | which do not fall under their own explicit license. The license 21 | affects thus the FreeType font engine, the test programs, 22 | documentation and makefiles, at the very least. 23 | 24 | This license was inspired by the BSD, Artistic, and IJG 25 | (Independent JPEG Group) licenses, which all encourage inclusion 26 | and use of free software in commercial and freeware products 27 | alike. As a consequence, its main points are that: 28 | 29 | o We don't promise that this software works. However, we will be 30 | interested in any kind of bug reports. (`as is' distribution) 31 | 32 | o You can use this software for whatever you want, in parts or 33 | full form, without having to pay us. (`royalty-free' usage) 34 | 35 | o You may not pretend that you wrote this software. If you use 36 | it, or only parts of it, in a program, you must acknowledge 37 | somewhere in your documentation that you have used the 38 | FreeType code. (`credits') 39 | 40 | We specifically permit and encourage the inclusion of this 41 | software, with or without modifications, in commercial products. 42 | We disclaim all warranties covering The FreeType Project and 43 | assume no liability related to The FreeType Project. 44 | 45 | 46 | Finally, many people asked us for a preferred form for a 47 | credit/disclaimer to use in compliance with this license. We thus 48 | encourage you to use the following text: 49 | 50 | """ 51 | Portions of this software are copyright © The FreeType 52 | Project (www.freetype.org). All rights reserved. 53 | """ 54 | 55 | Please replace with the value from the FreeType version you 56 | actually use. 57 | 58 | 59 | Legal Terms 60 | =========== 61 | 62 | 0. Definitions 63 | -------------- 64 | 65 | Throughout this license, the terms `package', `FreeType Project', 66 | and `FreeType archive' refer to the set of files originally 67 | distributed by the authors (David Turner, Robert Wilhelm, and 68 | Werner Lemberg) as the `FreeType Project', be they named as alpha, 69 | beta or final release. 70 | 71 | `You' refers to the licensee, or person using the project, where 72 | `using' is a generic term including compiling the project's source 73 | code as well as linking it to form a `program' or `executable'. 74 | This program is referred to as `a program using the FreeType 75 | engine'. 76 | 77 | This license applies to all files distributed in the original 78 | FreeType Project, including all source code, binaries and 79 | documentation, unless otherwise stated in the file in its 80 | original, unmodified form as distributed in the original archive. 81 | If you are unsure whether or not a particular file is covered by 82 | this license, you must contact us to verify this. 83 | 84 | The FreeType Project is copyright (C) 1996-2000 by David Turner, 85 | Robert Wilhelm, and Werner Lemberg. All rights reserved except as 86 | specified below. 87 | 88 | 1. No Warranty 89 | -------------- 90 | 91 | THE FREETYPE PROJECT IS PROVIDED `AS IS' WITHOUT WARRANTY OF ANY 92 | KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 93 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 94 | PURPOSE. IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS 95 | BE LIABLE FOR ANY DAMAGES CAUSED BY THE USE OR THE INABILITY TO 96 | USE, OF THE FREETYPE PROJECT. 97 | 98 | 2. Redistribution 99 | ----------------- 100 | 101 | This license grants a worldwide, royalty-free, perpetual and 102 | irrevocable right and license to use, execute, perform, compile, 103 | display, copy, create derivative works of, distribute and 104 | sublicense the FreeType Project (in both source and object code 105 | forms) and derivative works thereof for any purpose; and to 106 | authorize others to exercise some or all of the rights granted 107 | herein, subject to the following conditions: 108 | 109 | o Redistribution of source code must retain this license file 110 | (`FTL.TXT') unaltered; any additions, deletions or changes to 111 | the original files must be clearly indicated in accompanying 112 | documentation. The copyright notices of the unaltered, 113 | original files must be preserved in all copies of source 114 | files. 115 | 116 | o Redistribution in binary form must provide a disclaimer that 117 | states that the software is based in part of the work of the 118 | FreeType Team, in the distribution documentation. We also 119 | encourage you to put an URL to the FreeType web page in your 120 | documentation, though this isn't mandatory. 121 | 122 | These conditions apply to any software derived from or based on 123 | the FreeType Project, not just the unmodified files. If you use 124 | our work, you must acknowledge us. However, no fee need be paid 125 | to us. 126 | 127 | 3. Advertising 128 | -------------- 129 | 130 | Neither the FreeType authors and contributors nor you shall use 131 | the name of the other for commercial, advertising, or promotional 132 | purposes without specific prior written permission. 133 | 134 | We suggest, but do not require, that you use one or more of the 135 | following phrases to refer to this software in your documentation 136 | or advertising materials: `FreeType Project', `FreeType Engine', 137 | `FreeType library', or `FreeType Distribution'. 138 | 139 | As you have not signed this license, you are not required to 140 | accept it. However, as the FreeType Project is copyrighted 141 | material, only this license, or another one contracted with the 142 | authors, grants you the right to use, distribute, and modify it. 143 | Therefore, by using, distributing, or modifying the FreeType 144 | Project, you indicate that you understand and accept all the terms 145 | of this license. 146 | 147 | 4. Contacts 148 | ----------- 149 | 150 | There are two mailing lists related to FreeType: 151 | 152 | o freetype@nongnu.org 153 | 154 | Discusses general use and applications of FreeType, as well as 155 | future and wanted additions to the library and distribution. 156 | If you are looking for support, start in this list if you 157 | haven't found anything to help you in the documentation. 158 | 159 | o freetype-devel@nongnu.org 160 | 161 | Discusses bugs, as well as engine internals, design issues, 162 | specific licenses, porting, etc. 163 | 164 | Our home page can be found at 165 | 166 | http://www.freetype.org 167 | 168 | 169 | --- end of FTL.TXT --- 170 | --------------------------------------------------------------------------------