1 // Copyright (c) 2008 GeometryFactory Sarl (France). 2 // All rights reserved. 3 // 4 // This file is part of CGAL (www.cgal.org); you may redistribute it under 5 // the terms of the Q Public License version 1.0. 6 // See the file LICENSE.QPL distributed with CGAL. 7 // 8 // Licensees holding a valid commercial license may use this file in 9 // accordance with the commercial license agreement provided with the software. 10 // 11 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 12 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 13 // 14 // $URL: https://github.com/CGAL/cgal/blob/v5.3/GraphicsView/demo/Periodic_2_triangulation_2/include/CGAL/Qt/PeriodicTriangulationGraphicsItem.h $ 15 // $Id: PeriodicTriangulationGraphicsItem.h cc99fd9 2021-02-19T16:02:12+01:00 Maxime Gimeno 16 // 17 // 18 // Author(s) : Andreas Fabri <Andreas.Fabri@geometryfactory.com> 19 // Laurent Rineau <Laurent.Rineau@geometryfactory.com> 20 // Nico Kruithof <Nico@nghk.nl> 21 22 #ifndef CGAL_QT_PERIODIC_TRIANGULATION_GRAPHICS_ITEM_H 23 #define CGAL_QT_PERIODIC_TRIANGULATION_GRAPHICS_ITEM_H 24 25 #include <CGAL/Bbox_2.h> 26 #include <CGAL/Qt/PainterOstream.h> 27 #include <CGAL/Qt/GraphicsItem.h> 28 #include <CGAL/Qt/Converter.h> 29 30 #include <QGraphicsScene> 31 #include <QPainter> 32 #include <QStyleOption> 33 34 namespace CGAL { 35 namespace Qt { 36 37 template <typename T> 38 class PeriodicTriangulationGraphicsItem : public GraphicsItem 39 { 40 typedef typename T::Geom_traits Geom_traits; 41 public: 42 PeriodicTriangulationGraphicsItem(T* t_); 43 44 void modelChanged(); 45 46 enum Iterator_type { 47 STORED = 0, 48 UNIQUE, // 1 49 STORED_COVER_DOMAIN, // 2 50 UNIQUE_COVER_DOMAIN, // 3 51 NONE 52 }; setEmphasizedSimplices(Iterator_type type)53 void setEmphasizedSimplices(Iterator_type type) { this->type = type; } getEmphasizedSimplices()54 Iterator_type getEmphasizedSimplices() { return this->type; } 55 public: 56 57 QRectF boundingRect() const; 58 59 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); 60 61 virtual void operator()(typename T::Face_handle fh); 62 verticesPen()63 const QPen& verticesPen() const 64 { 65 return vertices_pen; 66 } 67 edgesPen()68 const QPen& edgesPen() const 69 { 70 return edges_pen; 71 } 72 facesPen()73 const QPen& facesPen() const 74 { 75 return faces_pen; 76 } 77 domainPen()78 const QPen& domainPen() const 79 { 80 return domain_pen; 81 } 82 setVerticesPen(const QPen & pen)83 void setVerticesPen(const QPen& pen) 84 { 85 vertices_pen = pen; 86 } 87 setEdgesPen(const QPen & pen)88 void setEdgesPen(const QPen& pen) 89 { 90 edges_pen = pen; 91 } 92 setFacesPen(const QPen & pen)93 void setFacesPen(const QPen& pen) 94 { 95 edges_pen = pen; 96 } 97 setDomainPen(const QPen & pen)98 void setDomainPen(const QPen& pen) 99 { 100 domain_pen = pen; 101 } 102 visibleVertices()103 bool visibleVertices() const 104 { 105 return visible_vertices; 106 } 107 setVisibleVertices(const bool b)108 void setVisibleVertices(const bool b) 109 { 110 visible_vertices = b; 111 update(); 112 } 113 visibleEdges()114 bool visibleEdges() const 115 { 116 return visible_edges; 117 } 118 setVisibleEdges(const bool b)119 void setVisibleEdges(const bool b) 120 { 121 visible_edges = b; 122 update(); 123 } 124 125 protected: 126 virtual void drawAll(QPainter *painter); 127 void paintVertices(QPainter *painter); 128 void paintOneVertex(const typename T::Point& point); 129 virtual void paintVertex(typename T::Vertex_handle vh); 130 void updateBoundingBox(); 131 132 T * t; 133 QPainter* m_painter; 134 PainterOstream<Geom_traits> painterostream; 135 136 typename T::Vertex_handle vh; 137 typename T::Point p; 138 QRectF bounding_rect; 139 140 QPen vertices_pen; 141 QPen edges_pen; 142 QPen faces_pen; 143 QPen domain_pen; 144 bool visible_edges; 145 bool visible_vertices; 146 147 Iterator_type type; 148 }; 149 150 151 template <typename T> PeriodicTriangulationGraphicsItem(T * t_)152 PeriodicTriangulationGraphicsItem<T>::PeriodicTriangulationGraphicsItem(T * t_) 153 : t(t_), painterostream(nullptr), 154 visible_edges(true), visible_vertices(true), 155 type(NONE) 156 { 157 setVerticesPen(QPen(::Qt::red, 1.)); 158 setFacesPen(QPen(QColor(100,100,100))); 159 setDomainPen(QPen(::Qt::blue, .01)); 160 setEdgesPen(QPen(::Qt::black, .01)); 161 if(t->number_of_vertices() == 0){ 162 this->hide(); 163 } 164 updateBoundingBox(); 165 setZValue(3); 166 } 167 168 template <typename T> 169 QRectF boundingRect()170 PeriodicTriangulationGraphicsItem<T>::boundingRect() const 171 { 172 return bounding_rect; 173 } 174 175 176 template <typename T> 177 void operator()178 PeriodicTriangulationGraphicsItem<T>::operator()(typename T::Face_handle fh) 179 { 180 if(visible_edges) { 181 for (int i=0; i<3; i++) { 182 if (fh < fh->neighbor(i)){ 183 m_painter->setPen(this->edgesPen()); 184 painterostream << t->segment(fh,i); 185 } 186 } 187 } 188 if(visible_vertices) { 189 for (int i=0; i<3; i++) { 190 paintVertex(fh->vertex(i)); 191 } 192 } 193 } 194 195 template <typename T> 196 void drawAll(QPainter * painter)197 PeriodicTriangulationGraphicsItem<T>::drawAll(QPainter *painter) 198 { 199 painterostream = PainterOstream<Geom_traits>(painter); 200 201 if (type != NONE) 202 { 203 typename T::Iterator_type itype; 204 switch (type) { 205 case STORED: 206 itype = T::STORED; 207 break; 208 case UNIQUE: 209 itype = T::UNIQUE; 210 break; 211 case STORED_COVER_DOMAIN: 212 itype = T::STORED_COVER_DOMAIN; 213 break; 214 case UNIQUE_COVER_DOMAIN: 215 itype = T::UNIQUE_COVER_DOMAIN; 216 break; 217 case NONE: 218 default: 219 assert(false); 220 itype = T::STORED; 221 break; 222 } 223 224 Converter<Geom_traits> convert; 225 226 QTransform matrix = painter->worldTransform(); 227 painter->resetTransform(); 228 229 { // Faces 230 painter->setPen(QPen()); 231 painter->setBrush(QBrush(::Qt::green)); 232 for (typename T::Periodic_triangle_iterator tit = t->periodic_triangles_begin(itype); 233 tit != t->periodic_triangles_end(itype); ++tit) { 234 painter->drawConvexPolygon(matrix.map(convert(t->triangle(*tit)))); 235 } 236 painter->setBrush(QBrush()); 237 } 238 { // Edges 239 QPen pen = edgesPen(); 240 pen.setWidth(pen.width() + 2); 241 painter->setPen(pen); 242 for (typename T::Periodic_segment_iterator sit = t->periodic_segments_begin(itype); 243 sit != t->periodic_segments_end(itype); ++sit) { 244 painter->drawLine(matrix.map(convert(t->segment(*sit)))); 245 } 246 } 247 { // Vertices 248 QPen pen = verticesPen(); 249 pen.setWidth(pen.width() + 2); 250 painter->setPen(pen); 251 for (typename T::Periodic_point_iterator pit = t->periodic_points_begin(itype); 252 pit != t->periodic_points_end(itype); ++pit) { 253 painter->drawPoint(matrix.map(convert(t->point(*pit)))); 254 } 255 } 256 257 painter->setWorldTransform(matrix); 258 } 259 260 if(visibleEdges()) { 261 painter->setPen(this->edgesPen()); 262 t->draw_triangulation(painterostream); 263 } 264 265 paintVertices(painter); 266 } 267 268 template <typename T> 269 void paintVertices(QPainter * painter)270 PeriodicTriangulationGraphicsItem<T>::paintVertices(QPainter *painter) 271 { 272 if(visibleVertices()) { 273 Converter<Geom_traits> convert; 274 275 QTransform matrix = painter->worldTransform(); 276 painter->resetTransform(); 277 278 QPen pen = verticesPen(); 279 if (t->number_of_vertices() < 8) { 280 int v_index=1; 281 for (typename T::Unique_vertex_iterator vit = t->unique_vertices_begin(); 282 vit != t->unique_vertices_end(); ++vit) { 283 pen.setColor(QColor(255*(v_index&1), 255*((v_index>>1)&1), 255*((v_index>>2)&1))); 284 painter->setPen(pen); 285 286 painter->drawPoint(matrix.map(convert(t->point(vit)))); 287 std::vector<typename T::Vertex_handle> copies = t->periodic_copies(vit); 288 for (size_t i=0; i<copies.size(); ++i) 289 painter->drawPoint(matrix.map(convert(t->point(copies[i])))); 290 291 ++v_index; 292 } 293 294 } else { 295 painter->setPen(verticesPen()); 296 for (typename T::Periodic_point_iterator ppit = t->periodic_points_begin(); 297 ppit != t->periodic_points_end(); ++ppit) 298 { 299 QPointF point = matrix.map(convert(t->point(*ppit))); 300 painter->drawPoint(point); 301 } 302 } 303 304 painter->setWorldTransform(matrix); 305 } 306 } 307 308 template <typename T> 309 void paintOneVertex(const typename T::Point & point)310 PeriodicTriangulationGraphicsItem<T>::paintOneVertex(const typename T::Point& point) 311 { 312 Converter<Geom_traits> convert; 313 314 m_painter->setPen(this->verticesPen()); 315 QTransform matrix = m_painter->worldTransform(); 316 m_painter->resetTransform(); 317 m_painter->drawPoint(matrix.map(convert(point))); 318 m_painter->setWorldTransform(matrix); 319 } 320 321 template <typename T> 322 void paintVertex(typename T::Vertex_handle vh)323 PeriodicTriangulationGraphicsItem<T>::paintVertex(typename T::Vertex_handle vh) 324 { 325 Converter<Geom_traits> convert; 326 327 m_painter->setPen(this->verticesPen()); 328 QTransform matrix = m_painter->worldTransform(); 329 m_painter->resetTransform(); 330 m_painter->drawPoint(matrix.map(convert(vh->point()))); 331 m_painter->setWorldTransform(matrix); 332 } 333 334 template <typename T> 335 void paint(QPainter * painter,const QStyleOptionGraphicsItem *,QWidget *)336 PeriodicTriangulationGraphicsItem<T>::paint(QPainter *painter, 337 const QStyleOptionGraphicsItem *, 338 QWidget *) 339 { 340 drawAll(painter); 341 342 painter->setPen(this->domainPen()); 343 const typename Geom_traits::Iso_rectangle_2 &domain = t->domain(); 344 double dx = domain.xmax()-domain.xmin(); 345 double dy = domain.ymax()-domain.ymin(); 346 typename T::Covering_sheets sheets = t->number_of_sheets(); 347 for (int x=0; x<sheets[0]; ++x) { 348 for (int y=0; y<sheets[1]; ++y) { 349 painter->drawRect((int)(domain.xmin() + x*dx), 350 (int)(domain.ymin() + y*dy), 351 (int)dx, (int)dy); 352 } 353 } 354 m_painter = painter; 355 } 356 357 // We let the bounding box only grow, so that when vertices get removed 358 // the maximal bbox gets refreshed in the GraphicsView 359 template <typename T> 360 void updateBoundingBox()361 PeriodicTriangulationGraphicsItem<T>::updateBoundingBox() 362 { 363 prepareGeometryChange(); 364 365 CGAL::Bbox_2 bb = t->domain().bbox(); 366 for (typename T::Periodic_triangle_iterator tit = t->periodic_triangles_begin(T::STORED_COVER_DOMAIN); 367 tit != t->periodic_triangles_end(T::STORED_COVER_DOMAIN); ++tit) { 368 bb = bb + t->triangle(*tit).bbox(); 369 } 370 371 double xmin = bb.xmin(); 372 double ymin = bb.ymin(); 373 double dx = bb.xmax() - xmin; 374 double dy = bb.ymax() - ymin; 375 376 double delta = 0.05; 377 xmin -= delta * dx; 378 ymin -= delta * dy; 379 dx += 2 * delta * dx; 380 dy += 2 * delta * dy; 381 382 bounding_rect = QRectF(xmin, ymin, dx, dy); 383 } 384 385 386 template <typename T> 387 void modelChanged()388 PeriodicTriangulationGraphicsItem<T>::modelChanged() 389 { 390 if((t->number_of_vertices() == 0) ){ 391 this->hide(); 392 } else if((t->number_of_vertices() > 0) && (! this->isVisible())){ 393 this->show(); 394 } 395 updateBoundingBox(); 396 update(); 397 } 398 399 400 } // namespace Qt 401 } // namespace CGAL 402 403 #endif // CGAL_QT_PERIODIC_TRIANGULATION_GRAPHICS_ITEM_H 404