First setup for the segment traverser small feature.

This commit is contained in:
Thijs van Lankveld 2014-06-13 14:42:51 +02:00 committed by Jane Tournois
parent 2f7eb3aed5
commit 5640b84b2b
19 changed files with 1244 additions and 2900 deletions

View File

@ -1,105 +0,0 @@
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Conforming_Delaunay_triangulation_3.h>
#include <CGAL/Triangulation_vertex_base_with_info_3.h>
typedef CGAL::Exact_predicates_exact_constructions_kernel K;
typedef K::Point_3 Point_3;
typedef CGAL::Triangulation_vertex_base_with_info_3<int,K,CGAL::Conforming_triangulation_vertex_base_3<K> > Vb;
typedef CGAL::Conforming_triangulation_cell_base_3<K> Cb;
typedef CGAL::Triangulation_data_structure_3 < Vb, Cb > Tds;
typedef CGAL::Conforming_Delaunay_triangulation_3< K, Tds > CDT3;
template <class Triangulation, class InputIterator>
std::ptrdiff_t insert_with_info(Triangulation& t, InputIterator first,InputIterator last)
{
typedef typename Triangulation::Geom_traits Geom_traits;
typedef typename Triangulation::Vertex_handle Vertex_handle;
std::size_t n = t.number_of_vertices();
std::vector<std::ptrdiff_t> indices;
std::vector<Point_3> points;
std::vector<typename Triangulation::Vertex::Info> infos;
std::ptrdiff_t index=0;
for (InputIterator it=first;it!=last;++it){
std::pair<Point_3,int> value=*it;
points.push_back( value.first );
infos.push_back ( value.second );
indices.push_back(index++);
}
typedef CGAL::Spatial_sort_traits_adapter_3<Geom_traits,Point_3*> Search_traits;
CGAL::spatial_sort(indices.begin(),indices.end(),Search_traits(&(points[0]),Geom_traits()));
Vertex_handle hint;
for (typename std::vector<std::ptrdiff_t>::const_iterator
it = indices.begin(), end = indices.end();
it != end; ++it){
hint = t.insert(points[*it], hint);
if (hint!=Vertex_handle()) hint->info()=infos[*it];
}
return t.number_of_vertices() - n;
}
int main()
{
std::vector< std::pair<Point_3,int> > points;
points.push_back( std::make_pair(Point_3(0,0,0),0) );
points.push_back( std::make_pair(Point_3(1,0,0),1) );
points.push_back( std::make_pair(Point_3(0,1,0),2) );
points.push_back( std::make_pair(Point_3(0.2,0.2,100),3) );
points.push_back( std::make_pair(Point_3(0.2,0.2,-100),4) );
std::vector< std::pair<int, int> > constraints;
constraints.push_back( std::make_pair(0,1) );
constraints.push_back( std::make_pair(0,2) );
constraints.push_back( std::make_pair(1,2) );
constraints.push_back( std::make_pair(3,4) );
CDT3 cdt3;
insert_with_info( cdt3, points.begin(), points.end() );
std::vector< CDT3::Vertex_handle > vertices( points.size() );
for (CDT3::Finite_vertices_iterator vit=cdt3.finite_vertices_begin(),
vit_end=cdt3.finite_vertices_end();vit!=vit_end;++vit)
{
vertices[ vit->info() ]=vit;
}
std::cout << cdt3.number_of_vertices() << std::endl;
std::cout << "Making Delaunay conform" << std::endl;
for (std::vector< std::pair<int,int> >::iterator cst_it=constraints.begin(),
cst_end=constraints.end();
cst_it!=cst_end; ++cst_it)
{
cdt3.insert_conforming( std::make_pair(vertices[cst_it->first], vertices[cst_it->second]) );
}
for(CDT3::Finite_edges_iterator it=cdt3.finite_edges_begin(); it!=cdt3.finite_edges_end(); ++it)
if ( it->first->vertex(it->second)->steiner() || it->first->vertex(it->third)->steiner() )
std::cout << "edge with steiner endpoint" << std::endl;
std::cout << "Making Gabriel conform" << std::endl;
for (std::vector< std::pair<int,int> >::iterator cst_it=constraints.begin(),
cst_end=constraints.end();
cst_it!=cst_end; ++cst_it)
{
cdt3.insert_conforming_Gabriel( vertices[cst_it->first], vertices[cst_it->second] );
}
for(CDT3::Finite_edges_iterator it=cdt3.finite_edges_begin(); it!=cdt3.finite_edges_end(); ++it)
if ( it->first->vertex(it->second)->steiner() || it->first->vertex(it->third)->steiner() )
std::cout << "edge with steiner endpoint" << std::endl;
}

View File

@ -1,179 +0,0 @@
//A tetrahedral cell in a conforming Delaunay triangulation.
//Copyright (C) 2012 Utrecht University
//
//This program is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// Author(s): Thijs van Lankveld
// Based on CGAL/Triangulation_cell_base_3.h
//
// Note that a constrained 3D Delaunay triangulation is partially conforming and guided.
// 1-dimensional constraints are specified by segments.
// 2-demensional constraints are specified by closure complete polygons.
// The constrained 3D DT must contain a collection of edges and faces that exactly cover
// each constrained segment or polygon. For example, a constrained edge will not necessarily
// be maintained as vertices are inserted, but after updating the triangulation to the vertex
// insertion, the constrained edge must be the union of one or more constrained edges.
#ifndef CGAL_CONFORMING_TRIANGULATION_CELL_BASE_3_H
#define CGAL_CONFORMING_TRIANGULATION_CELL_BASE_3_H
#include <CGAL/basic.h>
#include <CGAL/triangulation_assertions.h>
#include <CGAL/Triangulation_cell_base_3.h>
namespace CGAL {
template < typename Gt, typename Cb = Triangulation_cell_base_3<Gt> >
class Conforming_triangulation_cell_base_3: public Cb {
public:
typedef typename Cb::Vertex_handle Vertex_handle;
typedef typename Cb::Cell_handle Cell_handle;
typedef Gt Geom_traits;
typedef typename Geom_traits::Point_3 Point;
typedef Point* Point_container;
typedef Point* Point_iterator;
typedef const Point* Point_const_iterator;
template < typename TDS2 >
struct Rebind_TDS {
typedef typename Cb::template Rebind_TDS<TDS2>::Other Cb2;
typedef Conforming_triangulation_cell_base_3<Gt, Cb2> Other;
}; // Rebind_TDS
protected:
// The edge states.
bool EF[6];
bool mm[6];
public:
Conforming_triangulation_cell_base_3(): Cb() {clear_conforming();}
Conforming_triangulation_cell_base_3(const Vertex_handle& v0, const Vertex_handle& v1,
const Vertex_handle& v2, const Vertex_handle& v3)
: Cb(v0, v1, v2, v3) {clear_conforming();}
Conforming_triangulation_cell_base_3(const Vertex_handle& v0, const Vertex_handle& v1,
const Vertex_handle& v2, const Vertex_handle& v3,
const Cell_handle& n0, const Cell_handle& n1,
const Cell_handle& n2, const Cell_handle& n3)
: Cb(v0, v1, v2, v3, n0, n1, n2, n3) {clear_conforming();}
bool is_conforming(int i, int j) const {return EF[getEdgeIndex(i,j)];}
bool is_marked(int i, int j) const {return mm[getEdgeIndex(i,j)];}
void set_conforming(bool c0, bool c1, bool c2, bool c3, bool c4, bool c5) {
EF[0] = c0;
EF[1] = c1;
EF[2] = c2;
EF[3] = c3;
EF[4] = c4;
EF[5] = c5;
clear_marked();
}
void set_conforming(int i, int j, bool c) {
int index = getEdgeIndex(i,j);
EF[index] = c;
mm[index] = false;
}
void mark(int i, int j) {
int index = getEdgeIndex(i,j);
EF[index] = true;
mm[index] = true;
}
void clear_conforming() {set_conforming(false, false, false, false, false, false);}
void clear_marked() {
mm[0] = false;
mm[1] = false;
mm[2] = false;
mm[3] = false;
mm[4] = false;
mm[5] = false;
}
virtual void clear() {clear_conforming();}
bool has_conforming() const {return EF[0] || EF[1] || EF[2] || EF[3] || EF[4] || EF[5];}
virtual void reorient() {
bool tmp = EF[1];
EF[1] = EF[3];
EF[3] = tmp;
tmp = mm[1];
mm[1] = mm[3];
mm[3] = tmp;
}
virtual std::istream& read_cell(std::istream& is);
virtual std::ostream& write_cell(std::ostream& os) const;
private:
int getEdgeIndex(int i, int j) const {
CGAL_triangulation_precondition(i>=0 && i<=3);
CGAL_triangulation_precondition(j>=0 && j<=3);
CGAL_triangulation_precondition(i != j);
return (i==0 || j==0) ? i+j-1 : i+j;
}
}; // Conforming_triangulation_cell_base_3
template < class Gt, class Cb >
inline std::istream& operator>>(std::istream& is, Conforming_triangulation_cell_base_3<Gt, Cb>& c) {
is >> static_cast<Cb&>(c);
return c.read_cell(is);
}
template < class Gt, class Cb >
inline std::ostream& operator<<(std::ostream &os, const Conforming_triangulation_cell_base_3<Gt, Cb>& c) {
os << static_cast<const Cb&>(c);
return c.write_cell(os);
}
template < class Gt, class Cb >
std::istream& Conforming_triangulation_cell_base_3<Gt, Cb>::read_cell(std::istream& is) {
char s;
for (int i = 0; i < 4; ++i) {
for (int j = i+1; j < 4; ++j) {
if (is_ascii(is))
is >> s;
else
read(is, s);
if (s == 'C')
set_conforming(i, j, true);
}
}
return is;
}
template < class Gt, class Cb >
std::ostream& Conforming_triangulation_cell_base_3<Gt, Cb>::write_cell(std::ostream& os) const {
for (int i = 0; i < 4; ++i) {
for (int j = i+1; j < 4; ++j) {
if (is_conforming(i, j)) {
os << "C";
}
else
os << "N";
if (is_ascii(os))
os << ' ';
}
}
return os;
}
} //end of CGAL namespace
#endif // CGAL_CONFORMING_TRIANGULATION_CELL_BASE_3_H

View File

@ -1,69 +0,0 @@
//A vertex in the conforming Delaunay triangulation structure.
//Copyright (C) 2012 Utrecht University
//
//This program is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// Author(s): Thijs van Lankveld
#ifndef CGAL_CONFORMING_TRIANGULATION_VERTEX_BASE_3_H
#define CGAL_CONFORMING_TRIANGULATION_VERTEX_BASE_3_H
#include <CGAL/Triangulation_vertex_base_3.h>
namespace CGAL {
template < typename GT, typename Vb = Triangulation_vertex_base_3<GT> >
class Conforming_triangulation_vertex_base_3: public Vb {
bool _s;
public:
typedef typename Vb::Cell_handle Cell_handle;
typedef typename Vb::Point Point;
template < typename TDS2 > struct Rebind_TDS {
typedef typename Vb::template Rebind_TDS<TDS2>::Other Vb2;
typedef Conforming_triangulation_vertex_base_3<GT, Vb2> Other;
};
Conforming_triangulation_vertex_base_3(): Vb(), _s(false) {}
Conforming_triangulation_vertex_base_3(const Point& p): Vb(p), _s(false) {}
Conforming_triangulation_vertex_base_3(const Point& p, bool s): Vb(p), _s(s) {}
Conforming_triangulation_vertex_base_3(const Point& p, Cell_handle c): Vb(p, c), _s(false) {}
Conforming_triangulation_vertex_base_3(const Point& p, bool s, Cell_handle c): Vb(p, c), _s(s) {}
Conforming_triangulation_vertex_base_3(Cell_handle c): Vb(c), _s(false) {}
const bool& steiner() const {return _s;}
bool& steiner() {return _s;}
};
template < class GT, class Vb >
std::istream&
operator>>(std::istream &is, Conforming_triangulation_vertex_base_3<GT, Vb> &v) {
is >> static_cast<Vb&>(v);
if (is_ascii(is)) is >> v.steiner();
else read(is, v.steiner());
return is;
}
template < class GT, class Vb >
std::ostream&
operator<<(std::ostream &os, const Conforming_triangulation_vertex_base_3<GT, Vb> &v) {
os << static_cast<const Vb&>(v);
if (is_ascii(os)) os << ' ';
return os << v.steiner();
}
} //end of CGAL namespace
#endif // CGAL_CONFORMING_TRIANGULATION_VERTEX_BASE_3_H

View File

