Save-Point
Geometry Module - Printable Version

+- Save-Point (https://www.save-point.org)
+-- Forum: Material Development (https://www.save-point.org/forum-8.html)
+--- Forum: Scripts Database (https://www.save-point.org/forum-39.html)
+---- Forum: RPGMaker XP (RGSS) Engine (https://www.save-point.org/forum-116.html)
+---- Thread: Geometry Module (/thread-2820.html)



Geometry Module - Trickster - 03-02-2008

Geometry Module
Version: 1.0


Introduction
This is the Geometry Module, originally created by ShadowText. It allows you to draw lines, shapes, circles and other stuff. So far you can only draw lines.

This module is designed to do some geometric functions, including drawing lines and shapes for whatever crazy purpose you need to draw lines and shapes for. It also draws text balloons. Yay.

NOT FOR NON-SCRIPTERS


Screenshots
Not a very pratical screenshot, but a screenshot of me playing around with it
[Image: my.php?image=lines0as.png]


Script
Yes a script this time

Code:
class Bitmap
  #-------------------------------------------------------------------------
  # * Name:      Draw Line
  #   Info:      Draws a Line
  #   Author:    Trickster (Based on ShadowTexts Line#draw)
  #   Call Info: One - Six Arguments
  #   Call 1 - Line line Line to draw (Integer width, Color color)
  #   Call 2 - Point a, b points to create line (Integer width, Color color)
  #   Call 3 - Numeric x1, y1, x2, y2 points to create line
  #            (Integer width, Color color)
  #-------------------------------------------------------------------------
  def draw_line(*args)
    if args[0].is_a?(Geometry::Line)
      line = args[0]
      width = args[1].nil? ? 1 : args[1]
      color = args[2].nil? ? Color.new(0, 0, 0) : args[2]
    elsif args[0].is_a?(Geometry::Point)
      line = Geometry::Line.new(*args[0..1])
      width = args[2].nil? ? 1 : args[2]
      color = args[3].nil? ? Color.new(0,0,0) : args[3]
    elsif args[0].is_a?(Integer)
      line = Geometry::Line.new(*args[0..3])
      width = args[4].nil? ? 1 : args[4]
      color = args[5].nil? ? Color.new(0,0,0) : args[5]
    end
    min_x, min_y = line.min_x, line.min_y
    max_x, max_y = line.max_x, line.max_y
    slope = line.slope
    if line.vertical?
      self.fill_rect(min_x, min_y, width, max_y - min_y, color)
    elsif line.horizontal?
      self.fill_rect(min_x, min_y, max_x - min_x, width, color)
    else
      line.each do |x, y|
        self.fill_rect(x, y, width, width, color)
      end
    end
  end
end


#==============================================================================
# ** Geometry V2.0                                     Originally by ShadowText
#                                                      Rewritten by Trickster
#-----------------------------------------------------------------------------
# Description by Shadow Text
# This module is designed to do some geometric functions, including drawing
# lines and shapes for whatever crazy purpose you need to draw lines and  
# shapes for. It also draws text balloons. Yay.  
#==============================================================================
module Geometry
#==============================================================================
# ** Point                                             Originally by ShadowText
#                                                      Rewritten by Trickster
#-----------------------------------------------------------------------------
#  The class of points, nothing interesting you can use this class to easily.
#  Set the position of line objects for now. There is also a move method.
#==============================================================================
class Point
  #--------------------------------------------------------------------------
  # * Public Instance Variables
  #--------------------------------------------------------------------------
  attr_reader :x
  attr_reader :y
  #-------------------------------------------------------------------------
  # * Name:      Object Initialization
  #   Info:      Creates a New Point Object
  #   Author:    ShadowText - Mods By Trickster
  #   Call Info: Two Arguments Numeric X and Y
  #-------------------------------------------------------------------------
  def initialize(x,y)
    @x, @y = x, y
  end
  #-------------------------------------------------------------------------
  # * Name:      - (Distance)
  #   Info:      Finds Distance Between two Points
  #   Author:    ShadowText - Mods By Trickster
  #   Call Info: One Argument Point i - Other Point
  #-------------------------------------------------------------------------
  def -(i)
    return Math.sqrt((i.x - x) ** 2 + (i.y - y) ** 2)
  end
  #-------------------------------------------------------------------------
  # * Name:      Move
  #   Info:      Returns a point moved width and height units
  #   Author:    Trickter (Based on ShadowText's version)
  #   Call Info: Two Arguments Mx My distance to move horiz. and vert.
  #   Returns:   A Point Object moved width and height units
  #-------------------------------------------------------------------------
  def move(mx,my)
    return Point.new(@x + mx, @y + my)
  end
  #-------------------------------------------------------------------------
  # * Name:      Move! (Dangerous)
  #   Info:      Moves this point width and height units
  #   Author:    ShadowText - Mods By Trickster
  #   Call Info: Two Arguments Mx My distance to move horiz. and vert.
  #-------------------------------------------------------------------------
  def move!(mx,my)
    @x += mx
    @y += my
  end
  #-------------------------------------------------------------------------
  # * Name:      To S (To String)
  #   Info:      Returns the string representation of this object
  #   Author:    ShadowText - Mods By Trickster
  #   Call Info: None
  #   Returns:   String (x,y)
  #-------------------------------------------------------------------------
  def to_s
    return "(#{@x},#{@y})"
  end
end

#==============================================================================
# ** Line                                             Originally by ShadowText
#                                                     Rewritten by Trickster
#-----------------------------------------------------------------------------
#  The class of lines, includes useful methods such as slope, intercepts, and
#  finding a point along the line. You can declare it with either Point Objects
#  or specify the points yourself. There are also pretty useful iterator methods
#  to use at your disposal. Can be used with Bitmap#draw_line to draw the line.
#==============================================================================
class Line
  #-------------------------------------------------------------------------
  # * Public Instance Variables
  #-------------------------------------------------------------------------
  attr_reader :x1
  attr_reader :x2
  attr_reader :y1
  attr_reader :y2
  #-------------------------------------------------------------------------
  # * Name:      Object Initialization
  #   Info:      Creates a new line object
  #   Author:    Trickster (Based on ShadowText's version)
  #   Call Info: Two Arguments Point p1 and p2 - Starting Point and Ending Point
  #              Four Arguments Numeric X1, Y1, X2, Y2 Coordinates
  #-------------------------------------------------------------------------
  def initialize(*args)
    if args.size == 2
      @x1, @y1 = args[0].x, args[0].y
      @x2, @y2 = args[1].x, args[1].y
    elsif args.size == 4
      @x1, @y1, @x2, @y2 = args
    end
  end
  #-------------------------------------------------------------------------
  # * Name:      To S (To String)
  #   Info:      String Representation of this line
  #   Author:    ShadowText - Mods By Trickster
  #   Call Info: No Arguments
  #   Returns:   (x1,y1):(x2,y2)
  #                Slope = slope
  #                Y-Int = yint
  #-------------------------------------------------------------------------
  def to_s
    return "(#{@x1},#{@y1}):(#{@x2},#{@y2})\nSlope = #{slope}\nY-Int = #{yint}"
  end
  #-------------------------------------------------------------------------
  # * Name:      Get X Coordinate
  #   Info:      Gets X Coordinate
  #   Author:    ShadowText - Mods By Trickster
  #   Call Info: One-Two Arguments Numeric Y - y coordinate
  #              Boolean Domain - Flag to restrict to domain (Def. True)
  #   Returns:   nil if domain option and outside domain
  #              Infinity if horizontal line (0 slope)
  #              Else the value for x that corresponds to y
  #-------------------------------------------------------------------------    
  def get_x(y, domain = true)
    return if domain && (y < min_y || y > max_y)
    return min_x if slope.infinite?
    return Infinity if slope.zero?
    return (y - y_int) / slope.to_f
  end
  #-------------------------------------------------------------------------
  # * Name:      Get Y Coordinate
  #   Info:      Gets Y Coordinate
  #   Author:    ShadowText - Mods By Trickster
  #   Call Info: One-Two Arguments Numeric X - x coordinate
  #              Boolean Domain - Flag to restrict to domain (Def. True)
  #   Returns:   nil if domain option and outside domain
  #              Infinity if vertical line (Infinite slope)
  #              Else the value for y that corresponds to x
  #-------------------------------------------------------------------------  
  def get_y(x, domain = true)
    return if domain && (x < min_x || x > max_x)
    return Infinity if slope.infinite?
    return min_y if slope.zero?
    return slope * x + y_int
  end
  #-------------------------------------------------------------------------
  # * Name:      Minimum X
  #   Info:      Returns the Minimum Value X can be for this line
  #   Author:    ShadowText - Mods By Trickster
  #   Call Info: No Arguments
  #   Returns:   The Minimum Value for X, that is, the minimum of the x values
  #              Sent for this line.
  #-------------------------------------------------------------------------  
  def min_x
    return [@x1, @x2].min
  end
  #-------------------------------------------------------------------------
  # * Name:      Minimum Y
  #   Info:      Returns the Minimum Value Y can be for this line
  #   Author:    ShadowText - Mods By Trickster
  #   Call Info: No Arguments
  #   Returns:   The Minimum Value for Y, that is, the minimum of the y values
  #              Sent for this line.
  #-------------------------------------------------------------------------  
  def min_y
    return [@y1, @y2].min
  end
  #-------------------------------------------------------------------------
  # * Name:      Maximum X
  #   Info:      Returns the Maximum Value X can be for this line
  #   Author:    ShadowText - Mods By Trickster
  #   Call Info: No Arguments
  #   Returns:   The Maximum Value for X, that is, the maximum of the x values
  #              Sent for this line.
  #-------------------------------------------------------------------------    
  def max_x
    return [@x1, @x2].max
  end
  #-------------------------------------------------------------------------
  # * Name:      Maximum Y
  #   Info:      Returns the Maximum Value Y can be for this line
  #   Author:    ShadowText - Mods By Trickster
  #   Call Info: No Arguments
  #   Returns:   The Maximum Value for Y, that is, the maximum of the y values
  #              Sent for this line.
  #-------------------------------------------------------------------------  
  def max_y
    return [@y1, @y2].max
  end
  #-------------------------------------------------------------------------
  # * Name:      Length
  #   Info:      Returns the Length of this Line Segment
  #   Author:    ShadowText - Mods By Trickster
  #   Call Info: No Arguments
  #   Returns:   The Length of this line segment
  #-------------------------------------------------------------------------    
  def length
    return Math.sqrt((@y1 - @y2) ** 2 + (@x1 - @x2) ** 2)
  end
  #-------------------------------------------------------------------------
  # * Name:      Slope
  #   Info:      Returns the slope of this line (rise over run)
  #   Author:    ShadowText - Mods By Trickster
  #   Call Info: No Arguments
  #   Returns:   The Slope that is the difference in y / difference in x
  #-------------------------------------------------------------------------
  def slope
    return (@y1 - @y2).to_f / (@x1 - @x2)
  end
  #-------------------------------------------------------------------------
  # * Name:      X Int
  #   Info:      X Intercept (Point where line crosses X Axis)
  #   Author:    Trickster
  #   Call Info: No Arguments
  #   Returns:   nil if Horizontal Line, else x intercept
  #-------------------------------------------------------------------------
  def x_int
    return slope.infinite? ? @x1 : slope.zero? ? nil : @x1 - @y1 / slope
  end
  #-------------------------------------------------------------------------
  # * Name:      Y Int
  #   Info:      Y Intercept (Point where line crosses Y Axis)
  #   Author:    ShadowText - Mods By Trickster
  #   Call Info: No Arguments
  #   Returns:   nil if Vertical Line, else y intercept
  #-------------------------------------------------------------------------
  def y_int
    return slope.infinite? ? nil : @y1 - slope * @x1
  end
  #-------------------------------------------------------------------------
  # * Name:      Horizontal?
  #   Info:      Is this a horizontal line?
  #   Author:    Trickster
  #   Call Info: No Arguments
  #   Returns:   True if slope is 0 false otherwise
  #-------------------------------------------------------------------------
  def horizontal?
    return slope.zero?
  end
  #-------------------------------------------------------------------------
  # * Name:      Vertical?
  #   Info:      Is this a vertical line?
  #   Author:    Trickster
  #   Call Info: No Arguments
  #   Returns:   True if slope is Infinite false otherwise
  #-------------------------------------------------------------------------
  def vertical?
    return slope.infinite? != nil
  end
  #-------------------------------------------------------------------------
  # * Name:      Find Point
  #   Info:      Finds Point on Line
  #   Author:    ShadowText - Mods By Trickster
  #   Call Info: One or Two Arguments - Numeric Percentage percentage of distance
  #              Boolean point - True returns a point object false [x, y]
  #   Returns:   A Point with the coordinate or an array with [x, y]
  #-------------------------------------------------------------------------
  def find_point(percentage, point = true)
    return if percentage < 0 or percentage > 100
    dist = percentage * length / 100.0
    if horizontal?
      return point ? Point.new(min_x + dist, min_y) : [min_x + dist, min_y]
    elsif vertical?
      return point ? Point.new(min_x, min_y + dist) : [min_x, dist + min_y]
    else
      x = @x1 + dist / Math.sqrt(slope ** 2 + 1)
      y = @y1 + dist * slope / Math.sqrt(slope ** 2 + 1)
      return point ? Point.new(x, y) : [x, y]
    end
  end
  #-------------------------------------------------------------------------
  # * Name:      Each (Iterator method)
  #   Info:      Runs Through each point (Integer) (x, y) in the line
  #   Author:    Trickster
  #   Call Info: A Block
  #   Returns:   an array of Integers [x, y]
  #   Coomments: See Each_Step to evaluate through decimals
  #-------------------------------------------------------------------------
  def each
    (min_x.round..max_x.round).each {|x| yield(x, get_y(x).round)}
  end
  #-------------------------------------------------------------------------
  # * Name:      Each X (Iterator method)
  #   Info:      Runs Through each x (Integer) in the line
  #   Author:    Trickster
  #   Call Info: A Block
  #   Returns:   an Integer x
  #-------------------------------------------------------------------------
  def each_x
    (min_x.round..max_x.round).each {|x| yield(x)}
  end
  #-------------------------------------------------------------------------
  # * Name:      Each Y (Iterator method)
  #   Info:      Runs Through each y (Integer) in the line
  #   Author:    Trickster
  #   Call Info: A Block
  #   Returns:   an Integer y
  #-------------------------------------------------------------------------
  def each_y
    (min_y.round..max_y.round).each {|y| yield(y)}
  end
  #-------------------------------------------------------------------------
  # * Name:      Each Step (Iterator method)
  #   Info:      Runs Through each point (Integer) (x, y) in the line
  #   Author:    Trickster
  #   Call Info: Zero - Two Arguments
  #              Numeric Step - Amount to increment by (def 1.0)    
  #              A Block
  #   Returns:   an Integer x
  #-------------------------------------------------------------------------
  def each_step(step = 1.0)
    min_x.step(max_x, step) {|x| yield(x, get_y(x))}
  end
end
end


Instructions
See method and class headers I spent some time writing those


FAQ
Note: Permission granted by Trickster to post:
Quote:And if you post what you have now of my stuff then you don't have the latest versions. I'm too lazy/busy to post stuff.
As this is his material, it is deletable upon his request. Due to his current absense, no support is available. Please do not PM or eMail him for support.


Compatibility
Well if you are using ShadowText's older version of this script then you will have some trouble


Credits and Thanks
ShadowText for version 1, which I rewrote, added, and removed stuff.


Terms and Conditions
Hey, I posted this publicly. You can use it. What do you expect? But if you do use it, I do expect you to spell my name correctly in your game. And yes you can use it in commercial games too.