Anabatic transient commit 5.

* Bug: In Anabatic:
    - In Dijkstra/Vertex, use the new Observer for fast access from the GCells.
    - In Dijktra::propagate() loop detection.
    - In Dijkstra, reset the "_from" of vertexes between two propagates on
      the same Net (otherwise: loops...).
    - In Matrix, there must be two different way of calculating an index from
      a position. One for the min, which is rounded to superior. And one for
      the max which is rounded to inferior.
    - In Matrix::updateArea(), checks for invalid indexes.
This commit is contained in:
Jean-Paul Chaput 2016-06-03 17:29:22 +02:00
parent 747027f23a
commit aa20813342
9 changed files with 201 additions and 80 deletions

View File

@ -54,11 +54,21 @@ namespace Anabatic {
string s = "<Vertex " + getString(_id) string s = "<Vertex " + getString(_id)
+ " connexId:" + getString(_connexId) + " connexId:" + getString(_connexId)
+ " d:" + ((_distance == unreached) ? "unreached" : getString(_distance) ) + " d:" + ((_distance == unreached) ? "unreached" : getString(_distance) )
+ " stamp:" + (hasValidStamp() ? "valid" : "outdated")
+ " from:" + ((_from) ? "set" : "NULL")
+ ">"; + ">";
return s; return s;
} }
void Vertex::notify ( Vertex* vertex, unsigned int flags )
{
//Vertex* vertex = getOwner();
cdebug.log(111) << "Vertex::notify() " << vertex << endl;
// Take into account the GCell modification here.
}
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Class : "Anabatic::Dijkstra". // Class : "Anabatic::Dijkstra".
@ -117,12 +127,13 @@ namespace Anabatic {
_searchArea.merge( rpBb ); _searchArea.merge( rpBb );
Vertex* vertex = gcell->lookup<Vertex>(); Vertex* vertex = gcell->getObserver<Vertex>(GCell::Observable::Vertex);
if (vertex->getConnexId() < 0) { if (vertex->getConnexId() < 0) {
cdebug.log(111) << "Add Vertex: " << vertex << endl; cdebug.log(111) << "Add Vertex: " << vertex << endl;
vertex->setStamp ( _stamp ); vertex->setStamp ( _stamp );
vertex->setConnexId( _targets.size() ); vertex->setConnexId( _targets.size() );
vertex->setFrom ( NULL );
Contact* gcontact = vertex->getGContact( _net ); Contact* gcontact = vertex->getGContact( _net );
rp->getBodyHook()->detach(); rp->getBodyHook()->detach();
rp->getBodyHook()->attach( gcontact->getBodyHook() ); rp->getBodyHook()->attach( gcontact->getBodyHook() );
@ -182,7 +193,7 @@ namespace Anabatic {
if (edge == current->getFrom()) continue; if (edge == current->getFrom()) continue;
GCell* gneighbor = edge->getOpposite(current->getGCell()); GCell* gneighbor = edge->getOpposite(current->getGCell());
Vertex* vneighbor = gneighbor->lookup<Vertex>(); Vertex* vneighbor = gneighbor->getObserver<Vertex>(GCell::Observable::Vertex);
cdebug.log(111) << "Neighbor: " << vneighbor << endl; cdebug.log(111) << "Neighbor: " << vneighbor << endl;
@ -212,10 +223,21 @@ namespace Anabatic {
while ( current ) { while ( current ) {
cdebug.log(111) << "| " << current << endl; cdebug.log(111) << "| " << current << endl;
if ( (current->getConnexId() == _connectedsId) and (current->getFrom()) ) {
cerr << Error( "Dijkstra::propagate(): There is a loop in the traceback path\n"
" while routing %s."
, getString(_net).c_str()
) <<endl;
break;
}
_sources.insert( current ); _sources.insert( current );
current->setDistance( 0.0 ); current->setDistance( 0.0 );
current->setConnexId( _connectedsId ); current->setConnexId( _connectedsId );
current = current->getPredecessor();
Vertex* predecessor = current->getPredecessor();
current->setFrom( NULL );
current = predecessor;
} }
cdebug.tabw(111,-1); cdebug.tabw(111,-1);

View File

@ -32,14 +32,14 @@ namespace Anabatic {
, _flags(Flags::EastSide) , _flags(Flags::EastSide)
, _iedge(0) , _iedge(0)
{ {
cdebug.log(110) << "GCell_Edges::Locator::Locator() " << isValid() << endl; // cdebug.log(110) << "GCell_Edges::Locator::Locator() " << isValid() << endl;
if (_gcell->getEastEdges().empty()) progress(); if (_gcell->getEastEdges().empty()) progress();
} }
EdgesHL* GCell_Edges::Locator::getClone () const EdgesHL* GCell_Edges::Locator::getClone () const
{ {
cdebug.log(110) << "GCell_Edges::Locator::getClone()" << endl; // cdebug.log(110) << "GCell_Edges::Locator::getClone()" << endl;
return new Locator (*this); return new Locator (*this);
} }
@ -60,48 +60,48 @@ namespace Anabatic {
void GCell_Edges::Locator::progress () void GCell_Edges::Locator::progress ()
{ {
cdebug.log(110) << "GCell_Edges::Locator::progress() [from] " << _flags << " iedge:" << _iedge << endl; // cdebug.log(110) << "GCell_Edges::Locator::progress() [from] " << _flags << " iedge:" << _iedge << endl;
cdebug.log(110) << " East:" << _gcell->getEastEdges().size() // cdebug.log(110) << " East:" << _gcell->getEastEdges().size()
<< " North:" << _gcell->getNorthEdges().size() // << " North:" << _gcell->getNorthEdges().size()
<< " West:" << _gcell->getWestEdges().size() // << " West:" << _gcell->getWestEdges().size()
<< " South:" << _gcell->getSouthEdges().size() << endl; // << " South:" << _gcell->getSouthEdges().size() << endl;
cdebug.log(110) << this << endl; // cdebug.log(110) << this << endl;
++_iedge; ++_iedge;
while (_flags) { while (_flags) {
if (_flags.contains(Flags::EastSide)) { if (_flags.contains(Flags::EastSide)) {
if (_iedge < _gcell->getEastEdges().size()) break; if (_iedge < _gcell->getEastEdges().size()) break;
cdebug.log(110) << "Switching to North side." << endl; // cdebug.log(110) << "Switching to North side." << endl;
_flags = Flags::NorthSide; _flags = Flags::NorthSide;
_iedge = 0; _iedge = 0;
cdebug.log(110) << this << endl; // cdebug.log(110) << this << endl;
continue; continue;
} }
if (_flags.contains(Flags::NorthSide)) { if (_flags.contains(Flags::NorthSide)) {
if (_iedge < _gcell->getNorthEdges().size()) break; if (_iedge < _gcell->getNorthEdges().size()) break;
cdebug.log(110) << "Switching to West side." << endl; // cdebug.log(110) << "Switching to West side." << endl;
_flags = Flags::WestSide; _flags = Flags::WestSide;
_iedge = 0; _iedge = 0;
cdebug.log(110) << this << endl; // cdebug.log(110) << this << endl;
continue; continue;
} }
if (_flags.contains(Flags::WestSide)) { if (_flags.contains(Flags::WestSide)) {
if (_iedge < _gcell->getWestEdges().size()) break; if (_iedge < _gcell->getWestEdges().size()) break;
cdebug.log(110) << "Switching to South side." << endl; // cdebug.log(110) << "Switching to South side." << endl;
_flags = Flags::SouthSide; _flags = Flags::SouthSide;
_iedge = 0; _iedge = 0;
continue; continue;
} }
if (_flags.contains(Flags::SouthSide)) { if (_flags.contains(Flags::SouthSide)) {
if (_iedge < _gcell->getSouthEdges().size()) break; if (_iedge < _gcell->getSouthEdges().size()) break;
cdebug.log(110) << "All edges done." << endl; // cdebug.log(110) << "All edges done." << endl;
_flags = 0; _flags = 0;
_iedge = 0; _iedge = 0;
break;; break;;
} }
} }
cdebug.log(110) << "GCell_Edges::Locator::progress() [to] " << _flags << " iedge:" << _iedge << endl; // cdebug.log(110) << "GCell_Edges::Locator::progress() [to] " << _flags << " iedge:" << _iedge << endl;
} }

View File

@ -34,6 +34,7 @@ namespace Anabatic {
GCell::GCell ( AnabaticEngine* anabatic, DbU::Unit xmin, DbU::Unit ymin ) GCell::GCell ( AnabaticEngine* anabatic, DbU::Unit xmin, DbU::Unit ymin )
: Super(anabatic->getCell()) : Super(anabatic->getCell())
, _observable()
, _anabatic (anabatic) , _anabatic (anabatic)
, _flags (Flags::NoFlags) , _flags (Flags::NoFlags)
, _westEdges () , _westEdges ()
@ -43,7 +44,6 @@ namespace Anabatic {
, _xmin (xmin) , _xmin (xmin)
, _ymin (ymin) , _ymin (ymin)
, _contacts () , _contacts ()
, _lookup (NULL)
{ } { }
@ -418,6 +418,7 @@ namespace Anabatic {
cerr << Error( "GCell::_revalidate(): %s, Y Min is greater than Max.", getString(this).c_str() ); cerr << Error( "GCell::_revalidate(): %s, Y Min is greater than Max.", getString(this).c_str() );
_anabatic->_updateLookup( this ); _anabatic->_updateLookup( this );
_anabatic->getMatrix()->show();
cdebug.tabw(110,-1); cdebug.tabw(110,-1);
} }

View File

@ -16,6 +16,7 @@
#include <sstream> #include <sstream>
#include <iostream> #include <iostream>
#include <iomanip>
#include "hurricane/Cell.h" #include "hurricane/Cell.h"
#include "anabatic/Matrix.h" #include "anabatic/Matrix.h"
#include "anabatic/GCell.h" #include "anabatic/GCell.h"
@ -26,6 +27,8 @@ namespace Anabatic {
using std::cout; using std::cout;
using std::cerr; using std::cerr;
using std::endl; using std::endl;
using std::setw;
using std::setfill;
using std::ostringstream; using std::ostringstream;
using Hurricane::Error; using Hurricane::Error;
@ -46,8 +49,8 @@ namespace Anabatic {
, _imax (0) , _imax (0)
, _jmax (0) , _jmax (0)
{ {
_imax = _area.getWidth () / side; _imax = _area.getWidth () / side + ((_area.getWidth () % side) ? 1 : 0);
_jmax = _area.getHeight() / side; _jmax = _area.getHeight() / side + ((_area.getHeight() % side) ? 1 : 0);
_gcells.resize( _imax*_jmax ); _gcells.resize( _imax*_jmax );
} }
@ -60,25 +63,47 @@ namespace Anabatic {
{ {
_area = cell->getAbutmentBox(); _area = cell->getAbutmentBox();
_side = side; _side = side;
_imax = _area.getWidth () / side; _imax = _area.getWidth () / side + ((_area.getWidth () % side) ? 1 : 0);
_jmax = _area.getHeight() / side; _jmax = _area.getHeight() / side + ((_area.getHeight() % side) ? 1 : 0);
_gcells.resize( _imax*_jmax ); _gcells.resize( _imax*_jmax );
cdebug.log(110) << "Matrix::setCell(): " << this << endl;
} }
GCell* Matrix::getUnder ( DbU::Unit x, DbU::Unit y ) const GCell* Matrix::getUnder ( DbU::Unit x, DbU::Unit y ) const
{ int index = xy2index(x,y); return (index < 0) ? NULL : _gcells[index]->getUnder(x,y); } {
int index = xy2maxIndex(x,y);
cdebug.log(110) << "Matrix::getUnder() ("
<< DbU::getValueString(x) << " "
<< DbU::getValueString(y) << " " << index << endl;
return (index < 0) ? NULL : _gcells[index]->getUnder(x,y);
}
void Matrix::updateLookup ( GCell* gcell ) void Matrix::updateLookup ( GCell* gcell )
{ {
//cdebug.log(110,1) << "Matrix::updateLookup(): " << gcell << endl; cdebug.log(110,1) << "Matrix::updateLookup(): " << gcell << endl;
if (gcell->isFlat()) return; if (gcell->isFlat()) {
cdebug.log(110) << " GCell is flat, no update." << endl;
cdebug.tabw(110,-1);
return;
}
Box gcellBb = gcell->getBoundingBox(); Box gcellBb = gcell->getBoundingBox();
Box updateArea = _area.getIntersection( gcellBb ); Box updateArea = _area.getIntersection( gcellBb );
cdebug.log(110) << "_side " << _side << endl;
cdebug.log(110) << "_area.getXMin() " << _area.getXMin() << endl;
cdebug.log(110) << "_area.getYMin() " << _area.getYMin() << endl;
cdebug.log(110) << "_area.getXMax() " << _area.getXMax() << endl;
cdebug.log(110) << "_area.getYMax() " << _area.getYMax() << endl;
cdebug.log(110) << "updateArea.getXMin() " << updateArea.getXMin() << endl;
cdebug.log(110) << "updateArea.getYMin() " << updateArea.getYMin() << endl;
cdebug.log(110) << "updateArea.getXMax() " << updateArea.getXMax() << endl;
cdebug.log(110) << "updateArea.getYMax() " << updateArea.getYMax() << endl;
if (updateArea.isEmpty()) { if (updateArea.isEmpty()) {
cerr << Error( "Matrix::updateLookup(): %s is not under area of %s." cerr << Error( "Matrix::updateLookup(): %s is not under area of %s."
, getString(gcell).c_str() , getString(gcell).c_str()
@ -86,12 +111,20 @@ namespace Anabatic {
) << endl; ) << endl;
} }
Index indexMin = Index( this, updateArea.getXMin(), updateArea.getYMin() ); Index indexMin = Index::asMin( this, updateArea.getXMin(), updateArea.getYMin() );
Index indexMax = Index( this, updateArea.getXMax(), updateArea.getYMax() ); Index indexMax = Index::asMax( this, updateArea.getXMax(), updateArea.getYMax() );
int xspan = indexMax.i() - indexMin.i(); int xspan = indexMax.i() - indexMin.i();
//cdebug.log(110) << "indexMin:" << indexMin << endl; DbU::Unit dx = updateArea.getXMin() - _area.getXMin();
//cdebug.log(110) << "indexMax:" << indexMax << endl; DbU::Unit dy = updateArea.getYMin() - _area.getYMin();
cdebug.log(110) << "raw_i:" << (dx / _side + ((dx%_side) ? 1 : 0))
<< " raw_j:" << (dy / _side + ((dy%_side) ? 1 : 0)) << endl;
cdebug.log(110) << "indexMin:" << indexMin << endl;
cdebug.log(110) << "indexMax:" << indexMax << endl;
cdebug.log(110) << "xspan: " << xspan << endl;
if (not indexMin.valid() or not indexMax.valid()) { cdebug.tabw(110,-1); return; }
int index = indexMin.index(); int index = indexMin.index();
while ( index <= indexMax.index() ) { while ( index <= indexMax.index() ) {
@ -101,7 +134,18 @@ namespace Anabatic {
else index += _imax - xspan; else index += _imax - xspan;
} }
//cdebug.tabw(110,-1); cdebug.tabw(110,-1);
}
void Matrix::show () const
{
cdebug.log(111) << this << endl;
for ( size_t i=0 ; i<_gcells.size() ; ++i ) {
cdebug.log(111) << "[" << setw(3) << setfill('0') << i << setfill(' ') << "] ("
<< setw(3) << index2i(i) << ","
<< setw(3) << index2j(i) << ") " << _gcells[i] << endl;
}
} }

View File

@ -56,6 +56,7 @@ namespace Anabatic {
virtual Configuration* getConfiguration (); virtual Configuration* getConfiguration ();
inline CellViewer* getViewer () const; inline CellViewer* getViewer () const;
inline void setViewer ( CellViewer* ); inline void setViewer ( CellViewer* );
inline const Matrix* getMatrix () const;
inline const vector<GCell*>& getGCells () const; inline const vector<GCell*>& getGCells () const;
inline GCell* getSouthWestGCell () const; inline GCell* getSouthWestGCell () const;
inline GCell* getGCellUnder ( DbU::Unit x, DbU::Unit y ) const; inline GCell* getGCellUnder ( DbU::Unit x, DbU::Unit y ) const;
@ -98,6 +99,7 @@ namespace Anabatic {
inline CellViewer* AnabaticEngine::getViewer () const { return _viewer; } inline CellViewer* AnabaticEngine::getViewer () const { return _viewer; }
inline void AnabaticEngine::setViewer ( CellViewer* viewer ) { _viewer=viewer; } inline void AnabaticEngine::setViewer ( CellViewer* viewer ) { _viewer=viewer; }
inline const Matrix* AnabaticEngine::getMatrix () const { return &_matrix; }
inline const vector<GCell*>& AnabaticEngine::getGCells () const { return _gcells; } inline const vector<GCell*>& AnabaticEngine::getGCells () const { return _gcells; }
inline GCell* AnabaticEngine::getSouthWestGCell () const { return _gcells[0]; } inline GCell* AnabaticEngine::getSouthWestGCell () const { return _gcells[0]; }
inline GCell* AnabaticEngine::getGCellUnder ( DbU::Unit x, DbU::Unit y ) const { return _matrix.getUnder(x,y); } inline GCell* AnabaticEngine::getGCellUnder ( DbU::Unit x, DbU::Unit y ) const { return _matrix.getUnder(x,y); }

View File

@ -19,6 +19,7 @@
#include <set> #include <set>
#include <iomanip> #include <iomanip>
#include "hurricane/Observer.h"
namespace Hurricane { namespace Hurricane {
class Net; class Net;
} }
@ -29,6 +30,7 @@ namespace Anabatic {
using std::set; using std::set;
using std::multiset; using std::multiset;
using Hurricane::Observer;
using Hurricane::Net; using Hurricane::Net;
class AnabaticEngine; class AnabaticEngine;
@ -44,6 +46,8 @@ namespace Anabatic {
}; };
public: public:
static float unreached; static float unreached;
public:
static void notify ( Vertex*, unsigned flags );
public: public:
inline Vertex ( GCell* ); inline Vertex ( GCell* );
inline Vertex ( size_t id ); inline Vertex ( size_t id );
@ -69,29 +73,33 @@ namespace Anabatic {
Vertex ( const Vertex& ); Vertex ( const Vertex& );
Vertex& operator= ( const Vertex& ); Vertex& operator= ( const Vertex& );
private: private:
size_t _id; size_t _id;
GCell* _gcell; GCell* _gcell;
int _connexId; Observer<Vertex> _observer;
int _stamp; int _connexId;
float _distance; int _stamp;
Edge* _from; float _distance;
Edge* _from;
}; };
inline Vertex::Vertex ( GCell* gcell ) inline Vertex::Vertex ( GCell* gcell )
: _id (gcell->getId()) : _id (gcell->getId())
, _gcell (gcell) , _gcell (gcell)
, _observer(this)
, _connexId(-1) , _connexId(-1)
, _stamp (-1) , _stamp (-1)
, _distance(unreached) , _distance(unreached)
, _from (NULL) , _from (NULL)
{ {
gcell->setLookup<Vertex>( this ); //gcell->setLookup<Vertex>( this );
gcell->setObserver( GCell::Observable::Vertex, &_observer );
} }
inline Vertex::Vertex ( size_t id ) inline Vertex::Vertex ( size_t id )
: _id (id) : _id (id)
, _gcell (NULL) , _gcell (NULL)
, _observer((Vertex*)0x1) // To trick the NULL detection.
, _connexId(-1) , _connexId(-1)
, _stamp (-1) , _stamp (-1)
, _distance(unreached) , _distance(unreached)
@ -114,11 +122,12 @@ namespace Anabatic {
inline void Vertex::setConnexId ( int id ) { _connexId=id; } inline void Vertex::setConnexId ( int id ) { _connexId=id; }
inline Vertex* Vertex::getPredecessor () const inline Vertex* Vertex::getPredecessor () const
{ return (hasValidStamp() and _from) ? _from->getOpposite(_gcell)->lookup<Vertex>() : NULL; } { return (hasValidStamp() and _from) ? _from->getOpposite(_gcell)->getObserver<Vertex>(GCell::Observable::Vertex) : NULL; }
inline bool Vertex::CompareById::operator() ( const Vertex* lhs, const Vertex* rhs ) inline bool Vertex::CompareById::operator() ( const Vertex* lhs, const Vertex* rhs )
{ return lhs->getId() < rhs->getId(); } { return lhs->getId() < rhs->getId(); }
typedef set<Vertex*,Vertex::CompareById> VertexSet; typedef set<Vertex*,Vertex::CompareById> VertexSet;

View File

@ -89,7 +89,7 @@ namespace Anabatic {
, _flags(locator._flags) , _flags(locator._flags)
, _iedge(locator._iedge) , _iedge(locator._iedge)
{ {
cdebug.log(110) << "GCell_Edges::Locator::Locator(const Locator&)" << std::endl; // cdebug.log(110) << "GCell_Edges::Locator::Locator(const Locator&)" << std::endl;
} }

View File

@ -34,6 +34,8 @@ namespace Anabatic {
using std::string; using std::string;
using std::vector; using std::vector;
using Hurricane::StaticObservable;
using Hurricane::BaseObserver;
using Hurricane::Name; using Hurricane::Name;
using Hurricane::Record; using Hurricane::Record;
using Hurricane::DbU; using Hurricane::DbU;
@ -54,6 +56,17 @@ namespace Anabatic {
class GCell : public ExtensionGo { class GCell : public ExtensionGo {
public: public:
typedef ExtensionGo Super; typedef ExtensionGo Super;
public:
class Observable : public StaticObservable<1> {
public:
enum Indexes { Vertex = 0
};
public:
inline Observable ();
private:
Observable ( const StaticObservable& );
Observable& operator= ( const StaticObservable& );
};
public: public:
static Box getBorder ( const GCell*, const GCell* ); static Box getBorder ( const GCell*, const GCell* );
public: public:
@ -88,10 +101,6 @@ namespace Anabatic {
GCell* vcut ( DbU::Unit x ); GCell* vcut ( DbU::Unit x );
bool doGrid (); bool doGrid ();
Contact* getGContact ( Net* ); Contact* getGContact ( Net* );
template<typename Type>
inline void setLookup ( Type* decorator );
template<typename Type>
inline Type* lookup () const;
// Misc. functions. // Misc. functions.
inline const Flags& flags () const; inline const Flags& flags () const;
inline Flags& flags (); inline Flags& flags ();
@ -102,27 +111,33 @@ namespace Anabatic {
void _revalidate (); void _revalidate ();
void _moveEdges ( GCell* dest, size_t ibegin, Flags flags ); void _moveEdges ( GCell* dest, size_t ibegin, Flags flags );
public: public:
// Observers.
inline void setObserver ( size_t slot, BaseObserver* );
template<typename OwnerT>
inline OwnerT* getObserver ( size_t slot );
inline void notify ( unsigned int flags );
// ExtensionGo support. // ExtensionGo support.
inline const Name& staticGetName (); inline const Name& staticGetName ();
virtual const Name& getName () const; virtual const Name& getName () const;
virtual void translate ( const DbU::Unit&, const DbU::Unit& ); virtual void translate ( const DbU::Unit&, const DbU::Unit& );
virtual Box getBoundingBox () const; virtual Box getBoundingBox () const;
public: public:
// Inspector support. // Inspector support.
virtual string _getTypeName () const; virtual string _getTypeName () const;
virtual string _getString () const; virtual string _getString () const;
virtual Record* _getRecord () const; virtual Record* _getRecord () const;
protected: protected:
GCell ( AnabaticEngine*, DbU::Unit xmin, DbU::Unit ymin ); GCell ( AnabaticEngine*, DbU::Unit xmin, DbU::Unit ymin );
virtual ~GCell (); virtual ~GCell ();
GCell* _create ( DbU::Unit xmin, DbU::Unit ymin ); GCell* _create ( DbU::Unit xmin, DbU::Unit ymin );
virtual void _postCreate (); virtual void _postCreate ();
virtual void _preDestroy (); virtual void _preDestroy ();
private: private:
GCell ( const GCell& ); GCell ( const GCell& );
GCell& operator= ( const GCell& ); GCell& operator= ( const GCell& );
private: private:
static Name _extensionName; static Name _extensionName;
Observable _observable;
AnabaticEngine* _anabatic; AnabaticEngine* _anabatic;
Flags _flags; Flags _flags;
vector<Edge*> _westEdges; vector<Edge*> _westEdges;
@ -132,7 +147,6 @@ namespace Anabatic {
DbU::Unit _xmin; DbU::Unit _xmin;
DbU::Unit _ymin; DbU::Unit _ymin;
vector<Contact*> _contacts; vector<Contact*> _contacts;
void* _lookup;
}; };
@ -172,11 +186,17 @@ namespace Anabatic {
return Interval( getXMin(), getXMax() ); return Interval( getXMin(), getXMax() );
} }
template<typename Type> inline void GCell::setObserver ( size_t slot, BaseObserver* observer )
inline void GCell::setLookup ( Type* decorator ) { _lookup=reinterpret_cast<void*>(decorator); } { _observable.setObserver( slot, observer ); }
template<typename Type> template<typename OwnerT>
inline Type* GCell::lookup () const { return reinterpret_cast<Type*>( _lookup ); } inline OwnerT* GCell::getObserver ( size_t slot )
{ return _observable.getObserver<OwnerT>(slot); }
inline void GCell::notify ( unsigned int flags )
{ _observable.notify( flags ); }
inline GCell::Observable::Observable () : StaticObservable<1>() { }
// ------------------------------------------------------------------- // -------------------------------------------------------------------

View File

@ -43,11 +43,14 @@ namespace Anabatic {
class Matrix { class Matrix {
public: public:
class Index { class Index {
public:
static inline Matrix::Index asMin ( Matrix*, DbU::Unit x, DbU::Unit y );
static inline Matrix::Index asMax ( Matrix*, DbU::Unit x, DbU::Unit y );
static inline Matrix::Index asMin ( Matrix*, Point position );
static inline Matrix::Index asMax ( Matrix*, Point position );
public: public:
inline Index ( Matrix*, int index ); inline Index ( Matrix*, int index );
inline Index ( Matrix*, int i, int j ); inline Index ( Matrix*, int i, int j );
inline Index ( Matrix*, DbU::Unit x, DbU::Unit y );
inline Index ( Matrix*, Point position );
inline Matrix* matrix () const; inline Matrix* matrix () const;
inline const int& index () const; inline const int& index () const;
inline int& index (); inline int& index ();
@ -78,8 +81,10 @@ namespace Anabatic {
inline int index2i ( const Index& ) const; inline int index2i ( const Index& ) const;
inline int index2j ( const Index& ) const; inline int index2j ( const Index& ) const;
inline int ij2index ( int i, int j ) const; inline int ij2index ( int i, int j ) const;
inline int xy2index ( DbU::Unit x, DbU::Unit y ) const; inline int xy2minIndex ( DbU::Unit x, DbU::Unit y ) const;
inline int xy2index ( Point ) const; inline int xy2minIndex ( Point ) const;
inline int xy2maxIndex ( DbU::Unit x, DbU::Unit y ) const;
inline int xy2maxIndex ( Point ) const;
inline Index& west ( Index& ) const; inline Index& west ( Index& ) const;
inline Index& east ( Index& ) const; inline Index& east ( Index& ) const;
inline Index& south ( Index& ) const; inline Index& south ( Index& ) const;
@ -88,6 +93,7 @@ namespace Anabatic {
inline GCell* getUnder ( Point ) const; inline GCell* getUnder ( Point ) const;
void setCell ( Cell*, DbU::Unit side ); void setCell ( Cell*, DbU::Unit side );
void updateLookup ( GCell* ); void updateLookup ( GCell* );
void show () const;
// Inspector support. // Inspector support.
virtual Record* _getRecord () const; virtual Record* _getRecord () const;
virtual string _getString () const; virtual string _getString () const;
@ -127,14 +133,29 @@ namespace Anabatic {
{ {
if ((i < 0) or (i >= _imax)) return -1; if ((i < 0) or (i >= _imax)) return -1;
if ((j < 0) or (j >= _jmax)) return -1; if ((j < 0) or (j >= _jmax)) return -1;
return j*_jmax + i; return j*_imax + i;
} }
inline int Matrix::xy2index ( DbU::Unit x, DbU::Unit y ) const inline int Matrix::xy2minIndex ( DbU::Unit x, DbU::Unit y ) const
{ return ij2index( (x - _area.getXMin()) / _side, (y - _area.getYMin()) / _side ); } {
DbU::Unit dx = x - _area.getXMin();
DbU::Unit dy = y - _area.getYMin();
return ij2index( dx / _side + ((dx%_side) ? 1 : 0)
, dy / _side + ((dy%_side) ? 1 : 0) );
}
inline int Matrix::xy2index ( Point p ) const inline int Matrix::xy2minIndex ( Point p ) const
{ return xy2index( p.getX(), p.getY() ); } { return xy2minIndex( p.getX(), p.getY() ); }
inline int Matrix::xy2maxIndex ( DbU::Unit x, DbU::Unit y ) const
{
DbU::Unit dx = x - _area.getXMin();
DbU::Unit dy = y - _area.getYMin();
return ij2index( dx / _side, dy / _side );
}
inline int Matrix::xy2maxIndex ( Point p ) const
{ return xy2maxIndex( p.getX(), p.getY() ); }
inline Matrix::Index& Matrix::west ( Matrix::Index& index ) const inline Matrix::Index& Matrix::west ( Matrix::Index& index ) const
{ {
@ -186,11 +207,13 @@ namespace Anabatic {
// Matrix::Index inline functions. // Matrix::Index inline functions.
inline Matrix::Index::Index ( Matrix* m, int index ) : _matrix(m), _index(index) { } inline Matrix::Index::Index ( Matrix* m, int index ) : _matrix(m), _index(index) { }
inline Matrix::Index::Index ( Matrix* m, int i, int j ) : _matrix(m), _index(m->ij2index(i,j)) { } inline Matrix::Index::Index ( Matrix* m, int i, int j ) : _matrix(m), _index(m->ij2index(i,j)) { }
inline Matrix::Index::Index ( Matrix* m, DbU::Unit x, DbU::Unit y ) : _matrix(m), _index(m->xy2index(x,y)) { }
inline Matrix::Index::Index ( Matrix* m, Point position ) : _matrix(m), _index(m->xy2index(position)) { }
inline Matrix::Index Matrix::Index::asMin ( Matrix* m, DbU::Unit x, DbU::Unit y ) { return Index( m, m->xy2minIndex(x,y) ); }
inline Matrix::Index Matrix::Index::asMin ( Matrix* m, Point position ) { return Index( m, m->xy2minIndex(position) ); }
inline Matrix::Index Matrix::Index::asMax ( Matrix* m, DbU::Unit x, DbU::Unit y ) { return Index( m, m->xy2maxIndex(x,y) ); }
inline Matrix::Index Matrix::Index::asMax ( Matrix* m, Point position ) { return Index( m, m->xy2maxIndex(position) ); }
inline Matrix* Matrix::Index::matrix () const { return _matrix; } inline Matrix* Matrix::Index::matrix () const { return _matrix; }
inline const int& Matrix::Index::index () const { return _index; } inline const int& Matrix::Index::index () const { return _index; }
inline int& Matrix::Index::index () { return _index; } inline int& Matrix::Index::index () { return _index; }