• Making a math function plot
    17 replies, posted
Hi. I am wondering if there are ways to plotting those mathematical functions... For example, y=ax+b, player's can set a and b by vgui and the shape of this function then is plotted somewhere in the game. (Of course the same vgui is the best). Of course I can plot them by excel or other software, the question is how to upload those .vtf or .vmt file dynamically in the game. Have any idea? Thanks!
You could plot the functions yourself using the [url=http://wiki.garrysmod.com/?title=Draw]draw library[/url], you just need to loop through the x axis, say from -10 to 10 and calculate the y value, then you can either draw a line from the last value to this one, or just draw a point.
Thanks.. Partly understand...
Completely untested but it should work : [lua]local function Y(x,a,b) return a*x+b end local a = 3 -- Default values for the example local b = 5 local xMin = -10 -- Lowest value to draw local xMax = 10 -- Highest value to draw local step = 1 --The distance between points on the x axis. local baseX = ScrW() * 0.5 -- This is the middle of the screen local baseY = ScrH() * 0.5 -- This is the middle of the screen hook.Add("HUDPaint", "DrawFunction", function() if (xMin >= xMax) or (step > xMax - xMin) then return end -- Checking our values for x1 = xMin,xMax-1,step do local x2 = x1+step -- Calculating the next value of x so we can draw a line between the 2 local y1 = Y(x1,a,b) local y2 = Y(x2,a,b) print("("..x1..", "..y1..") to ("..x2..", "..y2..")") -- For debug purposes surface.DrawLine( baseX + x1, baseY + (y1*-1),baseX + x2, baseY + (y2*-1) ) -- Adding our points to the coordinates of the middle of the screen. I'm reverting the y because I'm pretty sure that on the screen a lower y is higher. I could be wrong. end end)[/lua] :science:
[QUOTE=Crazy Quebec;20919053]Completely untested but it should work : [lua]local function Y(x,a,b) return a*x+b end local a = 3 -- Default values for the example local b = 5 local xMin = -10 -- Lowest value to draw local xMax = 10 -- Highest value to draw local step = 1 --The distance between points on the x axis. local baseX = ScrW() * 0.5 -- This is the middle of the screen local baseY = ScrH() * 0.5 -- This is the middle of the screen hook.Add("HUDPaint", "DrawFunction", function() if (xMin >= xMax) or (step > xMax - xMin) then return end -- Checking our values for x1 = xMin,xMax-1,step do local x2 = x1+step -- Calculating the next value of x so we can draw a line between the 2 local y1 = Y(x1,a,b) local y2 = Y(x2,a,b) print("("..x1..", "..y1..") to ("..x2..", "..y2..")") -- For debug purposes surface.DrawLine( baseX + x1, baseY + (y1*-1),baseX + x2, baseY + (y2*-1) ) -- Adding our points to the coordinates of the middle of the screen. I'm reverting the y because I'm pretty sure that on the screen a lower y is higher. I could be wrong. end end)[/lua] :science:[/QUOTE] Wow, nice.
Wow... Really appreciate!
Another problem is the hook. I find that if I do not use [lua] hook.Add("HUDPaint", "DrawFunction", function() [/lua] but directly put the surface.DrawLine in a function that mainly describe vgui, there will be no line drew. However, if I use this hook, it will draw at the beginning of the game, which is not what I want. SO must surface.DrawLine relates to the "HUDPaint" hook or is there anyway that not let "HUDPaint" happen... THanks
It doesn't really matter where as long as it's in a drawing hook. In your case you should create a derma vgui and do the drawing in one of the panel's Paint hook. [url]http://wiki.garrysmod.com/?title=DPanel[/url] [url]http://wiki.garrysmod.com/?title=Vgui.Create[/url] [b][url=wiki.garrysmod.com/?title=Panel.Paint]Panel.Paint [img]http://wiki.garrysmod.com/favicon.ico[/img][/url][/b] [editline]02:13PM[/editline] So that means that when defining your panel you want to draw on you can do this : [lua]function mypanel:Paint() if (xMin >= xMax) or (step > xMax - xMin) then return end -- Checking our values for x1 = xMin,xMax-1,step do local x2 = x1+step -- Calculating the next value of x so we can draw a line between the 2 local y1 = Y(x1,a,b) local y2 = Y(x2,a,b) print("("..x1..", "..y1..") to ("..x2..", "..y2..")") -- For debug purposes surface.DrawLine( baseX + x1, baseY + (y1*-1),baseX + x2, baseY + (y2*-1) ) -- Adding our points to the coordinates of the middle of the screen. I'm reverting the y because I'm pretty sure that on the screen a lower y is higher. I could be wrong. end end[/lua] And then you can change the a and b values through other derma controls. Also baseX and baseY's values should be the center of the control you want to draw on.
I made this [img_thumb]http://i44.tinypic.com/2itos5e.jpg[/img_thumb] [img_thumb]http://i44.tinypic.com/357r3bn.jpg[/img_thumb] Is it similar to what you are looking for? [editline]06:31PM[/editline] Click on the images, the line are a bit thin to see in the thumb.
Looks quite like it, what do you use to draw points? surface.DrawLine(x1,y1,x1,y1) ?
I'm actually using surface.DrawRect(x1 - 1, y1 - 1, 3, 3). [editline]06:39PM[/editline] In those images though I was using surface.DrawRect(x1, y1, 1, 1), but I changed it when I realised that this is wrong.
[QUOTE=MakeR;20939152]I made this [img_thumb]http://i44.tinypic.com/2itos5e.jpg[/img_thumb] [img_thumb]http://i44.tinypic.com/357r3bn.jpg[/img_thumb] Is it similar to what you are looking for? [editline]06:31PM[/editline] Click on the images, the line are a bit thin to see in the thumb.[/QUOTE] Almost exactly what I want. This is my code that define a vgui which belongs to the entity. I paste an example draw circle script inside. [lua] function ENT:PanelSetting() local Frames=vgui.Create("DFrame") Frames:SetPos(50,50) Frames:SetSize(450,450) Frames:SetVisible( true ) Frames:SetDraggable( true ) -- Draggable by mouse? Frames:ShowCloseButton(true) local NumSlide=vgui.Create("DNumSlider",Frames) NumSlide:SetPos(25,25) NumSlide:SetSize(100,40) NumSlide:SetMax(24) NumSlide:SetMin(0) NumSlide:SetDecimals(0) --Here is the part to drawing local center = Vector( ScrW() / 2, ScrH() / 2, 0 ) local scale = Vector( 100, 100, 0 ) local segmentdist = 360 / ( 2 * math.pi * math.max( scale.x, scale.y ) / 2 ) surface.SetDrawColor( 255, 0, 0, 255 ) Msg("Hi Drawing") for a = 0, 360 - segmentdist, segmentdist do surface.DrawLine( center.x + math.cos( math.rad( a ) ) * scale.x, center.y - math.sin( math.rad( a ) ) * scale.y, center.x + math.cos( math.rad( a + segmentdist ) ) * scale.x, center.y - math.sin( math.rad( a + segmentdist ) ) * scale.y ) end --Drawing the circle ends here local Button=vgui.Create("DButton",Frames) Button:SetPos(25,95) Button:SetSize(50,50) Button:SetText("OK") Button.DoClick=function() self.Fre=NumSlide:GetValue() Frames:Close() end end [/lua] And this is the result: [IMG]http://i43.tinypic.com/212bk08.jpg[/IMG] No circle is put. However, if I did it like this way: [lua] function ENT:PanelSetting() ... end hook.Add( "HUDPaint", "Circle", function() local center = Vector( ScrW() / 2, ScrH() / 2, 0 ) local scale = Vector( 100, 100, 0 ) local segmentdist = 360 / ( 2 * math.pi * math.max( scale.x, scale.y ) / 2 ) surface.SetDrawColor( 255, 0, 0, 255 ) for a = 0, 360 - segmentdist, segmentdist do surface.DrawLine( center.x + math.cos( math.rad( a ) ) * scale.x, center.y - math.sin( math.rad( a ) ) * scale.y, center.x + math.cos( math.rad( a + segmentdist ) ) * scale.x, center.y - math.sin( math.rad( a + segmentdist ) ) * scale.y ) end end) [/lua] There will be a circle that drawing on the screen when the game start. [IMG]http://i40.tinypic.com/2iswq3l.jpg[/IMG]
2 things, you're not doing the drawing in your frame's Paint hook and you're using the middle of the screen as a center value. You should be using a value that will make it fit on said frame. If you just want it to draw in the center anyway you could put a condition to the drawing.
I want to let it to be on the vgui panel, looks same as makeR does. However, when I use: [lua] local Frames=vgui.Create("DFrame") Frames:SetPos(50,50) Frames:SetSize(450,450) Frames:SetVisible( true ) Frames:SetDraggable( true ) -- Draggable by mouse? Frames:ShowCloseButton(true) Frames.Paint=function( for a = 0, 360 - segmentdist, segmentdist do surface.DrawLine( center.x + math.cos( math.rad( a ) ) * scale.x, center.y - math.sin( math.rad( a ) ) * scale.y, center.x + math.cos( math.rad( a + segmentdist ) ) * scale.x, center.y - math.sin( math.rad( a + segmentdist ) ) * scale.y ) end ) [/lua] The nightmare was that the frame will even not come out... Really Thanks....
[lua] Frames.Paint=function( for a = 0, 360 - segmentdist, segmentdist do surface.DrawLine( center.x + math.cos( math.rad( a ) ) * scale.x, center.y - math.sin( math.rad( a ) ) * scale.y, center.x + math.cos( math.rad( a + segmentdist ) ) * scale.x, center.y - math.sin( math.rad( a + segmentdist ) ) * scale.y ) end )[/lua] That's because you put all of your code in the argument to the function and did not end it. :smile: This should work better : [lua]Frames.Paint=function() for a = 0, 360 - segmentdist, segmentdist do surface.DrawLine( center.x + math.cos( math.rad( a ) ) * scale.x, center.y - math.sin( math.rad( a ) ) * scale.y, center.x + math.cos( math.rad( a + segmentdist ) ) * scale.x, center.y - math.sin( math.rad( a + segmentdist ) ) * scale.y ) end end[/lua]
Er................... Sorry........ In my script I did so... with the end on it...
The important part is the parenthesis after function. You put all of the code in them while rhey should be closed.
Er... Seems not this problem... Thank you guys very much.
Sorry, you need to Log In to post a reply to this thread.