class EasyGeometry::D2::Point

A point in a 2-dimensional Euclidean space.

Constants

EQUITY_TOLERANCE

Attributes

x[R]
y[R]

Public Class Methods

affine_rank(*points) click to toggle source

The affine rank of a set of points is the dimension of the smallest affine space containing all the points.

For example, if the points lie on a line (and are not all the same) their affine rank is 1.

If the points lie on a plane but not a line, their affine rank is 2.

By convention, the empty set has affine rank -1.

# File lib/easy_geometry/d2/point.rb, line 51
def self.affine_rank(*points)
  raise TypeError, 'Args should be a Points' unless points.detect { |p| !p.is_a?(Point) }.nil?
  return -1 if points.length == 0

  origin = points[0]
  points = points[1..-1].map {|p| p - origin}

  Matrix[*points.map {|p| [p.x, p.y]}].rank
end
is_collinear?(*points) click to toggle source

Returns:

true if there exists a line that contains `points`,

or if no points are given.

false otherwise.
# File lib/easy_geometry/d2/point.rb, line 39
def self.is_collinear?(*points)
  # raise TypeError, 'Args should be a Points' unless points.detect { |p| !p.is_a?(Point) }.nil?
  Point.affine_rank(*points.uniq) <= 1
end
new(x, y) click to toggle source
# File lib/easy_geometry/d2/point.rb, line 9
def initialize(x, y)
  @x = x; @y = y

  validate!
  converting_to_rational!
end
project(a, b) click to toggle source

Project the point 'a' onto the line between the origin and point 'b' along the normal direction.

Parameters:

Point, Point

Returns:

Point
# File lib/easy_geometry/d2/point.rb, line 25
def self.project(a, b)
  unless a.is_a?(Point) && b.is_a?(Point)
    raise TypeError, "Project between #{ a.class } and #{ b.class } is not defined"
  end
  raise ArgumentError, "Cannot project to the zero vector" if b.zero?
  
  b * a.dot(b) / b.dot(b)
end

Public Instance Methods

*(scalar) click to toggle source

Multiplication of point and number.

# File lib/easy_geometry/d2/point.rb, line 91
def *(scalar)
  raise TypeError, "Multiplication between Point and #{ scalar.class } is not defined" unless scalar.is_a?(Numeric)
  Point.new(x * scalar, y * scalar)
end
+(other) click to toggle source

Addition of two points.

# File lib/easy_geometry/d2/point.rb, line 85
def +(other)
  raise TypeError, "Addition between Point and #{ other.class } is not defined" unless other.is_a?(Point)
  Point.new(self.x + other.x, self.y + other.y)
end
-(other) click to toggle source

Subtraction of two points.

# File lib/easy_geometry/d2/point.rb, line 79
def -(other)
  raise TypeError, "Subtract between Point and #{ other.class } is not defined" unless other.is_a?(Point)
  Point.new(self.x - other.x, self.y - other.y)
end
/(scalar) click to toggle source

Dividing of point and number.

# File lib/easy_geometry/d2/point.rb, line 97
def /(scalar)
  raise TypeError, "Dividing between Point and #{ scalar.class } is not defined" unless scalar.is_a?(Numeric)
  Point.new(x / scalar, y / scalar)
end
<=>(other) click to toggle source
# File lib/easy_geometry/d2/point.rb, line 102
def <=>(other)
  return self.y <=> other.y if self.x == other.x 
  self.x <=> other.x
end
==(other) click to toggle source

Compare self and other Point.

# File lib/easy_geometry/d2/point.rb, line 73
def ==(other)
  return false unless other.is_a?(Point)
  (x - other.x).abs < EQUITY_TOLERANCE && (y - other.y).abs < EQUITY_TOLERANCE
end
abs() click to toggle source

Returns the distance between this point and the origin.

# File lib/easy_geometry/d2/point.rb, line 108
def abs
  self.distance(Point.new(0, 0))
end
distance(other) click to toggle source

Distance between self and another geometry entity.

Parameters:

geometry_entity

Returns:

int
# File lib/easy_geometry/d2/point.rb, line 120
def distance(other)
  if other.is_a?(Point)
    return distance_between_points(self, other)
  end
  
  if other.respond_to?(:distance)
    return other.distance(self)
  end
  
  raise TypeError, "Distance between Point and #{ other.class } is not defined"
end
dot(other) click to toggle source

Dot product, also known as inner product or scalar product.

# File lib/easy_geometry/d2/point.rb, line 62
def dot(other)
  raise TypeError, "Scalar (dot) product between Point and #{ other.class } is not defined" unless other.is_a?(Point)
  x * other.x + y * other.y
end
intersection(other) click to toggle source

Intersection between point and another geometry entity.

Parameters:

geometry_entity

Returns:

Array of Points
# File lib/easy_geometry/d2/point.rb, line 140
def intersection(other)
  if other.is_a?(Point)
    return points_intersection(self, other)
  end

  if other.respond_to?(:intersection)
    return other.intersection(self)
  end

  raise TypeError, "Intersection between Point and #{ other.class } is not defined"
end
midpoint(other) click to toggle source

The midpoint between self and another point.

Parameters:

Point

Returns:

Point
# File lib/easy_geometry/d2/point.rb, line 160
def midpoint(other)
  raise TypeError, "Midpoint between Point and #{ other.class } is not defined" unless other.is_a?(Point)

  Point.new(
    (self.x + other.x) / 2,
    (self.y + other.y) / 2
  )
end
zero?() click to toggle source

True if every coordinate is zero, False if any coordinate is not zero.

# File lib/easy_geometry/d2/point.rb, line 68
def zero?
  x.zero? && y.zero? 
end

Private Instance Methods

converting_to_rational!() click to toggle source
# File lib/easy_geometry/d2/point.rb, line 186
def converting_to_rational!
  @x = Rational(x.to_s) unless x.is_a?(Rational)
  @y = Rational(y.to_s) unless y.is_a?(Rational)
end
distance_between_points(p1, p2) click to toggle source
# File lib/easy_geometry/d2/point.rb, line 176
def distance_between_points(p1, p2)
  # AB = √(x2 - x1)**2 + (y2 - y1)**2
  Math.sqrt( (p2.x - p1.x)**2 + (p2.y - p1.y)**2 )
  # Math.hypot((p2.x - p1.x), (p2.y - p1.y))
end
points_intersection(p1, p2) click to toggle source
# File lib/easy_geometry/d2/point.rb, line 171
def points_intersection(p1, p2)
  return [p1] if p1 == p2
  return []
end
validate!() click to toggle source
# File lib/easy_geometry/d2/point.rb, line 182
def validate!
  raise TypeError, 'Coords should be numbers' if !x.is_a?(Numeric) || !y.is_a?(Numeric)
end