cgal/Triangulation_2/include/CGAL/Constrained_triangulation_p...

650 lines
18 KiB
C++

// Copyright (c) 1997 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) : Mariette Yvinec
#ifndef CGAL_CONSTRAINED_TRIANGULATION_PLUS_2_H
#define CGAL_CONSTRAINED_TRIANGULATION_PLUS_2_H
#include <CGAL/triangulation_assertions.h>
#include <CGAL/Triangulation_short_names_2.h>
#include <CGAL/Constraint_hierarchy_2.h>
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
CGAL_BEGIN_NAMESPACE
// Tr the base triangulation class
// Tr has to be Constrained or Constrained_Delaunay
template < class Tr >
class Constrained_triangulation_plus_2
: public Tr
{
public:
typedef Tr Triangulation;
typedef typename Tr::Intersection_tag Intersection_tag;
typedef Constrained_triangulation_plus_2<Tr> Self;
typedef Tr Base;
typedef typename Triangulation::Edge Edge;
typedef typename Triangulation::Vertex Vertex;
typedef typename Triangulation::Vertex_handle Vertex_handle;
typedef typename Triangulation::Face_handle Face_handle;
typedef typename Triangulation::Vertex_iterator Vertex_iterator;
typedef typename Triangulation::Locate_type Locate_type;
typedef typename Triangulation::Line_face_circulator Line_face_circulator;
typedef typename Triangulation::Geom_traits Geom_traits;
typedef typename Geom_traits::Point_2 Point;
typedef typename Geom_traits::Segment_2 Segment;
typedef typename Triangulation::Constraint Constraint;
typedef typename Triangulation::size_type size_type;
typedef typename Triangulation::List_edges List_edges;
typedef typename Triangulation::List_faces List_faces;
typedef typename Triangulation::List_vertices List_vertices;
typedef typename Triangulation::List_constraints List_constraints;
typedef Constraint_hierarchy_2<Vertex_handle, bool> Constraint_hierarchy;
typedef Tag_true Constraint_hierarchy_tag;
// for user interface with the constraint hierarchy
typedef typename Constraint_hierarchy::H_vertex_it
Vertices_in_constraint_iterator;
typedef typename Constraint_hierarchy::H_context Context;
typedef typename Constraint_hierarchy::H_context_iterator Context_iterator;
typedef typename Constraint_hierarchy::H_c_iterator Constraint_iterator;
typedef typename Constraint_hierarchy::H_sc_iterator Subconstraint_iterator;
//for backward compatibility
typedef Vertices_in_constraint_iterator Vertices_in_constraint;
using Triangulation::geom_traits;
using Triangulation::cw;
using Triangulation::ccw;
using Triangulation::number_of_vertices;
using Triangulation::vertices_begin;
protected:
Constraint_hierarchy hierarchy;
public:
Constrained_triangulation_plus_2(const Geom_traits& gt=Geom_traits())
: Triangulation(gt) { }
Constrained_triangulation_plus_2(const Self& ctp)
: Triangulation() { copy_triangulation(ctp);}
virtual ~Constrained_triangulation_plus_2() {}
Constrained_triangulation_plus_2 & operator=(const Self& ctp);
Constrained_triangulation_plus_2(List_constraints& lc,
const Geom_traits& gt=Geom_traits())
: Triangulation(gt)
{
typename List_constraints::iterator lcit=lc.begin();
for( ;lcit != lc.end(); lcit++) {
insert_constraint( (*lcit).first, (*lcit).second);
}
CGAL_triangulation_postcondition( this->is_valid() );
}
template<class InputIterator>
Constrained_triangulation_plus_2(InputIterator first,
InputIterator last,
const Geom_traits& gt=Geom_traits() )
: Triangulation(gt)
{
while( first != last){
insert_constraint((*first).first, (*first).second);
++first;
}
CGAL_triangulation_postcondition( this->is_valid() );
}
//Helping
void clear() { Base::clear(); hierarchy.clear();}
void copy_triangulation(const Constrained_triangulation_plus_2 &ctp);
void swap(Constrained_triangulation_plus_2 &ctp);
// INSERTION
Vertex_handle insert(const Point& a,
Face_handle start = Face_handle() );
Vertex_handle insert(const Point& p,
Locate_type lt,
Face_handle loc, int li );
void insert_constraint(const Point& a, const Point& b);
void insert_constraint(Vertex_handle va, Vertex_handle vb);
// template < class InputIterator >
// int insert(InputIterator first, InputIterator last);
Vertex_handle push_back(const Point& a);
void push_back(const Constraint& c);
//for backward compatibility
// not const Point&, because otherwise VC6/7 messes it up with
// the insert that takes an iterator range
void insert(Point a, Point b) { insert_constraint(a, b);}
void insert(Vertex_handle va, Vertex_handle vb) {insert_constraint(va,vb);}
virtual Vertex_handle intersect(Face_handle f, int i,
Vertex_handle vaa,
Vertex_handle vbb);
Vertex_handle intersect(Face_handle f, int i,
Vertex_handle vaa,
Vertex_handle vbb,
No_intersection_tag);
Vertex_handle intersect(Face_handle f, int i,
Vertex_handle vaa,
Vertex_handle vbb,
Exact_intersections_tag);
Vertex_handle intersect(Face_handle f, int i,
Vertex_handle vaa,
Vertex_handle vbb,
Exact_predicates_tag);
// REMOVAL
void remove_constraint(Vertex_handle va, Vertex_handle vb);
// Query of the constraint hierarchy
Constraint_iterator constraints_begin() const;
Constraint_iterator constraints_end() const;
Subconstraint_iterator subconstraints_begin() const;
Subconstraint_iterator subconstraints_end() const;
Context context(Vertex_handle va, Vertex_handle vb);
size_type number_of_enclosing_constraints(Vertex_handle va,
Vertex_handle vb);
Context_iterator contexts_begin(Vertex_handle va,
Vertex_handle vb);
Context_iterator contexts_end(Vertex_handle va,
Vertex_handle vb);
Vertices_in_constraint_iterator
vertices_in_constraint_begin(Vertex_handle va,
Vertex_handle vb);
Vertices_in_constraint_iterator
vertices_in_constraint_end(Vertex_handle va,
Vertex_handle vb);
size_type number_of_constraints() {
return static_cast<size_type> (hierarchy.number_of_constraints());}
size_type number_of_subconstraints(){
return static_cast<size_type> (hierarchy.number_of_subconstraints());}
protected:
void insert_subconstraint(Vertex_handle va,Vertex_handle vb);
//to debug
public:
void print_hierarchy() { hierarchy.print(); }
//template member functions
public:
template < class InputIterator >
#if defined(_MSC_VER)
int insert(InputIterator first, InputIterator last, int i = 0)
#else
int insert(InputIterator first, InputIterator last)
#endif
{
int n = number_of_vertices();
std::vector<Point> points (first, last);
std::random_shuffle (points.begin(), points.end());
spatial_sort (points.begin(), points.end(), geom_traits());
Face_handle hint;
for (typename std::vector<Point>::const_iterator p = points.begin(), end = points.end();
p != end; ++p)
hint = insert (*p, hint)->face();
return number_of_vertices() - n;
}
template <class OutputItFaces>
OutputItFaces
remove_constraint(Vertex_handle va,
Vertex_handle vb,
OutputItFaces out) {
CGAL_triangulation_precondition(hierarchy.is_constrained_edge(va,vb));
for(Vertices_in_constraint_iterator it =
hierarchy.vertices_in_constraint_begin(va,vb), succ = it;
++succ != hierarchy.vertices_in_constraint_end(va,vb);
++it){
Face_handle fh;
int i;
CGAL_triangulation_assertion_code( bool b = )
Triangulation::is_edge(*it, *succ, fh, i);
CGAL_triangulation_assertion(b);
// this does also flipping if necessary.
Triangulation::remove_constrained_edge(fh,i,out);
}
hierarchy.remove_constraint(va,vb);
return out;
}
};
template <class Tr>
void
Constrained_triangulation_plus_2<Tr>::
copy_triangulation(const Constrained_triangulation_plus_2 &ctp)
{
Base::copy_triangulation(ctp);
//the following assume that the triangulation and its copy
// iterates on their vertices on the same order
std::map<Vertex_handle,Vertex_handle> vmap;
Vertex_iterator vit = ctp.vertices_begin();
Vertex_iterator vvit = vertices_begin();
for( ; vit != ctp.vertices_end(); ++vit, ++vvit) {
CGAL_triangulation_assertion(vit->point() == vvit->point());
vmap[vit] = vvit;
}
hierarchy.copy(ctp.hierarchy, vmap);
}
template <class Tr>
void
Constrained_triangulation_plus_2<Tr>::
swap(Constrained_triangulation_plus_2 &ctp)
{
Base::swap(ctp);
hierarchy.swap(ctp.hierarchy);
}
template <class Tr>
Constrained_triangulation_plus_2<Tr>&
Constrained_triangulation_plus_2<Tr>::
operator=(const Constrained_triangulation_plus_2 &ctp)
{
copy_triangulation(ctp);
return *this;
}
template <class Tr>
inline
typename Constrained_triangulation_plus_2<Tr>::Vertex_handle
Constrained_triangulation_plus_2<Tr>::
push_back(const Point &p)
{
return insert(p);
}
template <class Tr>
inline
void
Constrained_triangulation_plus_2<Tr>::
push_back(const Constraint &c)
{
insert_constraint(c.first, c.second);
}
template < class Tr >
inline
typename Constrained_triangulation_plus_2<Tr>::Vertex_handle
Constrained_triangulation_plus_2<Tr>::
insert(const Point& a, Face_handle start)
{
Locate_type lt;
int li;
Face_handle loc = locate(a, lt, li, start);
return insert(a,lt,loc,li);
}
template < class Tr>
typename Constrained_triangulation_plus_2<Tr>::Vertex_handle
Constrained_triangulation_plus_2<Tr>::
insert(const Point& a, Locate_type lt, Face_handle loc, int li)
{
Vertex_handle v1, v2;
bool insert_in_constrained_edge = false;
if ( lt == Triangulation::EDGE && loc->is_constrained(li) ){
insert_in_constrained_edge = true;
v1=loc->vertex(ccw(li)); //endpoint of the constraint
v2=loc->vertex(cw(li)); // endpoint of the constraint
}
Vertex_handle va = Triangulation::insert(a,lt,loc,li);
// update the hierarchy
if (insert_in_constrained_edge) {
hierarchy.split_constraint(v1,v2,va);
}
return va;
}
template <class Tr>
inline void
Constrained_triangulation_plus_2<Tr>::
insert_constraint(const Point& a, const Point& b)
// insert endpoints first
{
Vertex_handle va= insert(a);
// If the segment is "short" it is a good idea to start the next insertion
// close to point a
// Otherwise, to start here is as good as elsewhere
Vertex_handle vb = insert(b, va->face());
insert_constraint(va, vb);
}
template <class Tr>
inline void
Constrained_triangulation_plus_2<Tr>::
insert_constraint(Vertex_handle va, Vertex_handle vb)
{
if( va != vb ){
// protects against inserting twice the same constraint
bool no_twice = hierarchy.insert_constraint(va, vb);
if ( no_twice ){
insert_subconstraint(va,vb);
}
}
return;
}
template <class Tr>
inline void
Constrained_triangulation_plus_2<Tr>::
insert_subconstraint(Vertex_handle vaa,
Vertex_handle vbb)
// insert the subconstraint [vaa vbb]
// it will eventually be splitted into several subconstraints
{
CGAL_triangulation_precondition( vaa != vbb);
Vertex_handle vi;
Face_handle fr;
int i;
if(includes_edge(vaa,vbb,vi,fr,i)) {
mark_constraint(fr,i);
if (vi != vbb) {
hierarchy.split_constraint(vaa,vbb,vi);
insert_subconstraint(vi,vbb);
}
return;
}
List_faces intersected_faces;
List_edges conflict_boundary_ab, conflict_boundary_ba;
bool intersection = find_intersected_faces( vaa, vbb,
intersected_faces,
conflict_boundary_ab,
conflict_boundary_ba,
vi);
if ( intersection) {
if (vi != vaa && vi != vbb) {
hierarchy.split_constraint(vaa,vbb,vi);
insert_subconstraint(vaa,vi);
insert_subconstraint(vi,vbb);
}
else insert_subconstraint(vaa,vbb);
return;
}
//no intersection
triangulate_hole(intersected_faces,
conflict_boundary_ab,
conflict_boundary_ba);
if (vi != vbb) {
hierarchy.split_constraint(vaa,vbb,vi);
insert_subconstraint(vi,vbb);
}
return;
}
template <class Tr>
typename Constrained_triangulation_plus_2<Tr>:: Vertex_handle
Constrained_triangulation_plus_2<Tr>::
intersect(Face_handle f, int i,
Vertex_handle vaa,
Vertex_handle vbb)
{
return intersect(f, i, vaa, vbb, Intersection_tag());
}
template <class Tr>
typename Constrained_triangulation_plus_2<Tr>:: Vertex_handle
Constrained_triangulation_plus_2<Tr>::
intersect(Face_handle , int ,
Vertex_handle ,
Vertex_handle ,
No_intersection_tag)
{
std::cerr << " sorry, this triangulation does not deal with"
<< std::endl
<< " intersecting constraints" << std::endl;
CGAL_triangulation_assertion(false);
return Vertex_handle();
}
template <class Tr>
typename Constrained_triangulation_plus_2<Tr>:: Vertex_handle
Constrained_triangulation_plus_2<Tr>::
intersect(Face_handle f, int i,
Vertex_handle vaa,
Vertex_handle vbb,
Exact_intersections_tag)
// compute the intersection of the constraint edge (f,i)
// with the subconstraint (vaa,vbb) being inserted
// insert the intersection point
// (the constraint edge (f,i) will be splitted in hierarchy by insert)
// and return the Vertex_handle of the new Vertex
{
Vertex_handle vc, vd, va, vb;
Vertex_handle vcc, vdd;
vcc = f->vertex(cw(i));
vdd = f->vertex(ccw(i));
CGAL_triangulation_assertion_code( bool b1 = )
hierarchy.enclosing_constraint(vcc,vdd,vc,vd);
CGAL_triangulation_assertion_code( bool b2 = )
hierarchy.enclosing_constraint(vaa,vbb,va,vb);
CGAL_triangulation_assertion(b1);
CGAL_triangulation_assertion(b2);
const Point& pa = va->point();
const Point& pb = vb->point();
const Point& pc = vc->point();
const Point& pd = vd->point();
Point pi;
Intersection_tag itag = Intersection_tag();
CGAL_triangulation_assertion_code( bool ok = )
intersection(geom_traits(), pa, pb, pc, pd, pi, itag );
CGAL_triangulation_assertion(ok);
Vertex_handle vi = insert(pi, Triangulation::EDGE, f, i);
return vi;
}
template <class Tr>
typename Constrained_triangulation_plus_2<Tr>::Vertex_handle
Constrained_triangulation_plus_2<Tr>::
intersect(Face_handle f, int i,
Vertex_handle vaa,
Vertex_handle vbb,
Exact_predicates_tag)
{
Vertex_handle vcc, vdd;
vcc = f->vertex(cw(i));
vdd = f->vertex(ccw(i));
const Point& pa = vaa->point();
const Point& pb = vbb->point();
const Point& pc = vcc->point();
const Point& pd = vdd->point();
Point pi; //creator for point is required here
Intersection_tag itag = Intersection_tag();
bool ok = intersection(geom_traits(), pa, pb, pc, pd, pi, itag );
Vertex_handle vi;
if ( !ok) { //intersection detected but not computed
int i = limit_intersection(geom_traits(), pa, pb, pc, pd, itag);
switch(i){
case 0 : vi = vaa; break;
case 1 : vi = vbb; break;
case 2 : vi = vcc; break;
case 3 : vi = vdd; break;
}
}
else{ //computed
Triangulation::remove_constrained_edge(f, i);
vi = insert(pi, f);
}
// vi == vc or vi == vd may happen even if intersection==true
// due to approximate construction of the intersection
if (vi != vcc && vi != vdd) {
hierarchy.split_constraint(vcc,vdd,vi);
insert_subconstraint(vcc,vi);
insert_subconstraint(vi, vdd);
}
else {
insert_subconstraint(vcc,vdd);
}
return vi;
}
// This remove_constraint leaves all vertices in the triangulation
template <class Tr>
void
Constrained_triangulation_plus_2<Tr>::
remove_constraint(Vertex_handle va, Vertex_handle vb)
{
remove_constraint(va, vb, Emptyset_iterator());
}
template <class Tr>
std::ostream &
operator<<(std::ostream& os,
const Constrained_triangulation_plus_2<Tr> &ct)
{
ct.file_output(os);
return os ;
}
// Constraint Hierarchy Queries
template <class Tr>
inline
typename
Constrained_triangulation_plus_2<Tr>::Constraint_iterator
Constrained_triangulation_plus_2<Tr>::
constraints_begin() const
{
return hierarchy.c_begin();
}
template <class Tr>
inline
typename
Constrained_triangulation_plus_2<Tr>::Constraint_iterator
Constrained_triangulation_plus_2<Tr>::
constraints_end() const
{
return hierarchy.c_end();
}
template <class Tr>
inline
typename
Constrained_triangulation_plus_2<Tr>::Subconstraint_iterator
Constrained_triangulation_plus_2<Tr>::
subconstraints_begin() const
{
return hierarchy.sc_begin();
}
template <class Tr>
inline
typename
Constrained_triangulation_plus_2<Tr>::Subconstraint_iterator
Constrained_triangulation_plus_2<Tr>::
subconstraints_end() const
{
return hierarchy.sc_end();
}
template <class Tr>
inline
typename Constrained_triangulation_plus_2<Tr>::Context
Constrained_triangulation_plus_2<Tr>::
context(Vertex_handle va, Vertex_handle vb)
{
return hierarchy.context(va,vb);
}
template <class Tr>
inline
typename Constrained_triangulation_plus_2<Tr>::size_type
Constrained_triangulation_plus_2<Tr>::
number_of_enclosing_constraints(Vertex_handle va, Vertex_handle vb)
{
return static_cast<size_type>
(hierarchy.number_of_enclosing_constraints(va,vb));
}
template <class Tr>
inline
typename Constrained_triangulation_plus_2<Tr>::Context_iterator
Constrained_triangulation_plus_2<Tr>::
contexts_begin(Vertex_handle va, Vertex_handle vb)
{
return hierarchy.contexts_begin(va,vb);
}
template <class Tr>
inline
typename Constrained_triangulation_plus_2<Tr>::Context_iterator
Constrained_triangulation_plus_2<Tr>::
contexts_end(Vertex_handle va, Vertex_handle vb)
{
return hierarchy.contexts_end(va,vb);
}
template <class Tr>
inline
typename Constrained_triangulation_plus_2<Tr>::Vertices_in_constraint_iterator
Constrained_triangulation_plus_2<Tr>::
vertices_in_constraint_begin(Vertex_handle va, Vertex_handle vb)
{
return hierarchy.vertices_in_constraint_begin(va,vb);
}
template <class Tr>
inline
typename Constrained_triangulation_plus_2<Tr>::Vertices_in_constraint_iterator
Constrained_triangulation_plus_2<Tr>::
vertices_in_constraint_end(Vertex_handle va, Vertex_handle vb)
{
return hierarchy.vertices_in_constraint_end(va,vb);
}
CGAL_END_NAMESPACE
#endif //CGAL_CONSTRAINED_TRIANGULATION_PLUS_2_H