Class: Postscript::Matrix

Inherits:
Object
  • Object
show all
Defined in:
lib/postscript/matrix.rb

Overview

2D affine transformation matrix [a b c d e f].

Used by both PS-side (CTM, transforms) and SVG-side (transform attribute parsing). General-purpose; lives here so both postsvg and a future pdf gem can share it.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(a: 1, b: 0, c: 0, d: 1, e: 0, f: 0) ⇒ Matrix

Returns a new instance of Matrix.



12
13
14
15
16
17
18
19
# File 'lib/postscript/matrix.rb', line 12

def initialize(a: 1, b: 0, c: 0, d: 1, e: 0, f: 0)
  @a = a
  @b = b
  @c = c
  @d = d
  @e = e
  @f = f
end

Instance Attribute Details

#aObject

Returns the value of attribute a.



10
11
12
# File 'lib/postscript/matrix.rb', line 10

def a
  @a
end

#bObject

Returns the value of attribute b.



10
11
12
# File 'lib/postscript/matrix.rb', line 10

def b
  @b
end

#cObject

Returns the value of attribute c.



10
11
12
# File 'lib/postscript/matrix.rb', line 10

def c
  @c
end

#dObject

Returns the value of attribute d.



10
11
12
# File 'lib/postscript/matrix.rb', line 10

def d
  @d
end

#eObject

Returns the value of attribute e.



10
11
12
# File 'lib/postscript/matrix.rb', line 10

def e
  @e
end

#fObject

Returns the value of attribute f.



10
11
12
# File 'lib/postscript/matrix.rb', line 10

def f
  @f
end

Instance Method Details

#apply_point(x, y) ⇒ Object



64
65
66
67
68
69
# File 'lib/postscript/matrix.rb', line 64

def apply_point(x, y)
  {
    x: (x * @a) + (y * @c) + @e,
    y: (x * @b) + (y * @d) + @f,
  }
end

#decomposeObject



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/postscript/matrix.rb', line 71

def decompose
  scale_x = Math.hypot(@a, @b)
  scale_y = ((@a * @d) - (@b * @c)) / scale_x

  rotation = Math.atan2(@b, @a) * (180.0 / Math::PI)

  skew_x = Math.atan2((@a * @c) + (@b * @d), scale_x * scale_x)
  skew_y = Math.atan2((@a * @b) + (@c * @d), scale_y * scale_y)

  {
    translate: { x: @e, y: @f },
    scale: { x: scale_x, y: scale_y },
    rotate: rotation,
    skew: {
      x: skew_x * (180.0 / Math::PI),
      y: skew_y * (180.0 / Math::PI),
    },
  }
end

#identity?Boolean

Returns:

  • (Boolean)


105
106
107
# File 'lib/postscript/matrix.rb', line 105

def identity?
  @a == 1 && @b.zero? && @c.zero? && @d == 1 && @e.zero? && @f.zero?
end

#invertObject



91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/postscript/matrix.rb', line 91

def invert
  det = (@a * @d) - (@b * @c)
  return Matrix.new if det.abs < 1e-10

  inv = Matrix.new
  inv.a = @d / det
  inv.b = -@b / det
  inv.c = -@c / det
  inv.d = @a / det
  inv.e = ((@c * @f) - (@d * @e)) / det
  inv.f = ((@b * @e) - (@a * @f)) / det
  inv
end

#multiply(matrix) ⇒ Object



21
22
23
24
25
26
27
28
29
30
# File 'lib/postscript/matrix.rb', line 21

def multiply(matrix)
  result = Matrix.new
  result.a = (@a * matrix.a) + (@c * matrix.b)
  result.b = (@b * matrix.a) + (@d * matrix.b)
  result.c = (@a * matrix.c) + (@c * matrix.d)
  result.d = (@b * matrix.c) + (@d * matrix.d)
  result.e = (@a * matrix.e) + (@c * matrix.f) + @e
  result.f = (@b * matrix.e) + (@d * matrix.f) + @f
  result
end

#rotate(degrees) ⇒ Object



40
41
42
43
44
45
46
47
48
# File 'lib/postscript/matrix.rb', line 40

def rotate(degrees)
  radians = degrees * Math::PI / 180.0
  m = Matrix.new
  m.a = Math.cos(radians)
  m.b = Math.sin(radians)
  m.c = -Math.sin(radians)
  m.d = Math.cos(radians)
  multiply(m)
end

#scale(sx, sy) ⇒ Object



36
37
38
# File 'lib/postscript/matrix.rb', line 36

def scale(sx, sy)
  multiply(Matrix.new(a: sx, d: sy))
end

#skew_x(angle) ⇒ Object



50
51
52
53
# File 'lib/postscript/matrix.rb', line 50

def skew_x(angle)
  radians = angle * Math::PI / 180.0
  multiply(Matrix.new(c: Math.tan(radians)))
end

#skew_y(angle) ⇒ Object



55
56
57
58
# File 'lib/postscript/matrix.rb', line 55

def skew_y(angle)
  radians = angle * Math::PI / 180.0
  multiply(Matrix.new(b: Math.tan(radians)))
end

#to_transform_stringObject



60
61
62
# File 'lib/postscript/matrix.rb', line 60

def to_transform_string
  "matrix(#{@a} #{@b} #{@c} #{@d} #{@e} #{@f})"
end

#translate(tx, ty) ⇒ Object



32
33
34
# File 'lib/postscript/matrix.rb', line 32

def translate(tx, ty)
  multiply(Matrix.new(e: tx, f: ty))
end