
How to draw arc in opengl? 
yew chee
Member #9,289
November 2007

these are some information to draw arc 1. point 1 How to write the code? 
Archon
Member #4,195
January 2004

Look up how to do bezier curves. 
yew chee
Member #9,289
November 2007

then,how to draw bezier?......:D 
Edgar Reynaldo
Member #8,592
May 2007

If you just want a circular arc from a defined point and radius you need to know these things :
This is just an example and is untested. I would make it into a function that accepts a BITMAP* , a center x and y for the circle , its radius and the starting angle and angular length of the arc. If you want to use this to draw an arc using two points on a circle and its radius then you can find the two points (center points) that are equidistant from each of the two points on the circle and then pick the appropriate one. Pass that as the center and its radius. You'll have to find the starting angle and angular length as well. 
Nicol Bolas
Member #9,238
November 2007

Quote: these are some information to draw arc 1. point 1 I'm afraid that this is not enough information. For example, the radius field is selfexplanatory, but what do point 1 and point 2 refer to? And how do these points relate to the angle? The usual definition of an arc is with a circle (point + radius) and two angles, with the arc drawn between them in a specific direction. Given this information, drawing the arc is simple in OpenGL. You build a loop, from the first angle to the second, with some reasonable stepsize. Then, compute points on the circle for each angular increment in the loop. After that, feed these points to OpenGL as a list of lines.

Thomas Fjellstrom
Member #476
June 2000

I had coded a simple "degraded" form (subset) of an arc, wrote it in agl and perl/glut. Basically the function took the start coord, the end coord, and the radius. the rest is worked out, and the actual ends always reached from one end to the other, always making a half oval/circle. If I could get to it, Id post it, but Im not at home, and once I get home, I have no idea if its on the most recent backup I made (back in april/may or something). edit: here it is  
yew chee
Member #9,289
November 2007

Thomas,your code just draw half circle....not arc! [IMG]http://img.photobucket.com/albums/v715/tiamchee/e.jpg[/IMG] 
Nicol Bolas
Member #9,238
November 2007

I'm afraid your link is a little broken. However, I did see the image. In any case, your definition of an arc is not in the format that is most reasonable for actual use. Also, it is not guaranteed to produce a result; if the radius is smaller than half the length of the line, then there can be no arc that fits the requirements. Even if the radius is large enough, it does not define a unique arc; it actually defines 2, depending on which side of the line you put the center of the circle. You can adopt a convention for it of course. But in any case, the most effective form is with a circle and two angles. You can convert your format to this with some trigonometry and a convention as stated above. But I'll leave that as an exercise for the reader.

yew chee
Member #9,289
November 2007

that why i state one of the information is "angle of arc below 180" so,only one center point can be determined...... 
Thomas Fjellstrom
Member #476
June 2000

Quote: Thomas,your code just draw half circle....not arc! I said that, but it actually draws half ellipses you can pass in any radius. Also, its a simple exercise to get it to draw normal arcs. I just short cut'ed it to do half ellipses.  
Edgar Reynaldo
Member #8,592
May 2007

{I revised and corrected this post on 12112007} Since an arc is a segment of a circle then what we need first is a circle. A circle can be defined in several ways :
Since we want to draw arcs and not circles then we need 4 things : I've already shown how to draw an arc using circle type # 1 in my previous code. I've refined it into a function which I will post below. In the meantime , I will explain how to draw an arc using circle types # 2 and # 3. Drawing an arc using circle method # 2 : Given 2 points A and B and a radius r : ################# Revision ################ I. Find the midpoint E of the line segment AB
II. Find the distances AE and then CE II a. Find the distance from A to E using the distance formula.
II b. Find the distance from C to E using the pythagorean theorem.
III. Find the angle of A to B and then the angle of C to E III a. Find angle AB
III b. Find angle CE by adding PI/2.0 to angle AB (one positive quarter turn)
IV. Now we can find the coordinates of the center of the circle IV a. Right handed curve (clockwise) (decreasing angles) IV b. Left handed curve (counterclockwise) (increasing angles) V. Finding angles from C or D to A and B V a. Right handed curve V b. Left handed curve VI. Now we find the starting angle and ending angle. VI a. Right handed curves VI b. Left handed curves VII. Finding the angular length
VIII. Solution for arc data complete! ############### End Revision ############### Here's my revised code for drawing an arc given (a) , (b) , (c) , and (d) from above and also the distance you would like between successive points on the arc.
I'll show how to draw an arc from point A through point B to point C in my next post. {Edited formulas for correctness 12112007} 
Albin Engström
Member #8,110
December 2006

