Class: PerfectShape::AffineTransform
- Inherits:
-
Object
- Object
- PerfectShape::AffineTransform
- Defined in:
- lib/perfect_shape/affine_transform.rb
Overview
Represents an affine transform
Instance Attribute Summary collapse
-
#xt ⇒ Object
(also: #m13)
Returns the value of attribute xt.
-
#xxp ⇒ Object
(also: #m11)
Returns the value of attribute xxp.
-
#xyp ⇒ Object
(also: #m12)
Returns the value of attribute xyp.
-
#yt ⇒ Object
(also: #m23)
Returns the value of attribute yt.
-
#yxp ⇒ Object
(also: #m21)
Returns the value of attribute yxp.
-
#yyp ⇒ Object
(also: #m22)
Returns the value of attribute yyp.
Instance Method Summary collapse
-
#identity! ⇒ Object
(also: #reset!)
Resets to identity matrix Returns self to support fluent interface chaining.
-
#initialize(xxp_element = nil, xyp_element = nil, yxp_element = nil, yyp_element = nil, xt_element = nil, yt_element = nil, xxp: nil, xyp: nil, yxp: nil, yyp: nil, xt: nil, yt: nil, m11: nil, m12: nil, m21: nil, m22: nil, m13: nil, m23: nil) ⇒ AffineTransform
constructor
Creates a new AffineTransform with the following Matrix:.
- #inverse_transform_point(x_or_point, y = nil) ⇒ Object
- #inverse_transform_points(*xy_coordinates_or_points) ⇒ Object
-
#invert! ⇒ Object
Inverts AffineTransform matrix if invertible Raises an error if affine transform matrix is not invertible Returns self to support fluent interface chaining.
- #invertible? ⇒ Boolean
-
#matrix_3d ⇒ Object
Returns Ruby Matrix representing Affine Transform matrix elements in 3D.
-
#matrix_3d=(the_matrix_3d) ⇒ Object
Sets elements from a Ruby Matrix representing Affine Transform matrix elements in 3D.
-
#multiply!(other_affine_transform) ⇒ Object
Multiplies by other AffineTransform.
-
#rotate!(degrees) ⇒ Object
Rotates AffineTransform counter-clockwise for positive angle value in degrees or clockwise for negative angle value in degrees.
-
#scale!(x_or_point, y = nil) ⇒ Object
Scales AffineTransform.
-
#shear!(x_or_point, y = nil) ⇒ Object
(also: #skew!)
Shears AffineTransform by (x,y) amount.
- #transform_point(x_or_point, y = nil) ⇒ Object
- #transform_points(*xy_coordinates_or_points) ⇒ Object
-
#translate!(x_or_point, y = nil) ⇒ Object
Translates AffineTransform.
Constructor Details
#initialize(xxp_element = nil, xyp_element = nil, yxp_element = nil, yyp_element = nil, xt_element = nil, yt_element = nil, xxp: nil, xyp: nil, yxp: nil, yyp: nil, xt: nil, yt: nil, m11: nil, m12: nil, m21: nil, m22: nil, m13: nil, m23: nil) ⇒ AffineTransform
Creates a new AffineTransform with the following Matrix:
- xxp xyp xt
- yxp yyp yt
-
The Matrix is used to transform (x,y) point coordinates as follows:
- xxp xyp xt
- x
-
[ xxp * x + xyp * y + xt ]
- yxp yyp yt
- y
-
[ yxp * x + yyp * y + yt ]
xxp is the x coordinate x product (m11) xyp is the x coordinate y product (m12) yxp is the y coordinate x product (m21) yyp is the y coordinate y product (m22) xt is the x coordinate translation (m13) yt is the y coordinate translation (m23)
The constructor accepts either the (x,y)-operation related argument/kwarg names or traditional Matrix element kwarg names
Example with (x,y)-operation kwarg names:
AffineTransform.new(xxp: 2, xyp: 3, yxp: 4, yyp: 5, xt: 6, yt: 7)
Example with traditional Matrix element kwarg names:
AffineTransform.new(m11: 2, m12: 3, m21: 4, m22: 5, m13: 6, m23: 7)
Example with standard arguments:
AffineTransform.new(2, 3, 4, 5, 6, 7)
If no arguments are supplied, it constructs an identity matrix (i.e. like calling ‘::new(xxp: 1, xyp: 0, yxp: 0, yyp: 1, xt: 0, yt: 0)`)
74 75 76 77 78 79 80 81 82 83 |
# File 'lib/perfect_shape/affine_transform.rb', line 74 def initialize(xxp_element = nil, xyp_element = nil, yxp_element = nil, yyp_element = nil, xt_element = nil, yt_element = nil, xxp: nil, xyp: nil, yxp: nil, yyp: nil, xt: nil, yt: nil, m11: nil, m12: nil, m21: nil, m22: nil, m13: nil, m23: nil) self.xxp = xxp_element || xxp || m11 || 1 self.xyp = xyp_element || xyp || m12 || 0 self.yxp = yxp_element || yxp || m21 || 0 self.yyp = yyp_element || yyp || m22 || 1 self.xt = xt_element || xt || m13 || 0 self.yt = yt_element || yt || m23 || 0 end |
Instance Attribute Details
#xt ⇒ Object Also known as: m13
Returns the value of attribute xt.
32 33 34 |
# File 'lib/perfect_shape/affine_transform.rb', line 32 def xt @xt end |
#xxp ⇒ Object Also known as: m11
Returns the value of attribute xxp.
32 33 34 |
# File 'lib/perfect_shape/affine_transform.rb', line 32 def xxp @xxp end |
#xyp ⇒ Object Also known as: m12
Returns the value of attribute xyp.
32 33 34 |
# File 'lib/perfect_shape/affine_transform.rb', line 32 def xyp @xyp end |
#yt ⇒ Object Also known as: m23
Returns the value of attribute yt.
32 33 34 |
# File 'lib/perfect_shape/affine_transform.rb', line 32 def yt @yt end |
#yxp ⇒ Object Also known as: m21
Returns the value of attribute yxp.
32 33 34 |
# File 'lib/perfect_shape/affine_transform.rb', line 32 def yxp @yxp end |
#yyp ⇒ Object Also known as: m22
Returns the value of attribute yyp.
32 33 34 |
# File 'lib/perfect_shape/affine_transform.rb', line 32 def yyp @yyp end |
Instance Method Details
#identity! ⇒ Object Also known as: reset!
Resets to identity matrix Returns self to support fluent interface chaining
117 118 119 120 121 122 123 124 125 126 |
# File 'lib/perfect_shape/affine_transform.rb', line 117 def identity! self.xxp = 1 self.xyp = 0 self.yxp = 0 self.yyp = 1 self.xt = 0 self.yt = 0 self end |
#inverse_transform_point(x_or_point, y = nil) ⇒ Object
219 220 221 |
# File 'lib/perfect_shape/affine_transform.rb', line 219 def inverse_transform_point(x_or_point, y = nil) clone.invert!.transform_point(x_or_point, y) end |
#inverse_transform_points(*xy_coordinates_or_points) ⇒ Object
229 230 231 232 233 |
# File 'lib/perfect_shape/affine_transform.rb', line 229 def inverse_transform_points(*xy_coordinates_or_points) points = xy_coordinates_or_points.first.is_a?(Array) ? xy_coordinates_or_points.first : xy_coordinates_or_points points = MultiPoint.normalize_point_array(points) points.map { |point| inverse_transform_point(point) } end |
#invert! ⇒ Object
Inverts AffineTransform matrix if invertible Raises an error if affine transform matrix is not invertible Returns self to support fluent interface chaining
132 133 134 135 136 137 138 |
# File 'lib/perfect_shape/affine_transform.rb', line 132 def invert! raise 'Cannot invert (matrix is not invertible)!' if !invertible? self.matrix_3d = matrix_3d.inverse self end |
#invertible? ⇒ Boolean
140 141 142 |
# File 'lib/perfect_shape/affine_transform.rb', line 140 def invertible? (m11 * m22 - m12 * m21) != 0 end |
#matrix_3d ⇒ Object
Returns Ruby Matrix representing Affine Transform matrix elements in 3D
208 209 210 |
# File 'lib/perfect_shape/affine_transform.rb', line 208 def matrix_3d Matrix[[xxp, xyp, xt], [yxp, yyp, yt], [0, 0, 1]] end |
#matrix_3d=(the_matrix_3d) ⇒ Object
Sets elements from a Ruby Matrix representing Affine Transform matrix elements in 3D
198 199 200 201 202 203 204 205 |
# File 'lib/perfect_shape/affine_transform.rb', line 198 def matrix_3d=(the_matrix_3d) self.xxp = the_matrix_3d[0, 0] self.xyp = the_matrix_3d[0, 1] self.xt = the_matrix_3d[0, 2] self.yxp = the_matrix_3d[1, 0] self.yyp = the_matrix_3d[1, 1] self.yt = the_matrix_3d[1, 2] end |
#multiply!(other_affine_transform) ⇒ Object
Multiplies by other AffineTransform
145 146 147 148 149 |
# File 'lib/perfect_shape/affine_transform.rb', line 145 def multiply!(other_affine_transform) self.matrix_3d = matrix_3d*other_affine_transform.matrix_3d self end |
#rotate!(degrees) ⇒ Object
Rotates AffineTransform counter-clockwise for positive angle value in degrees or clockwise for negative angle value in degrees
175 176 177 178 179 180 181 182 183 |
# File 'lib/perfect_shape/affine_transform.rb', line 175 def rotate!(degrees) degrees = Math.normalize_degrees(degrees) radians = Math.degrees_to_radians(degrees) rotation_affine_transform = AffineTransform.new(xxp: Math.cos(radians), xyp: -Math.sin(radians), yxp: Math.sin(radians), yyp: Math.cos(radians), xt: 0, yt: 0) multiply!(rotation_affine_transform) self end |
#scale!(x_or_point, y = nil) ⇒ Object
Scales AffineTransform
163 164 165 166 167 168 169 170 171 |
# File 'lib/perfect_shape/affine_transform.rb', line 163 def scale!(x_or_point, y = nil) x, y = Point.normalize_point(x_or_point, y) return unless x && y scale_affine_transform = AffineTransform.new(xxp: x, xyp: 0, yxp: 0, yyp: y, xt: 0, yt: 0) multiply!(scale_affine_transform) self end |
#shear!(x_or_point, y = nil) ⇒ Object Also known as: skew!
Shears AffineTransform by (x,y) amount
186 187 188 189 190 191 192 193 194 |
# File 'lib/perfect_shape/affine_transform.rb', line 186 def shear!(x_or_point, y = nil) x, y = Point.normalize_point(x_or_point, y) return unless x && y shear_affine_transform = AffineTransform.new(xxp: 1 + x*y, xyp: x, yxp: y, yyp: 1, xt: 0, yt: 0) multiply!(shear_affine_transform) self end |
#transform_point(x_or_point, y = nil) ⇒ Object
212 213 214 215 216 217 |
# File 'lib/perfect_shape/affine_transform.rb', line 212 def transform_point(x_or_point, y = nil) x, y = Point.normalize_point(x_or_point, y) return unless x && y [xxp*x + xyp*y + xt, yxp*x + yyp*y + yt] end |
#transform_points(*xy_coordinates_or_points) ⇒ Object
223 224 225 226 227 |
# File 'lib/perfect_shape/affine_transform.rb', line 223 def transform_points(*xy_coordinates_or_points) points = xy_coordinates_or_points.first.is_a?(Array) ? xy_coordinates_or_points.first : xy_coordinates_or_points points = MultiPoint.normalize_point_array(points) points.map { |point| transform_point(point) } end |
#translate!(x_or_point, y = nil) ⇒ Object
Translates AffineTransform
152 153 154 155 156 157 158 159 160 |
# File 'lib/perfect_shape/affine_transform.rb', line 152 def translate!(x_or_point, y = nil) x, y = Point.normalize_point(x_or_point, y) return unless x && y translation_affine_transform = AffineTransform.new(xxp: 1, xyp: 0, yxp: 0, yyp: 1, xt: x, yt: y) multiply!(translation_affine_transform) self end |