Реализация Polygon2D в Java 2D

Я создаю 2D-игру на Java, используя библиотеку Java2D для рисования, и мне действительно нужен объект полигона с плавающей точностью, который я могу использовать как для рисования игровых объектов, так и для обнаружения столкновений на них. К сожалению, полигональный объект Java поставляется только с точностью int, и нет эквивалентного Polygon2D, как с Rectangle и Rectangle2D. Я уже провел достаточно исследований, чтобы увидеть, что у меня есть несколько вариантов, но ни один из них не кажется очень хороший.

  1. Использовать Path2D. Согласно публикации разработчика Java в этот форум, отсутствие Polygon2D было упущением, но его предлагаемая замена-Path2D. К сожалению, Path2D не предоставляет способ доступа к отдельным вершинам или ребрам, который мне нужен для обнаружения столкновений (в частности, мне нужно получить вектор, ортогональный каждому ребру).

  2. реализовать свой собственный Polygon2D это реализует интерфейс формы, так что я все еще могу передать его Graphics2D.draw(Shape). Похоже, это будет довольно сложно. Интерфейс Shape требует сложных методов реализации, таких как contains(Rectangle2D) и getPathIterator(AffineTransform). Для getPathIterator в частности, кажется, что для его реализации мне нужно вернуть объект типа PathIterator, но нет никаких конкретных реализаций интерфейса PathIterator, доступных в общедоступном AWT пакеты.

  3. Обернуть Path2d В в объекте, который "запоминает" отдельные вершины и предоставляет их клиенту. Это сработало для меня, когда мне нужна была область, которая помнила свои формы компонентов: я завернул ее в класс CompoundShape, который реализовал интерфейс Shape и перенаправил все методы Shape в их реализацию области, отслеживая каждую форму, которая была добавлена в область в ArrayList. Проблема в том, что если я следите за отдельными вершинами в двух массивах floats, нет никакого способа выставить их пользователю без возможности изменения пользователем вершин - и поскольку это произойдет путем прямого доступа к массиву, внутренний Path2D не будет получать уведомления об изменениях.

  4. Скопировать Полигон.java. Фактический исходный код класса Polygon Java доступен на grepcode.com, и я мог бы просто заменить связанный с вершиной intС floats во всем, чтобы получить Polygon2D. К сожалению, когда я попробовал это, линия import sun.awt.geom.Crossings; бросил ошибку компилятора, сказав: "пересечения типов недоступны из-за ограничения на требуемую библиотеку C:Program FilesJavajre7librt.jar - ... - Согласно этот вопрос это происходит потому, что лицензионное соглашение Sun запрещает вам заменять основные классы Java своими собственными, но Polygon не пытается это сделать - он просто создает объект типа sun.ОУ.геометрия.Переходы, без замены или расширение происходит, и я убедился, что моя копия Polygon находится в пакете, который не называется "java".

каков наилучший способ продолжить это? Я был бы признателен за предложения о том, как сделать один из этих вариантов работы или идею для другого варианта, который не имеет проблем, с которыми они сталкиваются.

3 ответов


Я бы также рекомендовал path2d в. GeneralPath является устаревшим классом; не используйте его.

Path2D предоставляет доступ к значениям вершин, хотя и окольным путем. Вам нужно использовать PathIterator:

PathIterator pi = path.getPathIterator(null);
float[] value = new float[6];
float x = 0, y = 0;

while (!pi.isDone()) {
    int type = pi.currentSegment(values);
    if (type == PathIterator.SEG_LINETO) {
        x = values[0];
        y = values[1];
    }
    else if (type == PathIterator.SEG_CLOSE) {
        x = 0;
        y = 0;
    }
    else {
        // SEG_MOVETO, SEG_QUADTO, SEG_CUBICTO
    }
    pi.next();
}

когда вы будете готовы получить фантазии, вы можете расширить это другое для поддержки квадратичных и кубических кривых. Я предполагаю, что они вам не нужны в это время, поскольку вы говорите о полигоны.

кроме того, Path2D имеет некоторые удобные статические методы для тестирования пути пересекает прямоугольник и Ли Путь содержит прямоугольник или точку. К сожалению, нет методов для тестирования пути, пересекающегося или содержащего другой путь.


можете ли вы использовать стороннюю библиотеку? Если да, могу ли я предложить использовать гладкий 2D полигон класса. Я бы сделал это внутренне, используйте этот класс для вашего фактического полигона, чтобы проверить пересечение с содержит а затем, когда вам нужно рисовать, просто бросьте float значения int и нарисуйте многоугольник Java2D.

Я знаю, что это может быть не оптимальное решение, но это может сработать для того, что вы делаете.


возможно, у внутренних частей многоугольника в другом масштабе?

умножить на большое число и typecast на int при записи на него, разделить на такое же большое число при чтении?