@ -1,406 +0,0 @@
//Some additional utilities for the Delaunay triangulation structure.
//Copyright (C) 2012 Utrecht University
//
//This program is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// Author(s): Thijs van Lankveld
// Based on CGAL/Delaunay_triangulation_3.h
//
// For the love of something, why is the 3D triangulation package so badly written?
#ifndef CGAL_DELAUNAY_TRIANGULATION_3_UTILS_H
#define CGAL_DELAUNAY_TRIANGULATION_3_UTILS_H
#include <CGAL/basic.h>
#include <utility>
#include <vector>
#include <CGAL/Delaunay_triangulation_3.h>
#include <CGAL/Triangulation_segment_traverser_3.h>
namespace CGAL {
template < class DT > class Natural_neighbors_3;
template < class Gt, class Tds > class Triangulation_cell_traverser_3;
template < class Gt,
class Tds_ = Triangulation_data_structure_3 < Triangulation_vertex_base_3<Gt>, Triangulation_cell_base_3<Gt> > >
class Delaunay_triangulation_utils_3: public Delaunay_triangulation_3<Gt, Tds_> {
//typedef Triangulation_data_structure Tds;
typedef Tds_ Tds;
typedef Delaunay_triangulation_utils_3<Gt, Tds> Self;
typedef Delaunay_triangulation_3<Gt, Tds> DT;
typedef Triangulation_3<Gt,Tds> Tr;
friend class Natural_neighbors_3<Self>;
public:
typedef Tds Triangulation_data_structure;
typedef Gt Geom_traits;
typedef typename Gt::FT FT;
typedef typename Gt::Point_3 Point;
typedef typename Gt::Vector_3 Vector;
typedef typename Gt::Segment_3 Segment;
typedef typename Gt::Line_3 Line;
typedef typename Gt::Triangle_3 Triangle;
typedef typename Gt::Tetrahedron_3 Tetrahedron;
typedef typename Gt::Plane_3 Plane;
typedef typename DT::Cell_handle Cell_handle;
typedef typename DT::Vertex_handle Vertex_handle;
typedef typename DT::Cell Cell;
typedef typename DT::Vertex Vertex;
typedef typename DT::Facet Facet;
typedef typename DT::Edge Edge;
typedef std::pair<Vertex_handle, Vertex_handle> Bi_vertex;
typedef Triple<Vertex_handle, Vertex_handle, Vertex_handle> Tri_vertex;
typedef std::pair<Point, Point> Constraint_1;
typedef std::vector<Point> Constraint_2;
typedef typename DT::Cell_circulator Cell_circulator;
typedef typename DT::Facet_circulator Facet_circulator;
typedef typename DT::Cell_iterator Cell_iterator;
typedef typename DT::Facet_iterator Facet_iterator;
typedef typename DT::Edge_iterator Edge_iterator;
typedef typename DT::Vertex_iterator Vertex_iterator;
typedef typename DT::Finite_vertices_iterator Finite_vertices_iterator;
typedef typename DT::Finite_cells_iterator Finite_cells_iterator;
typedef typename DT::Finite_facets_iterator Finite_facets_iterator;
typedef typename DT::Finite_edges_iterator Finite_edges_iterator;
typedef typename DT::All_cells_iterator All_cells_iterator;
typedef Triangulation_segment_traverser_3<Gt,Tds> Cell_traverser;
typedef typename DT::Locate_type Locate_type;
#ifndef CGAL_CFG_USING_BASE_MEMBER_BUG_2
using DT::cw;
using DT::ccw;
using DT::coplanar;
using DT::coplanar_orientation;
using DT::dimension;
using DT::finite_facets_begin;
using DT::finite_facets_end;
using DT::finite_vertices_begin;
using DT::finite_vertices_end;
using DT::finite_cells_begin;
using DT::finite_cells_end;
using DT::finite_edges_begin;
using DT::finite_edges_end;
using DT::geom_traits;
using DT::infinite_vertex;
using DT::is_valid;
using DT::mirror_vertex;
using DT::next_around_edge;
using DT::number_of_vertices;
using DT::orientation;
using DT::remove;
using DT::coplanar_side_of_bounded_circle;
using DT::side_of_oriented_sphere;
using DT::side_of_segment;
using DT::tds;
using DT::vertex_triple_index;
using DT::locate;
using DT::insert_in_conflict;
using DT::is_infinite;
using DT::insert;
#endif
protected:
typedef std::list<Tri_vertex> Tri_vertex_collection;
typedef std::list<Bi_vertex> Bi_vertex_collection;
protected:
// Test whether a newly inserted point conflicts with the existing cells.
class Conflict_tester_3 {
protected:
const Point& _p;
const Self* _tr;
public:
Conflict_tester_3(const Point& pt, const Self* tr): _p(pt), _tr(tr) {}
bool operator()(const Cell_handle c) const {return _tr->side_of_sphere(c, _p, true) == ON_BOUNDED_SIDE;}
Oriented_side compare_weight(const Point&, const Point&) const {return ZERO;}
bool test_initial_cell(Cell_handle) const {return true;}
}; // class Conflict_tester_3
// Test whether a newly inserted point conflicts with the existing cells.
class Conflict_tester_2 {
protected:
const Point& _p;
const Self* _tr;
public:
Conflict_tester_2(const Point& pt, const Self* tr): _p(pt), _tr(tr) {}
bool operator()(const Cell_handle c) const {return _tr->side_of_circle(c, 3, _p, true) == ON_BOUNDED_SIDE;}
Oriented_side compare_weight(const Point&, const Point&) const {return ZERO;}
bool test_initial_cell(Cell_handle) const {return true;}
}; // class Conflict_tester_2
class Hidden_point_visitor {
public:
Hidden_point_visitor() {}
template < class InputIterator >
void process_cells_in_conflict(InputIterator, InputIterator) const {}
void reinsert_vertices(Vertex_handle) {}
Vertex_handle replace_vertex(Cell_handle c, int index, const Point&) {return c->vertex(index);}
void hide_point(Cell_handle, const Point&) {}
}; // class Hidden_point_visitor
Hidden_point_visitor hidden_point_visitor;
public:
// Constructors for bi-vertices.
inline Bi_vertex to_bi_vertex(Cell_handle c, int li, int lj) const {return Bi_vertex(c->vertex(li), c->vertex(lj));}
inline Bi_vertex to_bi_vertex(const Edge& e) const {return to_bi_vertex(e.first, e.second, e.third);}
inline Bi_vertex sort_bi_vertex(Vertex_handle v1, Vertex_handle v2) const {if (v1 < v2) return Bi_vertex(v1, v2); return Bi_vertex(v2, v1);}
inline Bi_vertex sort_bi_vertex(const Bi_vertex& bv) const {return sort_bi_vertex(bv.first, bv.second);}
inline Bi_vertex sort_bi_vertex(Cell_handle c, int li, int lj) const {return sort_bi_vertex(c->vertex(li), c->vertex(lj));}
inline Bi_vertex sort_bi_vertex(const Edge& e) const {return sort_bi_vertex(e.first, e.second, e.third);}
// Constructors for tri-vertices.
inline Tri_vertex to_tri_vertex(Cell_handle c, int li) const {return Tri_vertex(c->vertex((li+1)&3), c->vertex((li+2)&3), c->vertex((li+3)&3));}
inline Tri_vertex to_tri_vertex(const Facet& f) const {return to_tri_vertex(f.first, f.second);}
inline Tri_vertex sort_tri_vertex(Vertex_handle v1, Vertex_handle v2, Vertex_handle v3) const {
CGAL_triangulation_precondition(v1 != v2 && v1 != v3 && v2 != v3);
if (v1 < v2) {
if (v2 < v3)
return Tri_vertex(v3, v2, v1);
if (v3 < v1)
return Tri_vertex(v2, v1, v3);
return Tri_vertex(v2, v3, v1);
}
else { // v2 < v1
if (v3 < v2)
return Tri_vertex(v1, v2, v3);
if (v1 < v3)
return Tri_vertex(v3, v1, v2);
return Tri_vertex(v1, v3, v2);
}
}
inline Tri_vertex sort_tri_vertex(const Tri_vertex& tv) const {return sort_tri_vertex(tv.first, tv.second, tv.third);}
inline Tri_vertex sort_tri_vertex(Cell_handle c, int li) const {return sort_tri_vertex(to_tri_vertex(c, li));}
inline Tri_vertex sort_tri_vertex(const Facet& f) const {return sort_tri_vertex(f.first, f.second);}
inline Tri_vertex oriented_tri_vertex(Cell_handle c, int li) const {
CGAL_triangulation_precondition(dimension() == 2 || dimension() == 3);
CGAL_triangulation_precondition((dimension() == 2 && li == 3) || (dimension() == 3 && li >= 0 && li <= 3) );
CGAL_triangulation_precondition(!is_infinite(c, li));
if ((li&1) == 0)
return Tri_vertex(c->vertex((li+2)&3),
c->vertex((li+1)&3),
c->vertex((li+3)&3));
return Tri_vertex(c->vertex((li+1)&3),
c->vertex((li+2)&3),
c->vertex((li+3)&3));
}
inline Tri_vertex oriented_tri_vertex(const Facet& f) const {return oriented_tri_vertex(f.first, f.second);}
protected:
// tri_vertex methods similar to Triangulation_3.
Tri_vertex make_tri_vertex(const Facet& f) const {
return Tri_vertex(f.first->vertex(vertex_triple_index(f.second, 0)),
f.first->vertex(vertex_triple_index(f.second, 1)),
f.first->vertex(vertex_triple_index(f.second, 2)));
}
void make_canonical(Tri_vertex& t) const {
int i = (&*(t.first) < &*(t.second))? 0 : 1;
if (i == 0)
i = (&*(t.first) < &*(t.third))? 0 : 2;
else
i = (&*(t.second) < &*(t.third))? 1 : 2;
Vertex_handle tmp;
switch (i) {
case 0: return;
case 1:
tmp = t.first;
t.first = t.second;
t.second = t.third;
t.third = tmp;
return;
default:
tmp = t.first;
t.first = t.third;
t.third = t.second;
t.second = tmp;
}
}
// PREDICATES
Orientation coplanar_orientation(const Point& p0, const Point& p1, const Point& p2, const Point& p) const {
return Gt().coplanar_orientation_3_object()(p0, p1, p2, p);
}
public:
// CONSTRUCTORS
Delaunay_triangulation_utils_3(const Gt& gt = Gt()): DT(gt) {}
// Copy constructor duplicates vertices and cells.
Delaunay_triangulation_utils_3(const Delaunay_triangulation_utils_3& tr): DT(tr) {
CGAL_triangulation_postcondition(is_valid());
}
// Create a 3D Delaunay triangulation from a number of points.
template < typename InputIterator >
Delaunay_triangulation_utils_3(InputIterator first, InputIterator last, const Gt& gt = Gt()): DT(gt) {
insert(first, last);
CGAL_triangulation_postcondition(is_valid());
}
public:
// INSERT POINT
Vertex_handle insert(const Point& p, Cell_handle start = Cell_handle());
virtual Vertex_handle insert(const Point& p, Locate_type lt, Cell_handle c, int li, int lj);
template < class InputIterator >
int insert(InputIterator first, InputIterator last) {
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());
Cell_handle hint;
for (typename std::vector<Point>::const_iterator it = points.begin(), end = points.end(); it != end; ++it)
hint = insert(*it, hint)->cell();
return number_of_vertices() - n;
}
public:
// MOVE
Vertex_handle move_point(Vertex_handle v, const Point& p);
public:
// Construct the edge of c opposite to ij.
Edge opposite_edge(Cell_handle c, int li, int lj) const {
CGAL_triangulation_precondition(li >= 0 && li < 4);
CGAL_triangulation_precondition(lj >= 0 && lj < 4);
CGAL_triangulation_precondition(li != lj);
switch (6-li-lj) { // i + j + missing indices = 6.
case 1: return Edge(c, 0, 1);
case 2: return Edge(c, 0, 2);
case 3: return (li == 0 || lj == 0)
? Edge(c, 1, 2)
: Edge(c, 0, 3);
case 4: return Edge(c, 1, 3);
case 5: return Edge(c, 2, 3);
}
CGAL_triangulation_assertion(false);
return Edge();
}
Edge opposite_edge(const Edge& e) const {return opposite_edge(e.first, e.second, e.third);}
// Give the same facet as seen from the other side.
Facet mirror_facet(Cell_handle c, int li) const {return Facet(c->neighbor(li), c->neighbor(li)->index(c));}
Facet mirror_facet(const Facet& f) const {return mirror_facet(f.first, f.second);}
// Construct a plane of a facet.
Plane plane(Cell_handle c, int li) const {
/* This should be removed to reduce orientation errors with the inexact kernel*/
CGAL_triangulation_precondition(dimension() >= 2);
CGAL_triangulation_precondition(dimension() == 3 || li == 3);
CGAL_triangulation_precondition(li >= 0 && li <= 3);
CGAL_triangulation_precondition(!is_infinite(c, li));
if ((li&1) == 0)
return Plane(c->vertex((li+2)&3)->point(),
c->vertex((li+1)&3)->point(),
c->vertex((li+3)&3)->point());
return Plane(c->vertex((li+1)&3)->point(),
c->vertex((li+2)&3)->point(),
c->vertex((li+3)&3)->point());
}
Plane plane(const Facet& f) const {return plane(f.first, f.second);}
// Construct a line of an edge.
Line line(Cell_handle c, int li, int lj) const {
CGAL_triangulation_precondition(dimension() >= 1);
CGAL_triangulation_precondition(li >= 0 && li <= 3);
CGAL_triangulation_precondition(lj >= 0 && lj <= 3);
CGAL_triangulation_precondition(li != lj);
CGAL_triangulation_precondition(li + lj < dimension() * 2);
CGAL_triangulation_precondition(!is_infinite(c, li, lj));
return Line(c->vertex(li)->point(),
c->vertex(lj)->point());
}
Line line(const Edge& e) const {return line(e.first, e.second, e.third);}
}; // Delaunay_triangulation_utils_3
template < class Gt, class Tds >
typename Delaunay_triangulation_utils_3<Gt,Tds>::Vertex_handle
Delaunay_triangulation_utils_3<Gt,Tds>::
insert(const Point& p, Cell_handle start) {
Locate_type lt;
int li, lj;
Cell_handle c = locate(p, lt, li, lj, start);
return insert(p, lt, c, li, lj);
}
template < class Gt, class Tds >
typename Delaunay_triangulation_utils_3<Gt,Tds>::Vertex_handle
Delaunay_triangulation_utils_3<Gt,Tds>::
insert(const Point& p, Locate_type lt, Cell_handle c, int li, int lj) {
switch (dimension()) {
case 3: {
Conflict_tester_3 tester(p, this);
Vertex_handle v = insert_in_conflict(p, lt, c, li, lj, tester, hidden_point_visitor);
return v;
}// dim 3
case 2: {
Conflict_tester_2 tester(p, this);
return insert_in_conflict(p, lt, c, li, lj, tester, hidden_point_visitor);
}//dim 2
default :
// dimension <= 1
// Do not use the generic insert.
return Tr::insert(p, c);
}
}
template < class Gt, class Tds >
typename Delaunay_triangulation_utils_3<Gt,Tds>::Vertex_handle
Delaunay_triangulation_utils_3<Gt,Tds>::move_point(Vertex_handle v, const Point& p) {
CGAL_triangulation_precondition(!is_infinite(v));
CGAL_triangulation_expensive_precondition(is_vertex(v));
// Remember an incident vertex to restart the point location after the removal.
Cell_handle c = v->cell();
Vertex_handle old_neighbor = c->vertex(c->index(v) == 0 ? 1 : 0);
CGAL_triangulation_assertion(old_neighbor != v);
if (!remove(v))
return v;
if (dimension() <= 0)
return insert(p);
return insert(p, old_neighbor->cell());
}
} //end of CGAL namespace
#endif // CGAL_DELAUNAY_TRIANGULATION_3_UTILS_H

