下切线起点为 pt2,终点为pt2; 切点为圆弧终点。
圆弧半径为R;上切线和下切线夹角为 S; 圆心在其夹角角平分线上,
通过算法,算出圆心center, 起始点Stpoint,终点Edpoint 的坐标,
求大佬给出具体的实现过程
10 个解决方案
#1
这个纯粹的初中几何问题,
#3
圆弧起始点、圆心、终点都是要用几何算法计算出来的。
因为很久没用数学几何了,所以我想求的是这个数学几何算法,
#4
你是要代码呢,还是要咋算呢?
#5
BOOL createArc(const GCPosition4D &pInt,const GCVector4D &vedge1,const GCVector4D &vedge2
,double R,GCArc3D& arc)
{
double angle = vedge1^vedge2;
if(fabs(angle-GCMathConst::PI)<GCMathConst::ZERO)
return FALSE;
if(angle<GCMathConst::ZERO)
return FALSE;
GCVector4D vedge11 = vedge1.toUnitVector();
GCVector4D vedge21 = vedge2.toUnitVector();
GCVector4D centerLineV = vedge11+vedge21;
centerLineV.normalize();
GCPosition4D p1 = pInt + vedge11*(R/tan(angle/2));
GCPosition4D p2 = pInt + vedge21*(R/tan(angle/2));
GCPosition4D pCenter = pInt + centerLineV* (R/sin(angle/2));
arc.create(pCenter,p1,p2,TRUE);
return TRUE;
}
BOOL createArc(const GCLine3D &line1,const GCLine3D &line2,double r,GCArc3D& arc)
{
GCPosition4D pInt;
BOOL isIntersected = intersected(line1,line2,pInt);
if(!isIntersected )
return FALSE;
return createArc(pInt,line1.getDirection(),line2.getDirection(),r,arc);
}
BOOL intersected(const GCLine3D &line1,const GCLine3D &line2,GCPosition4D &p)
{
double distance1 = line1.getBase()-line2;
if(distance1<GCMathConst::ZERO)
{
p.clone(line1.getBase());
return TRUE;
}
if((line2.getBase()-line1)<GCMathConst::ZERO)
{
p.clone(line2.getBase());
return TRUE;
}
GCVector4D v3 = line1.getDirection()|line2.getDirection();
GCPlane3D plane(line1.getBase(),v3);
BOOL samePlane = (line2.getBase()-plane)<GCMathConst::ZERO;
if(!samePlane)
return FALSE;
double angle = (line1.getDirection())^(line2.getDirection());
double len = distance1/sin(angle);
GCPosition4D s1 = line1.getBase() + line1.getDirection() * len;
if((s1-line2)<GCMathConst::ZERO)
{
p.clone(s1);
return TRUE;
}
s1 = line1.getBase() + line1.getDirection() * (-len);
p.clone(s1);
return TRUE;
}
#6
一个例子 (不通用)
#define PI 3.14159265359
#define Rd 70
BOOL CMyDlg::RoundChamfer(CPoint p1,CPoint p2,CPoint p3,CDC &dc)
{// angle a
double dx21=p2.x-p1.x;// 180
double dy21=p1.y-p2.y;// 180
double k1=dy21/dx21;
double a21=0;
if(dx21!=0) a21=atan(k1);// 0.78
afxDump << a21*180/PI << " a度\n";
// angle b
double dx23=p3.x-p2.x;// 120
double dy23=p2.y-p3.y;// 280
double k2=dy23/dx23;
double b23=0;
if(dy23!=0) b23=atan(k2);
afxDump << b23*180/PI << " b度\n";
// angle
// 设直线l1、l2的斜率存在,分别为k1、k2,
// l1与l2的夹角为θ,则tanθ=∣(k2- k1)/(1+ k1k2)∣.
double s;
if(k2>k1)
s =atan((k2-k1)/(1+k1*k2));
else
s =atan((k1-k2)/(1+k1*k2));
afxDump << s*180/PI << " s度\n";
s /= 2;
// middle line
double L=Rd/tan(s);
//
double dBx=L*cos(a21);
double dBy=L*sin(a21);
//
CPoint B;// begin
B.x=(int)(p2.x-dBx);
B.y=(int)(p2.y+dBy);
//
double dEx=L*cos(b23);
double dEy=L*sin(b23);
CPoint E;// end
E.x=(int)(p2.x-dEx);
E.y=(int)(p2.y+dEy);
//
afxDump << (a21+s)*180/PI << " Mid度\n";
double M=L/cos(s);// middle
double dCx=M*cos(a21+s);
double dCy=M*sin(a21+s);
CPoint C;// center
C.x=(int)(p2.x-dCx);
C.y=(int)(p2.y+dCy);
//
dc.MoveTo(p1);
dc.LineTo(p2);
dc.LineTo(p3);
//
dc.MoveTo(B);
dc.LineTo(C);
dc.LineTo(E);
//
dc.SelectObject(GetStockObject(NULL_BRUSH));
CRect rc(C.x-Rd,C.y-Rd,C.x+Rd,C.y+Rd);
dc.Ellipse(rc);
//
return TRUE;
}
#7
调用:
else
{
// CDialog::OnPaint();
CPaintDC dc(this); // device context for painting
CPoint p1(20,220);
CPoint p2(200,20);
CPoint p3(140,280);
RoundChamfer(p1,p2,p3,dc);
}
else
{
// CDialog::OnPaint();
CPaintDC dc(this); // device context for painting
CPoint p1(20,220);
CPoint p2(200,20);
CPoint p3(140,280);
RoundChamfer(p1,p2,p3,dc);
}
#8
好一点了
#define PI 3.14159265359
#define Rd 40
BOOL CMyDlg::RoundChamfer(CPoint p1,CPoint p2,CPoint p3,CDC &dc)
{// angle a
double dx21=p2.x-p1.x;// 180
double dy21=p1.y-p2.y;// 180
double a21;
if(dx21==0)
{
a21=PI/2;// 90
}
else if(dx21 > 0)
{
a21=atan(dy21/dx21);
}
else
{// <0
a21=PI-atan(-dy21/dx21);
}
afxDump << a21*180/PI << " a度\n";
// angle b
double dx23=p3.x-p2.x;// 120
double dy23=p2.y-p3.y;// 280
double b23;
if(dx23==0)
{
b23=PI/2;// 90
}
else if(dx23 >0)
{
b23=PI-atan(-dy23/dx23);// 90
}
else
{// <0
b23=atan(dy23/dx23);
}
//
double s;
s=(b23-a21)/2;
afxDump << b23*180/PI << " b度\n";
// tangent line of circle
double L=Rd/tan(s);
//
double dBx=L*cos(a21);
double dBy=L*sin(a21);
//
CPoint B;// begin
B.x=(int)(p2.x-dBx);
B.y=(int)(p2.y+dBy);
//
double dEx=L*cos(b23);
double dEy=L*sin(b23);
CPoint E;// end
E.x=(int)(p2.x-dEx);
E.y=(int)(p2.y+dEy);
//
afxDump << (a21+s)*180/PI << " Mid度\n";
double M=L/cos(s);// middle line
double dCx=M*cos(a21+s);
double dCy=M*sin(a21+s);
CPoint C;// center
C.x=(int)(p2.x-dCx);
C.y=(int)(p2.y+dCy);
//
dc.MoveTo(p1);
dc.LineTo(p2);
dc.LineTo(p3);
//
dc.MoveTo(B);
dc.LineTo(C);
dc.LineTo(E);
//
dc.MoveTo(C);
dc.LineTo(p2);
//
dc.SelectObject(GetStockObject(NULL_BRUSH));
CRect rc(C.x-Rd,C.y-Rd,C.x+Rd,C.y+Rd);
CPen pen;
CPen *old;
pen.CreatePen(PS_SOLID,2,RGB(255,0,0));
old=dc.SelectObject(&pen);
dc.MoveTo(p1);
dc.LineTo(B);
dc.Arc(rc, E,B);
dc.MoveTo(E);
dc.LineTo(p3);
//
dc.SelectObject(old);
return TRUE;
}
#9
很专业的结果,点赞!
#10
很专业的结果,点赞!
#1
这个纯粹的初中几何问题,
#2
#3
圆弧起始点、圆心、终点都是要用几何算法计算出来的。
因为很久没用数学几何了,所以我想求的是这个数学几何算法,
#4
你是要代码呢,还是要咋算呢?
#5
BOOL createArc(const GCPosition4D &pInt,const GCVector4D &vedge1,const GCVector4D &vedge2
,double R,GCArc3D& arc)
{
double angle = vedge1^vedge2;
if(fabs(angle-GCMathConst::PI)<GCMathConst::ZERO)
return FALSE;
if(angle<GCMathConst::ZERO)
return FALSE;
GCVector4D vedge11 = vedge1.toUnitVector();
GCVector4D vedge21 = vedge2.toUnitVector();
GCVector4D centerLineV = vedge11+vedge21;
centerLineV.normalize();
GCPosition4D p1 = pInt + vedge11*(R/tan(angle/2));
GCPosition4D p2 = pInt + vedge21*(R/tan(angle/2));
GCPosition4D pCenter = pInt + centerLineV* (R/sin(angle/2));
arc.create(pCenter,p1,p2,TRUE);
return TRUE;
}
BOOL createArc(const GCLine3D &line1,const GCLine3D &line2,double r,GCArc3D& arc)
{
GCPosition4D pInt;
BOOL isIntersected = intersected(line1,line2,pInt);
if(!isIntersected )
return FALSE;
return createArc(pInt,line1.getDirection(),line2.getDirection(),r,arc);
}
BOOL intersected(const GCLine3D &line1,const GCLine3D &line2,GCPosition4D &p)
{
double distance1 = line1.getBase()-line2;
if(distance1<GCMathConst::ZERO)
{
p.clone(line1.getBase());
return TRUE;
}
if((line2.getBase()-line1)<GCMathConst::ZERO)
{
p.clone(line2.getBase());
return TRUE;
}
GCVector4D v3 = line1.getDirection()|line2.getDirection();
GCPlane3D plane(line1.getBase(),v3);
BOOL samePlane = (line2.getBase()-plane)<GCMathConst::ZERO;
if(!samePlane)
return FALSE;
double angle = (line1.getDirection())^(line2.getDirection());
double len = distance1/sin(angle);
GCPosition4D s1 = line1.getBase() + line1.getDirection() * len;
if((s1-line2)<GCMathConst::ZERO)
{
p.clone(s1);
return TRUE;
}
s1 = line1.getBase() + line1.getDirection() * (-len);
p.clone(s1);
return TRUE;
}
#6
一个例子 (不通用)
#define PI 3.14159265359
#define Rd 70
BOOL CMyDlg::RoundChamfer(CPoint p1,CPoint p2,CPoint p3,CDC &dc)
{// angle a
double dx21=p2.x-p1.x;// 180
double dy21=p1.y-p2.y;// 180
double k1=dy21/dx21;
double a21=0;
if(dx21!=0) a21=atan(k1);// 0.78
afxDump << a21*180/PI << " a度\n";
// angle b
double dx23=p3.x-p2.x;// 120
double dy23=p2.y-p3.y;// 280
double k2=dy23/dx23;
double b23=0;
if(dy23!=0) b23=atan(k2);
afxDump << b23*180/PI << " b度\n";
// angle
// 设直线l1、l2的斜率存在,分别为k1、k2,
// l1与l2的夹角为θ,则tanθ=∣(k2- k1)/(1+ k1k2)∣.
double s;
if(k2>k1)
s =atan((k2-k1)/(1+k1*k2));
else
s =atan((k1-k2)/(1+k1*k2));
afxDump << s*180/PI << " s度\n";
s /= 2;
// middle line
double L=Rd/tan(s);
//
double dBx=L*cos(a21);
double dBy=L*sin(a21);
//
CPoint B;// begin
B.x=(int)(p2.x-dBx);
B.y=(int)(p2.y+dBy);
//
double dEx=L*cos(b23);
double dEy=L*sin(b23);
CPoint E;// end
E.x=(int)(p2.x-dEx);
E.y=(int)(p2.y+dEy);
//
afxDump << (a21+s)*180/PI << " Mid度\n";
double M=L/cos(s);// middle
double dCx=M*cos(a21+s);
double dCy=M*sin(a21+s);
CPoint C;// center
C.x=(int)(p2.x-dCx);
C.y=(int)(p2.y+dCy);
//
dc.MoveTo(p1);
dc.LineTo(p2);
dc.LineTo(p3);
//
dc.MoveTo(B);
dc.LineTo(C);
dc.LineTo(E);
//
dc.SelectObject(GetStockObject(NULL_BRUSH));
CRect rc(C.x-Rd,C.y-Rd,C.x+Rd,C.y+Rd);
dc.Ellipse(rc);
//
return TRUE;
}
#7
调用:
else
{
// CDialog::OnPaint();
CPaintDC dc(this); // device context for painting
CPoint p1(20,220);
CPoint p2(200,20);
CPoint p3(140,280);
RoundChamfer(p1,p2,p3,dc);
}
else
{
// CDialog::OnPaint();
CPaintDC dc(this); // device context for painting
CPoint p1(20,220);
CPoint p2(200,20);
CPoint p3(140,280);
RoundChamfer(p1,p2,p3,dc);
}
#8
好一点了
#define PI 3.14159265359
#define Rd 40
BOOL CMyDlg::RoundChamfer(CPoint p1,CPoint p2,CPoint p3,CDC &dc)
{// angle a
double dx21=p2.x-p1.x;// 180
double dy21=p1.y-p2.y;// 180
double a21;
if(dx21==0)
{
a21=PI/2;// 90
}
else if(dx21 > 0)
{
a21=atan(dy21/dx21);
}
else
{// <0
a21=PI-atan(-dy21/dx21);
}
afxDump << a21*180/PI << " a度\n";
// angle b
double dx23=p3.x-p2.x;// 120
double dy23=p2.y-p3.y;// 280
double b23;
if(dx23==0)
{
b23=PI/2;// 90
}
else if(dx23 >0)
{
b23=PI-atan(-dy23/dx23);// 90
}
else
{// <0
b23=atan(dy23/dx23);
}
//
double s;
s=(b23-a21)/2;
afxDump << b23*180/PI << " b度\n";
// tangent line of circle
double L=Rd/tan(s);
//
double dBx=L*cos(a21);
double dBy=L*sin(a21);
//
CPoint B;// begin
B.x=(int)(p2.x-dBx);
B.y=(int)(p2.y+dBy);
//
double dEx=L*cos(b23);
double dEy=L*sin(b23);
CPoint E;// end
E.x=(int)(p2.x-dEx);
E.y=(int)(p2.y+dEy);
//
afxDump << (a21+s)*180/PI << " Mid度\n";
double M=L/cos(s);// middle line
double dCx=M*cos(a21+s);
double dCy=M*sin(a21+s);
CPoint C;// center
C.x=(int)(p2.x-dCx);
C.y=(int)(p2.y+dCy);
//
dc.MoveTo(p1);
dc.LineTo(p2);
dc.LineTo(p3);
//
dc.MoveTo(B);
dc.LineTo(C);
dc.LineTo(E);
//
dc.MoveTo(C);
dc.LineTo(p2);
//
dc.SelectObject(GetStockObject(NULL_BRUSH));
CRect rc(C.x-Rd,C.y-Rd,C.x+Rd,C.y+Rd);
CPen pen;
CPen *old;
pen.CreatePen(PS_SOLID,2,RGB(255,0,0));
old=dc.SelectObject(&pen);
dc.MoveTo(p1);
dc.LineTo(B);
dc.Arc(rc, E,B);
dc.MoveTo(E);
dc.LineTo(p3);
//
dc.SelectObject(old);
return TRUE;
}
#9
很专业的结果,点赞!
#10
很专业的结果,点赞!