MFC特定矩形框内绘制不同方向的椭圆

最近深度学习项目需要自己设计标注软件,主要针对规则几何图形缺失部分信息时,要求定位的中心是原始图形的几何中心,而不是外接矩形框中心。
在这里插入图片描述
考虑到实际采图时还要考虑旋转角度,因此标注软件就要设计在特定矩形框内生成不同旋转角度的椭圆,对套接缺失圆或者椭圆。自己算了两天,思路对了就是不会化简求解,在知乎查找到求解方案。

数学求解

部分参考:知乎链接,我的实际是根据theta角度来生成不同椭圆,有所不同
在这里插入图片描述在这里插入图片描述在MFC绘制时,发现上图最终求解的方式绘制图像,相切得不是很好,且偏转角度较大时,完全乱了。
在这里插入图片描述在这里插入图片描述 我觉得可能是求得p,q值后再进行多次运算求A,B,C,再求细分线段下的y时计算精度不断丢失了。
最终采用的方式时,求出p,q后,在偏转的坐标系求出细分线段后再转换至无偏转的坐标系。这样效果就可以了。还有就是一个问题是45度时,上面的方法无法求解p,q,以后再处理。

相关代码

double A, B, C, p, q,a,b,deltax,tmp;
CPoint up1, up2, low1, low2,transup1, transup2, translow1, translow2;
a = fabs(lt.x - rb.x); 
b = fabs(lt.y - rb.y);
double CX = (lt.x + rb.x) / 2.0;
double CY = (lt.y + rb.y) / 2.0;

p = sqrt((pow(a*cos(gl_rotate),2)- pow(b*sin(gl_rotate), 2))/(4*cos(2*gl_rotate)));
//q = sqrt((pow(b*cos(gl_rotate), 2) - pow(a*sin(gl_rotate), 2)) / (4 * cos(2 * gl_rotate)));
//p = sqrt((pow(a, 2) - pow(b*tan(gl_rotate), 2)) /(4 *(1-pow(tan(gl_rotate),2))));
q = sqrt((a*a + b * b) / 4 - p * p);
#if 1
//先在偏转坐标系求各细分线段,再转换至标准坐标系
deltax = 2.0*p / 200;
low1 = up1 = CPoint(-p,0);
for (int i=1;i<201;i++)
{
	if(i!=200)up2.x = low2.x = -p + i * deltax;
	else up2.x = low2.x = p;
	up2.y = q * sqrt(1 - pow(up2.x / p, 2));//由椭圆方程求解y坐标
	low2.y = -up2.y;
					//转换至标准坐标系
	transup1.x = int(up1.x*cos(gl_rotate) - up1.y*sin(gl_rotate)+0.5);
	transup2.x = int(up2.x*cos(gl_rotate) - up2.y*sin(gl_rotate)+0.5);
	transup1.y = int(up1.y*cos(gl_rotate) + up1.x*sin(gl_rotate)+0.5);
	transup2.y = int(up2.y*cos(gl_rotate) + up2.x*sin(gl_rotate)+0.5);
					
	translow1.x = int(low1.x*cos(gl_rotate) - low1.y*sin(gl_rotate)+0.5);
	translow2.x = int(low2.x*cos(gl_rotate) - low2.y*sin(gl_rotate)+0.5);
	translow1.y = int(low1.y*cos(gl_rotate) + low1.x*sin(gl_rotate)+0.5);
	translow2.y = int(low2.y*cos(gl_rotate) + low2.x*sin(gl_rotate)+0.5);
	pMemDc->MoveTo(CPoint(transup1.x + CX, transup1.y + CY)); 		 pMemDc->LineTo(CPoint(transup2.x + CX, transup2.y + CY));
	pMemDc->MoveTo(CPoint(translow1.x + CX, translow1.y + CY)); pMemDc->LineTo(CPoint(translow2.x + CX, translow2.y + CY));
	up1 = up2;
	low1 = low2;
}
#else
//这种方式误差大
A = pow(cos(gl_rotate), 2) / pow(p, 2) + pow(sin(gl_rotate), 2) / pow(q, 2);
B = pow(sin(gl_rotate), 2) / pow(p, 2) + pow(cos(gl_rotate), 2) / pow(q, 2);
C = sin(2 * gl_rotate)*(1 / pow(p, 2) - 1 / pow(q, 2));
deltax = a / 200;
up1.x = low1.x = lt.x-CX;
up1.y = low1.y = int(-C * up1.x / B+0.5);//中心在原点
for (int i=1;i<201;i++)
{
	if (i == 200) { low2.x = up2.x = rb.x-CX; }
	else { low2.x = up2.x = int(lt.x - CX + i * deltax + 0.5); }
	tmp = sqrt(pow(C*low2.x, 2) - B * (A*pow(low2.x, 2) - 1));
	low2.y  = int((-C* low2.x - tmp) / B + 0.5);
	up2.y = int((-C * up2.x + tmp) / B + 0.5);
	pMemDc->MoveTo(CPoint(up1.x+CX, up1.y + CY)); pMemDc->LineTo(CPoint(up2.x + CX, up2.y + CY));
	pMemDc->MoveTo(CPoint(low1.x + CX, low1.y + CY)); pMemDc->LineTo(CPoint(low2.x + CX, low2.y + CY));
	up1 = up2;
	low1 = low2;
}
#endif
最终效果图,勉强满足需求。

在这里插入图片描述在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值