C++ graphing problem

1. Dec 19, 2006

chaoseverlasting

Hi,
I've a basic knowledge of c++, but I've never learnt graphing. What little I know, I've picked up myself. Im trying to graph the motion of a projectile launched with a given speed and at a given angle, but the graph doesnt 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 doesnt go to completion*/
{
x=c*t;
y=s*t - 5*t*t;
gotoxy(x,y);
cout<<".";
}

getch();

If anyone wants to see the whole program, Ill put it up.

2. Dec 19, 2006

Jheriko

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.

3. Dec 19, 2006

verty

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).

4. Dec 19, 2006

Sane

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.

5. Dec 20, 2006

chaoseverlasting

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 havent 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();

cout<<"Projectile Motion Program"<<endl;
cout<<"Enter initial velocity (floating point number): "<<endl;
cin>>v;
cout<<"Enter the angle of projection (in degrees): "<<endl;
cin>>a;

cout<<"The range of the projectile is: "<<pow(v,2)*(sin(2*a))/10<<endl;
cout<<"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);
cout<<".";
}

getch();

}

6. Dec 20, 2006

chaoseverlasting

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?

7. Dec 20, 2006

chaoseverlasting

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();

cout<<"Projectile Motion Program"<<endl;
cout<<"Enter initial velocity (floating point number): "<<endl;
cin>>v;
cout<<"Enter the angle of projection (in degrees): "<<endl;
cin>>a;

cout<<"The range of the projectile is: "<<pow(v,2)*(sin(2*a))/10<<endl;
cout<<"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();

}

8. Dec 20, 2006

Sane

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: Dec 20, 2006
9. Dec 20, 2006

verty

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. Dec 21, 2006

chaoseverlasting

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 doesnt 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. Dec 21, 2006

verty

You could easily translate the co-ordinates.

12. Dec 21, 2006

Jheriko

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: Dec 21, 2006
13. Dec 21, 2006

chaoseverlasting

Thank you, that helps... I didnt think about transformations.... How do you write individual pixels though?

14. Dec 21, 2006

Jheriko

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 [Broken]

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: May 2, 2017
15. Dec 21, 2006

chaoseverlasting

Thanks a lot man. That helps a lot.

16. Sep 16, 2011

Trevorwin

Thanks!! I'm not a specialist in graphing, but try to better my knowledge in it myself. So, i highly appreciate your codes)))