draught 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,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: []