This documentation is automatically generated by online-judge-tools/verification-helper

:warning: src/geometric/utility.cr

Depends on

Required by

Code

require "./object/vec2"

module Geometric
  extend self

  #
  #        C [+1]
  #       /
  # A -- B
  #       \
  #        C [-1]
  #
  # A -- B -- C [+2]
  # A -- C -- B [ 0]
  # B -- A -- C [-2]
  #
  def ccw(a : Vec2, b : Vec2, c : Vec2) : Int32
    if (x = (b - a).cross(c - a).sign) != 0
      x
    elsif (b - a).dot(c - b).sign > 0
      2
    elsif (a - b).dot(c - a).sign > 0
      -2
    else
      0
    end
  end

  # Calclates the angle of `∠abc`
  def angle(a : Vec2, b : Vec2, c : Vec2)
    (c - b).rotate(-(a - b).angle).angle
  end
end
# require "./object/vec2"
# require "../real"
require "big"

alias Real = BigFloat
EPS = Real.new(1e-12)

struct Real
  def <=>(other : Real)
    {% if Real == BigFloat %}
      if previous_def(other - EPS) < 0
        -1
      elsif previous_def(other + EPS) > 0
        1
      else
        0
      end
    {% else %}
      if self < other - EPS
        -1
      elsif self > other + EPS
        1
      else
        0
      end
    {% end %}
  end

  def sign : Int32
    self < -EPS ? -1 : self > EPS ? 1 : 0
  end

  def to_radian
    self * Math::PI / 180
  end

  def to_degree
    self * 180 / Math::PI
  end

  def self.scan(scanner, io : IO) : self
    Real.new scanner.s(io)
  end
end

module Geometric
  struct Vec2
    include Comparable(Vec2)

    property x : Real, y : Real

    def self.zero
      Vec2.new(Real.zero, Real.zero)
    end

    def initialize(x, y)
      @x, @y = Real.new(x), Real.new(y)
    end

    def self.scan(scanner, io : IO) : self
      Vec2.new(scanner.f(io), scanner.f(io))
    end

    def +
      self
    end

    def -
      Vec2.new(-x, -y)
    end

    {% for op in %w[+ - * /] %}
      def {{op.id}}(other : Vec2)
        Vec2.new(x {{op.id}} other.x, y {{op.id}} other.y)
      end

      def {{op.id}}(other)
        Vec2.new(x {{op.id}} other, y {{op.id}} other)
      end
    {% end %}

    def <=>(other : Vec2)
      x_cmp = x <=> other.x
      if x_cmp != 0
        x_cmp
      else
        y <=> other.y
      end
    end

    def [](index : Int)
      return x if index == 0
      return y if index == 1
      raise IndexError.new
    end

    def length : Real
      Math.hypot(x, y)
    end

    def dot(other : Vec2) : Real
      x * other.x + y * other.y
    end

    def cross(other : Vec2) : Real
      x * other.y - y * other.x
    end

    def angle : Real
      Real.new Math.atan2(y, x)
    end

    def rotate(rad : Real) : Vec2
      c, s = Math.cos(rad), Math.sin(rad)
      Vec2.new(x * c - y * s, x * s + y * c)
    end

    def to_tuple
      {x, y}
    end

    def inspect(io : IO)
      io << '(' << x << ", " << y << ')'
    end
  end
end

module Geometric
  extend self

  #
  #        C [+1]
  #       /
  # A -- B
  #       \
  #        C [-1]
  #
  # A -- B -- C [+2]
  # A -- C -- B [ 0]
  # B -- A -- C [-2]
  #
  def ccw(a : Vec2, b : Vec2, c : Vec2) : Int32
    if (x = (b - a).cross(c - a).sign) != 0
      x
    elsif (b - a).dot(c - b).sign > 0
      2
    elsif (a - b).dot(c - a).sign > 0
      -2
    else
      0
    end
  end

  # Calclates the angle of `∠abc`
  def angle(a : Vec2, b : Vec2, c : Vec2)
    (c - b).rotate(-(a - b).angle).angle
  end
end
Back to top page