00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "circuitdocument.h"
00012 #include "src/core/ktlconfig.h"
00013 #include "component.h"
00014 #include "connector.h"
00015 #include "ecnode.h"
00016 #include "pin.h"
00017
00018 #include <kdebug.h>
00019 #include <qpainter.h>
00020
00021 #include <cmath>
00022
00023
00024 const double vMidPoint = 5.;
00025
00026
00027 const int vLength = 10;
00028
00029
00030 const double iMidPoint = 0.05;
00031
00032
00033 const int iLength = 6;
00034
00035 inline double calcVProp( const double v )
00036 {
00037 return 1 - vMidPoint/(vMidPoint+std::abs(v));
00038 }
00039
00040 inline double calcIProp( const double i )
00041 {
00042 return 1 - iMidPoint/(iMidPoint+std::abs(i));
00043 }
00044
00045 inline int calcThickness( const double prop )
00046 {
00047 return (int)((iLength-2)*prop+2);
00048 }
00049
00050 inline int calcLength( const double prop, const double v )
00051 {
00052 return (v>0) ? -int(vLength*prop) : int(vLength*prop);
00053 }
00054
00055 ECNode::ECNode( ICNDocument *icnDocument, Node::node_type _type, node_dir dir, const QPoint &pos, QString *_id )
00056 : Node( icnDocument, _type, dir, pos, _id )
00057 {
00058 m_prevV = 0;
00059 m_prevI = 0;
00060 m_pinPoint = 0;
00061 m_bShowVoltageBars = KTLConfig::showVoltageBars();
00062
00063 icnDocument->registerItem(this);
00064
00065 if ( type() == ec_pin ) {
00066 m_pinPoint = new QCanvasRectangle( 0, 0, 3, 3, canvas() );
00067 m_pinPoint->setBrush(Qt::black);
00068 m_pinPoint->setPen(Qt::black);
00069 }
00070
00071 m_pins.resize(1);
00072 m_pins[0] = new Pin(this);
00073 }
00074
00075
00076 ECNode::~ECNode()
00077 {
00078 if (m_pinPoint) m_pinPoint->setCanvas(0);
00079 delete m_pinPoint;
00080
00081 for(unsigned i = 0; i < m_pins.size(); i++)
00082 delete m_pins[i];
00083
00084 m_pins.resize(0);
00085 }
00086
00087
00088 void ECNode::setNumPins( unsigned num )
00089 {
00090 unsigned oldNum = m_pins.size();
00091
00092 if ( num == oldNum ) return;
00093
00094 if ( num > oldNum ) {
00095 m_pins.resize(num);
00096 for ( unsigned i = oldNum; i < num; i++ )
00097 m_pins[i] = new Pin(this);
00098 } else {
00099 for ( unsigned i = num; i < oldNum; i++ )
00100 delete m_pins[i];
00101 m_pins.resize(num);
00102 }
00103
00104 emit numPinsChanged(num);
00105 }
00106
00107 void ECNode::setNodeChanged()
00108 {
00109 if ( !canvas() || numPins() != 1 ) return;
00110
00111 Pin * pin = m_pins[0];
00112
00113 double v = pin->voltage();
00114 double i = pin->current();
00115
00116 if ( v != m_prevV || i != m_prevI ) {
00117 QRect r = boundingRect();
00118 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 );
00119 canvas()->setChanged(r);
00120 m_prevV = v;
00121 m_prevI = i;
00122 }
00123 }
00124
00125 void ECNode::setParentItem( CNItem * parentItem )
00126 {
00127 Node::setParentItem(parentItem);
00128
00129 if ( Component * component = dynamic_cast<Component*>(parentItem) )
00130 {
00131 connect( component, SIGNAL(elementDestroyed(Element* )), this, SLOT(removeElement(Element* )) );
00132 connect( component, SIGNAL(switchDestroyed( Switch* )), this, SLOT(removeSwitch( Switch* )) );
00133 }
00134 }
00135
00136 void ECNode::removeElement( Element * e )
00137 {
00138 for ( unsigned i = 0; i < m_pins.size(); i++ )
00139 m_pins[i]->removeElement(e);
00140 }
00141
00142 void ECNode::removeSwitch( Switch * sw )
00143 {
00144 for ( unsigned i = 0; i < m_pins.size(); i++ )
00145 m_pins[i]->removeSwitch( sw );
00146 }
00147
00148 void ECNode::drawShape( QPainter &p )
00149 {
00150 const int _x = int(x());
00151 const int _y = int(y());
00152
00153 if ( type() == ec_junction ) {
00154
00155
00156 p.drawRect( _x-1, _y-1, 3, 3 );
00157 return;
00158 }
00159
00160 if (m_pinPoint) {
00161 bool drawDivPoint;
00162 QPoint divPoint = findConnectorDivergePoint(&drawDivPoint);
00163 m_pinPoint->setVisible(drawDivPoint);
00164 m_pinPoint->move( divPoint.x()-1, divPoint.y()-1 );
00165 }
00166
00167
00168
00169 if ( numPins() == 1 )
00170 {
00171 double v = pin()->voltage();
00172 double vProp = calcVProp(v);
00173 int length = calcLength( vProp, v );
00174
00175 if ( m_bShowVoltageBars && length != 0 )
00176 {
00177
00178
00179 QPen oldPen = p.pen();
00180
00181 double i = pin()->current();
00182 double iProp = calcIProp(i);
00183 int thickness = calcThickness(iProp);
00184
00185 if ( v > 0 )
00186 p.setPen( QPen( QColor( 255, 166, 0 ), thickness ));
00187 else p.setPen( QPen( QColor( 0, 136, 255 ), thickness ) );
00188
00189
00190
00191 if ( v > 0 && (m_dir == Node::dir_up || m_dir == Node::dir_down) )
00192 length--;
00193 else if ( v < 0 && (m_dir == Node::dir_left || m_dir == Node::dir_right) )
00194 length++;
00195
00196 if ( m_dir == Node::dir_right )
00197 p.drawLine( _x+3, _y, _x+3, _y+length );
00198
00199 else if ( m_dir == Node::dir_down )
00200 p.drawLine( _x, _y+3, _x-length, _y+3 );
00201
00202 else if ( m_dir == Node::dir_left )
00203 p.drawLine( _x-3, _y, _x-3, _y+length );
00204
00205 else if ( m_dir == Node::dir_up )
00206 p.drawLine( _x, _y-3, _x-length, _y-3 );
00207
00208 p.setPen(oldPen);
00209 }
00210 }
00211
00212 QPen pen( p.pen() );
00213 pen.setWidth( (numPins() > 1) ? 2 : 1 );
00214 p.setPen(pen);
00215
00216 if( m_dir == Node::dir_right ) p.drawLine( _x, _y, _x+8, _y );
00217 else if ( m_dir == Node::dir_down ) p.drawLine( _x, _y, _x, _y+8 );
00218 else if ( m_dir == Node::dir_left ) p.drawLine( _x, _y, _x-8, _y );
00219 else if ( m_dir == Node::dir_up ) p.drawLine( _x, _y, _x, _y-8 );
00220 }
00221
00222 #include "ecnode.moc"
00223