2015-10-20 24 views
3

В настоящее время я пытаюсь нарисовать и заполнить многоугольник с отверстием в нем на 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 не поддерживает многоугольники с отверстиями.

ответ

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

    Area polygonWithHole = polygonShape.subtract(ellipseShape); 
    
+0

отверстия в моих многоугольниках обычно также многоугольники, а не эллипсы, также ли это работает с вашим подходом? – LBecker

+0

спасибо за дружеский и быстрый ответ. В настоящее время я не могу попробовать и запрограммировать ваше предложение, так как я не нахожусь на своем компьютере Да, я прочитал документацию. Я опубликую свои результаты, как только смогу добраться до кодирования. – LBecker

+0

@AndrewThompson. Я полностью согласен, хотя я бы сформулировал комментарий немного дружелюбно.;) – brimborium

-1

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

+2

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

+0

cheseaux прав, это печально не правильный ответ :( – LBecker

+0

Вам нужно было бы сделать обрезанный раздел изображения и нарисовать его над полигоном. – Zymus

1

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

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

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

+0

Спасибо за ваш ответ, я просмотрю его. Использование вашего подхода означало бы tesselate каждый полигон каждый раз, когда я должен их рисовать. У меня есть около 30 000 полигонов, на которых на экране есть 100 отверстий. Ill проверить, как это повлияет на производительность. В качестве альтернативы, мне нужно сохранить тесселированные версии полигонов с самого начала в классе и нарисовать это (мне нравится эта версия лучше) – LBecker

+0

@LBecker Я просто вернул этот ответ для полноты. Думаю, я предпочел бы работать с «Зоной» или чем-то подобным. Мысль, которая может повлиять на производительность. Если производительность является проблемой, вам придется посмотреть на все свои варианты и выяснить, что является лучшим. – brimborium

1

Вы можете использовать java.awt.geom.Path2D вынести «соединение формы» с отверстием в нем:

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

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

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

См. How to create shape with a hole? для более длинного примера кода.