kicad/pcbnew/plugins/pcad/pcb.cpp

965 lines
29 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-2021 KiCad Developers, see AUTHORS.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
*/
#include <pcad/pcb.h>
#include <pcad/pcb_keepout.h>
#include <pcad/pcb_footprint.h>
#include <pcad/pcb_net.h>
#include <pcad/pcb_pad.h>
#include <pcad/pcb_text.h>
#include <pcad/pcb_via.h>
#include <pcad/s_expr_loader.h>
#include <board.h>
#include <common.h>
#include <xnode.h>
#include <wx/string.h>
namespace PCAD2KICAD {
PCB_LAYER_ID PCB::GetKiCadLayer( int aPCadLayer ) const
{
auto it = m_LayersMap.find( aPCadLayer );
if( it == m_LayersMap.end() )
THROW_IO_ERROR( wxString::Format( _( "Unknown PCad layer %u" ), unsigned( aPCadLayer ) ) );
return it->second.KiCadLayer;
}
LAYER_TYPE_T PCB::GetLayerType( int aPCadLayer ) const
{
auto it = m_LayersMap.find( aPCadLayer );
if( it == m_LayersMap.end() )
THROW_IO_ERROR( wxString::Format( _( "Unknown PCad layer %u" ), unsigned( aPCadLayer ) ) );
return it->second.layerType;
}
wxString PCB::GetLayerNetNameRef( int aPCadLayer ) const
{
auto it = m_LayersMap.find( aPCadLayer );
if( it == m_LayersMap.end() )
THROW_IO_ERROR( wxString::Format( _( "Unknown PCad layer %u" ), unsigned( aPCadLayer ) ) );
return it->second.netNameRef;
}
PCB::PCB( BOARD* aBoard ) :
PCB_FOOTPRINT( this, aBoard )
{
m_DefaultMeasurementUnit = wxT( "mil" );
for( size_t i = 0; i < 8; ++i )
{
TLAYER layer;
layer.KiCadLayer = F_Mask; // default
layer.layerType = LAYER_TYPE_NONSIGNAL; // default
layer.netNameRef = wxT( "" ); // default
m_LayersMap.insert( std::make_pair( i, layer ) );
}
m_SizeX = 0;
m_SizeY = 0;
m_LayersMap[1].KiCadLayer = F_Cu;
m_LayersMap[1].layerType = LAYER_TYPE_SIGNAL;
m_LayersMap[2].KiCadLayer = B_Cu;
m_LayersMap[2].layerType = LAYER_TYPE_SIGNAL;
m_LayersMap[3].KiCadLayer = Eco2_User;
m_LayersMap[6].KiCadLayer = F_SilkS;
m_LayersMap[7].KiCadLayer = B_SilkS;
}
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::GetNetCode( const wxString& aNetName ) const
{
const 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, const wxString& aName ) const
{
XNODE* result = nullptr, * lNode;
wxString propValue;
lNode = FindNode( aNode, wxT( "compDef" ) );
while( lNode )
{
if( lNode->GetName().IsSameAs( wxT( "compDef" ), false ) )
{
lNode->GetAttribute( wxT( "Name" ), &propValue );
if( propValue == aName )
{
result = lNode;
lNode = nullptr;
}
}
if( lNode )
lNode = lNode->GetNext();
}
return result;
}
void PCB::SetTextProperty( XNODE* aNode, TTEXTVALUE* aTextValue, const wxString& aPatGraphRefName,
const wxString& aXmlName, const wxString& aActualConversion )
{
XNODE* tNode, * t1Node;
wxString n, nnew, 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().IsSameAs( wxT( "patternGraphicsRef" ), false ) )
{
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 );
nnew = n; // new file version
n = n + wxT( ' ' ) + str; // old file version
tNode = nullptr;
}
}
}
if( tNode )
tNode = tNode->GetNext();
}
}
// old version and compatible for 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 || propValue == nnew )
break;
tNode = tNode->GetNext();
}
if( tNode )
SetTextParameters( tNode, aTextValue, m_DefaultMeasurementUnit, aActualConversion );
}
void PCB::DoPCBComponents( XNODE* aNode, wxXmlDocument* aXmlDoc, const wxString& aActualConversion,
wxStatusBar* aStatusBar )
{
XNODE* lNode, * tNode, * mNode;
PCB_FOOTPRINT* fp;
PCB_PAD* pad;
PCB_VIA* via;
PCB_KEEPOUT* keepOut;
wxString cn, str, propValue;
lNode = aNode->GetChildren();
while( lNode )
{
fp = nullptr;
if( lNode->GetName().IsSameAs( wxT( "pattern" ), false ) )
{
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 )
{
fp = new PCB_FOOTPRINT( this, m_board );
mNode = FindNode( lNode, wxT( "patternGraphicsNameRef" ) );
if( mNode )
mNode->GetAttribute( wxT( "Name" ), &fp->m_patGraphRefName );
fp->Parse( tNode, aStatusBar, m_DefaultMeasurementUnit, aActualConversion );
}
}
if( fp )
{
fp->m_compRef = cn; // default - in new version of file it is updated later....
tNode = FindNode( lNode, wxT( "refDesRef" ) );
if( tNode )
{
tNode->GetAttribute( wxT( "Name" ), &fp->m_name.text );
SetTextProperty( lNode, &fp->m_name, fp->m_patGraphRefName, wxT( "RefDes" ),
aActualConversion );
SetTextProperty( lNode, &fp->m_Value, fp->m_patGraphRefName, wxT( "Value" ),
aActualConversion );
}
tNode = FindNode( lNode, wxT( "pt" ) );
if( tNode )
{
SetPosition( tNode->GetNodeContent(), m_DefaultMeasurementUnit,
&fp->m_positionX, &fp->m_positionY, aActualConversion );
}
tNode = FindNode( lNode, wxT( "rotation" ) );
if( tNode )
{
str = tNode->GetNodeContent();
str.Trim( false );
fp->m_rotation = EDA_ANGLE( StrToInt1Units( str ), TENTHS_OF_A_DEGREE_T );
}
str = FindNodeGetContent( lNode, wxT( "isFlipped" ) );
if( str.IsSameAs( wxT( "True" ), false ) )
fp->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 == fp->m_name.text )
{
if( FindNode( tNode, wxT( "compValue" ) ) )
{
FindNode( tNode,
wxT( "compValue" ) )->GetAttribute( wxT( "Name" ),
&fp->m_Value.text );
fp->m_Value.text.Trim( false );
fp->m_Value.text.Trim( true );
}
if( FindNode( tNode, wxT( "compRef" ) ) )
{
FindNode( tNode,
wxT( "compRef" ) )->GetAttribute( wxT( "Name" ),
&fp->m_compRef );
fp->m_compRef.Trim( false );
fp->m_compRef.Trim( true );
}
tNode = nullptr;
}
else
{
tNode = tNode->GetNext();
}
}
}
// map pins
tNode = FindNode( (XNODE *)aXmlDoc->GetRoot(), wxT( "library" ) );
tNode = FindCompDefName( tNode, fp->m_compRef );
if( tNode )
{
tNode = FindPinMap( tNode );
if( tNode )
{
mNode = tNode->GetChildren();
while( mNode )
{
if( mNode->GetName().IsSameAs( wxT( "padNum" ), false ) )
{
str = mNode->GetNodeContent();
mNode = mNode->GetNext();
if( !mNode )
break;
mNode->GetAttribute( wxT( "Name" ), &propValue );
fp->SetName( str, propValue );
mNode = mNode->GetNext();
}
else
{
mNode = mNode->GetNext();
if( !mNode )
break;
mNode = mNode->GetNext();
}
}
}
}
m_PcbComponents.Add( fp );
}
}
else if( lNode->GetName().IsSameAs( wxT( "pad" ), false ) )
{
pad = new PCB_PAD( this, m_board );
pad->Parse( lNode, m_DefaultMeasurementUnit, aActualConversion );
m_PcbComponents.Add( pad );
}
else if( lNode->GetName().IsSameAs( wxT( "via" ), false ) )
{
via = new PCB_VIA( this, m_board );
via->Parse( lNode, m_DefaultMeasurementUnit, aActualConversion );
m_PcbComponents.Add( via );
}
else if( lNode->GetName().IsSameAs( wxT( "polyKeepOut" ), false ) )
{
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( const wxString& aCompRef, const wxString& aPinRef,
const wxString& aNetName )
{
PCB_FOOTPRINT* footprint;
PCB_PAD* cp;
int i, j;
for( i = 0; i < (int) m_PcbComponents.GetCount(); i++ )
{
footprint = (PCB_FOOTPRINT*) m_PcbComponents[i];
if( footprint->m_objType == wxT( 'M' ) && footprint->m_name.text == aCompRef )
{
for( j = 0; j < (int) footprint->m_FootprintItems.GetCount(); j++ )
{
if( footprint->m_FootprintItems[j]->m_objType == wxT( 'P' ) )
{
cp = (PCB_PAD*) footprint->m_FootprintItems[j];
if( cp->m_name.text == aPinRef )
cp->m_net = aNetName;
}
}
}
}
}
int PCB::FindLayer( const wxString& aLayerName ) const
{
for( int i = 0; i < (int) m_layersStackup.size(); ++i )
{
if( m_layersStackup[i].first == aLayerName )
return i;
}
return -1;
}
void PCB::MapLayer( XNODE* aNode )
{
wxString lName, layerType;
PCB_LAYER_ID KiCadLayer;
long num = 0;
aNode->GetAttribute( wxT( "Name" ), &lName );
lName = lName.MakeUpper();
if( lName == wxT( "TOP ASSY" ) )
{
KiCadLayer = F_Fab;
}
else if( lName == wxT( "TOP SILK" ) )
{
KiCadLayer = F_SilkS;
}
else if( lName == wxT( "TOP PASTE" ) )
{
KiCadLayer = F_Paste;
}
else if( lName == wxT( "TOP MASK" ) )
{
KiCadLayer = F_Mask;
}
else if( lName == wxT( "TOP" ) )
{
KiCadLayer = F_Cu;
}
else if( lName == wxT( "BOTTOM" ) )
{
KiCadLayer = B_Cu;
}
else if( lName == wxT( "BOT MASK" ) )
{
KiCadLayer = B_Mask;
}
else if( lName == wxT( "BOT PASTE" ) )
{
KiCadLayer = B_Paste;
}
else if( lName == wxT( "BOT SILK" ) )
{
KiCadLayer = B_SilkS;
}
else if( lName == wxT( "BOT ASSY" ) )
{
KiCadLayer = B_Fab;
}
else if( lName == wxT( "BOARD" ) )
{
KiCadLayer = Edge_Cuts;
}
else
{
int layernum = FindLayer( lName );
if( layernum == -1 )
KiCadLayer = Dwgs_User; // default
else
KiCadLayer = ToLAYER_ID( layernum );
}
if( FindNode( aNode, wxT( "layerNum" ) ) )
FindNode( aNode, wxT( "layerNum" ) )->GetNodeContent().ToLong( &num );
if( num < 0 )
THROW_IO_ERROR( wxString::Format( wxT( "layerNum = %ld is out of range" ), num ) );
TLAYER newlayer;
newlayer.KiCadLayer = KiCadLayer;
if( FindNode( aNode, wxT( "layerType" ) ) )
{
layerType = FindNode( aNode, wxT( "layerType" ) )->GetNodeContent().Trim( false );
if( layerType.IsSameAs( wxT( "NonSignal" ), false ) )
newlayer.layerType = LAYER_TYPE_NONSIGNAL;
if( layerType.IsSameAs( wxT( "Signal" ), false ) )
newlayer.layerType = LAYER_TYPE_SIGNAL;
if( layerType.IsSameAs( wxT( "Plane" ), false ) )
newlayer.layerType = LAYER_TYPE_PLANE;
}
m_LayersMap.insert( std::make_pair( num, newlayer ) );
if( FindNode( aNode, wxT( "netNameRef" ) ) )
{
FindNode( aNode, wxT( "netNameRef" ) )->GetAttribute( wxT( "Name" ),
&m_LayersMap[(int) num].netNameRef );
}
}
int PCB::FindOutlinePoint( const VERTICES_ARRAY* aOutline, wxRealPoint aPoint ) const
{
int i;
for( i = 0; i < (int) aOutline->GetCount(); i++ )
{
if( *((*aOutline)[i]) == aPoint )
return i;
}
return -1;
}
double PCB::GetDistance( const wxRealPoint* aPoint1, const wxRealPoint* aPoint2 ) const
{
return sqrt( ( aPoint1->x - aPoint2->x ) * ( aPoint1->x - aPoint2->x ) +
( aPoint1->y - aPoint2->y ) * ( aPoint1->y - aPoint2->y ) );
}
void PCB::GetBoardOutline( wxXmlDocument* aXmlDoc, const 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().IsSameAs( wxT( "layerContents" ), false ) )
{
if( FindNode( iNode, wxT( "layerNumRef" ) ) )
FindNode( iNode, wxT( "layerNumRef" ) )->GetNodeContent().ToLong( &PCadLayer );
if( GetKiCadLayer( PCadLayer ) == Edge_Cuts )
{
lNode = iNode->GetChildren();
while( lNode )
{
if( lNode->GetName().IsSameAs( wxT( "line" ), false ) )
{
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 ) );
}
if( pNode )
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::ParseBoard( wxStatusBar* aStatusBar, wxXmlDocument* aXmlDoc,
const wxString& aActualConversion )
{
XNODE* aNode;//, *aaNode;
PCB_NET* net;
PCB_COMPONENT* comp;
PCB_FOOTPRINT* footprint;
wxString compRef, pinRef, layerName, layerType;
int i, j, netCode;
// Default measurement units
aNode = FindNode( (XNODE *)aXmlDoc->GetRoot(), wxT( "asciiHeader" ) );
if( aNode )
{
aNode = FindNode( aNode, wxT( "fileUnits" ) );
if( aNode )
{
m_DefaultMeasurementUnit = aNode->GetNodeContent().Lower();
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().IsSameAs( wxT( "layerDef" ), false ) )
{
if( FindNode( aNode, wxT( "layerType" ) ) )
{
long num = -1;
if( FindNode( aNode, wxT( "layerNum" ) ) )
FindNode( aNode, wxT( "layerNum" ) )->GetNodeContent().ToLong( &num );
layerType = FindNode( aNode, wxT( "layerType" ) )->GetNodeContent().Trim(
false );
if( num > 0 && ( layerType.IsSameAs( wxT( "Signal" ), false )
|| layerType.IsSameAs( wxT( "Plane" ), false ) ) )
{
aNode->GetAttribute( wxT( "Name" ), &layerName );
layerName = layerName.MakeUpper();
m_layersStackup.emplace_back( layerName, num );
if( m_layersStackup.size() > 32 )
THROW_IO_ERROR( _( "KiCad only supports 32 signal layers." ) );
}
}
}
aNode = aNode->GetNext();
}
// Ensure that the layers are properly mapped to their order with the bottom
// copper (layer 2 in PCAD) at the end
std::sort( m_layersStackup.begin(), m_layersStackup.end(),
[&]( const std::pair<wxString, long>& a, const std::pair<wxString, long>& b ) {
long lhs = a.second == 2 ? std::numeric_limits<long>::max() : a.second;
long rhs = b.second == 2 ? std::numeric_limits<long>::max() : b.second;
return lhs < rhs;
} );
}
// Layers mapping
aNode = FindNode( (XNODE *)aXmlDoc->GetRoot(), wxT( "pcbDesign" ) );
if( aNode )
{
aNode = FindNode( aNode, wxT( "layerDef" ) );
while( aNode )
{
if( aNode->GetName().IsSameAs( wxT( "layerDef" ), false ) )
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/footprints
if( aNode->GetName().IsSameAs( wxT( "multiLayer" ), false ) )
DoPCBComponents( aNode, aXmlDoc, aActualConversion, aStatusBar );
// objects
if( aNode->GetName().IsSameAs( wxT( "layerContents" ), false ) )
DoLayerContentsObjects( aNode, nullptr, &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_FOOTPRINT*) 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().IsSameAs( wxT( "compDef" ), false ) )
{
footprint = new PCB_FOOTPRINT( this, m_board );
footprint->Parse( aNode, aStatusBar, m_DefaultMeasurementUnit,
aActualConversion );
m_PcbComponents.Add( footprint );
}
aNode = aNode->GetNext();
}
}
}
}
void PCB::AddToBoard()
{
int i;
PCB_NET* net;
m_board->SetCopperLayerCount( m_layersStackup.size() );
for( i = 0; i < (int) m_PcbNetlist.GetCount(); i++ )
{
net = m_PcbNetlist[i];
m_board->Add( new NETINFO_ITEM( m_board, net->m_Name, net->m_NetCode ) );
}
for( i = 0; i < (int) m_PcbComponents.GetCount(); i++ )
{
m_PcbComponents[i]->AddToBoard();
}
}
} // namespace PCAD2KICAD