basis-processing 0.1

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.
@@ -0,0 +1,99 @@
1
+ require 'ranges'
2
+ require 'ruby-processing'
3
+ require 'matrix_operations'
4
+
5
+ include Math
6
+
7
+ class Axis
8
+ attr_accessor :basis_vector, :range
9
+ def initialize(basis_vector, range)
10
+ @basis_vector = basis_vector
11
+ @range = range
12
+ end
13
+ end
14
+
15
+ class CoordinateSystem
16
+ include MatrixOperations
17
+ attr_accessor :x_basis_vector, :y_basis_vector
18
+
19
+ def initialize(x_axis, y_axis, transform, artist)
20
+ @artist = artist
21
+ @x_axis = x_axis
22
+ @y_axis = y_axis
23
+ @x_basis_vector = x_axis.basis_vector
24
+ @y_basis_vector = y_axis.basis_vector
25
+ @basis_transform = transform
26
+ @basis_matrix =
27
+ [
28
+ [@x_basis_vector[:x],@y_basis_vector[:x]],
29
+ [@x_basis_vector[:y],@y_basis_vector[:y]]
30
+ ]
31
+
32
+ d = @basis_matrix[0][0]*@basis_matrix[1][1] - @basis_matrix[0][1]*@basis_matrix[1][0]
33
+ @inverse_basis =
34
+ [
35
+ [@basis_matrix[1][1]/d, -@basis_matrix[0][1]/d],
36
+ [-@basis_matrix[1][0]/d, @basis_matrix[0][0]/d]
37
+ ]
38
+
39
+ @standard_transform = MatrixOperations::into2Dx2D(MatrixOperations::into2Dx2D(@basis_matrix, @basis_transform), @inverse_basis)
40
+ end
41
+
42
+ def tick_vectors
43
+ unnormalised_vectors =
44
+ {
45
+ :x_tick_vector => MatrixOperations::into2Dx1D(rotation(-90),@x_basis_vector),
46
+ :y_tick_vector => MatrixOperations::into2Dx1D(rotation(90),@y_basis_vector)
47
+ }
48
+ {
49
+ :x_tick_vector => normal(unnormalised_vectors[:x_tick_vector]),
50
+ :y_tick_vector => normal(unnormalised_vectors[:y_tick_vector])
51
+ }
52
+ end
53
+
54
+ def normal(vector)
55
+ magnitude = sqrt(vector[:x]**2 + vector[:y]**2)
56
+ {:x => 5*vector[:x]/magnitude, :y => 5*vector[:y]/magnitude}
57
+ end
58
+
59
+ def sum(v1, v2)
60
+ {:x => v1[:x] + v2[:x], :y => v1[:y] + v2[:y]}
61
+ end
62
+
63
+ def x_ticks(x_basis_interval)
64
+ lines = []
65
+ t_vectors = tick_vectors
66
+ @x_axis.range.run(x_basis_interval) do |i,v|
67
+ tick_origin = standard_basis({:x => i, :y => 0})
68
+ lines << {:label => v, :from => tick_origin, :to => sum(tick_origin, t_vectors[:x_tick_vector])}
69
+ end
70
+ lines
71
+ end
72
+
73
+ def y_ticks(y_basis_interval)
74
+ lines = []
75
+ t_vectors = tick_vectors
76
+ @y_axis.range.run(y_basis_interval) do |i,v|
77
+ tick_origin = standard_basis({:x => 0, :y => i})
78
+ lines << {:label => v, :from => tick_origin, :to => sum(tick_origin, t_vectors[:y_tick_vector])}
79
+ end
80
+ lines
81
+ end
82
+
83
+ def rotation(angle)
84
+ radians = angle * PI/180.0
85
+ [[cos(radians), -sin(radians)],[sin(radians),cos(radians)]]
86
+ end
87
+
88
+
89
+ def standard_basis(point)
90
+ standard_point =
91
+ {
92
+ :x => @x_basis_vector[:x]*point[:x] + @y_basis_vector[:x]*point[:y],
93
+ :y => @x_basis_vector[:y]*point[:x] + @y_basis_vector[:y]*point[:y]
94
+ }
95
+
96
+ MatrixOperations::into2Dx1D(@standard_transform, standard_point)
97
+ end
98
+ end
99
+
@@ -0,0 +1,16 @@
1
+ module MatrixOperations
2
+ def MatrixOperations.into2Dx2D(first, second)
3
+ [
4
+ [second[0][0]*first[0][0] + second[1][0]*first[0][1], second[0][1]*first[0][0] + second[1][1]*first[0][1]],
5
+ [second[0][0]*first[1][0] + second[1][0]*first[1][1], second[0][1]*first[1][0] + second[1][1]*first[1][1]]
6
+ ]
7
+ end
8
+
9
+ def MatrixOperations.into2Dx1D(transform, point)
10
+ {
11
+ :x => transform[0][0]*point[:x] + transform[0][1]*point[:y],
12
+ :y => transform[1][0]*point[:x] + transform[1][1]*point[:y]
13
+ }
14
+ end
15
+ end
16
+
data/ranges.rb ADDED
@@ -0,0 +1,48 @@
1
+ class ContinuousRange
2
+ attr_accessor :minimum, :maximum
3
+
4
+ def initialize(range)
5
+ @minimum = range[:minimum]
6
+ @maximum = range[:maximum]
7
+ end
8
+
9
+ def interval
10
+ @maximum - @minimum
11
+ end
12
+
13
+ def index(element)
14
+ element.to_f
15
+ end
16
+
17
+ def run(interval)
18
+ current = @minimum
19
+ while(current <= @maximum)
20
+ yield(current,current)
21
+ current += interval
22
+ end
23
+ end
24
+ end
25
+
26
+ class DiscreteRange
27
+ attr_accessor :values
28
+ def initialize(v)
29
+ @values = v[:values]
30
+ end
31
+
32
+ def interval
33
+ @values.count
34
+ end
35
+
36
+ def index(element)
37
+ @values.index(element)
38
+ end
39
+
40
+ def run(interval)
41
+ current = 0
42
+ while(current <= @values.count - 1)
43
+ yield(current,@values[current])
44
+ current += interval
45
+ end
46
+ end
47
+ end
48
+
data/screen.rb ADDED
@@ -0,0 +1,41 @@
1
+ require 'transform'
2
+
3
+ class Screen
4
+ def initialize(transform, artist)
5
+ @transform = transform
6
+ @artist = artist
7
+ end
8
+
9
+ def plot(point, basis)
10
+ standard_point = basis.standard_basis(point)
11
+ p = @transform.apply(standard_point)
12
+ @artist.ellipse(p[:x], p[:y], 5, 5)
13
+ end
14
+
15
+ def draw_ticks(ticks, displacement)
16
+ ticks.each do |l|
17
+ from = @transform.apply(l[:from])
18
+ to = @transform.apply(l[:to])
19
+ @artist.line(from[:x],from[:y],to[:x],to[:y])
20
+ @artist.fill(1)
21
+ @artist.text(l[:label], to[:x]+displacement[:x], to[:y]+displacement[:y])
22
+ end
23
+ end
24
+
25
+ def draw_axes(basis, x_interval, y_interval)
26
+ f = @artist.createFont("Georgia", 24, true);
27
+ @artist.text_font(f,16)
28
+ @artist.stroke(1,1,1,1)
29
+ axis_screen_transform = Transform.new({:x => 800, :y => -800}, @transform.origin)
30
+ origin = {:x => 0, :y => 0}
31
+ screen_origin = @transform.apply(origin)
32
+ x_basis_edge = axis_screen_transform.apply(basis.x_basis_vector)
33
+ y_basis_edge = axis_screen_transform.apply(basis.y_basis_vector)
34
+ @artist.line(screen_origin[:x],screen_origin[:y],x_basis_edge[:x],x_basis_edge[:y])
35
+ @artist.line(screen_origin[:x],screen_origin[:y],y_basis_edge[:x],y_basis_edge[:y])
36
+
37
+ draw_ticks(basis.x_ticks(x_interval), {:x => 0, :y => 20})
38
+ draw_ticks(basis.y_ticks(y_interval), {:x => -50, :y => 0})
39
+ end
40
+ end
41
+
data/transform.rb ADDED
@@ -0,0 +1,18 @@
1
+ class Transform
2
+ attr_accessor :scale, :origin
3
+ def initialize(scale, origin)
4
+ @origin = origin
5
+ @scale = scale
6
+ end
7
+
8
+ def apply(p)
9
+ { :x => @origin[:x] + p[:x] * @scale[:x], :y => @origin[:y] + p[:y] * @scale[:y]}
10
+ end
11
+ end
12
+
13
+ class SignedTransform < Transform
14
+ def apply(p)
15
+ { :x => @origin[:x] + p[:x] * (@scale[:x]<=>0.0).to_i, :y => @origin[:y] + p[:y] * (@scale[:y]<=>0.0).to_i}
16
+ end
17
+ end
18
+
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: basis-processing
3
+ version: !ruby/object:Gem::Version
4
+ hash: 9
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ version: "0.1"
10
+ platform: ruby
11
+ authors:
12
+ - Avishek Sen Gupta
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-08-20 00:00:00 Z
18
+ dependencies: []
19
+
20
+ description: Basis provides a set of classes for easily plotting and transforming arbitrary 2D coordinate systems by specifying their basis vectors in Ruby-Processing.
21
+ email: avishek.sen.gupta@gmail.com
22
+ executables: []
23
+
24
+ extensions: []
25
+
26
+ extra_rdoc_files: []
27
+
28
+ files:
29
+ - transform.rb
30
+ - ranges.rb
31
+ - coordinate_system.rb
32
+ - matrix_operations.rb
33
+ - screen.rb
34
+ homepage: http://avishek.net/blog
35
+ licenses: []
36
+
37
+ post_install_message:
38
+ rdoc_options: []
39
+
40
+ require_paths:
41
+ - lib
42
+ required_ruby_version: !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ hash: 3
48
+ segments:
49
+ - 0
50
+ version: "0"
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ hash: 3
57
+ segments:
58
+ - 0
59
+ version: "0"
60
+ requirements: []
61
+
62
+ rubyforge_project:
63
+ rubygems_version: 1.7.2
64
+ signing_key:
65
+ specification_version: 3
66
+ summary: Basis provides a set of classes for easily plotting and transforming arbitrary 2D coordinate systems by specifying their basis vectors in Ruby-Processing.
67
+ test_files: []
68
+