mirror of https://github.com/CGAL/cgal
348 lines
9.8 KiB
C++
348 lines
9.8 KiB
C++
// Copyright (c) 2004, 2005 INRIA Sophia-Antipolis (France).
|
||
// All rights reserved.
|
||
//
|
||
// This file is part of CGAL (www.cgal.org); you may redistribute it under
|
||
// the terms of the Q Public License version 1.0.
|
||
// See the file LICENSE.QPL distributed with CGAL.
|
||
//
|
||
// Licensees holding a valid commercial license may use this file in
|
||
// accordance with the commercial license agreement provided with the software.
|
||
//
|
||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||
//
|
||
// $URL$
|
||
// $Id$
|
||
//
|
||
//
|
||
// Author(s) : Laurent RINEAU
|
||
|
||
#ifndef CGAL_MESH_3_REFINE_EDGES_H
|
||
#define CGAL_MESH_3_REFINE_EDGES_H
|
||
|
||
#include <CGAL/Mesher_level.h>
|
||
#include <CGAL/Mesh_3/Triangulation_mesher_level_traits_3.h>
|
||
#include <CGAL/Mesh_3/Simple_queue_container.h>
|
||
|
||
#include <list>
|
||
#include <utility>
|
||
|
||
namespace CGAL {
|
||
|
||
namespace Mesh_3 {
|
||
|
||
namespace details {
|
||
template <typename Tr>
|
||
struct Refine_edges_base_types
|
||
{
|
||
typedef typename Tr::Vertex_handle Vertex_handle;
|
||
typedef std::pair<Vertex_handle,
|
||
Vertex_handle> Constrained_edge;
|
||
|
||
typedef ::CGAL::Mesh_3::Simple_queue_container<Constrained_edge>
|
||
Default_container;
|
||
};
|
||
}; // end namespace details
|
||
|
||
template <
|
||
class Tr,
|
||
class Container =
|
||
typename details::Refine_edges_base_types<Tr>::Default_container
|
||
>
|
||
class Refine_edges_base :
|
||
public Triangulation_mesher_level_traits_3<Tr>
|
||
{
|
||
protected:
|
||
typedef typename Tr::Bare_point Bare_point;
|
||
typedef typename Tr::Point Point;
|
||
typedef typename Tr::Edge Edge;
|
||
typedef typename Tr::Vertex_handle Vertex_handle;
|
||
typedef typename Tr::Cell_handle Cell_handle;
|
||
|
||
typedef typename Tr::Geom_traits Geom_traits;
|
||
typedef typename Triangulation_mesher_level_traits_3<Tr>::Zone Zone;
|
||
|
||
typedef typename Tr::Facet_circulator Facet_circulator;
|
||
typedef typename Tr::Finite_edges_iterator Finite_edges_iterator;
|
||
|
||
typedef details::Refine_edges_base_types<Tr> Types;
|
||
|
||
typedef typename Types::Constrained_edge Constrained_edge;
|
||
|
||
using Triangulation_mesher_level_traits_3<Tr>::triangulation_ref_impl;
|
||
|
||
public:
|
||
/** \name CONSTRUCTORS */
|
||
|
||
Refine_edges_base(Tr& t)
|
||
: Triangulation_mesher_level_traits_3<Tr>(t) {}
|
||
|
||
protected:
|
||
/* --- protected datas --- */
|
||
Container edges_to_be_conformed; /**< Edge queue */
|
||
Vertex_handle va, vb; /**< (\c va, \c vb) is the edge that will be
|
||
refined. */
|
||
|
||
bool is_encroached(Edge e) const
|
||
{
|
||
const Vertex_handle& va = e.first->vertex(e.second);
|
||
const Vertex_handle& vb = e.first->vertex(e.third);
|
||
|
||
Facet_circulator f_circ = tr.incident_facets(e), end(f_circ);
|
||
|
||
do {
|
||
|
||
// Small algorithm to retrieve the third vertex of a facet
|
||
// (ch,<2C>index), knowing two vertices (Vertex_handle) of the
|
||
// facets.
|
||
// Another implementation would be:
|
||
// int ia = c->index(va);
|
||
// int ib = c->index(vb);
|
||
// int k = 6-index-ia-ib;
|
||
//
|
||
Vertex_handle v;
|
||
for(int i = 0; i < 4; ++i)
|
||
{
|
||
if( i == (*f_circ).second ) continue;
|
||
v = (*f_circ).first->vertex(i);
|
||
if( v != va && v != vb) break;
|
||
}
|
||
// here v is the third point of the facet
|
||
|
||
typename Geom_traits::Angle_3 angle =
|
||
tr.geom_traits().angle_3_object();
|
||
|
||
/** @todo S'occuper de ces point() */
|
||
if( angle(va->point(), v->point(),
|
||
vb->point()) == OBTUSE )
|
||
return true;
|
||
|
||
++f_circ;
|
||
}
|
||
while( f_circ != end );
|
||
return false;
|
||
}
|
||
|
||
bool is_encroached(Edge e, const Bare_point& p) const
|
||
{
|
||
const Vertex_handle& va = e.first->vertex(e.second);
|
||
const Vertex_handle& vb = e.first->vertex(e.third);
|
||
return is_encroached(va, vb, p);
|
||
}
|
||
|
||
bool is_encroached(const Vertex_handle& va, const Vertex_handle& vb,
|
||
const Bare_point& p) const
|
||
{
|
||
typename Geom_traits::Angle_3 angle =
|
||
tr.geom_traits().angle_3_object();
|
||
|
||
return( angle(va->point(), p,
|
||
vb->point()) == OBTUSE );
|
||
}
|
||
|
||
bool test_if_encroached(const Vertex_handle va, const Vertex_handle vb)
|
||
{
|
||
Cell_handle c;
|
||
int i, j;
|
||
|
||
CGAL_assertion_code(bool b =) tr.is_edge(va, vb, c, i, j);
|
||
CGAL_assertion(b);
|
||
|
||
if( is_encroached(Edge(c, i, j)) )
|
||
{
|
||
edges_to_be_conformed.add_element(std::make_pair(va, vb));
|
||
return true;
|
||
}
|
||
else
|
||
return false;
|
||
}
|
||
|
||
void fill_edges_to_be_conformed()
|
||
{
|
||
for(Finite_edges_iterator it = tr.finite_edges_begin();
|
||
it != tr.finite_edges_end();
|
||
++it)
|
||
if(complex_2.is_in_complex(*it) && is_encroached(*it))
|
||
edges_to_be_conformed.add_element(std::make_pair(it->first->
|
||
vertex(it->second),
|
||
it->first->
|
||
vertex(it->third)));
|
||
}
|
||
|
||
public:
|
||
/** \name Functions that this level must declare. */
|
||
|
||
Tr& get_triangulation_ref()
|
||
{
|
||
return tr;
|
||
}
|
||
|
||
const Tr& get_triangulation_ref() const
|
||
{
|
||
return tr;
|
||
}
|
||
|
||
void do_scan_triangulation()
|
||
{
|
||
fill_edges_to_be_conformed();
|
||
}
|
||
|
||
bool is_no_longer_element_to_refine() const
|
||
{
|
||
return edges_to_be_conformed.empty();
|
||
}
|
||
|
||
Constrained_edge do_get_next_element()
|
||
{
|
||
return edges_to_be_conformed.get_next_element();
|
||
}
|
||
|
||
void do_pop_next_element()
|
||
{
|
||
edges_to_be_conformed.remove_next_element();
|
||
}
|
||
|
||
Point get_refinement_point(const Constrained_edge& edge) const
|
||
{
|
||
typename Geom_traits::Construct_midpoint_3 midpoint =
|
||
tr.geom_traits().construct_midpoint_3_object();
|
||
|
||
return midpoint(edge.first->point(),
|
||
edge.second->point());
|
||
}
|
||
|
||
void do_before_conflicts(const Constrained_edge&, const Point&)
|
||
{}
|
||
|
||
std::pair<bool, bool>
|
||
do_test_point_conflict_from_superior(const Point& p,
|
||
Zone& z)
|
||
{
|
||
bool one_edge_is_encroached = false;
|
||
|
||
for(typename Zone::Facets_iterator fit = zone.boundary_facets.begin();
|
||
fit != zone.boundary_facets.end();
|
||
++fit)
|
||
{
|
||
const Cell_handle& c = (*fit).first;
|
||
const int index = (*fit).second;
|
||
|
||
// @todo Utiliser la table vertex_triple_index et boucler
|
||
// entre 0 et 2 au lieu de faire la boucle suivante.
|
||
|
||
// 0 < i_off < j_off <4
|
||
for(int i_off = 1; i_off < 3; ++i_off)
|
||
for(int j_off = i_off+1; j_off < 4; ++j_off)
|
||
{
|
||
const int i = (index+i_off) % 4;
|
||
const int j = (index+j_off) % 4;
|
||
// (i,j) is one of the three edges of the facet *fit
|
||
const Vertex_handle& vi = c->vertex(i);
|
||
const Vertex_handle& vj = c->vertex(j);
|
||
if( vi < vj ) // (vi, vj) will be visited twice.
|
||
// BUG!!!
|
||
if( is_not_locally_Delaunay(vi, vj) )
|
||
one_edge_is_encroached = true;
|
||
}
|
||
}
|
||
// The first boolean tells if there is a conflict.
|
||
// The second one tells if the element can be dropped.
|
||
return std::make_pair(!one_edge_is_encroached, false);
|
||
// Here, can_drop=false, because the facet (from which the point
|
||
// is the circumcenter) should be refined latter.
|
||
}
|
||
|
||
std::pair<bool, bool> do_private_test_point_conflict(const Point&,
|
||
Zone& ) const
|
||
{
|
||
// nothing
|
||
return std::make_pair(true, true);
|
||
}
|
||
|
||
void do_before_insertion(const Constrained_edge& e, const Point&,
|
||
const Zone&)
|
||
{
|
||
va = e.first;
|
||
vb = e.first;
|
||
}
|
||
|
||
void do_after_insertion(const Vertex_handle& v)
|
||
{
|
||
test_if_encroached(va, v);
|
||
test_if_encroached(vb, v);
|
||
|
||
// scan edges
|
||
typedef std::list<Cell_handle> Cells;
|
||
typedef typename Cells::iterator Cell_iterator;
|
||
Cells incident_cells;
|
||
|
||
tr.incident_cells(v, std::back_inserter(incident_cells));
|
||
|
||
for(Cell_iterator it = incident_cells.begin();
|
||
it != incident_cells.end();
|
||
++it)
|
||
{
|
||
const int index = (*it)->index(v);
|
||
// for (i,j) from 0 to 3, i<j, i!=index, j!=index
|
||
for(int i = 0; i<3; ++i)
|
||
{
|
||
if(i == index) continue;
|
||
for(int j = i; j<4; ++j)
|
||
{
|
||
if(j == index) continue;
|
||
const int k = 6-index-i-j; // the last vertex
|
||
// Consider the edge (i, j).
|
||
// This edge will be twice in the zone. So one must test if
|
||
// the orientation (index, i, j, k) is positive. If not,
|
||
// the other occurence will be positively oriented.
|
||
typename Geom_traits::Orientation_3 orientation =
|
||
tr.geom_traits().orientation_3_object();
|
||
const Vertex_handle& vindex = (*it)->vertex(index);
|
||
const Vertex_handle& vi = (*it)->vertex(i);
|
||
const Vertex_handle& vj = (*it)->vertex(j);
|
||
const Vertex_handle& vk = (*it)->vertex(k);
|
||
if( orientation(vindex->point(),
|
||
vi->point(),
|
||
vj->point(),
|
||
vk->point())
|
||
== CGAL::POSITIVE )
|
||
if(complex_2.is_in_complex(*it, i, j))
|
||
test_if_encroached(vi, vj);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
}; // end Refine_edges_base
|
||
|
||
template <typename Tr,
|
||
typename Base = Refine_edges_base<Tr> >
|
||
struct Refine_edges :
|
||
public Base,
|
||
public Mesher_level <
|
||
Tr,
|
||
Refine_edges<Tr, Base>,
|
||
std::pair<typename Tr::Vertex_handle,
|
||
typename Tr::Vertex_handle>,
|
||
Null_mesher_level,
|
||
Triangulation_mesher_level_traits_3<Tr>
|
||
>
|
||
{
|
||
typedef Refine_edges<Tr, Base> Self;
|
||
typedef Mesher_level <
|
||
Tr,
|
||
Refine_edges<Tr, Base>,
|
||
std::pair<typename Tr::Vertex_handle,
|
||
typename Tr::Vertex_handle>,
|
||
Null_mesher_level,
|
||
Triangulation_mesher_level_traits_3<Tr>
|
||
> Mesher;
|
||
|
||
Refine_edges(Tr& t): Base(t), Mesher(&null_mesher_level) {}
|
||
}; // end Refine_edges
|
||
|
||
}; // end namespace Mesh_3
|
||
}; // end namespace CGAL
|
||
|
||
#endif // CGAL_MESH_3_REFINE_EDGES_H
|