【发布时间】:2014-04-07 16:15:17
【问题描述】:
我正在尝试绘制在简化的完美圆形轨道上移动的天体。我还绘制了这些物体将采用的预计轨道路径。但是,问题在于对象所采用的实际路径与放大得足够近时的投影不一致。
演示该问题的视频:https://www.youtube.com/watch?v=ALSVfx48zXw
如果缩小,问题是不存在的,因为偏差太小了。偏差的表观大小似乎主要受到圆的可见曲率的影响——注意卫星的路径如何与它们的运动相一致。如果将卫星的投影路径放大以接近直线,它们将具有与行星显示的相同模式的偏差。
坐标计算方法:
double getX (long int time) {
return orbit * cos(offset + time * speed);
}
double getY (long int time) {
return orbit * sin(offset + time * speed);
}
投影轨道图:
ellipse = scene->addEllipse(system.starX-body.orbit,
system.starY-body.orbit,
body.orbit*2,body.orbit*2,greenPen,transBrush);
在它们实际出现的地方画出天体:
ellipse = scene->addEllipse(-body.radius,
-body.radius,
body.radius*2,body.radius*2,blackPen,greenBrush);
ellipse->setFlag(QGraphicsItem::ItemIgnoresTransformations);
ellipse->setPos(system.starX+body.getX(date2days(game.date)),
system.starY+body.getY(date2days(game.date)));
如何解决这个问题,使天体始终在预测曲线上?
编辑1:
我尝试使用建议的算法来绘制我自己的椭圆。我在这里复制了适用于 Qt 的版本:
QPoint get_point(double a, double b, double theta, QPoint center)
{
QPoint point;
point.setX(center.x() + a * cos(theta));
point.setY(center.y() + b * sin(theta));
return point;
}
void draw_ellipse(double a, double b, QPoint center, double zoom_factor, QGraphicsScene * scene, QPen pen)
{
double d_theta = 1.0d / zoom_factor;
double theta = 0.0d;
int count = 2.0d * 3.14159265358979323846 / d_theta;
QPoint p1, p2;
p1 = get_point(a, b, 0.0f, center);
for (int i = 0; i <= count; i++)
{
theta += d_theta;
p2 = p1;
p1 = get_point(a, b, theta, center);
scene->addLine(p1.x(),p1.y(),p2.x(),p2.y(),pen);
}
}
结果并不令人鼓舞:
除了在 zoom_factor 360 上看起来不漂亮之外,该应用程序运行非常缓慢,使用的资源比以前多得多。
EDIT2:
改进后的版本提供了更好的结果,但仍然很慢。代码如下:
QPointF get_point(qreal a, qreal b, qreal theta, QPointF center)
{
QPointF point;
point.setX(center.x() + a * cos(theta));
point.setY(center.y() + b * sin(theta));
return point;
}
void draw_ellipse(qreal a, qreal b, QPointF center, qreal zoom_factor, QGraphicsScene * scene, QPen pen)
{
qreal d_theta = 1.0d / zoom_factor;
qreal theta = 0.0d;
int count = 2.0d * 3.14159265358979323846 / d_theta;
QPointF p1, p2;
p1 = get_point(a, b, 0.0f, center);
for (int i = 0; i <= count; i++)
{
theta = i * d_theta;
p2 = p1;
p1 = get_point(a, b, theta, center);
scene->addLine(p1.x(),p1.y(),p2.x(),p2.y(),pen);
}
}
【问题讨论】:
-
您不能在
draw_ellipse和get_point中使用整数坐标。代替QPoint,使用QPointF。 -
您也不需要显式使用
double或float,只需使用qreal来匹配Qt 的浮点几何类型所使用的内容。 -
将
theta添加到d_theta是一个错误,因为这样的重复添加不会以2*pi 弧度结束。你应该设置theta = i * d_theta- 这样的乘法足够便宜。 -
您也应该只绘制可见角度。您应该首先适当地计算开始和结束角度。这将加快速度。
-
是的。理想情况下,声明从弧到其近似弦(弧高)相对于半径大小的允许偏差,并选择角度增量以保持该偏差。
标签: c++ qt trigonometry qgraphicsview qgraphicsscene