KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcad_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 The 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, see <https://www.gnu.org/licenses/>.
20 */
21
22#include <pcad/pcad_pcb.h>
23
24#include <pcad/pcad_keepout.h>
25#include <pcad/pcad_footprint.h>
26#include <pcad/pcad_nets.h>
27#include <pcad/pcad_pad.h>
28#include <pcad/pcad_via.h>
29
30#include <board.h>
31#include <common.h>
32#include <xnode.h>
33
34#include <wx/string.h>
35
36namespace PCAD2KICAD {
37
38
40{
41 auto it = m_LayersMap.find( aPCadLayer );
42
43 if( it == m_LayersMap.end() )
44 THROW_IO_ERROR( wxString::Format( _( "Unknown PCad layer %u" ), unsigned( aPCadLayer ) ) );
45
46 return it->second.KiCadLayer;
47}
48
49
50LAYER_TYPE_T PCAD_PCB::GetLayerType( int aPCadLayer ) const
51{
52 auto it = m_LayersMap.find( aPCadLayer );
53
54 if( it == m_LayersMap.end() )
55 THROW_IO_ERROR( wxString::Format( _( "Unknown PCad layer %u" ), unsigned( aPCadLayer ) ) );
56
57 return it->second.layerType;
58}
59
60
61wxString PCAD_PCB::GetLayerNetNameRef( int aPCadLayer ) const
62{
63 auto it = m_LayersMap.find( aPCadLayer );
64
65 if( it == m_LayersMap.end() )
66 THROW_IO_ERROR( wxString::Format( _( "Unknown PCad layer %u" ), unsigned( aPCadLayer ) ) );
67
68 return it->second.netNameRef;
69}
70
71
72PCAD_PCB::PCAD_PCB( BOARD* aBoard ) : PCAD_FOOTPRINT( this, aBoard )
73{
74 m_DefaultMeasurementUnit = wxT( "mil" );
75
76 // Fill layer map with PCAD defaults
77 for( size_t i = 1; i < 12; ++i )
78 {
79 TLAYER layer;
80 layer.KiCadLayer = User_1; // default
81 layer.layerType = LAYER_TYPE_NONSIGNAL; // default
82 layer.netNameRef = wxT( "" ); // default
83 layer.hasContent = false;
84
85 m_LayersMap.insert( std::make_pair( i, layer ) );
86 }
87
88 m_SizeX = 0;
89 m_SizeY = 0;
90
91 m_LayersMap[1].KiCadLayer = F_Cu;
92 m_LayersMap[1].layerType = LAYER_TYPE_SIGNAL;
93
94 m_LayersMap[2].KiCadLayer = B_Cu;
95 m_LayersMap[2].layerType = LAYER_TYPE_SIGNAL;
96
97 m_LayersMap[3].KiCadLayer = Edge_Cuts;
98
99 m_LayersMap[4].KiCadLayer = F_Mask;
100
101 m_LayersMap[5].KiCadLayer = B_Mask;
102
103 m_LayersMap[6].KiCadLayer = F_SilkS;
104
105 m_LayersMap[7].KiCadLayer = B_SilkS;
106
107 m_LayersMap[8].KiCadLayer = F_Paste;
108
109 m_LayersMap[9].KiCadLayer = B_Paste;
110
111 m_LayersMap[10].KiCadLayer = F_Fab;
112
113 m_LayersMap[11].KiCadLayer = B_Fab;
114}
115
116
118{
119 int i;
120
121 for( i = 0; i < (int) m_PcbComponents.GetCount(); i++ )
122 {
123 delete m_PcbComponents[i];
124 }
125
126 for( i = 0; i < (int) m_PcbNetlist.GetCount(); i++ )
127 {
128 delete m_PcbNetlist[i];
129 }
130}
131
132
133int PCAD_PCB::GetNetCode( const wxString& aNetName ) const
134{
135 const PCAD_NET* net;
136
137 for( int i = 0; i < (int) m_PcbNetlist.GetCount(); i++ )
138 {
139 net = m_PcbNetlist[i];
140
141 if( net->m_Name == aNetName )
142 {
143 return net->m_NetCode;
144 }
145 }
146
147 return 0;
148}
149
150XNODE* PCAD_PCB::FindCompDefName( XNODE* aNode, const wxString& aName ) const
151{
152 XNODE* result = nullptr, * lNode;
153 wxString propValue;
154
155 lNode = FindNode( aNode, wxT( "compDef" ) );
156
157 while( lNode )
158 {
159 if( lNode->GetName().IsSameAs( wxT( "compDef" ), false ) )
160 {
161 lNode->GetAttribute( wxT( "Name" ), &propValue );
162
163 if( propValue == aName )
164 {
165 result = lNode;
166 lNode = nullptr;
167 }
168 }
169
170 if( lNode )
171 lNode = lNode->GetNext();
172 }
173
174 return result;
175}
176
177
178void PCAD_PCB::SetTextProperty( XNODE* aNode, TTEXTVALUE* aTextValue, const wxString& aPatGraphRefName,
179 const wxString& aXmlName, const wxString& aActualConversion )
180{
181 XNODE* tNode, * t1Node;
182 wxString n, nnew, pn, propValue, str;
183
184 // aNode is pattern now
185 tNode = aNode;
186 t1Node = aNode;
187 n = aXmlName;
188
189 // new file format version
190 if( FindNode( tNode, wxT( "patternGraphicsNameRef" ) ) )
191 {
192 FindNode( tNode,
193 wxT( "patternGraphicsNameRef" ) )->GetAttribute( wxT( "Name" ),
194 &pn );
195 pn.Trim( false );
196 pn.Trim( true );
197 tNode = FindNode( tNode, wxT( "patternGraphicsRef" ) );
198
199 while( tNode )
200 {
201 if( tNode->GetName().IsSameAs( wxT( "patternGraphicsRef" ), false ) )
202 {
203 if( FindNode( tNode, wxT( "patternGraphicsNameRef" ) ) )
204 {
205 FindNode( tNode,
206 wxT( "patternGraphicsNameRef" ) )->GetAttribute( wxT( "Name" ),
207 &propValue );
208
209 if( propValue == pn )
210 {
211 t1Node = tNode; // find correct section with same name.
212 str = aTextValue->text;
213 str.Trim( false );
214 str.Trim( true );
215 nnew = n; // new file version
216 n = n + wxT( ' ' ) + str; // old file version
217 tNode = nullptr;
218 }
219 }
220 }
221
222 if( tNode )
223 tNode = tNode->GetNext();
224 }
225 }
226
227 // old version and compatible for both from this point
228 tNode = FindNode( t1Node, wxT( "attr" ) );
229
230 while( tNode )
231 {
232 tNode->GetAttribute( wxT( "Name" ), &propValue );
233 propValue.Trim( false );
234 propValue.Trim( true );
235
236 if( propValue == n || propValue == nnew )
237 break;
238
239 tNode = tNode->GetNext();
240 }
241
242 if( tNode )
243 SetTextParameters( tNode, aTextValue, m_DefaultMeasurementUnit, aActualConversion );
244}
245
246
247void PCAD_PCB::DoPCBComponents( XNODE* aNode, wxXmlDocument* aXmlDoc, const wxString& aActualConversion,
248 wxStatusBar* aStatusBar )
249{
250 XNODE* lNode, * tNode, * mNode;
251 PCAD_FOOTPRINT* fp;
252 PCAD_PAD* pad;
253 PCAD_VIA* via;
254 PCAD_KEEPOUT* keepOut;
255 wxString cn, str, propValue;
256
257 lNode = aNode->GetChildren();
258
259 while( lNode )
260 {
261 fp = nullptr;
262
263 if( lNode->GetName().IsSameAs( wxT( "pattern" ), false ) )
264 {
265 FindNode( lNode, wxT( "patternRef" ) )->GetAttribute( wxT( "Name" ),
266 &cn );
267 cn = ValidateName( cn );
268 tNode = FindNode( (XNODE *)aXmlDoc->GetRoot(), wxT( "library" ) );
269
270 if( tNode && cn.Len() > 0 )
271 {
272 tNode = FindModulePatternDefName( tNode, cn );
273
274 if( tNode )
275 {
276 fp = new PCAD_FOOTPRINT( this, m_board );
277
278 mNode = FindNode( lNode, wxT( "patternGraphicsNameRef" ) );
279
280 if( mNode )
281 mNode->GetAttribute( wxT( "Name" ), &fp->m_PatGraphRefName );
282
283 fp->Parse( tNode, aStatusBar, m_DefaultMeasurementUnit, aActualConversion );
284 }
285 }
286
287 if( fp )
288 {
289 fp->m_CompRef = cn; // default - in new version of file it is updated later....
290 tNode = FindNode( lNode, wxT( "refDesRef" ) );
291
292 if( tNode )
293 {
294 tNode->GetAttribute( wxT( "Name" ), &fp->m_Name.text );
295 SetTextProperty( lNode, &fp->m_Name, fp->m_PatGraphRefName, wxT( "RefDes" ),
296 aActualConversion );
297 SetTextProperty( lNode, &fp->m_Value, fp->m_PatGraphRefName, wxT( "Value" ),
298 aActualConversion );
299 }
300
301 tNode = FindNode( lNode, wxT( "pt" ) );
302
303 if( tNode )
304 {
305 SetPosition( tNode->GetNodeContent(), m_DefaultMeasurementUnit,
306 &fp->m_PositionX, &fp->m_PositionY, aActualConversion );
307 }
308
309 tNode = FindNode( lNode, wxT( "rotation" ) );
310
311 if( tNode )
312 {
313 str = tNode->GetNodeContent();
314 str.Trim( false );
316 }
317
318 str = FindNodeGetContent( lNode, wxT( "isFlipped" ) );
319
320 if( str.IsSameAs( wxT( "True" ), false ) )
321 fp->m_Mirror = 1;
322
323 tNode = aNode;
324
325 while( tNode->GetName() != wxT( "www.lura.sk" ) )
326 tNode = tNode->GetParent();
327
328 tNode = FindNode( tNode, wxT( "netlist" ) );
329
330 if( tNode )
331 {
332 tNode = FindNode( tNode, wxT( "compInst" ) );
333
334 while( tNode )
335 {
336 tNode->GetAttribute( wxT( "Name" ), &propValue );
337
338 if( propValue == fp->m_Name.text )
339 {
340 if( FindNode( tNode, wxT( "compValue" ) ) )
341 {
342 FindNode( tNode,
343 wxT( "compValue" ) )->GetAttribute( wxT( "Name" ),
344 &fp->m_Value.text );
345 fp->m_Value.text.Trim( false );
346 fp->m_Value.text.Trim( true );
347 }
348
349 if( FindNode( tNode, wxT( "compRef" ) ) )
350 {
351 FindNode( tNode,
352 wxT( "compRef" ) )->GetAttribute( wxT( "Name" ),
353 &fp->m_CompRef );
354 fp->m_CompRef.Trim( false );
355 fp->m_CompRef.Trim( true );
356 }
357
358 tNode = nullptr;
359 }
360 else
361 {
362 tNode = tNode->GetNext();
363 }
364 }
365 }
366
367 // map pins
368 tNode = FindNode( (XNODE *)aXmlDoc->GetRoot(), wxT( "library" ) );
369 tNode = FindCompDefName( tNode, fp->m_CompRef );
370
371 if( tNode )
372 {
373 tNode = FindPinMap( tNode );
374
375 if( tNode )
376 {
377 mNode = tNode->GetChildren();
378
379 while( mNode )
380 {
381 if( mNode->GetName().IsSameAs( wxT( "padNum" ), false ) )
382 {
383 str = mNode->GetNodeContent();
384 mNode = mNode->GetNext();
385
386 if( !mNode )
387 break;
388
389 mNode->GetAttribute( wxT( "Name" ), &propValue );
390 fp->SetName( str, propValue );
391 mNode = mNode->GetNext();
392 }
393 else
394 {
395 mNode = mNode->GetNext();
396
397 if( !mNode )
398 break;
399
400 mNode = mNode->GetNext();
401 }
402 }
403 }
404 }
405
406 m_PcbComponents.Add( fp );
407 }
408 }
409 else if( lNode->GetName().IsSameAs( wxT( "pad" ), false ) )
410 {
411 pad = new PCAD_PAD( this, m_board );
412 pad->Parse( lNode, m_DefaultMeasurementUnit, aActualConversion );
413 m_PcbComponents.Add( pad );
414 }
415 else if( lNode->GetName().IsSameAs( wxT( "via" ), false ) )
416 {
417 via = new PCAD_VIA( this, m_board );
418 via->Parse( lNode, m_DefaultMeasurementUnit, aActualConversion );
419 m_PcbComponents.Add( via );
420 }
421 else if( lNode->GetName().IsSameAs( wxT( "polyKeepOut" ), false ) )
422 {
423 keepOut = new PCAD_KEEPOUT( m_callbacks, m_board, 0 );
424
425 if( keepOut->Parse( lNode, m_DefaultMeasurementUnit, aActualConversion ) )
426 m_PcbComponents.Add( keepOut );
427 else
428 delete keepOut;
429 }
430
431 lNode = lNode->GetNext();
432 }
433}
434
435
436void PCAD_PCB::ConnectPinToNet( const wxString& aCompRef, const wxString& aPinRef,
437 const wxString& aNetName )
438{
439 PCAD_FOOTPRINT* footprint;
440 PCAD_PAD* cp;
441 int i, j;
442
443 for( i = 0; i < (int) m_PcbComponents.GetCount(); i++ )
444 {
445 footprint = (PCAD_FOOTPRINT*) m_PcbComponents[i];
446
447 if( footprint->m_ObjType == wxT( 'M' ) && footprint->m_Name.text == aCompRef )
448 {
449 for( j = 0; j < (int) footprint->m_FootprintItems.GetCount(); j++ )
450 {
451 if( footprint->m_FootprintItems[j]->m_ObjType == wxT( 'P' ) )
452 {
453 cp = (PCAD_PAD*) footprint->m_FootprintItems[j];
454
455 if( cp->m_Name.text == aPinRef )
456 cp->m_Net = aNetName;
457 }
458 }
459 }
460 }
461}
462
463
464int PCAD_PCB::FindLayer( const wxString& aLayerName ) const
465{
466 int layerIndex = -1;
467 long layerNum = -1;
468
469 for( int i = 0; i < (int) m_layersStackup.size(); ++i )
470 {
471 if( m_layersStackup[i].first == aLayerName )
472 {
473 layerIndex = i;
474 layerNum = m_layersStackup[i].second;
475 break;
476 }
477 }
478
479 switch( layerNum )
480 {
481 case -1: return -1;
482 case 1: return F_Cu;
483 case 2: return B_Cu;
484 default: return ( layerIndex + 1 ) * 2;
485 }
486}
487
488
490{
491 wxString lName, layerType;
492 PCB_LAYER_ID KiCadLayer = UNDEFINED_LAYER;
493 long num = 0;
494
495 aNode->GetAttribute( wxT( "Name" ), &lName );
496 lName = lName.MakeUpper();
497
498 if( lName == wxT( "TOP ASSY" ) )
499 {
500 KiCadLayer = F_Fab;
501 }
502 else if( lName == wxT( "TOP SILK" ) )
503 {
504 KiCadLayer = F_SilkS;
505 }
506 else if( lName == wxT( "TOP PASTE" ) )
507 {
508 KiCadLayer = F_Paste;
509 }
510 else if( lName == wxT( "TOP MASK" ) )
511 {
512 KiCadLayer = F_Mask;
513 }
514 else if( lName == wxT( "TOP" ) )
515 {
516 KiCadLayer = F_Cu;
517 }
518 else if( lName == wxT( "BOTTOM" ) )
519 {
520 KiCadLayer = B_Cu;
521 }
522 else if( lName == wxT( "BOT MASK" ) )
523 {
524 KiCadLayer = B_Mask;
525 }
526 else if( lName == wxT( "BOT PASTE" ) )
527 {
528 KiCadLayer = B_Paste;
529 }
530 else if( lName == wxT( "BOT SILK" ) )
531 {
532 KiCadLayer = B_SilkS;
533 }
534 else if( lName == wxT( "BOT ASSY" ) )
535 {
536 KiCadLayer = B_Fab;
537 }
538 else if( lName == wxT( "BOARD" ) )
539 {
540 KiCadLayer = Edge_Cuts;
541 }
542 else
543 {
544 int layernum = FindLayer( lName );
545
546 if( layernum != -1 )
547 KiCadLayer = ToLAYER_ID( layernum );
548 }
549
550 if( FindNode( aNode, wxT( "layerNum" ) ) )
551 FindNode( aNode, wxT( "layerNum" ) )->GetNodeContent().ToLong( &num );
552
553 if( num < 0 )
554 THROW_IO_ERROR( wxString::Format( wxT( "layerNum = %ld is out of range" ), num ) );
555
556 TLAYER newlayer;
557 newlayer.KiCadLayer = KiCadLayer;
558 newlayer.hasContent = false;
559
560 if( KiCadLayer == UNDEFINED_LAYER )
561 {
562 newlayer.KiCadLayer = Dwgs_User; // default
563 }
564
565 if( FindNode( aNode, wxT( "layerType" ) ) )
566 {
567 layerType = FindNode( aNode, wxT( "layerType" ) )->GetNodeContent().Trim( false );
568
569 if( layerType.IsSameAs( wxT( "NonSignal" ), false ) )
571
572 if( layerType.IsSameAs( wxT( "Signal" ), false ) )
573 newlayer.layerType = LAYER_TYPE_SIGNAL;
574
575 if( layerType.IsSameAs( wxT( "Plane" ), false ) )
576 newlayer.layerType = LAYER_TYPE_PLANE;
577 }
578
579 if( auto [it, success] = m_LayersMap.insert( std::make_pair( num, newlayer ) ); !success )
580 {
581 // If we can't assign layer by name or stackup, but it has been already assigned by default pcad id in constructor, we don't want to change the assignment
582 if( KiCadLayer == UNDEFINED_LAYER )
583 {
584 newlayer.KiCadLayer = it->second.KiCadLayer;
585 }
586 it->second = newlayer;
587 }
588
589 if( FindNode( aNode, wxT( "netNameRef" ) ) )
590 {
591 FindNode( aNode, wxT( "netNameRef" ) )->GetAttribute( wxT( "Name" ),
592 &m_LayersMap[(int) num].netNameRef );
593 m_LayersMap[(int) num].netNameRef.Trim( false );
594 m_LayersMap[(int) num].netNameRef.Trim( true );
595 m_LayersMap[(int) num].netNameRef = ConvertNetName( m_LayersMap[(int) num].netNameRef );
596 }
597}
598
599int PCAD_PCB::FindOutlinePoint( const VERTICES_ARRAY* aOutline, wxRealPoint aPoint ) const
600{
601 int i;
602
603 for( i = 0; i < (int) aOutline->GetCount(); i++ )
604 {
605 if( *((*aOutline)[i]) == aPoint )
606 return i;
607 }
608
609 return -1;
610}
611
612
613double PCAD_PCB::GetDistance( const wxRealPoint* aPoint1, const wxRealPoint* aPoint2 ) const
614{
615 return sqrt( ( aPoint1->x - aPoint2->x ) * ( aPoint1->x - aPoint2->x ) +
616 ( aPoint1->y - aPoint2->y ) * ( aPoint1->y - aPoint2->y ) );
617}
618
619void PCAD_PCB::ExtractOutlinePointsFromEnhancedPolygon( const wxString& aActualConversion, XNODE* lNode )
620{
621 XNODE* epNode = nullptr;
622 int x = 0;
623 int y = 0;
624
625 epNode = FindNode( lNode, wxT( "enhancedPolygon" ) );
626
627 if( !epNode )
628 return;
629
630 epNode = epNode->GetChildren();
631
632 while( epNode )
633 {
634 if( epNode->GetName().IsSameAs( wxT( "polyPoint" ), false ) )
635 {
636 SetPosition( epNode->GetNodeContent(), m_DefaultMeasurementUnit, &x, &y, aActualConversion );
637
638 if( FindOutlinePoint( &m_BoardOutline, wxRealPoint( x, y ) ) == -1 )
639 m_BoardOutline.Add( new wxRealPoint( x, y ) );
640 }
641
642 epNode = epNode->GetNext();
643 }
644}
645
646void PCAD_PCB::GetBoardOutline( wxXmlDocument* aXmlDoc, const wxString& aActualConversion )
647{
648 XNODE * iNode, *lNode, *pNode;
649 long PCadLayer = 0;
650 int x, y, i, j, targetInd;
651 wxRealPoint* xchgPoint;
652 double minDistance, distance;
653
654 iNode = FindNode( (XNODE *)aXmlDoc->GetRoot(), wxT( "pcbDesign" ) );
655
656 if( iNode )
657 {
658 // COMPONENTS AND OBJECTS
659 iNode = iNode->GetChildren();
660
661 while( iNode )
662 {
663 // objects
664 if( iNode->GetName().IsSameAs( wxT( "layerContents" ), false ) )
665 {
666 if( FindNode( iNode, wxT( "layerNumRef" ) ) )
667 FindNode( iNode, wxT( "layerNumRef" ) )->GetNodeContent().ToLong( &PCadLayer );
668
669 if( GetKiCadLayer( PCadLayer ) == Edge_Cuts )
670 {
671 lNode = iNode->GetChildren();
672
673 while( lNode )
674 {
675 if( lNode->GetName().IsSameAs( wxT( "boardOutlineObj" ), false ) )
676 {
677 ExtractOutlinePointsFromEnhancedPolygon( aActualConversion, lNode );
678 }
679
680 if( lNode->GetName().IsSameAs( wxT( "line" ), false ) )
681 {
682 pNode = FindNode( lNode, wxT( "pt" ) );
683
684 if( pNode )
685 {
686 SetPosition( pNode->GetNodeContent(), m_DefaultMeasurementUnit,
687 &x, &y, aActualConversion );
688
689 if( FindOutlinePoint( &m_BoardOutline, wxRealPoint( x, y) ) == -1 )
690 m_BoardOutline.Add( new wxRealPoint( x, y ) );
691 }
692
693 if( pNode )
694 pNode = pNode->GetNext();
695
696 if( pNode )
697 {
698 SetPosition( pNode->GetNodeContent(), m_DefaultMeasurementUnit,
699 &x, &y, aActualConversion );
700
701 if( FindOutlinePoint( &m_BoardOutline, wxRealPoint( x, y) ) == -1 )
702 m_BoardOutline.Add( new wxRealPoint( x, y ) );
703 }
704 }
705
706 lNode = lNode->GetNext();
707 }
708
709 //m_boardOutline.Sort( cmpFunc );
710 // sort vertices according to the distances between them
711 if( m_BoardOutline.GetCount() > 3 )
712 {
713 for( i = 0; i < (int) m_BoardOutline.GetCount() - 1; i++ )
714 {
715 minDistance = GetDistance( m_BoardOutline[i], m_BoardOutline[ i + 1] );
716 targetInd = i + 1;
717
718 for( j = i + 2; j < (int) m_BoardOutline.GetCount(); j++ )
719 {
721
722 if( distance < minDistance )
723 {
724 minDistance = distance;
725 targetInd = j;
726 }
727 }
728
729 xchgPoint = m_BoardOutline[ i + 1];
730 m_BoardOutline[ i + 1] = m_BoardOutline[targetInd];
731 m_BoardOutline[targetInd] = xchgPoint;
732 }
733 }
734
735 break;
736 }
737 }
738
739 iNode = iNode->GetNext();
740 }
741 }
742}
743
744
745void PCAD_PCB::ExtractLayerStackup( wxXmlDocument* aXmlDoc )
746{
747 XNODE* rootNode;
748 XNODE* aNode;
749 XNODE* aaNode;
750 wxString layerName, layerType;
751 bool isSignalLayer;
752 bool stackupIncomplete = false;
753
754 rootNode = FindNode( (XNODE*) aXmlDoc->GetRoot(), wxT( "pcbDesign" ) );
755
756 if( rootNode )
757 {
758 aNode = FindNode( rootNode, wxT( "layersStackup" ) );
759
760 if( aNode )
761 {
762 aNode = FindNode( aNode, wxT( "layerStackupData" ) );
763
764 while( aNode )
765 {
766 if( aNode->GetName() == wxT( "layerStackupData" ) )
767 {
768 aaNode = FindNode( aNode, wxT( "layerStackupName" ) );
769
770 if( aaNode ) {
771 aaNode->GetAttribute( wxT( "Name" ), &layerName );
772 layerName = layerName.MakeUpper();
773 m_layersStackup.emplace_back( layerName,
774 -1 ); // pcad layer numbers to be fixed later
775 }
776 }
777
778 aNode = aNode->GetNext();
779 }
780 }
781
782 // parse missing layers and numbers
783 aNode = FindNode( rootNode, wxT( "layerDef" ) );
784
785 while( aNode )
786 {
787 if( aNode->GetName().IsSameAs( wxT( "layerDef" ), false ) )
788 {
789 if( FindNode( aNode, wxT( "layerType" ) ) )
790 {
791 long num = -1;
792
793 if( FindNode( aNode, wxT( "layerNum" ) ) )
794 FindNode( aNode, wxT( "layerNum" ) )->GetNodeContent().ToLong( &num );
795
796 layerType = FindNode( aNode, wxT( "layerType" ) )->GetNodeContent().Trim( false );
797 isSignalLayer =
798 layerType.IsSameAs( wxT( "Signal" ), false ) || layerType.IsSameAs( wxT( "Plane" ), false );
799
800 if( num > 0 )
801 {
802 aNode->GetAttribute( wxT( "Name" ), &layerName );
803 layerName = layerName.MakeUpper();
804
805 auto compare = [&layerName]( const auto& el )
806 {
807 return layerName.IsSameAs( el.first, false );
808 };
809
810 if( auto el = std::find_if( m_layersStackup.begin(), m_layersStackup.end(), compare );
811 el != m_layersStackup.end() )
812 {
813 if( isSignalLayer )
814 {
815 el->second = num;
816 }
817 else
818 {
819 // remove layer from stackup if it is not signal layer
820 m_layersStackup.erase( el );
821 }
822 }
823 else
824 {
825 if( isSignalLayer ) // ignore non signal layers
826 {
827 // Stackup defined inside pcad file is incomplete.
828 // We will ignore it and sort layers later preserving original imported behavior
829 stackupIncomplete = true;
830 m_layersStackup.emplace_back( layerName, num );
831 }
832 }
833 }
834 }
835 }
836
837 aNode = aNode->GetNext();
838 }
839
840
841 if( stackupIncomplete )
842 {
843 // Stackup inside pcad file is incomplete, so we;ve added all missing signal layers at the end,
844 // so now ensure that the layers are properly mapped to their order with the bottom
845 // copper (layer 2 in PCAD) at the end
846 std::sort( m_layersStackup.begin(), m_layersStackup.end(),
847 [&]( const std::pair<wxString, long>& a, const std::pair<wxString, long>& b )
848 {
849 long lhs = a.second == 2 ? std::numeric_limits<long>::max() : a.second;
850 long rhs = b.second == 2 ? std::numeric_limits<long>::max() : b.second;
851
852 return lhs < rhs;
853 } );
854 }
855
856 if( m_layersStackup.size() > 32 )
857 THROW_IO_ERROR( _( "KiCad only supports 32 signal layers." ) );
858 }
859}
860
862{
863 PCAD_POLYGON* plane_layer = nullptr;
864
865 for( const auto& [nbr, layer] : m_LayersMap )
866 {
867 if( layer.layerType == LAYER_TYPE_PLANE && layer.hasContent == false )
868 {
869 // fill the polygon with the same contour as its outline is
870 plane_layer = new PCAD_POLYGON( m_callbacks, m_board, nbr );
871 plane_layer->AssignNet( layer.netNameRef );
872 plane_layer->SetOutline( &m_BoardOutline );
873 m_PcbComponents.Add( plane_layer );
874 }
875 }
876}
877
878void PCAD_PCB::ProcessLayerContentsObjects( wxStatusBar* aStatusBar, const wxString& aActualConversion, XNODE* aNode )
879{
880 long num = 0;
881
882 if( FindNode( aNode, wxT( "layerNumRef" ) ) )
883 FindNode( aNode, wxT( "layerNumRef" ) )->GetNodeContent().ToLong( &num );
884
885 if( num <= 0 )
886 return;
887
888 DoLayerContentsObjects( aNode, nullptr, &m_PcbComponents, aStatusBar, m_DefaultMeasurementUnit, aActualConversion );
889
890 m_LayersMap[num].hasContent = true;
891}
892
893void PCAD_PCB::ParseBoard( wxStatusBar* aStatusBar, wxXmlDocument* aXmlDoc, const wxString& aActualConversion )
894{
895 XNODE* aNode; //, *aaNode;
896 PCAD_NET* net;
898 PCAD_FOOTPRINT* footprint;
899 wxString compRef, pinRef;
900 int i, j, netCode;
901
902 // Default measurement units
903 aNode = FindNode( (XNODE*) aXmlDoc->GetRoot(), wxT( "asciiHeader" ) );
904
905 if( aNode )
906 {
907 aNode = FindNode( aNode, wxT( "fileUnits" ) );
908
909 if( aNode )
910 {
911 m_DefaultMeasurementUnit = aNode->GetNodeContent().Lower();
912 m_DefaultMeasurementUnit.Trim( true );
913 m_DefaultMeasurementUnit.Trim( false );
914 }
915 }
916
917 // Determine layers stackup
918 ExtractLayerStackup( aXmlDoc );
919
920 // Layers mapping
921 aNode = FindNode( (XNODE *)aXmlDoc->GetRoot(), wxT( "pcbDesign" ) );
922
923 if( aNode )
924 {
925 aNode = FindNode( aNode, wxT( "layerDef" ) );
926
927 while( aNode )
928 {
929 if( aNode->GetName().IsSameAs( wxT( "layerDef" ), false ) )
930 MapLayer( aNode );
931
932 aNode = aNode->GetNext();
933 }
934 }
935
936 GetBoardOutline( aXmlDoc, aActualConversion );
937
938 // NETLIST
939 // aStatusBar->SetStatusText( wxT( "Loading NETLIST " ) );
940
941 aNode = FindNode( (XNODE *)aXmlDoc->GetRoot(), wxT( "netlist" ) );
942
943 if( aNode )
944 {
945 aNode = FindNode( aNode, wxT( "net" ) );
946
947 netCode = 1;
948
949 while( aNode )
950 {
951 net = new PCAD_NET( netCode++ );
952 net->Parse( aNode );
953 m_PcbNetlist.Add( net );
954
955 aNode = aNode->GetNext();
956 }
957 }
958
959 // BOARD FILE
960 // aStatusBar->SetStatusText( wxT( "Loading BOARD DEFINITION " ) );
961
962 aNode = FindNode( (XNODE *)aXmlDoc->GetRoot(), wxT( "pcbDesign" ) );
963
964 if( aNode )
965 {
966 // COMPONENTS AND OBJECTS
967 aNode = aNode->GetChildren();
968
969 while( aNode )
970 {
971 // Components/footprints
972 if( aNode->GetName().IsSameAs( wxT( "multiLayer" ), false ) )
973 DoPCBComponents( aNode, aXmlDoc, aActualConversion, aStatusBar );
974
975 // objects
976 if( aNode->GetName().IsSameAs( wxT( "layerContents" ), false ) )
977 ProcessLayerContentsObjects( aStatusBar, aActualConversion, aNode );
978
979 aNode = aNode->GetNext();
980 }
981
983
984 // POSTPROCESS -- SET NETLIST REFERENCES
985 // aStatusBar->SetStatusText( wxT( "Processing NETLIST " ) );
986
987 for( i = 0; i < (int) m_PcbNetlist.GetCount(); i++ )
988 {
989 net = m_PcbNetlist[i];
990
991 for( j = 0; j < (int) net->m_NetNodes.GetCount(); j++ )
992 {
993 compRef = net->m_NetNodes[j]->m_CompRef;
994 compRef.Trim( false );
995 compRef.Trim( true );
996 pinRef = net->m_NetNodes[j]->m_PinRef;
997 pinRef.Trim( false );
998 pinRef.Trim( true );
999 ConnectPinToNet( compRef, pinRef, net->m_Name );
1000 }
1001 }
1002
1003 // POSTPROCESS -- FLIP COMPONENTS
1004 for( i = 0; i < (int) m_PcbComponents.GetCount(); i++ )
1005 {
1006 if( m_PcbComponents[i]->m_ObjType == wxT( 'M' ) )
1007 ( (PCAD_FOOTPRINT*) m_PcbComponents[i] )->Flip();
1008 }
1009
1010 // POSTPROCESS -- SET/OPTIMIZE NEW PCB POSITION
1011 // aStatusBar->SetStatusText( wxT( "Optimizing BOARD POSITION " ) );
1012
1013 m_SizeX = 10000000;
1014 m_SizeY = 0;
1015
1016 for( i = 0; i < (int) m_PcbComponents.GetCount(); i++ )
1017 {
1018 comp = m_PcbComponents[i];
1019
1020 if( comp->m_PositionY < m_SizeY )
1021 m_SizeY = comp->m_PositionY; // max Y
1022
1023 if( comp->m_PositionX < m_SizeX && comp->m_PositionX > 0 )
1024 m_SizeX = comp->m_PositionX; // Min X
1025 }
1026
1027 m_SizeY -= 10000;
1028 m_SizeX -= 10000;
1029 // aStatusBar->SetStatusText( wxT( " POSITIONING POSTPROCESS " ) );
1030
1031 for( i = 0; i < (int) m_PcbComponents.GetCount(); i++ )
1033
1034 m_SizeX = 0;
1035 m_SizeY = 0;
1036
1037 for( i = 0; i < (int) m_PcbComponents.GetCount(); i++ )
1038 {
1039 comp = m_PcbComponents[i];
1040
1041 if( comp->m_PositionY < m_SizeY )
1042 m_SizeY = comp->m_PositionY; // max Y
1043
1044 if( comp->m_PositionX > m_SizeX )
1045 m_SizeX = comp->m_PositionX; // Min X
1046 }
1047
1048 // SHEET SIZE CALCULATION
1049 m_SizeY = -m_SizeY; // it is in absolute units
1050 m_SizeX += 10000;
1051 m_SizeY += 10000;
1052
1053 // A4 is minimum $Descr A4 11700 8267
1054 if( m_SizeX < 11700 )
1055 m_SizeX = 11700;
1056
1057 if( m_SizeY < 8267 )
1058 m_SizeY = 8267;
1059 }
1060 else
1061 {
1062 // LIBRARY FILE
1063 // aStatusBar->SetStatusText( wxT( "Processing LIBRARY FILE " ) );
1064
1065 aNode = FindNode( (XNODE *)aXmlDoc->GetRoot(), wxT( "library" ) );
1066
1067 if( aNode )
1068 {
1069 aNode = FindNode( aNode, wxT( "compDef" ) );
1070
1071 while( aNode )
1072 {
1073 // aStatusBar->SetStatusText( wxT( "Processing COMPONENTS " ) );
1074
1075 if( aNode->GetName().IsSameAs( wxT( "compDef" ), false ) )
1076 {
1077 footprint = new PCAD_FOOTPRINT( this, m_board );
1078 footprint->Parse( aNode, aStatusBar, m_DefaultMeasurementUnit,
1079 aActualConversion );
1080 m_PcbComponents.Add( footprint );
1081 }
1082
1083 aNode = aNode->GetNext();
1084 }
1085 }
1086 }
1087}
1088
1089
1091{
1092 int i;
1093 PCAD_NET* net;
1094
1095 m_board->SetCopperLayerCount( m_layersStackup.size() );
1096
1097 for( i = 0; i < (int) m_PcbNetlist.GetCount(); i++ )
1098 {
1099 net = m_PcbNetlist[i];
1100
1101 m_board->Add( new NETINFO_ITEM( m_board, net->m_Name, net->m_NetCode ) );
1102 }
1103
1104 for( i = 0; i < (int) m_PcbComponents.GetCount(); i++ )
1105 {
1106 m_PcbComponents[i]->AddToBoard();
1107 }
1108}
1109
1110} // namespace PCAD2KICAD
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:372
Handle the data for a net.
Definition netinfo.h:46
PCAD_FOOTPRINT(PCAD_CALLBACKS *aCallbacks, BOARD *aBoard)
void DoLayerContentsObjects(XNODE *aNode, PCAD_FOOTPRINT *aFootprint, PCAD_COMPONENTS_ARRAY *aList, wxStatusBar *aStatusBar, const wxString &aDefaultMeasurementUnit, const wxString &aActualConversion)
PCAD_COMPONENTS_ARRAY m_FootprintItems
XNODE * FindModulePatternDefName(XNODE *aNode, const wxString &aName)
void SetName(const wxString &aPin, const wxString &aName)
virtual void Parse(XNODE *aNode, wxStatusBar *aStatusBar, const wxString &aDefaultMeasurementUnit, const wxString &aActualConversion)
virtual bool Parse(XNODE *aNode, const wxString &aDefaultMeasurementUnit, const wxString &aActualConversion) override
PCAD_NET_NODES_ARRAY m_NetNodes
Definition pcad_nets.h:58
void Parse(XNODE *aNode)
Definition pcad_nets.cpp:89
virtual void SetPosOffset(int aX_offs, int aY_offs)
wxString m_DefaultMeasurementUnit
Definition pcad_pcb.h:82
void SetTextProperty(XNODE *aNode, TTEXTVALUE *aTextValue, const wxString &aPatGraphRefName, const wxString &aXmlName, const wxString &aActualConversion)
Definition pcad_pcb.cpp:178
void DoPCBComponents(XNODE *aNode, wxXmlDocument *aXmlDoc, const wxString &aActualConversion, wxStatusBar *aStatusBar)
Definition pcad_pcb.cpp:247
LAYER_TYPE_T GetLayerType(int aPCadLayer) const override
Definition pcad_pcb.cpp:50
void ExtractOutlinePointsFromEnhancedPolygon(const wxString &aActualConversion, XNODE *lNode)
Definition pcad_pcb.cpp:619
int GetNetCode(const wxString &aNetName) const override
Definition pcad_pcb.cpp:133
std::map< int, TLAYER > m_LayersMap
Definition pcad_pcb.h:83
void ProcessLayerContentsObjects(wxStatusBar *aStatusBar, const wxString &aActualConversion, XNODE *aNode)
Definition pcad_pcb.cpp:878
void MapLayer(XNODE *aNode)
Definition pcad_pcb.cpp:489
wxString GetLayerNetNameRef(int aPCadLayer) const override
Definition pcad_pcb.cpp:61
PCAD_NETS_ARRAY m_PcbNetlist
Definition pcad_pcb.h:81
int FindOutlinePoint(const VERTICES_ARRAY *aOutline, wxRealPoint aPoint) const
Definition pcad_pcb.cpp:599
PCAD_COMPONENTS_ARRAY m_PcbComponents
Definition pcad_pcb.h:80
void ExtractLayerStackup(wxXmlDocument *aXmlDoc)
Definition pcad_pcb.cpp:745
std::vector< std::pair< wxString, long > > m_layersStackup
Definition pcad_pcb.h:88
void ParseBoard(wxStatusBar *aStatusBar, wxXmlDocument *aXmlDoc, const wxString &aActualConversion)
Definition pcad_pcb.cpp:893
XNODE * FindCompDefName(XNODE *aNode, const wxString &aName) const
Definition pcad_pcb.cpp:150
PCAD_PCB(BOARD *aBoard)
Definition pcad_pcb.cpp:72
int FindLayer(const wxString &aLayerName) const
Definition pcad_pcb.cpp:464
void ConnectPinToNet(const wxString &aCr, const wxString &aPr, const wxString &aNetName)
Definition pcad_pcb.cpp:436
void AddToBoard(FOOTPRINT *aFootprint=nullptr) override
void GetBoardOutline(wxXmlDocument *aXmlDoc, const wxString &aActualConversion)
Definition pcad_pcb.cpp:646
void CreatePolygonsForEmptyPowerPlanes()
Definition pcad_pcb.cpp:861
double GetDistance(const wxRealPoint *aPoint1, const wxRealPoint *aPoint2) const
Definition pcad_pcb.cpp:613
void SetOutline(VERTICES_ARRAY *aOutline)
void AssignNet(const wxString &aNetName)
An extension of wxXmlNode that can format its contents as KiCad-style s-expressions.
Definition xnode.h:67
XNODE * GetParent() const
Definition xnode.h:107
XNODE * GetChildren() const
Definition xnode.h:97
XNODE * GetNext() const
Definition xnode.h:102
The common library.
#define _(s)
@ TENTHS_OF_A_DEGREE_T
Definition eda_angle.h:30
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
@ Edge_Cuts
Definition layer_ids.h:108
@ Dwgs_User
Definition layer_ids.h:103
@ F_Paste
Definition layer_ids.h:100
@ B_Mask
Definition layer_ids.h:94
@ B_Cu
Definition layer_ids.h:61
@ F_Mask
Definition layer_ids.h:93
@ B_Paste
Definition layer_ids.h:101
@ F_Fab
Definition layer_ids.h:115
@ F_SilkS
Definition layer_ids.h:96
@ UNDEFINED_LAYER
Definition layer_ids.h:57
@ User_1
Definition layer_ids.h:120
@ B_SilkS
Definition layer_ids.h:97
@ F_Cu
Definition layer_ids.h:60
@ B_Fab
Definition layer_ids.h:114
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition lset.cpp:750
wxString ValidateName(const wxString &aName)
int StrToInt1Units(const wxString &aStr)
XNODE * FindNode(XNODE *aChild, const wxString &aTag)
void SetPosition(const wxString &aStr, const wxString &aDefaultMeasurementUnit, int *aX, int *aY, const wxString &aActualConversion)
XNODE * FindPinMap(XNODE *aNode)
wxString ConvertNetName(const wxString &aName)
Definition pcad_nets.cpp:32
wxString FindNodeGetContent(XNODE *aChild, const wxString &aTag)
void SetTextParameters(XNODE *aNode, TTEXTVALUE *aTextValue, const wxString &aDefaultMeasurementUnit, const wxString &aActualConversion)
LAYER_TYPE_T
@ LAYER_TYPE_NONSIGNAL
@ LAYER_TYPE_PLANE
@ LAYER_TYPE_SIGNAL
static float distance(const SFVEC2UI &a, const SFVEC2UI &b)
bool hasContent
LAYER_TYPE_T layerType
PCB_LAYER_ID KiCadLayer
wxString netNameRef
KIBIS_COMPONENT * comp
wxString result
Test unit parsing edge cases and error handling.