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.



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

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

#optionsObject



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

def options
  @options = {} if !@options
  @options
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



36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/geometry/edge.rb', line 36

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



30
31
32
# File 'lib/geometry/edge.rb', line 30

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



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

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:



98
99
100
# File 'lib/geometry/edge.rb', line 98

def direction
    self.vector.normalize
end

#heightObject

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



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

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

#inspectObject Also known as: to_s



71
72
73
# File 'lib/geometry/edge.rb', line 71

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



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
132
133
134
# File 'lib/geometry/edge.rb', line 105

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



77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/geometry/edge.rb', line 77

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



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

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

#reverse!Object

In-place swap the endpoints



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

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

#to_aObject



141
142
143
# File 'lib/geometry/edge.rb', line 141

def to_a
    [@first, @last]
end

#vectorVector

Returns A Vector pointing from first to last.

Returns:



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

def vector
    Vector[*((last-first).to_a)]
end

#widthObject

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



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

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