mirror of https://github.com/CGAL/cgal
Merge pull request #7535 from lrineau/Triangulation_3-fix_simplex_traverser-GF-CGAL-5.6
fix simplex traverser for CGAL 5.6
This commit is contained in:
commit
04077e9f4f
|
|
@ -78,6 +78,13 @@ namespace CGAL {
|
||||||
{
|
{
|
||||||
return std::tuple<const I&, const I&>{this->first, this->second};
|
return std::tuple<const I&, const I&>{this->first, this->second};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <template<class...> class Container>
|
||||||
|
auto to() const
|
||||||
|
{
|
||||||
|
using V = std::remove_cv_t<std::remove_reference_t<decltype(*begin())>>;
|
||||||
|
return Container<V>(begin(), end());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|
|
||||||
|
|
@ -96,8 +96,10 @@ public:
|
||||||
|
|
||||||
// returns the dimension of the simplex
|
// returns the dimension of the simplex
|
||||||
int dimension () const {
|
int dimension () const {
|
||||||
return (ref & 3);
|
if(ref == -1) return -1;
|
||||||
|
else return (ref & 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns an incident cell:
|
// returns an incident cell:
|
||||||
Cell_handle incident_cell() {
|
Cell_handle incident_cell() {
|
||||||
return ch;
|
return ch;
|
||||||
|
|
@ -161,6 +163,7 @@ operator==(Triangulation_simplex_3<TriangulationDataStructure_3> s0,
|
||||||
typename Sim::Cell_handle neighbor;
|
typename Sim::Cell_handle neighbor;
|
||||||
|
|
||||||
switch (s0.dimension()) {
|
switch (s0.dimension()) {
|
||||||
|
case -1: return s1.dimension() == -1;
|
||||||
case (0): // Vertex
|
case (0): // Vertex
|
||||||
return (s0.ch->vertex(s0.index(0)) == s1.ch->vertex(s1.index(0)));
|
return (s0.ch->vertex(s0.index(0)) == s1.ch->vertex(s1.index(0)));
|
||||||
case (1): // Edge
|
case (1): // Edge
|
||||||
|
|
@ -180,7 +183,7 @@ operator==(Triangulation_simplex_3<TriangulationDataStructure_3> s0,
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
case (3):
|
case (3):
|
||||||
return (&(*s0.ch) == &(*s1.ch));
|
return s0.ch.operator->() == s1.ch.operator->();
|
||||||
}
|
}
|
||||||
CGAL_error();
|
CGAL_error();
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ Triangulation_segment_cell_iterator_3( const Tr* tr, Vertex_handle s, Vertex_han
|
||||||
if( c->has_vertex( _tr->infinite_vertex(), inf ) )
|
if( c->has_vertex( _tr->infinite_vertex(), inf ) )
|
||||||
c = c->neighbor(inf);
|
c = c->neighbor(inf);
|
||||||
|
|
||||||
_cur = Simplex( c, Tr::VERTEX, c->index(s), -1 );
|
_cur = Simplex{ c, Tr::VERTEX, c->index(s), -1 };
|
||||||
|
|
||||||
jump_to_intersecting_cell();
|
jump_to_intersecting_cell();
|
||||||
}
|
}
|
||||||
|
|
@ -62,7 +62,7 @@ Triangulation_segment_cell_iterator_3( const Tr* tr, Vertex_handle s, const Poin
|
||||||
if( c->has_vertex( _tr->infinite_vertex(), inf ) )
|
if( c->has_vertex( _tr->infinite_vertex(), inf ) )
|
||||||
c = c->neighbor(inf);
|
c = c->neighbor(inf);
|
||||||
|
|
||||||
_cur = Simplex( c, Tr::VERTEX, c->index(s), -1 );
|
_cur = Simplex{ c, Tr::VERTEX, c->index(s), -1 };
|
||||||
|
|
||||||
jump_to_intersecting_cell();
|
jump_to_intersecting_cell();
|
||||||
}
|
}
|
||||||
|
|
@ -124,7 +124,7 @@ template < class Tr, class Inc >
|
||||||
Triangulation_segment_cell_iterator_3<Tr,Inc>
|
Triangulation_segment_cell_iterator_3<Tr,Inc>
|
||||||
Triangulation_segment_cell_iterator_3<Tr,Inc>::end() const {
|
Triangulation_segment_cell_iterator_3<Tr,Inc>::end() const {
|
||||||
SCI sci(_tr);
|
SCI sci(_tr);
|
||||||
std::get<0>(sci._cur) = Cell_handle();
|
sci._cur.cell = Cell_handle();
|
||||||
return sci;
|
return sci;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -239,8 +239,9 @@ walk_to_next() {
|
||||||
int ti;
|
int ti;
|
||||||
if( cell()->has_vertex( _t_vertex, ti ) ) {
|
if( cell()->has_vertex( _t_vertex, ti ) ) {
|
||||||
// The target is inside the cell.
|
// The target is inside the cell.
|
||||||
_prev = Simplex( cell(), Tr::VERTEX, ti, -1 );
|
_prev = Simplex{ cell(), Tr::VERTEX, ti, -1 };
|
||||||
cell() = Cell_handle();
|
cell() = Cell_handle();
|
||||||
|
lt() = Locate_type::VERTEX;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -302,24 +303,24 @@ bool Triangulation_segment_cell_iterator_3<Tr, Inc>::
|
||||||
have_same_entry(const Simplex& s1, const Simplex& s2) const
|
have_same_entry(const Simplex& s1, const Simplex& s2) const
|
||||||
{
|
{
|
||||||
//type
|
//type
|
||||||
if (std::get<1>(s1) != std::get<1>(s2))
|
if (s1.lt != s2.lt)
|
||||||
return false;
|
return false;
|
||||||
switch (std::get<1>(s1))
|
switch (s1.lt)
|
||||||
{
|
{
|
||||||
case Locate_type::VERTEX:
|
case Locate_type::VERTEX:
|
||||||
return std::get<0>(s1)->vertex(std::get<2>(s1)) == std::get<0>(s2)->vertex(std::get<2>(s2));
|
return s1.cell->vertex(s1.li) == s2.cell->vertex(s2.li);
|
||||||
case Locate_type::EDGE:
|
case Locate_type::EDGE:
|
||||||
{
|
{
|
||||||
Vertex_handle v1a = std::get<0>(s1)->vertex(std::get<2>(s1));
|
Vertex_handle v1a = s1.cell->vertex(s1.li);
|
||||||
Vertex_handle v1b = std::get<0>(s1)->vertex(std::get<3>(s1));
|
Vertex_handle v1b = s1.cell->vertex(s1.lj);
|
||||||
Vertex_handle v2a = std::get<0>(s2)->vertex(std::get<2>(s2));
|
Vertex_handle v2a = s2.cell->vertex(s2.li);
|
||||||
Vertex_handle v2b = std::get<0>(s2)->vertex(std::get<3>(s2));
|
Vertex_handle v2b = s2.cell->vertex(s2.lj);
|
||||||
return (v1a == v2a && v1b == v2b)
|
return (v1a == v2a && v1b == v2b)
|
||||||
|| (v1a == v2b && v1b == v2a);
|
|| (v1a == v2b && v1b == v2a);
|
||||||
}
|
}
|
||||||
case Locate_type::FACET:
|
case Locate_type::FACET:
|
||||||
return triangulation()->are_equal(Facet(std::get<0>(s1), std::get<2>(s1)),
|
return triangulation()->are_equal(Facet(s1.cell, s1.li),
|
||||||
Facet(std::get<0>(s2), std::get<2>(s2)));
|
Facet(s2.cell, s2.li));
|
||||||
default:
|
default:
|
||||||
CGAL_assertion(false);
|
CGAL_assertion(false);
|
||||||
};
|
};
|
||||||
|
|
@ -332,305 +333,296 @@ std::pair<typename Triangulation_segment_cell_iterator_3<Tr, Inc>::Simplex,
|
||||||
Triangulation_segment_cell_iterator_3<Tr,Inc>::walk_to_next_3(const Simplex& prev,
|
Triangulation_segment_cell_iterator_3<Tr,Inc>::walk_to_next_3(const Simplex& prev,
|
||||||
const Simplex& cur) const
|
const Simplex& cur) const
|
||||||
{
|
{
|
||||||
std::array<const Point*, 4> vert
|
const auto cur_cell = cur.cell;
|
||||||
= {&(std::get<0>(cur)->vertex(0)->point()),
|
std::array<const Point*, 4> vert = {&(cur_cell->vertex(0)->point()), &(cur_cell->vertex(1)->point()),
|
||||||
&(std::get<0>(cur)->vertex(1)->point()),
|
&(cur_cell->vertex(2)->point()), &(cur_cell->vertex(3)->point())};
|
||||||
&(std::get<0>(cur)->vertex(2)->point()),
|
|
||||||
&(std::get<0>(cur)->vertex(3)->point()) };
|
|
||||||
|
|
||||||
int inside=0,outside=0,regular_case=0,degenerate=0;
|
int inside = 0, outside = 0, regular_case = 0, degenerate = 0;
|
||||||
Cell_handle nnext;
|
|
||||||
|
|
||||||
if (std::get<1>(cur) == Tr::FACET) {
|
if(cur.lt == Tr::FACET && prev.cell != Cell_handle()) {
|
||||||
|
// [source, target] entered the cell `cur` via a facet.
|
||||||
|
// Note that, if prev.cell == Cell_handle(), that means `source` is *on*
|
||||||
|
// the facet, and the block of this `if` cannot be applied.
|
||||||
|
Simplex prev_after_walk;
|
||||||
|
Simplex cur_after_walk;
|
||||||
|
|
||||||
|
auto case_target_is_inside_cur_cell = [&](int case_nb) {
|
||||||
|
inside = case_nb;
|
||||||
|
prev_after_walk = {cur_cell, Tr::CELL, -1, -1};
|
||||||
|
cur_after_walk = {{}, Tr::CELL, -1, -1};
|
||||||
|
};
|
||||||
|
auto case_segment_exits_cur_cell_by = [&](int facet_nb, Cell_handle nnext = {}) {
|
||||||
|
if(nnext == Cell_handle{}) {
|
||||||
|
nnext = cur_cell->neighbor(facet_nb);
|
||||||
|
}
|
||||||
|
outside = facet_nb;
|
||||||
|
prev_after_walk = {cur_cell, Tr::FACET, facet_nb, -1};
|
||||||
|
cur_after_walk = {nnext, Tr::FACET, nnext->index(cur_cell), -1};
|
||||||
|
};
|
||||||
regular_case = 1;
|
regular_case = 1;
|
||||||
int i = std::get<2>(cur);
|
const int i = cur.li;
|
||||||
int j0 = Tr::vertex_triple_index(i, 0);
|
const int j0 = Tr::vertex_triple_index(i, 0);
|
||||||
int j1 = Tr::vertex_triple_index(i, 1);
|
const int j1 = Tr::vertex_triple_index(i, 1);
|
||||||
int j2 = Tr::vertex_triple_index(i, 2);
|
const int j2 = Tr::vertex_triple_index(i, 2);
|
||||||
Orientation o0 = _tr->orientation(_source, *vert[i], *vert[j0], _target);
|
Orientation o0 = _tr->orientation(_source, *vert[i], *vert[j0], _target);
|
||||||
if (o0 == POSITIVE) {
|
if(o0 == POSITIVE) { // o0 > 0
|
||||||
Orientation o1 = _tr->orientation(_source, *vert[i], *vert[j1], _target);
|
Orientation o1 = _tr->orientation(_source, *vert[i], *vert[j1], _target);
|
||||||
if (o1 != POSITIVE) {
|
if(o1 != POSITIVE) { // o1 <= 0
|
||||||
if (_tr->orientation(*vert[i], *vert[j0], *vert[j1], _target) == POSITIVE) {
|
Orientation oi01 = _tr->orientation(*vert[i], *vert[j0], *vert[j1], _target);
|
||||||
nnext = std::get<0>(cur)->neighbor(j2);
|
if(oi01 == POSITIVE) {
|
||||||
outside = j2;
|
case_segment_exits_cur_cell_by(j2);
|
||||||
if (o1 == ZERO) degenerate = 1; //EDGE i j1
|
if(o1 == ZERO)
|
||||||
|
degenerate = 1; // EDGE i j1
|
||||||
|
} else { // o0 > 0, o1 <= 0, oi01 <= 0
|
||||||
|
case_target_is_inside_cur_cell(1);
|
||||||
|
if(oi01 == ZERO) { // on FACET j2 (i, j0, j1)
|
||||||
|
degenerate = 1;
|
||||||
|
} // end oi01 == ZERO
|
||||||
}
|
}
|
||||||
|
} // end o1 <= 0
|
||||||
else
|
else
|
||||||
inside = 1;
|
{ // o1 > 0
|
||||||
}
|
Orientation oi12 = _tr->orientation(*vert[i], *vert[j1], *vert[j2], _target);
|
||||||
else {
|
if(oi12 == POSITIVE) {
|
||||||
if (_tr->orientation(*vert[i], *vert[j1], *vert[j2], _target) == POSITIVE) {
|
case_segment_exits_cur_cell_by(j0);
|
||||||
nnext = std::get<0>(cur)->neighbor(j0);
|
} else { // o0 > 0, o1 > 0, oi12 <= 0
|
||||||
outside = j0;
|
case_target_is_inside_cur_cell(2);
|
||||||
}
|
if(oi12 == ZERO) { // on FACET j0 (i, j1, j2)
|
||||||
else
|
degenerate = 1;
|
||||||
inside = 2;
|
} // end oi12 == ZERO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (o0 == ZERO) {
|
} // end o0 > 0
|
||||||
|
else if(o0 == ZERO)
|
||||||
|
{
|
||||||
|
// target is on plane (source, vert[i], vert[j0])
|
||||||
Orientation o1 = _tr->orientation(_source, *vert[i], *vert[j1], _target);
|
Orientation o1 = _tr->orientation(_source, *vert[i], *vert[j1], _target);
|
||||||
if (o1 == NEGATIVE) {
|
if(o1 == NEGATIVE) {
|
||||||
if (_tr->orientation(*vert[i], *vert[j0], *vert[j1], _target) == POSITIVE) {
|
Orientation oi12 = _tr->orientation(*vert[i], *vert[j0], *vert[j1], _target);
|
||||||
nnext = std::get<0>(cur)->neighbor(j2); //EDGE i j0
|
if(oi12 == POSITIVE) {
|
||||||
degenerate = 2;
|
degenerate = 2;
|
||||||
outside = 44;
|
case_segment_exits_cur_cell_by(44, cur_cell->neighbor(j2)); // EDGE i j0
|
||||||
|
} else {
|
||||||
|
case_target_is_inside_cur_cell(3);
|
||||||
|
if(oi12 == ZERO) { // target is *on* EDGE i j0
|
||||||
|
degenerate = 1;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
inside = 3;
|
|
||||||
}
|
}
|
||||||
else if (o1 == ZERO) {
|
} else if(o1 == ZERO) {
|
||||||
if (_tr->orientation(*vert[i], *vert[j0], *vert[j2], _target) == POSITIVE)
|
// o0 == o1 == 0 -> target is on line source-vert[i]
|
||||||
inside = 55;
|
if(_tr->orientation(*vert[i], *vert[j0], *vert[j2], _target) == POSITIVE)
|
||||||
else
|
case_target_is_inside_cur_cell(55);
|
||||||
{
|
else {
|
||||||
nnext = std::get<0>(cur)->neighbor(j2); //VERTEX i
|
|
||||||
degenerate = 3;
|
degenerate = 3;
|
||||||
outside = 5;
|
case_segment_exits_cur_cell_by(5, cur_cell->neighbor(j2)); // VERTEX i
|
||||||
|
}
|
||||||
|
} else { // o0 == 0, o1 > 0
|
||||||
|
Orientation oi12 = _tr->orientation(*vert[i], *vert[j1], *vert[j2], _target);
|
||||||
|
if(oi12 == POSITIVE) {
|
||||||
|
case_segment_exits_cur_cell_by(j0);
|
||||||
|
} else {
|
||||||
|
case_target_is_inside_cur_cell(4);
|
||||||
|
if(oi12 == ZERO) { // on FACET j0 (i, j1, j2)
|
||||||
|
degenerate = 1;
|
||||||
|
} // end oi12 == ZERO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
} // end o0 == 0
|
||||||
if (_tr->orientation(*vert[i], *vert[j1], *vert[j2], _target) == POSITIVE) {
|
|
||||||
nnext = std::get<0>(cur)->neighbor(j0);
|
|
||||||
outside = j0;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
inside = 4;
|
{ // o0 < 0
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Orientation o2 = _tr->orientation(_source, *vert[i], *vert[j2], _target);
|
Orientation o2 = _tr->orientation(_source, *vert[i], *vert[j2], _target);
|
||||||
if (o2 != NEGATIVE) {
|
if(o2 != NEGATIVE) {
|
||||||
if (_tr->orientation(*vert[i], *vert[j2], *vert[j0], _target) == POSITIVE) {
|
// o2 >= 0
|
||||||
nnext = std::get<0>(cur)->neighbor(j1);
|
Orientation oi20 = _tr->orientation(*vert[i], *vert[j2], *vert[j0], _target);
|
||||||
outside = j1;
|
if(oi20 == POSITIVE) {
|
||||||
if (o2 == ZERO) degenerate = 4; // EDGE i j2
|
case_segment_exits_cur_cell_by(j1);
|
||||||
|
if(o2 == ZERO)
|
||||||
|
degenerate = 4; // EDGE i j2
|
||||||
|
} else {
|
||||||
|
case_target_is_inside_cur_cell(5);
|
||||||
|
if(oi20 == ZERO) { // on FACET j1 (i, j2, j0)
|
||||||
|
degenerate = 1;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
inside = 5;
|
|
||||||
}
|
}
|
||||||
else {
|
} else {
|
||||||
if (_tr->orientation(*vert[i], *vert[j1], *vert[j2], _target) == POSITIVE) {
|
Orientation oi12 = _tr->orientation(*vert[i], *vert[j1], *vert[j2], _target);
|
||||||
nnext = std::get<0>(cur)->neighbor(j0);
|
if(oi12 == POSITIVE) {
|
||||||
outside = j0;
|
case_segment_exits_cur_cell_by(j0);
|
||||||
|
} else {
|
||||||
|
case_target_is_inside_cur_cell(6);
|
||||||
|
if(oi12 == ZERO) { // on FACET j0 (i, j1, j2)
|
||||||
|
degenerate = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
inside = 6;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((!degenerate) && (!inside))
|
if(!degenerate) {
|
||||||
{
|
return {prev_after_walk, cur_after_walk};
|
||||||
Simplex prev_after_walk(std::get<0>(cur), Tr::FACET, outside, -1);
|
|
||||||
Simplex cur_after_walk( nnext, Tr::FACET, nnext->index(std::get<0>(cur)), -1);
|
|
||||||
return std::make_pair(prev_after_walk, cur_after_walk);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((!degenerate) && inside)
|
|
||||||
{
|
|
||||||
Simplex prev_after_walk(std::get<0>(cur), Tr::CELL, -1, -1);
|
|
||||||
Simplex cur_after_walk(Cell_handle(), Tr::OUTSIDE_AFFINE_HULL, -1, -1);
|
|
||||||
return std::make_pair(prev_after_walk, cur_after_walk);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// We check in which direction the target lies
|
// We check in which direction the target lies
|
||||||
// by comparing its position relative to the planes through the
|
// by comparing its position relative to the planes through the
|
||||||
// source and the edges of the cell.
|
// source and the edges of the cell.
|
||||||
Orientation o[6];
|
std::array<Orientation, 6> o;
|
||||||
Orientation op[4];
|
std::array<Orientation, 4> op;
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
// We keep track of which orientations are calculated.
|
// We keep track of which orientations are calculated.
|
||||||
bool calc[6] = { false, false, false, false, false, false };
|
bool calc[6] = {false, false, false, false, false, false};
|
||||||
|
|
||||||
if( std::get<1>(cur) == Tr::VERTEX ) {
|
if(cur.lt == Tr::VERTEX) {
|
||||||
// The three planes through the vertex are set to coplanar.
|
// The three planes through the vertex are set to coplanar.
|
||||||
for( int j = 0; j < 4; ++j ) {
|
for(int j = 0; j < 4; ++j) {
|
||||||
if( std::get<2>(cur) != j ) {
|
if(cur.li != j) {
|
||||||
int ij = edgeIndex( std::get<2>(cur), j );
|
int ij = edgeIndex(cur.li, j);
|
||||||
o[ij] = COPLANAR;
|
o[ij] = COPLANAR;
|
||||||
calc[ij] = true;
|
calc[ij] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if(cur.lt == Tr::EDGE) {
|
||||||
else if( std::get<1>(cur) == Tr::EDGE ) {
|
|
||||||
// The plane through the edge is set to coplanar.
|
// The plane through the edge is set to coplanar.
|
||||||
int ij = edgeIndex( std::get<2>(cur), std::get<3>(cur) );
|
int ij = edgeIndex(cur.li, cur.lj);
|
||||||
o[ij] = COPLANAR;
|
o[ij] = COPLANAR;
|
||||||
calc[ij] = true;
|
calc[ij] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For the remembering stochastic walk, we start trying with a random facet.
|
// For the remembering stochastic walk, we start trying with a random facet.
|
||||||
int li = 0;
|
CGAL_assertion_code(bool incell = true;)
|
||||||
CGAL_assertion_code( bool incell = true; )
|
|
||||||
for( int k = 0; k < 4; ++k, ++li )
|
for(int li = 0; li < 4; ++li)
|
||||||
{
|
{
|
||||||
// Skip the previous cell.
|
// Skip the previous cell.
|
||||||
Cell_handle next = std::get<0>(cur)->neighbor(li);
|
Cell_handle next = cur_cell->neighbor(li);
|
||||||
if( next == std::get<0>(prev) )
|
if(next == prev.cell) {
|
||||||
{
|
|
||||||
op[li] = POSITIVE;
|
op[li] = POSITIVE;
|
||||||
pos += li;
|
pos += li;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const Point* backup = vert[li];
|
const Point* const backup_vert_li = std::exchange(vert[li], &_target);
|
||||||
vert[li] = &_target;
|
|
||||||
|
|
||||||
// Check if the target is on the opposite side of the supporting plane.
|
// Check if the target is on the opposite side of the supporting plane.
|
||||||
op[li] = _tr->orientation( *vert[0], *vert[1], *vert[2], *vert[3] );
|
op[li] = _tr->orientation(*vert[0], *vert[1], *vert[2], *vert[3]);
|
||||||
if( op[li] == POSITIVE )
|
if(op[li] == POSITIVE)
|
||||||
pos += li;
|
pos += li;
|
||||||
if( op[li] != NEGATIVE ) {
|
if(op[li] != NEGATIVE) {
|
||||||
vert[li] = backup;
|
vert[li] = backup_vert_li;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
CGAL_assertion_code( incell = false; )
|
CGAL_assertion_code(incell = false;)
|
||||||
|
|
||||||
// Check if the target is inside the 3-wedge with
|
// Check if the target is inside the 3-wedge with
|
||||||
// the source as apex and the facet as an intersection.
|
// the source as apex and the facet as an intersection.
|
||||||
int lj = 0;
|
|
||||||
int Or = 0;
|
int Or = 0;
|
||||||
for( int l = 0; l < 4; ++l, ++lj ) {
|
for(int lj = 0; lj < 4; ++lj) {
|
||||||
if( li == lj )
|
if(li == lj)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// We check the orientation of the target compared to the plane
|
// We check the orientation of the target compared to the plane
|
||||||
// Through the source and the edge opposite of ij.
|
// Through the source and the edge opposite of ij.
|
||||||
int oij = 5 - edgeIndex( li, lj );
|
const int oij = 5 - edgeIndex(li, lj);
|
||||||
if( !calc[oij] ) {
|
if(!calc[oij]) {
|
||||||
const Point* backup2 = vert[lj];
|
const Point* const backup_vert_lj = std::exchange(vert[lj], &_source);
|
||||||
vert[lj] = &_source;
|
o[oij] = _tr->orientation(*vert[0], *vert[1], *vert[2], *vert[3]);
|
||||||
o[oij] = _tr->orientation( *vert[0], *vert[1], *vert[2], *vert[3] );
|
vert[lj] = backup_vert_lj;
|
||||||
vert[lj] = backup2;
|
|
||||||
calc[oij] = true;
|
calc[oij] = true;
|
||||||
}
|
}
|
||||||
|
if(o[oij] == POSITIVE) {
|
||||||
if( o[oij] == POSITIVE ) {
|
|
||||||
// The target is not inside the pyramid.
|
// The target is not inside the pyramid.
|
||||||
// Invert the planes.
|
// Invert the planes.
|
||||||
// This can be safely done because either
|
for(int j = 0; j < 4; ++j) {
|
||||||
// they were not calculated yet,
|
if(li == j)
|
||||||
// or they will no longer be used.
|
continue;
|
||||||
for( int j = 0; j < 4; ++j ) {
|
int oij = 5 - edgeIndex(li, j);
|
||||||
if( li == j ) continue;
|
if(calc[oij])
|
||||||
int oij = 5 - edgeIndex( li, j );
|
|
||||||
o[oij] = -o[oij];
|
o[oij] = -o[oij];
|
||||||
}
|
}
|
||||||
Or = 0;
|
Or = 0;
|
||||||
break;
|
break;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
Or -= o[oij];
|
Or -= o[oij];
|
||||||
}
|
}
|
||||||
|
|
||||||
if( Or == 0 ) {
|
if(Or == 0) {
|
||||||
// Either the target is not inside the pyramid,
|
// Either the target is not inside the pyramid,
|
||||||
// or the pyramid is degenerate.
|
// or the pyramid is degenerate.
|
||||||
vert[li] = backup;
|
vert[li] = backup_vert_li;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The target is inside the pyramid.
|
// The target is inside the pyramid.
|
||||||
|
switch(Or) {
|
||||||
Simplex prev_after_walk;
|
case 3: {
|
||||||
Simplex cur_after_walk;
|
if(regular_case) {
|
||||||
|
CGAL_assertion(li == outside);
|
||||||
std::get<0>(prev_after_walk) = std::get<0>(cur);
|
CGAL_assertion(!inside);
|
||||||
std::get<0>(cur_after_walk) = next;
|
}
|
||||||
switch( Or ) {
|
return {{cur_cell, Tr::FACET, li}, {next, Tr::FACET, next->index(cur_cell)}};
|
||||||
case 3:
|
}
|
||||||
std::get<1>(prev_after_walk) = Tr::FACET;
|
case 2: {
|
||||||
std::get<2>(prev_after_walk) = li;
|
|
||||||
std::get<1>(cur_after_walk) = Tr::FACET;
|
|
||||||
std::get<2>(cur_after_walk) = std::get<0>(cur_after_walk)->index(std::get<0>(prev_after_walk));
|
|
||||||
|
|
||||||
if(regular_case)
|
if(regular_case)
|
||||||
{
|
CGAL_assertion(degenerate);
|
||||||
CGAL_assertion( std::get<0>(cur_after_walk)==nnext );
|
for(int j = 0; j < 4; ++j) {
|
||||||
CGAL_assertion( li==outside );
|
if(li != j && o[5 - edgeIndex(li, j)] == COPLANAR) {
|
||||||
CGAL_assertion( ! inside );
|
Edge opp = opposite_edge(prev.cell, li, j);
|
||||||
}
|
return {
|
||||||
return std::make_pair(prev_after_walk, cur_after_walk);
|
{cur_cell, Tr::EDGE, opp.second, opp.third},
|
||||||
|
{next, Tr::EDGE, next->index(cur_cell->vertex(opp.second)), next->index(cur_cell->vertex(opp.third))}};
|
||||||
case 2:
|
|
||||||
if(regular_case)
|
|
||||||
CGAL_assertion(degenerate );
|
|
||||||
|
|
||||||
std::get<1>(prev_after_walk) = Tr::EDGE;
|
|
||||||
std::get<1>(cur_after_walk) = Tr::EDGE;
|
|
||||||
for( int j = 0; j < 4; ++j ) {
|
|
||||||
if( li != j && o[ 5 - edgeIndex(li, j) ] == COPLANAR) {
|
|
||||||
Edge opp = opposite_edge( std::get<0>(prev), li, j );
|
|
||||||
std::get<2>(prev_after_walk) = opp.second;
|
|
||||||
std::get<3>(prev_after_walk) = opp.third;
|
|
||||||
std::get<2>(cur_after_walk)
|
|
||||||
= std::get<0>(cur_after_walk)->index(
|
|
||||||
std::get<0>(prev_after_walk)->vertex( std::get<2>(prev_after_walk) ) );
|
|
||||||
std::get<3>(cur_after_walk)
|
|
||||||
= std::get<0>(cur_after_walk)->index(
|
|
||||||
std::get<0>(prev_after_walk)->vertex( std::get<3>(prev_after_walk) ) );
|
|
||||||
|
|
||||||
return std::make_pair(prev_after_walk, cur_after_walk);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CGAL_assertion( false );
|
CGAL_unreachable();
|
||||||
return std::make_pair(prev, cur);
|
return std::make_pair(prev, cur);
|
||||||
|
}
|
||||||
case 1:
|
case 1:
|
||||||
if(regular_case)
|
if(regular_case)
|
||||||
CGAL_assertion(degenerate );
|
CGAL_assertion(degenerate);
|
||||||
|
for(int j = 0; j < 4; ++j) {
|
||||||
std::get<1>(prev_after_walk) = Tr::VERTEX;
|
if(li != j && o[5 - edgeIndex(li, j)] == NEGATIVE) {
|
||||||
std::get<1>(cur_after_walk) = Tr::VERTEX;
|
return {{cur_cell, Tr::VERTEX, j}, {next, Tr::VERTEX, next->index(cur_cell->vertex(j))}};
|
||||||
for( int j = 0; j < 4; ++j ) {
|
|
||||||
if( li != j && o[ 5 - edgeIndex(li, j) ] == NEGATIVE ) {
|
|
||||||
std::get<2>(prev_after_walk) = j;
|
|
||||||
std::get<2>(cur_after_walk)
|
|
||||||
= std::get<0>(cur_after_walk)->index(
|
|
||||||
std::get<0>(prev_after_walk)->vertex(j) );
|
|
||||||
|
|
||||||
return std::make_pair(prev_after_walk, cur_after_walk);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CGAL_assertion( false );
|
CGAL_unreachable();
|
||||||
return std::make_pair(prev, cur);
|
return std::make_pair(prev, cur);
|
||||||
default:
|
default:
|
||||||
CGAL_assertion( false );
|
CGAL_unreachable();
|
||||||
return std::make_pair(prev, cur);
|
return std::make_pair(prev, cur);
|
||||||
}
|
}
|
||||||
|
CGAL_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
// The target lies inside this cell.
|
// The target lies inside this cell.
|
||||||
Simplex prev_after_walk;
|
|
||||||
CGAL_assertion( incell );
|
CGAL_assertion( incell );
|
||||||
|
return {
|
||||||
|
[&]() -> Simplex {
|
||||||
switch( op[0] + op[1] + op[2] + op[3] ) {
|
switch( op[0] + op[1] + op[2] + op[3] ) {
|
||||||
case 4:
|
case 4:
|
||||||
CGAL_assertion( pos == 6 );
|
CGAL_assertion( pos == 6 );
|
||||||
prev_after_walk = Simplex( std::get<0>(cur), Tr::CELL, -1, -1 );
|
|
||||||
CGAL_assertion( (! regular_case) || inside );
|
CGAL_assertion( (! regular_case) || inside );
|
||||||
|
return { cur_cell, Tr::CELL };
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
prev_after_walk = Simplex( std::get<0>(cur), Tr::FACET, 6-pos, -1 );
|
return { cur_cell, Tr::FACET, 6 - pos };
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if( pos < 3 )
|
if( pos < 3 ) // first is 0
|
||||||
prev_after_walk = Simplex( std::get<0>(cur), Tr::EDGE, 0, pos+1 );
|
return { cur_cell, Tr::EDGE, 0, pos };
|
||||||
else if( pos < 5 )
|
else if( pos < 5 ) { // could be (0, pos), or (1, pos-1)
|
||||||
prev_after_walk = Simplex( std::get<0>(cur), Tr::EDGE, 1, pos-1 );
|
if(op[0] == POSITIVE)
|
||||||
|
return { cur_cell, Tr::EDGE, 0, pos };
|
||||||
else
|
else
|
||||||
prev_after_walk = Simplex( std::get<0>(cur), Tr::EDGE, 2, 3 );
|
return { cur_cell, Tr::EDGE, 1, pos-1 };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return { cur_cell, Tr::EDGE, 2, 3 };
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
prev_after_walk = Simplex( std::get<0>(cur), Tr::VERTEX, pos, -1 );
|
return { cur_cell, Tr::VERTEX, pos };
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
prev_after_walk = Simplex( std::get<0>(cur), Tr::OUTSIDE_AFFINE_HULL, -1, -1 );
|
CGAL_unreachable();
|
||||||
CGAL_assertion( false );
|
|
||||||
}
|
}
|
||||||
|
}(),
|
||||||
Simplex cur_after_walk(Cell_handle(), Tr::OUTSIDE_AFFINE_HULL, -1, -1);
|
{ Cell_handle() }
|
||||||
return std::make_pair(prev_after_walk, cur_after_walk);
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
template < class Tr, class Inc >
|
template < class Tr, class Inc >
|
||||||
|
|
@ -643,7 +635,9 @@ walk_to_next_3_inf( int inf )
|
||||||
Cell_handle fin = cell()->neighbor(inf);
|
Cell_handle fin = cell()->neighbor(inf);
|
||||||
if( fin == prev_cell() ) {
|
if( fin == prev_cell() ) {
|
||||||
_prev = _cur;
|
_prev = _cur;
|
||||||
|
prev_lt() = Tr::CELL;
|
||||||
cell() = Cell_handle();
|
cell() = Cell_handle();
|
||||||
|
lt() = Tr::CELL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -658,7 +652,7 @@ walk_to_next_3_inf( int inf )
|
||||||
if( _tr->orientation( *vert[0], *vert[1], *vert[2], *vert[3] ) == POSITIVE ) {
|
if( _tr->orientation( *vert[0], *vert[1], *vert[2], *vert[3] ) == POSITIVE ) {
|
||||||
// The target lies in an infinite cell.
|
// The target lies in an infinite cell.
|
||||||
// Note that we do not traverse to other infinite cells.
|
// Note that we do not traverse to other infinite cells.
|
||||||
_prev = Simplex( cell(), Tr::OUTSIDE_CONVEX_HULL, -1, -1 );
|
_prev = Simplex{ cell(), Tr::OUTSIDE_CONVEX_HULL, -1, -1 };
|
||||||
cell() = Cell_handle();
|
cell() = Cell_handle();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -683,20 +677,20 @@ walk_to_next_3_inf( int inf )
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Point* backup = vert[li];
|
Point* backup_vert_li = vert[li];
|
||||||
vert[li] = &(_target);
|
vert[li] = &(_target);
|
||||||
o[li] = _tr->orientation( *vert[0], *vert[1], *vert[2], *vert[3] );
|
o[li] = _tr->orientation( *vert[0], *vert[1], *vert[2], *vert[3] );
|
||||||
|
|
||||||
if( o[li] != NEGATIVE ) {
|
if( o[li] != NEGATIVE ) {
|
||||||
vert[li] = backup;
|
vert[li] = backup_vert_li;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The target lies behind the plane through the source and two finite vertices.
|
// The target lies behind the plane through the source and two finite vertices.
|
||||||
// Traverse to the incident infinite cell.
|
// Traverse to the incident infinite cell.
|
||||||
CGAL_assertion( _tr->is_infinite( next ) );
|
CGAL_assertion( _tr->is_infinite( next ) );
|
||||||
_prev = Simplex( cell(), Tr::FACET, li, -1 );
|
_prev = Simplex{ cell(), Tr::FACET, li, -1 };
|
||||||
_cur = Simplex( next, Tr::FACET, next->index( prev_cell() ), -1 );
|
_cur = Simplex{ next, Tr::FACET, next->index(prev_cell()), -1 };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -725,7 +719,7 @@ walk_to_next_3_inf( int inf )
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CGAL_assertion( false );
|
CGAL_unreachable();
|
||||||
return;
|
return;
|
||||||
case 1:
|
case 1:
|
||||||
prev_lt() = Tr::VERTEX;
|
prev_lt() = Tr::VERTEX;
|
||||||
|
|
@ -737,10 +731,10 @@ walk_to_next_3_inf( int inf )
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CGAL_assertion( false );
|
CGAL_unreachable();
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
CGAL_assertion( false );
|
CGAL_unreachable();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -802,7 +796,7 @@ walk_to_next_2()
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
// The current vertex is the target.
|
// The current vertex is the target.
|
||||||
CGAL_assertion(false);
|
CGAL_unreachable();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -810,27 +804,26 @@ walk_to_next_2()
|
||||||
// The target lies in this cell.
|
// The target lies in this cell.
|
||||||
switch( ocw+occw+op ) {
|
switch( ocw+occw+op ) {
|
||||||
case 3:
|
case 3:
|
||||||
_prev = Simplex( cell(), Tr::FACET, 3, -1 );
|
_prev = Simplex{ cell(), Tr::FACET, 3, -1 };
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if( ocw == 0 )
|
if( ocw == 0 )
|
||||||
_prev = Simplex( cell(), Tr::EDGE, _tr->ccw(li()), -1 );
|
_prev = Simplex{ cell(), Tr::EDGE, _tr->ccw(li()), -1 };
|
||||||
else if( occw == 0 )
|
else if( occw == 0 )
|
||||||
_prev = Simplex( cell(), Tr::EDGE, _tr->cw(li()), -1 );
|
_prev = Simplex{ cell(), Tr::EDGE, _tr->cw(li()), -1 };
|
||||||
else
|
else
|
||||||
_prev = Simplex( cell(), Tr::EDGE, li(), -1 );
|
_prev = Simplex{ cell(), Tr::EDGE, li(), -1 };
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if( ocw == 1 )
|
if( ocw == 1 )
|
||||||
_prev = Simplex( cell(), Tr::VERTEX, _tr->ccw(li()), -1 );
|
_prev = Simplex{ cell(), Tr::VERTEX, _tr->ccw(li()), -1 };
|
||||||
else if( occw == 1 )
|
else if( occw == 1 )
|
||||||
_prev = Simplex( cell(), Tr::VERTEX, _tr->cw(li()), -1 );
|
_prev = Simplex{ cell(), Tr::VERTEX, _tr->cw(li()), -1 };
|
||||||
else
|
else
|
||||||
_prev = Simplex( cell(), Tr::VERTEX, li(), -1 );
|
_prev = Simplex{ cell(), Tr::VERTEX, li(), -1 };
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
CGAL_assertion(false);
|
CGAL_unreachable();
|
||||||
_prev = Simplex( cell(), Tr::OUTSIDE_AFFINE_HULL, -1, -1 );
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
cell() = Cell_handle();
|
cell() = Cell_handle();
|
||||||
|
|
@ -927,18 +920,18 @@ walk_to_next_2()
|
||||||
|
|
||||||
// The target lies in this cell.
|
// The target lies in this cell.
|
||||||
if( op == POSITIVE )
|
if( op == POSITIVE )
|
||||||
_prev = Simplex( cell(), Tr::FACET, 3, -1 );
|
_prev = Simplex{ cell(), Tr::FACET, 3, -1 };
|
||||||
else {
|
else {
|
||||||
CGAL_assertion( op == ZERO );
|
CGAL_assertion( op == ZERO );
|
||||||
switch( o ) {
|
switch( o ) {
|
||||||
case POSITIVE:
|
case POSITIVE:
|
||||||
_prev = Simplex( cell(), Tr::EDGE, li(), lk );
|
_prev = Simplex{ cell(), Tr::EDGE, li(), lk };
|
||||||
break;
|
break;
|
||||||
case NEGATIVE:
|
case NEGATIVE:
|
||||||
_prev = Simplex( cell(), Tr::EDGE, lj(), lk );
|
_prev = Simplex{ cell(), Tr::EDGE, lj(), lk };
|
||||||
break;
|
break;
|
||||||
case ZERO:
|
case ZERO:
|
||||||
_prev = Simplex( cell(), Tr::VERTEX, lk, -1 );
|
_prev = Simplex{ cell(), Tr::VERTEX, lk, -1 };
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -969,7 +962,7 @@ walk_to_next_2()
|
||||||
if( o[_tr->ccw(li)] == NEGATIVE )
|
if( o[_tr->ccw(li)] == NEGATIVE )
|
||||||
continue;
|
continue;
|
||||||
else if( op == COLLINEAR && o[_tr->ccw(li)] == COLLINEAR ) {
|
else if( op == COLLINEAR && o[_tr->ccw(li)] == COLLINEAR ) {
|
||||||
_prev = Simplex( cell(), Tr::VERTEX, _tr->ccw(li), -1 );
|
_prev = Simplex{ cell(), Tr::VERTEX, _tr->ccw(li), -1 };
|
||||||
cell() = Cell_handle();
|
cell() = Cell_handle();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -981,7 +974,7 @@ walk_to_next_2()
|
||||||
if( o[_tr->cw(li)] == POSITIVE )
|
if( o[_tr->cw(li)] == POSITIVE )
|
||||||
continue;
|
continue;
|
||||||
else if( op == COLLINEAR && o[_tr->cw(li)] == COLLINEAR ) {
|
else if( op == COLLINEAR && o[_tr->cw(li)] == COLLINEAR ) {
|
||||||
_prev = Simplex( cell(), Tr::VERTEX, _tr->cw(li), -1 );
|
_prev = Simplex{ cell(), Tr::VERTEX, _tr->cw(li), -1 };
|
||||||
cell() = Cell_handle();
|
cell() = Cell_handle();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1006,18 +999,18 @@ walk_to_next_2()
|
||||||
this->li() = cell()->index( prev_cell()->vertex( prev_li() ) );
|
this->li() = cell()->index( prev_cell()->vertex( prev_li() ) );
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
CGAL_assertion( false );
|
CGAL_unreachable();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The target lies in this cell.
|
// The target lies in this cell.
|
||||||
_prev = Simplex( cell(), Tr::FACET, 3, -1 );
|
_prev = Simplex{ cell(), Tr::FACET, 3, -1 };
|
||||||
cell() = Cell_handle();
|
cell() = Cell_handle();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
CGAL_assertion( false );
|
CGAL_unreachable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1046,8 +1039,8 @@ walk_to_next_2_inf( int inf )
|
||||||
_target );
|
_target );
|
||||||
if( occw == NEGATIVE ) {
|
if( occw == NEGATIVE ) {
|
||||||
Cell_handle tmp = cell()->neighbor(_tr->cw(inf));
|
Cell_handle tmp = cell()->neighbor(_tr->cw(inf));
|
||||||
_prev = Simplex( cell(), Tr::EDGE, _tr->ccw(inf), inf );
|
_prev = Simplex{ cell(), Tr::EDGE, _tr->ccw(inf), inf };
|
||||||
_cur = Simplex( tmp, Tr::EDGE, tmp->index( prev_cell()->vertex( prev_li() ) ), tmp->index( prev_cell()->vertex( prev_lj() ) ) );
|
_cur = Simplex{ tmp, Tr::EDGE, tmp->index(prev_cell()->vertex(prev_li())), tmp->index(prev_cell()->vertex(prev_lj())) };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Orientation ocw = coplanar_orientation( _source,
|
Orientation ocw = coplanar_orientation( _source,
|
||||||
|
|
@ -1056,8 +1049,8 @@ walk_to_next_2_inf( int inf )
|
||||||
_target );
|
_target );
|
||||||
if( ocw == NEGATIVE ) {
|
if( ocw == NEGATIVE ) {
|
||||||
Cell_handle tmp = cell()->neighbor(_tr->ccw(inf));
|
Cell_handle tmp = cell()->neighbor(_tr->ccw(inf));
|
||||||
_prev = Simplex( cell(), Tr::EDGE, _tr->cw(inf), inf );
|
_prev = Simplex{ cell(), Tr::EDGE, _tr->cw(inf), inf };
|
||||||
_cur = Simplex( tmp, Tr::EDGE, tmp->index( prev_cell()->vertex( prev_li() ) ), tmp->index( prev_cell()->vertex( prev_lj() ) ) );
|
_cur = Simplex{ tmp, Tr::EDGE, tmp->index(prev_cell()->vertex(prev_li())), tmp->index(prev_cell()->vertex(prev_lj())) };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Orientation op = coplanar_orientation(
|
Orientation op = coplanar_orientation(
|
||||||
|
|
@ -1067,35 +1060,35 @@ walk_to_next_2_inf( int inf )
|
||||||
switch( op ) {
|
switch( op ) {
|
||||||
case NEGATIVE:
|
case NEGATIVE:
|
||||||
if( occw == COLLINEAR ) {
|
if( occw == COLLINEAR ) {
|
||||||
_prev = Simplex( cell(), Tr::VERTEX, _tr->ccw(inf), -1 );
|
_prev = Simplex{ cell(), Tr::VERTEX, _tr->ccw(inf), -1 };
|
||||||
_cur = Simplex( fin, Tr::VERTEX, fin->index( prev_cell()->vertex( prev_li() ) ), -1 );
|
_cur = Simplex{ fin, Tr::VERTEX, fin->index(prev_cell()->vertex(prev_li())), -1 };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if( ocw == COLLINEAR ) {
|
if( ocw == COLLINEAR ) {
|
||||||
_prev = Simplex( cell(), Tr::VERTEX, _tr->cw(inf), -1 );
|
_prev = Simplex{ cell(), Tr::VERTEX, _tr->cw(inf), -1 };
|
||||||
_cur = Simplex( fin, Tr::VERTEX, fin->index( prev_cell()->vertex( prev_li() ) ), -1 );
|
_cur = Simplex{ fin, Tr::VERTEX, fin->index(prev_cell()->vertex(prev_li())), -1 };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_prev = Simplex( cell(), Tr::EDGE, _tr->ccw(inf), _tr->cw(inf) );
|
_prev = Simplex{ cell(), Tr::EDGE, _tr->ccw(inf), _tr->cw(inf) };
|
||||||
_cur = Simplex( fin, Tr::EDGE, fin->index( prev_cell()->vertex( prev_li() ) ), fin->index( prev_cell()->vertex( prev_lj() ) ) );
|
_cur = Simplex{ fin, Tr::EDGE, fin->index(prev_cell()->vertex(prev_li())), fin->index(prev_cell()->vertex(prev_lj())) };
|
||||||
return;
|
return;
|
||||||
case COLLINEAR:
|
case COLLINEAR:
|
||||||
if( occw == COLLINEAR ) {
|
if( occw == COLLINEAR ) {
|
||||||
_prev = Simplex( cell(), Tr::VERTEX, _tr->ccw(inf), -1 );
|
_prev = Simplex{ cell(), Tr::VERTEX, _tr->ccw(inf), -1 };
|
||||||
cell() = Cell_handle();
|
cell() = Cell_handle();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if( ocw == COLLINEAR ) {
|
if( ocw == COLLINEAR ) {
|
||||||
_prev = Simplex( cell(), Tr::VERTEX, _tr->cw(inf), -1 );
|
_prev = Simplex{ cell(), Tr::VERTEX, _tr->cw(inf), -1 };
|
||||||
cell() = Cell_handle();
|
cell() = Cell_handle();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_prev = Simplex( cell(), Tr::EDGE, _tr->ccw(inf), _tr->cw(inf) );
|
_prev = Simplex{ cell(), Tr::EDGE, _tr->ccw(inf), _tr->cw(inf) };
|
||||||
cell() = Cell_handle();
|
cell() = Cell_handle();
|
||||||
return;
|
return;
|
||||||
case POSITIVE:
|
case POSITIVE:
|
||||||
// The tarstd::std::get lies in this infinite cell.
|
// The tarstd::std::get lies in this infinite cell.
|
||||||
_prev = Simplex( cell(), Tr::OUTSIDE_CONVEX_HULL, -1, -1 );
|
_prev = Simplex{ cell(), Tr::OUTSIDE_CONVEX_HULL, -1, -1 };
|
||||||
cell() = Cell_handle();
|
cell() = Cell_handle();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1138,7 +1131,7 @@ Triangulation_segment_cell_iterator_3<Tr, Inc>::opposite_edge(
|
||||||
case 5: return Edge(c, 2, 3);
|
case 5: return Edge(c, 2, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
CGAL_assertion(false);
|
CGAL_unreachable();
|
||||||
return Edge();
|
return Edge();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <tuple>
|
|
||||||
|
|
||||||
#include <CGAL/assertions.h>
|
#include <CGAL/assertions.h>
|
||||||
#include <CGAL/Triangulation_utils_3.h>
|
#include <CGAL/Triangulation_utils_3.h>
|
||||||
|
|
@ -27,6 +26,7 @@
|
||||||
#include <CGAL/Triangulation_vertex_base_3.h>
|
#include <CGAL/Triangulation_vertex_base_3.h>
|
||||||
#include <CGAL/Triangulation_simplex_3.h>
|
#include <CGAL/Triangulation_simplex_3.h>
|
||||||
|
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
|
||||||
// If defined, type casting is done statically,
|
// If defined, type casting is done statically,
|
||||||
// reducing type-safety overhead.
|
// reducing type-safety overhead.
|
||||||
|
|
@ -113,7 +113,13 @@ public:
|
||||||
|
|
||||||
typedef typename Tr::Locate_type Locate_type; //< defines the simplex type returned from location.
|
typedef typename Tr::Locate_type Locate_type; //< defines the simplex type returned from location.
|
||||||
|
|
||||||
typedef std::tuple<Cell_handle,Locate_type,int,int> Simplex; //< defines the simplex type.
|
struct Simplex //< defines the simplex type
|
||||||
|
{
|
||||||
|
Cell_handle cell = {};
|
||||||
|
Locate_type lt = Locate_type::OUTSIDE_AFFINE_HULL;
|
||||||
|
int li = -1;
|
||||||
|
int lj = -1;
|
||||||
|
};
|
||||||
|
|
||||||
typedef Cell value_type; //< defines the value type the iterator refers to.
|
typedef Cell value_type; //< defines the value type the iterator refers to.
|
||||||
typedef Cell& reference; //< defines the reference type of the iterator.
|
typedef Cell& reference; //< defines the reference type of the iterator.
|
||||||
|
|
@ -127,6 +133,55 @@ public:
|
||||||
template < class Tr2, class Inc2 >
|
template < class Tr2, class Inc2 >
|
||||||
struct Rebind { typedef Triangulation_segment_cell_iterator_3<Tr2,Inc2> Other; };
|
struct Rebind { typedef Triangulation_segment_cell_iterator_3<Tr2,Inc2> Other; };
|
||||||
|
|
||||||
|
#if CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3
|
||||||
|
static auto display_vert(Vertex_handle v)
|
||||||
|
{
|
||||||
|
std::stringstream os;
|
||||||
|
os.precision(17);
|
||||||
|
if(v->time_stamp() == 0) {
|
||||||
|
os << "inf";
|
||||||
|
} else {
|
||||||
|
os << '#' << v->time_stamp() << "=(" << v->point() << ")";
|
||||||
|
}
|
||||||
|
return os.str();
|
||||||
|
};
|
||||||
|
|
||||||
|
static auto display_lt(Locate_type lt) {
|
||||||
|
std::stringstream os;
|
||||||
|
switch(lt) {
|
||||||
|
case Locate_type::VERTEX: os << " VERTEX"; break;
|
||||||
|
case Locate_type::EDGE: os << " EDGE"; break;
|
||||||
|
case Locate_type::FACET: os << " FACET"; break;
|
||||||
|
case Locate_type::CELL: os << " CELL"; break;
|
||||||
|
case Locate_type::OUTSIDE_CONVEX_HULL: os << " OUTSIDE_CONVEX_HULL"; break;
|
||||||
|
case Locate_type::OUTSIDE_AFFINE_HULL: os << " OUTSIDE_AFFINE_HULL"; break;
|
||||||
|
}
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
static auto debug_simplex(Simplex s) {
|
||||||
|
std::stringstream os;
|
||||||
|
os.precision(17);
|
||||||
|
const auto [c, lt, i, j] = s;
|
||||||
|
if(c == Cell_handle{}) {
|
||||||
|
os << "end()";
|
||||||
|
} else {
|
||||||
|
os << display_vert(c->vertex(0)) << " - " << display_vert(c->vertex(1)) << " - "
|
||||||
|
<< display_vert(c->vertex(2)) << " - " << display_vert(c->vertex(3));
|
||||||
|
os << display_lt(lt) << " " << i << " " << j;
|
||||||
|
}
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto debug_iterator() const
|
||||||
|
{
|
||||||
|
std::stringstream os;
|
||||||
|
os.precision(17);
|
||||||
|
os << " prev: " << debug_simplex(_prev) << "\n cur: " << debug_simplex(_cur);
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
#endif // CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef Segment_cell_iterator SCI;
|
typedef Segment_cell_iterator SCI;
|
||||||
|
|
||||||
|
|
@ -228,15 +283,17 @@ public:
|
||||||
*/
|
*/
|
||||||
const Point& target() const { return _target; }
|
const Point& target() const { return _target; }
|
||||||
|
|
||||||
|
Vertex_handle target_vertex() const { return _t_vertex; }
|
||||||
|
|
||||||
// gives a handle to the current cell.
|
// gives a handle to the current cell.
|
||||||
/* By invariance, this cell is intersected by the segment
|
/* By invariance, this cell is intersected by the segment
|
||||||
* between `source()` and `target()`.
|
* between `source()` and `target()`.
|
||||||
* \return a handle to the current cell.
|
* \return a handle to the current cell.
|
||||||
* \sa `cell()`.
|
* \sa `cell()`.
|
||||||
*/
|
*/
|
||||||
Cell_handle handle()
|
Cell_handle handle() const
|
||||||
{
|
{
|
||||||
return std::get<0>(_cur);
|
return _cur.cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
// gives the previous cell.
|
// gives the previous cell.
|
||||||
|
|
@ -257,7 +314,7 @@ public:
|
||||||
*/
|
*/
|
||||||
Cell* operator->()
|
Cell* operator->()
|
||||||
{
|
{
|
||||||
return &*std::get<0>(_cur);
|
return &*(_cur.cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
// provides an indirection operator.
|
// provides an indirection operator.
|
||||||
|
|
@ -265,7 +322,7 @@ public:
|
||||||
*/
|
*/
|
||||||
Cell& operator*()
|
Cell& operator*()
|
||||||
{
|
{
|
||||||
return *std::get<0>(_cur);
|
return *(_cur.cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
// provides a conversion operator.
|
// provides a conversion operator.
|
||||||
|
|
@ -273,7 +330,7 @@ public:
|
||||||
*/
|
*/
|
||||||
operator Cell_handle() const
|
operator Cell_handle() const
|
||||||
{
|
{
|
||||||
return std::get<0>(_cur);
|
return _cur.cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
// provides a conversion operator.
|
// provides a conversion operator.
|
||||||
|
|
@ -299,6 +356,10 @@ public:
|
||||||
{
|
{
|
||||||
lt = this->lt(); li = this->li(); lj = this->lj();
|
lt = this->lt(); li = this->li(); lj = this->lj();
|
||||||
}
|
}
|
||||||
|
std::tuple<Locate_type, int, int> entry() const
|
||||||
|
{
|
||||||
|
return { lt(), li(), lj() };
|
||||||
|
}
|
||||||
// gives the simplex through which the previous cell was exited.
|
// gives the simplex through which the previous cell was exited.
|
||||||
/* \pre the current cell is not the initial cell.
|
/* \pre the current cell is not the initial cell.
|
||||||
*/
|
*/
|
||||||
|
|
@ -306,6 +367,10 @@ public:
|
||||||
{
|
{
|
||||||
lt = prev_lt(); li = prev_li(); lj = prev_lj();
|
lt = prev_lt(); li = prev_li(); lj = prev_lj();
|
||||||
}
|
}
|
||||||
|
std::tuple<Locate_type, int, int> exit() const
|
||||||
|
{
|
||||||
|
return { prev_lt(), prev_li(), prev_lj() };
|
||||||
|
}
|
||||||
|
|
||||||
// gives the past-the-end iterator associated with this iterator.
|
// gives the past-the-end iterator associated with this iterator.
|
||||||
SCI end() const;
|
SCI end() const;
|
||||||
|
|
@ -364,7 +429,7 @@ public:
|
||||||
*/
|
*/
|
||||||
bool operator==( const Cell_handle& ch ) const
|
bool operator==( const Cell_handle& ch ) const
|
||||||
{
|
{
|
||||||
return ch == std::get<0>(_cur);
|
return ch == _cur.cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
// compares the current cell with `ch`.
|
// compares the current cell with `ch`.
|
||||||
|
|
@ -375,7 +440,7 @@ public:
|
||||||
*/
|
*/
|
||||||
bool operator!=( const Cell_handle& ch ) const
|
bool operator!=( const Cell_handle& ch ) const
|
||||||
{
|
{
|
||||||
return ch != std::get<0>(_cur);
|
return ch != _cur.cell;
|
||||||
}
|
}
|
||||||
// \}
|
// \}
|
||||||
|
|
||||||
|
|
@ -439,32 +504,33 @@ private:
|
||||||
Edge opposite_edge(Cell_handle c, int li, int lj) const;
|
Edge opposite_edge(Cell_handle c, int li, int lj) const;
|
||||||
Edge opposite_edge(const Edge& e) const;
|
Edge opposite_edge(const Edge& e) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
// ref-accessors to the simplex, for use in internal code
|
// ref-accessors to the simplex, for use in internal code
|
||||||
// access _cur
|
// access _cur
|
||||||
Cell_handle& cell() { return std::get<0>(_cur); }
|
Cell_handle& cell() { return _cur.cell; }
|
||||||
Cell_handle const& cell() const { return std::get<0>(_cur); }
|
Cell_handle const& cell() const { return _cur.cell; }
|
||||||
|
|
||||||
Locate_type& lt() { return std::get<1>(_cur); }
|
Locate_type& lt() { return _cur.lt; }
|
||||||
Locate_type const& lt() const { return std::get<1>(_cur); }
|
Locate_type const& lt() const { return _cur.lt; }
|
||||||
|
|
||||||
int& li() { return std::get<2>(_cur); }
|
int& li() { return _cur.li; }
|
||||||
int const& li() const { return std::get<2>(_cur); }
|
int const& li() const { return _cur.li; }
|
||||||
|
|
||||||
int& lj() { return std::get<3>(_cur); }
|
int& lj() { return _cur.lj; }
|
||||||
int const& lj() const { return std::get<3>(_cur); }
|
int const& lj() const { return _cur.lj; }
|
||||||
|
|
||||||
// access _prev
|
// access _prev
|
||||||
Cell_handle& prev_cell() { return std::get<0>(_prev); }
|
Cell_handle& prev_cell() { return _prev.cell; }
|
||||||
Cell_handle const& prev_cell() const { return std::get<0>(_prev); }
|
Cell_handle const& prev_cell() const { return _prev.cell; }
|
||||||
|
|
||||||
Locate_type& prev_lt() { return std::get<1>(_prev); }
|
Locate_type& prev_lt() { return _prev.lt; }
|
||||||
Locate_type const& prev_lt() const { return std::get<1>(_prev); }
|
Locate_type const& prev_lt() const { return _prev.lt; }
|
||||||
|
|
||||||
int& prev_li() { return std::get<2>(_prev); }
|
int& prev_li() { return _prev.li; }
|
||||||
int const& prev_li() const { return std::get<2>(_prev); }
|
int const& prev_li() const { return _prev.li; }
|
||||||
|
|
||||||
int& prev_lj() { return std::get<3>(_prev); }
|
int& prev_lj() { return _prev.lj; }
|
||||||
int const& prev_lj() const { return std::get<3>(_prev); }
|
int const& prev_lj() const { return _prev.lj; }
|
||||||
|
|
||||||
}; // class Triangulation_segment_cell_iterator_3
|
}; // class Triangulation_segment_cell_iterator_3
|
||||||
|
|
||||||
|
|
@ -572,7 +638,7 @@ public:
|
||||||
const Point& source() const { return _cell_iterator.source(); }
|
const Point& source() const { return _cell_iterator.source(); }
|
||||||
const Point& target() const { return _cell_iterator.target(); }
|
const Point& target() const { return _cell_iterator.target(); }
|
||||||
|
|
||||||
const Tr* triangulation() const { return _cell_iterator.triangulation(); }
|
const Tr& triangulation() const { return *_cell_iterator.triangulation(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Triangulation_segment_simplex_iterator_3
|
Triangulation_segment_simplex_iterator_3
|
||||||
|
|
@ -584,20 +650,23 @@ private:
|
||||||
private:
|
private:
|
||||||
void set_curr_simplex_to_entry()
|
void set_curr_simplex_to_entry()
|
||||||
{
|
{
|
||||||
|
#if CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3
|
||||||
|
std::cerr << "cell iterator is:\n" << _cell_iterator.debug_iterator() << std::endl;
|
||||||
|
#endif // #if CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3
|
||||||
|
|
||||||
Locate_type lt;
|
Locate_type lt;
|
||||||
int li, lj;
|
int li, lj;
|
||||||
Cell_handle cell;
|
Cell_handle cell = Cell_handle(_cell_iterator);
|
||||||
|
|
||||||
//check what is the entry type of _cell_iterator
|
//check what is the entry type of _cell_iterator
|
||||||
if (Cell_handle(_cell_iterator) == Cell_handle())
|
if (cell == Cell_handle())
|
||||||
{
|
{
|
||||||
//where did the segment std::get out from previous cell
|
//where did the segment get out from previous cell
|
||||||
cell = _cell_iterator.previous();
|
cell = _cell_iterator.previous();
|
||||||
_cell_iterator.exit(lt, li, lj);
|
_cell_iterator.exit(lt, li, lj);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cell = Cell_handle(_cell_iterator);
|
|
||||||
_cell_iterator.entry(lt, li, lj);
|
_cell_iterator.entry(lt, li, lj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -623,7 +692,7 @@ private:
|
||||||
_curr_simplex = cell;
|
_curr_simplex = cell;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
CGAL_assertion(false);
|
CGAL_unreachable();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -637,282 +706,145 @@ public:
|
||||||
// provides the increment postfix operator.
|
// provides the increment postfix operator.
|
||||||
Simplex_iterator& operator++()
|
Simplex_iterator& operator++()
|
||||||
{
|
{
|
||||||
|
auto increment_cell_iterator = [&]() {
|
||||||
|
++_cell_iterator;
|
||||||
|
#if CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3
|
||||||
|
std::cerr << "increment cell iterator to:\n" << _cell_iterator.debug_iterator() << '\n';
|
||||||
|
#endif
|
||||||
|
};
|
||||||
CGAL_assertion(_curr_simplex.incident_cell() != Cell_handle());
|
CGAL_assertion(_curr_simplex.incident_cell() != Cell_handle());
|
||||||
|
|
||||||
switch(_curr_simplex.dimension())
|
if(!cell_iterator_is_ahead()) {
|
||||||
{
|
increment_cell_iterator(); // cell_iterator needs to be ahead
|
||||||
case 3 :/*Cell_handle*/
|
}
|
||||||
{
|
|
||||||
Cell_handle ch = Cell_handle(_cell_iterator);
|
Cell_handle ch_next = Cell_handle(_cell_iterator);
|
||||||
if (ch == Cell_handle())
|
Cell_handle ch_prev = _cell_iterator.previous();
|
||||||
{
|
Locate_type lt_prev;
|
||||||
if(!triangulation()->is_infinite(Cell_handle(_curr_simplex)))
|
int li_prev, lj_prev;
|
||||||
|
_cell_iterator.exit(lt_prev, li_prev, lj_prev);
|
||||||
|
|
||||||
|
if(_curr_simplex.dimension() == 3) {
|
||||||
set_curr_simplex_to_entry();
|
set_curr_simplex_to_entry();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
if(lt_prev == Locate_type::CELL ||
|
||||||
|
lt_prev == Locate_type::OUTSIDE_CONVEX_HULL ||
|
||||||
|
lt_prev == Locate_type::OUTSIDE_AFFINE_HULL)
|
||||||
|
{
|
||||||
|
CGAL_assertion(ch_next == Cell_handle());
|
||||||
|
_curr_simplex = ch_prev;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(_curr_simplex.dimension()) {
|
||||||
|
case 2: { /*Facet*/
|
||||||
|
CGAL_assertion((ch_next == Cell_handle()) == (_cell_iterator == _cell_iterator.end()));
|
||||||
|
|
||||||
|
switch(lt_prev) {
|
||||||
|
case Locate_type::VERTEX: { // facet-cell?-vertex-outside
|
||||||
|
Vertex_handle v_prev{ch_prev->vertex(li_prev)};
|
||||||
|
if(facet_has_vertex(get_facet(), v_prev))
|
||||||
|
_curr_simplex = v_prev;
|
||||||
else
|
else
|
||||||
|
_curr_simplex = ch_prev;
|
||||||
|
} break;
|
||||||
|
case Locate_type::EDGE: { // facet-cell?-edge-outside
|
||||||
|
Edge edge_prev{ch_prev, li_prev, lj_prev};
|
||||||
|
if(facet_has_edge(get_facet(), edge_prev))
|
||||||
|
_curr_simplex = edge_prev;
|
||||||
|
else
|
||||||
|
_curr_simplex = ch_prev;
|
||||||
|
} break;
|
||||||
|
case Locate_type::FACET: { // facet-cell-facet-outside
|
||||||
|
Facet f_prev{ch_prev, li_prev};
|
||||||
|
if(is_same_facet(f_prev, get_facet())) {
|
||||||
|
if(ch_next == Cell_handle())
|
||||||
_curr_simplex = Simplex_3();
|
_curr_simplex = Simplex_3();
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
_curr_simplex = ch_next;
|
||||||
if (!cell_iterator_is_ahead())
|
} else
|
||||||
++_cell_iterator;
|
_curr_simplex = ch_prev;
|
||||||
set_curr_simplex_to_entry();
|
} break;
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2 :/*Facet*/
|
|
||||||
{
|
|
||||||
Cell_handle ch = Cell_handle(_cell_iterator);
|
|
||||||
if (!cell_iterator_is_ahead())
|
|
||||||
{
|
|
||||||
//cell_iterator is not ahead. get_facet() is part of cell_iterator
|
|
||||||
//we cannot be in any of the degenerate cases, only detected by
|
|
||||||
//taking cell_iterator one step forward
|
|
||||||
CGAL_assertion(cell_has_facet(Cell_handle(_cell_iterator), get_facet()));
|
|
||||||
++_cell_iterator;
|
|
||||||
if (Cell_handle(_cell_iterator) == Cell_handle())
|
|
||||||
{
|
|
||||||
_curr_simplex = _cell_iterator.previous();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ch = _cell_iterator.previous();
|
|
||||||
|
|
||||||
Cell_handle chnext = Cell_handle(_cell_iterator);
|
|
||||||
Locate_type ltnext;
|
|
||||||
int linext, ljnext;
|
|
||||||
_cell_iterator.entry(ltnext, linext, ljnext);
|
|
||||||
switch (ltnext)//entry simplex in next cell
|
|
||||||
{
|
|
||||||
case Locate_type::VERTEX:
|
|
||||||
{
|
|
||||||
if (_cell_iterator == _cell_iterator.end())
|
|
||||||
{
|
|
||||||
_curr_simplex = Simplex_3();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
//if the entry vertex is a vertex of current facet
|
|
||||||
int i;
|
|
||||||
if (triangulation()->has_vertex(get_facet(), chnext->vertex(linext), i))
|
|
||||||
set_curr_simplex_to_entry();
|
|
||||||
else
|
|
||||||
_curr_simplex = ch;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Locate_type::EDGE:
|
|
||||||
if (facet_has_edge(get_facet(), Edge(chnext, linext, ljnext)))
|
|
||||||
set_curr_simplex_to_entry();
|
|
||||||
else
|
|
||||||
_curr_simplex = ch;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Locate_type::FACET:
|
|
||||||
_curr_simplex = ch;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Locate_type::OUTSIDE_AFFINE_HULL:
|
|
||||||
_curr_simplex = Simplex_3();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
CGAL_assertion(false);
|
CGAL_unreachable();
|
||||||
};
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case 1:/*Edge*/
|
} break;
|
||||||
{
|
case 1: {/*Edge*/
|
||||||
Cell_handle ch = Cell_handle(_cell_iterator);
|
switch(lt_prev) {
|
||||||
if (ch == _cell_iterator.previous())
|
case Locate_type::VERTEX: { //edge-vertex-outside
|
||||||
{
|
Vertex_handle v_prev{ch_prev->vertex(li_prev)};
|
||||||
|
if(edge_has_vertex(get_edge(), v_prev))
|
||||||
|
_curr_simplex = v_prev;
|
||||||
|
else
|
||||||
|
_curr_simplex = shared_facet(get_edge(), v_prev);
|
||||||
|
} break;
|
||||||
|
case Locate_type::EDGE: { //edge-outside or edge-cell-edge-outside
|
||||||
|
const Edge e_prev(ch_prev, li_prev, lj_prev);
|
||||||
|
if(is_same_edge(get_edge(), e_prev)) {
|
||||||
|
if(ch_next == Cell_handle()) {
|
||||||
_curr_simplex = Simplex_3();
|
_curr_simplex = Simplex_3();
|
||||||
break;
|
} else {
|
||||||
|
_curr_simplex = ch_next;
|
||||||
}
|
}
|
||||||
Locate_type lt;
|
} else {
|
||||||
int li, lj;
|
auto facet_opt = shared_facet(get_edge(), e_prev);
|
||||||
_cell_iterator.entry(lt, li, lj);
|
if(static_cast<bool>(facet_opt)) {
|
||||||
|
_curr_simplex = *facet_opt;
|
||||||
if (!cell_iterator_is_ahead())
|
}
|
||||||
{
|
else {
|
||||||
++_cell_iterator;//cell_iterator needs to be ahead to detect degeneracies
|
_curr_simplex = shared_cell(get_edge(), e_prev);
|
||||||
if (Cell_handle(_cell_iterator) == Cell_handle())
|
|
||||||
{
|
|
||||||
_curr_simplex = _cell_iterator.previous();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} break;
|
||||||
Cell_handle chnext = Cell_handle(_cell_iterator);
|
case Locate_type::FACET: {
|
||||||
Locate_type ltnext;
|
Facet f_prev{ch_prev, li_prev};
|
||||||
int linext, ljnext;
|
if(facet_has_edge(f_prev, get_edge()))
|
||||||
_cell_iterator.entry(ltnext, linext, ljnext);
|
_curr_simplex = f_prev; //edge-facet-outside
|
||||||
switch (ltnext)//entry simplex in next cell
|
|
||||||
{
|
|
||||||
case Locate_type::VERTEX:
|
|
||||||
if (edge_has_vertex(get_edge(), chnext->vertex(linext)))
|
|
||||||
_curr_simplex = chnext->vertex(linext);
|
|
||||||
else
|
else
|
||||||
_curr_simplex = shared_facet(get_edge(), chnext->vertex(linext));
|
_curr_simplex = ch_prev; //query goes through the cell
|
||||||
break;
|
} break;
|
||||||
|
|
||||||
case Locate_type::EDGE:
|
|
||||||
{
|
|
||||||
CGAL_assertion(_cell_iterator == _cell_iterator.end()
|
|
||||||
|| triangulation()->is_infinite(chnext)
|
|
||||||
|| _curr_simplex != Simplex_3(Edge(chnext, linext, ljnext)));
|
|
||||||
|
|
||||||
if (_cell_iterator == _cell_iterator.end())
|
|
||||||
_curr_simplex = Simplex_3();
|
|
||||||
else if (triangulation()->is_infinite(chnext)
|
|
||||||
&& _curr_simplex == Simplex_3(Edge(chnext, linext, ljnext)))
|
|
||||||
_curr_simplex = chnext;
|
|
||||||
else
|
|
||||||
_curr_simplex = shared_facet(get_edge(), Edge(chnext, linext, ljnext));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Locate_type::FACET:
|
|
||||||
_curr_simplex = Cell_handle(_cell_iterator);//query goes through the cell
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Locate_type::OUTSIDE_AFFINE_HULL:
|
|
||||||
{
|
|
||||||
Cell_handle chprev = _cell_iterator.previous();
|
|
||||||
Locate_type ltprev;
|
|
||||||
int liprev, ljprev;
|
|
||||||
_cell_iterator.exit(ltprev, liprev, ljprev);
|
|
||||||
|
|
||||||
if (ltprev == Locate_type::VERTEX) //edge-vertex-outside
|
|
||||||
_curr_simplex = chprev->vertex(liprev);
|
|
||||||
else
|
|
||||||
_curr_simplex = Simplex_3(); //edge-outside
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
CGAL_assertion(false);//should not happen
|
CGAL_unreachable();
|
||||||
};
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
} break;
|
||||||
case 0 :/*Vertex_handle*/
|
case 0 :/*Vertex_handle*/
|
||||||
{
|
{
|
||||||
Cell_handle ch = Cell_handle(_cell_iterator);
|
switch(lt_prev) {
|
||||||
if (ch == _cell_iterator.previous())
|
case Locate_type::VERTEX: {
|
||||||
{
|
if(ch_prev->vertex(li_prev) != get_vertex()) // avoid infinite loop edge-vertex-same edge-...
|
||||||
|
_curr_simplex = Edge(ch_prev, li_prev, ch_prev->index(get_vertex()));
|
||||||
|
else {
|
||||||
|
if(ch_next == Cell_handle()) {
|
||||||
_curr_simplex = Simplex_3();
|
_curr_simplex = Simplex_3();
|
||||||
break;
|
} else {
|
||||||
|
_curr_simplex = ch_next;
|
||||||
}
|
}
|
||||||
if (!cell_iterator_is_ahead()) //_curr_simplex does contain v
|
|
||||||
{
|
|
||||||
++_cell_iterator;//cell_iterator needs to be ahead to detect degeneracies
|
|
||||||
}
|
}
|
||||||
|
} break;
|
||||||
|
case Locate_type::EDGE: {
|
||||||
|
const Edge e_prev(ch_prev, li_prev, lj_prev);
|
||||||
|
if(edge_has_vertex(e_prev, get_vertex()))
|
||||||
|
_curr_simplex = e_prev;
|
||||||
else
|
else
|
||||||
ch = _cell_iterator.previous();
|
_curr_simplex = shared_facet(Edge(ch_prev, li_prev, lj_prev), get_vertex());
|
||||||
|
} break;
|
||||||
Cell_handle chnext = Cell_handle(_cell_iterator);
|
case Locate_type::FACET: {
|
||||||
//_cell_iterator is one step forward _curr_simplex
|
if(ch_prev->vertex(li_prev) != get_vertex()) // vertex-facet-outside
|
||||||
CGAL_assertion(ch != chnext);
|
_curr_simplex = Facet(ch_prev, li_prev);
|
||||||
|
else // vertex-cell-facet-outside
|
||||||
Locate_type ltnext;
|
_curr_simplex = ch_prev;
|
||||||
int linext, ljnext;
|
} break;
|
||||||
_cell_iterator.entry(ltnext, linext, ljnext);
|
|
||||||
|
|
||||||
Cell_handle prev;
|
|
||||||
Locate_type ltprev;
|
|
||||||
int liprev, ljprev;
|
|
||||||
prev = _cell_iterator.previous();
|
|
||||||
_cell_iterator.exit(ltprev, liprev, ljprev);
|
|
||||||
|
|
||||||
switch (ltnext)
|
|
||||||
{
|
|
||||||
case Locate_type::VERTEX:
|
|
||||||
{
|
|
||||||
CGAL_assertion(_cell_iterator == _cell_iterator.end()
|
|
||||||
|| get_vertex() != chnext->vertex(linext)
|
|
||||||
|| triangulation()->is_infinite(chnext));
|
|
||||||
if (_cell_iterator == _cell_iterator.end())
|
|
||||||
{
|
|
||||||
if (prev == ch && ltprev == Locate_type::VERTEX)
|
|
||||||
{
|
|
||||||
CGAL_assertion(prev->vertex(liprev) == get_vertex());
|
|
||||||
_curr_simplex = ch;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(ltprev == Locate_type::FACET)
|
|
||||||
_curr_simplex = Facet(prev, liprev);
|
|
||||||
else if(ltprev == Locate_type::EDGE)
|
|
||||||
_curr_simplex = Edge(prev, liprev, ljprev);
|
|
||||||
else
|
|
||||||
CGAL_assertion(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (triangulation()->is_infinite(chnext) && get_vertex() == chnext->vertex(linext))
|
|
||||||
_curr_simplex = chnext;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Cell_handle ec;
|
|
||||||
int ei = -1, ej = -1;
|
|
||||||
if (!triangulation()->is_edge(get_vertex(), chnext->vertex(linext), ec, ei, ej))
|
|
||||||
CGAL_assertion(false);
|
|
||||||
_curr_simplex = Edge(ec, ei, ej);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Locate_type::EDGE:
|
|
||||||
{
|
|
||||||
//facet shared by get_vertex() and the edge
|
|
||||||
//none of ch and chnext is certainly shared by both endpoints
|
|
||||||
_curr_simplex = shared_facet(Edge(chnext, linext, ljnext), get_vertex());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Locate_type::OUTSIDE_AFFINE_HULL:
|
|
||||||
{
|
|
||||||
CGAL_assertion(_cell_iterator == _cell_iterator.end());
|
|
||||||
if (ltprev == Locate_type::VERTEX) //vertex-edge-vertex-outside
|
|
||||||
{
|
|
||||||
if(prev->vertex(liprev) != get_vertex())//avoid infinite loop edge-vertex-same edge-...
|
|
||||||
_curr_simplex = Edge(prev, liprev, prev->index(get_vertex()));
|
|
||||||
else
|
|
||||||
_curr_simplex = Simplex_3();
|
|
||||||
}
|
|
||||||
else if (ltprev == Locate_type::EDGE)//vertex-facet-edge-outside
|
|
||||||
_curr_simplex = Facet(prev, prev->index(get_vertex()));
|
|
||||||
else if (ltprev == Locate_type::FACET) //vertex-facet-outside
|
|
||||||
{
|
|
||||||
if(prev->vertex(liprev) != get_vertex()) //vertex-facet-outside
|
|
||||||
_curr_simplex = Facet(prev, liprev);
|
|
||||||
else //vertex-cell-facet-outside
|
|
||||||
_curr_simplex = prev;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CGAL_assertion(ltprev == Locate_type::CELL);//vertex-cell-outside
|
|
||||||
_curr_simplex = prev;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default://FACET
|
|
||||||
if (chnext == Cell_handle())
|
|
||||||
_curr_simplex = Simplex_3();
|
|
||||||
else
|
|
||||||
_curr_simplex = shared_cell(Facet(chnext, linext), get_vertex());
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
CGAL_assertion(false);
|
CGAL_unreachable();
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
CGAL_unreachable();
|
||||||
};
|
};
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// provides the increment prefix operator.
|
// provides the increment prefix operator.
|
||||||
Simplex_iterator operator++(int)
|
Simplex_iterator operator++(int)
|
||||||
{
|
{
|
||||||
|
|
@ -1010,10 +942,10 @@ private:
|
||||||
case 3 ://cell
|
case 3 ://cell
|
||||||
return ch != get_cell();
|
return ch != get_cell();
|
||||||
default:
|
default:
|
||||||
CGAL_assertion(false);
|
CGAL_unreachable();
|
||||||
}
|
}
|
||||||
//should not be reached
|
//should not be reached
|
||||||
CGAL_assertion(false);
|
CGAL_unreachable();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1048,13 +980,29 @@ private:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool facet_has_vertex(const Facet& f, const Vertex_handle v) const
|
||||||
|
{
|
||||||
|
return triangulation().tds().has_vertex(f, v);
|
||||||
|
}
|
||||||
|
|
||||||
bool edge_has_vertex(const Edge& e, const Vertex_handle v) const
|
bool edge_has_vertex(const Edge& e, const Vertex_handle v) const
|
||||||
{
|
{
|
||||||
return e.first->vertex(e.second) == v
|
return e.first->vertex(e.second) == v
|
||||||
|| e.first->vertex(e.third) == v;
|
|| e.first->vertex(e.third) == v;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vertex_handle shared_vertex(const Edge& e1, const Edge& e2) const
|
bool is_same_edge(const Edge& e1, const Edge& e2) const
|
||||||
|
{
|
||||||
|
return edge_has_vertex(e1, e2.first->vertex(e2.second))
|
||||||
|
&& edge_has_vertex(e1, e2.first->vertex(e2.third));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_same_facet(const Facet& f1, const Facet& f2) const
|
||||||
|
{
|
||||||
|
return f1 == f2 || triangulation().mirror_facet(f1) == f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::optional<Vertex_handle> shared_vertex(const Edge& e1, const Edge& e2) const
|
||||||
{
|
{
|
||||||
Vertex_handle v1a = e1.first->vertex(e1.second);
|
Vertex_handle v1a = e1.first->vertex(e1.second);
|
||||||
Vertex_handle v1b = e1.first->vertex(e1.third);
|
Vertex_handle v1b = e1.first->vertex(e1.third);
|
||||||
|
|
@ -1065,22 +1013,22 @@ private:
|
||||||
return v1a;
|
return v1a;
|
||||||
else if (v1b == v2a || v1b == v2b)
|
else if (v1b == v2a || v1b == v2b)
|
||||||
return v1b;
|
return v1b;
|
||||||
|
else
|
||||||
std::cerr << "There is no vertex shared by e1 and e2" << std::endl;
|
return {};
|
||||||
CGAL_assertion(false);
|
|
||||||
return Vertex_handle();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Facet shared_facet(const Edge& e1, const Edge& e2) const
|
boost::optional<Facet> shared_facet(const Edge& e1, const Edge& e2) const
|
||||||
{
|
{
|
||||||
Vertex_handle v2a = e2.first->vertex(e2.second);
|
Vertex_handle v2a = e2.first->vertex(e2.second);
|
||||||
Vertex_handle v2b = e2.first->vertex(e2.third);
|
Vertex_handle v2b = e2.first->vertex(e2.third);
|
||||||
|
|
||||||
Vertex_handle sv = shared_vertex(e1, e2);
|
auto sv_opt = shared_vertex(e1, e2);
|
||||||
|
if(!sv_opt) return {};
|
||||||
|
Vertex_handle sv = *sv_opt;
|
||||||
Vertex_handle nsv2 = (sv == v2a) ? v2b : v2a;
|
Vertex_handle nsv2 = (sv == v2a) ? v2b : v2a;
|
||||||
|
|
||||||
typename Tr::Facet_circulator circ
|
typename Tr::Facet_circulator circ
|
||||||
= triangulation()->incident_facets(e1);
|
= triangulation().incident_facets(e1);
|
||||||
typename Tr::Facet_circulator end = circ;
|
typename Tr::Facet_circulator end = circ;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
|
@ -1092,33 +1040,30 @@ private:
|
||||||
}
|
}
|
||||||
} while (++circ != end);
|
} while (++circ != end);
|
||||||
|
|
||||||
std::cerr << "There is no facet shared by e1 and e2" << std::endl;
|
return {};
|
||||||
CGAL_assertion(false);
|
|
||||||
return Facet(Cell_handle(), 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Facet shared_facet(const Edge& e, const Vertex_handle v) const
|
Facet shared_facet(const Edge& e, const Vertex_handle v) const
|
||||||
{
|
{
|
||||||
typename Tr::Facet_circulator circ
|
typename Tr::Facet_circulator circ
|
||||||
= triangulation()->incident_facets(e);
|
= triangulation().incident_facets(e);
|
||||||
typename Tr::Facet_circulator end = circ;
|
typename Tr::Facet_circulator end = circ;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
Facet f = *circ;
|
Facet f = *circ;
|
||||||
int i;
|
if (facet_has_vertex(f, v))
|
||||||
if (triangulation()->has_vertex(f, v, i))
|
|
||||||
return f;
|
return f;
|
||||||
} while (++circ != end);
|
} while (++circ != end);
|
||||||
|
|
||||||
std::cerr << "There is no facet shared by e and v" << std::endl;
|
std::cerr << "There is no facet shared by e and v" << std::endl;
|
||||||
CGAL_assertion(false);
|
CGAL_unreachable();
|
||||||
return Facet(Cell_handle(), 0);
|
return Facet(Cell_handle(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Cell_handle shared_cell(const Edge& e, const Vertex_handle v) const
|
Cell_handle shared_cell(const Edge& e, const Vertex_handle v) const
|
||||||
{
|
{
|
||||||
typename Tr::Cell_circulator circ
|
typename Tr::Cell_circulator circ
|
||||||
= triangulation()->incident_cells(e);
|
= triangulation().incident_cells(e);
|
||||||
typename Tr::Cell_circulator end = circ;
|
typename Tr::Cell_circulator end = circ;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
|
@ -1128,7 +1073,7 @@ private:
|
||||||
} while (++circ != end);
|
} while (++circ != end);
|
||||||
|
|
||||||
std::cerr << "There is no cell shared by e and v" << std::endl;
|
std::cerr << "There is no cell shared by e and v" << std::endl;
|
||||||
CGAL_assertion(false);
|
CGAL_unreachable();
|
||||||
return Cell_handle();
|
return Cell_handle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1145,6 +1090,11 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Cell_handle shared_cell(const Edge e1, const Edge e2) const {
|
||||||
|
auto facet = shared_facet(e1, e2.first->vertex(e2.second));
|
||||||
|
return shared_cell(facet, e2.first->vertex(e2.third));
|
||||||
|
}
|
||||||
|
|
||||||
};//class Triangulation_segment_simplex_iterator_3
|
};//class Triangulation_segment_simplex_iterator_3
|
||||||
|
|
||||||
} // namespace CGAL
|
} // namespace CGAL
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,14 @@ create_single_source_cgal_program("test_simplex_3.cpp")
|
||||||
create_single_source_cgal_program("test_simplex_iterator_3.cpp" )
|
create_single_source_cgal_program("test_simplex_iterator_3.cpp" )
|
||||||
create_single_source_cgal_program("test_segment_cell_traverser_3.cpp" )
|
create_single_source_cgal_program("test_segment_cell_traverser_3.cpp" )
|
||||||
create_single_source_cgal_program("test_segment_simplex_traverser_3.cpp" )
|
create_single_source_cgal_program("test_segment_simplex_traverser_3.cpp" )
|
||||||
|
if(cxx_std_17 IN_LIST CMAKE_CXX_COMPILE_FEATURES)
|
||||||
|
target_compile_features(test_segment_simplex_traverser_3 PRIVATE cxx_std_17)
|
||||||
|
else()
|
||||||
|
message(
|
||||||
|
STATUS
|
||||||
|
"NOTICE: test_segment_simplex_traverser_3.cpp requires C++17 and will not be compiled."
|
||||||
|
)
|
||||||
|
endif()
|
||||||
create_single_source_cgal_program("test_static_filters.cpp")
|
create_single_source_cgal_program("test_static_filters.cpp")
|
||||||
create_single_source_cgal_program("test_triangulation_3.cpp")
|
create_single_source_cgal_program("test_triangulation_3.cpp")
|
||||||
create_single_source_cgal_program("test_io_triangulation_3.cpp")
|
create_single_source_cgal_program("test_io_triangulation_3.cpp")
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
|
//#define CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3 1
|
||||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||||
#include <CGAL/Delaunay_triangulation_3.h>
|
#include <CGAL/Delaunay_triangulation_3.h>
|
||||||
|
#include <CGAL/Base_with_time_stamp.h>
|
||||||
|
#include <CGAL/IO/io.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
@ -15,18 +18,400 @@
|
||||||
// Define the kernel.
|
// Define the kernel.
|
||||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||||
typedef Kernel::Point_3 Point_3;
|
typedef Kernel::Point_3 Point_3;
|
||||||
|
typedef Kernel::Segment_3 Segment_3;
|
||||||
|
typedef Kernel::Triangle_3 Triangle_3;
|
||||||
|
typedef Kernel::Tetrahedron_3 Tetrahedron_3;
|
||||||
|
|
||||||
// Define the structure.
|
// Define the structure.
|
||||||
typedef CGAL::Delaunay_triangulation_3<Kernel> DT;
|
typedef CGAL::Base_with_time_stamp<CGAL::Triangulation_vertex_base_3<Kernel>> Vb;
|
||||||
|
typedef CGAL::Delaunay_triangulation_cell_base_3<Kernel> Cb;
|
||||||
|
typedef CGAL::Triangulation_data_structure_3<Vb, Cb> Tds;
|
||||||
|
typedef CGAL::Delaunay_triangulation_3<Kernel, Tds> DT;
|
||||||
typedef DT::Cell_handle Cell_handle;
|
typedef DT::Cell_handle Cell_handle;
|
||||||
|
typedef DT::Edge Edge;
|
||||||
|
typedef DT::Facet Facet;
|
||||||
|
typedef DT::Vertex_handle Vertex_handle;
|
||||||
|
typedef DT::Simplex Simplex;
|
||||||
typedef DT::Segment_simplex_iterator Segment_simplex_iterator;
|
typedef DT::Segment_simplex_iterator Segment_simplex_iterator;
|
||||||
|
|
||||||
|
#include "test_triangulation_simplex_3_debug.h"
|
||||||
|
|
||||||
|
// a function to insert without spatial sorting
|
||||||
|
template <typename Point_it>
|
||||||
|
void insert(DT& dt, Point_it first, Point_it end) {
|
||||||
|
for(; first != end; ++first) {
|
||||||
|
dt.insert(*first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const std::vector<Point_3> bbox_points =
|
||||||
|
{
|
||||||
|
{ -10.1, -10, -10.08 },
|
||||||
|
{ -10.2, 10, -10.07 },
|
||||||
|
{ 10.3, 10, -10.06 },
|
||||||
|
{ 10.4, -10, -10.05 },
|
||||||
|
{ -10.5, -10, 10.04 },
|
||||||
|
{ -10.6, 10, 10.03 },
|
||||||
|
{ 10.7, 10, 10.02 },
|
||||||
|
{ 10.8, -10, 10.01 },
|
||||||
|
};
|
||||||
|
|
||||||
|
DT dt;
|
||||||
|
std::string result_string;
|
||||||
|
|
||||||
|
bool reverse_sort_vertex_handles(Vertex_handle v1, Vertex_handle v2) {
|
||||||
|
return v1.operator->() > v2.operator->();
|
||||||
|
};
|
||||||
|
|
||||||
|
auto vertices_of_simplex(Simplex simplex) -> std::array<Vertex_handle, 4> {
|
||||||
|
std::array<Vertex_handle, 4> vertices = { Vertex_handle{}, Vertex_handle{}, Vertex_handle{}, Vertex_handle{} };
|
||||||
|
switch(simplex.dimension()) {
|
||||||
|
case 0: {
|
||||||
|
vertices[0] = static_cast<Vertex_handle>(simplex);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1: {
|
||||||
|
const auto [c, index1, index2] = static_cast<Edge>(simplex);
|
||||||
|
vertices[0] = c->vertex(index1);
|
||||||
|
vertices[1] = c->vertex(index2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
const auto [c, index] = static_cast<Facet>(simplex);
|
||||||
|
vertices[0] = c->vertex(DT::vertex_triple_index(index, 0));
|
||||||
|
vertices[1] = c->vertex(DT::vertex_triple_index(index, 1));
|
||||||
|
vertices[2] = c->vertex(DT::vertex_triple_index(index, 2));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3: {
|
||||||
|
const auto c = static_cast<Cell_handle>(simplex);
|
||||||
|
vertices[0] = c->vertex(0);
|
||||||
|
vertices[1] = c->vertex(1);
|
||||||
|
vertices[2] = c->vertex(2);
|
||||||
|
vertices[3] = c->vertex(3);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: CGAL_unreachable();
|
||||||
|
}
|
||||||
|
std::sort(vertices.begin(), vertices.end(), reverse_sort_vertex_handles);
|
||||||
|
for(int i = 0; i < 4; ++i) {
|
||||||
|
assert((i <= simplex.dimension()) == (vertices[i] != Vertex_handle{}));
|
||||||
|
}
|
||||||
|
return vertices;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::variant<Point_3, Segment_3, Triangle_3, Tetrahedron_3> get_simplex_geometry(Simplex simplex) {
|
||||||
|
switch(simplex.dimension()) {
|
||||||
|
case 0: {
|
||||||
|
return static_cast<Vertex_handle>(simplex)->point();
|
||||||
|
}
|
||||||
|
case 1: {
|
||||||
|
const auto [c, index1, index2] = static_cast<Edge>(simplex);
|
||||||
|
return Segment_3(c->vertex(index1)->point(), c->vertex(index2)->point());
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
const auto [c, index] = static_cast<Facet>(simplex);
|
||||||
|
return Triangle_3(c->vertex(DT::vertex_triple_index(index, 0))->point(),
|
||||||
|
c->vertex(DT::vertex_triple_index(index, 1))->point(),
|
||||||
|
c->vertex(DT::vertex_triple_index(index, 2))->point());
|
||||||
|
}
|
||||||
|
case 3: {
|
||||||
|
const auto c = static_cast<Cell_handle>(simplex);
|
||||||
|
return Tetrahedron_3(c->vertex(0)->point(),
|
||||||
|
c->vertex(1)->point(),
|
||||||
|
c->vertex(2)->point(),
|
||||||
|
c->vertex(3)->point());
|
||||||
|
}
|
||||||
|
default: CGAL_unreachable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void visit_simplex(Point_3 a, Point_3 b, Simplex s, std::optional<Simplex> previous_simplex_optional) {
|
||||||
|
auto d = s.dimension();
|
||||||
|
if(3 == d && dt.is_infinite(static_cast<Cell_handle>(s))) {
|
||||||
|
result_string += 'I';
|
||||||
|
} else {
|
||||||
|
result_string += std::to_string(d);
|
||||||
|
}
|
||||||
|
std::clog << debug_simplex(s) << '\n';
|
||||||
|
const bool does_intersect_ab = (3 == d && dt.is_infinite(static_cast<Cell_handle>(s))) ||
|
||||||
|
std::visit(
|
||||||
|
[&](auto geometry) { return CGAL::do_intersect(Segment_3(a, b), geometry); },
|
||||||
|
get_simplex_geometry(s));
|
||||||
|
if(!does_intersect_ab) {
|
||||||
|
CGAL_error_msg("the simplex does not intersect the query segment");
|
||||||
|
}
|
||||||
|
if(previous_simplex_optional) {
|
||||||
|
// this block checks that consecutive simplices are incident
|
||||||
|
using Set = std::array<Vertex_handle, 4>;
|
||||||
|
Set prev_vertices = vertices_of_simplex(*previous_simplex_optional);
|
||||||
|
Set s_vertices = vertices_of_simplex(s);
|
||||||
|
if(previous_simplex_optional->dimension() < s.dimension()) {
|
||||||
|
std::swap(prev_vertices, s_vertices);
|
||||||
|
std::swap(*previous_simplex_optional, s);
|
||||||
|
}
|
||||||
|
if(!std::includes(
|
||||||
|
prev_vertices.begin(), prev_vertices.begin() + 1 + previous_simplex_optional->dimension(),
|
||||||
|
s_vertices.begin(), s_vertices.begin() + 1 + s.dimension(),
|
||||||
|
reverse_sort_vertex_handles))
|
||||||
|
{
|
||||||
|
CGAL_error_msg("consecutive simplices are not incident");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
bool test_vfefv(bool with_bbox = false)
|
||||||
|
{
|
||||||
|
std::cerr << "## test_vfefv(" << std::boolalpha << with_bbox << ")\n";
|
||||||
|
result_string.clear();
|
||||||
|
static const std::vector<Point_3> points =
|
||||||
|
{
|
||||||
|
{ -1, 0, 0 },
|
||||||
|
{ 0, 1, 0 },
|
||||||
|
{ 0, -1, 0 },
|
||||||
|
{ 5, 0, 0 },
|
||||||
|
{ 6, 2, 2 },
|
||||||
|
{ 6, -2, -2 },
|
||||||
|
};
|
||||||
|
|
||||||
|
dt.clear();
|
||||||
|
insert(dt, points.begin(), points.end());
|
||||||
|
if(with_bbox) insert(dt, bbox_points.begin(), bbox_points.end());
|
||||||
|
|
||||||
|
const auto v = dt.finite_vertex_handles().to<std::vector>();
|
||||||
|
|
||||||
|
Cell_handle c; int i, j, k;
|
||||||
|
assert(dt.is_facet(v[0], v[1], v[2], c, i, j, k));
|
||||||
|
assert(dt.is_facet(v[1], v[2], v[3], c, i, j, k));
|
||||||
|
assert(dt.is_cell (v[1], v[2], v[3], v[4], c));
|
||||||
|
assert(dt.is_cell (v[1], v[2], v[3], v[5], c));
|
||||||
|
|
||||||
|
std::optional<Simplex> previous{};
|
||||||
|
for(auto s: dt.segment_traverser_simplices(v[0], v[3])) {
|
||||||
|
visit_simplex(points[0], points[3], s, previous);
|
||||||
|
previous = s;
|
||||||
|
}
|
||||||
|
static const std::string expected_result_string = "02120";
|
||||||
|
bool ok = (result_string == expected_result_string);
|
||||||
|
if(!ok) {
|
||||||
|
std::cerr << "test_vfefv failed\n";
|
||||||
|
std::cerr << " result_string is " << result_string << " instead of "
|
||||||
|
<< expected_result_string << '\n';
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool test_a_simple_tetrahedron(const std::vector<Point_3>& points) {
|
||||||
|
|
||||||
|
DT dt2;
|
||||||
|
for(const auto& p: points) dt2.insert(p);
|
||||||
|
|
||||||
|
bool ok = true;
|
||||||
|
auto test = [&](Point_3 a, Point_3 b, std::string expected_result) {
|
||||||
|
// This test function calls `do_test` with four configurations:
|
||||||
|
// - with [ab] and [ba],
|
||||||
|
// - and with or without a bbox around the central tetrahedron.
|
||||||
|
dt = dt2;
|
||||||
|
auto do_with_or_without_bbox = [&](Point_3 a, Point_3 b, bool with_bbox, std::string expected_result) {
|
||||||
|
auto do_it = [&](auto from, auto to) {
|
||||||
|
bool exception_thrown = false;
|
||||||
|
result_string.clear();
|
||||||
|
try {
|
||||||
|
std::optional<Simplex> previous_simplex;
|
||||||
|
for(auto s: dt.segment_traverser_simplices(from, to)) {
|
||||||
|
visit_simplex(a, b, s, previous_simplex);
|
||||||
|
previous_simplex = s;
|
||||||
|
}
|
||||||
|
} catch(const CGAL::Assertion_exception& e) {
|
||||||
|
CGAL::get_static_warning_handler()("Assertion", e.expression().c_str(),
|
||||||
|
e.filename().c_str(),
|
||||||
|
e.line_number(),
|
||||||
|
e.message().c_str());
|
||||||
|
exception_thrown = true;
|
||||||
|
}
|
||||||
|
if(result_string != expected_result || exception_thrown) {
|
||||||
|
std::cerr << "test_a_simple_tetrahedron failed on case " << expected_result
|
||||||
|
<< (with_bbox ? " with bbox\n" : "\n");
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
if(result_string != expected_result) {
|
||||||
|
std::cerr << " result_string is " << result_string << " instead of "
|
||||||
|
<< expected_result << '\n';
|
||||||
|
}
|
||||||
|
if(exception_thrown) {
|
||||||
|
std::cerr << " exception thrown\n";
|
||||||
|
}
|
||||||
|
}; // end do_it
|
||||||
|
|
||||||
|
std::clog << "### Case " << expected_result;
|
||||||
|
if(with_bbox) std::clog << " with bbox";
|
||||||
|
std::clog << '\n';
|
||||||
|
std::clog << "from (" << a << ") to (" << b << ")\n";
|
||||||
|
do_it(a, b);
|
||||||
|
|
||||||
|
// then re-test using vertex handles, if possible
|
||||||
|
Vertex_handle va{};
|
||||||
|
Vertex_handle vb{};
|
||||||
|
DT::Locate_type lt;
|
||||||
|
int i, j;
|
||||||
|
auto c = dt.locate(a, lt, i, j);
|
||||||
|
if(lt == DT::VERTEX) va = c->vertex(i);
|
||||||
|
c = dt.locate(b, lt, i, j);
|
||||||
|
if(lt == DT::VERTEX) vb = c->vertex(i);
|
||||||
|
if(va != Vertex_handle{} && vb != Vertex_handle{}) {
|
||||||
|
std::clog << "from vertex" << display_vert(va) << " to vertex" << display_vert(vb) << ")\n";
|
||||||
|
do_it(va, vb);
|
||||||
|
};
|
||||||
|
}; // end do_with_or_without_bbox
|
||||||
|
std::string expected_result_reversed{expected_result.rbegin(), expected_result.rend()};
|
||||||
|
do_with_or_without_bbox(a, b, false, expected_result);
|
||||||
|
do_with_or_without_bbox(b, a, false, expected_result_reversed);
|
||||||
|
std::replace(expected_result.begin(), expected_result.end(), 'I', '3');
|
||||||
|
std::replace(expected_result_reversed.begin(), expected_result_reversed.end(), 'I', '3');
|
||||||
|
insert(dt, bbox_points.begin(), bbox_points.end());
|
||||||
|
do_with_or_without_bbox(a, b, true, expected_result);
|
||||||
|
do_with_or_without_bbox(b, a, true, expected_result_reversed);
|
||||||
|
}; // end test() lambda
|
||||||
|
|
||||||
|
// [010] queries entering by a vertex and exiting by the other vertex of an incident edge,
|
||||||
|
// on the line (x,0,0)
|
||||||
|
test({ 0, 0, 0}, {.5, 0, 0}, "01");
|
||||||
|
test({ 0, 0, 0}, { 1, 0, 0}, "010");
|
||||||
|
test({ 0, 0, 0}, { 2, 0, 0}, "010I");
|
||||||
|
test({-1, 0, 0}, { 2, 0, 0}, "I010I");
|
||||||
|
test({-1, 0, 0}, { 1, 0, 0}, "I010");
|
||||||
|
test({-1, 0, 0}, {.5, 0, 0}, "I01");
|
||||||
|
|
||||||
|
// x [020] is not possible, because that would have passed through the edge -> see [010]
|
||||||
|
|
||||||
|
// [021] queries entering by a vertex and exiting by the opposite edge of a same face,
|
||||||
|
// on the line (x,x,0) (y==x)
|
||||||
|
test({ 0, 0, 0}, {.2, .2, 0}, "02");
|
||||||
|
test({ 0, 0, 0}, {.5, .5, 0}, "021");
|
||||||
|
test({ 0, 0, 0}, { 1, 1, 0}, "021I");
|
||||||
|
test({-1, -1, 0}, { 1, 1, 0}, "I021I");
|
||||||
|
test({-1, -1, 0}, {.5, .5, 0}, "I021");
|
||||||
|
test({-1, -1, 0}, {.2, .2, 0}, "I02");
|
||||||
|
|
||||||
|
// x [030] (entering by a vertex and exiting by a non-adjacent vertex) is not possible
|
||||||
|
// because that would have passed by the common edge -> see [010]
|
||||||
|
|
||||||
|
// x [031] (entering by a vertex and exiting by a non-incident edge), is not possible
|
||||||
|
// because that would have passed by the face -> see [021]
|
||||||
|
|
||||||
|
// [032] queries entering by a vertex and exiting by the opposite facet,
|
||||||
|
// on the line x==y==0.25-0.25z
|
||||||
|
test({ 0, 0, 1}, { .25, .25, .25 }, "03");
|
||||||
|
test({ 0, 0, 1}, { .25, .25, 0 }, "032");
|
||||||
|
test({ 0, 0, 1}, { .5, .5, -.1 }, "032I");
|
||||||
|
test({-.25,-.25, 2}, { .28125, .28125, -.125}, "I032I");
|
||||||
|
test({-.25,-.25, 2}, { .25, .25, 0 }, "I032");
|
||||||
|
test({-.25,-.25, 2}, { .125, .125, .5 }, "I03");
|
||||||
|
|
||||||
|
// [121] queries entering by an edge and exiting by an edge of the same face,
|
||||||
|
// on the line (x,.5,0)
|
||||||
|
test({0, .5, 0}, {.2, .5, 0}, "12");
|
||||||
|
test({0, .5, 0}, {.5 , .5, 0}, "121");
|
||||||
|
test({0, .5, 0}, {.6 , .5, 0}, "121I");
|
||||||
|
test({-.1, .5, 0}, {.6 , .5, 0}, "I121I");
|
||||||
|
test({-.1, .5, 0}, {.5 , .5, 0}, "I121");
|
||||||
|
test({-.1, .5, 0}, {.25, .5, 0}, "I12");
|
||||||
|
|
||||||
|
// x [130] (entering by an edge and exiting by a non-incident vertex) is not possible
|
||||||
|
// because that would have passed by the common face -> see [120] ([021] in reverse)
|
||||||
|
|
||||||
|
// [131] entering by an edge and exiting by the opposite edge in the cell,
|
||||||
|
// on the line x==y==0.5-z, also known as (.5-z, .5-z, z)
|
||||||
|
test({ 0, 0, .5 }, { .25, .25, .25 }, "13");
|
||||||
|
test({ 0, 0, .5 }, { .5, .5, 0 }, "131");
|
||||||
|
test({ 0, 0, .5 }, { .625, .625, -.125}, "131I");
|
||||||
|
test({ -.125, -.125, .625}, { .625, .625, -.125}, "I131I");
|
||||||
|
test({ -.125, -.125, .625}, { .5 , .5 , 0 }, "I131");
|
||||||
|
test({ -.125, -.125, .625}, { .25, .25, .25 }, "I13");
|
||||||
|
|
||||||
|
// [132] queries entering by an edge and exiting by a facet, on the line (x, .25-x, x)
|
||||||
|
test({ 0, .25, 0}, { .20, .05, .20}, "13");
|
||||||
|
test({ 0, .25, 0}, { .25, 0, .25}, "132");
|
||||||
|
test({ 0, .25, 0}, { .5 ,-.25, .5 }, "132I");
|
||||||
|
test({-.5, .75,-.5}, { .5 ,-.25, .5 }, "I132I");
|
||||||
|
test({-.5, .75,-.5}, { .25, 0, .25}, "I132");
|
||||||
|
test({-.5, .75,-.5}, { .20, .05, .20}, "I13");
|
||||||
|
|
||||||
|
// [232] queries entering by a facet and exiting by a facet, on the line (x,.5-x,.2)
|
||||||
|
test({ 0, .5, .2}, {.2, .3, .2}, "23");
|
||||||
|
test({ 0, .5, .2}, {.5, 0, .2}, "232");
|
||||||
|
test({ 0, .5, .2}, {.55, -.05, .2}, "232I");
|
||||||
|
test({-.05, .45, .2}, {.55, -.05, .2}, "I232I");
|
||||||
|
test({-.05, .45, .2}, {.5, 0, .2}, "I232");
|
||||||
|
test({-.05, .45, .2}, {.2, .3, .2}, "I23");
|
||||||
|
|
||||||
|
// special case: queries stay in a single simplex
|
||||||
|
test({ -.125, -.125, .625}, { -.125, -.125, .6251}, "I");
|
||||||
|
test({ .25, .25, .25}, { .20, .25, .25}, "3");
|
||||||
|
test({ 0, .5, .2}, { 0, .4, .2}, "2");
|
||||||
|
test({ 0, .5, .0}, { 0, .6, .0}, "1");
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool test_a_simple_tetrahedron() {
|
||||||
|
bool ok = true;
|
||||||
|
std::cout << "## test_a_simple_tetrahedron()\n"
|
||||||
|
<< R"#(
|
||||||
|
This test uses with a trivial tetrahedron, and is launched with all the
|
||||||
|
24 permutations of the four vertices. There are 7 test cases, and for each of
|
||||||
|
them 6 different segments are tested:
|
||||||
|
- The segment starts at the incoming boundary of the tetrahedron and ends
|
||||||
|
inside.
|
||||||
|
- The segment starts at the incoming boundary of the tetrahedron and ends
|
||||||
|
at the outgoing boundary.
|
||||||
|
- The segment starts at the incoming boundary of the tetrahedron, goes out
|
||||||
|
and beyond.
|
||||||
|
- The segment starts before the tetrahedron, goes through it, and comes out.
|
||||||
|
- The segment starts before the tetrahedron and ends at the outgoing boundary.
|
||||||
|
- The segment starts before the tetrahedron and ends inside.
|
||||||
|
|
||||||
|
For each of those query segments, 4 tests are performed:
|
||||||
|
- with/without 8 extra vertices in the triangulation, forming a bounding
|
||||||
|
box,
|
||||||
|
- and in the direct and reverse direction.
|
||||||
|
|
||||||
|
In total, 4032 tests are performed...
|
||||||
|
|
||||||
|
|
||||||
|
)#";
|
||||||
|
std::cout.flush();
|
||||||
|
std::vector<Point_3> points = {
|
||||||
|
{0., 0., 0.},
|
||||||
|
{1., 0., 0.},
|
||||||
|
{0., 1., 0.},
|
||||||
|
{0., 0., 1.},
|
||||||
|
};
|
||||||
|
std::sort(points.begin(), points.end());
|
||||||
|
do {
|
||||||
|
std::cout << "### new permutation of the four points\n";
|
||||||
|
for(const auto& p: points) std::cout << " " << p << '\n';
|
||||||
|
std::cout << std::endl;
|
||||||
|
ok = test_a_simple_tetrahedron(points) && ok;
|
||||||
|
}
|
||||||
|
while (std::next_permutation(points.begin(), points.end()));
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
bool test(const DT& dt,
|
bool test(const DT& dt,
|
||||||
const std::pair<Point_3, Point_3>& query,
|
const std::pair<Point_3, Point_3>& query,
|
||||||
const std::array<unsigned, 4>& expected_result);
|
const std::array<unsigned, 4>& expected_result);
|
||||||
|
|
||||||
|
|
||||||
int main(int, char* [])
|
int main(int, char* [])
|
||||||
{
|
{
|
||||||
|
std::cerr.precision(17);
|
||||||
|
std::clog.precision(17);
|
||||||
|
std::cout.precision(17);
|
||||||
|
|
||||||
|
bool ok = true;
|
||||||
|
ok = test_a_simple_tetrahedron() && ok;
|
||||||
|
|
||||||
const std::vector<Point_3> points = { { -2, 0, 0 },
|
const std::vector<Point_3> points = { { -2, 0, 0 },
|
||||||
{ 2, 0, 0 },
|
{ 2, 0, 0 },
|
||||||
{ 0, 1, -1 },
|
{ 0, 1, -1 },
|
||||||
|
|
@ -43,15 +428,13 @@ int main(int, char* [])
|
||||||
};
|
};
|
||||||
std::vector<DT::Vertex_handle> vertices;
|
std::vector<DT::Vertex_handle> vertices;
|
||||||
vertices.reserve(points.size());
|
vertices.reserve(points.size());
|
||||||
DT dt;
|
dt.clear();
|
||||||
for(auto p: points) vertices.push_back(dt.insert(p));
|
for(auto p: points) vertices.push_back(dt.insert(p));
|
||||||
Cell_handle c;
|
Cell_handle c;
|
||||||
assert(dt.is_valid());
|
assert(dt.is_valid());
|
||||||
assert(dt.is_cell(vertices[0], vertices[2], vertices[3], vertices[4], c));
|
assert(dt.is_cell(vertices[0], vertices[2], vertices[3], vertices[4], c));
|
||||||
assert(dt.is_cell(vertices[1], vertices[2], vertices[3], vertices[4], c));
|
assert(dt.is_cell(vertices[1], vertices[2], vertices[3], vertices[4], c));
|
||||||
|
|
||||||
std::cerr << dt.number_of_finite_cells() << '\n';
|
|
||||||
|
|
||||||
const std::vector < std::pair<Point_3, Point_3>> queries = {
|
const std::vector < std::pair<Point_3, Point_3>> queries = {
|
||||||
{{-1, 0, 0}, { 1, 0, 0}}, // CFC
|
{{-1, 0, 0}, { 1, 0, 0}}, // CFC
|
||||||
{{-1, 0, 0}, { 2, 0, 0}}, // CFCV
|
{{-1, 0, 0}, { 2, 0, 0}}, // CFCV
|
||||||
|
|
@ -74,12 +457,20 @@ int main(int, char* [])
|
||||||
{2, 1, 1, 0} // reverse case: FVEV
|
{2, 1, 1, 0} // reverse case: FVEV
|
||||||
};
|
};
|
||||||
|
|
||||||
bool ok = true;
|
|
||||||
for(std::size_t i=0; i<queries.size(); ++i) {
|
for(std::size_t i=0; i<queries.size(); ++i) {
|
||||||
if(!test(dt, queries[i], expected_results[i])) ok = false;
|
ok = test(dt, queries[i], expected_results[i]) && ok;
|
||||||
}
|
}
|
||||||
std::cout << "Done (" << queries.size() << " queries)\n";
|
std::cout << "Done (" << queries.size() << " queries)\n";
|
||||||
return ok ? EXIT_SUCCESS : EXIT_FAILURE;
|
|
||||||
|
ok = test_vfefv() && ok;
|
||||||
|
ok = test_vfefv(true) && ok;
|
||||||
|
if(ok) {
|
||||||
|
std::cout << "All tests passed\n";
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
} else {
|
||||||
|
std::cout << "Some tests failed\n";
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool test(const DT& dt,
|
bool test(const DT& dt,
|
||||||
|
|
@ -100,6 +491,7 @@ bool test(const DT& dt,
|
||||||
|
|
||||||
// Count the number of finite cells traversed.
|
// Count the number of finite cells traversed.
|
||||||
unsigned int inf = 0, fin = 0;
|
unsigned int inf = 0, fin = 0;
|
||||||
|
std::optional<Simplex> previous;
|
||||||
for (; st != stend; ++st)
|
for (; st != stend; ++st)
|
||||||
{
|
{
|
||||||
if (st->dimension() == 3
|
if (st->dimension() == 3
|
||||||
|
|
@ -108,46 +500,18 @@ bool test(const DT& dt,
|
||||||
else {
|
else {
|
||||||
++fin;
|
++fin;
|
||||||
|
|
||||||
|
visit_simplex(p1, p2, *st, previous);
|
||||||
|
previous = *st;
|
||||||
|
|
||||||
switch (st->dimension()) {
|
switch (st->dimension()) {
|
||||||
case 2: {
|
case 2: ++nb_facets; break;
|
||||||
++nb_facets;
|
case 1: ++nb_edges; break;
|
||||||
std::cout << "facet " << std::endl;
|
case 0: ++nb_vertex; break;
|
||||||
DT::Facet f = *st;
|
case 3: ++nb_cells; break;
|
||||||
std::cout << " ( " << f.first->vertex((f.second + 1) & 3)->point()
|
default: CGAL_unreachable();
|
||||||
<< " " << f.first->vertex((f.second + 2) & 3)->point()
|
|
||||||
<< " " << f.first->vertex((f.second + 3) & 3)->point()
|
|
||||||
<< " )\n";
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case 1: {
|
|
||||||
++nb_edges;
|
|
||||||
std::cout << "edge " << std::endl;
|
|
||||||
DT::Edge e = *st;
|
|
||||||
std::cout << " ( " << e.first->vertex(e.second)->point() << " "
|
|
||||||
<< e.first->vertex(e.third)->point() << " )\n";
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case 0: {
|
|
||||||
++nb_vertex;
|
|
||||||
std::cout << "vertex " << std::endl;
|
|
||||||
DT::Vertex_handle v = *st;
|
|
||||||
std::cout << " ( " << v->point() << " )\n";
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case 3: {
|
|
||||||
++nb_cells;
|
|
||||||
std::cout << "cell \n ( ";
|
|
||||||
DT::Cell_handle ch = *st;
|
|
||||||
for (int i = 0; i < 4; ++i)
|
|
||||||
std::cout << ch->vertex(i)->point() << " ";
|
|
||||||
std::cout << " )\n";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
CGAL_unreachable();
|
|
||||||
} // end switch
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CGAL_TRIANGULATION_3_VERBOSE_TRAVERSER_EXAMPLE
|
#ifdef CGAL_TRIANGULATION_3_VERBOSE_TRAVERSER_EXAMPLE
|
||||||
std::cout << "While traversing from " << st.source()
|
std::cout << "While traversing from " << st.source()
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
|
// #define CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3 1
|
||||||
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||||
#include <CGAL/Delaunay_triangulation_3.h>
|
#include <CGAL/Delaunay_triangulation_3.h>
|
||||||
|
#include <CGAL/Base_with_time_stamp.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
@ -17,14 +19,20 @@ typedef Kernel::Vector_3 Vector_3;
|
||||||
typedef Kernel::Segment_3 Segment_3;
|
typedef Kernel::Segment_3 Segment_3;
|
||||||
|
|
||||||
// Define the structure.
|
// Define the structure.
|
||||||
typedef CGAL::Delaunay_triangulation_3< Kernel > DT;
|
typedef CGAL::Base_with_time_stamp<CGAL::Triangulation_vertex_base_3<Kernel>> Vb;
|
||||||
|
typedef CGAL::Delaunay_triangulation_cell_base_3<Kernel> Cb;
|
||||||
|
typedef CGAL::Triangulation_data_structure_3<Vb, Cb> Tds;
|
||||||
|
typedef CGAL::Delaunay_triangulation_3< Kernel, Tds > DT;
|
||||||
|
|
||||||
typedef DT::Vertex_handle Vertex_handle;
|
typedef DT::Vertex_handle Vertex_handle;
|
||||||
typedef DT::Cell_handle Cell_handle;
|
typedef DT::Cell_handle Cell_handle;
|
||||||
typedef DT::Edge Edge;
|
typedef DT::Edge Edge;
|
||||||
typedef DT::Facet Facet;
|
typedef DT::Facet Facet;
|
||||||
|
typedef DT::Simplex Simplex;
|
||||||
typedef DT::Segment_simplex_iterator Segment_simplex_iterator;
|
typedef DT::Segment_simplex_iterator Segment_simplex_iterator;
|
||||||
|
|
||||||
|
#include "test_triangulation_simplex_3_debug.h"
|
||||||
|
|
||||||
void test_vertex_edge_vertex(const DT& dt, const std::size_t& nb_tests)
|
void test_vertex_edge_vertex(const DT& dt, const std::size_t& nb_tests)
|
||||||
{
|
{
|
||||||
std::cout << "* test_vertex_edge_vertex *" << std::endl;
|
std::cout << "* test_vertex_edge_vertex *" << std::endl;
|
||||||
|
|
@ -299,8 +307,8 @@ void test_triangulation_on_a_grid()
|
||||||
unsigned int nb_facets = 0, nb_edges = 0, nb_vertex = 0;
|
unsigned int nb_facets = 0, nb_edges = 0, nb_vertex = 0;
|
||||||
for (; st != st.end(); ++st)
|
for (; st != st.end(); ++st)
|
||||||
{
|
{
|
||||||
std::cout << st->dimension() << " ";
|
std::cerr << st->dimension() << " ";
|
||||||
std::cout.flush();
|
std::cerr << debug_simplex(*st) <<'\n';
|
||||||
if (st->dimension() == 3)
|
if (st->dimension() == 3)
|
||||||
{
|
{
|
||||||
if (dt.is_infinite(Cell_handle(*st))) ++inf;
|
if (dt.is_infinite(Cell_handle(*st))) ++inf;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
template <typename Vertex_handle>
|
||||||
|
auto display_vert(Vertex_handle v) {
|
||||||
|
std::stringstream os;
|
||||||
|
os.precision(17);
|
||||||
|
if(v->time_stamp() == 0) {
|
||||||
|
os << "inf";
|
||||||
|
} else {
|
||||||
|
os << '#' << v->time_stamp() << "=(" << v->point() << ")";
|
||||||
|
}
|
||||||
|
return os.str();
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename DT>
|
||||||
|
struct Debug_simplex {
|
||||||
|
using Cell_handle = typename DT::Cell_handle;
|
||||||
|
using Edge = typename DT::Edge;
|
||||||
|
using Facet = typename DT::Facet;
|
||||||
|
using Vertex_handle = typename DT::Vertex_handle;
|
||||||
|
using Simplex = typename DT::Simplex;
|
||||||
|
|
||||||
|
Simplex simplex;
|
||||||
|
|
||||||
|
template<typename Dt, typename CharT, typename Traits>
|
||||||
|
friend
|
||||||
|
std::basic_ostream<CharT, Traits>&
|
||||||
|
operator<<(std::basic_ostream<CharT, Traits>& os, const Debug_simplex<Dt>& d) {
|
||||||
|
auto&& simplex = d.simplex;
|
||||||
|
switch(simplex.dimension()) {
|
||||||
|
case 0: {
|
||||||
|
os << "- vertex " << display_vert(static_cast<Vertex_handle>(simplex));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1: {
|
||||||
|
const auto [c, index1, index2] = static_cast<Edge>(simplex);
|
||||||
|
os << "- edge "
|
||||||
|
<< display_vert(c->vertex(index1)) << " - "
|
||||||
|
<< display_vert(c->vertex(index2));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
const auto [c, index] = static_cast<Facet>(simplex);
|
||||||
|
os << "- facet "
|
||||||
|
<< display_vert(c->vertex(DT::vertex_triple_index(index, 0))) << " - "
|
||||||
|
<< display_vert(c->vertex(DT::vertex_triple_index(index, 1))) << " - "
|
||||||
|
<< display_vert(c->vertex(DT::vertex_triple_index(index, 2)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3: {
|
||||||
|
const auto c = static_cast<Cell_handle>(simplex);
|
||||||
|
os << "- cell "
|
||||||
|
<< display_vert(c->vertex(0)) << " - "
|
||||||
|
<< display_vert(c->vertex(1)) << " - "
|
||||||
|
<< display_vert(c->vertex(2)) << " - "
|
||||||
|
<< display_vert(c->vertex(3));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: CGAL_assume(false);
|
||||||
|
}
|
||||||
|
return os;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#include <CGAL/Triangulation_simplex_3.h>
|
||||||
|
|
||||||
|
template <typename Triangulation>
|
||||||
|
auto debug_simplex(CGAL::Triangulation_simplex_3<Triangulation> simplex) {
|
||||||
|
return Debug_simplex<Triangulation>{simplex};
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue