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

#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

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



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

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

#directionVector

Returns A unit Vector pointing from first to last.

Returns:



93
94
95
# File 'lib/geometry/edge.rb', line 93

def direction
    self.vector.normalize
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



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

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

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



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

def to_a
    [@first, @last]
end

#vectorVector

Returns A Vector pointing from first to last.

Returns:



132
133
134
# File 'lib/geometry/edge.rb', line 132

def vector
    Vector[*((last-first).to_a)]
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