Improve basic viewer for face graph with paths, and convertion between handle and descriptor.

This commit is contained in:
Guillaume Damiand 2020-04-09 17:44:25 +02:00
parent 02bc93a84d
commit de6030aa78
5 changed files with 198 additions and 115 deletions

View File

@ -19,7 +19,7 @@ static unsigned int seed; // Use the same seed for all the tests
///////////////////////////////////////////////////////////////////////////////
template<class FaceGraph>
void test(const FaceGraph& mesh, bool draw)
void test(const FaceGraph& mesh, bool draw, const char* title)
{
CGAL::Random random(seed);
Curves_on_surface_topology<FaceGraph> cst(mesh);
@ -30,14 +30,14 @@ void test(const FaceGraph& mesh, bool draw)
Path_on_surface<FaceGraph> p2(mesh); // A second path
p2.generate_random_closed_path(10, random);
bool res1=cst.is_contractible(p1);
bool res1=cst.is_contractible(p1, true);
std::cout<<"Path p1 "<<(res1?"IS":"IS NOT")<<" contractible."<<std::endl;
bool res2=cst.are_freely_homotopic(p1, p2);
bool res2=cst.are_freely_homotopic(p1, p2, true);
std::cout<<"Path p1 "<<(res2?"IS":"IS NOT")<<" homotopic with path p2."<<std::endl;
if (draw)
{ CGAL::draw(mesh, {p1, p2}); }
{ CGAL::draw(mesh, {p1, p2}, title); }
}
///////////////////////////////////////////////////////////////////////////////
int main(int argc, char** argv)
@ -53,7 +53,7 @@ int main(int argc, char** argv)
std::cout<<"ERROR reading file "<<file<<" for linear cell complex."<<std::endl;
exit(EXIT_FAILURE);
}
test(lcc, draw);
test(lcc, draw, "Linear cell complex for combinatorial map");
}
{
@ -63,7 +63,7 @@ int main(int argc, char** argv)
std::cout<<"ERROR reading file "<<file<<" for polyhedron."<<std::endl;
exit(EXIT_FAILURE);
}
test(p, draw);
test(p, draw, "Polyhedron");
}
{
@ -73,7 +73,7 @@ int main(int argc, char** argv)
std::cout<<"ERROR reading file "<<file<<" for surface mesh."<<std::endl;
exit(EXIT_FAILURE);
}
test(sm, draw);
test(sm, draw, "Surface mesh");
}
return EXIT_SUCCESS;

View File

@ -447,17 +447,14 @@ public:
{ return num_halfedges(mmap.get_fg()); }
bool is_used(size_type i) const
{
for (typename boost::template graph_traits<typename Self::HEG>::halfedge_iterator
it=halfedges(mmap.get_fg()).begin(),
itend=halfedges(mmap.get_fg()).end(); it!=itend; ++it)
{
if (i==0) { return !is_border(*it, mmap.get_fg()); }
--i;
}
return false;
}
{ return internal::Is_index_used<HEG>::run(mmap.get_fg(), i); }
std::size_t index(const_iterator it) const
{
return internal::Index_from_halfedge_descriptor<HEG>::
run(mmap.get_fg(), *it);
}
private:
const Self & mmap;
mutable typename Self::size_type msize;
@ -496,28 +493,12 @@ public:
Dart_handle dart_handle(size_type i)
{
CGAL_assertion(darts().is_used(i));
for (typename boost::template graph_traits<typename Self::HEG>::halfedge_iterator
it=halfedges(get_fg()).begin(),
itend=halfedges(get_fg()).end(); it!=itend; ++it)
{
if (i==0) { return *it; }
--i;
}
CGAL_assertion(false);
return Dart_handle();
return internal::Halfedge_descriptor_from_index<HEG>::run(get_fg(), i);
}
Dart_const_handle dart_handle(size_type i) const
{
CGAL_assertion(darts().is_used(i));
for (typename boost::template graph_traits<typename Self::HEG>::halfedge_iterator
it=halfedges(get_fg()).begin(),
itend=halfedges(get_fg()).end(); it!=itend; ++it)
{
if (i==0) { return *it; }
--i;
}
CGAL_assertion(false);
return Dart_const_handle();
return internal::Halfedge_descriptor_from_index<HEG>::run(get_fg(), i);
}
template <unsigned int i>

