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 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
296 VECTOR2D center;
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
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( footprint, footprint->GetFieldCount(),
655 field.SetLayer( Cmts_User );
656 field.SetVisible( false );
657 field.SetText( *euuid );
658 footprint->AddField( field );
659 }
660
661 /*if( etransform )
662 {
663 PCB_FIELD field( footprint, footprint->GetFieldCount(), "3D Transform" );
664 field.SetLayer( Cmts_User );
665 field.SetVisible( false );
666 field.SetText( *etransform );
667 footprint->AddField( field );
668 }*/
669
670 if( ec_width && ec_height )
671 {
672 double fitXmm = pcbIUScale.IUTomm( ScaleSize( Convert( *ec_width ) ) );
673 double fitYmm = pcbIUScale.IUTomm( ScaleSize( Convert( *ec_height ) ) );
674
675 double rounding = 0.001;
676 fitXmm = KiROUND( fitXmm / rounding ) * rounding;
677 fitYmm = KiROUND( fitYmm / rounding ) * rounding;
678
679 PCB_FIELD field( footprint, footprint->GetFieldCount(), MODEL_SIZE_KEY );
680 field.SetLayer( Cmts_User );
681 field.SetVisible( false );
682 field.SetText( wxString::FromCDouble( fitXmm ) + wxS( " " )
683 + wxString::FromCDouble( fitYmm ) );
684 footprint->AddField( field );
685 }
686
687 if( ec_origin )
688 {
689 wxArrayString orParts = wxSplit( *ec_origin, ',', '\0' );
690
691 if( orParts.size() == 2 )
692 {
693 VECTOR2D pos;
694 pos.x = Convert( orParts[0].Trim() );
695 pos.y = Convert( orParts[1].Trim() );
696
697 VECTOR2D rel = RelPos( pos );
698 kmodelOffset.x = -pcbIUScale.IUTomm( rel.x );
699 kmodelOffset.y = -pcbIUScale.IUTomm( rel.y );
700
701 RotatePoint( &kmodelOffset.x, &kmodelOffset.y,
702 -footprint->GetOrientation() );
703 }
704 }
705
706 if( ez )
707 {
708 kmodelOffset.z = pcbIUScale.IUTomm( ScaleSize( Convert( ez->Trim() ) ) );
709 }
710
711 if( ec_rotation )
712 {
713 wxArrayString rotParts = wxSplit( *ec_rotation, ',', '\0' );
714
715 if( rotParts.size() == 3 )
716 {
717 kmodelRotation.x = -Convert( rotParts[0].Trim() );
718 kmodelRotation.y = -Convert( rotParts[1].Trim() );
719 kmodelRotation.z = -Convert( rotParts[2].Trim() )
720 + footprint->GetOrientationDegrees();
721 }
722 }
723
724 if( footprint->GetLayer() == B_Cu )
725 {
726 kmodelRotation.z = 180 - kmodelRotation.z;
727 RotatePoint( &kmodelOffset.x, &kmodelOffset.y, ANGLE_180 );
728 }
729
730 FP_3DMODEL model;
731 model.m_Filename = kicadModelPrefix
732 + EscapeString( modelTitle, ESCAPE_CONTEXT::CTX_FILENAME )
733 + wxS( ".step" );
734 model.m_Offset = kmodelOffset;
735 model.m_Rotation = kmodelRotation;
736 footprint->Models().push_back( model );
737 }
738 else
739 {
740 if( auto dataStr = get_opt( attributes, "d" ) )
741 {
742 int minSegLen = dataStr->size() < 8000 ? pcbIUScale.mmToIU( 0.005 )
743 : pcbIUScale.mmToIU( 0.05 );
744
745 SHAPE_POLY_SET polySet =
746 ParseLineChains( dataStr->Trim(), minSegLen, true );
747
748 polySet.RebuildHolesFromContours();
749
750 std::unique_ptr<PCB_GROUP> group;
751
752 if( polySet.OutlineCount() > 1 )
753 group = std::make_unique<PCB_GROUP>( aContainer );
754
755 for( const SHAPE_POLY_SET::POLYGON& poly : polySet.CPolygons() )
756 {
757 auto shape = std::make_unique<PCB_SHAPE>( aContainer, SHAPE_T::POLY );
758
759 shape->SetFilled( true );
760 shape->SetPolyShape( poly );
761 shape->SetLayer( klayer );
762 shape->SetWidth( 0 );
763
764 if( group )
765 group->AddItem( shape.get() );
766
767 aContainer->Add( shape.release(), ADD_MODE::APPEND );
768 }
769
770 if( group )
771 aContainer->Add( group.release(), ADD_MODE::APPEND );
772 }
773 }
774 }
775 else
776 {
777 THROW_IO_ERROR( wxString::Format( _( "Unknown SVGNODE nodeType %d" ), nodeType ) );
778 }
779 }
780 else if( elType == wxS( "TEXT" ) )
781 {
782 PCB_TEXT* text;
783 wxString textType = arr[1];
784 bool add = false;
785
786 if( footprint && textType == wxS( "P" ) )
787 {
788 text = footprint->GetField( REFERENCE_FIELD );
789 }
790 else if( footprint && textType == wxS( "N" ) )
791 {
792 text = footprint->GetField( VALUE_FIELD );
793 }
794 else
795 {
796 text = new PCB_TEXT( aContainer );
797 add = true;
798 }
799
800 VECTOR2D start;
801 start.x = RelPosX( arr[2] );
802 start.y = RelPosY( arr[3] );
803 text->SetPosition( start );
804
805 double thickness = ConvertSize( arr[4] );
806 text->SetTextThickness( thickness );
807
808 double rot = Convert( arr[5] );
809 text->SetTextAngleDegrees( rot );
810
811 text->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
812 text->SetVertJustify( GR_TEXT_V_ALIGN_TOP );
813
814 PCB_LAYER_ID layer = LayerToKi( arr[7] );
815 text->SetLayer( layer );
816
817 if( IsBackLayer( layer ) )
818 text->SetMirrored( true );
819
820 double height = ConvertSize( arr[9] ) * 0.8;
821 text->SetTextSize( VECTOR2I( height, height ) );
822
823 wxString textStr = arr[10];
824 textStr.Replace( wxS( "\\n" ), wxS( "\n" ) );
825 text->SetText( UnescapeHTML( textStr ) );
826
827 //arr[11] // Geometry data
828
829 text->SetVisible( arr[12] != wxS( "none" ) );
830
831 wxString font = arr[14];
832 if( !font.IsEmpty() )
833 text->SetFont( KIFONT::FONT::GetFont( font ) );
834
835 TransformTextToBaseline( text, wxEmptyString );
836
837 if( add )
838 aContainer->Add( text, ADD_MODE::APPEND );
839 }
840 else if( elType == wxS( "VIA" ) )
841 {
842 VECTOR2D center( RelPosX( arr[1] ), RelPosY( arr[2] ) );
843 int kdia = ConvertSize( arr[3] );
844 int kdrill = ConvertSize( arr[5] ) * 2;
845
846 if( footprint )
847 {
848 std::unique_ptr<PAD> pad = std::make_unique<PAD>( footprint );
849
850 pad->SetPosition( center );
851 pad->SetLayerSet( PAD::PTHMask() );
852 pad->SetAttribute( PAD_ATTRIB::PTH );
853 pad->SetShape( PAD_SHAPE::CIRCLE );
854 pad->SetSize( VECTOR2I( kdia, kdia ) );
855 pad->SetDrillShape( PAD_DRILL_SHAPE_CIRCLE );
856 pad->SetDrillSize( VECTOR2I( kdrill, kdrill ) );
857
858 footprint->Add( pad.release(), ADD_MODE::APPEND );
859 }
860 else
861 {
862 std::unique_ptr<PCB_VIA> via = std::make_unique<PCB_VIA>( aContainer );
863
864 via->SetPosition( center );
865
866 via->SetWidth( kdia );
867 via->SetNet( getOrAddNetItem( arr[4] ) );
868 via->SetDrill( kdrill );
869
870 aContainer->Add( via.release(), ADD_MODE::APPEND );
871 }
872 }
873 else if( elType == wxS( "HOLE" ) )
874 {
875 FOOTPRINT* padContainer;
876
877 VECTOR2D center( RelPosX( arr[1] ), RelPosY( arr[2] ) );
878 int kdia = ConvertSize( arr[3] ) * 2;
879 wxString holeUuid = arr[4];
880
881 if( footprint )
882 {
883 padContainer = footprint;
884 }
885 else
886 {
887 std::unique_ptr<FOOTPRINT> newFootprint =
888 std::make_unique<FOOTPRINT>( dynamic_cast<BOARD*>( aContainer ) );
889
890 wxString name = wxS( "Hole_" ) + holeUuid;
891
892 newFootprint->SetFPID( LIB_ID( wxEmptyString, name ) );
893 newFootprint->SetPosition( center );
894 newFootprint->SetLocked( true );
895
896 newFootprint->Reference().SetText( name );
897 newFootprint->Reference().SetVisible( false );
898 newFootprint->Reference().SetTextSize( HIDDEN_TEXT_SIZE );
899 newFootprint->Value().SetText( name );
900 newFootprint->Value().SetVisible( false );
901 newFootprint->Value().SetTextSize( HIDDEN_TEXT_SIZE );
902
903 padContainer = newFootprint.get();
904 aContainer->Add( newFootprint.release(), ADD_MODE::APPEND );
905 }
906
907 std::unique_ptr<PAD> pad = std::make_unique<PAD>( padContainer );
908
909 pad->SetPosition( center );
910 pad->SetLayerSet( PAD::UnplatedHoleMask() );
911 pad->SetAttribute( PAD_ATTRIB::NPTH );
912 pad->SetShape( PAD_SHAPE::CIRCLE );
913 pad->SetSize( VECTOR2I( kdia, kdia ) );
914 pad->SetDrillShape( PAD_DRILL_SHAPE_CIRCLE );
915 pad->SetDrillSize( VECTOR2I( kdia, kdia ) );
916
917 padContainer->Add( pad.release(), ADD_MODE::APPEND );
918 }
919 else if( elType == wxS( "PAD" ) )
920 {
921 FOOTPRINT* padContainer;
922
923 VECTOR2D center( RelPosX( arr[2] ), RelPosY( arr[3] ) );
924 VECTOR2D size( ConvertSize( arr[4] ), ConvertSize( arr[5] ) );
925 wxString padUuid = arr[12];
926
927 if( footprint )
928 {
929 padContainer = footprint;
930 }
931 else
932 {
933 std::unique_ptr<FOOTPRINT> newFootprint =
934 std::make_unique<FOOTPRINT>( dynamic_cast<BOARD*>( aContainer ) );
935
936 wxString name = wxS( "Pad_" ) + padUuid;
937
938 newFootprint->SetFPID( LIB_ID( wxEmptyString, name ) );
939 newFootprint->SetPosition( center );
940 newFootprint->SetLocked( true );
941
942 newFootprint->Reference().SetText( name );
943 newFootprint->Reference().SetVisible( false );
944 newFootprint->Reference().SetTextSize( HIDDEN_TEXT_SIZE );
945 newFootprint->Value().SetText( name );
946 newFootprint->Value().SetVisible( false );
947 newFootprint->Value().SetTextSize( HIDDEN_TEXT_SIZE );
948
949 padContainer = newFootprint.get();
950 aContainer->Add( newFootprint.release(), ADD_MODE::APPEND );
951 }
952
953 std::unique_ptr<PAD> pad = std::make_unique<PAD>( padContainer );
954
955 pad->SetNet( getOrAddNetItem( arr[7] ) );
956 pad->SetNumber( arr[8] );
957 pad->SetPosition( center );
958 pad->SetSize( size );
959 pad->SetOrientationDegrees( Convert( arr[11] ) );
960 pad->SetThermalSpokeAngle( ANGLE_0 );
961
962 wxString elayer = arr[6];
963 PCB_LAYER_ID klayer = LayerToKi( elayer );
964
965 bool plated = arr[15] == wxS( "Y" );
966
967 if( klayer == F_Cu )
968 {
969 pad->SetLayer( F_Cu );
970 pad->SetLayerSet( PAD::SMDMask() );
971 pad->SetAttribute( PAD_ATTRIB::SMD );
972 }
973 else if( klayer == B_Cu )
974 {
975 pad->SetLayer( B_Cu );
976 pad->SetLayerSet( FlipLayerMask( PAD::SMDMask() ) );
977 pad->SetAttribute( PAD_ATTRIB::SMD );
978 }
979 else if( elayer == wxS( "11" ) )
980 {
981 pad->SetLayerSet( plated ? PAD::PTHMask() : PAD::UnplatedHoleMask() );
982 pad->SetAttribute( plated ? PAD_ATTRIB::PTH : PAD_ATTRIB::NPTH );
983 }
984 else
985 {
986 pad->SetLayer( klayer );
987 pad->SetLayerSet( LSET( 1, klayer ) );
988 pad->SetAttribute( PAD_ATTRIB::SMD );
989 }
990
991 wxString padType = arr[1];
992 if( padType == wxS( "ELLIPSE" ) )
993 {
994 pad->SetShape( PAD_SHAPE::OVAL );
995 }
996 else if( padType == wxS( "RECT" ) )
997 {
998 pad->SetShape( PAD_SHAPE::RECTANGLE );
999 }
1000 else if( padType == wxS( "OVAL" ) )
1001 {
1002 if( pad->GetSizeX() == pad->GetSizeY() )
1003 pad->SetShape( PAD_SHAPE::CIRCLE );
1004 else
1005 pad->SetShape( PAD_SHAPE::OVAL );
1006 }
1007 else if( padType == wxS( "POLYGON" ) )
1008 {
1009 pad->SetShape( PAD_SHAPE::CUSTOM );
1010 pad->SetAnchorPadShape( PAD_SHAPE::CIRCLE );
1011 pad->SetSize( { 1, 1 } );
1012
1013 wxArrayString data = wxSplit( arr[10], ' ', '\0' );
1014
1015 SHAPE_LINE_CHAIN chain;
1016 for( int i = 1; i < data.size(); i += 2 )
1017 {
1018 VECTOR2D pt;
1019 pt.x = RelPosX( data[i - 1] );
1020 pt.y = RelPosY( data[i] );
1021 chain.Append( pt );
1022 }
1023 chain.SetClosed( true );
1024
1025 chain.Move( -center );
1026 chain.Rotate( -pad->GetOrientation() );
1027 pad->AddPrimitivePoly( chain, 0, true );
1028 }
1029
1030 wxString holeDia = arr[9];
1031 if( !holeDia.IsEmpty() )
1032 {
1033 double holeD = ConvertSize( holeDia ) * 2;
1034 double holeL = 0;
1035
1036 wxString holeLength = arr[13];
1037 if( !holeLength.IsEmpty() )
1038 holeL = ConvertSize( holeLength );
1039
1040 if( holeL > 0 )
1041 {
1042 pad->SetDrillShape( PAD_DRILL_SHAPE_OBLONG );
1043
1044 if( size.x < size.y )
1045 pad->SetDrillSize( VECTOR2I( holeD, holeL ) );
1046 else
1047 pad->SetDrillSize( VECTOR2I( holeL, holeD ) );
1048 }
1049 else
1050 {
1051 pad->SetDrillShape( PAD_DRILL_SHAPE_CIRCLE );
1052 pad->SetDrillSize( VECTOR2I( holeD, holeD ) );
1053 }
1054 }
1055
1056 wxString pasteExp = arr[17];
1057 if( !pasteExp.IsEmpty() )
1058 {
1059 double pasteExpansion = ConvertSize( pasteExp );
1060 pad->SetLocalSolderPasteMargin( pasteExpansion );
1061 }
1062
1063 wxString maskExp = arr[18];
1064 if( !maskExp.IsEmpty() )
1065 {
1066 double maskExpansion = ConvertSize( maskExp );
1067 pad->SetLocalSolderMaskMargin( maskExpansion );
1068 }
1069
1070 padContainer->Add( pad.release(), ADD_MODE::APPEND );
1071 }
1072 }
1073}
1074
1075
1077 const VECTOR2D& aOrigin, const EDA_ANGLE& aOrientation, int aLayer, BOARD* aParent,
1078 std::map<wxString, wxString> aParams,
1079 std::map<wxString, std::unique_ptr<FOOTPRINT>>& aFootprintMap, wxArrayString aShapes )
1080{
1081 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>( aParent );
1082
1083 if( aLayer == 2 ) // Bottom layer
1084 {
1085 footprint->SetLayer( B_Cu );
1086 footprint->SetOrientation( aOrientation - ANGLE_180 );
1087 }
1088 else
1089 {
1090 footprint->SetLayer( F_Cu );
1091 footprint->SetOrientation( aOrientation );
1092 }
1093
1094 footprint->Value().SetText( aParams[wxS( "package" )] );
1095
1096 m_relOrigin = aOrigin;
1097
1098 ParseToBoardItemContainer( footprint.get(), aParent, aParams, aFootprintMap, aShapes );
1099
1100 // Heal board outlines
1101 std::vector<PCB_SHAPE*> shapes;
1102 std::vector<std::unique_ptr<PCB_SHAPE>> newShapes;
1103
1104 for( BOARD_ITEM* item : footprint->GraphicalItems() )
1105 {
1106 if( !item->IsOnLayer( Edge_Cuts ) )
1107 continue;
1108
1109 if( item->Type() == PCB_SHAPE_T )
1110 shapes.push_back( static_cast<PCB_SHAPE*>( item ) );
1111 }
1112
1113 ConnectBoardShapes( shapes, newShapes, SHAPE_JOIN_DISTANCE );
1114
1115 for( std::unique_ptr<PCB_SHAPE>& ptr : newShapes )
1116 footprint->Add( ptr.release(), ADD_MODE::APPEND );
1117
1118 return footprint.release();
1119}
1120
1121
1123 std::map<wxString, std::unique_ptr<FOOTPRINT>>& aFootprintMap,
1124 wxArrayString aShapes )
1125{
1126 m_relOrigin = aOrigin;
1127
1128 ParseToBoardItemContainer( aBoard, nullptr, {}, aFootprintMap, aShapes );
1129
1130 // Heal board outlines
1131 std::vector<PCB_SHAPE*> shapes;
1132 std::vector<std::unique_ptr<PCB_SHAPE>> newShapes;
1133
1134 for( BOARD_ITEM* item : aBoard->Drawings() )
1135 {
1136 if( !item->IsOnLayer( Edge_Cuts ) )
1137 continue;
1138
1139 if( item->Type() == PCB_SHAPE_T )
1140 shapes.push_back( static_cast<PCB_SHAPE*>( item ) );
1141 }
1142
1143 ConnectBoardShapes( shapes, newShapes, SHAPE_JOIN_DISTANCE );
1144
1145 for( std::unique_ptr<PCB_SHAPE>& ptr : newShapes )
1146 aBoard->Add( ptr.release(), ADD_MODE::APPEND );
1147}
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:282
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:1810
unsigned GetNetCount() const
Definition: board.h:884
const DRAWINGS & Drawings() const
Definition: board.h:325
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:243
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:181
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:580
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:2191
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition: footprint.cpp:968
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:504
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:575
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:978
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:881
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:118
VECTOR2< double > VECTOR2D
Definition: vector2d.h:587
VECTOR2< int > VECTOR2I
Definition: vector2d.h:588