KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcb_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 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
25#include "pcb_easyeda_parser.h"
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( "SOLIDREGION" ) )
434 {
435 wxString layer = arr[1];
436
437 SHAPE_POLY_SET polySet = ParseLineChains( arr[3].Trim(), pcbIUScale.mmToIU( 0.01 ) );
438
439 if( layer == wxS( "11" ) ) // Multi-layer (board cutout)
440 {
441 for( const SHAPE_POLY_SET::POLYGON& poly : polySet.CPolygons() )
442 {
443 std::unique_ptr<PCB_SHAPE> shape =
444 std::make_unique<PCB_SHAPE>( aContainer, SHAPE_T::POLY );
445
446 shape->SetLayer( Edge_Cuts );
447 shape->SetFilled( false );
448 shape->SetWidth( pcbIUScale.mmToIU( 0.1 ) );
449 shape->SetPolyShape( poly );
450
451 aContainer->Add( shape.release(), ADD_MODE::APPEND );
452 }
453 }
454 else
455 {
456 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aContainer );
457
458 PCB_LAYER_ID klayer = LayerToKi( layer );
459 zone->SetLayer( klayer );
460
461 if( IsCopperLayer( klayer ) )
462 zone->SetNet( getOrAddNetItem( arr[2] ) );
463
464 for( const SHAPE_POLY_SET::POLYGON& poly : polySet.CPolygons() )
465 zone->Outline()->AddPolygon( poly );
466
467 if( arr[4].Lower() == wxS( "cutout" ) )
468 {
469 zone->SetIsRuleArea( true );
470 zone->SetDoNotAllowCopperPour( true );
471 zone->SetDoNotAllowTracks( false );
472 zone->SetDoNotAllowVias( false );
473 zone->SetDoNotAllowPads( false );
474 zone->SetDoNotAllowFootprints( false );
475 }
476 else
477 { // solid
478 zone->SetFilledPolysList( klayer, polySet );
479 zone->SetPadConnection( ZONE_CONNECTION::FULL );
480 zone->SetIsFilled( true );
481 zone->SetNeedRefill( false );
482 }
483
484 zone->SetMinThickness( 0 );
485 zone->SetLocalClearance( 0 );
486 zone->SetAssignedPriority( 100 );
487
488 aContainer->Add( zone.release(), ADD_MODE::APPEND );
489 }
490 }
491 else if( elType == wxS( "COPPERAREA" ) )
492 {
493 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aContainer );
494
495 PCB_LAYER_ID layer = LayerToKi( arr[2] );
496 zone->SetLayer( layer );
497
498 wxString netname = arr[3];
499 if( IsCopperLayer( layer ) )
500 zone->SetNet( getOrAddNetItem( netname ) );
501
502 zone->SetLocalClearance( ConvertSize( arr[5] ) );
503 zone->SetThermalReliefGap( zone->GetLocalClearance() );
504
505 wxString fillStyle = arr[5];
506 if( fillStyle == wxS( "none" ) )
507 {
508 // Do not fill?
509 }
510
511 SHAPE_POLY_SET polySet = ParseLineChains( arr[4].Trim(), pcbIUScale.mmToIU( 0.01 ) );
512
513 for( const SHAPE_POLY_SET::POLYGON& poly : polySet.CPolygons() )
514 zone->Outline()->AddPolygon( poly );
515
516 wxString thermal = arr[8];
517 if( thermal == wxS( "direct" ) )
518 zone->SetPadConnection( ZONE_CONNECTION::FULL );
519
520 wxString keepIsland = arr[9];
521 if( keepIsland == wxS( "yes" ) )
522 zone->SetIslandRemovalMode( ISLAND_REMOVAL_MODE::NEVER );
523
524 wxString fillData = arr[10];
525 SHAPE_POLY_SET fillPolySet;
526 try
527 {
528 for( const nlohmann::json& polyData : nlohmann::json::parse( fillData ) )
529 {
530 for( const nlohmann::json& contourData : polyData )
531 {
532 SHAPE_POLY_SET contourPolySet = ParseLineChains( contourData.get<wxString>(),
533 pcbIUScale.mmToIU( 0.01 ) );
534
535 SHAPE_POLY_SET currentOutline( contourPolySet.COutline( 0 ) );
536
537 for( int i = 1; i < contourPolySet.OutlineCount(); i++ )
538 currentOutline.AddHole( contourPolySet.COutline( i ) );
539
540 fillPolySet.Append( currentOutline );
541 }
542 }
543
545
546 zone->SetFilledPolysList( layer, fillPolySet );
547 zone->SetIsFilled( true );
548 zone->SetNeedRefill( false );
549 }
550 catch( nlohmann::json::exception& e )
551 {
552 }
553
554 int fillOrder = wxAtoi( arr[13] );
555 zone->SetAssignedPriority( 100 - fillOrder );
556
557 wxString improveFabrication = arr[17];
558 if( improveFabrication == wxS( "none" ) )
559 {
560 zone->SetMinThickness( 0 );
561 }
562 else
563 {
564 // arr[1] is "stroke Width" per docs
565 int minThickness =
566 std::max( pcbIUScale.mmToIU( 0.03 ), int( ConvertSize( arr[1] ) ) );
567 zone->SetMinThickness( minThickness );
568 }
569
570 if( arr.size() > 18 )
571 {
572 zone->SetThermalReliefSpokeWidth(
573 std::max( int( ConvertSize( arr[18] ) ), zone->GetMinThickness() ) );
574 }
575 else
576 {
577 wxFAIL_MSG( wxString::Format( "COPPERAREA unexpected size %d: %s ", arr.size(),
578 shape ) );
579
580 zone->SetThermalReliefSpokeWidth( zone->GetMinThickness() );
581 }
582
583 aContainer->Add( zone.release(), ADD_MODE::APPEND );
584 }
585 else if( elType == wxS( "SVGNODE" ) )
586 {
587 nlohmann::json nodeData = nlohmann::json::parse( arr[1] );
588
589 int nodeType = nodeData.at( "nodeType" );
590 wxString layer = nodeData.at( "layerid" );
591 PCB_LAYER_ID klayer = LayerToKi( layer );
592
593 if( nodeType == 1 )
594 {
595 std::map<wxString, wxString> attributes = nodeData.at( "attrs" );
596
597 if( layer == wxS( "19" ) ) // 3DModel
598 {
599 if( !footprint )
600 continue;
601
602 auto ec_eType = get_opt( attributes, "c_etype" );
603 auto ec_rotation = get_opt( attributes, "c_rotation" );
604 auto ec_origin = get_opt( attributes, "c_origin" );
605 auto ec_width = get_opt( attributes, "c_width" );
606 auto ec_height = get_opt( attributes, "c_height" );
607 auto ez = get_opt( attributes, "z" );
608 auto etitle = get_opt( attributes, "title" );
609 auto euuid = get_opt( attributes, "uuid" );
610 auto etransform = get_opt( attributes, "transform" );
611
612 if( !ec_eType || *ec_eType != wxS( "outline3D" ) || !etitle )
613 continue;
614
615 wxString modelTitle = *etitle;
616 VECTOR3D kmodelOffset;
617 VECTOR3D kmodelRotation;
618
619 if( euuid )
620 {
621 PCB_FIELD field( footprint, footprint->GetFieldCount(),
623 field.SetLayer( Cmts_User );
624 field.SetVisible( false );
625 field.SetText( *euuid );
626 footprint->AddField( field );
627 }
628
629 /*if( etransform )
630 {
631 PCB_FIELD field( footprint, footprint->GetFieldCount(), "3D Transform" );
632 field.SetLayer( Cmts_User );
633 field.SetVisible( false );
634 field.SetText( *etransform );
635 footprint->AddField( field );
636 }*/
637
638 if( ec_width && ec_height )
639 {
640 double fitXmm = pcbIUScale.IUTomm( ScaleSize( Convert( *ec_width ) ) );
641 double fitYmm = pcbIUScale.IUTomm( ScaleSize( Convert( *ec_height ) ) );
642
643 double rounding = 0.001;
644 fitXmm = KiROUND( fitXmm / rounding ) * rounding;
645 fitYmm = KiROUND( fitYmm / rounding ) * rounding;
646
647 PCB_FIELD field( footprint, footprint->GetFieldCount(), MODEL_SIZE_KEY );
648 field.SetLayer( Cmts_User );
649 field.SetVisible( false );
650 field.SetText( wxString::FromCDouble( fitXmm ) + wxS( " " )
651 + wxString::FromCDouble( fitYmm ) );
652 footprint->AddField( field );
653 }
654
655 if( ec_origin )
656 {
657 wxArrayString orParts = wxSplit( *ec_origin, ',', '\0' );
658
659 if( orParts.size() == 2 )
660 {
661 VECTOR2D pos;
662 pos.x = Convert( orParts[0].Trim() );
663 pos.y = Convert( orParts[1].Trim() );
664
665 VECTOR2D rel = RelPos( pos );
666 kmodelOffset.x = -pcbIUScale.IUTomm( rel.x );
667 kmodelOffset.y = -pcbIUScale.IUTomm( rel.y );
668
669 RotatePoint( &kmodelOffset.x, &kmodelOffset.y,
670 -footprint->GetOrientation() );
671 }
672 }
673
674 if( ez )
675 {
676 kmodelOffset.z = pcbIUScale.IUTomm( ScaleSize( Convert( ez->Trim() ) ) );
677 }
678
679 if( ec_rotation )
680 {
681 wxArrayString rotParts = wxSplit( *ec_rotation, ',', '\0' );
682
683 if( rotParts.size() == 3 )
684 {
685 kmodelRotation.x = -Convert( rotParts[0].Trim() );
686 kmodelRotation.y = -Convert( rotParts[1].Trim() );
687 kmodelRotation.z = -Convert( rotParts[2].Trim() )
688 + footprint->GetOrientationDegrees();
689 }
690 }
691
692 if( footprint->GetLayer() == B_Cu )
693 {
694 kmodelRotation.z = 180 - kmodelRotation.z;
695 RotatePoint( &kmodelOffset.x, &kmodelOffset.y, ANGLE_180 );
696 }
697
698 FP_3DMODEL model;
699 model.m_Filename = kicadModelPrefix
700 + EscapeString( modelTitle, ESCAPE_CONTEXT::CTX_FILENAME )
701 + wxS( ".step" );
702 model.m_Offset = kmodelOffset;
703 model.m_Rotation = kmodelRotation;
704 footprint->Models().push_back( model );
705 }
706 else
707 {
708 if( auto dataStr = get_opt( attributes, "d" ) )
709 {
710 SHAPE_POLY_SET polySet =
711 ParseLineChains( dataStr->Trim(),
712 dataStr->size() < 8000 ? pcbIUScale.mmToIU( 0.005 )
713 : pcbIUScale.mmToIU( 0.05 ) );
714
715 polySet.RebuildHolesFromContours();
716
717 std::unique_ptr<PCB_GROUP> group;
718
719 if( polySet.OutlineCount() > 1 )
720 group = std::make_unique<PCB_GROUP>( aContainer );
721
722 for( const SHAPE_POLY_SET::POLYGON& poly : polySet.CPolygons() )
723 {
724 std::unique_ptr<PCB_SHAPE> shape =
725 std::make_unique<PCB_SHAPE>( aContainer, SHAPE_T::POLY );
726
727 shape->SetFilled( true );
728 shape->SetPolyShape( poly );
729 shape->SetLayer( klayer );
730 shape->SetWidth( 0 );
731
732 if( group )
733 group->AddItem( shape.get() );
734
735 aContainer->Add( shape.release(), ADD_MODE::APPEND );
736 }
737
738 if( group )
739 aContainer->Add( group.release(), ADD_MODE::APPEND );
740 }
741 }
742 }
743 else
744 {
745 THROW_IO_ERROR( wxString::Format( _( "Unknown SVGNODE nodeType %d" ), nodeType ) );
746 }
747 }
748 else if( elType == wxS( "TEXT" ) )
749 {
750 PCB_TEXT* text;
751 wxString textType = arr[1];
752 bool add = false;
753
754 if( textType == wxS( "P" ) )
755 {
756 text = footprint->GetField( REFERENCE_FIELD );
757 }
758 else if( textType == wxS( "N" ) )
759 {
760 text = footprint->GetField( VALUE_FIELD );
761 }
762 else
763 {
764 text = new PCB_TEXT( aContainer );
765 add = true;
766 }
767
768 VECTOR2D start;
769 start.x = RelPosX( arr[2] );
770 start.y = RelPosY( arr[3] );
771 text->SetPosition( start );
772
773 double thickness = ConvertSize( arr[4] );
774 text->SetTextThickness( thickness );
775
776 double rot = Convert( arr[5] );
777 text->SetTextAngleDegrees( rot );
778
779 text->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
780 text->SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM );
781
782 PCB_LAYER_ID layer = LayerToKi( arr[7] );
783 text->SetLayer( layer );
784
785 if( IsBackLayer( layer ) )
786 text->SetMirrored( true );
787
788 double height = ConvertSize( arr[9] ) * 0.8;
789 text->SetTextSize( VECTOR2I( height, height ) );
790
791 text->SetText( UnescapeHTML( arr[10] ) );
792
793 //arr[11] // Geometry data
794
795 text->SetVisible( arr[12] != wxS( "none" ) );
796
797 wxString font = arr[14];
798 if( !font.IsEmpty() )
799 text->SetFont( KIFONT::FONT::GetFont( font ) );
800
801 if( add )
802 aContainer->Add( text, ADD_MODE::APPEND );
803 }
804 else if( elType == wxS( "VIA" ) )
805 {
806 VECTOR2D center( RelPosX( arr[1] ), RelPosY( arr[2] ) );
807 int kdia = ConvertSize( arr[3] );
808 int kdrill = ConvertSize( arr[5] ) * 2;
809
810 if( footprint )
811 {
812 std::unique_ptr<PAD> pad = std::make_unique<PAD>( footprint );
813
814 pad->SetPosition( center );
815 pad->SetLayerSet( PAD::PTHMask() );
816 pad->SetAttribute( PAD_ATTRIB::PTH );
817 pad->SetShape( PAD_SHAPE::CIRCLE );
818 pad->SetSize( VECTOR2I( kdia, kdia ) );
819 pad->SetDrillShape( PAD_DRILL_SHAPE_CIRCLE );
820 pad->SetDrillSize( VECTOR2I( kdrill, kdrill ) );
821
822 footprint->Add( pad.release(), ADD_MODE::APPEND );
823 }
824 else
825 {
826 std::unique_ptr<PCB_VIA> via = std::make_unique<PCB_VIA>( aContainer );
827
828 via->SetPosition( center );
829
830 via->SetWidth( kdia );
831 via->SetNet( getOrAddNetItem( arr[4] ) );
832 via->SetDrill( kdrill );
833
834 aContainer->Add( via.release(), ADD_MODE::APPEND );
835 }
836 }
837 else if( elType == wxS( "HOLE" ) )
838 {
839 FOOTPRINT* padContainer;
840
841 VECTOR2D center( RelPosX( arr[1] ), RelPosY( arr[2] ) );
842 int kdia = ConvertSize( arr[3] ) * 2;
843 wxString holeUuid = arr[4];
844
845 if( footprint )
846 {
847 padContainer = footprint;
848 }
849 else
850 {
851 std::unique_ptr<FOOTPRINT> newFootprint =
852 std::make_unique<FOOTPRINT>( dynamic_cast<BOARD*>( aContainer ) );
853
854 wxString name = wxS( "Hole_" ) + holeUuid;
855
856 newFootprint->SetFPID( LIB_ID( wxEmptyString, name ) );
857 newFootprint->SetPosition( center );
858 newFootprint->SetLocked( true );
859
860 newFootprint->Reference().SetText( name );
861 newFootprint->Reference().SetVisible( false );
862 newFootprint->Reference().SetTextSize( HIDDEN_TEXT_SIZE );
863 newFootprint->Value().SetText( name );
864 newFootprint->Value().SetVisible( false );
865 newFootprint->Value().SetTextSize( HIDDEN_TEXT_SIZE );
866
867 padContainer = newFootprint.get();
868 aContainer->Add( newFootprint.release(), ADD_MODE::APPEND );
869 }
870
871 std::unique_ptr<PAD> pad = std::make_unique<PAD>( padContainer );
872
873 pad->SetPosition( center );
874 pad->SetLayerSet( PAD::UnplatedHoleMask() );
875 pad->SetAttribute( PAD_ATTRIB::NPTH );
876 pad->SetShape( PAD_SHAPE::CIRCLE );
877 pad->SetSize( VECTOR2I( kdia, kdia ) );
878 pad->SetDrillShape( PAD_DRILL_SHAPE_CIRCLE );
879 pad->SetDrillSize( VECTOR2I( kdia, kdia ) );
880
881 padContainer->Add( pad.release(), ADD_MODE::APPEND );
882 }
883 else if( elType == wxS( "PAD" ) )
884 {
885 FOOTPRINT* padContainer;
886
887 VECTOR2D center( RelPosX( arr[2] ), RelPosY( arr[3] ) );
888 VECTOR2D size( ConvertSize( arr[4] ), ConvertSize( arr[5] ) );
889 wxString padUuid = arr[12];
890
891 if( footprint )
892 {
893 padContainer = footprint;
894 }
895 else
896 {
897 std::unique_ptr<FOOTPRINT> newFootprint =
898 std::make_unique<FOOTPRINT>( dynamic_cast<BOARD*>( aContainer ) );
899
900 wxString name = wxS( "Pad_" ) + padUuid;
901
902 newFootprint->SetFPID( LIB_ID( wxEmptyString, name ) );
903 newFootprint->SetPosition( center );
904 newFootprint->SetLocked( true );
905
906 newFootprint->Reference().SetText( name );
907 newFootprint->Reference().SetVisible( false );
908 newFootprint->Reference().SetTextSize( HIDDEN_TEXT_SIZE );
909 newFootprint->Value().SetText( name );
910 newFootprint->Value().SetVisible( false );
911 newFootprint->Value().SetTextSize( HIDDEN_TEXT_SIZE );
912
913 padContainer = newFootprint.get();
914 aContainer->Add( newFootprint.release(), ADD_MODE::APPEND );
915 }
916
917 std::unique_ptr<PAD> pad = std::make_unique<PAD>( padContainer );
918
919 pad->SetNet( getOrAddNetItem( arr[7] ) );
920 pad->SetNumber( arr[8] );
921 pad->SetPosition( center );
922 pad->SetSize( size );
923 pad->SetOrientationDegrees( Convert( arr[11] ) );
924 pad->SetThermalSpokeAngle( ANGLE_0 );
925
926 wxString elayer = arr[6];
927 PCB_LAYER_ID klayer = LayerToKi( elayer );
928
929 bool plated = arr[15] == wxS( "Y" );
930
931 if( klayer == F_Cu )
932 {
933 pad->SetLayer( F_Cu );
934 pad->SetLayerSet( PAD::SMDMask() );
935 pad->SetAttribute( PAD_ATTRIB::SMD );
936 }
937 else if( klayer == B_Cu )
938 {
939 pad->SetLayer( B_Cu );
940 pad->SetLayerSet( FlipLayerMask( PAD::SMDMask() ) );
941 pad->SetAttribute( PAD_ATTRIB::SMD );
942 }
943 else if( elayer == wxS( "11" ) )
944 {
945 pad->SetLayerSet( plated ? PAD::PTHMask() : PAD::UnplatedHoleMask() );
946 pad->SetAttribute( plated ? PAD_ATTRIB::PTH : PAD_ATTRIB::NPTH );
947 }
948 else
949 {
950 pad->SetLayer( klayer );
951 pad->SetLayerSet( LSET( 1, klayer ) );
952 pad->SetAttribute( PAD_ATTRIB::SMD );
953 }
954
955 wxString padType = arr[1];
956 if( padType == wxS( "ELLIPSE" ) )
957 {
958 pad->SetShape( PAD_SHAPE::OVAL );
959 }
960 else if( padType == wxS( "RECT" ) )
961 {
962 pad->SetShape( PAD_SHAPE::RECTANGLE );
963 }
964 else if( padType == wxS( "OVAL" ) )
965 {
966 if( pad->GetSizeX() == pad->GetSizeY() )
967 pad->SetShape( PAD_SHAPE::CIRCLE );
968 else
969 pad->SetShape( PAD_SHAPE::OVAL );
970 }
971 else if( padType == wxS( "POLYGON" ) )
972 {
973 pad->SetShape( PAD_SHAPE::CUSTOM );
974 pad->SetAnchorPadShape( PAD_SHAPE::CIRCLE );
975 pad->SetSize( { 1, 1 } );
976
977 wxArrayString data = wxSplit( arr[10], ' ', '\0' );
978
979 SHAPE_LINE_CHAIN chain;
980 for( int i = 1; i < data.size(); i += 2 )
981 {
982 VECTOR2D pt;
983 pt.x = RelPosX( data[i - 1] );
984 pt.y = RelPosY( data[i] );
985 chain.Append( pt );
986 }
987 chain.SetClosed( true );
988
989 chain.Move( -center );
990 chain.Rotate( -pad->GetOrientation() );
991 pad->AddPrimitivePoly( chain, 0, true );
992 }
993
994 wxString holeDia = arr[9];
995 if( !holeDia.IsEmpty() )
996 {
997 double holeD = ConvertSize( holeDia ) * 2;
998 double holeL = 0;
999
1000 wxString holeLength = arr[13];
1001 if( !holeLength.IsEmpty() )
1002 holeL = ConvertSize( holeLength );
1003
1004 if( holeL > 0 )
1005 {
1006 pad->SetDrillShape( PAD_DRILL_SHAPE_OBLONG );
1007
1008 if( size.x < size.y )
1009 pad->SetDrillSize( VECTOR2I( holeD, holeL ) );
1010 else
1011 pad->SetDrillSize( VECTOR2I( holeL, holeD ) );
1012 }
1013 else
1014 {
1015 pad->SetDrillShape( PAD_DRILL_SHAPE_CIRCLE );
1016 pad->SetDrillSize( VECTOR2I( holeD, holeD ) );
1017 }
1018 }
1019
1020 wxString pasteExp = arr[17];
1021 if( !pasteExp.IsEmpty() )
1022 {
1023 double pasteExpansion = ConvertSize( pasteExp );
1024 pad->SetLocalSolderPasteMargin( pasteExpansion );
1025 }
1026
1027 wxString maskExp = arr[18];
1028 if( !maskExp.IsEmpty() )
1029 {
1030 double maskExpansion = ConvertSize( maskExp );
1031 pad->SetLocalSolderMaskMargin( maskExpansion );
1032 }
1033
1034 padContainer->Add( pad.release(), ADD_MODE::APPEND );
1035 }
1036 }
1037}
1038
1039
1041 const VECTOR2D& aOrigin, const EDA_ANGLE& aOrientation, int aLayer, BOARD* aParent,
1042 std::map<wxString, wxString> aParams,
1043 std::map<wxString, std::unique_ptr<FOOTPRINT>>& aFootprintMap, wxArrayString aShapes )
1044{
1045 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>( aParent );
1046
1047 if( aLayer == 2 ) // Bottom layer
1048 {
1049 footprint->SetLayer( B_Cu );
1050 footprint->SetOrientation( aOrientation - ANGLE_180 );
1051 }
1052 else
1053 {
1054 footprint->SetLayer( F_Cu );
1055 footprint->SetOrientation( aOrientation );
1056 }
1057
1058 footprint->Value().SetText( aParams[wxS( "package" )] );
1059
1060 m_relOrigin = aOrigin;
1061
1062 ParseToBoardItemContainer( footprint.get(), aParent, aParams, aFootprintMap, aShapes );
1063
1064 // Heal board outlines
1065 std::vector<PCB_SHAPE*> shapes;
1066 std::vector<std::unique_ptr<PCB_SHAPE>> newShapes;
1067
1068 for( BOARD_ITEM* item : footprint->GraphicalItems() )
1069 {
1070 if( !item->IsOnLayer( Edge_Cuts ) )
1071 continue;
1072
1073 if( item->Type() == PCB_SHAPE_T )
1074 shapes.push_back( static_cast<PCB_SHAPE*>( item ) );
1075 }
1076
1077 ConnectBoardShapes( shapes, newShapes, SHAPE_JOIN_DISTANCE );
1078
1079 for( std::unique_ptr<PCB_SHAPE>& ptr : newShapes )
1080 footprint->Add( ptr.release(), ADD_MODE::APPEND );
1081
1082 return footprint.release();
1083}
1084
1085
1086void PCB_EASYEDA_PARSER::ParseBoard( BOARD* aBoard, const VECTOR2D& aOrigin,
1087 std::map<wxString, std::unique_ptr<FOOTPRINT>>& aFootprintMap,
1088 wxArrayString aShapes )
1089{
1090 m_relOrigin = aOrigin;
1091
1092 ParseToBoardItemContainer( aBoard, nullptr, {}, aFootprintMap, aShapes );
1093
1094 // Heal board outlines
1095 std::vector<PCB_SHAPE*> shapes;
1096 std::vector<std::unique_ptr<PCB_SHAPE>> newShapes;
1097
1098 for( BOARD_ITEM* item : aBoard->Drawings() )
1099 {
1100 if( !item->IsOnLayer( Edge_Cuts ) )
1101 continue;
1102
1103 if( item->Type() == PCB_SHAPE_T )
1104 shapes.push_back( static_cast<PCB_SHAPE*>( item ) );
1105 }
1106
1107 ConnectBoardShapes( shapes, newShapes, SHAPE_JOIN_DISTANCE );
1108
1109 for( std::unique_ptr<PCB_SHAPE>& ptr : newShapes )
1110 aBoard->Add( ptr.release(), ADD_MODE::APPEND );
1111}
const char * name
Definition: DXF_plotter.cpp:57
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:109
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:259
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:276
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition: board.cpp:855
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:1642
DRAWINGS & Drawings()
Definition: board.h:321
unsigned GetNetCount() const
Definition: board.h:858
double ConvertSize(const wxString &aValue)
std::vector< SHAPE_LINE_CHAIN > ParseLineChains(const wxString &aData, int aArcMinSegLen)
static double Convert(const wxString &aValue)
double RelPosX(double aValue)
double RelPosY(double aValue)
VECTOR2< T > RelPos(const VECTOR2< T > &aVec)
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:229
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:183
void SetFPID(const LIB_ID &aFPID)
Definition: footprint.h:231
int GetFieldCount() const
Return the number of fields in this symbol.
Definition: footprint.h:674
EDA_ANGLE GetOrientation() const
Definition: footprint.h:209
PCB_FIELD * AddField(const PCB_FIELD &aField)
Add a field to the symbol.
Definition: footprint.cpp:336
double GetOrientationDegrees() const
Definition: footprint.h:225
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition: footprint.h:218
void Move(const VECTOR2I &aMoveVector) override
Move this object.
Definition: footprint.cpp:1895
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition: footprint.cpp:724
std::vector< FP_3DMODEL > & Models()
Definition: footprint.h:202
PCB_FIELD * GetField(MANDATORY_FIELD_T aFieldType)
Return a mandatory field in this symbol.
Definition: footprint.cpp:260
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:556
Handle the data for a net.
Definition: netinfo.h:56
static LSET PTHMask()
layer set for a through hole pad
Definition: pad.cpp:194
static LSET UnplatedHoleMask()
layer set for a mechanical unplated through hole pad
Definition: pad.cpp:215
static LSET SMDMask()
layer set for a SMD pad on Front layer
Definition: pad.cpp:201
void ParseBoard(BOARD *aBoard, const VECTOR2D &aOrigin, std::map< wxString, std::unique_ptr< FOOTPRINT > > &aFootprintMap, wxArrayString aShapes)
void ParseToBoardItemContainer(BOARD_ITEM_CONTAINER *aContainer, BOARD *aParent, std::map< wxString, wxString > paramMap, std::map< wxString, std::unique_ptr< FOOTPRINT > > &aFootprintMap, wxArrayString shapes)
PCB_EASYEDA_PARSER(PROGRESS_REPORTER *aProgressReporter)
PCB_LAYER_ID LayerToKi(const wxString &aLayer)
double ScaleSize(double aValue) override
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)
A progress reporter interface for use in multi-threaded environments.
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_180
Definition: eda_angle.h:441
@ DEGREES_T
Definition: eda_angle.h:31
static constexpr EDA_ANGLE & ANGLE_0
Definition: eda_angle.h:437
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:950
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:853
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:114
@ Dwgs_User
Definition: layer_ids.h:110
@ F_Paste
Definition: layer_ids.h:102
@ In9_Cu
Definition: layer_ids.h:74
@ Cmts_User
Definition: layer_ids.h:111
@ 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:107
@ B_Cu
Definition: layer_ids.h:96
@ User_5
Definition: layer_ids.h:128
@ Eco1_User
Definition: layer_ids.h:112
@ F_Mask
Definition: layer_ids.h:108
@ In21_Cu
Definition: layer_ids.h:86
@ In23_Cu
Definition: layer_ids.h:88
@ B_Paste
Definition: layer_ids.h:101
@ In15_Cu
Definition: layer_ids.h:80
@ In2_Cu
Definition: layer_ids.h:67
@ F_Fab
Definition: layer_ids.h:121
@ In10_Cu
Definition: layer_ids.h:75
@ F_SilkS
Definition: layer_ids.h:105
@ In4_Cu
Definition: layer_ids.h:69
@ Eco2_User
Definition: layer_ids.h:113
@ 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:104
@ 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:65
@ In18_Cu
Definition: layer_ids.h:83
@ In25_Cu
Definition: layer_ids.h:90
@ B_Fab
Definition: layer_ids.h:120
LSET FlipLayerMask(LSET aMask, int aCopperLayersCount)
Calculate the mask layer when flipping a footprint.
Definition: lset.cpp:599
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:70
@ PAD_DRILL_SHAPE_OBLONG
Definition: pad_shapes.h:71
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)
Class to handle a set of BOARD_ITEMs.
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:87
constexpr int mmToIU(double mm) const
Definition: base_units.h:89
@ 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_BOTTOM
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