torqml 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +32 -0
  3. data/.yardopts +3 -0
  4. data/Gemfile +5 -0
  5. data/LICENSE +21 -0
  6. data/README.md +148 -0
  7. data/Rakefile +6 -0
  8. data/assets/images/capture.png +0 -0
  9. data/assets/images/configure.png +0 -0
  10. data/assets/images/edit.png +0 -0
  11. data/assets/images/play.png +0 -0
  12. data/assets/images/reload.png +0 -0
  13. data/assets/images/stop.png +0 -0
  14. data/assets/shapes/TQBox.obj +44 -0
  15. data/assets/shapes/TQCone.obj +169 -0
  16. data/assets/shapes/TQCylinder.obj +585 -0
  17. data/assets/shapes/TQSphere.obj +1497 -0
  18. data/assets/shapes/TQTorus.obj +3754 -0
  19. data/bin/torqml +12 -0
  20. data/examples/SerialLink/SerialLink.qml +35 -0
  21. data/examples/SerialLink/main.qml +29 -0
  22. data/examples/SerialLink/main_multi.qml +40 -0
  23. data/examples/Tutorial/MyModel.qml +34 -0
  24. data/examples/Tutorial/main_00_minimal.qml +10 -0
  25. data/examples/Tutorial/main_01_property.qml +15 -0
  26. data/examples/Tutorial/main_02_pose.qml +19 -0
  27. data/examples/Tutorial/main_03_link.qml +32 -0
  28. data/examples/Tutorial/main_04_importmodel.qml +7 -0
  29. data/examples/Tutorial/main_05_cameralight.qml +17 -0
  30. data/examples/Tutorial/main_06_animation.qml +18 -0
  31. data/examples/WheeledVehicle/WheeledVehicle.qml +62 -0
  32. data/examples/WheeledVehicle/data/maze2014student.dat +19 -0
  33. data/examples/WheeledVehicle/data/wheeledvehicle.csv +11712 -0
  34. data/examples/WheeledVehicle/main.qml +38 -0
  35. data/examples/WheeledVehicle/plugins/MazeWallGenerator/plugin.rb +68 -0
  36. data/examples/WheeledVehicle/plugins/MazeWallGenerator/qml/TorQML/Plugins/MazeWallGenerator/MazeHorizWall.qml +29 -0
  37. data/examples/WheeledVehicle/plugins/MazeWallGenerator/qml/TorQML/Plugins/MazeWallGenerator/MazeVertWall.qml +30 -0
  38. data/examples/WheeledVehicle/plugins/MazeWallGenerator/qml/TorQML/Plugins/MazeWallGenerator/MazeWallGenerator.qml +24 -0
  39. data/examples/WheeledVehicle/plugins/MazeWallGenerator/qml/TorQML/Plugins/MazeWallGenerator/qmldir +4 -0
  40. data/examples/WheeledVehicle/plugins/MazeWallGenerator/qml/TorQML/Plugins/MazeWallGenerator/wallAllocator.js +47 -0
  41. data/ext/TorQML/FrameGrabber/extconf.rb +45 -0
  42. data/ext/TorQML/FrameGrabber/framegrabber.cpp +36 -0
  43. data/ext/TorQML/FrameGrabber/framegrabber.pro +9 -0
  44. data/ext/TorQML/FrameGrabber/qmldir +2 -0
  45. data/lib/torqml.rb +47 -0
  46. data/lib/torqml/datasources.rb +12 -0
  47. data/lib/torqml/datasources/csvdatasource.rb +44 -0
  48. data/lib/torqml/datasources/datasource.rb +44 -0
  49. data/lib/torqml/datasources/lineardatasource.rb +47 -0
  50. data/lib/torqml/datasources/matrixdatasource.rb +37 -0
  51. data/lib/torqml/plugins.rb +44 -0
  52. data/lib/torqml/version.rb +6 -0
  53. data/plugins/DO_NOT_MODIFY_THIS_DIRECTORY +2 -0
  54. data/qml/TorQML/DataSources/TQCSVDataSource.qml +17 -0
  55. data/qml/TorQML/DataSources/TQLinearDataSource.qml +18 -0
  56. data/qml/TorQML/DataSources/qmldir +3 -0
  57. data/qml/TorQML/Shapes/TQAxis.qml +26 -0
  58. data/qml/TorQML/Shapes/TQBox.qml +11 -0
  59. data/qml/TorQML/Shapes/TQCone.qml +17 -0
  60. data/qml/TorQML/Shapes/TQCoordinate.qml +30 -0
  61. data/qml/TorQML/Shapes/TQCylinder.qml +17 -0
  62. data/qml/TorQML/Shapes/TQGrid.qml +36 -0
  63. data/qml/TorQML/Shapes/TQPrimitive.qml +33 -0
  64. data/qml/TorQML/Shapes/TQSphere.qml +18 -0
  65. data/qml/TorQML/Shapes/TQTorus.qml +18 -0
  66. data/qml/TorQML/Shapes/qmldir +10 -0
  67. data/qml/TorQML/TQModel.qml +9 -0
  68. data/qml/TorQML/Views/Dialogs/TQCaptureDialog.qml +197 -0
  69. data/qml/TorQML/Views/Dialogs/TQProgressDialog.qml +36 -0
  70. data/qml/TorQML/Views/Dialogs/qmldir +3 -0
  71. data/qml/TorQML/Views/TQBasicView.qml +148 -0
  72. data/qml/TorQML/Views/TQCamera.qml +11 -0
  73. data/qml/TorQML/Views/TQViewport.qml +41 -0
  74. data/qml/TorQML/Views/basicview.js +172 -0
  75. data/qml/TorQML/Views/mouseEventHandler.js +55 -0
  76. data/qml/TorQML/Views/qmldir +4 -0
  77. data/qml/TorQML/qmldir +2 -0
  78. data/torqml.gemspec +29 -0
  79. metadata +181 -0
