Very first version of conforming triangulation 3.

This commit is contained in:
Thijs van Lankveld 2013-02-25 18:26:51 +01:00 committed by Jane Tournois
parent 593901efcf
commit 68daecef6e
10 changed files with 2739 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,179 @@
//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>
CGAL_BEGIN_NAMESPACE
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;
}
CGAL_END_NAMESPACE
#endif // CGAL_CONFORMING_TRIANGULATION_CELL_BASE_3_H

View File

@ -0,0 +1,69 @@
//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>
CGAL_BEGIN_NAMESPACE
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();
}
CGAL_END_NAMESPACE
#endif // CGAL_CONFORMING_TRIANGULATION_VERTEX_BASE_3_H

View File

@ -0,0 +1,402 @@
//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 "CCDT/Triangulation_segment_traverser_3.h"
CGAL_BEGIN_NAMESPACE
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 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;
#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 (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());
}
CGAL_END_NAMESPACE
#endif // CGAL_DELAUNAY_TRIANGULATION_3_UTILS_H

View File

@ -0,0 +1,123 @@
//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"
//#include "Conforming_Delaunay_triangulation_3.h"
CGAL_BEGIN_NAMESPACE
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;
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;
}
}
CGAL_END_NAMESPACE
#endif // CGAL_ENCROACHING_COLLECTER_3_H

View File

@ -0,0 +1,695 @@
//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>
CGAL_BEGIN_NAMESPACE
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);
}
}
}
}
CGAL_END_NAMESPACE
#endif // CGAL_TRIANGULATION_SEGMENT_TRAVERSER_3_H

View File

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

View File

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

View File

@ -0,0 +1 @@
GPL (v3 or later)

View File

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