View File

@ -1,135 +0,0 @@
//A traverser that collects points encroaching upon its path.
//Copyright (C) 2012 Utrecht University
//
//This program is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// Author(s): Thijs van Lankveld
// A class that traverses the cells of a triangulation by following a segment from source to target,
// while collecting points that encroach upon the segment.
#ifndef CGAL_ENCROACHING_COLLECTER_3_H
#define CGAL_ENCROACHING_COLLECTER_3_H
#include "Triangulation_segment_traverser_3.h"
namespace CGAL {
#ifndef CGAL_CONSTRAINED_TRIANGULATION_2_H
/// \todo factorize with CDT2
struct No_intersection_tag{};
struct Exact_intersections_tag{}; // To be used with an exact number type.
struct Exact_predicates_tag{}; // To be used with filtered exact number type.
#endif
template < class Gt, class Tds, class Itag >
class Conforming_Delaunay_triangulation_3;
template < class Gt, class Tds, class Itag = No_intersection_tag, class Out = std::back_insert_iterator<std::list<Point_3<Gt> > > >
class Encroaching_collecter_3: public Triangulation_segment_traverser_3<Gt,Tds> {
typedef Encroaching_collecter_3<Gt,Tds,Itag,Out> Self;
typedef Triangulation_segment_traverser_3<Gt,Tds> Base;
typedef typename Gt::Plane_3 Plane;
public:
typedef Conforming_Delaunay_triangulation_3<Gt,Tds,Itag> CDT;
typedef typename Tds::Vertex Vertex;
typedef typename Tds::Cell Cell;
typedef typename Tds::Edge Edge;
typedef typename Tds::Facet Facet;
typedef typename Tds::Vertex_handle Vertex_handle;
typedef typename Tds::Cell_handle Cell_handle;
typedef typename Tds::Cell_iterator Cell_iterator;
typedef typename Tds::Cell_circulator Cell_circulator;
typedef typename Tds::Facet_iterator Facet_iterator;
typedef typename Tds::Facet_circulator Facet_circulator;
typedef typename Gt::Point_3 Point;
typedef typename CDT::Locate_type Locate_type;
typedef typename CDT::Bi_vertex Bi_vertex;
using Base::_lt;
using Base::_tr;
using Base::_pos;
using Base::_li;
using Base::_lj;
using Base::_source;
using Base::_target;
protected:
Out _out;
Bi_vertex se; // These are used when the source lies on an edge.
public:
Encroaching_collecter_3(): Base() {}
Encroaching_collecter_3(Vertex_handle v, const Point& t, const CDT* tr, Out output)
: Base(v, t, tr), _out(output) {if (_lt == CDT::EDGE) se = _tr->sort_bi_vertex(_pos, _li, _lj);}
Encroaching_collecter_3(const Point& s, const Point& t, const CDT* tr, Out output, Cell_handle hint = Cell_handle())
: Base(s, t, tr, hint), _out(output) {if (_lt == CDT::EDGE) se = _tr->sort_bi_vertex(_pos, _li, _lj);}
virtual bool barrier_hit() const {return _lt == CDT::EDGE && _pos->is_conforming(_li, _lj) && _tr->sort_bi_vertex(_pos, _li, _lj) != se;}
protected:
// Traverse to the next cell along the line.
virtual void increment();
};
template < class Gt, class Tds, class Itag, class Out >
void Encroaching_collecter_3<Gt,Tds,Itag,Out>::increment() {
// Walk to the next cell.
Base::increment();
// Check for encroaching points.
// Which points are checked is based on the type of simplex traversed.
const CDT* _cdt = dynamic_cast<const CDT*>(_tr);
switch (_lt) {
case CDT::FACET:
for (int i = 0; i < 4; ++i)
if (i != _li && !_cdt->is_infinite(_pos->vertex(i)) && _cdt->is_encroaching(_source, _target, _pos->vertex(i)->point()))
*_out++ = _pos->vertex(i)->point();
break;
case CDT::EDGE: {
Vertex_handle vi = _pos->vertex(_li), vj = _pos->vertex(_lj), vk;
Cell_handle c;
// Check the vertices in the star around the edge.
Facet_circulator fit = _cdt->incident_facets(_pos, _li, _lj), start(fit);
do {
c = fit->first;
vk = c->vertex(6 - c->index(vi) - c->index(vj) - fit->second);
if (!_cdt->is_infinite(vk) && !collinear(_source, _target, vk->point()) && _cdt->is_encroaching(_source, _target, vk->point()))
*_out++ = vk->point();
++fit;
} while (fit != start);
// Check the vertices of the edge.
if (_cdt->is_encroaching(_source, _target, vi->point()))
*_out++ = vi->point();
if (_cdt->is_encroaching(_source, _target, vj->point()))
*_out++ = vj->point();
break;
}
case CDT::VERTEX:
CGAL_triangulation_assertion(collinear(_source, _target, _pos->vertex(_li)->point()));
break;
default:
CGAL_triangulation_assertion(false);
break;
}
}
} //end of CGAL namespace
#endif // CGAL_ENCROACHING_COLLECTER_3_H

View File

