Class: Geometry::Edge

Inherits:
Object
  • Object
show all
Defined in:
lib/geometry/edge.rb

Overview

An edge. It’s a line segment between 2 points. Generally part of a Polygon.

Usage

edge = Geometry::Edge.new([1,1], [2,2])
edge = Geometry::Edge([1,1], [2,2])

Instance Attribute Summary collapse

Attributes collapse

Instance Method Summary collapse

Constructor Details

#initialize(point0, point1) ⇒ Edge

Construct a new Geometry::Edge object from any two things that can be converted to a Point.



18
19
20
# File 'lib/geometry/edge.rb', line 18

def initialize(point0, point1)
    @first, @last = [Point[point0], Point[point1]]
end

Instance Attribute Details

#directionVector (readonly)

Returns A unit Vector pointing from first to last.

Returns:



117
118
119
# File 'lib/geometry/edge.rb', line 117

def direction
    @direction ||= self.vector.normalize
end

#firstObject (readonly)

Returns the value of attribute first.



14
15
16
# File 'lib/geometry/edge.rb', line 14

def first
  @first
end

#lastObject (readonly)

Returns the value of attribute last.



14
15
16
# File 'lib/geometry/edge.rb', line 14

def last
  @last
end

#vectorVector (readonly)

Returns A Vector pointing from first to last.

Returns:



157
158
159
# File 'lib/geometry/edge.rb', line 157

def vector
    @vector ||= last - first
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

Parameters:

Returns:

  • (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



29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/geometry/edge.rb', line 29

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



23
24
25
# File 'lib/geometry/edge.rb', line 23

def ==(other)
    (@first == other.first) && (@last == other.last)
end

#connected?(other) ⇒ Bool

Returns true if the receiver and the passed Geometry::Edge share an endpoint

Parameters:

Returns:

  • (Bool)

    Returns true if the receiver and the passed Geometry::Edge share an endpoint



111
112
113
# File 'lib/geometry/edge.rb', line 111

def connected?(other)
    (@first == other.last) || (@last == other.first) || (@first == other.first) || (@last == other.last)
end

#heightObject

Return the Geometry::Edge‘s length along the Y axis



79
80
81
# File 'lib/geometry/edge.rb', line 79

def height
    (@first.y - @last.y).abs
end

#inspectObject Also known as: to_s



88
89
90
# File 'lib/geometry/edge.rb', line 88

def inspect
    'Edge(' + @first.inspect + ', ' + @last.inspect + ')'
end

#intersection(other) ⇒ Point

Parameters:

Returns:

  • (Point)

    The intersection of the two Geometry::Edges, nil if they don’t intersect, true if they’re collinear and overlapping, and false if they’re collinear and non-overlapping



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
# File 'lib/geometry/edge.rb', line 124

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).to_r / denominator	# v1 x (p0 - p2) / denominator
	t = ( v2[0] * p.y - v2[1] * p.x).to_r / denominator	# v2 x (p0 - p2) / denominator

	p0 + v1 * t if ((0..1) === s) && ((0..1) === t)
    end
end

#lengthNumber

Returns the length of the Geometry::Edge.

Returns:



74
75
76
# File 'lib/geometry/edge.rb', line 74

def length
    @length ||= vector.magnitude
end

#maxPoint

Returns The upper-right corner of the bounding rectangle that encloses the Geometry::Edge.

Returns:

  • (Point)

    The upper-right corner of the bounding rectangle that encloses the Geometry::Edge



46
47
48
# File 'lib/geometry/edge.rb', line 46

def max
    first.max(last)
end

#minPoint

Returns The lower-left corner of the bounding rectangle that encloses the Geometry::Edge.

Returns:



51
52
53
# File 'lib/geometry/edge.rb', line 51

def min
    first.min(last)
end

#minmaxArray<Point>

Returns The lower-left and upper-right corners of the enclosing bounding rectangle.

Returns:

  • (Array<Point>)

    The lower-left and upper-right corners of the enclosing bounding rectangle



56
57
58
# File 'lib/geometry/edge.rb', line 56

def minmax
    first.minmax(last)
end

#parallel?(edge) ⇒ Bool

Returns true if the passed Geometry::Edge is parallel to the receiver

Returns:

  • (Bool)

    Returns true if the passed Geometry::Edge is parallel to the receiver



94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/geometry/edge.rb', line 94

def parallel?(edge)
    v1 = self.direction
    v2 = edge.direction
    winding = v1[0]*v2[1] - v1[1]*v2[0]
    if 0 == winding	# collinear?
	if v1 == v2
	    1		# same direction
	else
	    -1		# opposite direction
	end
    else
	false
    end
end

#reverseObject

Return a new Geometry::Edge with swapped endpoints



63
64
65
# File 'lib/geometry/edge.rb', line 63

def reverse
    self.class.new(@last, @first)
end

#reverse!Object

In-place swap the endpoints



68
69
70
71
# File 'lib/geometry/edge.rb', line 68

def reverse!
    @first, @last = @last, @first
    self
end

#to_aObject



161
162
163
# File 'lib/geometry/edge.rb', line 161

def to_a
    [@first, @last]
end

#widthObject

Return the Geometry::Edge‘s length along the X axis



84
85
86
# File 'lib/geometry/edge.rb', line 84

def width
    (@first.x - @last.x).abs
end