|
-
Apr 3rd, 2010, 05:44 PM
#1
Thread Starter
New Member
Simple Graphics Problem (please help)
Hello guys
This problem has been bugging me for a while now so hopefully one of your wonderful minds can solve it.
I simply want to use the Line Shape in VB to create an "Inclined Plane"
In order to do that I need two lines. One line should just be horizontal and the other line should change from being horizontal until it goes all the way up to 90 degrees (i.e. it's vertical)
Question is:
1. How do I make that line rotate from 0-90 degrees to the left
2. How do I add a "mass" to the plane that "sticks" to the plane as I change the angle
To sum things up and make this less confusing I simply want to make a program where someone can enter a value for the angle of an inclined plane and enter details such as the weight of the mass that is on that plane etc.
Then click "Go" and that mass just "falls" down accordingly.
It should look something like the image 1 attached.
Image2 shows what I currently have done in VB.
Hopefully you guys can point me in the right direction.
Thanks.
-
Apr 3rd, 2010, 05:48 PM
#2
Re: Simple Graphics Problem (please help)
This isn't a graphics problem, it's a physics problem. Usually, you'd need to solve a complicated differential equation (newton's law), but luckily your setup is simple. So, you can simply pre-calculate the acceleration the block will have under the specified circumstances. I assume you know how to do that, on paper? If you got it on paper it won't be hard to translate into code.
To draw the inclined line, well, judging from your screenshot you can do that already, so what's the problem?
You can find the end point of the line using simple trigonometry.
x = length * cos(angle)
y = length * sin(angle)
Of course these points are relative to the starting point. Also, you need to take into account that the y-axis is inversed in VB (it starts from 0 at the top of the container and increases towards the bottom of the container), so you'll need a negative sign in the y-position.
To draw the block itself, you'd probably need to draw the four lines separately, or use something more complicated like drawing a rectangle and then rotating the graphics object (you can't draw inclined rectangles like that in any simple way as far as I know).
Last edited by NickThissen; Apr 3rd, 2010 at 05:52 PM.
-
Apr 3rd, 2010, 06:45 PM
#3
Thread Starter
New Member
Re: Simple Graphics Problem (please help)
 Originally Posted by NickThissen