@ -1,695 +0,0 @@
//A class that follows a straight line through a Delaunay triangulation structure.
//Copyright (C) 2012 Utrecht University
//
//This program is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// Author(s): Thijs van Lankveld
// A class that traverses the cells of a triangulation by following a segment from source to target.
#ifndef CGAL_TRIANGULATION_SEGMENT_TRAVERSER_3_H
#define CGAL_TRIANGULATION_SEGMENT_TRAVERSER_3_H
#include "Delaunay_triangulation_utils_3.h"
#include <CGAL/Random.h>
namespace CGAL {
template < class Gt, class Tds>
class Delaunay_triangulation_utils_3;
template < class Gt, class Tds >
class Triangulation_segment_traverser_3: public Forward_circulator_base< typename Tds::Cell, std::ptrdiff_t, std::size_t > {
typedef Triangulation_segment_traverser_3<Gt,Tds> Self;
public:
typedef Delaunay_triangulation_utils_3<Gt,Tds> Tr;
typedef typename Tds::Vertex Vertex;
typedef typename Tds::Cell Cell;
typedef typename Tds::Edge Edge;
typedef typename Tds::Facet Facet;
typedef typename Tds::Vertex_handle Vertex_handle;
typedef typename Tds::Cell_handle Cell_handle;
typedef typename Tds::Cell_iterator Cell_iterator;
typedef typename Tds::Cell_circulator Cell_circulator;
typedef typename Tds::Facet_iterator Facet_iterator;
typedef typename Tds::Facet_circulator Facet_circulator;
typedef typename Gt::Point_3 Point;
typedef typename Tr::Locate_type Locate_type;
protected:
// The triangulation being traversed.
const Tr* _tr;
// The source and target points of the traversal.
Point _source, _target;
// The cell currently traversed and the previous one.
Cell_handle _pos, _prev;
// Otherwise, they indicate the simplex through which this cell was entered,
// or the location of the source if it is in this cell.
int _li, _lj;
Locate_type _lt;
// This bit signifies when a cell containing the target is found.
bool _done;
// Where possible, facets are checked in a random order.
mutable Random rng;
public:
Triangulation_segment_traverser_3(): _tr(NULL), _pos(), _prev(), _li(-1), _lj(-1), _lt(Tr::CELL), _done(true) {}
Triangulation_segment_traverser_3(Vertex_handle s, const Point& t, const Tr* tr);
Triangulation_segment_traverser_3(const Point& s, const Point& t, const Tr* tr, Cell_handle hint = Cell_handle());
Self& operator++();
Self operator++(int);
Cell* operator->() {return &*_pos;}
Cell& operator*() {return *_pos;}
Cell_handle handle() {return _pos;}
operator const Cell_handle() const {return _pos;}
bool operator==(const Self& ct) const;
bool operator!=(const Self& ct) const;
bool operator==(const Cell_handle& ch) const {return ch == _pos;}
bool operator!=(const Cell_handle& ch) const {return ch != _pos;}
bool operator==(Nullptr_t CGAL_triangulation_assertion_code(n)) const;
bool operator!=(Nullptr_t n) const;
// Check if a cell containing the target has been reached.
bool has_next() const {return !_done;}
// Access the current and previous cells.
Cell_handle previous() const {return _prev;}
// Traverse to a cell containing the target.
Cell_handle traverse();
// Get the type of simplex traversed last.
void traversed(Locate_type& lt, int& li, int& lj) const {lt = _lt; li = _li; lj = _lj;}
protected:
// Traverse to the next cell along the line.
virtual void increment();
private:
inline int edgeIndex(int i, int j) const {
CGAL_triangulation_precondition(i>=0 && i<=3);
CGAL_triangulation_precondition(j>=0 && j<=3);
CGAL_triangulation_precondition(i != j);
return (i==0 || j==0) ? i+j-1 : i+j;
}
inline Orientation coplanar_orientation(const Point& p, const Point& q, const Point& r, const Point& s) {
return Gt().coplanar_orientation_3_object()(p, q, r, s);
}
}; // class Triangulation_segment_traverser_3
template < class Gt, class Tds >
inline bool operator==(typename Tds::Cell_handle ch, Triangulation_segment_traverser_3<Gt, Tds> tci) {return tci == ch;}
template < class Gt, class Tds >
inline bool operator!=(typename Tds::Cell_handle ch, Triangulation_segment_traverser_3<Gt, Tds> tci) {return tci != ch;}
template < class Gt, class Tds >
Triangulation_segment_traverser_3<Gt,Tds>::Triangulation_segment_traverser_3(Vertex_handle s, const Point& t, const Tr* tr)
: _tr(tr), _pos(), _prev(), _lj(-1), _lt(Tr::VERTEX), _done(false) {
CGAL_triangulation_precondition(!_tr->is_infinite(s));
CGAL_triangulation_precondition(s->point() != t);
CGAL_triangulation_precondition(_tr->dimension() >= 2);
CGAL_triangulation_assertion(_tr->dimension() == 3 || _tr->plane(*_tr->finite_facets_begin()).has_on(_target));
_source = s->point();
_target = t;
_pos = s->cell();
int inf;
if (_pos->has_vertex(_tr->infinite_vertex(), inf))
_pos = _pos->neighbor(inf);
_li = _pos->index(s);
CGAL_triangulation_postcondition(_pos != Cell_handle());
}
template < class Gt, class Tds >
Triangulation_segment_traverser_3<Gt,Tds>::Triangulation_segment_traverser_3(const Point& s, const Point& t, const Tr* tr, Cell_handle hint)
: _tr(tr), _pos(), _prev(), _li(-1), _lj(-1), _done(false) {
CGAL_triangulation_precondition(s != t);
CGAL_triangulation_precondition(_tr->dimension() >= 2);
CGAL_triangulation_assertion(_tr->dimension() == 3 || _tr->plane(*_tr->finite_facets_begin()).has_on(_target));
_source = s;
_target = t;
_pos = _tr->locate(s, _lt, _li, _lj, hint);
CGAL_triangulation_postcondition(_pos != Cell_handle());
}
template < class Gt, class Tds >
inline Triangulation_segment_traverser_3<Gt,Tds>&
Triangulation_segment_traverser_3<Gt,Tds>::operator++() {
CGAL_triangulation_precondition(_pos != Cell_handle());
increment();
return *this;
}
template < class Gt, class Tds >
inline Triangulation_segment_traverser_3<Gt,Tds>
Triangulation_segment_traverser_3<Gt,Tds>::operator++(int) {
Self tmp(*this);
++(*this);
return tmp;
}
template < class Gt, class Tds >
inline bool Triangulation_segment_traverser_3<Gt,Tds>::operator==(const Self& ct) const {
CGAL_triangulation_precondition(_pos != Cell_handle() && ct._pos != Cell_handle());
return (_pos == ct._pos &&
_prev == ct._prev &&
_tr == ct._tr &&
_li == ct._li &&
_lj == ct._lj &&
_lt == ct._lt &&
_source == ct._source &&
_target == ct._target &&
_done == ct._done);
}
template < class Gt, class Tds >
inline bool Triangulation_segment_traverser_3<Gt,Tds>::operator!=(const Self& ct) const {
return !(*this == ct);
}
template < class Gt, class Tds >
inline bool Triangulation_segment_traverser_3<Gt,Tds>::operator==(Nullptr_t CGAL_triangulation_assertion_code(n)) const {
CGAL_triangulation_assertion(n == NULL);
return _pos == Cell_handle();
}
template < class Gt, class Tds >
inline bool Triangulation_segment_traverser_3<Gt,Tds>::operator!=(Nullptr_t n) const {
CGAL_triangulation_assertion(n == NULL);
return !(*this == n);
}
template < class Gt, class Tds >
inline typename Triangulation_segment_traverser_3<Gt,Tds>::Cell_handle
Triangulation_segment_traverser_3<Gt,Tds>::traverse() {
while (!_done)
increment();
return _pos;
}
template < class Gt, class Tds >
void Triangulation_segment_traverser_3<Gt,Tds>::increment() {
CGAL_triangulation_precondition(!_done);
// Walks to the next cell over a facet intersected by the line from source to target.
// This method is based on Triangulation_3::locate().
switch (_tr->dimension()) {
case 3: {
// Infinite cells should be handled differently.
int inf;
if (_pos->has_vertex(_tr->infinite_vertex(), inf)) {
// If this cell was reached by traversal from a finite one, it must be the final cell.
Cell_handle fin = _pos->neighbor(inf);
if (fin == _prev) {
_done = true;
// Here, I do not change the _lt etc. because they were already set.
return;
}
const Point* pts[4];
for (int i = 0; i != 4; ++i)
if (i != inf)
pts[i] = &(_pos->vertex(i)->point());
pts[inf] = &_target;
Orientation o[4];
// For the remembering stochastic walk, we start trying with a random index:
int li = rng.template get_bits<2>();
// Check if the target lies outside the convex hull.
if (orientation(*pts[0], *pts[1], *pts[2], *pts[3]) == POSITIVE) {
// The target lies in an infinite cell.
_done = true;
return;
// Note that we do not traverse to other infinite cells.
}
pts[inf] = &_source;
CGAL_triangulation_assertion(orientation(*pts[0], *pts[1], *pts[2], *pts[3]) == POSITIVE);
// Check if the line enters an adjacent infinite cell.
// This occurs if the target lies on the other side of
// a plane through one of the finite edges and the source point.
for (int j = 0; j != 4; ++j, li = (li+1)&3) {
if (li == inf) {
o[li] = COPLANAR;
continue;
}
Cell_handle next = _pos->neighbor(li);
if (next == _prev) {
o[li] = POSITIVE;
continue;
}
const Point* backup = pts[li];
pts[li] = &_target;
o[li] = orientation(*pts[0], *pts[1], *pts[2], *pts[3]);
if (o[li] != NEGATIVE) {
pts[li] = backup;
continue;
}
// The target lies behind the plane through the source and two finite vertices.
// Traverse to the incident infinite cell.
_prev = _pos;
_pos = next;
CGAL_triangulation_assertion(_tr->is_infinite(_pos));
_lt = Tr::FACET;
_li = _pos->index(_prev);
return;
}
// The line enters the convex hull here (or lies on the finite facet).
_prev = _pos;
_pos = fin;
// Check through which simplex the line traverses.
switch (o[0]+o[1]+o[2]+o[3]) {
case 3:
_lt = Tr::FACET;
_li = _pos->index(_prev);
return;
case 2:
_lt = Tr::EDGE;
for (int i = 0; i < 4; ++i) {
if (o[i] == COPLANAR && i != inf) {
Edge opp = _tr->opposite_edge(_prev, inf, i);
_li = _pos->index(_prev->vertex(opp.second));
_lj = _pos->index(_prev->vertex(opp.third));
return;
}
}
CGAL_triangulation_assertion(false);
return;
case 1:
_lt = Tr::VERTEX;
for (int i = 0; i < 4; ++i) {
if (o[i] == POSITIVE) {
_li = _pos->index(_prev->vertex(i));
return;
}
}
CGAL_triangulation_assertion(false);
return;
default:
CGAL_triangulation_assertion(false);
return;
}
}
const Point* pts[4] = {&(_pos->vertex(0)->point()),
&(_pos->vertex(1)->point()),
&(_pos->vertex(2)->point()),
&(_pos->vertex(3)->point())};
// We check in which direction the target lies
// by comparing its position relative to the planes through the
// source and the edges of the cell.
Orientation o[6];
bool calc[6] = {false, false, false, false, false, false};
if (_lt == Tr::VERTEX) {
// The three planes through the vertex are set to coplanar.
for (int j = 0; j < 4; ++j) {
if (_li != j) {
int ij = edgeIndex(_li, j);
o[ij] = COPLANAR;
calc[ij] = true;
}
}
}
else if (_lt == Tr::EDGE) {
// The plane through the edge is set to coplanar.
int ij = edgeIndex(_li, _lj);
o[ij] = COPLANAR;
calc[ij] = true;
}
// For the remembering stochastic walk, we start trying with a random facet:
int li = rng.template get_bits<2>();
CGAL_triangulation_assertion_code(bool incell = true;)
for (int k = 0; k < 4; ++k, li = (li+1)&3) {
Cell_handle next = _pos->neighbor(li);
if (next == _prev)
continue;
// Check if the target is outside the cell.
const Point* backup = pts[li];
pts[li] = &_target;
if (orientation(*pts[0], *pts[1], *pts[2], *pts[3]) != NEGATIVE) {
pts[li] = backup;
continue;
}
CGAL_triangulation_assertion_code(incell = false;)
// Check if the target is inside the pyramid.
int lj = rng.template get_bits<2>();
int Or = 0;
for (int l = 0; l < 4; ++l, lj = (lj+1)&3) {
if (li == lj)
continue;
// We check the orientation of the target compared to the plane
// Through the source and the edge opposite of ij.
int oij = 5 - edgeIndex(li, lj);
if (!calc[oij]) {
const Point* backup2 = pts[lj];
pts[lj] = &_source;
o[oij] = orientation(*pts[0], *pts[1], *pts[2], *pts[3]);
pts[lj] = backup2;
calc[oij] = true;
}
Or -= o[oij];
if (o[oij] == POSITIVE) {
// The target is not inside the pyramid.
// Invert the planes.
// This can be safely done because either
// they were not calculated yet,
// or they will no longer be used.
for (int j = 0; j < 4; ++j) {
if (li == j) continue;
int oij = 5 - edgeIndex(li, j);
o[oij] = -o[oij];
}
Or = 0;
break;
}
}
if (Or == 0) {
// Either the target is not inside the pyramid,
// or the pyramid is degenerate.
pts[li] = backup;
continue;
}
// The target is inside the pyramid.
_prev = _pos;
_pos = next;
switch (Or) {
case 3:
_lt = Tr::FACET;
_li = _pos->index(_prev);
return;
case 2:
_lt = Tr::EDGE;
for (int j = 0; j < 4; ++j) {
if (li != j && o[5-edgeIndex(li, j)] == COPLANAR) {
Edge opp = _tr->opposite_edge(_prev, li, j);
_li = _pos->index(_prev->vertex(opp.second));
_lj = _pos->index(_prev->vertex(opp.third));
return;
}
}
CGAL_triangulation_assertion(false);
return;
case 1:
_lt = Tr::VERTEX;
for (int j = 0; j < 4; ++j) {
if (li != j && o[5-edgeIndex(li, j)] == NEGATIVE) {
_li = _pos->index(_prev->vertex(j));
return;
}
}
CGAL_triangulation_assertion(false);
return;
default:
CGAL_triangulation_assertion(false);
return;
}
}
// The target lies inside this cell.
CGAL_triangulation_assertion(incell);
_done = true;
return;
}
case 2: {
int inf;
if (_pos->has_vertex(_tr->infinite_vertex(), inf) && inf < 3) {
// If this cell was reached by traversal from a finite one, it must be the final cell.
Cell_handle fin = _pos->neighbor(inf);
if (fin == _prev) {
_done = true;
return;
}
// Check the neighboring cells.
if (coplanar_orientation(_source, _pos->vertex(_tr->ccw(inf))->point(), _pos->vertex(_tr->cw(inf))->point(), _target) == NEGATIVE) {
Cell_handle tmp = _pos->neighbor(_tr->cw(inf));
_prev = _pos;
_pos = tmp;
return;
}
if (coplanar_orientation(_source, _pos->vertex(_tr->cw(inf))->point(), _pos->vertex(_tr->ccw(inf))->point(), _target) == NEGATIVE) {
Cell_handle tmp = _pos->neighbor(_tr->ccw(inf));
_prev = _pos;
_pos = tmp;
return;
}
if (coplanar_orientation(_pos->vertex(_tr->ccw(inf))->point(), _pos->vertex(_tr->cw(inf))->point(), _source, _target) != POSITIVE) {
_prev = _pos;
_pos = fin;
return;
}
// The target lies in this infinite cell.
_done = true;
return;
}
const Point* pts[3] = {&(_pos->vertex(0)->point()),
&(_pos->vertex(1)->point()),
&(_pos->vertex(2)->point())};
switch (_lt) {
case Tr::VERTEX: {
// First we try the incident edges.
Orientation ocw = coplanar_orientation(*pts[_li], *pts[(_li+2)%3], *pts[(_li+1)%3], _target);
if (_pos->neighbor((_li+1)%3) != _prev &&
ocw == NEGATIVE) {
Cell_handle tmp = _pos->neighbor((_li+1)%3);
_prev = _pos;
_pos = tmp;
_li = _pos->index(_prev->vertex(_li));
return;
}
Orientation occw = coplanar_orientation(*pts[_li], *pts[(_li+1)%3], *pts[(_li+2)%3], _target);
if (_pos->neighbor((_li+2)%3) != _prev &&
occw == NEGATIVE) {
Cell_handle tmp = _pos->neighbor((_li+2)%3);
_prev = _pos;
_pos = tmp;
_li = _pos->index(_prev->vertex(_li));
return;
}
// Then we try the opposite edge.
if (coplanar_orientation(*pts[(_li+1)%3], *pts[(_li+2)%3], *pts[_li], _target) == NEGATIVE) {
Cell_handle tmp = _pos->neighbor(_li);
_prev = _pos;
_pos = tmp;
switch (ocw+occw) {
case 2: {
_lt = Tr::EDGE;
_li = _pos->index(_prev->vertex((_li+1)%3));
_lj = _pos->index(_prev->vertex((_li+2)%3));
return;
}
case 1: {
_lt = Tr::VERTEX;
if (ocw == COLLINEAR) _li = _pos->index(_prev->vertex((_li+2)%3));
else _li = _pos->index(_prev->vertex((_li+1)%3));
return;
}
default:
CGAL_triangulation_assertion(false);
return;
}
}
// The target lies in this cell.
_done = true;
return;
}
case Tr::EDGE: {
int lk = 3-_li-_lj;
if (_pos->neighbor(lk) != _prev) {
// Check the edge itself
switch (coplanar_orientation(*pts[_li], *pts[_lj], *pts[lk], _target)) {
case COLLINEAR: {
// The target lies in this cell.
_done = true;
return;
}
case NEGATIVE: {
// The target lies opposite of the edge.
Cell_handle tmp = _pos->neighbor(lk);
_prev = _pos;
_pos = tmp;
_li = _pos->index(_prev->vertex(_li));
_lj = _pos->index(_prev->vertex(_lj));
return;
}
default:
break;
}
}
Orientation o = coplanar_orientation(_source, *pts[lk], *pts[_li], _target);
switch (o) {
case POSITIVE: {
// The ray passes through the edge ik.
if (coplanar_orientation(*pts[lk], *pts[_li], _source, _target) == NEGATIVE) {
Cell_handle tmp = _pos->neighbor(_lj);
_prev = _pos;
_pos = tmp;
if (collinear(_source, *pts[_li], _target)) {
_lt = Tr::VERTEX;
_li = _pos->index(_prev->vertex(_li));
}
else {
_lt = Tr::EDGE;
_li = _pos->index(_prev->vertex(_li));
_lj = _pos->index(_prev->vertex(lk));
}
return;
}
break;
}
default: {
// The ray passes through the edge jk.
if (coplanar_orientation(*pts[lk], *pts[_lj], _source, _target) == NEGATIVE) {
Cell_handle tmp = _pos->neighbor(_li);
_prev = _pos;
_pos = tmp;
if (collinear(_source, *pts[_lj], _target)) {
_lt = Tr::VERTEX;
_li = _pos->index(_prev->vertex(_lj));
}
else if (o == COLLINEAR) {
_lt = Tr::VERTEX;
_li = _pos->index(_prev->vertex(lk));
}
else {
_lt = Tr::EDGE;
_li = _pos->index(_prev->vertex(lk));
_lj = _pos->index(_prev->vertex(_lj));
}
return;
}
break;
}
}
// The target lies in this cell.
_done = true;
return;
}
case Tr::FACET: {
// We test its edges in a random order until we find a neighbor to go further
int li = rng.get_int(0, 3);
Orientation o[3];
bool calc[3] = {false, false, false};
for (int j = 0; j != 3; ++j, li = (li+1)%3) {
Cell_handle next = _pos->neighbor(li);
if (next == _prev)
continue;
// The target should lie on the other side of the edge.
if (coplanar_orientation(*pts[(li+1)%3], *pts[(li+2)%3], *pts[li], _target) != NEGATIVE)
continue;
// The target should lie inside the wedge.
if (!calc[(li+1)%3]) {
o[(li+1)%3] = coplanar_orientation(_source, *pts[(li+1)%3], *pts[(li+2)%3], _target);
calc[(li+1)%3] = true;
}
if (o[(li+1)%3] == NEGATIVE) continue;
if (!calc[(li+2)%3]) {
o[(li+2)%3] = coplanar_orientation(_source, *pts[(li+2)%3], *pts[(li+1)%3], _target);
calc[(li+2)%3] = true;
}
if (o[(li+2)%3] == POSITIVE) continue;
_prev = _pos;
_pos = next;
switch (o[(li+1)%3]+o[(li+2)%3]) {
case 2: {
_lt = Tr::EDGE;
_li = _pos->index(_prev->vertex((li+1)%3));
_lj = _pos->index(_prev->vertex((li+2)%3));
return;
}
case 1: {
_lt = Tr::VERTEX;
if (o[(li+1)%3] == COLLINEAR) _li = _pos->index(_prev->vertex((li+1)%3));
else _li = _pos->index(_prev->vertex((li+2)%3));
return;
}
default:
CGAL_triangulation_assertion(false);
return;
}
}
// The target lies in this cell.
_done = true;
return;
}
default:
CGAL_triangulation_assertion(false);
}
}
}
}
} //end of CGAL namespace
#endif // CGAL_TRIANGULATION_SEGMENT_TRAVERSER_3_H

