Class: HexaPDF::Content::GraphicObject::Arc
- Inherits:
-
Object
- Object
- HexaPDF::Content::GraphicObject::Arc
- Includes:
- Utils::MathHelpers
- Defined in:
- lib/hexapdf/content/graphic_object/arc.rb
Overview
This class describes an elliptical in center parameterization arc that is approximated using Bezier curves. It can be used to draw circles, circular arcs, ellipses and elliptical arcs, all either in clockwise or counterclockwise direction and optionally inclined in respect to the x-axis.
See: ELL - spaceroots.org/documents/ellipse/elliptical-arc.pdf
Instance Attribute Summary collapse
-
#a ⇒ Object
readonly
Length of semi-major axis.
-
#b ⇒ Object
readonly
Length of semi-minor axis.
-
#clockwise ⇒ Object
readonly
Direction of arc - if
true
in clockwise direction, else in counterclockwise direction. -
#cx ⇒ Object
readonly
x-coordinate of center point.
-
#cy ⇒ Object
readonly
y-coordinate of center point.
-
#end_angle ⇒ Object
readonly
End angle in degrees.
-
#inclination ⇒ Object
readonly
Inclination in degrees of semi-major axis in respect to x-axis.
-
#max_curves ⇒ Object
The maximal number of curves used for approximating a complete ellipse.
-
#start_angle ⇒ Object
readonly
Start angle in degrees.
Class Method Summary collapse
-
.configure(**kwargs) ⇒ Object
Creates and configures a new elliptical arc object.
Instance Method Summary collapse
-
#configure(cx: nil, cy: nil, a: nil, b: nil, start_angle: nil, end_angle: nil, inclination: nil, clockwise: nil) ⇒ Object
Configures the arc with.
-
#curves ⇒ Object
Returns an array of arrays that contain the points for the Bezier curves which are used for approximating the elliptical arc between #start_point and #end_point.
-
#draw(canvas, move_to_start: true) ⇒ Object
Draws the arc on the given Canvas.
-
#end_point ⇒ Object
Returns the end point of the elliptical arc.
-
#initialize ⇒ Arc
constructor
Creates an elliptical arc with default values (a counterclockwise unit circle at the origin).
-
#point_at(angle) ⇒ Object
Returns the point at
angle
degrees on the ellipse. -
#start_point ⇒ Object
Returns the start point of the elliptical arc.
Methods included from Utils::MathHelpers
Constructor Details
#initialize ⇒ Arc
Creates an elliptical arc with default values (a counterclockwise unit circle at the origin).
93 94 95 96 97 98 99 100 101 102 |
# File 'lib/hexapdf/content/graphic_object/arc.rb', line 93 def initialize @max_curves = 6 @cx = @cy = 0 @a = @b = 1 @start_angle = 0 @end_angle = 360 @inclination = 0 @clockwise = false calculate_cached_values end |
Instance Attribute Details
#a ⇒ Object (readonly)
Length of semi-major axis
74 75 76 |
# File 'lib/hexapdf/content/graphic_object/arc.rb', line 74 def a @a end |
#b ⇒ Object (readonly)
Length of semi-minor axis
77 78 79 |
# File 'lib/hexapdf/content/graphic_object/arc.rb', line 77 def b @b end |
#clockwise ⇒ Object (readonly)
Direction of arc - if true
in clockwise direction, else in counterclockwise direction
89 90 91 |
# File 'lib/hexapdf/content/graphic_object/arc.rb', line 89 def clockwise @clockwise end |
#cx ⇒ Object (readonly)
x-coordinate of center point
68 69 70 |
# File 'lib/hexapdf/content/graphic_object/arc.rb', line 68 def cx @cx end |
#cy ⇒ Object (readonly)
y-coordinate of center point
71 72 73 |
# File 'lib/hexapdf/content/graphic_object/arc.rb', line 71 def cy @cy end |
#end_angle ⇒ Object (readonly)
End angle in degrees
83 84 85 |
# File 'lib/hexapdf/content/graphic_object/arc.rb', line 83 def end_angle @end_angle end |
#inclination ⇒ Object (readonly)
Inclination in degrees of semi-major axis in respect to x-axis
86 87 88 |
# File 'lib/hexapdf/content/graphic_object/arc.rb', line 86 def inclination @inclination end |
#max_curves ⇒ Object
The maximal number of curves used for approximating a complete ellipse.
The higher the value the better the approximation will be but it will also take longer to compute. The value should not be lower than 4. Default value is 6 which already provides a good approximation.
65 66 67 |
# File 'lib/hexapdf/content/graphic_object/arc.rb', line 65 def max_curves @max_curves end |
#start_angle ⇒ Object (readonly)
Start angle in degrees
80 81 82 |
# File 'lib/hexapdf/content/graphic_object/arc.rb', line 80 def start_angle @start_angle end |
Class Method Details
.configure(**kwargs) ⇒ Object
Creates and configures a new elliptical arc object.
See #configure for the allowed keyword arguments.
56 57 58 |
# File 'lib/hexapdf/content/graphic_object/arc.rb', line 56 def self.configure(**kwargs) new.configure(**kwargs) end |
Instance Method Details
#configure(cx: nil, cy: nil, a: nil, b: nil, start_angle: nil, end_angle: nil, inclination: nil, clockwise: nil) ⇒ Object
Configures the arc with
-
center point (
cx
,cy
), -
semi-major axis
a
, -
semi-minor axis
b
, -
start angle of
start_angle
degrees, -
end angle of
end_angle
degrees and -
an inclination in respect to the x-axis of
inclination
degrees.
The clockwise
argument determines if the arc is drawn in the counterclockwise direction (false
) or in the clockwise direction (true
).
Any arguments not specified are not modified and retain their old value, see #initialize for the inital values.
Returns self.
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/hexapdf/content/graphic_object/arc.rb', line 120 def configure(cx: nil, cy: nil, a: nil, b: nil, start_angle: nil, end_angle: nil, inclination: nil, clockwise: nil) @cx = cx if cx @cy = cy if cy @a = a.abs if a @b = b.abs if b if @a == 0 || @b == 0 raise HexaPDF::Error, "Semi-major and semi-minor axes must be greater than zero" end @start_angle = start_angle if start_angle @end_angle = end_angle if end_angle @inclination = inclination if inclination @clockwise = clockwise unless clockwise.nil? calculate_cached_values self end |
#curves ⇒ Object
Returns an array of arrays that contain the points for the Bezier curves which are used for approximating the elliptical arc between #start_point and #end_point.
One subarray consists of
[end_point_x, end_point_y, p1: control_point_1, p2: control_point_2]
The first start point is the one returned by #start_point, the other start points are the end points of the curve before.
The format of the subarray is chosen so that it can be fed to the Canvas#curve_to method by using array splatting.
See: ELL s3.4.1 (especially the last box on page 18)
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
# File 'lib/hexapdf/content/graphic_object/arc.rb', line 182 def curves result = [] # Number of curves to use, maximal segment angle is 2*PI/max_curves n = [@max_curves, ((@end_eta - @start_eta).abs / (2 * Math::PI / @max_curves)).ceil].min d_eta = (@end_eta - @start_eta) / n alpha = Math.sin(d_eta) * (Math.sqrt(4 + 3 * Math.tan(d_eta / 2)**2) - 1) / 3 eta2 = @start_eta p2x, p2y = evaluate(eta2) p2x_prime, p2y_prime = derivative_evaluate(eta2) 1.upto(n) do p1x = p2x p1y = p2y p1x_prime = p2x_prime p1y_prime = p2y_prime eta2 += d_eta p2x, p2y = evaluate(eta2) p2x_prime, p2y_prime = derivative_evaluate(eta2) result << [p2x, p2y, {p1: [p1x + alpha * p1x_prime, p1y + alpha * p1y_prime], p2: [p2x - alpha * p2x_prime, p2y - alpha * p2y_prime]}] end result end |
#draw(canvas, move_to_start: true) ⇒ Object
Draws the arc on the given Canvas.
If the argument move_to_start
is true
, a Canvas#move_to operation is executed to move the current point to the start point of the arc. Otherwise it is assumed that the current point already coincides with the start point
The #max_curves value is set to the value of the configuration option ‘graphic_object.arc.max_curves’ before drawing.
162 163 164 165 166 |
# File 'lib/hexapdf/content/graphic_object/arc.rb', line 162 def draw(canvas, move_to_start: true) @max_curves = canvas.context.document.config['graphic_object.arc.max_curves'] canvas.move_to(*start_point) if move_to_start curves.each {|x, y, hash| canvas.curve_to(x, y, **hash) } end |
#end_point ⇒ Object
Returns the end point of the elliptical arc.
143 144 145 |
# File 'lib/hexapdf/content/graphic_object/arc.rb', line 143 def end_point evaluate(@end_eta) end |
#point_at(angle) ⇒ Object
Returns the point at angle
degrees on the ellipse.
Note that the point may not lie on the arc itself!
150 151 152 |
# File 'lib/hexapdf/content/graphic_object/arc.rb', line 150 def point_at(angle) evaluate(angle_to_param(angle)) end |
#start_point ⇒ Object
Returns the start point of the elliptical arc.
138 139 140 |
# File 'lib/hexapdf/content/graphic_object/arc.rb', line 138 def start_point evaluate(@start_eta) end |