gpt4 book ai didi

c++ - CDC::Ellipse 不能正确绘制圆圈

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:25:38 28 4
gpt4 key购买 nike

在我的一个项目中(VC++2010,MFC),我想用CDC::Ellipse画一个圆。我设置了两个点:第一个是圆心,第二个是我希望它在圆周上的一个点。

我将左上角和右下角的坐标传递给 CDC::Ellipse( int x1, int y1, int x2, int y2 )。

简而言之:我使用 Pitagora 定理计算两点之间的距离(半径),然后我从中心的坐标中减去该值以获得左上角并添加以获得右下角。

当我绘制圆和点并放大时,我看到第二个并不像预期的那样在圆周上,它稍微在里面,除非你将它设置为 0°、45°、90° 和以此类推关于坐标的绝对系统。

然后我尝试使用 CDC::Polyline 绘制相同的圆,我将获得的点赋予该方法,该点围绕中心旋转另一个点,距离等于半径。在这种情况下,该点位于我设置的每个圆周上。

这两个圆的重叠表明它们在 0°、45°、90° 等处完全重叠,但在 22.5°、67.5° 等处差距最大。

有没有人注意到类似的行为?

感谢所有能帮助我的人!

代码片段:

这就是我如何计算给定 2 个点的半径:

centerPX = vvFPoint( 1380, 845 );
secondPointPX = vvFPoint( 654,654 );
double radiusPX = (sqrt( (secondPointPX.x - centerPX.x) * (secondPointPX.x - centerPX.x) + (secondPointPX.y - centerPX.y) * (secondPointPX.y - centerPX.y) ));

(vvFPoint 是从 CPoint 派生的自定义类型)

这就是我使用 CDC::Ellipse 绘制“圆”的方式:

int up = (int)(((double)(m_p1.y-(double)originY - m_radius) / zoom) + 0.5) + offY;
int left = (int)(((double)(m_p1.x-(double)originX - m_radius) / zoom) + 0.5) + offX;
int down = (int)(((double)(m_p1.y-(double)originY + m_radius) / zoom) + 0.5) + offY;
int right = (int)(((double)(m_p1.x-(double)originX + m_radius) / zoom) + 0.5) + offX;
pDC->Ellipse( left, up, right, down);

(m_p1为圆心,originX/Y为图像原点,m_radius为圆半径, zoom 是比例因子, offX/Y 是我软件客户区的偏移)

这就是我使用自定义多段线类“手动”绘制圆(以及非常简单的方法)的方式:

1) 创建点数组:

point.x = centerPX.x + radiusPX;
point.y = centerPX.y;
for ( i=0; i < 3600; i++ )
{
pt1.RotateDeg ( centerPX, (double)0.1 );
poly->AddPoint( pt1 );
}

(RotateDeg 是一种自定义方法,使用第一个参数作为枢轴,第二个参数作为以度为单位的角度值来旋转点,AddPoint 是一种自定义方法来创建点数组,poly 是我的自定义折线对象)。

2) 绘制它:

当我调用 Draw( CDC* pDC ) 时,我使用之前的数组绘制折线:

pDC->MoveTo(p);

我希望这可以帮助您重现我奇怪的观察结果!

代码片段 2:

void vvPoint<Tipo>::RotateDeg(const vvPoint<Tipo> &center, double angle)
{
vvPoint<Tipo> ptB;

angle *= -(M_PI / 180);

*this -= center;
ptB.x = ((this->x * cos(angle)) - (this->y * sin(angle)));
ptB.y = ((this->x * sin(angle)) + (this->y * cos(angle)));
*this = ptB + center;
}

但为了让您更好地理解我的观察结果,我想添加一些图片,以便您可以看到我的整个问题是从哪里开始的……问题是:我无法添加图片,因为我需要有 10 个声誉。我在保管箱上上传了一个 .zip 文件,如果您需要,我可以将此文件的 URL 发送给您。让我知道这是否是绕过此问题的正确(和安全..)方法。

谢谢!

最佳答案

这可能是一个可能的解释。作为MSDN says关于 CDC::Ellipse(我强调):

The center of the ellipse is the center of the bounding rectangle specified by x1, y1, x2, and y2, or lpRect. The ellipse is drawn with the current pen, and its interior is filled with the current brush.

The figure drawn by this function extends up to, but does not include, the right and bottom coordinates. This means that the height of the figure is y2 – y1 and the width of the figure is x2 – x1.

您描述的如何计算边界矩形的方式并不完全清楚(一些源代码会有所帮助)但是,鉴于上面引用的第二段,您可能需要将 1 添加到您的 x2y2 值,以确保您有一个具有所需半径的圆。

还值得注意的是,您的两种绘图方法之间可能存在细微的舍入差异,其中您的边界框大小不正确(即中心点逻辑上落在半像素上)。

更新

使用您的代码片段(谢谢),并假设没有缩放和零偏移等,我得到了 750.704 像素的半径和以下椭圆参数:

pDC->Ellipse(629, 94, 2131, 1596);

根据MSDN,这意味着椭圆将绘制成如下尺寸的图形:

width  = (2131 - 629) = 1502
height = (1596 - 94) = 1502

据我所知,这应该产生一个圆而不是椭圆。

接下来要做的是弄清楚您是如何绘制多边形的 - 为此我们需要查看 RotateDeg 的实现 - 您可以发布该代码吗?我怀疑这里有一些简单的舍入误差,当你缩放时它可能会被放大。

更新 2

只看这段代码:

for ( i=0; i < 3600; i++ )
{
pt1.RotateDeg ( centerPX, (double)0.1 );
poly->AddPoint( pt1 );
}

您每次以 0.1 度的增量旋转多边形点。这可能会累积一些错误,因此可能值得这样做:

for ( i=0; i < 3600; i++ )
{
vvFPoint ptNew = pt1;
ptNew.RotateDeg ( centerPX, (double)i * 0.1 );
poly->AddPoint( ptNew );
}

也许这意味着您必须更改 RotateDeg 函数以处理正确的象限。

还有一点,您提到在放大图像时会看到问题。如果这意味着您正在使用 zoom 变量,则值得检查这一行 ...:

pDC->Ellipse( left, up, right, down);

...参数仍然形成正方形,所以 (right - left) == (down - up)

更新 3

我刚刚以当前形式运行了您的 RotateDeg 函数,以查看错误是如何累积的(通过将上一个结果输入下一个迭代)。在每一步中,我都会计算新点与中心之间的距离,并将其与所需的半径进行比较。

下图显示了结果,在计算点时您可以看到 4 个像素的误差。

errors

我认为这至少解释了部分差异(即你的多边形绘图有缺陷)并且 - 根据 zoom - 你可能会在椭圆参数中引入不对称性,你可以通过比较来调试如上所述的宽度到高度。

关于c++ - CDC::Ellipse 不能正确绘制圆圈,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19703907/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com