Edgar Reynaldo rocks, just coming out of nowhere and posting awesomely detailed answers.. unfortunately, I'm not good enough to understand half of it but i really like the time he spends on sharing his knowledge, i think you should make handy tutorials instead of letting things like this fade away as mere replies. . Also, maybe the draw_arc function could make a good contribution too the allegro library? as far as i can tell allegro does not have such a function and i think it might be a cool thing to have included. 
Edgar Reynaldo
Member #8,592
May 2007

{I revised and corrected this post on 12142007} My previous post in this thread has been updated and corrected. I've tested the process for finding the correct information to draw an arc from 2 unique points , a radius , and the direction of the angle drawing the curve. It works now! This post has been revised and corrected since the last method was based on incorrect formulas.  Albin  BTW , Allegro already has an arc function that accepts integer circle coordinates and angles in allegro's fixed data type. Other note : The function for drawing an arc that I posted takes degrees and not radians , but could be easily altered to accept radian angles. On to cooler things , drawing an arc from point A through point B to point C. http://www.allegro.cc/files/attachment/593951 #################### Revision ######################### Okay , step by step here is how to get the relevant data to draw an arc from point A through point B to point C. I. First make sure that all three points are unique (are not equivalent). II. Find the angles from A to B , from B to C , and from A to C by using the atan2 function : Since the atan2 function returns values in the range from PI to PI , normalize them to [0,2.0*PI). III. Determine the direction that the curve of the arc is being drawn and make sure all 3 points are not on a line. In this case let's normalize the angle to [PI , PI] so : double ang_X = ang_BtoC  ang_AtoB; if (ang_X > PI) { ang_X = two_pi; } else { if (ang_X < 1.0*PI) {ang_X += two_pi;} } Angle X tells us whether the arc from A through B to C is a right handed arc (drawn clockwise) (as the arc is drawn the angle decreases) or if it is a left handed arc (drawn counterclockwise) (as the arc is drawn the angle increases). If angle X is from 0 degrees to 180 degrees (0 to PI) then it is left handed. If angle X is from 180 to 360 degrees (PI to 2*PI) (also 180 to 0 or PI to 0) then it is right handed. Note that angle X can not be 0 degrees or 180 degrees otherwise all three points are on the same line and could never be points on a circle. So now we check whether angle X is equal to 0.0 or whether angle X is equal to PI. If either is true then all three points are on the same line and cannot be used to make a circle. Now that we know angle X and that the three points are not on a line then from its value we know which direction the curve is being drawn. If angle X is greater than zero then the curve of arc is left handed (counterclockwise) (increasing angles). If angle X is less than zero then the curve of the arc is right handed (clockwise) (decreasing angles). if (ang_X < 0.0) {righthanded = true;} IV. Find the midpoints of AB , BC , and AC. V. Find the angles from the center of the circle (point G) to points D , E , and F.
If any of these angles are greater than or equal to 2.0*PI than subtract 2.0*PI from them to get a normalized angle from [0,2.0*PI). VI. Find general first degree equations for the lines through G and D , G and E , and G and F. Now take two points and assume they are on the same line. Since the left hand side of each equation is equal to negative C then we can set them equal to each other and solve for A or B. This gives us : and then : so : Since we only have one point and an angle to find the equation of the line from , we need to refine these a little. Using trigonometry we can replace (y2  y1) with r*sin(θ) and replace (x1  x2) with r*cos(θ) where θ is the angle of the line. This diagram should make it clear. {"name":"593952","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/a\/6\/a6e00543828d1cf74db7ab9e8fd637ac.png","w":480,"h":360,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/a\/6\/a6e00543828d1cf74db7ab9e8fd637ac"} Okay , so if we substitute r*sin(θ) and r*cos(θ) into our equation then the r's factor out and give us : Formula # 1 Formula # 2 If the line is either horizontal or vertical then one of these formulas will be undefined due to division by zero , but the other will still be valid. If the line is diagonal then either formula will work but I prefer # 1 because it is easier to translate it to a slopeintercept line equation. Okay , so now we have the ratio between A and B , but how do we go on from here? Using N as a constant multiplier of the formula for a first degree general equation we have : This means that we can scale the equation according to our needs. If we set N = 1/B as long as B != 0 then we have effectively changed B to the value of 1. Similarly this can be used to scale A as well as long as A != 0. This gives us three cases to handle then when we want to find the general first degree equation of a line from a point and an angle : Horizontal line (cos(θ) == 0) Vertical line (sin(θ) == 0) Diagonal line (nonzero values for sin(θ) and cos(θ)) Okay , so we use this method to find the general first degree equations of the lines through GD , GE , and GF. VII. Now find the intersection of two of the three equations and we have found the center of the circle. Say we have two first degree general equations like this : Subtract the constants from each side of the appropriate equation. Now to find x or y then we need to multiply one of the equations by a constant so we can subtract away either x or y. To find x , multiply the second equation times (B/E) and then subtract the result from the first equation and solve for x. To find y , multiply the second equation by (A/D) and then subtract the result from the first equation and solve for y. If B*D is equal to A*E then the lines are parallel and have no strict intersection. They may be the same line or just parallel to each other. So now we have equations to find the x and y point of the circle's center. VIII. Find the radius of the circle. IX. Find the starting angle , ending angle , and then the angular length of the arc. The starting angle of the arc is the angle from G to A. The ending angle of the arc is the angle from G to C. If we are making a right handed (clockwise , angle decreasing) curving arc then we need to make sure that the ending angle is less than the starting angle so that we get the correct portion of the curve. If the curve is left handed (counterclockwise , angle increasing) then we need to make sure the ending angle is greater than the starting angle. if (left_handed_arc) { if (EndingAngle <= StartingAngle) {EndingAngle += 2.0*PI;} } if (right_handed_arc) { if (EndingAngle >= StartingAngle) {EndingAngle = 2.0*PI;} }
So now from the diagram , angle Y is the angular length of the arc to be drawn and since angle GA plus angle Y equals angle GC then : So : X. Draw the arc and enjoy! So finally we have our circle's center , the radius , the starting angle , and the angular length of the arc so we can pass all of our values to our arc drawing function! I have expanded the example program to use three moveable points and display an arc drawn through them. Here's the up to date , working ArcTest source code , just link against Allegro. Key reference
The program is fun , give it a try! ################# End Revision ############################ {I revised and corrected this post on 12142007} 
juvinious
Member #5,145
October 2004

Nice stuff. __________________________________________ 
Edgar Reynaldo
Member #8,592
May 2007

 juvinious  I have completely revised both of my previous posts in this thread since I screwed up the method used to find an arc from 2 points and a radius or from three points. If anyone was using them before , please reread them. Both new methods now work properly and I made a fun example program that uses them. The links to source code , key reference , and windows binary are at the end of my previous post.  Edit  Here are a couple of pics from the program. Mode 2 Mode 3 Mode 3 with screen clearing off (key I) 
Jonatan Hedborg
Member #4,886
July 2004

My god Very nice post!  
Rash
Member #2,374
May 2002

Mathematics aside, no one has mentioned gluPartialDisk yet. 
SiegeLord
Member #7,827
October 2006

I have recently wrote an arc and a circle drawing functions for my game framework. They are unremarkable in terms of their functionality, but I wanted to draw attention to the way I calculate points on the circle. My way is significantly faster than calculating each point using repeated calls of cos and sin. My inspiration came from physics, where the circular motion is described by a constant centripetal acceleration. The algorithm first moves the current point on the tangent line to the circle for some precomputed distance. Then it moves it towards the centre for some precomputed distance. Here they are:
"For in much wisdom is much grief: and he that increases knowledge increases sorrow."Ecclesiastes 1:18 
Edgar Reynaldo
Member #8,592
May 2007

 SiegeLord  Are your sinf , cosf , and tanf functions just wrappers for the sin,cos,and tan C functions that cast the float to a double , apply the function and then cast it back to a float and return the value? I don't quite understand the geometry behind how you adjust the position to plot each time through the loop. The radial_factor , 1  cosf(theta) , what does that represent geometrically? Don't you get compiler redeclaration errors in the for loops when you declare float tx,ty , rx,ry in each iteration? As a note , when you assign "float tx = (y  _y);" , you could just rewrite that as "tx = _y  y;" and save a negation. Not that it matters codewise , but tangetial_factor is misspelled , a missing "n". Anyways , it's a cool idea , thanks for sharing. 
Milan Mimica
Member #3,877
September 2003

I can respond to some of the questions. Quote: Are your sinf , cosf , and tanf functions just wrappers... sinf, cosf and tanf are standard C99 functions, nothing special, they just take and return a float. Quote: Don't you get compiler redeclaration errors in the for loops when you declare float tx,ty , rx,ry in each iteration? No. You do? The variable goes out of scope on each loop iteration.
 
Edgar Reynaldo
Member #8,592
May 2007

Quote:
Quote: Don't you get compiler redeclaration errors in the for loops when you declare float tx,ty , rx,ry in each iteration? No. You do? The variable goes out of scope on each loop iteration.
Tried a simple test and it works just fine. Silly me. Can anyone explain what the radial_factor (1  cosf(theta)) represents geometrically? 
SiegeLord
Member #7,827
October 2006

Thanks for the typo corrections... this code shall be part of my ChristMassHack entry, and I'd rather it not to be too incomprehensible... Quote: Why not just declare them once outside the for loop though? I believe that that is just a style preference. Anyway, here is a geometric explanation of my algorithm. So, as per our algorithm we first move tangentially to point K and then move radially to point B  which is the second point on our circle and would be connected to A by some sort of a line, OpenGL or otherwise. Now, since we know OA and we know theta we can calculate the magnitude of KA quite easily.
or: So our tangential factor is known. And amusing property of this factor is that it is negative when theta is negative, which allows for negative angular lengths for arcs. Now, what is the direction of KA? It is simply the normal vector to OA. We just exchange the components of the radius and negativize one of them. This is where my awkward "float tx = (y  _y);" comes from. I just wanted to emphasize the fact that that is a normal(tangent) vector. Thus, to find KA all we do is find the normal of OA and multiply it by the tangential factor. Now, how to find KB, our radial vector that we move on to get to B? It is important to realize that we know what KO is, since we know where K is from the previous compuation (just add the KA vector to the point A). We also know OA and thus OB. Now, we form two equations: 1) which reduces to: 1) And equation 2: 2) Since OA = OB, we can plug equation 1 into 2 to get: Simplifying that we get: So, our radial factor is 1  cos(theta). Thus, to get KB we would simply find the vector KO from K and O and then multiply it by our factor. If we add that vector to K we will get the point B. Repeat that however number of times and you will get a number of equally spaced points on the circle. As you can see we only needed to precalculate the two factors. Everything else is determined iteratively in the main loop itself. "For in much wisdom is much grief: and he that increases knowledge increases sorrow."Ecclesiastes 1:18 
