Я делаю приложение о космической физике, так что я много работаю с орбитами. Естественно, я сталкиваюсь с Ellipse2D.Double
, чтобы нарисовать свои орбиты на экране.
Всякий раз, когда моя JPanel обновляется, я рисую орбиту тела, используя Ellipse2D, а также само тело другим методом.
По сути, я обнаружил, что когда числа становятся очень большими (будь то размер орбит становится большим или визуализация сильно увеличивается), положение тела и Ellipse2D не совпадают.
Я вычисляю положение тела с помощью преобразования полярных координат в прямоугольные, а математику для Ellipse2D оставляю до пакета geom
.
Взгляните на этот пример кода. Это самая автономная версия моей задачи, которую я могу сделать, поскольку масштаб круга должен быть очень большим:
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.math.BigDecimal;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class EllipseDemo extends JPanel {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setSize(500, 500);
frame.add(new EllipseDemo());
frame.setVisible(true);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
// These values allow for a very zoomed in view of a piece of the circle
BigDecimal[] circleCenter = { new BigDecimal(-262842.5), new BigDecimal(-93212.8) };
BigDecimal circleRadius = new BigDecimal(279081.3);
// Draw the circle at the given center, with the given width and height
// x = centerx - radius, y = centery - radius, w = h = radius * 2
g2d.draw(new Ellipse2D.Double(circleCenter[0].subtract(circleRadius).doubleValue(),
circleCenter[1].subtract(circleRadius).doubleValue(), circleRadius.multiply(new BigDecimal(2)).doubleValue(),
circleRadius.multiply(new BigDecimal(2)).doubleValue()));
// Get a rectangular conversion of a point on the circle at this angle
BigDecimal angle = new BigDecimal(0.34117696217);
BigDecimal[] rectangular = convertPolarToRectangular(new BigDecimal[] {
circleRadius, angle });
// Draw a line from the center of the circle to the point
g2d.draw(new Line2D.Double(circleCenter[0].doubleValue(), circleCenter[1].doubleValue(),
circleCenter[0].add(rectangular[0]).doubleValue(), circleCenter[1]
.add(rectangular[1]).doubleValue()));
}
public BigDecimal[] convertPolarToRectangular(BigDecimal[] polar) {
BigDecimal radius = polar[0];
BigDecimal angle = polar[1];
BigDecimal x = radius.multiply(new BigDecimal(Math.cos(angle.doubleValue())));
BigDecimal y = radius.multiply(new BigDecimal(Math.sin(angle.doubleValue())));
return new BigDecimal[] { x, y };
}
}
Приведенный выше код, по сути, рисует на экране круг большого радиуса очень далеко. Я выбрал размер так, чтобы часть круга была видна в маленьком окошке.
Затем он рисует линию от центра круга к точке на круге, которая видна в окне: я выбрал угол, который был виден в окне, и использовал геометрию, чтобы преобразовать этот угол и радиус круга в прямоугольные координаты.
Вот что показывает программа:
Обратите внимание, что линия на самом деле не касается эллипса. Теперь я решил, что должен выяснить, была ли это точка, которую я вычислил, или эллипс, которые были неправильными. Я подсчитал на своем калькуляторе и обнаружил, что линия была правильной, а эллипс — неточным:
Учитывая, что калькулятор, вероятно, не ошибается, я считаю, что Ellipse2D рисует неправильно. Тем не менее, я пробовал много других ракурсов, и вот что я нашел:
И это наводит меня на мысль, что расчеты в чем-то неверны.
Так что это моя проблема. Должен ли я использовать что-то другое, кроме Ellipse2D? Может быть, Ellipse2D недостаточно точен? Я использовал BigDecimals в своем примере кода, потому что думал, что это даст мне больше точности — это неправильный подход? Моя конечная цель — вычислить прямоугольное положение точки на эллипсе под определенным углом.
Заранее спасибо.