diff --git a/GraphicsView/include/CGAL/Buffer_for_vao.h b/GraphicsView/include/CGAL/Buffer_for_vao.h index fc4a8cae272..c70d4a920a2 100644 --- a/GraphicsView/include/CGAL/Buffer_for_vao.h +++ b/GraphicsView/include/CGAL/Buffer_for_vao.h @@ -273,7 +273,7 @@ public: add_segment(kp1, kp2); add_color(c); add_color(c); - } + } // 2.3) Add an indexed segment, without color. template @@ -900,7 +900,7 @@ protected: bool m_inverse_normal;; - // Local variables, used when we started a new face. + // Local variables, used when we started a new face.g bool m_face_started; bool m_started_face_is_colored; bool m_started_face_has_normal; diff --git a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h index f6b962daae7..cc15c5c9676 100644 --- a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h +++ b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h @@ -94,7 +94,6 @@ const char fragment_source_color[] = "uniform float spec_power ; \n" "void main(void) { \n" - " highp vec3 L = light_pos.xyz - fP.xyz; \n" " highp vec3 V = -fP.xyz; \n" @@ -105,8 +104,7 @@ const char fragment_source_color[] = " highp vec3 R = reflect(-L, N); \n" " highp vec4 diffuse = max(dot(N,L), 0.0) * light_diff * fColor; \n" " highp vec4 specular = pow(max(dot(R,V), 0.0), spec_power) * light_spec; \n" - - "gl_FragColor = light_amb*fColor + diffuse ; \n" + " gl_FragColor = light_amb*fColor + diffuse ; \n" "} \n" "\n" }; diff --git a/Maintenance/infrastructure/cgal.geometryfactory.com/crontab b/Maintenance/infrastructure/cgal.geometryfactory.com/crontab index ec794d29533..2d11b351e7c 100644 --- a/Maintenance/infrastructure/cgal.geometryfactory.com/crontab +++ b/Maintenance/infrastructure/cgal.geometryfactory.com/crontab @@ -53,7 +53,7 @@ LC_CTYPE=en_US.UTF-8 # Launch our Docker testsuite , at 21:36, # after a pull of all new images at 20:23. -06 20 * * * /usr/bin/time docker pull -a docker.io/cgal/testsuite-docker; docker rmi $(docker images | awk '// {print $3}') +06 20 * * * for i in $(cat /home/lrineau/.config/CGAL/test_cgal_docker_images); do docker pull $i; done; docker rmi $(docker images | awk '// {print $3}') 36 21 * * * cd /home/lrineau/Git/cgal-testsuite-dockerfiles && /usr/bin/time ./test_cgal.py --use-fedora-selinux-policy --force-rm --max-cpus 12 --container-cpus 4 --jobs 5 --upload-results --images $($HOME/bin/docker_images_to_test_today) diff --git a/Nef_3/doc/Nef_3/CGAL/draw_nef_3.h b/Nef_3/doc/Nef_3/CGAL/draw_nef_3.h new file mode 100644 index 00000000000..3ec9c0b2a8c --- /dev/null +++ b/Nef_3/doc/Nef_3/CGAL/draw_nef_3.h @@ -0,0 +1,15 @@ +namespace CGAL { + +/*! +\ingroup PkgDrawNef3 + +Open a new window and draws `anef3`, the `Nef_polyhedron_3`. A call to this function is blocking, that is the program continues as soon as the user closes the window. + This function requires CGAL_Qt5, and is only available if the flag CGAL_USE_BASIC_VIEWER is defined at compile time. +\tparam Nef3 a model of the `Nef_polyhedron_3` concept. +\param anef3 the nef polyhedron to draw. + +*/ +template +void draw(const Nef3& anef3); + +} /* namespace CGAL */ \ No newline at end of file diff --git a/Nef_3/doc/Nef_3/Nef_3.txt b/Nef_3/doc/Nef_3/Nef_3.txt index b1bd50533b8..c4d45087f12 100644 --- a/Nef_3/doc/Nef_3/Nef_3.txt +++ b/Nef_3/doc/Nef_3/Nef_3.txt @@ -425,6 +425,18 @@ the symbolical value, large but finite, for the size of the infimaximal box. \cgalExample{Nef_3/extended_kernel.cpp} +\subsection Nef_3DrawNefPolyhedron Draw a Nef Polyhedron + +A nef polyhedron can be visualised by calling the \link PkgDrawNef3 CGAL::draw() \endlink function as shown in the following example. This function opens a new window showing the given Nef Polyhedron. + +\cgalExample{Nef_3/draw_nef_3.cpp} + +This function requires CGAL_Qt5, and is only available if the flag CGAL_USE_BASIC_VIEWER is defined at compile time. + +\cgalFigureBegin{fig_draw_nef_polyhedron, draw_nef_3.png} +Result of the run of the draw_nef_3 program. A window shows the nef polyhedron and allows to navigate through the 3D scene. +\cgalFigureEnd + \section Nef_3File File I/O \anchor sectionNef_3IO diff --git a/Nef_3/doc/Nef_3/PackageDescription.txt b/Nef_3/doc/Nef_3/PackageDescription.txt index b8a0ab9c5e1..91de0089d8d 100644 --- a/Nef_3/doc/Nef_3/PackageDescription.txt +++ b/Nef_3/doc/Nef_3/PackageDescription.txt @@ -3,6 +3,13 @@ /// \defgroup PkgNef3IOFunctions I/O Functions /// \ingroup PkgNef3Ref +/*! Draw. + \code + #include + \endcode +*/ +/// \defgroup PkgDrawNef3 Draw a Nef Polyhedron +/// \ingroup PkgNef3Ref /*! \addtogroup PkgNef3Ref @@ -64,5 +71,8 @@ a simple OpenGL visualization for debugging and illustrations. - \link PkgNef3IOFunctions `CGAL::operator<<()` \endlink - \link PkgNef3IOFunctions `CGAL::operator>>()` \endlink +\cgalCRPSection{Draw a Nef Polyhedron} +- \link PkgDrawNef3 CGAL::draw() \endlink + */ diff --git a/Nef_3/doc/Nef_3/dependencies b/Nef_3/doc/Nef_3/dependencies index 92b8ee474e4..467cacb769e 100644 --- a/Nef_3/doc/Nef_3/dependencies +++ b/Nef_3/doc/Nef_3/dependencies @@ -11,3 +11,4 @@ Number_types BGL Surface_mesh Polygon_mesh_processing +GraphicsView diff --git a/Nef_3/doc/Nef_3/examples.txt b/Nef_3/doc/Nef_3/examples.txt index 3c394cfd017..4a790f646bc 100644 --- a/Nef_3/doc/Nef_3/examples.txt +++ b/Nef_3/doc/Nef_3/examples.txt @@ -17,4 +17,5 @@ \example Nef_3/topological_operations.cpp \example Nef_3/transformation.cpp \example Nef_3/nef_3_to_surface_mesh.cpp +\example Nef_3/draw_nef_3.cpp */ diff --git a/Nef_3/doc/Nef_3/fig/draw_nef_3.png b/Nef_3/doc/Nef_3/fig/draw_nef_3.png new file mode 100644 index 00000000000..03d51641277 Binary files /dev/null and b/Nef_3/doc/Nef_3/fig/draw_nef_3.png differ diff --git a/Nef_3/examples/Nef_3/CMakeLists.txt b/Nef_3/examples/Nef_3/CMakeLists.txt index ec12fc129f2..3ae02207f06 100644 --- a/Nef_3/examples/Nef_3/CMakeLists.txt +++ b/Nef_3/examples/Nef_3/CMakeLists.txt @@ -6,7 +6,11 @@ cmake_minimum_required(VERSION 3.1...3.15) project( Nef_3_Examples ) -find_package(CGAL QUIET) +find_package(CGAL COMPONENTS Qt5) + +if(CGAL_Qt5_FOUND) + add_definitions(-DCGAL_USE_BASIC_VIEWER -DQT_NO_KEYWORDS) +endif() if ( CGAL_FOUND ) @@ -16,6 +20,10 @@ if ( CGAL_FOUND ) create_single_source_cgal_program( "${cppfile}" ) endforeach() + if(CGAL_Qt5_FOUND) + target_link_libraries(draw_nef_3 PUBLIC CGAL::CGAL_Qt5) + endif() + else() message(STATUS "This program requires the CGAL library, and will not be compiled.") diff --git a/Nef_3/examples/Nef_3/data/cross.off b/Nef_3/examples/Nef_3/data/cross.off new file mode 100644 index 00000000000..0f08a5b0f18 --- /dev/null +++ b/Nef_3/examples/Nef_3/data/cross.off @@ -0,0 +1,85 @@ +OFF +40 38 0 + +0 3 0 +1 3 0 +2 3 0 +2 4 0 +2 5 0 +3 5 0 +3 4 0 +3 3 0 +4 3 0 +5 3 0 +5 2 0 +4 2 0 +3 2 0 +3 1 0 +3 0 0 +2 0 0 +2 1 0 +2 2 0 +1 2 0 +0 2 0 + +0 3 1 +1 3 1 +2 3 1 +2 4 1 +2 5 1 +3 5 1 +3 4 1 +3 3 1 +4 3 1 +5 3 1 +5 2 1 +4 2 1 +3 2 1 +3 1 1 +3 0 1 +2 0 1 +2 1 1 +2 2 1 +1 2 1 +0 2 1 + +4 0 1 18 19 +4 1 2 17 18 +4 2 7 12 17 +4 2 3 6 7 +4 3 4 5 6 +4 7 8 11 12 +4 8 9 10 11 +4 12 13 16 17 +4 13 14 15 16 + +4 1 0 20 21 +4 2 1 21 22 +4 3 2 22 23 +4 4 3 23 24 +4 5 4 24 25 +4 6 5 25 26 +4 7 6 26 27 +4 8 7 27 28 +4 9 8 28 29 +4 10 9 29 30 +4 11 10 30 31 +4 12 11 31 32 +4 13 12 32 33 +4 14 13 33 34 +4 15 14 34 35 +4 16 15 35 36 +4 17 16 36 37 +4 18 17 37 38 +4 19 18 38 39 +4 0 19 39 20 + +4 39 38 21 20 +4 38 37 22 21 +4 37 32 27 22 +4 27 26 23 22 +4 26 25 24 23 +4 32 31 28 27 +4 31 30 29 28 +4 37 36 33 32 +4 36 35 34 33 diff --git a/Nef_3/examples/Nef_3/draw_nef_3.cpp b/Nef_3/examples/Nef_3/draw_nef_3.cpp new file mode 100644 index 00000000000..06727eac187 --- /dev/null +++ b/Nef_3/examples/Nef_3/draw_nef_3.cpp @@ -0,0 +1,27 @@ +#include +#include +#include +#include + +#include +#include + +typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel; +typedef CGAL::Polyhedron_3 Polyhedron; +typedef CGAL::Nef_polyhedron_3 Nef_polyhedron; + +int main(int argc, char *argv[]) +{ + // read OFF file into a polyhedron + Polyhedron P; + std::ifstream ifs((argc > 1) ? argv[1] : "data/cross.off"); + ifs >> P; + + // initialize nef from polyhedron + Nef_polyhedron N(P); + + // draw Nef Polyhedron + CGAL::draw(N); + + return EXIT_SUCCESS; +} diff --git a/Nef_3/include/CGAL/draw_nef_3.h b/Nef_3/include/CGAL/draw_nef_3.h new file mode 100644 index 00000000000..da8e01bacc8 --- /dev/null +++ b/Nef_3/include/CGAL/draw_nef_3.h @@ -0,0 +1,272 @@ +// Copyright (c) 2019 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Jasmeet Singh + +#ifndef DRAW_NEF_3_H +#define DRAW_NEF_3_H + +#include +#include + +#ifdef CGAL_USE_BASIC_VIEWER + +#include +#include +#include +#include + +namespace CGAL { + +// Default color functor; user can change it to have its own face color +struct DefaultColorFunctorNefPolyhedron +{ + template + static CGAL::Color run(const NefPolyhedron&, + typename NefPolyhedron::Halffacet_const_handle fh) + { + if (fh == nullptr) // use to get the mono color + return CGAL::Color(100, 125, 200); // R G B between 0-255 + + CGAL::Random random((unsigned int)(std::size_t)(&(*fh))); + return get_random_color(random); + } +}; + +// Viewer class for Nef Polyhedron +template +class SimpleNefPolyhedronViewerQt : public Basic_viewer_qt +{ + typedef Basic_viewer_qt Base; + typedef typename Nef_Polyhedron::Kernel Kernel; + + typedef typename Nef_Polyhedron::Halffacet_cycle_const_iterator Halffacet_cycle_const_iterator; + typedef typename Nef_Polyhedron::SHalfedge_around_facet_const_circulator SHalfedge_around_facet_const_circulator; + + typedef typename Nef_Polyhedron::Shell_entry_const_iterator Shell_entry_const_iterator; + typedef typename Nef_Polyhedron::SHalfedge_const_iterator SHalfedge_const_iterator; + typedef typename Nef_Polyhedron::Volume_const_iterator Volume_const_iterator; + + typedef typename Nef_Polyhedron::Vertex_const_handle Vertex_const_handle; + typedef typename Nef_Polyhedron::SFace_const_handle SFace_const_handle; + typedef typename Nef_Polyhedron::Halfedge_const_handle Halfedge_const_handle; + typedef typename Nef_Polyhedron::Halffacet_const_handle Halffacet_const_handle; + typedef typename Nef_Polyhedron::SHalfedge_const_handle SHalfedge_const_handle; + typedef typename Nef_Polyhedron::SHalfloop_const_handle SHalfloop_const_handle; + +public: + /// Construct the viewer + /// @param anef the nef polyhedron 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 big objects) + SimpleNefPolyhedronViewerQt(QWidget* parent, + const Nef_Polyhedron& anef, + const char* title="Basic Nef Polyhedron Viewer", + bool anofaces=false, + const ColorFunctor& fcolor=ColorFunctor()) : + //First draw: vertex; edges, faces; mon-color; inverse normal + Base(parent, title, false, true, true, true, false), + nef(anef), + m_nofaces(anofaces), + m_fcolor(fcolor) + { + compute_elements(); + } +protected: + // Visitor class to iterate through shell objects + class Nef_Visitor { + public: + Nef_Visitor(SimpleNefPolyhedronViewerQt &v) + : n_faces(0), n_edges(0), viewer(v) {} + + void visit(Vertex_const_handle vh) { + viewer.add_point(vh->point()); + } + + void visit(Halffacet_const_handle opposite_facet) + { + Halffacet_const_handle f = opposite_facet->twin(); + + if (facets_done.find(f) != facets_done.end() || + facets_done.find(opposite_facet) != facets_done.end()) { + return; + } + + SHalfedge_const_handle se; + Halffacet_cycle_const_iterator fc; + fc = f->facet_cycles_begin(); + + se = SHalfedge_const_handle(fc); // non-zero if shalfedge is returned + if(se == 0) + { //return if not-shalfedge + return; + } + + CGAL::Color c = viewer.run_color(f); + viewer.face_begin(c); + + SHalfedge_around_facet_const_circulator hc_start(se); + SHalfedge_around_facet_const_circulator hc_end(hc_start); + CGAL_For_all(hc_start, hc_end) { + Vertex_const_handle vh = hc_start->source()->center_vertex(); + viewer.add_point_in_face(vh->point(), + viewer.get_vertex_normal(vh)); + } + viewer.face_end(); + facets_done[f] = true; + n_faces++; + } + + void visit(Halfedge_const_handle he) + { + Halfedge_const_handle twin = he->twin(); + if (edges_done.find(he) != edges_done.end() || + edges_done.find(twin) != edges_done.end()) + { + // Edge already added + return; + } + + viewer.add_segment(he->source()->point(), he->target()->point()); + edges_done[he] = true; + n_edges++; + } + + void visit(SHalfedge_const_handle ) {} + void visit(SHalfloop_const_handle ) {} + void visit(SFace_const_handle ) {} + int n_faces; + int n_edges; + protected: + std::unordered_map facets_done; + std::unordered_map edges_done; + SimpleNefPolyhedronViewerQt& viewer; + }; + + void compute_elements() + { + clear(); + + Volume_const_iterator c; + + Nef_Visitor V(*this); + CGAL_forall_volumes(c, nef) + { + Shell_entry_const_iterator it; + CGAL_forall_shells_of(it, c) + { + nef.visit_shell_objects(SFace_const_handle(it), V); + } + } + + negate_all_normals(); + } + + CGAL::Color run_color(Halffacet_const_handle fh) + { + return m_fcolor.run(nef, fh); + } + + virtual void keyPressEvent(QKeyEvent *e) + { + // Test key pressed: + // const ::Qt::KeyboardModifiers modifiers = e->modifiers(); + // if ((e->key()==Qt::Key_PageUp) && (modifiers==Qt::NoButton)) { ... } + + // Call: * compute_elements() if the model changed, followed by + // * redraw() if some viewing parameters changed that implies some + // modifications of the buffers + // (eg. type of normal, color/mono) + // * update() just to update the drawing + + // Call the base method to process others/classicals key + Base::keyPressEvent(e); + } + +protected: + Local_vector get_face_normal(SHalfedge_const_handle she) + { + SHalfedge_around_facet_const_circulator he(she); + Local_vector normal = CGAL::NULL_VECTOR; + SHalfedge_around_facet_const_circulator end = he; + unsigned int nb = 0; + + CGAL_For_all(he, end) + { + internal::newell_single_step_3(this->get_local_point + (he->next()->source()->center_vertex()->point()), + this->get_local_point(he->source()->center_vertex()-> + point()), normal); + ++nb; + } + + assert(nb > 0); + return (typename Local_kernel::Construct_scaled_vector_3()(normal, 1.0 / nb)); + } + + Local_vector get_vertex_normal(Vertex_const_handle vh) + { + Local_vector normal = CGAL::NULL_VECTOR; + + SHalfedge_const_iterator it = vh->shalfedges_begin(); + SHalfedge_const_handle end = it; + do { + Local_vector n = get_face_normal(it); + normal = typename Local_kernel::Construct_sum_of_vectors_3()(normal, n); + it = it->snext(); + } while( it != end ); + + if (!typename Local_kernel::Equal_3()(normal, CGAL::NULL_VECTOR)) + { + normal = (typename Local_kernel::Construct_scaled_vector_3()( + normal, 1.0 / CGAL::sqrt(normal.squared_length()))); + } + + return normal; + } + +protected: + const Nef_Polyhedron &nef; + bool m_nofaces; + const ColorFunctor &m_fcolor; +}; + +#define CGAL_NEF3_TYPE Nef_polyhedron_3 + +template +void draw(const CGAL_NEF3_TYPE &anef, + const char *title = "Nef Polyhedron Viewer", + bool nofill = false) { +#if defined(CGAL_TEST_SUITE) + bool cgal_test_suite = true; +#else + bool cgal_test_suite = qEnvironmentVariableIsSet("CGAL_TEST_SUITE"); +#endif + + if (!cgal_test_suite) + { + int argc = 1; + const char *argv[2] = {"nef_polyhedron_viewer", "\0"}; + QApplication app(argc, const_cast(argv)); + DefaultColorFunctorNefPolyhedron fcolor; + SimpleNefPolyhedronViewerQt + mainwindow(app.activeWindow(), anef, title, nofill, fcolor); + mainwindow.show(); + app.exec(); + } +} + +} // End namespace CGAL + +#endif // CGAL_USE_BASIC_VIEWER + +#endif // DRAW_NEF_3_H diff --git a/Nef_3/package_info/Nef_3/dependencies b/Nef_3/package_info/Nef_3/dependencies index 71b69c66df6..9723ec4e097 100644 --- a/Nef_3/package_info/Nef_3/dependencies +++ b/Nef_3/package_info/Nef_3/dependencies @@ -7,6 +7,7 @@ Circulator Distance_2 Distance_3 Filtered_kernel +GraphicsView HalfedgeDS Hash_map Homogeneous_kernel diff --git a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/CGAL/draw_periodic_2_triangulation_2.h b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/CGAL/draw_periodic_2_triangulation_2.h new file mode 100644 index 00000000000..6365c1c51c8 --- /dev/null +++ b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/CGAL/draw_periodic_2_triangulation_2.h @@ -0,0 +1,15 @@ +namespace CGAL { + +/*! +\ingroup PkgDrawPeriodic2Triangulation2 + +opens a new window and draws `ap2t2`, the `Periodic_2_Triangulation_2`. A call to this function is blocking, that is the program continues as soon as the user closes the window. + This function requires CGAL_Qt5, and is only available if the flag CGAL_USE_BASIC_VIEWER is defined at compile time. +\tparam P2T2 a model of the `Periodic_2TriangulationTraits_2` concept. +\param ap2t2 the 2D periodic trinagulation to draw. + +*/ +template +void draw(const P2T2& ap2t2); + +} /* namespace CGAL */ diff --git a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/PackageDescription.txt b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/PackageDescription.txt index 91e32e18995..4f3a46a85b1 100644 --- a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/PackageDescription.txt +++ b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/PackageDescription.txt @@ -15,6 +15,14 @@ /// \defgroup PkgPeriodic2Triangulation2Enums Enums /// \ingroup PkgPeriodic2Triangulation2Ref +/*! Draw. + \code + #include + \endcode +*/ +/// \defgroup PkgDrawPeriodic2Triangulation2 Draw a 2D Periodic Triangulation +/// \ingroup PkgPeriodic2Triangulation2Ref + /*! \addtogroup PkgPeriodic2Triangulation2Ref @@ -103,5 +111,8 @@ of the concept `Periodic_2Offset_2`. - `CGAL::Periodic_2_triangulation_2::Iterator_type` - `CGAL::Periodic_2_triangulation_2::Locate_type` +\cgalCRPSection{Draw 2D Periodic Triangulation} + - \link PkgDrawPeriodic2Triangulation2 CGAL::draw() \endlink + */ diff --git a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/Periodic_2_triangulation_2.txt b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/Periodic_2_triangulation_2.txt index ac02381048b..26a3cce21d1 100644 --- a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/Periodic_2_triangulation_2.txt +++ b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/Periodic_2_triangulation_2.txt @@ -394,6 +394,26 @@ in the unit rectangle. The tests were done on an Intel i7 @ 2.67GHz. \image html p2dt2_performance.png \image latex p2dt2_performance.png +\section P2T2_Draw_Periodic_Triangulation Draw a 2D Periodic Triangulation + +A 2D periodic triangulation can be visualized by calling the \link PkgDrawPeriodic2Triangulation2 CGAL::draw() \endlink function as shown in the following example. This function opens a new window showing the given Periodic Triangulation. Elements of the periodic triangulation can be viewed in four different modes: + +\cgalExample{Periodic_2_triangulation_2/draw_periodic_2_triangulation_2.cpp} + +- STORED Display all geometric primitives as they are stored in Triangulation_data_structure_2; +- UNIQUE Display only one representative of each geometric primitive even if the triangulation is computed in multiply sheeted covering space; +- STORED_COVER_DOMAIN Same as STORED but also display all primitives whose intersection with the original domain of the current covering space is non-empty; +- UNIQUE_COVER_DOMAIN Same as UNIQUE but also display all primitives whose intersection with the original domain of the current covering space is non-empty. + +The domain can also be visualized by a key press. To see how to visualize the Periodic Triangulation in various modes, press key H when the viewer window is active and go to Keyboard tab. See \cgalFigureRef{P2Triangulation2figdraw1} and \cgalFigureRef{P2Triangulation2figdraw2}. + +\cgalFigureBegin{P2Triangulation2figdraw1, unique.png, unique-cover.png} +Result of the run of the draw_periodic_2_triangulation_2 program for display modes Unique(left) and Unique Cover Domain(right). The window allows to navigate through the 2D scene. +\cgalFigureEnd +\cgalFigureBegin{P2Triangulation2figdraw2, stored.png, stored-cover.png} +Result of the run of the draw_periodic_2_triangulation_2 program for display modes Stored(left) and Stored Cover Domain(right). +\cgalFigureEnd + \section P2T2_Design Design and Implementation History The periodic 2D-triangulation is based on the 2D triangulation package diff --git a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/dependencies b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/dependencies index 32fa6fbdf73..b0b47131d59 100644 --- a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/dependencies +++ b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/dependencies @@ -7,3 +7,4 @@ Stream_support TDS_2 Triangulation_2 Spatial_sorting +GraphicsView diff --git a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/examples.txt b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/examples.txt index 9be1a7e1709..37a43d200ff 100644 --- a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/examples.txt +++ b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/examples.txt @@ -9,4 +9,5 @@ \example Periodic_2_triangulation_2/p2t2_info_insert_with_transform_iterator_2.cpp \example Periodic_2_triangulation_2/p2t2_info_insert_with_zip_iterator_2.cpp \example Periodic_2_triangulation_2/p2t2_large_point_set.cpp +\example Periodic_2_triangulation_2/draw_periodic_2_triangulation_2.cpp */ diff --git a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/fig/stored-cover.png b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/fig/stored-cover.png new file mode 100644 index 00000000000..ead02c3044c Binary files /dev/null and b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/fig/stored-cover.png differ diff --git a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/fig/stored.png b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/fig/stored.png new file mode 100644 index 00000000000..cc14f2a0de1 Binary files /dev/null and b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/fig/stored.png differ diff --git a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/fig/unique-cover.png b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/fig/unique-cover.png new file mode 100644 index 00000000000..77fddcc5c6a Binary files /dev/null and b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/fig/unique-cover.png differ diff --git a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/fig/unique.png b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/fig/unique.png new file mode 100644 index 00000000000..66008914fe5 Binary files /dev/null and b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/fig/unique.png differ diff --git a/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/CMakeLists.txt b/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/CMakeLists.txt index 71e272f464c..849f222a5df 100644 --- a/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/CMakeLists.txt +++ b/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/CMakeLists.txt @@ -6,7 +6,11 @@ cmake_minimum_required(VERSION 3.1...3.15) project( Periodic_2_triangulation_2_Examples ) -find_package(CGAL QUIET) +find_package(CGAL COMPONENTS Qt5) + +if(CGAL_Qt5_FOUND) + add_definitions(-DCGAL_USE_BASIC_VIEWER -DQT_NO_KEYWORDS) +endif() if ( CGAL_FOUND ) @@ -16,6 +20,9 @@ if ( CGAL_FOUND ) create_single_source_cgal_program( "${cppfile}" ) endforeach() + if(CGAL_Qt5_FOUND) + target_link_libraries(draw_periodic_2_triangulation_2 PUBLIC CGAL::CGAL_Qt5) + endif() else() message(STATUS "This program requires the CGAL library, and will not be compiled.") diff --git a/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/data/data1.dt.cin b/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/data/data1.dt.cin new file mode 100644 index 00000000000..30765637fa5 --- /dev/null +++ b/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/data/data1.dt.cin @@ -0,0 +1,20 @@ +0.192592592592593 0.037037037037037 +0.17037037037037 0.177777777777778 +0.451851851851852 0.111111111111111 +0.274074074074074 0.37037037037037 +0.133333333333333 0.592592592592593 +0.037037037037037 0.688888888888889 +0.177777777777778 0.844444444444444 +0.288888888888889 0.674074074074074 +0.318518518518519 0.925925925925926 +0.540740740740741 0.844444444444444 +0.637037037037037 0.703703703703704 +0.511111111111111 0.496296296296296 +0.725925925925926 0.237037037037037 +0.933333333333333 0.22962962962963 +0.733333333333333 0.511111111111111 +0.925925925925926 0.459259259259259 +0.866666666666667 0.777777777777778 +0.77037037037037 0.925925925925926 +0.881481481481482 0.977777777777778 +0.990000000000000 0.911111111111111 diff --git a/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/draw_periodic_2_triangulation_2.cpp b/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/draw_periodic_2_triangulation_2.cpp new file mode 100644 index 00000000000..28a49c76731 --- /dev/null +++ b/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/draw_periodic_2_triangulation_2.cpp @@ -0,0 +1,36 @@ +#include +#include +#include +#include + +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef CGAL::Periodic_2_Delaunay_triangulation_traits_2 GT; +typedef CGAL::Periodic_2_Delaunay_triangulation_2 PDT; + +typedef PDT::Point Point; + +int main(int argc, char* argv[]) +{ + // Declare periodic triangulation 2D + PDT T; + + // Read points and insert in T + Point p; + std::ifstream ifs((argc > 1) ? argv[1] : "data/data1.dt.cin"); + if (ifs) + { + while (ifs >> p) + { T.insert(p); } + CGAL_assertion(T.is_valid()); + + if( T.is_triangulation_in_1_sheet()) + { T.convert_to_9_sheeted_covering(); } + + // Draw the periodic triangulation + CGAL::draw(T); + } + + return EXIT_SUCCESS; +} diff --git a/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h b/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h new file mode 100644 index 00000000000..42970bfa8e9 --- /dev/null +++ b/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h @@ -0,0 +1,279 @@ +// Copyright (c) 2019 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// Author(s) : Jasmeet Singh + +#ifndef DRAW_PERIODIC_2_TRIANGULATION_2_H +#define DRAW_PERIODIC_2_TRIANGULATION_2_H + +#include +#include + +#ifdef CGAL_USE_BASIC_VIEWER + +#include +#include + +namespace CGAL { + +// Default color functor; user can change it to have its own face color +struct DefaultColorFunctorP2T2 { + template + static CGAL::Color run(const P2T2 &, + const typename P2T2::Periodic_triangle_iterator /*ti*/) { + //CGAL::Random random((unsigned int)(std::size_t)(&*ti)); + //return get_random_color(random); + return CGAL::Color(73, 250, 117); + } +}; + +// Viewer class for P2T2 +template +class SimplePeriodic2Triangulation2ViewerQt : public Basic_viewer_qt +{ + typedef Basic_viewer_qt Base; + + typedef typename P2T2::Iterator_type Iterator_type; + + // Vertex iterators + typedef typename P2T2::Periodic_point_iterator Periodic_point_iterator; + + // Edge iterators + typedef typename P2T2::Periodic_segment_iterator Periodic_segment_iterator; + typedef typename P2T2::Segment Segment; + + // Face iterators + typedef typename P2T2::Periodic_triangle_iterator Periodic_triangle_iterator; + typedef typename P2T2::Triangle Triangle; + + typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; + +public: + /// Construct the viewer. + /// @param ap2t2 the p2t2 to view + /// @param title the title of the window + /// @param anofaces if true, do not draw faces (faces are not computed; this can be + /// usefull for very big object where this time could be long) + SimplePeriodic2Triangulation2ViewerQt(QWidget* parent, const P2T2& ap2t2, + const char* title="Basic P2T2 Viewer", + bool anofaces=false, + const ColorFunctor& fcolor=ColorFunctor()) : + // First draw: vertices; edges, faces; multi-color; no inverse normal + Base(parent, title, true, true, true, false, false), + p2t2(ap2t2), + m_nofaces(anofaces), + m_fcolor(fcolor), + m_display_type(STORED_COVER_DOMAIN), + m_domain(true) + { + // Add custom key description (see keyPressEvent). + setKeyDescription(::Qt::Key_1, "STORED: Display all geometric primitives as they are stored in " + "Triangulation_data_structure_2"); + setKeyDescription(::Qt::Key_2, "UNIQUE: Display only one representative of each geometric primitive even " + "if the triangulation is computed in multiply sheeted covering space."); + setKeyDescription(::Qt::Key_3, "STORED_COVER_DOMAIN: Same as STORED but also display " + "all primitives whose intersection with the original " + "domain of the current covering space is non-empty"); + setKeyDescription(::Qt::Key_4, "UNIQUE_COVER_DOMAIN: Same as UNIQUE but also display " + "all primitives whose intersection with the original " + "domain of the current covering space is non-empty"); + setKeyDescription(::Qt::Key_D, "Toggle 9-sheeted domain display"); + + compute_elements(); + } +protected: + void compute_vertex(Periodic_point_iterator pi) + { + // Construct the point in 9-sheeted covering space and add to viewer + add_point(p2t2.point(*pi)); + } + + void compute_edge(Periodic_segment_iterator si) + { + // Construct the segment in 9-sheeted covering space and add to viewer + Segment s(p2t2.segment(*si)); + add_segment(s[0], s[1]); + } + + void compute_face(Periodic_triangle_iterator ti) + { + // Construct the triangle in 9-sheeted covering space and add to viewer + Triangle t(p2t2.triangle(*ti)); + + CGAL::Color c=m_fcolor.run(p2t2, ti); + face_begin(c); + add_point_in_face(t[0]); + add_point_in_face(t[1]); + add_point_in_face(t[2]); + face_end(); + + // Display the edges of the faces as segments with a + // light gray color for better visualization + add_segment(t[0], t[1], CGAL::Color(207, 213, 211)); + add_segment(t[1], t[2], CGAL::Color(207, 213, 211)); + add_segment(t[2], t[0], CGAL::Color(207, 213, 211)); + } + + void compute_domain() + { + Kernel::Iso_rectangle_2 orig_domain = p2t2.domain(); + std::array covering_sheets = p2t2.number_of_sheets(); + + for(int i = 0; i < covering_sheets[0]; i++){ + for(int j = 0; j < covering_sheets[1]; j++){ + Kernel::Vector_2 shift(i * (orig_domain.xmax() - orig_domain.xmin()), + j * orig_domain.ymax() - orig_domain.ymin()); + Kernel::Point_2 p1(orig_domain.min()); + Kernel::Point_2 p2(orig_domain.xmin(), orig_domain.ymax()); + Kernel::Point_2 p3(orig_domain.xmax(), orig_domain.ymin()); + Kernel::Point_2 p4(orig_domain.max()); + + add_segment(p1 + shift, p2 + shift, CGAL::Color(96, 104, 252)); + add_segment(p1 + shift, p3 + shift, CGAL::Color(96, 104, 252)); + add_segment(p2 + shift, p4 + shift, CGAL::Color(96, 104, 252)); + add_segment(p3 + shift, p4 + shift, CGAL::Color(96, 104, 252)); + } + } + } + + void compute_elements() { + // Clear the buffers + clear(); + + // Get the display type, iterate through periodic elements according + // to the display type + Iterator_type it_type = (Iterator_type)m_display_type; + + // Iterate through vertices, edges and faces, add elements to buffer + for (Periodic_point_iterator it = + p2t2.periodic_points_begin(it_type); + it != p2t2.periodic_points_end(it_type); it++) + { + compute_vertex(it); + } + + for (Periodic_segment_iterator it = + p2t2.periodic_segments_begin(it_type); + it != p2t2.periodic_segments_end(it_type); it++) + { + compute_edge(it); + } + + for (Periodic_triangle_iterator it = + p2t2.periodic_triangles_begin(it_type); + it != p2t2.periodic_triangles_end(it_type); it++) + { + compute_face(it); + } + + if(m_domain){ + // Compute the (9-sheet covering space) domain of the periodic triangulation + compute_domain(); + } + } + + virtual void keyPressEvent(QKeyEvent *e) + { + // Test key pressed: + // const ::Qt::KeyboardModifiers modifiers = e->modifiers(); + // if ((e->key()==Qt::Key_PageUp) && (modifiers==Qt::NoButton)) { ... } + + // Call: * compute_elements() if the model changed, followed by + // * redraw() if some viewing parameters changed that implies some + // modifications of the buffers + // (eg. type of normal, color/mono) + // * update() just to update the drawing + + // Call the base method to process others/classicals key + const ::Qt::KeyboardModifiers modifiers = e->modifiers(); + if (e->text()=="1") + { + m_display_type = Display_type::UNIQUE; + displayMessage(QString("Display type= UNIQUE")); + compute_elements(); + redraw(); + } else if (e->text()=="2") + { + m_display_type = Display_type::UNIQUE_COVER_DOMAIN; + displayMessage(QString("Display type= UNIQUE_COVER_DOMAIN")); + compute_elements(); + redraw(); + } else if (e->text()=="3") + { + m_display_type = Display_type::STORED; + displayMessage(QString("Display type= STORED")); + compute_elements(); + redraw(); + } else if (e->text()=="4") + { + m_display_type = Display_type::STORED_COVER_DOMAIN; + displayMessage(QString("Display type= STORED_COVER_DOMAIN")); + compute_elements(); + redraw(); + } else if ((e->key() == ::Qt::Key_D) && (modifiers == ::Qt::NoButton)) + { + m_domain=!m_domain; + displayMessage(QString("Draw domain=%1.").arg(m_domain?"true":"false")); + compute_elements(); + redraw(); + } else { + Base::keyPressEvent(e); + } + } + +protected: + const P2T2& p2t2; + bool m_nofaces; + const ColorFunctor& m_fcolor; + enum Display_type + { + STORED = 0, + UNIQUE, // 1 + STORED_COVER_DOMAIN, // 2 + UNIQUE_COVER_DOMAIN // 3 + }; + Display_type m_display_type; + bool m_domain; +}; + +// Specialization of draw function +#define CGAL_P2T2_TYPE CGAL::Periodic_2_triangulation_2 \ + + +template < class Gt, + class Tds > +void draw(const CGAL_P2T2_TYPE& ap2t2, + const char* title = "2D Periodic Triangulation Viewer", + bool nofill = false) +{ +#if defined(CGAL_TEST_SUITE) + bool cgal_test_suite=true; +#else + bool cgal_test_suite=qEnvironmentVariableIsSet("CGAL_TEST_SUITE"); +#endif + + if (!cgal_test_suite) + { + int argc=1; + const char* argv[2]={"p2t2_viewer","\0"}; + QApplication app(argc,const_cast(argv)); + DefaultColorFunctorP2T2 fcolor; + SimplePeriodic2Triangulation2ViewerQt + mainwindow(app.activeWindow(), ap2t2, title, nofill, fcolor); + mainwindow.show(); + app.exec(); + } +} + +} // namespace CGAL + +#endif // CGAL_USE_BASIC_VIEWER + +#endif // DRAW_PERIODIC_2_TRIANGULATION_2_H diff --git a/Periodic_2_triangulation_2/package_info/Periodic_2_triangulation_2/dependencies b/Periodic_2_triangulation_2/package_info/Periodic_2_triangulation_2/dependencies index 9ee86e3775d..a78447643d8 100644 --- a/Periodic_2_triangulation_2/package_info/Periodic_2_triangulation_2/dependencies +++ b/Periodic_2_triangulation_2/package_info/Periodic_2_triangulation_2/dependencies @@ -4,6 +4,7 @@ Circulator Distance_2 Distance_3 Filtered_kernel +GraphicsView Hash_map Installation Intersections_2 diff --git a/Voronoi_diagram_2/doc/Voronoi_diagram_2/CGAL/draw_voronoi_diagram_2.h b/Voronoi_diagram_2/doc/Voronoi_diagram_2/CGAL/draw_voronoi_diagram_2.h new file mode 100644 index 00000000000..ef273cb1734 --- /dev/null +++ b/Voronoi_diagram_2/doc/Voronoi_diagram_2/CGAL/draw_voronoi_diagram_2.h @@ -0,0 +1,17 @@ +namespace CGAL { + +/*! +\ingroup PkgDrawVoronoiDiagram2 + +opens a new window and draws `av2`, the `Voronoi_diagram_2` constructed from a Delaunay Graph which is a model of `DelaunayGraph_2` concept. +The class `Voronoi_diagram_2` provides an adaptor to view a triangulated Delaunay graph as their dual subdivision, the +Voronoi diagram. A call to this function is blocking, that is the program continues as soon as the user closes the window. + This function requires CGAL_Qt5, and is only available if the flag CGAL_USE_BASIC_VIEWER is defined at compile time. +\tparam V2 a model of the `AdaptationTraits_2` concept. +\param av2 the voronoi diagram to draw. + +*/ +template +void draw(const V2& av2); + +} /* namespace CGAL */ diff --git a/Voronoi_diagram_2/doc/Voronoi_diagram_2/PackageDescription.txt b/Voronoi_diagram_2/doc/Voronoi_diagram_2/PackageDescription.txt index 379a9b01b4e..a173d3af29b 100644 --- a/Voronoi_diagram_2/doc/Voronoi_diagram_2/PackageDescription.txt +++ b/Voronoi_diagram_2/doc/Voronoi_diagram_2/PackageDescription.txt @@ -12,6 +12,14 @@ /// \defgroup PkgVoronoiDiagram2Disks Voronoi Diagram of Disks /// \ingroup PkgVoronoiDiagram2Ref +/*! + \code + #include + \endcode +*/ +/// \defgroup PkgDrawVoronoiDiagram2 Draw a 2D Voronoi Diagram +/// \ingroup PkgVoronoiDiagram2Ref + /*! \addtogroup PkgVoronoiDiagram2Ref \todo check generated documentation @@ -81,5 +89,9 @@ performing this adaptation. - `CGAL::Segment_Delaunay_graph_degeneracy_removal_policy_2` - `CGAL::Segment_Delaunay_graph_caching_degeneracy_removal_policy_2` +\cgalCRPSection{Draw Voronoi Diagram} + +- \link PkgDrawVoronoiDiagram2 CGAL::draw() \endlink + */ diff --git a/Voronoi_diagram_2/doc/Voronoi_diagram_2/Voronoi_diagram_2.txt b/Voronoi_diagram_2/doc/Voronoi_diagram_2/Voronoi_diagram_2.txt index 163719da3aa..41b3f9828cf 100644 --- a/Voronoi_diagram_2/doc/Voronoi_diagram_2/Voronoi_diagram_2.txt +++ b/Voronoi_diagram_2/doc/Voronoi_diagram_2/Voronoi_diagram_2.txt @@ -488,6 +488,20 @@ location queries. \cgalExample{Voronoi_diagram_2/vd_2_point_location.cpp} +\section secvda2drawvoronoi Draw a Voronoi Diagram + +A 2D Voronoi Diagram can be visualized by calling the \link PkgDrawVoronoiDiagram2 CGAL::draw() \endlink function as +shown in the following example. This function opens a new window showing the Voronoi Diagram of the given input sites/vertix locations. A call to this function is blocking, that is the program continues as soon as the user closes the window. + +This function requires CGAL_Qt5, and is only available if the flag CGAL_USE_BASIC_VIEWER is defined at compile time. + +\cgalExample{Voronoi_diagram_2/draw_voronoi_diagram_2.cpp} + +\cgalFigureBegin{draw_voronoi_diagram, draw_voronoi_diagram.png} +Result of the draw_voronoi_diagram_2 program. A window shows the Voronoi vertices and edges. +The window allows navigation through the 2D scene. +\cgalFigureEnd + */ } /* namespace CGAL */ diff --git a/Voronoi_diagram_2/doc/Voronoi_diagram_2/dependencies b/Voronoi_diagram_2/doc/Voronoi_diagram_2/dependencies index 8cd9d01cbec..e89d9d8be77 100644 --- a/Voronoi_diagram_2/doc/Voronoi_diagram_2/dependencies +++ b/Voronoi_diagram_2/doc/Voronoi_diagram_2/dependencies @@ -7,3 +7,4 @@ Stream_support Triangulation_2 Segment_Delaunay_graph_2 Apollonius_graph_2 +GraphicsView diff --git a/Voronoi_diagram_2/doc/Voronoi_diagram_2/examples.txt b/Voronoi_diagram_2/doc/Voronoi_diagram_2/examples.txt index 059a4823bc2..2c2e063da4c 100644 --- a/Voronoi_diagram_2/doc/Voronoi_diagram_2/examples.txt +++ b/Voronoi_diagram_2/doc/Voronoi_diagram_2/examples.txt @@ -1,4 +1,5 @@ /*! \example Voronoi_diagram_2/vd_2_point_location.cpp \example Voronoi_diagram_2/vd_2_point_location_sdg_linf.cpp +\example Voronoi_diagram_2/draw_voronoi_diagram_2.cpp */ diff --git a/Voronoi_diagram_2/doc/Voronoi_diagram_2/fig/draw_voronoi_diagram.png b/Voronoi_diagram_2/doc/Voronoi_diagram_2/fig/draw_voronoi_diagram.png new file mode 100644 index 00000000000..b48e63207a5 Binary files /dev/null and b/Voronoi_diagram_2/doc/Voronoi_diagram_2/fig/draw_voronoi_diagram.png differ diff --git a/Voronoi_diagram_2/examples/Voronoi_diagram_2/CMakeLists.txt b/Voronoi_diagram_2/examples/Voronoi_diagram_2/CMakeLists.txt index 2741d391aec..775a3faf64c 100644 --- a/Voronoi_diagram_2/examples/Voronoi_diagram_2/CMakeLists.txt +++ b/Voronoi_diagram_2/examples/Voronoi_diagram_2/CMakeLists.txt @@ -6,7 +6,11 @@ cmake_minimum_required(VERSION 3.1...3.15) project( Voronoi_diagram_2_Examples ) -find_package(CGAL QUIET) +find_package(CGAL COMPONENTS Qt5) + +if(CGAL_Qt5_FOUND) + add_definitions(-DCGAL_USE_BASIC_VIEWER -DQT_NO_KEYWORDS) +endif() if ( CGAL_FOUND ) @@ -16,6 +20,11 @@ if ( CGAL_FOUND ) create_single_source_cgal_program( "${cppfile}" ) endforeach() + if(CGAL_Qt5_FOUND ) + target_link_libraries(draw_voronoi_diagram_2 PUBLIC CGAL::CGAL_Qt5) + endif() + + else() message(STATUS "This program requires the CGAL library, and will not be compiled.") diff --git a/Voronoi_diagram_2/examples/Voronoi_diagram_2/data/data4.dt.cin b/Voronoi_diagram_2/examples/Voronoi_diagram_2/data/data4.dt.cin new file mode 100644 index 00000000000..4f0d7b4565e --- /dev/null +++ b/Voronoi_diagram_2/examples/Voronoi_diagram_2/data/data4.dt.cin @@ -0,0 +1,10 @@ +0 0 +100 0 +100 100 +0 100 +200 0 +300 0 +350 0 +150 150 +100 150 +300 325 diff --git a/Voronoi_diagram_2/examples/Voronoi_diagram_2/draw_voronoi_diagram_2.cpp b/Voronoi_diagram_2/examples/Voronoi_diagram_2/draw_voronoi_diagram_2.cpp new file mode 100644 index 00000000000..faa24a70034 --- /dev/null +++ b/Voronoi_diagram_2/examples/Voronoi_diagram_2/draw_voronoi_diagram_2.cpp @@ -0,0 +1,37 @@ +// standard includes +#include + +// includes for drawing the Voronoi Diagram +#include +#include +#include +#include +#include +#include + +// typedefs for defining the adaptor +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef CGAL::Delaunay_triangulation_2 DT; +typedef CGAL::Delaunay_triangulation_adaptation_traits_2
AT; +typedef CGAL::Delaunay_triangulation_caching_degeneracy_removal_policy_2
AP; +typedef CGAL::Voronoi_diagram_2 VD; + +// typedef for the result type of the point location +typedef AT::Site_2 Site_2; + +int main() +{ + VD vd; + std::ifstream ifs("data/data4.dt.cin"); + assert(ifs); + + Site_2 t; + while ( ifs >> t ) { vd.insert(t); } + ifs.close(); + + assert( vd.is_valid() ); + + CGAL::draw(vd); + + return EXIT_SUCCESS; +} diff --git a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h new file mode 100644 index 00000000000..5e32e12d3d4 --- /dev/null +++ b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h @@ -0,0 +1,335 @@ +// Copyright(c) 2019 Foundation for Research and Technology-Hellas (Greece). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// Author(s) : Jasmeet Singh + +#ifndef CGAL_DRAW_VORONOI_DIAGRAM_2_H +#define CGAL_DRAW_VORONOI_DIAGRAM_2_H + +#include +#include + +#ifdef CGAL_USE_BASIC_VIEWER + +#include +#include +#include +#include +#include +#include +#include + +namespace CGAL { + +// Default color functor; user can change it to have its own face color +struct DefaultColorFunctorV2 +{ + template + static CGAL::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::Color(73, 250, 117); + } +}; + +// Viewer for Voronoi diagram +template +class SimpleVoronoiDiagram2ViewerQt : public Basic_viewer_qt +{ + 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; + + typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; + +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::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) + { + 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)); + add_ray(he->source()->point(), direction, CGAL::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); + add_line(pointOnLine, direction); + } + } + + void compute_face(Face_const_handle fh) + { + CGAL::Color c = m_fcolor.run(v2, fh); + + 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; +}; + +// Specialization of draw function. +#define CGAL_VORONOI_TYPE CGAL::Voronoi_diagram_2 + +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) { + int argc = 1; + const char *argv[2] = {"voronoi_2_viewer", "\0"}; + 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(); + } +} + +} // End namespace CGAL + +#endif // CGAL_USE_BASIC_VIEWER + +#endif // CGAL_DRAW_VORONOI_DIAGRAM_2_H diff --git a/Voronoi_diagram_2/package_info/Voronoi_diagram_2/dependencies b/Voronoi_diagram_2/package_info/Voronoi_diagram_2/dependencies index 59ff755db76..47ba473b701 100644 --- a/Voronoi_diagram_2/package_info/Voronoi_diagram_2/dependencies +++ b/Voronoi_diagram_2/package_info/Voronoi_diagram_2/dependencies @@ -1,6 +1,7 @@ Algebraic_foundations Apollonius_graph_2 Circulator +GraphicsView Hash_map Installation Interval_support