У меня есть задача записать программу, разрешающую пользователям потянуть звезды, которые могут отличаться по размеру и сумме рук. Когда я имел дело с основными звездами, я делал его с GeneralPath и таблицами точек:
int xPoints[] = { 55, 67, 109, 73, 83, 55, 27, 37, 1, 43 };
int yPoints[] = { 0, 36, 36, 54, 96, 72, 96, 54, 36, 36 };
Graphics2D g2d = ( Graphics2D ) g;
GeneralPath star = new GeneralPath();
star.moveTo( xPoints[ 0 ], yPoints[ 0 ] );
for ( int k = 1; k < xPoints.length; k++ )
star.lineTo( xPoints[ k ], yPoints[ k ] );
star.closePath();
g2d.fill( star );
Какой метод я должен выбрать для рисования звезд с переменным внутренним и внешним радиусом, а также другой суммы рук? Это - то, что я должен получить:
сопроводительный текст http://img228.imageshack.us/img228/6427/lab6c.jpg
Наличие n плеч означает, что у вас будет 2n вершин, четные находятся на внешний круг, а нечетные - на внутреннем. Если смотреть из центра, вершины находятся под равномерно разнесенными углами (угол равен 2 * PI / 2 * n = Pi / n). На единичной окружности (r = 1) координаты x, y точек i = 0..n равны cos (x), sin (x). Умножьте эти координаты на соответствующий радиус (rOuter или rInner, в зависимости от того, является ли i нечетным или четным), и добавьте этот вектор к центру звезды, чтобы получить координаты для каждой вершины на пути звезды.
Вот функция для создания формы звезды с заданным количеством плеч, центральной координатой и внешним, внутренним радиусом:
public static Shape createStar(int arms, Point center, double rOuter, double rInner) {
double angle = Math.PI / arms;
GeneralPath path = new GeneralPath();
for (int i = 0; i < 2 * arms; i++) {
double r = (i & 1) == 0 ? rOuter : rInner;
Point2D.Double p = new Point2D.Double(
center.x + Math.cos(i * angle) * r,
center.y + Math.sin(i * angle) * r);
if (i == 0) {
path.moveTo(p.getX(), p.getY());
}
else {
path.lineTo(p.getX(), p.getY());
}
}
path.closePath();
return path;
}
Вот пример поиска равноотстоящих точек на окружности , который может помочь. Просто сделайте количество точек n параметром в конструкторе.
private int n;
...
public CircleTest(int n) {
...
this.n = n;
}
...
for (int i = 0; i < n; i++) {
double t = 2 * Math.PI * i / n;
...
}
Я думаю, вам следует использовать те же классы (GeneralPath), но здесь вы должны сосредоточиться на том, как вычислять координаты вершин.
Первое, что приходит мне в голову, - это разместить 2N точек на окружности радиуса R1 с центром в точке (0,0). Затем «растяните» каждую нечетную вершину, умножив ее вектор на c. Константа c должна быть равна R2 / R1 (то есть пропорции внутреннего и внешнего радиусов).
Но, может быть, есть более простое решение ...