KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pads_sch_symbol_builder.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) 2025 KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 3
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
21
22#include <lib_symbol.h>
23#include <sch_shape.h>
24#include <sch_pin.h>
25#include <sch_text.h>
26#include <pin_type.h>
27#include <layer_ids.h>
28#include <sch_screen.h>
29#include <sch_sheet_path.h>
30#include <sch_symbol.h>
31#include <stroke_params.h>
32
33#include <advanced_config.h>
34#include <io/pads/pads_common.h>
35
36#include <algorithm>
37#include <array>
38#include <cctype>
39#include <cmath>
40#include <tuple>
41
42
43namespace PADS_SCH
44{
45
50
51
55
56
57int PADS_SCH_SYMBOL_BUILDER::toKiCadUnits( double aPadsValue ) const
58{
59 // PADS Logic ASCII schematics always store geometry in mils. The UNITS field selects only
60 // the design-rules unit and must not scale the schematic coordinates.
61 return schIUScale.MilsToIU( aPadsValue );
62}
63
64
66{
67 LIB_SYMBOL* libSymbol = new LIB_SYMBOL( wxString::FromUTF8( aSymbolDef.name ) );
68
69 // Add graphics
70 for( const SYMBOL_GRAPHIC& graphic : aSymbolDef.graphics )
71 {
72 std::vector<SCH_SHAPE*> shapes = createShapes( graphic );
73
74 for( SCH_SHAPE* shape : shapes )
75 libSymbol->AddDrawItem( shape );
76 }
77
78 // Add pins
79 bool mapDiodeAK = isDiodeAKPinSet( aSymbolDef.pins );
80
81 for( const SYMBOL_PIN& pin : aSymbolDef.pins )
82 {
83 SCH_PIN* schPin = createPin( pin, libSymbol, mapDiodeAK );
84
85 if( schPin )
86 libSymbol->AddDrawItem( schPin );
87 }
88
89 // Add embedded text labels
90 for( const SYMBOL_TEXT& text : aSymbolDef.texts )
91 {
92 if( SCH_TEXT* schText = createSymbolText( text ) )
93 libSymbol->AddDrawItem( schText );
94 }
95
96 libSymbol->SetShowPinNumbers( false );
97 libSymbol->SetShowPinNames( false );
98
99 return libSymbol;
100}
101
102
104{
105 auto it = m_symbolCache.find( aSymbolDef.name );
106
107 if( it != m_symbolCache.end() )
108 return it->second.get();
109
110 LIB_SYMBOL* newSymbol = BuildSymbol( aSymbolDef );
111 m_symbolCache[aSymbolDef.name] = std::unique_ptr<LIB_SYMBOL>( newSymbol );
112
113 return newSymbol;
114}
115
116
118 const std::vector<SYMBOL_DEF>& aSymbolDefs )
119{
120 // Build a lookup from CAEDECAL name to definition
121 std::map<std::string, const SYMBOL_DEF*> symDefByName;
122
123 for( const SYMBOL_DEF& sd : aSymbolDefs )
124 symDefByName[sd.name] = &sd;
125
126 int gateCount = static_cast<int>( aPartType.gates.size() );
127 LIB_SYMBOL* libSymbol = new LIB_SYMBOL( wxString::FromUTF8( aPartType.name ) );
128 libSymbol->SetUnitCount( gateCount, false );
129 libSymbol->LockUnits( true );
130
131 for( int gi = 0; gi < gateCount; gi++ )
132 {
133 const GATE_DEF& gate = aPartType.gates[gi];
134 int unit = gi + 1;
135
136 // Resolve the CAEDECAL for this gate
137 std::string decalName;
138
139 if( !gate.decal_names.empty() )
140 decalName = gate.decal_names[0];
141
142 auto sdIt = symDefByName.find( decalName );
143
144 if( sdIt == symDefByName.end() )
145 continue;
146
147 const SYMBOL_DEF& symDef = *sdIt->second;
148
149 // Add graphics for this unit
150 for( const SYMBOL_GRAPHIC& graphic : symDef.graphics )
151 {
152 std::vector<SCH_SHAPE*> shapes = createShapes( graphic );
153
154 for( SCH_SHAPE* shape : shapes )
155 {
156 shape->SetUnit( unit );
157 libSymbol->AddDrawItem( shape );
158 }
159 }
160
161 // Add pins with PARTTYPE overrides
162 std::vector<SYMBOL_PIN> pins = applyGateOverrides( symDef.pins, gate );
163 bool mapDiodeAK = isDiodeAKPinSet( pins );
164
165 for( const SYMBOL_PIN& pin : pins )
166 {
167 SCH_PIN* schPin = createPin( pin, libSymbol, mapDiodeAK );
168
169 if( schPin )
170 {
171 schPin->SetUnit( unit );
172 libSymbol->AddDrawItem( schPin );
173 }
174 }
175
176 // Add embedded text labels for this unit
177 for( const SYMBOL_TEXT& text : symDef.texts )
178 {
179 if( SCH_TEXT* schText = createSymbolText( text, unit ) )
180 libSymbol->AddDrawItem( schText );
181 }
182 }
183
184 libSymbol->SetShowPinNumbers( true );
185 libSymbol->SetShowPinNames( true );
186
187 return libSymbol;
188}
189
190
192 const std::vector<SYMBOL_DEF>& aSymbolDefs )
193{
194 // Use a prefixed key to avoid collision with CAEDECAL symbols that may
195 // share the same name as the PARTTYPE (e.g. both named "TL082").
196 std::string cacheKey = "parttype:" + aPartType.name;
197 auto it = m_symbolCache.find( cacheKey );
198
199 if( it != m_symbolCache.end() )
200 return it->second.get();
201
202 LIB_SYMBOL* newSymbol = BuildMultiUnitSymbol( aPartType, aSymbolDefs );
203 m_symbolCache[cacheKey] = std::unique_ptr<LIB_SYMBOL>( newSymbol );
204
205 return newSymbol;
206}
207
208
210 const SYMBOL_DEF& aSymbolDef )
211{
212 // Cache by PARTTYPE + CAEDECAL pair. A single-gate PARTTYPE with multiple decal
213 // variants (e.g. horizontal vs vertical resistor) needs a separate LIB_SYMBOL per
214 // variant because the graphics and pin positions differ.
215 std::string cacheKey = aPartType.name + ":" + aSymbolDef.name;
216 auto it = m_symbolCache.find( cacheKey );
217
218 if( it != m_symbolCache.end() )
219 return it->second.get();
220
221 if( aPartType.gates.empty() )
222 return nullptr;
223
224 // Build from the CAEDECAL then apply pin overrides from the PARTTYPE gate
225 LIB_SYMBOL* libSymbol = new LIB_SYMBOL( wxString::FromUTF8( aSymbolDef.name ) );
226
227 for( const SYMBOL_GRAPHIC& graphic : aSymbolDef.graphics )
228 {
229 std::vector<SCH_SHAPE*> shapes = createShapes( graphic );
230
231 for( SCH_SHAPE* shape : shapes )
232 libSymbol->AddDrawItem( shape );
233 }
234
235 const GATE_DEF& gate = aPartType.gates[0];
236 std::vector<SYMBOL_PIN> pins = applyGateOverrides( aSymbolDef.pins, gate );
237 bool mapDiodeAK = isDiodeAKPinSet( pins );
238
239 for( const SYMBOL_PIN& pin : pins )
240 {
241 SCH_PIN* schPin = createPin( pin, libSymbol, mapDiodeAK );
242
243 if( schPin )
244 libSymbol->AddDrawItem( schPin );
245 }
246
247 for( const SYMBOL_TEXT& text : aSymbolDef.texts )
248 {
249 if( SCH_TEXT* schText = createSymbolText( text ) )
250 libSymbol->AddDrawItem( schText );
251 }
252
253 // Show pin names/numbers if any gate pin has an explicit name
254 bool hasPinNames = false;
255
256 for( const PARTTYPE_PIN& pin : gate.pins )
257 {
258 if( !pin.pin_name.empty() )
259 {
260 hasPinNames = true;
261 break;
262 }
263 }
264
265 // Connectors number their pins even though they carry no pin names. A single
266 // multi-pin connector placement (no per-pin reference suffix) still routes here,
267 // so force pin numbers on for connector part types.
268 libSymbol->SetShowPinNumbers( hasPinNames || aPartType.is_connector );
269 libSymbol->SetShowPinNames( hasPinNames );
270
271 m_symbolCache[cacheKey] = std::unique_ptr<LIB_SYMBOL>( libSymbol );
272
273 return libSymbol;
274}
275
276
278 const SYMBOL_DEF& aSymbolDef,
279 const std::string& aPinNumber )
280{
281 std::string cacheKey = aPartType.name + ":" + aSymbolDef.name + ":" + aPinNumber;
282 auto it = m_symbolCache.find( cacheKey );
283
284 if( it != m_symbolCache.end() )
285 return it->second.get();
286
287 LIB_SYMBOL* libSymbol = new LIB_SYMBOL( wxString::FromUTF8( aSymbolDef.name ) );
288
289 for( const SYMBOL_GRAPHIC& graphic : aSymbolDef.graphics )
290 {
291 std::vector<SCH_SHAPE*> shapes = createShapes( graphic );
292
293 for( SCH_SHAPE* shape : shapes )
294 libSymbol->AddDrawItem( shape );
295 }
296
297 // Create pin(s) from the CAEDECAL but override the pin number
298 for( size_t p = 0; p < aSymbolDef.pins.size(); p++ )
299 {
300 SYMBOL_PIN pin = aSymbolDef.pins[p];
301 pin.number = aPinNumber;
302
303 if( !aPartType.gates.empty() && p < aPartType.gates[0].pins.size() )
304 {
305 pin.name = aPartType.gates[0].pins[p].pin_name;
306
307 if( aPartType.gates[0].pins[p].pin_type != 0 )
308 pin.type = PADS_SCH_PARSER::ParsePinTypeChar( aPartType.gates[0].pins[p].pin_type );
309 }
310
311 SCH_PIN* schPin = createPin( pin, libSymbol );
312
313 if( schPin )
314 libSymbol->AddDrawItem( schPin );
315 }
316
317 for( const SYMBOL_TEXT& text : aSymbolDef.texts )
318 {
319 if( SCH_TEXT* schText = createSymbolText( text ) )
320 libSymbol->AddDrawItem( schText );
321 }
322
323 libSymbol->SetShowPinNumbers( false );
324 libSymbol->SetShowPinNames( false );
325
326 m_symbolCache[cacheKey] = std::unique_ptr<LIB_SYMBOL>( libSymbol );
327
328 return libSymbol;
329}
330
331
333 const SYMBOL_DEF& aSymbolDef,
334 const std::vector<std::string>& aPinNumbers )
335{
336 int unitCount = static_cast<int>( aPinNumbers.size() );
337 LIB_SYMBOL* libSymbol = new LIB_SYMBOL( wxString::FromUTF8( aPartType.name ) );
338 libSymbol->SetUnitCount( unitCount, false );
339 libSymbol->LockUnits( true );
340
341 // Build a lookup from pin ID to PARTTYPE pin definition
342 std::map<std::string, const PARTTYPE_PIN*> ptPinById;
343
344 if( !aPartType.gates.empty() )
345 {
346 for( const PARTTYPE_PIN& ptPin : aPartType.gates[0].pins )
347 ptPinById[ptPin.pin_id] = &ptPin;
348 }
349
350 for( int u = 0; u < unitCount; u++ )
351 {
352 int unit = u + 1;
353
354 for( const SYMBOL_GRAPHIC& graphic : aSymbolDef.graphics )
355 {
356 std::vector<SCH_SHAPE*> shapes = createShapes( graphic );
357
358 for( SCH_SHAPE* shape : shapes )
359 {
360 shape->SetUnit( unit );
361 libSymbol->AddDrawItem( shape );
362 }
363 }
364
365 // One pin per unit with the correct pin number
366 if( !aSymbolDef.pins.empty() )
367 {
368 SYMBOL_PIN pin = aSymbolDef.pins[0];
369 pin.number = aPinNumbers[u];
370
371 auto ptPinIt = ptPinById.find( aPinNumbers[u] );
372
373 if( ptPinIt != ptPinById.end() )
374 {
375 if( ptPinIt->second->pin_type != 0 )
376 pin.type = PADS_SCH_PARSER::ParsePinTypeChar( ptPinIt->second->pin_type );
377
378 if( !ptPinIt->second->pin_name.empty() )
379 pin.name = ptPinIt->second->pin_name;
380 }
381
382 SCH_PIN* schPin = createPin( pin, libSymbol );
383
384 if( schPin )
385 {
386 schPin->SetUnit( unit );
387 libSymbol->AddDrawItem( schPin );
388 }
389 }
390
391 for( const SYMBOL_TEXT& text : aSymbolDef.texts )
392 {
393 if( SCH_TEXT* schText = createSymbolText( text, unit ) )
394 libSymbol->AddDrawItem( schText );
395 }
396 }
397
398 libSymbol->SetShowPinNumbers( true );
399 libSymbol->SetShowPinNames( false );
400
401 return libSymbol;
402}
403
404
406 const SYMBOL_DEF& aSymbolDef,
407 const std::vector<std::string>& aPinNumbers,
408 const std::string& aCacheKey )
409{
410 auto it = m_symbolCache.find( aCacheKey );
411
412 if( it != m_symbolCache.end() )
413 return it->second.get();
414
415 LIB_SYMBOL* newSymbol = BuildMultiUnitConnectorSymbol( aPartType, aSymbolDef, aPinNumbers );
416 m_symbolCache[aCacheKey] = std::unique_ptr<LIB_SYMBOL>( newSymbol );
417
418 return newSymbol;
419}
420
421
422bool PADS_SCH_SYMBOL_BUILDER::HasSymbol( const std::string& aName ) const
423{
424 return m_symbolCache.find( aName ) != m_symbolCache.end();
425}
426
427
428LIB_SYMBOL* PADS_SCH_SYMBOL_BUILDER::GetSymbol( const std::string& aName ) const
429{
430 auto it = m_symbolCache.find( aName );
431
432 if( it != m_symbolCache.end() )
433 return it->second.get();
434
435 return nullptr;
436}
437
438
440{
441 SCH_SHAPE* shape = nullptr;
442
443 switch( aGraphic.type )
444 {
447 {
448 bool hasArcs = false;
449
450 for( const GRAPHIC_POINT& pt : aGraphic.points )
451 {
452 if( pt.arc.has_value() )
453 {
454 hasArcs = true;
455 break;
456 }
457 }
458
459 if( !hasArcs )
460 {
461 shape = new SCH_SHAPE( SHAPE_T::POLY, LAYER_DEVICE );
462
463 for( const auto& pt : aGraphic.points )
464 shape->AddPoint( VECTOR2I( toKiCadUnits( pt.coord.x ), -toKiCadUnits( pt.coord.y ) ) );
465 }
466 else
467 {
468 // Mixed line/arc path requires multiple shapes. Return nullptr here and let
469 // BuildSymbol handle this via createShapes() instead.
470 return nullptr;
471 }
472
473 break;
474 }
475
477 {
479
480 if( aGraphic.points.size() >= 2 )
481 {
482 VECTOR2I start( toKiCadUnits( aGraphic.points[0].coord.x ), -toKiCadUnits( aGraphic.points[0].coord.y ) );
483 VECTOR2I end( toKiCadUnits( aGraphic.points[1].coord.x ), -toKiCadUnits( aGraphic.points[1].coord.y ) );
484
485 shape->SetStart( start );
486 shape->SetEnd( end );
487 }
488
489 break;
490 }
491
493 {
494 shape = new SCH_SHAPE( SHAPE_T::CIRCLE, LAYER_DEVICE );
495
496 VECTOR2I center( toKiCadUnits( aGraphic.center.x ), -toKiCadUnits( aGraphic.center.y ) );
497 int radius = toKiCadUnits( aGraphic.radius );
498
499 shape->SetStart( center );
500 shape->SetEnd( VECTOR2I( center.x + radius, center.y ) );
501
502 break;
503 }
504
506 {
507 shape = new SCH_SHAPE( SHAPE_T::ARC, LAYER_DEVICE );
508
509 VECTOR2I center( toKiCadUnits( aGraphic.center.x ), -toKiCadUnits( aGraphic.center.y ) );
510 int radius = toKiCadUnits( aGraphic.radius );
511
512 // Convert angles from PADS format to KiCad
513 // PADS uses degrees, KiCad uses tenths of degrees for arc definition
514 double startAngle = aGraphic.start_angle * M_PI / 180.0;
515 double endAngle = aGraphic.end_angle * M_PI / 180.0;
516
517 VECTOR2I startPt( center.x + radius * cos( startAngle ), center.y - radius * sin( startAngle ) );
518 VECTOR2I endPt( center.x + radius * cos( endAngle ), center.y - radius * sin( endAngle ) );
519
520 shape->SetStart( startPt );
521 shape->SetEnd( endPt );
522 shape->SetCenter( center );
523
524 break;
525 }
526 }
527
528 if( shape )
529 {
530 int lineWidth = toKiCadUnits( aGraphic.line_width );
531
532 if( lineWidth == 0 )
533 lineWidth = toKiCadUnits( m_params.line_width );
534
535 shape->SetStroke( STROKE_PARAMS( lineWidth, PADS_COMMON::PadsLineStyleToKiCad( aGraphic.line_style ) ) );
536
537 if( aGraphic.filled )
539 }
540
541 return shape;
542}
543
544
545std::vector<SCH_SHAPE*> PADS_SCH_SYMBOL_BUILDER::createShapes( const SYMBOL_GRAPHIC& aGraphic )
546{
547 std::vector<SCH_SHAPE*> result;
548
549 // Try the simple single-shape path first
550 SCH_SHAPE* single = createShape( aGraphic );
551
552 if( single )
553 {
554 result.push_back( single );
555 return result;
556 }
557
558 // Mixed line/arc path: emit individual segments
559 int lineWidth = toKiCadUnits( aGraphic.line_width );
560
561 if( lineWidth == 0 )
562 lineWidth = toKiCadUnits( m_params.line_width );
563
565
566 for( size_t i = 0; i + 1 < aGraphic.points.size(); i++ )
567 {
568 const GRAPHIC_POINT& cur = aGraphic.points[i];
569 const GRAPHIC_POINT& next = aGraphic.points[i + 1];
570
571 VECTOR2I startPt( toKiCadUnits( cur.coord.x ), -toKiCadUnits( cur.coord.y ) );
572 VECTOR2I endPt( toKiCadUnits( next.coord.x ), -toKiCadUnits( next.coord.y ) );
573
574 if( cur.arc.has_value() )
575 {
576 const ARC_DATA& ad = *cur.arc;
577 double cx = ( ad.bbox_x1 + ad.bbox_x2 ) / 2.0;
578 double cy = ( ad.bbox_y1 + ad.bbox_y2 ) / 2.0;
579 VECTOR2I center( toKiCadUnits( cx ), -toKiCadUnits( cy ) );
580
581 VECTOR2I midPt = padsSchArcMidpoint( startPt, endPt, center );
582
583 // The initial midpoint is always on the minor arc side (between start
584 // and end radii). Flip to the major arc side when the sweep exceeds
585 // 180 degrees. The sign of the angle encodes CW/CCW direction in PADS
586 // but does not affect which semicircle the arc occupies.
587 if( std::abs( ad.angle ) > 1800 )
588 {
589 midPt.x = 2 * center.x - midPt.x;
590 midPt.y = 2 * center.y - midPt.y;
591 }
592
594 arc->SetArcGeometry( startPt, midPt, endPt );
595 arc->SetStroke( STROKE_PARAMS( lineWidth, lineStyle ) );
596
597 if( aGraphic.filled )
599
600 result.push_back( arc );
601 }
602 else
603 {
604 if( startPt == endPt )
605 continue;
606
608 line->AddPoint( startPt );
609 line->AddPoint( endPt );
610 line->SetStroke( STROKE_PARAMS( lineWidth, lineStyle ) );
611
612 if( aGraphic.filled )
614
615 result.push_back( line );
616 }
617 }
618
619 return result;
620}
621
622
624{
625 if( aText.content.empty() )
626 return nullptr;
627
628 SCH_TEXT* schText = new SCH_TEXT( VECTOR2I( toKiCadUnits( aText.position.x ), -toKiCadUnits( aText.position.y ) ),
629 wxString::FromUTF8( aText.content ), LAYER_DEVICE );
630
631 if( aText.size > 0.0 )
632 {
633 int scaledSize = toKiCadUnits( aText.size );
634 int charHeight = static_cast<int>( scaledSize * ADVANCED_CFG::GetCfg().m_PadsSchTextHeightScale );
635 int charWidth = static_cast<int>( scaledSize * ADVANCED_CFG::GetCfg().m_PadsSchTextWidthScale );
636 schText->SetTextSize( VECTOR2I( charWidth, charHeight ) );
637 }
638
639 if( aText.rotation != 0.0 )
640 schText->SetTextAngleDegrees( aText.rotation );
641
642 if( aUnit != 0 )
643 schText->SetUnit( aUnit );
644
645 return schText;
646}
647
648
649std::vector<SYMBOL_PIN> PADS_SCH_SYMBOL_BUILDER::applyGateOverrides( const std::vector<SYMBOL_PIN>& aDecalPins,
650 const GATE_DEF& aGate )
651{
652 std::vector<SYMBOL_PIN> pins = aDecalPins;
653
654 for( size_t p = 0; p < pins.size() && p < aGate.pins.size(); p++ )
655 {
656 pins[p].name = aGate.pins[p].pin_name;
657 pins[p].number = aGate.pins[p].pin_id;
658
659 if( aGate.pins[p].pin_type != 0 )
660 pins[p].type = PADS_SCH_PARSER::ParsePinTypeChar( aGate.pins[p].pin_type );
661 }
662
663 return pins;
664}
665
666
667bool PADS_SCH_SYMBOL_BUILDER::isDiodeAKPinSet( const std::vector<SYMBOL_PIN>& aPins )
668{
669 if( aPins.size() != 2 )
670 return false;
671
672 bool haveA = false;
673 bool haveK = false;
674
675 for( const SYMBOL_PIN& pin : aPins )
676 {
677 if( !pin.name.empty() )
678 return false;
679
680 if( pin.number == "A" )
681 haveA = true;
682 else if( pin.number == "K" )
683 haveK = true;
684 else
685 return false;
686 }
687
688 return haveA && haveK;
689}
690
691
692SCH_PIN* PADS_SCH_SYMBOL_BUILDER::createPin( const SYMBOL_PIN& aPin, LIB_SYMBOL* aParent, bool aMapDiodeAK )
693{
694 SCH_PIN* pin = new SCH_PIN( aParent );
695
696 // Set pin name and number
697 if( aMapDiodeAK && aPin.number == "A" )
698 {
699 pin->SetName( wxString::FromUTF8( aPin.number ) );
700 pin->SetNumber( wxT( "2" ) );
701 }
702 else if( aMapDiodeAK && aPin.number == "K" )
703 {
704 pin->SetName( wxString::FromUTF8( aPin.number ) );
705 pin->SetNumber( wxT( "1" ) );
706 }
707 else
708 {
709 pin->SetName( wxString::FromUTF8( aPin.name ) );
710 pin->SetNumber( wxString::FromUTF8( aPin.number ) );
711 }
712
713 // Set pin position (end point where wire connects)
714 VECTOR2I pos( toKiCadUnits( aPin.position.x ), -toKiCadUnits( aPin.position.y ) );
715 pin->SetPosition( pos );
716
717 // Set pin length
718 int length = toKiCadUnits( aPin.length );
719 pin->SetLength( length );
720
721 // Determine pin orientation from the T-line angle and side fields.
722 // The angle indicates pin text rotation (0=horizontal, 90=vertical) while
723 // the side field indicates which edge of the symbol body the pin is on.
724 // Pin decal names containing "VRT" indicate perpendicular pins.
726 bool isVerticalDecal = ( aPin.pin_decal_name.find( "VRT" ) != std::string::npos );
727 int angle = static_cast<int>( aPin.rotation ) % 360;
728
729 if( isVerticalDecal )
730 {
731 orientation = ( aPin.side == 2 ) ? PIN_ORIENTATION::PIN_UP : PIN_ORIENTATION::PIN_DOWN;
732 }
733 else if( angle >= 45 && angle < 135 )
734 {
735 // Sides 0,1 (horizontal edges) point up; sides 2,3 (vertical edges) point down
736 orientation = ( aPin.side >= 2 ) ? PIN_ORIENTATION::PIN_DOWN : PIN_ORIENTATION::PIN_UP;
737 }
738 else if( angle >= 225 && angle < 315 )
739 {
740 orientation = ( aPin.side >= 2 ) ? PIN_ORIENTATION::PIN_UP : PIN_ORIENTATION::PIN_DOWN;
741 }
742 else if( angle >= 135 && angle < 225 )
743 {
744 orientation = ( aPin.side & 1 ) ? PIN_ORIENTATION::PIN_RIGHT : PIN_ORIENTATION::PIN_LEFT;
745 }
746 else
747 {
748 orientation = ( aPin.side & 1 ) ? PIN_ORIENTATION::PIN_LEFT : PIN_ORIENTATION::PIN_RIGHT;
749 }
750
751 pin->SetOrientation( orientation );
752
753 // Set electrical type
754 ELECTRICAL_PINTYPE pinType = static_cast<ELECTRICAL_PINTYPE>( mapPinType( aPin.type ) );
755 pin->SetType( pinType );
756
757 // Set graphic style
759
760 if( aPin.inverted )
762 else if( aPin.clock )
763 pinShape = GRAPHIC_PINSHAPE::CLOCK;
764
765 pin->SetShape( pinShape );
766
767 int pinTextSize = schIUScale.MilsToIU( 50 );
768 pin->SetNumberTextSize( pinTextSize );
769 pin->SetNameTextSize( pinTextSize );
770
771 return pin;
772}
773
774
777enum class POWER_STYLE
778{
779 GROUND_BARS, // three descending horizontal bars, body below the pin
780 FILLED_BAR, // one thick filled bar, body below the pin
781 FILLED_ARROW, // filled triangle, body above the pin
782 OPEN_ARROW, // two open arrow strokes, body below the pin
783 OPEN_CIRCLE // open circle, body above the pin
784};
785
786
787static POWER_STYLE powerStyleFromName( const std::string& aUpperName )
788{
789 if( aUpperName == "GND" || aUpperName == "GNDA" || aUpperName == "GNDPWR" || aUpperName == "EARTH"
790 || aUpperName == "CHASSIS" )
791 {
793 }
794
795 if( aUpperName == "GNDD" || aUpperName == "PWR_BAR" )
797
798 if( aUpperName == "PWR_TRIANGLE" )
800
801 if( aUpperName == "VEE" || aUpperName == "VSS" )
803
805}
806
807
808static SCH_SHAPE* addPolyline( LIB_SYMBOL* aSymbol, const std::vector<VECTOR2I>& aPoints, int aWidth = 0 )
809{
811
812 for( const VECTOR2I& point : aPoints )
813 shape->AddPoint( point );
814
815 shape->SetStroke( STROKE_PARAMS( aWidth, LINE_STYLE::SOLID ) );
816 aSymbol->AddDrawItem( shape );
817
818 return shape;
819}
820
821
822static void addPowerPin( LIB_SYMBOL* aSymbol, const std::string& aKiCadName, PIN_ORIENTATION aOrientation )
823{
824 SCH_PIN* pin = new SCH_PIN( aSymbol );
825 pin->SetNumber( wxT( "1" ) );
826 pin->SetName( wxString::FromUTF8( aKiCadName ) );
828 pin->SetVisible( false );
829 pin->SetLength( 0 );
830 pin->SetPosition( VECTOR2I( 0, 0 ) );
831 pin->SetOrientation( aOrientation );
832 aSymbol->AddDrawItem( pin );
833}
834
835
837{
838 // Convert mm coordinates from KiCad power symbol library to internal units
839 auto mm = [&]( double v )
840 {
841 return schIUScale.mmToIU( v );
842 };
843
844 LIB_SYMBOL* sym = new LIB_SYMBOL( wxString::FromUTF8( aKiCadName ) );
845 sym->SetGlobalPower();
846 sym->SetShowPinNumbers( false );
847 sym->SetShowPinNames( false );
848
849 // Determine which visual style to use based on the KiCad symbol name
850 std::string upper = aKiCadName;
851 std::transform( upper.begin(), upper.end(), upper.begin(),
852 []( unsigned char c )
853 {
854 return std::toupper( c );
855 } );
856
857 switch( powerStyleFromName( upper ) )
858 {
860 {
861 const std::array<std::tuple<double, double, double>, 3> bars{ std::tuple{ -1.27, 1.27, -1.27 },
862 std::tuple{ -0.762, 0.762, -1.778 },
863 std::tuple{ -0.254, 0.254, -2.286 } };
864
865 for( const auto& [x1, x2, y] : bars )
866 addPolyline( sym, { VECTOR2I( mm( x1 ), mm( y ) ), VECTOR2I( mm( x2 ), mm( y ) ) } );
867
868 addPolyline( sym, { VECTOR2I( 0, 0 ), VECTOR2I( 0, mm( -1.27 ) ) } );
869 addPowerPin( sym, aKiCadName, PIN_ORIENTATION::PIN_DOWN );
870 break;
871 }
872
874 {
875 // Placed with 180 degree rotation for positive supplies (+V1) so the bar points up on
876 // the schematic. Negative supplies (-V1) use it unrotated.
878 bar->SetStart( VECTOR2I( mm( -1.27 ), mm( -1.524 ) ) );
879 bar->SetEnd( VECTOR2I( mm( 1.27 ), mm( -2.032 ) ) );
880 bar->SetStroke( STROKE_PARAMS( mm( 0.254 ), LINE_STYLE::SOLID ) );
882 sym->AddDrawItem( bar );
883
884 addPolyline( sym, { VECTOR2I( mm( 0 ), mm( 0 ) ), VECTOR2I( mm( 0 ), mm( -1.524 ) ) } );
885 addPowerPin( sym, aKiCadName, PIN_ORIENTATION::PIN_DOWN );
886 break;
887 }
888
890 {
891 SCH_SHAPE* tri = addPolyline( sym, { VECTOR2I( mm( 0.762 ), mm( 1.27 ) ),
892 VECTOR2I( mm( -0.762 ), mm( 1.27 ) ),
893 VECTOR2I( mm( 0 ), mm( 2.54 ) ),
894 VECTOR2I( mm( 0.762 ), mm( 1.27 ) ) } );
896
897 addPolyline( sym, { VECTOR2I( mm( 0 ), mm( 0 ) ), VECTOR2I( mm( 0 ), mm( 1.27 ) ) } );
898 addPowerPin( sym, aKiCadName, PIN_ORIENTATION::PIN_UP );
899 break;
900 }
901
903 addPolyline( sym, { VECTOR2I( mm( -0.762 ), mm( -1.27 ) ), VECTOR2I( mm( 0 ), mm( -2.54 ) ) } );
904 addPolyline( sym, { VECTOR2I( mm( 0 ), mm( -2.54 ) ), VECTOR2I( mm( 0.762 ), mm( -1.27 ) ) } );
905 addPolyline( sym, { VECTOR2I( mm( 0 ), mm( 0 ) ), VECTOR2I( mm( 0 ), mm( -2.54 ) ) } );
906 addPowerPin( sym, aKiCadName, PIN_ORIENTATION::PIN_DOWN );
907 break;
908
910 {
912 circle->SetCenter( VECTOR2I( 0, mm( 2.032 ) ) );
913 circle->SetEnd( VECTOR2I( mm( 0.635 ), mm( 2.032 ) ) );
914 circle->SetStroke( STROKE_PARAMS( 0, LINE_STYLE::SOLID ) );
915 circle->SetFillMode( FILL_T::NO_FILL );
916 sym->AddDrawItem( circle );
917
918 addPolyline( sym, { VECTOR2I( 0, 0 ), VECTOR2I( 0, mm( 1.397 ) ) } );
919 addPowerPin( sym, aKiCadName, PIN_ORIENTATION::PIN_UP );
920 break;
921 }
922 }
923
924 sym->GetReferenceField().SetText( wxT( "#PWR" ) );
925 sym->GetReferenceField().SetVisible( false );
926
927 return sym;
928}
929
930
931std::string PADS_SCH_SYMBOL_BUILDER::GetPowerStyleFromVariant( const std::string& aDecalName,
932 const std::string& aPinType )
933{
934 std::string upper = aDecalName;
935 std::transform( upper.begin(), upper.end(), upper.begin(),
936 []( unsigned char c )
937 {
938 return std::toupper( c );
939 } );
940
941 bool isPositive = !upper.empty() && upper[0] == '+';
942 bool isGround = ( aPinType == "G" );
943
944 if( upper.find( "RAIL" ) != std::string::npos )
945 return isPositive ? "PWR_BAR" : "GNDD";
946
947 if( upper.find( "ARROW" ) != std::string::npos )
948 return isPositive ? "PWR_TRIANGLE" : "VEE";
949
950 if( upper.find( "BUBBLE" ) != std::string::npos )
951 return isPositive ? "VCC" : "VEE";
952
953 if( isGround )
954 {
955 if( upper.find( "CH" ) != std::string::npos )
956 return "Chassis";
957
958 return "GND";
959 }
960
961 if( isPositive )
962 return "VCC";
963
964 return "VEE";
965}
966
967
969{
970 int next = 1;
971
972 if( !aSheet )
973 return next;
974
975 // Walk the destination directly; SCHEMATIC::Hierarchy() is a cache the importer has
976 // no reason to have refreshed mid-load
977 for( const SCH_SHEET_PATH& path : SCH_SHEET_LIST( aSheet ) )
978 {
979 SCH_SCREEN* screen = path.LastScreen();
980
981 if( !screen )
982 continue;
983
984 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
985 {
986 wxString digits;
987 long ordinal = 0;
988
989 if( static_cast<SCH_SYMBOL*>( item )->GetRef( &path ).StartsWith( wxS( "#PWR" ), &digits )
990 && digits.ToLong( &ordinal ) )
991 {
992 next = std::max( next, static_cast<int>( ordinal ) + 1 );
993 }
994 }
995 }
996
997 return next;
998}
999
1000
1002 const std::vector<PARTTYPE_DEF::SIGPIN>& aSigpins )
1003{
1004 if( !aSymbol )
1005 return;
1006
1007 // Collect existing pin numbers to avoid duplicates
1008 std::set<wxString> existingPins;
1009
1010 for( const SCH_ITEM& item : aSymbol->GetDrawItems() )
1011 {
1012 if( item.Type() == SCH_PIN_T )
1013 existingPins.insert( static_cast<const SCH_PIN&>( item ).GetNumber() );
1014 }
1015
1016 for( const PARTTYPE_DEF::SIGPIN& sp : aSigpins )
1017 {
1018 wxString pinNum = wxString::FromUTF8( sp.pin_number );
1019
1020 if( existingPins.count( pinNum ) )
1021 continue;
1022
1023 SCH_PIN* pin = new SCH_PIN( aSymbol );
1024 pin->SetNumber( pinNum );
1025 pin->SetName( wxString::FromUTF8( sp.net_name ) );
1027 pin->SetVisible( false );
1028 pin->SetLength( 0 );
1029 pin->SetPosition( VECTOR2I( 0, 0 ) );
1030 pin->SetShape( GRAPHIC_PINSHAPE::LINE );
1031
1032 aSymbol->AddDrawItem( pin );
1033 existingPins.insert( pinNum );
1034 }
1035}
1036
1037
1039{
1040 switch( aPadsType )
1041 {
1042 case PIN_TYPE::INPUT: return static_cast<int>( ELECTRICAL_PINTYPE::PT_INPUT );
1043 case PIN_TYPE::OUTPUT: return static_cast<int>( ELECTRICAL_PINTYPE::PT_OUTPUT );
1044 case PIN_TYPE::BIDIRECTIONAL: return static_cast<int>( ELECTRICAL_PINTYPE::PT_BIDI );
1045 case PIN_TYPE::TRISTATE: return static_cast<int>( ELECTRICAL_PINTYPE::PT_TRISTATE );
1046 case PIN_TYPE::OPEN_COLLECTOR: return static_cast<int>( ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR );
1047 case PIN_TYPE::OPEN_EMITTER: return static_cast<int>( ELECTRICAL_PINTYPE::PT_OPENEMITTER );
1048 case PIN_TYPE::POWER: return static_cast<int>( ELECTRICAL_PINTYPE::PT_POWER_IN );
1049 case PIN_TYPE::PASSIVE: return static_cast<int>( ELECTRICAL_PINTYPE::PT_PASSIVE );
1051 default: return static_cast<int>( ELECTRICAL_PINTYPE::PT_UNSPECIFIED );
1052 }
1053}
1054
1055
1056bool PADS_SCH_SYMBOL_BUILDER::IsPowerSymbol( const std::string& aName )
1057{
1058 // Convert to uppercase for case-insensitive comparison
1059 std::string upper = aName;
1060 std::transform( upper.begin(), upper.end(), upper.begin(),
1061 []( unsigned char c )
1062 {
1063 return std::toupper( c );
1064 } );
1065
1066 // Check for ground variants
1067 if( upper == "GND" || upper == "AGND" || upper == "DGND" || upper == "PGND" || upper == "EARTH"
1068 || upper == "CHASSIS" || upper == "VSS" || upper == "0V" )
1069 {
1070 return true;
1071 }
1072
1073 // Check for power supply variants
1074 if( upper == "VCC" || upper == "VDD" || upper == "VEE" || upper == "VPP" || upper == "VBAT" || upper == "VBUS"
1075 || upper == "V+" || upper == "V-" )
1076 {
1077 return true;
1078 }
1079
1080 // Check for voltage patterns like +3V3, +5V, -12V, +V1, -V2, etc.
1081 if( upper.length() >= 2 && ( upper[0] == '+' || upper[0] == '-' ) )
1082 return true;
1083
1084 return false;
1085}
1086
1087
1088std::optional<LIB_ID> PADS_SCH_SYMBOL_BUILDER::GetKiCadPowerSymbolId( const std::string& aPadsName )
1089{
1090 // Convert to uppercase for case-insensitive comparison
1091 std::string upper = aPadsName;
1092 std::transform( upper.begin(), upper.end(), upper.begin(),
1093 []( unsigned char c )
1094 {
1095 return std::toupper( c );
1096 } );
1097
1098 // Map common power symbol names to KiCad power library symbols
1099 struct PowerMapping
1100 {
1101 const char* padsName;
1102 const char* kicadSymbol;
1103 };
1104
1105 static const PowerMapping mappings[] = {
1106 { "GND", "GND" }, { "AGND", "GND" }, { "DGND", "GNDD" }, { "PGND", "GNDPWR" }, { "EARTH", "Earth" },
1107 { "CHASSIS", "Chassis" }, { "VSS", "VSS" }, { "0V", "GND" }, { "VCC", "VCC" }, { "VDD", "VDD" },
1108 { "VEE", "VEE" }, { "VPP", "VPP" }, { "VBAT", "VBAT" }, { "VBUS", "VBUS" }, { "V+", "VCC" },
1109 { "V-", "VEE" }, { "+5V", "+5V" }, { "-5V", "-5V" }, { "+3V3", "+3V3" }, { "+3.3V", "+3V3" },
1110 { "+12V", "+12V" }, { "-12V", "-12V" }, { "+15V", "+15V" }, { "-15V", "-15V" }, { "+1V8", "+1V8" },
1111 { "+2V5", "+2V5" }, { "+9V", "+9V" }, { "+24V", "+24V" },
1112 };
1113
1114 for( const auto& mapping : mappings )
1115 {
1116 if( upper == mapping.padsName )
1117 {
1118 LIB_ID libId;
1119 libId.SetLibNickname( "power" );
1120 libId.SetLibItemName( mapping.kicadSymbol );
1121 return libId;
1122 }
1123 }
1124
1125 // Generic handling for +/- prefixed names not in the table
1126 if( upper.length() >= 2 && upper[0] == '+' )
1127 {
1128 LIB_ID libId;
1129 libId.SetLibNickname( "power" );
1130 libId.SetLibItemName( "VCC" );
1131 return libId;
1132 }
1133
1134 if( upper.length() >= 2 && upper[0] == '-' )
1135 {
1136 LIB_ID libId;
1137 libId.SetLibNickname( "power" );
1138 libId.SetLibItemName( "VEE" );
1139 return libId;
1140 }
1141
1142 return std::nullopt;
1143}
1144
1145} // namespace PADS_SCH
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:123
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
virtual void SetEnd(const VECTOR2I &aEnd)
Definition eda_shape.h:329
void SetCenter(const VECTOR2I &aCenter)
void SetArcGeometry(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Set the three controlling points for an arc.
void SetFillMode(FILL_T aFill)
virtual void SetStart(const VECTOR2I &aStart)
Definition eda_shape.h:279
virtual void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
Definition eda_text.cpp:495
virtual void SetVisible(bool aVisible)
Definition eda_text.cpp:342
void SetTextAngleDegrees(double aOrientation)
Definition eda_text.h:181
EE_TYPE OfType(KICAD_T aType) const
Definition sch_rtree.h:248
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:45
int SetLibItemName(const UTF8 &aLibItemName)
Override the library item name portion of the LIB_ID to aLibItemName.
Definition lib_id.cpp:124
int SetLibNickname(const UTF8 &aLibNickname)
Override the logical library name portion of the LIB_ID to aLibNickname.
Definition lib_id.cpp:113
Define a library symbol object.
Definition lib_symbol.h:119
void SetGlobalPower()
void LockUnits(bool aLockUnits)
Set interchangeable the property for symbol units.
Definition lib_symbol.h:365
LIB_ITEMS_CONTAINER & GetDrawItems()
Return a reference to the draw item list.
Definition lib_symbol.h:832
void SetUnitCount(int aCount, bool aDuplicateDrawItems)
Set the units per symbol count.
void AddDrawItem(SCH_ITEM *aItem, bool aSort=true)
Add a new draw aItem to the draw object list and sort according to aSort.
SCH_FIELD & GetReferenceField()
Return reference to the reference designator field.
Definition lib_symbol.h:441
static PIN_TYPE ParsePinTypeChar(char aTypeChar)
LIB_SYMBOL * BuildMultiUnitSymbol(const PARTTYPE_DEF &aPartType, const std::vector< SYMBOL_DEF > &aSymbolDefs)
Build a composite multi-unit symbol from a multi-gate PARTTYPE.
bool HasSymbol(const std::string &aName) const
void AddHiddenPowerPins(LIB_SYMBOL *aSymbol, const std::vector< PARTTYPE_DEF::SIGPIN > &aSigpins)
Add hidden PT_POWER_IN pins from PARTTYPE SIGPIN entries, skipping duplicate numbers.
static std::vector< SYMBOL_PIN > applyGateOverrides(const std::vector< SYMBOL_PIN > &aDecalPins, const GATE_DEF &aGate)
Return the decal's pins with the gate's name, number and type overrides applied.
LIB_SYMBOL * GetSymbol(const std::string &aName) const
int toKiCadUnits(double aPadsValue) const
LIB_SYMBOL * GetOrCreateMultiUnitSymbol(const PARTTYPE_DEF &aPartType, const std::vector< SYMBOL_DEF > &aSymbolDefs)
Return the cached multi-unit symbol for the PARTTYPE, building it if needed, so all instances of the ...
static std::optional< LIB_ID > GetKiCadPowerSymbolId(const std::string &aPadsName)
Map a PADS power symbol name to a KiCad power library LIB_ID, or nullopt if unmapped.
std::vector< SCH_SHAPE * > createShapes(const SYMBOL_GRAPHIC &aGraphic)
LIB_SYMBOL * BuildKiCadPowerSymbol(const std::string &aKiCadName)
Build a power symbol using hard-coded KiCad-standard graphics, or nullptr if the name is unrecognized...
PADS_SCH_SYMBOL_BUILDER(const PARAMETERS &aParams)
SCH_PIN * createPin(const SYMBOL_PIN &aPin, LIB_SYMBOL *aParent, bool aMapDiodeAK=false)
static bool IsPowerSymbol(const std::string &aName)
static std::string GetPowerStyleFromVariant(const std::string &aDecalName, const std::string &aPinType)
Map a PADS special_variant decal name and pin type to a power symbol style name for BuildKiCadPowerSy...
SCH_SHAPE * createShape(const SYMBOL_GRAPHIC &aGraphic)
Create a SCH_SHAPE from a PADS graphic element.
LIB_SYMBOL * GetOrCreateSymbol(const SYMBOL_DEF &aSymbolDef)
Return the cached symbol for the given definition, building and caching it if needed.
LIB_SYMBOL * GetOrCreateConnectorPinSymbol(const PARTTYPE_DEF &aPartType, const SYMBOL_DEF &aSymbolDef, const std::string &aPinNumber)
Return a connector symbol variant carrying a specific pin number, since PADS connectors reuse one dec...
LIB_SYMBOL * GetOrCreateMultiUnitConnectorSymbol(const PARTTYPE_DEF &aPartType, const SYMBOL_DEF &aSymbolDef, const std::vector< std::string > &aPinNumbers, const std::string &aCacheKey)
Return the cached multi-unit connector symbol, building it if needed.
LIB_SYMBOL * BuildMultiUnitConnectorSymbol(const PARTTYPE_DEF &aPartType, const SYMBOL_DEF &aSymbolDef, const std::vector< std::string > &aPinNumbers)
Build a multi-unit connector symbol with one unit per pin, letting all of a connector's individually ...
std::map< std::string, std::unique_ptr< LIB_SYMBOL > > m_symbolCache
LIB_SYMBOL * BuildSymbol(const SYMBOL_DEF &aSymbolDef)
Build a KiCad LIB_SYMBOL from a PADS symbol definition.
static bool isDiodeAKPinSet(const std::vector< SYMBOL_PIN > &aPins)
True when aPins is a bare two-pin A/K pair, i.e.
SCH_TEXT * createSymbolText(const SYMBOL_TEXT &aText, int aUnit=0)
Build the configured SCH_TEXT for one symbol text field, or nullptr when its content is empty.
LIB_SYMBOL * GetOrCreatePartTypeSymbol(const PARTTYPE_DEF &aPartType, const SYMBOL_DEF &aSymbolDef)
Return a single-gate symbol with PARTTYPE pin overrides applied at build time.
static int NextFreePowerOrdinal(SCH_SHEET *aSheet)
Return the first 1-based ordinal that no "#PWRnnnn" reference under aSheet uses.
void SetText(const wxString &aText) override
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:165
virtual void SetUnit(int aUnit)
Definition sch_item.h:236
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition sch_screen.h:118
void SetStroke(const STROKE_PARAMS &aStroke) override
Definition sch_shape.cpp:97
void AddPoint(const VECTOR2I &aPosition)
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:48
Schematic symbol object.
Definition sch_symbol.h:75
Simple container to manage line stroke parameters.
virtual void SetShowPinNumbers(bool aShow)
Set or clear the pin number visibility flag.
Definition symbol.h:170
virtual void SetShowPinNames(bool aShow)
Set or clear the pin name visibility flag.
Definition symbol.h:164
@ NO_FILL
Definition eda_fill.h:30
@ FILLED_SHAPE
Fill with object color.
Definition eda_fill.h:31
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
Definition eda_shape.h:57
double m_PadsSchTextWidthScale
PADS text width scale factor for schematic imports.
double m_PadsSchTextHeightScale
PADS text height scale factor for schematic imports.
@ LAYER_DEVICE
Definition layer_ids.h:488
LINE_STYLE PadsLineStyleToKiCad(int aPadsStyle)
Convert a PADS line style integer to a KiCad LINE_STYLE enum value.
VECTOR2I padsSchArcMidpoint(const VECTOR2I &aStart, const VECTOR2I &aEnd, const VECTOR2I &aCenter)
Midpoint of the arc through aStart and aEnd about aCenter, on the minor-arc side (the perpendicular b...
POWER_STYLE
The distinct body shapes KiCad power symbols are drawn with.
static SCH_SHAPE * addPolyline(LIB_SYMBOL *aSymbol, const std::vector< VECTOR2I > &aPoints, int aWidth=0)
static void addPowerPin(LIB_SYMBOL *aSymbol, const std::string &aKiCadName, PIN_ORIENTATION aOrientation)
static POWER_STYLE powerStyleFromName(const std::string &aUpperName)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:411
ELECTRICAL_PINTYPE
The symbol library pin object electrical types used in ERC tests.
Definition pin_type.h:32
@ PT_INPUT
usual pin input: must be connected
Definition pin_type.h:33
@ PT_OUTPUT
usual output
Definition pin_type.h:34
@ PT_TRISTATE
tri state bus pin
Definition pin_type.h:36
@ PT_BIDI
input or output (like port for a microprocessor)
Definition pin_type.h:35
@ PT_OPENEMITTER
pin type open emitter
Definition pin_type.h:45
@ PT_OPENCOLLECTOR
pin type open collector
Definition pin_type.h:44
@ PT_POWER_IN
power input (GND, VCC for ICs). Must be connected to a power output.
Definition pin_type.h:42
@ PT_UNSPECIFIED
unknown electrical properties: creates always a warning when connected
Definition pin_type.h:41
@ PT_PASSIVE
pin for passive symbols: must be connected, and can be connected to any pin.
Definition pin_type.h:39
PIN_ORIENTATION
The symbol library pin object orientations.
Definition pin_type.h:101
@ PIN_UP
The pin extends upwards from the connection point: Probably on the bottom side of the symbol.
Definition pin_type.h:123
@ PIN_RIGHT
The pin extends rightwards from the connection point.
Definition pin_type.h:107
@ PIN_LEFT
The pin extends leftwards from the connection point: Probably on the right side of the symbol.
Definition pin_type.h:114
@ PIN_DOWN
The pin extends downwards from the connection: Probably on the top side of the symbol.
Definition pin_type.h:131
GRAPHIC_PINSHAPE
Definition pin_type.h:80
CITER next(CITER it)
Definition ptree.cpp:120
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
LINE_STYLE
Dashed line types.
std::vector< std::string > decal_names
std::vector< PARTTYPE_PIN > pins
std::optional< ARC_DATA > arc
std::vector< GATE_DEF > gates
std::vector< SYMBOL_GRAPHIC > graphics
std::vector< SYMBOL_PIN > pins
std::vector< SYMBOL_TEXT > texts
std::vector< GRAPHIC_POINT > points
std::string path
KIBIS_PIN * pin
VECTOR2I center
int radius
VECTOR2I end
SHAPE_CIRCLE circle(c.m_circle_center, c.m_circle_radius)
wxString result
Test unit parsing edge cases and error handling.
#define M_PI
@ SCH_SYMBOL_T
Definition typeinfo.h:168
@ SCH_PIN_T
Definition typeinfo.h:149
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683