@@ -0,0 +1,172 @@
1
+ function updateFrame() {
2
+ if(!_viewport) return; // viewport has not initialized yet
3
+
4
+ for(var i = 0; i < _viewport.children.length; i++){
5
+ if("dataSource" in _viewport.children[i])
6
+ _viewport.children[i].dataSource.currentFrame = _slider.value // update current frame
7
+ }
8
+ _slider.from = _slider.value;
9
+ _frameText.text = Math.floor(_slider.value)
10
+ }
11
+
12
+ function restartTransition(value) {
13
+ // suspend & resume transition to apply the change of time/frame value
14
+ if(_sliderTransition.running){
15
+ _sliderTransition.stop();
16
+ _sliderTransition.start();
17
+ }
18
+ }
19
+
20
+ function reloadData() {
21
+ var min = -1;
22
+ for(var i = 0; i < _viewport.children.length; i++){
23
+ if("dataSource" in _viewport.children[i]){
24
+ _viewport.children[i].dataSource.prepare_data();
25
+ var n = _viewport.children[i].dataSource.rows();
26
+ // use minimum number as the maximum frame number
27
+ if(min <= 0) min = n;
28
+ else min = Math.min(min, n);
29
+ }
30
+ }
31
+ // FIXME: what if `min` is still negative here?
32
+ numberOfFrames = min;
33
+ _slider.value = 1;
34
+ }
35
+
36
+ function showCaptureDialog() {
37
+ // stop before proceeding
38
+ _sliderTransition.stop();
39
+
40
+ _captureDialog.frameWidth = _viewport.width;
41
+ _captureDialog.frameHeight = _viewport.height;
42
+ _captureDialog.maxFrame = numberOfFrames;
43
+ _captureDialog.show();
44
+ }
45
+
46
+ function onCaptureDialogClosed() {
47
+ var target = _captureConnection.target;
48
+ if(target.visible) return;
49
+
50
+ // closed with OK button
51
+ if(target.returnValue){
52
+ var config = JSON.parse(target.returnValue);
53
+ _window.width = config.dimension.width + _window.width - _viewport.width;
54
+ _window.height = config.dimension.height + _window.height - _viewport.height;
55
+
56
+ // preset frame range
57
+ if(config.range.mode == "current"){
58
+ config.range.from = config.range.to = _slider.value;
59
+ } else if(config.range.mode == "all"){
60
+ config.range.from = 1;
61
+ config.range.to = numberOfFrames;
62
+ }
63
+
64
+ // show a dialog to display the progress of exporting
65
+ _progressDialog.minimumValue = config.range.from;
66
+ _progressDialog.maximumValue = config.range.to;
67
+ _progressDialog.show();
68
+
69
+ // set configs and initial value, then delegate bootstrap to `_frameGrabberStarter`
70
+ _frameGrabberTimer.config = config;
71
+ _frameGrabberTimer.currentFrame = config.range.from;
72
+ _frameGrabberStarter.start();
73
+ }
74
+ }
75
+
76
+ function shouldFinish() {
77
+ var config = _frameGrabberTimer.config;
78
+
79
+ if(_frameGrabberTimer.currentFrame > config.range.to){
80
+ // finish exporting
81
+ _progressDialog.close();
82
+ _frameGrabberTimer.stop();
83
+ return true;
84
+ }
85
+
86
+ // abort exporting
87
+ if(!_progressDialog.visible) return true;
88
+
89
+ return false;
90
+ }
91
+
92
+ function captureFrame() {
93
+ if(shouldFinish()) return;
94
+
95
+ var config = _frameGrabberTimer.config;
96
+
97
+ // update values and capture a frame
98
+ _slider.value = _frameGrabberTimer.currentFrame;
99
+ _progressDialog.value = _frameGrabberTimer.currentFrame;
100
+
101
+ var filePath = config.path.directory + "/" + config.path.prefix + _frameGrabberTimer.currentFrame + ".png";
102
+ _frameGrabber.capture(
103
+ filePath,
104
+ 0, _window.height - _viewport.height - _statusBar.height,
105
+ _viewport.width, _viewport.height
106
+ );
107
+ _frameGrabberTimer.currentFrame += config.range.frameSkip + 1;
108
+ }
109
+
110
+ function onKeyPressed(event) {
111
+ // offers vim-like motion + arrow keys
112
+ event.accepted = true;
113
+ switch(event.key){
114
+ case Qt.Key_Left:
115
+ case Qt.Key_H:
116
+ if(_sliderTransition.running) _sliderTransition.stop();
117
+ _slider.value--;
118
+ break;
119
+ case Qt.Key_Right:
120
+ case Qt.Key_L:
121
+ if(_sliderTransition.running) _sliderTransition.stop();
122
+ _slider.value++;
123
+ break;
124
+ case Qt.Key_W:
125
+ if(_sliderTransition.running) _sliderTransition.stop();
126
+ if(event.modifiers & Qt.ShiftModifier){
127
+ _slider.value += 40;
128
+ } else {
129
+ _slider.value += 10;
130
+ }
131
+ break;
132
+ case Qt.Key_B:
133
+ if(_sliderTransition.running) _sliderTransition.stop();
134
+ if(event.modifiers & Qt.ShiftModifier){
135
+ _slider.value -= 40;
136
+ } else {
137
+ _slider.value -= 10;
138
+ }
139
+ break;
140
+ case Qt.Key_G:
141
+ if(_sliderTransition.running) _sliderTransition.stop();
142
+ if(event.modifiers & Qt.ShiftModifier){
143
+ _slider.value = numberOfFrames;
144
+ } else {
145
+ _slider.value = 1;
146
+ }
147
+ break;
148
+ default:
149
+ event.accepted = false;
150
+ break;
151
+ }
152
+ }
153
+
154
+ function initialize() {
155
+ // adjust window size to fix the size of viewport
156
+ _window.width -= _viewport.width;
157
+ _window.height -= _viewport.height;
158
+
159
+ // to avoid pointing out of bound, use the least value of frame numbers as the number of frames
160
+ var min = -1;
161
+ for(var i = 0; i < _viewport.children.length; i++){
162
+ if("dataSource" in _viewport.children[i]){
163
+ _viewport.children[i].dataSource.prepare_data();
164
+ var n = _viewport.children[i].dataSource.rows();
165
+ if(min < 0) min = n;
166
+ else min = Math.min(min, n);
167
+ }
168
+ }
169
+ numberOfFrames = min;
170
+ }
171
+
172
+ // vim:set ts=4 sw=4 et:
@@ -0,0 +1,55 @@
1
+ function onPressed(mouse) {
2
+ _viewport.focus = true;
3
+ if (mouse.button == Qt.LeftButton) {
4
+ _mouseArea.startX = mouse.x;
5
+ _mouseArea.startY = mouse.y;
6
+ _mouseArea.startEye = _viewport.camera.eye;
7
+ _mouseArea.startCenter = _viewport.camera.center;
8
+ _mouseArea.startUpVector = _viewport.camera.upVector;
9
+ if (mouse.modifiers & Qt.ShiftModifier) {
10
+ _mouseArea.translating = true;
11
+ } else {
12
+ _mouseArea.rotating = true;
13
+ }
14
+ }
15
+ }
16
+
17
+ function onReleased(mouse) {
18
+ if (mouse.button == Qt.LeftButton) {
19
+ _mouseArea.rotating = false;
20
+ _mouseArea.translating = false;
21
+ }
22
+ }
23
+
24
+ function onPositionChanged(mouse) {
25
+ var deltaX = mouse.x - _mouseArea.startX;
26
+ var deltaY = mouse.y - _mouseArea.startY;
27
+ if (_mouseArea.rotating) {
28
+ var angleAroundY = deltaX * 90 / _mouseArea.width;
29
+ var angleAroundX = deltaY * 90 / _mouseArea.height;
30
+ _viewport.camera.eye = _mouseArea.startEye;
31
+ _viewport.camera.center = _mouseArea.startCenter;
32
+ _viewport.camera.upVector = _mouseArea.startUpVector;
33
+ _viewport.camera.tiltPanRollCenter(-angleAroundX, -angleAroundY, 0);
34
+ } else if (_mouseArea.translating) {
35
+ var e = _mouseArea.startEye.minus(_mouseArea.startCenter);
36
+ var e3 = e.normalized();
37
+ var e2 = _mouseArea.startUpVector.normalized();
38
+ var e1 = e2.crossProduct(e3);
39
+ var deltaE1 = deltaX * e.length() * 0.5 / _mouseArea.width;
40
+ var deltaE2 = deltaY * e.length() * 0.5 / _mouseArea.height;
41
+ var afterEye = _mouseArea.startEye.minus(e1.times(deltaE1)).plus(e2.times(deltaE2));
42
+ var afterCenter = _mouseArea.startCenter.minus(e1.times(deltaE1)).plus(e2.times(deltaE2));
43
+ _viewport.camera.eye = afterEye;
44
+ _viewport.camera.center = afterCenter;
45
+ }
46
+ }
47
+
48
+ function onWheel(wheel) {
49
+ var delta = wheel.angleDelta.y / 2000;
50
+ var e = _viewport.camera.eye;
51
+ var afterEye = e.minus(e.times(delta));
52
+ _viewport.camera.eye = afterEye;
53
+ }
54
+
55
+ // vim:set ts=4 sw=4 et:
@@ -0,0 +1,4 @@
1
+ module TorQML.Views
2
+ TQBasicView 0.1 TQBasicView.qml
3
+ TQViewport 0.1 TQViewport.qml
4
+ TQCamera 0.1 TQCamera.qml
@@ -0,0 +1,2 @@
1
+ module TorQML
2
+ TQModel 0.1 TQModel.qml
@@ -0,0 +1,29 @@
1
+ # encoding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'torqml/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "torqml"
8
+ s.version = TorQML::VERSION
9
+ s.authors = ["Yuichi Tadokoro"]
10
+ s.email = ["tokoro10g@tokor.org"]
11
+ s.homepage = "http://torqml.tokor.org/"
12
+ s.license = "MIT"
13
+ s.summary = %q{A 3D visualization toolkit for simulations}
14
+ s.description = %q{TorQML provides an architecture for describing 3D structures in Qt Quick QML and enables you to animate the models with numerical data series.}
15
+
16
+ s.files = `git ls-files -z`.split("\x0")
17
+ s.executables = s.files.grep(%r{^bin/}){ |f| File.basename(f) }
18
+ s.test_files = s.files.grep(%r{^(test,spec,features)/})
19
+ s.require_paths = ["lib"]
20
+ s.extensions = ["ext/TorQML/FrameGrabber/extconf.rb"]
21
+
22
+ s.required_ruby_version = '>=2.0.0'
23
+
24
+ s.add_runtime_dependency "qml", "~> 1.0"
25
+
26
+ s.add_development_dependency "bundler", "~> 1.5"
27
+ s.add_development_dependency "rake", "~> 10.3"
28
+ s.add_development_dependency "rspec", "~> 3.0"
29
+ end
metadata ADDED
@@ -0,0 +1,181 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: torqml
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Yuichi Tadokoro
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-06-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: qml
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.5'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.5'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ description: TorQML provides an architecture for describing 3D structures in Qt Quick
70
+ QML and enables you to animate the models with numerical data series.
71
+ email:
72
+ - tokoro10g@tokor.org
73
+ executables:
74
+ - torqml
75
+ extensions:
76
+ - ext/TorQML/FrameGrabber/extconf.rb
77
+ extra_rdoc_files: []
78
+ files:
79
+ - ".gitignore"
80
+ - ".yardopts"
81
+ - Gemfile
82
+ - LICENSE
83
+ - README.md
84
+ - Rakefile
85
+ - assets/images/capture.png
86
+ - assets/images/configure.png
87
+ - assets/images/edit.png
88
+ - assets/images/play.png
89
+ - assets/images/reload.png
90
+ - assets/images/stop.png
91
+ - assets/shapes/TQBox.obj
92
+ - assets/shapes/TQCone.obj
93
+ - assets/shapes/TQCylinder.obj
94
+ - assets/shapes/TQSphere.obj
95
+ - assets/shapes/TQTorus.obj
96
+ - bin/torqml
97
+ - examples/SerialLink/SerialLink.qml
98
+ - examples/SerialLink/main.qml
99
+ - examples/SerialLink/main_multi.qml
100
+ - examples/Tutorial/MyModel.qml
101
+ - examples/Tutorial/main_00_minimal.qml
102
+ - examples/Tutorial/main_01_property.qml
103
+ - examples/Tutorial/main_02_pose.qml
104
+ - examples/Tutorial/main_03_link.qml
105
+ - examples/Tutorial/main_04_importmodel.qml
106
+ - examples/Tutorial/main_05_cameralight.qml
107
+ - examples/Tutorial/main_06_animation.qml
108
+ - examples/WheeledVehicle/WheeledVehicle.qml
109
+ - examples/WheeledVehicle/data/maze2014student.dat
110
+ - examples/WheeledVehicle/data/wheeledvehicle.csv
111
+ - examples/WheeledVehicle/main.qml
112
+ - examples/WheeledVehicle/plugins/MazeWallGenerator/plugin.rb
113
+ - examples/WheeledVehicle/plugins/MazeWallGenerator/qml/TorQML/Plugins/MazeWallGenerator/MazeHorizWall.qml
114
+ - examples/WheeledVehicle/plugins/MazeWallGenerator/qml/TorQML/Plugins/MazeWallGenerator/MazeVertWall.qml
115
+ - examples/WheeledVehicle/plugins/MazeWallGenerator/qml/TorQML/Plugins/MazeWallGenerator/MazeWallGenerator.qml
116
+ - examples/WheeledVehicle/plugins/MazeWallGenerator/qml/TorQML/Plugins/MazeWallGenerator/qmldir
117
+ - examples/WheeledVehicle/plugins/MazeWallGenerator/qml/TorQML/Plugins/MazeWallGenerator/wallAllocator.js
118
+ - ext/TorQML/FrameGrabber/extconf.rb
119
+ - ext/TorQML/FrameGrabber/framegrabber.cpp
120
+ - ext/TorQML/FrameGrabber/framegrabber.pro
121
+ - ext/TorQML/FrameGrabber/qmldir
122
+ - lib/torqml.rb
123
+ - lib/torqml/datasources.rb
124
+ - lib/torqml/datasources/csvdatasource.rb
125
+ - lib/torqml/datasources/datasource.rb
126
+ - lib/torqml/datasources/lineardatasource.rb
127
+ - lib/torqml/datasources/matrixdatasource.rb
128
+ - lib/torqml/plugins.rb
129
+ - lib/torqml/version.rb
130
+ - plugins/DO_NOT_MODIFY_THIS_DIRECTORY
131
+ - qml/TorQML/DataSources/TQCSVDataSource.qml
132
+ - qml/TorQML/DataSources/TQLinearDataSource.qml
133
+ - qml/TorQML/DataSources/qmldir
134
+ - qml/TorQML/Shapes/TQAxis.qml
135
+ - qml/TorQML/Shapes/TQBox.qml
136
+ - qml/TorQML/Shapes/TQCone.qml
137
+ - qml/TorQML/Shapes/TQCoordinate.qml
138
+ - qml/TorQML/Shapes/TQCylinder.qml
139
+ - qml/TorQML/Shapes/TQGrid.qml
140
+ - qml/TorQML/Shapes/TQPrimitive.qml
141
+ - qml/TorQML/Shapes/TQSphere.qml
142
+ - qml/TorQML/Shapes/TQTorus.qml
143
+ - qml/TorQML/Shapes/qmldir
144
+ - qml/TorQML/TQModel.qml
145
+ - qml/TorQML/Views/Dialogs/TQCaptureDialog.qml
146
+ - qml/TorQML/Views/Dialogs/TQProgressDialog.qml
147
+ - qml/TorQML/Views/Dialogs/qmldir
148
+ - qml/TorQML/Views/TQBasicView.qml
149
+ - qml/TorQML/Views/TQCamera.qml
150
+ - qml/TorQML/Views/TQViewport.qml
151
+ - qml/TorQML/Views/basicview.js
152
+ - qml/TorQML/Views/mouseEventHandler.js
153
+ - qml/TorQML/Views/qmldir
154
+ - qml/TorQML/qmldir
155
+ - torqml.gemspec
156
+ homepage: http://torqml.tokor.org/
157
+ licenses:
158
+ - MIT
159
+ metadata: {}
160
+ post_install_message:
161
+ rdoc_options: []
162
+ require_paths:
163
+ - lib
164
+ required_ruby_version: !ruby/object:Gem::Requirement
165
+ requirements:
166
+ - - ">="
167
+ - !ruby/object:Gem::Version
168
+ version: 2.0.0
169
+ required_rubygems_version: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ requirements: []
175
+ rubyforge_project:
176
+ rubygems_version: 2.2.2
177
+ signing_key:
178
+ specification_version: 4
179
+ summary: A 3D visualization toolkit for simulations
180
+ test_files: []
181
+ has_rdoc: