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