wicket 0.0.2 → 0.1.0

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,24 @@
1
+ module Wicket
2
+ module Commands
3
+ class C < Command
4
+ ARGS = 6
5
+ ARG_LIST = [:c1x,:c1y,:c2x,:c2y,:x,:y]
6
+ include CubicBezier
7
+
8
+ def initialize(absolute,cursor_start,subpath,opts,c1x,c1y,c2x,c2y,x,y)
9
+ @absolute = absolute
10
+ @cursor_start = cursor_start
11
+ @subpath = subpath
12
+ @opts = opts
13
+ @c1x = c1x
14
+ @c1y = c1y
15
+ @c2x = c2x
16
+ @c2y = c2y
17
+ @x = x
18
+ @y = y
19
+ end
20
+
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,20 @@
1
+ module Wicket
2
+ module Commands
3
+ module CubicBezier
4
+ include BezierCurve
5
+
6
+ def control_points
7
+ [cursor_start,c1,c2,cursor_end]
8
+ end
9
+
10
+ def c1
11
+ @absolute ? Coordinate.new(@c1x,@c1y) : @cursor_start.absolutize(@c1x,@c1y)
12
+ end
13
+
14
+ def c2
15
+ @absolute ? Coordinate.new(@c2x,@c2y) : @cursor_start.absolutize(@c2x,@c2y)
16
+ end
17
+
18
+ end
19
+ end
20
+ end
@@ -1,29 +1,25 @@
1
1
  module Wicket
2
2
  module Commands
3
3
  class H < Command
4
+ ARGS = 1
5
+ ARG_LIST = [:x]
4
6
 
5
- def self.arg_count
6
- 1
7
- end
8
-
9
- def initialize(absolute,cursor_start,x)
7
+ def initialize(absolute,cursor_start,subpath,opts,x)
10
8
  @absolute = absolute
11
9
  @cursor_start = cursor_start
10
+ @subpath = subpath
11
+ @opts = opts
12
12
  @x = x
13
13
  end
14
14
 
15
- def coordinates
16
- {:x => @x, :y => cursor_start[:y]}
15
+ def absolute_y
16
+ @cursor_start.y
17
17
  end
18
18
 
19
- def cursor_end
20
- if @absolute
21
- coordinates
22
- else
23
- {:x => (@cursor_start[:x] + @x), :y => @cursor_start[:y]}
24
- end
19
+ def to_svg(opts={})
20
+ o = @opts.merge(opts)
21
+ "H #{Utilities.format(absolute_x,o)}"
25
22
  end
26
-
27
23
  end
28
24
  end
29
25
  end
@@ -1,28 +1,16 @@
1
1
  module Wicket
2
2
  module Commands
3
3
  class L < Command
4
+ ARGS = 2
5
+ ARG_LIST = [:x,:y]
4
6
 
5
- def self.arg_count
6
- 2
7
- end
8
-
9
- def initialize(absolute,cursor_start,x,y)
7
+ def initialize(absolute,cursor_start,subpath,opts,x,y)
10
8
  @absolute = absolute
9
+ @cursor_start = cursor_start
10
+ @subpath = subpath
11
+ @opts = opts
11
12
  @x = x
12
13
  @y = y
13
- @cursor_start = cursor_start
14
- end
15
-
16
- def coordinates
17
- {:x => @x, :y => @y}
18
- end
19
-
20
- def cursor_end
21
- if @absolute
22
- coordinates
23
- else
24
- {:x => (@cursor_start[:x] + @x), :y => (@cursor_start[:y] + @y)}
25
- end
26
14
  end
27
15
 
28
16
  end
@@ -1,28 +1,16 @@
1
1
  module Wicket
2
2
  module Commands
3
3
  class M < Command
4
+ ARGS = 2
5
+ ARG_LIST = [:x,:y]
4
6
 
5
- def self.arg_count
6
- 2
7
- end
8
-
9
- def initialize(absolute,cursor_start,x,y)
7
+ def initialize(absolute,cursor_start,subpath,opts,x,y)
10
8
  @absolute = absolute
9
+ @cursor_start = cursor_start
10
+ @subpath = subpath
11
+ @opts = opts
11
12
  @x = x
12
13
  @y = y
13
- @cursor_start = cursor_start
14
- end
15
-
16
- def coordinates
17
- {:x => @x, :y => @y}
18
- end
19
-
20
- def cursor_end
21
- if @absolute
22
- coordinates
23
- else
24
- {:x => (@cursor_start[:x] + @x), :y => (@cursor_start[:y] + @y)}
25
- end
26
14
  end
