class EasyGeometry::D2::Segment

A segment in a 2-dimensional Euclidean space.

Public Instance Methods

<=>(other) click to toggle source
# File lib/easy_geometry/d2/segment.rb, line 49
def <=>(other)
  return self.p2 <=> other.p2 if self.p1 == other.p1 
  self.p1 <=> other.p1
end
==(other) click to toggle source

Returns True if self and other are the same mathematical entities.

Parameters:

GeometryEntity
# File lib/easy_geometry/d2/segment.rb, line 44
def ==(other)
  return false unless other.is_a?(Segment)
  [p1, p2].sort_by {|p| [p.x, p.y]} == [other.p1, other.p2].sort_by {|p| [p.x, p.y]}
end
contains?(other) click to toggle source

Is the other GeometryEntity contained within this Segment?

Parameters:

GeometryEntity or Array of Numeric(coordinates)

Returns:

true if `other` is in this Segment.
false otherwise.
# File lib/easy_geometry/d2/segment.rb, line 15
def contains?(other)
  other = Point.new(other[0], other[1]) if other.is_a?(Array)

  if other.is_a?(Point)
    if Point.is_collinear?(other, self.p1, self.p2)
      # if it is collinear and is in the bounding box of the
      # segment then it must be on the segment
      vert = (1/self.slope).zero?
      
      if vert
        return (self.p1.y - other.y) * (self.p2.y - other.y) <= 0
      end
      
      return (self.p1.x - other.x) * (self.p2.x - other.x) <= 0
    end
  end

  if other.is_a?(Segment)
    return self.contains?(other.p1) && self.contains?(other.p2)
  end

  return false
end
distance(other) click to toggle source

Finds the shortest distance between a line segment and a point.

Parameters:

Point or Array of Numeric(coordinates)

Returns:

Number
# File lib/easy_geometry/d2/segment.rb, line 62
def distance(other)
  other = Point.new(other[0], other[1]) if other.is_a?(Array)
  raise TypeError, "Distance between Segment and #{ other.class } is not defined" unless other.is_a?(Point)

  vp1 = other - self.p1
  vp2 = other - self.p2

  dot_prod_sign_1 = self.direction.to_point.dot(vp1) >= 0
  dot_prod_sign_2 = self.direction.to_point.dot(vp2) <= 0

  if dot_prod_sign_1 && dot_prod_sign_2
    return Line.new(self.p1, self.p2).distance(other)
  end

  if dot_prod_sign_1 && !dot_prod_sign_2
    return vp2.abs
  end

  if !dot_prod_sign_1 && dot_prod_sign_2
    return vp1.abs
  end
end
length() click to toggle source

The length of the line segment.

# File lib/easy_geometry/d2/segment.rb, line 86
def length
  @length ||= p1.distance(p2)
end
midpoint() click to toggle source

The midpoint of the line segment.

# File lib/easy_geometry/d2/segment.rb, line 91
def midpoint
  @midpoint ||= p1.midpoint(p2)
end
perpendicular_bisector(point=nil) click to toggle source

The perpendicular bisector of this segment. If no point is specified or the point specified is not on the bisector then the bisector is returned as a Line. Otherwise a Segment is returned that joins the point specified and the intersection of the bisector and the segment.

Parameters:

Point

Returns:

Line or Segment
# File lib/easy_geometry/d2/segment.rb, line 107
def perpendicular_bisector(point=nil)
  l = self.perpendicular_line(self.midpoint)
  
  if !point.nil?
    point = Point.new(point[0], point[1]) if point.is_a?(Array)        
    raise TypeError, "This method is not defined for #{ point.class }" unless point.is_a?(Point)
    return Segment.new(point, self.midpoint) if l.contains?(point)
  end

  return l
end