Я пытаюсь нарисовать небесные тела, движущиеся по упрощенным, идеально круговым орбитам. Я также рисую спроецированные орбитальные пути, по которым пойдут эти объекты. Однако проблема в том, что реальный путь, по которому идут объекты, не согласуется с проекцией при достаточном увеличении.
Видео, демонстрирующее проблему: 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)));
Как это исправить, чтобы небесные тела всегда находились на предсказанной кривой?
EDIT1:
Я попытался использовать предложенный алгоритм для рисования собственного эллипса. Версия, адаптированная для использования с 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
. - person Kuba hasn't forgotten Monica   schedule 08.04.2014double
илиfloat
, просто используйтеqreal
, чтобы соответствовать тому, что используется типами геометрии Qt с плавающей запятой. - person Kuba hasn't forgotten Monica   schedule 08.04.2014theta
кd_theta
является ошибкой, поскольку такое многократное добавление не приведет к 2*pi радианам. Вы должны установитьtheta = i * d_theta
- такое умножение достаточно дешево. - person Kuba hasn't forgotten Monica   schedule 08.04.2014