* ./hurricane/src/hviewer:

- Change: In CellWidget/Ruler, rulers are now unidirectionals (as in Cadence).
    - New: In CellWidget, support for drawing components names. Includes correction
        of badly computed coordinates in drawDisplayText.
          Components names are drawed only for the top level of hierarchy and only
        if the bounding box is large enought (currently hard-coded to 50x50 pixels).
    - New: In Net, "Automatic" attributes to distinguish automatically generated
        net names without string pattern matching. "Automatic" Net's names are not
        drawn by the CellWidget to much cluttering the display. And testing a boolean
        is way faster than a pattern matching on a hard-coded name.
    - Change: In CellWidget, when loading a terminal Cell, draw it's internals.
This commit is contained in:
Jean-Paul Chaput 2010-01-22 16:38:21 +00:00
parent d2fa201e09
commit ae85636e13
16 changed files with 170 additions and 91 deletions

View File

@ -209,8 +209,8 @@ namespace Hurricane {
{ return _connectorLayer; }
BasicLayer* BasicLayer::getObstructionLayer () const
{ return _obstructionLayer; }
BasicLayer* BasicLayer::getBlockageLayer () const
{ return _blockageLayer; }
BasicLayers BasicLayer::getBasicLayers () const

View File

@ -82,8 +82,8 @@ namespace Hurricane {
{ return NULL; }
Layer* Layer::getObstructionLayer () const
{ return NULL; }
const Layer* Layer::getBlockageLayer () const
{ return NULL; }
const Layer* Layer::getTop () const

View File

@ -257,6 +257,7 @@ Net::Net(Cell* cell, const Name& name)
_arity(1),
_isGlobal(false),
_isExternal(false),
_isAutomatic(false),
_type(),
_direction(),
_position(0,0),
@ -473,6 +474,12 @@ void Net::setExternal(bool isExternal)
}
}
void Net::setAutomatic(bool isAutomatic)
// *************************************
{
_isAutomatic = isAutomatic;
}
void Net::setType(const Type& type)
// ********************************
{
@ -662,12 +669,12 @@ Record* Net::_getRecord() const
record->add(getSlot("Arity", &_arity));
record->add(getSlot("Global", &_isGlobal));
record->add(getSlot("External", &_isExternal));
record->add(getSlot("Automatic", &_isAutomatic));
record->add(getSlot("Type", &_type));
record->add(getSlot("Direction", &_direction));
record->add(getSlot("Position", &_position));
record->add(getSlot("Components", &_componentSet));
record->add(getSlot("Rubbers", &_rubberSet));
record->add(getSlot("External", &_isExternal));
}
return record;
}

View File