27
15
 
28
16
  end
@@ -0,0 +1,21 @@
1
+ module Wicket
2
+ module Commands
3
+ class Q < Command
4
+ ARGS = 4
5
+ ARG_LIST = [:c1x,:c1y,:x,:y]
6
+ include QuadraticBezier
7
+
8
+ def initialize(absolute,cursor_start,subpath,opts,c1x,c1y,x,y)
9
+ @absolute = absolute
10
+ @cursor_start = cursor_start
11
+ @subpath = subpath
12
+ @opts = opts
13
+ @c1x = c1x
14
+ @c1y = c1y
15
+ @x = x
16
+ @y = y
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ module Wicket
2
+ module Commands
3
+ module QuadraticBezier
4
+ include BezierCurve
5
+
6
+ def control_points
7
+ [cursor_start,c1,cursor_end]
8
+ end
9
+
10
+ def c1
11
+ @absolute ? Coordinate.new(@c1x,@c1y) : @cursor_start.absolutize(@c1x,@c1y)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,37 @@
1
+ module Wicket
2
+ module Commands
3
+ class S < Command
4
+ ARGS = 4
5
+ include CubicBezier
6
+ ARG_LIST = [:c2x,:c2y,:x,:y]
7
+
8
+ def initialize(absolute,cursor_start,subpath,opts,c2x,c2y,x,y)
9
+ @absolute = absolute
10
+ @cursor_start = cursor_start
11
+ @subpath = subpath
12
+ @opts = opts
13
+ set_implicit_control_point!
14
+ @c2x = c2x
15
+ @c2y = c2y
16
+ @x = x
17
+ @y = y
18
+ end
19
+
20
+ private
21
+
22
+ # > The first control point is assumed to be the reflection of the second
23
+ # > control point on the previous command relative to the current point.
24
+ # > (If there is no previous command or if the previous command was not an
25
+ # > C, c, S or s, assume the first control point is coincident with the
26
+ # > current point.)
27
+ # > http://www.w3.org/TR/SVG11/paths.html#PathDataCubicBezierCommands
28
+ def implied_c1
29
+ last = @subpath.last_command
30
+ case last
31
+ when C,S then @cursor_start.reflect(last.c2)
32
+ else @cursor_start
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,34 @@
1
+ module Wicket
2
+ module Commands
3
+ class T < Command
4
+ ARGS = 2
5
+ include QuadraticBezier
6
+ ARG_LIST = [:x,:y]
7
+
8
+ def initialize(absolute,cursor_start,subpath,opts,x,y)
9
+ @absolute = absolute
10
+ @cursor_start = cursor_start
11
+ @subpath = subpath
12
+ @opts = opts
13
+ set_implicit_control_point!
14
+ @x = x
15
+ @y = y
16
+ end
17
+
18
+ private
19
+
20
+ # > The control point is assumed to be the reflection of the control point on
21
+ # > the previous command relative to the current point. (If there is no previous
22
+ # > command or if the previous command was not a Q, q, T or t, assume the control
23
+ # > point is coincident with the current point.)
24
+ # > http://www.w3.org/TR/SVG11/paths.html#PathDataQuadraticBezierCommands
25
+ def implied_c1
26
+ last = @subpath.last_command
27
+ case last
28
+ when Q,T then @cursor_start.reflect(last.c1)
29
+ else @cursor_start
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -1,27 +1,24 @@
1
1
  module Wicket
2
2
  module Commands
3
3
  class V < Command
4
+ ARGS = 1
5
+ ARG_LIST = [:y]
4
6
 
5
- def self.arg_count
6
- 1
7
- end
8
-
9
- def initialize(absolute,cursor_start,y)
7
+ def initialize(absolute,cursor_start,subpath,opts,y)
10
8
  @absolute = absolute
11
9
  @cursor_start = cursor_start
10
+ @subpath = subpath
11
+ @opts = opts
12
12
  @y = y
13
13
  end
14
14
 
15
- def coordinates
16
- {:x => cursor_start[:x], :y => @y}
15
+ def absolute_x
16
+ cursor_start.x
17
17
  end
18
18
 
19
- def cursor_end
20
- if @absolute
21
- coordinates
22
- else
23
- {:x => @cursor_start[:x], :y => (@cursor_start[:y] + @y)}
24
- end
19
+ def to_svg(opts={})
20
+ o = @opts.merge(opts)
21
+ "V #{Utilities.format(absolute_y,o)}"
25
22
  end
