mirror of https://github.com/CGAL/cgal
First setup for the segment traverser small feature.
This commit is contained in:
parent
2f7eb3aed5
commit
5640b84b2b
|
|
@ -1,105 +0,0 @@
|
|||
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||
#include <CGAL/Conforming_Delaunay_triangulation_3.h>
|
||||
#include <CGAL/Triangulation_vertex_base_with_info_3.h>
|
||||
|
||||
|
||||
typedef CGAL::Exact_predicates_exact_constructions_kernel K;
|
||||
typedef K::Point_3 Point_3;
|
||||
|
||||
typedef CGAL::Triangulation_vertex_base_with_info_3<int,K,CGAL::Conforming_triangulation_vertex_base_3<K> > Vb;
|
||||
typedef CGAL::Conforming_triangulation_cell_base_3<K> Cb;
|
||||
typedef CGAL::Triangulation_data_structure_3 < Vb, Cb > Tds;
|
||||
|
||||
typedef CGAL::Conforming_Delaunay_triangulation_3< K, Tds > CDT3;
|
||||
|
||||
|
||||
template <class Triangulation, class InputIterator>
|
||||
std::ptrdiff_t insert_with_info(Triangulation& t, InputIterator first,InputIterator last)
|
||||
{
|
||||
typedef typename Triangulation::Geom_traits Geom_traits;
|
||||
typedef typename Triangulation::Vertex_handle Vertex_handle;
|
||||
|
||||
std::size_t n = t.number_of_vertices();
|
||||
std::vector<std::ptrdiff_t> indices;
|
||||
std::vector<Point_3> points;
|
||||
std::vector<typename Triangulation::Vertex::Info> infos;
|
||||
std::ptrdiff_t index=0;
|
||||
for (InputIterator it=first;it!=last;++it){
|
||||
std::pair<Point_3,int> value=*it;
|
||||
points.push_back( value.first );
|
||||
infos.push_back ( value.second );
|
||||
indices.push_back(index++);
|
||||
}
|
||||
|
||||
typedef CGAL::Spatial_sort_traits_adapter_3<Geom_traits,Point_3*> Search_traits;
|
||||
|
||||
CGAL::spatial_sort(indices.begin(),indices.end(),Search_traits(&(points[0]),Geom_traits()));
|
||||
|
||||
Vertex_handle hint;
|
||||
for (typename std::vector<std::ptrdiff_t>::const_iterator
|
||||
it = indices.begin(), end = indices.end();
|
||||
it != end; ++it){
|
||||
hint = t.insert(points[*it], hint);
|
||||
if (hint!=Vertex_handle()) hint->info()=infos[*it];
|
||||
}
|
||||
|
||||
return t.number_of_vertices() - n;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
std::vector< std::pair<Point_3,int> > points;
|
||||
points.push_back( std::make_pair(Point_3(0,0,0),0) );
|
||||
points.push_back( std::make_pair(Point_3(1,0,0),1) );
|
||||
points.push_back( std::make_pair(Point_3(0,1,0),2) );
|
||||
points.push_back( std::make_pair(Point_3(0.2,0.2,100),3) );
|
||||
points.push_back( std::make_pair(Point_3(0.2,0.2,-100),4) );
|
||||
|
||||
|
||||
std::vector< std::pair<int, int> > constraints;
|
||||
constraints.push_back( std::make_pair(0,1) );
|
||||
constraints.push_back( std::make_pair(0,2) );
|
||||
constraints.push_back( std::make_pair(1,2) );
|
||||
constraints.push_back( std::make_pair(3,4) );
|
||||
|
||||
CDT3 cdt3;
|
||||
insert_with_info( cdt3, points.begin(), points.end() );
|
||||
|
||||
|
||||
std::vector< CDT3::Vertex_handle > vertices( points.size() );
|
||||
|
||||
for (CDT3::Finite_vertices_iterator vit=cdt3.finite_vertices_begin(),
|
||||
vit_end=cdt3.finite_vertices_end();vit!=vit_end;++vit)
|
||||
{
|
||||
vertices[ vit->info() ]=vit;
|
||||
}
|
||||
|
||||
std::cout << cdt3.number_of_vertices() << std::endl;
|
||||
|
||||
std::cout << "Making Delaunay conform" << std::endl;
|
||||
for (std::vector< std::pair<int,int> >::iterator cst_it=constraints.begin(),
|
||||
cst_end=constraints.end();
|
||||
cst_it!=cst_end; ++cst_it)
|
||||
{
|
||||
cdt3.insert_conforming( std::make_pair(vertices[cst_it->first], vertices[cst_it->second]) );
|
||||
}
|
||||
|
||||
|
||||
for(CDT3::Finite_edges_iterator it=cdt3.finite_edges_begin(); it!=cdt3.finite_edges_end(); ++it)
|
||||
if ( it->first->vertex(it->second)->steiner() || it->first->vertex(it->third)->steiner() )
|
||||
std::cout << "edge with steiner endpoint" << std::endl;
|
||||
|
||||
std::cout << "Making Gabriel conform" << std::endl;
|
||||
for (std::vector< std::pair<int,int> >::iterator cst_it=constraints.begin(),
|
||||
cst_end=constraints.end();
|
||||
cst_it!=cst_end; ++cst_it)
|
||||
{
|
||||
cdt3.insert_conforming_Gabriel( vertices[cst_it->first], vertices[cst_it->second] );
|
||||
}
|
||||
|
||||
for(CDT3::Finite_edges_iterator it=cdt3.finite_edges_begin(); it!=cdt3.finite_edges_end(); ++it)
|
||||
if ( it->first->vertex(it->second)->steiner() || it->first->vertex(it->third)->steiner() )
|
||||
std::cout << "edge with steiner endpoint" << std::endl;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,179 +0,0 @@
|
|||
//A tetrahedral cell in a conforming Delaunay triangulation.
|
||||
//Copyright (C) 2012 Utrecht University
|
||||
//
|
||||
//This program is free software: you can redistribute it and/or modify
|
||||
//it under the terms of the GNU General Public License as published by
|
||||
//the Free Software Foundation, either version 3 of the License, or
|
||||
//(at your option) any later version.
|
||||
//
|
||||
//This program is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
//GNU General Public License for more details.
|
||||
//
|
||||
//You should have received a copy of the GNU General Public License
|
||||
//along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// Author(s): Thijs van Lankveld
|
||||
|
||||
// Based on CGAL/Triangulation_cell_base_3.h
|
||||
//
|
||||
|
||||
// Note that a constrained 3D Delaunay triangulation is partially conforming and guided.
|
||||
// 1-dimensional constraints are specified by segments.
|
||||
// 2-demensional constraints are specified by closure complete polygons.
|
||||
// The constrained 3D DT must contain a collection of edges and faces that exactly cover
|
||||
// each constrained segment or polygon. For example, a constrained edge will not necessarily
|
||||
// be maintained as vertices are inserted, but after updating the triangulation to the vertex
|
||||
// insertion, the constrained edge must be the union of one or more constrained edges.
|
||||
|
||||
#ifndef CGAL_CONFORMING_TRIANGULATION_CELL_BASE_3_H
|
||||
#define CGAL_CONFORMING_TRIANGULATION_CELL_BASE_3_H
|
||||
|
||||
#include <CGAL/basic.h>
|
||||
#include <CGAL/triangulation_assertions.h>
|
||||
#include <CGAL/Triangulation_cell_base_3.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template < typename Gt, typename Cb = Triangulation_cell_base_3<Gt> >
|
||||
class Conforming_triangulation_cell_base_3: public Cb {
|
||||
public:
|
||||
typedef typename Cb::Vertex_handle Vertex_handle;
|
||||
typedef typename Cb::Cell_handle Cell_handle;
|
||||
|
||||
typedef Gt Geom_traits;
|
||||
typedef typename Geom_traits::Point_3 Point;
|
||||
|
||||
typedef Point* Point_container;
|
||||
typedef Point* Point_iterator;
|
||||
typedef const Point* Point_const_iterator;
|
||||
|
||||
template < typename TDS2 >
|
||||
struct Rebind_TDS {
|
||||
typedef typename Cb::template Rebind_TDS<TDS2>::Other Cb2;
|
||||
typedef Conforming_triangulation_cell_base_3<Gt, Cb2> Other;
|
||||
}; // Rebind_TDS
|
||||
|
||||
protected:
|
||||
// The edge states.
|
||||
bool EF[6];
|
||||
bool mm[6];
|
||||
|
||||
public:
|
||||
Conforming_triangulation_cell_base_3(): Cb() {clear_conforming();}
|
||||
Conforming_triangulation_cell_base_3(const Vertex_handle& v0, const Vertex_handle& v1,
|
||||
const Vertex_handle& v2, const Vertex_handle& v3)
|
||||
: Cb(v0, v1, v2, v3) {clear_conforming();}
|
||||
Conforming_triangulation_cell_base_3(const Vertex_handle& v0, const Vertex_handle& v1,
|
||||
const Vertex_handle& v2, const Vertex_handle& v3,
|
||||
const Cell_handle& n0, const Cell_handle& n1,
|
||||
const Cell_handle& n2, const Cell_handle& n3)
|
||||
: Cb(v0, v1, v2, v3, n0, n1, n2, n3) {clear_conforming();}
|
||||
|
||||
bool is_conforming(int i, int j) const {return EF[getEdgeIndex(i,j)];}
|
||||
bool is_marked(int i, int j) const {return mm[getEdgeIndex(i,j)];}
|
||||
|
||||
void set_conforming(bool c0, bool c1, bool c2, bool c3, bool c4, bool c5) {
|
||||
EF[0] = c0;
|
||||
EF[1] = c1;
|
||||
EF[2] = c2;
|
||||
EF[3] = c3;
|
||||
EF[4] = c4;
|
||||
EF[5] = c5;
|
||||
clear_marked();
|
||||
}
|
||||
void set_conforming(int i, int j, bool c) {
|
||||
int index = getEdgeIndex(i,j);
|
||||
EF[index] = c;
|
||||
mm[index] = false;
|
||||
}
|
||||
void mark(int i, int j) {
|
||||
int index = getEdgeIndex(i,j);
|
||||
EF[index] = true;
|
||||
mm[index] = true;
|
||||
}
|
||||
|
||||
void clear_conforming() {set_conforming(false, false, false, false, false, false);}
|
||||
void clear_marked() {
|
||||
mm[0] = false;
|
||||
mm[1] = false;
|
||||
mm[2] = false;
|
||||
mm[3] = false;
|
||||
mm[4] = false;
|
||||
mm[5] = false;
|
||||
}
|
||||
virtual void clear() {clear_conforming();}
|
||||
|
||||
bool has_conforming() const {return EF[0] || EF[1] || EF[2] || EF[3] || EF[4] || EF[5];}
|
||||
|
||||
virtual void reorient() {
|
||||
bool tmp = EF[1];
|
||||
EF[1] = EF[3];
|
||||
EF[3] = tmp;
|
||||
tmp = mm[1];
|
||||
mm[1] = mm[3];
|
||||
mm[3] = tmp;
|
||||
}
|
||||
|
||||
virtual std::istream& read_cell(std::istream& is);
|
||||
virtual std::ostream& write_cell(std::ostream& os) const;
|
||||
|
||||
private:
|
||||
int getEdgeIndex(int i, int j) const {
|
||||
CGAL_triangulation_precondition(i>=0 && i<=3);
|
||||
CGAL_triangulation_precondition(j>=0 && j<=3);
|
||||
CGAL_triangulation_precondition(i != j);
|
||||
return (i==0 || j==0) ? i+j-1 : i+j;
|
||||
}
|
||||
}; // Conforming_triangulation_cell_base_3
|
||||
|
||||
template < class Gt, class Cb >
|
||||
inline std::istream& operator>>(std::istream& is, Conforming_triangulation_cell_base_3<Gt, Cb>& c) {
|
||||
is >> static_cast<Cb&>(c);
|
||||
return c.read_cell(is);
|
||||
}
|
||||
|
||||
template < class Gt, class Cb >
|
||||
inline std::ostream& operator<<(std::ostream &os, const Conforming_triangulation_cell_base_3<Gt, Cb>& c) {
|
||||
os << static_cast<const Cb&>(c);
|
||||
return c.write_cell(os);
|
||||
}
|
||||
|
||||
template < class Gt, class Cb >
|
||||
std::istream& Conforming_triangulation_cell_base_3<Gt, Cb>::read_cell(std::istream& is) {
|
||||
char s;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
for (int j = i+1; j < 4; ++j) {
|
||||
if (is_ascii(is))
|
||||
is >> s;
|
||||
else
|
||||
read(is, s);
|
||||
if (s == 'C')
|
||||
set_conforming(i, j, true);
|
||||
}
|
||||
}
|
||||
|
||||
return is;
|
||||
}
|
||||
|
||||
template < class Gt, class Cb >
|
||||
std::ostream& Conforming_triangulation_cell_base_3<Gt, Cb>::write_cell(std::ostream& os) const {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
for (int j = i+1; j < 4; ++j) {
|
||||
if (is_conforming(i, j)) {
|
||||
os << "C";
|
||||
}
|
||||
else
|
||||
os << "N";
|
||||
if (is_ascii(os))
|
||||
os << ' ';
|
||||
}
|
||||
}
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
} //end of CGAL namespace
|
||||
|
||||
#endif // CGAL_CONFORMING_TRIANGULATION_CELL_BASE_3_H
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
//A vertex in the conforming Delaunay triangulation structure.
|
||||
//Copyright (C) 2012 Utrecht University
|
||||
//
|
||||
//This program is free software: you can redistribute it and/or modify
|
||||
//it under the terms of the GNU General Public License as published by
|
||||
//the Free Software Foundation, either version 3 of the License, or
|
||||
//(at your option) any later version.
|
||||
//
|
||||
//This program is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
//GNU General Public License for more details.
|
||||
//
|
||||
//You should have received a copy of the GNU General Public License
|
||||
//along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// Author(s): Thijs van Lankveld
|
||||
|
||||
#ifndef CGAL_CONFORMING_TRIANGULATION_VERTEX_BASE_3_H
|
||||
#define CGAL_CONFORMING_TRIANGULATION_VERTEX_BASE_3_H
|
||||
|
||||
#include <CGAL/Triangulation_vertex_base_3.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template < typename GT, typename Vb = Triangulation_vertex_base_3<GT> >
|
||||
class Conforming_triangulation_vertex_base_3: public Vb {
|
||||
bool _s;
|
||||
|
||||
public:
|
||||
typedef typename Vb::Cell_handle Cell_handle;
|
||||
typedef typename Vb::Point Point;
|
||||
|
||||
template < typename TDS2 > struct Rebind_TDS {
|
||||
typedef typename Vb::template Rebind_TDS<TDS2>::Other Vb2;
|
||||
typedef Conforming_triangulation_vertex_base_3<GT, Vb2> Other;
|
||||
};
|
||||
|
||||
Conforming_triangulation_vertex_base_3(): Vb(), _s(false) {}
|
||||
Conforming_triangulation_vertex_base_3(const Point& p): Vb(p), _s(false) {}
|
||||
Conforming_triangulation_vertex_base_3(const Point& p, bool s): Vb(p), _s(s) {}
|
||||
Conforming_triangulation_vertex_base_3(const Point& p, Cell_handle c): Vb(p, c), _s(false) {}
|
||||
Conforming_triangulation_vertex_base_3(const Point& p, bool s, Cell_handle c): Vb(p, c), _s(s) {}
|
||||
Conforming_triangulation_vertex_base_3(Cell_handle c): Vb(c), _s(false) {}
|
||||
|
||||
const bool& steiner() const {return _s;}
|
||||
bool& steiner() {return _s;}
|
||||
};
|
||||
|
||||
template < class GT, class Vb >
|
||||
std::istream&
|
||||
operator>>(std::istream &is, Conforming_triangulation_vertex_base_3<GT, Vb> &v) {
|
||||
is >> static_cast<Vb&>(v);
|
||||
if (is_ascii(is)) is >> v.steiner();
|
||||
else read(is, v.steiner());
|
||||
return is;
|
||||
}
|
||||
|
||||
template < class GT, class Vb >
|
||||
std::ostream&
|
||||
operator<<(std::ostream &os, const Conforming_triangulation_vertex_base_3<GT, Vb> &v) {
|
||||
os << static_cast<const Vb&>(v);
|
||||
if (is_ascii(os)) os << ' ';
|
||||
return os << v.steiner();
|
||||
}
|
||||
|
||||
} //end of CGAL namespace
|
||||
|
||||
#endif // CGAL_CONFORMING_TRIANGULATION_VERTEX_BASE_3_H
|
||||
|
|
@ -1,406 +0,0 @@
|
|||
//Some additional utilities for the Delaunay triangulation structure.
|
||||
//Copyright (C) 2012 Utrecht University
|
||||
//
|
||||
//This program is free software: you can redistribute it and/or modify
|
||||
//it under the terms of the GNU General Public License as published by
|
||||
//the Free Software Foundation, either version 3 of the License, or
|
||||
//(at your option) any later version.
|
||||
//
|
||||
//This program is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
//GNU General Public License for more details.
|
||||
//
|
||||
//You should have received a copy of the GNU General Public License
|
||||
//along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// Author(s): Thijs van Lankveld
|
||||
|
||||
// Based on CGAL/Delaunay_triangulation_3.h
|
||||
//
|
||||
// For the love of something, why is the 3D triangulation package so badly written?
|
||||
|
||||
#ifndef CGAL_DELAUNAY_TRIANGULATION_3_UTILS_H
|
||||
#define CGAL_DELAUNAY_TRIANGULATION_3_UTILS_H
|
||||
|
||||
#include <CGAL/basic.h>
|
||||
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <CGAL/Delaunay_triangulation_3.h>
|
||||
#include <CGAL/Triangulation_segment_traverser_3.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template < class DT > class Natural_neighbors_3;
|
||||
|
||||
template < class Gt, class Tds > class Triangulation_cell_traverser_3;
|
||||
|
||||
template < class Gt,
|
||||
class Tds_ = Triangulation_data_structure_3 < Triangulation_vertex_base_3<Gt>, Triangulation_cell_base_3<Gt> > >
|
||||
class Delaunay_triangulation_utils_3: public Delaunay_triangulation_3<Gt, Tds_> {
|
||||
//typedef Triangulation_data_structure Tds;
|
||||
typedef Tds_ Tds;
|
||||
typedef Delaunay_triangulation_utils_3<Gt, Tds> Self;
|
||||
typedef Delaunay_triangulation_3<Gt, Tds> DT;
|
||||
typedef Triangulation_3<Gt,Tds> Tr;
|
||||
|
||||
friend class Natural_neighbors_3<Self>;
|
||||
|
||||
public:
|
||||
typedef Tds Triangulation_data_structure;
|
||||
typedef Gt Geom_traits;
|
||||
|
||||
typedef typename Gt::FT FT;
|
||||
|
||||
typedef typename Gt::Point_3 Point;
|
||||
typedef typename Gt::Vector_3 Vector;
|
||||
typedef typename Gt::Segment_3 Segment;
|
||||
typedef typename Gt::Line_3 Line;
|
||||
typedef typename Gt::Triangle_3 Triangle;
|
||||
typedef typename Gt::Tetrahedron_3 Tetrahedron;
|
||||
typedef typename Gt::Plane_3 Plane;
|
||||
|
||||
typedef typename DT::Cell_handle Cell_handle;
|
||||
typedef typename DT::Vertex_handle Vertex_handle;
|
||||
|
||||
typedef typename DT::Cell Cell;
|
||||
typedef typename DT::Vertex Vertex;
|
||||
typedef typename DT::Facet Facet;
|
||||
typedef typename DT::Edge Edge;
|
||||
|
||||
typedef std::pair<Vertex_handle, Vertex_handle> Bi_vertex;
|
||||
typedef Triple<Vertex_handle, Vertex_handle, Vertex_handle> Tri_vertex;
|
||||
|
||||
typedef std::pair<Point, Point> Constraint_1;
|
||||
typedef std::vector<Point> Constraint_2;
|
||||
|
||||
typedef typename DT::Cell_circulator Cell_circulator;
|
||||
typedef typename DT::Facet_circulator Facet_circulator;
|
||||
typedef typename DT::Cell_iterator Cell_iterator;
|
||||
typedef typename DT::Facet_iterator Facet_iterator;
|
||||
typedef typename DT::Edge_iterator Edge_iterator;
|
||||
typedef typename DT::Vertex_iterator Vertex_iterator;
|
||||
|
||||
typedef typename DT::Finite_vertices_iterator Finite_vertices_iterator;
|
||||
typedef typename DT::Finite_cells_iterator Finite_cells_iterator;
|
||||
typedef typename DT::Finite_facets_iterator Finite_facets_iterator;
|
||||
typedef typename DT::Finite_edges_iterator Finite_edges_iterator;
|
||||
|
||||
typedef typename DT::All_cells_iterator All_cells_iterator;
|
||||
|
||||
typedef Triangulation_segment_traverser_3<Gt,Tds> Cell_traverser;
|
||||
|
||||
typedef typename DT::Locate_type Locate_type;
|
||||
|
||||
#ifndef CGAL_CFG_USING_BASE_MEMBER_BUG_2
|
||||
using DT::cw;
|
||||
using DT::ccw;
|
||||
using DT::coplanar;
|
||||
using DT::coplanar_orientation;
|
||||
using DT::dimension;
|
||||
using DT::finite_facets_begin;
|
||||
using DT::finite_facets_end;
|
||||
using DT::finite_vertices_begin;
|
||||
using DT::finite_vertices_end;
|
||||
using DT::finite_cells_begin;
|
||||
using DT::finite_cells_end;
|
||||
using DT::finite_edges_begin;
|
||||
using DT::finite_edges_end;
|
||||
using DT::geom_traits;
|
||||
using DT::infinite_vertex;
|
||||
using DT::is_valid;
|
||||
using DT::mirror_vertex;
|
||||
using DT::next_around_edge;
|
||||
using DT::number_of_vertices;
|
||||
using DT::orientation;
|
||||
using DT::remove;
|
||||
using DT::coplanar_side_of_bounded_circle;
|
||||
using DT::side_of_oriented_sphere;
|
||||
using DT::side_of_segment;
|
||||
using DT::tds;
|
||||
using DT::vertex_triple_index;
|
||||
using DT::locate;
|
||||
using DT::insert_in_conflict;
|
||||
using DT::is_infinite;
|
||||
using DT::insert;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
typedef std::list<Tri_vertex> Tri_vertex_collection;
|
||||
typedef std::list<Bi_vertex> Bi_vertex_collection;
|
||||
|
||||
protected:
|
||||
// Test whether a newly inserted point conflicts with the existing cells.
|
||||
class Conflict_tester_3 {
|
||||
protected:
|
||||
const Point& _p;
|
||||
const Self* _tr;
|
||||
|
||||
public:
|
||||
Conflict_tester_3(const Point& pt, const Self* tr): _p(pt), _tr(tr) {}
|
||||
bool operator()(const Cell_handle c) const {return _tr->side_of_sphere(c, _p, true) == ON_BOUNDED_SIDE;}
|
||||
Oriented_side compare_weight(const Point&, const Point&) const {return ZERO;}
|
||||
bool test_initial_cell(Cell_handle) const {return true;}
|
||||
}; // class Conflict_tester_3
|
||||
|
||||
// Test whether a newly inserted point conflicts with the existing cells.
|
||||
class Conflict_tester_2 {
|
||||
protected:
|
||||
const Point& _p;
|
||||
const Self* _tr;
|
||||
|
||||
public:
|
||||
Conflict_tester_2(const Point& pt, const Self* tr): _p(pt), _tr(tr) {}
|
||||
bool operator()(const Cell_handle c) const {return _tr->side_of_circle(c, 3, _p, true) == ON_BOUNDED_SIDE;}
|
||||
Oriented_side compare_weight(const Point&, const Point&) const {return ZERO;}
|
||||
bool test_initial_cell(Cell_handle) const {return true;}
|
||||
}; // class Conflict_tester_2
|
||||
|
||||
class Hidden_point_visitor {
|
||||
public:
|
||||
Hidden_point_visitor() {}
|
||||
|
||||
template < class InputIterator >
|
||||
void process_cells_in_conflict(InputIterator, InputIterator) const {}
|
||||
void reinsert_vertices(Vertex_handle) {}
|
||||
Vertex_handle replace_vertex(Cell_handle c, int index, const Point&) {return c->vertex(index);}
|
||||
void hide_point(Cell_handle, const Point&) {}
|
||||
}; // class Hidden_point_visitor
|
||||
|
||||
Hidden_point_visitor hidden_point_visitor;
|
||||
|
||||
public:
|
||||
// Constructors for bi-vertices.
|
||||
inline Bi_vertex to_bi_vertex(Cell_handle c, int li, int lj) const {return Bi_vertex(c->vertex(li), c->vertex(lj));}
|
||||
inline Bi_vertex to_bi_vertex(const Edge& e) const {return to_bi_vertex(e.first, e.second, e.third);}
|
||||
inline Bi_vertex sort_bi_vertex(Vertex_handle v1, Vertex_handle v2) const {if (v1 < v2) return Bi_vertex(v1, v2); return Bi_vertex(v2, v1);}
|
||||
inline Bi_vertex sort_bi_vertex(const Bi_vertex& bv) const {return sort_bi_vertex(bv.first, bv.second);}
|
||||
inline Bi_vertex sort_bi_vertex(Cell_handle c, int li, int lj) const {return sort_bi_vertex(c->vertex(li), c->vertex(lj));}
|
||||
inline Bi_vertex sort_bi_vertex(const Edge& e) const {return sort_bi_vertex(e.first, e.second, e.third);}
|
||||
|
||||
// Constructors for tri-vertices.
|
||||
inline Tri_vertex to_tri_vertex(Cell_handle c, int li) const {return Tri_vertex(c->vertex((li+1)&3), c->vertex((li+2)&3), c->vertex((li+3)&3));}
|
||||
inline Tri_vertex to_tri_vertex(const Facet& f) const {return to_tri_vertex(f.first, f.second);}
|
||||
inline Tri_vertex sort_tri_vertex(Vertex_handle v1, Vertex_handle v2, Vertex_handle v3) const {
|
||||
CGAL_triangulation_precondition(v1 != v2 && v1 != v3 && v2 != v3);
|
||||
if (v1 < v2) {
|
||||
if (v2 < v3)
|
||||
return Tri_vertex(v3, v2, v1);
|
||||
if (v3 < v1)
|
||||
return Tri_vertex(v2, v1, v3);
|
||||
return Tri_vertex(v2, v3, v1);
|
||||
}
|
||||
else { // v2 < v1
|
||||
if (v3 < v2)
|
||||
return Tri_vertex(v1, v2, v3);
|
||||
if (v1 < v3)
|
||||
return Tri_vertex(v3, v1, v2);
|
||||
return Tri_vertex(v1, v3, v2);
|
||||
}
|
||||
}
|
||||
inline Tri_vertex sort_tri_vertex(const Tri_vertex& tv) const {return sort_tri_vertex(tv.first, tv.second, tv.third);}
|
||||
inline Tri_vertex sort_tri_vertex(Cell_handle c, int li) const {return sort_tri_vertex(to_tri_vertex(c, li));}
|
||||
inline Tri_vertex sort_tri_vertex(const Facet& f) const {return sort_tri_vertex(f.first, f.second);}
|
||||
inline Tri_vertex oriented_tri_vertex(Cell_handle c, int li) const {
|
||||
CGAL_triangulation_precondition(dimension() == 2 || dimension() == 3);
|
||||
CGAL_triangulation_precondition((dimension() == 2 && li == 3) || (dimension() == 3 && li >= 0 && li <= 3) );
|
||||
CGAL_triangulation_precondition(!is_infinite(c, li));
|
||||
if ((li&1) == 0)
|
||||
return Tri_vertex(c->vertex((li+2)&3),
|
||||
c->vertex((li+1)&3),
|
||||
c->vertex((li+3)&3));
|
||||
return Tri_vertex(c->vertex((li+1)&3),
|
||||
c->vertex((li+2)&3),
|
||||
c->vertex((li+3)&3));
|
||||
}
|
||||
inline Tri_vertex oriented_tri_vertex(const Facet& f) const {return oriented_tri_vertex(f.first, f.second);}
|
||||
|
||||
protected:
|
||||
// tri_vertex methods similar to Triangulation_3.
|
||||
Tri_vertex make_tri_vertex(const Facet& f) const {
|
||||
return Tri_vertex(f.first->vertex(vertex_triple_index(f.second, 0)),
|
||||
f.first->vertex(vertex_triple_index(f.second, 1)),
|
||||
f.first->vertex(vertex_triple_index(f.second, 2)));
|
||||
}
|
||||
void make_canonical(Tri_vertex& t) const {
|
||||
int i = (&*(t.first) < &*(t.second))? 0 : 1;
|
||||
if (i == 0)
|
||||
i = (&*(t.first) < &*(t.third))? 0 : 2;
|
||||
else
|
||||
i = (&*(t.second) < &*(t.third))? 1 : 2;
|
||||
Vertex_handle tmp;
|
||||
switch (i) {
|
||||
case 0: return;
|
||||
case 1:
|
||||
tmp = t.first;
|
||||
t.first = t.second;
|
||||
t.second = t.third;
|
||||
t.third = tmp;
|
||||
return;
|
||||
default:
|
||||
tmp = t.first;
|
||||
t.first = t.third;
|
||||
t.third = t.second;
|
||||
t.second = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
// PREDICATES
|
||||
Orientation coplanar_orientation(const Point& p0, const Point& p1, const Point& p2, const Point& p) const {
|
||||
return Gt().coplanar_orientation_3_object()(p0, p1, p2, p);
|
||||
}
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
Delaunay_triangulation_utils_3(const Gt& gt = Gt()): DT(gt) {}
|
||||
|
||||
// Copy constructor duplicates vertices and cells.
|
||||
Delaunay_triangulation_utils_3(const Delaunay_triangulation_utils_3& tr): DT(tr) {
|
||||
CGAL_triangulation_postcondition(is_valid());
|
||||
}
|
||||
|
||||
// Create a 3D Delaunay triangulation from a number of points.
|
||||
template < typename InputIterator >
|
||||
Delaunay_triangulation_utils_3(InputIterator first, InputIterator last, const Gt& gt = Gt()): DT(gt) {
|
||||
insert(first, last);
|
||||
CGAL_triangulation_postcondition(is_valid());
|
||||
}
|
||||
|
||||
public:
|
||||
// INSERT POINT
|
||||
|
||||
Vertex_handle insert(const Point& p, Cell_handle start = Cell_handle());
|
||||
virtual Vertex_handle insert(const Point& p, Locate_type lt, Cell_handle c, int li, int lj);
|
||||
|
||||
template < class InputIterator >
|
||||
int insert(InputIterator first, InputIterator last) {
|
||||
int n = number_of_vertices();
|
||||
|
||||
std::vector<Point> points(first, last);
|
||||
std::random_shuffle(points.begin(), points.end());
|
||||
spatial_sort(points.begin(), points.end(), geom_traits());
|
||||
|
||||
Cell_handle hint;
|
||||
for (typename std::vector<Point>::const_iterator it = points.begin(), end = points.end(); it != end; ++it)
|
||||
hint = insert(*it, hint)->cell();
|
||||
|
||||
return number_of_vertices() - n;
|
||||
}
|
||||
|
||||
public:
|
||||
// MOVE
|
||||
|
||||
Vertex_handle move_point(Vertex_handle v, const Point& p);
|
||||
|
||||
public:
|
||||
// Construct the edge of c opposite to ij.
|
||||
Edge opposite_edge(Cell_handle c, int li, int lj) const {
|
||||
CGAL_triangulation_precondition(li >= 0 && li < 4);
|
||||
CGAL_triangulation_precondition(lj >= 0 && lj < 4);
|
||||
CGAL_triangulation_precondition(li != lj);
|
||||
|
||||
switch (6-li-lj) { // i + j + missing indices = 6.
|
||||
case 1: return Edge(c, 0, 1);
|
||||
case 2: return Edge(c, 0, 2);
|
||||
case 3: return (li == 0 || lj == 0)
|
||||
? Edge(c, 1, 2)
|
||||
: Edge(c, 0, 3);
|
||||
case 4: return Edge(c, 1, 3);
|
||||
case 5: return Edge(c, 2, 3);
|
||||
}
|
||||
|
||||
CGAL_triangulation_assertion(false);
|
||||
return Edge();
|
||||
}
|
||||
Edge opposite_edge(const Edge& e) const {return opposite_edge(e.first, e.second, e.third);}
|
||||
|
||||
// Give the same facet as seen from the other side.
|
||||
Facet mirror_facet(Cell_handle c, int li) const {return Facet(c->neighbor(li), c->neighbor(li)->index(c));}
|
||||
Facet mirror_facet(const Facet& f) const {return mirror_facet(f.first, f.second);}
|
||||
|
||||
// Construct a plane of a facet.
|
||||
Plane plane(Cell_handle c, int li) const {
|
||||
/* This should be removed to reduce orientation errors with the inexact kernel*/
|
||||
CGAL_triangulation_precondition(dimension() >= 2);
|
||||
CGAL_triangulation_precondition(dimension() == 3 || li == 3);
|
||||
CGAL_triangulation_precondition(li >= 0 && li <= 3);
|
||||
CGAL_triangulation_precondition(!is_infinite(c, li));
|
||||
if ((li&1) == 0)
|
||||
return Plane(c->vertex((li+2)&3)->point(),
|
||||
c->vertex((li+1)&3)->point(),
|
||||
c->vertex((li+3)&3)->point());
|
||||
return Plane(c->vertex((li+1)&3)->point(),
|
||||
c->vertex((li+2)&3)->point(),
|
||||
c->vertex((li+3)&3)->point());
|
||||
}
|
||||
Plane plane(const Facet& f) const {return plane(f.first, f.second);}
|
||||
|
||||
// Construct a line of an edge.
|
||||
Line line(Cell_handle c, int li, int lj) const {
|
||||
CGAL_triangulation_precondition(dimension() >= 1);
|
||||
CGAL_triangulation_precondition(li >= 0 && li <= 3);
|
||||
CGAL_triangulation_precondition(lj >= 0 && lj <= 3);
|
||||
CGAL_triangulation_precondition(li != lj);
|
||||
CGAL_triangulation_precondition(li + lj < dimension() * 2);
|
||||
CGAL_triangulation_precondition(!is_infinite(c, li, lj));
|
||||
return Line(c->vertex(li)->point(),
|
||||
c->vertex(lj)->point());
|
||||
}
|
||||
Line line(const Edge& e) const {return line(e.first, e.second, e.third);}
|
||||
}; // Delaunay_triangulation_utils_3
|
||||
|
||||
template < class Gt, class Tds >
|
||||
typename Delaunay_triangulation_utils_3<Gt,Tds>::Vertex_handle
|
||||
Delaunay_triangulation_utils_3<Gt,Tds>::
|
||||
insert(const Point& p, Cell_handle start) {
|
||||
Locate_type lt;
|
||||
int li, lj;
|
||||
Cell_handle c = locate(p, lt, li, lj, start);
|
||||
return insert(p, lt, c, li, lj);
|
||||
}
|
||||
|
||||
template < class Gt, class Tds >
|
||||
typename Delaunay_triangulation_utils_3<Gt,Tds>::Vertex_handle
|
||||
Delaunay_triangulation_utils_3<Gt,Tds>::
|
||||
insert(const Point& p, Locate_type lt, Cell_handle c, int li, int lj) {
|
||||
switch (dimension()) {
|
||||
case 3: {
|
||||
Conflict_tester_3 tester(p, this);
|
||||
Vertex_handle v = insert_in_conflict(p, lt, c, li, lj, tester, hidden_point_visitor);
|
||||
return v;
|
||||
}// dim 3
|
||||
case 2: {
|
||||
Conflict_tester_2 tester(p, this);
|
||||
return insert_in_conflict(p, lt, c, li, lj, tester, hidden_point_visitor);
|
||||
}//dim 2
|
||||
default :
|
||||
// dimension <= 1
|
||||
// Do not use the generic insert.
|
||||
return Tr::insert(p, c);
|
||||
}
|
||||
}
|
||||
|
||||
template < class Gt, class Tds >
|
||||
typename Delaunay_triangulation_utils_3<Gt,Tds>::Vertex_handle
|
||||
Delaunay_triangulation_utils_3<Gt,Tds>::move_point(Vertex_handle v, const Point& p) {
|
||||
CGAL_triangulation_precondition(!is_infinite(v));
|
||||
CGAL_triangulation_expensive_precondition(is_vertex(v));
|
||||
|
||||
// Remember an incident vertex to restart the point location after the removal.
|
||||
Cell_handle c = v->cell();
|
||||
Vertex_handle old_neighbor = c->vertex(c->index(v) == 0 ? 1 : 0);
|
||||
CGAL_triangulation_assertion(old_neighbor != v);
|
||||
|
||||
if (!remove(v))
|
||||
return v;
|
||||
|
||||
if (dimension() <= 0)
|
||||
return insert(p);
|
||||
return insert(p, old_neighbor->cell());
|
||||
}
|
||||
|
||||
} //end of CGAL namespace
|
||||
|
||||
#endif // CGAL_DELAUNAY_TRIANGULATION_3_UTILS_H
|
||||
|
|
@ -1,135 +0,0 @@
|
|||
//A traverser that collects points encroaching upon its path.
|
||||
//Copyright (C) 2012 Utrecht University
|
||||
//
|
||||
//This program is free software: you can redistribute it and/or modify
|
||||
//it under the terms of the GNU General Public License as published by
|
||||
//the Free Software Foundation, either version 3 of the License, or
|
||||
//(at your option) any later version.
|
||||
//
|
||||
//This program is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
//GNU General Public License for more details.
|
||||
//
|
||||
//You should have received a copy of the GNU General Public License
|
||||
//along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// Author(s): Thijs van Lankveld
|
||||
|
||||
// A class that traverses the cells of a triangulation by following a segment from source to target,
|
||||
// while collecting points that encroach upon the segment.
|
||||
|
||||
#ifndef CGAL_ENCROACHING_COLLECTER_3_H
|
||||
#define CGAL_ENCROACHING_COLLECTER_3_H
|
||||
|
||||
#include "Triangulation_segment_traverser_3.h"
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
#ifndef CGAL_CONSTRAINED_TRIANGULATION_2_H
|
||||
/// \todo factorize with CDT2
|
||||
struct No_intersection_tag{};
|
||||
struct Exact_intersections_tag{}; // To be used with an exact number type.
|
||||
struct Exact_predicates_tag{}; // To be used with filtered exact number type.
|
||||
#endif
|
||||
|
||||
template < class Gt, class Tds, class Itag >
|
||||
class Conforming_Delaunay_triangulation_3;
|
||||
|
||||
template < class Gt, class Tds, class Itag = No_intersection_tag, class Out = std::back_insert_iterator<std::list<Point_3<Gt> > > >
|
||||
class Encroaching_collecter_3: public Triangulation_segment_traverser_3<Gt,Tds> {
|
||||
typedef Encroaching_collecter_3<Gt,Tds,Itag,Out> Self;
|
||||
typedef Triangulation_segment_traverser_3<Gt,Tds> Base;
|
||||
|
||||
typedef typename Gt::Plane_3 Plane;
|
||||
|
||||
public:
|
||||
typedef Conforming_Delaunay_triangulation_3<Gt,Tds,Itag> CDT;
|
||||
|
||||
typedef typename Tds::Vertex Vertex;
|
||||
typedef typename Tds::Cell Cell;
|
||||
typedef typename Tds::Edge Edge;
|
||||
typedef typename Tds::Facet Facet;
|
||||
typedef typename Tds::Vertex_handle Vertex_handle;
|
||||
typedef typename Tds::Cell_handle Cell_handle;
|
||||
typedef typename Tds::Cell_iterator Cell_iterator;
|
||||
typedef typename Tds::Cell_circulator Cell_circulator;
|
||||
typedef typename Tds::Facet_iterator Facet_iterator;
|
||||
typedef typename Tds::Facet_circulator Facet_circulator;
|
||||
|
||||
typedef typename Gt::Point_3 Point;
|
||||
typedef typename CDT::Locate_type Locate_type;
|
||||
typedef typename CDT::Bi_vertex Bi_vertex;
|
||||
using Base::_lt;
|
||||
using Base::_tr;
|
||||
using Base::_pos;
|
||||
using Base::_li;
|
||||
using Base::_lj;
|
||||
using Base::_source;
|
||||
using Base::_target;
|
||||
protected:
|
||||
Out _out;
|
||||
|
||||
Bi_vertex se; // These are used when the source lies on an edge.
|
||||
|
||||
public:
|
||||
Encroaching_collecter_3(): Base() {}
|
||||
Encroaching_collecter_3(Vertex_handle v, const Point& t, const CDT* tr, Out output)
|
||||
: Base(v, t, tr), _out(output) {if (_lt == CDT::EDGE) se = _tr->sort_bi_vertex(_pos, _li, _lj);}
|
||||
Encroaching_collecter_3(const Point& s, const Point& t, const CDT* tr, Out output, Cell_handle hint = Cell_handle())
|
||||
: Base(s, t, tr, hint), _out(output) {if (_lt == CDT::EDGE) se = _tr->sort_bi_vertex(_pos, _li, _lj);}
|
||||
|
||||
virtual bool barrier_hit() const {return _lt == CDT::EDGE && _pos->is_conforming(_li, _lj) && _tr->sort_bi_vertex(_pos, _li, _lj) != se;}
|
||||
|
||||
protected:
|
||||
// Traverse to the next cell along the line.
|
||||
virtual void increment();
|
||||
};
|
||||
|
||||
template < class Gt, class Tds, class Itag, class Out >
|
||||
void Encroaching_collecter_3<Gt,Tds,Itag,Out>::increment() {
|
||||
// Walk to the next cell.
|
||||
Base::increment();
|
||||
|
||||
// Check for encroaching points.
|
||||
// Which points are checked is based on the type of simplex traversed.
|
||||
const CDT* _cdt = dynamic_cast<const CDT*>(_tr);
|
||||
switch (_lt) {
|
||||
case CDT::FACET:
|
||||
for (int i = 0; i < 4; ++i)
|
||||
if (i != _li && !_cdt->is_infinite(_pos->vertex(i)) && _cdt->is_encroaching(_source, _target, _pos->vertex(i)->point()))
|
||||
*_out++ = _pos->vertex(i)->point();
|
||||
break;
|
||||
case CDT::EDGE: {
|
||||
Vertex_handle vi = _pos->vertex(_li), vj = _pos->vertex(_lj), vk;
|
||||
Cell_handle c;
|
||||
|
||||
// Check the vertices in the star around the edge.
|
||||
Facet_circulator fit = _cdt->incident_facets(_pos, _li, _lj), start(fit);
|
||||
do {
|
||||
c = fit->first;
|
||||
vk = c->vertex(6 - c->index(vi) - c->index(vj) - fit->second);
|
||||
if (!_cdt->is_infinite(vk) && !collinear(_source, _target, vk->point()) && _cdt->is_encroaching(_source, _target, vk->point()))
|
||||
*_out++ = vk->point();
|
||||
++fit;
|
||||
} while (fit != start);
|
||||
|
||||
// Check the vertices of the edge.
|
||||
if (_cdt->is_encroaching(_source, _target, vi->point()))
|
||||
*_out++ = vi->point();
|
||||
if (_cdt->is_encroaching(_source, _target, vj->point()))
|
||||
*_out++ = vj->point();
|
||||
break;
|
||||
}
|
||||
case CDT::VERTEX:
|
||||
CGAL_triangulation_assertion(collinear(_source, _target, _pos->vertex(_li)->point()));
|
||||
break;
|
||||
default:
|
||||
CGAL_triangulation_assertion(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} //end of CGAL namespace
|
||||
|
||||
#endif // CGAL_ENCROACHING_COLLECTER_3_H
|
||||
|
|
@ -1,695 +0,0 @@
|
|||
//A class that follows a straight line through a Delaunay triangulation structure.
|
||||
//Copyright (C) 2012 Utrecht University
|
||||
//
|
||||
//This program is free software: you can redistribute it and/or modify
|
||||
//it under the terms of the GNU General Public License as published by
|
||||
//the Free Software Foundation, either version 3 of the License, or
|
||||
//(at your option) any later version.
|
||||
//
|
||||
//This program is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
//GNU General Public License for more details.
|
||||
//
|
||||
//You should have received a copy of the GNU General Public License
|
||||
//along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// Author(s): Thijs van Lankveld
|
||||
|
||||
// A class that traverses the cells of a triangulation by following a segment from source to target.
|
||||
|
||||
#ifndef CGAL_TRIANGULATION_SEGMENT_TRAVERSER_3_H
|
||||
#define CGAL_TRIANGULATION_SEGMENT_TRAVERSER_3_H
|
||||
|
||||
#include "Delaunay_triangulation_utils_3.h"
|
||||
|
||||
#include <CGAL/Random.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template < class Gt, class Tds>
|
||||
class Delaunay_triangulation_utils_3;
|
||||
|
||||
template < class Gt, class Tds >
|
||||
class Triangulation_segment_traverser_3: public Forward_circulator_base< typename Tds::Cell, std::ptrdiff_t, std::size_t > {
|
||||
typedef Triangulation_segment_traverser_3<Gt,Tds> Self;
|
||||
|
||||
public:
|
||||
typedef Delaunay_triangulation_utils_3<Gt,Tds> Tr;
|
||||
|
||||
typedef typename Tds::Vertex Vertex;
|
||||
typedef typename Tds::Cell Cell;
|
||||
typedef typename Tds::Edge Edge;
|
||||
typedef typename Tds::Facet Facet;
|
||||
typedef typename Tds::Vertex_handle Vertex_handle;
|
||||
typedef typename Tds::Cell_handle Cell_handle;
|
||||
typedef typename Tds::Cell_iterator Cell_iterator;
|
||||
typedef typename Tds::Cell_circulator Cell_circulator;
|
||||
typedef typename Tds::Facet_iterator Facet_iterator;
|
||||
typedef typename Tds::Facet_circulator Facet_circulator;
|
||||
|
||||
typedef typename Gt::Point_3 Point;
|
||||
typedef typename Tr::Locate_type Locate_type;
|
||||
|
||||
protected:
|
||||
// The triangulation being traversed.
|
||||
const Tr* _tr;
|
||||
|
||||
// The source and target points of the traversal.
|
||||
Point _source, _target;
|
||||
|
||||
// The cell currently traversed and the previous one.
|
||||
Cell_handle _pos, _prev;
|
||||
|
||||
// Otherwise, they indicate the simplex through which this cell was entered,
|
||||
// or the location of the source if it is in this cell.
|
||||
int _li, _lj;
|
||||
Locate_type _lt;
|
||||
|
||||
// This bit signifies when a cell containing the target is found.
|
||||
bool _done;
|
||||
|
||||
// Where possible, facets are checked in a random order.
|
||||
mutable Random rng;
|
||||
|
||||
public:
|
||||
Triangulation_segment_traverser_3(): _tr(NULL), _pos(), _prev(), _li(-1), _lj(-1), _lt(Tr::CELL), _done(true) {}
|
||||
Triangulation_segment_traverser_3(Vertex_handle s, const Point& t, const Tr* tr);
|
||||
Triangulation_segment_traverser_3(const Point& s, const Point& t, const Tr* tr, Cell_handle hint = Cell_handle());
|
||||
|
||||
Self& operator++();
|
||||
Self operator++(int);
|
||||
Cell* operator->() {return &*_pos;}
|
||||
Cell& operator*() {return *_pos;}
|
||||
Cell_handle handle() {return _pos;}
|
||||
operator const Cell_handle() const {return _pos;}
|
||||
bool operator==(const Self& ct) const;
|
||||
bool operator!=(const Self& ct) const;
|
||||
|
||||
bool operator==(const Cell_handle& ch) const {return ch == _pos;}
|
||||
bool operator!=(const Cell_handle& ch) const {return ch != _pos;}
|
||||
|
||||
bool operator==(Nullptr_t CGAL_triangulation_assertion_code(n)) const;
|
||||
bool operator!=(Nullptr_t n) const;
|
||||
|
||||
// Check if a cell containing the target has been reached.
|
||||
bool has_next() const {return !_done;}
|
||||
|
||||
// Access the current and previous cells.
|
||||
Cell_handle previous() const {return _prev;}
|
||||
|
||||
// Traverse to a cell containing the target.
|
||||
Cell_handle traverse();
|
||||
|
||||
// Get the type of simplex traversed last.
|
||||
void traversed(Locate_type& lt, int& li, int& lj) const {lt = _lt; li = _li; lj = _lj;}
|
||||
|
||||
protected:
|
||||
// Traverse to the next cell along the line.
|
||||
virtual void increment();
|
||||
|
||||
private:
|
||||
inline int edgeIndex(int i, int j) const {
|
||||
CGAL_triangulation_precondition(i>=0 && i<=3);
|
||||
CGAL_triangulation_precondition(j>=0 && j<=3);
|
||||
CGAL_triangulation_precondition(i != j);
|
||||
return (i==0 || j==0) ? i+j-1 : i+j;
|
||||
}
|
||||
|
||||
inline Orientation coplanar_orientation(const Point& p, const Point& q, const Point& r, const Point& s) {
|
||||
return Gt().coplanar_orientation_3_object()(p, q, r, s);
|
||||
}
|
||||
}; // class Triangulation_segment_traverser_3
|
||||
|
||||
template < class Gt, class Tds >
|
||||
inline bool operator==(typename Tds::Cell_handle ch, Triangulation_segment_traverser_3<Gt, Tds> tci) {return tci == ch;}
|
||||
|
||||
template < class Gt, class Tds >
|
||||
inline bool operator!=(typename Tds::Cell_handle ch, Triangulation_segment_traverser_3<Gt, Tds> tci) {return tci != ch;}
|
||||
|
||||
template < class Gt, class Tds >
|
||||
Triangulation_segment_traverser_3<Gt,Tds>::Triangulation_segment_traverser_3(Vertex_handle s, const Point& t, const Tr* tr)
|
||||
: _tr(tr), _pos(), _prev(), _lj(-1), _lt(Tr::VERTEX), _done(false) {
|
||||
CGAL_triangulation_precondition(!_tr->is_infinite(s));
|
||||
CGAL_triangulation_precondition(s->point() != t);
|
||||
CGAL_triangulation_precondition(_tr->dimension() >= 2);
|
||||
CGAL_triangulation_assertion(_tr->dimension() == 3 || _tr->plane(*_tr->finite_facets_begin()).has_on(_target));
|
||||
|
||||
_source = s->point();
|
||||
_target = t;
|
||||
|
||||
_pos = s->cell();
|
||||
int inf;
|
||||
if (_pos->has_vertex(_tr->infinite_vertex(), inf))
|
||||
_pos = _pos->neighbor(inf);
|
||||
_li = _pos->index(s);
|
||||
|
||||
CGAL_triangulation_postcondition(_pos != Cell_handle());
|
||||
}
|
||||
|
||||
template < class Gt, class Tds >
|
||||
Triangulation_segment_traverser_3<Gt,Tds>::Triangulation_segment_traverser_3(const Point& s, const Point& t, const Tr* tr, Cell_handle hint)
|
||||
: _tr(tr), _pos(), _prev(), _li(-1), _lj(-1), _done(false) {
|
||||
CGAL_triangulation_precondition(s != t);
|
||||
CGAL_triangulation_precondition(_tr->dimension() >= 2);
|
||||
CGAL_triangulation_assertion(_tr->dimension() == 3 || _tr->plane(*_tr->finite_facets_begin()).has_on(_target));
|
||||
|
||||
_source = s;
|
||||
_target = t;
|
||||
|
||||
_pos = _tr->locate(s, _lt, _li, _lj, hint);
|
||||
|
||||
CGAL_triangulation_postcondition(_pos != Cell_handle());
|
||||
}
|
||||
|
||||
template < class Gt, class Tds >
|
||||
inline Triangulation_segment_traverser_3<Gt,Tds>&
|
||||
Triangulation_segment_traverser_3<Gt,Tds>::operator++() {
|
||||
CGAL_triangulation_precondition(_pos != Cell_handle());
|
||||
increment();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template < class Gt, class Tds >
|
||||
inline Triangulation_segment_traverser_3<Gt,Tds>
|
||||
Triangulation_segment_traverser_3<Gt,Tds>::operator++(int) {
|
||||
Self tmp(*this);
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template < class Gt, class Tds >
|
||||
inline bool Triangulation_segment_traverser_3<Gt,Tds>::operator==(const Self& ct) const {
|
||||
CGAL_triangulation_precondition(_pos != Cell_handle() && ct._pos != Cell_handle());
|
||||
return (_pos == ct._pos &&
|
||||
_prev == ct._prev &&
|
||||
_tr == ct._tr &&
|
||||
_li == ct._li &&
|
||||
_lj == ct._lj &&
|
||||
_lt == ct._lt &&
|
||||
_source == ct._source &&
|
||||
_target == ct._target &&
|
||||
_done == ct._done);
|
||||
}
|
||||
|
||||
template < class Gt, class Tds >
|
||||
inline bool Triangulation_segment_traverser_3<Gt,Tds>::operator!=(const Self& ct) const {
|
||||
return !(*this == ct);
|
||||
}
|
||||
|
||||
template < class Gt, class Tds >
|
||||
inline bool Triangulation_segment_traverser_3<Gt,Tds>::operator==(Nullptr_t CGAL_triangulation_assertion_code(n)) const {
|
||||
CGAL_triangulation_assertion(n == NULL);
|
||||
return _pos == Cell_handle();
|
||||
}
|
||||
|
||||
template < class Gt, class Tds >
|
||||
inline bool Triangulation_segment_traverser_3<Gt,Tds>::operator!=(Nullptr_t n) const {
|
||||
CGAL_triangulation_assertion(n == NULL);
|
||||
return !(*this == n);
|
||||
}
|
||||
|
||||
template < class Gt, class Tds >
|
||||
inline typename Triangulation_segment_traverser_3<Gt,Tds>::Cell_handle
|
||||
Triangulation_segment_traverser_3<Gt,Tds>::traverse() {
|
||||
while (!_done)
|
||||
increment();
|
||||
return _pos;
|
||||
}
|
||||
|
||||
template < class Gt, class Tds >
|
||||
void Triangulation_segment_traverser_3<Gt,Tds>::increment() {
|
||||
CGAL_triangulation_precondition(!_done);
|
||||
|
||||
// Walks to the next cell over a facet intersected by the line from source to target.
|
||||
// This method is based on Triangulation_3::locate().
|
||||
switch (_tr->dimension()) {
|
||||
case 3: {
|
||||
// Infinite cells should be handled differently.
|
||||
int inf;
|
||||
if (_pos->has_vertex(_tr->infinite_vertex(), inf)) {
|
||||
// If this cell was reached by traversal from a finite one, it must be the final cell.
|
||||
Cell_handle fin = _pos->neighbor(inf);
|
||||
if (fin == _prev) {
|
||||
_done = true;
|
||||
// Here, I do not change the _lt etc. because they were already set.
|
||||
return;
|
||||
}
|
||||
|
||||
const Point* pts[4];
|
||||
for (int i = 0; i != 4; ++i)
|
||||
if (i != inf)
|
||||
pts[i] = &(_pos->vertex(i)->point());
|
||||
pts[inf] = &_target;
|
||||
Orientation o[4];
|
||||
|
||||
// For the remembering stochastic walk, we start trying with a random index:
|
||||
int li = rng.template get_bits<2>();
|
||||
|
||||
// Check if the target lies outside the convex hull.
|
||||
if (orientation(*pts[0], *pts[1], *pts[2], *pts[3]) == POSITIVE) {
|
||||
// The target lies in an infinite cell.
|
||||
_done = true;
|
||||
return;
|
||||
|
||||
// Note that we do not traverse to other infinite cells.
|
||||
}
|
||||
|
||||
pts[inf] = &_source;
|
||||
CGAL_triangulation_assertion(orientation(*pts[0], *pts[1], *pts[2], *pts[3]) == POSITIVE);
|
||||
|
||||
// Check if the line enters an adjacent infinite cell.
|
||||
// This occurs if the target lies on the other side of
|
||||
// a plane through one of the finite edges and the source point.
|
||||
for (int j = 0; j != 4; ++j, li = (li+1)&3) {
|
||||
if (li == inf) {
|
||||
o[li] = COPLANAR;
|
||||
continue;
|
||||
}
|
||||
|
||||
Cell_handle next = _pos->neighbor(li);
|
||||
if (next == _prev) {
|
||||
o[li] = POSITIVE;
|
||||
continue;
|
||||
}
|
||||
|
||||
const Point* backup = pts[li];
|
||||
pts[li] = &_target;
|
||||
o[li] = orientation(*pts[0], *pts[1], *pts[2], *pts[3]);
|
||||
|
||||
if (o[li] != NEGATIVE) {
|
||||
pts[li] = backup;
|
||||
continue;
|
||||
}
|
||||
|
||||
// The target lies behind the plane through the source and two finite vertices.
|
||||
// Traverse to the incident infinite cell.
|
||||
_prev = _pos;
|
||||
_pos = next;
|
||||
CGAL_triangulation_assertion(_tr->is_infinite(_pos));
|
||||
|
||||
_lt = Tr::FACET;
|
||||
_li = _pos->index(_prev);
|
||||
return;
|
||||
}
|
||||
|
||||
// The line enters the convex hull here (or lies on the finite facet).
|
||||
_prev = _pos;
|
||||
_pos = fin;
|
||||
|
||||
// Check through which simplex the line traverses.
|
||||
switch (o[0]+o[1]+o[2]+o[3]) {
|
||||
case 3:
|
||||
_lt = Tr::FACET;
|
||||
_li = _pos->index(_prev);
|
||||
return;
|
||||
case 2:
|
||||
_lt = Tr::EDGE;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (o[i] == COPLANAR && i != inf) {
|
||||
Edge opp = _tr->opposite_edge(_prev, inf, i);
|
||||
_li = _pos->index(_prev->vertex(opp.second));
|
||||
_lj = _pos->index(_prev->vertex(opp.third));
|
||||
return;
|
||||
}
|
||||
}
|
||||
CGAL_triangulation_assertion(false);
|
||||
return;
|
||||
case 1:
|
||||
_lt = Tr::VERTEX;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (o[i] == POSITIVE) {
|
||||
_li = _pos->index(_prev->vertex(i));
|
||||
return;
|
||||
}
|
||||
}
|
||||
CGAL_triangulation_assertion(false);
|
||||
return;
|
||||
default:
|
||||
CGAL_triangulation_assertion(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const Point* pts[4] = {&(_pos->vertex(0)->point()),
|
||||
&(_pos->vertex(1)->point()),
|
||||
&(_pos->vertex(2)->point()),
|
||||
&(_pos->vertex(3)->point())};
|
||||
|
||||
// We check in which direction the target lies
|
||||
// by comparing its position relative to the planes through the
|
||||
// source and the edges of the cell.
|
||||
Orientation o[6];
|
||||
bool calc[6] = {false, false, false, false, false, false};
|
||||
|
||||
if (_lt == Tr::VERTEX) {
|
||||
// The three planes through the vertex are set to coplanar.
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
if (_li != j) {
|
||||
int ij = edgeIndex(_li, j);
|
||||
o[ij] = COPLANAR;
|
||||
calc[ij] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (_lt == Tr::EDGE) {
|
||||
// The plane through the edge is set to coplanar.
|
||||
int ij = edgeIndex(_li, _lj);
|
||||
o[ij] = COPLANAR;
|
||||
calc[ij] = true;
|
||||
}
|
||||
|
||||
// For the remembering stochastic walk, we start trying with a random facet:
|
||||
int li = rng.template get_bits<2>();
|
||||
|
||||
CGAL_triangulation_assertion_code(bool incell = true;)
|
||||
for (int k = 0; k < 4; ++k, li = (li+1)&3) {
|
||||
Cell_handle next = _pos->neighbor(li);
|
||||
if (next == _prev)
|
||||
continue;
|
||||
|
||||
// Check if the target is outside the cell.
|
||||
const Point* backup = pts[li];
|
||||
pts[li] = &_target;
|
||||
if (orientation(*pts[0], *pts[1], *pts[2], *pts[3]) != NEGATIVE) {
|
||||
pts[li] = backup;
|
||||
continue;
|
||||
}
|
||||
|
||||
CGAL_triangulation_assertion_code(incell = false;)
|
||||
|
||||
// Check if the target is inside the pyramid.
|
||||
int lj = rng.template get_bits<2>();
|
||||
int Or = 0;
|
||||
for (int l = 0; l < 4; ++l, lj = (lj+1)&3) {
|
||||
if (li == lj)
|
||||
continue;
|
||||
|
||||
// We check the orientation of the target compared to the plane
|
||||
// Through the source and the edge opposite of ij.
|
||||
int oij = 5 - edgeIndex(li, lj);
|
||||
if (!calc[oij]) {
|
||||
const Point* backup2 = pts[lj];
|
||||
pts[lj] = &_source;
|
||||
o[oij] = orientation(*pts[0], *pts[1], *pts[2], *pts[3]);
|
||||
pts[lj] = backup2;
|
||||
calc[oij] = true;
|
||||
}
|
||||
|
||||
Or -= o[oij];
|
||||
if (o[oij] == POSITIVE) {
|
||||
// The target is not inside the pyramid.
|
||||
// Invert the planes.
|
||||
// This can be safely done because either
|
||||
// they were not calculated yet,
|
||||
// or they will no longer be used.
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
if (li == j) continue;
|
||||
int oij = 5 - edgeIndex(li, j);
|
||||
o[oij] = -o[oij];
|
||||
}
|
||||
Or = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Or == 0) {
|
||||
// Either the target is not inside the pyramid,
|
||||
// or the pyramid is degenerate.
|
||||
pts[li] = backup;
|
||||
continue;
|
||||
}
|
||||
|
||||
// The target is inside the pyramid.
|
||||
_prev = _pos;
|
||||
_pos = next;
|
||||
|
||||
switch (Or) {
|
||||
case 3:
|
||||
_lt = Tr::FACET;
|
||||
_li = _pos->index(_prev);
|
||||
return;
|
||||
case 2:
|
||||
_lt = Tr::EDGE;
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
if (li != j && o[5-edgeIndex(li, j)] == COPLANAR) {
|
||||
Edge opp = _tr->opposite_edge(_prev, li, j);
|
||||
_li = _pos->index(_prev->vertex(opp.second));
|
||||
_lj = _pos->index(_prev->vertex(opp.third));
|
||||
return;
|
||||
}
|
||||
}
|
||||
CGAL_triangulation_assertion(false);
|
||||
return;
|
||||
case 1:
|
||||
_lt = Tr::VERTEX;
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
if (li != j && o[5-edgeIndex(li, j)] == NEGATIVE) {
|
||||
_li = _pos->index(_prev->vertex(j));
|
||||
return;
|
||||
}
|
||||
}
|
||||
CGAL_triangulation_assertion(false);
|
||||
return;
|
||||
default:
|
||||
CGAL_triangulation_assertion(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// The target lies inside this cell.
|
||||
CGAL_triangulation_assertion(incell);
|
||||
_done = true;
|
||||
return;
|
||||
}
|
||||
case 2: {
|
||||
int inf;
|
||||
if (_pos->has_vertex(_tr->infinite_vertex(), inf) && inf < 3) {
|
||||
// If this cell was reached by traversal from a finite one, it must be the final cell.
|
||||
Cell_handle fin = _pos->neighbor(inf);
|
||||
if (fin == _prev) {
|
||||
_done = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the neighboring cells.
|
||||
if (coplanar_orientation(_source, _pos->vertex(_tr->ccw(inf))->point(), _pos->vertex(_tr->cw(inf))->point(), _target) == NEGATIVE) {
|
||||
Cell_handle tmp = _pos->neighbor(_tr->cw(inf));
|
||||
_prev = _pos;
|
||||
_pos = tmp;
|
||||
return;
|
||||
}
|
||||
if (coplanar_orientation(_source, _pos->vertex(_tr->cw(inf))->point(), _pos->vertex(_tr->ccw(inf))->point(), _target) == NEGATIVE) {
|
||||
Cell_handle tmp = _pos->neighbor(_tr->ccw(inf));
|
||||
_prev = _pos;
|
||||
_pos = tmp;
|
||||
return;
|
||||
}
|
||||
if (coplanar_orientation(_pos->vertex(_tr->ccw(inf))->point(), _pos->vertex(_tr->cw(inf))->point(), _source, _target) != POSITIVE) {
|
||||
_prev = _pos;
|
||||
_pos = fin;
|
||||
return;
|
||||
}
|
||||
|
||||
// The target lies in this infinite cell.
|
||||
_done = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const Point* pts[3] = {&(_pos->vertex(0)->point()),
|
||||
&(_pos->vertex(1)->point()),
|
||||
&(_pos->vertex(2)->point())};
|
||||
|
||||
switch (_lt) {
|
||||
case Tr::VERTEX: {
|
||||
// First we try the incident edges.
|
||||
Orientation ocw = coplanar_orientation(*pts[_li], *pts[(_li+2)%3], *pts[(_li+1)%3], _target);
|
||||
if (_pos->neighbor((_li+1)%3) != _prev &&
|
||||
ocw == NEGATIVE) {
|
||||
Cell_handle tmp = _pos->neighbor((_li+1)%3);
|
||||
_prev = _pos;
|
||||
_pos = tmp;
|
||||
_li = _pos->index(_prev->vertex(_li));
|
||||
return;
|
||||
}
|
||||
Orientation occw = coplanar_orientation(*pts[_li], *pts[(_li+1)%3], *pts[(_li+2)%3], _target);
|
||||
if (_pos->neighbor((_li+2)%3) != _prev &&
|
||||
occw == NEGATIVE) {
|
||||
Cell_handle tmp = _pos->neighbor((_li+2)%3);
|
||||
_prev = _pos;
|
||||
_pos = tmp;
|
||||
_li = _pos->index(_prev->vertex(_li));
|
||||
return;
|
||||
}
|
||||
|
||||
// Then we try the opposite edge.
|
||||
if (coplanar_orientation(*pts[(_li+1)%3], *pts[(_li+2)%3], *pts[_li], _target) == NEGATIVE) {
|
||||
Cell_handle tmp = _pos->neighbor(_li);
|
||||
_prev = _pos;
|
||||
_pos = tmp;
|
||||
|
||||
switch (ocw+occw) {
|
||||
case 2: {
|
||||
_lt = Tr::EDGE;
|
||||
_li = _pos->index(_prev->vertex((_li+1)%3));
|
||||
_lj = _pos->index(_prev->vertex((_li+2)%3));
|
||||
return;
|
||||
}
|
||||
case 1: {
|
||||
_lt = Tr::VERTEX;
|
||||
if (ocw == COLLINEAR) _li = _pos->index(_prev->vertex((_li+2)%3));
|
||||
else _li = _pos->index(_prev->vertex((_li+1)%3));
|
||||
return;
|
||||
}
|
||||
default:
|
||||
CGAL_triangulation_assertion(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// The target lies in this cell.
|
||||
_done = true;
|
||||
return;
|
||||
}
|
||||
case Tr::EDGE: {
|
||||
int lk = 3-_li-_lj;
|
||||
|
||||
if (_pos->neighbor(lk) != _prev) {
|
||||
// Check the edge itself
|
||||
switch (coplanar_orientation(*pts[_li], *pts[_lj], *pts[lk], _target)) {
|
||||
case COLLINEAR: {
|
||||
// The target lies in this cell.
|
||||
_done = true;
|
||||
return;
|
||||
}
|
||||
case NEGATIVE: {
|
||||
// The target lies opposite of the edge.
|
||||
Cell_handle tmp = _pos->neighbor(lk);
|
||||
_prev = _pos;
|
||||
_pos = tmp;
|
||||
_li = _pos->index(_prev->vertex(_li));
|
||||
_lj = _pos->index(_prev->vertex(_lj));
|
||||
return;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Orientation o = coplanar_orientation(_source, *pts[lk], *pts[_li], _target);
|
||||
switch (o) {
|
||||
case POSITIVE: {
|
||||
// The ray passes through the edge ik.
|
||||
if (coplanar_orientation(*pts[lk], *pts[_li], _source, _target) == NEGATIVE) {
|
||||
Cell_handle tmp = _pos->neighbor(_lj);
|
||||
_prev = _pos;
|
||||
_pos = tmp;
|
||||
|
||||
if (collinear(_source, *pts[_li], _target)) {
|
||||
_lt = Tr::VERTEX;
|
||||
_li = _pos->index(_prev->vertex(_li));
|
||||
}
|
||||
else {
|
||||
_lt = Tr::EDGE;
|
||||
_li = _pos->index(_prev->vertex(_li));
|
||||
_lj = _pos->index(_prev->vertex(lk));
|
||||
}
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// The ray passes through the edge jk.
|
||||
if (coplanar_orientation(*pts[lk], *pts[_lj], _source, _target) == NEGATIVE) {
|
||||
Cell_handle tmp = _pos->neighbor(_li);
|
||||
_prev = _pos;
|
||||
_pos = tmp;
|
||||
|
||||
if (collinear(_source, *pts[_lj], _target)) {
|
||||
_lt = Tr::VERTEX;
|
||||
_li = _pos->index(_prev->vertex(_lj));
|
||||
}
|
||||
else if (o == COLLINEAR) {
|
||||
_lt = Tr::VERTEX;
|
||||
_li = _pos->index(_prev->vertex(lk));
|
||||
}
|
||||
else {
|
||||
_lt = Tr::EDGE;
|
||||
_li = _pos->index(_prev->vertex(lk));
|
||||
_lj = _pos->index(_prev->vertex(_lj));
|
||||
}
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// The target lies in this cell.
|
||||
_done = true;
|
||||
return;
|
||||
}
|
||||
case Tr::FACET: {
|
||||
// We test its edges in a random order until we find a neighbor to go further
|
||||
int li = rng.get_int(0, 3);
|
||||
|
||||
Orientation o[3];
|
||||
bool calc[3] = {false, false, false};
|
||||
|
||||
for (int j = 0; j != 3; ++j, li = (li+1)%3) {
|
||||
Cell_handle next = _pos->neighbor(li);
|
||||
if (next == _prev)
|
||||
continue;
|
||||
|
||||
// The target should lie on the other side of the edge.
|
||||
if (coplanar_orientation(*pts[(li+1)%3], *pts[(li+2)%3], *pts[li], _target) != NEGATIVE)
|
||||
continue;
|
||||
|
||||
// The target should lie inside the wedge.
|
||||
if (!calc[(li+1)%3]) {
|
||||
o[(li+1)%3] = coplanar_orientation(_source, *pts[(li+1)%3], *pts[(li+2)%3], _target);
|
||||
calc[(li+1)%3] = true;
|
||||
}
|
||||
if (o[(li+1)%3] == NEGATIVE) continue;
|
||||
|
||||
if (!calc[(li+2)%3]) {
|
||||
o[(li+2)%3] = coplanar_orientation(_source, *pts[(li+2)%3], *pts[(li+1)%3], _target);
|
||||
calc[(li+2)%3] = true;
|
||||
}
|
||||
if (o[(li+2)%3] == POSITIVE) continue;
|
||||
|
||||
_prev = _pos;
|
||||
_pos = next;
|
||||
|
||||
switch (o[(li+1)%3]+o[(li+2)%3]) {
|
||||
case 2: {
|
||||
_lt = Tr::EDGE;
|
||||
_li = _pos->index(_prev->vertex((li+1)%3));
|
||||
_lj = _pos->index(_prev->vertex((li+2)%3));
|
||||
return;
|
||||
}
|
||||
case 1: {
|
||||
_lt = Tr::VERTEX;
|
||||
if (o[(li+1)%3] == COLLINEAR) _li = _pos->index(_prev->vertex((li+1)%3));
|
||||
else _li = _pos->index(_prev->vertex((li+2)%3));
|
||||
return;
|
||||
}
|
||||
default:
|
||||
CGAL_triangulation_assertion(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// The target lies in this cell.
|
||||
_done = true;
|
||||
return;
|
||||
}
|
||||
default:
|
||||
CGAL_triangulation_assertion(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} //end of CGAL namespace
|
||||
|
||||
#endif // CGAL_TRIANGULATION_SEGMENT_TRAVERSER_3_H
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
Utrecht University (The Netherlands) & INRIA Sophia-Antipolis (France)
|
||||
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
Package Conforming_triangulation_3 :
|
||||
conforming triangulation data structure
|
||||
this can be wrapped around any CGAL::Triangulation_3, usually CGAL::Delaunay_triangulation_3
|
||||
|
|
@ -1 +0,0 @@
|
|||
GPL (v3 or later)
|
||||
|
|
@ -1 +0,0 @@
|
|||
Thijs van Lankveld <thijs.van-lankveld@sophia.inria.fr>
|
||||
|
|
@ -7,6 +7,7 @@
|
|||
\example Triangulation_3/info_insert_with_transform_iterator.cpp
|
||||
\example Triangulation_3/simplex.cpp
|
||||
\example Triangulation_3/fast_location_3.cpp
|
||||
\example Triangulation_3/segment_traverser_3.cpp
|
||||
\example Triangulation_3/find_conflicts_3.cpp
|
||||
\example Triangulation_3/regular_3.cpp
|
||||
\example Triangulation_3/copy_triangulation_3.cpp
|
||||
|
|
|
|||
|
|
@ -22,6 +22,11 @@ in a triangulation, when he needs to add handles in it.
|
|||
This example shows the use of the Fast_location policy to speed up
|
||||
point location queries in a Delaunay triangulation.
|
||||
|
||||
------- segment_traverser_3 --------------------------------------------
|
||||
|
||||
This example shows how to use a Triangulation_segment_traverser_3
|
||||
to traverse the triangulation in a straight line.
|
||||
|
||||
------- tds --------------------------------------------------
|
||||
|
||||
Shows how to construct a 3D triangulation data structure by
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Delaunay_triangulation_3.h>
|
||||
#include <CGAL/Triangulation_segment_traverser_3.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
|
||||
// Define the kernel.
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
typedef Kernel::Point_3 Point_3;
|
||||
|
||||
// Define the structure.
|
||||
typedef CGAL::Delaunay_triangulation_3< Kernel > DT;
|
||||
|
||||
typedef DT::Cell_handle Cell_handle;
|
||||
|
||||
typedef CGAL::Triangulation_segment_traverser_3< DT > Traverser;
|
||||
|
||||
void main() {
|
||||
std::vector< Point_3 > points;
|
||||
points.reserve( 6 );
|
||||
points.push_back( Point_3(-.9063, .4226, 1.0 ) );
|
||||
points.push_back( Point_3( .8192, .5736, 1.0 ) );
|
||||
points.push_back( Point_3( .0872,-.9992, 1.0 ) );
|
||||
points.push_back( Point_3(-.8192, .5736,-1.0 ) );
|
||||
points.push_back( Point_3( .9063, .4226,-1.0 ) );
|
||||
points.push_back( Point_3( .0872,-.9962,-1.0 ) );
|
||||
|
||||
// Construct the Delaunay triangulation.
|
||||
DT dt( points.begin(), points.end() );
|
||||
assert( dt.is_valid() );
|
||||
|
||||
// Construct a traverser.
|
||||
Traverser st( dt, Point_3(-3,0,0), Point_3(3,0,0) );
|
||||
|
||||
// Count the number of finite cells traversed.
|
||||
unsigned int cells = 0;
|
||||
while( st.has_next() ) {
|
||||
if( !dt.is_infinite(st) )
|
||||
++cells;
|
||||
++st;
|
||||
}
|
||||
|
||||
std::cout << "The number of finite cells between " << st.source() << " and " << st.target() << " is " << cells << std::endl;
|
||||
}
|
||||
|
|
@ -539,6 +539,7 @@ protected:
|
|||
GT _gt;
|
||||
Vertex_handle infinite; //infinite vertex
|
||||
|
||||
public:
|
||||
Comparison_result
|
||||
compare_xyz(const Point &p, const Point &q) const
|
||||
{
|
||||
|
|
@ -557,6 +558,9 @@ protected:
|
|||
{
|
||||
return geom_traits().orientation_3_object()(p, q, r, s);
|
||||
}
|
||||
|
||||
// Compute the orientation of a point compared to the oriented plane supporting a half-facet.
|
||||
Orientation orientation( const Facet& f, const Point& p ) const;
|
||||
|
||||
bool
|
||||
coplanar(const Point &p, const Point &q,
|
||||
|
|
@ -565,6 +569,21 @@ protected:
|
|||
return orientation(p, q, r, s) == COPLANAR;
|
||||
}
|
||||
|
||||
// Check whether the points of four vertices `a`, `b`, `c`, and `d` are coplanar.
|
||||
bool coplanar( Vertex_handle a, Vertex_handle b, Vertex_handle c, Vertex_handle d ) const {
|
||||
return coplanar( a->point(), b->point(), c->point(), d->point() );
|
||||
}
|
||||
|
||||
// Check whether the points of facet `f` and point `p` are coplanar.
|
||||
bool coplanar( const Facet& f, const Point& p ) const {
|
||||
return orientation(f, p) == COPLANAR;
|
||||
}
|
||||
|
||||
// Check whether the points of facet `f` and vertex `v` are coplanar.
|
||||
bool coplanar( const Facet& f, Vertex_handle v ) const{
|
||||
return orientation(f, v->point()) == COPLANAR;
|
||||
}
|
||||
|
||||
Orientation
|
||||
coplanar_orientation(const Point &p, const Point &q, const Point &r) const
|
||||
{
|
||||
|
|
@ -577,6 +596,7 @@ protected:
|
|||
return coplanar_orientation(p, q, r) == COLLINEAR;
|
||||
}
|
||||
|
||||
protected:
|
||||
Segment
|
||||
construct_segment(const Point &p, const Point &q) const
|
||||
{
|
||||
|
|
@ -1034,6 +1054,22 @@ public:
|
|||
Facet mirror_facet(Facet f) const
|
||||
{ return _tds.mirror_facet(f);}
|
||||
|
||||
|
||||
// Gives the edge incident to the same cell that is not incident to any of the input vertices.
|
||||
Edge opposite_edge( Cell_handle c, int li, int lj ) const;
|
||||
|
||||
// Gives the edge incident to the same cell that is not incident to any of the vertices of the input edge.
|
||||
Edge opposite_edge( const Edge& e ) const { return opposite_edge( e.first, e.second, e.third ); }
|
||||
|
||||
// Gives the half-facet incident to the opposite cell.
|
||||
Facet mirror_facet( Cell_handle c, int li ) const { return Facet( c->neighbor(li), c->neighbor(li)->index(c) ); }
|
||||
|
||||
// Gives the opposite half-facet.
|
||||
Facet mirror_facet( const Facet& f ) const { return mirror_facet( f.first, f.second ); }
|
||||
|
||||
|
||||
|
||||
|
||||
// MODIFIERS
|
||||
bool flip(const Facet &f)
|
||||
// returns false if the facet is not flippable
|
||||
|
|
@ -2244,9 +2280,23 @@ operator<< (std::ostream& os, const Triangulation_3<GT, Tds, Lds> &tr)
|
|||
return os ;
|
||||
}
|
||||
|
||||
template < class GT, class Tds, class Lds >
|
||||
typename Triangulation_3<GT,Tds,Lds>::size_type
|
||||
Triangulation_3<GT,Tds,Lds>::
|
||||
|
||||
|
||||
|
||||
|
||||
template <class Gt, class Tds>
|
||||
inline Orientation Triangulation_3<Gt,Tds>::
|
||||
orientation( const Facet& f, const Point& p ) const {
|
||||
return Gt().orientation_3_object()( f.first->vertex( vertex_triple_index(f.second, 0) )->point(),
|
||||
f.first->vertex( vertex_triple_index(f.second, 1) )->point(),
|
||||
f.first->vertex( vertex_triple_index(f.second, 2) )->point(),
|
||||
p );
|
||||
}
|
||||
|
||||
|
||||
template < class GT, class Tds >
|
||||
typename Triangulation_3<GT,Tds>::size_type
|
||||
Triangulation_3<GT,Tds>::
|
||||
number_of_finite_cells() const
|
||||
{
|
||||
if ( dimension() < 3 ) return 0;
|
||||
|
|
@ -3339,7 +3389,30 @@ side_of_edge(const Point & p,
|
|||
}
|
||||
}
|
||||
|
||||
template < class GT, class Tds, class Lds >
|
||||
|
||||
template <class Gt, class Tds>
|
||||
inline
|
||||
typename Triangulation_3<Gt,Tds>::Edge
|
||||
Triangulation_3<Gt,Tds>::
|
||||
opposite_edge( Cell_handle c, int li, int lj ) const {
|
||||
CGAL_triangulation_precondition( li >= 0 && li < 4 );
|
||||
CGAL_triangulation_precondition( lj >= 0 && lj < 4 );
|
||||
CGAL_triangulation_precondition( li != lj );
|
||||
|
||||
switch( 6-li-lj ) { // i + j + missing indices = 6.
|
||||
case 1: return Edge( c, 0, 1 );
|
||||
case 2: return Edge( c, 0, 2 );
|
||||
case 3: return ( li == 0 || lj == 0 ) ? Edge( c, 1, 2 ) : Edge( c, 0, 3 );
|
||||
case 4: return Edge( c, 1, 3 );
|
||||
case 5: return Edge( c, 2, 3 );
|
||||
}
|
||||
|
||||
CGAL_triangulation_assertion( false );
|
||||
return Edge();
|
||||
}
|
||||
|
||||
|
||||
template < class GT, class Tds >
|
||||
bool
|
||||
Triangulation_3<GT,Tds,Lds>::
|
||||
flip( Cell_handle c, int i )
|
||||
|
|
|
|||
|
|
@ -0,0 +1,356 @@
|
|||
//A class that follows a straight line through a Delaunay triangulation structure.
|
||||
//Copyright (C) 2012 Utrecht University
|
||||
//
|
||||
//This program is free software: you can redistribute it and/or modify
|
||||
//it under the terms of the GNU General Public License as published by
|
||||
//the Free Software Foundation, either version 3 of the License, or
|
||||
//(at your option) any later version.
|
||||
//
|
||||
//This program is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
//GNU General Public License for more details.
|
||||
//
|
||||
//You should have received a copy of the GNU General Public License
|
||||
//along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// Author(s): Thijs van Lankveld
|
||||
|
||||
#ifndef CGAL_TRIANGULATION_SEGMENT_TRAVERSER_3_H
|
||||
#define CGAL_TRIANGULATION_SEGMENT_TRAVERSER_3_H
|
||||
|
||||
#include <CGAL/internal/Dummy_gt.h>
|
||||
#include <CGAL/Random.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
#ifndef DOXYGEN_RUNNING
|
||||
/**
|
||||
* \ingroup PkgConformingTriangulation3Classes
|
||||
*
|
||||
* The `Triangulation_segment_traverser_3` iterates over the cells
|
||||
* of a `Triangulation_3` by following a straight line segment \f$ st \f$.
|
||||
*
|
||||
* This class is closely related to `Triangulation_3::locate(...)`.
|
||||
* However, unlike this `locate(...)` method, all the cells traversed
|
||||
* by the `Triangulation_segment_traverser_3` intersect the interior of the line
|
||||
* segment \f$ st \f$.
|
||||
*
|
||||
* Traversal starts from a cell containing \f$ s \f$ and it ends in a cell containing
|
||||
* \f$ t \f$.
|
||||
* If \f$ st \f$ is coplanar with a facet or collinear with an edge, at most one of the
|
||||
* incident cells is traversed.
|
||||
* If \f$ st \f$ intersects an edge or vertex, at most two incident cells are traversed:
|
||||
* the cells intersecting \f$ st \f$ strictly in their interior.
|
||||
*
|
||||
* If \f$ s \f$ lies on the convex hull, traversal starts in an incident cell inside
|
||||
* the convex hull. Similarly, if \f$ t \f$ lies on the convex hull, traversal ends in
|
||||
* an adjacent cell inside the convex hull.
|
||||
*
|
||||
* Both \f$ s \f$ and \f$ t \f$ may lie outside the convex hull of the triangulation,
|
||||
* but they must lie within the affine hull of the triangulation. In either case, the
|
||||
* finite facet of any infinite cells traversed must intersect \f$ st \f$.
|
||||
*
|
||||
* The traverser may be applied to any triangulation of dimension > 0.
|
||||
* However, for triangulations of dimension 1, the functionality is somewhat trivial.
|
||||
*
|
||||
* The traverser becomes invalid whenever the triangulation is changed.
|
||||
*
|
||||
* \tparam Tr_ is the triangulation type to traverse.
|
||||
*
|
||||
* \sa `Triangulation_3`
|
||||
* \sa `Forward_circulator_base`
|
||||
*/
|
||||
#endif // DOXYGEN_RUNNING
|
||||
template < class Tr_ = void >
|
||||
class Triangulation_segment_traverser_3
|
||||
: public Forward_circulator_base< typename Tr_::Triangulation_data_structure::Cell,
|
||||
std::ptrdiff_t, std::size_t > {
|
||||
typedef Tr_ Tr;
|
||||
typedef typename Tr::Triangulation_data_structure Tds;
|
||||
typedef typename Tr::Geom_traits Gt;
|
||||
|
||||
public:
|
||||
/// \name Types
|
||||
/// \{
|
||||
typedef Tr Triangulation; ///< The triangulation type.
|
||||
typedef Triangulation_segment_traverser_3<Tr> TST; ///< A triangulation segment traverser.
|
||||
typedef typename Tr::Point Point; ///< A point embedded in the vertices of the triangulation.
|
||||
typedef typename Tr::Segment Segment; ///< A segment connecting two points.
|
||||
typedef typename Tr::Cell Cell; ///< A cell in the triangulation.
|
||||
typedef typename Tr::Edge Edge; ///< An edge in the triangulation.
|
||||
typedef typename Tr::Vertex_handle Vertex_handle; ///< A handle for a vertex in the triangulation.
|
||||
typedef typename Tr::Cell_handle Cell_handle; ///< A handle for a cell in the triangulation.
|
||||
typedef typename Tr::Locate_type Locate_type; ///< The simplex containing a geometric object.
|
||||
/// \}
|
||||
|
||||
template < class Tr2 >
|
||||
struct Rebind_Tr {
|
||||
typedef Triangulation_segment_traverser_3<Tr2> Other;
|
||||
};
|
||||
|
||||
protected:
|
||||
/// \internal \name Protected Attributes
|
||||
/// \{
|
||||
/// \internal The triangulation to traverse.
|
||||
const Tr& _tr;
|
||||
/// \}
|
||||
|
||||
// The source and target points of the traversal.
|
||||
Point _source;
|
||||
Point _target;
|
||||
Vertex_handle _s_vertex;
|
||||
Vertex_handle _t_vertex;
|
||||
|
||||
// The cell currently traversed and the previous one.
|
||||
Cell_handle _pos, _prev;
|
||||
|
||||
// Otherwise, they indicate the simplex through which this cell was entered,
|
||||
// or the location of the source if it is in this cell.
|
||||
int _li, _lj;
|
||||
Locate_type _lt;
|
||||
|
||||
// This bit signifies when a cell containing the target is found.
|
||||
bool _done;
|
||||
|
||||
// Where possible, facets are checked in a random order.
|
||||
mutable Random rng;
|
||||
|
||||
private:
|
||||
Tds _tds2;
|
||||
Vertex_handle _s_vert, _t_vert;
|
||||
|
||||
public:
|
||||
/// \name Constructors
|
||||
/// \{
|
||||
/// Constructs a traverser.
|
||||
/** \param tr the triangulation to traverse. This triangulation must have dimension > 0.
|
||||
* \param s the source vertex. This vertex must be initialized and cannot be the infinite vertex.
|
||||
* \param t the target vertex. This vertex must be initialized and cannot be the infinite vertex.
|
||||
* It cannot equal `s`.
|
||||
*/
|
||||
Triangulation_segment_traverser_3( const Tr& tr, Vertex_handle s, Vertex_handle t );
|
||||
|
||||
/// Constructs a traverser.
|
||||
/** \param tr the triangulation to traverse. This triangulation must have dimension > 0.
|
||||
* \param s the source vertex. This vertex must be initialized and cannot be the infinite vertex.
|
||||
* \param t the target point. This point must be initialized and it cannot be be at the same location as `s`.
|
||||
* If `tr` has dimension < 3, `t` must lie inside the affine hull of `tr`.
|
||||
*/
|
||||
Triangulation_segment_traverser_3( const Tr& tr, Vertex_handle s, const Point& t );
|
||||
|
||||
/// Constructs a traverser.
|
||||
/** \param tr the triangulation to traverse. This triangulation must have dimension > 0.
|
||||
* \param s the source point. This point must be initialized. If `tr` has dimension < 3, `s` must lie inside
|
||||
* the affine hull of `tr`.
|
||||
* \param t the target point. This point must be initialized and it cannot be be at the same location as `s`.
|
||||
* If `tr` has dimension < 3, `t` must lie inside the affine hull of `tr`.
|
||||
* \param hint the starting point to search for `s`.
|
||||
*/
|
||||
Triangulation_segment_traverser_3( const Tr& tr, const Point& s, const Point& t, Cell_handle hint = Cell_handle() );
|
||||
|
||||
/// Constructs a traverser.
|
||||
/** \param tr the triangulation to traverse. This triangulation must have dimension > 0.
|
||||
* \param S the segment to be traversed. If `tr` has dimension < 3, `S` must lie inside
|
||||
* the affine hull of `tr`. `S` must not be degenerate, i.e. its source and target must not be equal.
|
||||
* \param hint the starting point to search for `S`.
|
||||
*/
|
||||
Triangulation_segment_traverser_3( const Tr& tr, const Segment& S, Cell_handle hint = Cell_handle() );
|
||||
/// \}
|
||||
|
||||
public:
|
||||
/// \name Accessors
|
||||
/// \{
|
||||
/// Gives the source point of the traversed segment.
|
||||
/** \return the source point.
|
||||
*/
|
||||
const Point& source() const { return _source; }
|
||||
|
||||
/// Gives the target point of the traversed segment.
|
||||
/** \return the target point.
|
||||
*/
|
||||
const Point& target() const { return _target; }
|
||||
|
||||
/// Gives the cell currently traversed.
|
||||
/** By invariance, this cell is intersected by the segment
|
||||
* between `source()` and `target()`.
|
||||
* \return the cell currently traversed.
|
||||
* \sa `handle()`.
|
||||
*/
|
||||
Cell_handle cell() const { return _pos; }
|
||||
|
||||
/// Gives a handle to the cell currently traversed.
|
||||
/** By invariance, this cell is intersected by the segment
|
||||
* between `source()` and `target()`.
|
||||
* \return a handle to the cell currently traversed.
|
||||
* \sa `cell()`.
|
||||
*/
|
||||
Cell_handle handle() { return _pos; }
|
||||
|
||||
/// Gives the cell traversed previously.
|
||||
/** This cell is uninitialized until the traverser leaves the initial
|
||||
* cell containing the `source()`.
|
||||
* By invariance, once initialized, this cell must be intersected by the segment
|
||||
* between `source()` and `target()`.
|
||||
* \return the cell traversed previously.
|
||||
* \sa `handle()`.
|
||||
*/
|
||||
Cell_handle previous() const { return _prev; }
|
||||
|
||||
/// Dereference operator.
|
||||
/** \return a pointer to the cell currently traversed.
|
||||
*/
|
||||
Cell* operator->() { return &*_pos; }
|
||||
|
||||
/// Indirection operator.
|
||||
/** \return the cell currently traversed.
|
||||
*/
|
||||
Cell& operator*() { return *_pos; }
|
||||
|
||||
/// Conversion operator.
|
||||
/** \return a handle to the cell currently traversed.
|
||||
*/
|
||||
operator const Cell_handle() const { return _pos; }
|
||||
|
||||
/// Checks if the traverser has reached the final cell, which contains the `target()`.
|
||||
/** If the `target()` lies on a facet, edge, or vertex, the final cell is the cell containing
|
||||
* the interior of the segment between `source()` and `target()`.
|
||||
* \return true iff the current cell contains the `target()`.
|
||||
*/
|
||||
bool has_next() const { return !_done; }
|
||||
|
||||
/// Gives the type of simplex traversed last.
|
||||
/** This simplex indicates where traversal has entered the cell.
|
||||
* For the first cell, containing the `source()` \f$ s \f$, this indicates the location of \f$ s \f$ in this cell.
|
||||
*/
|
||||
void entry( Locate_type& lt, int& li, int& lj ) const { lt = _lt; li = _li; lj = _lj; }
|
||||
/// \}
|
||||
|
||||
public:
|
||||
/// \name Mutators
|
||||
/// \{
|
||||
/// Increment postfix operator.
|
||||
/** The current cell must not contain the `target()`.
|
||||
* After incrementing the traverser, the current cell intersects the segment
|
||||
* between `source()` and `target()` closer to the `target()` than the previous cell.
|
||||
* \sa `operator++(int)`.
|
||||
*/
|
||||
TST& operator++();
|
||||
|
||||
/// Increment prefix operator.
|
||||
/** The current cell must not contain the `target()`.
|
||||
* After incrementing the traverser, the current cell intersects the segment
|
||||
* between `source()` and `target()` closer to the `target()` than the previous cell.
|
||||
* than the previous cell.
|
||||
* \sa `operator++()`.
|
||||
*/
|
||||
TST operator++( int );
|
||||
|
||||
/// Traverse to the final cell, which contains the `target()`.
|
||||
/** \return the final cell.
|
||||
*/
|
||||
Cell_handle traverse();
|
||||
/// \}
|
||||
|
||||
public:
|
||||
/// \name Comparison
|
||||
/// \{
|
||||
/// Compares this traverser with `ct`.
|
||||
/** \param ct the other traverser.
|
||||
* \return true iff the other traverser traverses the same triangulation along the same line segment
|
||||
* and has the same current cell.
|
||||
* \sa `operator!=( const TST& t )`.
|
||||
*/
|
||||
bool operator==( const TST& ct ) const;
|
||||
|
||||
/// Compares this traverser with `ct`.
|
||||
/** \param ct the other traverser.
|
||||
* \return `false` iff the other traverser traverses the same triangulation along the same line segment
|
||||
* and has the same current cell.
|
||||
* \sa `operator==( const TST& t ) const`.
|
||||
*/
|
||||
bool operator!=( const TST& ct ) const;
|
||||
|
||||
/// Compares the cell currently traversed with `ch`.
|
||||
/** \param ch a handle to the other cell.
|
||||
* \return true iff the cell currently traversed is the same as the one pointed to by `ch`.
|
||||
* \sa `operator!=( const Cell_handle& ch ) const`.
|
||||
* \sa `operator==( typename TriangulationTraits_3::Cell_handle ch, Triangulation_segment_traverser_3<TriangulationTraits_3> t )`.
|
||||
*/
|
||||
bool operator==( const Cell_handle& ch ) const { return ch == _pos; }
|
||||
|
||||
/// Compares the cell currently traversed with `ch`.
|
||||
/** \param ch a handle to the other cell.
|
||||
* \return `false` iff the cell currently traversed is the same as the one pointed to by `ch`.
|
||||
* \sa `operator==( const Cell_handle& ch )`.
|
||||
* \sa `operator!=( typename TriangulationTraits_3::Cell_handle ch, Triangulation_segment_traverser_3<TriangulationTraits_3> t )`.
|
||||
*/
|
||||
bool operator!=( const Cell_handle& ch ) const { return ch != _pos; }
|
||||
/// \}
|
||||
|
||||
bool operator==( Nullptr_t CGAL_triangulation_assertion_code(n) ) const;
|
||||
bool operator!=( Nullptr_t n ) const;
|
||||
|
||||
protected:
|
||||
/// \internal \name Protected Member Functions
|
||||
/// \{
|
||||
/// \internal Traverse to the next cell.
|
||||
/** \internal \sa `traverse()`.
|
||||
*/
|
||||
virtual void increment();
|
||||
/// \}
|
||||
|
||||
private:
|
||||
// increment(), if the triangulation is 3D.
|
||||
void increment_3();
|
||||
void increment_3_inf( int inf );
|
||||
|
||||
// increment(), if the triangulation is 2D.
|
||||
void increment_2();
|
||||
void increment_2_inf( int inf );
|
||||
|
||||
private:
|
||||
inline int edgeIndex( int i, int j ) const {
|
||||
CGAL_triangulation_precondition( i>=0 && i<=3 );
|
||||
CGAL_triangulation_precondition( j>=0 && j<=3 );
|
||||
CGAL_triangulation_precondition( i != j );
|
||||
return ( i==0 || j==0 ) ? i+j-1 : i+j;
|
||||
}
|
||||
}; // class Triangulation_segment_traverser_3
|
||||
|
||||
/// Compares a handle to a cell to a traverser.
|
||||
/** \param ch the handle to a cell.
|
||||
* \param t the traverser.
|
||||
* \return true iff the cell currently traversed by `t` is the same as the one pointed to by `ch`.
|
||||
* \sa `operator!=( typename TriangulationTraits_3::Cell_handle ch, Triangulation_segment_traverser_3<TriangulationTraits_3> t )`.
|
||||
* \sa `Triangulation_segment_traverser_3::operator==( const Cell_handle& ch )`.
|
||||
*/
|
||||
template <class Tr>
|
||||
inline bool operator==( typename Tr::Cell_handle ch, Triangulation_segment_traverser_3<Tr> tci ) { return tci == ch; }
|
||||
|
||||
/// Compares a handle to a cell to a traverser.
|
||||
/** \param ch the handle to a cell.
|
||||
* \param t the traverser.
|
||||
* \return `false` iff the cell currently traversed by `t` is the same as the one pointed to by `ch`.
|
||||
* \sa `operator==( typename TriangulationTraits_3::Cell_handle ch, Triangulation_segment_traverser_3<TriangulationTraits_3> t )`.
|
||||
* \sa `Triangulation_segment_traverser_3::operator!=( const Cell_handle& ch )`.
|
||||
*/
|
||||
template <class Tr>
|
||||
inline bool operator!=( typename Tr::Cell_handle ch, Triangulation_segment_traverser_3<Tr> tci ) { return tci != ch; }
|
||||
|
||||
// Specialization for void
|
||||
template <>
|
||||
class Triangulation_segment_traverser_3<void> {
|
||||
typedef internal::Dummy_gt Gt;
|
||||
typedef internal::Dummy_tds_3 Tds;
|
||||
public:
|
||||
typedef Triangulation_3<Gt,Tds> Triangulation;
|
||||
template <typename Tr2>
|
||||
struct Rebind_Tr { typedef Triangulation_segment_traverser_3<Tr2> Other; };
|
||||
}; // class Triangulation_segment_traverser_3<void>
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
#include <CGAL/Triangulation_segment_traverser_3_impl.h>
|
||||
|
||||
#endif // CGAL_TRIANGULATION_SEGMENT_TRAVERSER_3_H
|
||||
|
|
@ -0,0 +1,665 @@
|
|||
//A class that follows a straight line through a Delaunay triangulation structure.
|
||||
//Copyright (C) 2012 Utrecht University
|
||||
//
|
||||
//This program is free software: you can redistribute it and/or modify
|
||||
//it under the terms of the GNU General Public License as published by
|
||||
//the Free Software Foundation, either version 3 of the License, or
|
||||
//(at your option) any later version.
|
||||
//
|
||||
//This program is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
//GNU General Public License for more details.
|
||||
//
|
||||
//You should have received a copy of the GNU General Public License
|
||||
//along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// Author(s): Thijs van Lankveld
|
||||
|
||||
#ifndef CGAL_TRIANGULATION_SEGMENT_TRAVERSER_3_IMPL_H
|
||||
#define CGAL_TRIANGULATION_SEGMENT_TRAVERSER_3_IMPL_H
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template <class Tr>
|
||||
Triangulation_segment_traverser_3<Tr>::
|
||||
Triangulation_segment_traverser_3( const Tr& tr, Vertex_handle s, const Point& t )
|
||||
: _tr(tr), _pos(), _prev(), _lj(-1), _lt(Tr::VERTEX), _done(false) {
|
||||
CGAL_triangulation_precondition( !_tr.is_infinite(s) );
|
||||
CGAL_triangulation_precondition( s->point() != t );
|
||||
CGAL_triangulation_precondition( _tr.dimension() >= 2 );
|
||||
CGAL_triangulation_precondition( _tr.dimension() == 3 ||
|
||||
_tr.orientation( *_tr.finite_facets_begin(), t ) == COPLANAR );
|
||||
|
||||
_source = s->point();
|
||||
_target = t;
|
||||
_s_vertex = s;
|
||||
_t_vertex = Vertex_handle();
|
||||
_s_vert = s;
|
||||
_t_vert = _tds2.create_vertex( Vertex(_target) );
|
||||
|
||||
_pos = s->cell();
|
||||
int inf;
|
||||
if( _pos->has_vertex( _tr.infinite_vertex(), inf ) )
|
||||
_pos = _pos->neighbor(inf);
|
||||
_li = _pos->index(s);
|
||||
|
||||
CGAL_triangulation_postcondition( _pos != Cell_handle() );
|
||||
}
|
||||
|
||||
template < class Tr>
|
||||
Triangulation_segment_traverser_3<Tr>::
|
||||
Triangulation_segment_traverser_3( const Tr& tr, Vertex_handle s, Vertex_handle t )
|
||||
: _tr(tr), _pos(), _prev(), _lj(-1), _lt(Tr::VERTEX), _done(false) {
|
||||
CGAL_triangulation_precondition( !_tr.is_infinite(s) );
|
||||
CGAL_triangulation_precondition( !_tr.is_infinite(t) );
|
||||
CGAL_triangulation_precondition( s->point() != t->point() );
|
||||
CGAL_triangulation_precondition( _tr.dimension() >= 2 );
|
||||
|
||||
_source = s->point();
|
||||
_target = t->point();
|
||||
_s_vertex = s;
|
||||
_t_vertex = t;
|
||||
_s_vert = s;
|
||||
_t_vert = t;
|
||||
|
||||
_pos = s->cell();
|
||||
int inf;
|
||||
if( _pos->has_vertex( _tr.infinite_vertex(), inf ) )
|
||||
_pos = _pos->neighbor(inf);
|
||||
_li = _pos->index(s);
|
||||
}
|
||||
|
||||
|
||||
template <class Tr>
|
||||
Triangulation_segment_traverser_3<Tr>::
|
||||
Triangulation_segment_traverser_3( const Tr& tr, const Point& s, const Point& t, Cell_handle hint )
|
||||
: _tr(tr), _pos(), _prev(), _li(-1), _lj(-1), _done(false) {
|
||||
CGAL_triangulation_precondition( s != t );
|
||||
CGAL_triangulation_precondition( _tr.dimension() >= 2 );
|
||||
CGAL_triangulation_precondition( _tr.dimension() == 3 ||
|
||||
_tr.coplanar( *_tr.finite_facets_begin(), _target ) );
|
||||
|
||||
_source = s;
|
||||
_target = t;
|
||||
_s_vertex = Vertex_handle();
|
||||
_t_vertex = Vertex_handle();
|
||||
_s_vert = _tds2.create_vertex( Tr::Vertex(_source) );
|
||||
_t_vert = _tds2.create_vertex( Tr::Vertex(_target) );
|
||||
|
||||
_pos = _tr.locate( s, _lt, _li, _lj, hint );
|
||||
|
||||
CGAL_triangulation_postcondition( _pos != Cell_handle() );
|
||||
}
|
||||
|
||||
template <class Tr>
|
||||
Triangulation_segment_traverser_3<Tr>::
|
||||
Triangulation_segment_traverser_3( const Tr& tr, const Segment& s, Cell_handle hint )
|
||||
: Triangulation_segment_traverser_3<Tr>( tr, s.source(), s.target(), hint ) {}
|
||||
|
||||
template <class Tr>
|
||||
inline Triangulation_segment_traverser_3<Tr>&
|
||||
Triangulation_segment_traverser_3<Tr>::operator++() {
|
||||
CGAL_triangulation_precondition( _pos != Cell_handle() );
|
||||
increment();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Tr>
|
||||
inline Triangulation_segment_traverser_3<Tr>
|
||||
Triangulation_segment_traverser_3<Tr>::operator++( int ) {
|
||||
TST tmp( *this );
|
||||
++( *this );
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template <class Tr>
|
||||
inline typename Triangulation_segment_traverser_3<Tr>::Cell_handle
|
||||
Triangulation_segment_traverser_3<Tr>::traverse() {
|
||||
while( !_done )
|
||||
increment();
|
||||
return _pos;
|
||||
}
|
||||
|
||||
template <class Tr>
|
||||
inline bool Triangulation_segment_traverser_3<Tr>::
|
||||
operator==( const TST& ct ) const {
|
||||
CGAL_triangulation_precondition( _pos != Cell_handle() );
|
||||
CGAL_triangulation_precondition( ct._pos != Cell_handle() );
|
||||
return ( _pos == ct._pos &&
|
||||
_prev == ct._prev &&
|
||||
_tr == ct._tr &&
|
||||
_li == ct._li &&
|
||||
_lj == ct._lj &&
|
||||
_lt == ct._lt &&
|
||||
_source == ct._source &&
|
||||
_target == ct._target &&
|
||||
_s_vertex == ct._s_vertex &&
|
||||
_t_vertex == ct._t_vertex &&
|
||||
_done == ct._done );
|
||||
}
|
||||
|
||||
template <class Tr>
|
||||
inline bool Triangulation_segment_traverser_3<Tr>::
|
||||
operator!=( const TST& ct ) const {
|
||||
return !( *this == ct );
|
||||
}
|
||||
|
||||
template <class Tr>
|
||||
inline bool Triangulation_segment_traverser_3<Tr>::
|
||||
operator==( Nullptr_t CGAL_triangulation_assertion_code(n) ) const {
|
||||
CGAL_triangulation_assertion( n == NULL );
|
||||
return _pos == Cell_handle();
|
||||
}
|
||||
|
||||
template <class Tr>
|
||||
inline bool Triangulation_segment_traverser_3<Tr>::
|
||||
operator!=( Nullptr_t n ) const {
|
||||
return !( *this == n );
|
||||
}
|
||||
|
||||
template <class Tr>
|
||||
void Triangulation_segment_traverser_3<Tr>::
|
||||
increment() {
|
||||
CGAL_triangulation_precondition( !_done );
|
||||
// Walks to the next cell over a facet intersected by the line from source to target.
|
||||
// This method is based on Triangulation_3::locate().
|
||||
int inf;
|
||||
switch( _tr.dimension() ) {
|
||||
case 3: {
|
||||
// Infinite cells should be handled differently.
|
||||
if( _pos->has_vertex( _tr.infinite_vertex(), inf ) )
|
||||
increment_3_inf( inf );
|
||||
else
|
||||
increment_3();
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
if( _pos->has_vertex( _tr.infinite_vertex(), inf ) )
|
||||
increment_2_inf( inf );
|
||||
else
|
||||
increment_2();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class Tr>
|
||||
void Triangulation_segment_traverser_3<Tr>::
|
||||
increment_3() {
|
||||
Vertex_handle vert[4] = { _pos->vertex(0),
|
||||
_pos->vertex(1),
|
||||
_pos->vertex(2),
|
||||
_pos->vertex(3) };
|
||||
|
||||
// We check in which direction the target lies
|
||||
// by comparing its position relative to the planes through the
|
||||
// source and the edges of the cell.
|
||||
Orientation o[6];
|
||||
// We keep track of which orientations are calculated.
|
||||
bool calc[6] = { false, false, false, false, false, false };
|
||||
|
||||
if( _lt == Tr::VERTEX ) {
|
||||
// The three planes through the vertex are set to coplanar.
|
||||
for( int j = 0; j < 4; ++j ) {
|
||||
if( _li != j ) {
|
||||
int ij = edgeIndex( _li, j );
|
||||
o[ij] = COPLANAR;
|
||||
calc[ij] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( _lt == Tr::EDGE ) {
|
||||
// The plane through the edge is set to coplanar.
|
||||
int ij = edgeIndex( _li, _lj );
|
||||
o[ij] = COPLANAR;
|
||||
calc[ij] = true;
|
||||
}
|
||||
|
||||
// For the remembering stochastic walk, we start trying with a random facet.
|
||||
int li = rng.template get_bits<2>();
|
||||
|
||||
CGAL_triangulation_assertion_code( bool incell = true; )
|
||||
for( int k = 0; k < 4; ++k, li = _tr.incr_ind(li) ) {
|
||||
Cell_handle next = _pos->neighbor(li);
|
||||
if( next == _prev )
|
||||
continue;
|
||||
|
||||
if( _t_vertex == _pos->vertex(0) || _t_vertex == _pos->vertex(1) ||
|
||||
_t_vertex == _pos->vertex(2) || _t_vertex == _pos->vertex(3) ) {
|
||||
// The target is inside the cell.
|
||||
_done = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the target is outside the cell.
|
||||
Vertex_handle backup = vert[li];
|
||||
vert[li] = _t_vert;
|
||||
|
||||
if( _tr.orientation( vert[0], vert[1], vert[2], vert[3] ) != NEGATIVE ) {
|
||||
vert[li] = backup;
|
||||
continue;
|
||||
}
|
||||
CGAL_triangulation_assertion_code( incell = false; )
|
||||
|
||||
// Check if the target is inside the pyramid.
|
||||
int lj = rng.template get_bits<2>();
|
||||
int Or = 0;
|
||||
for( int l = 0; l < 4; ++l, lj = _tr.incr_ind(lj) ) {
|
||||
if( li == lj )
|
||||
continue;
|
||||
|
||||
// We check the orientation of the target compared to the plane
|
||||
// Through the source and the edge opposite of ij.
|
||||
int oij = 5 - edgeIndex( li, lj );
|
||||
if( !calc[oij] ) {
|
||||
Vertex_handle backup2 = vert[lj];
|
||||
vert[lj] = _s_vert;
|
||||
o[oij] = _tr.orientation( vert[0], vert[1], vert[2], vert[3] );
|
||||
vert[lj] = backup2;
|
||||
calc[oij] = true;
|
||||
}
|
||||
|
||||
Or -= o[oij];
|
||||
if( o[oij] == POSITIVE ) {
|
||||
// The target is not inside the pyramid.
|
||||
// Invert the planes.
|
||||
// This can be safely done because either
|
||||
// they were not calculated yet,
|
||||
// or they will no longer be used.
|
||||
for( int j = 0; j < 4; ++j ) {
|
||||
if( li == j ) continue;
|
||||
int oij = 5 - edgeIndex( li, j );
|
||||
o[oij] = -o[oij];
|
||||
}
|
||||
Or = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( Or == 0 ) {
|
||||
// Either the target is not inside the pyramid,
|
||||
// or the pyramid is degenerate.
|
||||
vert[li] = backup;
|
||||
continue;
|
||||
}
|
||||
|
||||
// The target is inside the pyramid.
|
||||
_prev = _pos;
|
||||
_pos = next;
|
||||
|
||||
switch( Or ) {
|
||||
case 3:
|
||||
_lt = Tr::FACET;
|
||||
_li = _pos->index(_prev);
|
||||
return;
|
||||
case 2:
|
||||
_lt = Tr::EDGE;
|
||||
for( int j = 0; j < 4; ++j ) {
|
||||
if( li != j && o[ 5 - edgeIndex(li, j) ] == COPLANAR) {
|
||||
Edge opp = _tr.opposite_edge( _prev, li, j );
|
||||
_li = _pos->index( _prev->vertex(opp.second) );
|
||||
_lj = _pos->index( _prev->vertex(opp.third) );
|
||||
return;
|
||||
}
|
||||
}
|
||||
CGAL_triangulation_assertion( false );
|
||||
return;
|
||||
case 1:
|
||||
_lt = Tr::VERTEX;
|
||||
for( int j = 0; j < 4; ++j ) {
|
||||
if( li != j && o[ 5 - edgeIndex(li, j) ] == NEGATIVE ) {
|
||||
_li = _pos->index( _prev->vertex(j) );
|
||||
return;
|
||||
}
|
||||
}
|
||||
CGAL_triangulation_assertion( false );
|
||||
return;
|
||||
default:
|
||||
CGAL_triangulation_assertion( false );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// The target lies inside this cell.
|
||||
CGAL_triangulation_assertion( incell );
|
||||
_done = true;
|
||||
return;
|
||||
}
|
||||
|
||||
template <class Tr>
|
||||
void Triangulation_segment_traverser_3<Tr>::
|
||||
increment_3_inf( int inf ) {
|
||||
CGAL_triangulation_precondition( _tr.is_infinite( _pos->vertex(inf) ) );
|
||||
|
||||
// If this cell was reached by traversal from a finite one, it must be the final cell.
|
||||
Cell_handle fin = _pos->neighbor(inf);
|
||||
if( fin == _prev ) {
|
||||
_done = true;
|
||||
// Here, I do not change the _lt etc. because they were already set.
|
||||
return;
|
||||
}
|
||||
|
||||
Vertex_handle vert[4];
|
||||
for( int i = 0; i != 4; ++i )
|
||||
if( i != inf )
|
||||
vert[i] = _pos->vertex(i);
|
||||
vert[inf] = _t_vert;
|
||||
Orientation o[4];
|
||||
|
||||
// For the remembering stochastic walk, we start trying with a random index:
|
||||
int li = rng.template get_bits<2>();
|
||||
|
||||
// Check if the target lies outside the convex hull.
|
||||
if( _tr.orientation( vert[0], vert[1], vert[2], vert[3] ) == POSITIVE ) {
|
||||
// The target lies in an infinite cell.
|
||||
// Note that we do not traverse to other infinite cells.
|
||||
_done = true;
|
||||
return;
|
||||
}
|
||||
|
||||
vert[inf] = _s_vert;
|
||||
CGAL_triangulation_assertion( _tr.orientation( vert[0], vert[1], vert[2], vert[3] ) == POSITIVE );
|
||||
|
||||
// Check if the line enters an adjacent infinite cell.
|
||||
// This occurs if the target lies on the other side of
|
||||
// a plane through one of the finite edges and the source point.
|
||||
for( int j = 0; j != 4; ++j, li = _tr.incr_ind(li) ) {
|
||||
if( li == inf ) {
|
||||
o[li] = COPLANAR;
|
||||
continue;
|
||||
}
|
||||
|
||||
Cell_handle next = _pos->neighbor(li);
|
||||
if( next == _prev ) {
|
||||
o[li] = POSITIVE;
|
||||
continue;
|
||||
}
|
||||
|
||||
Vertex_handle backup = vert[li];
|
||||
vert[li] = _t_vert;
|
||||
o[li] = _tr.orientation( vert[0], vert[1], vert[2], vert[3] );
|
||||
|
||||
if( o[li] != NEGATIVE ) {
|
||||
vert[li] = backup;
|
||||
continue;
|
||||
}
|
||||
|
||||
// The target lies behind the plane through the source and two finite vertices.
|
||||
// Traverse to the incident infinite cell.
|
||||
_prev = _pos;
|
||||
_pos = next;
|
||||
CGAL_triangulation_assertion( _tr.is_infinite(_pos) );
|
||||
|
||||
_lt = Tr::FACET;
|
||||
_li = _pos->index(_prev);
|
||||
return;
|
||||
}
|
||||
|
||||
// The line enters the convex hull here (or lies on the finite facet).
|
||||
_prev = _pos;
|
||||
_pos = fin;
|
||||
|
||||
// Check through which simplex the line traverses.
|
||||
switch( o[0]+o[1]+o[2]+o[3] ) {
|
||||
case 3:
|
||||
_lt = Tr::FACET;
|
||||
_li = _pos->index(_prev);
|
||||
return;
|
||||
case 2:
|
||||
_lt = Tr::EDGE;
|
||||
for( int i = 0; i < 4; ++i ) {
|
||||
if( o[i] == COPLANAR && i != inf ) {
|
||||
Edge opp = _tr.opposite_edge( _prev, inf, i );
|
||||
_li = _pos->index( _prev->vertex(opp.second) );
|
||||
_lj = _pos->index( _prev->vertex(opp.third) );
|
||||
return;
|
||||
}
|
||||
}
|
||||
CGAL_triangulation_assertion( false );
|
||||
return;
|
||||
case 1:
|
||||
_lt = Tr::VERTEX;
|
||||
for( int i = 0; i < 4; ++i ) {
|
||||
if( o[i] == POSITIVE ) {
|
||||
_li = _pos->index( _prev->vertex(i) );
|
||||
return;
|
||||
}
|
||||
}
|
||||
CGAL_triangulation_assertion( false );
|
||||
return;
|
||||
default:
|
||||
CGAL_triangulation_assertion( false );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
template <class Tr>
|
||||
void Triangulation_segment_traverser_3<Tr>::
|
||||
increment_2() {
|
||||
Vertex_handle vert[3] = { _pos->vertex(0),
|
||||
_pos->vertex(1),
|
||||
_pos->vertex(2) };
|
||||
|
||||
switch( _lt ) {
|
||||
case Tr::VERTEX: {
|
||||
// First we try the incident edges.
|
||||
Orientation ocw = _tr.coplanar_orientation( vert[_li], vert[_tr.cw(_li)], vert[_tr.ccw(_li)], _t_vert );
|
||||
if( _pos->neighbor( _tr.ccw(_li) ) != _prev && ocw == NEGATIVE) {
|
||||
Cell_handle tmp = _pos->neighbor( _tr.ccw(_li) );
|
||||
_prev = _pos;
|
||||
_pos = tmp;
|
||||
_li = _pos->index( _prev->vertex(_li) );
|
||||
return;
|
||||
}
|
||||
Orientation occw = _tr.coplanar_orientation( vert[_li], vert[_tr.ccw(_li)], vert[_tr.cw(_li)], _t_vert );
|
||||
if( _pos->neighbor( _tr.cw(_li) ) != _prev && occw == NEGATIVE) {
|
||||
Cell_handle tmp = _pos->neighbor( _tr.cw(_li) );
|
||||
_prev = _pos;
|
||||
_pos = tmp;
|
||||
_li = _pos->index( _prev->vertex(_li) );
|
||||
return;
|
||||
}
|
||||
|
||||
// Then we try the opposite edge.
|
||||
if( _tr.coplanar_orientation( vert[_tr.ccw(_li)], vert[_tr.cw(_li)], vert[_li], _t_vert ) == NEGATIVE) {
|
||||
Cell_handle tmp = _pos->neighbor(_li);
|
||||
_prev = _pos;
|
||||
_pos = tmp;
|
||||
|
||||
switch( ocw+occw ) {
|
||||
case 2:
|
||||
_lt = Tr::EDGE;
|
||||
_li = _pos->index( _prev->vertex( _tr.ccw(_li) ) );
|
||||
_lj = _pos->index( _prev->vertex( _tr.cw(_li) ) );
|
||||
return;
|
||||
case 1:
|
||||
_lt = Tr::VERTEX;
|
||||
if( ocw == COLLINEAR ) _li = _pos->index( _prev->vertex( _tr.cw(_li) ) );
|
||||
else _li = _pos->index( _prev->vertex( _tr.ccw(_li) ) );
|
||||
return;
|
||||
default:
|
||||
CGAL_triangulation_assertion(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// The target lies in this cell.
|
||||
_done = true;
|
||||
return;
|
||||
}
|
||||
case Tr::EDGE: {
|
||||
int lk = 3-_li-_lj;
|
||||
|
||||
if( _pos->neighbor(lk) != _prev ) {
|
||||
// Check the edge itself
|
||||
switch( _tr.coplanar_orientation( vert[_li], vert[_lj], vert[lk], _t_vert ) ) {
|
||||
case COLLINEAR:
|
||||
// The target lies in this cell.
|
||||
_done = true;
|
||||
return;
|
||||
case NEGATIVE: {
|
||||
// The target lies opposite of the edge.
|
||||
Cell_handle tmp = _pos->neighbor(lk);
|
||||
_prev = _pos;
|
||||
_pos = tmp;
|
||||
_li = _pos->index( _prev->vertex(_li) );
|
||||
_lj = _pos->index( _prev->vertex(_lj) );
|
||||
return;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Orientation o = _tr.coplanar_orientation( _s_vert, vert[lk], vert[_li], _t_vert );
|
||||
switch( o ) {
|
||||
case POSITIVE: {
|
||||
// The ray passes through the edge ik.
|
||||
if( _tr.coplanar_orientation( vert[lk], vert[_li], _s_vert, _t_vert ) == NEGATIVE ) {
|
||||
Cell_handle tmp = _pos->neighbor(_lj);
|
||||
_prev = _pos;
|
||||
_pos = tmp;
|
||||
|
||||
if( _tr.collinear( _s_vert, vert[_li], _t_vert ) ) {
|
||||
_lt = Tr::VERTEX;
|
||||
_li = _pos->index( _prev->vertex(_li) );
|
||||
}
|
||||
else {
|
||||
_lt = Tr::EDGE;
|
||||
_li = _pos->index( _prev->vertex(_li) );
|
||||
_lj = _pos->index( _prev->vertex(lk) );
|
||||
}
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// The ray passes through the edge jk.
|
||||
if( _tr.coplanar_orientation( vert[lk], vert[_lj], _s_vert, _t_vert ) == NEGATIVE ) {
|
||||
Cell_handle tmp = _pos->neighbor(_li);
|
||||
_prev = _pos;
|
||||
_pos = tmp;
|
||||
|
||||
if( _tr.collinear( _s_vert, vert[_lj], _t_vert ) ) {
|
||||
_lt = Tr::VERTEX;
|
||||
_li = _pos->index( _prev->vertex(_lj) );
|
||||
}
|
||||
else if( o == COLLINEAR ) {
|
||||
_lt = Tr::VERTEX;
|
||||
_li = _pos->index( _prev->vertex(lk) );
|
||||
}
|
||||
else {
|
||||
_lt = Tr::EDGE;
|
||||
_li = _pos->index( _prev->vertex(lk) );
|
||||
_lj = _pos->index( _prev->vertex(_lj) );
|
||||
}
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// The target lies in this cell.
|
||||
_done = true;
|
||||
return;
|
||||
}
|
||||
case Tr::FACET: {
|
||||
// We test its edges in a random order until we find a neighbor to go further
|
||||
int li = rng.get_int(0, 3);
|
||||
|
||||
Orientation o[3];
|
||||
bool calc[3] = { false, false, false };
|
||||
|
||||
for( int j = 0; j != 3; ++j, li = _tr.ccw(li) ) {
|
||||
Cell_handle next = _pos->neighbor(li);
|
||||
if( next == _prev )
|
||||
continue;
|
||||
|
||||
// The target should lie on the other side of the edge.
|
||||
if( _tr.coplanar_orientation( vert[_tr.ccw(li)], vert[_tr.cw(li)], vert[li], _t_vert ) != NEGATIVE )
|
||||
continue;
|
||||
|
||||
// The target should lie inside the wedge.
|
||||
if( !calc[_tr.ccw(li)] ) {
|
||||
o[_tr.ccw(li)] = _tr.coplanar_orientation( _s_vert, vert[_tr.ccw(li)], vert[_tr.cw(li)], _t_vert );
|
||||
calc[_tr.ccw(li)] = true;
|
||||
}
|
||||
if( o[_tr.ccw(li)] == NEGATIVE ) continue;
|
||||
|
||||
if( !calc[_tr.cw(li)] ) {
|
||||
o[_tr.cw(li)] = _tr.coplanar_orientation( _s_vert, vert[_tr.cw(li)], vert[_tr.ccw(li)], _t_vert );
|
||||
calc[_tr.cw(li)] = true;
|
||||
}
|
||||
if( o[_tr.cw(li)] == POSITIVE ) continue;
|
||||
|
||||
_prev = _pos;
|
||||
_pos = next;
|
||||
|
||||
switch( o[_tr.ccw(li)] + o[_tr.cw(li)] ) {
|
||||
case 2:
|
||||
_lt = Tr::EDGE;
|
||||
_li = _pos->index( _prev->vertex( _tr.ccw(li) ) );
|
||||
_lj = _pos->index( _prev->vertex( _tr.cw(li) ) );
|
||||
return;
|
||||
case 1:
|
||||
_lt = Tr::VERTEX;
|
||||
if( o[_tr.ccw(li)] == COLLINEAR ) _li = _pos->index( _prev->vertex( _tr.ccw(li) ) );
|
||||
else _li = _pos->index( _prev->vertex( _tr.cw(li) ) );
|
||||
return;
|
||||
default:
|
||||
CGAL_triangulation_assertion( false );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// The target lies in this cell.
|
||||
_done = true;
|
||||
return;
|
||||
}
|
||||
default:
|
||||
CGAL_triangulation_assertion( false );
|
||||
}
|
||||
}
|
||||
|
||||
template <class Tr>
|
||||
void Triangulation_segment_traverser_3<Tr>::
|
||||
increment_2_inf( int inf ) {
|
||||
CGAL_triangulation_precondition( _tr.is_infinite( _pos->vertex(3) ) );
|
||||
CGAL_triangulation_precondition( _tr.is_infinite( _pos->vertex(inf) ) );
|
||||
|
||||
// If this cell was reached by traversal from a finite one, it must be the final cell.
|
||||
Cell_handle fin = _pos->neighbor(inf);
|
||||
if (fin == _prev) {
|
||||
_done = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the neighboring cells.
|
||||
Gt::Coplanar_orientation_3 coplanar_orientation = Gt().coplanar_orientation_3_object();
|
||||
if( _tr.coplanar_orientation( _s_vert, _pos->vertex( _tr.ccw(inf)), _pos->vertex(_tr.cw(inf)), _t_vert ) == NEGATIVE ) {
|
||||
Cell_handle tmp = _pos->neighbor(_tr.cw(inf));
|
||||
_prev = _pos;
|
||||
_pos = tmp;
|
||||
return;
|
||||
}
|
||||
if( _tr.coplanar_orientation( _s_vert, _pos->vertex( _tr.cw(inf)), _pos->vertex(_tr.ccw(inf)), _t_vert ) == NEGATIVE ) {
|
||||
Cell_handle tmp = _pos->neighbor(_tr.ccw(inf));
|
||||
_prev = _pos;
|
||||
_pos = tmp;
|
||||
return;
|
||||
}
|
||||
if( _tr.coplanar_orientation( _pos->vertex( _tr.ccw(inf)), _pos->vertex(_tr.cw(inf)), _s_vert, _t_vert ) != POSITIVE ) {
|
||||
_prev = _pos;
|
||||
_pos = fin;
|
||||
return;
|
||||
}
|
||||
|
||||
// The target lies in this infinite cell.
|
||||
_done = true;
|
||||
return;
|
||||
}
|
||||
|
||||
} //end of CGAL namespace
|
||||
|
||||
#endif // CGAL_TRIANGULATION_SEGMENT_TRAVERSER_3_IMPL_H
|
||||
|
|
@ -29,55 +29,81 @@ namespace CGAL {
|
|||
// We use the following template class in order to avoid having a static data
|
||||
// member of a non-template class which would require src/Triangulation_3.C .
|
||||
template < class T = void >
|
||||
struct Triangulation_utils_base_3
|
||||
{
|
||||
static const char tab_next_around_edge[4][4];
|
||||
static const int tab_vertex_triple_index[4][3];
|
||||
struct Triangulation_utils_base_3 {
|
||||
static const char tab_next_around_edge[4][4];
|
||||
static const int tab_vertex_triple_index[4][3];
|
||||
|
||||
static const int index_increment_map[4];
|
||||
static const int index_jump_map[4];
|
||||
static const int index_decrement_map[4];
|
||||
};
|
||||
|
||||
template < class T >
|
||||
const char Triangulation_utils_base_3<T>::tab_next_around_edge[4][4] = {
|
||||
{5, 2, 3, 1},
|
||||
{3, 5, 0, 2},
|
||||
{1, 3, 5, 0},
|
||||
{2, 0, 1, 5} };
|
||||
{ 5, 2, 3, 1 },
|
||||
{ 3, 5, 0, 2 },
|
||||
{ 1, 3, 5, 0 },
|
||||
{ 2, 0, 1, 5 }
|
||||
};
|
||||
|
||||
template < class T >
|
||||
const int Triangulation_utils_base_3<T>::tab_vertex_triple_index[4][3] = {
|
||||
{1, 3, 2},
|
||||
{0, 2, 3},
|
||||
{0, 3, 1},
|
||||
{0, 1, 2}
|
||||
{ 1, 3, 2 },
|
||||
{ 0, 2, 3 },
|
||||
{ 0, 3, 1 },
|
||||
{ 0, 1, 2 }
|
||||
};
|
||||
|
||||
template < class T >
|
||||
const int Triangulation_utils_base_3<T>::index_increment_map[4] = { 1, 2, 3, 0 };
|
||||
|
||||
template < class T >
|
||||
const int Triangulation_utils_base_3<T>::index_jump_map[4] = { 2, 3, 0, 1 };
|
||||
|
||||
template < class T >
|
||||
const int Triangulation_utils_base_3<T>::index_decrement_map[4] = { 3, 0, 1, 2 };
|
||||
|
||||
// We derive from Triangulation_cw_ccw_2 because we still use cw() and ccw()
|
||||
// in the 2D part of the code. Ideally, this should go away when we re-use
|
||||
// T2D entirely.
|
||||
|
||||
struct Triangulation_utils_3
|
||||
: public Triangulation_cw_ccw_2,
|
||||
public Triangulation_utils_base_3<>
|
||||
{
|
||||
static int next_around_edge(const int i, const int j)
|
||||
{
|
||||
// index of the next cell when turning around the
|
||||
// oriented edge vertex(i) vertex(j) in 3d
|
||||
CGAL_triangulation_precondition( ( i >= 0 && i < 4 ) &&
|
||||
( j >= 0 && j < 4 ) &&
|
||||
( i != j ) );
|
||||
return tab_next_around_edge[i][j];
|
||||
}
|
||||
: public Triangulation_cw_ccw_2,
|
||||
public Triangulation_utils_base_3<> {
|
||||
static int next_around_edge( const int i, const int j ) {
|
||||
// index of the next cell when turning around the
|
||||
// oriented edge vertex(i) vertex(j) in 3d
|
||||
CGAL_triangulation_precondition( ( i >= 0 && i < 4 ) &&
|
||||
( j >= 0 && j < 4 ) &&
|
||||
( i != j ) );
|
||||
return tab_next_around_edge[i][j];
|
||||
}
|
||||
|
||||
static int vertex_triple_index( const int i, const int j ) {
|
||||
// indexes of the jth vertex of the facet of a cell
|
||||
// opposite to vertx i
|
||||
CGAL_triangulation_precondition( ( i >= 0 && i < 4 ) &&
|
||||
( j >= 0 && j < 3 ) );
|
||||
return tab_vertex_triple_index[i][j];
|
||||
}
|
||||
|
||||
static int vertex_triple_index(const int i, const int j)
|
||||
{
|
||||
// indexes of the jth vertex of the facet of a cell
|
||||
// opposite to vertx i
|
||||
CGAL_triangulation_precondition( ( i >= 0 && i < 4 ) &&
|
||||
( j >= 0 && j < 3 ) );
|
||||
return tab_vertex_triple_index[i][j];
|
||||
}
|
||||
// Get the index of the next vertex or facet.
|
||||
static int increment_index( int li ) {
|
||||
CGAL_triangulation_precondition( li >= 0 && li < 4 );
|
||||
return index_increment_map[ li ];
|
||||
}
|
||||
|
||||
// Get the index of the vertex or facet two places further.
|
||||
static int jump_index( int li ) {
|
||||
CGAL_triangulation_precondition( li >= 0 && li < 4 );
|
||||
return index_jump_map[ li ];
|
||||
}
|
||||
|
||||
// Get the index of the previous vertex or facet.
|
||||
static int decrement_index( int li ) {
|
||||
CGAL_triangulation_precondition( li >= 0 && li < 4 );
|
||||
return index_decrement_map[ li ];
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace CGAL
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
// A dummy geometry traits class.
|
||||
// Copyright (c) 2003 INRIA Sophia-Antipolis (France).
|
||||
// All rights reserved.
|
||||
//
|
||||
//This program is free software: you can redistribute it and/or modify
|
||||
//it under the terms of the GNU General Public License as published by
|
||||
//the Free Software Foundation, either version 3 of the License, or
|
||||
//(at your option) any later version.
|
||||
//
|
||||
//This program is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
//GNU General Public License for more details.
|
||||
//
|
||||
//You should have received a copy of the GNU General Public License
|
||||
//along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// Author(s): Thijs van Lankveld
|
||||
|
||||
#ifndef CGAL_INTERNAL_TRIANGULATION_DUMMY_GT_H
|
||||
#define CGAL_INTERNAL_TRIANGULATION_DUMMY_GT_H
|
||||
|
||||
namespace CGAL { namespace internal {
|
||||
|
||||
// Dummy triangulation which provides all types that a triangulation can use.
|
||||
struct Dummy_gt {
|
||||
struct Point_3 {};
|
||||
struct Segment_3 {};
|
||||
struct Triangle_3 {};
|
||||
struct Tetrahedron_3 {};
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
#endif // CGAL_INTERNAL_TRIANGULATION_DUMMY_GT_H
|
||||
Loading…
Reference in New Issue