Class: Euclidean::Edge
- Inherits:
-
Object
- Object
- Euclidean::Edge
- Defined in:
- lib/euclidean/edge.rb
Overview
An edge. It’s a line segment between 2 points. Generally part of a Polygon.
Usage
edge = Geometry::Edge([1,1], [2,2])
Instance Attribute Summary collapse
-
#first ⇒ Object
readonly
Returns the value of attribute first.
-
#last ⇒ Object
readonly
Returns the value of attribute last.
Instance Method Summary collapse
-
#<=>(point) ⇒ Boolean
Returns 1 if the Point is strictly to the left of the receiver, -1 to the right, and 0 if the point is on the receiver.
-
#==(other) ⇒ Object
Two Edges are equal if both have equal Points in the same order.
-
#connected?(other) ⇒ Bool
Returns true if the receiver and the passed Edge share an endpoint.
-
#direction ⇒ Vector
A unit Vector pointing from first to last.
-
#height ⇒ Object
Return the Edge‘s length along the Y axis.
- #initialize(point0, point1) ⇒ Edge constructor
- #inspect ⇒ Object (also: #to_s)
-
#intersection(other) ⇒ Point
Find the intersection of two Edges (bloggingmath.wordpress.com/2009/05/29/line-segment-intersection/).
-
#parallel?(edge) ⇒ Bool
Returns true if the passed Edge is parallel to the receiver.
-
#reverse ⇒ Object
Return a new Edge with swapped endpoints.
-
#reverse! ⇒ Object
In-place swap the endpoints.
- #to_a ⇒ Object
-
#vector ⇒ Vector
A Vector pointing from first to last.
-
#width ⇒ Object
Return the Edge‘s length along the X axis.
Constructor Details
#initialize(point0, point1) ⇒ Edge
Construct a new Euclidean::Edge object from any two things that can be converted to a Point.
17 18 19 |
# File 'lib/euclidean/edge.rb', line 17 def initialize(point0, point1) @first, @last = [Point[point0], Point[point1]] end |
Instance Attribute Details
#first ⇒ Object (readonly)
Returns the value of attribute first.
13 14 15 |
# File 'lib/euclidean/edge.rb', line 13 def first @first end |
#last ⇒ Object (readonly)
Returns the value of attribute last.
13 14 15 |
# File 'lib/euclidean/edge.rb', line 13 def last @last end |
Instance Method Details
#<=>(point) ⇒ Boolean
Returns 1 if the Point is strictly to the left of the receiver, -1 to the right, and 0 if the point is on the receiver
28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/euclidean/edge.rb', line 28 def <=>(point) case point when Point k = (@last.x - @first.x) * (point.y - @first.y) - (point.x - @first.x) * (@last.y - @first.y) if 0 == k (((@first.x <=> point.x) + (@last.x <=> point.x)).abs <= 1) && (((@first.y <=> point.y) + (@last.y <=> point.y)).abs <= 1) ? 0 : nil else k <=> 0 end else raise ArgumentError, "Can't spaceship with #{point.class}" end end |
#==(other) ⇒ Object
Two Edges are equal if both have equal Points in the same order
22 23 24 |
# File 'lib/euclidean/edge.rb', line 22 def ==(other) (@first == other.first) && (@last == other.last) end |
#connected?(other) ⇒ Bool
Returns true if the receiver and the passed Euclidean::Edge share an endpoint
44 45 46 |
# File 'lib/euclidean/edge.rb', line 44 def connected?(other) (@first == other.last) || (@last == other.first) || (@first == other.first) || (@last == other.last) end |
#direction ⇒ Vector
Returns A unit Vector pointing from first to last.
49 50 51 |
# File 'lib/euclidean/edge.rb', line 49 def direction self.vector.normalize end |
#height ⇒ Object
Return the Euclidean::Edge‘s length along the Y axis
54 55 56 |
# File 'lib/euclidean/edge.rb', line 54 def height (@first.y - @last.y).abs end |
#inspect ⇒ Object Also known as: to_s
58 59 60 |
# File 'lib/euclidean/edge.rb', line 58 def inspect 'Edge(' + @first.inspect + ', ' + @last.inspect + ')' end |
#intersection(other) ⇒ Point
Find the intersection of two Euclidean::Edges (bloggingmath.wordpress.com/2009/05/29/line-segment-intersection/)
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/euclidean/edge.rb', line 66 def intersection(other) return self.first if (self.first == other.first) or (self.first == other.last) return self.last if (self.last == other.first) or (self.last == other.last) p0, p1 = self.first, self.last p2, p3 = other.first, other.last v1, v2 = self.vector, other.vector denominator = v1[0] * v2[1] - v2[0] * v1[1] # v1 x v2 p = p0 - p2 if denominator == 0 # collinear, so check for overlap if 0 == (-v1[1] * p.x + v1[0] * p.y) # collinear? # The edges are collinear, but do they overlap? # Project them onto the x and y axes to find out left1, right1 = [self.first[0], self.last[0]].sort bottom1, top1 = [self.first[1], self.last[1]].sort left2, right2 = [other.first[0], other.last[0]].sort bottom2, top2 = [other.first[1], other.last[1]].sort !((left2 > right1) || (right2 < left1) || (top2 < bottom1) || (bottom2 > top1)) else nil end else s = (-v1[1] * p.x + v1[0] * p.y) / denominator # v1 x (p0 - p2) / denominator t = ( v2[0] * p.y - v2[1] * p.x) / denominator # v2 x (p0 - p2) / denominator p0 + v1 * t if ((0..1) === s) && ((0..1) === t) end end |
#parallel?(edge) ⇒ Bool
Returns true if the passed Euclidean::Edge is parallel to the receiver
99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/euclidean/edge.rb', line 99 def parallel?(edge) v1, v2 = self.direction, edge.direction winding = v1[0]*v2[1] - v1[1]*v2[0] if 0 == winding # collinear? if v1 == v2 true # 1 # same direction else true # -1 # opposite direction end else false end end |
#reverse ⇒ Object
Return a new Euclidean::Edge with swapped endpoints
114 115 116 |
# File 'lib/euclidean/edge.rb', line 114 def reverse Edge.new(@last, @first) end |
#reverse! ⇒ Object
In-place swap the endpoints
119 120 121 122 |
# File 'lib/euclidean/edge.rb', line 119 def reverse! @first, @last = @last, @first self end |
#to_a ⇒ Object
124 125 126 |
# File 'lib/euclidean/edge.rb', line 124 def to_a [@first, @last] end |
#vector ⇒ Vector
Returns A Vector pointing from first to last.
129 130 131 |
# File 'lib/euclidean/edge.rb', line 129 def vector Vector[*((last-first).to_a)] end |
#width ⇒ Object
Return the Euclidean::Edge‘s length along the X axis
134 135 136 |
# File 'lib/euclidean/edge.rb', line 134 def width (@first.x - @last.x).abs end |