Improving Projectile Motion Graphing in C++

  • Context: C/C++ 
  • Thread starter Thread starter chaoseverlasting
  • Start date Start date
  • Tags Tags
    C++ Graphing
Click For Summary
SUMMARY

The discussion focuses on improving the graphing of projectile motion in C++ using the graphics.h library. Initially, the user faced issues with incomplete and poorly spaced graphs when using text characters for rendering. Suggestions included implementing coordinate transformations, using the putpixel function for better resolution, and optimizing calculations by avoiding the pow function for squaring. The conversation emphasizes the importance of precise sampling techniques and the potential use of the Simple Direct Media Layer (SDL) for advanced graphics rendering.

PREREQUISITES
  • Understanding of C++ programming and syntax
  • Familiarity with projectile motion physics
  • Knowledge of graphics.h library functions
  • Basic concepts of coordinate transformations
NEXT STEPS
  • Learn how to use the putpixel function in graphics.h for pixel-level rendering
  • Research coordinate transformations for scaling and translating graphical output
  • Explore optimization techniques in C++, such as avoiding the pow function for squaring
  • Investigate the Simple Direct Media Layer (SDL) for advanced graphics applications
USEFUL FOR

C++ developers, physics educators, and anyone interested in enhancing graphical representations of mathematical concepts, particularly in projectile motion simulations.

chaoseverlasting
Messages
1,050
Reaction score
3
Hi,
I've a basic knowledge of c++, but I've never learned graphing. What little I know, I've picked up myself. I am trying to graph the motion of a projectile launched with a given speed and at a given angle, but the graph doesn't complete. Also, its very spaced out. I know its a parabola so I can recognise it, otherwise, it very broken up. Can anyone tell me a better way to do this? Here's the code:

r=pow(v,2)*(sin(2*a))/10; //Range
s=v*sin(a);
c=v*cos(a);

for(t=0;x<=r;t=t+0.5) /*Here, instead of the range, I've also tried to use total time taken, but still the graph doesn't go to completion*/
{
x=c*t;
y=s*t - 5*t*t;
gotoxy(x,y);
count<<".";
}

getch();


If anyone wants to see the whole program, Ill put it up.
 
Technology news on Phys.org
You need to use a graphics library of some sort. The reason that the resolution of your graph is so low at the moment is because you are using text to draw with. The "." character is as tall and wide as any other, its just mostly empty space.

There might be a library out there for creating and rendering to a simple window from the console... but I don't know of one off of the top of my head.
 
You are sampling the curve at intervals of 0.5s but what you really want to do is 'ray tracing', which means you find the y for an x or find the x for a y.

Depending on the gradient, one of these will be more precise and you would choose the more precise one. I'm thinking you would have two procedures, one f:x->y and one g:y->x. Then you choose the more precise one initially and at each step you check the gradient to see if you should swap procs.

For instance, if you are using f and your previous point was (2,2) but this point is (3,4) then you know you should have used g, so you use g(3) instead of f(3).
 
Yes, verty's method would definitely help. How you're doing it right now is pretty awkward.

To get it looking nice, you could use the Simple Direct Media Layer. But that is advanced, and I'm not sure how well you could cope with it.

It might help if you posted your whole code too.
 
Ahh.. SDL looks way beyond me... there's a graphics header file, graphics.h in c++ which looks similar (the examples initialize a graphics driver which looks somewhat similar) but my attempts to use it haven't exactly been brilliant.

Here's the rest of the code:
#include<iostream.h>
#include<conio.h>
#include<math.h>
int main(void)
{
float v,a,t,r,s,c,x,y;

clrscr();

count<<"Projectile Motion Program"<<endl;
count<<"Enter initial velocity (floating point number): "<<endl;
cin>>v;
count<<"Enter the angle of projection (in degrees): "<<endl;
cin>>a;
a=0.0175*a; //Converting degrees into radians

count<<"The range of the projectile is: "<<pow(v,2)*(sin(2*a))/10<<endl;
count<<"Press any key to trace the path of the projectile: ";
getch();
clrscr();
r=pow(v,2)*(sin(2*a))/10; //Range
s=v*sin(a);
c=v*cos(a);

for(t=0;x<=r;t=t+0.5)
{
x=c*t;
y=s*t - 5*t*t;
gotoxy(x,y);
count<<".";
}

getch();

}
 
Hey all,
I just figured out how to use graphics.h. The program works much better, its a continuous curve, but sometimes, it runs out of space to plot on and I only see a part of the graph. How could I work around that?
 
Here's the code I've written:

#include<graphics.h>
#include<iostream.h>
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<conio.h>
int main(void)
{
float v,a,t,r,s,c,x,y;

clrscr();

count<<"Projectile Motion Program"<<endl;
count<<"Enter initial velocity (floating point number): "<<endl;
cin>>v;
count<<"Enter the angle of projection (in degrees): "<<endl;
cin>>a;
a=0.0175*a; //Converting degrees into radians

count<<"The range of the projectile is: "<<pow(v,2)*(sin(2*a))/10<<endl;
count<<"Press any key to compute the path of the projectile: ";
r=pow(v,2)*(sin(2*a))/10; //Range
s=v*sin(a);
c=v*cos(a);
getch();
clrscr();

/* request auto detection */
int gdriver = DETECT, gmode, errorcode;

/* initialize graphics mode */
initgraph(&gdriver, &gmode, "");

/* read result of initialization */
errorcode = graphresult();

if (errorcode != grOk) /* an error occurred */
{
printf("Graphics error: %s\n", grapherrormsg(errorcode));
printf("Press any key to halt:");
getch();
exit(1); /* return with error code */
}

for(t=0;x<=r;t=t+0.01)
{
x=c*t;
y=s*t - 5*t*t;
outtextxy(x,y,".");
}

getch();
closegraph();

}
 
