1 // Copyright (c) 2008 GeometryFactory Sarl (France).
2 // All rights reserved.
3 //
4 // This file is part of CGAL (www.cgal.org).
5 //
6 // $URL: https://github.com/CGAL/cgal/blob/v5.3/GraphicsView/include/CGAL/Qt/PolygonWithHolesGraphicsItem.h $
7 // $Id: PolygonWithHolesGraphicsItem.h 0779373 2020-03-26T13:31:46+01:00 Sébastien Loriot
8 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
9 //
10 //
11 // Author(s) : Andreas Fabri <Andreas.Fabri@geometryfactory.com>
12 // Laurent Rineau <Laurent.Rineau@geometryfactory.com>
13
14 #ifndef CGAL_QT_POLYGON_WITH_HOLES_GRAPHICS_ITEM_H
15 #define CGAL_QT_POLYGON_WITH_HOLES_GRAPHICS_ITEM_H
16
17 #include <CGAL/license/GraphicsView.h>
18
19
20 #include <CGAL/Bbox_2.h>
21 #include <CGAL/Polygon_with_holes_2.h>
22 #include <CGAL/apply_to_range.h>
23 #include <CGAL/Qt/PainterOstream.h>
24 #include <CGAL/Qt/GraphicsItem.h>
25 #include <CGAL/Qt/Converter.h>
26 #include <QGraphicsScene>
27 #include <QPainter>
28 #include <QStyleOption>
29
30 namespace CGAL {
31 namespace Qt {
32
33 template <typename P>
34 class PolygonWithHolesGraphicsItem : public GraphicsItem
35 {
36 typedef typename P::General_polygon_2::Traits Traits;
37 public:
38 PolygonWithHolesGraphicsItem(P* p_);
39
40 void modelChanged();
41
42 public:
43 QRectF boundingRect() const;
44
45 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
46
47
brush()48 const QBrush& brush() const
49 {
50 return brush_;
51 }
52
53
setBrush(const QBrush & b)54 void setBrush(const QBrush& b)
55 {
56 brush_ = b;
57 }
58
verticesPen()59 const QPen& verticesPen() const
60 {
61 return vertices_pen;
62 }
63
edgesPen()64 const QPen& edgesPen() const
65 {
66 return edges_pen;
67 }
68
setVerticesPen(const QPen & pen)69 void setVerticesPen(const QPen& pen)
70 {
71 vertices_pen = pen;
72 }
73
setEdgesPen(const QPen & pen)74 void setEdgesPen(const QPen& pen)
75 {
76 edges_pen = pen;
77 }
78
drawVertices()79 bool drawVertices() const
80 {
81 return draw_vertices;
82 }
83
setDrawVertices(const bool b)84 void setDrawVertices(const bool b)
85 {
86 draw_vertices = b;
87 update();
88 }
89
90
91 protected:
92 void updateBoundingBox();
93
94 P * poly;
95 QPainter* m_painter;
96 PainterOstream<Traits> painterostream;
97
98 typename P::General_polygon_2::Point_2 p;
99 QRectF bounding_rect;
100
101 QBrush brush_;
102 QPen vertices_pen;
103 QPen edges_pen;
104 bool draw_vertices;
105 };
106
107
108 template <typename P>
PolygonWithHolesGraphicsItem(P * p_)109 PolygonWithHolesGraphicsItem<P>::PolygonWithHolesGraphicsItem(P * p_)
110 : poly(p_), painterostream(0),
111 draw_vertices(true)
112 {
113 setVerticesPen(QPen(::Qt::red, 3.));
114 if(poly->outer_boundary().size() == 0){
115 this->hide();
116 }
117 updateBoundingBox();
118 setZValue(0);
119 }
120
121 template <typename P>
122 QRectF
boundingRect()123 PolygonWithHolesGraphicsItem<P>::boundingRect() const
124 {
125 return bounding_rect;
126 }
127
128
129
130
131 template <typename P>
132 void
paint(QPainter * painter,const QStyleOptionGraphicsItem *,QWidget *)133 PolygonWithHolesGraphicsItem<P>::paint(QPainter *painter,
134 const QStyleOptionGraphicsItem * /*option*/,
135 QWidget * /*widget*/)
136 {
137 Converter<Traits> convert;
138 QPainterPath border;
139 typename P::General_polygon_2 boundary = poly->outer_boundary();
140 painter->setPen(this->edgesPen());
141
142 typename P::General_polygon_2::Vertex_iterator it = poly->outer_boundary().vertices_begin();
143 QPointF firstPoint = convert(*it);
144 border.moveTo(firstPoint);
145 painterostream = PainterOstream<Traits>(painter);
146
147 for(++it;
148 it != poly->outer_boundary().vertices_end();
149 ++it){
150 border.lineTo(convert(*it));
151 }
152 border.lineTo(firstPoint);
153
154
155 for(typename P::Hole_const_iterator hit = poly->holes_begin();
156 hit != poly->holes_end();
157 ++hit){
158 typename P::General_polygon_2::Vertex_iterator it = hit->vertices_begin();
159 QPointF firstPoint = convert(*it);
160 border.moveTo(firstPoint);
161 for(++it;
162 it != hit->vertices_end();
163 ++it){
164 border.lineTo(convert(*it));
165 }
166 border.lineTo(firstPoint);
167 }
168
169 painter->setBrush(this->brush());
170 painter->drawPath(border);
171
172 if(drawVertices()) {
173
174 painter->setPen(verticesPen());
175 QTransform matrix = painter->worldTransform();
176 painter->resetTransform();
177 for(typename P::General_polygon_2::Vertex_iterator it = poly->outer_boundary().vertices_begin();
178 it != poly->outer_boundary().vertices_end();
179 it++){
180 QPointF point = matrix.map(convert(*it));
181 painter->drawPoint(point);
182 }
183 }
184 }
185
186 // We let the bounding box only grow, so that when vertices get removed
187 // the maximal bbox gets refreshed in the GraphicsView
188 template <typename P>
189 void
updateBoundingBox()190 PolygonWithHolesGraphicsItem<P>::updateBoundingBox()
191 {
192 Converter<Traits> convert;
193 prepareGeometryChange();
194 if(poly->outer_boundary().size() == 0){
195 return;
196 }
197 bounding_rect = convert(poly->outer_boundary().bbox());
198 }
199
200
201 template <typename P>
202 void
modelChanged()203 PolygonWithHolesGraphicsItem<P>::modelChanged()
204 {
205 if((poly->outer_boundary().size() == 0) ){
206 this->hide();
207 } else if((poly->outer_boundary().size() > 0) && (! this->isVisible())){
208 this->show();
209 }
210 updateBoundingBox();
211 update();
212 }
213
214
215 } // namespace Qt
216 } // namespace CGAL
217
218 #endif // CGAL_QT_POLYGON_WITH_HOLES_GRAPHICS_ITEM_H
219