View File

@ -16,34 +16,22 @@
#include <boost/graph/graph_traits.hpp>
#include <CGAL/boost/graph/helpers.h>
#include <CGAL/Surface_mesh_topology/internal/Iterators_for_face_graph_wrapper.h>
////////////////////////////////////////////////////////////////////////////////
/** This file contains the following functors for Face_graph_wrapper:
* Is_free<typename HEG, unsigned int i>::
operator() (const HEG& heg, Dart_const_handle dh)
* Get_beta<typename HEG, unsigned int i>::
operator() (const HEG& heg, Dart_const_handle dh)
* Index_from_halfedge_descriptor<Mesh>::run(m, h)
* Halfedge_descriptor_from_index<Mesh>::run(m, i)
* Is_index_used<Mesh>::run(m, i)
*/
////////////////////////////////////////////////////////////////////////////////
namespace CGAL {
////////////////////////////////////////////////////////////////////////////////
template<typename P>
class Surface_mesh;
////////////////////////////////////////////////////////////////////////////////
namespace internal {
/// Is_free
//template<typename HEG, unsigned int i>
//struct Is_free
//{
// typedef typename boost::graph_traits<HEG>::halfedge_descriptor Dart_const_handle;
// static bool value(const HEG& /*heg*/, Dart_const_handle /*dh*/)
// { CGAL_static_assertion(i==0 || i==1); return false; }
//};
//template<typename HEG>
//struct Is_free<HEG, 2>
//{
// typedef typename boost::graph_traits<HEG>::halfedge_descriptor Dart_const_handle;
// static bool value(const HEG& heg, Dart_const_handle dh)
// { return is_border(opposite(dh, heg), heg); }
//};
////////////////////////////////////////////////////////////////////////////////
/// Get_beta
template<typename HEG, unsigned int i>
@ -52,7 +40,7 @@ struct Get_beta
typedef typename boost::graph_traits<HEG>::halfedge_descriptor Dart_const_handle;
static Dart_const_handle value(const HEG& /*heg*/, Dart_const_handle /*dh*/)
{ /* CGAL_static_assertion(false);*/
{
std::cout<<"ERROR Get_beta<HEG, "<<i<<">"<<std::endl;
CGAL_assertion(false);
return nullptr;
@ -77,11 +65,82 @@ struct Get_beta<HEG, 2>
{
typedef typename boost::graph_traits<HEG>::halfedge_descriptor Dart_const_handle;
static Dart_const_handle value(const HEG& heg, Dart_const_handle dh)
{
//if (Is_free<HEG, 2>::value(heg, dh)) return Dart_const_handle();
return opposite(dh, heg);
{ return opposite(dh, heg); }
};
////////////////////////////////////////////////////////////////////////////////
template<typename Mesh>
struct Index_from_halfedge_descriptor
{
typedef boost::uint32_t size_type;
typedef typename boost::template graph_traits<Mesh>::halfedge_descriptor
halfedge_descriptor;
static size_type run(const Mesh& m, halfedge_descriptor h)
{ std::cout<<"V1"<<std::endl;
size_type res=0;
for (typename boost::template graph_traits<Mesh>::halfedge_iterator
it=halfedges(m).begin(), itend=halfedges(m).end(); it!=itend; ++it, ++res)
{ if ((*it)==h) { return res; } }
return (std::numeric_limits<size_type>::max)();
}
};
template<typename P>
struct Index_from_halfedge_descriptor<CGAL::Surface_mesh<P> >
{
using Mesh=CGAL::Surface_mesh<P>;
typedef boost::uint32_t size_type;
typedef typename boost::template graph_traits<Mesh>::halfedge_descriptor
halfedge_descriptor;
static size_type run(const Mesh& /*m*/, halfedge_descriptor h)
{ std::cout<<"V2"<<std::endl; return (size_type)(h); }
};
////////////////////////////////////////////////////////////////////////////////
template<typename Mesh>
struct Halfedge_descriptor_from_index
{
typedef boost::uint32_t size_type;
typedef typename boost::template graph_traits<Mesh>::halfedge_descriptor
halfedge_descriptor;
static halfedge_descriptor run(const Mesh& m, size_type i)
{
for (typename boost::template graph_traits<Mesh>::halfedge_iterator
it=halfedges(m).begin(), itend=halfedges(m).end(); it!=itend; ++it, --i)
{ if (i==0) { return *it; } }
return halfedge_descriptor(nullptr);
}
};
template<typename P>
struct Halfedge_descriptor_from_index<CGAL::Surface_mesh<P> >
{
using Mesh=CGAL::Surface_mesh<P>;
typedef boost::uint32_t size_type;
typedef typename boost::template graph_traits<Mesh>::halfedge_descriptor
halfedge_descriptor;
static halfedge_descriptor run(const Mesh& /*m*/, size_type i)
{ std::cout<<"V2"<<std::endl; return halfedge_descriptor(i); }
};
////////////////////////////////////////////////////////////////////////////////
template<typename Mesh>
struct Is_index_used
{
typedef boost::uint32_t size_type;
static bool run(const Mesh& m, size_type i)
{ return i<m.size_of_halfedges(); }
};
template<typename P>
struct Is_index_used<CGAL::Surface_mesh<P> >
{
using Mesh=CGAL::Surface_mesh<P>;
typedef boost::uint32_t size_type;
static bool run(const Mesh& m, size_type i)
{ return i<(m.number_of_halfedges()+m.number_of_removed_halfedges()) &&
!m.is_removed(typename Mesh::Halfedge_index(i)); }
};
////////////////////////////////////////////////////////////////////////////////
} // namespace internal
} // namespace CGAL

View File

@ -16,6 +16,7 @@
#include <boost/graph/graph_traits.hpp>
#include <CGAL/boost/graph/helpers.h>
#include <CGAL/Surface_mesh_topology/internal/Functors_for_face_graph_wrapper.h>
#include <stack>
namespace CGAL {
@ -40,11 +41,7 @@ namespace internal {
FGW_dart_iterator_basic_of_all(const Map& amap):
mmap(amap),
m_it(halfedges(amap.get_fg()).begin())
{
/*if (m_it!=halfedges(amap.get_fg()).end() &&
is_border(*m_it, amap.get_fg()))
{ operator++(0); } */
}
{}
/// Constructor with a dart in parameter (for end iterator).
FGW_dart_iterator_basic_of_all(const Map& amap, Dart_handle /*adart*/):
@ -57,6 +54,12 @@ namespace internal {
m_it(other.m_it)
{}
Self& operator=(const Self& other)
{
CGAL_assertion(&mmap==&(other.mmap));
m_it=other.m_it;
}
operator Dart_handle() const
{ return operator*(); }
@ -70,14 +73,7 @@ namespace internal {
Self& operator++()
{
CGAL_assertion(m_it!=halfedges(this->mmap.get_fg()).end());
//do
{
++m_it;
}
/*while(m_it!=halfedges(this->mmap.get_fg()).end() &&
is_border(*m_it, this->mmap.get_fg())); */
++m_it;
return *this;
}
@ -85,6 +81,19 @@ namespace internal {
Self operator++(int)
{ Self res=*this; operator ++(); return res; }
/// Prefix -- operator.
Self& operator--()
{
CGAL_assertion(m_it!=halfedges(this->mmap.get_fg()).begin());
--m_it;
return *this;
}
/// Postfix -- operator.
Self operator--(int)
{ Self res=*this; operator --(); return res; }
Dart_handle operator*() const
{
CGAL_assertion(m_it!=halfedges(this->mmap.get_fg()).end());

View File

@ -85,11 +85,11 @@ struct LCC_geom_utils<CGAL::Face_graph_wrapper<Mesh>, Local_kernel, 3>
template<class Mesh, class DrawingFunctorLCC>
class Face_graph_with_path_viewer : public Basic_viewer_qt
{
typedef Basic_viewer_qt Base;
typedef typename Get_map<Mesh, Mesh>::type LCC;
typedef typename LCC::Dart_const_handle Dart_const_handle;
typedef Basic_viewer_qt Base;
typedef typename Get_map<Mesh, Mesh>::type LCC;
typedef typename LCC::Dart_const_handle Dart_const_handle;
typedef typename CGAL::Get_traits<Mesh>::Kernel Kernel;
typedef typename CGAL::Get_traits<Mesh>::Point Point;
typedef typename CGAL::Get_traits<Mesh>::Point Point;
typedef typename CGAL::Get_traits<Mesh>::Vector Vector;
public:
@ -114,13 +114,11 @@ public:
m_drawing_functor(drawing_functor),
m_paths(paths),
m_current_path(m_paths->size()),
m_current_dart(0),
m_current_dart(lcc.darts().end()),
m_draw_marked_darts(true),
m_amark(amark==std::numeric_limits<std::size_t>::max()?
LCC::INVALID_MARK:amark)
{
m_current_dart=lcc.number_of_darts(); compute_elements();
}
{ compute_elements(); }
protected:
@ -135,18 +133,15 @@ protected:
typename LCC::size_type markedges = lcc.get_new_mark();
typename LCC::size_type markvertices = lcc.get_new_mark();
if (m_current_dart!=lcc.number_of_darts())
if (m_current_dart!=lcc.darts().end())
{ // We want to draw only one dart
if (lcc.darts().is_used(m_current_dart))
{
Dart_const_handle selected_dart=lcc.dart_handle(m_current_dart);
compute_edge(selected_dart, CGAL::Color(255,0,0));
lcc.template mark_cell<1>(selected_dart, markedges);
compute_vertex(selected_dart);
Dart_const_handle selected_dart=m_current_dart; //lcc.dart_handle(m_current_dart);
compute_edge(selected_dart, CGAL::Color(255,0,0));
lcc.template mark_cell<1>(selected_dart, markedges);
compute_vertex(selected_dart);
if ( !m_nofaces )
{ compute_face(selected_dart); }
}
if ( !m_nofaces )
{ compute_face(selected_dart); }
for (typename LCC::Dart_range::const_iterator it=lcc.darts().begin(),
itend=lcc.darts().end(); it!=itend; ++it )
@ -251,38 +246,58 @@ protected:
void compute_vertex(Dart_const_handle dh)
{ add_point(get_point(dh)); }
virtual void init()
{
Base::init();
setKeyDescription(::Qt::Key_D, "Increase current dart drawing");
setKeyDescription(::Qt::Key_D+::Qt::ControlModifier, "Decrease current dart drawing");
setKeyDescription(::Qt::Key_D+::Qt::ShiftModifier, "Draw all darts");
setKeyDescription(::Qt::Key_X, "Toggles marked darts display");
setKeyDescription(::Qt::Key_P, "Increase current path drawing");
setKeyDescription(::Qt::Key_P+::Qt::ControlModifier, "Decrease current path drawing");
setKeyDescription(::Qt::Key_P+::Qt::ShiftModifier, "Draw all paths");
}
virtual void keyPressEvent(QKeyEvent *e)
{
const ::Qt::KeyboardModifiers modifiers = e->modifiers();
if ((e->key()==::Qt::Key_D) && (modifiers==::Qt::NoButton))
{
m_current_dart=(m_current_dart+1)%(lcc.number_of_darts()+1);
if (m_current_dart==lcc.number_of_darts())
{
displayMessage(QString("Draw all darts."));
}
if (m_current_dart==lcc.darts().end())
{ m_current_dart=lcc.darts().begin(); }
else
{
displayMessage(QString("Draw dart=%1.").arg((m_current_dart)));
}
{ ++m_current_dart; }
if (m_current_dart==lcc.darts().end())
{ displayMessage(QString("Draw all darts.")); }
else
{ displayMessage(QString("Draw dart=%1.").arg(lcc.darts().index(m_current_dart))); }
compute_elements();
redraw();
}
else if ((e->key()==::Qt::Key_M) && (modifiers==::Qt::NoButton))
else if ((e->key()==::Qt::Key_D) && (modifiers==::Qt::ControlModifier))
{
m_draw_marked_darts=!m_draw_marked_darts;
if (m_draw_marked_darts)
{ displayMessage(QString("Draw marked darts in blue.")); }
if (m_current_dart==lcc.darts().begin())
{ m_current_dart=lcc.darts().end(); }
else
{
displayMessage(QString("Do not draw marked darts in different color."));
}
{ --m_current_dart; }
if (m_current_dart==lcc.darts().end())
{ displayMessage(QString("Draw all darts.")); }
else
{ displayMessage(QString("Draw dart=%1.").arg(lcc.darts().index(m_current_dart))); }
compute_elements();
redraw();
}
else if ((e->key()==::Qt::Key_N) && (modifiers==::Qt::NoButton))
else if ((e->key()==::Qt::Key_D) && (modifiers==::Qt::ShiftModifier))
{
m_current_dart=lcc.darts().end();
displayMessage(QString("Draw all darts."));
compute_elements();
redraw();
}
else if ((e->key()==::Qt::Key_P) && (modifiers==::Qt::NoButton))
{
m_current_path=(m_current_path+1)%(m_paths->size()+2);
if (m_current_path==m_paths->size())
@ -296,17 +311,36 @@ protected:
compute_elements();
redraw();
}
else if ((e->key()==::Qt::Key_P) && (modifiers==::Qt::NoButton))
else if ((e->key()==::Qt::Key_P) && (modifiers==::Qt::ControlModifier))
{
m_current_dart=(m_current_dart==0?lcc.number_of_darts():
m_current_dart-1);
if (m_current_dart==lcc.number_of_darts())
{
displayMessage(QString("Draw all darts."));
}
m_current_path=(m_current_path==0?m_paths->size()+1:m_current_path-1);
if (m_current_path==m_paths->size())
{ displayMessage(QString("Draw all paths.")); }
else if (m_current_path==m_paths->size()+1)
{ displayMessage(QString("Do not draw paths.")); }
else
{ displayMessage(QString("Draw path=%1, nb_darts=%2.").
arg(m_current_path).
arg((*m_paths)[m_current_path].length())); }
compute_elements();
redraw();
}
else if ((e->key()==::Qt::Key_P) && (modifiers==::Qt::ShiftModifier))
{
m_current_path=m_paths->size();
displayMessage(QString("Draw all paths."));
compute_elements();
redraw();
}
else if ((e->key()==::Qt::Key_X) && (modifiers==::Qt::NoButton))
{
m_draw_marked_darts=!m_draw_marked_darts;
if (m_draw_marked_darts)
{ displayMessage(QString("Draw marked darts in blue.")); }
else
{
displayMessage(QString("Draw dart=%1.").arg((m_current_dart)));
displayMessage(QString("Do not draw marked darts in different color."));
}
compute_elements();
redraw();
@ -341,7 +375,7 @@ protected:
const DrawingFunctorLCC& m_drawing_functor;
const std::vector<Surface_mesh_topology::Path_on_surface<Mesh> >* m_paths;
std::size_t m_current_path;
std::size_t m_current_dart;
typename LCC::Dart_range::const_iterator m_current_dart;
bool m_draw_marked_darts;
typename LCC::size_type m_amark; // If !=INVALID_MARK, show darts marked with this mark
};