KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcb_io_easyeda_parser.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) 2023 Alex Shvartzkop <[email protected]>
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
26
27#include <memory>
28
29#include <nlohmann/json.hpp>
30#include <core/map_helpers.h>
32#include <string_utils.h>
33
34#include <wx/log.h>
35
36#include <font/font.h>
37#include <footprint.h>
38#include <progress_reporter.h>
39#include <board.h>
41#include <bezier_curves.h>
42#include <pcb_group.h>
43#include <pcb_track.h>
44#include <pcb_shape.h>
45#include <pcb_text.h>
46#include <zone.h>
47#include <pad.h>
48#include <project.h>
49#include <fix_board_shape.h>
50
51
52static const wxString DIRECT_MODEL_UUID_KEY = wxS( "JLC_3DModel" );
53static const wxString MODEL_SIZE_KEY = wxS( "JLC_3D_Size" );
54
55static const int SHAPE_JOIN_DISTANCE = pcbIUScale.mmToIU( 1.5 );
57
58
60{
61}
62
64{
65}
66
68{
69 int elayer = wxAtoi( aLayer );
70
71 switch( elayer )
72 {
73 case 1: return F_Cu;
74 case 2: return B_Cu;
75 case 3: return F_SilkS;
76 case 4: return B_SilkS;
77 case 5: return F_Paste;
78 case 6: return B_Paste;
79 case 7: return F_Mask;
80 case 8: return B_Mask;
81 /*case 9: return UNDEFINED_LAYER;*/ // Ratsnest
82 case 10: return Edge_Cuts;
83 case 11: return Eco1_User;
84 case 12: return Dwgs_User;
85 case 13: return F_Fab;
86 case 14: return B_Fab;
87 case 15: return Eco2_User;
88
89 case 19: return User_2; // 3D model
90
91 case 21: return In1_Cu;
92 case 22: return In2_Cu;
93 case 23: return In3_Cu;
94 case 24: return In4_Cu;
95 case 25: return In5_Cu;
96 case 26: return In6_Cu;
97 case 27: return In7_Cu;
98 case 28: return In8_Cu;
99 case 29: return In9_Cu;
100 case 30: return In10_Cu;
101 case 31: return In11_Cu;
102 case 32: return In12_Cu;
103 case 33: return In13_Cu;
104 case 34: return In14_Cu;
105 case 35: return In15_Cu;
106 case 36: return In16_Cu;
107 case 37: return In17_Cu;
108 case 38: return In18_Cu;
109 case 39: return In19_Cu;
110 case 40: return In20_Cu;
111 case 41: return In21_Cu;
112 case 42: return In22_Cu;
113 case 43: return In23_Cu;
114 case 44: return In24_Cu;
115 case 45: return In25_Cu;
116 case 46: return In26_Cu;
117 case 47: return In27_Cu;
118 case 48: return In28_Cu;
119 case 49: return In29_Cu;
120 case 50: return In30_Cu;
121
122 case 99: return User_3;
123 case 100: return User_4;
124 case 101: return User_5;
125
126 default: break;
127 }
128
129 return User_1;
130}
131
132
133static LIB_ID EasyEdaToKiCadLibID( const wxString& aLibName, const wxString& aLibReference )
134{
135 wxString libReference = EscapeString( aLibReference, CTX_LIBID );
136
137 wxString key = !aLibName.empty() ? ( aLibName + ':' + libReference ) : libReference;
138
139 LIB_ID libId;
140 libId.Parse( key, true );
141
142 return libId;
143}
144
145
147 BOARD_ITEM_CONTAINER* aContainer, BOARD* aParent, std::map<wxString, wxString> paramMap,
148 std::map<wxString, std::unique_ptr<FOOTPRINT>>& aFootprintMap, wxArrayString aShapes )
149{
150 // TODO: make this path configurable?
151 const wxString easyedaModelDir = wxS( "EASYEDA_MODELS" );
152 wxString kicadModelPrefix = wxS( "${KIPRJMOD}/" ) + easyedaModelDir + wxS( "/" );
153
154 BOARD* board = aParent ? aParent : dynamic_cast<BOARD*>( aContainer );
155 FOOTPRINT* footprint = dynamic_cast<FOOTPRINT*>( aContainer );
156
157 auto getOrAddNetItem = [&]( const wxString& aNetName ) -> NETINFO_ITEM*
158 {
159 if( !board )
160 return nullptr;
161
162 if( aNetName.empty() )
163 return nullptr;
164
165 if( NETINFO_ITEM* item = board->FindNet( aNetName ) )
166 {
167 return item;
168 }
169 else
170 {
171 item = new NETINFO_ITEM( board, aNetName, board->GetNetCount() + 1 );
172 board->Add( item, ADD_MODE::APPEND );
173 return item;
174 }
175 };
176
177 if( footprint )
178 {
179 // TODO: library name
180 LIB_ID fpID = EasyEdaToKiCadLibID( wxEmptyString, paramMap[wxS( "package" )] );
181 footprint->SetFPID( fpID );
182 }
183
184 for( wxString shape : aShapes )
185 {
186 wxArrayString arr = wxSplit( shape, '~', '\0' );
187
188 wxString elType = arr[0];
189 if( elType == wxS( "LIB" ) )
190 {
191 shape.Replace( wxS( "#@$" ), "\n" );
192 wxArrayString parts = wxSplit( shape, '\n', '\0' );
193
194 if( parts.size() < 1 )
195 continue;
196
197 wxArrayString paramsRoot = wxSplit( parts[0], '~', '\0' );
198
199 if( paramsRoot.size() < 4 )
200 continue;
201
202 VECTOR2D fpOrigin( Convert( paramsRoot[1] ), Convert( paramsRoot[2] ) );
203
204 wxString packageName =
205 wxString::Format( wxS( "Unknown_%s_%s" ), paramsRoot[1], paramsRoot[2] );
206
207 wxArrayString paramParts = wxSplit( paramsRoot[3], '`', '\0' );
208
209 EDA_ANGLE orientation;
210 if( !paramsRoot[4].IsEmpty() )
211 orientation = EDA_ANGLE( Convert( paramsRoot[4] ), DEGREES_T ); // Already applied
212
213 int layer = 1;
214
215 if( !paramsRoot[7].IsEmpty() )
216 layer = Convert( paramsRoot[7] );
217
218 std::map<wxString, wxString> paramMap;
219
220 for( int i = 1; i < paramParts.size(); i += 2 )
221 {
222 wxString key = paramParts[i - 1];
223 wxString value = paramParts[i];
224
225 if( key == wxS( "package" ) )
226 packageName = value;
227
228 paramMap[key] = value;
229 }
230
231 parts.RemoveAt( 0 );
232
233 VECTOR2D pcbOrigin = m_relOrigin;
234 FOOTPRINT* fp = ParseFootprint( fpOrigin, orientation, layer, board, paramMap,
235 aFootprintMap, parts );
236
237 if( !fp )
238 continue;
239
240 m_relOrigin = pcbOrigin;
241
242 fp->Move( RelPos( fpOrigin ) );
243
244 aContainer->Add( fp, ADD_MODE::APPEND );
245 }
246 else if( elType == wxS( "TRACK" ) )
247 {
248 double width = ConvertSize( arr[1] );
249 PCB_LAYER_ID layer = LayerToKi( arr[2] );
250 wxString netname = arr[3];
251 wxArrayString data = wxSplit( arr[4], ' ', '\0' );
252
253 for( int i = 3; i < data.size(); i += 2 )
254 {
255 VECTOR2D start, end;
256 start.x = RelPosX( data[i - 3] );
257 start.y = RelPosY( data[i - 2] );
258 end.x = RelPosX( data[i - 1] );
259 end.y = RelPosY( data[i] );
260
261 if( !footprint && IsCopperLayer( layer ) )
262 {
263 std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>( aContainer );
264
265 track->SetLayer( layer );
266 track->SetWidth( width );
267 track->SetStart( start );
268 track->SetEnd( end );
269 track->SetNet( getOrAddNetItem( netname ) );
270
271 aContainer->Add( track.release(), ADD_MODE::APPEND );
272 }
273 else
274 {
275 std::unique_ptr<PCB_SHAPE> seg =
276 std::make_unique<PCB_SHAPE>( aContainer, SHAPE_T::SEGMENT );
277
278 seg->SetLayer( layer );
279 seg->SetWidth( width );
280 seg->SetStart( start );
281 seg->SetEnd( end );
282
283 aContainer->Add( seg.release(), ADD_MODE::APPEND );
284 }
285 }
286 }
287 else if( elType == wxS( "CIRCLE" ) )
288 {
289 auto shape = std::make_unique<PCB_SHAPE>( aContainer, SHAPE_T::CIRCLE );
290 double width = ConvertSize( arr[4] );
291 shape->SetWidth( width );
292
293 PCB_LAYER_ID layer = LayerToKi( arr[5] );
294 shape->SetLayer( layer );
295
297 center.x = RelPosX( arr[1] );
298 center.y = RelPosY( arr[2] );
299
300 double radius = ConvertSize( arr[3] );
301
302 shape->SetCenter( center );
303 shape->SetEnd( center + VECTOR2I( radius, 0 ) );
304
305 if( IsCopperLayer( layer ) )
306 shape->SetNet( getOrAddNetItem( arr[8] ) );
307
308 aContainer->Add( shape.release(), ADD_MODE::APPEND );
309 }
310 else if( elType == wxS( "RECT" ) )
311 {
312 auto shape = std::make_unique<PCB_SHAPE>( aContainer, SHAPE_T::RECTANGLE );
313 double width = ConvertSize( arr[8] );
314 shape->SetWidth( width );
315
316 PCB_LAYER_ID layer = LayerToKi( arr[5] );
317 shape->SetLayer( layer );
318
319 bool filled = arr[9] != wxS( "none" );
320 shape->SetFilled( filled );
321
322 VECTOR2D start;
323 start.x = RelPosX( arr[1] );
324 start.y = RelPosY( arr[2] );
325
326 VECTOR2D size;
327 size.x = ConvertSize( arr[3] );
328 size.y = ConvertSize( arr[4] );
329
330 shape->SetStart( start );
331 shape->SetEnd( start + size );
332
333 if( IsCopperLayer( layer ) )
334 shape->SetNet( getOrAddNetItem( arr[11] ) );
335
336 aContainer->Add( shape.release(), ADD_MODE::APPEND );
337 }
338 else if( elType == wxS( "ARC" ) )
339 {
340 std::unique_ptr<PCB_SHAPE> shape =
341 std::make_unique<PCB_SHAPE>( aContainer, SHAPE_T::ARC );
342
343 double width = ConvertSize( arr[1] );
344 shape->SetWidth( width );
345
346 PCB_LAYER_ID layer = LayerToKi( arr[2] );
347 shape->SetLayer( layer );
348
349 if( IsCopperLayer( layer ) )
350 shape->SetNet( getOrAddNetItem( arr[3] ) );
351
352 VECTOR2D start, end;
353 VECTOR2D rad( 10, 10 );
354 bool isFar = false;
355 bool cw = false;
356
357 int pos = 0;
358 wxString data = arr[4];
359 auto readNumber = [&]( wxString& aOut )
360 {
361 wxUniChar ch = data[pos];
362
363 while( ch == ' ' || ch == ',' )
364 ch = data[++pos];
365
366 while( isdigit( ch ) || ch == '.' || ch == '-' )
367 {
368 aOut += ch;
369 pos++;
370
371 if( pos == data.size() )
372 break;
373
374 ch = data[pos];
375 }
376 };
377
378 do
379 {
380 wxUniChar sym = data[pos++];
381
382 if( sym == 'M' )
383 {
384 wxString xStr, yStr;
385 readNumber( xStr );
386 readNumber( yStr );
387
388 start = VECTOR2D( Convert( xStr ), Convert( yStr ) );
389 }
390 else if( sym == 'A' )
391 {
392 wxString radX, radY, unknown, farFlag, cwFlag, endX, endY;
393 readNumber( radX );
394 readNumber( radY );
395 readNumber( unknown );
396 readNumber( farFlag );
397 readNumber( cwFlag );
398 readNumber( endX );
399 readNumber( endY );
400
401 isFar = farFlag == wxS( "1" );
402 cw = cwFlag == wxS( "1" );
403 rad = VECTOR2D( Convert( radX ), Convert( radY ) );
404 end = VECTOR2D( Convert( endX ), Convert( endY ) );
405 }
406 } while( pos < data.size() );
407
408 VECTOR2D delta = end - start;
409
410 double d = delta.EuclideanNorm();
411 double h = sqrt( std::max( 0.0, rad.x * rad.x - d * d / 4 ) );
412
413 //( !far && cw ) => h
414 //( far && cw ) => -h
415 //( !far && !cw ) => -h
416 //( far && !cw ) => h
417 VECTOR2D arcCenter =
418 start + delta / 2 + delta.Perpendicular().Resize( ( isFar ^ cw ) ? h : -h );
419
420 if( !cw )
421 std::swap( start, end );
422
423 shape->SetStart( RelPos( start ) );
424 shape->SetEnd( RelPos( end ) );
425 shape->SetCenter( RelPos( arcCenter ) );
426
427 aContainer->Add( shape.release(), ADD_MODE::APPEND );
428 }
429 else if( elType == wxS( "DIMENSION" ) )
430 {
431 PCB_LAYER_ID layer = LayerToKi( arr[1] );
432 double lineWidth = ConvertSize( arr[7] );
433 wxString shapeData = arr[2].Trim();
434 //double textHeight = !arr[4].IsEmpty() ? ConvertSize( arr[4] ) : 0;
435
436 std::vector<SHAPE_LINE_CHAIN> lineChains =
437 ParseLineChains( shapeData, pcbIUScale.mmToIU( 0.01 ), false );
438
439 std::unique_ptr<PCB_GROUP> group = std::make_unique<PCB_GROUP>( aContainer );
440 group->SetName( wxS( "Dimension" ) );
441
442 for( const SHAPE_LINE_CHAIN& chain : lineChains )
443 {
444 for( int segId = 0; segId < chain.SegmentCount(); segId++ )
445 {
446 SEG seg = chain.CSegment( segId );
447 auto shape = std::make_unique<PCB_SHAPE>( aContainer, SHAPE_T::SEGMENT );
448
449 shape->SetLayer( layer );
450 shape->SetWidth( lineWidth );
451 shape->SetStart( seg.A );
452 shape->SetEnd( seg.B );
453
454 group->AddItem( shape.get() );
455
456 aContainer->Add( shape.release(), ADD_MODE::APPEND );
457 }
458 }
459
460 aContainer->Add( group.release(), ADD_MODE::APPEND );
461 }
462 else if( elType == wxS( "SOLIDREGION" ) )
463 {
464 wxString layer = arr[1];
465
466 SHAPE_POLY_SET polySet =
467 ParseLineChains( arr[3].Trim(), pcbIUScale.mmToIU( 0.01 ), true );
468
469 if( layer == wxS( "11" ) ) // Multi-layer (board cutout)
470 {
471 for( const SHAPE_POLY_SET::POLYGON& poly : polySet.CPolygons() )
472 {
473 auto shape = std::make_unique<PCB_SHAPE>( aContainer, SHAPE_T::POLY );
474
475 shape->SetLayer( Edge_Cuts );
476 shape->SetFilled( false );
477 shape->SetWidth( pcbIUScale.mmToIU( 0.1 ) );
478 shape->SetPolyShape( poly );
479
480 aContainer->Add( shape.release(), ADD_MODE::APPEND );
481 }
482 }
483 else
484 {
485 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aContainer );
486
487 PCB_LAYER_ID klayer = LayerToKi( layer );
488 zone->SetLayer( klayer );
489
490 if( IsCopperLayer( klayer ) )
491 zone->SetNet( getOrAddNetItem( arr[2] ) );
492
493 for( const SHAPE_POLY_SET::POLYGON& poly : polySet.CPolygons() )
494 zone->Outline()->AddPolygon( poly );
495
496 if( arr[4].Lower() == wxS( "cutout" ) )
497 {
498 zone->SetIsRuleArea( true );
499 zone->SetDoNotAllowCopperPour( true );
500 zone->SetDoNotAllowTracks( false );
501 zone->SetDoNotAllowVias( false );
502 zone->SetDoNotAllowPads( false );
503 zone->SetDoNotAllowFootprints( false );
504 }
505 else
506 { // solid
507 zone->SetFilledPolysList( klayer, polySet );
508 zone->SetPadConnection( ZONE_CONNECTION::FULL );
509 zone->SetIsFilled( true );
510 zone->SetNeedRefill( false );
511 }
512
513 zone->SetMinThickness( 0 );
514 zone->SetLocalClearance( 0 );
515 zone->SetAssignedPriority( 100 );
516
517 aContainer->Add( zone.release(), ADD_MODE::APPEND );
518 }
519 }
520 else if( elType == wxS( "COPPERAREA" ) )
521 {
522 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aContainer );
523
524 PCB_LAYER_ID layer = LayerToKi( arr[2] );
525 zone->SetLayer( layer );
526
527 wxString netname = arr[3];
528
529 if( IsCopperLayer( layer ) )
530 zone->SetNet( getOrAddNetItem( netname ) );
531
532 zone->SetLocalClearance( ConvertSize( arr[5] ) );
533 zone->SetThermalReliefGap( zone->GetLocalClearance().value() );
534
535 wxString fillStyle = arr[5];
536 if( fillStyle == wxS( "none" ) )
537 {
538 // Do not fill?
539 }
540
541 SHAPE_POLY_SET polySet =
542 ParseLineChains( arr[4].Trim(), pcbIUScale.mmToIU( 0.01 ), true );
543
544 for( const SHAPE_POLY_SET::POLYGON& poly : polySet.CPolygons() )
545 zone->Outline()->AddPolygon( poly );
546
547 wxString thermal = arr[8];
548 if( thermal == wxS( "direct" ) )
549 zone->SetPadConnection( ZONE_CONNECTION::FULL );
550
551 wxString keepIsland = arr[9];
552 if( keepIsland == wxS( "yes" ) )
553 zone->SetIslandRemovalMode( ISLAND_REMOVAL_MODE::NEVER );
554
555 wxString fillData = arr[10];
556 SHAPE_POLY_SET fillPolySet;
557 try
558 {
559 for( const nlohmann::json& polyData : nlohmann::json::parse( fillData ) )
560 {
561 for( const nlohmann::json& contourData : polyData )
562 {
563 SHAPE_POLY_SET contourPolySet = ParseLineChains(
564 contourData.get<wxString>(), pcbIUScale.mmToIU( 0.01 ), true );
565
566 SHAPE_POLY_SET currentOutline( contourPolySet.COutline( 0 ) );
567
568 for( int i = 1; i < contourPolySet.OutlineCount(); i++ )
569 currentOutline.AddHole( contourPolySet.COutline( i ) );
570
571 fillPolySet.Append( currentOutline );
572 }
573 }
574
575 fillPolySet.Fracture();
576
577 zone->SetFilledPolysList( layer, fillPolySet );
578 zone->SetIsFilled( true );
579 zone->SetNeedRefill( false );
580 }
581 catch( nlohmann::json::exception& e )
582 {
583 }
584
585 int fillOrder = wxAtoi( arr[13] );
586 zone->SetAssignedPriority( 100 - fillOrder );
587
588 wxString improveFabrication = arr[17];
589 if( improveFabrication == wxS( "none" ) )
590 {
591 zone->SetMinThickness( 0 );
592 }
593 else
594 {
595 // arr[1] is "stroke Width" per docs
596 int minThickness = std::max( pcbIUScale.mmToIU( 0.03 ),
597 int( ConvertSize( arr[1] ) ) );
598 zone->SetMinThickness( minThickness );
599 }
600
601 if( arr.size() > 18 )
602 {
603 zone->SetThermalReliefSpokeWidth( std::max( int( ConvertSize( arr[18] ) ),
604 zone->GetMinThickness() ) );
605 }
606 else
607 {
608 wxFAIL_MSG( wxString::Format( "COPPERAREA unexpected size %d: %s ",
609 arr.size(),
610 shape ) );
611
612 zone->SetThermalReliefSpokeWidth( zone->GetMinThickness() );
613 }
614
615 aContainer->Add( zone.release(), ADD_MODE::APPEND );
616 }
617 else if( elType == wxS( "SVGNODE" ) )
618 {
619 nlohmann::json nodeData = nlohmann::json::parse( arr[1] );
620
621 int nodeType = nodeData.at( "nodeType" );
622 wxString layer = nodeData.at( "layerid" );
623 PCB_LAYER_ID klayer = LayerToKi( layer );
624
625 if( nodeType == 1 )
626 {
627 std::map<wxString, wxString> attributes = nodeData.at( "attrs" );
628
629 if( layer == wxS( "19" ) ) // 3DModel
630 {
631 if( !footprint )
632 continue;
633
634 auto ec_eType = get_opt( attributes, "c_etype" );
635 auto ec_rotation = get_opt( attributes, "c_rotation" );
636 auto ec_origin = get_opt( attributes, "c_origin" );
637 auto ec_width = get_opt( attributes, "c_width" );
638 auto ec_height = get_opt( attributes, "c_height" );
639 auto ez = get_opt( attributes, "z" );
640 auto etitle = get_opt( attributes, "title" );
641 auto euuid = get_opt( attributes, "uuid" );
642 auto etransform = get_opt( attributes, "transform" );
643
644 if( !ec_eType || *ec_eType != wxS( "outline3D" ) || !etitle )
645 continue;
646
647 wxString modelTitle = *etitle;
648 VECTOR3D kmodelOffset;
649 VECTOR3D kmodelRotation;
650
651 if( euuid )
652 {
653 PCB_FIELD* field = new PCB_FIELD( footprint, FIELD_T::USER,
655 field->SetLayer( Cmts_User );
656 field->SetVisible( false );
657 field->SetText( *euuid );
658 footprint->Add( field );
659 }
660
661 /*if( etransform )
662 {
663 PCB_FIELD* field = new PCB_FIELD( footprint, FIELD_T::USER,
664 "3D Transform" );
665 field->SetLayer( Cmts_User );
666 field->SetVisible( false );
667 field->SetText( *etransform );
668 footprint->Add( field );
669 }*/
670
671 if( ec_width && ec_height )
672 {
673 double fitXmm = pcbIUScale.IUTomm( ScaleSize( Convert( *ec_width ) ) );
674 double fitYmm = pcbIUScale.IUTomm( ScaleSize( Convert( *ec_height ) ) );
675
676 double rounding = 0.001;
677 fitXmm = KiROUND( fitXmm / rounding ) * rounding;
678 fitYmm = KiROUND( fitYmm / rounding ) * rounding;
679
680 PCB_FIELD* field = new PCB_FIELD( footprint, FIELD_T::USER,
682 field->SetLayer( Cmts_User );
683 field->SetVisible( false );
684 field->SetText( wxString::FromCDouble( fitXmm ) + wxS( " " )
685 + wxString::FromCDouble( fitYmm ) );
686 footprint->Add( field );
687 }
688
689 if( ec_origin )
690 {
691 wxArrayString orParts = wxSplit( *ec_origin, ',', '\0' );
692
693 if( orParts.size() == 2 )
694 {
695 VECTOR2D pos;
696 pos.x = Convert( orParts[0].Trim() );
697 pos.y = Convert( orParts[1].Trim() );
698
699 VECTOR2D rel = RelPos( pos );
700 kmodelOffset.x = -pcbIUScale.IUTomm( rel.x );
701 kmodelOffset.y = -pcbIUScale.IUTomm( rel.y );
702
703 RotatePoint( &kmodelOffset.x, &kmodelOffset.y,
704 -footprint->GetOrientation() );
705 }
706 }
707
708 if( ez )
709 {
710 kmodelOffset.z = pcbIUScale.IUTomm( ScaleSize( Convert( ez->Trim() ) ) );
711 }
712
713 if( ec_rotation )
714 {
715 wxArrayString rotParts = wxSplit( *ec_rotation, ',', '\0' );
716
717 if( rotParts.size() == 3 )
718 {
719 kmodelRotation.x = -Convert( rotParts[0].Trim() );
720 kmodelRotation.y = -Convert( rotParts[1].Trim() );
721 kmodelRotation.z = -Convert( rotParts[2].Trim() )
722 + footprint->GetOrientationDegrees();
723 }
724 }
725
726 if( footprint->GetLayer() == B_Cu )
727 {
728 kmodelRotation.z = 180 - kmodelRotation.z;
729 RotatePoint( &kmodelOffset.x, &kmodelOffset.y, ANGLE_180 );
730 }
731
732 FP_3DMODEL model;
733 model.m_Filename = kicadModelPrefix
734 + EscapeString( modelTitle, ESCAPE_CONTEXT::CTX_FILENAME )
735 + wxS( ".step" );
736 model.m_Offset = kmodelOffset;
737 model.m_Rotation = kmodelRotation;
738 footprint->Models().push_back( model );
739 }
740 else
741 {
742 if( auto dataStr = get_opt( attributes, "d" ) )
743 {
744 int minSegLen = dataStr->size() < 8000 ? pcbIUScale.mmToIU( 0.005 )
745 : pcbIUScale.mmToIU( 0.05 );
746
747 SHAPE_POLY_SET polySet =
748 ParseLineChains( dataStr->Trim(), minSegLen, true );
749
750 polySet.RebuildHolesFromContours();
751
752 std::unique_ptr<PCB_GROUP> group;
753
754 if( polySet.OutlineCount() > 1 )
755 group = std::make_unique<PCB_GROUP>( aContainer );
756
757 for( const SHAPE_POLY_SET::POLYGON& poly : polySet.CPolygons() )
758 {
759 auto shape = std::make_unique<PCB_SHAPE>( aContainer, SHAPE_T::POLY );
760
761 shape->SetFilled( true );
762 shape->SetPolyShape( poly );
763 shape->SetLayer( klayer );
764 shape->SetWidth( 0 );
765
766 if( group )
767 group->AddItem( shape.get() );
768
769 aContainer->Add( shape.release(), ADD_MODE::APPEND );
770 }
771
772 if( group )
773 aContainer->Add( group.release(), ADD_MODE::APPEND );
774 }
775 }
776 }
777 else
778 {
779 THROW_IO_ERROR( wxString::Format( _( "Unknown SVGNODE nodeType %d" ), nodeType ) );
780 }
781 }
782 else if( elType == wxS( "TEXT" ) )
783 {
784 PCB_TEXT* text;
785 wxString textType = arr[1];
786
787 if( footprint && textType == wxS( "P" ) )
788 {
789 text = footprint->GetField( FIELD_T::REFERENCE );
790 }
791 else if( footprint && textType == wxS( "N" ) )
792 {
793 text = footprint->GetField( FIELD_T::VALUE );
794 }
795 else if( arr[12] == wxS( "none" ) )
796 {
797 text = new PCB_FIELD( aContainer, FIELD_T::USER );
798 static_cast<PCB_FIELD*>( text )->SetVisible( false );
799 }
800 else
801 {
802 text = new PCB_TEXT( aContainer );
803 aContainer->Add( text, ADD_MODE::APPEND );
804 }
805
806 VECTOR2D start;
807 start.x = RelPosX( arr[2] );
808 start.y = RelPosY( arr[3] );
809 text->SetPosition( start );
810
811 double thickness = ConvertSize( arr[4] );
812 text->SetTextThickness( thickness );
813
814 double rot = Convert( arr[5] );
815 text->SetTextAngleDegrees( rot );
816
817 text->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
818 text->SetVertJustify( GR_TEXT_V_ALIGN_TOP );
819
820 PCB_LAYER_ID layer = LayerToKi( arr[7] );
821 text->SetLayer( layer );
822
823 if( IsBackLayer( layer ) )
824 text->SetMirrored( true );
825
826 double height = ConvertSize( arr[9] ) * 0.8;
827 text->SetTextSize( VECTOR2I( height, height ) );
828
829 wxString textStr = arr[10];
830 textStr.Replace( wxS( "\\n" ), wxS( "\n" ) );
831 text->SetText( UnescapeHTML( textStr ) );
832
833 //arr[11] // Geometry data
834
835 wxString font = arr[14];
836 if( !font.IsEmpty() )
837 text->SetFont( KIFONT::FONT::GetFont( font ) );
838
839 TransformTextToBaseline( text, wxEmptyString );
840 }
841 else if( elType == wxS( "VIA" ) )
842 {
843 VECTOR2D center( RelPosX( arr[1] ), RelPosY( arr[2] ) );
844 int kdia = ConvertSize( arr[3] );
845 int kdrill = ConvertSize( arr[5] ) * 2;
846
847 if( footprint )
848 {
849 std::unique_ptr<PAD> pad = std::make_unique<PAD>( footprint );
850
851 pad->SetPosition( center );
852 pad->SetLayerSet( PAD::PTHMask() );
853 pad->SetAttribute( PAD_ATTRIB::PTH );
854 pad->SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::CIRCLE );
855 pad->SetSize( PADSTACK::ALL_LAYERS, VECTOR2I( kdia, kdia ) );
856 pad->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
857 pad->SetDrillSize( VECTOR2I( kdrill, kdrill ) );
858
859 footprint->Add( pad.release(), ADD_MODE::APPEND );
860 }
861 else
862 {
863 std::unique_ptr<PCB_VIA> via = std::make_unique<PCB_VIA>( aContainer );
864
865 via->SetPosition( center );
866
867 via->SetWidth( PADSTACK::ALL_LAYERS, kdia );
868 via->SetNet( getOrAddNetItem( arr[4] ) );
869 via->SetDrill( kdrill );
870
871 aContainer->Add( via.release(), ADD_MODE::APPEND );
872 }
873 }
874 else if( elType == wxS( "HOLE" ) )
875 {
876 FOOTPRINT* padContainer;
877
878 VECTOR2D center( RelPosX( arr[1] ), RelPosY( arr[2] ) );
879 int kdia = ConvertSize( arr[3] ) * 2;
880 wxString holeUuid = arr[4];
881
882 if( footprint )
883 {
884 padContainer = footprint;
885 }
886 else
887 {
888 std::unique_ptr<FOOTPRINT> newFootprint =
889 std::make_unique<FOOTPRINT>( dynamic_cast<BOARD*>( aContainer ) );
890
891 wxString name = wxS( "Hole_" ) + holeUuid;
892
893 newFootprint->SetFPID( LIB_ID( wxEmptyString, name ) );
894 newFootprint->SetPosition( center );
895 newFootprint->SetLocked( true );
896
897 newFootprint->Reference().SetText( name );
898 newFootprint->Reference().SetVisible( false );
899 newFootprint->Reference().SetTextSize( HIDDEN_TEXT_SIZE );
900 newFootprint->Value().SetText( name );
901 newFootprint->Value().SetVisible( false );
902 newFootprint->Value().SetTextSize( HIDDEN_TEXT_SIZE );
903
904 padContainer = newFootprint.get();
905 aContainer->Add( newFootprint.release(), ADD_MODE::APPEND );
906 }
907
908 std::unique_ptr<PAD> pad = std::make_unique<PAD>( padContainer );
909
910 pad->SetPosition( center );
911 pad->SetLayerSet( PAD::UnplatedHoleMask() );
912 pad->SetAttribute( PAD_ATTRIB::NPTH );
913 pad->SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::CIRCLE );
914 pad->SetSize( PADSTACK::ALL_LAYERS, VECTOR2I( kdia, kdia ) );
915 pad->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
916 pad->SetDrillSize( VECTOR2I( kdia, kdia ) );
917
918 padContainer->Add( pad.release(), ADD_MODE::APPEND );
919 }
920 else if( elType == wxS( "PAD" ) )
921 {
922 FOOTPRINT* padContainer;
923
924 VECTOR2D center( RelPosX( arr[2] ), RelPosY( arr[3] ) );
925 VECTOR2D size( ConvertSize( arr[4] ), ConvertSize( arr[5] ) );
926 wxString padUuid = arr[12];
927
928 if( footprint )
929 {
930 padContainer = footprint;
931 }
932 else
933 {
934 std::unique_ptr<FOOTPRINT> newFootprint =
935 std::make_unique<FOOTPRINT>( dynamic_cast<BOARD*>( aContainer ) );
936
937 wxString name = wxS( "Pad_" ) + padUuid;
938
939 newFootprint->SetFPID( LIB_ID( wxEmptyString, name ) );
940 newFootprint->SetPosition( center );
941 newFootprint->SetLocked( true );
942
943 newFootprint->Reference().SetText( name );
944 newFootprint->Reference().SetVisible( false );
945 newFootprint->Reference().SetTextSize( HIDDEN_TEXT_SIZE );
946 newFootprint->Value().SetText( name );
947 newFootprint->Value().SetVisible( false );
948 newFootprint->Value().SetTextSize( HIDDEN_TEXT_SIZE );
949
950 padContainer = newFootprint.get();
951 aContainer->Add( newFootprint.release(), ADD_MODE::APPEND );
952 }
953
954 std::unique_ptr<PAD> pad = std::make_unique<PAD>( padContainer );
955
956 pad->SetNet( getOrAddNetItem( arr[7] ) );
957 pad->SetNumber( arr[8] );
958 pad->SetPosition( center );
959 pad->SetSize( PADSTACK::ALL_LAYERS, size );
960 pad->SetOrientationDegrees( Convert( arr[11] ) );
961 pad->SetThermalSpokeAngle( ANGLE_0 );
962
963 wxString elayer = arr[6];
964 PCB_LAYER_ID klayer = LayerToKi( elayer );
965
966 bool plated = arr[15] == wxS( "Y" );
967
968 if( klayer == F_Cu )
969 {
970 pad->SetLayer( F_Cu );
971 pad->SetLayerSet( PAD::SMDMask() );
972 pad->SetAttribute( PAD_ATTRIB::SMD );
973 }
974 else if( klayer == B_Cu )
975 {
976 pad->SetLayer( B_Cu );
977 pad->SetLayerSet( PAD::SMDMask().FlipStandardLayers() );
978 pad->SetAttribute( PAD_ATTRIB::SMD );
979 }
980 else if( elayer == wxS( "11" ) )
981 {
982 pad->SetLayerSet( plated ? PAD::PTHMask() : PAD::UnplatedHoleMask() );
983 pad->SetAttribute( plated ? PAD_ATTRIB::PTH : PAD_ATTRIB::NPTH );
984 }
985 else
986 {
987 pad->SetLayer( klayer );
988 pad->SetLayerSet( LSET( { klayer } ) );
989 pad->SetAttribute( PAD_ATTRIB::SMD );
990 }
991
992 wxString padType = arr[1];
993 if( padType == wxS( "ELLIPSE" ) )
994 {
995 pad->SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::OVAL );
996 }
997 else if( padType == wxS( "RECT" ) )
998 {
999 pad->SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::RECTANGLE );
1000 }
1001 else if( padType == wxS( "OVAL" ) )
1002 {
1003 if( pad->GetSizeX() == pad->GetSizeY() )
1004 pad->SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::CIRCLE );
1005 else
1006 pad->SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::OVAL );
1007 }
1008 else if( padType == wxS( "POLYGON" ) )
1009 {
1010 pad->SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::CUSTOM );
1011 pad->SetAnchorPadShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::CIRCLE );
1012 pad->SetSize( PADSTACK::ALL_LAYERS, { 1, 1 } );
1013
1014 wxArrayString data = wxSplit( arr[10], ' ', '\0' );
1015
1017 for( int i = 1; i < data.size(); i += 2 )
1018 {
1019 VECTOR2D pt;
1020 pt.x = RelPosX( data[i - 1] );
1021 pt.y = RelPosY( data[i] );
1022 chain.Append( pt );
1023 }
1024 chain.SetClosed( true );
1025
1026 chain.Move( -center );
1027 chain.Rotate( -pad->GetOrientation() );
1028 pad->AddPrimitivePoly( PADSTACK::ALL_LAYERS, chain, 0, true );
1029 }
1030
1031 wxString holeDia = arr[9];
1032 if( !holeDia.IsEmpty() )
1033 {
1034 double holeD = ConvertSize( holeDia ) * 2;
1035 double holeL = 0;
1036
1037 wxString holeLength = arr[13];
1038 if( !holeLength.IsEmpty() )
1039 holeL = ConvertSize( holeLength );
1040
1041 if( holeL > 0 )
1042 {
1043 pad->SetDrillShape( PAD_DRILL_SHAPE::OBLONG );
1044
1045 if( size.x < size.y )
1046 pad->SetDrillSize( VECTOR2I( holeD, holeL ) );
1047 else
1048 pad->SetDrillSize( VECTOR2I( holeL, holeD ) );
1049 }
1050 else
1051 {
1052 pad->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
1053 pad->SetDrillSize( VECTOR2I( holeD, holeD ) );
1054 }
1055 }
1056
1057 wxString pasteExp = arr[17];
1058 if( !pasteExp.IsEmpty() )
1059 {
1060 double pasteExpansion = ConvertSize( pasteExp );
1061 pad->SetLocalSolderPasteMargin( pasteExpansion );
1062 }
1063
1064 wxString maskExp = arr[18];
1065 if( !maskExp.IsEmpty() )
1066 {
1067 double maskExpansion = ConvertSize( maskExp );
1068 pad->SetLocalSolderMaskMargin( maskExpansion );
1069 }
1070
1071 padContainer->Add( pad.release(), ADD_MODE::APPEND );
1072 }
1073 }
1074}
1075
1076
1078 const VECTOR2D& aOrigin, const EDA_ANGLE& aOrientation, int aLayer, BOARD* aParent,
1079 std::map<wxString, wxString> aParams,
1080 std::map<wxString, std::unique_ptr<FOOTPRINT>>& aFootprintMap, wxArrayString aShapes )
1081{
1082 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>( aParent );
1083
1084 if( aLayer == 2 ) // Bottom layer
1085 {
1086 footprint->SetLayer( B_Cu );
1087 footprint->SetOrientation( aOrientation - ANGLE_180 );
1088 }
1089 else
1090 {
1091 footprint->SetLayer( F_Cu );
1092 footprint->SetOrientation( aOrientation );
1093 }
1094
1095 footprint->Value().SetText( aParams[wxS( "package" )] );
1096
1097 m_relOrigin = aOrigin;
1098
1099 ParseToBoardItemContainer( footprint.get(), aParent, aParams, aFootprintMap, aShapes );
1100
1101 // Heal board outlines
1102 std::vector<PCB_SHAPE*> shapes;
1103 std::vector<std::unique_ptr<PCB_SHAPE>> newShapes;
1104
1105 for( BOARD_ITEM* item : footprint->GraphicalItems() )
1106 {
1107 if( !item->IsOnLayer( Edge_Cuts ) )
1108 continue;
1109
1110 if( item->Type() == PCB_SHAPE_T )
1111 shapes.push_back( static_cast<PCB_SHAPE*>( item ) );
1112 }
1113
1114 ConnectBoardShapes( shapes, newShapes, SHAPE_JOIN_DISTANCE );
1115
1116 for( std::unique_ptr<PCB_SHAPE>& ptr : newShapes )
1117 footprint->Add( ptr.release(), ADD_MODE::APPEND );
1118
1119 return footprint.release();
1120}
1121
1122
1124 std::map<wxString, std::unique_ptr<FOOTPRINT>>& aFootprintMap,
1125 wxArrayString aShapes )
1126{
1127 m_relOrigin = aOrigin;
1128
1129 ParseToBoardItemContainer( aBoard, nullptr, {}, aFootprintMap, aShapes );
1130
1131 // Heal board outlines
1132 std::vector<PCB_SHAPE*> shapes;
1133 std::vector<std::unique_ptr<PCB_SHAPE>> newShapes;
1134
1135 for( BOARD_ITEM* item : aBoard->Drawings() )
1136 {
1137 if( !item->IsOnLayer( Edge_Cuts ) )
1138 continue;
1139
1140 if( item->Type() == PCB_SHAPE_T )
1141 shapes.push_back( static_cast<PCB_SHAPE*>( item ) );
1142 }
1143
1144 ConnectBoardShapes( shapes, newShapes, SHAPE_JOIN_DISTANCE );
1145
1146 for( std::unique_ptr<PCB_SHAPE>& ptr : newShapes )
1147 aBoard->Add( ptr.release(), ADD_MODE::APPEND );
1148}
const char * name
Definition: DXF_plotter.cpp:59
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:108
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition: box2.h:990
Abstract interface for BOARD_ITEMs capable of storing other items inside.
virtual void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false)=0
Adds an item to the container.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:79
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:290
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:296
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition: board.cpp:1056
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:2005
unsigned GetNetCount() const
Definition: board.h:925
const DRAWINGS & Drawings() const
Definition: board.h:339
double ConvertSize(const wxString &aValue)
std::vector< SHAPE_LINE_CHAIN > ParseLineChains(const wxString &aData, int aArcMinSegLen, bool aForceClosed)
static double Convert(const wxString &aValue)
double RelPosX(double aValue)
double RelPosY(double aValue)
VECTOR2< T > RelPos(const VECTOR2< T > &aVec)
void TransformTextToBaseline(EDA_TEXT *textItem, const wxString &baselineAlign)
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:379
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:270
void SetFPID(const LIB_ID &aFPID)
Definition: footprint.h:248
EDA_ANGLE GetOrientation() const
Definition: footprint.h:226
PCB_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this footprint.
Definition: footprint.cpp:580
double GetOrientationDegrees() const
Definition: footprint.h:242
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition: footprint.h:235
void Move(const VECTOR2I &aMoveVector) override
Move this object.
Definition: footprint.cpp:2358
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition: footprint.cpp:1046
std::vector< FP_3DMODEL > & Models()
Definition: footprint.h:219
VECTOR3D m_Offset
3D model offset (mm)
Definition: footprint.h:105
VECTOR3D m_Rotation
3D model rotation (degrees)
Definition: footprint.h:104
wxString m_Filename
The 3D shape filename in 3D library.
Definition: footprint.h:107
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false, const std::vector< wxString > *aEmbeddedFiles=nullptr, bool aForDrawingSheet=false)
Definition: font.cpp:147
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:49
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
Definition: lib_id.cpp:51
LSET is a set of PCB_LAYER_IDs.
Definition: lset.h:37
Handle the data for a net.
Definition: netinfo.h:56
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
Definition: padstack.h:144
static LSET PTHMask()
layer set for a through hole pad
Definition: pad.cpp:274
static LSET UnplatedHoleMask()
layer set for a mechanical unplated through hole pad
Definition: pad.cpp:295
static LSET SMDMask()
layer set for a SMD pad on Front layer
Definition: pad.cpp:281
PCB_IO_EASYEDA_PARSER(PROGRESS_REPORTER *aProgressReporter)
void ParseToBoardItemContainer(BOARD_ITEM_CONTAINER *aContainer, BOARD *aParent, std::map< wxString, wxString > paramMap, std::map< wxString, std::unique_ptr< FOOTPRINT > > &aFootprintMap, wxArrayString shapes)
FOOTPRINT * ParseFootprint(const VECTOR2D &aOrigin, const EDA_ANGLE &aOrientation, int aLayer, BOARD *aParent, std::map< wxString, wxString > aParams, std::map< wxString, std::unique_ptr< FOOTPRINT > > &aFootprintMap, wxArrayString aShapes)
double ScaleSize(double aValue) override
void ParseBoard(BOARD *aBoard, const VECTOR2D &aOrigin, std::map< wxString, std::unique_ptr< FOOTPRINT > > &aFootprintMap, wxArrayString aShapes)
PCB_LAYER_ID LayerToKi(const wxString &aLayer)
A progress reporter interface for use in multi-threaded environments.
Definition: seg.h:42
VECTOR2I A
Definition: seg.h:49
VECTOR2I B
Definition: seg.h:50
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void Move(const VECTOR2I &aVector) override
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
void Rotate(const EDA_ANGLE &aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Rotate all vertices by a given angle.
int SegmentCount() const
Return the number of segments in this line chain.
const SEG CSegment(int aIndex) const
Return a constant copy of the aIndex segment in the line chain.
Represent a set of closed polygons.
void Fracture()
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
std::vector< SHAPE_LINE_CHAIN > POLYGON
represents a single polygon outline with holes.
int AddHole(const SHAPE_LINE_CHAIN &aHole, int aOutline=-1)
Adds a new hole to the given outline (default: last) and returns its index.
void RebuildHolesFromContours()
Extract all contours from this polygon set, then recreate polygons with holes.
int OutlineCount() const
Return the number of outlines in the set.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
const std::vector< POLYGON > & CPolygons() const
T y
Definition: vector3.h:64
T z
Definition: vector3.h:65
T x
Definition: vector3.h:63
#define _(s)
static constexpr EDA_ANGLE ANGLE_0
Definition: eda_angle.h:401
@ DEGREES_T
Definition: eda_angle.h:31
static constexpr EDA_ANGLE ANGLE_180
Definition: eda_angle.h:405
void ConnectBoardShapes(std::vector< PCB_SHAPE * > &aShapeList, std::vector< std::unique_ptr< PCB_SHAPE > > &aNewShapes, int aChainingEpsilon)
Connects shapes to each other, making continious contours (adjacent shapes will have a common vertex)...
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:39
bool IsBackLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a back layer.
Definition: layer_ids.h:743
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition: layer_ids.h:618
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ In22_Cu
Definition: layer_ids.h:87
@ In11_Cu
Definition: layer_ids.h:76
@ In29_Cu
Definition: layer_ids.h:94
@ In30_Cu
Definition: layer_ids.h:95
@ In17_Cu
Definition: layer_ids.h:82
@ Edge_Cuts
Definition: layer_ids.h:112
@ Dwgs_User
Definition: layer_ids.h:107
@ F_Paste
Definition: layer_ids.h:104
@ In9_Cu
Definition: layer_ids.h:74
@ Cmts_User
Definition: layer_ids.h:108
@ In19_Cu
Definition: layer_ids.h:84
@ In7_Cu
Definition: layer_ids.h:72
@ In28_Cu
Definition: layer_ids.h:93
@ In26_Cu
Definition: layer_ids.h:91
@ B_Mask
Definition: layer_ids.h:98
@ B_Cu
Definition: layer_ids.h:65
@ User_5
Definition: layer_ids.h:128
@ Eco1_User
Definition: layer_ids.h:109
@ F_Mask
Definition: layer_ids.h:97
@ In21_Cu
Definition: layer_ids.h:86
@ In23_Cu
Definition: layer_ids.h:88
@ B_Paste
Definition: layer_ids.h:105
@ In15_Cu
Definition: layer_ids.h:80
@ In2_Cu
Definition: layer_ids.h:67
@ F_Fab
Definition: layer_ids.h:119
@ In10_Cu
Definition: layer_ids.h:75
@ F_SilkS
Definition: layer_ids.h:100
@ In4_Cu
Definition: layer_ids.h:69
@ Eco2_User
Definition: layer_ids.h:110
@ In16_Cu
Definition: layer_ids.h:81
@ In24_Cu
Definition: layer_ids.h:89
@ In1_Cu
Definition: layer_ids.h:66
@ User_3
Definition: layer_ids.h:126
@ User_1
Definition: layer_ids.h:124
@ B_SilkS
Definition: layer_ids.h:101
@ In13_Cu
Definition: layer_ids.h:78
@ User_4
Definition: layer_ids.h:127
@ In8_Cu
Definition: layer_ids.h:73
@ In14_Cu
Definition: layer_ids.h:79
@ User_2
Definition: layer_ids.h:125
@ In12_Cu
Definition: layer_ids.h:77
@ In27_Cu
Definition: layer_ids.h:92
@ In6_Cu
Definition: layer_ids.h:71
@ In5_Cu
Definition: layer_ids.h:70
@ In3_Cu
Definition: layer_ids.h:68
@ In20_Cu
Definition: layer_ids.h:85
@ F_Cu
Definition: layer_ids.h:64
@ In18_Cu
Definition: layer_ids.h:83
@ In25_Cu
Definition: layer_ids.h:90
@ B_Fab
Definition: layer_ids.h:118
std::optional< V > get_opt(const std::map< wxString, V > &aMap, const wxString &aKey)
Definition: map_helpers.h:34
Class to handle a set of BOARD_ITEMs.
static const wxString MODEL_SIZE_KEY
static const wxString DIRECT_MODEL_UUID_KEY
static const int SHAPE_JOIN_DISTANCE
static const VECTOR2I HIDDEN_TEXT_SIZE(pcbIUScale.mmToIU(0.5), pcbIUScale.mmToIU(0.5))
static LIB_ID EasyEdaToKiCadLibID(const wxString &aLibName, const wxString &aLibReference)
static LIB_ID EasyEdaToKiCadLibID(const wxString &aLibName, const wxString &aLibReference)
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
wxString UnescapeHTML(const wxString &aString)
Return a new wxString unescaped from HTML format.
@ CTX_LIBID
Definition: string_utils.h:54
constexpr double IUTomm(int iu) const
Definition: base_units.h:86
constexpr int mmToIU(double mm) const
Definition: base_units.h:88
bool cw
VECTOR2I center
const SHAPE_LINE_CHAIN chain
int radius
VECTOR2I end
constexpr int delta
@ GR_TEXT_H_ALIGN_LEFT
@ GR_TEXT_V_ALIGN_TOP
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition: trigo.cpp:229
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:88
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:695
VECTOR2< double > VECTOR2D
Definition: vector2d.h:694