View File

@ -1,2 +0,0 @@
Utrecht University (The Netherlands) & INRIA Sophia-Antipolis (France)

View File

@ -1,3 +0,0 @@
Package Conforming_triangulation_3 :
conforming triangulation data structure
this can be wrapped around any CGAL::Triangulation_3, usually CGAL::Delaunay_triangulation_3

View File

@ -1 +0,0 @@
Thijs van Lankveld <thijs.van-lankveld@sophia.inria.fr>

View File

@ -7,6 +7,7 @@
\example Triangulation_3/info_insert_with_transform_iterator.cpp
\example Triangulation_3/simplex.cpp
\example Triangulation_3/fast_location_3.cpp
\example Triangulation_3/segment_traverser_3.cpp
\example Triangulation_3/find_conflicts_3.cpp
\example Triangulation_3/regular_3.cpp
\example Triangulation_3/copy_triangulation_3.cpp

View File

@ -22,6 +22,11 @@ in a triangulation, when he needs to add handles in it.
This example shows the use of the Fast_location policy to speed up
point location queries in a Delaunay triangulation.
------- segment_traverser_3 --------------------------------------------
This example shows how to use a Triangulation_segment_traverser_3
to traverse the triangulation in a straight line.
------- tds --------------------------------------------------
Shows how to construct a 3D triangulation data structure by

View File

@ -0,0 +1,45 @@
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Delaunay_triangulation_3.h>
#include <CGAL/Triangulation_segment_traverser_3.h>
#include <assert.h>
#include <iostream>
// Define the kernel.
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef Kernel::Point_3 Point_3;
// Define the structure.
typedef CGAL::Delaunay_triangulation_3< Kernel > DT;
typedef DT::Cell_handle Cell_handle;
typedef CGAL::Triangulation_segment_traverser_3< DT > Traverser;
void main() {
std::vector< Point_3 > points;
points.reserve( 6 );
points.push_back( Point_3(-.9063, .4226, 1.0 ) );
points.push_back( Point_3( .8192, .5736, 1.0 ) );
points.push_back( Point_3( .0872,-.9992, 1.0 ) );
points.push_back( Point_3(-.8192, .5736,-1.0 ) );
points.push_back( Point_3( .9063, .4226,-1.0 ) );
points.push_back( Point_3( .0872,-.9962,-1.0 ) );
// Construct the Delaunay triangulation.
DT dt( points.begin(), points.end() );
assert( dt.is_valid() );
// Construct a traverser.
Traverser st( dt, Point_3(-3,0,0), Point_3(3,0,0) );
// Count the number of finite cells traversed.
unsigned int cells = 0;
while( st.has_next() ) {
if( !dt.is_infinite(st) )
++cells;
++st;
}
std::cout << "The number of finite cells between " << st.source() << " and " << st.target() << " is " << cells << std::endl;
}

View File

