mirror of https://github.com/CGAL/cgal
198 lines
5.8 KiB
C++
198 lines
5.8 KiB
C++
// Copyright (c) 2018-2020 GeometryFactory (France)
|
|
// All rights reserved.
|
|
//
|
|
// This file is part of CGAL (www.cgal.org).
|
|
//
|
|
// $URL$
|
|
// $Id$
|
|
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
|
|
//
|
|
// Author(s) : Guillaume Damiand <guillaume.damiand@liris.cnrs.fr>
|
|
// Laurent Rineau <laurent.rineau@cgal.org>
|
|
|
|
#ifndef CGAL_DRAW_FACE_GRAPH_H
|
|
#define CGAL_DRAW_FACE_GRAPH_H
|
|
|
|
#ifdef CGAL_USE_BASIC_VIEWER
|
|
|
|
#include <CGAL/Dynamic_property_map.h>
|
|
#include <CGAL/Random.h>
|
|
#include <CGAL/boost/graph/helpers.h>
|
|
|
|
namespace CGAL
|
|
{
|
|
|
|
// Default color functor; user can change it to have its own face color
|
|
struct DefaultColorFunctorFaceGraph
|
|
{
|
|
template<typename Graph>
|
|
CGAL::IO::Color operator()(const Graph&,
|
|
typename boost::graph_traits<Graph>::face_descriptor fh) const
|
|
{
|
|
if (fh==boost::graph_traits<Graph>::null_face()) // use to get the mono color
|
|
return CGAL::IO::Color(100, 125, 200); // R G B between 0-255
|
|
|
|
return get_random_color(CGAL::get_default_random());
|
|
}
|
|
};
|
|
|
|
class SimpleFaceGraphViewerQt : public Basic_viewer_qt
|
|
{
|
|
using Base = Basic_viewer_qt;
|
|
|
|
public:
|
|
SimpleFaceGraphViewerQt(QWidget* parent) :
|
|
Base(parent, "", false, true, true, true, false),
|
|
m_compute_elements_impl([]{})
|
|
{
|
|
}
|
|
|
|
/// Construct the viewer.
|
|
/// @param amesh the surface mesh 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)
|
|
template <typename SM>
|
|
SimpleFaceGraphViewerQt(QWidget* parent,
|
|
const SM& amesh,
|
|
const char* title="Basic Surface_mesh Viewer",
|
|
bool anofaces=false) :
|
|
SimpleFaceGraphViewerQt(parent, amesh, title, anofaces, DefaultColorFunctorFaceGraph())
|
|
{
|
|
}
|
|
|
|
template <typename SM, typename ColorFunctor>
|
|
SimpleFaceGraphViewerQt(QWidget* parent,
|
|
const SM& amesh,
|
|
const char* title,
|
|
bool anofaces,
|
|
ColorFunctor fcolor) :
|
|
// First draw: no vertex; edges, faces; mono-color; inverse normal
|
|
Base(parent, title, false, true, true, true, false),
|
|
m_compute_elements_impl(compute_elements_functor(amesh, anofaces, fcolor))
|
|
{
|
|
}
|
|
|
|
void init() override {
|
|
compute_elements();
|
|
Base::init();
|
|
}
|
|
|
|
void compute_elements() {
|
|
m_compute_elements_impl();
|
|
}
|
|
|
|
template <typename SM, typename ColorFunctor>
|
|
void set_face_graph(const SM& amesh,
|
|
bool anofaces,
|
|
ColorFunctor fcolor) {
|
|
m_compute_elements_impl = compute_elements_functor(amesh, anofaces, fcolor);
|
|
}
|
|
|
|
template <typename SM, typename ColorFunctor>
|
|
void set_face_graph(const SM& amesh,
|
|
bool anofaces=false) {
|
|
set_mesh(amesh, anofaces, DefaultColorFunctorFaceGraph());
|
|
}
|
|
protected:
|
|
template <typename SM, typename ColorFunctor>
|
|
std::function<void()>
|
|
compute_elements_functor(const SM& sm,
|
|
bool anofaces,
|
|
ColorFunctor fcolor)
|
|
{
|
|
using Point =
|
|
typename boost::property_map_value<SM, CGAL::vertex_point_t>::type;
|
|
using Kernel = typename CGAL::Kernel_traits<Point>::Kernel;
|
|
using Vector = typename Kernel::Vector_3;
|
|
|
|
auto vnormals = get(CGAL::dynamic_vertex_property_t<Vector>(), sm);
|
|
auto point_pmap = get(CGAL::vertex_point, sm);
|
|
for (auto v : vertices(sm))
|
|
{
|
|
Vector n(NULL_VECTOR);
|
|
int i=0;
|
|
for (auto h : halfedges_around_target(halfedge(v, sm), sm))
|
|
{
|
|
if (!is_border(h, sm))
|
|
{
|
|
Vector ni = CGAL::cross_product(
|
|
Vector(get(point_pmap, source(h, sm)), get(point_pmap, target(h, sm))),
|
|
Vector(get(point_pmap, target(h, sm)), get(point_pmap, target(next(h, sm), sm))));
|
|
if (ni != NULL_VECTOR)
|
|
{
|
|
n+=ni;
|
|
++i;
|
|
}
|
|
}
|
|
}
|
|
put(vnormals, v, n/i);
|
|
}
|
|
|
|
// This function return a lambda expression, type-erased in a
|
|
// `std::function<void()>` object.
|
|
return [this, &sm, vnormals, anofaces, fcolor, point_pmap]()
|
|
{
|
|
this->clear();
|
|
|
|
if (!anofaces)
|
|
{
|
|
for (auto fh: faces(sm))
|
|
{
|
|
if (fh!=boost::graph_traits<SM>::null_face())
|
|
{
|
|
CGAL::IO::Color c=fcolor(sm, fh);
|
|
face_begin(c);
|
|
auto hd=halfedge(fh, sm);
|
|
const auto first_hd = hd;
|
|
do
|
|
{
|
|
auto v = source(hd, sm);
|
|
add_point_in_face(get(point_pmap, v), get(vnormals, v));
|
|
hd=next(hd, sm);
|
|
}
|
|
while(hd!=first_hd);
|
|
face_end();
|
|
}
|
|
}
|
|
}
|
|
|
|
for (auto e: edges(sm))
|
|
{
|
|
add_segment(get(point_pmap, source(halfedge(e, sm), sm)),
|
|
get(point_pmap, target(halfedge(e, sm), sm)));
|
|
}
|
|
|
|
for (auto v: vertices(sm))
|
|
{
|
|
this->add_point(get(point_pmap, v));
|
|
}
|
|
};
|
|
}
|
|
|
|
void keyPressEvent(QKeyEvent *e) override
|
|
{
|
|
// 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:
|
|
std::function<void()> m_compute_elements_impl;
|
|
};
|
|
|
|
} // End namespace CGAL
|
|
|
|
#endif // CGAL_USE_BASIC_VIEWER
|
|
|
|
#endif // CGAL_DRAW_SURFACE_MESH_H
|