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 <json_common.h>
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 =
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(), SHAPE_ARC::DefaultAccuracyForPCB(), 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->SetDoNotAllowZoneFills( 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(), SHAPE_ARC::DefaultAccuracyForPCB(), 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>(), SHAPE_ARC::DefaultAccuracyForPCB(), 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 maxError = SHAPE_ARC::DefaultAccuracyForPCB();
745
746 if( dataStr->size() >= 8000 )
747 maxError *= 10;
748
749 SHAPE_POLY_SET polySet = ParseLineChains( dataStr->Trim(), maxError, true );
750
751 polySet.RebuildHolesFromContours();
752
753 std::unique_ptr<PCB_GROUP> group;
754
755 if( polySet.OutlineCount() > 1 )
756 group = std::make_unique<PCB_GROUP>( aContainer );
757
758 for( const SHAPE_POLY_SET::POLYGON& poly : polySet.CPolygons() )
759 {
760 auto shape = std::make_unique<PCB_SHAPE>( aContainer, SHAPE_T::POLY );
761
762 shape->SetFilled( true );
763 shape->SetPolyShape( poly );
764 shape->SetLayer( klayer );
765 shape->SetWidth( 0 );
766
767 if( group )
768 group->AddItem( shape.get() );
769
770 aContainer->Add( shape.release(), ADD_MODE::APPEND );
771 }
772
773 if( group )
774 aContainer->Add( group.release(), ADD_MODE::APPEND );
775 }
776 }
777 }
778 else
779 {
780 THROW_IO_ERROR( wxString::Format( _( "Unknown SVGNODE nodeType %d" ), nodeType ) );
781 }
782 }
783 else if( elType == wxS( "TEXT" ) )
784 {
785 PCB_TEXT* text;
786 wxString textType = arr[1];
787
788 if( footprint && textType == wxS( "P" ) )
789 {
790 text = footprint->GetField( FIELD_T::REFERENCE );
791 }
792 else if( footprint && textType == wxS( "N" ) )
793 {
794 text = footprint->GetField( FIELD_T::VALUE );
795 }
796 else if( arr[12] == wxS( "none" ) )
797 {
798 text = new PCB_FIELD( aContainer, FIELD_T::USER );
799 static_cast<PCB_FIELD*>( text )->SetVisible( false );
800 }
801 else
802 {
803 text = new PCB_TEXT( aContainer );
804 aContainer->Add( text, ADD_MODE::APPEND );
805 }
806
807 VECTOR2D start;
808 start.x = RelPosX( arr[2] );
809 start.y = RelPosY( arr[3] );
810 text->SetPosition( start );
811
812 double thickness = ConvertSize( arr[4] );
813 text->SetTextThickness( thickness );
814
815 double rot = Convert( arr[5] );
816 text->SetTextAngleDegrees( rot );
817
818 text->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
819 text->SetVertJustify( GR_TEXT_V_ALIGN_TOP );
820
821 PCB_LAYER_ID layer = LayerToKi( arr[7] );
822 text->SetLayer( layer );
823
824 if( IsBackLayer( layer ) )
825 text->SetMirrored( true );
826
827 double height = ConvertSize( arr[9] ) * 0.8;
828 text->SetTextSize( VECTOR2I( height, height ) );
829
830 wxString textStr = arr[10];
831 textStr.Replace( wxS( "\\n" ), wxS( "\n" ) );
832 text->SetText( UnescapeHTML( textStr ) );
833
834 //arr[11] // Geometry data
835
836 wxString font = arr[14];
837 if( !font.IsEmpty() )
838 text->SetFont( KIFONT::FONT::GetFont( font ) );
839
840 TransformTextToBaseline( text, wxEmptyString );
841 }
842 else if( elType == wxS( "VIA" ) )
843 {
844 VECTOR2D center( RelPosX( arr[1] ), RelPosY( arr[2] ) );
845 int kdia = ConvertSize( arr[3] );
846 int kdrill = ConvertSize( arr[5] ) * 2;
847
848 if( footprint )
849 {
850 std::unique_ptr<PAD> pad = std::make_unique<PAD>( footprint );
851
852 pad->SetPosition( center );
853 pad->SetLayerSet( PAD::PTHMask() );
854 pad->SetAttribute( PAD_ATTRIB::PTH );
855 pad->SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::CIRCLE );
856 pad->SetSize( PADSTACK::ALL_LAYERS, VECTOR2I( kdia, kdia ) );
857 pad->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
858 pad->SetDrillSize( VECTOR2I( kdrill, kdrill ) );
859
860 footprint->Add( pad.release(), ADD_MODE::APPEND );
861 }
862 else
863 {
864 std::unique_ptr<PCB_VIA> via = std::make_unique<PCB_VIA>( aContainer );
865
866 via->SetPosition( center );
867
868 via->SetWidth( PADSTACK::ALL_LAYERS, kdia );
869 via->SetNet( getOrAddNetItem( arr[4] ) );
870 via->SetDrill( kdrill );
871
872 aContainer->Add( via.release(), ADD_MODE::APPEND );
873 }
874 }
875 else if( elType == wxS( "HOLE" ) )
876 {
877 FOOTPRINT* padContainer;
878
879 VECTOR2D center( RelPosX( arr[1] ), RelPosY( arr[2] ) );
880 int kdia = ConvertSize( arr[3] ) * 2;
881 wxString holeUuid = arr[4];
882
883 if( footprint )
884 {
885 padContainer = footprint;
886 }
887 else
888 {
889 std::unique_ptr<FOOTPRINT> newFootprint =
890 std::make_unique<FOOTPRINT>( dynamic_cast<BOARD*>( aContainer ) );
891
892 wxString name = wxS( "Hole_" ) + holeUuid;
893
894 newFootprint->SetFPID( LIB_ID( wxEmptyString, name ) );
895 newFootprint->SetPosition( center );
896 newFootprint->SetLocked( true );
897
898 newFootprint->Reference().SetText( name );
899 newFootprint->Reference().SetVisible( false );
900 newFootprint->Reference().SetTextSize( HIDDEN_TEXT_SIZE );
901 newFootprint->Value().SetText( name );
902 newFootprint->Value().SetVisible( false );
903 newFootprint->Value().SetTextSize( HIDDEN_TEXT_SIZE );
904
905 padContainer = newFootprint.get();
906 aContainer->Add( newFootprint.release(), ADD_MODE::APPEND );
907 }
908
909 std::unique_ptr<PAD> pad = std::make_unique<PAD>( padContainer );
910
911 pad->SetPosition( center );
912 pad->SetLayerSet( PAD::UnplatedHoleMask() );
913 pad->SetAttribute( PAD_ATTRIB::NPTH );
914 pad->SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::CIRCLE );
915 pad->SetSize( PADSTACK::ALL_LAYERS, VECTOR2I( kdia, kdia ) );
916 pad->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
917 pad->SetDrillSize( VECTOR2I( kdia, kdia ) );
918
919 padContainer->Add( pad.release(), ADD_MODE::APPEND );
920 }
921 else if( elType == wxS( "PAD" ) )
922 {
923 FOOTPRINT* padContainer;
924
925 VECTOR2D center( RelPosX( arr[2] ), RelPosY( arr[3] ) );
926 VECTOR2D size( ConvertSize( arr[4] ), ConvertSize( arr[5] ) );
927 wxString padUuid = arr[12];
928
929 if( footprint )
930 {
931 padContainer = footprint;
932 }
933 else
934 {
935 std::unique_ptr<FOOTPRINT> newFootprint =
936 std::make_unique<FOOTPRINT>( dynamic_cast<BOARD*>( aContainer ) );
937
938 wxString name = wxS( "Pad_" ) + padUuid;
939
940 newFootprint->SetFPID( LIB_ID( wxEmptyString, name ) );
941 newFootprint->SetPosition( center );
942 newFootprint->SetLocked( true );
943
944 newFootprint->Reference().SetText( name );
945 newFootprint->Reference().SetVisible( false );
946 newFootprint->Reference().SetTextSize( HIDDEN_TEXT_SIZE );
947 newFootprint->Value().SetText( name );
948 newFootprint->Value().SetVisible( false );
949 newFootprint->Value().SetTextSize( HIDDEN_TEXT_SIZE );
950
951 padContainer = newFootprint.get();
952 aContainer->Add( newFootprint.release(), ADD_MODE::APPEND );
953 }
954
955 std::unique_ptr<PAD> pad = std::make_unique<PAD>( padContainer );
956
957 pad->SetNet( getOrAddNetItem( arr[7] ) );
958 pad->SetNumber( arr[8] );
959 pad->SetPosition( center );
960 pad->SetSize( PADSTACK::ALL_LAYERS, size );
961 pad->SetOrientationDegrees( Convert( arr[11] ) );
962 pad->SetThermalSpokeAngle( ANGLE_0 );
963
964 wxString elayer = arr[6];
965 PCB_LAYER_ID klayer = LayerToKi( elayer );
966
967 bool plated = arr[15] == wxS( "Y" );
968
969 if( klayer == F_Cu )
970 {
971 pad->SetLayer( F_Cu );
972 pad->SetLayerSet( PAD::SMDMask() );
973 pad->SetAttribute( PAD_ATTRIB::SMD );
974 }
975 else if( klayer == B_Cu )
976 {
977 pad->SetLayer( B_Cu );
978 pad->SetLayerSet( PAD::SMDMask().FlipStandardLayers() );
979 pad->SetAttribute( PAD_ATTRIB::SMD );
980 }
981 else if( elayer == wxS( "11" ) )
982 {
983 pad->SetLayerSet( plated ? PAD::PTHMask() : PAD::UnplatedHoleMask() );
984 pad->SetAttribute( plated ? PAD_ATTRIB::PTH : PAD_ATTRIB::NPTH );
985 }
986 else
987 {
988 pad->SetLayer( klayer );
989 pad->SetLayerSet( LSET( { klayer } ) );
990 pad->SetAttribute( PAD_ATTRIB::SMD );
991 }
992
993 wxString padType = arr[1];
994 if( padType == wxS( "ELLIPSE" ) )
995 {
996 pad->SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::OVAL );
997 }
998 else if( padType == wxS( "RECT" ) )
999 {
1000 pad->SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::RECTANGLE );
1001 }
1002 else if( padType == wxS( "OVAL" ) )
1003 {
1004 if( pad->GetSizeX() == pad->GetSizeY() )
1005 pad->SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::CIRCLE );
1006 else
1007 pad->SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::OVAL );
1008 }
1009 else if( padType == wxS( "POLYGON" ) )
1010 {
1011 pad->SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::CUSTOM );
1012 pad->SetAnchorPadShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::CIRCLE );
1013 pad->SetSize( PADSTACK::ALL_LAYERS, { 1, 1 } );
1014
1015 wxArrayString data = wxSplit( arr[10], ' ', '\0' );
1016
1018 for( int i = 1; i < data.size(); i += 2 )
1019 {
1020 VECTOR2D pt;
1021 pt.x = RelPosX( data[i - 1] );
1022 pt.y = RelPosY( data[i] );
1023 chain.Append( pt );
1024 }
1025 chain.SetClosed( true );
1026
1027 chain.Move( -center );
1028 chain.Rotate( -pad->GetOrientation() );
1029 pad->AddPrimitivePoly( PADSTACK::ALL_LAYERS, chain, 0, true );
1030 }
1031
1032 wxString holeDia = arr[9];
1033 if( !holeDia.IsEmpty() )
1034 {
1035 double holeD = ConvertSize( holeDia ) * 2;
1036 double holeL = 0;
1037
1038 wxString holeLength = arr[13];
1039 if( !holeLength.IsEmpty() )
1040 holeL = ConvertSize( holeLength );
1041
1042 if( holeL > 0 )
1043 {
1044 pad->SetDrillShape( PAD_DRILL_SHAPE::OBLONG );
1045
1046 if( size.x < size.y )
1047 pad->SetDrillSize( VECTOR2I( holeD, holeL ) );
1048 else
1049 pad->SetDrillSize( VECTOR2I( holeL, holeD ) );
1050 }
1051 else
1052 {
1053 pad->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
1054 pad->SetDrillSize( VECTOR2I( holeD, holeD ) );
1055 }
1056 }
1057
1058 wxString pasteExp = arr[17];
1059 if( !pasteExp.IsEmpty() )
1060 {
1061 double pasteExpansion = ConvertSize( pasteExp );
1062 pad->SetLocalSolderPasteMargin( pasteExpansion );
1063 }
1064
1065 wxString maskExp = arr[18];
1066 if( !maskExp.IsEmpty() )
1067 {
1068 double maskExpansion = ConvertSize( maskExp );
1069 pad->SetLocalSolderMaskMargin( maskExpansion );
1070 }
1071
1072 padContainer->Add( pad.release(), ADD_MODE::APPEND );
1073 }
1074 }
1075}
1076
1077
1079 const VECTOR2D& aOrigin, const EDA_ANGLE& aOrientation, int aLayer, BOARD* aParent,
1080 std::map<wxString, wxString> aParams,
1081 std::map<wxString, std::unique_ptr<FOOTPRINT>>& aFootprintMap, wxArrayString aShapes )
1082{
1083 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>( aParent );
1084
1085 if( aLayer == 2 ) // Bottom layer
1086 {
1087 footprint->SetLayer( B_Cu );
1088 footprint->SetOrientation( aOrientation - ANGLE_180 );
1089 }
1090 else
1091 {
1092 footprint->SetLayer( F_Cu );
1093 footprint->SetOrientation( aOrientation );
1094 }
1095
1096 footprint->Value().SetText( aParams[wxS( "package" )] );
1097
1098 m_relOrigin = aOrigin;
1099
1100 ParseToBoardItemContainer( footprint.get(), aParent, aParams, aFootprintMap, aShapes );
1101
1102 // Heal board outlines
1103 std::vector<PCB_SHAPE*> shapes;
1104 std::vector<std::unique_ptr<PCB_SHAPE>> newShapes;
1105
1106 for( BOARD_ITEM* item : footprint->GraphicalItems() )
1107 {
1108 if( !item->IsOnLayer( Edge_Cuts ) )
1109 continue;
1110
1111 if( item->Type() == PCB_SHAPE_T )
1112 shapes.push_back( static_cast<PCB_SHAPE*>( item ) );
1113 }
1114
1115 ConnectBoardShapes( shapes, newShapes, SHAPE_JOIN_DISTANCE );
1116
1117 for( std::unique_ptr<PCB_SHAPE>& ptr : newShapes )
1118 footprint->Add( ptr.release(), ADD_MODE::APPEND );
1119
1120 return footprint.release();
1121}
1122
1123
1125 std::map<wxString, std::unique_ptr<FOOTPRINT>>& aFootprintMap,
1126 wxArrayString aShapes )
1127{
1128 m_relOrigin = aOrigin;
1129
1130 ParseToBoardItemContainer( aBoard, nullptr, {}, aFootprintMap, aShapes );
1131
1132 // Heal board outlines
1133 std::vector<PCB_SHAPE*> shapes;
1134 std::vector<std::unique_ptr<PCB_SHAPE>> newShapes;
1135
1136 for( BOARD_ITEM* item : aBoard->Drawings() )
1137 {
1138 if( !item->IsOnLayer( Edge_Cuts ) )
1139 continue;
1140
1141 if( item->Type() == PCB_SHAPE_T )
1142 shapes.push_back( static_cast<PCB_SHAPE*>( item ) );
1143 }
1144
1145 ConnectBoardShapes( shapes, newShapes, SHAPE_JOIN_DISTANCE );
1146
1147 for( std::unique_ptr<PCB_SHAPE>& ptr : newShapes )
1148 aBoard->Add( ptr.release(), ADD_MODE::APPEND );
1149}
const char * name
Definition: DXF_plotter.cpp:62
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:112
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:283
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:317
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition: board.cpp:1138
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:2090
unsigned GetNetCount() const
Definition: board.h:963
const DRAWINGS & Drawings() const
Definition: board.h:360
double ConvertSize(const wxString &aValue)
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)
std::vector< SHAPE_LINE_CHAIN > ParseLineChains(const wxString &aData, int aMaxError, bool aForceClosed)
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:386
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:270
void SetFPID(const LIB_ID &aFPID)
Definition: footprint.h:252
EDA_ANGLE GetOrientation() const
Definition: footprint.h:230
PCB_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this footprint.
Definition: footprint.cpp:589
double GetOrientationDegrees() const
Definition: footprint.h:246
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition: footprint.h:239
void Move(const VECTOR2I &aMoveVector) override
Move this object.
Definition: footprint.cpp:2364
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition: footprint.cpp:1076
std::vector< FP_3DMODEL > & Models()
Definition: footprint.h:223
VECTOR3D m_Offset
3D model offset (mm)
Definition: footprint.h:104
VECTOR3D m_Rotation
3D model rotation (degrees)
Definition: footprint.h:103
wxString m_Filename
The 3D shape filename in 3D library.
Definition: footprint.h:106
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:52
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:285
static LSET UnplatedHoleMask()
layer set for a mechanical unplated through hole pad
Definition: pad.cpp:306
static LSET SMDMask()
layer set for a SMD pad on Front layer
Definition: pad.cpp:292
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
static int DefaultAccuracyForPCB()
Definition: shape_arc.h:278
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:411
@ DEGREES_T
Definition: eda_angle.h:31
static constexpr EDA_ANGLE ANGLE_180
Definition: eda_angle.h:415
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:789
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition: layer_ids.h:664
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:90
constexpr int mmToIU(double mm) const
Definition: base_units.h:92
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