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([1,1], [2,2])

Instance Attribute Summary 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.



20
21
22
# File 'lib/geometry/edge.rb', line 20

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:



95
96
97
# File 'lib/geometry/edge.rb', line 95

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

#firstObject (readonly)

Returns the value of attribute first.



16
17
18
# File 'lib/geometry/edge.rb', line 16

def first
  @first
end

#lastObject (readonly)

Returns the value of attribute last.



16
17
18
# File 'lib/geometry/edge.rb', line 16

def last
  @last
end

#vectorVector (readonly)

Returns A Vector pointing from first to last.

Returns:



135
136
137
# File 'lib/geometry/edge.rb', line 135

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



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

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



25
26
27
# File 'lib/geometry/edge.rb', line 25

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



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

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



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

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

#inspectObject Also known as: to_s



66
67
68
# File 'lib/geometry/edge.rb', line 66

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



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/geometry/edge.rb', line 102

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 Geometry::Edge is parallel to the receiver

Returns:

  • (Bool)

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



72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/geometry/edge.rb', line 72

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



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

def reverse
    Edge.new(@last, @first)
end

#reverse!Object

In-place swap the endpoints



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

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

#to_aObject



139
140
141
# File 'lib/geometry/edge.rb', line 139

def to_a
    [@first, @last]
end

#widthObject

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



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

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