From cc4aa7cd9dea55dddf5e68f3cf17089a4a5ca2b8 Mon Sep 17 00:00:00 2001 From: Mostafa-ashraf19 Date: Thu, 6 Oct 2022 17:48:58 +0200 Subject: [PATCH] Applied new APIs version in Voronoi 2, with modifications in Basic_viewer_qt. --- .../include/CGAL/Qt/Basic_viewer_qt.h | 2 +- .../include/CGAL/draw_voronoi_diagram_2.h | 532 +++++++++--------- 2 files changed, 266 insertions(+), 268 deletions(-) diff --git a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h index ceae3cfd1c4..728d1ed7bc1 100644 --- a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h +++ b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h @@ -399,7 +399,6 @@ public: update(); } -protected: // Shortcuts to simplify function calls. template static Local_point get_local_point(const KPoint& p) @@ -414,6 +413,7 @@ protected: get_local_vector(v); } +protected: void compile_shaders() { rendering_program_face.removeAllShaders(); diff --git a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h index f92e9af630e..a16714badaf 100644 --- a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h +++ b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h @@ -8,10 +8,13 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // Author(s) : Jasmeet Singh +// Mostafa Ashraf #ifndef CGAL_DRAW_VORONOI_DIAGRAM_2_H #define CGAL_DRAW_VORONOI_DIAGRAM_2_H +#include +#include #include #include @@ -28,306 +31,301 @@ namespace CGAL { -// Default color functor; user can change it to have its own face color -struct DefaultColorFunctorV2 +namespace draw_function_for_v2 { - template - static CGAL::IO::Color run(const V2 &, const typename V2::Face_iterator /*fh*/) { - //CGAL::Random random((unsigned int)(std::size_t)(&*fh)); - //return get_random_color(random); - return CGAL::IO::Color(73, 250, 117); - } -}; -// Viewer for Voronoi diagram -template -class SimpleVoronoiDiagram2ViewerQt : public Basic_viewer_qt +typedef CGAL::Exact_predicates_inexact_constructions_kernel Local_kernel; +typedef Local_kernel::Point_3 Local_point; +typedef Local_kernel::Vector_3 Local_vector; + +template +void compute_vertex(typename V2::Vertex_iterator vh, CGAL::Graphic_buffer &graphic_buffer) { + + graphic_buffer.add_point(vh->point()); + +} + +template +void compute_dual_vertex(typename V2::Delaunay_graph::Finite_vertices_iterator vi, CGAL::Graphic_buffer &graphic_buffer) { - typedef Basic_viewer_qt Base; - typedef typename V2::Vertex_iterator Vertex_const_handle; - typedef typename V2::Delaunay_vertex_handle Delaunay_vertex_const_handle; - typedef typename V2::Delaunay_graph::Finite_vertices_iterator Dual_vertices_iterator; - - typedef typename V2::Halfedge_iterator Halfedge_const_handle; - typedef typename V2::Ccb_halfedge_circulator Ccb_halfedge_circulator; - typedef typename V2::Halfedge_handle Halfedge_handle; - - typedef typename V2::Face_iterator Face_const_handle; + graphic_buffer.add_point(vi->point(), CGAL::IO::Color(50, 100, 180)); +} +template +void add_segments_and_update_bounding_box(typename V2::Halfedge_handle he, CGAL::Graphic_buffer &graphic_buffer) +{ typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; + typedef typename V2::Delaunay_vertex_handle Delaunay_vertex_const_handle; -public: - /// Construct the viewer. - /// @param av2 the voronoi diagram to view - /// @param title the title of the window - /// @param anofaces if true, do not draw faces (faces are not computed; this - /// can be useful for very big object where this time could be long) - SimpleVoronoiDiagram2ViewerQt(QWidget *parent, const V2 &av2, - const char *title = "Basic Voronoi Viewer", - bool anofaces = false, - bool draw_voronoi_vertices = true, - bool draw_delaunay_vertices = true, - const ColorFunctor &fcolor = ColorFunctor()) - : // First draw: vertices; half-edges; faces; multi-color; no inverse - // normal - Base(parent, title, true, true, true, false, false, true, true), - v2(av2), m_nofaces(anofaces), - m_draw_voronoi_vertices(draw_voronoi_vertices), - m_draw_dual_vertices(draw_delaunay_vertices), m_fcolor(fcolor) { - // Add custom key description (see keyPressEvent) - setKeyDescription(::Qt::Key_R, "Toggles rays display"); - setKeyDescription(::Qt::Key_D, "Toggles dual vertices display"); - setKeyDescription(::Qt::Key_V, "Toggles voronoi vertices display"); - - compute_elements(); - } - -protected: - - void compute_vertex(Vertex_const_handle vh) { add_point(vh->point()); } - - void compute_dual_vertex(Dual_vertices_iterator vi) - { - add_point(vi->point(), CGAL::IO::Color(50, 100, 180)); - } - - void add_segments_and_update_bounding_box(Halfedge_handle he) - { - if (he->is_segment()) { - add_segment(he->source()->point(), he->target()->point()); - } else { - Delaunay_vertex_const_handle v1 = he->up(); - Delaunay_vertex_const_handle v2 = he->down(); - - Kernel::Vector_2 direction(v1->point().y() - v2->point().y(), - v2->point().x() - v1->point().x()); - if (he->is_ray()) { - Kernel::Point_2 end_point; - if (he->has_source()) { - end_point = he->source()->point(); - update_bounding_box_for_ray(end_point, direction); - } - } else if (he->is_bisector()) { - Kernel::Point_2 pointOnLine((v1->point().x() + v2->point().x()) / 2, - (v1->point().y() + v2->point().y()) / 2); - Kernel::Vector_2 perpendicularDirection( - v2->point().x() - v1->point().x(), - v2->point().y() - v1->point().y()); - update_bounding_box_for_line(pointOnLine, direction, - perpendicularDirection); - } - } - } - - Local_kernel::Point_2 get_second_point(Halfedge_handle ray) - { - Delaunay_vertex_const_handle v1 = ray->up(); - Delaunay_vertex_const_handle v2 = ray->down(); - - // calculate direction of ray and its inverse - Kernel::Vector_2 v(v1->point().y() - v2->point().y(), - v2->point().x() - v1->point().x()); - Local_kernel::Vector_2 inv(1 / v.x(), 1 / v.y()); - - // origin of the ray - Kernel::Point_2 p; - if (ray->has_source()) { - p = ray->source()->point(); - } else { - p = ray->target()->point(); - } - - // get the bounding box of the viewer - Local_kernel::Vector_2 boundsMin(m_bounding_box.xmin(), - m_bounding_box.zmin()); - Local_kernel::Vector_2 boundsMax(m_bounding_box.xmax(), - m_bounding_box.zmax()); - // calculate intersection - double txmax, txmin, tymax, tymin; - - if (inv.x() >= 0) { - txmax = (boundsMax.x() - p.x()) * inv.x(); - txmin = (boundsMin.x() - p.x()) * inv.x(); - } else { - txmax = (boundsMin.x() - p.x()) * inv.x(); - txmin = (boundsMax.x() - p.x()) * inv.x(); - } - - if (inv.y() >= 0) { - tymax = (boundsMax.y() - p.y()) * inv.y(); - tymin = (boundsMin.y() - p.y()) * inv.y(); - } else { - tymax = (boundsMin.y() - p.y()) * inv.y(); - tymin = (boundsMax.y() - p.y()) * inv.y(); - } - - if (tymin > txmin) - txmin = tymin; - if (tymax < txmax) - txmax = tymax; - - Local_kernel::Point_2 p1; - if (v.x() == 0) { - p1 = Local_kernel::Point_2(p.x(), p.y() + tymax * v.y()); - } else if (v.y() == 0) { - p1 = Local_kernel::Point_2(p.x() + txmax * v.x(), p.y()); - } else { - p1 = Local_kernel::Point_2(p.x() + txmax * v.x(), p.y() + tymax * v.y()); - } - return p1; - } - - void compute_rays_and_bisectors(Halfedge_const_handle he) - { + if (he->is_segment()) { + graphic_buffer.add_segment(he->source()->point(), he->target()->point()); + } else { Delaunay_vertex_const_handle v1 = he->up(); Delaunay_vertex_const_handle v2 = he->down(); Kernel::Vector_2 direction(v1->point().y() - v2->point().y(), - v2->point().x() - v1->point().x()); + v2->point().x() - v1->point().x()); if (he->is_ray()) { + Kernel::Point_2 end_point; if (he->has_source()) { - // add_ray_segment(he->source()->point(), get_second_point(he)); - add_ray(he->source()->point(), direction, CGAL::IO::Color(100, 0, 0)); + end_point = he->source()->point(); + + // update_bounding_box_for_ray(end_point, direction); + + // update_bounding_box_for_ray + Local_point lp = Basic_viewer_qt<>::get_local_point(end_point); + Local_vector lv = Basic_viewer_qt<>::get_local_vector(direction); + CGAL::Bbox_3 b = (lp + lv).bbox(); + graphic_buffer.update_bounding_box(b); + + } } else if (he->is_bisector()) { Kernel::Point_2 pointOnLine((v1->point().x() + v2->point().x()) / 2, (v1->point().y() + v2->point().y()) / 2); - add_line(pointOnLine, direction); + Kernel::Vector_2 perpendicularDirection( + v2->point().x() - v1->point().x(), + v2->point().y() - v1->point().y()); + + // update_bounding_box_for_line(pointOnLine, direction, + // perpendicularDirection); + + // update_bounding_box_for_line + Local_point lp = Basic_viewer_qt<>::get_local_point(pointOnLine); + Local_vector lv = Basic_viewer_qt<>::get_local_vector(direction); + Local_vector lpv = Basic_viewer_qt<>::get_local_vector(perpendicularDirection); + + CGAL::Bbox_3 b = lp.bbox() + (lp + lv).bbox() + (lp + lpv).bbox(); + graphic_buffer.update_bounding_box(b); + + } + } +} + +template +Local_kernel::Point_2 get_second_point(typename V2::Halfedge_handle ray, const CGAL::Bbox_3 & m_bounding_box) +{ + typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; + typedef typename V2::Delaunay_vertex_handle Delaunay_vertex_const_handle; + + Delaunay_vertex_const_handle v1 = ray->up(); + Delaunay_vertex_const_handle v2 = ray->down(); + + // calculate direction of ray and its inverse + Kernel::Vector_2 v(v1->point().y() - v2->point().y(), + v2->point().x() - v1->point().x()); + Local_kernel::Vector_2 inv(1 / v.x(), 1 / v.y()); + + // origin of the ray + Kernel::Point_2 p; + if (ray->has_source()) { + p = ray->source()->point(); + } else { + p = ray->target()->point(); + } + + // get the bounding box of the viewer + Local_kernel::Vector_2 boundsMin(m_bounding_box.xmin(), + m_bounding_box.zmin()); + Local_kernel::Vector_2 boundsMax(m_bounding_box.xmax(), + m_bounding_box.zmax()); + // calculate intersection + double txmax, txmin, tymax, tymin; + + if (inv.x() >= 0) { + txmax = (boundsMax.x() - p.x()) * inv.x(); + txmin = (boundsMin.x() - p.x()) * inv.x(); + } else { + txmax = (boundsMin.x() - p.x()) * inv.x(); + txmin = (boundsMax.x() - p.x()) * inv.x(); + } + + if (inv.y() >= 0) { + tymax = (boundsMax.y() - p.y()) * inv.y(); + tymin = (boundsMin.y() - p.y()) * inv.y(); + } else { + tymax = (boundsMin.y() - p.y()) * inv.y(); + tymin = (boundsMax.y() - p.y()) * inv.y(); + } + + if (tymin > txmin) + txmin = tymin; + if (tymax < txmax) + txmax = tymax; + + Local_kernel::Point_2 p1; + if (v.x() == 0) { + p1 = Local_kernel::Point_2(p.x(), p.y() + tymax * v.y()); + } else if (v.y() == 0) { + p1 = Local_kernel::Point_2(p.x() + txmax * v.x(), p.y()); + } else { + p1 = Local_kernel::Point_2(p.x() + txmax * v.x(), p.y() + tymax * v.y()); + } + return p1; +} + +// Halfedge_const_handle +template +void compute_rays_and_bisectors(typename V2::Halfedge_iterator he, CGAL::Graphic_buffer &graphic_buffer) +{ + typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; + typedef typename V2::Delaunay_vertex_handle Delaunay_vertex_const_handle; + + Delaunay_vertex_const_handle v1 = he->up(); + Delaunay_vertex_const_handle v2 = he->down(); + + Kernel::Vector_2 direction(v1->point().y() - v2->point().y(), + v2->point().x() - v1->point().x()); + if (he->is_ray()) { + if (he->has_source()) { + // add_ray_segment(he->source()->point(), get_second_point(he, graphic_buffer.get_bounding_box())); + graphic_buffer.add_ray(he->source()->point(), direction, CGAL::IO::Color(100, 0, 0)); + } + } else if (he->is_bisector()) { + Kernel::Point_2 pointOnLine((v1->point().x() + v2->point().x()) / 2, + (v1->point().y() + v2->point().y()) / 2); + graphic_buffer.add_line(pointOnLine, direction); + } +} + +template +void compute_face(typename V2::Face_iterator fh, const V2& v2, CGAL::Graphic_buffer &graphic_buffer, const DrawingFunctor &m_drawing_functor) +{ + typedef typename V2::Ccb_halfedge_circulator Ccb_halfedge_circulator; + + if(m_drawing_functor.colored_face(v2, fh)) { + + CGAL::IO::Color c = m_drawing_functor.face_color(v2, fh); + + Ccb_halfedge_circulator ec_start = fh->ccb(); + Ccb_halfedge_circulator ec = ec_start; + + if (!fh->is_unbounded()) { + graphic_buffer.face_begin(c); + do { + graphic_buffer.add_point_in_face(ec->source()->point()); + } while (++ec != ec_start); + graphic_buffer.face_end(); + } + + } + // Test: for unbounded faces + // else { + // do{ + // if( ec->has_source() ){ + // add_point_in_face(ec->source()->point()); + // } + // else{ + // add_point_in_face(get_second_point(ec->twin(), graphic_buffer.get_bounding_box())); + // } + // } while(++ec != ec_start); + // } +} + +template +void compute_elements(const V2& v2, CGAL::Graphic_buffer &graphic_buffer, + const DrawingFunctor &m_drawing_functor , bool m_nofaces = false, bool m_draw_voronoi_vertices = true, bool m_draw_dual_vertices = true) +{ + typedef typename V2::Delaunay_graph::Finite_vertices_iterator Dual_vertices_iterator; + + // Draw the voronoi vertices + if (m_draw_voronoi_vertices) { + for (typename V2::Vertex_iterator it = v2.vertices_begin(); + it != v2.vertices_end(); ++it) { + compute_vertex(it, graphic_buffer); } } - void compute_face(Face_const_handle fh) + // Draw the dual vertices + if (m_draw_dual_vertices) { + for (Dual_vertices_iterator it = v2.dual().finite_vertices_begin(); + it != v2.dual().finite_vertices_end(); ++it) { + compute_dual_vertex(it, graphic_buffer); + } + } + + // Add segments and update bounding box + for (typename V2::Halfedge_iterator it = v2.halfedges_begin(); + it != v2.halfedges_end(); ++it) { + add_segments_and_update_bounding_box(it, graphic_buffer); + } + + for (typename V2::Halfedge_iterator it = v2.halfedges_begin(); + it != v2.halfedges_end(); ++it) { + compute_rays_and_bisectors(it, graphic_buffer); + } + + if (!m_nofaces) { + for (typename V2::Face_iterator it = v2.faces_begin(); + it != v2.faces_end(); ++it) { + compute_face(it, v2, graphic_buffer, m_drawing_functor); + } + } +} + +} // namespace draw_function_for_v2 + +template +void add_in_graphic_buffer(const V2 &v2, CGAL::Graphic_buffer &graphic_buffer, + const DrawingFunctor &m_drawing_functor, bool m_nofaces = false, + bool m_draw_voronoi_vertices = true, bool m_draw_dual_vertices = true ) { + draw_function_for_v2::compute_elements(v2, graphic_buffer, m_drawing_functor, m_nofaces, m_draw_voronoi_vertices, m_draw_dual_vertices); +} + +template +void add_in_graphic_buffer(const V2 &v2, CGAL::Graphic_buffer &graphic_buffer, + bool m_nofaces = false, bool m_draw_voronoi_vertices = true, + bool m_draw_dual_vertices = true ) { + + // Default functor; user can add his own functor. + Drawing_functor + drawing_functor; + + drawing_functor.colored_face = [](const V2&, + typename V2::Face_iterator fh) -> bool + { return true; }; + + + drawing_functor.face_color = [] (const V2& alcc, + typename V2::Face_iterator fh) -> CGAL::IO::Color { - CGAL::IO::Color c = m_fcolor.run(v2, fh); + return CGAL::IO::Color(73, 250, 117); + }; - Ccb_halfedge_circulator ec_start = fh->ccb(); - Ccb_halfedge_circulator ec = ec_start; - - if (!fh->is_unbounded()) { - face_begin(c); - do { - add_point_in_face(ec->source()->point()); - } while (++ec != ec_start); - face_end(); - } - // Test: for unbounded faces - // else { - // do{ - // if( ec->has_source() ){ - // add_point_in_face(ec->source()->point()); - // } - // else{ - // add_point_in_face(get_second_point(ec->twin())); - // } - // } while(++ec != ec_start); - // } - } - - void compute_elements() - { - clear(); - - // Draw the voronoi vertices - if (m_draw_voronoi_vertices) { - for (typename V2::Vertex_iterator it = v2.vertices_begin(); - it != v2.vertices_end(); ++it) { - compute_vertex(it); - } - } - - // Draw the dual vertices - if (m_draw_dual_vertices) { - for (Dual_vertices_iterator it = v2.dual().finite_vertices_begin(); - it != v2.dual().finite_vertices_end(); ++it) { - compute_dual_vertex(it); - } - } - - // Add segments and update bounding box - for (typename V2::Halfedge_iterator it = v2.halfedges_begin(); - it != v2.halfedges_end(); ++it) { - add_segments_and_update_bounding_box(it); - } - - for (typename V2::Halfedge_iterator it = v2.halfedges_begin(); - it != v2.halfedges_end(); ++it) { - compute_rays_and_bisectors(it); - } - - if (!m_nofaces) { - for (typename V2::Face_iterator it = v2.faces_begin(); - it != v2.faces_end(); ++it) { - compute_face(it); - } - } - } - - virtual void keyPressEvent(QKeyEvent *e) - { - /// [Keypress] - const ::Qt::KeyboardModifiers modifiers = e->modifiers(); - if ((e->key() == ::Qt::Key_R) && (modifiers == ::Qt::NoButton)) { - m_draw_rays = !m_draw_rays; - displayMessage( - QString("Draw rays=%1.").arg(m_draw_rays ? "true" : "false")); - update(); - } else if ((e->key() == ::Qt::Key_V) && (modifiers == ::Qt::NoButton)) { - m_draw_voronoi_vertices = !m_draw_voronoi_vertices; - displayMessage( - QString("Voronoi vertices=%1.").arg(m_draw_voronoi_vertices? "true" : "false")); - compute_elements(); - redraw(); - } else if ((e->key() == ::Qt::Key_D) && (modifiers == ::Qt::NoButton)) { - m_draw_dual_vertices = !m_draw_dual_vertices; - displayMessage(QString("Dual vertices=%1.") - .arg(m_draw_dual_vertices ? "true" : "false")); - compute_elements(); - redraw(); - } else { - // Call the base method to process others/classicals key - Base::keyPressEvent(e); - } - /// [Keypress] - } - -protected: - const V2 &v2; - bool m_nofaces; - bool m_draw_voronoi_vertices; - bool m_draw_dual_vertices; - const ColorFunctor &m_fcolor; -}; + add_in_graphic_buffer(v2, graphic_buffer, drawing_functor, m_nofaces, m_draw_voronoi_vertices, m_draw_dual_vertices); +} // Specialization of draw function. #define CGAL_VORONOI_TYPE CGAL::Voronoi_diagram_2 template + class AP, typename BufferType = float, class DrawingFunctor> +void draw(const CGAL_VORONOI_TYPE &av2, + const DrawingFunctor &drawing_functor, + bool nofill = false, + bool draw_voronoi_vertices = true, + bool draw_dual_vertices = true) +{ + CGAL::Graphic_buffer buffer; + add_in_graphic_buffer(av2, buffer, drawing_functor, nofill, draw_voronoi_vertices, draw_dual_vertices); + draw_buffer(buffer); +} + +template void draw(const CGAL_VORONOI_TYPE &av2, const char *title="2D Voronoi Diagram Basic Viewer", bool nofill = false, bool draw_voronoi_vertices = true, bool draw_dual_vertices = true) { -#if defined(CGAL_TEST_SUITE) - bool cgal_test_suite = true; -#else - bool cgal_test_suite = qEnvironmentVariableIsSet("CGAL_TEST_SUITE"); -#endif - - if (!cgal_test_suite) { - CGAL::Qt::init_ogl_context(4,3); - int argc = 1; - const char *argv[2] = {"voronoi_2_viewer", nullptr}; - QApplication app(argc, const_cast(argv)); - DefaultColorFunctorV2 fcolor; - SimpleVoronoiDiagram2ViewerQt - mainwindow(app.activeWindow(), av2, title, nofill, - draw_voronoi_vertices, draw_dual_vertices, fcolor); - mainwindow.show(); - app.exec(); - } + CGAL::Graphic_buffer buffer; + add_in_graphic_buffer(av2, buffer, nofill, draw_voronoi_vertices, draw_dual_vertices); + draw_buffer(buffer); } } // End namespace CGAL