cgal/Cubical_gaussian_map_3/include/CGAL/Sphere_dcel.h

1011 lines
31 KiB
C++

// Copyright (c) 2005 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you may redistribute it under
// the terms of the Q Public License version 1.0.
// See the file LICENSE.QPL distributed with CGAL.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
//
//
// Author(s) : Kapelushnik Lior <liorkape@post.tau.ac.il>
/*! \file
* spherical arrangements of none intersecting arcs of great circles on a sphere
*/
#ifndef CGAL_SPHERE_DCEL_H
#define CGAL_SPHERE_DCEL_H
#include <CGAL/Spherical_cgm_arr_dcel.h>
#include <CGAL/Cubical_gaussian_map_3.h>
#include <CGAL/Sphere_arc.h>
#include <list>
//temporary:
#include <iostream>
// end temporary
CGAL_BEGIN_NAMESPACE
/*
the class represents the spherical arrangement elements which are
halfedge, vertex, face and circulators around vertex or connected compononent boundary
_Kernel - the kernel to base uppon the spherical map and the internal cubical gaussian map
_T_Dcel - the cubical gaussian map basic dcel structure template class
*/
template <class _Kernel,
#ifndef CGAL_CFG_NO_TMPL_IN_TMPL_PARAM
template <class T>
#endif
class _T_Dcel = Spherical_cgm_arr_dcel>
class SphereTopologicalMap {
public:
class Halfedge;
class Vertex;
class Face;
class Halfedge_around_vertex_circulator;
class Ccb_halfedge_circulator;
// public definitions
typedef CGAL::Cubical_gaussian_map_3<_Kernel, _T_Dcel> CGM;
typedef _Kernel Kernel;
typedef std::list<Halfedge> HalfedgeList;
typedef typename HalfedgeList::iterator Halfedge_iterator;
typedef typename HalfedgeList::const_iterator Halfedge_const_iterator;
typedef Halfedge_iterator Halfedge_handle;
typedef Halfedge_const_iterator Halfedge_const_handle;
typedef std::list<Vertex> VertexList;
typedef typename VertexList::iterator Vertex_iterator;
typedef typename VertexList::const_iterator Vertex_const_iterator;
typedef Vertex_iterator Vertex_handle;
typedef Vertex_const_iterator Vertex_const_handle;
typedef std::list<Face> FaceList;
typedef typename FaceList::iterator Face_iterator;
typedef typename FaceList::const_iterator Face_const_iterator;
typedef Face_iterator Face_handle;
typedef Face_const_iterator Face_const_handle;
typedef std::list<Ccb_halfedge_circulator> HolesList;
typedef typename HolesList::iterator Hole_iterator;
/*
represents a circulator around vertex that allows for circulating
the incoming halfedges of a vertex
*/
class Halfedge_around_vertex_circulator: public Halfedge_handle {
private:
typedef Halfedge_handle Base;
typedef Halfedge_around_vertex_circulator Self;
// basic arrangement circulator
typedef typename CGM::Arr_halfedge_around_vertex_const_circulator PM_Circulator;
typedef typename CGM::Arr_halfedge_const_iterator Int_Halfedge_const_iterator;
// cubical gaussian map circulator
typedef typename CGM::Halfedge_around_vertex_const_circulator CGM_Circulator;
// the corresponding cubical circulator around the vertex
CGM_Circulator m_cubeCirculator;
CGM *m_cgm; // pointer to the cubical gaussian map representing the spherical map
public:
/*
empty constructor
*/
Halfedge_around_vertex_circulator() {}
/*
constructor from a cubical map circulator and a cubical map pointer
inCir - a cubical map circulator
cgm - a cubical gaussian map of the circulator
*/
Halfedge_around_vertex_circulator(CGM_Circulator &inCir, CGM *cgm):
m_cubeCirculator(inCir), m_cgm(cgm) {
Base * base = this;
Halfedge_handle spEdge;
// spEdge will hold the spherical map halfedge pointed by the cubical map
// circulator halfedge, since the target of the cubical map is a real vertex
// it is guaranteed that the cubical halfedge will have a pointer to
// a spherical halfedge
spEdge = *((Halfedge_handle *)(m_cubeCirculator->getSphereEdge()));
// set circulator halfedge value to the spherical map halfedge
*base = spEdge;
}
/*
advance to next halfedge around vertex
return value - the next halfedge around spherical vertex
*/
Self & operator++() {
Base * base = this;
++m_cubeCirculator; // advance internal cgm circulator
Halfedge_handle spEdge;
// get spherical halfedge pointed by cgm advanced circulator
spEdge = *((Halfedge_handle *)(m_cubeCirculator->getSphereEdge()));
*base = spEdge; // set value to next halfedge
return *this;
}
/*
advance to next halfedge around vertex and return current halfedge as if
the circulator was not advanced
return value - the current circulator
*/
Self operator++(int) {
Self tmp = *this; // save current circulator
++(*this); // advance circulator
return tmp; // return circulator before advancing
}
/*
test equality of two circulators
circulator - circulator to compare object with
return value - true if current object and circulator are the same
*/
bool operator==(const Self &circulator) const {
// compare the halfedge values with the circulator
return Base::operator==(circulator);
}
/*
test inequality of two circulators
circulator - circulator to compare object with
return value - true if current object and circulator are not the same
*/
bool operator!=(const Self &circulator) const {
// use composition of the equality operator
return (!(*this == circulator));
}
};
/*
represents a circulator around a connected component boudary that allows for
circulating a ccb of a face
*/
class Ccb_halfedge_circulator: public Halfedge_handle {
typedef Halfedge_handle Base;
typedef Ccb_halfedge_circulator Self;
public:
/*
constructor from a regular halfedge to a ccb circulator
i - a spherical map halfedge
*/
Ccb_halfedge_circulator(Halfedge_handle i):
Base(i) {}
/*
empty constructor
*/
Ccb_halfedge_circulator(): Base() {};
/*
test for equality of two ccb circulators
i - the ccb circulator to compare with
return value - true if the circulators are equal
*/
bool operator==(const Self &i) const {
// compare the halfedge part of the two circulators
return Base::operator==(i);
}
/*
test for inequality of two ccb circulators
i - the ccb circulator to compare with
return value - true if the circulators are not equal
*/
bool operator!=(const Self &i) const {
// by composition check if the two circulators are not equal
return (!((*this) == i));
}
/*
advance the circulator
return value - the next ccb circulator
*/
Self & operator++() {
Base *base = this;
// advancing is moving to the next halfedge
*base = (*base)->next();
return *this;
}
/*
advance the circulator and return the circulator before advancing
return value - the circulator before advancing
*/
Self operator++(int) {
Self tmp = *this; // remember circulator before advance is done
++(*this); // advance current circulator
return tmp; // return the circulator before advancing
}
};
/*
this class represents a spherical vertex
*/
class Vertex {
public:
// public definitions
typedef typename CGM::Arr_vertex_iterator Int_Vertex_iterator;
typedef typename CGM::Arr_halfedge_iterator Int_Halfedge_iterator;
typedef typename _Kernel::Direction_3 Direction_3;
/*
constructor,
inVer - the cubical vertex that represents the sphere vertex
cgm - pointer to the cubical gaussian map holding the cgm vertex
*/
Vertex(Int_Vertex_iterator inVer, CGM *cgm):
m_cubeVertex(inVer), m_cgm(cgm) {};
~Vertex() {
}
/*
get the sphere vertex handle pointing to the internal cgm vertex that represents
the spherical vertex
return value - a pointer to Vertex_handle as defined in the Spherical_map
which points to the cubical vertex
*/
inline void *sphereVertexPointer() {
return m_cubeVertex->getSphereVertex();
}
/*
test equality of vertices
sphere_it - the other vertex to compare with
return value - true if sphere_it and current vertex are the same
*/
bool operator==(const Vertex & sphere_it) {
// two sphere vertices are equal if they are represented by the sane
// cubical vertex
return (m_cubeVertex == sphere_it.m_cubeVertex);
}
/*
test inequality of vertices
sphere_it - the other vertex to compare with
return value - true if sphere_it and current vertex are not the same
*/
bool operator!=(const Vertex & sphere_it) {
// use composition with the equality operator
return (!(*this == sphere_it));
}
/*
the direction of the vertex (the intersection of the direction
and the sphere is the vertex point)
return value - the vertex direction
*/
inline Direction_3 direction() {
// get direction stored in cubical map vertex
return m_cubeVertex->get_direction();
}
/*
the direction of the vertex (the intersection of the direction
and the sphere is the vertex point)
return value - the vertex direction
a const version
*/
inline const Direction_3 direction() const {
// get direction stored in cubical map vertex
return m_cubeVertex->get_direction();
}
/*
returns a circulator that allows to traverse the halfedges that have the vertex
as their target
return value - a halfedge circulator around the vertex
*/
Halfedge_around_vertex_circulator incident_halfedges() const {
// build a cgm circulator around the corresponding cgm vertex
typename CGM::Halfedge_around_vertex_const_circulator hec(m_cubeVertex-> incident_halfedges());
// return a circulator based on the cgm circulator
return Halfedge_around_vertex_circulator(hec, m_cgm);
}
/*
returns true if e is incident to v (i.e., if v is the source or the
target of e).
e - the halfedge to check incidence to
return value - true if e is incident to the vertex
*/
bool is_incident_edge (Halfedge_const_handle e) {
// the halfedge is incident if it's target or source is the vertex
if ((e->target())->direction() == direction()) {
return true;
}
if ((e->source())->direction() == direction()) {
return true;
}
return false;
}
/*
returns true if face f is incident to the vertex
f - the face to check if the vertex is incident to
return value - true if f is incident to the vertex
*/
bool is_incident_face(Face_const_handle f) {
/*
IntFaceList nearFaces;
Int_face_handle nearFace;
nearFace = f->m_cubeFace;
connectedFaces(*m_cgm, nearFaces, nearFace);
typename IntFaceList::iterator lit;
*/
/*
see if one the the cgm faces of the sphere face is incident to
the representative vertex
*/
/*
for (lit = nearFaces.begin(); lit != nearFaces.end(); lit++) {
if (m_cubeVertex->is_incident_face(*lit)) {
return true;
}
}
return false;
*/
Halfedge_around_vertex_circulator adjEdges=incident_halfedges();
Halfedge_around_vertex_circulator circEnd=adjEdges;
// circulate the halfedges around the vertex, for each halfedge check if
// it's pointed spherical face is f, if so f is incident, if all the surrounding
// halfedges faces are not f, f is not incident to the vertex
do {
if (adjEdges->face() == f) {
return true;
}
++adjEdges;
} while (adjEdges != circEnd);
return false;
}
/*
find the number of halfedges pointing to the vertex
return value - the number of incoming halfedges pointing to the vertex
*/
unsigned int degree() const {
Halfedge_around_vertex_circulator circ=incident_halfedges();
Halfedge_around_vertex_circulator startCirc = circ;
unsigned int counter;
counter = 0;
// circulate the halfedges around the vertex and count
do {
++counter;
++circ;
} while (circ != startCirc);
// return m_cgm->degree(m_cubeVertex);
return counter;
}
private:
// the cubical vertex projected by the sphere vertex
Int_Vertex_iterator m_cubeVertex;
CGM *m_cgm; // the cubical gaussian map holding the cubical corresponding vertex
};
class Halfedge {
public:
// public definitions
typedef typename CGM::Arr_halfedge_handle Int_halfedge_handle;
typedef typename CGM::Arr_vertex_handle Int_vertex_handle;
typedef Sphere_arc<_Kernel> Curve;
/*
constructor, create a new halfedge
inEdge - a halfedge on the cubical gaussian map that is part of the
sphere halfedge
cgm - the cubical gaussian map holding the internal halfedge
*/
Halfedge(Int_halfedge_handle inEdge, CGM *cgm):
m_cgm(cgm), m_cubeHalfedge(inEdge) {};
~Halfedge() {
}
/*
get the sphere halfedge handle pointing to the internal cgm halfedge that represents
the spherical halfedge
return value - a pointer to Halfedge_handle as defined in the Spherical_map
which points to the cubical halfedge
*/
inline void *sphereHalfedgePointer() {
return m_cubeHalfedge->getSphereEdge();
}
/*
returns the destination vertex of the spherical halfedge
return value - the spherical handle to the target vertex of the halfedge
*/
Vertex_handle target() {
Int_halfedge_handle lEdge;
lEdge = lastEdge(); // get last cubical halfedge of the spherical halfedge
Int_vertex_handle targ = lEdge->target(); // get the target of last halfedge
// find the representative target vertex
// which may be the last vertex or one of it's adjacent vertices
while (!targ->is_rep()) {
void *tmp = targ->get_adjacent_vertex();
targ = *((Int_vertex_handle *) (&tmp));
}
return *((Vertex_handle *)(targ->getSphereVertex()));
}
/*
returns the curve represented by the halfedge
return value - the curve represented by the halfedge
*/
Curve curve() {
// create a curve with the halfedge endpoints (short arc)
return Curve(source()->direction(), target()->direction());
}
/*
returns the destination vertex of the spherical halfedge
a const version of the none const target
*/
Vertex_const_handle target() const {
Int_halfedge_handle lEdge;
lEdge = lastEdge();
Int_vertex_handle targ = lEdge->target();
// find the representative target vertex
while (!targ->is_rep()) {
void *tmp = targ->get_adjacent_vertex();
targ = *((Int_vertex_handle *) (&tmp));
}
return *((Vertex_const_handle *)(targ->getSphereVertex()));
}
/*
returns the source vertex of the spherical halfedge
return value - the spherical handle to the source vertex of the halfedge
*/
Vertex_handle source() {
Halfedge_handle theTwin;
theTwin = twin();
// source is the target of the twin
return theTwin->target();
}
/*
returns the source vertex of the spherical halfedge
a const version of the none const source
*/
Vertex_const_handle source() const {
Halfedge_const_handle theTwin;
theTwin = twin();
return theTwin->target();
}
/*
get the face next to the halfedge
return value - a spherical face handle to the face adjacent of the halfedge
*/
Face_handle face() {
// get the spherical face handle pointed by the adjacent face to the
// cubical halfedge
return *((Face_handle *)((m_cubeHalfedge->face())->getSphereFace()));
}
/*
get the face next to the halfedge, a const version
return value - a spherical face handle to the face adjacent of the halfedge
*/
Face_const_handle face() const {
// get the spherical face handle pointed by the adjacent face to the
// cubical halfedge
return *((Face_handle *)((m_cubeHalfedge->face())->getSphereFace()));
}
/*
the next halfedge around the face
return value - next face halfedge
*/
Halfedge_handle next() {
Int_halfedge_handle cur; // current halfedge of arc
// find the last halfedge of the arc
cur = lastEdge();
// found last edge, now find it's next
cur = cur->next();
// if cube unreal halfedge, traverse adjacent until real halfedge
while (!cur->get_is_real()) {
cur = m_cgm->get_adjacent_halfedge_handle(cur);
cur = cur->next();
}
return Face::outHandle(cur, m_cgm);
}
/*
the twin halfedge
return value - the spherical twin halfedge
*/
Halfedge_handle twin() {
Int_halfedge_handle twin;
twin = m_cubeHalfedge->twin(); // get cubical twin
if ((twin->face())->is_unbounded()) {
// if cubical twin in unbounded face, twin is the adjacent on another
// cubical face
twin = m_cgm->get_adjacent_halfedge_handle(m_cubeHalfedge);
}
// find last cubical halfedge of the spherical halfedge
while (!(twin->target()->getReal())) {
twin = twin->next(); // advance cubical halfedge
while (!twin->get_is_real()) {
// traverse cubical unreal halfedges until a real halfedge
twin = m_cgm->get_adjacent_halfedge_handle(twin);
twin = twin->next();
}
}
return *((Halfedge_handle *)(twin->getSphereEdge()));
}
/*
the twin halfedge
a const version of the none const twin
*/
Halfedge_const_handle twin() const {
Int_halfedge_handle twin;
twin = m_cubeHalfedge->twin(); // get cubical twin
if ((twin->face())->is_unbounded()) {
// if cubical twin in unbounded face, twin is the adjacent on another
// cubical face
twin = m_cgm->get_adjacent_halfedge_handle(m_cubeHalfedge);
}
// find last cubical halfedge of the spherical halfedge
while (!(twin->target()->getReal())) {
twin = twin->next(); // advance cubical halfedge
while (!twin->get_is_real()) {
// traverse cubical unreal halfedges until a real halfedge
twin = m_cgm->get_adjacent_halfedge_handle(twin);
twin = twin->next();
}
}
return *((Halfedge_const_handle *)(twin->getSphereEdge()));
}
/*
get a halfedge around ccb circulator starting at the halfedge
return value - a ccb halfedge circulator starting from the halfedge
*/
Ccb_halfedge_circulator ccb() {
Halfedge_handle thisHandle;
thisHandle = *((Halfedge_handle *)(m_cubeHalfedge->getSphereEdge()));
return Ccb_halfedge_circulator(thisHandle);
}
/*
get the last cgm halfedge of the spherical halfedge
return value - the last cgm halfedge of the spherical halfedge
*/
inline const Int_halfedge_handle cubeHalfedge() const {
return m_cubeHalfedge;
}
private:
CGM * m_cgm; // the internal cubical gaussian map
// a cubical gaussian map halfedge corresponding the spherical halfedge,
// the target of this cgm halfedge is real and it is part of the sphere halfedge arc
Int_halfedge_handle m_cubeHalfedge;
/*
given a halfedge, finds the last edge of the arc
that contains the halfedge
return value - the last cgm halfedge that correspond the sphere halfedge,
it's cgm target is a real vertex
*/
Int_halfedge_handle lastEdge() const {
Int_halfedge_handle cur;
cur = m_cubeHalfedge;
// move to next real cgm halfedge until target is real
while (!(cur->target()->getReal())) {
cur = cur->next();
// traverse cubical unreal halfedges until a real halfedge
while (!cur->get_is_real()) {
cur = m_cgm->get_adjacent_halfedge_handle(cur);
cur = cur->next();
}
}
return cur;
}
};
/*
this class represents a spherical face
*/
class Face {
public:
// allow the spherical map to access m_doesOuterExist and set it's value
template <class SphericalMapDcel, class Sphere_traits>
friend class Spherical_map;
// public definitions
typedef typename CGM::Arr_face_handle Int_face_handle;
typedef typename CGM::Arr_halfedge_handle Int_halfedge_handle;
typedef typename CGM::Arrangement::Hole_iterator Int_hole_iterator;
/*
constructor from a cubical face
inFace - an internal cubical face that is part of the spherical face
cgm - the cubical gaussian map containing the cgm face
*/
Face(Int_face_handle inFace, CGM *cgm):
m_cgm(cgm), m_cubeFace(inFace), m_dirty(true), m_doesOuterExist(true) {}
/*
get the sphere face handle pointing to the internal cgm face that represents
the spherical face (occupying part of the spherical face area)
return value - a pointer to Face_handle as defined in the Spherical_map
which points to a cubical face that is part of the spherical face
*/
inline void *sphereFacePointer() {
return m_cubeFace->getSphereFace();
}
/*
get an iterator to first hole in face
return value - an iterator to the first hole of the face
*/
Hole_iterator holes_begin() {
update();
return m_holes.begin();
}
/*
get an iterator to past the end hole in face
return value - an iterator to the past the end hole of the face
*/
Hole_iterator holes_end() {
update();
return m_holes.end();
}
/*
get a halfedge on the face outer connected component boundary
return value - a halfedge on the face outer ccb
*/
Halfedge_handle halfedge_on_outer_ccb() {
update();
return m_outerCcb;
}
/*
get a ccb circulator on the face outer connected component boundary
return value - a ccb circulator on the face outer ccb
*/
Ccb_halfedge_circulator outer_ccb() {
update();
return m_outerCcb;
}
/*
find if the face has an outer ccb (are there any halfedges in the face)
return value - true if the face has an outer ccb
*/
inline bool does_outer_ccb_exist() {
return m_doesOuterExist;
}
/*
find if a halfedge is on the face's outer ccb
e - the halfedge to check if on outer ccb
return value - true if e is a halfedge on the face outer ccb
*/
bool is_halfedge_on_outer_ccb(Halfedge_const_handle e) {
update();
if (!m_doesOuterExist) {
// no outer ccb, halfedge can't be on outer ccb
return false;
}
Ccb_halfedge_circulator circ = m_outerCcb;
// circulate on the halfedge ccb and check if e is one of the halfedges
do {
if (e==circ) {
return true; // e found on the outer ccb
}
++circ;
} while (circ != m_outerCcb);
// e not found on the outer ccb
return false;
}
/*
find if a halfedge is on a face's inner ccb
e - the halfedge to check if on an inner ccb
return value - true if e is a halfedge one of the face's inner ccb
*/
bool is_halfedge_on_inner_ccb(Halfedge_const_handle e) {
if (e->face() == *((Face_const_handle *)m_cubeFace->getSphereFace())) {
// if halfedge is adjacent to face,
// using composition, if not on on outer ccb, on inner ccb
return (!(this->is_halfedge_on_outer_ccb(e)));
} else {
// halfedge not adjacent to face
return false;
}
}
/*
update the ccb structures of the face
*/
void update() {
if (!m_dirty || !m_doesOuterExist) {
// already updated or one face of entire cube
return;
}
IntFaceList nearFaces;
// find all cgm faces that are part of the spherical face
connectedFaces(*m_cgm, nearFaces, m_cubeFace);
typename IntFaceList::iterator lit;
bool firstCcb = true; // seperate first ccb as outer ccb
// loop over all cgm faces of the spherical face
for (lit = nearFaces.begin(); lit != nearFaces.end(); lit++) {
// process one internal cgm face
// first process internal face outer ccb
Int_halfedge_handle curIntHe = (*lit)->outer_ccb();
Int_halfedge_handle baseIntHe = curIntHe;
// search for a real halfedge on the cgm face ccb
// if halfedge is not real but it is marked, it is known
// that the ccb have already been processed
while (!curIntHe->get_is_real() && !curIntHe->getMark()) {
curIntHe = curIntHe->next();
if (curIntHe == baseIntHe) {
break;
}
}
if (curIntHe->getMark() || !curIntHe->get_is_real()) {
// the ccb has already been processed or isn't real,
// any ccb will have one cgm face with real halfedge
// and will be processed at laest in one cgm face
} else {
// process new ccb
// get spherical handle
Halfedge_handle curHe = outHandle(curIntHe, m_cgm);
Ccb_halfedge_circulator currentCcb(curHe);
markCcb(curIntHe); // mark ccb not to be processed again
if (firstCcb) {
// spherical outer ccb
m_outerCcb = currentCcb;
firstCcb = false;
} else {
// a hole
m_holes.push_back(currentCcb);
}
}
// process holes of internal face
Int_hole_iterator holesIt;
for (holesIt=(*lit)->holes_begin();
holesIt!= (*lit)->holes_end();
holesIt++) {
// process each hole similar to the outer ccb processing
Int_halfedge_handle curIntHe = (*holesIt);
Int_halfedge_handle baseIntHe = curIntHe;
// get a real or marked halfedge on the ccb if any
while (!curIntHe->get_is_real() && !curIntHe->getMark()) {
curIntHe = curIntHe->next();
if (curIntHe == baseIntHe) {
break;
}
}
if (curIntHe->getMark() || !curIntHe->get_is_real()) {
// the ccb has already been processed or isn't real,
// any ccb will have one cgm face with real halfedge
// and will be processed at laest in one cgm face
continue;
} else {
// process new ccb
Halfedge_handle curHe = outHandle(curIntHe, m_cgm);
Ccb_halfedge_circulator currentCcb(curHe);
markCcb(curIntHe); // mark ccb not to be processed again
if (firstCcb) {
// spherical outer ccb
m_outerCcb = currentCcb;
firstCcb = false;
} else {
// a hole
m_holes.push_back(currentCcb);
}
}
}
}
m_dirty = false;
}
/*
find the spherical halfedge from a cgm halfedge
ihandle - a cubical halfedge
cgm - the cgm holding the cubical halfedge
return value - the spherical halfedge handle that ihandle is part of it
*/
static
Halfedge_handle outHandle(Int_halfedge_handle ihandle, CGM *cgm) {
// search for halfedeg with real target
while (!(ihandle->target()->getReal())) {
// advance
ihandle = ihandle->next();
// if on cube unreal halfedge, traverse adjacents until real halfedge
while (!ihandle->get_is_real()) {
ihandle = cgm->get_adjacent_halfedge_handle(ihandle);
ihandle = ihandle->next();
}
}
return *((Halfedge_handle *)(ihandle->getSphereEdge()));
}
private:
/*
mark a connected component boundary starting at ccbHandle
ccbHandle - a cubical halfedge handle on the ccb to be marked
*/
void markCcb(Int_halfedge_handle ccbHandle) {
Int_halfedge_handle cur;
cur = ccbHandle;
// traverse cgm ccb halfedges
do {
cur = cur->next(); // advance a halfedge
// if on cube unreal halfedge, traverse adjacents until real halfedge
while (!cur->get_is_real()) {
cur = m_cgm->get_adjacent_halfedge_handle(cur);
cur = cur->next();
}
cur->setMark(); // mark cgm halfedge
} while (!(cur == ccbHandle));
}
CGM * m_cgm; // the internal cubical gaussian map
// a cubical gaussian map face corresponding the spherical face, part of the
// spherical face
Int_face_handle m_cubeFace;
// are ccb structures valid or needed to be updated
bool m_dirty;
bool m_doesOuterExist; // is there an outer ccb to the spherical face
Ccb_halfedge_circulator m_outerCcb;
HolesList m_holes; // list of face holes
};
private:
public:
typedef typename CGM::Arr_ccb_halfedge_circulator Int_Ccb_halfedge_circulator;
typedef typename CGM::Arr_face_handle Int_face_handle;
typedef std::list<Int_face_handle> IntFaceList;
public:
/*
find all faces on cube that represents the same sphere face
cgm - the cubical gaussian map
faces - will hold the cubical faces that represents the sphere face
startFace - one cubical face of the sphere face
*/
static void connectedFaces(CGM &cgm, IntFaceList &faces, Int_face_handle &startFace) {
connectedFacesRec(cgm, faces, startFace); // find connected sub faces
typename IntFaceList::iterator fit;
// clear the sub-faces mark
for (fit = faces.begin(); fit != faces.end(); fit++) {
(*fit)->setMark(false);
}
}
/*
find all faces on cube that represents the same sphere face by recursivley
traversing all adjacent faces, leave faces marked
cgm - the cubical gaussian map
faces - will hold the cubical faces that represents the sphere face
startFace - one cubical face of the sphere face
*/
static void connectedFacesRec(CGM &cgm, IntFaceList &faces,
Int_face_handle &startFace) {
if (startFace->getMark() || startFace->is_unbounded()) {
// face has already been processed or outside the cube
return;
}
startFace->setMark(true); // mark face as processed
faces.push_back(startFace); // add to list of faces
Int_Ccb_halfedge_circulator ccbIt, ccbEnd;
if (startFace->is_unbounded()) {
// the cgm face should be on the cube
std::cerr << "unbounded, no boudary" << std::endl;
}
ccbIt = startFace->outer_ccb();
ccbEnd = ccbIt;
do {
if (!ccbIt->get_is_real()) {
// an unreal boundary, continue in adjacent face
Int_face_handle nextFace = (cgm.get_adjacent_halfedge_handle(ccbIt))->face();
// process adjacent cgm face
connectedFacesRec(cgm, faces, nextFace);
}
ccbIt++;
} while (ccbIt != ccbEnd);
};
};
CGAL_END_NAMESPACE
#endif