require_relative 'point' module Geometry NotSquareError = Class.new(ArgumentError) =begin The {Square} class cluster is like the {Rectangle} class cluster, but not longer in one direction. == Constructors square = Square.new from:[1,2], to:[2,3] # Using two corners square = Square.new origin:[3,4], size:5 # Using an origin point and a size =end class Square attr_reader :origin attr_writer :options def options @options = {} if !@options @options end # Creates a {Square} given two {Point}s # @option options [Point] :from A corner (ie. bottom-left) # @option options [Point] :to The other corner (ie. top-right) # @option options [Point] :origin The lower left corner # @option options [Number] :size Bigness def initialize(options={}) origin = options[:from] || options[:origin] origin = origin ? Point[origin] : PointZero.new if options.has_key? :to point1 = options[:to] elsif options.has_key? :size point1 = origin + options[:size] end point1 = Point[point1] raise(ArgumentError, "Point sizes must match (#{origin.size} != #{point1.size})") unless origin.is_a?(PointZero) || (origin.size == point1.size) # Reorder the points to get lower-left and upper-right minx, maxx = [origin.x, point1.x].minmax miny, maxy = [origin.y, point1.y].minmax @points = [Point[minx, miny], Point[maxx, maxy]] raise(NotSquareError) if height != width end # !@group Accessors # @attribute [r] origin # @return [Point] The lower left corner def origin @points.first end def height min, max = @points.minmax {|a,b| a.y <=> b.y} max.y - min.y end def width min, max = @points.minmax {|a,b| a.x <=> b.x} max.x - min.x end # @endgroup end # A {Square} created with a center point and a size class CenteredSquare < Square # @attribute [r] center # @return [Point] The center of the {Square} attr_reader :center # @param [Point] center The center point # @param [Numeric] size The length of each side def initialize(center, size) @center = Point[center] @size = size end # @group Accessors # @attribute [r] origin # @return [Point] The lower left corner def origin Point[@center.x - size/2, @center.y - size/2] end # @attribute [r] points # @return [Array<Point>] The {Square}'s four points (counterclockwise) def points half_size = @size/2 minx = @center.x - half_size maxx = @center.x + half_size miny = @center.y - half_size maxy = @center.y + half_size [Point[minx,miny], Point[maxx, miny], Point[maxx, maxy], Point[minx,maxy]] end def height @size end def width @size end # @endgroup end # A {Square} created with an origin point and a size class SizedSquare < Square # @param [Point] origin The origin point (bottom-left corner) # @param [Numeric] size The length of each side def initialize(origin, size) @origin = Point[origin] @size = size end end end