MFC + OpenGL three-point dynamic arc drawing

    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.



Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324809171&siteId=291194637