mirror of https://github.com/CGAL/cgal
Very first version of conforming triangulation 3.
This commit is contained in:
parent
593901efcf
commit
68daecef6e
File diff suppressed because it is too large
Load Diff
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
Utrecht University (The Netherlands) & INRIA Sophia-Antipolis (France)
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1 @@
|
|||
GPL (v3 or later)
|
||||
|
|
@ -0,0 +1 @@
|
|||
Thijs van Lankveld <thijs.van-lankveld@sophia.inria.fr>
|
||||
Loading…
Reference in New Issue