Module: Sevgi::Geometry

Defined in:
lib/sevgi/geometry/point.rb,
lib/sevgi/geometry/errors.rb,
lib/sevgi/geometry/element.rb,
lib/sevgi/geometry/version.rb,
lib/sevgi/geometry/auxilary.rb,
lib/sevgi/geometry/operation.rb,
lib/sevgi/geometry/elements/rect.rb,
lib/sevgi/geometry/equation/line.rb,
lib/sevgi/geometry/sundries/grid.rb,
lib/sevgi/geometry/sundries/tile.rb,
lib/sevgi/geometry/sundries/ruler.rb,
lib/sevgi/geometry/operation/align.rb,
lib/sevgi/geometry/operation/sweep.rb,
lib/sevgi/geometry/elements/segment.rb,
lib/sevgi/geometry/equation/line/diagonal.rb,
lib/sevgi/geometry/equation/line/vertical.rb,
lib/sevgi/geometry/equation/line/horizontal.rb

Defined Under Namespace

Modules: Equation, Operation Classes: Element, Grid, Interval, Rect, Ruler, RulerEven, Segment, Tile

Constant Summary collapse

Point =
Data.define(:x, :y) do
  include Comparable

  def initialize(x:, y:)          = super(x: x.to_f, y: y.to_f)

  def <=>(other)                  = (other.nan? || nan?) ? nil : deconstruct <=> other.deconstruct

  def above?(other)               = y <= other.y

  def approx(precision = nil)     = with(x: F.approx(x, precision), y: F.approx(y, precision))

  def below?(other)               = y >= other.y

  def eq?(other, precision: nil)  = self.class.eq?(self, other, precision:)

  def eql?(other)                 = self.class == other.class && [ x, y ] == [ other.x, other.y ]

  def hash                        = [ self.class, x, y ].hash

  def infinite?                   = [ x, y ].any?(&:infinite?)

  def left?(other)                = x <= other.x

  def nan?                        = [ x, y ].any?(&:nan?)

  def right?(other)               = x >= other.x

  def to_cs                       = "#{F.approx(x)},#{F.approx(y)}"

  def to_s                        = "P(#{F.approx(x)} #{F.approx(y)})"

  def translate(dx: nil, dy: nil) = with(x: x + (dx || 0.0), y: y + (dy || 0.0))

  def unordered_between?(p, q)    = nan? ? false : between?([ p, q ].min, [ p, q ].max)

  alias_method :==,   :eql?
  alias_method :to_a, :deconstruct

  class << self
    def eq?(p, q, precision: nil) = F.eq?(p.x, q.x, precision:) && F.eq?(p.y, q.y, precision:)

    def origin                    = new(x: 0.0, y: 0.0)
  end
end
Error =
Class.new(Error)
VERSION =
"0.1.0"
Corner =

Argument order is in clockwise rotation from position point

Data.define(:top_left, :top_right, :bottom_right, :bottom_left) do
  def corners       = self.class.members.map { public_send(_1) }

  def corners!(...) = corners.map { _1.approx(...) }

  class << self
    def of(rect)
      position = rect.position

      new(
        top_left:     position,
        top_right:    position.translate(dx: rect.width),
        bottom_right: position.translate(dx: rect.width, dy: rect.height),
        bottom_left:  position.translate(dy: rect.height)
      )
    end
  end
end
Side =

Argument order is in clockwise rotation from top segment (as in CSS)

Data.define(:top, :right, :bottom, :left) do
  def sides       = self.class.members.map { public_send(_1) }

  def sides!(...) = sides.map { _1.approx(...) }

  class << self
    def of(rect)
      corner = rect.corner

      new(
        top:    Segment[corner.top_left,    corner.top_right],
        right:  Segment[corner.top_right,   corner.bottom_right],
        bottom: Segment[corner.bottom_left, corner.bottom_right],
        left:   Segment[corner.top_left,    corner.bottom_left]
      )
    end
  end
end
Translation =
Data.define(:dx, :dy) do
  def apply(element) = element.translate(**to_h)

  class << self
    def applicable?(element) = element.respond_to?(:translate)
  end
end