Class: Sevgi::Geometry::Arc
- Inherits:
-
Element::Arced
- Object
- Element
- Element::Arced
- Sevgi::Geometry::Arc
- Defined in:
- lib/sevgi/geometry/elements/arc.rb
Overview
Finite, directed portion of an Ellipse, with less than one full turn. Positive extent is clockwise in screen coordinates. Zero extent has a single-point trace and draws nothing.
Instance Attribute Summary collapse
-
#ellipse ⇒ Sevgi::Geometry::Ellipse
readonly
Immutable parent ellipse.
-
#extent ⇒ Float
readonly
Signed extent in degrees.
-
#starting_angle ⇒ Float
readonly
Local starting parameter angle in degrees.
Class Method Summary collapse
-
.[](rx, ry = rx, extent:, position: Origin, rotation: 0, starting_angle: 0) ⇒ Sevgi::Geometry::Arc
Builds a circular or elliptical arc from dimensions and angles.
Instance Method Summary collapse
-
#approx(precision = nil) ⇒ Sevgi::Geometry::Arc
Rebuilds an arc from rounded canonical fields.
-
#box ⇒ Sevgi::Geometry::Rect
Returns bounds of the finite trace without display rounding.
-
#circular? ⇒ Boolean
Reports whether the parent radii are exactly equal.
-
#clockwise? ⇒ Boolean
Reports whether the traversal is clockwise.
-
#counterclockwise? ⇒ Boolean
Reports whether the traversal is counterclockwise.
-
#draw(node, **attributes) ⇒ Object
Draws the finite trace as an SVG path using unrounded geometry.
-
#empty? ⇒ Boolean
Reports whether angular extent is exactly zero, independently of numeric precision.
-
#ending ⇒ Sevgi::Geometry::Point
Returns the ending point.
-
#ending_angle ⇒ Float
Returns the unnormalized ending parameter angle.
-
#equation ⇒ Sevgi::Geometry::Equation::Quadratic
Returns the complete parent ellipse carrier.
-
#equations ⇒ Array<Sevgi::Geometry::Equation::Quadratic>
Returns the immutable parent carrier collection.
-
#initialize(ellipse, starting_angle:, extent:) ⇒ void
constructor
Creates a finite arc.
-
#inside?(point) ⇒ Boolean
Reports whether a point belongs to the open boundary.
-
#length ⇒ Float
Returns the non-negative finite-trace length, independently of thread precision.
-
#on?(point) ⇒ Boolean
Reports membership using endpoint coordinate tolerance and the finite angular span.
-
#position ⇒ Sevgi::Geometry::Point
(also: #center)
Returns the parent ellipse center, not the starting endpoint.
-
#reflect(x: true, y: true) ⇒ Sevgi::Geometry::Arc
Returns an arc reflected across the selected axes.
-
#reverse ⇒ Sevgi::Geometry::Arc
Reverses traversal without changing the finite trace.
-
#rotate(angle) ⇒ Sevgi::Geometry::Arc
Rotates the arc around the origin without changing local angles.
-
#rotation ⇒ Float
Returns the parent ellipse rotation in degrees.
-
#rx ⇒ Float
Returns the parent local x radius.
-
#ry ⇒ Float
Returns the parent local y radius.
-
#scale(sx, sy = Undefined) ⇒ Sevgi::Geometry::Arc
Scales the arc from the origin, preserving its finite trace and traversal.
-
#skew(ax, ay = Undefined) ⇒ Sevgi::Geometry::Arc
Skews the arc from the origin.
-
#skew_x(angle) ⇒ Sevgi::Geometry::Arc
Skews the arc along x.
-
#skew_y(angle) ⇒ Sevgi::Geometry::Arc
Skews the arc along y.
-
#starting ⇒ Sevgi::Geometry::Point
Returns the starting point.
-
#translate(dx, dy = Undefined) ⇒ Sevgi::Geometry::Arc
Returns a translated arc without changing local angles.
Methods inherited from Element::Arced
Methods inherited from Element
#at, #closed?, #ignorable?, #intersection, lined
Constructor Details
#initialize(ellipse, starting_angle:, extent:) ⇒ void
Creates a finite arc. Use the bracket constructor or Ellipse#arc.
45 46 47 48 49 50 51 |
# File 'lib/sevgi/geometry/elements/arc.rb', line 45 def initialize(ellipse, starting_angle:, extent:) super() @ellipse = ellipse @starting_angle = Real[:starting_angle, starting_angle] @extent = Real[:extent, extent] Error.("Arc extent must be between -360 and 360 degrees") unless @extent.abs < 360 end |
Instance Attribute Details
#ellipse ⇒ Sevgi::Geometry::Ellipse (readonly)
Returns immutable parent ellipse.
33 34 35 |
# File 'lib/sevgi/geometry/elements/arc.rb', line 33 def ellipse @ellipse end |
#extent ⇒ Float (readonly)
Returns signed extent in degrees.
35 36 37 |
# File 'lib/sevgi/geometry/elements/arc.rb', line 35 def extent @extent end |
#starting_angle ⇒ Float (readonly)
Returns local starting parameter angle in degrees.
37 38 39 |
# File 'lib/sevgi/geometry/elements/arc.rb', line 37 def starting_angle @starting_angle end |
Class Method Details
.[](rx, ry = rx, extent:, position: Origin, rotation: 0, starting_angle: 0) ⇒ Sevgi::Geometry::Arc
Builds a circular or elliptical arc from dimensions and angles.
23 24 25 |
# File 'lib/sevgi/geometry/elements/arc.rb', line 23 def self.[](rx, ry = rx, extent:, position: Origin, rotation: 0, starting_angle: 0) Ellipse[rx, ry, position:, rotation:].arc(starting_angle:, extent:) end |
Instance Method Details
#approx(precision = nil) ⇒ Sevgi::Geometry::Arc
Rebuilds an arc from rounded canonical fields.
58 59 60 61 62 |
# File 'lib/sevgi/geometry/elements/arc.rb', line 58 def approx(precision = nil) ellipse .approx(precision) .arc(starting_angle: F.approx(starting_angle, precision), extent: F.approx(extent, precision)) end |
#box ⇒ Sevgi::Geometry::Rect
Returns bounds of the finite trace without display rounding.
66 67 68 69 70 |
# File 'lib/sevgi/geometry/elements/arc.rb', line 66 def box points = [starting, ending, *ellipse.send(:extrema).select { contains_angle?(it) }.map { ellipse.point(it) }] xs, ys = points.map(&:x), points.map(&:y) Rect.from_corners([xs.min, ys.min], [xs.max, ys.max]) end |
#circular? ⇒ Boolean
Reports whether the parent radii are exactly equal.
74 |
# File 'lib/sevgi/geometry/elements/arc.rb', line 74 def circular? = ellipse.circular? |
#clockwise? ⇒ Boolean
Reports whether the traversal is clockwise.
78 |
# File 'lib/sevgi/geometry/elements/arc.rb', line 78 def clockwise? = extent.positive? |
#counterclockwise? ⇒ Boolean
Reports whether the traversal is counterclockwise.
82 |
# File 'lib/sevgi/geometry/elements/arc.rb', line 82 def counterclockwise? = extent.negative? |
#draw(node, **attributes) ⇒ Object
Draws the finite trace as an SVG path using unrounded geometry.
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/sevgi/geometry/elements/arc.rb', line 90 def draw(node, **attributes) return node.path(d: "", **attributes) if empty? return node.path(d: split_path, **attributes) if extent.abs > 180 && starting == ending node.ArcTo( x1: starting.x, y1: starting.y, x2: ending.x, y2: ending.y, rx:, ry:, rotation:, large: extent.abs > 180, sweep: clockwise?, **attributes ) end |
#empty? ⇒ Boolean
Reports whether angular extent is exactly zero, independently of numeric precision.
112 |
# File 'lib/sevgi/geometry/elements/arc.rb', line 112 def empty? = extent.zero? |
#ending ⇒ Sevgi::Geometry::Point
Returns the ending point.
116 |
# File 'lib/sevgi/geometry/elements/arc.rb', line 116 def ending = ellipse.point(ending_angle) |
#ending_angle ⇒ Float
Returns the unnormalized ending parameter angle.
120 |
# File 'lib/sevgi/geometry/elements/arc.rb', line 120 def ending_angle = starting_angle + extent |
#equation ⇒ Sevgi::Geometry::Equation::Quadratic
Returns the complete parent ellipse carrier.
124 |
# File 'lib/sevgi/geometry/elements/arc.rb', line 124 def equation = ellipse.equation |
#equations ⇒ Array<Sevgi::Geometry::Equation::Quadratic>
Returns the immutable parent carrier collection.
128 |
# File 'lib/sevgi/geometry/elements/arc.rb', line 128 def equations = ellipse.equations |
#inside?(point) ⇒ Boolean
Reports whether a point belongs to the open boundary.
134 |
# File 'lib/sevgi/geometry/elements/arc.rb', line 134 def inside?(point) = on?(point) |
#length ⇒ Float
Returns the non-negative finite-trace length, independently of thread precision.
139 |
# File 'lib/sevgi/geometry/elements/arc.rb', line 139 def length = @length ||= empty? ? 0.0 : ellipse.send(:arc_length, starting_angle, extent) |
#on?(point) ⇒ Boolean
Reports membership using endpoint coordinate tolerance and the finite angular span.
145 146 147 148 149 150 |
# File 'lib/sevgi/geometry/elements/arc.rb', line 145 def on?(point) point = Tuple[Point, point] return true if point.eq?(starting) || point.eq?(ending) !empty? && ellipse.on?(point) && contains_angle?(ellipse.send(:parameter, point)) end |
#position ⇒ Sevgi::Geometry::Point Also known as: center
Returns the parent ellipse center, not the starting endpoint.
154 |
# File 'lib/sevgi/geometry/elements/arc.rb', line 154 def position = ellipse.position |
#reflect(x: true, y: true) ⇒ Sevgi::Geometry::Arc
Returns an arc reflected across the selected axes.
161 |
# File 'lib/sevgi/geometry/elements/arc.rb', line 161 def reflect(x: true, y: true) = affine(:reflect, x:, y:) |
#reverse ⇒ Sevgi::Geometry::Arc
Reverses traversal without changing the finite trace.
165 |
# File 'lib/sevgi/geometry/elements/arc.rb', line 165 def reverse = ellipse.arc(starting_angle: ending_angle, extent: -extent) |
#rotate(angle) ⇒ Sevgi::Geometry::Arc
Rotates the arc around the origin without changing local angles.
171 |
# File 'lib/sevgi/geometry/elements/arc.rb', line 171 def rotate(angle) = ellipse.rotate(angle).arc(starting_angle:, extent:) |
#rotation ⇒ Float
Returns the parent ellipse rotation in degrees.
175 |
# File 'lib/sevgi/geometry/elements/arc.rb', line 175 def rotation = ellipse.rotation |
#rx ⇒ Float
Returns the parent local x radius.
179 |
# File 'lib/sevgi/geometry/elements/arc.rb', line 179 def rx = ellipse.rx |
#ry ⇒ Float
Returns the parent local y radius.
183 |
# File 'lib/sevgi/geometry/elements/arc.rb', line 183 def ry = ellipse.ry |
#scale(sx, sy = Undefined) ⇒ Sevgi::Geometry::Arc
Scales the arc from the origin, preserving its finite trace and traversal.
190 191 192 193 194 195 |
# File 'lib/sevgi/geometry/elements/arc.rb', line 190 def scale(sx, sy = Undefined) sx, sy = Real[:sx, sx], Real[:sy, Undefined.default(sy, sx)] return ellipse.scale(sx, sy).arc(starting_angle:, extent:) if sx == sy affine(:scale, sx, sy) end |
#skew(ax, ay = Undefined) ⇒ Sevgi::Geometry::Arc
Skews the arc from the origin.
202 |
# File 'lib/sevgi/geometry/elements/arc.rb', line 202 def skew(ax, ay = Undefined) = affine(:skew, ax, ay) |
#skew_x(angle) ⇒ Sevgi::Geometry::Arc
Skews the arc along x.
208 |
# File 'lib/sevgi/geometry/elements/arc.rb', line 208 def skew_x(angle) = affine(:skew_x, angle) |
#skew_y(angle) ⇒ Sevgi::Geometry::Arc
Skews the arc along y.
214 |
# File 'lib/sevgi/geometry/elements/arc.rb', line 214 def skew_y(angle) = affine(:skew_y, angle) |
#starting ⇒ Sevgi::Geometry::Point
Returns the starting point.
218 |
# File 'lib/sevgi/geometry/elements/arc.rb', line 218 def starting = ellipse.point(starting_angle) |
#translate(dx, dy = Undefined) ⇒ Sevgi::Geometry::Arc
Returns a translated arc without changing local angles.
225 |
# File 'lib/sevgi/geometry/elements/arc.rb', line 225 def translate(dx, dy = Undefined) = ellipse.translate(dx, dy).arc(starting_angle:, extent:) |