diff options
Diffstat (limited to 'src/electronics/ecnode.cpp')
-rw-r--r-- | src/electronics/ecnode.cpp | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/src/electronics/ecnode.cpp b/src/electronics/ecnode.cpp new file mode 100644 index 0000000..0fb2801 --- /dev/null +++ b/src/electronics/ecnode.cpp @@ -0,0 +1,239 @@ +/*************************************************************************** + * Copyright (C) 2003-2005 by David Saxton * + * david@bluehaze.org * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#include "circuitdocument.h" +#include "src/core/ktlconfig.h" +#include "component.h" +#include "connector.h" +#include "ecnode.h" +#include "pin.h" + +#include <kdebug.h> +#include <qpainter.h> + +#include <cmath> + +// The voltage at the middle of the voltage indicator +const double vMidPoint = 5.; + +// The maximum length of the voltage indiactor +const int vLength = 8; + +// The current at the middle of the current indicator +const double iMidPoint = 0.03; + +// The maximum thicnkess of the current indicator +const int iLength = 6; + +inline double calcVProp( const double v ) +{ + return 1 - vMidPoint/(vMidPoint+std::abs(v)); +} + +inline double calcIProp( const double i ) +{ + return 1 - iMidPoint/(iMidPoint+std::abs(i)); +} + +inline int calcThickness( const double prop ) +{ + return (int)((iLength-2)*prop+2); +} + +inline int calcLength( const double prop, const double v ) +{ + return (v>0) ? -int(vLength*prop) : int(vLength*prop); +} + +ECNode::ECNode( ICNDocument *icnDocument, Node::node_type _type, node_dir dir, const QPoint &pos, QString *_id ) + : Node( icnDocument, _type, dir, pos, _id ) +{ + m_prevV = 0; + m_prevI = 0; + m_pinPoint = 0l; + m_bShowVoltageBars = KTLConfig::showVoltageBars(); + + icnDocument->registerItem(this); + + if ( type() == ec_pin ) + { + m_pinPoint = new QCanvasRectangle( 0, 0, 3, 3, canvas() ); + m_pinPoint->setBrush(Qt::black); + m_pinPoint->setPen(Qt::black); + } + + m_pins.resize(1); + m_pins[0] = new Pin(this); +} + + +ECNode::~ECNode() +{ + if (m_pinPoint) + m_pinPoint->setCanvas(0l); + delete m_pinPoint; + m_pinPoint = 0l; + + for ( unsigned i = 0; i < m_pins.size(); i++ ) + delete m_pins[i]; + m_pins.resize(0); +} + + +void ECNode::setNumPins( unsigned num ) +{ + unsigned oldNum = m_pins.size(); + + if ( num == oldNum ) + return; + + if ( num > oldNum ) + { + m_pins.resize(num); + for ( unsigned i = oldNum; i < num; i++ ) + m_pins[i] = new Pin(this); + } + else + { + for ( unsigned i = num; i < oldNum; i++ ) + delete m_pins[i]; + m_pins.resize(num); + } + + emit numPinsChanged(num); +} + + +void ECNode::setNodeChanged() +{ + if ( !canvas() || numPins() != 1 ) + return; + + Pin * pin = m_pins[0]; + + double v = pin->voltage(); + double i = pin->current(); + + if ( v != m_prevV || i != m_prevI ) + { + QRect r = boundingRect(); + r.setCoords( r.left()+(r.width()/2)-1, r.top()+(r.height()/2)-1, r.right()-(r.width()/2)+1, r.bottom()-(r.height()/2)+1 ); + canvas()->setChanged(r); + m_prevV = v; + m_prevI = i; + } +} + + +void ECNode::setParentItem( CNItem * parentItem ) +{ + Node::setParentItem(parentItem); + + if ( Component * component = dynamic_cast<Component*>(parentItem) ) + { + connect( component, SIGNAL(elementDestroyed(Element* )), this, SLOT(removeElement(Element* )) ); + connect( component, SIGNAL(switchDestroyed( Switch* )), this, SLOT(removeSwitch( Switch* )) ); + } +} + + +void ECNode::removeElement( Element * e ) +{ + for ( unsigned i = 0; i < m_pins.size(); i++ ) + m_pins[i]->removeElement(e); +} + + +void ECNode::removeSwitch( Switch * sw ) +{ + for ( unsigned i = 0; i < m_pins.size(); i++ ) + m_pins[i]->removeSwitch( sw ); +} + + +void ECNode::drawShape( QPainter &p ) +{ + const int _x = int(x()); + const int _y = int(y()); + + if ( type() == ec_junction ) + { +// p.drawRect( _x-2, _y-1, 5, 3 ); +// p.drawRect( _x-1, _y-2, 3, 5 ); + p.drawRect( _x-1, _y-1, 3, 3 ); + return; + } + + if (m_pinPoint) + { + bool drawDivPoint; + QPoint divPoint = findConnectorDivergePoint(&drawDivPoint); + m_pinPoint->setVisible(drawDivPoint); + m_pinPoint->move( divPoint.x()-1, divPoint.y()-1 ); + } + + // Now to draw on our current/voltage bar indicators + + if ( numPins() == 1 ) + { + double v = pin()->voltage(); + double vProp = calcVProp(v); + int length = calcLength( vProp, v ); + + if ( m_bShowVoltageBars && length != 0 ) + { + // we can assume that v != 0 as length != 0 + + QPen oldPen = p.pen(); + + double i = pin()->current(); + double iProp = calcIProp(i); + int thickness = calcThickness(iProp); + + if ( v > 0 ) + p.setPen( QPen( QColor( 255, 166, 0 ), thickness ) ); + + else + p.setPen( QPen( QColor( 0, 136, 255 ), thickness ) ); + + // The node line (drawn at the end of this function) will overdraw + // some of the voltage bar, so we need to adapt the length + if ( v > 0 && (m_dir == Node::dir_up || m_dir == Node::dir_down) ) + length--; + else if ( v < 0 && (m_dir == Node::dir_left || m_dir == Node::dir_right) ) + length++; + + if ( m_dir == Node::dir_right ) + p.drawLine( _x+3, _y, _x+3, _y+length ); + + else if ( m_dir == Node::dir_down ) + p.drawLine( _x, _y+3, _x-length, _y+3 ); + + else if ( m_dir == Node::dir_left ) + p.drawLine( _x-3, _y, _x-3, _y+length ); + + else if ( m_dir == Node::dir_up ) + p.drawLine( _x, _y-3, _x-length, _y-3 ); + + p.setPen(oldPen); + } + } + + QPen pen( p.pen() ); + pen.setWidth( (numPins() > 1) ? 2 : 1 ); + p.setPen(pen); + + if ( m_dir == Node::dir_right ) p.drawLine( _x, _y, _x+8, _y ); + else if ( m_dir == Node::dir_down ) p.drawLine( _x, _y, _x, _y+8 ); + else if ( m_dir == Node::dir_left ) p.drawLine( _x, _y, _x-8, _y ); + else if ( m_dir == Node::dir_up ) p.drawLine( _x, _y, _x, _y-8 ); +} + +#include "ecnode.moc" |