9

Вопрос по java, java-2d, awt – Реализация Polygon2D в Java 2D

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

Use Path2D. According to a Java developer posting in this forum, the lack of Polygon2D was an oversight, but its suggested replacement is Path2D. Unfortunately, Path2D doesn't provide a way to access its individual vertices or edges, which I need in order to do collision detection (specifically I need to get a vector orthogonal to each edge).

Implement my own Polygon2D that implements the Shape interface so that I can still pass it to Graphics2D.draw(Shape). This looks like it would be pretty difficult. The Shape interface requires tricky-to-implement methods like contains(Rectangle2D) and getPathIterator(AffineTransform). For getPathIterator in particular, it seems that in order to implement it I'd need to return an object of type PathIterator, but there are no concrete implementations of the PathIterator interface available in the public AWT packages.

Wrap Path2D in an object that "remembers" the individual vertices and provides them to the client. This worked for me when I needed an Area that remembered its component shapes: I wrapped it in a CompoundShape class that implemented the Shape interface and forwarded all the Shape methods to Area's implementation of them, while keeping track of each Shape that was added to the Area in an ArrayList. The problem with this is that if I keep track of the individual vertices in two arrays of floats, there is no way to expose them to the user without the possibility of the user changing the vertices - and since that would happen by direct array access, the internal Path2D wouldn't get notified of the changes.

Copy Polygon.java. The actual source code of Java's Polygon class is available on grepcode.com, and I could simply replace the vertex-related ints with floats throughout to get a Polygon2D. Unfortunately, when I tried this, the line import sun.awt.geom.Crossings; threw a compiler error saying "The type Crossings is not accessible due to restriction on required library C:\Program Files\Java\jre7\lib\rt.jar." According to this question that happens because Sun's license agreement prevents you from replacing core Java classes with your own, but Polygon doesn't try to do that - it simply creates an object of type sun.awt.geom.Crossings, no replacing or extending happens, and I made sure to put my copy of Polygon in a package not called "java".

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

Похоже, что в коде Polygon2D также используется sun.awt.geom.Crossings, поэтому у него будут те же проблемы, что и при попытке скопироватьPolygon и измените его, чтобы использоватьfloats.

от Edward

В поискахjava Polygon2D на гугл дал мнеthis site который являетсяPolygon2D используя двойную точность.

от dacwe
3 ответа
0

Может быть, внутренности многоугольника в другом масштабе?

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

7

Я бы также рекомендовал

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();
}

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

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

Я проверяю пересечение и ограничение Path2D / Path2D путем итерации по каждому сегменту одного пути и для каждого такого сегмента итерации по каждому сегменту другого пути. Это O (n ^ 2), но я думаю, что это неизбежно. Для каждых двух сегментов (по одному от каждого пути) я проверяю на пересечение. Если нет пересечения между любыми двумя сегментами, я проверяю точки каждого пути, содержащиеся внутри другого. Если оба теста не пройдены, ни один из путей не пересекает и не закрывает другой.

от 
0

Можете ли вы использовать стороннюю библиотеку? Если да

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

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

Похожие вопросы