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