KiCad PCB EDA Suite
pcb.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2007, 2008 Lubo Racko <[email protected]>
5  * Copyright (C) 2007, 2008, 2012-2013 Alexander Lunev <[email protected]>
6  * Copyright (C) 2012-2021 KiCad Developers, see AUTHORS.txt for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
26 #include <pcad/pcb.h>
27 
28 #include <pcad/pcb_keepout.h>
29 #include <pcad/pcb_footprint.h>
30 #include <pcad/pcb_net.h>
31 #include <pcad/pcb_pad.h>
32 #include <pcad/pcb_text.h>
33 #include <pcad/pcb_via.h>
34 #include <pcad/s_expr_loader.h>
35 
36 #include <board.h>
37 #include <common.h>
38 #include <xnode.h>
39 
40 #include <wx/gdicmn.h>
41 #include <wx/string.h>
42 
43 namespace PCAD2KICAD {
44 
45 
46 PCB_LAYER_ID PCB::GetKiCadLayer( int aPCadLayer ) const
47 {
48  auto it = m_LayersMap.find( aPCadLayer );
49 
50  if( it == m_LayersMap.end() )
51  THROW_IO_ERROR( wxString::Format( _( "Unknown PCad layer %u" ), unsigned( aPCadLayer ) ) );
52 
53  return it->second.KiCadLayer;
54 }
55 
56 
57 LAYER_TYPE_T PCB::GetLayerType( int aPCadLayer ) const
58 {
59  auto it = m_LayersMap.find( aPCadLayer );
60 
61  if( it == m_LayersMap.end() )
62  THROW_IO_ERROR( wxString::Format( _( "Unknown PCad layer %u" ), unsigned( aPCadLayer ) ) );
63 
64  return it->second.layerType;
65 }
66 
67 
68 wxString PCB::GetLayerNetNameRef( int aPCadLayer ) const
69 {
70  auto it = m_LayersMap.find( aPCadLayer );
71 
72  if( it == m_LayersMap.end() )
73  THROW_IO_ERROR( wxString::Format( _( "Unknown PCad layer %u" ), unsigned( aPCadLayer ) ) );
74 
75  return it->second.netNameRef;
76 }
77 
78 
79 PCB::PCB( BOARD* aBoard ) :
80  PCB_FOOTPRINT( this, aBoard )
81 {
82  m_DefaultMeasurementUnit = wxT( "mil" );
83 
84  for( size_t i = 0; i < 8; ++i )
85  {
86  TLAYER layer;
87  layer.KiCadLayer = F_Mask; // default
88  layer.layerType = LAYER_TYPE_NONSIGNAL; // default
89  layer.netNameRef = wxEmptyString; // default
90 
91  m_LayersMap.insert( std::make_pair( i, layer ) );
92  }
93 
94  m_SizeX = 0;
95  m_SizeY = 0;
96 
97  m_LayersMap[1].KiCadLayer = F_Cu;
98  m_LayersMap[1].layerType = LAYER_TYPE_SIGNAL;
99 
100  m_LayersMap[2].KiCadLayer = B_Cu;
101  m_LayersMap[2].layerType = LAYER_TYPE_SIGNAL;
102 
103  m_LayersMap[3].KiCadLayer = Eco2_User;
104  m_LayersMap[6].KiCadLayer = F_SilkS;
105  m_LayersMap[7].KiCadLayer = B_SilkS;
106 }
107 
108 
110 {
111  int i;
112 
113  for( i = 0; i < (int) m_PcbComponents.GetCount(); i++ )
114  {
115  delete m_PcbComponents[i];
116  }
117 
118  for( i = 0; i < (int) m_PcbNetlist.GetCount(); i++ )
119  {
120  delete m_PcbNetlist[i];
121  }
122 }
123 
124 
125 int PCB::GetNetCode( const wxString& aNetName ) const
126 {
127  const PCB_NET* net;
128 
129  for( int i = 0; i < (int) m_PcbNetlist.GetCount(); i++ )
130  {
131  net = m_PcbNetlist[i];
132 
133  if( net->m_Name == aNetName )
134  {
135  return net->m_NetCode;
136  }
137  }
138 
139  return 0;
140 }
141 
142 XNODE* PCB::FindCompDefName( XNODE* aNode, const wxString& aName ) const
143 {
144  XNODE* result = nullptr, * lNode;
145  wxString propValue;
146 
147  lNode = FindNode( aNode, wxT( "compDef" ) );
148 
149  while( lNode )
150  {
151  if( lNode->GetName().IsSameAs( wxT( "compDef" ), false ) )
152  {
153  lNode->GetAttribute( wxT( "Name" ), &propValue );
154 
155  if( propValue == aName )
156  {
157  result = lNode;
158  lNode = nullptr;
159  }
160  }
161 
162  if( lNode )
163  lNode = lNode->GetNext();
164  }
165 
166  return result;
167 }
168 
169 
170 void PCB::SetTextProperty( XNODE* aNode, TTEXTVALUE* aTextValue, const wxString& aPatGraphRefName,
171  const wxString& aXmlName, const wxString& aActualConversion )
172 {
173  XNODE* tNode, * t1Node;
174  wxString n, nnew, pn, propValue, str;
175 
176  // aNode is pattern now
177  tNode = aNode;
178  t1Node = aNode;
179  n = aXmlName;
180 
181  // new file format version
182  if( FindNode( tNode, wxT( "patternGraphicsNameRef" ) ) )
183  {
184  FindNode( tNode,
185  wxT( "patternGraphicsNameRef" ) )->GetAttribute( wxT( "Name" ),
186  &pn );
187  pn.Trim( false );
188  pn.Trim( true );
189  tNode = FindNode( tNode, wxT( "patternGraphicsRef" ) );
190 
191  while( tNode )
192  {
193  if( tNode->GetName().IsSameAs( wxT( "patternGraphicsRef" ), false ) )
194  {
195  if( FindNode( tNode, wxT( "patternGraphicsNameRef" ) ) )
196  {
197  FindNode( tNode,
198  wxT( "patternGraphicsNameRef" ) )->GetAttribute( wxT( "Name" ),
199  &propValue );
200 
201  if( propValue == pn )
202  {
203  t1Node = tNode; // find correct section with same name.
204  str = aTextValue->text;
205  str.Trim( false );
206  str.Trim( true );
207  nnew = n; // new file version
208  n = n + wxT( ' ' ) + str; // old file version
209  tNode = nullptr;
210  }
211  }
212  }
213 
214  if( tNode )
215  tNode = tNode->GetNext();
216  }
217  }
218 
219  // old version and compatible for both from this point
220  tNode = FindNode( t1Node, wxT( "attr" ) );
221 
222  while( tNode )
223  {
224  tNode->GetAttribute( wxT( "Name" ), &propValue );
225  propValue.Trim( false );
226  propValue.Trim( true );
227 
228  if( propValue == n || propValue == nnew )
229  break;
230 
231  tNode = tNode->GetNext();
232  }
233 
234  if( tNode )
235  SetTextParameters( tNode, aTextValue, m_DefaultMeasurementUnit, aActualConversion );
236 }
237 
238 
239 void PCB::DoPCBComponents( XNODE* aNode, wxXmlDocument* aXmlDoc, const wxString& aActualConversion,
240  wxStatusBar* aStatusBar )
241 {
242  XNODE* lNode, * tNode, * mNode;
243  PCB_FOOTPRINT* fp;
244  PCB_PAD* pad;
245  PCB_VIA* via;
246  PCB_KEEPOUT* keepOut;
247  wxString cn, str, propValue;
248 
249  lNode = aNode->GetChildren();
250 
251  while( lNode )
252  {
253  fp = nullptr;
254 
255  if( lNode->GetName().IsSameAs( wxT( "pattern" ), false ) )
256  {
257  FindNode( lNode, wxT( "patternRef" ) )->GetAttribute( wxT( "Name" ),
258  &cn );
259  cn = ValidateName( cn );
260  tNode = FindNode( (XNODE *)aXmlDoc->GetRoot(), wxT( "library" ) );
261 
262  if( tNode && cn.Len() > 0 )
263  {
264  tNode = FindModulePatternDefName( tNode, cn );
265 
266  if( tNode )
267  {
268  fp = new PCB_FOOTPRINT( this, m_board );
269 
270  mNode = FindNode( lNode, wxT( "patternGraphicsNameRef" ) );
271 
272  if( mNode )
273  mNode->GetAttribute( wxT( "Name" ), &fp->m_patGraphRefName );
274 
275  fp->Parse( tNode, aStatusBar, m_DefaultMeasurementUnit, aActualConversion );
276  }
277  }
278 
279  if( fp )
280  {
281  fp->m_compRef = cn; // default - in new version of file it is updated later....
282  tNode = FindNode( lNode, wxT( "refDesRef" ) );
283 
284  if( tNode )
285  {
286  tNode->GetAttribute( wxT( "Name" ), &fp->m_name.text );
287  SetTextProperty( lNode, &fp->m_name, fp->m_patGraphRefName, wxT( "RefDes" ),
288  aActualConversion );
289  SetTextProperty( lNode, &fp->m_Value, fp->m_patGraphRefName, wxT( "Value" ),
290  aActualConversion );
291  }
292 
293  tNode = FindNode( lNode, wxT( "pt" ) );
294 
295  if( tNode )
296  {
297  SetPosition( tNode->GetNodeContent(), m_DefaultMeasurementUnit,
298  &fp->m_positionX, &fp->m_positionY, aActualConversion );
299  }
300 
301  tNode = FindNode( lNode, wxT( "rotation" ) );
302 
303  if( tNode )
304  {
305  str = tNode->GetNodeContent();
306  str.Trim( false );
307  fp->m_rotation = StrToInt1Units( str );
308  }
309 
310  str = FindNodeGetContent( lNode, wxT( "isFlipped" ) );
311 
312  if( str.IsSameAs( wxT( "True" ), false ) )
313  fp->m_Mirror = 1;
314 
315  tNode = aNode;
316 
317  while( tNode->GetName() != wxT( "www.lura.sk" ) )
318  tNode = tNode->GetParent();
319 
320  tNode = FindNode( tNode, wxT( "netlist" ) );
321 
322  if( tNode )
323  {
324  tNode = FindNode( tNode, wxT( "compInst" ) );
325 
326  while( tNode )
327  {
328  tNode->GetAttribute( wxT( "Name" ), &propValue );
329 
330  if( propValue == fp->m_name.text )
331  {
332  if( FindNode( tNode, wxT( "compValue" ) ) )
333  {
334  FindNode( tNode,
335  wxT( "compValue" ) )->GetAttribute( wxT( "Name" ),
336  &fp->m_Value.text );
337  fp->m_Value.text.Trim( false );
338  fp->m_Value.text.Trim( true );
339  }
340 
341  if( FindNode( tNode, wxT( "compRef" ) ) )
342  {
343  FindNode( tNode,
344  wxT( "compRef" ) )->GetAttribute( wxT( "Name" ),
345  &fp->m_compRef );
346  fp->m_compRef.Trim( false );
347  fp->m_compRef.Trim( true );
348  }
349 
350  tNode = nullptr;
351  }
352  else
353  {
354  tNode = tNode->GetNext();
355  }
356  }
357  }
358 
359  // map pins
360  tNode = FindNode( (XNODE *)aXmlDoc->GetRoot(), wxT( "library" ) );
361  tNode = FindCompDefName( tNode, fp->m_compRef );
362 
363  if( tNode )
364  {
365  tNode = FindPinMap( tNode );
366 
367  if( tNode )
368  {
369  mNode = tNode->GetChildren();
370 
371  while( mNode )
372  {
373  if( mNode->GetName().IsSameAs( wxT( "padNum" ), false ) )
374  {
375  str = mNode->GetNodeContent();
376  mNode = mNode->GetNext();
377 
378  if( !mNode )
379  break;
380 
381  mNode->GetAttribute( wxT( "Name" ), &propValue );
382  fp->SetName( str, propValue );
383  mNode = mNode->GetNext();
384  }
385  else
386  {
387  mNode = mNode->GetNext();
388 
389  if( !mNode )
390  break;
391 
392  mNode = mNode->GetNext();
393  }
394  }
395  }
396  }
397 
398  m_PcbComponents.Add( fp );
399  }
400  }
401  else if( lNode->GetName().IsSameAs( wxT( "pad" ), false ) )
402  {
403  pad = new PCB_PAD( this, m_board );
404  pad->Parse( lNode, m_DefaultMeasurementUnit, aActualConversion );
405  m_PcbComponents.Add( pad );
406  }
407  else if( lNode->GetName().IsSameAs( wxT( "via" ), false ) )
408  {
409  via = new PCB_VIA( this, m_board );
410  via->Parse( lNode, m_DefaultMeasurementUnit, aActualConversion );
411  m_PcbComponents.Add( via );
412  }
413  else if( lNode->GetName().IsSameAs( wxT( "polyKeepOut" ), false ) )
414  {
415  keepOut = new PCB_KEEPOUT( m_callbacks, m_board, 0 );
416 
417  if( keepOut->Parse( lNode, m_DefaultMeasurementUnit, aActualConversion ) )
418  m_PcbComponents.Add( keepOut );
419  else
420  delete keepOut;
421  }
422 
423  lNode = lNode->GetNext();
424  }
425 }
426 
427 
428 void PCB::ConnectPinToNet( const wxString& aCompRef, const wxString& aPinRef,
429  const wxString& aNetName )
430 {
431  PCB_FOOTPRINT* footprint;
432  PCB_PAD* cp;
433  int i, j;
434 
435  for( i = 0; i < (int) m_PcbComponents.GetCount(); i++ )
436  {
437  footprint = (PCB_FOOTPRINT*) m_PcbComponents[i];
438 
439  if( footprint->m_objType == wxT( 'M' ) && footprint->m_name.text == aCompRef )
440  {
441  for( j = 0; j < (int) footprint->m_FootprintItems.GetCount(); j++ )
442  {
443  if( footprint->m_FootprintItems[j]->m_objType == wxT( 'P' ) )
444  {
445  cp = (PCB_PAD*) footprint->m_FootprintItems[j];
446 
447  if( cp->m_name.text == aPinRef )
448  cp->m_net = aNetName;
449  }
450  }
451  }
452  }
453 }
454 
455 
456 int PCB::FindLayer( const wxString& aLayerName ) const
457 {
458  for( LAYER_NUM i = 0; i < (int)m_layersStackup.size(); ++i )
459  {
460  if( m_layersStackup[i].first == aLayerName )
461  return i;
462  }
463 
464  return -1;
465 }
466 
467 
468 void PCB::MapLayer( XNODE* aNode )
469 {
470  wxString lName, layerType;
471  PCB_LAYER_ID KiCadLayer;
472  long num = 0;
473 
474  aNode->GetAttribute( wxT( "Name" ), &lName );
475  lName = lName.MakeUpper();
476 
477  if( lName == wxT( "TOP ASSY" ) )
478  {
479  KiCadLayer = F_Fab;
480  }
481  else if( lName == wxT( "TOP SILK" ) )
482  {
483  KiCadLayer = F_SilkS;
484  }
485  else if( lName == wxT( "TOP PASTE" ) )
486  {
487  KiCadLayer = F_Paste;
488  }
489  else if( lName == wxT( "TOP MASK" ) )
490  {
491  KiCadLayer = F_Mask;
492  }
493  else if( lName == wxT( "TOP" ) )
494  {
495  KiCadLayer = F_Cu;
496  }
497  else if( lName == wxT( "BOTTOM" ) )
498  {
499  KiCadLayer = B_Cu;
500  }
501  else if( lName == wxT( "BOT MASK" ) )
502  {
503  KiCadLayer = B_Mask;
504  }
505  else if( lName == wxT( "BOT PASTE" ) )
506  {
507  KiCadLayer = B_Paste;
508  }
509  else if( lName == wxT( "BOT SILK" ) )
510  {
511  KiCadLayer = B_SilkS;
512  }
513  else if( lName == wxT( "BOT ASSY" ) )
514  {
515  KiCadLayer = B_Fab;
516  }
517  else if( lName == wxT( "BOARD" ) )
518  {
519  KiCadLayer = Edge_Cuts;
520  }
521  else
522  {
523  int layernum = FindLayer( lName );
524 
525  if( layernum == -1 )
526  KiCadLayer = Dwgs_User; // default
527  else
528  KiCadLayer = ToLAYER_ID( layernum );
529  }
530 
531  if( FindNode( aNode, wxT( "layerNum" ) ) )
532  FindNode( aNode, wxT( "layerNum" ) )->GetNodeContent().ToLong( &num );
533 
534  if( num < 0 )
535  THROW_IO_ERROR( wxString::Format( wxT( "layerNum = %ld is out of range" ), num ) );
536 
537  TLAYER newlayer;
538  newlayer.KiCadLayer = KiCadLayer;
539 
540  if( FindNode( aNode, wxT( "layerType" ) ) )
541  {
542  layerType = FindNode( aNode, wxT( "layerType" ) )->GetNodeContent().Trim( false );
543 
544  if( layerType.IsSameAs( wxT( "NonSignal" ), false ) )
545  newlayer.layerType = LAYER_TYPE_NONSIGNAL;
546 
547  if( layerType.IsSameAs( wxT( "Signal" ), false ) )
548  newlayer.layerType = LAYER_TYPE_SIGNAL;
549 
550  if( layerType.IsSameAs( wxT( "Plane" ), false ) )
551  newlayer.layerType = LAYER_TYPE_PLANE;
552  }
553 
554  m_LayersMap.insert( std::make_pair( num, newlayer ) );
555 
556  if( FindNode( aNode, wxT( "netNameRef" ) ) )
557  {
558  FindNode( aNode, wxT( "netNameRef" ) )->GetAttribute( wxT( "Name" ),
559  &m_LayersMap[(int) num].netNameRef );
560  }
561 }
562 
563 int PCB::FindOutlinePoint( const VERTICES_ARRAY* aOutline, wxRealPoint aPoint ) const
564 {
565  int i;
566 
567  for( i = 0; i < (int) aOutline->GetCount(); i++ )
568  {
569  if( *((*aOutline)[i]) == aPoint )
570  return i;
571  }
572 
573  return -1;
574 }
575 
576 
577 double PCB::GetDistance( const wxRealPoint* aPoint1, const wxRealPoint* aPoint2 ) const
578 {
579  return sqrt( ( aPoint1->x - aPoint2->x ) * ( aPoint1->x - aPoint2->x ) +
580  ( aPoint1->y - aPoint2->y ) * ( aPoint1->y - aPoint2->y ) );
581 }
582 
583 void PCB::GetBoardOutline( wxXmlDocument* aXmlDoc, const wxString& aActualConversion )
584 {
585  XNODE* iNode, *lNode, *pNode;
586  long PCadLayer = 0;
587  int x, y, i, j, targetInd;
588  wxRealPoint* xchgPoint;
589  double minDistance, distance;
590 
591  iNode = FindNode( (XNODE *)aXmlDoc->GetRoot(), wxT( "pcbDesign" ) );
592 
593  if( iNode )
594  {
595  // COMPONENTS AND OBJECTS
596  iNode = iNode->GetChildren();
597 
598  while( iNode )
599  {
600  // objects
601  if( iNode->GetName().IsSameAs( wxT( "layerContents" ), false ) )
602  {
603  if( FindNode( iNode, wxT( "layerNumRef" ) ) )
604  FindNode( iNode, wxT( "layerNumRef" ) )->GetNodeContent().ToLong( &PCadLayer );
605 
606  if( GetKiCadLayer( PCadLayer ) == Edge_Cuts )
607  {
608  lNode = iNode->GetChildren();
609 
610  while( lNode )
611  {
612  if( lNode->GetName().IsSameAs( wxT( "line" ), false ) )
613  {
614  pNode = FindNode( lNode, wxT( "pt" ) );
615 
616  if( pNode )
617  {
618  SetPosition( pNode->GetNodeContent(), m_DefaultMeasurementUnit,
619  &x, &y, aActualConversion );
620 
621  if( FindOutlinePoint( &m_BoardOutline, wxRealPoint( x, y) ) == -1 )
622  m_BoardOutline.Add( new wxRealPoint( x, y ) );
623  }
624 
625  if( pNode )
626  pNode = pNode->GetNext();
627 
628  if( pNode )
629  {
630  SetPosition( pNode->GetNodeContent(), m_DefaultMeasurementUnit,
631  &x, &y, aActualConversion );
632 
633  if( FindOutlinePoint( &m_BoardOutline, wxRealPoint( x, y) ) == -1 )
634  m_BoardOutline.Add( new wxRealPoint( x, y ) );
635  }
636  }
637 
638  lNode = lNode->GetNext();
639  }
640 
641  //m_boardOutline.Sort( cmpFunc );
642  // sort vertices according to the distances between them
643  if( m_BoardOutline.GetCount() > 3 )
644  {
645  for( i = 0; i < (int) m_BoardOutline.GetCount() - 1; i++ )
646  {
647  minDistance = GetDistance( m_BoardOutline[i], m_BoardOutline[ i + 1] );
648  targetInd = i + 1;
649 
650  for( j = i + 2; j < (int) m_BoardOutline.GetCount(); j++ )
651  {
653 
654  if( distance < minDistance )
655  {
656  minDistance = distance;
657  targetInd = j;
658  }
659  }
660 
661  xchgPoint = m_BoardOutline[ i + 1];
662  m_BoardOutline[ i + 1] = m_BoardOutline[targetInd];
663  m_BoardOutline[targetInd] = xchgPoint;
664  }
665  }
666 
667  break;
668  }
669  }
670 
671  iNode = iNode->GetNext();
672  }
673  }
674 }
675 
676 
677 void PCB::ParseBoard( wxStatusBar* aStatusBar, wxXmlDocument* aXmlDoc,
678  const wxString& aActualConversion )
679 {
680  XNODE* aNode;//, *aaNode;
681  PCB_NET* net;
682  PCB_COMPONENT* comp;
683  PCB_FOOTPRINT* footprint;
684  wxString compRef, pinRef, layerName, layerType;
685  int i, j, netCode;
686 
687  // Default measurement units
688  aNode = FindNode( (XNODE *)aXmlDoc->GetRoot(), wxT( "asciiHeader" ) );
689 
690  if( aNode )
691  {
692  aNode = FindNode( aNode, wxT( "fileUnits" ) );
693 
694  if( aNode )
695  {
696  m_DefaultMeasurementUnit = aNode->GetNodeContent().Lower();
697  m_DefaultMeasurementUnit.Trim( true );
698  m_DefaultMeasurementUnit.Trim( false );
699  }
700  }
701 
702  // Determine layers stackup
703  aNode = FindNode( (XNODE *)aXmlDoc->GetRoot(), wxT( "pcbDesign" ) );
704 
705  /*if( aNode )
706  {
707  aNode = FindNode( aNode, wxT( "layersStackup" ) );
708 
709  if( aNode )
710  {
711  aNode = FindNode( aNode, wxT( "layerStackupData" ) );
712 
713  while( aNode )
714  {
715  if( aNode->GetName() == wxT( "layerStackupData" ) )
716  {
717  aaNode = FindNode( aNode, wxT( "layerStackupName" ) );
718 
719  if( aaNode ) {
720  aaNode->GetAttribute( wxT( "Name" ), &layerName );
721  layerName = layerName.MakeUpper();
722  m_layersStackup.Add( layerName );
723  }
724  }
725 
726  aNode = aNode->GetNext();
727  }
728  }
729  }*/
730 
731  if( aNode )
732  {
733  aNode = FindNode( aNode, wxT( "layerDef" ) );
734 
735  while( aNode )
736  {
737  if( aNode->GetName().IsSameAs( wxT( "layerDef" ), false ) )
738  {
739  if( FindNode( aNode, wxT( "layerType" ) ) )
740  {
741  long num = -1;
742 
743  if( FindNode( aNode, wxT( "layerNum" ) ) )
744  FindNode( aNode, wxT( "layerNum" ) )->GetNodeContent().ToLong( &num );
745 
746  layerType = FindNode( aNode, wxT( "layerType" ) )->GetNodeContent().Trim(
747  false );
748 
749  if( num > 0 && ( layerType.IsSameAs( wxT( "Signal" ), false )
750  || layerType.IsSameAs( wxT( "Plane" ), false ) ) )
751  {
752  aNode->GetAttribute( wxT( "Name" ), &layerName );
753  layerName = layerName.MakeUpper();
754  m_layersStackup.emplace_back( layerName, num );
755 
756  if( m_layersStackup.size() > 32 )
757  THROW_IO_ERROR( _( "KiCad only supports 32 signal layers." ) );
758  }
759  }
760  }
761 
762  aNode = aNode->GetNext();
763  }
764 
765  // Ensure that the layers are properly mapped to their order with the bottom
766  // copper (layer 2 in PCAD) at the end
767  std::sort( m_layersStackup.begin(), m_layersStackup.end(),
768  [&]( const std::pair<wxString, long>& a, const std::pair<wxString, long>& b ) {
769  long lhs = a.second == 2 ? std::numeric_limits<long>::max() : a.second;
770  long rhs = b.second == 2 ? std::numeric_limits<long>::max() : b.second;
771 
772  return lhs < rhs;
773  } );
774  }
775 
776  // Layers mapping
777  aNode = FindNode( (XNODE *)aXmlDoc->GetRoot(), wxT( "pcbDesign" ) );
778 
779  if( aNode )
780  {
781  aNode = FindNode( aNode, wxT( "layerDef" ) );
782 
783  while( aNode )
784  {
785  if( aNode->GetName().IsSameAs( wxT( "layerDef" ), false ) )
786  MapLayer( aNode );
787 
788  aNode = aNode->GetNext();
789  }
790  }
791 
792  GetBoardOutline( aXmlDoc, aActualConversion );
793 
794  // NETLIST
795  // aStatusBar->SetStatusText( wxT( "Loading NETLIST " ) );
796 
797  aNode = FindNode( (XNODE *)aXmlDoc->GetRoot(), wxT( "netlist" ) );
798 
799  if( aNode )
800  {
801  aNode = FindNode( aNode, wxT( "net" ) );
802 
803  netCode = 1;
804 
805  while( aNode )
806  {
807  net = new PCB_NET( netCode++ );
808  net->Parse( aNode );
809  m_PcbNetlist.Add( net );
810 
811  aNode = aNode->GetNext();
812  }
813  }
814 
815  // BOARD FILE
816  // aStatusBar->SetStatusText( wxT( "Loading BOARD DEFINITION " ) );
817 
818  aNode = FindNode( (XNODE *)aXmlDoc->GetRoot(), wxT( "pcbDesign" ) );
819 
820  if( aNode )
821  {
822  // COMPONENTS AND OBJECTS
823  aNode = aNode->GetChildren();
824 
825  while( aNode )
826  {
827  // Components/footprints
828  if( aNode->GetName().IsSameAs( wxT( "multiLayer" ), false ) )
829  DoPCBComponents( aNode, aXmlDoc, aActualConversion, aStatusBar );
830 
831  // objects
832  if( aNode->GetName().IsSameAs( wxT( "layerContents" ), false ) )
833  DoLayerContentsObjects( aNode, nullptr, &m_PcbComponents, aStatusBar,
834  m_DefaultMeasurementUnit, aActualConversion );
835 
836  aNode = aNode->GetNext();
837  }
838 
839  // POSTPROCESS -- SET NETLIST REFERENCES
840  // aStatusBar->SetStatusText( wxT( "Processing NETLIST " ) );
841 
842  for( i = 0; i < (int) m_PcbNetlist.GetCount(); i++ )
843  {
844  net = m_PcbNetlist[i];
845 
846  for( j = 0; j < (int) net->m_NetNodes.GetCount(); j++ )
847  {
848  compRef = net->m_NetNodes[j]->m_CompRef;
849  compRef.Trim( false );
850  compRef.Trim( true );
851  pinRef = net->m_NetNodes[j]->m_PinRef;
852  pinRef.Trim( false );
853  pinRef.Trim( true );
854  ConnectPinToNet( compRef, pinRef, net->m_Name );
855  }
856  }
857 
858  // POSTPROCESS -- FLIP COMPONENTS
859  for( i = 0; i < (int) m_PcbComponents.GetCount(); i++ )
860  {
861  if( m_PcbComponents[i]->m_objType == wxT( 'M' ) )
862  ( (PCB_FOOTPRINT*) m_PcbComponents[i] )->Flip();
863  }
864 
865  // POSTPROCESS -- SET/OPTIMIZE NEW PCB POSITION
866  // aStatusBar->SetStatusText( wxT( "Optimizing BOARD POSITION " ) );
867 
868  m_SizeX = 10000000;
869  m_SizeY = 0;
870 
871  for( i = 0; i < (int) m_PcbComponents.GetCount(); i++ )
872  {
873  comp = m_PcbComponents[i];
874 
875  if( comp->m_positionY < m_SizeY )
876  m_SizeY = comp->m_positionY; // max Y
877 
878  if( comp->m_positionX < m_SizeX && comp->m_positionX > 0 )
879  m_SizeX = comp->m_positionX; // Min X
880  }
881 
882  m_SizeY -= 10000;
883  m_SizeX -= 10000;
884  // aStatusBar->SetStatusText( wxT( " POSITIONING POSTPROCESS " ) );
885 
886  for( i = 0; i < (int) m_PcbComponents.GetCount(); i++ )
888 
889  m_SizeX = 0;
890  m_SizeY = 0;
891 
892  for( i = 0; i < (int) m_PcbComponents.GetCount(); i++ )
893  {
894  comp = m_PcbComponents[i];
895 
896  if( comp->m_positionY < m_SizeY )
897  m_SizeY = comp->m_positionY; // max Y
898 
899  if( comp->m_positionX > m_SizeX )
900  m_SizeX = comp->m_positionX; // Min X
901  }
902 
903  // SHEET SIZE CALCULATION
904  m_SizeY = -m_SizeY; // it is in absolute units
905  m_SizeX += 10000;
906  m_SizeY += 10000;
907 
908  // A4 is minimum $Descr A4 11700 8267
909  if( m_SizeX < 11700 )
910  m_SizeX = 11700;
911 
912  if( m_SizeY < 8267 )
913  m_SizeY = 8267;
914  }
915  else
916  {
917  // LIBRARY FILE
918  // aStatusBar->SetStatusText( wxT( "Processing LIBRARY FILE " ) );
919 
920  aNode = FindNode( (XNODE *)aXmlDoc->GetRoot(), wxT( "library" ) );
921 
922  if( aNode )
923  {
924  aNode = FindNode( aNode, wxT( "compDef" ) );
925 
926  while( aNode )
927  {
928  // aStatusBar->SetStatusText( wxT( "Processing COMPONENTS " ) );
929 
930  if( aNode->GetName().IsSameAs( wxT( "compDef" ), false ) )
931  {
932  footprint = new PCB_FOOTPRINT( this, m_board );
933  footprint->Parse( aNode, aStatusBar, m_DefaultMeasurementUnit,
934  aActualConversion );
935  m_PcbComponents.Add( footprint );
936  }
937 
938  aNode = aNode->GetNext();
939  }
940  }
941  }
942 }
943 
944 
946 {
947  int i;
948  PCB_NET* net;
949 
951 
952  for( i = 0; i < (int) m_PcbNetlist.GetCount(); i++ )
953  {
954  net = m_PcbNetlist[i];
955 
956  m_board->Add( new NETINFO_ITEM( m_board, net->m_Name, net->m_NetCode ) );
957  }
958 
959  for( i = 0; i < (int) m_PcbComponents.GetCount(); i++ )
960  {
961  m_PcbComponents[i]->AddToBoard();
962  }
963 }
964 
965 } // namespace PCAD2KICAD
int m_SizeX
Definition: pcb.h:66
int GetNetCode(const wxString &aNetName) const override
Definition: pcb.cpp:125
LAYER_TYPE_T GetLayerType(int aPCadLayer) const override
Definition: pcb.cpp:57
void ParseBoard(wxStatusBar *aStatusBar, wxXmlDocument *aXmlDoc, const wxString &aActualConversion)
Definition: pcb.cpp:677
wxString ValidateName(const wxString &aName)
virtual void Parse(XNODE *aNode, wxStatusBar *aStatusBar, const wxString &aDefaultMeasurementUnit, const wxString &aActualConversion)
int FindOutlinePoint(const VERTICES_ARRAY *aOutline, wxRealPoint aPoint) const
Definition: pcb.cpp:563
void DoLayerContentsObjects(XNODE *aNode, PCB_FOOTPRINT *aFootprint, PCB_COMPONENTS_ARRAY *aList, wxStatusBar *aStatusBar, const wxString &aDefaultMeasurementUnit, const wxString &aActualConversion)
void SetCopperLayerCount(int aCount)
Definition: board.cpp:461
int LAYER_NUM
This can be replaced with int and removed.
Definition: layer_ids.h:41
XNODE * FindModulePatternDefName(XNODE *aNode, const wxString &aName)
PCB_NET_NODES_ARRAY m_NetNodes
Definition: pcb_net.h:58
PCB_COMPONENTS_ARRAY m_PcbComponents
Definition: pcb.h:62
void SetTextProperty(XNODE *aNode, TTEXTVALUE *aTextValue, const wxString &aPatGraphRefName, const wxString &aXmlName, const wxString &aActualConversion)
Definition: pcb.cpp:170
PCB_LAYER_ID KiCadLayer
Definition: pcb_callbacks.h:46
int FindLayer(const wxString &aLayerName) const
Definition: pcb.cpp:456
PCB_NETS_ARRAY m_PcbNetlist
Definition: pcb.h:63
virtual void SetPosOffset(int aX_offs, int aY_offs)
virtual void Flip() override
PCB(BOARD *aBoard)
Definition: pcb.cpp:79
void ConnectPinToNet(const wxString &aCr, const wxString &aPr, const wxString &aNetName)
Definition: pcb.cpp:428
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Adds an item to the container.
Definition: board.cpp:608
std::map< int, TLAYER > m_LayersMap
Definition: pcb.h:65
void SetName(const wxString &aPin, const wxString &aName)
void AddToBoard() override
Definition: pcb.cpp:945
wxString m_DefaultMeasurementUnit
Definition: pcb.h:64
XNODE * GetChildren() const
Definition: xnode.h:62
LAYER_TYPE_T layerType
Definition: pcb_callbacks.h:47
void DoPCBComponents(XNODE *aNode, wxXmlDocument *aXmlDoc, const wxString &aActualConversion, wxStatusBar *aStatusBar)
Definition: pcb.cpp:239
XNODE * GetParent() const
Definition: xnode.h:72
wxString FindNodeGetContent(XNODE *aChild, const wxString &aTag)
wxString netNameRef
Definition: pcb_callbacks.h:48
void SetTextParameters(XNODE *aNode, TTEXTVALUE *aTextValue, const wxString &aDefaultMeasurementUnit, const wxString &aActualConversion)
VERTICES_ARRAY m_BoardOutline
Definition: pcb_footprint.h:66
int m_SizeY
Definition: pcb.h:67
double GetDistance(const wxRealPoint *aPoint1, const wxRealPoint *aPoint2) const
Definition: pcb.cpp:577
XNODE * FindCompDefName(XNODE *aNode, const wxString &aName) const
Definition: pcb.cpp:142
#define _(s)
void GetBoardOutline(wxXmlDocument *aXmlDoc, const wxString &aActualConversion)
Definition: pcb.cpp:583
wxString GetLayerNetNameRef(int aPCadLayer) const override
Definition: pcb.cpp:68
static float distance(const SFVEC2UI &a, const SFVEC2UI &b)
PCB_LAYER_ID GetKiCadLayer() const
Definition: pcb_component.h:56
virtual bool Parse(XNODE *aNode, const wxString &aDefaultMeasurementUnit, const wxString &aActualConversion) override
Definition: pcb_keepout.cpp:49
Hold an XML or S-expression element.
Definition: xnode.h:43
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
std::vector< std::pair< wxString, long > > m_layersStackup
Definition: pcb.h:86
Handle the data for a net.
Definition: netinfo.h:66
PCB_COMPONENTS_ARRAY m_FootprintItems
Definition: pcb_footprint.h:64
XNODE * GetNext() const
Definition: xnode.h:67
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:191
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:65
Definition: layer_ids.h:71
PCB_FOOTPRINT(PCB_CALLBACKS *aCallbacks, BOARD *aBoard)
void MapLayer(XNODE *aNode)
Definition: pcb.cpp:468
XNODE * FindNode(XNODE *aChild, const wxString &aTag)
The common library.
wxString m_Name
Definition: pcb_net.h:56
PCB_CALLBACKS * m_callbacks
Definition: pcb_component.h:78
LAYER_TYPE_T
Definition: pcb_callbacks.h:37
void Parse(XNODE *aNode)
Definition: pcb_net.cpp:63
XNODE * FindPinMap(XNODE *aNode)
int StrToInt1Units(const wxString &aStr)
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:914
void SetPosition(const wxString &aStr, const wxString &aDefaultMeasurementUnit, int *aX, int *aY, const wxString &aActualConversion)