It could have to do with non-standard initialization or buffering of your display. I don't have Turbo C++, nor graphics.h, nor do I know how to use it, so I wouldn't be able to test that theory.

If you're just talking about a consistent breaking point for any arbitrary function, that's because you need to do what verty said. Right now, you're just testing arbitrary points at intervals of t. What you should really be doing is using the function f(x), that way you can directly control the domain. As you could control the range with g(x). Then limit the range or domain, respectively, by conditioning the output from whichever function you use.
 
Last edited:
My suggestions weren't all that good because they assume that the graph won't turn too quickly, or have lines too close to each other.
 
  • #10
The thing is, the function y=f(x), usually involves terms with square roots which would take more time to compute (I think). Since I've used parametric equations of the curves, I can just vary the parameter to get the curve.

What I meant was, that sometimes the curve is so big that it doesn't show on the screen. If I could somehow vary the resolution of the screen if the curve is that big, then that would solve the problem...
 
  • #11
You could easily translate the co-ordinates.
 
  • #12
chaoseverlasting said:
Hey all,
I just figured out how to use graphics.h. The program works much better, its a continuous curve, but sometimes, it runs out of space to plot on and I only see a part of the graph. How could I work around that?


Remember basic coordinate transformations?

Just scale and translate the result accordingly. This is very easy and looks like this in code:

x0 = x0*sx + ox;
y0 = y0*sy + oy;
z0 = z0*sz + oz; // neglect for 2 dimensions

Where the ox/oy/oz are the offsets in the relevant directions and the sx/sy/sz are the scale factors.

e.g. sx=sy=sz=0.5; will draw more graph on the screen (4 times as much area!)

If you are familiar with keyboard input (not cin!) you could make these parameters adjustable by keypresses for ease of use.

If you want more speed btw you should not use pow(x,2) for squaring. The C++ pow function uses a series expansion to calculate the result iirc. In practice this means that it is very slow compared to x*x, x*x*x etc. If you write your own (even quite sloppy) integer pow() function it will probably outperform the double precision C++ math lib pow(). e.g.

double ipow(double d, int n)
{
double ret = 1;
for(int i = 0; i < n; i++) ret*=d;
return ret;
}

There might already be an integer power function but I have never used it... so I don't know its name. That would be better to use than the above code snippet, since it would likely contain all the common optimisations and have been refined and improved over the years...

Another speed tip is to avoid division by constants. Multiply by inverses instead. e.g.

x/10 --> x*0.1

Don't worry too much about optimisation though, not everything needs to be as fast as possible, but it is good practice to get used to writing things with some optimisation in the first place.

EDIT: some further advice, instead of rendering with "." characters you should be writing individual pixels, this will further increase the resolution, and his how a graphics library is supposed to be used. Even better is to use lines, this way you can decimate the curve a bit without it looking too bad (if you want). Most graphics library have a line function, if not the Bresenham algorithm is well described and documented on the internet and fast to implement.

Looking up graphics.h there is void far drawpoly(int numpoints, int far *points) and void far line(int startx, int starty, int endx, int endy) which fill this purpose. Also from looking it up I found out that it is a Borland specific library and not part of the C++ standard libraries.. so be warned that your code may not be portable.
 
Last edited:
  • #13
Thank you, that helps... I didnt think about transformations... How do you write individual pixels though?
 
  • #14
chaoseverlasting said:
Thank you, that helps... I didnt think about transformations... How do you write individual pixels though?

I can't find the page I found earlier which had a nice list of all of the graphics.h functions, nor do I have the facilities to look up the actual file...

I'm not sure if this one that I have just found is the same or not: http://www.uniqueness-template.com/devcpp/graphics.h

It looks like it should be... according to this there is

void putpixel( int x, int y, int color );

Hopefully this is what you are looking for...

EDIT: for future reference you can often find .h files on the internet by using google with filetype:h, this is occasionally useful when you are cut off from other more immediate sources of information like online help and such, but not very often (since you should have the .h file you want to look up!).
 
Last edited by a moderator:
  • #15
Thanks a lot man. That helps a lot.
 
  • #16
Thanks! I'm not a specialist in graphing, but try to better my knowledge in it myself. So, i highly appreciate your codes)))
 

Similar threads

Replies
2
Views
2K
Replies
3
Views
1K
  • · Replies 17 ·
Replies
17
Views
2K
  • · Replies 5 ·
Replies
5
Views
2K
  • · Replies 2 ·
Replies
2
Views
2K
  • · Replies 8 ·
Replies
8
Views
2K
Replies
6
Views
2K
  • · Replies 1 ·
Replies
1
Views
2K
  • · Replies 1 ·
Replies
1
Views
2K
  • · Replies 8 ·
Replies
8
Views
3K