@ -90,6 +90,10 @@ namespace Hurricane {
{ }
void Query::setBasicLayer ( const BasicLayer* basicLayer )
{ _basicLayer = basicLayer; }
void Query::setQuery ( Cell* cell
, const Box& area
, const Transformation& transformation

View File

@ -221,6 +221,10 @@ namespace Hurricane {
return regularLayer;
}
const Layer* RegularLayer::getBlockageLayer () const
{ return _basicLayer->getBlockageLayer(); }
BasicLayers RegularLayer::getBasicLayers () const

View File

@ -97,11 +97,11 @@ namespace Hurricane {
inline unsigned getExtractNumber () const;
virtual BasicLayers getBasicLayers () const;
virtual BasicLayer* getConnectorLayer () const;
virtual BasicLayer* getObstructionLayer () const;
virtual BasicLayer* getBlockageLayer () const;
inline const Name& getRealName () const;
// Updators
inline void setConnectorLayer ( BasicLayer* layer);
inline void setObstructionLayer ( BasicLayer* layer);
inline void setBlockageLayer ( BasicLayer* layer);
inline void setExtractNumber ( unsigned int );
inline void setRealName ( const char* realName);
// Hurricane Managment.
@ -115,7 +115,7 @@ namespace Hurricane {
Material _material;
unsigned _extractNumber;
BasicLayer* _connectorLayer;
BasicLayer* _obstructionLayer;
BasicLayer* _blockageLayer;
Name _realName;
protected:
@ -142,7 +142,7 @@ namespace Hurricane {
inline unsigned BasicLayer::getExtractNumber () const { return _extractNumber; }
inline const Name& BasicLayer::getRealName () const { return _realName; }
inline void BasicLayer::setConnectorLayer ( BasicLayer* layer) { _connectorLayer = layer; }
inline void BasicLayer::setObstructionLayer ( BasicLayer* layer) { _obstructionLayer = layer; }
inline void BasicLayer::setBlockageLayer ( BasicLayer* layer) { _blockageLayer = layer; }
inline void BasicLayer::setExtractNumber ( unsigned int number ) { _extractNumber=number; }
inline void BasicLayer::setRealName ( const char* realName) { _realName = realName; }

View File

@ -69,6 +69,7 @@ namespace Hurricane {
inline DbU::Unit getPitch () const;
virtual BasicLayers getBasicLayers () const = 0;
virtual Layer* getConnectorLayer () const;
virtual const Layer* getBlockageLayer () const;
virtual const Layer* getTop () const;
virtual const Layer* getBottom () const;
virtual const Layer* getOpposite ( const Layer* ) const;
@ -76,7 +77,6 @@ namespace Hurricane {
Layer* getMetalBelow ( bool useWorking=true ) const;
Layer* getCutAbove ( bool useWorking=true ) const;
Layer* getCutBelow ( bool useWorking=true ) const;
virtual Layer* getObstructionLayer () const;
virtual DbU::Unit getEnclosure () const;
virtual DbU::Unit getExtentionCap () const;
virtual DbU::Unit getExtentionWidth () const;

View File

@ -132,6 +132,7 @@ class Net : public Entity {
private: Arity _arity;
private: bool _isGlobal;
private: bool _isExternal;
private: bool _isAutomatic;
private: Type _type;
private: Direction _direction;
private: Point _position;
@ -188,14 +189,15 @@ class Net : public Entity {
// Predicates
// **********
public: virtual bool isDeepNet () const {return false;};
public: bool isGlobal () const {return _isGlobal;};
public: bool isExternal() const {return _isExternal;};
public: bool isLogical () const {return (_type == Type::LOGICAL);};
public: bool isClock () const {return (_type == Type::CLOCK);};
public: bool isPower () const {return (_type == Type::POWER);};
public: bool isGround () const {return (_type == Type::GROUND);};
public: bool isSupply () const {return (isPower() || isGround());};
public: virtual bool isDeepNet () const {return false;};
public: bool isGlobal () const {return _isGlobal;};
public: bool isExternal () const {return _isExternal;};
public: bool isAutomatic() const {return _isAutomatic;};
public: bool isLogical () const {return (_type == Type::LOGICAL);};
public: bool isClock () const {return (_type == Type::CLOCK);};
public: bool isPower () const {return (_type == Type::POWER);};
public: bool isGround () const {return (_type == Type::GROUND);};
public: bool isSupply () const {return (isPower() || isGround());};
// Updators
// ********
@ -204,6 +206,7 @@ class Net : public Entity {
public: void setArity(const Arity& arity);
public: void setGlobal(bool isGlobal);
public: void setExternal(bool isExternal);
public: void setAutomatic(bool isAutomatic);
public: void setType(const Type& type);
public: void setDirection(const Direction& direction);
public: void setPosition(const Point& position);

View File

@ -339,12 +339,12 @@ namespace Hurricane {
inline void setCell ( Cell* cell );
inline void setArea ( const Box& area );
inline void setTransformation ( const Transformation& transformation );
inline void setBasicLayer ( const BasicLayer* basicLayer );
virtual void setBasicLayer ( const BasicLayer* basicLayer );
inline void setExtensionMask ( ExtensionSlice::Mask mode );
inline void setFilter ( Mask mode );
inline void setStartLevel ( unsigned int level );
inline void setStopLevel ( unsigned int level );
void doQuery ();
virtual void doQuery ();
protected:
// Internal: Attributes.
@ -360,7 +360,6 @@ namespace Hurricane {
inline void Query::setCell ( Cell* cell ) { _stack.setTopCell(cell); }
inline void Query::setArea ( const Box& area ) { _stack.setTopArea(area); }
inline void Query::setTransformation ( const Transformation& transformation ) { _stack.setTopTransformation(transformation); }
inline void Query::setBasicLayer ( const BasicLayer* basicLayer ) { _basicLayer = basicLayer; }
inline void Query::setFilter ( Mask filter ) { _filter = filter; }
inline void Query::setExtensionMask ( ExtensionSlice::Mask mask ) { _extensionMask = mask; }
inline void Query::setStartLevel ( unsigned int level ) { _stack.setStartLevel(level); }

View File

@ -58,6 +58,7 @@ namespace Hurricane {
// Accessors.
virtual BasicLayers getBasicLayers () const;
inline BasicLayer* getBasicLayer () const;
virtual const Layer* getBlockageLayer () const;
virtual const Layer* getTop () const;
virtual const Layer* getBottom () const;
virtual const Layer* getOpposite ( const Layer* ) const;
@ -94,7 +95,7 @@ namespace Hurricane {
// Inline Functions.
BasicLayer* RegularLayer::getBasicLayer () const { return _basicLayer; }
inline BasicLayer* RegularLayer::getBasicLayer () const { return _basicLayer; }
} // End of Hurricane namespace.

View File

@ -36,6 +36,7 @@
#include <QBitmap>
#include <QLabel>
#include "hurricane/SharedName.h"
#include "hurricane/DataBase.h"
#include "hurricane/Technology.h"
#include "hurricane/BasicLayer.h"
@ -793,7 +794,8 @@ namespace Hurricane {
const Component* component = dynamic_cast<const Component*>(go);
if ( component ) {
_goCount++;
rectangle = _cellWidget->dbuToDisplayRect ( transformation.getBox(component->getBoundingBox(basicLayer)) );
Box bb = transformation.getBox(component->getBoundingBox(basicLayer));
rectangle = _cellWidget->dbuToDisplayRect ( bb );
state = ( (rectangle.width() > 2) ? 1:0) | ( (rectangle.height() > 2) ? 2:0);
switch ( state ) {
case 0: break;
@ -801,6 +803,17 @@ namespace Hurricane {
case 2: _cellWidget->drawScreenLine ( rectangle.bottomLeft(), rectangle.topLeft () ); break;
case 3: _cellWidget->drawScreenRect ( rectangle ); break;
}
if ( _cellWidget->isDrawable("text.component")
and (getDepth() < 2)
and (rectangle.width () > 30)
and (rectangle.height() > 30) ) {
const Net* net = component->getNet();
if ( not net->isAutomatic() ) {
const char* netName = net->getName()._getSharedName()->_getSString().c_str();
_cellWidget->drawDisplayText ( rectangle, netName, BigFont|Bold|Center|Frame );
}
}
}
}
@ -909,9 +922,8 @@ namespace Hurricane {
if ( getDepth() == 2 )
_cellWidget->drawText ( Point(bbox.getXMin(),bbox.getYMin())
, getString(getInstance()->getName()).c_str()
, false
, Reverse|Top
, -90
, true
);
}
@ -1609,25 +1621,69 @@ namespace Hurricane {
}
void CellWidget::drawText ( const Point& point, const char* text, bool bold, int angle, bool reverse )
void CellWidget::drawText ( const Point& point, const char* text, unsigned int flags, int angle )
{
drawDisplayText ( dbuToDisplayPoint(point), text, bold, angle, reverse );
drawDisplayText ( dbuToDisplayPoint(point), text, flags, angle );
}
void CellWidget::drawDisplayText ( const QPoint& point, const char* text, bool bold, int angle, bool reverse )
void CellWidget::drawDisplayText ( const QRect& box, const char* text, unsigned int flags )
{
_drawingPlanes.painter().save();
if ( reverse ) {
_drawingPlanes.painter().setPen ( Graphics::getPen ("background") );
_drawingPlanes.painter().setBackgroundMode ( Qt::OpaqueMode );
QFont font = Graphics::getNormalFont(flags&Bold);
if ( flags & BigFont ) font.setPointSize ( 18 );
QFontMetrics metrics = QFontMetrics(font);
int width = metrics.width ( text );
int height = metrics.height ();
int angle = 0;
if ( (width > box.width()) and (box.height() > 2*box.width()) )
angle = -90;
drawDisplayText ( box.center(), text, flags, angle );
}
void CellWidget::drawDisplayText ( const QPoint& point, const char* text, unsigned int flags, int angle )
{
QPainter& painter = _drawingPlanes.painter();
QPen pen = painter.pen ();
QBrush brush = painter.brush ();
QFont font = Graphics::getNormalFont(flags&Bold);
painter.save();
if ( flags & Reverse ) painter.setPen ( Graphics::getPen("background") );
if ( flags & Reverse ) painter.setBackgroundMode ( Qt::OpaqueMode );
if ( flags & BigFont ) font.setPointSize ( 18 );
QFontMetrics metrics = QFontMetrics(font);
int width = metrics.width ( text );
int height = metrics.height ();
pen.setStyle ( Qt::SolidLine );
pen.setColor ( painter.brush().color() );
brush.setStyle ( Qt::NoBrush );
painter.setPen ( pen );
painter.setBrush ( brush );
painter.setFont ( font );
painter.translate ( point );
painter.rotate ( angle );
QPoint bottomLeft ( 0, 0);
if ( flags & Center ) {
bottomLeft.rx() -= width /2;
bottomLeft.ry() += height/2;
} else if ( flags & Top ) {
bottomLeft.ry() += height;
}
_drawingPlanes.painter().setFont ( Graphics::getNormalFont(bold) );
_drawingPlanes.painter().translate ( point );
_drawingPlanes.painter().rotate ( angle );
_drawingPlanes.painter().drawText ( 0, _textFontHeight, text );
_drawingPlanes.painter().restore ();
if ( flags & Frame ) painter.drawRect ( bottomLeft.x()-1, bottomLeft.y()-height, width+2, height );
painter.drawText ( bottomLeft.x(), bottomLeft.y()-metrics.descent(), text );
painter.restore ();
}
@ -1787,19 +1843,21 @@ namespace Hurricane {
pxAngle = dbuToDisplayPoint ( angle );
}
bool hRuler = ( abs(pxAngle.x() - pxOrigin.x()) >= abs(pxAngle.y() - pxOrigin.y()) );
int pxGrad;
int pyGrad;
string textGrad;
int tick;
_drawingPlanes.painter().setPen ( Graphics::getPen("text.ruler") );
_drawingPlanes.painter().setPen ( Graphics::getPen ("text.ruler") );
_drawingPlanes.painter().setBrush ( Graphics::getBrush("text.ruler") );
// The horizontal ruler.
bool increase = ( origin.getX() < extremity.getX() );
if ( !increase )
gradStep = -gradStep;
if ( abs(pxAngle.x() - pxOrigin.x()) > 20 ) {
if ( hRuler and (abs(pxAngle.x() - pxOrigin.x()) > 20) ) {
// The horizontal ruler axis.
_drawingPlanes.painter().drawLine ( pxOrigin, pxAngle );
@ -1818,26 +1876,24 @@ namespace Hurricane {
_drawingPlanes.painter().drawLine ( pxGrad, pxOrigin.y()
, pxGrad, pxOrigin.y()+((tick%2)?5:10) );
} else {
if ( tick == 0 ) {
int delta = (increase) ? 2 : -2;
_drawingPlanes.painter().drawLine ( pxGrad-delta, pxOrigin.y()
, pxGrad-delta, pxOrigin.y()+tickLength );
}
// if ( tick == 0 ) {
// int delta = (increase) ? 2 : -2;
// _drawingPlanes.painter().drawLine ( pxGrad-delta, pxOrigin.y()
// , pxGrad-delta, pxOrigin.y()+tickLength );
// }
_drawingPlanes.painter().drawLine ( pxGrad, pxOrigin.y()
, pxGrad, pxOrigin.y()+tickLength );
if ( !tick ) continue;
// if ( !tick ) continue;
textGrad = DbU::getValueString( gradStep*tick );
textGrad.resize ( textGrad.size()-1 );
drawDisplayText ( QPoint(pxGrad - _textFontHeight - 1
,pxOrigin.y() + tickLength)
drawDisplayText ( QPoint ( pxGrad - 1, pxOrigin.y() + tickLength )
, textGrad.c_str()
, true
, Bold
, -90
, false
);
}
}
@ -1849,74 +1905,68 @@ namespace Hurricane {
textGrad = DbU::getValueString ( angle.getX() - origin.getX() );
textGrad.resize ( textGrad.size()-1 );
drawDisplayText ( QPoint(pxAngle.x() - _textFontHeight - 1
,pxAngle.y() + tickLength)
drawDisplayText ( QPoint ( pxAngle.x() - 1,pxAngle.y() + tickLength )
, textGrad.c_str()
, true
, Bold
, -90
, false
);
}
if ( abs(pxExtremity.y() - pxAngle.y()) > 20 ) {
if ( not hRuler and (abs(pxAngle.y() - pxOrigin.y()) > 20) ) {
// The vertical ruler.
increase = ( angle.getY() < extremity.getY() );
increase = ( origin.getY() < angle.getY() );
if ( increase xor ( gradStep > 0 ) )
gradStep = -gradStep;
// The vertical ruler axis.
_drawingPlanes.painter().drawLine ( pxAngle, pxExtremity );
_drawingPlanes.painter().drawLine ( pxOrigin, pxAngle );
// The vertical ruler ticks.
for ( graduation=angle.getY(), tick=0 ; true ; graduation+=gradStep, tick++ ) {
for ( graduation=origin.getY(), tick=0 ; true ; graduation+=gradStep, tick++ ) {
if ( increase ) {
if ( graduation >= extremity.getY() ) break;
if ( graduation >= angle.getY() ) break;
} else
if ( graduation <= extremity.getY() ) break;
if ( graduation <= angle.getY() ) break;
if ( onScreen ) pyGrad = dbuToScreenY ( graduation );
else pyGrad = dbuToDisplayY ( graduation );
if ( tick % 10 ) {
_drawingPlanes.painter().drawLine ( pxAngle.x() , pyGrad
, pxAngle.x()-((tick%2)?5:10), pyGrad );
_drawingPlanes.painter().drawLine ( pxOrigin.x() , pyGrad
, pxOrigin.x()-((tick%2)?5:10), pyGrad );
} else {
if ( tick == 0 ) {
_drawingPlanes.painter().drawLine ( pxAngle.x() , pyGrad-2
, pxAngle.x()-tickLength, pyGrad-2);
}
// if ( tick == 0 ) {
// _drawingPlanes.painter().drawLine ( pxOrigin.x() , pyGrad-2
// , pxOrigin.x()-tickLength, pyGrad-2);
// }
_drawingPlanes.painter().drawLine ( pxAngle.x() , pyGrad
, pxAngle.x()-tickLength, pyGrad );
_drawingPlanes.painter().drawLine ( pxOrigin.x() , pyGrad
, pxOrigin.x()-tickLength, pyGrad );
if ( !tick ) continue;
// if ( !tick ) continue;
textGrad = DbU::getValueString( gradStep*tick );
textGrad.resize ( textGrad.size()-1 );
drawDisplayText ( QPoint(pxAngle.x() - tickLength
,pyGrad + 1)
drawDisplayText ( QPoint(pxOrigin.x() - tickLength,pyGrad + 1)
, textGrad.c_str()
, true
, Bold
, 0
, false
);
}
}
// The last vertical tick.
_drawingPlanes.painter().drawLine ( pxAngle.x() , pxExtremity.y()
, pxAngle.x()-tickLength, pxExtremity.y() );
_drawingPlanes.painter().drawLine ( pxOrigin.x() , pxAngle.y()
, pxOrigin.x()-tickLength, pxAngle.y() );
textGrad = DbU::getValueString( extremity.getY() - angle.getY() );
textGrad = DbU::getValueString( angle.getY() - origin.getY() );
textGrad.resize ( textGrad.size()-1 );
drawDisplayText ( QPoint(pxAngle.x() - tickLength
,pxExtremity.y() + 1)
drawDisplayText ( QPoint(pxOrigin.x() - tickLength,pxAngle.y() + 1)
, textGrad.c_str()
, true
, Bold
, 0
, false
);
}
}
@ -2453,6 +2503,7 @@ namespace Hurricane {
shared_ptr<State> state ( new State(cell) );
setState ( state );
if ( cell->isTerminal() ) setQueryFilter ( ~0 );
//setRealMode ();
fitToContents ( false );

View File

@ -52,6 +52,7 @@ namespace Hurricane {
const Name DisplayStyle::TextRuler = "text.ruler";
const Name DisplayStyle::TextCell = "text.cell";
const Name DisplayStyle::TextInstance = "text.instance";
const Name DisplayStyle::TextComponent = "text.component";
const Name DisplayStyle::Undef = "undef";
@ -101,12 +102,13 @@ namespace Hurricane {
if ( !_color ) {
_color = new QColor ( _red, _green, _blue );
_pen = new QPen ( *_color );
_pen = new QPen ();
if ( _borderWidth ) {
_pen->setStyle ( Qt::SolidLine );
_pen->setWidth ( _borderWidth );
} else
_pen->setStyle ( Qt::NoPen );
_pen->setColor ( *_color );
_brush = Hurricane::getBrush ( _pattern, _red, _green, _blue );
}
@ -267,6 +269,7 @@ namespace Hurricane {
addDrawingStyle ( Viewer, TextRuler , "FFFFFFFFFFFFFFFF", 255, 255, 255, 1, 0.0 );
addDrawingStyle ( Viewer, TextCell , "8822441188224411", 255, 255, 255, 0, 1.0 );
addDrawingStyle ( Viewer, TextInstance , "8822441188224411", 255, 255, 255, 0, 1.0 );
addDrawingStyle ( Viewer, TextComponent, "FFFFFFFFFFFFFFFF", 255, 255, 255, 0, 1.0 );
addDrawingStyle ( Viewer, Undef , "2244118822441188", 238, 130, 238, 0, 1.0 );
}

View File

@ -45,10 +45,11 @@ namespace Hurricane {
{ }
bool Ruler::intersect ( const Box& area ) const
Point Ruler::getAngle () const
{
Point angle = getAngle ();
return area.intersect(Box(_origin,angle)) || area.intersect(Box(angle,_extremity));
if ( abs(_extremity.getX() - _origin.getX()) >= abs(_extremity.getY() - _origin.getY()) )
return Point(_extremity.getX(),_origin.getY());
return Point(_origin.getX(),_extremity.getY());
}

View File

@ -111,9 +111,13 @@ namespace Hurricane {
, const Transformation&
);
typedef void ( InitExtensionGo_t )( CellWidget* );
enum RubberShape { Centric = 1
, Barycentric
, Steiner
enum RubberShape { Centric=1, Barycentric, Steiner };
enum TextFlag { Bold =0x01
, BigFont=0x02
, Reverse=0x04
, Frame =0x08
, Center =0x10
, Top =0x20
};
public:
// Constructor & Destructor.
@ -174,12 +178,13 @@ namespace Hurricane {
void drawBox ( const Box& );
void drawLine ( DbU::Unit, DbU::Unit, DbU::Unit, DbU::Unit, bool mode=true );
void drawLine ( const Point&, const Point&, bool mode=true );
void drawText ( const Point&, const char*, bool bold=false, int angle=0, bool reverse=false );
void drawText ( const Point&, const char*, unsigned int flags=0, int angle=0 );
void drawGrid ( QRect );
void drawSpot ();
void drawRuler ( shared_ptr<Ruler> );
void drawRulers ( QRect );
void drawDisplayText ( const QPoint&, const char*, bool bold=false, int angle=0, bool reverse=false );
void drawDisplayText ( const QRect& , const char*, unsigned int flags=0 );
void drawDisplayText ( const QPoint&, const char*, unsigned int flags=0, int angle=0 );
void drawScreenLine ( const QPoint&, const QPoint&, size_t plane=PlaneId::Working, bool mode=true );
void drawScreenRect ( const QPoint&, const QPoint&, size_t plane=PlaneId::Working );
void drawScreenRect ( const QRect& , size_t plane=PlaneId::Working );

View File

@ -156,6 +156,7 @@ namespace Hurricane {
static const Name TextRuler;
static const Name TextCell;
static const Name TextInstance;
static const Name TextComponent;
static const Name Undef;
static const Name UnmatchedGroup;

View File

@ -46,10 +46,10 @@ namespace Hurricane {
Ruler ( const Point& origin, const Point& extremity );
inline const Point& getOrigin () const;
inline const Point& getExtremity () const;
inline Point getAngle () const;
Point getAngle () const;
inline Box getBoundingBox () const;
inline void setExtremity ( const Point& );
bool intersect ( const Box& ) const;
inline bool intersect ( const Box& ) const;
private:
Point _origin;
Point _extremity;
@ -59,9 +59,9 @@ namespace Hurricane {
// Inline Functions.
inline const Point& Ruler::getOrigin () const { return _origin; }
inline const Point& Ruler::getExtremity () const { return _extremity; }
inline Point Ruler::getAngle () const { return Point(_extremity.getX(),_origin.getY()); }
inline Box Ruler::getBoundingBox () const { return Box(_origin,_extremity); }
inline void Ruler::setExtremity ( const Point& extremity ) { _extremity = extremity; }
inline bool Ruler::intersect ( const Box& area ) const { return area.intersect(Box(_origin,getAngle())); }
typedef std::set< std::tr1::shared_ptr<Ruler> > RulerSet;