BOOKS i'm reading |
/* * Module ID: dcel.cpp * Titre : Definition de la classe DCEL (doubly connected edge list). * Utilite : Structure de donnee pour contenir les aretes d'un graphe * planaire comme decrit dans 'Computational Geometry' de * Franco P. Preparata & Michael Ian Shamos (P. 15) * * Auteur : Olivier Langlois (olivier@olivierlanglois.net) * Date : 08 Mars 1998 * * Revision : * * 001 27-Mar-1998 - Olivier Langlois * Les fstreams ne fonctionnent pas avec le compilateur GNU 2.7.2.1 * lorsque compile avec l'option -frtti. */ #ifdef __GNUG__ #include <std/typeinfo.h> #include "umath.h" #else #include <math.h> // Pour HUGE_VAL #endif #include "collect/idlist.h" #include "../tools/collect/pq.cpp" #include "geo/point.h" #include "geo/segment.h" #include "geo/ray.h" #include "collect/colvar.h" #include "geo/dcel.h" #include <limits.h> DEFINE_COLLECTABLE(VerticesDictionary , __VERTICESDICT) DEFINE_COLLECTABLE(vertex, __VERTEX) DEFINE_COLLECTABLE(face , __FACE) DEFINE_COLLECTABLE(edge , __EDGE) DEFINE_COLLECTABLE(DCEL , __DCEL) /****************************************************************************** * * Nom : removeIdx * ****************************************************************************/ void graphObject::removeIdx( const CollectableULong *key ) { delete edgeIdxList.remove(&IDList::CollectableIsEqual, (void *)(Collectable *)key ); } /****************************************************************************** * * Nom : addIdx * ****************************************************************************/ void graphObject::addIdx ( const CollectableULong *key ) { D( if( edgeIdxList.contains(&IDList::CollectableIsEqual, (void *)(Collectable *)key ) == BOOL_TRUE ) cerr << "graphObject::addIdx : Clef deja presente" << endl; ) edgeIdxList.insert( dynamic_cast< IsvDlink * >(key->copy()) ); } /****************************************************************************** * * Nom : restoreList * ****************************************************************************/ #ifdef __GNUG__ void graphObject::restoreList( FILE *is ) #else void graphObject::restoreList( istream &is ) #endif { edgeIdxList.restoreGuts(is); IDList *tmpPtr = &edgeIdxList; RESTORE_IDLIST_ITEM( tmpPtr, CollectableULong, is ) setRefCount( edgeIdxList.entries() ); } /****************************************************************************** * * Nom : clear * ****************************************************************************/ void VerticesDictionary::clear() { xmin.value(ULONG_MAX); xmax.value(ULONG_MAX); ymin.value(ULONG_MAX); ymax.value(ULONG_MAX); Dictionary::clear(); } /****************************************************************************** * * Nom : Insert * * Utilite : Insere un vertex et sa clef dans le dictionaire. * * Reference : dcel.h * ****************************************************************************/ void VerticesDictionary::Insert(const Collectable *kx, const Collectable *dx ) { D( cout << "Insert #" << ((const CollectableULong *)kx)->value(); ) D( cout << " " << *(point *)dx << endl; ) if( xmin.value() == ULONG_MAX ) xmin.value(((const CollectableULong *)kx)->value()); else { if( point::cmp_xy( *((const vertex *)dx), *dynamic_cast< vertex * >(getValue(&xmin)) ) < 0 ) xmin.value(((const CollectableULong *)kx)->value()); } if( xmax.value() == ULONG_MAX ) xmax.value(((const CollectableULong *)kx)->value()); else { if( point::cmp_xy( *((const vertex *)dx), *dynamic_cast< vertex * >(getValue(&xmax)) ) > 0 ) xmax.value(((const CollectableULong *)kx)->value()); } if( ymin.value() == ULONG_MAX ) ymin.value(((const CollectableULong *)kx)->value()); else { if( point::cmp_yx( *((const vertex *)dx), *dynamic_cast< vertex * >(getValue(&ymin)) ) < 0 ) ymin.value(((const CollectableULong *)kx)->value()); } if( ymax.value() == ULONG_MAX ) ymax.value(((const CollectableULong *)kx)->value()); else { if( point::cmp_yx( *((const vertex *)dx), *dynamic_cast< vertex * >(getValue(&ymax)) ) > 0 ) ymax.value(((const CollectableULong *)kx)->value()); } Dictionary::Insert( kx, dx ); } /****************************************************************************** * * Nom : remove * * Utilite : Enleve un vertex associee a la clef specifiee. * * Reference : dcel.h * ****************************************************************************/ Collectable *VerticesDictionary::remove(const Collectable *kx) { Collectable *result = Dictionary::remove(kx); D( cout << "remove #" << ((const CollectableULong *)kx)->value(); ) if( result ) { D( cout << " " << *(point *)result << endl; ) if( isEmpty() == BOOL_TRUE ) { xmin.value(ULONG_MAX); xmax.value(ULONG_MAX); ymin.value(ULONG_MAX); ymax.value(ULONG_MAX); } else { vertex *tmp; DictIterator it(*this); if( xmin.value() == ((const CollectableULong *)kx)->value() ) { ++it; tmp = dynamic_cast< vertex * >(it.getValue()); xmin.value(dynamic_cast< CollectableULong * >(it.getKey())->value()); while( ++it == BOOL_TRUE ) { if( point::cmp_xy( *dynamic_cast< vertex * >(it.getValue()), *tmp ) < 0 ) { tmp = dynamic_cast< vertex * >(it.getValue()); xmin.value(dynamic_cast< CollectableULong * >(it.getKey())->value()); } } } if( xmax.value() == ((const CollectableULong *)kx)->value() ) { it.reset(); ++it; tmp = dynamic_cast< vertex * >(it.getValue()); xmax.value(dynamic_cast< CollectableULong * >(it.getKey())->value()); while( ++it == BOOL_TRUE ) { if( point::cmp_xy( *dynamic_cast< vertex * >(it.getValue()), *tmp ) > 0 ) { tmp = dynamic_cast< vertex * >(it.getValue()); xmax.value(dynamic_cast< CollectableULong * >(it.getKey())->value()); } } } if( ymin.value() == ((const CollectableULong *)kx)->value() ) { it.reset(); ++it; tmp = dynamic_cast< vertex * >(it.getValue()); ymin.value(dynamic_cast< CollectableULong * >(it.getKey())->value()); while( ++it == BOOL_TRUE ) { if( point::cmp_yx( *dynamic_cast< vertex * >(it.getValue()), *tmp ) < 0 ) { tmp = dynamic_cast< vertex * >(it.getValue()); ymin.value(dynamic_cast< CollectableULong * >(it.getKey())->value()); } } } if( ymax.value() == ((const CollectableULong *)kx)->value() ) { it.reset(); ++it; tmp = dynamic_cast< vertex * >(it.getValue()); ymax.value(dynamic_cast< CollectableULong * >(it.getKey())->value()); while( ++it == BOOL_TRUE ) { if( point::cmp_yx( *dynamic_cast< vertex * >(it.getValue()), *tmp ) > 0 ) { tmp = dynamic_cast< vertex * >(it.getValue()); ymax.value(dynamic_cast< CollectableULong * >(it.getKey())->value()); } } } } // ELSE(isEmpty()) } // IF(result) return result; } vertex::vertex(const point &p) : graphObject(), point(p) {} vertex::~vertex() { } /****************************************************************************** * * Nom : isEqual * ****************************************************************************/ Boolean vertex::isEqual(const Collectable *v) const { if( v->isA() != __VERTEX ) return BOOL_FALSE; return operator==(*((const vertex *)v)); } /****************************************************************************** * * Nom : saveGuts * ****************************************************************************/ #ifdef __GNUG__ void vertex::saveGuts( FILE *os ) #else void vertex::saveGuts( ostream &os ) #endif { #ifdef __GNUG__ fwrite( &myAtom, sizeof(ClassID), 1, os ); #else os.write((char *)&myAtom, sizeof(ClassID)); #endif point::saveGuts(os); saveList(os); #ifdef __GNUG__ fwrite( &myAtom, sizeof(ClassID), 1, os ); #else os.write((char *)&myAtom, sizeof(ClassID)); #endif } /****************************************************************************** * * Nom : restoreGuts * ****************************************************************************/ #ifdef __GNUG__ void vertex::restoreGuts( FILE *is ) #else void vertex::restoreGuts( istream &is ) #endif { ClassID id; // Verifie la validite du fichier #ifdef __GNUG__ fread( &id, sizeof(ClassID), 1, is ); #else is.read( (char *)&id, sizeof(ClassID) ); #endif if( id != myAtom ) throw int(0); point::restoreGuts(is); restoreList(is); // Verifie de nouveau l'intregrite du fichier #ifdef __GNUG__ fread( &id, sizeof(ClassID), 1, is ); #else is.read( (char *)&id, sizeof(ClassID) ); #endif if( id != myAtom ) throw int(0); } /****************************************************************************** * * Nom : operator== * ****************************************************************************/ Boolean vertex::operator==(const vertex &v) const { return point::operator==(v)?BOOL_TRUE:BOOL_FALSE; } /****************************************************************************** * * Nom : operator== * ****************************************************************************/ Boolean face::operator==(const face &f) const { return (location == f.location)?BOOL_TRUE:BOOL_FALSE; } /****************************************************************************** * * Nom : isEqual * ****************************************************************************/ Boolean face::isEqual(const Collectable *f) const { if( f->isA() != __FACE ) return BOOL_FALSE; return operator==(*((const face *)f)); } /****************************************************************************** * * Nom : saveGuts * ****************************************************************************/ #ifdef __GNUG__ void face::saveGuts( FILE *os ) #else void face::saveGuts( ostream &os ) #endif { #ifdef __GNUG__ fwrite( &myAtom, sizeof(ClassID), 1, os ); #else os.write((char *)&myAtom, sizeof(ClassID)); #endif location.saveGuts(os); saveList(os); #ifdef __GNUG__ fwrite( &myAtom, sizeof(ClassID), 1, os ); #else os.write((char *)&myAtom, sizeof(ClassID)); #endif } /****************************************************************************** * * Nom : restoreGuts * ****************************************************************************/ #ifdef __GNUG__ void face::restoreGuts( FILE *is ) #else void face::restoreGuts( istream &is ) #endif { ClassID id; // Verifie la validite du fichier #ifdef __GNUG__ fread( &id, sizeof(ClassID), 1, is ); #else is.read( (char *)&id, sizeof(ClassID) ); #endif if( id != myAtom ) throw int(0); location.restoreGuts(is); restoreList(is); // Verifie de nouveau l'intregrite du fichier #ifdef __GNUG__ fread( &id, sizeof(ClassID), 1, is ); #else is.read( (char *)&id, sizeof(ClassID) ); #endif if( id != myAtom ) throw int(0); } edge::edge( DCEL *l, face *f1, face *f2, vertex *v1, vertex *v2 ) : associatedList(l), P1(ULONG_MAX), P2(ULONG_MAX), myKey(ULONG_MAX) { // N'est pas un edge Sentinel if( f1 && f2 && v1 && v2 ) { init(f1, f2, v1, v2 ); } else { // Juste au cas... if( f1 && !f1->references() ) delete f1; if( f2 && !f2->references() ) delete f2; if( v1 && !v1->references() ) delete v1; if( v2 && !v2->references() ) delete v2; throw GeoEx(GX_INVPAR); } } edge::edge( DCEL *l, face *f1, face *f2, const segment &s ) : associatedList(l), P1(ULONG_MAX), P2(ULONG_MAX), myKey(ULONG_MAX) { vertex *v1 = new vertex(s.source()); vertex *v2 = new vertex(s.target()); if( f1 && f2 && v1 && v2 ) { init(f1, f2, v1, v2 ); } else { // Juste au cas... if( f1 && !f1->references() ) delete f1; if( f2 && !f2->references() ) delete f2; delete v1; delete v2; throw GeoEx(GX_INVPAR); } } edge::edge( DCEL *l, face *f1, face *f2, const line &s ) : associatedList(l), P1(ULONG_MAX), P2(ULONG_MAX), myKey(ULONG_MAX) { vertex *v1 = new vertex(s.point1()); vertex *v2 = new vertex(s.point2()); if( f1 && f2 && v1 && v2 ) { init(f1, f2, v1, v2 ); } else { // Juste au cas... if( f1 && !f1->references() ) delete f1; if( f2 && !f2->references() ) delete f2; delete v1; delete v2; throw GeoEx(GX_INVPAR); } } /****************************************************************************** * * Nom : init * * Reference : dcel.h * ****************************************************************************/ void edge::init( face *f1, face *f2, vertex *v1, vertex *v2 ) { CollectableULong *key; if( key = (CollectableULong *)associatedList->Faces().getKey(f1) ) { if( !f1->references() ) delete f1; F1.value(key->value()); dynamic_cast< face * > (associatedList->Faces().getValue(key))->addReference(); } else { F1.value(associatedList->getNextFaceKey()); f1->addReference(); associatedList->Faces().Insert( F1.copy(), f1 ); } if( key = (CollectableULong *)associatedList->Faces().getKey(f2) ) { if( !f2->references() ) delete f2; F2.value(key->value()); dynamic_cast< face * > (associatedList->Faces().getValue(key))->addReference(); } else { F2.value(associatedList->getNextFaceKey()); f2->addReference(); associatedList->Faces().Insert( F2.copy(), f2 ); } if( key = (CollectableULong *)associatedList->Vertices().getKey(v1) ) { if( !v1->references() )delete v1; V1.value(key->value()); dynamic_cast< vertex * > (associatedList->Vertices().getValue(key))->addReference(); } else { V1.value(associatedList->getNextVertexKey()); v1->addReference(); associatedList->Vertices().Insert( V1.copy(), v1 ); } if( key = (CollectableULong *)associatedList->Vertices().getKey(v2) ) { if( !v2->references() ) delete v2; V2.value(key->value()); dynamic_cast< vertex * >(associatedList->Vertices().getValue(key))->addReference(); } else { V2.value(associatedList->getNextVertexKey()); v2->addReference(); associatedList->Vertices().Insert( V2.copy(), v2 ); } } edge::~edge() { associatedList->removeP1(this); associatedList->removeP2(this); face *f = getF1(); if( !f->removeReference() ) { delete associatedList->Faces().remove(&F1); } else if( myKey.value() != ULONG_MAX ) { f->removeIdx(&myKey); } f = getF2(); if( !f->removeReference() ) { delete associatedList->Faces().remove(&F2); } else if( myKey.value() != ULONG_MAX ) { f->removeIdx(&myKey); } vertex *v = getV1(); if( !v->removeReference() ) { delete associatedList->Vertices().remove(&V1); } else if( myKey.value() != ULONG_MAX ) { v->removeIdx(&myKey); } v = getV2(); if( !v->removeReference() ) { delete associatedList->Vertices().remove(&V2); } else if( myKey.value() != ULONG_MAX ) { v->removeIdx(&myKey); } } /****************************************************************************** * * Nom : isEqual * ****************************************************************************/ Boolean edge::isEqual(const Collectable *c) const { edge *e; if( c->isA() != __EDGE ) return BOOL_FALSE; else e = (edge *)c; if( F1.value() == e->F1.value() && F2.value() == e->F2.value() && V1.value() == e->V1.value() && V2.value() == e->V2.value() ) return BOOL_TRUE; else return BOOL_FALSE; } /****************************************************************************** * * Nom : saveGuts * ****************************************************************************/ #ifdef __GNUG__ void edge::saveGuts( FILE *os ) #else void edge::saveGuts( ostream &os ) #endif { #ifdef __GNUG__ fwrite( &myAtom, sizeof(ClassID), 1, os ); #else os.write((char *)&myAtom, sizeof(ClassID)); #endif V1.saveGuts(os); V2.saveGuts(os); F1.saveGuts(os); F2.saveGuts(os); P1.saveGuts(os); P2.saveGuts(os); myKey.saveGuts(os); #ifdef __GNUG__ fwrite( &myAtom, sizeof(ClassID), 1, os ); #else os.write((char *)&myAtom, sizeof(ClassID)); #endif } /****************************************************************************** * * Nom : restoreGuts * ****************************************************************************/ #ifdef __GNUG__ void edge::restoreGuts( FILE *is ) #else void edge::restoreGuts( istream &is ) #endif { ClassID id; // Verifie la validite du fichier #ifdef __GNUG__ fread( &id, sizeof(ClassID), 1, is ); #else is.read( (char *)&id, sizeof(ClassID) ); #endif if( id != myAtom ) throw int(0); V1.restoreGuts(is); V2.restoreGuts(is); F1.restoreGuts(is); F2.restoreGuts(is); P1.restoreGuts(is); P2.restoreGuts(is); myKey.restoreGuts(is); // Verifie de nouveau l'intregrite du fichier #ifdef __GNUG__ fread( &id, sizeof(ClassID), 1, is ); #else is.read( (char *)&id, sizeof(ClassID) ); #endif if( id != myAtom ) throw int(0); } /****************************************************************************** * * Nom : setMyKey * ****************************************************************************/ void edge::setMyKey( unsigned long key ) { myKey.value(key); dynamic_cast< face * >(associatedList->Faces().getValue(&F1))->addIdx(&myKey); if( F2.value() != F1.value() ) dynamic_cast< face * > (associatedList->Faces().getValue(&F2))->addIdx(&myKey); dynamic_cast< vertex * >(associatedList->Vertices().getValue(&V1))->addIdx(&myKey); if( V2.value() != V1.value() ) dynamic_cast< vertex * > (associatedList->Vertices().getValue(&V2))->addIdx(&myKey); } /****************************************************************************** * * Nom : getF1 * ****************************************************************************/ face *edge::getF1() const { // D( cout << "getF1 :" << F1.value() << endl; ) return (face *)associatedList->Faces().getValue(&F1); } /****************************************************************************** * * Nom : getF2 * ****************************************************************************/ face *edge::getF2() const { // D( cout << "getF2 :" << F2.value() << endl; ) return (face *)associatedList->Faces().getValue(&F2); } /****************************************************************************** * * Nom : getV1 * ****************************************************************************/ vertex *edge::getV1() const { // D( cout << "getV1 :" << V1.value() << endl; ) return (vertex *)associatedList->Vertices().getValue(&V1); } /****************************************************************************** * * Nom : getV2 * ****************************************************************************/ vertex *edge::getV2() const { // D( cout << "getV2 :" << V2.value() << endl; ) return (vertex *)associatedList->Vertices().getValue(&V2); } /****************************************************************************** * * Nom : setF1 * * Reference : dcel.h * ****************************************************************************/ void edge::setF1( face *f ) { CollectableULong *key; // Recupere l'ancienne face face *f1 = dynamic_cast< face * >(associatedList->Faces().getValue(&F1)); if( f1->isEqual(f) == BOOL_FALSE ) { if( !f1->removeReference() ) { delete associatedList->Faces().remove(&F1); } else if( myKey.value() != ULONG_MAX ) { f1->removeIdx(&myKey); } if( key = (CollectableULong *)associatedList->Faces().getKey(f) ) { if( !f->references() ) delete f; F1.value(key->value()); f = dynamic_cast< face * >(associatedList->Faces().getValue(key)); f->addReference(); if( myKey.value() != ULONG_MAX ) f->addIdx(&myKey); } else { F1.value(associatedList->getNextFaceKey()); f->addReference(); if( myKey.value() != ULONG_MAX ) f->addIdx(&myKey); associatedList->Faces().Insert( F1.copy(), f ); } } } /****************************************************************************** * * Nom : setF2 * * Reference : dcel.h * ****************************************************************************/ void edge::setF2( face *f ) { CollectableULong *key; // Recupere l'ancienne face face *f2 = dynamic_cast< face * >(associatedList->Faces().getValue(&F2)); if( f2->isEqual(f) == BOOL_FALSE ) { if( !f2->removeReference() ) { delete associatedList->Faces().remove(&F2); } else if( myKey.value() != ULONG_MAX ) { f2->removeIdx(&myKey); } if( key = (CollectableULong *)associatedList->Faces().getKey(f) ) { if( !f->references() ) delete f; F2.value(key->value()); f = dynamic_cast< face * >(associatedList->Faces().getValue(key)); f->addReference(); if( myKey.value() != ULONG_MAX ) f->addIdx(&myKey); } else { F1.value(associatedList->getNextFaceKey()); f->addReference(); if( myKey.value() != ULONG_MAX ) f->addIdx(&myKey); associatedList->Faces().Insert( F2.copy(), f ); } } } /****************************************************************************** * * Nom : setV1 * * Reference : dcel.h * ****************************************************************************/ void edge::setV1( vertex *p ) { CollectableULong *key; // Recupere l'ancienne face vertex *v1 = dynamic_cast< vertex * >(associatedList->Vertices().getValue(&V1)); if( v1->isEqual(p) == BOOL_FALSE ) { associatedList->removeP1(this); if( !v1->removeReference() ) { delete associatedList->Vertices().remove(&V1); } else if( myKey.value() != ULONG_MAX ) { v1->removeIdx(&myKey); } if( key = (CollectableULong *)associatedList->Vertices().getKey(p) ) { if( !p->references() ) delete p; V1.value(key->value()); p = dynamic_cast< vertex * >(associatedList->Vertices().getValue(key)); p->addReference(); } else { V1.value(associatedList->getNextVertexKey()); p->addReference(); associatedList->Vertices().Insert( V1.copy(), p ); } // Reajuste P1 if( myKey.value() != ULONG_MAX ) { associatedList->setP1( this, &myKey ); p->addIdx(&myKey); } } } /****************************************************************************** * * Nom : setV2 * * Reference : dcel.h * ****************************************************************************/ void edge::setV2( vertex *p ) { CollectableULong *key; // Recupere l'ancienne face vertex *v2 = dynamic_cast< vertex * >(associatedList->Vertices().getValue(&V2)); if( v2->isEqual(p) == BOOL_FALSE ) { associatedList->removeP2(this); if( !v2->removeReference() ) { delete associatedList->Vertices().remove(&V2); } else if( myKey.value() != ULONG_MAX ) { v2->removeIdx(&myKey); } if( key = (CollectableULong *)associatedList->Vertices().getKey(p) ) { if( !p->references() ) delete p; V2.value(key->value()); p = dynamic_cast< vertex * >(associatedList->Vertices().getValue(key)); p->addReference(); } else { V2.value(associatedList->getNextVertexKey()); p->addReference(); associatedList->Vertices().Insert( V2.copy(), p ); } // Reajuste P2 if( myKey.value() != ULONG_MAX ) { associatedList->setP2( this, &myKey ); p->addIdx(&myKey); } } } /****************************************************************************** * * Nom : atRight * ****************************************************************************/ Boolean edge::atRight( const point &p ) const { vertex *v1 = dynamic_cast< vertex * >(associatedList->Vertices().getValue(&V1)); vertex *v2 = dynamic_cast< vertex * >(associatedList->Vertices().getValue(&V2)); return right_turn( *v1, *v2, p ); } /****************************************************************************** * * Nom : intersection * ****************************************************************************/ Boolean edge::intersection( edge &e, point &p ) { point f1 = dynamic_cast< face * >(associatedList->Faces().getValue(&F1))->getLocation(); point f2 = dynamic_cast< face * >(associatedList->Faces().getValue(&F2))->getLocation(); point ef1 = e.getF1()->getLocation(); point ef2 = e.getF2()->getLocation(); return p_bisector( f1, f2 ).intersection( p_bisector( ef1, ef2 ), p ); } DCEL::DCEL() { init(); } /****************************************************************************** * * Nom : init * ****************************************************************************/ void DCEL::init( void ) { nextVertexKey = 0; nextFaceKey = 0; nextEdgeKey = 0; } DCEL::~DCEL() { clear(); } /****************************************************************************** * * Nom : clear * ****************************************************************************/ void DCEL::clear() { EdgesList.clear(); VerticesList.clear(); FacesList.clear(); nextVertexKey = 0; nextFaceKey = 0; nextEdgeKey = 0; } /****************************************************************************** * * Nom : getNextVertexKey * ****************************************************************************/ unsigned long DCEL::getNextVertexKey() { return nextVertexKey++; } /****************************************************************************** * * Nom : getNextFaceKey * ****************************************************************************/ unsigned long DCEL::getNextFaceKey() { return nextFaceKey++; } /****************************************************************************** * * Nom : getNextEdgeKey * ****************************************************************************/ unsigned long DCEL::getNextEdgeKey() { return nextEdgeKey++; } /****************************************************************************** * * Nom : getxminEdge * ****************************************************************************/ edge *DCEL::getxminEdge() { edge *result; CollectableULong xminIdx = VerticesList.getxminIdx(); vertex *xminV = (vertex *)VerticesList.getValue(&xminIdx); vertex *resultOtherVertex, *nextOtherVertex; if( xminV ) { const IDList *listPtr = xminV->getEdgeIdxList(); result = (edge *)EdgesList.getValue(listPtr->first()); // Trouve l'autre vertex. if( result->V1.value() == xminIdx.value() ) resultOtherVertex = (vertex *)VerticesList.getValue( &result->V2 ); else resultOtherVertex = (vertex *)VerticesList.getValue( &result->V1 ); IDListIterator it(*listPtr); CollectableULong *idx; edge *nextEdge; while( (idx = (CollectableULong *)++it) ) { nextEdge = (edge *)EdgesList.getValue(idx); if( nextEdge->V1.value() == xminIdx.value() ) nextOtherVertex = (vertex *)VerticesList.getValue( &nextEdge->V2 ); else nextOtherVertex = (vertex *)VerticesList.getValue( &nextEdge->V1 ); if( nextOtherVertex->xcoord() < resultOtherVertex->xcoord() ) { result = nextEdge; resultOtherVertex = resultOtherVertex; } } return result; } else return NULL; } /****************************************************************************** * * Nom : getyminEdge * ****************************************************************************/ edge *DCEL::getyminEdge() { edge *result; CollectableULong yminIdx = VerticesList.getyminIdx(); vertex *yminV = (vertex *)VerticesList.getValue(&yminIdx); vertex *resultOtherVertex, *nextOtherVertex; if( yminV ) { const IDList *listPtr = yminV->getEdgeIdxList(); result = (edge *)EdgesList.getValue(listPtr->first()); // Trouve l'autre vertex. if( result->V1.value() == yminIdx.value() ) resultOtherVertex = (vertex *)VerticesList.getValue( &result->V2 ); else resultOtherVertex = (vertex *)VerticesList.getValue( &result->V1 ); IDListIterator it(*listPtr); CollectableULong *idx; edge *nextEdge; while( (idx = (CollectableULong *)++it) ) { nextEdge = (edge *)EdgesList.getValue(idx); if( nextEdge->V1.value() == yminIdx.value() ) nextOtherVertex = (vertex *)VerticesList.getValue( &nextEdge->V2 ); else nextOtherVertex = (vertex *)VerticesList.getValue( &nextEdge->V1 ); if( nextOtherVertex->ycoord() < resultOtherVertex->ycoord() ) { result = nextEdge; resultOtherVertex = resultOtherVertex; } } return result; } else return NULL; } /****************************************************************************** * * Nom : getxmaxEdge * ****************************************************************************/ edge *DCEL::getxmaxEdge() { edge *result; CollectableULong xmaxIdx = VerticesList.getxmaxIdx(); vertex *xmaxV = (vertex *)VerticesList.getValue(&xmaxIdx); vertex *resultOtherVertex, *nextOtherVertex; if( xmaxV ) { const IDList *listPtr = xmaxV->getEdgeIdxList(); result = (edge *)EdgesList.getValue(listPtr->first()); // Trouve l'autre vertex. if( result->V1.value() == xmaxIdx.value() ) resultOtherVertex = (vertex *)VerticesList.getValue( &result->V2 ); else resultOtherVertex = (vertex *)VerticesList.getValue( &result->V1 ); IDListIterator it(*listPtr); CollectableULong *idx; edge *nextEdge; while( (idx = (CollectableULong *)++it) ) { nextEdge = (edge *)EdgesList.getValue(idx); if( nextEdge->V1.value() == xmaxIdx.value() ) nextOtherVertex = (vertex *)VerticesList.getValue( &nextEdge->V2 ); else nextOtherVertex = (vertex *)VerticesList.getValue( &nextEdge->V1 ); if( nextOtherVertex->xcoord() > resultOtherVertex->xcoord() ) { result = nextEdge; resultOtherVertex = resultOtherVertex; } } return result; } else return NULL; } /****************************************************************************** * * Nom : getymaxEdge * ****************************************************************************/ edge *DCEL::getymaxEdge() { edge *result; CollectableULong ymaxIdx = VerticesList.getymaxIdx(); vertex *ymaxV = (vertex *)VerticesList.getValue(&ymaxIdx); vertex *resultOtherVertex, *nextOtherVertex; if( ymaxV ) { const IDList *listPtr = ymaxV->getEdgeIdxList(); result = (edge *)EdgesList.getValue(listPtr->first()); // Trouve l'autre vertex. if( result->V1.value() == ymaxIdx.value() ) resultOtherVertex = (vertex *)VerticesList.getValue( &result->V2 ); else resultOtherVertex = (vertex *)VerticesList.getValue( &result->V1 ); IDListIterator it(*listPtr); CollectableULong *idx; edge *nextEdge; while( (idx = (CollectableULong *)++it) ) { nextEdge = (edge *)EdgesList.getValue(idx); if( nextEdge->V1.value() == ymaxIdx.value() ) nextOtherVertex = (vertex *)VerticesList.getValue( &nextEdge->V2 ); else nextOtherVertex = (vertex *)VerticesList.getValue( &nextEdge->V1 ); if( nextOtherVertex->ycoord() > resultOtherVertex->ycoord() ) { result = nextEdge; resultOtherVertex = resultOtherVertex; } } return result; } else return NULL; } /****************************************************************************** * * Nom : setP1 * ****************************************************************************/ void DCEL::setP1( edge *e, CollectableULong *key ) { edge *lastEdge, *curEdge; segment lastSegment, curSegment; const IDList *edgeIdxListPtr; size_t numEdge; edgeIdxListPtr = dynamic_cast< vertex * > (VerticesList.getValue(&e->V1))->getEdgeIdxList(); if( (numEdge = edgeIdxListPtr->entries()) > 0 ) { curEdge = (edge *)EdgesList.getValue( edgeIdxListPtr->first() ); if( numEdge > 1 ) { for( size_t i = 0; i < numEdge; i++ ) { lastEdge = curEdge; D( cout << "lastEdge P1, P2:" << lastEdge->P1.value() << " " << lastEdge->P2.value() << endl; ) curEdge = (edge *) EdgesList.getValue((e->V1.value()==lastEdge->V1.value())?&lastEdge->P1:&lastEdge->P2); if( e->V1.value() == curEdge->V1.value() ) curSegment = segment(*curEdge->getV1(),*curEdge->getV2()); else curSegment = segment(*curEdge->getV2(), *curEdge->getV1() ); if( e->V1.value() == lastEdge->V1.value() ) lastSegment = segment(*lastEdge->getV1(),*lastEdge->getV2()); else lastSegment = segment(*lastEdge->getV2(),*lastEdge->getV1()); if( segment( *e->getV1(), *e->getV2()).angle( curSegment ) > lastSegment.angle( curSegment ) ) break; D( if( e->getSegment().angle( curSegment ) >= lastEdge->getSegment().angle( curSegment ) ) cout << e->getSegment() << endl << curSegment << endl << lastEdge->getSegment() << endl; ) D( if( e->getSegment().angle( curSegment ) >= lastEdge->getSegment().angle( curSegment ) ) cout << e->getSegment().angle( curSegment ) << " " << lastEdge->getSegment().angle( curSegment ) << endl; ) } // Verifie les cas limites lorsque le # d'aretes connectees est 2. if( numEdge == 2 && segment( *e->getV1(), *e->getV2()).angle( curSegment ) > lastSegment.angle( curSegment ) && left_turn(curSegment.target(),*e->getV1(),*e->getV2()) == BOOL_TRUE) { edge *tmp = curEdge; curEdge = lastEdge; lastEdge = tmp; } } else lastEdge = curEdge; e->P1.value(curEdge->myKey.value()); if( lastEdge->V1.value() == e->V1.value() ) lastEdge->P1.value(key->value()); else lastEdge->P2.value(key->value()); } } /****************************************************************************** * * Nom : setP2 * ****************************************************************************/ void DCEL::setP2( edge *e, CollectableULong *key ) { edge *lastEdge, *curEdge; segment lastSegment, curSegment; const IDList *edgeIdxListPtr; size_t numEdge; edgeIdxListPtr = dynamic_cast< vertex * > (VerticesList.getValue(&e->V2))->getEdgeIdxList(); if( (numEdge = edgeIdxListPtr->entries()) > 0 ) { curEdge = (edge *)EdgesList.getValue( edgeIdxListPtr->first() ); if( numEdge > 1 ) { for( size_t i = 0; i < numEdge; i++ ) { lastEdge = curEdge; D( cout << "lastEdge P1, P2:" << lastEdge->P1.value() << " " << lastEdge->P2.value() << endl; ) curEdge = (edge *) EdgesList.getValue((e->V2.value()==lastEdge->V1.value())?&lastEdge->P1:&lastEdge->P2); if( e->V1.value() == curEdge->V1.value() ) curSegment = segment(*curEdge->getV1(),*curEdge->getV2()); else curSegment = segment(*curEdge->getV2(), *curEdge->getV1() ); if( e->V1.value() == lastEdge->V1.value() ) lastSegment = segment(*lastEdge->getV1(),*lastEdge->getV2()); else lastSegment = segment(*lastEdge->getV2(),*lastEdge->getV1()); if( segment( *e->getV2(), *e->getV1()).angle( curSegment ) > lastSegment.angle( curSegment ) ) break; D( if( e->getSegment().angle( curSegment ) >= lastEdge->getSegment().angle( curSegment ) ) cout << e->getSegment() << endl << curSegment << endl << lastEdge->getSegment() << endl; ) D( if( e->getSegment().angle( curSegment ) >= lastEdge->getSegment().angle( curSegment ) ) cout << e->getSegment().angle( curSegment ) << " " << lastEdge->getSegment().angle( curSegment ) << endl; ) } // Verifie les cas limites lorsque le # d'aretes connectees est 2. if( numEdge == 2 && segment( *e->getV2(), *e->getV1()).angle( curSegment ) > lastSegment.angle( curSegment ) && left_turn(curSegment.target(),*e->getV2(),*e->getV1()) == BOOL_TRUE) { edge *tmp = curEdge; curEdge = lastEdge; lastEdge = tmp; } } else lastEdge = curEdge; e->P2.value(curEdge->myKey.value()); if( lastEdge->V1.value() == e->V2.value() ) lastEdge->P1.value(key->value()); else lastEdge->P2.value(key->value()); } } /****************************************************************************** * * Nom : removeP1 * ****************************************************************************/ void DCEL::removeP1( edge *e ) { if( e->P1.value() != ULONG_MAX ) { edge *nextEdge = (edge *)EdgesList.getValue(&e->P1); vertex *v1 = e->getV1(); if( v1->getEdgeIdxList()->entries() > 2 ) { unsigned long p1 = e->P1.value(); do { if( nextEdge->V1.value() == e->V1.value() ) nextEdge = (edge *)EdgesList.getValue(&nextEdge->P1); else nextEdge = (edge *)EdgesList.getValue(&nextEdge->P2); } while( nextEdge->P1.value() != e->myKey.value() && nextEdge->P2.value() != e->myKey.value() ); if( nextEdge->V1.value() == e->V1.value() ) nextEdge->P1.value(p1); else nextEdge->P2.value(p1); } else { if( e->V1.value() == nextEdge->V1.value() ) nextEdge->P1.value(ULONG_MAX); else nextEdge->P2.value(ULONG_MAX); } e->P1.value(ULONG_MAX); } } /****************************************************************************** * * Nom : removeP2 * ****************************************************************************/ void DCEL::removeP2( edge *e ) { if( e->P2.value() != ULONG_MAX ) { edge *nextEdge = (edge *)EdgesList.getValue(&e->P2); vertex *v2 = e->getV2(); if( v2->getEdgeIdxList()->entries() > 2 ) { unsigned long p2 = e->P2.value(); do { if( nextEdge->V2.value() == e->V2.value() ) nextEdge = (edge *)EdgesList.getValue(&nextEdge->P2); else nextEdge = (edge *)EdgesList.getValue(&nextEdge->P1); } while( nextEdge->P1.value() != e->myKey.value() && nextEdge->P2.value() != e->myKey.value() ); if( nextEdge->V1.value() == e->V2.value() ) nextEdge->P1.value(p2); else nextEdge->P2.value(p2); } else { if( e->V2.value() == nextEdge->V1.value() ) nextEdge->P1.value(ULONG_MAX); else nextEdge->P2.value(ULONG_MAX); } e->P2.value(ULONG_MAX); } } /****************************************************************************** * * Nom : insertEdge * * Reference : dcel.h * ****************************************************************************/ int DCEL::insertEdge( edge *e ) { const IDList *edgeIdxListPtr; D( if( point::cmp_xy(*e->getV1(),*e->getV2()) > 0 ) cout << "DCEL::insertEdge : V1 > V2" << endl; ) D( cout << "insert :" << e->getSegment() << endl; ) // Pour etre valide, une arete doit avoir 2 vertices distincts. if( e->V1.value() == e->V2.value() ) { delete e; return -1; } CollectableULong *key = new CollectableULong(getNextEdgeKey()); // Branche V1 edgeIdxListPtr = dynamic_cast< vertex * > (VerticesList.getValue(&e->V1))->getEdgeIdxList(); if( edgeIdxListPtr->entries() > 0 ) { // Verifie si on essaie d'inserer plus d'une fois la meme arete. DictIterator it(EdgesList); while( ++it == BOOL_TRUE ) { if( e->isEqual(it.getValue()) == BOOL_TRUE ) { delete e; delete key; return -1; } } } setP1(e, key); // Branche V2 setP2(e, key); D( cout << "New edge:" << key->value() << endl; ) e->setMyKey( key->value() ); EdgesList.Insert( key, e ); return 0; } /****************************************************************************** * * Nom : setBox * * Utilite : Ferme le graph a l'interieur d'une boite. * * Reference : dcel.h * ****************************************************************************/ void DCEL::setBox( polygon &poly ) { face *outside = new face(point(-1000,-1000)); BoxInfo *curInfo; segment *segPtr; PQ<BoxInfo> *curPQ; const IDList &segmentsList = poly.segments(); IDList PQList; Boolean found; BoxInfo Sentinel; Sentinel.Key = -HUGE_VAL; #ifndef __GNUG__ PQ<BoxInfo>::setSentinel(&Sentinel); for( size_t i = segmentsList.entries()+1; --i; ) { PQList.insert( new CollectableDlink( new PQ<BoxInfo> ) ); } #else for( int i = 0; i < segmentsList.entries(); i++ ) { curPQ = new PQ<BoxInfo>; curPQ->setSentinel(&Sentinel); PQList.insert( new CollectableDlink( curPQ ) ); } #endif IDListIterator segIT(segmentsList); IDListIterator pqIT(PQList); /* vertex *lbV = new vertex(*lb); vertex *rbV = new vertex(point(ub->xcoord(),lb->ycoord())); vertex *luV = new vertex(point(lb->xcoord(),ub->ycoord())); vertex *ruV = new vertex(*ub); segment d(*lbV,*rbV); segment l(*lbV,*luV); segment u(*luV,*ruV); segment r(*rbV,*ruV); */ edge *edgePtr; vertex *newVertex, *oldVertex; IDList edgeToRemove; segment curSeg; point interLocation; { D( cout << "Trouve les intersections" << endl; ) DictIterator it(Edges()); // Trouve les intersections. // Pas optimal, possibilite d'optimisation ? while( ++it == BOOL_TRUE ) { edgePtr = (edge *)it.getValue(); curSeg = edgePtr->getSegment(); found = BOOL_FALSE; while( found == BOOL_FALSE && (segPtr = (segment *)++segIT) && (curPQ = (PQ<BoxInfo> *)((CollectableDlink *)++pqIT)->item )) { if( segPtr->intersection(curSeg, interLocation) == BOOL_TRUE ) { newVertex = new vertex(interLocation); if( segPtr->contains( *edgePtr->getV1() ) == BOOL_FALSE && segPtr->contains( *edgePtr->getV2() ) == BOOL_FALSE ) { // Si un des vertices est deja contenu dans le segment, // il n'est pas necessaire d'ajuster les vertices. if(right_turn( segPtr->source(), segPtr->target(), *edgePtr->getV1() ) == BOOL_TRUE) { edgePtr->setV1(newVertex); if( poly.outside(*edgePtr->getV2()) == BOOL_FALSE ) found = BOOL_TRUE; } else { edgePtr->setV2(newVertex); if( poly.outside(*edgePtr->getV1()) == BOOL_FALSE ) found = BOOL_TRUE; } } curInfo = new BoxInfo; curInfo->Vertex = newVertex; curInfo->leftFace = edgePtr->getF1(); curInfo->rightFace = edgePtr->getF2(); if( right_turn( curInfo->leftFace->getLocation(), curInfo->rightFace->getLocation(), *newVertex) == BOOL_FALSE ) { face *tmpFace = curInfo->leftFace; curInfo->leftFace = curInfo->rightFace; curInfo->rightFace = tmpFace; } curInfo->Key = segPtr->source().distance(*newVertex); curPQ->insert(curInfo); // L'arete a change curSeg = edgePtr->getSegment(); } } //WHILE(segment) if( poly.outside(curSeg.source()) == BOOL_TRUE || poly.outside(curSeg.target()) == BOOL_TRUE ) { edgeToRemove.insert( (IsvDlink *)edgePtr->myKey.copy() ); } segIT.reset(); pqIT.reset(); } // WHILE(edge) } CollectableULong *idx; while( (idx = (CollectableULong *)edgeToRemove.get()) ) { delete EdgesList.remove(idx); delete idx; } D( cout << "Connecte les aretes qui n'ont qu'une seule connection au diagramme" << endl; ) { // Connecte les aretes qui n'ont qu'une seule connection au diagramme // Une copie du dictionnaire de Vertices est utilise car on ne peut // utiliser un iterateur et modifier le dictionnaire qui lui est associe. Dictionary tmpDict(VerticesList); DictIterator VerticesIt(tmpDict); while( ++VerticesIt == BOOL_TRUE ) { Boolean V1isSource; oldVertex = (vertex *)VerticesIt.getValue(); if( oldVertex->getEdgeIdxList()->entries() == 1 && // S'assure que ce n'est pas un vertex cree par l'etape precedente poly.contains(*oldVertex) == BOOL_FALSE ) { vertex *sourceVertex; edgePtr = getEdge((CollectableULong *) oldVertex->getEdgeIdxList()->first()); sourceVertex = edgePtr->getV1(); if( oldVertex->isEqual(sourceVertex) == BOOL_TRUE ) { sourceVertex = edgePtr->getV2(); V1isSource = BOOL_FALSE; } else { V1isSource = BOOL_TRUE; } D( if( sourceVertex->getEdgeIdxList()->entries() == 1 ) cout << "DCEL::clean() n'a pas fait sa job" << endl; ) ray curRay(*sourceVertex,*oldVertex); found = BOOL_FALSE; while( found == BOOL_FALSE && (segPtr = (segment *)++segIT) && (curPQ = (PQ<BoxInfo> *)((CollectableDlink *)++pqIT)->item )) { if( curRay.intersection(*segPtr,interLocation) == BOOL_TRUE && interLocation != *sourceVertex ) { newVertex = new vertex(interLocation); if(V1isSource == BOOL_TRUE) { edgePtr->setV2(newVertex); } else { edgePtr->setV1(newVertex); } curInfo = new BoxInfo; curInfo->Vertex = newVertex; curInfo->leftFace = edgePtr->getF1(); curInfo->rightFace = edgePtr->getF2(); if( right_turn( curInfo->leftFace->getLocation(), curInfo->rightFace->getLocation(), *newVertex) == BOOL_FALSE ) { face *tmpFace = curInfo->leftFace; curInfo->leftFace = curInfo->rightFace; curInfo->rightFace = tmpFace; } curInfo->Key = segPtr->source().distance(*newVertex); curPQ->insert(curInfo); found = BOOL_TRUE; } } segIT.reset(); pqIT.reset(); } // IF(vertex.entries() == 1) } // WHILE(vertex) } face *f1, *f2; double minDist; BoxInfo *lastInfo; while( (segPtr = (segment *)++segIT) && (curPQ = (PQ<BoxInfo> *)((CollectableDlink *)++pqIT)->item) ) { if( curPQ->isEmpty() == BOOL_TRUE ) { { DictIterator FaceIt(FacesList); if( ++FaceIt == BOOL_TRUE ) { f1 = (face *)FaceIt.getValue(); minDist = segPtr->distance(f1->getLocation()); while( ++FaceIt == BOOL_TRUE ) { f2 = (face *)FaceIt.getValue(); if( segPtr->distance(f2->getLocation()) < minDist ) { f1 = f2; minDist = segPtr->distance(f1->getLocation()); } } } } edgePtr = new edge( this, outside, f1, new vertex(segPtr->source()), new vertex(segPtr->target()) ); insertEdge(edgePtr); } else { lastInfo = curPQ->removeFirst(); edgePtr = new edge( this, outside, lastInfo->leftFace, new vertex(segPtr->source()), lastInfo->Vertex ); insertEdge(edgePtr); while( (curInfo = curPQ->removeFirst()) != &Sentinel ) { if( lastInfo->rightFace != curInfo->leftFace ) { D( cout << "lastInfo leftFace " << lastInfo->leftFace->getLocation() << " rightFace " << lastInfo->rightFace->getLocation() << endl; ) D( cout << "curInfo leftFace " << curInfo->leftFace->getLocation() << " rightFace " << curInfo->rightFace->getLocation() << endl; ) D( cout << "lastInfo Vertex " << *lastInfo->Vertex << " curInfo Vertex " << *curInfo->Vertex << endl; ) throw GeoEx(GX_CORFAC); } edgePtr = new edge( this, outside, lastInfo->rightFace, lastInfo->Vertex, curInfo->Vertex ); insertEdge(edgePtr); delete lastInfo; lastInfo = curInfo; } edgePtr = new edge( this, outside, lastInfo->rightFace, lastInfo->Vertex, new vertex(segPtr->target()) ); delete lastInfo; insertEdge(edgePtr); } } // WHILE(segment) } /****************************************************************************** * * Nom : clean * * Utilite : Elimine toutes les aretes non connectees. * * Reference : dcel.h * ****************************************************************************/ void DCEL::clean() { // Une liste est necessaire car on ne peut modifier un dictionnaire en // utilisant un iterateur sur ce dictionnaire en meme temps. IDList edgeToRemove; vertex *curVertex; Collectable *idx; D( cout << "Entering DCEL::clean()" << endl; ) { DictIterator it(Vertices()); while( ++it == BOOL_TRUE ) { curVertex = (vertex *)it.getValue(); const IDList *listPtr = curVertex->getEdgeIdxList(); if( listPtr->entries() == 1 ) { idx = (CollectableULong *)listPtr->first(); edge *curEdge = (edge *)EdgesList.getValue(idx); if( ((CollectableULong *)it.getKey())->value() == curEdge->V1.value() ) { curVertex = curEdge->getV2(); } else { curVertex = curEdge->getV1(); } if( curVertex->getEdgeIdxList()->entries() == 1 && edgeToRemove.contains(&IDList::CollectableIsEqual, (void *)(Collectable *)idx ) == BOOL_FALSE ) edgeToRemove.insert((IsvDlink *)idx->copy()); } } } while( (idx = (CollectableULong *)edgeToRemove.get()) ) { delete EdgesList.remove(idx); delete idx; } D( cout << "Exiting DCEL::clean()" << endl; ) } /****************************************************************************** * * Nom : saveGuts * ****************************************************************************/ #ifdef __GNUG__ void DCEL::saveGuts( FILE *os ) #else void DCEL::saveGuts( ostream &os ) #endif { #ifdef __GNUG__ fwrite( &myAtom, sizeof(ClassID), 1, os ); fwrite( &nextVertexKey, sizeof(unsigned long), 1, os ); fwrite( &nextFaceKey, sizeof(unsigned long), 1, os ); fwrite( &nextEdgeKey, sizeof(unsigned long), 1, os ); #else os.write((char *)&myAtom, sizeof(ClassID)); os.write((char *)&nextVertexKey, sizeof(unsigned long)); os.write((char *)&nextFaceKey, sizeof(unsigned long)); os.write((char *)&nextEdgeKey, sizeof(unsigned long)); #endif EdgesList.saveGuts(os); FacesList.saveGuts(os); VerticesList.saveGuts(os); #ifdef __GNUG__ fwrite( &myAtom, sizeof(ClassID), 1, os ); #else os.write((char *)&myAtom, sizeof(ClassID)); #endif } /****************************************************************************** * * Nom : restoreGuts * ****************************************************************************/ #ifdef __GNUG__ void DCEL::restoreGuts( FILE *is ) #else void DCEL::restoreGuts( istream &is ) #endif { ClassID id; // Verifie la validite du fichier #ifdef __GNUG__ fread( &id, sizeof(ClassID), 1, is ); #else is.read( (char *)&id, sizeof(ClassID) ); #endif if( id != myAtom ) throw int(0); clear(); #ifdef __GNUG__ fread( &nextVertexKey, sizeof(unsigned long), 1, is ); fread( &nextFaceKey, sizeof(unsigned long), 1, is ); fread( &nextEdgeKey, sizeof(unsigned long), 1, is ); #else is.read((char *)&nextVertexKey, sizeof(unsigned long)); is.read((char *)&nextFaceKey, sizeof(unsigned long)); is.read((char *)&nextEdgeKey, sizeof(unsigned long)); #endif Dictionary *tmpPtr; EdgesList.restoreGuts(is); tmpPtr = &EdgesList; RESTORE_DICT_ITEM( tmpPtr, CollectableULong, edge, is ) D( cout << EdgesList.entries() << " edges restaures" << endl; ) DictIterator it(EdgesList); edge *e; while( ++it == BOOL_TRUE ) { e = (edge *)it.getValue(); e->associatedList = this; } FacesList.restoreGuts(is); tmpPtr = &FacesList; RESTORE_DICT_ITEM( tmpPtr, CollectableULong, face, is ) VerticesList.restoreGuts(is); tmpPtr = &VerticesList; RESTORE_DICT_ITEM( tmpPtr, CollectableULong, vertex, is ) // Verifie de nouveau l'intregrite du fichier #ifdef __GNUG__ fread( &id, sizeof(ClassID), 1, is ); #else is.read( (char *)&id, sizeof(ClassID) ); #endif if( id != myAtom ) throw int(0); } #ifdef __GNUG__ template class PQ<BoxInfo>; #endif |