cgal/Nef_3/include/CGAL/Nef_3/SNC_external_structure.h

1328 lines
46 KiB
C++

// Copyright (c) 1997-2002 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Michael Seel <seel@mpi-sb.mpg.de>
// Miguel Granados <granados@mpi-sb.mpg.de>
// Susan Hert <hert@mpi-sb.mpg.de>
// Lutz Kettner <kettner@mpi-sb.mpg.de>
// Peter Hachenberger <hachenberger@mpi-sb.mpg.de>
#ifndef CGAL_SNC_EXTERNAL_STRUCTURE_H
#define CGAL_SNC_EXTERNAL_STRUCTURE_H
#include <CGAL/license/Nef_3.h>
#include <CGAL/Nef_S2/Normalizing.h>
#include <CGAL/Nef_3/Pluecker_line_3.h>
#include <CGAL/Nef_3/SNC_decorator.h>
#include <CGAL/Nef_3/SNC_point_locator.h>
#include <CGAL/Nef_S2/SM_point_locator.h>
#include <CGAL/Nef_3/SNC_FM_decorator.h>
#include <CGAL/Nef_3/SNC_halfedge_key.h>
#include <CGAL/Nef_3/SNC_indexed_items.h>
#include <CGAL/Nef_3/SNC_simplify.h>
#include <map>
#include <list>
#include <unordered_map>
#undef CGAL_NEF_DEBUG
#define CGAL_NEF_DEBUG 43
#include <CGAL/Nef_2/debug.h>
#include <CGAL/use.h>
namespace CGAL {
template <typename R>
int sign_of(const CGAL::Plane_3<R>& h)
{ if ( h.c() != 0 ) return CGAL_NTS sign(h.c());
if ( h.b() != 0 ) return CGAL_NTS sign(-h.b());
return CGAL_NTS sign(h.a());
}
struct Plane_lt {
template <typename R>
bool operator()(const CGAL::Plane_3<R>& h1,
const CGAL::Plane_3<R>& h2) const
{
typedef typename R::RT RT;
typedef typename R::FT FT;
bool flag=false;
FT ratioa,ratiob,ratioc,ratiod;
FT a1,b1,c1,d1,a2,b2,c2,d2;
a1=h1.a();
a2=h2.a();
b1=h1.b();
b2=h2.b();
c1=h1.c();
c2=h2.c();
d1=h1.d();
d2=h2.d();
if(a2==0 || a1==0)
{
if(a2==a1) ratioa=1;
else flag=true;
}
else{ratioa=a1/a2;}
if(b2==0 || b1==0)
{
if(b2==b1) ratiob=ratioa;
else flag=true;
}
else{ ratiob=b1/b2;}
if(c2==0 || c1==0)
{
if(c2==c1) ratioc=ratioa;
else flag=true;
}
else{ ratioc=c1/c2;}
if(d2==0 || d1==0)
{
if(d2==d1) ratiod=ratioc;
else flag=true;
}
else{ ratiod=d1/d2;}
if(flag || !(ratioa==ratiob && ratioc==ratiod && ratioa==ratioc))
{
RT diff = h1.a()-h2.a();
if ( (diff) != 0 ) return CGAL_NTS sign(diff) < 0;
diff = h1.b()-h2.b();
if ( (diff) != 0 ) return CGAL_NTS sign(diff) < 0;
diff = h1.c()-h2.c();
if ( (diff) != 0 ) return CGAL_NTS sign(diff) < 0;
diff = h1.d()-h2.d();
if ( (diff) != 0 ) return CGAL_NTS sign(diff) < 0;
}
return 0;
}
};
struct Plane_RT_lt {
template <typename R>
bool operator()(const CGAL::Plane_3<R>& h1,
const CGAL::Plane_3<R>& h2) const
{ return (&(h1.a())) < (&(h2.a())); }
};
// ----------------------------------------------------------------------------
// SNC_external_structure
// ----------------------------------------------------------------------------
template <typename Items_, typename SNC_structure_>
class SNC_external_structure_base : public SNC_decorator<SNC_structure_>
{
public:
typedef SNC_structure_ SNC_structure;
typedef typename SNC_structure::Infi_box Infi_box;
typedef typename Infi_box::Standard_kernel Standard_kernel;
typedef typename Standard_kernel::Point_3 Standard_point_3;
typedef typename Infi_box::NT NT;
typedef CGAL::SNC_decorator<SNC_structure> SNC_decorator;
typedef CGAL::SNC_point_locator<SNC_decorator> SNC_point_locator;
typedef CGAL::SNC_FM_decorator<SNC_structure> FM_decorator;
typedef CGAL::SNC_simplify<Items_, SNC_structure> SNC_simplify;
typedef typename SNC_structure::Sphere_map Sphere_map;
typedef CGAL::SM_decorator<Sphere_map> SM_decorator;
typedef CGAL::SM_const_decorator<Sphere_map> SM_const_decorator;
typedef CGAL::SM_point_locator<SM_const_decorator> SM_point_locator;
typedef typename SNC_structure::Halfedge_iterator Halfedge_iterator;
typedef typename SNC_structure::Halffacet_iterator Halffacet_iterator;
typedef typename SNC_structure::Volume_iterator Volume_iterator;
typedef typename SNC_structure::Vertex_handle Vertex_handle;
typedef typename SNC_structure::Halfedge_handle Halfedge_handle;
typedef typename SNC_structure::Halffacet_handle Halffacet_handle;
typedef typename SNC_structure::Volume_handle Volume_handle;
typedef typename SNC_structure::Halffacet_const_handle Halffacet_const_handle;
typedef typename SNC_structure::SFace_const_handle SFace_const_handle;
typedef typename SNC_structure::SHalfedge_iterator SHalfedge_iterator;
typedef typename SNC_structure::SFace_iterator SFace_iterator;
typedef typename SNC_structure::SHalfloop_iterator SHalfloop_iterator;
typedef typename SNC_structure::SVertex_handle SVertex_handle;
typedef typename SNC_structure::SHalfedge_handle SHalfedge_handle;
typedef typename SNC_structure::SFace_handle SFace_handle;
typedef typename SNC_structure::SHalfloop_handle SHalfloop_handle;
typedef typename SNC_structure::Object_handle Object_handle;
typedef typename SNC_structure::SHalfedge_around_facet_circulator
SHalfedge_around_facet_circulator;
typedef typename SNC_structure::Point_3 Point_3;
typedef typename SNC_structure::Direction_3 Direction_3;
typedef typename SNC_structure::Plane_3 Plane_3;
typedef typename SNC_structure::Ray_3 Ray_3;
typedef typename SNC_structure::Sphere_point Sphere_point;
typedef typename SNC_structure::Sphere_circle Sphere_circle;
typedef typename SM_decorator::SHalfedge_around_svertex_circulator
SHalfedge_around_svertex_circulator;
SNC_point_locator* pl;
typedef CGAL::Unique_hash_map<SFace_const_handle,unsigned int>
Sface_shell_hash;
typedef CGAL::Unique_hash_map<Halffacet_const_handle,unsigned int>
Face_shell_hash;
typedef CGAL::Unique_hash_map<SFace_const_handle,bool> SFace_visited_hash;
typedef CGAL::Unique_hash_map<SFace_const_handle,bool> Shell_closed_hash;
using SNC_decorator::visit_shell_objects;
using SNC_decorator::link_as_inner_shell;
using SNC_decorator::link_as_outer_shell;
using SNC_decorator::link_as_prev_next_pair;
using SNC_decorator::get_visible_facet;
using SNC_decorator::adjacent_sface;
using SNC_decorator::make_twins;
struct Shell_explorer {
const SNC_decorator& D;
Sface_shell_hash& ShellSf;
Face_shell_hash& ShellF;
// Shell_closed_hash& Closed;
SFace_visited_hash& Done;
SFace_handle sf_min;
int n;
Shell_explorer(const SNC_decorator& Di, Sface_shell_hash& SSf,
Face_shell_hash& SF, SFace_visited_hash& Vi)
: D(Di), ShellSf(SSf), ShellF(SF), Done(Vi), n(0) {}
void visit(SFace_handle h) {
CGAL_NEF_TRACEN("visit sf "<<h->center_vertex()->point());
ShellSf[h]=n;
Done[h]=true;
if ( CGAL::lexicographically_xyz_smaller(h->center_vertex()->point(),
sf_min->center_vertex()->point()))
sf_min = h;
}
void visit(Vertex_handle h) {
CGAL_USE(h);
CGAL_NEF_TRACEN("visit v "<<h->point());
}
void visit(Halfedge_handle h) {
CGAL_USE(h);
CGAL_NEF_TRACEN("visit he "<< h->source()->point());
}
void visit(Halffacet_handle h) {
CGAL_NEF_TRACEN(h->plane());
ShellF[h]=n;
}
void visit(SHalfedge_handle ) {}
void visit(SHalfloop_handle ) {}
SFace_handle& minimal_sface() { return sf_min; }
void increment_shell_number() {
CGAL_NEF_TRACEN("leaving shell "<<n);
++n;
}
};
SNC_external_structure_base( SNC_structure& W, SNC_point_locator* spl = nullptr)
: SNC_decorator(W), pl(spl) {}
/*{\Mcreate makes |\Mvar| a decorator of |W|.}*/
public:
//#define CGAL_NEF_NO_HALFEDGE_KEYS
#ifdef CGAL_NEF_NO_HALFEDGE_KEYS
void pair_up_halfedges() const {
/*{\Mop pairs all halfedge stubs to create the edges in 3-space.}*/
// CGAL_NEF_SETDTHREAD(43*61);
CGAL_NEF_TRACEN(">>>>>pair_up_halfedges");
typedef Halfedge_key_lt3<Halfedge_handle>
Halfedge_key_lt;
typedef std::list<Halfedge_handle> Halfedge_list;
typedef typename Standard_kernel::Kernel_tag Kernel_tag;
typedef CGAL::Pluecker_line_3<Kernel_tag,Standard_kernel> Pluecker_line_3;
typedef CGAL::Pluecker_line_lt Pluecker_line_lt;
typedef std::map< Pluecker_line_3, Halfedge_list, Pluecker_line_lt>
Pluecker_line_map;
Pluecker_line_map M;
Pluecker_line_map M2;
Pluecker_line_map M3;
Pluecker_line_map M4;
NT eval(Infi_box::compute_evaluation_constant_for_halfedge_pairup(*this->sncp()));
Halfedge_iterator e;
CGAL_forall_halfedges(e,*this->sncp()) {
// progress++;
Point_3 p = e->source()->point();
Point_3 q = p + e->vector();
CGAL_NEF_TRACE(" segment("<<p<<", "<<q<<")"<<
" direction("<<e->vector()<<")");
Standard_point_3 sp = Infi_box::standard_point(p,eval);
Standard_point_3 sq = Infi_box::standard_point(q,eval);
Pluecker_line_3 l( sp, sq);
int inverted;
l = categorize( l, inverted);
if(Infi_box::is_edge_on_infibox(e))
if(Infi_box::is_type4(e))
M4[l].push_back(e);
else
if(Infi_box::is_type3(e))
M3[l].push_back(e);
else
M2[l].push_back(e);
else
M[l].push_back(e);
// the following trace crashes when compiling with optimizations (-O{n})
//CGAL_NEF_TRACEN(Infi_box::standard_point(point(vertex(e)))+
CGAL_NEF_TRACEN(" line("<<l<<")"<<" inverted="<<inverted);
}
typename Pluecker_line_map::iterator it;
CGAL_forall_iterators(it,M4) {
// progress++;
it->second.sort(Halfedge_key_lt());
CGAL_NEF_TRACEN("search opposite "<<it->first);
typename Halfedge_list::iterator itl;
CGAL_forall_iterators(itl,it->second) {
Halfedge_handle e1 = *itl;
++itl;
CGAL_assertion(itl != it->second.end());
Halfedge_handle e2 = *itl;
while(normalized(e1->vector()) != normalized(-e2->vector())) {
++itl;
make_twins(e1,*itl);
e1 = e2;
++itl;
e2 = *itl;
}
CGAL_NEF_TRACEN(" " << e1->source()->point()
<< " -> " << e2->source()->point());
CGAL_NEF_TRACEN(e1->vector()<<" -> "<<-e2->vector());
make_twins(e1,e2);
CGAL_assertion(e1->mark()==e2->mark());
// discard temporary sphere_point ?
}
}
CGAL_forall_iterators(it,M3) {
// progress++;
it->second.sort(Halfedge_key_lt());
CGAL_NEF_TRACEN("search opposite "<<it->first);
typename Halfedge_list::iterator itl;
CGAL_forall_iterators(itl,it->second) {
Halfedge_handle e1 = *itl;
++itl;
CGAL_assertion(itl != it->second.end());
Halfedge_handle e2 = *itl;
while(normalized(e1->vector()) != normalized(-e2->vector())) {
++itl;
make_twins(e1,*itl);
e1 = e2;
++itl;
e2 = *itl;
}
CGAL_NEF_TRACEN(" " << e1->source()->point()
<< " -> " << e2->source()->point());
CGAL_NEF_TRACEN(e1->vector()<<" -> "<<-e2->vector());
make_twins(e1,e2);
CGAL_assertion(e1->mark()==e2->mark());
// discard temporary sphere_point ?
}
}
CGAL_forall_iterators(it,M2) {
// progress++;
it->second.sort(Halfedge_key_lt());
CGAL_NEF_TRACEN("search opposite "<<it->first);
typename Halfedge_list::iterator itl;
CGAL_forall_iterators(itl,it->second) {
Halfedge_handle e1 = *itl;
++itl;
CGAL_assertion(itl != it->second.end());
Halfedge_handle e2 = *itl;
while(normalized(e1->vector()) != normalized(-e2->vector())) {
++itl;
this->make_twins(e1,*itl);
e1 = e2;
++itl;
e2 = *itl;
}
CGAL_NEF_TRACEN(" " << e1->source()->point()
<< " -> " << e2->source()->point());
CGAL_NEF_TRACEN(e1->vector()<<" -> "<<-e2->vector());
this->make_twins(e1,e2);
CGAL_assertion(e1->mark()==e2->mark());
// discard temporary sphere_point ?
}
}
CGAL_forall_iterators(it,M) {
// progress++;
it->second.sort(Halfedge_key_lt());
CGAL_NEF_TRACEN("search opposite "<<it->first);
typename Halfedge_list::iterator itl;
CGAL_forall_iterators(itl,it->second) {
Halfedge_handle e1 = *itl;
++itl;
CGAL_assertion(itl != it->second.end());
Halfedge_handle e2 = *itl;
while(normalized(e1->vector()) != normalized(-e2->vector())) {
++itl;
this->make_twins(e1,*itl);
e1 = e2;
++itl;
e2 = *itl;
}
CGAL_NEF_TRACEN(" " << e1->source()->point()
<< " -> " << e2->source()->point());
CGAL_NEF_TRACEN(e1->vector()<<" -> "<<-e2->vector());
this->make_twins(e1,e2);
CGAL_assertion(e1->mark()==e2->mark());
// discard temporary sphere_point ?
}
}
}
#else
void pair_up_halfedges() const {
/*{\Mop pairs all halfedge stubs to create the edges in 3-space.}*/
// CGAL_NEF_SETDTHREAD(43*61);
CGAL_NEF_TRACEN(">>>>>pair_up_halfedges");
typedef Halfedge_key< Point_3, Halfedge_handle>
Halfedge_key;
typedef Halfedge_key_lt< Point_3, Halfedge_handle, SNC_decorator>
Halfedge_key_lt;
typedef std::list<Halfedge_key> Halfedge_list;
typedef typename Standard_kernel::Kernel_tag Kernel_tag;
typedef CGAL::Pluecker_line_3<Kernel_tag,Standard_kernel> Pluecker_line_3;
typedef CGAL::Pluecker_line_lt Pluecker_line_lt;
typedef std::map< Pluecker_line_3, Halfedge_list, Pluecker_line_lt>
Pluecker_line_map;
SNC_decorator D(*this);
Pluecker_line_map M;
Pluecker_line_map M2;
Pluecker_line_map M3;
Pluecker_line_map M4;
NT eval(Infi_box::compute_evaluation_constant_for_halfedge_pairup(*this->sncp()));;
Halfedge_iterator e;
CGAL_forall_halfedges(e,*this->sncp()) {
// progress++;
Point_3 p = e->source()->point();
Point_3 q = p + e->vector();
CGAL_NEF_TRACE(" segment("<<p<<", "<<q<<")"<<
" direction("<<e->vector()<<")");
Standard_point_3 sp = Infi_box::standard_point(p,eval);
Standard_point_3 sq = Infi_box::standard_point(q,eval);
Pluecker_line_3 l( sp, sq);
int inverted;
l = categorize( l, inverted);
if(Infi_box::is_edge_on_infibox(e))
if(Infi_box::is_type4(e))
M4[l].push_back(Halfedge_key(p,inverted,e));
else
if(Infi_box::is_type3(e))
M3[l].push_back(Halfedge_key(p,inverted,e));
else
M2[l].push_back(Halfedge_key(p,inverted,e));
else
M[l].push_back(Halfedge_key(p,inverted,e));
// the following trace crashes when compiling with optimizations (-O{n})
//CGAL_NEF_TRACEN(Infi_box::standard_point(point(vertex(e)))+
CGAL_NEF_TRACEN(" line("<<l<<")"<<" inverted="<<inverted);
}
typename Pluecker_line_map::iterator it;
CGAL_forall_iterators(it,M4) {
// progress++;
it->second.sort(Halfedge_key_lt());
CGAL_NEF_TRACEN("search opposite "<<it->first);
typename Halfedge_list::iterator itl;
CGAL_forall_iterators(itl,it->second) {
Halfedge_handle e1 = itl->e;
++itl;
CGAL_assertion(itl != it->second.end());
Halfedge_handle e2 = itl->e;
CGAL_NEF_TRACEN(" " << e1->source()->point()
<< " -> " << e2->source()->point());
CGAL_NEF_TRACEN(e1->vector()<<" -> "<<-e2->vector());
make_twins(e1,e2);
CGAL_assertion(e1->mark()==e2->mark());
// discard temporary sphere_point ?
}
}
CGAL_forall_iterators(it,M3) {
// progress++;
it->second.sort(Halfedge_key_lt());
CGAL_NEF_TRACEN("search opposite "<<it->first);
typename Halfedge_list::iterator itl;
CGAL_forall_iterators(itl,it->second) {
Halfedge_handle e1 = itl->e;
++itl;
CGAL_assertion(itl != it->second.end());
Halfedge_handle e2 = itl->e;
CGAL_NEF_TRACEN(" " << e1->source()->point()
<< " -> " << e2->source()->point());
CGAL_NEF_TRACEN(e1->vector()<<" -> "<<-e2->vector());
make_twins(e1,e2);
CGAL_assertion(e1->mark()==e2->mark());
// discard temporary sphere_point ?
}
}
CGAL_forall_iterators(it,M2) {
// progress++;
it->second.sort(Halfedge_key_lt());
CGAL_NEF_TRACEN("search opposite "<<it->first);
typename Halfedge_list::iterator itl;
CGAL_forall_iterators(itl,it->second) {
Halfedge_handle e1 = itl->e;
++itl;
CGAL_assertion(itl != it->second.end());
Halfedge_handle e2 = itl->e;
CGAL_NEF_TRACEN(" " << e1->source()->point()
<< " -> " << e2->source()->point());
CGAL_NEF_TRACEN(e1->vector()<<" -> "<<-e2->vector());
make_twins(e1,e2);
CGAL_assertion(e1->mark()==e2->mark());
// discard temporary sphere_point ?
}
}
CGAL_forall_iterators(it,M) {
// progress++;
it->second.sort(Halfedge_key_lt());
CGAL_NEF_TRACEN("search opposite "<<it->first);
typename Halfedge_list::iterator itl;
CGAL_forall_iterators(itl,it->second) {
Halfedge_handle e1 = itl->e;
++itl;
CGAL_assertion(itl != it->second.end());
Halfedge_handle e2 = itl->e;
CGAL_NEF_TRACEN(" " << e1->source()->point()
<< " -> " << e2->source()->point());
CGAL_NEF_TRACEN(e1->vector()<<" -> "<< -e2->vector());
CGAL_assertion(e1->source()->point() != e2->source()->point());
CGAL_assertion(e1->mark()==e2->mark());
make_twins(e1,e2);
// discard temporary sphere_point ?
}
}
}
#endif
void link_shalfedges_to_facet_cycles() const {
/*{\Mop creates all non-trivial facet cycles from sedges.
\precond |pair_up_halfedges()| was called before.}*/
// CGAL_NEF_SETDTHREAD(43*31);
CGAL_NEF_TRACEN(">>>>>link_shalfedges_to_facet_cycles");
#ifdef CGAL_NEF_EXPLOIT_REFERENCE_COUNTING
Point_3 p1(1,2,7), p2(p1);
bool reference_counted = (&(p1.hx()) == &(p2.hx()));
#endif
Halfedge_iterator e;
CGAL_forall_edges(e,*this->sncp()) {
// progress++;
CGAL_NEF_TRACEN("");
CGAL_NEF_TRACEN(PH(e));
Halfedge_iterator et = e->twin();
SM_decorator D(&*e->source()), Dt(&*et->source());
CGAL_NEF_TRACEN(e->source()->point());
if ( D.is_isolated(e) ) continue;
SHalfedge_around_svertex_circulator ce(D.first_out_edge(e)),cee(ce);
SHalfedge_around_svertex_circulator cet(Dt.first_out_edge(et)),cete(cet);
#ifdef CGAL_NEF_EXPLOIT_REFERENCE_COUNTING
if(reference_counted) {
CGAL_For_all(cet,cete)
if ( &(cet->circle().a()) == &(ce->circle().opposite().a()) &&
cet->source()->twin() == ce->source() )
break;
} else
#endif
CGAL_For_all(cet,cete)
if ( cet->circle() == ce->circle().opposite() &&
cet->source()->twin() == ce->source() )
break;
#ifdef CGAL_USE_TRACE
if( cet->circle() != ce->circle().opposite() )
CGAL_NEF_TRACEN("assertion failed!");
CGAL_NEF_TRACEN("vertices " << e->source()->point() <<
" " << et->source()->point());
SHalfedge_around_svertex_circulator sc(D.first_out_edge(e));
SHalfedge_around_svertex_circulator sct(Dt.first_out_edge(et));
CGAL_NEF_TRACEN("");
CGAL_For_all(sc,cee)
CGAL_NEF_TRACEN("sseg@E addr="<<&*sc<<
" src="<< sc->source()->point()<<
" tgt="<< sc->target()->point()<<std::endl<<
" circle=" << normalized(sc->circle()));
CGAL_NEF_TRACEN("");
CGAL_For_all(sct,cete)
CGAL_NEF_TRACEN("sseg@ET addr="<<&*sct<<
" src="<< sct->source()->point()<<
" tgt="<<sct->target()->point()<<std::endl<<
" circle=" << normalized(sct->circle()));
CGAL_NEF_TRACEN("");
#endif
CGAL_assertion( normalized(cet->circle()) == normalized(ce->circle().opposite()) );
CGAL_assertion( cet->source()->twin() == ce->source());
CGAL_For_all(ce,cee) {
CGAL_NEF_TRACEN("circles " << normalized(cet->circle()) << " " << normalized(ce->circle()) <<
" sources " << cet->target()->point() <<
" " << ce->target()->point());
CGAL_assertion( normalized(cet->circle()) == normalized(ce->circle().opposite()));
CGAL_assertion( cet->source()->twin() == ce->source());
CGAL_assertion(ce->mark()==cet->mark());
link_as_prev_next_pair(cet->twin(),ce);
link_as_prev_next_pair(ce->twin(),cet);
--cet; // ce moves ccw, cet moves cw
}
}
}
void categorize_facet_cycles_and_create_facets() const {
/*{\Mop collects all facet cycles incident to a facet and creates
the facets. \precond |link_shalfedges_to_facet_cycles()| was called
before.}*/
// CGAL_NEF_SETDTHREAD(43*31);
CGAL_NEF_TRACEN(">>>>>categorize_facet_cycles_and_create_facets");
typedef std::list<Object_handle> Object_list;
#ifdef CGAL_NEF_EXPLOIT_REFERENCE_COUNTING
typedef std::map<Plane_3, Object_list, Plane_RT_lt>
Map_planes;
#else
typedef std::map<Plane_3, Object_list, Plane_lt>
Map_planes;
#endif
Map_planes M;
SHalfedge_iterator e;
CGAL_forall_shalfedges(e,*this->sncp()) {
Sphere_circle c(e->circle());
Plane_3 h = c.plane_through(e->source()->source()->point());
CGAL_NEF_TRACEN("\n" << e->source()->twin()->source()->point() <<" - "
<< e->source()->source()->point() <<" - "<<
e->twin()->source()->twin()->source()->point() <<
" has plane " << h << " has circle " << e->circle() <<
" has signum " << sign_of(h));
if ( sign_of(h)<0 ) continue;
M[normalized(h)].push_back(make_object(e->twin()));
CGAL_NEF_TRACEN(" normalized as " << normalized(h));
/*
Unique_hash_map<SHalfedge_handle, bool> Done(false);
SHalfedge_iterator ei;
CGAL_forall_sedges(ei,*this->sncp()) {
if(Done[ei]) continue;
Sphere_circle c(ei->circle());
Plane_3 h = c.plane_through(ei->source()->source()->point());
CGAL_NEF_TRACEN("\n" << ei->source()->twin()->source()->point() <<" - "
<< ei->source()->source()->point() <<" - "<<
ei->twin()->source()->twin()->source()->point() <<
" has plane " << h << " has circle " << ei->circle() <<
" has signum " << sign_of(h));
SHalfedge_handle e(ei);
if ( sign_of(h)<0 ) {
h = h.opposite();
e = e->twin();
}
SHalfedge_around_facet_circulator sfc(e), send(sfc);
CGAL_For_all(sfc, send) {
M[normalized(h)].push_back(make_object(e->twin()));
Done[sfc] = true;
Done[sfc->twin()] = true;
CGAL_NEF_TRACEN(" normalized as " << normalized(h));
}
*/
}
SHalfloop_iterator l;
CGAL_forall_shalfloops(l,*this->sncp()) {
Sphere_circle c(l->circle());
Plane_3 h = c.plane_through(l->incident_sface()->center_vertex()->point());
if ( sign_of(h)<0 ) continue;
// CGAL_assertion( h == normalized(h));
M[normalized(h)].push_back(make_object(l->twin()));
}
#ifdef CGAL_NEF3_TIMER_PLANE_SWEEPS
number_of_plane_sweeps=0;
timer_plane_sweeps.reset();
#endif
typename Map_planes::iterator it;
CGAL_forall_iterators(it,M) {
// progress2++;
// CGAL_NEF_TRACEN(" plane "<<it->first<<" "<<(it->first).point());
FM_decorator D(*this->sncp());
D.create_facet_objects(it->first,it->second.begin(),it->second.end());
}
// CGAL_NEF_SETDTHREAD(1);
}
void create_volumes() {
/*{\Mop collects all shells incident to a volume and creates the
volumes. \precond |categorize_facet_cycles_and_creating_facets()| was
called before.}*/
#ifdef CGAL_NEF3_TIMER_POINT_LOCATION
number_of_ray_shooting_queries=0;
timer_ray_shooting.reset();
#endif
// CGAL_NEF_SETDTHREAD(37*43*503*509);
CGAL_NEF_TRACEN(">>>>>create_volumes");
auto face_count = this->sncp()->number_of_halffacets();
auto sface_count = this->sncp()->number_of_sfaces();
Sface_shell_hash ShellSf(0, sface_count);
Face_shell_hash ShellF(0, face_count);
SFace_visited_hash Done(false, sface_count);
Shell_explorer V(*this,ShellSf,ShellF,Done);
std::vector<SFace_handle> MinimalSFace;
std::vector<SFace_handle> EntrySFace;
std::vector<bool> Closed;
SFace_iterator f;
// First, we classify all the Shere Faces per Shell. For each Shell we
// determine its minimum lexicographyly vertex and we check whether the
// Shell encloses a region (closed surface) or not.
CGAL_forall_sfaces(f,*this->sncp()) {
// progress++;
CGAL_NEF_TRACEN("sface in " << ShellSf[f]);
if ( Done[f] )
continue;
V.minimal_sface() = f;
visit_shell_objects(f,V);
CGAL_NEF_TRACEN("minimal vertex " << V.minimal_sface()->center_vertex()->point());
MinimalSFace.push_back(V.minimal_sface());
EntrySFace.push_back(f);
V.increment_shell_number();
CGAL_NEF_TRACEN("sface out " << ShellSf[f]);
}
for(unsigned int i=0; i<EntrySFace.size(); ++i)
Closed.push_back(false);
Halffacet_iterator hf;
CGAL_forall_facets(hf,*this) {
unsigned int shf = ShellF[hf];
unsigned int shf_twin = ShellF[hf->twin()];
if(shf != shf_twin) {
Closed[shf] = true;
Closed[shf_twin] = true;
}
}
CGAL_assertion( pl != nullptr);
#ifdef CGAL_NEF3_TIMER_INITIALIZE_KDTREE
CGAL::Timer timer_initialize_kdtree;
timer_initialize_kdtree.start();
#endif
pl->initialize(this->sncp()); // construct the point locator
#ifdef CGAL_NEF3_TIMER_INITIALIZE_KDTREE
timer_initialize_kdtree.stop();
if(cgal_nef3_timer_on)
std::cout << "Runtime_initialize_kdtree: "
<< timer_initialize_kdtree.time() << std::endl;
#endif
// then, we determine the Shells which correspond to Volumes via a ray
// shootting in the direction (-1,0,0) over the Sphere_map of the minimal
// vertex. The Shell corresponds to a Volume if the object hit belongs
// to another Shell.
this->sncp()->new_volume(); // outermost volume (nirvana)
if(MinimalSFace.size() == 0) return;
Vertex_handle v_min = MinimalSFace[0]->center_vertex();
for( unsigned int i = 0; i < MinimalSFace.size(); ++i) {
// progress2++;
Vertex_handle v = MinimalSFace[i]->center_vertex();
if(CGAL::lexicographically_xyz_smaller(v->point(),v_min->point()))
v_min=v;
CGAL_NEF_TRACEN( "Shell #" << i << " minimal vertex: " << v->point());
SM_point_locator D((Sphere_map*) &*v);
Object_handle o = D.locate(Sphere_point(-1,0,0));
SFace_const_handle sfc;
if( !CGAL::assign(sfc, o) || ShellSf[sfc] != i) {
CGAL_NEF_TRACEN("the shell encloses a volume");
CGAL_NEF_TRACEN("sface hit? "<<CGAL::assign(sfc,o));
if( CGAL::assign(sfc, o)) { CGAL_NEF_TRACEN("sface on another shell? "<<ShellSf[sfc]); }
SFace_handle f = MinimalSFace[i];
CGAL_assertion( ShellSf[f] == i );
if( Closed[i] ) {
CGAL_NEF_TRACEN("Shell #" << i << " is closed");
SM_decorator SD(&*v);
Volume_handle c = this->sncp()->new_volume();
c->mark() = f->mark(); // TODO test if line is redundant
link_as_inner_shell(f, c );
CGAL_NEF_TRACE( "Shell #" << i <<" linked as inner shell");
CGAL_NEF_TRACEN( "(sface" << (CGAL::assign(sfc,o)?"":" not") << " hit case)");
}
}
}
// finally, we go through all the Shells which do not correspond to a Volume
// and we assign them to its enclosing Volume determined via a facet below
// check.
CGAL_forall_sfaces(f,*this->sncp()) {
// progress3++;
if ( f->volume() != Volume_handle() )
continue;
CGAL_NEF_TRACEN( "Outer shell #" << ShellSf[f] << " volume?");
Volume_handle c = determine_volume( f, MinimalSFace, ShellSf );
c->mark() = f->mark();
link_as_outer_shell( f, c );
}
}
Halffacet_handle get_facet_below( Vertex_handle vi,
const std::vector< SFace_handle>& MinimalSFace,
const Sface_shell_hash& Shell) const {
// {\Mop determines the facet below a vertex |vi| via ray shooting. }
Halffacet_handle f_below;
Point_3 p = vi->point();
if(!Infi_box::is_standard(p))
return Halffacet_handle();
Ray_3 ray = Ray_3(p, Direction_3(-1,0,0));
#ifdef CGAL_NEF3_TIMER_POINT_LOCATION
number_of_ray_shooting_queries++;
timer_ray_shooting.start();
#endif
Object_handle o = pl->shoot(ray, vi);
#ifdef CGAL_NEF3_TIMER_POINT_LOCATION
timer_ray_shooting.stop();
#endif
// The ray here has an special property since it is shooted from the lowest
// vertex in a shell, so it would be expected that the ray goes along the
// interior of a volume before it hits a 2-skeleton element.
// Unfortunately, it seems to be possible that several shells are incident
// to this lowest vertex, and in consequence, the ray could also go along
// an edge or a facet belonging to a different shell.
// This fact invalidates the precondition of the get_visible_facet method,
// (the ray must pierce the local view of the hit object in a sface).
// This situation has not been analyzed and has to be verified. Granados.
Vertex_handle v;
Halfedge_handle e;
Halffacet_handle f;
CGAL_NEF_TRACEN("get_facet_below");
if( CGAL::assign(v, o)) {
CGAL_NEF_TRACEN("facet below from from vertex...");
f_below = get_visible_facet(v, ray);
if( f_below == Halffacet_handle()) {
CGAL_assertion(v->sfaces_begin() == v->sfaces_last());
f_below = get_facet_below(MinimalSFace[Shell[v->sfaces_begin()]]->center_vertex(),
MinimalSFace,Shell);
}
}
else if( CGAL::assign(e, o)) {
CGAL_NEF_TRACEN("facet below from from edge...");
f_below = get_visible_facet(e, ray);
if( f_below == Halffacet_handle()) {
CGAL_assertion(e->source()->sfaces_begin() == e->source()->sfaces_last());
f_below = get_facet_below(MinimalSFace[Shell[e->source()->sfaces_begin()]]->center_vertex(),
MinimalSFace, Shell);
}
}
else if( CGAL::assign(f, o)) {
CGAL_NEF_TRACEN("facet below from from facet...");
f_below = get_visible_facet(f, ray);
CGAL_assertion( f_below != Halffacet_handle());
}
else { CGAL_NEF_TRACEN("no facet below found..."); }
return f_below;
}
Volume_handle determine_volume( SFace_handle sf,
const std::vector< SFace_handle>& MinimalSFace,
const Sface_shell_hash& Shell ) const {
//{\Mop determines the volume |C| that a shell |S| pointed by |sf|
// belongs to. \precondition |S| separates the volume |C| from an enclosed
// volume.}
CGAL_NEF_TRACEN("determine volume");
Vertex_handle v_min = MinimalSFace[Shell[sf]]->center_vertex();
Halffacet_handle f_below = get_facet_below(v_min, MinimalSFace, Shell);
if ( f_below == Halffacet_handle())
return SNC_decorator(*this).volumes_begin();
Volume_handle c = f_below->incident_volume();
if( c != Volume_handle()) {
CGAL_NEF_TRACE( "Volume " << &*c << " hit ");
CGAL_NEF_TRACEN("(Shell #" << Shell[adjacent_sface(f_below)] << ")");
return c;
}
SFace_handle sf_below = adjacent_sface(f_below);
CGAL_NEF_TRACE( "Shell not assigned to a volume hit ");
CGAL_NEF_TRACEN( "(Inner shell #" << Shell[sf_below] << ")");
c = determine_volume( sf_below, MinimalSFace, Shell);
link_as_inner_shell( sf_below, c);
return c;
}
void build_external_structure() {
#ifdef CGAL_NEF3_TIMER_EXTERNAL_STRUCTURE
CGAL::Timer timer_external_structure;
timer_external_structure.start();
#endif
#ifdef CGAL_NEF3_TIMER_PLUECKER
CGAL::Timer timer_pluecker;
timer_pluecker.start();
#endif
// SNC_io_parser<SNC_structure> O0(std::cerr,*this->sncp());
// O0.print();
pair_up_halfedges();
#ifdef CGAL_NEF3_TIMER_PLUECKER
timer_pluecker.stop();
if(cgal_nef3_timer_on)
std::cout << "Runtime_pluecker: "
<< timer_pluecker.time() << std::endl;
#endif
link_shalfedges_to_facet_cycles();
// SNC_io_parser<SNC_structure> O0(std::cerr,*this->sncp());
// O0.print();
categorize_facet_cycles_and_create_facets();
create_volumes();
#ifdef CGAL_NEF3_TIMER_EXTERNAL_STRUCTURE
timer_external_structure.stop();
if(cgal_nef3_timer_on)
std::cout << "Runtime_external_structure: "
<< timer_external_structure.time() << std::endl;
#endif
}
template<typename Association>
void build_after_binary_operation(Association) {
#ifdef CGAL_NEF3_TIMER_SIMPLIFICATION
CGAL::Timer timer_simplification;
timer_simplification.start();
#endif
SNC_simplify simp(*this->sncp());
simp.vertex_simplification(SNC_simplify::NO_SNC);
#ifdef CGAL_NEF3_TIMER_SIMPLIFICATION
timer_simplification.stop();
if(cgal_nef3_timer_on)
std::cout << "Runtime_simplification: "
<< timer_simplification.time() << std::endl;
#endif
CGAL_NEF_TRACEN("\nnumber of vertices (so far...) = "
<< this->sncp()->number_of_vertices());
CGAL_NEF_TRACEN("=> resultant vertices (after simplification): ");
build_external_structure();
}
void clear_external_structure() {
this->sncp()->clear_snc_boundary();
while(this->sncp()->volumes_begin()!= this->sncp()->volumes_end())
this->sncp()->delete_volume(this->sncp()->volumes_begin());
while(this->sncp()->halffacets_begin()!= this->sncp()->halffacets_end())
this->sncp()->delete_halffacet_pair(this->sncp()->halffacets_begin());
SHalfedge_iterator se;
CGAL_forall_shalfedges(se,*this)
se->facet() = Halffacet_handle();
SFace_iterator sf;
CGAL_forall_sfaces(sf,*this)
sf->volume() = Volume_handle();
}
};
template <typename Items_, typename SNC_structure_>
class SNC_external_structure : public SNC_external_structure_base<Items_, SNC_structure_>
{
typedef CGAL::SNC_decorator<SNC_structure_> SNC_decorator;
typedef CGAL::SNC_point_locator<SNC_decorator> SNC_point_locator;
public:
SNC_external_structure( SNC_structure_& W, SNC_point_locator* spl = nullptr)
: SNC_external_structure_base<Items_, SNC_structure_>(W, spl)
{}
};
template <typename SNC_structure_>
class SNC_external_structure<SNC_indexed_items, SNC_structure_>
: public SNC_external_structure_base<int, SNC_structure_> {
public:
typedef SNC_structure_ SNC_structure;
typedef SNC_external_structure_base<int, SNC_structure> Base;
typedef CGAL::SNC_decorator<SNC_structure> SNC_decorator;
typedef CGAL::SNC_point_locator<SNC_decorator> SNC_point_locator;
typedef CGAL::SNC_FM_decorator<SNC_structure> FM_decorator;
typedef typename SNC_structure::Sphere_map Sphere_map;
typedef CGAL::SM_decorator<Sphere_map> SM_decorator;
typedef CGAL::SNC_simplify<SNC_indexed_items, SNC_structure> SNC_simplify;
typedef typename SNC_structure::Halfedge_iterator Halfedge_iterator;
typedef typename SNC_structure::SHalfedge_iterator SHalfedge_iterator;
typedef typename SNC_structure::SHalfloop_iterator SHalfloop_iterator;
typedef typename SNC_structure::Halfedge_handle Halfedge_handle;
typedef typename SNC_structure::SHalfedge_handle SHalfedge_handle;
typedef typename SNC_structure::Object_handle Object_handle;
typedef typename SNC_structure::SHalfedge_around_facet_circulator
SHalfedge_around_facet_circulator;
typedef typename SM_decorator::SHalfedge_around_svertex_circulator
SHalfedge_around_svertex_circulator;
typedef typename SNC_structure::Plane_3 Plane_3;
using Base::make_twins;
using Base::link_as_prev_next_pair;
using Base::link_as_inner_shell;
SNC_external_structure( SNC_structure& W, SNC_point_locator* spl = nullptr)
: Base(W, spl) {}
/*{\Mcreate makes |\Mvar| a decorator of |W|.}*/
public:
void pair_up_halfedges() const {
typedef Halfedge_key_lt4<Halfedge_handle> Halfedge_key_lt;
typedef std::list<Halfedge_handle> Halfedge_list;
typedef std::map<int, Halfedge_list, int_lt> index_map;
CGAL_NEF_TRACEN("pair up by indexes");
index_map i2he;
Halfedge_iterator ei;
CGAL_forall_halfedges(ei, *this->sncp())
i2he[ei->get_index()].push_back(ei);
typename index_map::iterator it;
CGAL_forall_iterators(it,i2he) {
CGAL_NEF_TRACEN("pair up " << it->first);
it->second.sort(Halfedge_key_lt());
typename Halfedge_list::iterator itl;
CGAL_forall_iterators(itl,it->second) {
Halfedge_handle e1 = *itl;
CGAL_NEF_TRACEN(e1->source()->point() << ", " << e1->vector());
++itl;
CGAL_assertion(itl != it->second.end());
Halfedge_handle e2 = *itl;
CGAL_NEF_TRACEN(" + " << e2->source()->point() << ", " << e2->vector());
make_twins(e1,e2);
// SNC_io_parser<SNC_structure> O0(std::cerr,*this->sncp());
// O0.print();
CGAL_assertion(e1->mark()==e2->mark());
}
}
}
void link_shalfedges_to_facet_cycles() const {
/*{\Mop creates all non-trivial facet cycles from sedges.
\precond |pair_up_halfedges()| was called before.}*/
// CGAL_NEF_SETDTHREAD(43*31);
CGAL_NEF_TRACEN(">>>>>link_shalfedges_to_facet_cycles");
Halfedge_iterator e;
CGAL_forall_edges(e,*this->sncp()) {
// progress++;
CGAL_NEF_TRACEN("");
CGAL_NEF_TRACEN(PH(e));
Halfedge_iterator et = e->twin();
SM_decorator D(&*e->source()), Dt(&*et->source());
CGAL_NEF_TRACEN(e->source()->point());
if ( D.is_isolated(e) ) continue;
SHalfedge_around_svertex_circulator ce(D.first_out_edge(e)),cee(ce);
SHalfedge_around_svertex_circulator cet(Dt.first_out_edge(et)),cete(cet);
CGAL_For_all(cet,cete) {
// std::cerr << cet->get_index() << ", " << ce->twin()->get_index() << std::endl;
if (cet->get_forward_index() == ce->twin()->get_backward_index())
// cet->source()->twin() == ce->source())
break;
}
CGAL_NEF_TRACEN("vertices " << e->source()->point() <<
" " << et->source()->point());
SHalfedge_around_svertex_circulator sc(D.first_out_edge(e));
SHalfedge_around_svertex_circulator sct(Dt.first_out_edge(et));
CGAL_NEF_TRACEN("");
CGAL_For_all(sc,cee)
CGAL_NEF_TRACEN("sseg@E addr="<<&*sc<<
" src="<< sc->source()->point()<<
" tgt="<< sc->target()->point()<< std::endl <<
" circle=" << sc->circle()<< std::endl <<
" indexes=" << sc->get_forward_index() <<
"," << sc->get_backward_index() << std::endl <<
" " << sc->twin()->get_forward_index() <<
"," << sc->twin()->get_backward_index());
CGAL_NEF_TRACEN("");
CGAL_For_all(sct,cete)
CGAL_NEF_TRACEN("sseg@ET addr="<<&*sct<<
" src="<< sct->source()->point()<<
" tgt="<<sct->target()->point() <<std::endl<<
" circle=" << sct->circle() << std::endl<<
" indexes=" << sct->get_forward_index() <<
"," << sct->get_backward_index() << std::endl <<
" " << sct->twin()->get_forward_index() <<
"," << sct->twin()->get_backward_index());
CGAL_NEF_TRACEN("");
CGAL_assertion( cet->get_index() == ce->twin()->get_index());
CGAL_assertion( cet->twin()->get_index() == ce->get_index());
CGAL_assertion( cet->source()->twin() == ce->source());
CGAL_For_all(ce,cee) {
CGAL_NEF_TRACEN("circles " << cet->circle() << " " << ce->circle() <<
" sources " << cet->target()->point() <<
" " << ce->target()->point());
CGAL_assertion( cet->source()->twin() == ce->source());
CGAL_assertion(ce->mark()==cet->mark());
link_as_prev_next_pair(cet->twin(),ce);
link_as_prev_next_pair(ce->twin(),cet);
--cet; // ce moves ccw, cet moves cw
}
}
}
void categorize_facet_cycles_and_create_facets() const {
/*{\Mop collects all facet cycles incident to a facet and creates
the facets. \precond |link_shalfedges_to_facet_cycles()| was called
before.}*/
// CGAL_NEF_SETDTHREAD(43*31);
CGAL_NEF_TRACEN(">>>>>categorize_facet_cycles_and_create_facets");
typedef std::list<Object_handle> Object_list;
typedef std::map<int, Object_list>
Map_planes;
Map_planes M;
SHalfedge_iterator e;
CGAL_forall_shalfedges(e,*this->sncp()) {
if(e->get_index() > e->twin()->get_index())
continue;
M[e->get_index()].push_back(make_object(e));
}
SHalfloop_iterator l;
CGAL_forall_shalfloops(l,*this->sncp()) {
if(l->get_index() > l->twin()->get_index())
continue;
M[l->get_index()].push_back(make_object(l));
}
#ifdef CGAL_NEF3_TIMER_PLANE_SWEEPS
number_of_plane_sweeps=0;
timer_plane_sweeps.reset();
#endif
typename Map_planes::iterator it;
CGAL_forall_iterators(it,M) {
CGAL_NEF_TRACEN(" plane "<< it->first);
CGAL_NEF_TRACEN(" size "<< it->second.size());
FM_decorator D(*this->sncp());
Plane_3 h;
Object_handle o(*it->second.begin());
if(CGAL::assign(e, o))
h = e->circle().opposite().plane_through(e->source()->source()->point());
else if(CGAL::assign(l, o))
h = l->circle().opposite().plane_through(l->incident_sface()->center_vertex()->point());
else
CGAL_error_msg( "wrong handle");
D.create_facet_objects(h,it->second.begin(),it->second.end());
}
// CGAL_NEF_SETDTHREAD(1);
}
void create_volumes() {
Base::create_volumes();
}
void build_external_structure() {
// CGAL_NEF_SETDTHREAD(503*509);
#ifdef CGAL_NEF3_TIMER_EXTERNAL_STRUCTURE
CGAL::Timer timer_external_structure;
timer_external_structure.start();
#endif
#ifdef CGAL_NEF3_TIMER_PLUECKER
CGAL::Timer timer_pluecker;
timer_pluecker.start();
#endif
// SNC_io_parser<SNC_structure> O0(std::cerr,*this->sncp());
// O0.print();
pair_up_halfedges();
#ifdef CGAL_NEF3_TIMER_PLUECKER
timer_pluecker.stop();
if(cgal_nef3_timer_on)
std::cout << "Runtime_pluecker: "
<< timer_pluecker.time() << std::endl;
#endif
// SNC_io_parser<SNC_structure> O0(std::cerr,*this->sncp());
// O0.print();
link_shalfedges_to_facet_cycles();
std::size_t num_shalfedges = this->sncp()->number_of_shalfedges();
std::unordered_map<int, int> hash(num_shalfedges);
CGAL::Unique_hash_map<SHalfedge_handle, bool> done(false, num_shalfedges);
SHalfedge_iterator sei;
CGAL_forall_shalfedges(sei, *this->sncp()) {
hash[sei->get_index()] = sei->get_index();
}
CGAL_forall_shalfedges(sei, *this->sncp()) {
if(done[sei])
continue;
SHalfedge_around_facet_circulator circ(sei), end(circ);
int index = circ->get_index();
++circ;
CGAL_For_all(circ, end)
if(circ->get_index() < index)
index = circ->get_index();
index = hash[index];
CGAL_For_all(circ, end) {
hash[circ->get_index()] = index;
circ->set_index(index);
done[circ] = true;
}
}
SHalfloop_iterator sli;
CGAL_forall_shalfloops(sli, *this->sncp())
sli->set_index(hash[sli->get_index()]);
categorize_facet_cycles_and_create_facets();
create_volumes();
#ifdef CGAL_NEF3_TIMER_EXTERNAL_STRUCTURE
timer_external_structure.stop();
if(cgal_nef3_timer_on)
std::cout << "Runtime_external_structure: "
<< timer_external_structure.time() << std::endl;
#endif
}
void clear_external_structure() {
Base::clear_external_structure();
}
template<typename Association>
void build_after_binary_operation(Association& A) {
SHalfedge_iterator sei;
CGAL_forall_shalfedges(sei, *this->sncp()) {
CGAL_NEF_TRACEN("hash sedge " << sei->get_index()
<< "->" << A.get_hash(sei->get_index()));
sei->set_index(A.get_hash(sei->get_index()));
}
SHalfloop_iterator sli;
CGAL_forall_shalfloops(sli, *this->sncp()) {
CGAL_NEF_TRACEN("hash sloop " << sli->get_index()
<< "->" << A.get_hash(sli->get_index()));
sli->set_index(A.get_hash(sli->get_index()));
}
// CGAL_NEF_SETDTHREAD(43);
/*
{ CGAL::SNC_io_parser<SNC_structure> O
(std::cerr, *this->sncp(), false, true);
O.print();}
*/
pair_up_halfedges();
/*
{ CGAL::SNC_io_parser<SNC_structure> O
(std::cerr, *this->sncp(), false, true);
O.print();}
*/
link_shalfedges_to_facet_cycles();
SNC_simplify simp(*this->sncp());
simp.vertex_simplificationI();
categorize_facet_cycles_and_create_facets();
create_volumes();
}
};
} //namespace CGAL
#endif //CGAL_SNC_EXTERNAL_STRUCTURE_H