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 (C) 2023-2024 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 std::unique_ptr<PCB_SHAPE> shape =
290 std::make_unique<PCB_SHAPE>( aContainer, SHAPE_T::CIRCLE );
291
292 double width = ConvertSize( arr[4] );
293 shape->SetWidth( width );
294
295 PCB_LAYER_ID layer = LayerToKi( arr[5] );
296 shape->SetLayer( layer );
297
298 VECTOR2D center;
299 center.x = RelPosX( arr[1] );
300 center.y = RelPosY( arr[2] );
301
302 double radius = ConvertSize( arr[3] );
303
304 shape->SetCenter( center );
305 shape->SetEnd( center + VECTOR2I( radius, 0 ) );
306
307 if( IsCopperLayer( layer ) )
308 shape->SetNet( getOrAddNetItem( arr[8] ) );
309
310 aContainer->Add( shape.release(), ADD_MODE::APPEND );
311 }
312 else if( elType == wxS( "RECT" ) )
313 {
314 std::unique_ptr<PCB_SHAPE> shape =
315 std::make_unique<PCB_SHAPE>( aContainer, SHAPE_T::RECTANGLE );
316
317 double width = ConvertSize( arr[8] );
318 shape->SetWidth( width );
319
320 PCB_LAYER_ID layer = LayerToKi( arr[5] );
321 shape->SetLayer( layer );
322
323 bool filled = arr[9] != wxS( "none" );
324 shape->SetFilled( filled );
325
326 VECTOR2D start;
327 start.x = RelPosX( arr[1] );
328 start.y = RelPosY( arr[2] );
329
330 VECTOR2D size;
331 size.x = ConvertSize( arr[3] );
332 size.y = ConvertSize( arr[4] );
333
334 shape->SetStart( start );
335 shape->SetEnd( start + size );
336
337 if( IsCopperLayer( layer ) )
338 shape->SetNet( getOrAddNetItem( arr[11] ) );
339
340 aContainer->Add( shape.release(), ADD_MODE::APPEND );
341 }
342 else if( elType == wxS( "ARC" ) )
343 {
344 std::unique_ptr<PCB_SHAPE> shape =
345 std::make_unique<PCB_SHAPE>( aContainer, SHAPE_T::ARC );
346
347 double width = ConvertSize( arr[1] );
348 shape->SetWidth( width );
349
350 PCB_LAYER_ID layer = LayerToKi( arr[2] );
351 shape->SetLayer( layer );
352
353 if( IsCopperLayer( layer ) )
354 shape->SetNet( getOrAddNetItem( arr[3] ) );
355
356 VECTOR2D start, end;
357 VECTOR2D rad( 10, 10 );
358 bool isFar = false;
359 bool cw = false;
360
361 int pos = 0;
362 wxString data = arr[4];
363 auto readNumber = [&]( wxString& aOut )
364 {
365 wxUniChar ch = data[pos];
366
367 while( ch == ' ' || ch == ',' )
368 ch = data[++pos];
369
370 while( isdigit( ch ) || ch == '.' || ch == '-' )
371 {
372 aOut += ch;
373 pos++;
374
375 if( pos == data.size() )
376 break;
377
378 ch = data[pos];
379 }
380 };
381
382 do
383 {
384 wxUniChar sym = data[pos++];
385
386 if( sym == 'M' )
387 {
388 wxString xStr, yStr;
389 readNumber( xStr );
390 readNumber( yStr );
391
392 start = VECTOR2D( Convert( xStr ), Convert( yStr ) );
393 }
394 else if( sym == 'A' )
395 {
396 wxString radX, radY, unknown, farFlag, cwFlag, endX, endY;
397 readNumber( radX );
398 readNumber( radY );
399 readNumber( unknown );
400 readNumber( farFlag );
401 readNumber( cwFlag );
402 readNumber( endX );
403 readNumber( endY );
404
405 isFar = farFlag == wxS( "1" );
406 cw = cwFlag == wxS( "1" );
407 rad = VECTOR2D( Convert( radX ), Convert( radY ) );
408 end = VECTOR2D( Convert( endX ), Convert( endY ) );
409 }
410 } while( pos < data.size() );
411
412 VECTOR2D delta = end - start;
413
414 double d = delta.EuclideanNorm();
415 double h = sqrt( std::max( 0.0, rad.x * rad.x - d * d / 4 ) );
416
417 //( !far && cw ) => h
418 //( far && cw ) => -h
419 //( !far && !cw ) => -h
420 //( far && !cw ) => h
421 VECTOR2D arcCenter =
422 start + delta / 2 + delta.Perpendicular().Resize( ( isFar ^ cw ) ? h : -h );
423
424 if( !cw )
425 std::swap( start, end );
426
427 shape->SetStart( RelPos( start ) );
428 shape->SetEnd( RelPos( end ) );
429 shape->SetCenter( RelPos( arcCenter ) );
430
431 aContainer->Add( shape.release(), ADD_MODE::APPEND );
432 }
433 else if( elType == wxS( "DIMENSION" ) )
434 {
435 PCB_LAYER_ID layer = LayerToKi( arr[1] );
436 double lineWidth = ConvertSize( arr[7] );
437 wxString shapeData = arr[2].Trim();
438 //double textHeight = !arr[4].IsEmpty() ? ConvertSize( arr[4] ) : 0;
439
440 std::vector<SHAPE_LINE_CHAIN> lineChains =
441 ParseLineChains( shapeData, pcbIUScale.mmToIU( 0.01 ), false );
442
443 std::unique_ptr<PCB_GROUP> group = std::make_unique<PCB_GROUP>( aContainer );
444 group->SetName( wxS( "Dimension" ) );
445
446 for( const SHAPE_LINE_CHAIN& chain : lineChains )
447 {
448 for( int segId = 0; segId < chain.SegmentCount(); segId++ )
449 {
450 SEG seg = chain.CSegment( segId );
451
452 std::unique_ptr<PCB_SHAPE> shape =
453 std::make_unique<PCB_SHAPE>( aContainer, SHAPE_T::SEGMENT );
454
455 shape->SetLayer( layer );
456 shape->SetWidth( lineWidth );
457 shape->SetStart( seg.A );
458 shape->SetEnd( seg.B );
459
460 group->AddItem( shape.get() );
461
462 aContainer->Add( shape.release(), ADD_MODE::APPEND );
463 }
464 }
465
466 aContainer->Add( group.release(), ADD_MODE::APPEND );
467 }
468 else if( elType == wxS( "SOLIDREGION" ) )
469 {
470 wxString layer = arr[1];
471
472 SHAPE_POLY_SET polySet =
473 ParseLineChains( arr[3].Trim(), pcbIUScale.mmToIU( 0.01 ), true );
474
475 if( layer == wxS( "11" ) ) // Multi-layer (board cutout)
476 {
477 for( const SHAPE_POLY_SET::POLYGON& poly : polySet.CPolygons() )
478 {
479 std::unique_ptr<PCB_SHAPE> shape =
480 std::make_unique<PCB_SHAPE>( aContainer, SHAPE_T::POLY );
481
482 shape->SetLayer( Edge_Cuts );
483 shape->SetFilled( false );
484 shape->SetWidth( pcbIUScale.mmToIU( 0.1 ) );
485 shape->SetPolyShape( poly );
486
487 aContainer->Add( shape.release(), ADD_MODE::APPEND );
488 }
489 }
490 else
491 {
492 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aContainer );
493
494 PCB_LAYER_ID klayer = LayerToKi( layer );
495 zone->SetLayer( klayer );
496
497 if( IsCopperLayer( klayer ) )
498 zone->SetNet( getOrAddNetItem( arr[2] ) );
499
500 for( const SHAPE_POLY_SET::POLYGON& poly : polySet.CPolygons() )
501 zone->Outline()->AddPolygon( poly );
502
503 if( arr[4].Lower() == wxS( "cutout" ) )
504 {
505 zone->SetIsRuleArea( true );
506 zone->SetDoNotAllowCopperPour( true );
507 zone->SetDoNotAllowTracks( false );
508 zone->SetDoNotAllowVias( false );
509 zone->SetDoNotAllowPads( false );
510 zone->SetDoNotAllowFootprints( false );
511 }
512 else
513 { // solid
514 zone->SetFilledPolysList( klayer, polySet );
515 zone->SetPadConnection( ZONE_CONNECTION::FULL );
516 zone->SetIsFilled( true );
517 zone->SetNeedRefill( false );
518 }
519
520 zone->SetMinThickness( 0 );
521 zone->SetLocalClearance( 0 );
522 zone->SetAssignedPriority( 100 );
523
524 aContainer->Add( zone.release(), ADD_MODE::APPEND );
525 }
526 }
527 else if( elType == wxS( "COPPERAREA" ) )
528 {
529 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aContainer );
530
531 PCB_LAYER_ID layer = LayerToKi( arr[2] );
532 zone->SetLayer( layer );
533
534 wxString netname = arr[3];
535
536 if( IsCopperLayer( layer ) )
537 zone->SetNet( getOrAddNetItem( netname ) );
538
539 zone->SetLocalClearance( ConvertSize( arr[5] ) );
540 zone->SetThermalReliefGap( zone->GetLocalClearance().value() );
541
542 wxString fillStyle = arr[5];
543 if( fillStyle == wxS( "none" ) )
544 {
545 // Do not fill?
546 }
547
548 SHAPE_POLY_SET polySet =
549 ParseLineChains( arr[4].Trim(), pcbIUScale.mmToIU( 0.01 ), true );
550
551 for( const SHAPE_POLY_SET::POLYGON& poly : polySet.CPolygons() )
552 zone->Outline()->AddPolygon( poly );
553
554 wxString thermal = arr[8];
555 if( thermal == wxS( "direct" ) )
556 zone->SetPadConnection( ZONE_CONNECTION::FULL );
557
558 wxString keepIsland = arr[9];
559 if( keepIsland == wxS( "yes" ) )
560 zone->SetIslandRemovalMode( ISLAND_REMOVAL_MODE::NEVER );
561
562 wxString fillData = arr[10];
563 SHAPE_POLY_SET fillPolySet;
564 try
565 {
566 for( const nlohmann::json& polyData : nlohmann::json::parse( fillData ) )
567 {
568 for( const nlohmann::json& contourData : polyData )
569 {
570 SHAPE_POLY_SET contourPolySet = ParseLineChains(
571 contourData.get<wxString>(), pcbIUScale.mmToIU( 0.01 ), true );
572
573 SHAPE_POLY_SET currentOutline( contourPolySet.COutline( 0 ) );
574
575 for( int i = 1; i < contourPolySet.OutlineCount(); i++ )
576 currentOutline.AddHole( contourPolySet.COutline( i ) );
577
578 fillPolySet.Append( currentOutline );
579 }
580 }
581
583
584 zone->SetFilledPolysList( layer, fillPolySet );
585 zone->SetIsFilled( true );
586 zone->SetNeedRefill( false );
587 }
588 catch( nlohmann::json::exception& e )
589 {
590 }
591
592 int fillOrder = wxAtoi( arr[13] );
593 zone->SetAssignedPriority( 100 - fillOrder );
594
595 wxString improveFabrication = arr[17];
596 if( improveFabrication == wxS( "none" ) )
597 {
598 zone->SetMinThickness( 0 );
599 }
600 else
601 {
602 // arr[1] is "stroke Width" per docs
603 int minThickness =
604 std::max( pcbIUScale.mmToIU( 0.03 ), int( ConvertSize( arr[1] ) ) );
605 zone->SetMinThickness( minThickness );
606 }
607
608 if( arr.size() > 18 )
609 {
610 zone->SetThermalReliefSpokeWidth(
611 std::max( int( ConvertSize( arr[18] ) ), zone->GetMinThickness() ) );
612 }
613 else
614 {
615 wxFAIL_MSG( wxString::Format( "COPPERAREA unexpected size %d: %s ", arr.size(),
616 shape ) );
617
618 zone->SetThermalReliefSpokeWidth( zone->GetMinThickness() );
619 }
620
621 aContainer->Add( zone.release(), ADD_MODE::APPEND );
622 }
623 else if( elType == wxS( "SVGNODE" ) )
624 {
625 nlohmann::json nodeData = nlohmann::json::parse( arr[1] );
626
627 int nodeType = nodeData.at( "nodeType" );
628 wxString layer = nodeData.at( "layerid" );
629 PCB_LAYER_ID klayer = LayerToKi( layer );
630
631 if( nodeType == 1 )
632 {
633 std::map<wxString, wxString> attributes = nodeData.at( "attrs" );
634
635 if( layer == wxS( "19" ) ) // 3DModel
636 {
637 if( !footprint )
638 continue;
639
640 auto ec_eType = get_opt( attributes, "c_etype" );
641 auto ec_rotation = get_opt( attributes, "c_rotation" );
642 auto ec_origin = get_opt( attributes, "c_origin" );
643 auto ec_width = get_opt( attributes, "c_width" );
644 auto ec_height = get_opt( attributes, "c_height" );
645 auto ez = get_opt( attributes, "z" );
646 auto etitle = get_opt( attributes, "title" );
647 auto euuid = get_opt( attributes, "uuid" );
648 auto etransform = get_opt( attributes, "transform" );
649
650 if( !ec_eType || *ec_eType != wxS( "outline3D" ) || !etitle )
651 continue;
652
653 wxString modelTitle = *etitle;
654 VECTOR3D kmodelOffset;
655 VECTOR3D kmodelRotation;
656
657 if( euuid )
658 {
659 PCB_FIELD field( footprint, footprint->GetFieldCount(),
661 field.SetLayer( Cmts_User );
662 field.SetVisible( false );
663 field.SetText( *euuid );
664 footprint->AddField( field );
665 }
666
667 /*if( etransform )
668 {
669 PCB_FIELD field( footprint, footprint->GetFieldCount(), "3D Transform" );
670 field.SetLayer( Cmts_User );
671 field.SetVisible( false );
672 field.SetText( *etransform );
673 footprint->AddField( field );
674 }*/
675
676 if( ec_width && ec_height )
677 {
678 double fitXmm = pcbIUScale.IUTomm( ScaleSize( Convert( *ec_width ) ) );
679 double fitYmm = pcbIUScale.IUTomm( ScaleSize( Convert( *ec_height ) ) );
680
681 double rounding = 0.001;
682 fitXmm = KiROUND( fitXmm / rounding ) * rounding;
683 fitYmm = KiROUND( fitYmm / rounding ) * rounding;
684
685 PCB_FIELD field( footprint, footprint->GetFieldCount(), MODEL_SIZE_KEY );
686 field.SetLayer( Cmts_User );
687 field.SetVisible( false );
688 field.SetText( wxString::FromCDouble( fitXmm ) + wxS( " " )
689 + wxString::FromCDouble( fitYmm ) );
690 footprint->AddField( field );
691 }
692
693 if( ec_origin )
694 {
695 wxArrayString orParts = wxSplit( *ec_origin, ',', '\0' );
696
697 if( orParts.size() == 2 )
698 {
699 VECTOR2D pos;
700 pos.x = Convert( orParts[0].Trim() );
701 pos.y = Convert( orParts[1].Trim() );
702
703 VECTOR2D rel = RelPos( pos );
704 kmodelOffset.x = -pcbIUScale.IUTomm( rel.x );
705 kmodelOffset.y = -pcbIUScale.IUTomm( rel.y );
706
707 RotatePoint( &kmodelOffset.x, &kmodelOffset.y,
708 -footprint->GetOrientation() );
709 }
710 }
711
712 if( ez )
713 {
714 kmodelOffset.z = pcbIUScale.IUTomm( ScaleSize( Convert( ez->Trim() ) ) );
715 }
716
717 if( ec_rotation )
718 {
719 wxArrayString rotParts = wxSplit( *ec_rotation, ',', '\0' );
720
721 if( rotParts.size() == 3 )
722 {
723 kmodelRotation.x = -Convert( rotParts[0].Trim() );
724 kmodelRotation.y = -Convert( rotParts[1].Trim() );
725 kmodelRotation.z = -Convert( rotParts[2].Trim() )
726 + footprint->GetOrientationDegrees();
727 }
728 }
729
730 if( footprint->GetLayer() == B_Cu )
731 {
732 kmodelRotation.z = 180 - kmodelRotation.z;
733 RotatePoint( &kmodelOffset.x, &kmodelOffset.y, ANGLE_180 );
734 }
735
736 FP_3DMODEL model;
737 model.m_Filename = kicadModelPrefix
738 + EscapeString( modelTitle, ESCAPE_CONTEXT::CTX_FILENAME )
739 + wxS( ".step" );
740 model.m_Offset = kmodelOffset;
741 model.m_Rotation = kmodelRotation;
742 footprint->Models().push_back( model );
743 }
744 else
745 {
746 if( auto dataStr = get_opt( attributes, "d" ) )
747 {
748 int minSegLen = dataStr->size() < 8000 ? pcbIUScale.mmToIU( 0.005 )
749 : pcbIUScale.mmToIU( 0.05 );
750
751 SHAPE_POLY_SET polySet =
752 ParseLineChains( dataStr->Trim(), minSegLen, true );
753
754 polySet.RebuildHolesFromContours();
755
756 std::unique_ptr<PCB_GROUP> group;
757
758 if( polySet.OutlineCount() > 1 )
759 group = std::make_unique<PCB_GROUP>( aContainer );
760
761 for( const SHAPE_POLY_SET::POLYGON& poly : polySet.CPolygons() )
762 {
763 std::unique_ptr<PCB_SHAPE> shape =
764 std::make_unique<PCB_SHAPE>( aContainer, SHAPE_T::POLY );
765
766 shape->SetFilled( true );
767 shape->SetPolyShape( poly );
768 shape->SetLayer( klayer );
769 shape->SetWidth( 0 );
770
771 if( group )
772 group->AddItem( shape.get() );
773
774 aContainer->Add( shape.release(), ADD_MODE::APPEND );
775 }
776
777 if( group )
778 aContainer->Add( group.release(), ADD_MODE::APPEND );
779 }
780 }
781 }
782 else
783 {
784 THROW_IO_ERROR( wxString::Format( _( "Unknown SVGNODE nodeType %d" ), nodeType ) );
785 }
786 }
787 else if( elType == wxS( "TEXT" ) )
788 {
789 PCB_TEXT* text;
790 wxString textType = arr[1];
791 bool add = false;
792
793 if( footprint && textType == wxS( "P" ) )
794 {
795 text = footprint->GetField( REFERENCE_FIELD );
796 }
797 else if( footprint && textType == wxS( "N" ) )
798 {
799 text = footprint->GetField( VALUE_FIELD );
800 }
801 else
802 {
803 text = new PCB_TEXT( aContainer );
804 add = true;
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 text->SetVisible( arr[12] != wxS( "none" ) );
837
838 wxString font = arr[14];
839 if( !font.IsEmpty() )
840 text->SetFont( KIFONT::FONT::GetFont( font ) );
841
842 TransformTextToBaseline( text, wxEmptyString, false );
843
844 if( add )
845 aContainer->Add( text, ADD_MODE::APPEND );
846 }
847 else if( elType == wxS( "VIA" ) )
848 {
849 VECTOR2D center( RelPosX( arr[1] ), RelPosY( arr[2] ) );
850 int kdia = ConvertSize( arr[3] );
851 int kdrill = ConvertSize( arr[5] ) * 2;
852
853 if( footprint )
854 {
855 std::unique_ptr<PAD> pad = std::make_unique<PAD>( footprint );
856
857 pad->SetPosition( center );
858 pad->SetLayerSet( PAD::PTHMask() );
859 pad->SetAttribute( PAD_ATTRIB::PTH );
860 pad->SetShape( PAD_SHAPE::CIRCLE );
861 pad->SetSize( VECTOR2I( kdia, kdia ) );
862 pad->SetDrillShape( PAD_DRILL_SHAPE_CIRCLE );
863 pad->SetDrillSize( VECTOR2I( kdrill, kdrill ) );
864
865 footprint->Add( pad.release(), ADD_MODE::APPEND );
866 }
867 else
868 {
869 std::unique_ptr<PCB_VIA> via = std::make_unique<PCB_VIA>( aContainer );
870
871 via->SetPosition( center );
872
873 via->SetWidth( kdia );
874 via->SetNet( getOrAddNetItem( arr[4] ) );
875 via->SetDrill( kdrill );
876
877 aContainer->Add( via.release(), ADD_MODE::APPEND );
878 }
879 }
880 else if( elType == wxS( "HOLE" ) )
881 {
882 FOOTPRINT* padContainer;
883
884 VECTOR2D center( RelPosX( arr[1] ), RelPosY( arr[2] ) );
885 int kdia = ConvertSize( arr[3] ) * 2;
886 wxString holeUuid = arr[4];
887
888 if( footprint )
889 {
890 padContainer = footprint;
891 }
892 else
893 {
894 std::unique_ptr<FOOTPRINT> newFootprint =
895 std::make_unique<FOOTPRINT>( dynamic_cast<BOARD*>( aContainer ) );
896
897 wxString name = wxS( "Hole_" ) + holeUuid;
898
899 newFootprint->SetFPID( LIB_ID( wxEmptyString, name ) );
900 newFootprint->SetPosition( center );
901 newFootprint->SetLocked( true );
902
903 newFootprint->Reference().SetText( name );
904 newFootprint->Reference().SetVisible( false );
905 newFootprint->Reference().SetTextSize( HIDDEN_TEXT_SIZE );
906 newFootprint->Value().SetText( name );
907 newFootprint->Value().SetVisible( false );
908 newFootprint->Value().SetTextSize( HIDDEN_TEXT_SIZE );
909
910 padContainer = newFootprint.get();
911 aContainer->Add( newFootprint.release(), ADD_MODE::APPEND );
912 }
913
914 std::unique_ptr<PAD> pad = std::make_unique<PAD>( padContainer );
915
916 pad->SetPosition( center );
917 pad->SetLayerSet( PAD::UnplatedHoleMask() );
918 pad->SetAttribute( PAD_ATTRIB::NPTH );
919 pad->SetShape( PAD_SHAPE::CIRCLE );
920 pad->SetSize( VECTOR2I( kdia, kdia ) );
921 pad->SetDrillShape( PAD_DRILL_SHAPE_CIRCLE );
922 pad->SetDrillSize( VECTOR2I( kdia, kdia ) );
923
924 padContainer->Add( pad.release(), ADD_MODE::APPEND );
925 }
926 else if( elType == wxS( "PAD" ) )
927 {
928 FOOTPRINT* padContainer;
929
930 VECTOR2D center( RelPosX( arr[2] ), RelPosY( arr[3] ) );
931 VECTOR2D size( ConvertSize( arr[4] ), ConvertSize( arr[5] ) );
932 wxString padUuid = arr[12];
933
934 if( footprint )
935 {
936 padContainer = footprint;
937 }
938 else
939 {
940 std::unique_ptr<FOOTPRINT> newFootprint =
941 std::make_unique<FOOTPRINT>( dynamic_cast<BOARD*>( aContainer ) );
942
943 wxString name = wxS( "Pad_" ) + padUuid;
944
945 newFootprint->SetFPID( LIB_ID( wxEmptyString, name ) );
946 newFootprint->SetPosition( center );
947 newFootprint->SetLocked( true );
948
949 newFootprint->Reference().SetText( name );
950 newFootprint->Reference().SetVisible( false );
951 newFootprint->Reference().SetTextSize( HIDDEN_TEXT_SIZE );
952 newFootprint->Value().SetText( name );
953 newFootprint->Value().SetVisible( false );
954 newFootprint->Value().SetTextSize( HIDDEN_TEXT_SIZE );
955
956 padContainer = newFootprint.get();
957 aContainer->Add( newFootprint.release(), ADD_MODE::APPEND );
958 }
959
960 std::unique_ptr<PAD> pad = std::make_unique<PAD>( padContainer );
961
962 pad->SetNet( getOrAddNetItem( arr[7] ) );
963 pad->SetNumber( arr[8] );
964 pad->SetPosition( center );
965 pad->SetSize( size );
966 pad->SetOrientationDegrees( Convert( arr[11] ) );
967 pad->SetThermalSpokeAngle( ANGLE_0 );
968
969 wxString elayer = arr[6];
970 PCB_LAYER_ID klayer = LayerToKi( elayer );
971
972 bool plated = arr[15] == wxS( "Y" );
973
974 if( klayer == F_Cu )
975 {
976 pad->SetLayer( F_Cu );
977 pad->SetLayerSet( PAD::SMDMask() );
978 pad->SetAttribute( PAD_ATTRIB::SMD );
979 }
980 else if( klayer == B_Cu )
981 {
982 pad->SetLayer( B_Cu );
983 pad->SetLayerSet( FlipLayerMask( PAD::SMDMask() ) );
984 pad->SetAttribute( PAD_ATTRIB::SMD );
985 }
986 else if( elayer == wxS( "11" ) )
987 {
988 pad->SetLayerSet( plated ? PAD::PTHMask() : PAD::UnplatedHoleMask() );
989 pad->SetAttribute( plated ? PAD_ATTRIB::PTH : PAD_ATTRIB::NPTH );
990 }
991 else
992 {
993 pad->SetLayer( klayer );
994 pad->SetLayerSet( LSET( 1, klayer ) );
995 pad->SetAttribute( PAD_ATTRIB::SMD );
996 }
997
998 wxString padType = arr[1];
999 if( padType == wxS( "ELLIPSE" ) )
1000 {
1001 pad->SetShape( PAD_SHAPE::OVAL );
1002 }
1003 else if( padType == wxS( "RECT" ) )
1004 {
1005 pad->SetShape( PAD_SHAPE::RECTANGLE );
1006 }
1007 else if( padType == wxS( "OVAL" ) )
1008 {
1009 if( pad->GetSizeX() == pad->GetSizeY() )
1010 pad->SetShape( PAD_SHAPE::CIRCLE );
1011 else
1012 pad->SetShape( PAD_SHAPE::OVAL );
1013 }
1014 else if( padType == wxS( "POLYGON" ) )
1015 {
1016 pad->SetShape( PAD_SHAPE::CUSTOM );
1017 pad->SetAnchorPadShape( PAD_SHAPE::CIRCLE );
1018 pad->SetSize( { 1, 1 } );
1019
1020 wxArrayString data = wxSplit( arr[10], ' ', '\0' );
1021
1022 SHAPE_LINE_CHAIN chain;
1023 for( int i = 1; i < data.size(); i += 2 )
1024 {
1025 VECTOR2D pt;
1026 pt.x = RelPosX( data[i - 1] );
1027 pt.y = RelPosY( data[i] );
1028 chain.Append( pt );
1029 }
1030 chain.SetClosed( true );
1031
1032 chain.Move( -center );
1033 chain.Rotate( -pad->GetOrientation() );
1034 pad->AddPrimitivePoly( chain, 0, true );
1035 }
1036
1037 wxString holeDia = arr[9];
1038 if( !holeDia.IsEmpty() )
1039 {
1040 double holeD = ConvertSize( holeDia ) * 2;
1041 double holeL = 0;
1042
1043 wxString holeLength = arr[13];
1044 if( !holeLength.IsEmpty() )
1045 holeL = ConvertSize( holeLength );
1046
1047 if( holeL > 0 )
1048 {
1049 pad->SetDrillShape( PAD_DRILL_SHAPE_OBLONG );
1050
1051 if( size.x < size.y )
1052 pad->SetDrillSize( VECTOR2I( holeD, holeL ) );
1053 else
1054 pad->SetDrillSize( VECTOR2I( holeL, holeD ) );
1055 }
1056 else
1057 {
1058 pad->SetDrillShape( PAD_DRILL_SHAPE_CIRCLE );
1059 pad->SetDrillSize( VECTOR2I( holeD, holeD ) );
1060 }
1061 }
1062
1063 wxString pasteExp = arr[17];
1064 if( !pasteExp.IsEmpty() )
1065 {
1066 double pasteExpansion = ConvertSize( pasteExp );
1067 pad->SetLocalSolderPasteMargin( pasteExpansion );
1068 }
1069
1070 wxString maskExp = arr[18];
1071 if( !maskExp.IsEmpty() )
1072 {
1073 double maskExpansion = ConvertSize( maskExp );
1074 pad->SetLocalSolderMaskMargin( maskExpansion );
1075 }
1076
1077 padContainer->Add( pad.release(), ADD_MODE::APPEND );
1078 }
1079 }
1080}
1081
1082
1084 const VECTOR2D& aOrigin, const EDA_ANGLE& aOrientation, int aLayer, BOARD* aParent,
1085 std::map<wxString, wxString> aParams,
1086 std::map<wxString, std::unique_ptr<FOOTPRINT>>& aFootprintMap, wxArrayString aShapes )
1087{
1088 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>( aParent );
1089
1090 if( aLayer == 2 ) // Bottom layer
1091 {
1092 footprint->SetLayer( B_Cu );
1093 footprint->SetOrientation( aOrientation - ANGLE_180 );
1094 }
1095 else
1096 {
1097 footprint->SetLayer( F_Cu );
1098 footprint->SetOrientation( aOrientation );
1099 }
1100
1101 footprint->Value().SetText( aParams[wxS( "package" )] );
1102
1103 m_relOrigin = aOrigin;
1104
1105 ParseToBoardItemContainer( footprint.get(), aParent, aParams, aFootprintMap, aShapes );
1106
1107 // Heal board outlines
1108 std::vector<PCB_SHAPE*> shapes;
1109 std::vector<std::unique_ptr<PCB_SHAPE>> newShapes;
1110
1111 for( BOARD_ITEM* item : footprint->GraphicalItems() )
1112 {
1113 if( !item->IsOnLayer( Edge_Cuts ) )
1114 continue;
1115
1116 if( item->Type() == PCB_SHAPE_T )
1117 shapes.push_back( static_cast<PCB_SHAPE*>( item ) );
1118 }
1119
1120 ConnectBoardShapes( shapes, newShapes, SHAPE_JOIN_DISTANCE );
1121
1122 for( std::unique_ptr<PCB_SHAPE>& ptr : newShapes )
1123 footprint->Add( ptr.release(), ADD_MODE::APPEND );
1124
1125 return footprint.release();
1126}
1127
1128
1130 std::map<wxString, std::unique_ptr<FOOTPRINT>>& aFootprintMap,
1131 wxArrayString aShapes )
1132{
1133 m_relOrigin = aOrigin;
1134
1135 ParseToBoardItemContainer( aBoard, nullptr, {}, aFootprintMap, aShapes );
1136
1137 // Heal board outlines
1138 std::vector<PCB_SHAPE*> shapes;
1139 std::vector<std::unique_ptr<PCB_SHAPE>> newShapes;
1140
1141 for( BOARD_ITEM* item : aBoard->Drawings() )
1142 {
1143 if( !item->IsOnLayer( Edge_Cuts ) )
1144 continue;
1145
1146 if( item->Type() == PCB_SHAPE_T )
1147 shapes.push_back( static_cast<PCB_SHAPE*>( item ) );
1148 }
1149
1150 ConnectBoardShapes( shapes, newShapes, SHAPE_JOIN_DISTANCE );
1151
1152 for( std::unique_ptr<PCB_SHAPE>& ptr : newShapes )
1153 aBoard->Add( ptr.release(), ADD_MODE::APPEND );
1154}
const char * name
Definition: DXF_plotter.cpp:57
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:108
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:77
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:260
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:281
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition: board.cpp:882
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:1804
unsigned GetNetCount() const
Definition: board.h:881
const DRAWINGS & Drawings() const
Definition: board.h:324
double ConvertSize(const wxString &aValue)
std::vector< SHAPE_LINE_CHAIN > ParseLineChains(const wxString &aData, int aArcMinSegLen, bool aForceClosed)
static double Convert(const wxString &aValue)
void TransformTextToBaseline(EDA_TEXT *textItem, const wxString &baselineAlign, bool invertY)
double RelPosX(double aValue)
double RelPosY(double aValue)
VECTOR2< T > RelPos(const VECTOR2< T > &aVec)
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:245
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:183
void SetFPID(const LIB_ID &aFPID)
Definition: footprint.h:234
int GetFieldCount() const
Return the number of fields in this symbol.
Definition: footprint.h:706
EDA_ANGLE GetOrientation() const
Definition: footprint.h:212
PCB_FIELD * AddField(const PCB_FIELD &aField)
Add a field to the symbol.
Definition: footprint.cpp:581
double GetOrientationDegrees() const
Definition: footprint.h:228
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition: footprint.h:221
void Move(const VECTOR2I &aMoveVector) override
Move this object.
Definition: footprint.cpp:2192
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition: footprint.cpp:969
std::vector< FP_3DMODEL > & Models()
Definition: footprint.h:205
PCB_FIELD * GetField(MANDATORY_FIELD_T aFieldType)
Return a mandatory field in this symbol.
Definition: footprint.cpp:505
VECTOR3D m_Offset
3D model offset (mm)
Definition: footprint.h:98
VECTOR3D m_Rotation
3D model rotation (degrees)
Definition: footprint.h:97
wxString m_Filename
The 3D shape filename in 3D library.
Definition: footprint.h:100
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false)
Definition: font.cpp:146
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: layer_ids.h:574
Handle the data for a net.
Definition: netinfo.h:56
static LSET PTHMask()
layer set for a through hole pad
Definition: pad.cpp:349
static LSET UnplatedHoleMask()
layer set for a mechanical unplated through hole pad
Definition: pad.cpp:370
static LSET SMDMask()
layer set for a SMD pad on Front layer
Definition: pad.cpp:356
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.
Represent a set of closed polygons.
void Fracture(POLYGON_MODE aFastMode)
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:63
T z
Definition: vector3.h:64
T x
Definition: vector3.h:62
#define _(s)
static constexpr EDA_ANGLE ANGLE_0
Definition: eda_angle.h:435
@ DEGREES_T
Definition: eda_angle.h:31
static constexpr EDA_ANGLE ANGLE_180
Definition: eda_angle.h:439
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:977
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:880
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ In22_Cu
Definition: layer_ids.h:86
@ In11_Cu
Definition: layer_ids.h:75
@ In29_Cu
Definition: layer_ids.h:93
@ In30_Cu
Definition: layer_ids.h:94
@ In17_Cu
Definition: layer_ids.h:81
@ Edge_Cuts
Definition: layer_ids.h:113
@ Dwgs_User
Definition: layer_ids.h:109
@ F_Paste
Definition: layer_ids.h:101
@ In9_Cu
Definition: layer_ids.h:73
@ Cmts_User
Definition: layer_ids.h:110
@ In19_Cu
Definition: layer_ids.h:83
@ In7_Cu
Definition: layer_ids.h:71
@ In28_Cu
Definition: layer_ids.h:92
@ In26_Cu
Definition: layer_ids.h:90
@ B_Mask
Definition: layer_ids.h:106
@ B_Cu
Definition: layer_ids.h:95
@ User_5
Definition: layer_ids.h:127
@ Eco1_User
Definition: layer_ids.h:111
@ F_Mask
Definition: layer_ids.h:107
@ In21_Cu
Definition: layer_ids.h:85
@ In23_Cu
Definition: layer_ids.h:87
@ B_Paste
Definition: layer_ids.h:100
@ In15_Cu
Definition: layer_ids.h:79
@ In2_Cu
Definition: layer_ids.h:66
@ F_Fab
Definition: layer_ids.h:120
@ In10_Cu
Definition: layer_ids.h:74
@ F_SilkS
Definition: layer_ids.h:104
@ In4_Cu
Definition: layer_ids.h:68
@ Eco2_User
Definition: layer_ids.h:112
@ In16_Cu
Definition: layer_ids.h:80
@ In24_Cu
Definition: layer_ids.h:88
@ In1_Cu
Definition: layer_ids.h:65
@ User_3
Definition: layer_ids.h:125
@ User_1
Definition: layer_ids.h:123
@ B_SilkS
Definition: layer_ids.h:103
@ In13_Cu
Definition: layer_ids.h:77
@ User_4
Definition: layer_ids.h:126
@ In8_Cu
Definition: layer_ids.h:72
@ In14_Cu
Definition: layer_ids.h:78
@ User_2
Definition: layer_ids.h:124
@ In12_Cu
Definition: layer_ids.h:76
@ In27_Cu
Definition: layer_ids.h:91
@ In6_Cu
Definition: layer_ids.h:70
@ In5_Cu
Definition: layer_ids.h:69
@ In3_Cu
Definition: layer_ids.h:67
@ In20_Cu
Definition: layer_ids.h:84
@ F_Cu
Definition: layer_ids.h:64
@ In18_Cu
Definition: layer_ids.h:82
@ In25_Cu
Definition: layer_ids.h:89
@ B_Fab
Definition: layer_ids.h:119
LSET FlipLayerMask(LSET aMask, int aCopperLayersCount)
Calculate the mask layer when flipping a footprint.
Definition: lset.cpp:680
std::optional< V > get_opt(const std::map< wxString, V > &aMap, const wxString &aKey)
Definition: map_helpers.h:34
@ PAD_DRILL_SHAPE_CIRCLE
Definition: pad_shapes.h:54
@ PAD_DRILL_SHAPE_OBLONG
Definition: pad_shapes.h:55
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
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".
@ REFERENCE_FIELD
Field Reference of part, i.e. "IC21".
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:228
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:88
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:85
VECTOR2< double > VECTOR2D
Definition: vector2d.h:587
VECTOR2< int > VECTOR2I
Definition: vector2d.h:588