@ -539,6 +539,7 @@ protected:
GT _gt;
Vertex_handle infinite; //infinite vertex
public:
Comparison_result
compare_xyz(const Point &p, const Point &q) const
{
@ -557,6 +558,9 @@ protected:
{
return geom_traits().orientation_3_object()(p, q, r, s);
}
// Compute the orientation of a point compared to the oriented plane supporting a half-facet.
Orientation orientation( const Facet& f, const Point& p ) const;
bool
coplanar(const Point &p, const Point &q,
@ -565,6 +569,21 @@ protected:
return orientation(p, q, r, s) == COPLANAR;
}
// Check whether the points of four vertices `a`, `b`, `c`, and `d` are coplanar.
bool coplanar( Vertex_handle a, Vertex_handle b, Vertex_handle c, Vertex_handle d ) const {
return coplanar( a->point(), b->point(), c->point(), d->point() );
}
// Check whether the points of facet `f` and point `p` are coplanar.
bool coplanar( const Facet& f, const Point& p ) const {
return orientation(f, p) == COPLANAR;
}
// Check whether the points of facet `f` and vertex `v` are coplanar.
bool coplanar( const Facet& f, Vertex_handle v ) const{
return orientation(f, v->point()) == COPLANAR;
}
Orientation
coplanar_orientation(const Point &p, const Point &q, const Point &r) const
{
@ -577,6 +596,7 @@ protected:
return coplanar_orientation(p, q, r) == COLLINEAR;
}
protected:
Segment
construct_segment(const Point &p, const Point &q) const
{
@ -1034,6 +1054,22 @@ public:
Facet mirror_facet(Facet f) const
{ return _tds.mirror_facet(f);}
// Gives the edge incident to the same cell that is not incident to any of the input vertices.
Edge opposite_edge( Cell_handle c, int li, int lj ) const;
// Gives the edge incident to the same cell that is not incident to any of the vertices of the input edge.
Edge opposite_edge( const Edge& e ) const { return opposite_edge( e.first, e.second, e.third ); }
// Gives the half-facet incident to the opposite cell.
Facet mirror_facet( Cell_handle c, int li ) const { return Facet( c->neighbor(li), c->neighbor(li)->index(c) ); }
// Gives the opposite half-facet.
Facet mirror_facet( const Facet& f ) const { return mirror_facet( f.first, f.second ); }
// MODIFIERS
bool flip(const Facet &f)
// returns false if the facet is not flippable
@ -2244,9 +2280,23 @@ operator<< (std::ostream& os, const Triangulation_3<GT, Tds, Lds> &tr)
return os ;
}
template < class GT, class Tds, class Lds >
typename Triangulation_3<GT,Tds,Lds>::size_type
Triangulation_3<GT,Tds,Lds>::
template <class Gt, class Tds>
inline Orientation Triangulation_3<Gt,Tds>::
orientation( const Facet& f, const Point& p ) const {
return Gt().orientation_3_object()( f.first->vertex( vertex_triple_index(f.second, 0) )->point(),
f.first->vertex( vertex_triple_index(f.second, 1) )->point(),
f.first->vertex( vertex_triple_index(f.second, 2) )->point(),
p );
}
template < class GT, class Tds >
typename Triangulation_3<GT,Tds>::size_type
Triangulation_3<GT,Tds>::
number_of_finite_cells() const
{
if ( dimension() < 3 ) return 0;
@ -3339,7 +3389,30 @@ side_of_edge(const Point & p,
}
}
template < class GT, class Tds, class Lds >
template <class Gt, class Tds>
inline
typename Triangulation_3<Gt,Tds>::Edge
Triangulation_3<Gt,Tds>::
opposite_edge( Cell_handle c, int li, int lj ) const {
CGAL_triangulation_precondition( li >= 0 && li < 4 );
CGAL_triangulation_precondition( lj >= 0 && lj < 4 );
CGAL_triangulation_precondition( li != lj );
switch( 6-li-lj ) { // i + j + missing indices = 6.
case 1: return Edge( c, 0, 1 );
case 2: return Edge( c, 0, 2 );
case 3: return ( li == 0 || lj == 0 ) ? Edge( c, 1, 2 ) : Edge( c, 0, 3 );
case 4: return Edge( c, 1, 3 );
case 5: return Edge( c, 2, 3 );
}
CGAL_triangulation_assertion( false );
return Edge();
}
template < class GT, class Tds >
bool
Triangulation_3<GT,Tds,Lds>::
flip( Cell_handle c, int i )

View File

@ -0,0 +1,356 @@
//A class that follows a straight line through a Delaunay triangulation structure.
//Copyright (C) 2012 Utrecht University
//
//This program is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// Author(s): Thijs van Lankveld
#ifndef CGAL_TRIANGULATION_SEGMENT_TRAVERSER_3_H
#define CGAL_TRIANGULATION_SEGMENT_TRAVERSER_3_H
#include <CGAL/internal/Dummy_gt.h>
#include <CGAL/Random.h>
namespace CGAL {
#ifndef DOXYGEN_RUNNING
/**
* \ingroup PkgConformingTriangulation3Classes
*
* The `Triangulation_segment_traverser_3` iterates over the cells
* of a `Triangulation_3` by following a straight line segment \f$ st \f$.
*
* This class is closely related to `Triangulation_3::locate(...)`.
* However, unlike this `locate(...)` method, all the cells traversed
* by the `Triangulation_segment_traverser_3` intersect the interior of the line
* segment \f$ st \f$.
*
* Traversal starts from a cell containing \f$ s \f$ and it ends in a cell containing
* \f$ t \f$.
* If \f$ st \f$ is coplanar with a facet or collinear with an edge, at most one of the
* incident cells is traversed.
* If \f$ st \f$ intersects an edge or vertex, at most two incident cells are traversed:
* the cells intersecting \f$ st \f$ strictly in their interior.
*
* If \f$ s \f$ lies on the convex hull, traversal starts in an incident cell inside
* the convex hull. Similarly, if \f$ t \f$ lies on the convex hull, traversal ends in
* an adjacent cell inside the convex hull.
*
* Both \f$ s \f$ and \f$ t \f$ may lie outside the convex hull of the triangulation,
* but they must lie within the affine hull of the triangulation. In either case, the
* finite facet of any infinite cells traversed must intersect \f$ st \f$.
*
* The traverser may be applied to any triangulation of dimension > 0.
* However, for triangulations of dimension 1, the functionality is somewhat trivial.
*
* The traverser becomes invalid whenever the triangulation is changed.
*
* \tparam Tr_ is the triangulation type to traverse.
*
* \sa `Triangulation_3`
* \sa `Forward_circulator_base`
*/
#endif // DOXYGEN_RUNNING
template < class Tr_ = void >
class Triangulation_segment_traverser_3
: public Forward_circulator_base< typename Tr_::Triangulation_data_structure::Cell,
std::ptrdiff_t, std::size_t > {
typedef Tr_ Tr;
typedef typename Tr::Triangulation_data_structure Tds;
typedef typename Tr::Geom_traits Gt;
public:
/// \name Types
/// \{
typedef Tr Triangulation; ///< The triangulation type.
typedef Triangulation_segment_traverser_3<Tr> TST; ///< A triangulation segment traverser.
typedef typename Tr::Point Point; ///< A point embedded in the vertices of the triangulation.
typedef typename Tr::Segment Segment; ///< A segment connecting two points.
typedef typename Tr::Cell Cell; ///< A cell in the triangulation.
typedef typename Tr::Edge Edge; ///< An edge in the triangulation.
typedef typename Tr::Vertex_handle Vertex_handle; ///< A handle for a vertex in the triangulation.
typedef typename Tr::Cell_handle Cell_handle; ///< A handle for a cell in the triangulation.
typedef typename Tr::Locate_type Locate_type; ///< The simplex containing a geometric object.
/// \}
template < class Tr2 >
struct Rebind_Tr {
typedef Triangulation_segment_traverser_3<Tr2> Other;
};
protected:
/// \internal \name Protected Attributes
/// \{
/// \internal The triangulation to traverse.
const Tr& _tr;
/// \}
// The source and target points of the traversal.
Point _source;
Point _target;
Vertex_handle _s_vertex;
Vertex_handle _t_vertex;
// The cell currently traversed and the previous one.
Cell_handle _pos, _prev;
// Otherwise, they indicate the simplex through which this cell was entered,
// or the location of the source if it is in this cell.
int _li, _lj;
Locate_type _lt;
// This bit signifies when a cell containing the target is found.
bool _done;
// Where possible, facets are checked in a random order.
mutable Random rng;
private:
Tds _tds2;
Vertex_handle _s_vert, _t_vert;
public:
/// \name Constructors
/// \{
/// Constructs a traverser.
/** \param tr the triangulation to traverse. This triangulation must have dimension > 0.
* \param s the source vertex. This vertex must be initialized and cannot be the infinite vertex.
* \param t the target vertex. This vertex must be initialized and cannot be the infinite vertex.
* It cannot equal `s`.
*/
Triangulation_segment_traverser_3( const Tr& tr, Vertex_handle s, Vertex_handle t );
/// Constructs a traverser.
/** \param tr the triangulation to traverse. This triangulation must have dimension > 0.
* \param s the source vertex. This vertex must be initialized and cannot be the infinite vertex.
* \param t the target point. This point must be initialized and it cannot be be at the same location as `s`.
* If `tr` has dimension < 3, `t` must lie inside the affine hull of `tr`.
*/
Triangulation_segment_traverser_3( const Tr& tr, Vertex_handle s, const Point& t );
/// Constructs a traverser.
/** \param tr the triangulation to traverse. This triangulation must have dimension > 0.
* \param s the source point. This point must be initialized. If `tr` has dimension < 3, `s` must lie inside
* the affine hull of `tr`.
* \param t the target point. This point must be initialized and it cannot be be at the same location as `s`.
* If `tr` has dimension < 3, `t` must lie inside the affine hull of `tr`.
* \param hint the starting point to search for `s`.
*/
Triangulation_segment_traverser_3( const Tr& tr, const Point& s, const Point& t, Cell_handle hint = Cell_handle() );
/// Constructs a traverser.
/** \param tr the triangulation to traverse. This triangulation must have dimension > 0.
* \param S the segment to be traversed. If `tr` has dimension < 3, `S` must lie inside
* the affine hull of `tr`. `S` must not be degenerate, i.e. its source and target must not be equal.
* \param hint the starting point to search for `S`.
*/
Triangulation_segment_traverser_3( const Tr& tr, const Segment& S, Cell_handle hint = Cell_handle() );
/// \}
public:
/// \name Accessors
/// \{
/// Gives the source point of the traversed segment.
/** \return the source point.
*/
const Point& source() const { return _source; }
/// Gives the target point of the traversed segment.
/** \return the target point.
*/
const Point& target() const { return _target; }
/// Gives the cell currently traversed.
/** By invariance, this cell is intersected by the segment
* between `source()` and `target()`.
* \return the cell currently traversed.
* \sa `handle()`.
*/
Cell_handle cell() const { return _pos; }
/// Gives a handle to the cell currently traversed.
/** By invariance, this cell is intersected by the segment
* between `source()` and `target()`.
* \return a handle to the cell currently traversed.
* \sa `cell()`.
*/
Cell_handle handle() { return _pos; }
/// Gives the cell traversed previously.
/** This cell is uninitialized until the traverser leaves the initial
* cell containing the `source()`.
* By invariance, once initialized, this cell must be intersected by the segment
* between `source()` and `target()`.
* \return the cell traversed previously.
* \sa `handle()`.
*/
Cell_handle previous() const { return _prev; }
/// Dereference operator.
/** \return a pointer to the cell currently traversed.
*/
Cell* operator->() { return &*_pos; }
/// Indirection operator.
/** \return the cell currently traversed.
*/
Cell& operator*() { return *_pos; }
/// Conversion operator.
/** \return a handle to the cell currently traversed.
*/
operator const Cell_handle() const { return _pos; }
/// Checks if the traverser has reached the final cell, which contains the `target()`.
/** If the `target()` lies on a facet, edge, or vertex, the final cell is the cell containing
* the interior of the segment between `source()` and `target()`.
* \return true iff the current cell contains the `target()`.
*/
bool has_next() const { return !_done; }
/// Gives the type of simplex traversed last.
/** This simplex indicates where traversal has entered the cell.
* For the first cell, containing the `source()` \f$ s \f$, this indicates the location of \f$ s \f$ in this cell.
*/
void entry( Locate_type& lt, int& li, int& lj ) const { lt = _lt; li = _li; lj = _lj; }
/// \}
public:
/// \name Mutators
/// \{
/// Increment postfix operator.
/** The current cell must not contain the `target()`.
* After incrementing the traverser, the current cell intersects the segment
* between `source()` and `target()` closer to the `target()` than the previous cell.
* \sa `operator++(int)`.
*/
TST& operator++();
/// Increment prefix operator.
/** The current cell must not contain the `target()`.
* After incrementing the traverser, the current cell intersects the segment
* between `source()` and `target()` closer to the `target()` than the previous cell.
* than the previous cell.
* \sa `operator++()`.
*/
TST operator++( int );
/// Traverse to the final cell, which contains the `target()`.
/** \return the final cell.
*/
Cell_handle traverse();
/// \}
public:
/// \name Comparison
/// \{
/// Compares this traverser with `ct`.
/** \param ct the other traverser.
* \return true iff the other traverser traverses the same triangulation along the same line segment
* and has the same current cell.
* \sa `operator!=( const TST& t )`.
*/
bool operator==( const TST& ct ) const;
/// Compares this traverser with `ct`.
/** \param ct the other traverser.
* \return `false` iff the other traverser traverses the same triangulation along the same line segment
* and has the same current cell.
* \sa `operator==( const TST& t ) const`.
*/
bool operator!=( const TST& ct ) const;
/// Compares the cell currently traversed with `ch`.
/** \param ch a handle to the other cell.
* \return true iff the cell currently traversed is the same as the one pointed to by `ch`.
* \sa `operator!=( const Cell_handle& ch ) const`.
* \sa `operator==( typename TriangulationTraits_3::Cell_handle ch, Triangulation_segment_traverser_3<TriangulationTraits_3> t )`.
*/
bool operator==( const Cell_handle& ch ) const { return ch == _pos; }
/// Compares the cell currently traversed with `ch`.
/** \param ch a handle to the other cell.
* \return `false` iff the cell currently traversed is the same as the one pointed to by `ch`.
* \sa `operator==( const Cell_handle& ch )`.
* \sa `operator!=( typename TriangulationTraits_3::Cell_handle ch, Triangulation_segment_traverser_3<TriangulationTraits_3> t )`.
*/
bool operator!=( const Cell_handle& ch ) const { return ch != _pos; }
/// \}
bool operator==( Nullptr_t CGAL_triangulation_assertion_code(n) ) const;
bool operator!=( Nullptr_t n ) const;
protected:
/// \internal \name Protected Member Functions
/// \{
/// \internal Traverse to the next cell.
/** \internal \sa `traverse()`.
*/
virtual void increment();
/// \}
private:
// increment(), if the triangulation is 3D.
void increment_3();
void increment_3_inf( int inf );
// increment(), if the triangulation is 2D.
void increment_2();
void increment_2_inf( int inf );
private:
inline int edgeIndex( int i, int j ) const {
CGAL_triangulation_precondition( i>=0 && i<=3 );
CGAL_triangulation_precondition( j>=0 && j<=3 );
CGAL_triangulation_precondition( i != j );
return ( i==0 || j==0 ) ? i+j-1 : i+j;
}
}; // class Triangulation_segment_traverser_3
/// Compares a handle to a cell to a traverser.
/** \param ch the handle to a cell.
* \param t the traverser.
* \return true iff the cell currently traversed by `t` is the same as the one pointed to by `ch`.
* \sa `operator!=( typename TriangulationTraits_3::Cell_handle ch, Triangulation_segment_traverser_3<TriangulationTraits_3> t )`.
* \sa `Triangulation_segment_traverser_3::operator==( const Cell_handle& ch )`.
*/
template <class Tr>
inline bool operator==( typename Tr::Cell_handle ch, Triangulation_segment_traverser_3<Tr> tci ) { return tci == ch; }
/// Compares a handle to a cell to a traverser.
/** \param ch the handle to a cell.
* \param t the traverser.
* \return `false` iff the cell currently traversed by `t` is the same as the one pointed to by `ch`.
* \sa `operator==( typename TriangulationTraits_3::Cell_handle ch, Triangulation_segment_traverser_3<TriangulationTraits_3> t )`.
* \sa `Triangulation_segment_traverser_3::operator!=( const Cell_handle& ch )`.
*/
template <class Tr>
inline bool operator!=( typename Tr::Cell_handle ch, Triangulation_segment_traverser_3<Tr> tci ) { return tci != ch; }
// Specialization for void
template <>
class Triangulation_segment_traverser_3<void> {
typedef internal::Dummy_gt Gt;
typedef internal::Dummy_tds_3 Tds;
public:
typedef Triangulation_3<Gt,Tds> Triangulation;
template <typename Tr2>
struct Rebind_Tr { typedef Triangulation_segment_traverser_3<Tr2> Other; };
}; // class Triangulation_segment_traverser_3<void>
} // namespace CGAL
#include <CGAL/Triangulation_segment_traverser_3_impl.h>
#endif // CGAL_TRIANGULATION_SEGMENT_TRAVERSER_3_H

View File

@ -0,0 +1,665 @@
//A class that follows a straight line through a Delaunay triangulation structure.
//Copyright (C) 2012 Utrecht University
//
//This program is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// Author(s): Thijs van Lankveld
#ifndef CGAL_TRIANGULATION_SEGMENT_TRAVERSER_3_IMPL_H
#define CGAL_TRIANGULATION_SEGMENT_TRAVERSER_3_IMPL_H
namespace CGAL {
template <class Tr>
Triangulation_segment_traverser_3<Tr>::
Triangulation_segment_traverser_3( const Tr& tr, Vertex_handle s, const Point& t )
: _tr(tr), _pos(), _prev(), _lj(-1), _lt(Tr::VERTEX), _done(false) {
CGAL_triangulation_precondition( !_tr.is_infinite(s) );
CGAL_triangulation_precondition( s->point() != t );
CGAL_triangulation_precondition( _tr.dimension() >= 2 );
CGAL_triangulation_precondition( _tr.dimension() == 3 ||
_tr.orientation( *_tr.finite_facets_begin(), t ) == COPLANAR );
_source = s->point();
_target = t;
_s_vertex = s;
_t_vertex = Vertex_handle();
_s_vert = s;
_t_vert = _tds2.create_vertex( Vertex(_target) );
_pos = s->cell();
int inf;
if( _pos->has_vertex( _tr.infinite_vertex(), inf ) )
_pos = _pos->neighbor(inf);
_li = _pos->index(s);
CGAL_triangulation_postcondition( _pos != Cell_handle() );
}
template < class Tr>
Triangulation_segment_traverser_3<Tr>::
Triangulation_segment_traverser_3( const Tr& tr, Vertex_handle s, Vertex_handle t )
: _tr(tr), _pos(), _prev(), _lj(-1), _lt(Tr::VERTEX), _done(false) {
CGAL_triangulation_precondition( !_tr.is_infinite(s) );
CGAL_triangulation_precondition( !_tr.is_infinite(t) );
CGAL_triangulation_precondition( s->point() != t->point() );
CGAL_triangulation_precondition( _tr.dimension() >= 2 );
_source = s->point();
_target = t->point();
_s_vertex = s;
_t_vertex = t;
_s_vert = s;
_t_vert = t;
_pos = s->cell();
int inf;
if( _pos->has_vertex( _tr.infinite_vertex(), inf ) )
_pos = _pos->neighbor(inf);
_li = _pos->index(s);
}
template <class Tr>
Triangulation_segment_traverser_3<Tr>::
Triangulation_segment_traverser_3( const Tr& tr, const Point& s, const Point& t, Cell_handle hint )
: _tr(tr), _pos(), _prev(), _li(-1), _lj(-1), _done(false) {
CGAL_triangulation_precondition( s != t );
CGAL_triangulation_precondition( _tr.dimension() >= 2 );
CGAL_triangulation_precondition( _tr.dimension() == 3 ||
_tr.coplanar( *_tr.finite_facets_begin(), _target ) );
_source = s;
_target = t;
_s_vertex = Vertex_handle();
_t_vertex = Vertex_handle();
_s_vert = _tds2.create_vertex( Tr::Vertex(_source) );
_t_vert = _tds2.create_vertex( Tr::Vertex(_target) );
_pos = _tr.locate( s, _lt, _li, _lj, hint );
CGAL_triangulation_postcondition( _pos != Cell_handle() );
}
template <class Tr>
Triangulation_segment_traverser_3<Tr>::
Triangulation_segment_traverser_3( const Tr& tr, const Segment& s, Cell_handle hint )
: Triangulation_segment_traverser_3<Tr>( tr, s.source(), s.target(), hint ) {}
template <class Tr>
inline Triangulation_segment_traverser_3<Tr>&
Triangulation_segment_traverser_3<Tr>::operator++() {
CGAL_triangulation_precondition( _pos != Cell_handle() );
increment();
return *this;
}
template <class Tr>
inline Triangulation_segment_traverser_3<Tr>
Triangulation_segment_traverser_3<Tr>::operator++( int ) {
TST tmp( *this );
++( *this );
return tmp;
}
template <class Tr>
inline typename Triangulation_segment_traverser_3<Tr>::Cell_handle
Triangulation_segment_traverser_3<Tr>::traverse() {
while( !_done )
increment();
return _pos;
}
template <class Tr>
inline bool Triangulation_segment_traverser_3<Tr>::
operator==( const TST& ct ) const {
CGAL_triangulation_precondition( _pos != Cell_handle() );
CGAL_triangulation_precondition( ct._pos != Cell_handle() );
return ( _pos == ct._pos &&
_prev == ct._prev &&
_tr == ct._tr &&
_li == ct._li &&
_lj == ct._lj &&
_lt == ct._lt &&
_source == ct._source &&
_target == ct._target &&
_s_vertex == ct._s_vertex &&
_t_vertex == ct._t_vertex &&
_done == ct._done );
}
template <class Tr>
inline bool Triangulation_segment_traverser_3<Tr>::
operator!=( const TST& ct ) const {
return !( *this == ct );
}
template <class Tr>
inline bool Triangulation_segment_traverser_3<Tr>::
operator==( Nullptr_t CGAL_triangulation_assertion_code(n) ) const {
CGAL_triangulation_assertion( n == NULL );
return _pos == Cell_handle();
}
template <class Tr>
inline bool Triangulation_segment_traverser_3<Tr>::
operator!=( Nullptr_t n ) const {
return !( *this == n );
}
template <class Tr>
void Triangulation_segment_traverser_3<Tr>::
increment() {
CGAL_triangulation_precondition( !_done );
// Walks to the next cell over a facet intersected by the line from source to target.
// This method is based on Triangulation_3::locate().
int inf;
switch( _tr.dimension() ) {
case 3: {
// Infinite cells should be handled differently.
if( _pos->has_vertex( _tr.infinite_vertex(), inf ) )
increment_3_inf( inf );
else
increment_3();
break;
}
case 2: {
if( _pos->has_vertex( _tr.infinite_vertex(), inf ) )
increment_2_inf( inf );
else
increment_2();
break;
}
}
}
template <class Tr>
void Triangulation_segment_traverser_3<Tr>::
increment_3() {
Vertex_handle vert[4] = { _pos->vertex(0),
_pos->vertex(1),
_pos->vertex(2),
_pos->vertex(3) };
// We check in which direction the target lies
// by comparing its position relative to the planes through the
// source and the edges of the cell.
Orientation o[6];
// We keep track of which orientations are calculated.
bool calc[6] = { false, false, false, false, false, false };
if( _lt == Tr::VERTEX ) {
// The three planes through the vertex are set to coplanar.
for( int j = 0; j < 4; ++j ) {
if( _li != j ) {
int ij = edgeIndex( _li, j );
o[ij] = COPLANAR;
calc[ij] = true;
}
}
}
else if( _lt == Tr::EDGE ) {
// The plane through the edge is set to coplanar.
int ij = edgeIndex( _li, _lj );
o[ij] = COPLANAR;
calc[ij] = true;
}
// For the remembering stochastic walk, we start trying with a random facet.
int li = rng.template get_bits<2>();
CGAL_triangulation_assertion_code( bool incell = true; )
for( int k = 0; k < 4; ++k, li = _tr.incr_ind(li) ) {
Cell_handle next = _pos->neighbor(li);
if( next == _prev )
continue;
if( _t_vertex == _pos->vertex(0) || _t_vertex == _pos->vertex(1) ||
_t_vertex == _pos->vertex(2) || _t_vertex == _pos->vertex(3) ) {
// The target is inside the cell.
_done = true;
return;
}
// Check if the target is outside the cell.
Vertex_handle backup = vert[li];
vert[li] = _t_vert;
if( _tr.orientation( vert[0], vert[1], vert[2], vert[3] ) != NEGATIVE ) {
vert[li] = backup;
continue;
}
CGAL_triangulation_assertion_code( incell = false; )
// Check if the target is inside the pyramid.
int lj = rng.template get_bits<2>();
int Or = 0;
for( int l = 0; l < 4; ++l, lj = _tr.incr_ind(lj) ) {
if( li == lj )
continue;
// We check the orientation of the target compared to the plane
// Through the source and the edge opposite of ij.
int oij = 5 - edgeIndex( li, lj );
if( !calc[oij] ) {
Vertex_handle backup2 = vert[lj];
vert[lj] = _s_vert;
o[oij] = _tr.orientation( vert[0], vert[1], vert[2], vert[3] );
vert[lj] = backup2;
calc[oij] = true;
}
Or -= o[oij];
if( o[oij] == POSITIVE ) {
// The target is not inside the pyramid.
// Invert the planes.
// This can be safely done because either
// they were not calculated yet,
// or they will no longer be used.
for( int j = 0; j < 4; ++j ) {
if( li == j ) continue;
int oij = 5 - edgeIndex( li, j );
o[oij] = -o[oij];
}
Or = 0;
break;
}
}
if( Or == 0 ) {
// Either the target is not inside the pyramid,
// or the pyramid is degenerate.
vert[li] = backup;
continue;
}
// The target is inside the pyramid.
_prev = _pos;
_pos = next;
switch( Or ) {
case 3:
_lt = Tr::FACET;
_li = _pos->index(_prev);
return;
case 2:
_lt = Tr::EDGE;
for( int j = 0; j < 4; ++j ) {
if( li != j && o[ 5 - edgeIndex(li, j) ] == COPLANAR) {
Edge opp = _tr.opposite_edge( _prev, li, j );
_li = _pos->index( _prev->vertex(opp.second) );
_lj = _pos->index( _prev->vertex(opp.third) );
return;
}
}
CGAL_triangulation_assertion( false );
return;
case 1:
_lt = Tr::VERTEX;
for( int j = 0; j < 4; ++j ) {
if( li != j && o[ 5 - edgeIndex(li, j) ] == NEGATIVE ) {
_li = _pos->index( _prev->vertex(j) );
return;
}
}
CGAL_triangulation_assertion( false );
return;
default:
CGAL_triangulation_assertion( false );
return;
}
}
// The target lies inside this cell.
CGAL_triangulation_assertion( incell );
_done = true;
return;
}
template <class Tr>
void Triangulation_segment_traverser_3<Tr>::
increment_3_inf( int inf ) {
CGAL_triangulation_precondition( _tr.is_infinite( _pos->vertex(inf) ) );
// If this cell was reached by traversal from a finite one, it must be the final cell.
Cell_handle fin = _pos->neighbor(inf);
if( fin == _prev ) {
_done = true;
// Here, I do not change the _lt etc. because they were already set.
return;
}
Vertex_handle vert[4];
for( int i = 0; i != 4; ++i )
if( i != inf )
vert[i] = _pos->vertex(i);
vert[inf] = _t_vert;
Orientation o[4];
// For the remembering stochastic walk, we start trying with a random index:
int li = rng.template get_bits<2>();
// Check if the target lies outside the convex hull.
if( _tr.orientation( vert[0], vert[1], vert[2], vert[3] ) == POSITIVE ) {
// The target lies in an infinite cell.
// Note that we do not traverse to other infinite cells.
_done = true;
return;
}
vert[inf] = _s_vert;
CGAL_triangulation_assertion( _tr.orientation( vert[0], vert[1], vert[2], vert[3] ) == POSITIVE );
// Check if the line enters an adjacent infinite cell.
// This occurs if the target lies on the other side of
// a plane through one of the finite edges and the source point.
for( int j = 0; j != 4; ++j, li = _tr.incr_ind(li) ) {
if( li == inf ) {
o[li] = COPLANAR;
continue;
}
Cell_handle next = _pos->neighbor(li);
if( next == _prev ) {
o[li] = POSITIVE;
continue;
}
Vertex_handle backup = vert[li];
vert[li] = _t_vert;
o[li] = _tr.orientation( vert[0], vert[1], vert[2], vert[3] );
if( o[li] != NEGATIVE ) {
vert[li] = backup;
continue;
}
// The target lies behind the plane through the source and two finite vertices.
// Traverse to the incident infinite cell.
_prev = _pos;
_pos = next;
CGAL_triangulation_assertion( _tr.is_infinite(_pos) );
_lt = Tr::FACET;
_li = _pos->index(_prev);
return;
}
// The line enters the convex hull here (or lies on the finite facet).
_prev = _pos;
_pos = fin;
// Check through which simplex the line traverses.
switch( o[0]+o[1]+o[2]+o[3] ) {
case 3:
_lt = Tr::FACET;
_li = _pos->index(_prev);
return;
case 2:
_lt = Tr::EDGE;
for( int i = 0; i < 4; ++i ) {
if( o[i] == COPLANAR && i != inf ) {
Edge opp = _tr.opposite_edge( _prev, inf, i );
_li = _pos->index( _prev->vertex(opp.second) );
_lj = _pos->index( _prev->vertex(opp.third) );
return;
}
}
CGAL_triangulation_assertion( false );
return;
case 1:
_lt = Tr::VERTEX;
for( int i = 0; i < 4; ++i ) {
if( o[i] == POSITIVE ) {
_li = _pos->index( _prev->vertex(i) );
return;
}
}
CGAL_triangulation_assertion( false );
return;
default:
CGAL_triangulation_assertion( false );
return;
}
}
template <class Tr>
void Triangulation_segment_traverser_3<Tr>::
increment_2() {
Vertex_handle vert[3] = { _pos->vertex(0),
_pos->vertex(1),
_pos->vertex(2) };
switch( _lt ) {
case Tr::VERTEX: {
// First we try the incident edges.
Orientation ocw = _tr.coplanar_orientation( vert[_li], vert[_tr.cw(_li)], vert[_tr.ccw(_li)], _t_vert );
if( _pos->neighbor( _tr.ccw(_li) ) != _prev && ocw == NEGATIVE) {
Cell_handle tmp = _pos->neighbor( _tr.ccw(_li) );
_prev = _pos;
_pos = tmp;
_li = _pos->index( _prev->vertex(_li) );
return;
}
Orientation occw = _tr.coplanar_orientation( vert[_li], vert[_tr.ccw(_li)], vert[_tr.cw(_li)], _t_vert );
if( _pos->neighbor( _tr.cw(_li) ) != _prev && occw == NEGATIVE) {
Cell_handle tmp = _pos->neighbor( _tr.cw(_li) );
_prev = _pos;
_pos = tmp;
_li = _pos->index( _prev->vertex(_li) );
return;
}
// Then we try the opposite edge.
if( _tr.coplanar_orientation( vert[_tr.ccw(_li)], vert[_tr.cw(_li)], vert[_li], _t_vert ) == NEGATIVE) {
Cell_handle tmp = _pos->neighbor(_li);
_prev = _pos;
_pos = tmp;
switch( ocw+occw ) {
case 2:
_lt = Tr::EDGE;
_li = _pos->index( _prev->vertex( _tr.ccw(_li) ) );
_lj = _pos->index( _prev->vertex( _tr.cw(_li) ) );
return;
case 1:
_lt = Tr::VERTEX;
if( ocw == COLLINEAR ) _li = _pos->index( _prev->vertex( _tr.cw(_li) ) );
else _li = _pos->index( _prev->vertex( _tr.ccw(_li) ) );
return;
default:
CGAL_triangulation_assertion(false);
return;
}
}
// The target lies in this cell.
_done = true;
return;
}
case Tr::EDGE: {
int lk = 3-_li-_lj;
if( _pos->neighbor(lk) != _prev ) {
// Check the edge itself
switch( _tr.coplanar_orientation( vert[_li], vert[_lj], vert[lk], _t_vert ) ) {
case COLLINEAR:
// The target lies in this cell.
_done = true;
return;
case NEGATIVE: {
// The target lies opposite of the edge.
Cell_handle tmp = _pos->neighbor(lk);
_prev = _pos;
_pos = tmp;
_li = _pos->index( _prev->vertex(_li) );
_lj = _pos->index( _prev->vertex(_lj) );
return;
}
default:
break;
}
}
Orientation o = _tr.coplanar_orientation( _s_vert, vert[lk], vert[_li], _t_vert );
switch( o ) {
case POSITIVE: {
// The ray passes through the edge ik.
if( _tr.coplanar_orientation( vert[lk], vert[_li], _s_vert, _t_vert ) == NEGATIVE ) {
Cell_handle tmp = _pos->neighbor(_lj);
_prev = _pos;
_pos = tmp;
if( _tr.collinear( _s_vert, vert[_li], _t_vert ) ) {
_lt = Tr::VERTEX;
_li = _pos->index( _prev->vertex(_li) );
}
else {
_lt = Tr::EDGE;
_li = _pos->index( _prev->vertex(_li) );
_lj = _pos->index( _prev->vertex(lk) );
}
return;
}
break;
}
default: {
// The ray passes through the edge jk.
if( _tr.coplanar_orientation( vert[lk], vert[_lj], _s_vert, _t_vert ) == NEGATIVE ) {
Cell_handle tmp = _pos->neighbor(_li);
_prev = _pos;
_pos = tmp;
if( _tr.collinear( _s_vert, vert[_lj], _t_vert ) ) {
_lt = Tr::VERTEX;
_li = _pos->index( _prev->vertex(_lj) );
}
else if( o == COLLINEAR ) {
_lt = Tr::VERTEX;
_li = _pos->index( _prev->vertex(lk) );
}
else {
_lt = Tr::EDGE;
_li = _pos->index( _prev->vertex(lk) );
_lj = _pos->index( _prev->vertex(_lj) );
}
return;
}
break;
}
}
// The target lies in this cell.
_done = true;
return;
}
case Tr::FACET: {
// We test its edges in a random order until we find a neighbor to go further
int li = rng.get_int(0, 3);
Orientation o[3];
bool calc[3] = { false, false, false };
for( int j = 0; j != 3; ++j, li = _tr.ccw(li) ) {
Cell_handle next = _pos->neighbor(li);
if( next == _prev )
continue;
// The target should lie on the other side of the edge.
if( _tr.coplanar_orientation( vert[_tr.ccw(li)], vert[_tr.cw(li)], vert[li], _t_vert ) != NEGATIVE )
continue;
// The target should lie inside the wedge.
if( !calc[_tr.ccw(li)] ) {
o[_tr.ccw(li)] = _tr.coplanar_orientation( _s_vert, vert[_tr.ccw(li)], vert[_tr.cw(li)], _t_vert );
calc[_tr.ccw(li)] = true;
}
if( o[_tr.ccw(li)] == NEGATIVE ) continue;
if( !calc[_tr.cw(li)] ) {
o[_tr.cw(li)] = _tr.coplanar_orientation( _s_vert, vert[_tr.cw(li)], vert[_tr.ccw(li)], _t_vert );
calc[_tr.cw(li)] = true;
}
if( o[_tr.cw(li)] == POSITIVE ) continue;
_prev = _pos;
_pos = next;
switch( o[_tr.ccw(li)] + o[_tr.cw(li)] ) {
case 2:
_lt = Tr::EDGE;
_li = _pos->index( _prev->vertex( _tr.ccw(li) ) );
_lj = _pos->index( _prev->vertex( _tr.cw(li) ) );
return;
case 1:
_lt = Tr::VERTEX;
if( o[_tr.ccw(li)] == COLLINEAR ) _li = _pos->index( _prev->vertex( _tr.ccw(li) ) );
else _li = _pos->index( _prev->vertex( _tr.cw(li) ) );
return;
default:
CGAL_triangulation_assertion( false );
return;
}
}
// The target lies in this cell.
_done = true;
return;
}
default:
CGAL_triangulation_assertion( false );
}
}
template <class Tr>
void Triangulation_segment_traverser_3<Tr>::
increment_2_inf( int inf ) {
CGAL_triangulation_precondition( _tr.is_infinite( _pos->vertex(3) ) );
CGAL_triangulation_precondition( _tr.is_infinite( _pos->vertex(inf) ) );
// If this cell was reached by traversal from a finite one, it must be the final cell.
Cell_handle fin = _pos->neighbor(inf);
if (fin == _prev) {
_done = true;
return;
}
// Check the neighboring cells.
Gt::Coplanar_orientation_3 coplanar_orientation = Gt().coplanar_orientation_3_object();
if( _tr.coplanar_orientation( _s_vert, _pos->vertex( _tr.ccw(inf)), _pos->vertex(_tr.cw(inf)), _t_vert ) == NEGATIVE ) {
Cell_handle tmp = _pos->neighbor(_tr.cw(inf));
_prev = _pos;
_pos = tmp;
return;
}
if( _tr.coplanar_orientation( _s_vert, _pos->vertex( _tr.cw(inf)), _pos->vertex(_tr.ccw(inf)), _t_vert ) == NEGATIVE ) {
Cell_handle tmp = _pos->neighbor(_tr.ccw(inf));
_prev = _pos;
_pos = tmp;
return;
}
if( _tr.coplanar_orientation( _pos->vertex( _tr.ccw(inf)), _pos->vertex(_tr.cw(inf)), _s_vert, _t_vert ) != POSITIVE ) {
_prev = _pos;
_pos = fin;
return;
}
// The target lies in this infinite cell.
_done = true;
return;
}
} //end of CGAL namespace
#endif // CGAL_TRIANGULATION_SEGMENT_TRAVERSER_3_IMPL_H

View File

@ -29,55 +29,81 @@ namespace CGAL {
// We use the following template class in order to avoid having a static data
// member of a non-template class which would require src/Triangulation_3.C .
template < class T = void >
struct Triangulation_utils_base_3
{
static const char tab_next_around_edge[4][4];
static const int tab_vertex_triple_index[4][3];
struct Triangulation_utils_base_3 {
static const char tab_next_around_edge[4][4];
static const int tab_vertex_triple_index[4][3];
static const int index_increment_map[4];
static const int index_jump_map[4];
static const int index_decrement_map[4];
};
template < class T >
const char Triangulation_utils_base_3<T>::tab_next_around_edge[4][4] = {
{5, 2, 3, 1},
{3, 5, 0, 2},
{1, 3, 5, 0},
{2, 0, 1, 5} };
{ 5, 2, 3, 1 },
{ 3, 5, 0, 2 },
{ 1, 3, 5, 0 },
{ 2, 0, 1, 5 }
};
template < class T >
const int Triangulation_utils_base_3<T>::tab_vertex_triple_index[4][3] = {
{1, 3, 2},
{0, 2, 3},
{0, 3, 1},
{0, 1, 2}
{ 1, 3, 2 },
{ 0, 2, 3 },
{ 0, 3, 1 },
{ 0, 1, 2 }
};
template < class T >
const int Triangulation_utils_base_3<T>::index_increment_map[4] = { 1, 2, 3, 0 };
template < class T >
const int Triangulation_utils_base_3<T>::index_jump_map[4] = { 2, 3, 0, 1 };
template < class T >
const int Triangulation_utils_base_3<T>::index_decrement_map[4] = { 3, 0, 1, 2 };
// We derive from Triangulation_cw_ccw_2 because we still use cw() and ccw()
// in the 2D part of the code. Ideally, this should go away when we re-use
// T2D entirely.
struct Triangulation_utils_3
: public Triangulation_cw_ccw_2,
public Triangulation_utils_base_3<>
{
static int next_around_edge(const int i, const int j)
{
// index of the next cell when turning around the
// oriented edge vertex(i) vertex(j) in 3d
CGAL_triangulation_precondition( ( i >= 0 && i < 4 ) &&
( j >= 0 && j < 4 ) &&
( i != j ) );
return tab_next_around_edge[i][j];
}
: public Triangulation_cw_ccw_2,
public Triangulation_utils_base_3<> {
static int next_around_edge( const int i, const int j ) {
// index of the next cell when turning around the
// oriented edge vertex(i) vertex(j) in 3d
CGAL_triangulation_precondition( ( i >= 0 && i < 4 ) &&
( j >= 0 && j < 4 ) &&
( i != j ) );
return tab_next_around_edge[i][j];
}
static int vertex_triple_index( const int i, const int j ) {
// indexes of the jth vertex of the facet of a cell
// opposite to vertx i
CGAL_triangulation_precondition( ( i >= 0 && i < 4 ) &&
( j >= 0 && j < 3 ) );
return tab_vertex_triple_index[i][j];
}
static int vertex_triple_index(const int i, const int j)
{
// indexes of the jth vertex of the facet of a cell
// opposite to vertx i
CGAL_triangulation_precondition( ( i >= 0 && i < 4 ) &&
( j >= 0 && j < 3 ) );
return tab_vertex_triple_index[i][j];
}
// Get the index of the next vertex or facet.
static int increment_index( int li ) {
CGAL_triangulation_precondition( li >= 0 && li < 4 );
return index_increment_map[ li ];
}
// Get the index of the vertex or facet two places further.
static int jump_index( int li ) {
CGAL_triangulation_precondition( li >= 0 && li < 4 );
return index_jump_map[ li ];
}
// Get the index of the previous vertex or facet.
static int decrement_index( int li ) {
CGAL_triangulation_precondition( li >= 0 && li < 4 );
return index_decrement_map[ li ];
}
};
} //namespace CGAL

View File

@ -0,0 +1,37 @@
// A dummy geometry traits class.
// Copyright (c) 2003 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
//This program is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// Author(s): Thijs van Lankveld
#ifndef CGAL_INTERNAL_TRIANGULATION_DUMMY_GT_H
#define CGAL_INTERNAL_TRIANGULATION_DUMMY_GT_H
namespace CGAL { namespace internal {
// Dummy triangulation which provides all types that a triangulation can use.
struct Dummy_gt {
struct Point_3 {};
struct Segment_3 {};
struct Triangle_3 {};
struct Tetrahedron_3 {};
};
} // namespace internal
} // namespace CGAL
#endif // CGAL_INTERNAL_TRIANGULATION_DUMMY_GT_H