mirror of https://github.com/CGAL/cgal
Add a edges mesher level that prevents edges to be refined, and let some bad triangles in the mesh (when their circumcenter encroaches a constrained edge, or when their circumcenter lies outside the meshing domain.
This commit is contained in:
parent
25ef46c2e1
commit
c5e779d227
|
|
@ -0,0 +1,362 @@
|
|||
// Copyright (c) 2004-2006 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_DELAUNAY_MESHER_NO_EDGE_REFINEMENT_2_H
|
||||
#define CGAL_DELAUNAY_MESHER_NO_EDGE_REFINEMENT_2_H
|
||||
|
||||
#include <CGAL/Mesh_2/Do_not_refine_edges.h>
|
||||
#include <CGAL/Mesh_2/Refine_faces.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template <typename Tr, typename Crit>
|
||||
class Delaunay_mesher_no_edge_refinement_2
|
||||
{
|
||||
|
||||
/** \name \c Tr types */
|
||||
typedef typename Tr::Vertex_handle Vertex_handle;
|
||||
typedef typename Tr::Face_handle Face_handle;
|
||||
typedef typename Tr::Edge Edge;
|
||||
|
||||
typedef typename Tr::Point Point;
|
||||
|
||||
/** \name Types needed for private member datas */
|
||||
typedef Mesh_2::Do_not_refine_edges<Tr,
|
||||
Mesh_2::Is_locally_conforming_Gabriel<Tr> > Edges_level_base;
|
||||
typedef Mesh_2::Refine_edges<Tr,
|
||||
Mesh_2::Is_locally_conforming_Gabriel<Tr>,
|
||||
Edges_level_base> Edges_level;
|
||||
|
||||
typedef Mesh_2::Refine_faces<Tr, Crit, Edges_level> Faces_level;
|
||||
|
||||
public:
|
||||
|
||||
typedef Tr Triangulation;
|
||||
typedef Crit Criteria;
|
||||
|
||||
/** \name Types needed to mark the domain for Delaunay_mesh_2<Tr> */
|
||||
|
||||
typedef std::list<Point> Seeds;
|
||||
typedef typename Seeds::const_iterator Seeds_iterator;
|
||||
typedef Seeds_iterator Seeds_const_iterator;
|
||||
|
||||
private:
|
||||
// --- PRIVATE MEMBER DATAS ---
|
||||
Tr& tr;
|
||||
Criteria criteria;
|
||||
Null_mesher_level null_level;
|
||||
Null_mesh_visitor null_visitor;
|
||||
Edges_level edges_level;
|
||||
Faces_level faces_level;
|
||||
|
||||
Seeds seeds;
|
||||
bool seeds_mark;
|
||||
public:
|
||||
/** \name CONSTRUCTORS */
|
||||
Delaunay_mesher_no_edge_refinement_2(Tr& tr_, const Criteria& criteria_ = Criteria())
|
||||
: tr(tr_),
|
||||
criteria(criteria_),
|
||||
null_level(),
|
||||
null_visitor(),
|
||||
edges_level(tr, null_level),
|
||||
faces_level(tr, criteria, edges_level),
|
||||
initialized(false)
|
||||
{
|
||||
}
|
||||
|
||||
Delaunay_mesher_no_edge_refinement_2(Tr& tr_, Edges_level& edges_level_,
|
||||
const Criteria& criteria_ = Criteria())
|
||||
: tr(tr_),
|
||||
criteria(criteria_),
|
||||
null_level(),
|
||||
null_visitor(),
|
||||
edges_level(edges_level_),
|
||||
faces_level(tr, criteria, edges_level),
|
||||
initialized(false)
|
||||
{
|
||||
}
|
||||
|
||||
/** SEEDS HANDLING FUNCTIONS */
|
||||
|
||||
Seeds_const_iterator seeds_begin() const
|
||||
{
|
||||
return seeds.begin();
|
||||
}
|
||||
|
||||
Seeds_const_iterator seeds_end() const
|
||||
{
|
||||
return seeds.end();
|
||||
}
|
||||
|
||||
private:
|
||||
/** \name INITIALIZED */
|
||||
|
||||
bool initialized;
|
||||
|
||||
public:
|
||||
/** \name MARKING FUNCTIONS */
|
||||
|
||||
/** The value type of \a InputIterator should be \c Point, and represents
|
||||
seeds. Connected components of seeds are marked with the value of
|
||||
\a mark. Other components are marked with \c !mark. The connected
|
||||
component of infinite faces is always marked with \c false.
|
||||
*/
|
||||
template <class InputIterator>
|
||||
void set_seeds(InputIterator b, InputIterator e,
|
||||
const bool mark = false,
|
||||
const bool do_it_now = false)
|
||||
{
|
||||
seeds.clear();
|
||||
std::copy(b, e, std::back_inserter(seeds));
|
||||
seeds_mark=mark;
|
||||
if(do_it_now) mark_facets();
|
||||
}
|
||||
|
||||
void clear_seeds()
|
||||
{
|
||||
seeds.clear();
|
||||
seeds_mark = false;
|
||||
}
|
||||
|
||||
void mark_facets(bool domain_specified = false)
|
||||
{
|
||||
if(!domain_specified) {
|
||||
mark_facets(tr, seeds.begin(), seeds.end(), seeds_mark);
|
||||
}
|
||||
else {
|
||||
propagate_marks(tr.infinite_face(), false);
|
||||
}
|
||||
}
|
||||
|
||||
/** Procedure that marks facets according to a list of seeds. */
|
||||
template <typename Seeds_it>
|
||||
static void mark_facets(Tr& tr,
|
||||
Seeds_it begin,
|
||||
Seeds_it end,
|
||||
bool mark = false)
|
||||
{
|
||||
if (tr.dimension()<2) return;
|
||||
if( begin != end )
|
||||
{
|
||||
for(typename Tr::All_faces_iterator it=tr.all_faces_begin();
|
||||
it!=tr.all_faces_end();
|
||||
++it)
|
||||
it->set_in_domain(!mark);
|
||||
|
||||
for(Seeds_it sit=begin; sit!=end; ++sit)
|
||||
{
|
||||
Face_handle fh=tr.locate(*sit);
|
||||
if(fh!=NULL)
|
||||
propagate_marks(fh, mark);
|
||||
}
|
||||
propagate_marks(tr.infinite_face(), false);
|
||||
}
|
||||
else
|
||||
mark_convex_hull(tr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks all faces of the convex hull but those connected to the
|
||||
* infinite faces.
|
||||
*/
|
||||
static void mark_convex_hull(Tr& tr)
|
||||
{
|
||||
for(typename Tr::All_faces_iterator fit=tr.all_faces_begin();
|
||||
fit!=tr.all_faces_end();
|
||||
++fit)
|
||||
fit->set_in_domain(true);
|
||||
propagate_marks(tr.infinite_face(), false);
|
||||
}
|
||||
|
||||
/** Propagates the mark \c mark recursivly. */
|
||||
static void propagate_marks(const Face_handle fh, bool mark)
|
||||
{
|
||||
// std::queue only works with std::list on VC++6, and not with
|
||||
// std::deque, which is the default
|
||||
// But it should be fixed by VC++7 know. [Laurent Rineau 2003/03/24]
|
||||
std::queue<Face_handle/*, std::list<Face_handle>*/> face_queue;
|
||||
fh->set_in_domain(mark);
|
||||
face_queue.push(fh);
|
||||
while( !face_queue.empty() )
|
||||
{
|
||||
Face_handle fh = face_queue.front();
|
||||
face_queue.pop();
|
||||
for(int i=0;i<3;i++)
|
||||
{
|
||||
const Face_handle& nb = fh->neighbor(i);
|
||||
if( !fh->is_constrained(i) && (mark != nb->is_in_domain()) )
|
||||
{
|
||||
nb->set_in_domain(mark);
|
||||
face_queue.push(nb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/** \name MESHING FUNCTIONS */
|
||||
|
||||
void refine_mesh()
|
||||
{
|
||||
if(initialized != true) init();
|
||||
faces_level.refine(null_visitor);
|
||||
}
|
||||
|
||||
/** \name REMESHING FUNCTIONS */
|
||||
|
||||
void set_criteria(const Criteria& criteria_,
|
||||
bool recalculate_bad_faces = true)
|
||||
{
|
||||
criteria = criteria_;
|
||||
if (recalculate_bad_faces) faces_level.scan_triangulation();
|
||||
}
|
||||
|
||||
const Criteria& get_criteria() const
|
||||
{
|
||||
return criteria;
|
||||
}
|
||||
|
||||
template <class Fh_it>
|
||||
void set_bad_faces(Fh_it begin, Fh_it end)
|
||||
{
|
||||
faces_level.set_bad_faces(begin, end);
|
||||
}
|
||||
|
||||
/** \name STEP BY STEP FUNCTIONS */
|
||||
|
||||
/**
|
||||
Initialize the data structures
|
||||
(The call of this function is REQUIRED before any step by step
|
||||
operation).
|
||||
*/
|
||||
void init(bool domain_specified = false)
|
||||
{
|
||||
mark_facets(domain_specified);
|
||||
edges_level.scan_triangulation();
|
||||
faces_level.scan_triangulation();
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
bool is_refinement_done ()
|
||||
{
|
||||
return faces_level.is_algorithm_done();
|
||||
};
|
||||
|
||||
bool
|
||||
step_by_step_refine_mesh()
|
||||
{
|
||||
return faces_level.try_to_insert_one_point(null_visitor);
|
||||
}
|
||||
|
||||
bool try_one_step_refine_mesh()
|
||||
{
|
||||
return faces_level.one_step(null_visitor);
|
||||
}
|
||||
|
||||
/** \name ACCESS FUNCTIONS */
|
||||
|
||||
const Triangulation& triangulation() const
|
||||
{
|
||||
return tr;
|
||||
}
|
||||
|
||||
/** \name DEBUGGING FUNCTIONS */
|
||||
|
||||
typedef typename Edges_level::Constrained_edge Constrained_edge;
|
||||
|
||||
bool is_edges_refinement_done()
|
||||
{
|
||||
return edges_level.is_algorithm_done();
|
||||
}
|
||||
|
||||
Edge next_encroached_edge()
|
||||
{
|
||||
return edges_level.get_next_element();
|
||||
}
|
||||
|
||||
const Face_handle next_bad_face()
|
||||
{
|
||||
return faces_level.get_next_element();
|
||||
}
|
||||
|
||||
const Point next_refinement_point()
|
||||
{
|
||||
if( !edges_level.is_algorithm_done() )
|
||||
return edges_level.refinement_point(next_encroached_edge());
|
||||
else
|
||||
return faces_level.refinement_point(next_bad_face());
|
||||
}
|
||||
|
||||
typedef typename Edges_level::Edges_const_iterator
|
||||
Encroached_edges_const_iterator;
|
||||
|
||||
typedef typename Faces_level::Bad_faces_const_iterator
|
||||
Bad_faces_const_iterator;
|
||||
|
||||
Encroached_edges_const_iterator encroached_edges_begin() const
|
||||
{
|
||||
return edges_level.begin();
|
||||
}
|
||||
|
||||
Encroached_edges_const_iterator encroached_edges_end() const
|
||||
{
|
||||
return edges_level.end();
|
||||
}
|
||||
|
||||
Bad_faces_const_iterator bad_faces_begin() const
|
||||
{
|
||||
return faces_level.begin();
|
||||
}
|
||||
|
||||
Bad_faces_const_iterator bad_faces_end() const
|
||||
{
|
||||
return faces_level.end();
|
||||
}
|
||||
}; // end class Delaunay_mesher_no_edge_refinement_2
|
||||
|
||||
// --- GLOBAL FUNCTIONS ---
|
||||
|
||||
template <typename Tr, typename Criteria>
|
||||
void
|
||||
refine_Delaunay_mesh_2_without_edge_refinement(Tr& t,
|
||||
const Criteria& criteria = Criteria(), bool domain_specified=false)
|
||||
{
|
||||
typedef Delaunay_mesher_no_edge_refinement_2<Tr, Criteria> Mesher;
|
||||
|
||||
Mesher mesher(t, criteria);
|
||||
mesher.init(domain_specified);
|
||||
mesher.refine_mesh();
|
||||
}
|
||||
|
||||
|
||||
template <typename Tr, typename Criteria, typename InputIterator>
|
||||
void
|
||||
refine_Delaunay_mesh_2_without_edge_refinement(Tr& t,
|
||||
InputIterator b, InputIterator e,
|
||||
const Criteria& criteria = Criteria(),
|
||||
bool mark = false)
|
||||
{
|
||||
typedef Delaunay_mesher_no_edge_refinement_2<Tr, Criteria> Mesher;
|
||||
|
||||
Mesher mesher(t, criteria);
|
||||
mesher.set_seeds(b, e, mark);
|
||||
mesher.refine_mesh();
|
||||
}
|
||||
|
||||
} // end namespace CGAL
|
||||
|
||||
#endif // CGAL_DELAUNAY_MESHER_NO_EDGE_REFINEMENT_2_H
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
// Copyright (c) 2004-2005 INRIA Sophia-Antipolis (France).
|
||||
// Copyright (c) 2009 GeometryFactory (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_2_DO_NOT_REFINE_EDGES_H
|
||||
#define CGAL_MESH_2_DO_NOT_REFINE_EDGES_H
|
||||
|
||||
#include <CGAL/Mesh_2/Refine_edges.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
namespace Mesh_2 {
|
||||
|
||||
template <
|
||||
class Tr,
|
||||
class Is_locally_conform = Is_locally_conforming_Gabriel<Tr>,
|
||||
class Container =
|
||||
typename details::Refine_edges_base_types<Tr>::Default_container
|
||||
>
|
||||
class Do_not_refine_edges :
|
||||
public Refine_edges_base<Tr, Is_locally_conform, Container>
|
||||
{
|
||||
typedef Refine_edges_base<Tr, Is_locally_conform, Container> Super;
|
||||
|
||||
typedef typename Tr::Vertex_handle Vertex_handle;
|
||||
typedef typename Tr::Face_handle Face_handle;
|
||||
typedef typename Tr::Edge Edge;
|
||||
typedef typename Tr::Point Point;
|
||||
typedef typename Tr::Geom_traits Geom_traits;
|
||||
|
||||
typedef typename Geom_traits::FT FT;
|
||||
|
||||
typedef typename Tr::Finite_edges_iterator Finite_edges_iterator;
|
||||
typedef typename Tr::Face_circulator Face_circulator;
|
||||
|
||||
typedef typename Triangulation_mesher_level_traits_2<Tr>::Zone Zone;
|
||||
|
||||
using Super::triangulation_ref_impl;
|
||||
|
||||
public:
|
||||
Do_not_refine_edges(Tr& tr_)
|
||||
: Super(tr_) {}
|
||||
|
||||
/** \name FUNCTIONS NEEDED BY Mesher_level OVERIDDEN BY THIS CLASS. */
|
||||
|
||||
void scan_triangulation_impl()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the edges of the boundary are locally conforming.
|
||||
* Push which that are not in the list of edges to be conformed.
|
||||
*/
|
||||
Mesher_level_conflict_status
|
||||
test_point_conflict_from_superior_impl(const Point& p,
|
||||
Zone& z)
|
||||
{
|
||||
if(z.locate_type != Tr::FACE || !z.fh->is_in_domain())
|
||||
return CONFLICT_AND_ELEMENT_SHOULD_BE_DROPPED;
|
||||
for(typename Zone::Edges_iterator eit = z.boundary_edges.begin();
|
||||
eit != z.boundary_edges.end(); ++eit)
|
||||
{
|
||||
const Face_handle& fh = eit->first;
|
||||
const int& i = eit->second;
|
||||
|
||||
if(fh->is_constrained(i) && !is_locally_conform(this->tr, fh, i, p))
|
||||
{
|
||||
return CONFLICT_AND_ELEMENT_SHOULD_BE_DROPPED;
|
||||
};
|
||||
}
|
||||
|
||||
return NO_CONFLICT;
|
||||
}
|
||||
|
||||
}; // end class Do_not_refine_edges
|
||||
|
||||
} // end namespace Mesh_2
|
||||
|
||||
} // end namespace CGAL
|
||||
|
||||
#endif // CGAL_MESH_2_DO_NOT_REFINE_EDGES_H
|
||||
Loading…
Reference in New Issue