class Geom2D::Segment
Represents a line segment.
Attributes
The end point of the segment.
The start point of the segment.
Public Class Methods
Creates a new Segment
from the start to the end point. The arguments are converted to proper Geom2D::Point
objects if needed.
# File lib/geom2d/segment.rb, line 27 def initialize(start_point, end_point) @start_point = Geom2D::Point(start_point) @end_point = Geom2D::Point(end_point) end
Public Instance Methods
Adds the given vector (given as array or Geom2D::Point
) to the segment, i.e. performs a translation.
# File lib/geom2d/segment.rb, line 168 def +(other) case other when Point, Array Segment.new(start_point + other, end_point + other) else raise ArgumentError, "Invalid argument class, must be Point" end end
Returns self.
# File lib/geom2d/segment.rb, line 157 def +@ self end
Subtracts the given vector (given as array or Geom2D::Point
) from the segment, i.e. performs a translation.
# File lib/geom2d/segment.rb, line 179 def -(other) case other when Point, Array Segment.new(start_point - other, end_point - other) else raise ArgumentError, "Invalid argument class, must be Point" end end
Returns the segment mirrored in the origin.
# File lib/geom2d/segment.rb, line 162 def -@ Segment.new(-start_point, -end_point) end
Compares this segment to the other, returning true if the end points match.
# File lib/geom2d/segment.rb, line 189 def ==(other) return false unless other.kind_of?(Segment) start_point == other.start_point && end_point == other.end_point end
Returns true
if the segment is degenerate, i.e. if it consists only of a point.
# File lib/geom2d/segment.rb, line 33 def degenerate? @start_point == @end_point end
Returns the direction vector of the segment as Geom2D::Point
object.
# File lib/geom2d/segment.rb, line 73 def direction end_point - start_point end
Returns true
if the segment is horizontal.
# File lib/geom2d/segment.rb, line 43 def horizontal? float_equal(start_point.y, end_point.y) end
Returns the intersection of this segment with the given one:
nil
-
No intersections
Geom2D::Point
-
Exactly one point
Geom2D::Segment
-
The segment overlapping both other segments.
# File lib/geom2d/segment.rb, line 109 def intersect(segment) p0 = start_point p1 = segment.start_point d0 = direction d1 = segment.direction e = p1 - p0 cross = d0.wedge(d1).to_f # cross product of direction vectors if cross.abs > Utils.precision # segments are not parallel s = e.wedge(d1) / cross return nil if s < 0 || s > 1 t = e.wedge(d0) / cross return nil if t < 0 || t > 1 result = p0 + [s * d0.x, s * d0.y] result = start_point if result == start_point result = end_point if result == end_point result = segment.start_point if result == segment.start_point result = segment.end_point if result == segment.end_point return result end return nil if e.wedge(d0).abs > Utils.precision # non-intersecting parallel segment lines e0 = end_point e1 = segment.end_point # sort segment points by x-value p0, e0 = e0, p0 if float_compare(p0.x, e0.x) > 0 p1, e1 = e1, p1 if float_compare(p1.x, e1.x) > 0 if float_compare(p0.x, p1.x) > 0 _p0, p1, e0, e1 = p1, p0, e1, e0 end # p0 before or equal to p1 if float_compare(e0.x, p1.x) < 0 # e0 before p1 nil # no common point elsif float_compare(e1.x, e0.x) <= 0 # e1 before or equal to e0 self.class.new(p1, e1) # p1-e1 inside p0-e0 elsif float_compare(p1.x, e0.x) == 0 # common endpoint p1=e0 p1 else self.class.new(p1, e0) # s1 overlaps end of s0 end end
Returns the length of the segment.
# File lib/geom2d/segment.rb, line 68 def length start_point.distance(end_point) end
Returns the right-most top-most point of the segment (either the start or the end point).
# File lib/geom2d/segment.rb, line 58 def max if start_point.x > end_point.x || (float_equal(start_point.x, end_point.x) && start_point.y > end_point.y) start_point else end_point end end
Returns the left-most bottom-most point of the segment (either the start or the end point).
# File lib/geom2d/segment.rb, line 48 def min if start_point.x < end_point.x || (float_equal(start_point.x, end_point.x) && start_point.y < end_point.y) start_point else end_point end end
Reverses the start and end point.
# File lib/geom2d/segment.rb, line 100 def reverse! @start_point, @end_point = @end_point, @start_point end
Returns the slope of the segment.
If the segment is vertical, Float::INFINITY is returned.
# File lib/geom2d/segment.rb, line 80 def slope if float_equal(start_point.x, end_point.x) Float::INFINITY else (end_point.y - start_point.y).to_f / (end_point.x - start_point.x) end end
Returns true
if the segment is vertical.
# File lib/geom2d/segment.rb, line 38 def vertical? float_equal(start_point.x, end_point.x) end
Returns the y-intercept, i.e. the point on the y-axis where the segment does/would intercept it.
# File lib/geom2d/segment.rb, line 90 def y_intercept slope = self.slope if slope == Float::INFINITY nil else -start_point.x * slope + start_point.y end end