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