933 lines
28 KiB
C++
933 lines
28 KiB
C++
/*
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
*
|
|
* Copyright (C) 2007, 2008 Lubo Racko <developer@lura.sk>
|
|
* Copyright (C) 2007, 2008, 2012-2013 Alexander Lunev <al.lunev@yahoo.com>
|
|
* Copyright (C) 2012 KiCad Developers, see CHANGELOG.TXT for contributors.
|
|
*
|
|
* 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.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, you may find one here:
|
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
|
* or you may write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
/**
|
|
* @file pcb.cpp
|
|
*/
|
|
|
|
#include <wx/wx.h>
|
|
#include <wx/config.h>
|
|
|
|
#include <common.h>
|
|
|
|
#include <pcb.h>
|
|
#include <pcb_arc.h>
|
|
#include <pcb_copper_pour.h>
|
|
#include <pcb_cutout.h>
|
|
#include <pcb_keepout.h>
|
|
#include <pcb_line.h>
|
|
#include <pcb_module.h>
|
|
#include <pcb_pad_shape.h>
|
|
#include <pcb_via_shape.h>
|
|
#include <pcb_pad.h>
|
|
#include <pcb_text.h>
|
|
#include <pcb_via.h>
|
|
#include <s_expr_loader.h>
|
|
|
|
namespace PCAD2KICAD {
|
|
|
|
int PCB::GetKiCadLayer( int aPCadLayer )
|
|
{
|
|
wxASSERT( aPCadLayer >= 0 && aPCadLayer < MAX_PCAD_LAYER_QTY );
|
|
return m_layersMap[aPCadLayer].KiCadLayer;
|
|
}
|
|
|
|
LAYER_TYPE_T PCB::GetLayerType( int aPCadLayer )
|
|
{
|
|
wxASSERT( aPCadLayer >= 0 && aPCadLayer < MAX_PCAD_LAYER_QTY );
|
|
return m_layersMap[aPCadLayer].layerType;
|
|
}
|
|
|
|
wxString PCB::GetLayerNetNameRef( int aPCadLayer )
|
|
{
|
|
wxASSERT( aPCadLayer >= 0 && aPCadLayer < MAX_PCAD_LAYER_QTY );
|
|
return m_layersMap[aPCadLayer].netNameRef;
|
|
}
|
|
|
|
PCB::PCB( BOARD* aBoard ) : PCB_MODULE( this, aBoard )
|
|
{
|
|
int i;
|
|
|
|
m_defaultMeasurementUnit = wxT( "mil" );
|
|
|
|
for( i = 0; i < MAX_PCAD_LAYER_QTY; i++ )
|
|
{
|
|
m_layersMap[i].KiCadLayer = SOLDERMASK_N_FRONT; // default
|
|
m_layersMap[i].layerType = LAYER_TYPE_NONSIGNAL; // default
|
|
m_layersMap[i].netNameRef = wxT( "" ); // default
|
|
}
|
|
|
|
m_sizeX = 0;
|
|
m_sizeY = 0;
|
|
|
|
m_layersMap[1].KiCadLayer = LAST_COPPER_LAYER;
|
|
m_layersMap[1].layerType = LAYER_TYPE_SIGNAL;
|
|
|
|
m_layersMap[2].KiCadLayer = FIRST_COPPER_LAYER;
|
|
m_layersMap[2].layerType = LAYER_TYPE_SIGNAL;
|
|
|
|
m_layersMap[3].KiCadLayer = ECO2_N;
|
|
m_layersMap[6].KiCadLayer = SILKSCREEN_N_FRONT;
|
|
m_layersMap[7].KiCadLayer = SILKSCREEN_N_BACK;
|
|
m_timestamp_cnt = 0x10000000;
|
|
}
|
|
|
|
|
|
PCB::~PCB()
|
|
{
|
|
int i;
|
|
|
|
for( i = 0; i < (int) m_pcbComponents.GetCount(); i++ )
|
|
{
|
|
delete m_pcbComponents[i];
|
|
}
|
|
|
|
for( i = 0; i < (int) m_pcbNetlist.GetCount(); i++ )
|
|
{
|
|
delete m_pcbNetlist[i];
|
|
}
|
|
}
|
|
|
|
|
|
int PCB::GetNewTimestamp()
|
|
{
|
|
return m_timestamp_cnt++;
|
|
}
|
|
|
|
int PCB::GetNetCode( wxString aNetName )
|
|
{
|
|
PCB_NET* net;
|
|
|
|
for( int i = 0; i < (int) m_pcbNetlist.GetCount(); i++ )
|
|
{
|
|
net = m_pcbNetlist[i];
|
|
|
|
if( net->m_name == aNetName )
|
|
{
|
|
return net->m_netCode;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
XNODE* PCB::FindCompDefName( XNODE* aNode, wxString aName )
|
|
{
|
|
XNODE* result = NULL, * lNode;
|
|
wxString propValue;
|
|
|
|
lNode = FindNode( aNode, wxT( "compDef" ) );
|
|
|
|
while( lNode )
|
|
{
|
|
if( lNode->GetName() == wxT( "compDef" ) )
|
|
{
|
|
lNode->GetAttribute( wxT( "Name" ), &propValue );
|
|
|
|
if( propValue == aName )
|
|
{
|
|
result = lNode;
|
|
lNode = NULL;
|
|
}
|
|
}
|
|
|
|
if( lNode )
|
|
lNode = lNode->GetNext();
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
void PCB::SetTextProperty( XNODE* aNode, TTEXTVALUE* aTextValue,
|
|
wxString aPatGraphRefName, wxString aXmlName,
|
|
wxString aActualConversion )
|
|
{
|
|
XNODE* tNode, * t1Node;
|
|
wxString n, pn, propValue, str;
|
|
|
|
// aNode is pattern now
|
|
tNode = aNode;
|
|
t1Node = aNode;
|
|
n = aXmlName;
|
|
|
|
// new file format version
|
|
if( FindNode( tNode, wxT( "patternGraphicsNameRef" ) ) )
|
|
{
|
|
FindNode( tNode,
|
|
wxT( "patternGraphicsNameRef" ) )->GetAttribute( wxT( "Name" ),
|
|
&pn );
|
|
pn.Trim( false );
|
|
pn.Trim( true );
|
|
tNode = FindNode( tNode, wxT( "patternGraphicsRef" ) );
|
|
|
|
while( tNode )
|
|
{
|
|
if( tNode->GetName() == wxT( "patternGraphicsRef" ) )
|
|
{
|
|
if( FindNode( tNode, wxT( "patternGraphicsNameRef" ) ) )
|
|
{
|
|
FindNode( tNode,
|
|
wxT( "patternGraphicsNameRef" ) )->GetAttribute( wxT( "Name" ),
|
|
&propValue );
|
|
|
|
if( propValue == pn )
|
|
{
|
|
t1Node = tNode; // find correct section with same name.
|
|
str = aTextValue->text;
|
|
str.Trim( false );
|
|
str.Trim( true );
|
|
n = n + wxT( ' ' ) + str; // changed in new file version.....
|
|
tNode = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( tNode )
|
|
tNode = tNode->GetNext();
|
|
}
|
|
}
|
|
|
|
// old version and compatibile fr both from this point
|
|
tNode = FindNode( t1Node, wxT( "attr" ) );
|
|
|
|
while( tNode )
|
|
{
|
|
tNode->GetAttribute( wxT( "Name" ), &propValue );
|
|
propValue.Trim( false );
|
|
propValue.Trim( true );
|
|
|
|
if( propValue == n )
|
|
break;
|
|
|
|
tNode = tNode->GetNext();
|
|
}
|
|
|
|
if( tNode )
|
|
SetTextParameters( tNode, aTextValue, m_defaultMeasurementUnit, aActualConversion );
|
|
}
|
|
|
|
|
|
void PCB::DoPCBComponents( XNODE* aNode,
|
|
wxXmlDocument* aXmlDoc,
|
|
wxString aActualConversion,
|
|
wxStatusBar* aStatusBar )
|
|
{
|
|
XNODE* lNode, * tNode, * mNode;
|
|
PCB_MODULE* mc;
|
|
PCB_PAD* pad;
|
|
PCB_VIA* via;
|
|
PCB_KEEPOUT* keepOut;
|
|
wxString cn, str, propValue;
|
|
|
|
lNode = aNode->GetChildren();
|
|
|
|
while( lNode )
|
|
{
|
|
mc = NULL;
|
|
|
|
if( lNode->GetName() == wxT( "pattern" ) )
|
|
{
|
|
FindNode( lNode, wxT( "patternRef" ) )->GetAttribute( wxT( "Name" ),
|
|
&cn );
|
|
cn = ValidateName( cn );
|
|
tNode = FindNode( (XNODE *)aXmlDoc->GetRoot(), wxT( "library" ) );
|
|
|
|
if( tNode && cn.Len() > 0 )
|
|
{
|
|
tNode = FindModulePatternDefName( tNode, cn );
|
|
|
|
if( tNode )
|
|
{
|
|
mc = new PCB_MODULE( this, m_board );
|
|
|
|
mNode = FindNode( lNode, wxT( "patternGraphicsNameRef" ) );
|
|
if( mNode )
|
|
mNode->GetAttribute( wxT( "Name" ), &mc->m_patGraphRefName );
|
|
|
|
mc->Parse( tNode, aStatusBar, m_defaultMeasurementUnit, aActualConversion );
|
|
}
|
|
}
|
|
|
|
if( mc )
|
|
{
|
|
mc->m_compRef = cn; // default - in new version of file it is updated later....
|
|
tNode = FindNode( lNode, wxT( "refDesRef" ) );
|
|
|
|
if( tNode )
|
|
{
|
|
tNode->GetAttribute( wxT( "Name" ), &mc->m_name.text );
|
|
SetTextProperty( lNode, &mc->m_name, mc->m_patGraphRefName, wxT(
|
|
"RefDes" ), aActualConversion );
|
|
SetTextProperty( lNode, &mc->m_value, mc->m_patGraphRefName, wxT(
|
|
"Value" ), aActualConversion );
|
|
}
|
|
|
|
tNode = FindNode( lNode, wxT( "pt" ) );
|
|
|
|
if( tNode )
|
|
SetPosition( tNode->GetNodeContent(),
|
|
m_defaultMeasurementUnit,
|
|
&mc->m_positionX,
|
|
&mc->m_positionY,
|
|
aActualConversion );
|
|
|
|
tNode = FindNode( lNode, wxT( "rotation" ) );
|
|
|
|
if( tNode )
|
|
{
|
|
str = tNode->GetNodeContent();
|
|
str.Trim( false );
|
|
mc->m_rotation = StrToInt1Units( str );
|
|
}
|
|
|
|
str = FindNodeGetContent( lNode, wxT( "isFlipped" ) );
|
|
|
|
if( str == wxT( "True" ) )
|
|
mc->m_mirror = 1;
|
|
|
|
tNode = aNode;
|
|
|
|
while( tNode->GetName() != wxT( "www.lura.sk" ) )
|
|
tNode = tNode->GetParent();
|
|
|
|
tNode = FindNode( tNode, wxT( "netlist" ) );
|
|
|
|
if( tNode )
|
|
{
|
|
tNode = FindNode( tNode, wxT( "compInst" ) );
|
|
|
|
while( tNode )
|
|
{
|
|
tNode->GetAttribute( wxT( "Name" ), &propValue );
|
|
|
|
if( propValue == mc->m_name.text )
|
|
{
|
|
if( FindNode( tNode, wxT( "compValue" ) ) )
|
|
{
|
|
FindNode( tNode,
|
|
wxT( "compValue" ) )->GetAttribute( wxT( "Name" ),
|
|
&mc->m_value.text );
|
|
mc->m_value.text.Trim( false );
|
|
mc->m_value.text.Trim( true );
|
|
}
|
|
|
|
if( FindNode( tNode, wxT( "compRef" ) ) )
|
|
{
|
|
FindNode( tNode,
|
|
wxT( "compRef" ) )->GetAttribute( wxT( "Name" ),
|
|
&mc->m_compRef );
|
|
mc->m_compRef.Trim( false );
|
|
mc->m_compRef.Trim( true );
|
|
}
|
|
|
|
tNode = NULL;
|
|
}
|
|
else
|
|
tNode = tNode->GetNext();
|
|
}
|
|
}
|
|
|
|
// map pins
|
|
tNode = FindNode( (XNODE *)aXmlDoc->GetRoot(), wxT( "library" ) );
|
|
tNode = FindCompDefName( tNode, mc->m_compRef );
|
|
|
|
if( tNode )
|
|
{
|
|
tNode = FindPinMap( tNode );
|
|
|
|
if( tNode )
|
|
{
|
|
mNode = tNode->GetChildren();
|
|
|
|
while( mNode )
|
|
{
|
|
if( mNode->GetName() == wxT( "padNum" ) )
|
|
{
|
|
str = mNode->GetNodeContent();
|
|
mNode = mNode->GetNext();
|
|
|
|
if( !mNode )
|
|
break;
|
|
|
|
mNode->GetAttribute( wxT( "Name" ), &propValue );
|
|
mc->SetPadName( str, propValue );
|
|
mNode = mNode->GetNext();
|
|
}
|
|
else
|
|
{
|
|
mNode = mNode->GetNext();
|
|
|
|
if( !mNode )
|
|
break;
|
|
|
|
mNode = mNode->GetNext();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
m_pcbComponents.Add( mc );
|
|
}
|
|
}
|
|
else if( lNode->GetName() == wxT( "pad" ) )
|
|
{
|
|
pad = new PCB_PAD( this, m_board );
|
|
pad->Parse( lNode, m_defaultMeasurementUnit, aActualConversion );
|
|
m_pcbComponents.Add( pad );
|
|
}
|
|
else if( lNode->GetName() == wxT( "via" ) )
|
|
{
|
|
via = new PCB_VIA( this, m_board );
|
|
via->Parse( lNode, m_defaultMeasurementUnit, aActualConversion );
|
|
m_pcbComponents.Add( via );
|
|
}
|
|
else if( lNode->GetName() == wxT( "polyKeepOut" ) )
|
|
{
|
|
keepOut = new PCB_KEEPOUT( m_callbacks, m_board, 0 );
|
|
|
|
if( keepOut->Parse( lNode, m_defaultMeasurementUnit, aActualConversion ) )
|
|
m_pcbComponents.Add( keepOut );
|
|
else
|
|
delete keepOut;
|
|
}
|
|
|
|
lNode = lNode->GetNext();
|
|
}
|
|
}
|
|
|
|
|
|
void PCB::ConnectPinToNet( wxString aCompRef, wxString aPinRef, wxString aNetName )
|
|
{
|
|
PCB_MODULE* module;
|
|
PCB_PAD* cp;
|
|
int i, j;
|
|
|
|
for( i = 0; i < (int) m_pcbComponents.GetCount(); i++ )
|
|
{
|
|
module = (PCB_MODULE*) m_pcbComponents[i];
|
|
|
|
if( module->m_objType == wxT( 'M' ) && module->m_name.text == aCompRef )
|
|
{
|
|
for( j = 0; j < (int) module->m_moduleObjects.GetCount(); j++ )
|
|
{
|
|
if( module->m_moduleObjects[j]->m_objType == wxT( 'P' ) )
|
|
{
|
|
cp = (PCB_PAD*) module->m_moduleObjects[j];
|
|
|
|
if( cp->m_name.text == aPinRef )
|
|
cp->m_net = aNetName;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int PCB::FindLayer( wxString aLayerName )
|
|
{
|
|
int i;
|
|
|
|
for ( i = 0; i < (int) m_layersStackup.GetCount(); i++ )
|
|
{
|
|
if( m_layersStackup[i] == aLayerName )
|
|
return i;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/* KiCad layers
|
|
* 0 Copper layer
|
|
* 1 to 14 Inner layers
|
|
* 15 Component layer
|
|
* 16 Copper side adhesive layer Technical layers
|
|
* 17 Component side adhesive layer
|
|
* 18 Copper side Solder paste layer
|
|
* 19 Component Solder paste layer
|
|
* 20 Copper side Silk screen layer
|
|
* 21 Component Silk screen layer
|
|
* 22 Copper side Solder mask layer
|
|
* 23 Component Solder mask layer
|
|
* 24 Draw layer (Used for general drawings)
|
|
* 25 Comment layer (Other layer used for general drawings)
|
|
* 26 ECO1 layer (Other layer used for general drawings) // BUG
|
|
* 26 ECO2 layer (Other layer used for general drawings) // BUG 27
|
|
* 27 Edge layer. Items on Edge layer are seen on all layers // BUG 28
|
|
*/
|
|
void PCB::MapLayer( XNODE* aNode )
|
|
{
|
|
wxString lName, layerType;
|
|
int KiCadLayer;
|
|
long num = 0;
|
|
|
|
aNode->GetAttribute( wxT( "Name" ), &lName );
|
|
lName = lName.MakeUpper();
|
|
|
|
if( lName == wxT( "TOP ASSY" ) )
|
|
KiCadLayer = COMMENT_N;
|
|
else if( lName == wxT( "TOP SILK" ) )
|
|
KiCadLayer = SILKSCREEN_N_FRONT;
|
|
else if( lName == wxT( "TOP PASTE" ) )
|
|
KiCadLayer = SOLDERPASTE_N_FRONT;
|
|
else if( lName == wxT( "TOP MASK" ) )
|
|
KiCadLayer = SOLDERMASK_N_FRONT;
|
|
else if( lName == wxT( "TOP" ) )
|
|
KiCadLayer = LAST_COPPER_LAYER;
|
|
else if( lName == wxT( "BOTTOM" ) )
|
|
KiCadLayer = FIRST_COPPER_LAYER;
|
|
else if( lName == wxT( "BOT MASK" ) )
|
|
KiCadLayer = SOLDERMASK_N_BACK;
|
|
else if( lName == wxT( "BOT PASTE" ) )
|
|
KiCadLayer = SOLDERPASTE_N_BACK;
|
|
else if( lName == wxT( "BOT SILK" ) )
|
|
KiCadLayer = SILKSCREEN_N_BACK;
|
|
else if( lName == wxT( "BOT ASSY" ) )
|
|
KiCadLayer = DRAW_N;
|
|
else if( lName == wxT( "BOARD" ) )
|
|
KiCadLayer = EDGE_N;
|
|
else
|
|
{
|
|
KiCadLayer = FindLayer( lName );
|
|
|
|
if( KiCadLayer == -1 )
|
|
KiCadLayer = DRAW_N; // default
|
|
else
|
|
KiCadLayer = FIRST_COPPER_LAYER + m_layersStackup.GetCount() - 1 - KiCadLayer;
|
|
}
|
|
|
|
if( FindNode( aNode, wxT( "layerNum" ) ) )
|
|
FindNode( aNode, wxT( "layerNum" ) )->GetNodeContent().ToLong( &num );
|
|
|
|
if( num < 0 || num >= MAX_PCAD_LAYER_QTY )
|
|
THROW_IO_ERROR( wxString::Format( wxT( "layerNum = %ld is out of range" ), num ) );
|
|
|
|
m_layersMap[(int) num].KiCadLayer = KiCadLayer;
|
|
|
|
if( FindNode( aNode, wxT( "layerType" ) ) )
|
|
{
|
|
layerType = FindNode( aNode, wxT( "layerType" ) )->GetNodeContent().Trim( false );
|
|
|
|
if( layerType == wxT( "NonSignal" ) )
|
|
m_layersMap[(int) num].layerType = LAYER_TYPE_NONSIGNAL;
|
|
if( layerType == wxT( "Signal" ) )
|
|
m_layersMap[(int) num].layerType = LAYER_TYPE_SIGNAL;
|
|
if( layerType == wxT( "Plane" ) )
|
|
m_layersMap[(int) num].layerType = LAYER_TYPE_PLANE;
|
|
}
|
|
|
|
if( FindNode( aNode, wxT( "netNameRef" ) ) )
|
|
{
|
|
FindNode( aNode, wxT( "netNameRef" ) )->GetAttribute( wxT( "Name" ),
|
|
&m_layersMap[(int) num].netNameRef );
|
|
}
|
|
}
|
|
|
|
int PCB::FindOutlinePoint( VERTICES_ARRAY* aOutline, wxRealPoint aPoint )
|
|
{
|
|
int i;
|
|
|
|
for( i = 0; i < (int) aOutline->GetCount(); i++ )
|
|
if( *((*aOutline)[i]) == aPoint )
|
|
return i;
|
|
|
|
return -1;
|
|
}
|
|
|
|
/*int cmpFunc( wxRealPoint **first, wxRealPoint **second )
|
|
{
|
|
return sqrt( pow( (double) aPointA.x - (double) aPointB.x, 2 ) +
|
|
pow( (double) aPointA.y - (double) aPointB.y, 2 ) );
|
|
|
|
return 0;
|
|
}*/
|
|
double PCB::GetDistance( wxRealPoint* aPoint1, wxRealPoint* aPoint2 )
|
|
{
|
|
return sqrt( ( aPoint1->x - aPoint2->x ) *
|
|
( aPoint1->x - aPoint2->x ) +
|
|
( aPoint1->y - aPoint2->y ) *
|
|
( aPoint1->y - aPoint2->y ) );
|
|
}
|
|
|
|
void PCB::GetBoardOutline( wxXmlDocument* aXmlDoc, wxString aActualConversion )
|
|
{
|
|
XNODE* iNode, *lNode, *pNode;
|
|
long PCadLayer = 0;
|
|
int x, y, i, j, targetInd;
|
|
wxRealPoint* xchgPoint;
|
|
double minDistance, distance;
|
|
|
|
iNode = FindNode( (XNODE *)aXmlDoc->GetRoot(), wxT( "pcbDesign" ) );
|
|
|
|
if( iNode )
|
|
{
|
|
// COMPONENTS AND OBJECTS
|
|
iNode = iNode->GetChildren();
|
|
|
|
while( iNode )
|
|
{
|
|
// objects
|
|
if( iNode->GetName() == wxT( "layerContents" ) )
|
|
{
|
|
if( FindNode( iNode, wxT( "layerNumRef" ) ) )
|
|
FindNode( iNode, wxT( "layerNumRef" ) )->GetNodeContent().ToLong( &PCadLayer );
|
|
|
|
if( GetKiCadLayer( PCadLayer ) == EDGE_N )
|
|
{
|
|
lNode = iNode->GetChildren();
|
|
while( lNode )
|
|
{
|
|
if( lNode->GetName() == wxT( "line" ) )
|
|
{
|
|
pNode = FindNode( lNode, wxT( "pt" ) );
|
|
|
|
if( pNode )
|
|
{
|
|
SetPosition( pNode->GetNodeContent(), m_defaultMeasurementUnit,
|
|
&x, &y, aActualConversion );
|
|
|
|
if( FindOutlinePoint( &m_boardOutline, wxRealPoint( x, y) ) == -1 )
|
|
m_boardOutline.Add( new wxRealPoint( x, y ) );
|
|
}
|
|
|
|
|
|
pNode = pNode->GetNext();
|
|
|
|
if( pNode )
|
|
{
|
|
SetPosition( pNode->GetNodeContent(), m_defaultMeasurementUnit,
|
|
&x, &y, aActualConversion );
|
|
|
|
if( FindOutlinePoint( &m_boardOutline, wxRealPoint( x, y) ) == -1 )
|
|
m_boardOutline.Add( new wxRealPoint( x, y ) );
|
|
}
|
|
}
|
|
|
|
lNode = lNode->GetNext();
|
|
}
|
|
|
|
//m_boardOutline.Sort( cmpFunc );
|
|
// sort vertices according to the distances between them
|
|
if( m_boardOutline.GetCount() > 3 )
|
|
{
|
|
for( i = 0; i < (int) m_boardOutline.GetCount() - 1; i++ )
|
|
{
|
|
minDistance = GetDistance( m_boardOutline[i], m_boardOutline[i + 1] );
|
|
targetInd = i + 1;
|
|
|
|
for( j = i + 2; j < (int) m_boardOutline.GetCount(); j++ )
|
|
{
|
|
distance = GetDistance( m_boardOutline[i], m_boardOutline[j] );
|
|
if( distance < minDistance )
|
|
{
|
|
minDistance = distance;
|
|
targetInd = j;
|
|
}
|
|
}
|
|
|
|
xchgPoint = m_boardOutline[i + 1];
|
|
m_boardOutline[i + 1] = m_boardOutline[targetInd];
|
|
m_boardOutline[targetInd] = xchgPoint;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
iNode = iNode->GetNext();
|
|
}
|
|
}
|
|
}
|
|
|
|
void PCB::Parse( wxStatusBar* aStatusBar, wxXmlDocument* aXmlDoc, wxString aActualConversion )
|
|
{
|
|
XNODE* aNode;//, *aaNode;
|
|
PCB_NET* net;
|
|
PCB_COMPONENT* comp;
|
|
PCB_MODULE* module;
|
|
wxString compRef, pinRef, layerName, layerType;
|
|
int i, j, netCode;
|
|
|
|
// Defaut measurement units
|
|
aNode = FindNode( (XNODE *)aXmlDoc->GetRoot(), wxT( "asciiHeader" ) );
|
|
|
|
if( aNode )
|
|
{
|
|
aNode = FindNode( aNode, wxT( "fileUnits" ) );
|
|
|
|
if( aNode )
|
|
{
|
|
m_defaultMeasurementUnit = aNode->GetNodeContent();
|
|
m_defaultMeasurementUnit.Trim( true );
|
|
m_defaultMeasurementUnit.Trim( false );
|
|
}
|
|
}
|
|
|
|
// Determine layers stackup
|
|
aNode = FindNode( (XNODE *)aXmlDoc->GetRoot(), wxT( "pcbDesign" ) );
|
|
|
|
/*if( aNode )
|
|
{
|
|
aNode = FindNode( aNode, wxT( "layersStackup" ) );
|
|
|
|
if( aNode )
|
|
{
|
|
aNode = FindNode( aNode, wxT( "layerStackupData" ) );
|
|
|
|
while( aNode )
|
|
{
|
|
if( aNode->GetName() == wxT( "layerStackupData" ) )
|
|
{
|
|
aaNode = FindNode( aNode, wxT( "layerStackupName" ) );
|
|
|
|
if( aaNode ) {
|
|
aaNode->GetAttribute( wxT( "Name" ), &layerName );
|
|
layerName = layerName.MakeUpper();
|
|
m_layersStackup.Add( layerName );
|
|
}
|
|
}
|
|
|
|
aNode = aNode->GetNext();
|
|
}
|
|
}
|
|
}*/
|
|
|
|
if( aNode )
|
|
{
|
|
aNode = FindNode( aNode, wxT( "layerDef" ) );
|
|
|
|
while( aNode )
|
|
{
|
|
if( aNode->GetName() == wxT( "layerDef" ) )
|
|
{
|
|
if( FindNode( aNode, wxT( "layerType" ) ) )
|
|
{
|
|
layerType = FindNode( aNode,
|
|
wxT( "layerType" ) )->GetNodeContent().Trim( false );
|
|
|
|
if( layerType == wxT( "Signal" ) || layerType == wxT( "Plane" ) )
|
|
{
|
|
aNode->GetAttribute( wxT( "Name" ), &layerName );
|
|
layerName = layerName.MakeUpper();
|
|
m_layersStackup.Add( layerName );
|
|
}
|
|
}
|
|
}
|
|
|
|
aNode = aNode->GetNext();
|
|
}
|
|
}
|
|
|
|
// Layers mapping
|
|
aNode = FindNode( (XNODE *)aXmlDoc->GetRoot(), wxT( "pcbDesign" ) );
|
|
|
|
if( aNode )
|
|
{
|
|
aNode = FindNode( aNode, wxT( "layerDef" ) );
|
|
|
|
while( aNode )
|
|
{
|
|
if( aNode->GetName() == wxT( "layerDef" ) )
|
|
MapLayer( aNode );
|
|
|
|
aNode = aNode->GetNext();
|
|
}
|
|
}
|
|
|
|
GetBoardOutline( aXmlDoc, aActualConversion );
|
|
|
|
// NETLIST
|
|
// aStatusBar->SetStatusText( wxT( "Loading NETLIST " ) );
|
|
|
|
aNode = FindNode( (XNODE *)aXmlDoc->GetRoot(), wxT( "netlist" ) );
|
|
|
|
if( aNode )
|
|
{
|
|
aNode = FindNode( aNode, wxT( "net" ) );
|
|
|
|
netCode = 1;
|
|
|
|
while( aNode )
|
|
{
|
|
net = new PCB_NET( netCode++ );
|
|
net->Parse( aNode );
|
|
m_pcbNetlist.Add( net );
|
|
|
|
aNode = aNode->GetNext();
|
|
}
|
|
}
|
|
|
|
// BOARD FILE
|
|
// aStatusBar->SetStatusText( wxT( "Loading BOARD DEFINITION " ) );
|
|
|
|
aNode = FindNode( (XNODE *)aXmlDoc->GetRoot(), wxT( "pcbDesign" ) );
|
|
|
|
if( aNode )
|
|
{
|
|
// COMPONENTS AND OBJECTS
|
|
aNode = aNode->GetChildren();
|
|
|
|
while( aNode )
|
|
{
|
|
// Components/modules
|
|
if( aNode->GetName() == wxT( "multiLayer" ) )
|
|
DoPCBComponents( aNode, aXmlDoc, aActualConversion, aStatusBar );
|
|
|
|
// objects
|
|
if( aNode->GetName() == wxT( "layerContents" ) )
|
|
DoLayerContentsObjects( aNode, NULL, &m_pcbComponents, aStatusBar,
|
|
m_defaultMeasurementUnit, aActualConversion );
|
|
|
|
aNode = aNode->GetNext();
|
|
}
|
|
|
|
// POSTPROCESS -- SET NETLIST REFERENCES
|
|
// aStatusBar->SetStatusText( wxT( "Processing NETLIST " ) );
|
|
|
|
for( i = 0; i < (int) m_pcbNetlist.GetCount(); i++ )
|
|
{
|
|
net = m_pcbNetlist[i];
|
|
|
|
for( j = 0; j < (int) net->m_netNodes.GetCount(); j++ )
|
|
{
|
|
compRef = net->m_netNodes[j]->m_compRef;
|
|
compRef.Trim( false );
|
|
compRef.Trim( true );
|
|
pinRef = net->m_netNodes[j]->m_pinRef;
|
|
pinRef.Trim( false );
|
|
pinRef.Trim( true );
|
|
ConnectPinToNet( compRef, pinRef, net->m_name );
|
|
}
|
|
}
|
|
|
|
// POSTPROCESS -- FLIP COMPONENTS
|
|
for( i = 0; i < (int) m_pcbComponents.GetCount(); i++ )
|
|
{
|
|
if( m_pcbComponents[i]->m_objType == wxT( 'M' ) )
|
|
( (PCB_MODULE*) m_pcbComponents[i] )->Flip();
|
|
}
|
|
|
|
// POSTPROCESS -- SET/OPTIMIZE NEW PCB POSITION
|
|
// aStatusBar->SetStatusText( wxT( "Optimizing BOARD POSITION " ) );
|
|
|
|
m_sizeX = 10000000;
|
|
m_sizeY = 0;
|
|
|
|
for( i = 0; i < (int) m_pcbComponents.GetCount(); i++ )
|
|
{
|
|
comp = m_pcbComponents[i];
|
|
|
|
if( comp->m_positionY < m_sizeY )
|
|
m_sizeY = comp->m_positionY; // max Y
|
|
|
|
if( comp->m_positionX < m_sizeX && comp->m_positionX > 0 )
|
|
m_sizeX = comp->m_positionX; // Min X
|
|
}
|
|
|
|
m_sizeY -= 10000;
|
|
m_sizeX -= 10000;
|
|
// aStatusBar->SetStatusText( wxT( " POSITIONING POSTPROCESS " ) );
|
|
|
|
for( i = 0; i < (int) m_pcbComponents.GetCount(); i++ )
|
|
m_pcbComponents[i]->SetPosOffset( -m_sizeX, -m_sizeY );
|
|
|
|
m_sizeX = 0;
|
|
m_sizeY = 0;
|
|
|
|
for( i = 0; i < (int) m_pcbComponents.GetCount(); i++ )
|
|
{
|
|
comp = m_pcbComponents[i];
|
|
|
|
if( comp->m_positionY < m_sizeY )
|
|
m_sizeY = comp->m_positionY; // max Y
|
|
|
|
if( comp->m_positionX > m_sizeX )
|
|
m_sizeX = comp->m_positionX; // Min X
|
|
}
|
|
|
|
// SHEET SIZE CALCULATION
|
|
m_sizeY = -m_sizeY; // it is in absolute units
|
|
m_sizeX += 10000;
|
|
m_sizeY += 10000;
|
|
|
|
// A4 is minimum $Descr A4 11700 8267
|
|
if( m_sizeX < 11700 )
|
|
m_sizeX = 11700;
|
|
|
|
if( m_sizeY < 8267 )
|
|
m_sizeY = 8267;
|
|
}
|
|
else
|
|
{
|
|
// LIBRARY FILE
|
|
// aStatusBar->SetStatusText( wxT( "Processing LIBRARY FILE " ) );
|
|
|
|
aNode = FindNode( (XNODE *)aXmlDoc->GetRoot(), wxT( "library" ) );
|
|
|
|
if( aNode )
|
|
{
|
|
aNode = FindNode( aNode, wxT( "compDef" ) );
|
|
|
|
while( aNode )
|
|
{
|
|
// aStatusBar->SetStatusText( wxT( "Processing COMPONENTS " ) );
|
|
|
|
if( aNode->GetName() == wxT( "compDef" ) )
|
|
{
|
|
module = new PCB_MODULE( this, m_board );
|
|
module->Parse( aNode, aStatusBar, m_defaultMeasurementUnit,
|
|
aActualConversion );
|
|
m_pcbComponents.Add( module );
|
|
}
|
|
|
|
aNode = aNode->GetNext();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void PCB::AddToBoard()
|
|
{
|
|
int i;
|
|
PCB_NET* net;
|
|
|
|
m_board->SetCopperLayerCount( m_layersStackup.GetCount() );
|
|
|
|
for( i = 0; i < (int) m_pcbComponents.GetCount(); i++ )
|
|
{
|
|
m_pcbComponents[i]->AddToBoard();
|
|
}
|
|
|
|
for( i = 0; i < (int) m_pcbNetlist.GetCount(); i++ )
|
|
{
|
|
net = m_pcbNetlist[i];
|
|
|
|
m_board->AppendNet( new NETINFO_ITEM( m_board, net->m_name, net->m_netCode ) );
|
|
}
|
|
}
|
|
|
|
} // namespace PCAD2KICAD
|