draught 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,63 @@
1
+ require 'matrix'
2
+ require_relative 'point'
3
+ require_relative 'transformations/affine'
4
+ require_relative 'transformations/proclike'
5
+ require_relative 'transformations/composer'
6
+
7
+ module Draught
8
+ module Transformations
9
+ extend self
10
+
11
+ MM_TO_PT = 2.8346456692913
12
+
13
+ def mm_to_pt
14
+ Affine.new(Matrix[
15
+ [MM_TO_PT, 0, 0],
16
+ [0, MM_TO_PT, 0],
17
+ [0, 0, 1]
18
+ ])
19
+ end
20
+
21
+ def x_axis_reflect
22
+ Affine.new(Matrix[
23
+ [1,0,0],
24
+ [0,-1,0],
25
+ [0,0,1]
26
+ ])
27
+ end
28
+
29
+ def y_axis_reflect
30
+ Affine.new(Matrix[
31
+ [-1,0,0],
32
+ [0,1,0],
33
+ [0,0,1]
34
+ ])
35
+ end
36
+
37
+ def xy_axis_reflect
38
+ Composer.compose(x_axis_reflect, y_axis_reflect)
39
+ end
40
+
41
+ def scale(factor)
42
+ Transformations::Affine.new(Matrix[
43
+ [factor, 0, 0],
44
+ [0, factor, 0],
45
+ [0, 0, 1]
46
+ ])
47
+ end
48
+
49
+ def rotate(radians)
50
+ cos = Math.cos(radians)
51
+ sin = Math.sin(radians)
52
+ Transformations::Affine.new(Matrix[
53
+ [cos, -sin, 0],
54
+ [sin, cos, 0],
55
+ [0, 0, 1]
56
+ ])
57
+ end
58
+
59
+ def round_to_n_decimal_places(n)
60
+ Proclike.new(->(p) { [p.x.round(n), p.y.round(n)] })
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,33 @@
1
+ require_relative 'common'
2
+ require_relative '../point'
3
+
4
+ module Draught
5
+ module Transformations
6
+ class Affine
7
+ include Common
8
+
9
+ attr_reader :transformation_matrix
10
+
11
+ def initialize(transformation_matrix)
12
+ @transformation_matrix = transformation_matrix
13
+ end
14
+
15
+ def call(point)
16
+ Point.from_matrix(transformation_matrix * point.to_matrix)
17
+ end
18
+
19
+ def affine?
20
+ true
21
+ end
22
+
23
+ def ==(other)
24
+ other.respond_to?(:transformation_matrix) && other.transformation_matrix == transformation_matrix
25
+ end
26
+
27
+ def coalesce(other)
28
+ raise TypeError, "other must be a matrix-based Affine transform" unless other.affine?
29
+ self.class.new(other.transformation_matrix * self.transformation_matrix)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,21 @@
1
+ module Draught
2
+ module Transformations
3
+ module Common
4
+ def call(point)
5
+ raise NotImplementedError, "Classes including Transformations::Common must implement #call, taking a Point and returning a new, transformed, Point"
6
+ end
7
+
8
+ def affine?
9
+ raise NotImplementedError, "Classes including Transformations::Common must implement #affine?"
10
+ end
11
+
12
+ def to_transform
13
+ self
14
+ end
15
+
16
+ def transforms
17
+ [self]
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,51 @@
1
+ require_relative './composition'
2
+
3
+ module Draught
4
+ module Transformations
5
+ class Composer
6
+ def self.compose(*transforms)
7
+ new(transforms).composition
8
+ end
9
+
10
+ attr_reader :transforms
11
+
12
+ def initialize(transforms)
13
+ @transforms = transforms
14
+ end
15
+
16
+ def composition
17
+ Composition.new(coalesced_transforms)
18
+ end
19
+
20
+ def coalesced_transforms
21
+ return [] if transforms.empty?
22
+ start_transforms = flattened_transforms
23
+ finished = start_transforms.shift(1)
24
+ return finished if start_transforms.empty?
25
+
26
+ start_transforms.each do |next_transform|
27
+ coalesce_pair(finished.pop, next_transform).each do |coalesced_transform|
28
+ finished << coalesced_transform
29
+ end
30
+ end
31
+ finished
32
+ end
33
+
34
+ def flattened_transforms
35
+ transforms.flat_map { |transform|
36
+ transform.to_transform.transforms
37
+ }
38
+ end
39
+
40
+ private
41
+
42
+ def coalesce_pair(first, second)
43
+ begin
44
+ [first.coalesce(second)]
45
+ rescue TypeError
46
+ [first, second]
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,31 @@
1
+ require_relative './common'
2
+
3
+ module Draught
4
+ module Transformations
5
+ class Composition
6
+ include Transformations::Common
7
+
8
+ attr_reader :transforms
9
+
10
+ def initialize(transforms)
11
+ @transforms = transforms
12
+ end
13
+
14
+ def call(point)
15
+ transforms.inject(point) { |result_point, transform| transform.call(result_point) }
16
+ end
17
+
18
+ def affine?
19
+ false
20
+ end
21
+
22
+ def to_transform
23
+ self
24
+ end
25
+
26
+ def ==(other)
27
+ other.transforms == transforms
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,43 @@
1
+ require_relative './common'
2
+ require_relative '../point'
3
+
4
+ module Draught
5
+ module Transformations
6
+ class Proclike
7
+ include Common
8
+
9
+ attr_reader :proclike
10
+
11
+ def initialize(proclike)
12
+ @proclike = proclike
13
+ end
14
+
15
+ def call(point)
16
+ point_from_tuple_or_point(proclike.call(point))
17
+ end
18
+
19
+ def affine?
20
+ false
21
+ end
22
+
23
+ def ==(other)
24
+ other.respond_to?(:proclike) && proclike == other.proclike
25
+ end
26
+
27
+ def flattened_transforms
28
+ [self]
29
+ end
30
+
31
+ def coalesce(_)
32
+ raise TypeError, "non-Affine transforms cannot be coalesced"
33
+ end
34
+
35
+ private
36
+
37
+ def point_from_tuple_or_point(tuple_or_point)
38
+ return Point.new(*tuple_or_point) if tuple_or_point.respond_to?(:each)
39
+ tuple_or_point
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,48 @@
1
+ require 'matrix'
2
+ require_relative './transformations/affine'
3
+ require_relative './point'
4
+
5
+ module Draught
6
+ class Vector
7
+ def self.from_xy(x, y)
8
+ new(x, y)
9
+ end
10
+
11
+ def self.from_degrees_and_magnitude(degrees, magnitude)
12
+ radians = degrees * (Math::PI / 180)
13
+ from_radians_and_magnitude(radians, magnitude)
14
+ end
15
+
16
+ def self.from_radians_and_magnitude(radians, magnitude)
17
+ x = Math.cos(radians) * magnitude
18
+ y = Math.sin(radians) * magnitude
19
+ new(x, y)
20
+ end
21
+
22
+ def self.translation_to_zero(point)
23
+ translation_between(point, Point::ZERO)
24
+ end
25
+
26
+ def self.translation_between(point_1, point_2)
27
+ from_xy(point_2.x - point_1.x, point_2.y - point_1.y)
28
+ end
29
+
30
+ attr_reader :x, :y
31
+
32
+ def initialize(x, y)
33
+ @x, @y = x, y
34
+ end
35
+
36
+ def ==(other)
37
+ other.respond_to?(:to_transform) && other.x == x && other.y == y
38
+ end
39
+
40
+ def to_transform
41
+ @transform ||= Transformations::Affine.new(
42
+ Matrix[[1, 0, x], [0, 1, y], [0, 0, 1]]
43
+ )
44
+ end
45
+
46
+ NULL = new(0,0)
47
+ end
48
+ end
@@ -0,0 +1,3 @@
1
+ module Draught
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,153 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: draught
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Matt Patterson
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-08-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: prawn
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.1'
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.14'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.14'
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.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
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
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description:
84
+ email:
85
+ - matt@reprocessed.org
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - ".rspec"
92
+ - ".ruby-version"
93
+ - ".travis.yml"
94
+ - CODE_OF_CONDUCT.md
95
+ - Gemfile
96
+ - Gemfile.lock
97
+ - LICENSE.txt
98
+ - README.md
99
+ - Rakefile
100
+ - bin/console
101
+ - bin/setup
102
+ - draught.gemspec
103
+ - lib/draught.rb
104
+ - lib/draught/arc_builder.rb
105
+ - lib/draught/bounding_box.rb
106
+ - lib/draught/boxlike.rb
107
+ - lib/draught/container.rb
108
+ - lib/draught/corner.rb
109
+ - lib/draught/cubic_bezier.rb
110
+ - lib/draught/curve.rb
111
+ - lib/draught/line.rb
112
+ - lib/draught/path.rb
113
+ - lib/draught/path_builder.rb
114
+ - lib/draught/path_cleaner.rb
115
+ - lib/draught/pathlike.rb
116
+ - lib/draught/point.rb
117
+ - lib/draught/pointlike.rb
118
+ - lib/draught/renderer.rb
119
+ - lib/draught/sheet.rb
120
+ - lib/draught/sheet_builder.rb
121
+ - lib/draught/transformations.rb
122
+ - lib/draught/transformations/affine.rb
123
+ - lib/draught/transformations/common.rb
124
+ - lib/draught/transformations/composer.rb
125
+ - lib/draught/transformations/composition.rb
126
+ - lib/draught/transformations/proclike.rb
127
+ - lib/draught/vector.rb
128
+ - lib/draught/version.rb
129
+ homepage: https://github.com/fidothe/draught
130
+ licenses:
131
+ - MIT
132
+ metadata: {}
133
+ post_install_message:
134
+ rdoc_options: []
135
+ require_paths:
136
+ - lib
137
+ required_ruby_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ required_rubygems_version: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ requirements: []
148
+ rubyforge_project:
149
+ rubygems_version: 2.6.11
150
+ signing_key:
151
+ specification_version: 4
152
+ summary: A library for creating 2D vector graphics as PDF.
153
+ test_files: []