ruby-processing 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +12 -0
- data/lib/ruby-processing.rb +2 -1
- data/lib/ruby-processing/app.rb +7 -5
- data/lib/ruby-processing/exporters/creator.rb +7 -4
- data/lib/ruby-processing/helpers/numeric.rb +11 -0
- data/lib/ruby-processing/helpers/string.rb +8 -0
- data/lib/ruby-processing/runner.rb +11 -10
- data/lib/ruby-processing/runners/watch.rb +33 -0
- data/samples/bezier_playground.rb +243 -0
- data/samples/flight_patterns.rb +1 -1
- data/samples/learning_processing/chapter_16/01_display_video.rb +1 -1
- data/samples/learning_processing/chapter_16/02_manipulate_video_image.rb +1 -1
- data/samples/processing_app/basics/arrays/array.rb +41 -0
- data/samples/processing_app/basics/arrays/array_2d.rb +38 -0
- data/samples/processing_app/basics/arrays/array_objects.rb +67 -0
- data/samples/processing_app/basics/color/brightness.rb +30 -0
- data/samples/processing_app/basics/color/color_wheel.rb +97 -0
- data/samples/processing_app/basics/color/creating.rb +37 -0
- data/samples/processing_app/basics/color/hue.rb +29 -0
- data/samples/processing_app/basics/color/linear_gradient.rb +47 -0
- data/samples/processing_app/basics/color/radial_gradient.rb +52 -0
- data/samples/processing_app/basics/color/reading/data/cait.jpg +0 -0
- data/samples/processing_app/basics/color/reading/reading.rb +43 -0
- data/samples/processing_app/basics/color/relativity.rb +38 -0
- data/samples/processing_app/basics/color/saturation.rb +35 -0
- data/samples/processing_app/basics/color/wave_gradient.rb +45 -0
- data/samples/processing_app/basics/control/conditionals1.rb +51 -0
- data/samples/processing_app/basics/control/conditionals2.rb +44 -0
- data/samples/processing_app/basics/control/embedded_iteration.rb +42 -0
- data/samples/processing_app/basics/control/iteration.rb +61 -0
- data/samples/processing_app/basics/control/logical_operators.rb +59 -0
- data/samples/processing_app/basics/data/characters_strings/characters_strings.rb +87 -0
- data/samples/processing_app/basics/data/characters_strings/data/Eureka-90.vlw +0 -0
- data/samples/processing_app/basics/data/characters_strings/data/rathausFrog.jpg +0 -0
- data/samples/processing_app/basics/data/datatype_conversion.rb +45 -0
- data/samples/processing_app/basics/data/integers_floats.rb +34 -0
- data/samples/processing_app/basics/data/true_false.rb +37 -0
- data/samples/processing_app/basics/data/variable_scope.rb +80 -0
- data/samples/processing_app/basics/data/variables.rb +40 -0
- data/samples/processing_app/basics/form/bezier.rb +23 -0
- data/samples/processing_app/basics/form/bezier_ellipse.rb +110 -0
- data/samples/processing_app/basics/form/pie_chart.rb +31 -0
- data/samples/processing_app/basics/form/points_lines.rb +37 -0
- data/samples/processing_app/basics/form/shape_primitives.rb +25 -0
- data/samples/processing_app/basics/form/triangle_strip.rb +43 -0
- data/samples/processing_app/basics/form/vertices.rb +51 -0
- data/samples/processing_app/basics/image/alphamask.rb +23 -0
- data/samples/processing_app/basics/image/background_image.rb +30 -0
- data/samples/processing_app/basics/image/create_image.rb +23 -0
- data/samples/processing_app/basics/image/data/construct.jpg +0 -0
- data/samples/processing_app/basics/image/data/eames.jpg +0 -0
- data/samples/processing_app/basics/image/data/jelly.jpg +0 -0
- data/samples/processing_app/basics/image/data/mask.jpg +0 -0
- data/samples/processing_app/basics/image/data/milan_rubbish.jpg +0 -0
- data/samples/processing_app/basics/image/data/teddy.gif +0 -0
- data/samples/processing_app/basics/image/data/test.jpg +0 -0
- data/samples/processing_app/basics/image/data/wash.jpg +0 -0
- data/samples/processing_app/basics/image/load_display_image.rb +25 -0
- data/samples/processing_app/basics/image/pointillism.rb +30 -0
- data/samples/processing_app/basics/image/request_image.rb +71 -0
- data/samples/processing_app/basics/image/sprite.rb +38 -0
- data/samples/processing_app/basics/image/transparency.rb +27 -0
- data/samples/processing_app/basics/input/clock.rb +46 -0
- data/samples/processing_app/basics/input/constrain.rb +39 -0
- data/samples/processing_app/basics/input/easing.rb +33 -0
- data/samples/processing_app/basics/input/keyboard.rb +36 -0
- data/samples/processing_app/basics/input/keyboard_2.rb +45 -0
- data/samples/processing_app/basics/input/keyboard_functions.rb +87 -0
- data/samples/processing_app/basics/input/milliseconds.rb +25 -0
- data/samples/processing_app/basics/input/mouse_1d.rb +34 -0
- data/samples/processing_app/basics/input/mouse_2d.rb +25 -0
- data/samples/processing_app/basics/input/mouse_functions.rb +73 -0
- data/samples/processing_app/basics/input/mouse_press.rb +21 -0
- data/samples/processing_app/basics/input/mouse_signals.rb +45 -0
- data/samples/processing_app/basics/input/storing_input.rb +39 -0
- data/samples/processing_app/basics/math/additive_wave.rb +66 -0
- data/samples/processing_app/basics/math/arctangent.rb +54 -0
- data/samples/processing_app/topics/simulate/chain.rb +82 -0
- data/samples/processing_app/topics/simulate/multiple_particle_systems.rb +166 -0
- data/samples/processing_app/topics/simulate/simple_particle_system.rb +113 -0
- data/samples/processing_app/topics/simulate/spring.rb +85 -0
- data/samples/processing_app/topics/simulate/springs.rb +125 -0
- metadata +93 -2
data/CHANGELOG
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
v1.0.3 Tweaks and Tuneups...
|
2
|
+
* "rp5 watch" is now a bit more robust, and tries to reload every
|
3
|
+
* file, global, and constant that it thinks it needs to.
|
4
|
+
* Many, many examples have been contributed by Marc Chung,
|
5
|
+
Peter Krenn, and Florian Jenett.
|
6
|
+
* Andreas Haller contributed a patch that added Ruby-1.9 compatibility.
|
7
|
+
* The render mode now defaults to JAVA2D, as does Processing.
|
8
|
+
* "rp5 create" now informs you of the file it just created.
|
9
|
+
* "key" now returns a character, if ASCII and the integer value otherwise,
|
10
|
+
mirroring Processing's behavior.
|
11
|
+
* Numbers now have the methods 'degrees' and 'radians', for ease.
|
12
|
+
|
1
13
|
v1.0.2 Bugfixes and Java Args...
|
2
14
|
* Application exporting, long plagued, should now be a little
|
3
15
|
closer to rock-solid. If you need to pass command-line options
|
data/lib/ruby-processing.rb
CHANGED
@@ -8,10 +8,11 @@ unless defined? RP5_ROOT
|
|
8
8
|
end
|
9
9
|
|
10
10
|
require 'ruby-processing/helpers/string'
|
11
|
+
require 'ruby-processing/helpers/numeric'
|
11
12
|
|
12
13
|
# The top-level namespace, a home for all Ruby-Processing classes.
|
13
14
|
module Processing
|
14
|
-
VERSION = [1,0,
|
15
|
+
VERSION = [1,0,3] unless defined? Processing::VERSION
|
15
16
|
|
16
17
|
# Returns the current version of Ruby-Processing.
|
17
18
|
def self.version
|
data/lib/ruby-processing/app.rb
CHANGED
@@ -8,7 +8,7 @@ module Processing
|
|
8
8
|
|
9
9
|
# Conditionally load core.jar
|
10
10
|
require "#{RP5_ROOT}/lib/core/core.jar" unless Object.const_defined?(:JRUBY_APPLET)
|
11
|
-
|
11
|
+
import "processing.core"
|
12
12
|
|
13
13
|
# This is the main Ruby-Processing class, and is what you'll
|
14
14
|
# inherit from when you create a sketch. This class can call
|
@@ -20,11 +20,11 @@ module Processing
|
|
20
20
|
class App < PApplet
|
21
21
|
include Math
|
22
22
|
|
23
|
-
|
23
|
+
import "javax.swing.JFrame"
|
24
24
|
|
25
25
|
# Include some processing classes that we'd like to use:
|
26
26
|
%w(PShape PImage PGraphics PFont PVector).each do |klass|
|
27
|
-
|
27
|
+
import "processing.core.#{klass}"
|
28
28
|
end
|
29
29
|
|
30
30
|
# Alias some methods for familiarity for Shoes coders.
|
@@ -175,7 +175,7 @@ module Processing
|
|
175
175
|
:full_screen => false
|
176
176
|
}.merge(options)
|
177
177
|
@width, @height, @title = options[:width], options[:height], options[:title]
|
178
|
-
@render_mode =
|
178
|
+
@render_mode = JAVA2D
|
179
179
|
determine_how_to_display options
|
180
180
|
end
|
181
181
|
|
@@ -235,10 +235,12 @@ module Processing
|
|
235
235
|
|
236
236
|
|
237
237
|
# Fix java conversion problems getting the last key
|
238
|
+
# If it's ASCII, return the character, otherwise the integer
|
238
239
|
def key
|
239
240
|
field = java_class.declared_field 'key'
|
240
241
|
app = Java.ruby_to_java self
|
241
|
-
field.value
|
242
|
+
int = field.value(app)
|
243
|
+
int < 256 ? int.chr : int
|
242
244
|
end
|
243
245
|
|
244
246
|
|
@@ -9,7 +9,10 @@ module Processing
|
|
9
9
|
main_file = File.basename(path, ".rb")
|
10
10
|
# Check to make sure that the main file exists
|
11
11
|
already_exists = File.exists?(path) || File.exists?("#{File.dirname(path)}/#{main_file.underscore}.rb")
|
12
|
-
|
12
|
+
if already_exists
|
13
|
+
puts "That sketch already exists."
|
14
|
+
exit
|
15
|
+
end
|
13
16
|
|
14
17
|
# Get the substitutions
|
15
18
|
@name = main_file.camelize
|
@@ -23,9 +26,9 @@ module Processing
|
|
23
26
|
mkdir_p dir
|
24
27
|
template = File.new("#{RP5_ROOT}/lib/templates/create/blank_sketch.rb.erb")
|
25
28
|
rendered = render_erb_from_string_with_binding(template.read, binding)
|
26
|
-
File.
|
27
|
-
|
28
|
-
|
29
|
+
full_path = File.join(dir, "#{@file_name}.rb")
|
30
|
+
File.open(full_path, "w") {|f| f.print(rendered) }
|
31
|
+
puts "Created Sketch \"#{@title}\" in #{full_path.sub(/\A\.\//, '')}"
|
29
32
|
end
|
30
33
|
|
31
34
|
# Show the help/usage message for create.
|
@@ -37,16 +37,17 @@ module Processing
|
|
37
37
|
# Dispatch central.
|
38
38
|
def execute!
|
39
39
|
case @options.action
|
40
|
-
when 'run'
|
41
|
-
when 'watch'
|
42
|
-
when 'create'
|
43
|
-
when 'live'
|
44
|
-
when 'app'
|
45
|
-
when 'applet'
|
46
|
-
when 'unpack'
|
47
|
-
when /-v/
|
48
|
-
when /-h/
|
49
|
-
else
|
40
|
+
when 'run' then run(@options.path)
|
41
|
+
when 'watch' then watch(@options.path)
|
42
|
+
when 'create' then create(@options.path, @options.args)
|
43
|
+
when 'live' then live(@options.path)
|
44
|
+
when 'app' then app(@options.path)
|
45
|
+
when 'applet' then applet(@options.path)
|
46
|
+
when 'unpack' then unpack(@options.path)
|
47
|
+
when /-v/ then show_version
|
48
|
+
when /-h/ then show_help
|
49
|
+
else
|
50
|
+
show_help
|
50
51
|
end
|
51
52
|
end
|
52
53
|
|
@@ -10,10 +10,12 @@ module Processing
|
|
10
10
|
def initialize(sketch)
|
11
11
|
@file = sketch
|
12
12
|
@time = Time.now
|
13
|
+
record_state_of_ruby
|
13
14
|
load @file
|
14
15
|
start_watching
|
15
16
|
end
|
16
17
|
|
18
|
+
|
17
19
|
# Kicks off a thread to watch the sketch, reloading Ruby-Processing
|
18
20
|
# and restarting the sketch whenever it changes.
|
19
21
|
def start_watching
|
@@ -23,6 +25,7 @@ module Processing
|
|
23
25
|
if file_mtime > @time
|
24
26
|
@time = file_mtime
|
25
27
|
Processing::App.wipe_out_current_app!
|
28
|
+
rewind_to_recorded_state
|
26
29
|
GC.start
|
27
30
|
begin
|
28
31
|
load @file
|
@@ -36,6 +39,36 @@ module Processing
|
|
36
39
|
thread.join
|
37
40
|
end
|
38
41
|
|
42
|
+
|
43
|
+
# Do the best we can to take a picture of the current Ruby interpreter.
|
44
|
+
# For now, this means top-level constants and loaded .rb files.
|
45
|
+
def record_state_of_ruby
|
46
|
+
@saved_constants = Object.send(:constants).dup
|
47
|
+
@saved_load_paths = $LOAD_PATH.dup
|
48
|
+
@saved_features = $LOADED_FEATURES.dup
|
49
|
+
@saved_globals = Kernel.global_variables.dup
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
# Try to go back to the recorded Ruby state.
|
54
|
+
def rewind_to_recorded_state
|
55
|
+
new_constants = Object.send(:constants).reject {|c| @saved_constants.include?(c) }
|
56
|
+
new_load_paths = $LOAD_PATH.reject {|p| @saved_load_paths.include?(p) }
|
57
|
+
new_features = $LOADED_FEATURES.reject {|f| @saved_features.include?(f) }
|
58
|
+
new_globals = Kernel.global_variables.reject {|g| @saved_globals.include?(g) }
|
59
|
+
|
60
|
+
new_constants.each {|c| Object.send(:remove_const, c) }
|
61
|
+
new_load_paths.each {|p| $LOAD_PATH.delete(p) }
|
62
|
+
new_features.each {|f| $LOADED_FEATURES.delete(f) }
|
63
|
+
new_globals.each do |g|
|
64
|
+
begin
|
65
|
+
eval("#{g} = nil") # There's no way to undef a global variable in Ruby
|
66
|
+
rescue NameError => e
|
67
|
+
# Some globals are read-only, and we can't set them to nil.
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
39
72
|
end
|
40
73
|
end
|
41
74
|
|
@@ -0,0 +1,243 @@
|
|
1
|
+
require 'ruby-processing'
|
2
|
+
|
3
|
+
# A Bezier playground. Click to shape the curve. Drag to move it.
|
4
|
+
# Arrows toggle between curves, delete removes them.
|
5
|
+
# You can print out the parametric equations for t = 0..1
|
6
|
+
|
7
|
+
|
8
|
+
module Math
|
9
|
+
|
10
|
+
def self.overlaps(x, y, point_x, point_y)
|
11
|
+
Math.sqrt((x-point_x)**2 + (y-point_y)**2) < Bezier::RADIUS
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
class Curve
|
18
|
+
|
19
|
+
attr_accessor :x1, :y1, :c1x, :c1y, :c2x, :c2y, :x2, :y2
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
@x1, @y1, @x2, @y2 = Bezier::X1, Bezier::Y1, Bezier::X2, Bezier::Y2
|
23
|
+
set_control_points( Bezier::X1+30, Bezier::Y1, Bezier::X2-30, Bezier::Y2)
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
def contains(x, y)
|
28
|
+
return :one if Math.overlaps(@x1, @y1, x, y)
|
29
|
+
return :two if Math.overlaps(@x2, @y2, x, y)
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
def all_points
|
34
|
+
return x1, y1, c1x, c1y, c2x, c2y, x2, y2
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
def control_points
|
39
|
+
return c1x, c1y, c2x, c2y
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
def set_control_points(*points)
|
44
|
+
@c1x, @c1y, @c2x, @c2y = *points
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
def draw
|
49
|
+
$app.bezier *all_points
|
50
|
+
$app.oval @x1, @y1, 3, 3
|
51
|
+
$app.oval @x2, @y2, 3, 3
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
def print_equation
|
56
|
+
p = all_points.map {|p| p.to_i }
|
57
|
+
puts ""
|
58
|
+
puts "*** line ##{$app.curves.index(self) + 1} ***"
|
59
|
+
puts "x = (1-t)^3 #{p[0]} + 3(1-t)^2 t#{p[2]} + 3(1-t)t^2 #{p[4]} + t^3 #{p[6]}"
|
60
|
+
puts "y = -1 * ((1-t)^3 #{p[1]} + 3(1-t)^2 t#{p[3]} + 3(1-t)t^2 #{p[5]} + t^3 #{p[7]})"
|
61
|
+
puts ""
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
class Bezier < Processing::App
|
68
|
+
|
69
|
+
attr_accessor :curves, :c1x, :c1y, :c2x, :c2y
|
70
|
+
|
71
|
+
X1, Y1, X2, Y2 = 50.0, 50.0, 250.0, 250.0
|
72
|
+
REDDISH = [250, 100, 100]
|
73
|
+
RADIUS = 7
|
74
|
+
|
75
|
+
load_library :control_panel
|
76
|
+
|
77
|
+
def setup
|
78
|
+
smooth
|
79
|
+
@curves = []
|
80
|
+
|
81
|
+
control_panel do |c|
|
82
|
+
c.button :new_curve
|
83
|
+
c.button :print_equations
|
84
|
+
end
|
85
|
+
|
86
|
+
generate_curve
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
def print_equations
|
91
|
+
@curves.each {|c| c.print_equation }
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
def control_points
|
96
|
+
return c1x, c1y, c2x, c2y
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
def set_control_points(*points)
|
101
|
+
@c1x, @c1y, @c2x, @c2y = points.any? ? points : [X1, Y1, X2, Y2]
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
def generate_curve
|
106
|
+
@curves << @current_curve = Curve.new
|
107
|
+
@current = @curves.length - 1
|
108
|
+
set_control_points(*current_curve.control_points)
|
109
|
+
end
|
110
|
+
|
111
|
+
|
112
|
+
def current_curve
|
113
|
+
@curves[@current]
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
def new_curve
|
118
|
+
current_curve.set_control_points(c1x, c1y, c2x, c2y)
|
119
|
+
generate_curve
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
def clicked_control_point?
|
124
|
+
x, y = mouse_x, mouse_y
|
125
|
+
return :one if Math.overlaps(@c1x, @c1y, x, y)
|
126
|
+
return :two if Math.overlaps(@c2x, @c2y, x, y)
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
def key_pressed
|
131
|
+
case keyCode
|
132
|
+
when 8 # Delete the current line
|
133
|
+
return if @curves.length <= 1
|
134
|
+
@curves.delete(current_curve)
|
135
|
+
@current = @curves.length - 1
|
136
|
+
when LEFT # Flip forward
|
137
|
+
@current = (@current + 1) % @curves.length
|
138
|
+
when RIGHT # Flip back
|
139
|
+
@current = (@current - 1) % @curves.length
|
140
|
+
end
|
141
|
+
set_control_points(*current_curve.control_points)
|
142
|
+
end
|
143
|
+
|
144
|
+
|
145
|
+
def mouse_pressed
|
146
|
+
switch_curve_if_endpoint_clicked
|
147
|
+
@control = clicked_control_point?
|
148
|
+
return if @control
|
149
|
+
curve = @curves.detect {|c| c.contains(mouse_x, mouse_y) }
|
150
|
+
@end_point = curve.contains(mouse_x, mouse_y) if curve
|
151
|
+
end
|
152
|
+
|
153
|
+
|
154
|
+
def mouse_released
|
155
|
+
@control, @end_point = nil, nil
|
156
|
+
end
|
157
|
+
|
158
|
+
|
159
|
+
def mouse_dragged
|
160
|
+
offs = compute_offsets
|
161
|
+
return if offs.map {|o| o.abs }.max > 100
|
162
|
+
return move_control_point(*offs) if @control
|
163
|
+
return move_end_point(*offs) && move_control_point(*offs) if @end_point
|
164
|
+
move_current_curve(*offs)
|
165
|
+
end
|
166
|
+
|
167
|
+
|
168
|
+
def switch_curve_if_endpoint_clicked
|
169
|
+
become = @curves.detect {|c| c.contains(mouse_x, mouse_y) }
|
170
|
+
return unless become && become != current_curve
|
171
|
+
current_curve.set_control_points(*control_points)
|
172
|
+
self.set_control_points(*become.control_points)
|
173
|
+
@current = @curves.index(become)
|
174
|
+
end
|
175
|
+
|
176
|
+
|
177
|
+
def move_current_curve(x_off, y_off)
|
178
|
+
@c1x += x_off; @c2x += x_off
|
179
|
+
@c1y += y_off; @c2y += y_off
|
180
|
+
current_curve.set_control_points(*control_points)
|
181
|
+
current_curve.x1 += x_off; current_curve.x2 += x_off
|
182
|
+
current_curve.y1 += y_off; current_curve.y2 += y_off
|
183
|
+
end
|
184
|
+
|
185
|
+
|
186
|
+
def move_control_point(x_off, y_off)
|
187
|
+
case @control || @end_point
|
188
|
+
when :one : @c1x += x_off and @c1y += y_off
|
189
|
+
when :two : @c2x += x_off and @c2y += y_off
|
190
|
+
end
|
191
|
+
current_curve.set_control_points(*control_points)
|
192
|
+
end
|
193
|
+
|
194
|
+
|
195
|
+
def move_end_point(x_off, y_off)
|
196
|
+
c = current_curve
|
197
|
+
case @end_point
|
198
|
+
when :one : c.x1 += x_off and c.y1 += y_off
|
199
|
+
when :two : c.x2 += x_off and c.y2 += y_off
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
|
204
|
+
def compute_offsets
|
205
|
+
return mouse_x - pmouse_x, mouse_y - pmouse_y
|
206
|
+
end
|
207
|
+
|
208
|
+
|
209
|
+
def draw_curves
|
210
|
+
stroke 255
|
211
|
+
no_fill
|
212
|
+
stroke_width 2
|
213
|
+
@curves.each {|curve| curve.draw }
|
214
|
+
end
|
215
|
+
|
216
|
+
|
217
|
+
def draw_current_control_points
|
218
|
+
fill *REDDISH
|
219
|
+
no_stroke
|
220
|
+
oval @c1x, @c1y, 5, 5
|
221
|
+
oval @c2x, @c2y, 5, 5
|
222
|
+
end
|
223
|
+
|
224
|
+
|
225
|
+
def draw_control_tangent_lines
|
226
|
+
c = current_curve
|
227
|
+
stroke *REDDISH
|
228
|
+
stroke_width 1
|
229
|
+
line @c1x, @c1y, c.x1, c.y1
|
230
|
+
line @c2x, @c2y, c.x2, c.y2
|
231
|
+
end
|
232
|
+
|
233
|
+
|
234
|
+
def draw
|
235
|
+
background 50
|
236
|
+
draw_control_tangent_lines
|
237
|
+
draw_curves
|
238
|
+
draw_current_control_points
|
239
|
+
end
|
240
|
+
|
241
|
+
end
|
242
|
+
|
243
|
+
Bezier.new :title => "Bezier", :width => 700, :height => 700
|