KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_io_pads.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 along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
24
25#include <lib_symbol.h>
26#include <page_info.h>
27#include <sch_junction.h>
28#include <sch_label.h>
29#include <sch_line.h>
30#include <sch_pin.h>
31#include <sch_screen.h>
32#include <sch_shape.h>
33#include <sch_sheet.h>
34#include <sch_sheet_path.h>
35#include <sch_symbol.h>
36#include <sch_text.h>
37#include <schematic.h>
38#include <schematic_settings.h>
40
41#include <math/util.h>
42#include <stroke_params.h>
43
44#include <advanced_config.h>
45#include <io/pads/pads_common.h>
46#include <locale_io.h>
47#include <progress_reporter.h>
48#include <reporter.h>
49
50#include <fstream>
51#include <map>
52#include <set>
53#include <wx/log.h>
54
55
60static std::string stripGateSuffix( const std::string& aRef )
61{
62 size_t sepPos = aRef.rfind( '-' );
63
64 if( sepPos == std::string::npos )
65 sepPos = aRef.rfind( '.' );
66
67 if( sepPos != std::string::npos && sepPos + 1 < aRef.size()
68 && std::isalpha( static_cast<unsigned char>( aRef[sepPos + 1] ) ) )
69 {
70 return aRef.substr( 0, sepPos );
71 }
72
73 return aRef;
74}
75
76
77static SCH_TEXT* createSchText( const PADS_SCH::TEXT_ITEM& aText, const VECTOR2I& aPos )
78{
79 SCH_TEXT* schText = new SCH_TEXT( aPos, wxString::FromUTF8( aText.content ) );
80
81 if( aText.height > 0 )
82 {
83 int scaledSize = schIUScale.MilsToIU( aText.height );
84 int charHeight = static_cast<int>( scaledSize
86 int charWidth = static_cast<int>( scaledSize
88 schText->SetTextSize( VECTOR2I( charWidth, charHeight ) );
89 }
90
91 if( aText.width_factor > 0 )
92 schText->SetTextThickness( schIUScale.MilsToIU( aText.width_factor ) );
93
94 // PADS justification: value = vertical_offset + horizontal_code
95 // Vertical offsets: bottom=0, top=2, middle=8
96 // Horizontal codes: left=0, right=1, center=4
97 int justVal = aText.justification;
98 int hCode = 0;
99 int vGroup = 0;
100
101 if( justVal >= 8 )
102 {
103 vGroup = 2; // middle
104 hCode = justVal - 8;
105 }
106 else if( justVal >= 2 )
107 {
108 vGroup = 1; // top
109 hCode = justVal - 2;
110 }
111 else
112 {
113 vGroup = 0; // bottom
114 hCode = justVal;
115 }
116
117 switch( hCode )
118 {
119 default:
120 case 0: schText->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT ); break;
121 case 1: schText->SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT ); break;
122 case 4: schText->SetHorizJustify( GR_TEXT_H_ALIGN_CENTER ); break;
123 }
124
125 switch( vGroup )
126 {
127 default:
128 case 0: schText->SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM ); break;
129 case 1: schText->SetVertJustify( GR_TEXT_V_ALIGN_TOP ); break;
130 case 2: schText->SetVertJustify( GR_TEXT_V_ALIGN_CENTER ); break;
131 }
132
133 if( aText.rotation != 0 )
134 schText->SetTextAngleDegrees( aText.rotation * 90.0 );
135
136 return schText;
137}
138
139
147static int computePowerOrientation( const std::string& aOpcId,
148 const std::vector<PADS_SCH::SCH_SIGNAL>& aSignals,
149 const VECTOR2I& aOpcPos, bool aPinUp, int aPageHeightIU )
150{
151 // Find the wire endpoint matching this OPC and get the adjacent vertex
152 std::string opcRef = "@@@O" + aOpcId;
153 VECTOR2I adjPos = aOpcPos;
154 bool found = false;
155
156 for( const auto& signal : aSignals )
157 {
158 for( const auto& wire : signal.wires )
159 {
160 if( wire.vertices.size() < 2 )
161 continue;
162
163 if( wire.endpoint_a == opcRef )
164 {
165 adjPos = VECTOR2I(
166 schIUScale.MilsToIU( KiROUND( wire.vertices[1].x ) ),
167 aPageHeightIU
168 - schIUScale.MilsToIU( KiROUND( wire.vertices[1].y ) ) );
169 found = true;
170 break;
171 }
172
173 if( wire.endpoint_b == opcRef )
174 {
175 size_t last = wire.vertices.size() - 1;
176 adjPos = VECTOR2I(
177 schIUScale.MilsToIU( KiROUND( wire.vertices[last - 1].x ) ),
178 aPageHeightIU
179 - schIUScale.MilsToIU(
180 KiROUND( wire.vertices[last - 1].y ) ) );
181 found = true;
182 break;
183 }
184 }
185
186 if( found )
187 break;
188 }
189
190 if( !found )
192
193 // Wire goes from aOpcPos toward adjPos
194 int dx = adjPos.x - aOpcPos.x;
195 int dy = adjPos.y - aOpcPos.y;
196
197 // Determine which direction the wire approaches from (relative to OPC position).
198 // The symbol body should face AWAY from the wire.
199 // In KiCad Y-down coordinates: dy > 0 means wire goes down from OPC.
200
201 if( std::abs( dx ) >= std::abs( dy ) )
202 {
203 // Horizontal wire
204 if( dx > 0 )
205 {
206 // Wire goes right → body should face left
209 }
210 else
211 {
212 // Wire goes left → body should face right
215 }
216 }
217 else
218 {
219 // Vertical wire
220 if( dy > 0 )
221 {
222 // Wire goes down → body should face up
225 }
226 else
227 {
228 // Wire goes up → body should face down
231 }
232 }
233}
234
235
236SCH_IO_PADS::SCH_IO_PADS() : SCH_IO( wxS( "PADS Logic" ) )
237{
238}
239
240
244
245
246bool SCH_IO_PADS::CanReadSchematicFile( const wxString& aFileName ) const
247{
248 if( !SCH_IO::CanReadSchematicFile( aFileName ) )
249 return false;
250
251 return checkFileHeader( aFileName );
252}
253
254
255bool SCH_IO_PADS::CanReadLibrary( const wxString& aFileName ) const
256{
257 if( !SCH_IO::CanReadLibrary( aFileName ) )
258 return false;
259
260 return checkFileHeader( aFileName );
261}
262
263
264SCH_SHEET* SCH_IO_PADS::LoadSchematicFile( const wxString& aFileName,
265 SCHEMATIC* aSchematic,
266 SCH_SHEET* aAppendToMe,
267 const std::map<std::string, UTF8>* aProperties )
268{
269 wxCHECK( !aFileName.IsEmpty() && aSchematic, nullptr );
270
271 LOCALE_IO setlocale;
272
273 SCH_SHEET* rootSheet = nullptr;
274
275 if( aAppendToMe )
276 {
277 wxCHECK_MSG( aSchematic->IsValid(), nullptr, "Can't append to a schematic with no root!" );
278 rootSheet = aAppendToMe;
279 }
280 else
281 {
282 rootSheet = new SCH_SHEET( aSchematic );
283 rootSheet->SetFileName( aFileName );
284 aSchematic->SetTopLevelSheets( { rootSheet } );
285 }
286
287 if( !rootSheet->GetScreen() )
288 {
289 SCH_SCREEN* screen = new SCH_SCREEN( aSchematic );
290 screen->SetFileName( aFileName );
291 rootSheet->SetScreen( screen );
292
293 const_cast<KIID&>( rootSheet->m_Uuid ) = screen->GetUuid();
294 }
295
296 SCH_SHEET_PATH rootPath;
297 rootPath.push_back( rootSheet );
298
299 SCH_SCREEN* rootScreen = rootSheet->GetScreen();
300 wxCHECK( rootScreen, nullptr );
301
302 SCH_SHEET_INSTANCE sheetInstance;
303 sheetInstance.m_Path = rootPath.Path();
304 sheetInstance.m_PageNumber = wxT( "#" );
305 rootScreen->m_sheetInstances.emplace_back( sheetInstance );
306
308 m_progressReporter->SetNumPhases( 3 );
309
311 std::string filename( aFileName.ToUTF8() );
312
313 if( !parser.Parse( filename ) )
314 {
315 THROW_IO_ERROR( wxString::Format( wxT( "Failed to parse PADS file: %s" ), aFileName ) );
316 }
317
319 m_progressReporter->BeginPhase( 1 );
320
321 const PADS_SCH::PARAMETERS& params = parser.GetParameters();
322 PADS_SCH::PADS_SCH_SYMBOL_BUILDER symbolBuilder( params );
323 PADS_SCH::PADS_SCH_SCHEMATIC_BUILDER schBuilder( params, aSchematic );
324
325 // Detect gate suffix separator from multi-gate part references (e.g. U17-A → '-')
326 for( const auto& part : parser.GetPartPlacements() )
327 {
328 const std::string& ref = part.reference;
329 size_t dashPos = ref.rfind( '-' );
330 size_t dotPos = ref.rfind( '.' );
331 size_t sepPos = std::string::npos;
332
333 if( dashPos != std::string::npos )
334 sepPos = dashPos;
335 else if( dotPos != std::string::npos )
336 sepPos = dotPos;
337
338 if( sepPos != std::string::npos && sepPos + 1 < ref.size()
339 && std::isalpha( static_cast<unsigned char>( ref[sepPos + 1] ) ) )
340 {
341 aSchematic->Settings().m_SubpartIdSeparator = static_cast<int>( ref[sepPos] );
342 aSchematic->Settings().m_SubpartFirstId = 'A';
343 break;
344 }
345 }
346
347 // Set KiCad page size to match the PADS drawing sheet
348 PAGE_INFO pageInfo;
349
350 if( !params.sheet_size.name.empty() )
351 pageInfo.SetType( wxString::FromUTF8( params.sheet_size.name ) );
352 else
353 pageInfo.SetType( PAGE_SIZE_TYPE::A );
354
355 // PADS Y-up to KiCad Y-down: Y_kicad = pageHeight - Y_pads
356 const int pageHeightIU = pageInfo.GetHeightIU( schIUScale.IU_PER_MILS );
357
358 // Build LIB_SYMBOL objects from all CAEDECAL definitions
359 for( const PADS_SCH::SYMBOL_DEF& symDef : parser.GetSymbolDefs() )
360 symbolBuilder.GetOrCreateSymbol( symDef );
361
362 std::set<int> sheetNumbers = parser.GetSheetNumbers();
363
364 if( sheetNumbers.empty() )
365 sheetNumbers.insert( 1 );
366
367 bool isSingleSheet = ( sheetNumbers.size() == 1 );
368
369 // Map sheet number -> (SCH_SHEET*, SCH_SCREEN*, SCH_SHEET_PATH)
370 struct SheetContext
371 {
372 SCH_SHEET* sheet = nullptr;
373 SCH_SCREEN* screen = nullptr;
375 };
376
377 std::map<int, SheetContext> sheetContexts;
378
379 if( isSingleSheet )
380 {
381 int sheetNum = *sheetNumbers.begin();
382 SheetContext ctx;
383 ctx.sheet = rootSheet;
384 ctx.screen = rootScreen;
385 ctx.path = rootPath;
386 ctx.screen->SetPageSettings( pageInfo );
387 sheetContexts[sheetNum] = ctx;
388 }
389 else
390 {
391 // Multi-sheet: root is a container with sub-sheets
392 int totalSheets = static_cast<int>( sheetNumbers.size() );
393
394 for( int sheetNum : sheetNumbers )
395 {
396 SCH_SHEET* subSheet = schBuilder.CreateHierarchicalSheet(
397 sheetNum, totalSheets, rootSheet, aFileName );
398
399 if( !subSheet )
400 continue;
401
402 // Find the sheet name from parser headers
403 for( const PADS_SCH::SHEET_HEADER& hdr : parser.GetSheetHeaders() )
404 {
405 if( hdr.sheet_num == sheetNum && !hdr.sheet_name.empty() )
406 {
408 wxString::FromUTF8( hdr.sheet_name ) );
409
410 break;
411 }
412 }
413
414 SCH_SHEET_PATH subPath;
415 subPath.push_back( rootSheet );
416 subPath.push_back( subSheet );
417
418 wxString pageNo = wxString::Format( wxT( "%d" ), sheetNum );
419 subPath.SetPageNumber( pageNo );
420
421 SCH_SHEET_INSTANCE subInstance;
422 subInstance.m_Path = subPath.Path();
423 subInstance.m_PageNumber = pageNo;
424 subSheet->GetScreen()->m_sheetInstances.emplace_back( subInstance );
425
426 SheetContext ctx;
427 ctx.sheet = subSheet;
428 ctx.screen = subSheet->GetScreen();
429 ctx.path = subPath;
430 ctx.screen->SetPageSettings( pageInfo );
431 sheetContexts[sheetNum] = ctx;
432 }
433 }
434
436 m_progressReporter->BeginPhase( 2 );
437
438 // Place symbols on each sheet
439 for( auto& [sheetNum, ctx] : sheetContexts )
440 {
441 std::vector<PADS_SCH::PART_PLACEMENT> parts = parser.GetPartsOnSheet( sheetNum );
442
443 for( const PADS_SCH::PART_PLACEMENT& part : parts )
444 {
445 auto ptIt = parser.GetPartTypes().find( part.part_type );
446
447 LIB_SYMBOL* libSymbol = nullptr;
448 bool isMultiGate = false;
449 bool isPower = false;
450 std::string libItemName;
451
452 if( ptIt != parser.GetPartTypes().end() )
453 {
454 const PADS_SCH::PARTTYPE_DEF& ptDef = ptIt->second;
455
456 if( ptDef.gates.size() > 1 )
457 {
458 // Multi-gate PARTTYPE: composite multi-unit symbol
459 libSymbol = symbolBuilder.GetOrCreateMultiUnitSymbol(
460 ptDef, parser.GetSymbolDefs() );
461 libItemName = ptDef.name;
462 isMultiGate = true;
463 }
464 else if( !ptDef.gates.empty() )
465 {
466 // Single-gate PARTTYPE: build with pin remapping
467 const PADS_SCH::GATE_DEF& gate = ptDef.gates[0];
468 int idx = std::max( 0, part.gate_index );
469 std::string decalName;
470
471 if( idx < static_cast<int>( gate.decal_names.size() ) )
472 decalName = gate.decal_names[idx];
473 else if( !gate.decal_names.empty() )
474 decalName = gate.decal_names[0];
475
476 const PADS_SCH::SYMBOL_DEF* symDef = parser.GetSymbolDef( decalName );
477
478 if( symDef )
479 {
480 libSymbol = symbolBuilder.GetOrCreatePartTypeSymbol( ptDef, *symDef );
481 libItemName = decalName;
482 }
483 }
484 else if( !ptDef.special_variants.empty() )
485 {
486 // Power/ground symbols
487 int idx = std::max( 0, part.gate_index );
488 idx = std::min( idx, static_cast<int>( ptDef.special_variants.size() ) - 1 );
489 std::string decalName = ptDef.special_variants[idx].decal_name;
490
491 const PADS_SCH::SYMBOL_DEF* symDef = parser.GetSymbolDef( decalName );
492
493 if( symDef )
494 {
495 libSymbol = symbolBuilder.GetOrCreateSymbol( *symDef );
496 libItemName = decalName;
497 }
498 }
499
500 if( !ptDef.special_keyword.empty() && ptDef.special_keyword != "OFF" )
501 isPower = true;
502 }
503
504 // Fallback: resolve directly by CAEDECAL name
505 if( !libSymbol )
506 {
507 const PADS_SCH::SYMBOL_DEF* symDef = parser.GetSymbolDef( part.symbol_name );
508
509 if( !symDef )
510 {
511 m_errorMessages.emplace(
512 wxString::Format( wxT( "PADS Import: symbol '%s' not found,"
513 " part '%s' skipped" ),
514 wxString::FromUTF8( part.symbol_name ),
515 wxString::FromUTF8( part.reference ) ),
517 continue;
518 }
519
520 libSymbol = symbolBuilder.GetOrCreateSymbol( *symDef );
521 libItemName = symDef->name;
522 }
523
524 if( !libSymbol )
525 continue;
526
527 if( ptIt != parser.GetPartTypes().end() && !ptIt->second.sigpins.empty() )
528 symbolBuilder.AddHiddenPowerPins( libSymbol, ptIt->second.sigpins );
529
530 if( !isPower )
531 isPower = PADS_SCH::PADS_SCH_SYMBOL_BUILDER::IsPowerSymbol( part.part_type );
532
533 // Resolve power symbol style. Prefer the PARTTYPE variant decal style
534 // (e.g. +BUBBLE → +VDC) which preserves the original PADS symbol shape,
535 // falling back to net-name matching (e.g. GND → GND, +5V → +5V).
536 std::string powerStyle;
537
538 if( isPower && ptIt != parser.GetPartTypes().end()
539 && !ptIt->second.special_variants.empty() )
540 {
541 int varIdx = std::max( 0, part.gate_index );
542 varIdx = std::min(
543 varIdx,
544 static_cast<int>( ptIt->second.special_variants.size() ) - 1 );
545 const auto& variant = ptIt->second.special_variants[varIdx];
546
548 variant.decal_name, variant.pin_type );
549 }
550
551 if( isPower && powerStyle.empty() )
552 {
553 std::string rawNetName = part.power_net_name.empty()
554 ? part.symbol_name
555 : part.power_net_name;
556
557 auto powerLibId =
559
560 if( powerLibId )
561 powerStyle = std::string( powerLibId->GetLibItemName().c_str() );
562 }
563
564 auto symbolPtr = std::make_unique<SCH_SYMBOL>();
565 SCH_SYMBOL* symbol = symbolPtr.get();
566 LIB_SYMBOL* instanceSymbol = nullptr;
567
568 if( isPower && !powerStyle.empty() )
569 {
570 instanceSymbol = symbolBuilder.BuildKiCadPowerSymbol( powerStyle );
571
572 LIB_ID libId;
573 libId.SetLibNickname( wxT( "power" ) );
574 libId.SetLibItemName( wxString::FromUTF8( powerStyle ) );
575 symbol->SetLibId( libId );
576 }
577 else
578 {
579 LIB_ID libId;
580 libId.SetLibNickname( wxT( "pads_import" ) );
581 libId.SetLibItemName( wxString::FromUTF8( libItemName ) );
582 symbol->SetLibId( libId );
583
584 instanceSymbol = new LIB_SYMBOL( *libSymbol );
585
586 if( isPower )
587 instanceSymbol->SetGlobalPower();
588 }
589
590 symbol->SetLibSymbol( instanceSymbol );
591 symbol->SetPosition( VECTOR2I(
592 schIUScale.MilsToIU( KiROUND( part.position.x ) ),
593 pageHeightIU - schIUScale.MilsToIU( KiROUND( part.position.y ) ) ) );
594
595 int orientation = SYMBOL_ORIENTATION_T::SYM_ORIENT_0;
596
597 if( part.rotation == 90.0 )
599 else if( part.rotation == 180.0 )
601 else if( part.rotation == 270.0 )
603
604 if( part.mirror_flags & 1 )
606
607 if( part.mirror_flags & 2 )
609
610 symbol->SetOrientation( orientation );
611
612 if( isMultiGate )
613 symbol->SetUnit( part.gate_index + 1 );
614 else
615 symbol->SetUnit( 1 );
616
617 // Assign deterministic UUID so PCB cross-probe can match footprints
618 // to symbols. Only the primary gate (index 0) gets the deterministic
619 // UUID since one footprint maps to one symbol instance.
620 if( !isPower && ( !isMultiGate || part.gate_index == 0 ) )
621 {
622 std::string baseRef = stripGateSuffix( part.reference );
623
624 const_cast<KIID&>( symbol->m_Uuid ) =
626 }
627
628 symbol->SetRef( &ctx.path, wxString::FromUTF8( part.reference ) );
629
630 schBuilder.ApplyPartAttributes( symbol, part );
631 schBuilder.CreateCustomFields( symbol, part );
632
633 // For passive components, override Value with VALUE1 parametric value
634 // so that e.g. C10 shows "0.1uF" instead of the generic "CAPMF0805".
635 // Also apply the VALUE1 attribute position.
636 if( ptIt != parser.GetPartTypes().end() )
637 {
638 const std::string& cat = ptIt->second.category;
639
640 if( cat == "CAP" || cat == "RES" || cat == "IND" )
641 {
642 auto valIt = part.attr_overrides.find( "VALUE1" );
643
644 if( valIt != part.attr_overrides.end() && !valIt->second.empty() )
645 {
646 symbol->SetValueFieldText( wxString::FromUTF8( valIt->second ) );
647
648 for( const auto& attr : part.attributes )
649 {
650 if( attr.name == "VALUE1" || attr.name == "Value1" )
651 {
652 SCH_FIELD* valField = symbol->GetField( FIELD_T::VALUE );
653 int fx = schIUScale.MilsToIU( KiROUND( attr.position.x ) );
654
655 if( part.mirror_flags & 1 )
656 fx = -fx;
657
658 VECTOR2I fieldPos( fx,
659 -schIUScale.MilsToIU(
660 KiROUND( attr.position.y ) ) );
661 valField->SetPosition( symbol->GetPosition() + fieldPos );
662
663 int fieldTextSize = schIUScale.MilsToIU( 50 );
664 valField->SetTextSize(
665 VECTOR2I( fieldTextSize, fieldTextSize ) );
668 break;
669 }
670 }
671 }
672 }
673 }
674
675 if( isPower )
676 {
677 symbol->GetField( FIELD_T::REFERENCE )->SetVisible( false );
678
679 wxString netName = part.power_net_name.empty()
680 ? wxString::FromUTF8( part.symbol_name )
681 : wxString::FromUTF8( part.power_net_name );
682
683 if( netName.StartsWith( wxT( "/" ) ) )
684 netName = wxT( "~{" ) + netName.Mid( 1 ) + wxT( "}" );
685
686 symbol->GetField( FIELD_T::VALUE )->SetText( netName );
687 symbol->GetField( FIELD_T::VALUE )->SetVisible( true );
688 }
689
690 symbol->AddHierarchicalReference( ctx.path.Path(),
691 wxString::FromUTF8( part.reference ),
692 symbol->GetUnit() );
693
694 symbol->ClearFlags();
695 ctx.screen->Append( symbolPtr.release() );
696 }
697 }
698
699 // Build set of power signal names so we can suppress duplicate global labels
700 // where a power symbol is placed instead. Non-power signal labels are handled
701 // by CreateNetLabels which places them at dangling wire endpoints.
702 std::set<std::string> powerSignalNames;
703
704 for( const PADS_SCH::OFF_PAGE_CONNECTOR& opc : parser.GetOffPageConnectors() )
705 {
706 if( opc.signal_name.empty() )
707 continue;
708
709 auto ptIt = parser.GetPartTypes().find( opc.symbol_lib );
710
711 if( ptIt != parser.GetPartTypes().end()
712 && !ptIt->second.special_keyword.empty() && ptIt->second.special_keyword != "OFF"
713 && !ptIt->second.special_variants.empty() )
714 {
715 int idx = std::max( 0, opc.flags2 );
716 idx = std::min( idx,
717 static_cast<int>( ptIt->second.special_variants.size() ) - 1 );
718 const auto& variant = ptIt->second.special_variants[idx];
719
721 variant.decal_name, variant.pin_type ).empty() )
722 {
723 powerSignalNames.insert( opc.signal_name );
724 }
725 }
726 }
727
728 // Build set of OPC reference IDs for non-power signal OPCs. Each entry
729 // corresponds to a wire endpoint reference like "@@@O48" that should receive
730 // its own global label with orientation derived from the wire direction.
731 std::set<std::string> signalOpcIds;
732
733 for( const PADS_SCH::OFF_PAGE_CONNECTOR& opc : parser.GetOffPageConnectors() )
734 {
735 if( opc.signal_name.empty() || powerSignalNames.count( opc.signal_name ) )
736 continue;
737
738 signalOpcIds.insert( "@@@O" + std::to_string( opc.id ) );
739 }
740
741 // Create wires and connectivity on each sheet
742 for( auto& [sheetNum, ctx] : sheetContexts )
743 {
744 std::vector<PADS_SCH::SCH_SIGNAL> sheetSignals = parser.GetSignalsOnSheet( sheetNum );
745
746 // Create wire segments from vertex data
747 for( const PADS_SCH::SCH_SIGNAL& signal : sheetSignals )
748 {
749 for( const PADS_SCH::WIRE_SEGMENT& wire : signal.wires )
750 {
751 if( wire.vertices.size() < 2 )
752 continue;
753
754 // Each consecutive pair of vertices becomes a wire segment
755 for( size_t v = 0; v + 1 < wire.vertices.size(); v++ )
756 {
757 VECTOR2I start(
758 schIUScale.MilsToIU( KiROUND( wire.vertices[v].x ) ),
759 pageHeightIU
760 - schIUScale.MilsToIU( KiROUND( wire.vertices[v].y ) ) );
762 schIUScale.MilsToIU( KiROUND( wire.vertices[v + 1].x ) ),
763 pageHeightIU
764 - schIUScale.MilsToIU( KiROUND( wire.vertices[v + 1].y ) ) );
765
766 if( start == end )
767 continue;
768
769 SCH_LINE* line = new SCH_LINE( start, SCH_LAYER_ID::LAYER_WIRE );
770 line->SetEndPoint( end );
771 line->SetConnectivityDirty();
772 ctx.screen->Append( line );
773 }
774 }
775 }
776
777 // Create junctions from TIEDOTS for this sheet
778 for( const PADS_SCH::TIED_DOT& dot : parser.GetTiedDots() )
779 {
780 if( dot.sheet_number != sheetNum )
781 continue;
782
783 VECTOR2I pos( schIUScale.MilsToIU( KiROUND( dot.position.x ) ),
784 pageHeightIU - schIUScale.MilsToIU( KiROUND( dot.position.y ) ) );
785
786 SCH_JUNCTION* junction = new SCH_JUNCTION( pos );
787 ctx.screen->Append( junction );
788 }
789
790 // Create net labels, skipping power nets that get dedicated symbols
791 schBuilder.CreateNetLabels( sheetSignals, ctx.screen, signalOpcIds,
792 powerSignalNames );
793
794 // Place off-page connectors: power/ground types become SCH_SYMBOL with
795 // KiCad standard power graphics; signal types become SCH_GLOBALLABEL.
796 int pwrIndex = 1;
797
798 for( const PADS_SCH::OFF_PAGE_CONNECTOR& opc : parser.GetOffPageConnectors() )
799 {
800 if( opc.source_sheet != sheetNum )
801 continue;
802
803 if( opc.signal_name.empty() )
804 continue;
805
806 VECTOR2I pos( schIUScale.MilsToIU( KiROUND( opc.position.x ) ),
807 pageHeightIU
808 - schIUScale.MilsToIU( KiROUND( opc.position.y ) ) );
809
810 // Resolve power style from the PARTTYPE variant definition
811 std::string powerStyle;
812 auto opcPtIt = parser.GetPartTypes().find( opc.symbol_lib );
813
814 if( opcPtIt != parser.GetPartTypes().end()
815 && !opcPtIt->second.special_keyword.empty() && opcPtIt->second.special_keyword != "OFF"
816 && !opcPtIt->second.special_variants.empty() )
817 {
818 int idx = std::max( 0, opc.flags2 );
819 idx = std::min( idx,
820 static_cast<int>(
821 opcPtIt->second.special_variants.size() ) - 1 );
822 const auto& variant = opcPtIt->second.special_variants[idx];
823
825 variant.decal_name, variant.pin_type );
826 }
827
828 if( !powerStyle.empty() )
829 {
830 LIB_SYMBOL* pwrSym = symbolBuilder.BuildKiCadPowerSymbol( powerStyle );
831
832 if( pwrSym )
833 {
834 auto symbolPtr = std::make_unique<SCH_SYMBOL>();
835 SCH_SYMBOL* symbol = symbolPtr.get();
836
837 LIB_ID libId;
838 libId.SetLibNickname( wxT( "power" ) );
839 libId.SetLibItemName( wxString::FromUTF8( powerStyle ) );
840 symbol->SetLibId( libId );
841 symbol->SetLibSymbol( pwrSym );
842 symbol->SetPosition( pos );
843 symbol->SetUnit( 1 );
844
845 // VCC and PWR_TRIANGLE have pin pointing up (body above pin).
846 // All others (GND, GNDD, PWR_BAR, VEE, Earth) have pin pointing down.
847 bool pinUp = ( powerStyle == "VCC" || powerStyle == "PWR_TRIANGLE" );
848 int orient = computePowerOrientation(
849 std::to_string( opc.id ), sheetSignals, pos, pinUp,
850 pageHeightIU );
851
852 symbol->SetOrientation( orient );
853
854 wxString netName = wxString::FromUTF8( opc.signal_name );
855
856 if( netName.StartsWith( wxT( "/" ) ) )
857 netName = wxT( "~{" ) + netName.Mid( 1 ) + wxT( "}" );
858
859 symbol->GetField( FIELD_T::VALUE )->SetText( netName );
860 symbol->GetField( FIELD_T::VALUE )->SetVisible( true );
861
862 wxString pwrRef = wxString::Format( wxT( "#PWR%03d" ), pwrIndex++ );
863 symbol->SetRef( &ctx.path, pwrRef );
864 symbol->GetField( FIELD_T::REFERENCE )->SetVisible( false );
865
866 symbol->ClearFlags();
867 ctx.screen->Append( symbolPtr.release() );
868 continue;
869 }
870 }
871
872 // Non-power signal OPCs don't create labels here. CreateNetLabels
873 // handles all signal net labels, placing them at dangling wire endpoints
874 // rather than at OPC positions (which may not land on a wire).
875 }
876 }
877
878 // Place free text items from *TEXT* section on the first (or only) sheet
879 if( !sheetContexts.empty() )
880 {
881 SCH_SCREEN* textScreen = sheetContexts.begin()->second.screen;
882
883 for( const PADS_SCH::TEXT_ITEM& textItem : parser.GetTextItems() )
884 {
885 if( textItem.content.empty() )
886 continue;
887
888 VECTOR2I pos( schIUScale.MilsToIU( KiROUND( textItem.position.x ) ),
889 pageHeightIU
890 - schIUScale.MilsToIU( KiROUND( textItem.position.y ) ) );
891
892 textScreen->Append( createSchText( textItem, pos ) );
893 }
894 }
895
896 // Place graphic lines from *LINES* section (skip the border template)
897 if( !sheetContexts.empty() )
898 {
899 SCH_SCREEN* linesScreen = sheetContexts.begin()->second.screen;
900
901 for( const PADS_SCH::LINES_ITEM& linesItem : parser.GetLinesItems() )
902 {
903 if( linesItem.name == params.border_template )
904 continue;
905
906 double ox = linesItem.origin.x;
907 double oy = linesItem.origin.y;
908
909 for( const PADS_SCH::SYMBOL_GRAPHIC& prim : linesItem.primitives )
910 {
911 int strokeWidth = prim.line_width > 0.0
912 ? schIUScale.MilsToIU( KiROUND( prim.line_width ) )
913 : 0;
914
916
918 {
920 schIUScale.MilsToIU( KiROUND( ox + prim.center.x ) ),
921 pageHeightIU
922 - schIUScale.MilsToIU( KiROUND( oy + prim.center.y ) ) );
923 int radius = schIUScale.MilsToIU( KiROUND( prim.radius ) );
924
926 circle->SetStart( center );
927 circle->SetEnd( VECTOR2I( center.x + radius, center.y ) );
928 circle->SetStroke( STROKE_PARAMS( strokeWidth, lineStyle ) );
929
930 if( prim.filled )
931 circle->SetFillMode( FILL_T::FILLED_SHAPE );
932
933 linesScreen->Append( circle );
934 }
936 && prim.points.size() == 2 )
937 {
938 VECTOR2I pos(
939 schIUScale.MilsToIU( KiROUND( ox + prim.points[0].coord.x ) ),
940 pageHeightIU
941 - schIUScale.MilsToIU(
942 KiROUND( oy + prim.points[0].coord.y ) ) );
944 schIUScale.MilsToIU( KiROUND( ox + prim.points[1].coord.x ) ),
945 pageHeightIU
946 - schIUScale.MilsToIU(
947 KiROUND( oy + prim.points[1].coord.y ) ) );
948
950 rect->SetPosition( pos );
951 rect->SetEnd( end );
952 rect->SetStroke( STROKE_PARAMS( strokeWidth, lineStyle ) );
953
954 if( prim.filled )
956
957 linesScreen->Append( rect );
958 }
959 else if( prim.points.size() >= 2 )
960 {
961 for( size_t p = 0; p + 1 < prim.points.size(); p++ )
962 {
963 VECTOR2I start(
964 schIUScale.MilsToIU(
965 KiROUND( ox + prim.points[p].coord.x ) ),
966 pageHeightIU
967 - schIUScale.MilsToIU(
968 KiROUND( oy + prim.points[p].coord.y ) ) );
970 schIUScale.MilsToIU(
971 KiROUND( ox + prim.points[p + 1].coord.x ) ),
972 pageHeightIU
973 - schIUScale.MilsToIU(
974 KiROUND( oy + prim.points[p + 1].coord.y ) ) );
975
976 if( start == end )
977 continue;
978
979 if( prim.points[p].arc.has_value() )
980 {
981 const PADS_SCH::ARC_DATA& ad = *prim.points[p].arc;
982 double cx = ( ad.bbox_x1 + ad.bbox_x2 ) / 2.0;
983 double cy = ( ad.bbox_y1 + ad.bbox_y2 ) / 2.0;
985 schIUScale.MilsToIU( KiROUND( ox + cx ) ),
986 pageHeightIU
987 - schIUScale.MilsToIU( KiROUND( oy + cy ) ) );
988
989 double sx = start.x - center.x;
990 double sy = start.y - center.y;
991 double ex = end.x - center.x;
992 double ey = end.y - center.y;
993 double radius = std::sqrt( sx * sx + sy * sy );
994
995 double mx = sx + ex;
996 double my = sy + ey;
997 double mlen = std::sqrt( mx * mx + my * my );
998
999 VECTOR2I midPt;
1000
1001 if( mlen > 0.001 )
1002 {
1003 midPt.x = center.x
1004 + static_cast<int>( radius * mx / mlen );
1005 midPt.y = center.y
1006 + static_cast<int>( radius * my / mlen );
1007 }
1008 else
1009 {
1010 midPt.x = center.x
1011 + static_cast<int>( -sy * radius
1012 / std::max( radius, 1.0 ) );
1013 midPt.y = center.y
1014 + static_cast<int>( sx * radius
1015 / std::max( radius, 1.0 ) );
1016 }
1017
1018 if( ad.angle < 0 )
1019 {
1020 midPt.x = 2 * center.x - midPt.x;
1021 midPt.y = 2 * center.y - midPt.y;
1022 }
1023
1024 SCH_SHAPE* arc = new SCH_SHAPE( SHAPE_T::ARC );
1025 arc->SetArcGeometry( start, midPt, end );
1026 arc->SetStroke( STROKE_PARAMS( strokeWidth, lineStyle ) );
1027
1028 if( prim.filled )
1030
1031 linesScreen->Append( arc );
1032 }
1033 else
1034 {
1035 SCH_LINE* line = new SCH_LINE(
1037 line->SetEndPoint( end );
1038 line->SetStroke( STROKE_PARAMS( strokeWidth, lineStyle ) );
1039 linesScreen->Append( line );
1040 }
1041 }
1042 }
1043 }
1044
1045 // Render text items within this LINES group
1046 for( const PADS_SCH::TEXT_ITEM& textItem : linesItem.texts )
1047 {
1048 if( textItem.content.empty() )
1049 continue;
1050
1051 VECTOR2I pos(
1052 schIUScale.MilsToIU( KiROUND( ox + textItem.position.x ) ),
1053 pageHeightIU
1054 - schIUScale.MilsToIU( KiROUND( oy + textItem.position.y ) ) );
1055
1056 linesScreen->Append( createSchText( textItem, pos ) );
1057 }
1058 }
1059 }
1060
1061 // Set title block from parsed parameters
1062 schBuilder.CreateTitleBlock( rootScreen );
1063
1064 // Finalize all sheets
1065 SCH_SCREENS allSheets( rootSheet );
1066 allSheets.UpdateSymbolLinks();
1067 allSheets.ClearEditFlags();
1068
1069 if( m_reporter )
1070 {
1071 for( const auto& [msg, severity] : m_errorMessages )
1072 m_reporter->Report( msg, severity );
1073 }
1074
1075 m_errorMessages.clear();
1076
1077 return rootSheet;
1078}
1079
1080
1081bool SCH_IO_PADS::checkFileHeader( const wxString& aFileName ) const
1082{
1083 try
1084 {
1085 std::ifstream file( aFileName.fn_str() );
1086
1087 if( !file.is_open() )
1088 return false;
1089
1090 std::string line;
1091
1092 if( std::getline( file, line ) )
1093 {
1094 if( line.find( "*PADS-POWERLOGIC" ) != std::string::npos )
1095 return true;
1096
1097 if( line.find( "*PADS-LOGIC" ) != std::string::npos )
1098 return true;
1099 }
1100 }
1101 catch( ... )
1102 {
1103 }
1104
1105 return false;
1106}
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:114
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:990
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
const KIID m_Uuid
Definition eda_item.h:522
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition eda_item.h:150
void SetEnd(const VECTOR2I &aEnd)
Definition eda_shape.h:220
void SetArcGeometry(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Set the three controlling points for an arc.
void SetFillMode(FILL_T aFill)
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
Definition eda_text.cpp:546
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
Definition eda_text.cpp:431
virtual void SetVisible(bool aVisible)
Definition eda_text.cpp:400
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition eda_text.cpp:298
void SetTextAngleDegrees(double aOrientation)
Definition eda_text.h:150
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
Definition eda_text.cpp:423
REPORTER * m_reporter
Reporter to log errors/warnings to, may be nullptr.
Definition io_base.h:237
PROGRESS_REPORTER * m_progressReporter
Progress reporter to track the progress of the operation, may be nullptr.
Definition io_base.h:240
virtual bool CanReadLibrary(const wxString &aFileName) const
Checks if this IO object can read the specified library file/directory.
Definition io_base.cpp:71
Definition kiid.h:49
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:49
int SetLibItemName(const UTF8 &aLibItemName)
Override the library item name portion of the LIB_ID to aLibItemName.
Definition lib_id.cpp:111
int SetLibNickname(const UTF8 &aLibNickname)
Override the logical library name portion of the LIB_ID to aLibNickname.
Definition lib_id.cpp:100
Define a library symbol object.
Definition lib_symbol.h:83
void SetGlobalPower()
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition locale_io.h:41
Parser for PADS Logic schematic design export files.
const std::vector< TEXT_ITEM > & GetTextItems() const
const std::vector< TIED_DOT > & GetTiedDots() const
const std::vector< OFF_PAGE_CONNECTOR > & GetOffPageConnectors() const
bool Parse(const std::string &aFileName)
const std::vector< SHEET_HEADER > & GetSheetHeaders() const
const std::vector< LINES_ITEM > & GetLinesItems() const
std::vector< SCH_SIGNAL > GetSignalsOnSheet(int aSheetNumber) const
std::set< int > GetSheetNumbers() const
const std::vector< SYMBOL_DEF > & GetSymbolDefs() const
const std::vector< PART_PLACEMENT > & GetPartPlacements() const
const std::map< std::string, PARTTYPE_DEF > & GetPartTypes() const
std::vector< PART_PLACEMENT > GetPartsOnSheet(int aSheetNumber) const
const SYMBOL_DEF * GetSymbolDef(const std::string &aName) const
const PARAMETERS & GetParameters() const
Builder class to create KiCad schematic elements from parsed PADS data.
int CreateNetLabels(const std::vector< SCH_SIGNAL > &aSignals, SCH_SCREEN *aScreen, const std::set< std::string > &aSignalOpcIds, const std::set< std::string > &aSkipSignals={})
Create net labels for named signals.
void ApplyPartAttributes(SCH_SYMBOL *aSymbol, const PART_PLACEMENT &aPlacement)
Apply part attributes to a symbol instance.
void CreateTitleBlock(SCH_SCREEN *aScreen)
Create title block from parsed PADS parameters.
int CreateCustomFields(SCH_SYMBOL *aSymbol, const PART_PLACEMENT &aPlacement)
Create custom fields from non-standard PADS attributes.
SCH_SHEET * CreateHierarchicalSheet(int aSheetNumber, int aTotalSheets, SCH_SHEET *aParentSheet, const wxString &aBaseFilename)
Create hierarchical sheet for a sub-schematic page.
Builder class to convert PADS symbol definitions to KiCad LIB_SYMBOL objects.
void AddHiddenPowerPins(LIB_SYMBOL *aSymbol, const std::vector< PARTTYPE_DEF::SIGPIN > &aSigpins)
Add hidden power pins from PARTTYPE SIGPIN entries to an existing symbol.
LIB_SYMBOL * GetOrCreateMultiUnitSymbol(const PARTTYPE_DEF &aPartType, const std::vector< SYMBOL_DEF > &aSymbolDefs)
Get or create a multi-unit symbol for the given PARTTYPE.
static std::optional< LIB_ID > GetKiCadPowerSymbolId(const std::string &aPadsName)
Get KiCad power library symbol ID for a PADS power symbol.
LIB_SYMBOL * BuildKiCadPowerSymbol(const std::string &aKiCadName)
Build a power symbol using hard-coded KiCad-standard graphics.
static bool IsPowerSymbol(const std::string &aName)
Check if a symbol name indicates a power symbol.
static std::string GetPowerStyleFromVariant(const std::string &aDecalName, const std::string &aPinType)
Map a PADS special_variant to a power symbol style name.
LIB_SYMBOL * GetOrCreateSymbol(const SYMBOL_DEF &aSymbolDef)
Get or create a symbol for the given definition.
LIB_SYMBOL * GetOrCreatePartTypeSymbol(const PARTTYPE_DEF &aPartType, const SYMBOL_DEF &aSymbolDef)
Get or create a single-gate symbol with PARTTYPE-specific pin remapping.
Describe the page size and margins of a paper page on which to eventually print or plot.
Definition page_info.h:79
int GetHeightIU(double aIUScale) const
Gets the page height in IU.
Definition page_info.h:168
bool SetType(PAGE_SIZE_TYPE aPageSize, bool aIsPortrait=false)
Set the name of the page type and also the sizes and margins commonly associated with that type name.
Holds all the data relating to one schematic.
Definition schematic.h:88
SCHEMATIC_SETTINGS & Settings() const
bool IsValid() const
A simple test if the schematic is loaded, not a complete one.
Definition schematic.h:172
void SetTopLevelSheets(const std::vector< SCH_SHEET * > &aSheets)
void SetPosition(const VECTOR2I &aPosition) override
void SetText(const wxString &aText) override
bool CanReadLibrary(const wxString &aFileName) const override
Checks if this IO object can read the specified library file/directory.
bool checkFileHeader(const wxString &aFileName) const
Check if the file header indicates a PADS Logic schematic file.
bool CanReadSchematicFile(const wxString &aFileName) const override
Checks if this SCH_IO can read the specified schematic file.
std::unordered_map< wxString, SEVERITY > m_errorMessages
Definition sch_io_pads.h:73
SCH_SHEET * LoadSchematicFile(const wxString &aFileName, SCHEMATIC *aSchematic, SCH_SHEET *aAppendToMe=nullptr, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Load information from some input file format that this SCH_IO implementation knows about,...
virtual bool CanReadSchematicFile(const wxString &aFileName) const
Checks if this SCH_IO can read the specified schematic file.
Definition sch_io.cpp:45
SCH_IO(const wxString &aName)
Definition sch_io.h:375
int GetUnit() const
Definition sch_item.h:239
void SetConnectivityDirty(bool aDirty=true)
Definition sch_item.h:590
virtual void SetUnit(int aUnit)
Definition sch_item.h:238
Segment description base class to describe items which have 2 end points (track, wire,...
Definition sch_line.h:42
virtual void SetStroke(const STROKE_PARAMS &aStroke) override
Definition sch_line.h:202
void SetEndPoint(const VECTOR2I &aPosition)
Definition sch_line.h:149
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition sch_screen.h:749
void UpdateSymbolLinks(REPORTER *aReporter=nullptr)
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in the full schematic.
void ClearEditFlags()
std::vector< SCH_SHEET_INSTANCE > m_sheetInstances
Definition sch_screen.h:727
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
const KIID & GetUuid() const
Definition sch_screen.h:532
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
void SetPosition(const VECTOR2I &aPos) override
Definition sch_shape.h:86
void SetStroke(const STROKE_PARAMS &aStroke) override
Definition sch_shape.cpp:63
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
KIID_PATH Path() const
Get the sheet path as an KIID_PATH.
void SetPageNumber(const wxString &aPageNumber)
Set the sheet instance user definable page number.
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:48
void SetFileName(const wxString &aFilename)
Definition sch_sheet.h:382
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this sheet.
SCH_SCREEN * GetScreen() const
Definition sch_sheet.h:145
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
Schematic symbol object.
Definition sch_symbol.h:76
void SetLibId(const LIB_ID &aName)
void SetPosition(const VECTOR2I &aPosition) override
Definition sch_symbol.h:868
void SetRef(const SCH_SHEET_PATH *aSheet, const wxString &aReference)
Set the reference for the given sheet path for this symbol.
void SetOrientation(int aOrientation)
Compute the new transform matrix based on aOrientation for the symbol which is applied to the current...
void AddHierarchicalReference(const KIID_PATH &aPath, const wxString &aRef, int aUnit)
Add a full hierarchical reference to this symbol.
VECTOR2I GetPosition() const override
Definition sch_symbol.h:867
void SetValueFieldText(const wxString &aValue, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString)
void SetLibSymbol(LIB_SYMBOL *aLibSymbol)
Set this schematic symbol library symbol reference to aLibSymbol.
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this symbol.
Simple container to manage line stroke parameters.
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
Definition eda_shape.h:46
@ FILLED_SHAPE
Fill with object color.
Definition eda_shape.h:58
double m_PadsSchTextWidthScale
PADS text width scale factor for schematic imports.
double m_PadsSchTextHeightScale
PADS text height scale factor for schematic imports.
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
@ LAYER_WIRE
Definition layer_ids.h:452
@ LAYER_NOTES
Definition layer_ids.h:467
LINE_STYLE PadsLineStyleToKiCad(int aPadsStyle)
Convert a PADS line style integer to a KiCad LINE_STYLE enum value.
KIID GenerateDeterministicUuid(const std::string &aIdentifier)
Generate a deterministic KIID from a PADS component identifier.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:400
Common utilities and types for parsing PADS file formats.
@ RPT_SEVERITY_WARNING
static int computePowerOrientation(const std::string &aOpcId, const std::vector< PADS_SCH::SCH_SIGNAL > &aSignals, const VECTOR2I &aOpcPos, bool aPinUp, int aPageHeightIU)
Determine the orientation for a power symbol at an OPC position based on the wire direction at that p...
static SCH_TEXT * createSchText(const PADS_SCH::TEXT_ITEM &aText, const VECTOR2I &aPos)
static std::string stripGateSuffix(const std::string &aRef)
Strip any alphabetic gate suffix (e.g.
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
LINE_STYLE
Dashed line types.
Gate definition within a PARTTYPE.
std::vector< std::string > decal_names
Graphical line/shape item from LINES section.
Off-page reference from OFFPAGE REFS section.
General schematic parameters from SCH and FIELDS sections.
std::string border_template
Part type definition from PARTTYPE section.
std::vector< GATE_DEF > gates
std::vector< SPECIAL_VARIANT > special_variants
Part instance from PART section.
Signal (net) definition from CONNECTION and SIGNAL sections.
Sheet header from SHT section.
Symbol definition from CAEDECAL section.
Graphic primitive from CAEDECAL or LINES sections (OPEN, CLOSED, CIRCLE, COPCLS).
std::vector< GRAPHIC_POINT > points
Free text item from TEXT section.
Junction dot from TIEDOTS section.
Wire segment connecting two endpoints through coordinate vertices.
std::vector< POINT > vertices
A simple container for sheet instance information.
@ SYM_ORIENT_270
Definition symbol.h:42
@ SYM_MIRROR_Y
Definition symbol.h:44
@ SYM_ORIENT_180
Definition symbol.h:41
@ SYM_MIRROR_X
Definition symbol.h:43
@ SYM_ORIENT_90
Definition symbol.h:40
@ SYM_ORIENT_0
Definition symbol.h:39
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
std::string path
VECTOR2I center
int radius
VECTOR2I end
SHAPE_CIRCLE circle(c.m_circle_center, c.m_circle_radius)
@ GR_TEXT_H_ALIGN_CENTER
@ GR_TEXT_H_ALIGN_RIGHT
@ GR_TEXT_H_ALIGN_LEFT
@ GR_TEXT_V_ALIGN_BOTTOM
@ GR_TEXT_V_ALIGN_CENTER
@ GR_TEXT_V_ALIGN_TOP
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695
Definition of file extensions used in Kicad.