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

component.cpp

/***************************************************************************
 *   Copyright (C) 2004-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 "canvasitemparts.h"
#include "circuitdocument.h"
#include "component.h"
#include "src/core/ktlconfig.h"
#include "ecnode.h"
#include "itemdocumentdata.h"
#include "node.h"
#include "pin.h"
#include "simulator.h"

#include "bjt.h"
#include "capacitance.h"
#include "cccs.h"
#include "ccvs.h"
#include "currentsignal.h"
#include "currentsource.h"
#include "diode.h"
#include "inductance.h"
#include "logic.h"
#include "opamp.h"
#include "resistance.h"
#include "switch.h"
#include "vccs.h"
#include "vcvs.h"
#include "voltagepoint.h"
#include "voltagesignal.h"
#include "voltagesource.h"

#include <cmath>
#include <kdebug.h>
#include <qbitarray.h>
#include <qpainter.h>
#include <qwidget.h>
#include <qwmatrix.h>

const int dipWidth = 112;
const int pairSep = 32;

// Degrees per radian
static const double DPR = 57.29577951308232087665461840231273527024;

Component::Component( ICNDocument *icnDocument, bool newItem, const QString &id )
      : CNItem( icnDocument, newItem, id ),
        m_angleDegrees(0),
        b_flipped(false)
{
      m_pCircuitDocument = dynamic_cast<CircuitDocument*>(icnDocument);
      
      for ( int i=0; i<4; ++i )
      {
            m_pPNode[i] = 0l;
            m_pNNode[i] = 0l;
      }
      
      // Get configuration options
      slotUpdateConfiguration();
      
      // And finally register this :-)
      icnDocument->registerItem(this);
}

Component::~Component()
{
      removeElements();
      Simulator::self()->detachComponent(this);
}

00078 void Component::removeItem( )
{
      if (b_deleted)
            return;
      Simulator::self()->detachComponent(this);
      CNItem::removeItem();
}

00086 void Component::removeElements( bool setPinsInterIndependent )
{
      const ElementMapList::iterator end = m_elementMapList.end();
      for ( ElementMapList::iterator it = m_elementMapList.begin(); it != end; ++it )
      {
            Element * e = (*it).e;
            if (e)
            {
                  emit elementDestroyed(e);
                  e->componentDeleted();
            }
      }
      m_elementMapList.clear();
      
      const SwitchList::iterator swEnd = m_switchList.end();
      for ( SwitchList::iterator it = m_switchList.begin(); it != swEnd; ++it )
      {
            Switch * sw = *it;
            if ( !sw )
                  continue;
            
            emit switchDestroyed( sw );
            delete sw;
      }
      m_switchList.clear();
      
      if ( setPinsInterIndependent )
            setAllPinsInterIndependent();
}


00117 void Component::removeElement( Element * element, bool setPinsInterIndependent )
{
      if (!element)
            return;
      
      emit elementDestroyed(element);
      element->componentDeleted();
      
      const ElementMapList::iterator end = m_elementMapList.end();
      for ( ElementMapList::iterator it = m_elementMapList.begin(); it != end; )
      {
            ElementMapList::iterator next = it;
            ++next;
            
            if ( (*it).e == element )
                  m_elementMapList.remove(it);
            
            it = next;
      }
      
      if ( setPinsInterIndependent )
            rebuildPinInterDepedence();
}


00142 void Component::removeSwitch( Switch * sw )
{
      if ( !sw )
            return;
      
      emit switchDestroyed( sw );
      delete sw;
      m_switchList.remove(sw);
      m_pCircuitDocument->requestAssignCircuits();
}


00154 void Component::setNodalCurrents()
{
      const ElementMapList::iterator end = m_elementMapList.end();
      for ( ElementMapList::iterator it = m_elementMapList.begin(); it != end; ++it )
      {
            ElementMap m = (*it);
            for ( int i=0; i<4; i++ )
            {
                  if ( m.n[i] ) {
                        m.n[i]->mergeCurrent( m.e->m_cnodeI[i] );
                  }
            }
      }
}


00170 void Component::initPainter( QPainter &p )
{
      CNItem::initPainter(p);
      
      if ( !b_flipped && (m_angleDegrees%360 == 0) )
            return;
      
      p.save();
      
      p.translate( int(x()), int(y()) );
      if (b_flipped)
            p.scale( -1, 1 );
      
      p.rotate(m_angleDegrees);
      p.translate( -int(x()), -int(y()) );
}


00188 void Component::deinitPainter( QPainter &p )
{
      if ( !b_flipped && (m_angleDegrees%360 == 0) )
            return;
      
      p.restore();
}


00197 void Component::setAngleDegrees( int degrees )
{
      updateConnectorPoints(false);
      m_angleDegrees = degrees;
      itemPointsChanged();
      updateAttachedPositioning();
      p_icnDocument->requestRerouteInvalidatedConnectors();
}


00207 void Component::setFlipped( bool flipped )
{
      updateConnectorPoints(false);
      b_flipped = flipped;
      itemPointsChanged();
      updateAttachedPositioning();
      p_icnDocument->requestRerouteInvalidatedConnectors();
}


00217 void Component::itemPointsChanged()
{
      QPointArray transformedPoints = transMatrix( m_angleDegrees, b_flipped, 0, 0, false ).map(m_itemPoints);
//    transformedPoints.translate( int(x()), int(y()) );
      setPoints(transformedPoints);
}


00225 void Component::restoreFromItemData( const ItemData &itemData )
{
      CNItem::restoreFromItemData(itemData);
      
      setAngleDegrees( int(itemData.angleDegrees) );
      setFlipped(itemData.flipped);
}


00234 ItemData Component::itemData() const
{
      ItemData itemData = CNItem::itemData();
      itemData.angleDegrees = m_angleDegrees;
      itemData.flipped = b_flipped;
      return itemData;
}


00243 QWMatrix Component::transMatrix( int angleDegrees, bool flipped, int x, int y, bool inverse )
{
      QWMatrix m;
      m.translate( x, y );
      if (inverse)
      {
            m.rotate(-angleDegrees);
            if (flipped)
                  m.scale( -1, 1 );
      }
      else
      {
            if (flipped)
                  m.scale( -1, 1 );
            m.rotate(angleDegrees);
      }
      m.translate( -x, -y );
      m.setTransformationMode( QWMatrix::Areas );
      return m;
}


00265 void Component::finishedCreation()
{
      CNItem::finishedCreation();
      updateAttachedPositioning();
}


00272 void Component::updateAttachedPositioning()
{
      if (b_deleted || !m_bDoneCreation)
            return;
      
      //BEGIN Transform the nodes
      const NodeMap::iterator end = m_nodeMap.end();
      for ( NodeMap::iterator it = m_nodeMap.begin(); it != end; ++it )
      {
            if ( !it.data().node )
                  kdError() << k_funcinfo << "Node in nodemap is null" << endl;
            else
            {
                  int nx = int((std::cos(m_angleDegrees/DPR) * it.data().x) - (std::sin(m_angleDegrees/DPR) * it.data().y));
                  int ny = int((std::sin(m_angleDegrees/DPR) * it.data().x) + (std::cos(m_angleDegrees/DPR) * it.data().y));
                  
                  if (b_flipped)
                        nx = -nx;
                  
#define round_8(x) (((x) > 0) ? int(((x)+4)/8)*8 : int(((x)-4)/8)*8)
                  nx = round_8(nx);
                  ny = round_8(ny);
#undef round_8
                  
                  int newDir = (((m_angleDegrees + it.data().orientation)%360)+360)%360;
                  if (b_flipped)
                        newDir = (((180-newDir)%360)+360)%360;
                  
                  it.data().node->move( nx+x(), ny+y() );
                  it.data().node->setOrientation( (Node::node_dir)newDir );
            }
      }
      //END Transform the nodes
      
      
      //BEGIN Transform the GuiParts
      QWMatrix m;
      
      if (b_flipped)
            m.scale( -1, 1 );
      m.rotate(m_angleDegrees);
      m.setTransformationMode( QWMatrix::Areas );
      
      const TextMap::iterator textMapEnd = m_textMap.end();
      for ( TextMap::iterator it = m_textMap.begin(); it != textMapEnd; ++it )
      {
            QRect newPos = m.mapRect( it.data()->recommendedRect() );
            it.data()->move( newPos.x() + x(), newPos.y() + y() );
            it.data()->setGuiPartSize( newPos.width(), newPos.height() );
            it.data()->setAngleDegrees(m_angleDegrees);
      }
      const WidgetMap::iterator widgetMapEnd = m_widgetMap.end();
      for ( WidgetMap::iterator it = m_widgetMap.begin(); it != widgetMapEnd; ++it )
      {
            QRect newPos = m.mapRect( it.data()->recommendedRect() );
            it.data()->move( newPos.x() + x(), newPos.y() + y() );
            it.data()->setGuiPartSize( newPos.width(), newPos.height() );
            it.data()->setAngleDegrees(m_angleDegrees);
      }
      //END Transform the GuiParts
}


00335 void Component::drawPortShape( QPainter & p )
{
      int h = height();
      int w = width() - 1;
      int _x = int( x() + offsetX() );
      int _y = int( y() + offsetY() );
      
      double roundSize = 8;
      double slantIndent = 8;
                  
      const double pi = 3.1415926536;
      const double DPR = 180./pi;
      double inner = std::atan(h/slantIndent);  // Angle for slight corner
      double outer = pi-inner;                              // Angle for sharp corner
                  
      int inner16 = int(16*inner*DPR);
      int outer16 = int(16*outer*DPR);
      
      p.save();
      p.setPen( Qt::NoPen );
      p.drawPolygon( areaPoints() );
      p.restore();
      
      initPainter( p );
      
      // Left line
      p.drawLine( int(_x),    int(_y+roundSize/2),    int(_x),    int(_y+h-roundSize/2) );
      
      // Right line
      p.drawLine( int(_x+w),  int(_y-slantIndent+h-roundSize/2),  int(_x+w),  int(_y+slantIndent+roundSize/2) );
      
      // Bottom line
      p.drawLine( int(_x+(1-std::cos(outer))*(roundSize/2)),            int(_y+h+(std::sin(outer)-1)*(roundSize/2)),                      
                        int(_x+w+(std::cos(inner)-1)*(roundSize/2)),    int(_y+h-slantIndent+(std::sin(inner)-1)*(roundSize/2)) );
      
      // Top line
      p.drawLine( int(_x+w+(std::cos(outer)-1)*(roundSize/2)),    int(_y+slantIndent+(1-std::sin(inner))*(roundSize/2)),
                        int(_x+(1-std::cos(inner))*(roundSize/2)),            int(_y+(1-std::sin(outer))*(roundSize/2)) );
      
      
      // Top left
      p.drawArc( int(_x),                       int(_y),                                        int(roundSize), int(roundSize), 90*16,    outer16 );
      
      // Bottom left
      p.drawArc( int(_x),                       int(_y+h-roundSize),                      int(roundSize), int(roundSize), 180*16,   outer16 );
      
      // Top right
      p.drawArc( int(_x+w-roundSize),     int(_y+slantIndent),                      int(roundSize), int(roundSize), 0,        inner16 );
      
      // Bottom right
      p.drawArc( int(_x+w-roundSize),     int(_y-slantIndent+h-roundSize),    int(roundSize), int(roundSize), 270*16,   inner16 );
      
      deinitPainter( p );
}


00391 void Component::initDIP( const QStringList & pins )
{
      const int numPins = pins.size();
      const int numSide = numPins/2 + numPins%2;
      
      // Pins along left
      for ( int i=0; i<numSide; i++ )
      {
            if ( !pins[i].isEmpty() )
            {
                  const int nodeX = -8+offsetX();
                  const int nodeY = (i+1)*16+offsetY();
                  ECNode *node = ecNodeWithID(pins[i]);
                  if (node)
                  {
                        m_nodeMap[pins[i]].x = nodeX;
                        m_nodeMap[pins[i]].y = nodeY;
                        m_nodeMap[pins[i]].orientation = (Node::node_dir)0;
                  }
                  else
                        createPin( nodeX, nodeY, 0, pins[i] );
            }
      }
      // Pins along right
      for ( int i=numSide; i<numPins; i++ )
      {
            if ( !pins[i].isEmpty() )
            {
                  const int nodeX = width()+8+offsetX();
                  const int nodeY = (2*numSide-i)*16+offsetY();
                  ECNode *node = ecNodeWithID(pins[i]);
                  if (node)
                  {
                        m_nodeMap[pins[i]].x = nodeX;
                        m_nodeMap[pins[i]].y = nodeY;
                        m_nodeMap[pins[i]].orientation = (Node::node_dir)180;
                  }
                  else
                        createPin( nodeX, nodeY, 180, pins[i] );
            }
      }
      
      updateAttachedPositioning();
}

00436 void Component::initDIPSymbol( const QStringList & pins, int _width )
{
      const int numPins = pins.size();
      const int numSide = numPins/2 + numPins%2;
      
      setSize( -(_width-(_width%16))/2, -(numSide+1)*8, _width, (numSide+1)*16, true );
      
      QWidget tmpWidget;
      QPainter p(&tmpWidget);
      
      p.setFont(m_font);
      
      // Pins along left
      for ( int i=0; i<numSide; i++ )
      {
            if ( !pins[i].isEmpty() )
            {
                  const QString text = *pins.at(i);
                  
                  const int _top = (i+1)*16-8 + offsetY();
                  const int _width = width()/2 - 6;
                  const int _left = 6 + offsetX();
                  const int _height = 16;
                  
                  QRect br = p.boundingRect( QRect( _left, _top, _width, _height ), Qt::AlignLeft, text );
                  addDisplayText( text, br, text );
            }
      }
      // Pins along right
      for ( int i=numSide; i<numPins; i++ )
      {
            if ( !pins[i].isEmpty() )
            {
                  const QString text = *pins.at(i);
                  
                  const int _top = (2*numSide-i)*16 - 8 + offsetY();
                  const int _width = width()/2 - 6;
                  const int _left = (width()/2) + offsetX();
                  const int _height = 16;
                  
                  QRect br = p.boundingRect( QRect( _left, _top, _width, _height ), Qt::AlignRight, text );
                  addDisplayText( text, br, text );
            }
      }
      
      updateAttachedPositioning();
}


//    QString createNode( double _x, double _y, int shape, int orientation, const QString &name, int type, bool isInput = true );

00487 void Component::init1PinLeft( int h1 )
{
      if ( h1 == -1 ) h1 = offsetY()+height()/2;

      m_pNNode[0] = createPin( offsetX()-8,                 h1, 0,      "n1" );
}

00494 void Component::init2PinLeft( int h1, int h2 )
{
      if ( h1 == -1 ) h1 = offsetY()+8;
      if ( h2 == -1 ) h2 = offsetY()+height()-8;
      
      m_pNNode[0] = createPin( offsetX()-8,                 h1, 0,      "n1" );
      m_pNNode[1] = createPin( offsetX()-8,                 h2, 0,      "n2" );
}

00503 void Component::init3PinLeft( int h1, int h2, int h3 )
{
      if ( h1 == -1 ) h1 = offsetY()+8;
      if ( h2 == -1 ) h2 = offsetY()+height()/2;
      if ( h3 == -1 ) h3 = offsetY()+height()-8;
      
      m_pNNode[0] = createPin( offsetX()-8,                 h1, 0,      "n1" );
      m_pNNode[1] = createPin( offsetX()-8,                 h2, 0,      "n2" );
      m_pNNode[2] = createPin( offsetX()-8,                 h3, 0,      "n3" );
}

00514 void Component::init4PinLeft( int h1, int h2, int h3, int h4 )
{
      if ( h1 == -1 ) h1 = offsetY()+8;
      if ( h2 == -1 ) h2 = offsetY()+24;
      if ( h3 == -1 ) h3 = offsetY()+height()-24;
      if ( h4 == -1 ) h4 = offsetY()+height()-8;
      
      m_pNNode[0] = createPin( offsetX()-8,                 h1, 0,      "n1" );
      m_pNNode[1] = createPin( offsetX()-8,                 h2, 0,      "n2" );
      m_pNNode[2] = createPin( offsetX()-8,                 h3, 0,      "n3" );
      m_pNNode[3] = createPin( offsetX()-8,                 h4, 0,      "n4" );
}

00527 void Component::init1PinRight( int h1 )
{
      if ( h1 == -1 ) h1 = offsetY()+height()/2;

      m_pPNode[0] = createPin( offsetX()+width()+8,   h1, 180, "p1" );
}


00535 void Component::init2PinRight( int h1, int h2 )
{
      if ( h1 == -1 ) h1 = offsetY()+8;
      if ( h2 == -1 ) h2 = offsetY()+height()-8;
      
      m_pPNode[0] = createPin( offsetX()+width()+8,   h1, 180,    "p1" );
      m_pPNode[1] = createPin( offsetX()+width()+8,   h2, 180,    "p2" );
}

00544 void Component::init3PinRight( int h1, int h2, int h3 )
{
      if ( h1 == -1 ) h1 = offsetY()+8;
      if ( h2 == -1 ) h2 = offsetY()+height()/2;
      if ( h3 == -1 ) h3 = offsetY()+height()-8;
      
      m_pPNode[0] = createPin( offsetX()+width()+8,   h1, 180,    "p1" );
      m_pPNode[1] = createPin( offsetX()+width()+8,   h2, 180,    "p2" );
      m_pPNode[2] = createPin( offsetX()+width()+8,   h3, 180,    "p3" );
}

00555 void Component::init4PinRight( int h1, int h2, int h3, int h4 )
{
      if ( h1 == -1 ) h1 = offsetY()+8;
      if ( h2 == -1 ) h2 = offsetY()+24;
      if ( h3 == -1 ) h3 = offsetY()+height()-24;
      if ( h4 == -1 ) h4 = offsetY()+height()-8;
      
      m_pPNode[0] = createPin( offsetX()+width()+8,   h1, 180,    "p1" );
      m_pPNode[1] = createPin( offsetX()+width()+8,   h2, 180,    "p2" );
      m_pPNode[2] = createPin( offsetX()+width()+8,   h3, 180,    "p3" );
      m_pPNode[3] = createPin( offsetX()+width()+8,   h4, 180,    "p4" );
}


ECNode* Component::ecNodeWithID( const QString &ecNodeId )
{
      return dynamic_cast<ECNode*>( p_icnDocument->nodeWithID( nodeId(ecNodeId) ) );
}


void Component::slotUpdateConfiguration()
{
      const LogicConfig logicConfig = LogicIn::getConfig();
      
      const ElementMapList::iterator end = m_elementMapList.end();
      for ( ElementMapList::iterator it = m_elementMapList.begin(); it != end; ++it )
      {
            if ( LogicIn * logicIn = dynamic_cast<LogicIn*>((*it).e) )
                  logicIn->setLogic(logicConfig);
      }
}



BJT *             Component::createBJT( ECNode *c, ECNode *b, ECNode *e, bool isNPN )
{ return createBJT( c->pin(), b->pin(), e->pin(), isNPN ); }
Capacitance *     Component::createCapacitance( ECNode *n0, ECNode *n1, double capacitance )
{ return createCapacitance( n0->pin(), n1->pin(), capacitance ); }
CCCS *                  Component::createCCCS( ECNode *n0, ECNode *n1, ECNode *n2, ECNode *n3, double gain )
{ return createCCCS( n0->pin(), n1->pin(), n2->pin(), n3->pin(), gain ); }
CCVS *                  Component::createCCVS( ECNode *n0, ECNode *n1, ECNode *n2, ECNode *n3, double gain )
{ return createCCVS( n0->pin(), n1->pin(), n2->pin(), n3->pin(), gain ); }
CurrentSignal *   Component::createCurrentSignal( ECNode *n0, ECNode *n1, double current )
{ return createCurrentSignal( n0->pin(), n1->pin(), current ); }
CurrentSource *   Component::createCurrentSource( ECNode *n0, ECNode *n1, double current )
{ return createCurrentSource( n0->pin(), n1->pin(), current ); }
Diode *                 Component::createDiode( ECNode *n0, ECNode *n1 )
{ return createDiode( n0->pin(), n1->pin() ); }
Inductance *      Component::createInductance( ECNode *n0, ECNode *n1, double inductance )
{ return createInductance( n0->pin(), n1->pin(), inductance ); }
LogicIn *         Component::createLogicIn( ECNode *node )
{ return createLogicIn( node->pin() ); }
LogicOut *        Component::createLogicOut( ECNode *node, bool isHigh )
{ return createLogicOut( node->pin(), isHigh ); }
OpAmp *                 Component::createOpAmp( ECNode * nonInverting, ECNode * out, ECNode * inverting )
{ return createOpAmp( nonInverting->pin(), out->pin(), inverting->pin() ); }
Resistance *      Component::createResistance( ECNode *n0, ECNode *n1, double resistance )
{ return createResistance( n0->pin(), n1->pin(), resistance ); }
Switch *          Component::createSwitch( ECNode *n0, ECNode *n1, bool open )
{ return createSwitch( n0->pin(), n1->pin(), open ); }
VCCS *                  Component::createVCCS( ECNode *n0, ECNode *n1, ECNode *n2, ECNode *n3, double gain )
{ return createVCCS( n0->pin(), n1->pin(), n2->pin(), n3->pin(), gain ); }
VCVS *                  Component::createVCVS( ECNode *n0, ECNode *n1, ECNode *n2, ECNode *n3, double gain )
{ return createVCVS( n0->pin(), n1->pin(), n2->pin(), n3->pin(), gain ); }
VoltagePoint *    Component::createVoltagePoint( ECNode *n0, double voltage )
{ return createVoltagePoint( n0->pin(), voltage ); }
VoltageSignal *   Component::createVoltageSignal( ECNode *n0, ECNode *n1, double voltage )
{ return createVoltageSignal( n0->pin(), n1->pin(), voltage ); }
VoltageSource *   Component::createVoltageSource( ECNode *n0, ECNode *n1, double voltage )
{ return createVoltageSource( n0->pin(), n1->pin(), voltage ); }

BJT* Component::createBJT( Pin *cN, Pin *bN, Pin *eN, bool isNPN )
{
      BJT *e = new BJT(isNPN);
      
      QValueList<Pin*> pins;
      pins << bN << cN << eN;
      
      ElementMapList::iterator it = handleElement( e, pins );
      setInterDependent( it, pins );
      return e;
}

Capacitance* Component::createCapacitance( Pin *n0, Pin *n1, double capacitance )
{
      Capacitance *e = new Capacitance( capacitance, 1./LINEAR_UPDATE_RATE );
      
      QValueList<Pin*> pins;
      pins << n0 << n1;
      
      ElementMapList::iterator it = handleElement( e, pins );
      setInterDependent( it, pins );
      return e;
}

CCCS* Component::createCCCS( Pin *n0, Pin *n1, Pin *n2, Pin *n3, double gain )
{
      CCCS *e = new CCCS(gain);
      
      QValueList<Pin*> pins;
      pins << n0 << n1 << n2 << n3;
      
      ElementMapList::iterator it = handleElement( e, pins );
      setInterDependent( it, pins );
      return e;
}

CCVS* Component::createCCVS( Pin *n0, Pin *n1, Pin *n2, Pin *n3, double gain )
{
      CCVS *e = new CCVS(gain);
      
      QValueList<Pin*> pins;
      pins << n0 << n1 << n2 << n3;
      
      ElementMapList::iterator it = handleElement( e, pins );
      setInterCircuitDependent( it, pins );
      
      pins.clear();
      pins << n0 << n1;
      setInterGroundDependent( it, pins );
      
      pins.clear();
      pins << n2 << n3;
      setInterGroundDependent( it, pins );
      
      return e;
}

CurrentSignal* Component::createCurrentSignal( Pin *n0, Pin *n1, double current )
{
      CurrentSignal *e = new CurrentSignal( 1./LINEAR_UPDATE_RATE, current );
      
      QValueList<Pin*> pins;
      pins << n0 << n1;
      
      ElementMapList::iterator it = handleElement( e, pins );
      setInterDependent( it, pins );
      return e;
}

CurrentSource* Component::createCurrentSource( Pin *n0, Pin *n1, double current )
{
      CurrentSource *e = new CurrentSource(current);
      
      QValueList<Pin*> pins;
      pins << n0 << n1;
      
      ElementMapList::iterator it = handleElement( e, pins );
      setInterDependent( it, pins );
      return e;
}

Diode* Component::createDiode( Pin *n0, Pin *n1 )
{
      Diode *e = new Diode();
      
      QValueList<Pin*> pins;
      pins << n0 << n1;
      
      ElementMapList::iterator it = handleElement( e, pins );
      setInterDependent( it, pins );
      return e;
}

Inductance* Component::createInductance( Pin *n0, Pin *n1, double inductance )
{
      Inductance *e = new Inductance( inductance, 1./LINEAR_UPDATE_RATE );
      
      QValueList<Pin*> pins;
      pins << n0 << n1;
      
      ElementMapList::iterator it = handleElement( e, pins );
      setInterDependent( it, pins );
      return e;
}

LogicIn *Component::createLogicIn( Pin *node )
{
      LogicIn *e = new LogicIn(LogicIn::getConfig());
      
      QValueList<Pin*> pins;
      pins << node;
      
      ElementMapList::iterator it = handleElement( e, pins );
      return e;
}

LogicOut *Component::createLogicOut( Pin *node, bool isHigh )
{
      LogicOut *e = new LogicOut( LogicIn::getConfig(), isHigh);
      
      QValueList<Pin*> pins;
      pins << node;
      
      ElementMapList::iterator it = handleElement( e, pins );
      setInterDependent( it, pins );
      return e;
}

OpAmp * Component::createOpAmp( Pin * nonInverting, Pin * inverting, Pin * out )
{
      OpAmp * e = new OpAmp();
      
      QValueList<Pin*> pins;
      pins << nonInverting << inverting << out;
      
      ElementMapList::iterator it = handleElement( e, pins );
      setInterDependent( it, pins );
      return e;
}

Resistance* Component::createResistance( Pin *n0, Pin *n1, double resistance )
{
      Resistance *e = new Resistance(resistance);
      
      QValueList<Pin*> pins;
      pins << n0 << n1;
      
      ElementMapList::iterator it = handleElement( e, pins );
      setInterDependent( it, pins );
      return e;
}

Switch* Component::createSwitch( Pin *n0, Pin *n1, bool open )
{
      // Note that a Switch is not really an element (although in many cases it
      // behaves very much like one).
      
      Switch * e = new Switch( this, n0, n1, open ? Switch::Open : Switch::Closed );
      m_switchList.append(e);
      n0->addSwitch( e );
      n1->addSwitch( e );
      emit switchCreated( e );
      return e;
}

VCCS* Component::createVCCS( Pin *n0, Pin *n1, Pin *n2, Pin *n3, double gain )
{
      VCCS *e = new VCCS(gain);
      
      QValueList<Pin*> pins;
      pins << n0 << n1 << n2 << n3;
      
      ElementMapList::iterator it = handleElement( e, pins );
      setInterDependent( it, pins );
      return e;
}

VCVS* Component::createVCVS( Pin *n0, Pin *n1, Pin *n2, Pin *n3, double gain )
{
      VCVS *e = new VCVS(gain);
      
      QValueList<Pin*> pins;
      pins << n0 << n1 << n2 << n3;
      
      ElementMapList::iterator it = handleElement( e, pins );
      setInterCircuitDependent( it, pins );
      
      pins.clear();
      pins << n0 << n1;
      setInterGroundDependent( it, pins );
      
      pins.clear();
      pins << n2 << n3;
      setInterGroundDependent( it, pins );
      return e;
}

VoltagePoint* Component::createVoltagePoint( Pin *n0, double voltage )
{
      VoltagePoint *e = new VoltagePoint(voltage);
      
      QValueList<Pin*> pins;
      pins << n0;
      
      ElementMapList::iterator it = handleElement( e, pins );
      setInterDependent( it, pins );
      return e;
}

VoltageSignal* Component::createVoltageSignal( Pin *n0, Pin *n1, double voltage )
{
      VoltageSignal *e = new VoltageSignal( 1./LINEAR_UPDATE_RATE, voltage );
      
      QValueList<Pin*> pins;
      pins << n0 << n1;
      
      ElementMapList::iterator it = handleElement( e, pins );
      setInterDependent( it, pins );
      return e;
}

VoltageSource* Component::createVoltageSource( Pin *n0, Pin *n1, double voltage )
{
      VoltageSource *e = new VoltageSource(voltage);
      
      QValueList<Pin*> pins;
      pins << n0 << n1;
      
      ElementMapList::iterator it = handleElement( e, pins );
      setInterDependent( it, pins );
      return e;
}


00860 ElementMapList::iterator Component::handleElement( Element *e, const QValueList<Pin*> & pins )
{
      if (!e)
            return m_elementMapList.end();
      
      ElementMap em;
      em.e = e;
      int at = 0;
      QValueList<Pin*>::ConstIterator end = pins.end();
      for ( QValueList<Pin*>::ConstIterator it = pins.begin(); it != end; ++it )
      {
            (*it)->addElement(e);
            em.n[at++] = *it;
      }
      
      ElementMapList::iterator it = m_elementMapList.append(em);
      
      emit elementCreated(e);
      return it;
}


00882 void Component::setInterDependent( ElementMapList::iterator it, const QValueList<Pin*> & pins )
{
      setInterCircuitDependent( it, pins );
      setInterGroundDependent( it, pins );
}


00889 void Component::setInterCircuitDependent( ElementMapList::iterator it, const QValueList<Pin*> & pins )
{
      QValueList<Pin*>::ConstIterator end = pins.end();
      for ( QValueList<Pin*>::ConstIterator it1 = pins.begin(); it1 != end; ++it1 )
      {
            for ( QValueList<Pin*>::ConstIterator it2 = pins.begin(); it2 != end; ++it2 )
            {
                  (*it1)->addCircuitDependentPin( *it2 );
            }
      }
      
      (*it).interCircuitDependent.append( pins );
}


00904 void Component::setInterGroundDependent( ElementMapList::iterator it, const QValueList<Pin*> & pins )
{
      QValueList<Pin*>::ConstIterator end = pins.end();
      for ( QValueList<Pin*>::ConstIterator it1 = pins.begin(); it1 != end; ++it1 )
      {
            for ( QValueList<Pin*>::ConstIterator it2 = pins.begin(); it2 != end; ++it2 )
            {
                  (*it1)->addGroundDependentPin( *it2 );
            }
      }
      
      (*it).interGroundDependent.append( pins );
}


00919 void Component::rebuildPinInterDepedence()
{
      setAllPinsInterIndependent();
      
      // Rebuild dependencies
      ElementMapList::iterator emlEnd = m_elementMapList.end();
      for ( ElementMapList::iterator it = m_elementMapList.begin(); it != emlEnd; ++it )
      {
            // Many copies of the pin lists as these will be affected when we call setInter*Dependent
            PinListList list = (*it).interCircuitDependent;
            
            PinListList::iterator depEnd = list.end();
            for ( PinListList::iterator depIt = list.begin(); depIt != depEnd; ++depIt )
                  setInterCircuitDependent( it, *depIt );
            
            list = (*it).interGroundDependent;
            
            depEnd = list.end();
            for ( PinListList::iterator depIt = list.begin(); depIt != depEnd; ++depIt )
                  setInterGroundDependent( it, *depIt );
      }
}


00943 void Component::setAllPinsInterIndependent()
{
      NodeMap::iterator nmEnd = m_nodeMap.end();
      for ( NodeMap::iterator it = m_nodeMap.begin(); it != nmEnd; ++it )
      {
            PinVector pins = (static_cast<ECNode*>(it.data().node))->pins();
            PinVector::iterator pinsEnd = pins.end();
            for ( PinVector::iterator pinsIt = pins.begin(); pinsIt != pinsEnd; ++pinsIt )
            {
                  if ( *pinsIt )
                        (*pinsIt)->removeDependentPins();
            }
      }
}


00959 void Component::initElements( const uint stage )
{
      /// @todo this function is ugly and messy and needs tidying up
      
      const ElementMapList::iterator end = m_elementMapList.end();
            
      if ( stage == 1 )
      {
            for ( ElementMapList::iterator it = m_elementMapList.begin(); it != end; ++it )
            {
                  (*it).e->add_initial_dc();
            }
            return;
      }
      
      for ( ElementMapList::iterator it = m_elementMapList.begin(); it != end; ++it )
      {
            ElementMap m = (*it);
            
            if ( m.n[3] ) {
                  m.e->setCNodes( m.n[0]->eqId(), m.n[1]->eqId(), m.n[2]->eqId(), m.n[3]->eqId() );
            }
            else if ( m.n[2] ) {
                  m.e->setCNodes( m.n[0]->eqId(), m.n[1]->eqId(), m.n[2]->eqId() );
            }
            else if ( m.n[1] ) {
                  m.e->setCNodes( m.n[0]->eqId(), m.n[1]->eqId() );
            }
            else if ( m.n[0] ) {
                  m.e->setCNodes( m.n[0]->eqId() );
            }
      }
      
      for ( ElementMapList::iterator it = m_elementMapList.begin(); it != end; ++it )
      {
            (*it).e->add_map();
      }
}


ECNode * Component::createPin( double x, double y, int orientation, const QString & name )
{
      return dynamic_cast<ECNode*>( createNode( x, y, orientation, name, Node::ec_pin ) );
}


//BEGIN class ElementMap
ElementMap::ElementMap()
{
      e = 0;
      for ( int i = 0; i < 4; ++i )
            n[i] = 0;
}
//END class ElementMap


#include "component.moc"



Generated by  Doxygen 1.6.0   Back to index