26
23
 
27
24
  end
@@ -1,22 +1,22 @@
1
1
  module Wicket
2
2
  module Commands
3
3
  class Z < Command
4
+ ARGS = 1
5
+ ARG_LIST = []
4
6
 
5
- def self.arg_count
6
- 1
7
- end
8
-
9
- def initialize(absolute,cursor_start)
7
+ def initialize(absolute,cursor_start,subpath,opts)
10
8
  @cursor_start = cursor_start
11
- end
12
-
13
- def coordinates
14
- {}
9
+ @subpath = subpath
10
+ @opts = opts
15
11
  end
16
12
 
17
13
  def cursor_end
18
14
  @subpath.first_command.cursor_end
19
15
  end
16
+
17
+ def to_svg(opts={})
18
+ "Z"
19
+ end
20
20
  end
21
21
  end
22
22
  end
@@ -0,0 +1,26 @@
1
+ module Wicket
2
+ class Configuration
3
+ SETTINGS = [
4
+ :min_angle,
5
+ :min_angle_unit
6
+ ]
7
+ attr_accessor *SETTINGS
8
+
9
+ def initialize
10
+ @min_angle = 165
11
+ end
12
+
13
+ def merge(*opts)
14
+ opts.each_with_object(to_h) do |opts,aggregate|
15
+ aggregate.merge!(opts)
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def to_h
22
+ SETTINGS.each_with_object({}){|s,h| h.merge!(s => send(s)) }
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,21 @@
1
+ module Wicket
2
+ class Coordinate < Struct.new(:x,:y)
3
+ include Cartesian
4
+
5
+ # method for a reference point to create absolute coords from
6
+ # relative measures.
7
+ def absolutize(delta_x,delta_y)
8
+ self.class.new(x + delta_x , y + delta_y)
9
+ end
10
+
11
+ def relativize(remote)
12
+ [remote.x - x, remote.y - y]
13
+ end
14
+
15
+ def reflect(remote)
16
+ x,y = relativize(remote)
17
+ absolutize(-x,-y)
18
+ end
19
+
20
+ end
21
+ end
@@ -7,9 +7,9 @@ module Wicket
7
7
 
8
8
  def add_command(*new_commands)
9
9
  new_commands.each do |c|
10
- c.subpath = self
11
10
  @commands << c
12
11
  end
12
+ self
13
13
  end
14
14
 
15
15
  def cursor_end
@@ -22,8 +22,8 @@ module Wicket
22
22
  @commands.last.class == Commands::Z
23
23
  end
24
24
 
25
- def to_polygon
26
- vertices = commands.map(&:to_wkt).join(",")
25
+ def to_polygon(opts)
26
+ vertices = commands.map{|c| c.to_wkt(opts) }.join(",")
27
27
  "((#{vertices}))"
28
28
  end
29
29
 
@@ -34,5 +34,9 @@ module Wicket
34
34
  def first_command
35
35
  @commands.first
36
36
  end
37
+
38
+ def to_svg(opts={})
39
+ @commands.map{|c| c.to_svg(opts) }.join(" ")
40
+ end
37
41
  end
38
42
  end
@@ -0,0 +1,39 @@
1
+ module Wicket
2
+ class Subpoint < Struct.new(:x,:y,:t,:siblings)
3
+ include Cartesian
4
+
5
+ def self.from_coordinate(coordinate,t,siblings)
6
+ new(coordinate.x,coordinate.y,t,siblings)
7
+ end
8
+
9
+ def initialize(x,y,t,siblings)
10
+ super(x,y,t,siblings)
11
+ siblings << self
12
+ end
13
+
14
+ def previous_neighbor
15
+ siblings.select{|s| s.t < t }.max_by(&:t)
16
+ end
17
+
18
+ def next_neighbor
19
+ siblings.select{|s| s.t > t }.min_by(&:t)
20
+ end
21
+
22
+ def angle
23
+ evaluate_angle(previous_neighbor,self,next_neighbor) unless endpoint?
24
+ end
25
+
26
+ def endpoint?
27
+ t == 0 || t == 1
28
+ end
29
+
30
+ # This method evaluates the angle at p2 in radians (180 deg = pi)
31
+ def evaluate_angle(p1,p2,p3)
32
+ a = p2.distance_to(p1)
33
+ b = p2.distance_to(p3)
34
+ c = p1.distance_to(p3)
35
+ Math.acos((a**2 + b**2 - c**2)/(2 * a * b))
36
+ end
37
+
38
+ end
39
+ end