65 double milsValue = aPadsValue;
70 milsValue = aPadsValue;
74 milsValue = aPadsValue * 39.3701;
78 milsValue = aPadsValue * 1000.0;
103 for(
const auto& signal : aSignals )
105 for(
const auto& wire : signal.wires )
112 aScreen->
Append( schLine );
139 for(
const auto& pt : junctionPoints )
143 aScreen->
Append( junction );
146 return static_cast<int>( junctionPoints.size() );
151 const std::vector<SCH_SIGNAL>& aSignals )
153 std::vector<VECTOR2I> junctions;
155 for(
const auto& signal : aSignals )
158 std::map<std::pair<int, int>,
int> pointCount;
160 for(
const auto& wire : signal.wires )
165 pointCount[{ start.
x, start.
y }]++;
166 pointCount[{
end.x,
end.y }]++;
170 for(
const auto& [coords, count] : pointCount )
174 junctions.emplace_back( coords.first, coords.second );
185 const std::set<std::string>& aSignalOpcIds,
186 const std::set<std::string>& aSkipSignals )
190 for(
const auto& signal : aSignals )
192 if( signal.name.empty() || signal.name[0] ==
'$' )
195 if( aSkipSignals.count( signal.name ) )
198 if( signal.wires.empty() )
202 std::vector<std::pair<VECTOR2I, VECTOR2I>> opcPlacements;
204 for(
const auto& wire : signal.wires )
206 if( wire.vertices.size() < 2 )
210 if( !wire.endpoint_a.empty() && wire.endpoint_a.substr( 0, 3 ) ==
"@@@"
211 && aSignalOpcIds.count( wire.endpoint_a ) )
214 toKiCadY( wire.vertices.front().y ) );
217 opcPlacements.emplace_back( labelPos, adjPos );
220 if( !wire.endpoint_b.empty() && wire.endpoint_b.substr( 0, 3 ) ==
"@@@"
221 && aSignalOpcIds.count( wire.endpoint_b ) )
223 size_t last = wire.vertices.size() - 1;
225 toKiCadY( wire.vertices[last].y ) );
227 toKiCadY( wire.vertices[last - 1].y ) );
228 opcPlacements.emplace_back( labelPos, adjPos );
232 for(
const auto& [labelPos, adjPos] : opcPlacements )
255 int dx = aAdjacentPos.
x - aLabelPos.
x;
256 int dy = aAdjacentPos.
y - aLabelPos.
y;
288 if( aSignal.
wires.empty() )
294 std::map<std::pair<int, int>,
int> endpointCount;
296 for(
const auto& wire : aSignal.
wires )
298 if( wire.vertices.size() < 2 )
301 auto first = wire.vertices.front();
302 auto last = wire.vertices.back();
304 endpointCount[{
static_cast<int>( first.x * 1000 ),
305 static_cast<int>( first.y * 1000 ) }]++;
306 endpointCount[{
static_cast<int>( last.x * 1000 ),
307 static_cast<int>( last.y * 1000 ) }]++;
311 std::set<std::pair<int, int>> pinEndpoints;
313 for(
const auto& wire : aSignal.
wires )
315 if( wire.vertices.size() < 2 )
321 if( !wire.endpoint_a.empty() && wire.endpoint_a.substr( 0, 3 ) !=
"@@@" )
323 auto pt = wire.vertices.front();
324 pinEndpoints.insert( {
static_cast<int>( pt.x * 1000 ),
325 static_cast<int>( pt.y * 1000 ) } );
328 if( !wire.endpoint_b.empty() && wire.endpoint_b.substr( 0, 3 ) !=
"@@@" )
330 auto pt = wire.vertices.back();
331 pinEndpoints.insert( {
static_cast<int>( pt.x * 1000 ),
332 static_cast<int>( pt.y * 1000 ) } );
337 for(
const auto& wire : aSignal.
wires )
339 if( wire.vertices.size() < 2 )
342 for(
const auto* vtx : { &wire.vertices.front(), &wire.vertices.back() } )
344 auto key = std::make_pair(
static_cast<int>( vtx->x * 1000 ),
345 static_cast<int>( vtx->y * 1000 ) );
347 if( endpointCount[key] == 1 && pinEndpoints.count( key ) == 0 )
353 for(
const auto& wire : aSignal.
wires )
355 if( wire.vertices.size() < 2 )
358 for(
const auto* vtx : { &wire.vertices.front(), &wire.vertices.back() } )
360 auto key = std::make_pair(
static_cast<int>( vtx->x * 1000 ),
361 static_cast<int>( vtx->y * 1000 ) );
363 if( endpointCount[key] == 1 )
369 for(
const auto& wire : aSignal.
wires )
371 if( !wire.vertices.empty() )
373 const auto& vtx = wire.vertices[0];
387 for(
const auto& signal : aSignals )
392 for(
const auto& wire : signal.wires )
399 aScreen->
Append( busLine );
428 size_t bracketPos = aName.find(
'[' );
430 if( bracketPos != std::string::npos )
432 size_t closeBracket = aName.find(
']', bracketPos );
434 if( closeBracket != std::string::npos )
436 std::string range = aName.substr( bracketPos + 1, closeBracket - bracketPos - 1 );
438 if( range.find(
':' ) != std::string::npos ||
439 range.find(
".." ) != std::string::npos )
447 size_t anglePos = aName.find(
'<' );
449 if( anglePos != std::string::npos )
451 size_t closeAngle = aName.find(
'>', anglePos );
453 if( closeAngle != std::string::npos )
455 std::string range = aName.substr( anglePos + 1, closeAngle - anglePos - 1 );
457 if( range.find(
':' ) != std::string::npos ||
458 range.find(
".." ) != std::string::npos )
479 size_t sepPos = ref.rfind(
'-' );
481 if( sepPos == std::string::npos )
482 sepPos = ref.rfind(
'.' );
484 if( sepPos != std::string::npos && sepPos + 1 < ref.size()
485 && std::isalpha(
static_cast<unsigned char>( ref[sepPos + 1] ) ) )
487 ref = ref.substr( 0, sepPos );
501 for(
const auto& attr : aPlacement.
attributes )
503 if( attr.name ==
"PCB DECAL" || attr.name ==
"PCB_DECAL" || attr.name ==
"FOOTPRINT" )
505 if( !attr.value.empty() )
527 for(
const auto& attr : aPlacement.
attributes )
530 bool isRefOrValue =
false;
554 field->
SetVisible( isRefOrValue ? attr.visible :
false );
567 if( attr.rotation != 0.0 )
572 if( attr.height > 0 )
574 int scaledH =
static_cast<int>(
577 int scaledW =
static_cast<int>(
584 int fieldTextSize =
schIUScale.MilsToIU( 50 );
604 int fieldsCreated = 0;
607 std::set<std::string> processedNames;
609 for(
const auto& attr : aPlacement.
attributes )
616 if( attr.value.empty() )
619 processedNames.insert( attr.name );
630 existingField->
SetText( wxString::FromUTF8( attr.value ) );
638 newField.
SetText( wxString::FromUTF8( attr.value ) );
646 if( attr.rotation != 0.0 )
652 if( attr.size > 0.0 )
658 aSymbol->
GetFields().push_back( newField );
674 existingField->
SetText( wxString::FromUTF8( value ) );
680 newField.
SetText( wxString::FromUTF8( value ) );
684 aSymbol->
GetFields().push_back( newField );
689 return fieldsCreated;
699 auto findField = [
this](
const std::initializer_list<const char*>& aCandidates ) -> std::string
701 for(
const char*
name : aCandidates )
705 if( it !=
m_params.fields.end() && !it->second.empty() )
714 std::string title = findField( {
"Title",
"TITLE1" } );
720 tb.
SetTitle( wxString::FromUTF8( title ) );
722 std::string date = findField( {
"DATE",
"Release Date",
"Drawn Date" } );
725 tb.
SetDate( wxString::FromUTF8( date ) );
727 std::string revision = findField( {
"Revision",
"VER" } );
729 if( !revision.empty() )
732 std::string company = findField( {
"Company Name" } );
734 if( !company.empty() )
735 tb.
SetCompany( wxString::FromUTF8( company ) );
737 std::string drawingNumber = findField( {
"DN",
"Drawing Number" } );
739 if( !drawingNumber.empty() )
740 tb.
SetComment( 0, wxString::FromUTF8( drawingNumber ) );
742 std::string designer = findField( {
"DESIGNER" } );
744 if( !designer.empty() )
745 tb.
SetComment( 1, wxString::FromUTF8( designer ) );
747 std::string drawnBy = findField( {
"DRAWNBY",
"Drawn By" } );
749 if( !drawnBy.empty() )
750 tb.
SetComment( 2, wxString::FromUTF8( drawnBy ) );
752 std::string builtFor = findField( {
"BUILTFOR" } );
754 if( !builtFor.empty() )
755 tb.
SetComment( 3, wxString::FromUTF8( builtFor ) );
763 const wxString& aBaseFilename )
778 wxFileName fn( aBaseFilename );
779 wxString sheetFilename = wxString::Format( wxT(
"%s_sheet%d.%s" ),
788 wxString sheetName = wxString::Format( wxT(
"Sheet %d" ), aSheetNumber );
794 wxFileName screenFn(
m_schematic->Project().GetProjectPath(), sheetFilename );
809 parentScreen->
Append( sheet );
827 const int startX =
schIUScale.MilsToIU( 500 );
828 const int startY =
schIUScale.MilsToIU( 500 );
831 const int spacingX =
schIUScale.MilsToIU( 2500 );
832 const int spacingY =
schIUScale.MilsToIU( 2000 );
835 int columns =
static_cast<int>( std::ceil( std::sqrt(
static_cast<double>( aTotalSheets ) ) ) );
840 int row = aSheetIndex / columns;
841 int col = aSheetIndex % columns;
843 return VECTOR2I( startX + col * spacingX, startY + row * spacingY );
848 const std::string& aSignalName,
854 wxString
name = wxString::FromUTF8( aSignalName );
860 int yOffset =
schIUScale.MilsToIU( 100 ) + aPinIndex * pinSpacing;
862 VECTOR2I pinPos( sheetPos.
x, sheetPos.
y + yOffset );
881 wxString
name = wxString::FromUTF8( aSignalName );
895 const std::set<int>& aSheetNumbers )
897 if( aSignalName.empty() )
901 if( aSheetNumbers.size() > 1 )
905 std::string upperName = aSignalName;
906 std::transform( upperName.begin(), upperName.end(), upperName.begin(), ::toupper );
908 static const std::set<std::string> globalPatterns = {
909 "VCC",
"VDD",
"VEE",
"VSS",
"GND",
"AGND",
"DGND",
"PGND",
910 "V+",
"V-",
"VBAT",
"VBUS",
"VIN",
"VOUT",
911 "+5V",
"+3V3",
"+3.3V",
"+12V",
"-12V",
"+24V",
912 "0V",
"EARTH",
"CHASSIS"
915 if( globalPatterns.count( upperName ) > 0 )
919 if( ( upperName[0] ==
'+' || upperName[0] ==
'-' ) && upperName.length() >= 3 )
921 bool hasDigit =
false;
924 for(
char c : upperName.substr( 1 ) )
926 if( std::isdigit( c ) )
933 if( hasDigit && hasV )
constexpr EDA_IU_SCALE schIUScale
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
void SetFlags(EDA_ITEM_FLAGS aMask)
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
virtual void SetVisible(bool aVisible)
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
void SetTextAngleDegrees(double aOrientation)
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
Maps PADS attribute names to KiCad field names.
bool IsReferenceField(const std::string &aPadsAttr) const
Check if a PADS attribute maps to the Reference field.
std::string GetKiCadFieldName(const std::string &aPadsAttr) const
Get the KiCad field name for a PADS attribute.
bool IsFootprintField(const std::string &aPadsAttr) const
Check if a PADS attribute maps to the Footprint field.
bool IsStandardField(const std::string &aPadsAttr) const
Check if a PADS attribute maps to a standard KiCad field.
bool IsValueField(const std::string &aPadsAttr) const
Check if a PADS attribute maps to the Value field.
SCH_LINE * CreateWire(const WIRE_SEGMENT &aWire)
Create a single wire segment.
std::vector< VECTOR2I > findJunctionPoints(const std::vector< SCH_SIGNAL > &aSignals)
Find junction points where 3+ wire segments meet.
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.
int toKiCadY(double aPadsY) const
Convert PADS Y coordinate to KiCad Y, accounting for Y-axis inversion and page offset.
SCH_SHEET_PIN * CreateSheetPin(SCH_SHEET *aSheet, const std::string &aSignalName, int aPinIndex)
Create hierarchical sheet pin on a sheet symbol.
int CreateJunctions(const std::vector< SCH_SIGNAL > &aSignals, SCH_SCREEN *aScreen)
Create junctions at wire intersection points.
void ApplyPartAttributes(SCH_SYMBOL *aSymbol, const PART_PLACEMENT &aPlacement)
Apply part attributes to a symbol instance.
PADS_SCH_SCHEMATIC_BUILDER(const PARAMETERS &aParams, SCHEMATIC *aSchematic)
void CreateTitleBlock(SCH_SCREEN *aScreen)
Create title block from parsed PADS parameters.
const PARAMETERS & m_params
VECTOR2I CalculateSheetPosition(int aSheetIndex, int aTotalSheets) const
Calculate position for a sheet symbol on the parent sheet.
SPIN_STYLE computeLabelOrientation(const VECTOR2I &aLabelPos, const VECTOR2I &aAdjacentPos)
Compute label orientation from the wire direction at the label position.
int toKiCadUnits(double aPadsValue) const
Convert PADS coordinate to KiCad internal units.
int CreateCustomFields(SCH_SYMBOL *aSymbol, const PART_PLACEMENT &aPlacement)
Create custom fields from non-standard PADS attributes.
VECTOR2I chooseLabelPosition(const SCH_SIGNAL &aSignal)
Choose best position for net label on a signal's wires.
SCH_LINE * CreateBusWire(const WIRE_SEGMENT &aWire)
Create a single bus wire segment.
SCH_HIERLABEL * CreateHierLabel(const std::string &aSignalName, const VECTOR2I &aPosition, SCH_SCREEN *aScreen)
Create hierarchical label in a sub-schematic.
void ApplyFieldSettings(SCH_SYMBOL *aSymbol, const PART_PLACEMENT &aPlacement)
Apply field visibility and position from PADS attribute settings.
int CreateWires(const std::vector< SCH_SIGNAL > &aSignals, SCH_SCREEN *aScreen)
Create wire segments from signal definitions and add to screen.
SCH_GLOBALLABEL * CreateNetLabel(const SCH_SIGNAL &aSignal, const VECTOR2I &aPosition, SPIN_STYLE aOrientation=SPIN_STYLE::RIGHT)
Create a global net label for a signal.
static bool IsGlobalSignal(const std::string &aSignalName, const std::set< int > &aSheetNumbers)
Check if a signal name represents a global signal.
int CreateBusWires(const std::vector< SCH_SIGNAL > &aSignals, SCH_SCREEN *aScreen)
Create bus wires and entries for bus signals.
wxString convertNetName(const std::string &aName) const
Convert a PADS net name for use as a KiCad label.
SCH_SHEET * CreateHierarchicalSheet(int aSheetNumber, int aTotalSheets, SCH_SHEET *aParentSheet, const wxString &aBaseFilename)
Create hierarchical sheet for a sub-schematic page.
VECTOR2I GetDefaultSheetSize() const
Get standard sheet size for a given sheet number.
~PADS_SCH_SCHEMATIC_BUILDER()
static bool IsBusSignal(const std::string &aName)
Check if a signal name indicates a bus.
Holds all the data relating to one schematic.
void SetPosition(const VECTOR2I &aPosition) override
void SetText(const wxString &aText) override
void SetSpinStyle(SPIN_STYLE aSpinStyle) override
void SetShape(LABEL_FLAG_SHAPE aShape)
Segment description base class to describe items which have 2 end points (track, wire,...
void SetEndPoint(const VECTOR2I &aPosition)
void SetTitleBlock(const TITLE_BLOCK &aTitleBlock)
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
void AddPin(SCH_SHEET_PIN *aSheetPin)
Add aSheetPin to the sheet.
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this sheet.
SCH_SCREEN * GetScreen() const
VECTOR2I GetPosition() const override
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
void SetRef(const SCH_SHEET_PATH *aSheet, const wxString &aReference)
Set the reference for the given sheet path for this symbol.
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly) const override
Populate a std::vector with SCH_FIELDs, sorted in ordinal order.
void SetFootprintFieldText(const wxString &aFootprint)
VECTOR2I GetPosition() const override
void SetValueFieldText(const wxString &aValue, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString)
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this symbol.
Hold the information shown in the lower right corner of a plot, printout, or editing view.
void SetRevision(const wxString &aRevision)
void SetComment(int aIdx, const wxString &aComment)
void SetTitle(const wxString &aTitle)
void SetCompany(const wxString &aCompany)
void SetDate(const wxString &aDate)
Set the date field, and defaults to the current time and date.
#define IS_NEW
New item, just created.
static const std::string KiCadSchematicFileExtension
wxString ConvertInvertedNetName(const std::string &aNetName)
Convert a PADS net name to KiCad format, handling inverted signal notation.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Common utilities and types for parsing PADS file formats.
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
General schematic parameters from SCH and FIELDS sections.
Part instance from PART section.
std::map< std::string, std::string > attr_overrides
std::vector< PART_ATTRIBUTE > attributes
Signal (net) definition from CONNECTION and SIGNAL sections.
std::vector< WIRE_SEGMENT > wires
Wire segment connecting two endpoints through coordinate vertices.
@ USER
The field ID hasn't been set yet; field is invalid.
@ FOOTPRINT
Field Name Module PCB, i.e. "16DIP300".
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
VECTOR2< int32_t > VECTOR2I
Definition of file extensions used in Kicad.