I have used GDI+ to draw arcs before, because the CDC class encapsulates the function of drawing arcs, so it is very convenient, you only need to calculate the parameters required for it; but the drawing efficiency with GDI+ is not high, so now it has been changed to OpenGL. , but OpenGL does not encapsulate the arc drawing function, so you can only write it yourself.
1. Three points can be used to find the center O and the radius R
2. According to these three points, the starting angle startAngle and sweep Angle (sweepAngle) of the arc drawing can also be obtained, such as:
//Arc scan angle, starting angle //Calculate arc length L = ⊙ * r (radian * radius) //Determine whether the midpoint B and the center O of the circle are within the included angle of AC //If the arc angle is angle = A angle - C angle; if not angle = 360 - (A angle - C angle) negate void CToolN::AngleOfArc() { // across the corner O//Center A//Start point B//Mid point C//End point GLfloat OA = TheAngleFmTwoPoints(O, A, TRUE); // Find the angle of two points 0~360 GLfloat OB = TheAngleFmTwoPoints (O, B, TRUE); GLfloat OC = TheAngleFmTwoPoints (O, C, TRUE); GLfloat fMax = max(OA, OC); GLfloat fMin = min(OA, OC); if (OB > fMin && OB < fMax) mSweepAngle_ = fMax - fMin; else mSweepAngle_ = 360 - (fMax - fMin); //start angle BOOL bCross = ArcCross(A, B, C);//Counterclockwise=0, Clockwise=1 mStartAngle_ = bCross? OC: OA; }
// drawing direction // Get the direction of drawing the arc If iResult is greater than 0, it is clockwise, and if it is less than 0, it is counterclockwise. // Let vector A = ( x1, y1 ), B = ( x2, y2 ) // |A×B| = x1*y2 - x2*y1 = |A|×|B|×sin (the angle between the vectors A and B) // So the positive and negative of this value is also the positive and negative of the A to B rotation angle sin value // Clockwise rotation angle 0~180, sin>0 // Clockwise rotation angle 180~360 or counterclockwise rotation 0~180, sin<0 // Here the direction is A->B->C // |AB| = (B.x - A.x, B.y - A.y) // |BC| = (C.x - B.x, C.y - B.y) // |B.x - A.x C.x - B.x| // |By - Ay Cy - By| cross-multiply and subtract // (B.x - A.x) * (C.y - B.y) - (B.y - A.y) * (C.x - B.x) = |AB| * |BC| * sin(angle) BOOL CToolN::ArcCross(GLPointF p1, GLPointF p2, GLPointF p3) { p1 = Point(p1, FALSE); p2 = Point(p2, FALSE); p3 = Point(p3, FALSE); GLfloat fRet = (p2.x_ - p1.x_) * (p3.y_ - p2.y_) - (p2.y_ - p1.y_) * (p3.x_ - p2.x_); return fRet > 0; }
3. Start drawing the arc
#define SIN(c) (sin(c * PI / 180.0)) //radians = angle multiplied by π and then divided by 180 #define COS(c) (cos(c * PI / 180.0))
// draw arc void CShape::RenderArc(GLPointF O, GLfloat fRadius, GLfloat startAngle, GLfloat sweepAngle) { glLineWidth(mfWidth_); //Set the brush size glColor3fv(mClrItem_); //Set the color //GL_LINE_STRIP is not closed glBegin(GL_LINE_STRIP); GLfloat angle = startAngle; GLdouble fStep = sweepAngle / DOTCOUNT; //The number of loops DOTCOUNT draw points for(; angle <= startAngle + sweepAngle; angle += fStep) { GLfloat x = fRadius * COS(angle) + O.x_; GLfloat y = fRadius * SIN(angle) + O.y_; glVertex2f(x, y); } glEnd(); glLineWidth(1); //Restore brush size }After thinking about the problem for many days, the problem is finally solved. After thinking about it carefully, I still rely too much on Baidu and did not think about it carefully.