Java, как рисовать и заполнять многоугольник с отверстиями

В настоящее время я пытаюсь нарисовать и заполнить полигон, в котором есть дыра в Java. Обычно это не было бы большой проблемой, так как я рисовал внешнее кольцо, а затем рисовал внутреннее кольцо цветом фона.

Но проблема в том, что полигон отображается над изображением, которое должно быть "увидено" через дырку.

Я пишу код на Java и использую JTS Topology Suite для своих геометрических данных.

Это мой текущий код, который просто рисует границу и заполняет многоугольник цветом.

private void drawPolygon(com.vividsolutions.jts.geom.Polygon gpoly, Color color, Graphics2D g2d){

    java.awt.Polygon poly = (java.awt.Polygon)gpoly;

    for(Coordinate co : gpoly.getExteriorRing().getCoordinates() {
        poly.addPoint(co.x, co.y);
    }
    g2d.setColor(col);
    g2d.fill(poly);

    g2d.setColor(Color.BLACK);
    g2d.draw(poly);
}

К сожалению, java.awt.Polygon не поддерживает Многоугольники с отверстиями.


person LBecker    schedule 20.10.2015    source источник


Ответы (4)


  • Используйте Polygon в качестве основы для Area (например, под названием polygonShape).
  • Создайте Ellipse2D для «отверстия», затем установите для него Area (ellipseShape).
  • Используйте Area.subtract(Area) что-то вроде:

    Area polygonWithHole = polygonShape.subtract(ellipseShape);
    
person Andrew Thompson    schedule 21.10.2015
comment
отверстия в моих многоугольниках обычно также имеют форму многоугольника, а не эллипса, это также работает с вашим подходом? - person LBecker; 21.10.2015
comment
спасибо за дружелюбный и быстрый ответ. В настоящее время я не могу попробовать и закодировать ваше предложение, так как я не на своем рабочем компьютере. Да, я прочитал документацию. Я опубликую свои результаты, как только смогу приступить к кодированию - person LBecker; 22.10.2015
comment
@AndrewThompson Я полностью согласен, хотя я бы сформулировал комментарий немного дружелюбнее. ;) - person brimborium; 22.10.2015
comment
@brimborium Я бы сформулировал комментарий немного дружелюбнее. Дерзайте. Я «дружелюбен» в FB. - person Andrew Thompson; 22.10.2015
comment
да, этот ответ сделал это. спасибо вам и brimborium за помощь - person LBecker; 22.10.2015
comment
Да, этот ответ помог Рад, что вы разобрались. И плюс 1 за инициативу «взять мяч и бежать с ним». спасибо вам и brimborium за помощь Совет: добавьте @brimborium (или кого-то еще, важно @), чтобы уведомить человека о новом комментарии. - person Andrew Thompson; 22.10.2015

Есть несколько способов рисовать фигуры или области, которые сложнее простого многоугольника (еще один ответ уже упоминался Area).

Кроме того, вы можете попробовать тесселировать ваш окончательный многоугольник. Для этого существует множество алгоритмов. Для более сложных форм алгоритмы также становятся немного сложнее. По сути, вы делите свою окончательную форму на маленькие многоугольники (обычно треугольники, но это также может быть что-то еще), а затем рисуете эти многоугольники.

Вы можете оценить свои возможности, выполнив поиск по запросу "Алгоритм тесселяции", также есть несколько уже реализованных библиотек для Java.

person brimborium    schedule 21.10.2015
comment
Спасибо за ваш ответ, я посмотрю на это. Использование вашего подхода означало бы тесселяцию каждого многоугольника каждый раз, когда мне нужно их рисовать. У меня есть около 30 000 полигонов для рисования на экране, из которых около 100 имеют отверстия. Я проверю, как это повлияет на производительность. В качестве альтернативы я должен сохранить мозаичные версии полигонов с самого начала в классе и нарисовать это (мне эта версия нравится больше) - person LBecker; 21.10.2015
comment
@LBecker Я просто поставил этот ответ для полноты картины. Думаю, я предпочел бы работать с Area или чем-то подобным. Думал, что это может повлиять и на производительность. Если производительность является проблемой, вам придется просмотреть все варианты и выяснить, какой из них лучше. - person brimborium; 22.10.2015

Вы можете использовать java.awt.geom.Path2D для отображения "составной фигуры" с отверстием:

  • Если у вас есть java.awt.Shape объекты, определяющие внешние и внутренние края фигуры, используйте append(shape, false) для добавления каждой фигуры.

  • Если у вас есть набор точек пути для внешнего края и набор точек пути для внутреннего края, используйте lineTo(), чтобы добавить первый набор точек — создав замкнутый цикл, либо закончив той же точкой, с которой вы начали, либо вызовом closePath() для автоматического закрытия петли. Затем используйте moveTo(), чтобы создать разрыв, прежде чем добавлять внутренний набор точек с помощью дополнительных вызовов lineTo().

В любом случае вы должны создать путь, передающий Path.WIND_NON_ZERO конструктору, иначе дыра не останется незаполненной.

См. Как создать фигуру с отверстием? для более длинного примера кода. .

person peterflynn    schedule 03.11.2016

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

person Zymus    schedule 20.10.2015
comment
Но проблема в том, что полигон отображается над изображением, которое должно быть видно сквозь дырку. - person cheseaux; 20.10.2015
comment
Шесо прав, это, к сожалению, неправильный ответ :( - person LBecker; 20.10.2015
comment
Вам нужно будет сделать обрезанный участок изображения и нарисовать его поверх многоугольника. - person Zymus; 20.10.2015
comment
это было бы решением, но я ищу способ правильно нарисовать многоугольник - person LBecker; 20.10.2015