Files
gtav-src/tools_ng/techart/script/Ruby/Global/graph/graph.rb
T
2025-09-29 00:52:08 +02:00

332 lines
8.7 KiB
Ruby
Executable File

#
# GENERIC CLASS
# Author:: Mark Harrison-Ball <Mark.Harrison-Ball@rockstargames.com>
# Date:: 20 Februray 2013 (AP3)
# Purpose:
# Draw a graph Utility
#
require 'System.Drawing'
path = File.expand_path $0
path = File.dirname(path)
require "#{path}/../../Global/image/Image.rb"
require "#{path}/../../Global/array/arrayUtils.rb"
class Graph
attr_reader :image
attr_reader :graphics
#attr_reader :defaultPenColor
attr_reader :pen
def initialize( x , y )
#Image
@x = x
@y = y
#margin
@margin = 20
#Graph
@gX = x-(@margin*2)
@gY = y-(@margin*2)
# Brush List
@BrushBeige = System::Drawing::SolidBrush.new(System::Drawing::Color.FromArgb(243,237,237))
@BrushGrey = System::Drawing::SolidBrush.new(System::Drawing::Color.FromArgb(160,160,160))
@BrushBlack = System::Drawing::SolidBrush.new(System::Drawing::Color.Black)
@BrushDarkGrey = System::Drawing::SolidBrush.new(System::Drawing::Color.FromArgb(150,150,150))
# Pen List
@PenBeige = System::Drawing::Pen.new(System::Drawing::Color.FromArgb(223,217,217))
@PenGrey = System::Drawing::Pen.new(System::Drawing::Color.FromArgb(97,95,95))
@PenBlack = System::Drawing::Pen.new(System::Drawing::Color.Black)
@PenRed = System::Drawing::Pen.new(System::Drawing::Color.Red)
@PenGreen = System::Drawing::Pen.new(System::Drawing::Color.Green)
@PenBlue = System::Drawing::Pen.new(System::Drawing::Color.Blue)
@PenPurple = System::Drawing::Pen.new(System::Drawing::Color.Purple)
# Font List
@DrawFont = System::Drawing::Font.new("Arial", 6)
# Pen Array List
@penList = [@PenRed, @PenGreen, @PenBlue, @PenPurple]
@gWidth = 0
@gHeight = 0
@marginX = 20
@marginY = 20
# Used for negative values
@setMinHOffset = 0
#fillbackground()
@Title = ""
@arrayUtils = ArrayUtils.new()
@stringformat = System::Drawing::StringFormat.new()
@right = System::Drawing::StringAlignment.Far
@center = System::Drawing::StringAlignment.Center
@left = System::Drawing::StringAlignment.Near
@stringformat.Alignment = @right
end
def path
@image.path()
end
def new(path)
@image = Image.new( @x , @y, path )
@graphics = System::Drawing::Graphics.from_image(@image.source)
fillbackground()
end
def save()
@image.save()
end
# draw a list of blocks
# block list is a list of pairs
# timecode is based on 0 -1
def drawblocks(blocklist)
blocklist.each do | block |
x1 = @x * block[0].to_f
x2 = @x * block[1].to_f
x3 = x2-x1
if x3 < 1 then
x3 = 1
end
drawtext('B', x1, 9, @center)
drawFillRectangle(@BrushDarkGrey, x1, (@margin/2)+5, x3, @gY+(@margin/2)-5)
end
end
# a Array of points
# Confim how many vectoras and draw all of them
# RED, GREEN and BLUE
def drawgraph(vectorArray, title = "")
@Title = title
#puts " Procewsing data: #{vectorArray} "
@gWidth = getMaxWidth(vectorArray)
@gHeight = setMaxHeight(vectorArray)
drawGraphInfo(vectorArray)
#puts " Drawn Graph Info"
# If vector
puts "Vecotr is a #{vectorArray[0].class}"
if vectorArray[0].class == Array then
#puts 'Is an Array'
(0..vectorArray[0].size-1).each do |x|
tempArray = Array.new()
(0..vectorArray.size-2).each do |n|
tempArray << vectorArray[n][x]
end
draw(tempArray, x)
end
else
# draw liner
#puts 'Not a Array, prob FOV'
#puts vectorArray.min
#puts vectorArray.max
draw(vectorArray, 0)
end
end
#private
def header()
drawFillRectangle(@BrushGrey, 0,0, @x, 14)
drawtext("BLOCKING TAGS", @x/2,0)
end
def drawgrid(array)
# work out steps for every 10
maxSize = array.size
# Set our Fontheigh here in the future
fontHeight = -5
stepX = @gX.to_f / maxSize.to_f
stepY = @gY.to_f / maxSize.to_f
#puts "stepX = #{stepX}"
# Horizitonal Gird and numbers
stepMultiplier = @gY.to_f/maxSize.to_f
#puts "stepMultiplier = #{stepMultiplier}"
mStep = maxSize/30
(0..maxSize).step(mStep) { |n|
drawline(@PenBeige, @margin+(stepX*n), @margin, @margin+(stepX*n), @gY+@margin)
drawtext(n, @margin+(stepX*n), @gY+@margin+4, @center)
}
drawline(@PenBeige, @gX.to_f+@margin-1, @margin, @gX.to_f+@margin-1, @gY+@margin)
# BIt of a cheat as we daw the last grid line 1 pixel in so its drawn on the screen
#drawtext(maxSize, @gX.to_f+@margin, @gY+@margin+4, @center)
#drawtext("frames", ((@margin+(@gX/2))-mStep),(@y-12))
# Verticl Gird and numbers
# Get our min max length
range = @arrayUtils.retRange(array)
#puts "range = #{range}"
#puts "Min = #{@arrayUtils.retMin(array)}"
#puts "Max = #{@arrayUtils.retMax(array)}"
# Mininmun number of Grid divisions
gridStepDivision = 10
# Check if we have a range, if not then the graph range difference is 0 and nothing has changed
if range > 0 then
# Divid our range by our bitmap display height size (@gY) to get our step multiplier
stepMultiplier = @gY.to_f/range.to_f
# Set our step Grid Y Size
mStep = range/gridStepDivision
#puts "mStep = #{mStep}"
# Get our offset if numbers are negative
#yOffset = @arrayUtils.retMin(array).abs
yOffset = @arrayUtils.retMin(array) * -1
#puts "ABS of #{@arrayUtils.retMin(array)} = #{yOffset} "
(@arrayUtils.retMin(array)..@arrayUtils.retMax(array)).step(mStep) { |n|
yHeight = @margin + ((n+yOffset)*stepMultiplier)
drawline(@PenBeige, @margin, yHeight, @gX+@margin, yHeight)
value = '%.2f' % n
drawtext(value, @margin, yHeight+fontHeight, @right)
}
value = '%.2f' % @arrayUtils.retMax(array)
drawtext(value, @margin, @gY+@margin+fontHeight, @right)
else
# Draw single line at centre as nothing has changed
drawline(@PenBeige, @margin, @margin+(@gY.to_f/2), @gX+@margin, @margin+(@gY.to_f/2))
drawtext(0, @margin, @margin+(@gY.to_f/2)+fontHeight, @right)
end
# GRID OUTLINES
# vertical
drawline(@PenBlack, @margin, @gY+@margin, @gX+@margin, @gY+@margin)
# Hotizontal
drawline(@PenBlack, @margin, @gY+@margin, @margin, @margin)
end
def drawGraphInfo(vectorArray)
drawgrid(vectorArray)
header()
drawtext(@Title, 20+@margin,20+@margin)
end
def getMaxHeight(array)
return @arrayUtils.retRange(array)
end
def setMaxHeight(array)
min = @arrayUtils.retMin(array)
#puts "min = #{min}"
# GEt are shift so number is positive
#heighShift = min * -1
#startPoint = (max.to_f - min.to_f / 2) + heighShift
# GET OUR OFFSET SO ITS STARTS AT 0
@setMinHOffset = 0.0
if min != 0.0 then
@setMinHOffset = min * -1
end
maxheightRange = getMaxHeight(array)
result = @gY.to_f/maxheightRange.to_f #-@margin
return result
# For nulll chnage
if maxheightRange != 0.0 then
result = (@y.to_f-@margin)/maxheightRange
else # Array does not contain any differences, so draw at 0 center of image
@setMinHOffset = (@gY/2)
#result =
end
return result
end
def getMaxWidth(array)
return (@gX.to_f)/(array.size-2).to_f
end
def fillbackground()
@graphics.FillRectangle(@BrushBeige, 0,0, @x, @y)
end
def draw(pointArray, penIndex)
if @arrayUtils.retRange(pointArray) > 0 then
(0..pointArray.size-2).each do |n|
pen = @penList[penIndex]
x1 = @margin+(n*@gWidth)
y1 = @margin+((pointArray[n]+@setMinHOffset)*@gHeight)
y2 = @gY + @margin
y2 = @margin+((pointArray[n+1]+@setMinHOffset)*@gHeight)
#draw lin emin and max height
x2 = @margin+((n+1)*@gWidth)
drawline(pen, x1, y1, x2, y2 )
#drawcircle(pen, x1, y1, 2)
end
else
pen = @penList[0]
drawline(pen, @margin,@margin+(@gY/2), @margin+@gX, @margin+(@gY/2) )
end
end
# draw a line
def drawline(penColor, x1, y1, x2, y2)
#puts " X1:#{x1} , Y1:#{y1} , X2:#{x2} ,Y2:#{y2}"
@graphics.DrawLine(penColor, x1, y1, x2, y2)
end
# Draw a circle
def drawcircle(penColor, x1, y1, d1)
@graphics.DrawEllipse(penColor, x1-(d1/2), y1-(d1/2), d1, d1)
end
# Draw Text
def drawtext(text, x, y, align = @left )
@stringformat.Alignment = align
@graphics.DrawString(text.to_s, @DrawFont, @BrushBlack, x, y, @stringformat)
end
# Draw solid rectangel
def drawFillRectangle(brushColor, x1, y1, w, h)
newRectangle = System::Drawing::Rectangle.new(x1, y1, w, h)
@graphics.FillRectangle(brushColor, newRectangle)
end
end