Applied new APIs version in Voronoi 2, with modifications in Basic_viewer_qt.

This commit is contained in:
Mostafa-ashraf19 2022-10-06 17:48:58 +02:00
parent 7404eb629f
commit cc4aa7cd9d
2 changed files with 266 additions and 268 deletions

View File

@ -399,7 +399,6 @@ public:
update(); update();
} }
protected:
// Shortcuts to simplify function calls. // Shortcuts to simplify function calls.
template<typename KPoint> template<typename KPoint>
static Local_point get_local_point(const KPoint& p) static Local_point get_local_point(const KPoint& p)
@ -414,6 +413,7 @@ protected:
get_local_vector(v); get_local_vector(v);
} }
protected:
void compile_shaders() void compile_shaders()
{ {
rendering_program_face.removeAllShaders(); rendering_program_face.removeAllShaders();

View File

@ -8,10 +8,13 @@
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
// //
// Author(s) : Jasmeet Singh <jasmeet.singh.mec11@iitbhu.ac.in> // Author(s) : Jasmeet Singh <jasmeet.singh.mec11@iitbhu.ac.in>
// Mostafa Ashraf <mostaphaashraf1996@gmail.com>
#ifndef CGAL_DRAW_VORONOI_DIAGRAM_2_H #ifndef CGAL_DRAW_VORONOI_DIAGRAM_2_H
#define CGAL_DRAW_VORONOI_DIAGRAM_2_H #define CGAL_DRAW_VORONOI_DIAGRAM_2_H
#include <CGAL/Graphic_buffer.h>
#include <CGAL/Drawing_functor.h>
#include <CGAL/Qt/Basic_viewer_qt.h> #include <CGAL/Qt/Basic_viewer_qt.h>
#include <CGAL/license/Voronoi_diagram_2.h> #include <CGAL/license/Voronoi_diagram_2.h>
@ -28,306 +31,301 @@
namespace CGAL { namespace CGAL {
// Default color functor; user can change it to have its own face color namespace draw_function_for_v2
struct DefaultColorFunctorV2
{ {
template <typename V2>
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 typedef CGAL::Exact_predicates_inexact_constructions_kernel Local_kernel;
template <class V2, class ColorFunctor> typedef Local_kernel::Point_3 Local_point;
class SimpleVoronoiDiagram2ViewerQt : public Basic_viewer_qt typedef Local_kernel::Vector_3 Local_vector;
template <typename BufferType = float, class V2>
void compute_vertex(typename V2::Vertex_iterator vh, CGAL::Graphic_buffer<BufferType> &graphic_buffer) {
graphic_buffer.add_point(vh->point());
}
template <typename BufferType = float, class V2>
void compute_dual_vertex(typename V2::Delaunay_graph::Finite_vertices_iterator vi, CGAL::Graphic_buffer<BufferType> &graphic_buffer)
{ {
typedef Basic_viewer_qt Base; graphic_buffer.add_point(vi->point(), CGAL::IO::Color(50, 100, 180));
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;
template <typename BufferType = float, class V2>
void add_segments_and_update_bounding_box(typename V2::Halfedge_handle he, CGAL::Graphic_buffer<BufferType> &graphic_buffer)
{
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef typename V2::Delaunay_vertex_handle Delaunay_vertex_const_handle;
public: if (he->is_segment()) {
/// Construct the viewer. graphic_buffer.add_segment(he->source()->point(), he->target()->point());
/// @param av2 the voronoi diagram to view } else {
/// @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)
{
Delaunay_vertex_const_handle v1 = he->up(); Delaunay_vertex_const_handle v1 = he->up();
Delaunay_vertex_const_handle v2 = he->down(); Delaunay_vertex_const_handle v2 = he->down();
Kernel::Vector_2 direction(v1->point().y() - v2->point().y(), 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()) { if (he->is_ray()) {
Kernel::Point_2 end_point;
if (he->has_source()) { if (he->has_source()) {
// add_ray_segment(he->source()->point(), get_second_point(he)); end_point = he->source()->point();
add_ray(he->source()->point(), direction, CGAL::IO::Color(100, 0, 0));
// 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()) { } else if (he->is_bisector()) {
Kernel::Point_2 pointOnLine((v1->point().x() + v2->point().x()) / 2, Kernel::Point_2 pointOnLine((v1->point().x() + v2->point().x()) / 2,
(v1->point().y() + v2->point().y()) / 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 <class V2>
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 <typename BufferType = float, class V2>
void compute_rays_and_bisectors(typename V2::Halfedge_iterator he, CGAL::Graphic_buffer<BufferType> &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 <typename BufferType = float, class V2, class DrawingFunctor>
void compute_face(typename V2::Face_iterator fh, const V2& v2, CGAL::Graphic_buffer<BufferType> &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 <typename BufferType = float, class V2, class DrawingFunctor>
void compute_elements(const V2& v2, CGAL::Graphic_buffer<BufferType> &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<BufferType, V2>(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<BufferType, V2>(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<BufferType, V2>(it, graphic_buffer);
}
for (typename V2::Halfedge_iterator it = v2.halfedges_begin();
it != v2.halfedges_end(); ++it) {
compute_rays_and_bisectors<BufferType, V2>(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 <typename BufferType = float, class V2, class DrawingFunctor>
void add_in_graphic_buffer(const V2 &v2, CGAL::Graphic_buffer<BufferType> &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 <typename BufferType = float, class V2>
void add_in_graphic_buffer(const V2 &v2, CGAL::Graphic_buffer<BufferType> &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<V2, typename V2::Vertex_iterator,
typename V2::Halfedge_iterator,
typename V2::Face_iterator>
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(); add_in_graphic_buffer(v2, graphic_buffer, drawing_functor, m_nofaces, m_draw_voronoi_vertices, m_draw_dual_vertices);
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. // Specialization of draw function.
#define CGAL_VORONOI_TYPE CGAL::Voronoi_diagram_2 <DG, AT, AP> #define CGAL_VORONOI_TYPE CGAL::Voronoi_diagram_2 <DG, AT, AP>
template<class DG, template<class DG,
class AT, class AT,
class AP> 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<BufferType> buffer;
add_in_graphic_buffer(av2, buffer, drawing_functor, nofill, draw_voronoi_vertices, draw_dual_vertices);
draw_buffer(buffer);
}
template<class DG,
class AT,
class AP, typename BufferType = float>
void draw(const CGAL_VORONOI_TYPE &av2, void draw(const CGAL_VORONOI_TYPE &av2,
const char *title="2D Voronoi Diagram Basic Viewer", const char *title="2D Voronoi Diagram Basic Viewer",
bool nofill = false, bool nofill = false,
bool draw_voronoi_vertices = true, bool draw_voronoi_vertices = true,
bool draw_dual_vertices = true) bool draw_dual_vertices = true)
{ {
#if defined(CGAL_TEST_SUITE) CGAL::Graphic_buffer<BufferType> buffer;
bool cgal_test_suite = true; add_in_graphic_buffer(av2, buffer, nofill, draw_voronoi_vertices, draw_dual_vertices);
#else draw_buffer(buffer);
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<char **>(argv));
DefaultColorFunctorV2 fcolor;
SimpleVoronoiDiagram2ViewerQt<CGAL_VORONOI_TYPE, DefaultColorFunctorV2>
mainwindow(app.activeWindow(), av2, title, nofill,
draw_voronoi_vertices, draw_dual_vertices, fcolor);
mainwindow.show();
app.exec();
}
} }
} // End namespace CGAL } // End namespace CGAL