Class: Geom2D::Segment
Overview
Represents a line segment.
Instance Attribute Summary collapse
-
#end_point ⇒ Object
readonly
The end point of the segment.
-
#start_point ⇒ Object
readonly
The start point of the segment.
Instance Method Summary collapse
-
#+(other) ⇒ Object
Adds the given vector (given as array or Geom2D::Point) to the segment, i.e.
-
#+@ ⇒ Object
Returns self.
-
#-(other) ⇒ Object
Subtracts the given vector (given as array or Geom2D::Point) from the segment, i.e.
-
#-@ ⇒ Object
Returns the segment mirrored in the origin.
-
#==(other) ⇒ Object
Compares this segment to the other, returning true if the end points match.
-
#degenerate? ⇒ Boolean
Returns
true
if the segment is degenerate, i.e. -
#direction ⇒ Object
Returns the direction vector of the segment as Geom2D::Point object.
-
#horizontal? ⇒ Boolean
Returns
true
if the segment is horizontal. -
#initialize(start_point, end_point) ⇒ Segment
constructor
Creates a new Segment from the start to the end point.
-
#inspect ⇒ Object
(also: #to_s)
:nodoc:.
-
#intersect(segment) ⇒ Object
Returns the intersection of this segment with the given one:.
-
#length ⇒ Object
Returns the length of the segment.
-
#max ⇒ Object
Returns the right-most top-most point of the segment (either the start or the end point).
-
#min ⇒ Object
Returns the left-most bottom-most point of the segment (either the start or the end point).
-
#reverse! ⇒ Object
Reverses the start and end point.
-
#slope ⇒ Object
Returns the slope of the segment.
-
#vertical? ⇒ Boolean
Returns
true
if the segment is vertical. -
#y_intercept ⇒ Object
Returns the y-intercept, i.e.
Constructor Details
#initialize(start_point, end_point) ⇒ Segment
Creates a new Segment from the start to the end point. The arguments are converted to proper Geom2D::Point objects if needed.
28 29 30 31 |
# File 'lib/geom2d/segment.rb', line 28 def initialize(start_point, end_point) @start_point = Geom2D::Point(start_point) @end_point = Geom2D::Point(end_point) end |
Instance Attribute Details
#end_point ⇒ Object (readonly)
The end point of the segment.
24 25 26 |
# File 'lib/geom2d/segment.rb', line 24 def end_point @end_point end |
#start_point ⇒ Object (readonly)
The start point of the segment.
21 22 23 |
# File 'lib/geom2d/segment.rb', line 21 def start_point @start_point end |
Instance Method Details
#+(other) ⇒ Object
Adds the given vector (given as array or Geom2D::Point) to the segment, i.e. performs a translation.
174 175 176 177 178 179 180 181 |
# File 'lib/geom2d/segment.rb', line 174 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 |
#+@ ⇒ Object
Returns self.
163 164 165 |
# File 'lib/geom2d/segment.rb', line 163 def +@ self end |
#-(other) ⇒ Object
Subtracts the given vector (given as array or Geom2D::Point) from the segment, i.e. performs a translation.
185 186 187 188 189 190 191 192 |
# File 'lib/geom2d/segment.rb', line 185 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 |
#-@ ⇒ Object
Returns the segment mirrored in the origin.
168 169 170 |
# File 'lib/geom2d/segment.rb', line 168 def -@ Segment.new(-start_point, -end_point) end |
#==(other) ⇒ Object
Compares this segment to the other, returning true if the end points match.
195 196 197 198 |
# File 'lib/geom2d/segment.rb', line 195 def ==(other) return false unless other.kind_of?(Segment) start_point == other.start_point && end_point == other.end_point end |
#degenerate? ⇒ Boolean
Returns true
if the segment is degenerate, i.e. if it consists only of a point.
34 35 36 |
# File 'lib/geom2d/segment.rb', line 34 def degenerate? @start_point == @end_point end |
#direction ⇒ Object
Returns the direction vector of the segment as Geom2D::Point object.
74 75 76 |
# File 'lib/geom2d/segment.rb', line 74 def direction end_point - start_point end |
#horizontal? ⇒ Boolean
Returns true
if the segment is horizontal.
44 45 46 |
# File 'lib/geom2d/segment.rb', line 44 def horizontal? float_equal(start_point.y, end_point.y) end |
#inspect ⇒ Object Also known as: to_s
:nodoc:
200 201 202 |
# File 'lib/geom2d/segment.rb', line 200 def inspect # :nodoc: "Segment[#{start_point}-#{end_point}]" end |
#intersect(segment) ⇒ Object
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.
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/geom2d/segment.rb', line 110 def intersect(segment) p0 = start_point p1 = segment.start_point d0x = end_point.x - start_point.x d0y = end_point.y - start_point.y d1x = segment.end_point.x - segment.start_point.x d1y = segment.end_point.y - segment.start_point.y ex = p1.x - p0.x ey = p1.y - p0.y cross = (d0x * d1y - d1x * d0y).to_f # cross product of direction vectors if cross.abs > Utils.precision # segments are not parallel s = (ex * d1y - d1x * ey) / cross return nil if s < 0 || s > 1 t = (ex * d0y - d0x * ey) / cross return nil if t < 0 || t > 1 result = p0 + Point.new(s * d0x, s * d0y) return case result when start_point then start_point when end_point then end_point when segment.start_point then segment.start_point when segment.end_point then segment.end_point else result end end return nil if (ex * d0y - d0x * ey).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 |
#length ⇒ Object
Returns the length of the segment.
69 70 71 |
# File 'lib/geom2d/segment.rb', line 69 def length start_point.distance(end_point) end |
#max ⇒ Object
Returns the right-most top-most point of the segment (either the start or the end point).
59 60 61 62 63 64 65 66 |
# File 'lib/geom2d/segment.rb', line 59 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 |
#min ⇒ Object
Returns the left-most bottom-most point of the segment (either the start or the end point).
49 50 51 52 53 54 55 56 |
# File 'lib/geom2d/segment.rb', line 49 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 |
#reverse! ⇒ Object
Reverses the start and end point.
101 102 103 |
# File 'lib/geom2d/segment.rb', line 101 def reverse! @start_point, @end_point = @end_point, @start_point end |
#slope ⇒ Object
Returns the slope of the segment.
If the segment is vertical, Float::INFINITY is returned.
81 82 83 84 85 86 87 |
# File 'lib/geom2d/segment.rb', line 81 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 |
#vertical? ⇒ Boolean
Returns true
if the segment is vertical.
39 40 41 |
# File 'lib/geom2d/segment.rb', line 39 def vertical? float_equal(start_point.x, end_point.x) end |
#y_intercept ⇒ Object
Returns the y-intercept, i.e. the point on the y-axis where the segment does/would intercept it.
91 92 93 94 95 96 97 98 |
# File 'lib/geom2d/segment.rb', line 91 def y_intercept slope = self.slope if slope == Float::INFINITY nil else -start_point.x * slope + start_point.y end end |