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