Logo Search packages:      
Sourcecode: ktechlab version File versions  Download package

ecnode.cpp

/***************************************************************************
 *   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);
}


00090 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;
      }
}


00135 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 );
}


00161 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"

Generated by  Doxygen 1.6.0   Back to index