Drawing An Arc Using Lines

I am new to C++ and attempting to put together my first Windows App.

I am using Visual Studio 2008 C++ Edition with Windows 7.

I have written a procedure which is called by WndProc using this statement:-

void DrawArc(HDC hdc, double x,double y,double r,double s,double e, COLORREF colour);

As the procedure is a modified procedure for drawing circles:-
hdc is the active window
x and y are the co-ordinates of the circle centre
r is the circle radius
s and e are the start and end of the arc
colour is the arc colour

The actual calling command is
DrawArc(hdc,700.0,85.0,50.0,0.0,90.0,Yellow); which
gives :-
x a value of 700.00
y a value of 85.00
s a value of 0 degrees
e a value of 90 degrees
colour the COLORREF value for yellow

The procedure first of all calculates the x and y co-ordinates for all the points on the circle and stores them in an array.

It then cycles through all the degrees but when it reaches the degrees bounded by the start and end of the arc it draws a line from each point to the centre forming the arc using the details in the array.

At present it is set up to draw an arc between 0 degrees at the top of the circle to 90 degrees in the 3 o'clock position but it actually draws the arc between 90 degrees and 180 degrees from the 3 o'clock position to the 6 o'clock position.I do not understand why this is.Here is the code I am using:-

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
void DrawArc(HDC hdc, double x, double y,double r,double s, double e, COLORREF colour)
 {
	// Initialise variables
	HPEN hPenOld;
	
	// declare hLinePen pen name
	HPEN hLinePen;
	
	// declare qLineColor as pen ink
	COLORREF qLineColor;
	
	// set qLineColor to desired parameter colour
	qLineColor=colour;
	
	// create pen with desired colour
	hLinePen = CreatePen(PS_SOLID, 2, qLineColor);
    
	// select desired pen
	hPenOld = (HPEN)SelectObject(hdc, hLinePen);
	
	// declare circle points array variables
	double xcoords[360];
	double ycoords[360];

	// declare circle centre co-ordinates variables
	double d_centre_x;
	double d_centre_y;

	// declare radius
	double radius;

	// declare start of arc
	double start_arc;

	// declare end of arc
	double end_arc;

	// declare degree
	double degree;

	// declare degrees to radians
	double deg_to_rads;

	// initialise deg_to_rad
	deg_to_rads=0.0174532925;

	// declare radians to degrees
	double rads_to_deg;

	//initialise rads_to_deg
	rads_to_deg=57.2957795;

	// declare int version of circle point co-ordinates
	int px;
	int py;

	// declare int version of circle centre co-ordinates
	int cx;
	int cy;

	//declare int  version of arc start point and end point
	int start;
	int end;

	// import parameters into variables
	d_centre_x=x;
	d_centre_y=y;
	radius=r;
	start_arc=s;
	end_arc=e;
	
        // declare int version of circle centre x & y co-ordinates
	cx=(int)d_centre_x;
	cy=(int)d_centre_y;

	// declare int version of arc start and end
        start=(int)start_arc;
	end=(int)end_arc;

	// declare ctr counter variables
	int ctr;
	int ctr1;

	// set up loop to calculate circle points
	
	for(ctr=1;ctr<360;ctr++)
	  {  
           degree=ctr*deg_to_rads;
	   xcoords[ctr]=d_centre_x+(radius*cos(degree));
	   ycoords[ctr]=d_centre_y+(radius*sin(degree));
	   px=(int)xcoords[ctr];
	   py=(int)ycoords[ctr];
	  }
	   
	// set up loop to draw arc
	for(ctr1 = 1;ctr1<360;ctr1++)
	   {
	   if(ctr1>=start && ctr1<=end)
	   	{
		 cx=(int)d_centre_x;
	         cy=(int)d_centre_y;

		 px=(int)xcoords[ctr1];
		 py=(int)ycoords[ctr1];
		 
		 MoveToEx(hdc,px,py,NULL);
		 LineTo(hdc,cx,cy);
		}
	   }
	
    // delete pen after use
	DeleteObject(hLinePen);
 }

Perhaps someone can spot what I am doing wrong. Any information would be greatly appreciated please.TIA.






Last edited on
Maybe you'll get an answer if you use code tags for your code. For example, I didn't read it because it doesn't use code tags. Maybe others are the same.
Thanks for that webJose. I'll add the codetags. Do I need to add further comments on the code please?
Lines 91 and 92 seem to be a waste because px and py are not used in the loop.

As for your problem: You may want to have zero degrees starting @ the top of the circle, but you have to make that happen. Pixel coordinates grow to the right and down. cos(0) = 1 and cos(pi/2) = 0; sin(0) = 0 and sin(pi/2) = 1. In a typical cartesian space, the Y coordinate grows up, not down. This will have an effect in your graphic: It will be upside down as you have witnessed.

The easiest would be to multiply by -1 the part (radius * sin(degree)), but the professional way probably would be to set the window and viewport origins and extents. See http://msdn.microsoft.com/en-us/library/dd183475(VS.85).aspx for details.

BTW, there is an Arc() function in GDI already. You don't have to create your own.
Thanks for that webJose.

As you say, px and py are not needed so I have deleted them from the loop.

I assumed that when I was creating the circle points they were beginning at the top of the circle and were recorded in 1 degree steps round the circle until it reached the top of the circle at the end of the process.

I put a 10 second delay between the MoveToEx command and the LineTo command and it did actually show the move down from the 3 o'clock position to the 6 o'clock position so as you say the graphics are moving to the right with the y co-ordinate getting bigger for the first half of the circle and smaller on the second half as it works.The problem is that it is starting from the wrong position.

I did try the -1 idea you mentioned and it did start the arc at the top of the circle but only for an angle of about 45 degrees as opposed to the desired 90 degrees.

I'll check out the Microsoft link you posted and see if I can make use of it.

I was not aware of the ARC() function and as I am a novice I tend to use the things I understand, which is rather limited at the moment.

Thanks again for all your help.



Just to finish this off, I had been calculating the circle point co-ordinates incorrectly. The relevant piece of code should have been:-

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// set up loop to calculate circle points
	
	for(ctr=0;ctr<360;ctr++)
	  {
	      //convert degree to rads
              degree=ctr*deg_to_rads;
	   
	      // work out circle point co-ordinates
              xcoords[ctr]=d_centre_x+(radius*sin(degree));
	      ycoords[ctr]=d_centre_y-(radius*cos(degree));

	  }

Just posting this in case anyone else is attempting the same thing and may find the code helpful.

I think we can consider this solved now.Thanks again for all the help.

Topic archived. No new replies allowed.