mirror of https://github.com/CGAL/cgal
- Remove in trunk/Polyhedron/demo/Polyhedron/ the bits about protecting
spheres. The experimental code will now be in branches/experimental-packages/Mesh_3-protecting_balls-branch/.
This commit is contained in:
parent
625905645b
commit
3eace192a7
|
|
@ -3,61 +3,11 @@
|
|||
|
||||
#include "Polyhedron_type.h"
|
||||
|
||||
#include <CGAL/Triangulation_vertex_base_with_info_3.h>
|
||||
#include <CGAL/Triangulation_cell_base_with_info_3.h>
|
||||
#include <CGAL/Surface_mesh_default_triangulation_3.h>
|
||||
#include <CGAL/Complex_2_in_triangulation_3.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Regular_triangulation_3.h>
|
||||
#include <CGAL/Regular_triangulation_euclidean_traits_3.h>
|
||||
#include <CGAL/Mesh_3/Robust_weighted_circumcenter_filtered_traits_3.h>
|
||||
|
||||
#include <bitset>
|
||||
|
||||
// traits class
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel K2;
|
||||
typedef CGAL::Robust_weighted_circumcenter_filtered_traits_3<K2> Traits;
|
||||
|
||||
// typedef CGAL::Regular_triangulation_euclidean_traits_3<K> Traits;
|
||||
|
||||
struct Ball_context;
|
||||
|
||||
class Vertex_info {
|
||||
Ball_context* context_;
|
||||
|
||||
public:
|
||||
Vertex_info();
|
||||
~Vertex_info();
|
||||
|
||||
Ball_context* context();
|
||||
};
|
||||
|
||||
class Cell_info {
|
||||
std::bitset<32> marks;
|
||||
|
||||
public:
|
||||
bool mark(int i) const
|
||||
{
|
||||
return marks[i];
|
||||
}
|
||||
|
||||
void set_mark(int i, bool b)
|
||||
{
|
||||
marks[i] = b;
|
||||
}
|
||||
};
|
||||
|
||||
// vertex and cell types
|
||||
typedef CGAL::Triangulation_vertex_base_with_info_3<Vertex_info, Traits> Vb1;
|
||||
typedef CGAL::Surface_mesh_vertex_base_3<Traits, Vb1> Vb;
|
||||
typedef CGAL::Triangulation_cell_base_with_info_3<Cell_info, Traits> Cb1;
|
||||
typedef CGAL::Surface_mesh_cell_base_3<Traits, Cb1> Cb;
|
||||
typedef CGAL::Triangulation_cell_base_with_circumcenter_3<Traits, Cb> Cb_with_circumcenter;
|
||||
|
||||
// triangulation
|
||||
typedef CGAL::Triangulation_data_structure_3<Vb, Cb_with_circumcenter> Tds;
|
||||
typedef CGAL::Regular_triangulation_3<Traits, Tds> Tr;
|
||||
|
||||
typedef CGAL::Surface_mesh_default_triangulation_3 Tr;
|
||||
typedef CGAL::Complex_2_in_triangulation_3<Tr> C2t3;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ if(CGAL_Qt4_FOUND AND QT4_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND)
|
|||
target_link_libraries( ${plugin_name} ${CGAL_LIBRARIES} ${CGAL_3RD_PARTY_LIBRARIES} )
|
||||
endmacro(polyhedron_demo_plugin)
|
||||
|
||||
polyhedron_demo_plugin(remeshing_plugin Polyhedron_demo_remeshing_plugin Polyhedron_demo_remeshing_plugin_cgal_code.cpp Polyhedron_demo_remeshing_plugin_protection_cgal_code.cpp Polyhedron_demo_remeshing_plugin_cgal_code.moc ${remeshingUI_FILES})
|
||||
polyhedron_demo_plugin(remeshing_plugin Polyhedron_demo_remeshing_plugin Polyhedron_demo_remeshing_plugin_cgal_code.cpp Polyhedron_demo_remeshing_plugin_cgal_code.moc ${remeshingUI_FILES})
|
||||
target_link_libraries(remeshing_plugin scene_polyhedron_item polygon_soup scene_c2t3_item)
|
||||
|
||||
qt4_generate_moc("${CMAKE_CURRENT_SOURCE_DIR}/Polyhedron_demo_mesh_3_plugin_cgal_code.cpp" Scene_c3t3_item.moc )
|
||||
|
|
|
|||
|
|
@ -20,9 +20,7 @@ Scene_item* cgal_code_remesh(QWidget* parent,
|
|||
const double angle,
|
||||
const double sizing,
|
||||
const double approx,
|
||||
int tag,
|
||||
bool protect,
|
||||
bool refine_balls);
|
||||
int tag);
|
||||
|
||||
class Polyhedron_demo_remeshing_plugin :
|
||||
public QObject,
|
||||
|
|
@ -39,18 +37,6 @@ public:
|
|||
connect(actionRemeshing, SIGNAL(triggered()),
|
||||
this, SLOT(remesh()));
|
||||
}
|
||||
actionShowSpheres = new QAction("Show protecting spheres", mw);
|
||||
actionShowSpheres->setCheckable(true);
|
||||
actionShowSpheres->setChecked(false);
|
||||
QMenu* menuView = mw->findChild<QMenu*>("menuView");
|
||||
if(menuView)
|
||||
{
|
||||
menuView->addAction(actionShowSpheres);
|
||||
}
|
||||
else {
|
||||
std::cerr << "Error: cannot find menu \"menuView\" in QMainWindow \""
|
||||
<< qPrintable(mw->objectName()) << "\"!\n";
|
||||
}
|
||||
}
|
||||
|
||||
QList<QAction*> actions() const {
|
||||
|
|
@ -61,7 +47,6 @@ public slots:
|
|||
|
||||
private:
|
||||
QAction* actionRemeshing;
|
||||
QAction* actionShowSpheres;
|
||||
}; // end class Polyhedron_demo_remeshing_plugin
|
||||
|
||||
void Polyhedron_demo_remeshing_plugin::remesh()
|
||||
|
|
@ -109,8 +94,6 @@ void Polyhedron_demo_remeshing_plugin::remesh()
|
|||
const double approx = ui.approx->value();
|
||||
const double sizing = ui.sizing->value();
|
||||
const int tag_index = ui.tags->currentIndex();
|
||||
const bool protect = ui.protect->isChecked();
|
||||
const bool refine_balls = ui.refine_balls->isChecked();
|
||||
if(tag_index < 0) return;
|
||||
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
|
@ -121,17 +104,13 @@ void Polyhedron_demo_remeshing_plugin::remesh()
|
|||
<< "\n approx=" << approx
|
||||
<< "\n tag=" << tag_index
|
||||
<< std::boolalpha
|
||||
<< "\n protect=" << protect
|
||||
<< "\n refine_balls=" << refine_balls
|
||||
<< std::endl;
|
||||
Scene_item* new_item = cgal_code_remesh(mw,
|
||||
pMesh,
|
||||
angle,
|
||||
sizing,
|
||||
approx,
|
||||
tag_index,
|
||||
protect,
|
||||
refine_balls);
|
||||
tag_index);
|
||||
|
||||
if(new_item)
|
||||
{
|
||||
|
|
@ -144,14 +123,6 @@ void Polyhedron_demo_remeshing_plugin::remesh()
|
|||
new_item->setRenderingMode(item->renderingMode());
|
||||
item->setVisible(false);
|
||||
scene->itemChanged(index);
|
||||
QObject::connect(actionShowSpheres, SIGNAL(toggled(bool)),
|
||||
new_item, SLOT(show_spheres(bool)));
|
||||
// meta-call, to avoid the inclusing of the CGAL headers
|
||||
QMetaObject::invokeMethod(new_item,
|
||||
"show_spheres",
|
||||
Qt::DirectConnection,
|
||||
Q_ARG(bool, actionShowSpheres->isChecked()));
|
||||
|
||||
scene->addItem(new_item);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -72,36 +72,17 @@ public:
|
|||
return false;
|
||||
if( squared_distance(pa, pc) < sq_distance_bound )
|
||||
return false;
|
||||
int nb_protecting_balls = 0;
|
||||
if(pa.weight() != FT(0)) ++nb_protecting_balls;
|
||||
if(pb.weight() != FT(0)) ++nb_protecting_balls;
|
||||
if(pc.weight() != FT(0)) ++nb_protecting_balls;
|
||||
if(nb_protecting_balls == 0)
|
||||
{
|
||||
if(aspect_ratio_criterion.is_bad(f, q[0]))
|
||||
return true;
|
||||
else {
|
||||
q[0] = 1;
|
||||
if(uniform_size_criterion.is_bad(f, q[1]))
|
||||
return true;
|
||||
else {
|
||||
q[1] = 1;
|
||||
if(curvature_size_criterion.is_bad(f, q[2]))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(aspect_ratio_criterion.is_bad(f, q[0]))
|
||||
return true;
|
||||
else {
|
||||
q[0] = 1;
|
||||
if(false && nb_protecting_balls == 3)
|
||||
return false;
|
||||
else if(uniform_size_criterion.is_bad(f, q[1]))
|
||||
if(uniform_size_criterion.is_bad(f, q[1]))
|
||||
return true;
|
||||
// else {
|
||||
// q[1] = 1;
|
||||
// if(nb_protecting_balls == 1 && curvature_size_criterion.is_bad(f, q[2]))
|
||||
// return true;
|
||||
// }
|
||||
else {
|
||||
q[1] = 1;
|
||||
if(curvature_size_criterion.is_bad(f, q[2]))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -131,8 +112,8 @@ namespace {
|
|||
//
|
||||
typedef CGAL::Simple_cartesian<double> Simple_cartesian_kernel;
|
||||
// input surface
|
||||
typedef CGAL::Mesh_3::Robust_intersection_traits_3<Kernel> IGT;
|
||||
typedef CGAL::AABB_polyhedral_oracle<Polyhedron,IGT,Simple_cartesian_kernel> Input_surface;
|
||||
// typedef CGAL::Mesh_3::Robust_intersection_traits_3<Kernel> IGT;
|
||||
typedef CGAL::AABB_polyhedral_oracle<Polyhedron,Kernel,Simple_cartesian_kernel> Input_surface;
|
||||
|
||||
|
||||
// A base non-templated class, to allow
|
||||
|
|
@ -249,16 +230,12 @@ struct Meshing_thread : QThread
|
|||
typedef Tr::Geom_traits GT;
|
||||
typedef Tr::Geom_traits::FT FT;
|
||||
|
||||
#include "Polyhedron_demo_remeshing_plugin_protection_cgal_code.h"
|
||||
|
||||
Scene_item* cgal_code_remesh(QWidget* parent,
|
||||
Polyhedron* pMesh,
|
||||
const double angle,
|
||||
const double sizing,
|
||||
const double approx,
|
||||
int tag,
|
||||
bool protect,
|
||||
bool refine_balls) {
|
||||
int tag) {
|
||||
// };
|
||||
|
||||
// class Mesh_process : public QObject {
|
||||
|
|
@ -312,18 +289,9 @@ Scene_item* cgal_code_remesh(QWidget* parent,
|
|||
Input_surface input(*pMesh);
|
||||
std::cerr << "done (" << timer.time() << " ms)" << std::endl;
|
||||
|
||||
if(protect) {
|
||||
std::cerr << "Insert protecting balls... ";
|
||||
timer.reset();
|
||||
insert_spheres(c2t3, pMesh, sizing/1.5, refine_balls);
|
||||
std::cerr << "done (" << timer.time() << " ms)" << std::endl;
|
||||
}
|
||||
|
||||
// initial point set
|
||||
timer.reset();
|
||||
std::cerr << "Insert initial point set... ";
|
||||
typedef CGAL::Cartesian_converter<Kernel,GT> Converter;
|
||||
Converter convert;
|
||||
|
||||
{ // new scope for the initialization, so that the vector
|
||||
// polyhedron_points is destroyed as soon as the initialization is
|
||||
|
|
@ -394,43 +362,30 @@ Scene_item* cgal_code_remesh(QWidget* parent,
|
|||
|
||||
if(triangulation.number_of_vertices() > 0)
|
||||
{
|
||||
// // add remesh as new polyhedron
|
||||
// Polyhedron *pRemesh = new Polyhedron;
|
||||
// CGAL::Complex_2_in_triangulation_3_polyhedron_builder<C2t3,
|
||||
// Polyhedron> builder(c2t3);
|
||||
return new Scene_c2t3_item(c2t3);
|
||||
|
||||
// try {
|
||||
// CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION);
|
||||
// pRemesh->delegate(builder);
|
||||
// } catch(CGAL::Failure_exception)
|
||||
// {
|
||||
// }
|
||||
// CGAL::set_error_behaviour(CGAL::ABORT);
|
||||
|
||||
// if(c2t3.number_of_facets() != pRemesh->size_of_facets())
|
||||
// {
|
||||
// delete pRemesh;
|
||||
// std::stringstream temp_file;
|
||||
// namespace sm = CGAL::Surface_mesher;
|
||||
// if(!CGAL::output_surface_facets_to_off(temp_file, c2t3,
|
||||
// sm::NO_OPTION | sm::IO_VERBOSE))
|
||||
// {
|
||||
// std::cerr << "Cannot write the mesh to an off file!\n";
|
||||
// std::cerr << temp_file.str() << std::endl;
|
||||
// return 0;
|
||||
// }
|
||||
// Scene_polygon_soup* soup = new Scene_polygon_soup();
|
||||
// if(!soup->load(temp_file))
|
||||
// {
|
||||
// std::cerr << "Cannot reload the mesh from an off file!\n";
|
||||
// return 0;
|
||||
// }
|
||||
// else
|
||||
// return soup;
|
||||
// } else {
|
||||
// return new Scene_polyhedron_item(pRemesh);
|
||||
// }
|
||||
// add remesh as new polyhedron
|
||||
Polyhedron *pRemesh = new Polyhedron;
|
||||
CGAL::Complex_2_in_triangulation_3_polyhedron_builder<C2t3, Polyhedron> builder(c2t3);
|
||||
pRemesh->delegate(builder);
|
||||
if(c2t3.number_of_facets() != pRemesh->size_of_facets())
|
||||
{
|
||||
delete pRemesh;
|
||||
std::stringstream temp_file;
|
||||
if(!CGAL::output_surface_facets_to_off(temp_file, c2t3))
|
||||
{
|
||||
std::cerr << "Cannot write the mesh to an off file!\n";
|
||||
return 0;
|
||||
}
|
||||
Scene_polygon_soup* soup = new Scene_polygon_soup();
|
||||
if(!soup->load(temp_file))
|
||||
{
|
||||
std::cerr << "Cannot reload the mesh from an off file!\n";
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return soup;
|
||||
} else {
|
||||
return new Scene_polyhedron_item(pRemesh);
|
||||
}
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1,778 +0,0 @@
|
|||
#include "config.h" // defines *_DEBUG_* macro for the demo
|
||||
#include <CGAL/config.h>
|
||||
#include "Polyhedron_type.h"
|
||||
#include "C2t3_type.h"
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <CGAL/tuple.h>
|
||||
#include <sstream>
|
||||
|
||||
typedef Tr::Geom_traits::FT FT;
|
||||
|
||||
struct Less {
|
||||
template <typename Handle>
|
||||
bool operator()(const Handle& va, const Handle& vb) const {
|
||||
return &*va < &*vb;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::vector<Tr::Geom_traits::Point_3> Polyline;
|
||||
typedef unsigned Polyline_id;
|
||||
|
||||
struct Ball_context {
|
||||
typedef Tr::Vertex_handle Tr_vertex_handle;
|
||||
|
||||
Tr_vertex_handle pred; // predecessor of the current non-corner ball on a
|
||||
// polyline
|
||||
Tr_vertex_handle succ; // successor..
|
||||
Polyline_id id; // polyline id
|
||||
Polyline::const_iterator iterator; // in the polyline, iterator to the
|
||||
// point that precedes the ball
|
||||
// (*it, *(it+1)) is the segment.
|
||||
FT position; // distance between the center of the current ball, and
|
||||
// halfedge->opposite()->vertex()->point()
|
||||
bool is_corner;
|
||||
};
|
||||
|
||||
Vertex_info::Vertex_info() : context_(0) {
|
||||
}
|
||||
|
||||
Vertex_info::~Vertex_info() {
|
||||
if(context_)
|
||||
{
|
||||
delete context_;
|
||||
context_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Ball_context* Vertex_info::context() {
|
||||
if(!context_) {
|
||||
context_ = new Ball_context;
|
||||
}
|
||||
return context_;
|
||||
}
|
||||
|
||||
struct Insert_spheres {
|
||||
typedef Polyhedron::Halfedge_const_handle Halfedge_const_handle;
|
||||
typedef Polyhedron::Vertex_const_handle Vertex_const_handle;
|
||||
typedef Polyhedron::size_type size_type;
|
||||
|
||||
typedef Tr::Geom_traits::Point_3 Point_3;
|
||||
typedef Tr::Vertex_handle Tr_vertex_handle;
|
||||
|
||||
typedef std::set<Vertex_const_handle, Less> Vertices_set;
|
||||
typedef std::map<Vertex_const_handle, size_type, Less> Vertices_counter;
|
||||
|
||||
typedef std::set<Halfedge_const_handle, Less> Border_edges_set;
|
||||
|
||||
Border_edges_set edges_to_consider;
|
||||
Vertices_counter border_vertices;
|
||||
Vertices_set corner_vertices;
|
||||
|
||||
typedef std::vector<Polyline> Polylines;
|
||||
|
||||
typedef std::vector<bool> Polyline_is_a_cycle;
|
||||
typedef std::set<Point_3> Hidden_balls;
|
||||
typedef CGAL::cpp0x::tuple<Polyline_id,
|
||||
Polyline::const_iterator,
|
||||
Tr_vertex_handle> Corner_context;
|
||||
typedef std::multimap<Tr_vertex_handle,
|
||||
Corner_context> Tr_corner_vertices;
|
||||
|
||||
Polylines polylines;
|
||||
Polyline_is_a_cycle polyline_is_a_cycle;
|
||||
Tr_corner_vertices tr_corner_vertices;
|
||||
Hidden_balls hidden_balls;
|
||||
|
||||
C2t3& c2t3;
|
||||
Polyhedron* pMesh;
|
||||
const FT size;
|
||||
|
||||
Halfedge_const_handle canonical(Halfedge_const_handle he)
|
||||
{
|
||||
const Halfedge_const_handle& op = he->opposite();
|
||||
if(Less()(he, op))
|
||||
return he;
|
||||
else
|
||||
return op;
|
||||
}
|
||||
|
||||
/** Follow a polyline or a polygon, from the halfedge he. */
|
||||
void follow_half_edge(const Halfedge_const_handle he, const bool is_cycle)
|
||||
{
|
||||
Border_edges_set::iterator it = edges_to_consider.find(canonical(he));
|
||||
if(it == edges_to_consider.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Polyline polyline;
|
||||
polyline.push_back(he->opposite()->vertex()->point());
|
||||
// std::cerr << "Start: " << he->opposite()->vertex()->point() << std::endl;
|
||||
|
||||
Halfedge_const_handle current_he = he;
|
||||
do {
|
||||
CGAL_assertion(current_he->is_border() ||
|
||||
current_he->opposite()->is_border());
|
||||
CGAL_assertion_code(const size_type n = )edges_to_consider.erase(canonical(current_he));
|
||||
CGAL_assertion(n > 0);
|
||||
Vertex_const_handle v = current_he->vertex();
|
||||
polyline.push_back(v->point());
|
||||
// std::cerr << v->point() << std::endl;
|
||||
if(corner_vertices.count(v) > 0) break;
|
||||
Polyhedron::Halfedge_around_vertex_const_circulator
|
||||
loop_he = v->vertex_begin(), end(loop_he);
|
||||
++loop_he;
|
||||
// CGAL_assertion((&*loop_he) != (&*current_he) );
|
||||
while((&*loop_he) == (&*current_he) ||
|
||||
(!loop_he->is_border() && !loop_he->opposite()->is_border()) ) {
|
||||
++loop_he;
|
||||
// CGAL_assertion((&*loop_he) != (&*current_he) );
|
||||
}
|
||||
current_he = loop_he->opposite();
|
||||
} while(current_he != he );
|
||||
|
||||
// if(current_he == he)
|
||||
// std::cerr << "New polyline, of size " << polyline.size() << std::endl;
|
||||
// else
|
||||
// std::cerr << "New polygon (cycle), of size " << polyline.size() << std::endl;
|
||||
|
||||
polyline_is_a_cycle.push_back(is_cycle);
|
||||
polylines.push_back(polyline);
|
||||
}
|
||||
|
||||
/** Loop around a corner vertex, and try to follow a polyline of border
|
||||
edges, from each incident edge. */
|
||||
void loop_around_corner(const Vertex_const_handle v)
|
||||
{
|
||||
Polyhedron::Halfedge_around_vertex_const_circulator
|
||||
he = v->vertex_begin(), end(he);
|
||||
do {
|
||||
CGAL_assertion(he->vertex() == v);
|
||||
follow_half_edge(he->opposite(), false);
|
||||
++he;
|
||||
} while(he != end);
|
||||
}
|
||||
|
||||
/** For a non-corner vertex v (that is incident to two border edges),
|
||||
mesure the angle between the two edges, and mark the vertex as corner
|
||||
edge, if the angle is < 120°. **/
|
||||
void mesure_angle(const Vertex_const_handle v)
|
||||
{
|
||||
Halfedge_const_handle e1;
|
||||
Halfedge_const_handle e2;
|
||||
Polyhedron::Halfedge_around_vertex_const_circulator he = v->vertex_begin(), end(he);
|
||||
// std::cerr << "mesure_handle(" << (void*)(&*v)
|
||||
// << " = " << v->point() << ")";
|
||||
bool first = true;
|
||||
do {
|
||||
CGAL_assertion(he->vertex() == v);
|
||||
// std::cerr << he->opposite()->vertex()->point() << std::endl;
|
||||
if(he->is_border() || he->opposite()->is_border()) {
|
||||
if(first) {
|
||||
e1 = he;
|
||||
first = false;
|
||||
}
|
||||
else {
|
||||
CGAL_assertion(e2 == Halfedge_const_handle());
|
||||
e2 = he;
|
||||
}
|
||||
// std::cerr << "x";
|
||||
}
|
||||
// else
|
||||
// std::cerr << ".";
|
||||
++he;
|
||||
} while(he != end);
|
||||
// std::cerr << "\n";
|
||||
const Point_3 pv = v->point();
|
||||
const Point_3 pa = e1->opposite()->vertex()->point();
|
||||
const Point_3 pb = e2->opposite()->vertex()->point();
|
||||
const Tr::Geom_traits::Vector_3 av = pv - pa;
|
||||
const Tr::Geom_traits::Vector_3 bv = pv - pb;
|
||||
const FT sc_prod = av * bv;
|
||||
if( sc_prod >= 0 ||
|
||||
(sc_prod < 0 &&
|
||||
CGAL::square(sc_prod) < (av * av) * (bv * bv) / 4 ) )
|
||||
{
|
||||
// std::cerr << "Corner (" << pa << ", " << pv
|
||||
// << ", " << pb << ")\n";
|
||||
corner_vertices.insert(v);
|
||||
}
|
||||
}
|
||||
|
||||
const Tr_vertex_handle insert(const Point_3& p, const Polyline_id polyline_id)
|
||||
{
|
||||
Tr::Vertex_handle v = c2t3.triangulation().insert(p);
|
||||
if(v == Tr_vertex_handle()) {
|
||||
v = c2t3.triangulation().nearest_power_vertex(p);
|
||||
hidden_balls.insert(p);
|
||||
#ifdef PROTECTION_DEBUG
|
||||
std::cerr << "Hidden ball " << p << " (id="
|
||||
<< polyline_id << "), hidden by the ball "
|
||||
<< v->point()
|
||||
<< " ("
|
||||
<< print_context(v)
|
||||
<< ")\n";
|
||||
#endif
|
||||
}
|
||||
v->info().context()->id = polyline_id;
|
||||
return v;
|
||||
}
|
||||
|
||||
void cover(Polyline::const_iterator begin,
|
||||
Polyline::const_iterator end2,
|
||||
const Polyline_id polyline_id,
|
||||
FT alpha, // alpha is the desired radius of covering ball
|
||||
// the real radius must be lower.
|
||||
Tr_vertex_handle va,
|
||||
Tr_vertex_handle vb,
|
||||
const FT position_begin,
|
||||
const FT position_end)
|
||||
{
|
||||
#ifdef PROTECTION_DEBUG
|
||||
std::cerr << "cover(" << va->point() << ", "
|
||||
<< vb->point() << ", " << polyline_id << ")\n";
|
||||
#endif
|
||||
FT radius_begin = CGAL_NTS sqrt(va->point().weight());
|
||||
FT radius_end = CGAL_NTS sqrt(vb->point().weight());
|
||||
|
||||
if(begin == end2 && position_begin >= position_end)
|
||||
return;
|
||||
|
||||
FT distance = 0;
|
||||
for(Polyline::const_iterator it = begin;
|
||||
it != end2; /*'it' is incremented in the body*/ ) {
|
||||
const Point& a = *it;
|
||||
const Point& b = *++it;
|
||||
distance += CGAL_NTS sqrt( CGAL::squared_distance(a, b) );
|
||||
}
|
||||
distance -= radius_begin;
|
||||
distance -= radius_end;
|
||||
distance -= position_begin;
|
||||
distance += position_end;
|
||||
if(distance < 0) return;
|
||||
// distance -= (alpha * 2) / 3;
|
||||
// std::cerr << "Distance: " << distance << std::endl;
|
||||
// std::cerr << "Size: " << size << std::endl;
|
||||
|
||||
// The desired radius is alpha. The desired inter-distance (between
|
||||
// balls centers) is 4*alpha/3
|
||||
// const FT desired_inter_distance = 4 * alpha / 3;
|
||||
|
||||
// Let r be the real radius (r <= alpha).
|
||||
// Let inter_distance be the real inter-distance:
|
||||
// inter_distance = 4 * r / 3 <= desired_inter_distance
|
||||
// Let n be the number of steps: the number of inserted balls is n+1.
|
||||
// Then :
|
||||
// distance = r / 3 + n * (4 * r /3 ) + r / 3
|
||||
//
|
||||
// 3* distance = (4 * n + 2 ) * r
|
||||
//
|
||||
// 1 3 * distance
|
||||
// n = - * ( ------------ - 2 )
|
||||
// 4 r
|
||||
//
|
||||
// n >= 1 then r <= distance / 2
|
||||
const int n = (std::max)
|
||||
(1,
|
||||
static_cast<int>(std::ceil(((3 * distance / alpha) - 2) / 4) + 0.5));
|
||||
|
||||
const FT r = (3 * distance ) / ( 4 * n + 2) ;
|
||||
// std::cerr << n << std::endl;
|
||||
// std::cerr << "Local size: " << local_size << std::endl;
|
||||
// CGAL_assertion(local_size < size);
|
||||
const FT inter_distance = 4 * r / 3;
|
||||
const FT r2 = CGAL::square(r);
|
||||
|
||||
#ifdef PROTECTION_DEBUG
|
||||
std::cerr << "distance = " << distance
|
||||
<< "\nalpha = " << alpha
|
||||
<< "\nn = " << n
|
||||
<< "\nr = " << r
|
||||
<< std::endl;
|
||||
#endif
|
||||
|
||||
Point_3 a(begin->point(), r2);
|
||||
Point_3 b(end2->point(), r2);
|
||||
FT small_distance_to_go = position_begin + radius_begin + (r / 3);
|
||||
Polyline::const_iterator it = begin;
|
||||
bool first = true;
|
||||
Tr_vertex_handle first_non_corner;
|
||||
Tr_vertex_handle last_non_corner;
|
||||
Tr_vertex_handle previous = va;
|
||||
int counter = 0;
|
||||
while(it <= end2 && counter <= n)//small_distance_to_go < (position_end - radius_end)))
|
||||
{
|
||||
const Point& a = *it;
|
||||
const Point& b = *(it+1);
|
||||
#ifdef PROTECTION_DEBUG
|
||||
std::cerr << "segment( " << a << ", " << b << ")\n";
|
||||
std::cerr << "small_distance_to_go=" << small_distance_to_go << std::endl;
|
||||
#endif
|
||||
const FT d = CGAL_NTS sqrt(squared_distance(a, b));
|
||||
#ifdef PROTECTION_DEBUG
|
||||
std::cerr << "d=" << d << std::endl;
|
||||
#endif
|
||||
FT pos = small_distance_to_go;
|
||||
if(pos < d && counter <= n) {
|
||||
for(; pos < d && counter <= n;
|
||||
pos += inter_distance)
|
||||
{
|
||||
#ifdef PROTECTION_DEBUG
|
||||
std::cerr << "pos=" << pos << "" << std::endl;
|
||||
#endif
|
||||
const Point p = a +
|
||||
pos * ( b - a ) / d;
|
||||
++counter;
|
||||
Tr_vertex_handle current = insert(Point_3(p, r2), polyline_id);
|
||||
if(current != Tr_vertex_handle()) {
|
||||
current->info().context()->pred = previous;
|
||||
current->info().context()->iterator = it;
|
||||
current->info().context()->position = pos;
|
||||
current->info().context()->is_corner = false;
|
||||
previous->info().context()->succ = current;
|
||||
|
||||
// at the end of the loop, last_non_corner is the last non-corner
|
||||
// ball on the polyline
|
||||
last_non_corner = current;
|
||||
if(first) {
|
||||
// and first_non_corner is the first non-corner ball on the
|
||||
// polyline
|
||||
first_non_corner = current;
|
||||
first = false;
|
||||
}
|
||||
previous = current;
|
||||
}
|
||||
}
|
||||
// pos -= inter_distance;
|
||||
small_distance_to_go = pos - d;
|
||||
}
|
||||
else {
|
||||
small_distance_to_go -= d;
|
||||
}
|
||||
++it;
|
||||
// std::cerr << "\n";
|
||||
}
|
||||
if(!polyline_is_a_cycle[polyline_id])
|
||||
{
|
||||
// CGAL_assertion(va == Tr_vertex_handle() ||
|
||||
// vb == Tr_vertex_handle() ||
|
||||
// va != vb);
|
||||
// if(va != Tr_vertex_handle())
|
||||
if(va->info().context()->is_corner) {
|
||||
#ifdef PROTECTION_DEBUG
|
||||
std::cerr << "Corner vertex va " << va->point()
|
||||
<< ", neighbor " << *first_non_corner << std::endl;
|
||||
#endif
|
||||
tr_corner_vertices.insert(std::make_pair(va,
|
||||
Corner_context(polyline_id, begin, first_non_corner)));
|
||||
// CGAL_assertion(first_non_corner->info().context()->pred == va);
|
||||
}
|
||||
if(vb->info().context()->is_corner) {
|
||||
#ifdef PROTECTION_DEBUG
|
||||
std::cerr << "Corner vertex vb " << vb->point()
|
||||
<< ", neighbor " << *last_non_corner << std::endl;
|
||||
#endif
|
||||
tr_corner_vertices.insert(std::make_pair(vb,
|
||||
Corner_context(polyline_id, end2, last_non_corner)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
vb = va;
|
||||
}
|
||||
if(last_non_corner != Tr_vertex_handle()) {
|
||||
last_non_corner->info().context()->succ = vb;
|
||||
}
|
||||
// if(vb != Tr_vertex_handle())
|
||||
vb->info().context()->pred = last_non_corner;
|
||||
|
||||
// std::cerr << "One polyline is protected!\n";
|
||||
}
|
||||
|
||||
void separate_balls() {
|
||||
Tr& tr = c2t3.triangulation();
|
||||
bool restart = false;
|
||||
do {
|
||||
restart = false;
|
||||
for(Tr::Finite_edges_iterator eit = tr.finite_edges_begin(),
|
||||
end = tr.finite_edges_end(); eit != end; ++eit)
|
||||
{
|
||||
const Tr_vertex_handle& va = eit->first->vertex(eit->second);
|
||||
const Tr_vertex_handle& vb = eit->first->vertex(eit->third);
|
||||
if(non_adjacent_but_intersect(va, vb))
|
||||
{
|
||||
#ifdef PROTECTION_DEBUG
|
||||
std::cerr << "Balls " << va->point() << " ("
|
||||
<< print_context(va)
|
||||
<< ") and " << vb->point() << " ("
|
||||
<< print_context(vb)
|
||||
<< ") intersect.\n";
|
||||
#endif
|
||||
|
||||
if(// !va->info().context()->is_corner &&
|
||||
va->point().weight() > vb->point().weight()) {
|
||||
restart = true;
|
||||
refine_ball(va);
|
||||
break;
|
||||
}
|
||||
else // if(!vb->info().context()->is_corner)
|
||||
{
|
||||
restart = true;
|
||||
refine_ball(vb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while(restart);
|
||||
}
|
||||
|
||||
std::string print_context(Tr_vertex_handle va) {
|
||||
std::stringstream s;
|
||||
using CGAL::cpp0x::get;
|
||||
if(!va->info().context()->is_corner)
|
||||
s << "on polyline " << va->info().context()->id;
|
||||
else {
|
||||
typedef Tr_corner_vertices::const_iterator const_iterator;
|
||||
typedef std::pair<const_iterator, const_iterator> Range;
|
||||
Range range_a = tr_corner_vertices.equal_range(va);
|
||||
s << "on polylines";
|
||||
for(const_iterator it = range_a.first; it != range_a.second; ++it)
|
||||
s << " " << get<0>(it->second);
|
||||
}
|
||||
return s.str();
|
||||
}
|
||||
|
||||
bool non_adjacent_but_intersect(const Tr_vertex_handle& va,
|
||||
const Tr_vertex_handle& vb) const
|
||||
{
|
||||
using CGAL::cpp0x::get;
|
||||
|
||||
typedef Tr_corner_vertices::const_iterator const_iterator;
|
||||
typedef std::pair<const_iterator, const_iterator> Range;
|
||||
typedef std::set<Polyline_id> P_id_set;
|
||||
bool non_adjacent;
|
||||
|
||||
if(!va->info().context()->is_corner && //range_a.first == range_a.second &&
|
||||
!vb->info().context()->is_corner) // range_b.first == range_b.second)
|
||||
{
|
||||
non_adjacent = ( va->info().context()->id != vb->info().context()->id );
|
||||
}
|
||||
else {
|
||||
Range range_a = tr_corner_vertices.equal_range(va);
|
||||
Range range_b = tr_corner_vertices.equal_range(vb);
|
||||
|
||||
P_id_set s_a;
|
||||
P_id_set s_b;
|
||||
for(const_iterator it = range_a.first; it != range_a.second; ++it)
|
||||
{
|
||||
s_a.insert(get<0>(it->second));
|
||||
}
|
||||
s_a.insert(va->info().context()->id);
|
||||
for(const_iterator it = range_b.first; it != range_b.second; ++it)
|
||||
{
|
||||
s_b.insert(get<0>(it->second));
|
||||
}
|
||||
s_b.insert(va->info().context()->id);
|
||||
P_id_set intersection;
|
||||
std::set_intersection(s_a.begin(), s_a.end(),
|
||||
s_b.begin(), s_b.end(),
|
||||
std::inserter(intersection, intersection.begin()));
|
||||
non_adjacent = intersection.empty();
|
||||
}
|
||||
if(non_adjacent)
|
||||
{
|
||||
const Point_3& a = va->point();
|
||||
const Point_3& b = vb->point();
|
||||
if( CGAL_NTS sqrt( CGAL::squared_distance(a, b) ) <
|
||||
CGAL_NTS sqrt( a.weight() ) + CGAL_NTS sqrt( b.weight() ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void refine_ball(Tr_vertex_handle v) {
|
||||
typedef Tr_corner_vertices::const_iterator const_iterator;
|
||||
typedef Tr_corner_vertices::iterator iterator;
|
||||
typedef std::pair<iterator, iterator> Range;
|
||||
using CGAL::cpp0x::get;
|
||||
if(v->info().context()->is_corner) //r.first != r.second)
|
||||
{
|
||||
Range r = tr_corner_vertices.equal_range(v);
|
||||
#ifdef PROTECTION_DEBUG
|
||||
std::cerr << "Refine vertex ball " << v->point() << "\n"
|
||||
<< "Number of adjacent balls: " << distance(r.first, r.second)
|
||||
<< std::endl;
|
||||
#endif
|
||||
Point_3 new_point(v->point().point(), v->point().weight() / 4);
|
||||
Polyline_id id = v->info().context()->id;
|
||||
c2t3.triangulation().remove(v);
|
||||
Tr_vertex_handle new_v = insert(new_point, id);
|
||||
new_v->info().context()->is_corner = true;
|
||||
for(iterator it = r.first; it != r.second; ++it) {
|
||||
Tr_vertex_handle neighbor = get<2>(it->second);
|
||||
Ball_context* context = neighbor->info().context();
|
||||
#ifdef PROTECTION_DEBUG
|
||||
std::cerr << " adjacent ball: " << neighbor->point()
|
||||
<< ", id=" << context->id << std::endl;
|
||||
#endif
|
||||
if(v == context->pred)
|
||||
{
|
||||
context->pred = new_v;
|
||||
}
|
||||
else {
|
||||
CGAL_assertion(v == context->succ);
|
||||
context->succ = new_v;
|
||||
}
|
||||
}
|
||||
|
||||
iterator hint = tr_corner_vertices.begin();
|
||||
for(iterator it = r.first; it != r.second; ++it) {
|
||||
hint = tr_corner_vertices.insert(hint,
|
||||
std::make_pair(new_v, it->second));
|
||||
}
|
||||
for(iterator it = r.first; it != r.second; ++it) {
|
||||
refine_ball(get<2>(it->second));
|
||||
}
|
||||
tr_corner_vertices.erase(r.first, r.second);
|
||||
}
|
||||
else {
|
||||
#ifdef PROTECTION_DEBUG
|
||||
std::cerr << "Refine ball " << v->point();
|
||||
#endif
|
||||
Point_3 new_point(v->point().point(), v->point().weight() / 16);
|
||||
Ball_context* context = v->info().context();
|
||||
const Polyline_id id = context->id;
|
||||
#ifdef PROTECTION_DEBUG
|
||||
std::cerr << ", id= " << id << "\n";
|
||||
#endif
|
||||
const Tr_vertex_handle pred = context->pred;
|
||||
const Tr_vertex_handle succ = context->succ;
|
||||
const Polyline::const_iterator it = context->iterator;
|
||||
// const FT position = context->position;
|
||||
|
||||
c2t3.triangulation().remove(v);
|
||||
// Tr_vertex_handle new_v = insert(new_point, id);
|
||||
// Ball_context* new_context = new_v->info().context();
|
||||
// new_context->is_corner = false;
|
||||
// new_context->pred = pred;
|
||||
// new_context->succ = succ;
|
||||
// new_context->iterator = it;
|
||||
// new_context->position = position;
|
||||
|
||||
Polyline::const_iterator pred_it, succ_it;
|
||||
FT pred_pos, succ_pos;
|
||||
boost::tie(pred_it, pred_pos) = get_it_and_pos(pred, id);
|
||||
boost::tie(succ_it, succ_pos) = get_it_and_pos(succ, id);
|
||||
if(pred_it != Polyline::const_iterator() &&
|
||||
succ_it != Polyline::const_iterator())
|
||||
{
|
||||
#ifdef PROTECTION_DEBUG
|
||||
std::cerr << "OK!\n";
|
||||
#endif
|
||||
if(pred_it > succ_it) {
|
||||
std::swap(pred_it, succ_it);
|
||||
std::swap(pred_pos, succ_pos);
|
||||
}
|
||||
cover(pred_it, succ_it,
|
||||
id,
|
||||
CGAL_NTS sqrt(new_point.weight()),
|
||||
pred, succ,
|
||||
pred_pos, succ_pos);
|
||||
}
|
||||
else {
|
||||
std::cerr << "ERROR!\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<Polyline::const_iterator, FT>
|
||||
get_it_and_pos(Tr_vertex_handle v, Polyline_id id)
|
||||
{
|
||||
Ball_context* context = v->info().context();
|
||||
if(!context->is_corner) {
|
||||
if(context->id == id)
|
||||
return std::make_pair(context->iterator, context->position);
|
||||
}
|
||||
else {
|
||||
typedef Tr_corner_vertices::const_iterator const_iterator;
|
||||
typedef std::pair<const_iterator, const_iterator> Range;
|
||||
Range range_a = tr_corner_vertices.equal_range(v);
|
||||
for(const_iterator it = range_a.first; it != range_a.second; ++it)
|
||||
{
|
||||
using CGAL::cpp0x::get;
|
||||
if(get<0>(it->second) == id)
|
||||
return std::make_pair(get<1>(it->second), 0);
|
||||
}
|
||||
}
|
||||
return std::make_pair(Polyline::const_iterator(), 0);
|
||||
}
|
||||
|
||||
Insert_spheres(C2t3& c2t3, Polyhedron* pMesh, const FT size,
|
||||
bool refine_balls)
|
||||
: c2t3(c2t3), pMesh(pMesh), size(size)
|
||||
{
|
||||
Tr& tr = c2t3.triangulation();
|
||||
|
||||
// That call orders the set of edges of the polyhedron, so that the
|
||||
// border edges are at the end of the sequence of edges.
|
||||
pMesh->normalize_border();
|
||||
|
||||
// Iterate over border edges, and find out which vertices are corner
|
||||
// vertices (more than two incident border edges).
|
||||
for(Polyhedron::Edge_const_iterator
|
||||
eit = pMesh->border_edges_begin (),
|
||||
end = pMesh->edges_end();
|
||||
eit != end; ++eit)
|
||||
{
|
||||
edges_to_consider.insert(canonical(eit));
|
||||
Polyhedron::Vertex_const_handle v = eit->vertex();
|
||||
for(Polyline_id i = 0; i < 2; ++i) {
|
||||
if(++border_vertices[v] == 3)
|
||||
corner_vertices.insert(v);
|
||||
v = eit->opposite()->vertex();
|
||||
}
|
||||
|
||||
}
|
||||
std::cerr << "Corner vertices: " << corner_vertices.size() << std::endl;
|
||||
std::cerr << "Border vertices: " << border_vertices.size() << std::endl;
|
||||
|
||||
// Iterate over non-corner border vertices, and mesure the angle.
|
||||
for(Vertices_counter::iterator it = border_vertices.begin(),
|
||||
end = border_vertices.end(); it != end; ++it)
|
||||
{
|
||||
const Vertex_const_handle v = it->first;
|
||||
if(corner_vertices.count(v) == 0) {
|
||||
CGAL_assertion(it->second == 2);
|
||||
mesure_angle(v);
|
||||
}
|
||||
}
|
||||
std::cerr << "New corner vertices: " << corner_vertices.size() << std::endl;
|
||||
|
||||
// Follow the polylines...
|
||||
for(Vertices_set::iterator it = corner_vertices.begin(),
|
||||
end = corner_vertices.end(); it != end; ++it)
|
||||
{
|
||||
loop_around_corner(*it);
|
||||
}
|
||||
|
||||
// ... and the cycles.
|
||||
while(! edges_to_consider.empty() ) {
|
||||
follow_half_edge(*edges_to_consider.begin(), true);
|
||||
}
|
||||
|
||||
typedef std::vector<std::pair<Tr_vertex_handle,
|
||||
Tr_vertex_handle> > Polylines_endpoints;
|
||||
Polylines_endpoints polylines_endpoints;
|
||||
|
||||
// Then insert the protecting balls.
|
||||
for(Polyline_id i = 0; i < polylines.size(); ++i)
|
||||
{
|
||||
Tr_vertex_handle va = insert(Point_3(*polylines[i].begin(), 0), i);
|
||||
Tr_vertex_handle vb = insert(Point_3(*(--polylines[i].end()), 0), i);
|
||||
polylines_endpoints.push_back(std::make_pair(va, vb));
|
||||
CGAL_assertion(!polyline_is_a_cycle[i] ||
|
||||
va == vb);
|
||||
}
|
||||
|
||||
typedef std::vector<std::pair<FT, FT> > Polylines_endpoints_sq_radii;
|
||||
std::map<Tr_vertex_handle, FT> sq_radii;
|
||||
Polylines_endpoints_sq_radii polylines_endpoints_sq_radii;
|
||||
|
||||
FT size2 = CGAL::square(size);
|
||||
for(Tr::Finite_vertices_iterator vit = tr.finite_vertices_begin(),
|
||||
end = tr.finite_vertices_end(); vit != end; ++vit)
|
||||
{
|
||||
const Point_3& a = vit->point();
|
||||
std::vector<Tr_vertex_handle> incident_vertices;
|
||||
incident_vertices.reserve(32);
|
||||
tr.incident_vertices(vit, std::back_inserter(incident_vertices));
|
||||
std::vector<Tr_vertex_handle>::const_iterator vit2 = incident_vertices.begin();
|
||||
FT min_sq_distance = CGAL::squared_distance(a, (*vit2)->point());
|
||||
for(std::vector<Tr_vertex_handle>::const_iterator end = incident_vertices.end();
|
||||
vit2 != end; ++vit2)
|
||||
{
|
||||
FT sq_distance = CGAL::squared_distance(a, (*vit2)->point());
|
||||
if(sq_distance < min_sq_distance) {
|
||||
min_sq_distance = sq_distance;
|
||||
}
|
||||
}
|
||||
sq_radii[vit] = (std::min)(min_sq_distance, size2);
|
||||
}
|
||||
|
||||
for(Polyline_id i = 0; i < polylines.size(); ++i) {
|
||||
polylines_endpoints_sq_radii.push_back(std::make_pair(sq_radii[polylines_endpoints[i].first],
|
||||
sq_radii[polylines_endpoints[i].second]));
|
||||
}
|
||||
|
||||
polylines_endpoints.clear();
|
||||
tr.clear();
|
||||
|
||||
// Then insert the protecting balls.
|
||||
for(Polyline_id i = 0; i < polylines.size(); ++i)
|
||||
{
|
||||
Tr_vertex_handle va = insert(Point_3(*polylines[i].begin(),
|
||||
polylines_endpoints_sq_radii[i].first), i);
|
||||
Tr_vertex_handle vb = insert(Point_3(*(polylines[i].end()-1),
|
||||
polylines_endpoints_sq_radii[i].second), i);
|
||||
if(!polyline_is_a_cycle[i]) {
|
||||
va->info().context()->is_corner = true;
|
||||
vb->info().context()->is_corner = true;
|
||||
}
|
||||
else {
|
||||
CGAL_assertion(va == vb);
|
||||
}
|
||||
|
||||
cover(polylines[i].begin(),
|
||||
polylines[i].end()-1,
|
||||
i,
|
||||
CGAL_NTS sqrt((std::min)(va->point().weight(),
|
||||
vb->point().weight())),
|
||||
va,
|
||||
vb,
|
||||
0,
|
||||
0);
|
||||
}
|
||||
polylines_endpoints_sq_radii.clear();
|
||||
|
||||
unsigned counter = 0;
|
||||
for(unsigned i = 0; i < polyline_is_a_cycle.size(); ++i)
|
||||
if(polyline_is_a_cycle[i]) ++counter;
|
||||
std::cerr << "Number of cycles: " << counter << std::endl;
|
||||
std::cerr << "Number of polylines: " << polylines.size() - counter << "\n";
|
||||
std::cerr << "Number of protecting balls: "
|
||||
<< c2t3.triangulation().number_of_vertices() << std::endl;
|
||||
|
||||
counter = 0;
|
||||
for(Tr::Finite_vertices_iterator vit = tr.finite_vertices_begin(),
|
||||
end = tr.finite_vertices_end(); vit != end; ++vit) {
|
||||
if(vit->info().context()->is_corner)
|
||||
++counter;
|
||||
}
|
||||
std::cerr << "Number of vertex balls: " << counter << std::endl;
|
||||
|
||||
std::cerr << "Number of hidden balls: " << hidden_balls.size() << "\n";
|
||||
for(Hidden_balls::const_iterator it = hidden_balls.begin(),
|
||||
end = hidden_balls.end(); it != end; ++it)
|
||||
{
|
||||
std::cerr << "Hidden ball " << *it << ", hidden by the ball "
|
||||
<< c2t3.triangulation().nearest_power_vertex(*it)->point()
|
||||
<< "\n";
|
||||
}
|
||||
if(refine_balls) {
|
||||
separate_balls();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#include "Polyhedron_demo_remeshing_plugin_protection_cgal_code.h"
|
||||
|
||||
void insert_spheres(C2t3& c2t3, Polyhedron* pMesh, const FT size,
|
||||
bool refine_balls) {
|
||||
|
||||
Insert_spheres go(c2t3, pMesh, size, refine_balls);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
void insert_spheres(C2t3& c2t3, Polyhedron* pMesh, const FT size,
|
||||
bool refine_balls);
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>389</width>
|
||||
<height>227</height>
|
||||
<height>173</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
|
@ -112,23 +112,6 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="protect">
|
||||
<property name="text">
|
||||
<string>&Protect borders with spheres</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="refine_balls">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Refine protecting balls</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
|
|
@ -188,21 +171,5 @@
|
|||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>protect</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>refine_balls</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>237</x>
|
||||
<y>119</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>241</x>
|
||||
<y>143</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
|
|
|
|||
|
|
@ -15,16 +15,12 @@ class SCENE_C2T3_ITEM_EXPORT Scene_c2t3_item : public Scene_item
|
|||
Q_OBJECT
|
||||
public:
|
||||
Scene_c2t3_item(const C2t3& c2t3)
|
||||
: sphere_display_list(0), quadric(0), c2t3_(c2t3)
|
||||
: c2t3_(c2t3)
|
||||
{
|
||||
}
|
||||
|
||||
~Scene_c2t3_item()
|
||||
{
|
||||
if(quadric != 0)
|
||||
gluDeleteQuadric(quadric);
|
||||
if(sphere_display_list != 0)
|
||||
glDeleteLists(sphere_display_list, 1);
|
||||
}
|
||||
|
||||
C2t3& c2t3() {
|
||||
|
|
@ -50,13 +46,11 @@ public:
|
|||
end = c2t3().triangulation().finite_vertices_end();
|
||||
vit != end; ++vit)
|
||||
{
|
||||
if(vit->point().weight() > 0) {
|
||||
if(first) {
|
||||
result = vit->point().bbox();
|
||||
first = false;
|
||||
} else {
|
||||
result = result + vit->point().bbox();
|
||||
}
|
||||
if(first) {
|
||||
result = vit->point().bbox();
|
||||
first = false;
|
||||
} else {
|
||||
result = result + vit->point().bbox();
|
||||
}
|
||||
}
|
||||
return Bbox(result.xmin(), result.ymin(), result.zmin(),
|
||||
|
|
@ -101,55 +95,6 @@ public:
|
|||
GLenum gl_error = ::glGetError();
|
||||
if(gl_error != GL_NO_ERROR)
|
||||
std::cerr << "GL error: " << gluErrorString(gl_error) << std::endl;
|
||||
|
||||
if(!draw_spheres)
|
||||
return;
|
||||
|
||||
// force wireframe for protecting spheres
|
||||
GLint polygon_mode[2];
|
||||
::glGetIntegerv(GL_POLYGON_MODE, &polygon_mode[0]);
|
||||
::glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
|
||||
for(Tr::Finite_vertices_iterator
|
||||
vit = c2t3().triangulation().finite_vertices_begin(),
|
||||
end = c2t3().triangulation().finite_vertices_end();
|
||||
vit != end; ++vit)
|
||||
{
|
||||
draw_sphere(vit->point());
|
||||
}
|
||||
::glPolygonMode(GL_FRONT_AND_BACK, polygon_mode[0]);
|
||||
}
|
||||
|
||||
void draw_sphere(const Tr::Point p) const
|
||||
{
|
||||
if(p.weight() > 0) {
|
||||
if(sphere_display_list == 0) {
|
||||
sphere_display_list = glGenLists(1);
|
||||
if(sphere_display_list == 0)
|
||||
std::cerr << "ERROR: Cannot create display list!\n";
|
||||
if(quadric == 0)
|
||||
quadric = gluNewQuadric();
|
||||
if(quadric == 0)
|
||||
std::cerr << "ERROR: Cannot create GLU quadric!\n";
|
||||
glNewList(sphere_display_list, GL_COMPILE);
|
||||
gluSphere(quadric, 1., 10, 10);
|
||||
glEndList();
|
||||
if(glGetError() != GL_NO_ERROR)
|
||||
std::cerr << gluErrorString(glGetError());
|
||||
}
|
||||
glPushMatrix();
|
||||
glTranslated(CGAL::to_double(p.point().x()),
|
||||
CGAL::to_double(p.point().y()),
|
||||
CGAL::to_double(p.point().z()));
|
||||
const GLdouble r = CGAL::to_double(CGAL_NTS sqrt(p.weight()));
|
||||
glScaled(r, r, r);
|
||||
glCallList(sphere_display_list);
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
public slots:
|
||||
void show_spheres(bool b) {
|
||||
draw_spheres = b;
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -167,10 +112,7 @@ private:
|
|||
}
|
||||
|
||||
private:
|
||||
mutable GLuint sphere_display_list;
|
||||
mutable GLUquadric* quadric;
|
||||
C2t3 c2t3_;
|
||||
bool draw_spheres;
|
||||
};
|
||||
|
||||
#endif // SCENE_C2T3_ITEM
|
||||
|
|
|
|||
Loading…
Reference in New Issue