This isn't a graphics problem, it's a physics problem. Usually, you'd need to solve a complicated differential equation (newton's law), but luckily your setup is simple. So, you can simply pre-calculate the acceleration the block will have under the specified circumstances. I assume you know how to do that, on paper? If you got it on paper it won't be hard to translate into code.
To draw the inclined line, well, judging from your screenshot you can do that already, so what's the problem?
You can find the end point of the line using simple trigonometry.
x = length * cos(angle)
y = length * sin(angle)
Of course these points are relative to the starting point. Also, you need to take into account that the y-axis is inversed in VB (it starts from 0 at the top of the container and increases towards the bottom of the container), so you'll need a negative sign in the y-position.
To draw the block itself, you'd probably need to draw the four lines separately, or use something more complicated like drawing a rectangle and then rotating the graphics object (you can't draw inclined rectangles like that in any simple way as far as I know).
First of all thanks for your response, though I still dont know how to put a an angle of lets say 60 degrees into the "angle" box and then make the line go from horizontal to 60 degrees.
My problem is just creating an equation where I can just input angle values and as a result the co-ordinates of the line changes accordingly.
any ideas?
PS: sorry for being such a noob!
-
Apr 4th, 2010, 12:46 AM
#4
Re: Simple Graphics Problem (please help)
I think this is a perfect example of where you should use Graphics transformations. You can think of the Graphics object like a sheet of tracing paper. You would work out your physics with the tracing paper horizontal - see the first picture below. That way you can work out the movement of the block on an x-y axis instead of on the slope.
Then when it comes to drawing the results, you turn and shift the sheet of "tracing paper" -- the graphics object -- to put the block and the slope in the right position. In VB.Net, you would normally do it in the Paint event sub of a form or a picture box. First of all, you draw the "straight" parts of the picture. Then you rotate and translate the Graphics object to draw the block and the slope:
vb.net Code:
'straight part of drawing: e.Graphics.DrawLine('.....etc.) '....... 'Rotate the graphics around its origin (angle in degrees): e.Graphics.RotateTransform(angle, MatrixOrder.Append) 'Translate the graphics to line up with the rest of the drawing: e.Graphics.TranslateTransform(distanceX, distanceY, MatrixOrder.Append) 'Draw the slope and the block as though they were on the straight: e.Graphics.FillRectangle('...block) e.Graphics.DrawLine('...horizontal line to represent the slope)
It's usual to do the rotation first and then the translation. But for some reason, VB.Net does all its graphics transformations in reverse order (MatrixOrder.Prepend) by default; I suppose it's a mathematician's thing. That's why I suggest specifying MatrixOrder.Append to get the transformations in the "right" order.
all the best, BB
Last edited by boops boops; Apr 4th, 2010 at 12:52 AM.
-
Apr 4th, 2010, 05:55 AM
#5
Thread Starter
New Member
Re: Simple Graphics Problem (please help)
BB
Thanks for your response, it seems like what you suggested is the best way to do it, though as a noob I am quite confused.
I get the part where you said you use the graphics object like "tracing" paper, but when it comes to the code I get very very confused...
Basically try to take things really step by step (I know, im like a baby in these things!)
Step 1:
Create a two pictures one for the block and the other for the inclined plane being horizontal
Step 2:
Create two picture boxes and place the pictures in them
etc etc
(the by the end, the program should look like a simple version of this one:
http://www.phy.hk/wiki/englishhtm/Incline.htm)
Thank you all for helping out someone new at vb!
-
Apr 4th, 2010, 07:17 AM
#6
Re: Simple Graphics Problem (please help)
There are always different ways to do things, but what I'm suggesting is to use just one picture box for all the drawing. Then, instead of setting the picture box's BackgroundImage or Image, you draw everything in the Paint sub using basic graphics commands like DrawLine, DrawRectangle and FillRectangle. That will make it possible to take advantage of the graphics transformations.
Do you have any experience of drawing that way? Are you familiar with doing a straight-line animation using a timer? And do you know how to get user input into your program, for example using a text box? None of these things are complicated in themselves, but you need to get the hang of them before you start on the sliding block animation. That will probably turn out to be more complicated than it looks at first sight. You mentioned step 1 and step 2, but there's the other 30 steps you need to think about -- not to mention working out the physics in VB.Net
BB
-
Apr 4th, 2010, 07:21 AM
#7
Thread Starter
New Member
Re: Simple Graphics Problem (please help)
Nope... I have no experience in any of that stuff...
god, this is gonna take longer then I expected (its a uni project so I have to do it anyway)
well, the first step I guess is learning all that stuff that you mentioned.
Do you know of any video tutorials or anything?
-
Apr 4th, 2010, 08:03 AM
#8
Re: Simple Graphics Problem (please help)
No, you don't need to create multiple pictureboxes. I suggest you use one picturebox, on which you do all the drawing.
You always draw using an instance of the Graphics class. You can create that Graphics object yourself, but you usually shouldn't. The PictureBox (and all other controls) has a Paint event, which you should use for drawing. The Paint event passes a PaintEventArgs parameter 'e'. That parameter contains the Graphics object you need to use (e.Graphics).
That Graphics object has many drawing methods, such as DrawLine, DrawRectangle, FillRectangle, DrawArc, etc, which you use to draw stuff.
Furthermore, you can manipulate the Graphics object itself. You can rotate it, translate ("move") it, resize it, etc. In general, you do that by using transformation matrices, which is quite complicated. Furtunately, the most used transformations have a built in method (TranslateTransform, RotateTransform, etc).
Since you cannot draw an inclined Rectangle (unless you draw the four lines manually, but then you cannot fill it with a different color), the best way to draw the block is to rotate the graphics object, and then draw it as if you are just drawing a horizontal block. This is what boops boops' code does, although you still need to fill in the method parameters.
Unfortunately, that is not an easy task. Boops boops suggest that you draw the straight lines of the inclined 'hill' first, before you start rotating the graphics object. Then, you rotate the graphics object and draw the inclined plane and the block. The hard part is to line them up exactly.
Well, since I was typing this I see I was too late, but ok 
I made you a little example:
vb.net Code:
Public Class Form1 Private Const STRAIGHT_START_X As Integer = 30 Private Const STRAIGHT_START_Y As Integer = 30 Private Const STRAIGHT_START_W As Integer = 150 Private Sub PictureBox1_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint Dim angle As Double = Double.Parse(TextBox1.Text) Dim rad As Double = angle * Math.PI / 180 'to radians Dim topX As Integer = STRAIGHT_START_X + STRAIGHT_START_W Dim radius As Double = STRAIGHT_START_W / Math.Cos(rad) Dim topY As Integer = STRAIGHT_START_Y + CInt(radius * Math.Sin(rad)) 'Straight parts e.Graphics.DrawLine(Pens.Black, _ STRAIGHT_START_X, _ PictureBox1.Height - STRAIGHT_START_Y, _ STRAIGHT_START_X + STRAIGHT_START_W, _ PictureBox1.Height - STRAIGHT_START_Y) e.Graphics.DrawLine(Pens.Black, _ topX, _ PictureBox1.Height - STRAIGHT_START_Y, _ topX, _ PictureBox1.Height - topY) 'Rotate and translate the matrix e.Graphics.RotateTransform(-CSng(angle), Drawing2D.MatrixOrder.Append) e.Graphics.TranslateTransform(STRAIGHT_START_X, PictureBox1.Height - STRAIGHT_START_Y, Drawing2D.MatrixOrder.Append) 'The origin is now on the left-most 'point' of the triangle 'Draw the inclined line (in our rotated coordinate system, just a horizontal line) e.Graphics.DrawLine(Pens.Black, _ 0, _ 0, _ CInt(radius), _ 0) 'Draw the rectangle Dim rectWidth As Integer = 50 Dim rectHeight As Integer = 25 Dim rect As New Rectangle(CInt((radius - rectWidth) / 2), _ -rectHeight, _ rectWidth, _ rectHeight) e.Graphics.FillRectangle(Brushes.Red, rect) e.Graphics.DrawRectangle(Pens.Black, rect) End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click PictureBox1.Invalidate() End Sub End Class
Add a PictureBox, TextBox and Button to your form. The text in the textbox represents the angle in degrees. Press the button to re-draw it.
This image shows you the constants I used:

The radius is calculated from the angle and the width of the triangle.
The y-coordinate of the top of the rectangle is calculated from the radius and the angle.
The code first draws the straight lines.
Then, I rotate the graphics object along the angle (minus the angle actually, because the rotation is clockwise). Then, I translate the graphics object so that the (new) origin is now at the left-most point of the triangle.

Drawing the inclined line and the block is then easy: the inclined line is just a 'horizontal' (in our new coordinate system) line, with length radius, starting at 0,0 and ending at (radius, 0).
The rectangle is drawn on the middle of the line. It's x-coordinate (top-left corner) is half of (radius - width):
Code:
CInt((radius - rectWidth) / 2)
It's y-coordinate is minus the height (minus because the y-axis is down!).
It wasn't as hard as I thought it would be, but it is a little tricky if you don't know what you're doing.
Now, in order to let the block slide, you'd need to calculate its acceleration. Once you know that, you can make it move, faster and faster, using a timer, along the (new, rotated) x-axis. You don't need to take the angle into account anymore (except for calculating the acceleration), you just need to change the x-position, because the coordinate system is rotated.
Once you know the acceleration you'll need to translate that into a velocity, every timer step, and that finally into a new x-coordinate.
Last edited by NickThissen; Apr 4th, 2010 at 08:11 AM.
-
Apr 4th, 2010, 09:06 AM
#9
Re: Simple Graphics Problem (please help)
Well it looks like Nick and I are both thinking along the same lines, I'm glad to say. The best way to learn is to try things out and ask if you get stuck. I'll just make a few extra points about the "baby steps" just in case you need them.
You clearly know about using the Visual Studio Designer, and I suppose you must know about the code page too. The code page has two drop down lists at the top. Select the picture box from the left list, and the Paint event from the right one. That puts the boilerplate code for the Paint Sub onto your form -- the same as Nick has used above. Once you are in that sub and you type:
Intellisense will offer you a whole list of Graphics commands you can use, and tell you what arguments you have to fill in. There's so much choice it's hard to start, but DrawLine, DrawRectangle and FillRectangle are pretty straightforward. When it asks you for a Pen or a Brush, just use something like these for the present:
Code:
Pens.Blue
Brushes.Purple
and so on. I suggest you play around with the commands to get familiar with them a bit.
For more information at this level, you could take a look at Bob Powell's GDI+ FAQ for beginners. You can ignore step 1 because it's not needed in VS2008. Just to avoid confusion, note that Bob Powell generally uses a Sub called OnPaint instead of the PictureBox_Paint Sub which most people use (see Nick's code); the difference is a very minor one, and it doesn't affect anything else.
For animation.. Well, you could just add a timer to your form in the Designer, set its interval to something like 30 ms. and use a button to start and stop it. Then you use the Timer Tick event to move something - a rectangle, an image etc. - by a few pixels in one direction. After that you put PictureBox1.Invalidate to fire off the Paint event and draw whatever it is in its new position.
I just posted a small program on another thread yesterday with a simple animation with images. You might find it interesting to look at the code at some point, because it also has a bit of acceleration: http://www.vbforums.com/showthread.php?t=609707
For information about inputting user data, search for examples of TextBox with TryCast on this forum.
all the best, BB
-
Apr 4th, 2010, 10:08 AM
#10
Re: Simple Graphics Problem (please help)
I just want to stress that you should approach this application in two parts. The first part is the physics; calculating the acceleration of the block. If you can do that on paper, you can do it in code too. The problem is then translating that acceleration to a change in velocity, and finally a change in position.
If you want to do it very thoroughly, you'd have to do a numerical integration to find the new position. But I think you can get away with 'cheating', by simply adding the value of the acceleration to the velocity, and adding the value of the velocity to the x-position of the block. That is not entirely physical, and will not result in 100% accurate results, but if you only care about the visual aspect (which I think you do, you're not going to plot the velocity against time or something, are you?), then it will do just fine. You'll get something like this
Code:
a = GetAcceleration() // calculate a, needs to be done only once because it's constant
v = v + a * some_factor
x = x + v
re-paint picturebox with new x-location
You can multiply the acceleration a by some_factor to get it to look good.
The second part is the drawing, which I've shown you an example of. Because I have rotated the coordinate system, you only need to change the x-location of the block. In the new system, the slope is horizontal, and the block is experiencing a 'sideways' gravity, under an angle. So it will only move in the horizontal direction. That makes it much easier.
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|