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