KiCad PCB EDA Suite
Loading...
Searching...
No Matches
odb_component.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 * Author: SYSUEric <[email protected]>.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21#include <wx/regex.h>
22#include <wx/log.h>
23
24#include <board.h>
25#include <footprint.h>
26
27#include "odb_component.h"
28#include "odb_util.h"
29#include "hash_eda.h"
30#include "pcb_io_odbpp.h"
31#include <trace_helpers.h>
32
33
35 const EDA_DATA::PACKAGE& aPkg )
36{
37 auto& comp = m_compList.emplace_back( m_compList.size(), aPkg.m_index );
38
39 comp.m_center = ODB::AddXY( aFp->GetPosition() );
40 EDA_ANGLE angle = aFp->GetOrientation();
41
42 if( angle != ANGLE_0 )
43 {
44 // odb Rotation is expressed in degrees and is always clockwise.
45 // while kicad EDA_ANGLE is anticlockwise.
46 angle = ANGLE_360 - angle;
47 comp.m_rot = ODB::Double2String( angle.Normalize().AsDegrees() );
48 }
49
50 if( aFp->IsFlipped() )
51 {
52 comp.m_mirror = wxT( "M" );
53 }
54
55 wxString originalRef = aFp->GetReference();
56 comp.m_comp_name = ODB::GenLegalComponentName( originalRef );
57
58 comp.m_part_name = wxString::Format( "%s_%s", aFp->GetFPID().GetFullLibraryName(),
59 aFp->GetFPID().GetLibItemName().wx_str() );
60
61 // ODB++ cannot handle spaces in these fields
62 ODB::RemoveWhitespace( comp.m_part_name );
63
64 if( comp.m_comp_name.IsEmpty() )
65 {
66 // The spec requires a component name; some ODB++ parsers can't handle it being empty
67 comp.m_comp_name = wxString::Format( "UNNAMED%zu", m_compList.size() );
68 }
69
70 // Warn if non-ASCII characters were converted
71 if( comp.m_comp_name != originalRef )
72 {
73 if( m_plugin )
74 {
75 m_plugin->Report( wxString::Format(
76 _( "Component '%s' has non-ASCII characters in its "
77 "designator; converted to '%s' for ODB++ export." ),
78 originalRef, comp.m_comp_name ),
80 }
81 }
82
83 wxString base_comp_name = comp.m_comp_name;
84
85 if( !m_usedCompNames.insert( comp.m_comp_name ).second )
86 {
87 size_t suffix = 1;
88 wxString candidate;
89
90 do
91 {
92 candidate = wxString::Format( "%s_%zu", base_comp_name, suffix++ );
93 } while( !m_usedCompNames.insert( candidate ).second );
94
95 if( m_plugin )
96 {
97 m_plugin->Report( wxString::Format(
98 _( "Component '%s' has an ambiguous designator after "
99 "conversion; renamed to '%s' for ODB++ export." ),
100 originalRef, candidate ),
102 }
103
104 comp.m_comp_name = candidate;
105 }
106
107 for( PCB_FIELD* field : aFp->GetFields() )
108 {
109 if( field->GetId() == FIELD_T::REFERENCE )
110 continue;
111
112 wxString key = field->GetName();
114 comp.m_prp[key] = wxString::Format( "'%s'", field->GetShownText( false ) );
115 }
116
117 if( aFp->GetDNPForVariant( aFp->GetBoard() ? aFp->GetBoard()->GetCurrentVariant() : wxString() ) )
118 {
119 AddSystemAttribute( comp, ODB_ATTR::NO_POP{ true } );
120 }
121
122 if( aFp->GetAttributes() & FP_SMD )
123 {
125 }
126 else if( aFp->GetAttributes() & FP_THROUGH_HOLE )
127 {
129 }
130 else
131 {
133 }
134
135 return comp;
136}
137
138
139void COMPONENTS_MANAGER::Write( std::ostream& ost ) const
140{
141 ost << "UNITS=" << PCB_IO_ODBPP::m_unitsStr << std::endl;
142
143 WriteAttributes( ost );
144
145 for( const auto& comp : m_compList )
146 {
147 comp.Write( ost );
148 }
149}
150
151
152void ODB_COMPONENT::Write( std::ostream& ost ) const
153{
154 ost << "# CMP " << m_index << std::endl;
155 ost << "CMP " << m_pkg_ref << " " << m_center.first << " " << m_center.second << " " << m_rot
156 << " " << m_mirror << " " << m_comp_name << " " << m_part_name;
157
158 WriteAttributes( ost );
159
160 ost << std::endl;
161
162 for( const auto& [key, value] : m_prp )
163 {
164 ost << "PRP " << key << " " << value << std::endl;
165 }
166
167 for( const auto& toep : m_toeprints )
168 {
169 toep.Write( ost );
170 }
171
172 ost << "#" << std::endl;
173}
174
175
176void ODB_COMPONENT::TOEPRINT::Write( std::ostream& ost ) const
177{
178 ost << "TOP " << m_pin_num << " " << m_center.first << " " << m_center.second << " " << m_rot
179 << " " << m_mirror << " " << m_net_num << " " << m_subnet_num << " " << m_toeprint_name
180 << std::endl;
181}
void WriteAttributes(std::ostream &ost, const std::string &prefix="") const
void AddSystemAttribute(Tr &r, Ta v)
void WriteAttributes(std::ostream &ost) const
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
wxString GetCurrentVariant() const
Definition board.h:473
PCB_IO_ODBPP * m_plugin
Plugin the export runs under, used to report designator changes; may be nullptr.
std::list< ODB_COMPONENT > m_compList
ODB_COMPONENT & AddComponent(const FOOTPRINT *aFp, const EDA_DATA::PACKAGE &aPkg)
void Write(std::ostream &ost) const
std::set< wxString > m_usedCompNames
const size_t m_index
EDA_ANGLE GetOrientation() const
Definition footprint.h:409
int GetAttributes() const
Definition footprint.h:510
bool IsFlipped() const
Definition footprint.h:617
const LIB_ID & GetFPID() const
Definition footprint.h:444
bool GetDNPForVariant(const wxString &aVariantName) const
Get the DNP status for a specific variant.
void GetFields(std::vector< PCB_FIELD * > &aVector, bool aVisibleOnly) const
Populate a std::vector with PCB_TEXTs.
const wxString & GetReference() const
Definition footprint.h:857
VECTOR2I GetPosition() const override
Definition footprint.h:406
const UTF8 & GetLibItemName() const
Definition lib_id.h:98
const wxString GetFullLibraryName() const
Definition lib_id.cpp:262
wxString m_mirror
const size_t m_index
! CMP index number on board to be used in SNT(TOP), 0~n-1
std::list< TOEPRINT > m_toeprints
std::pair< wxString, wxString > m_center
size_t m_pkg_ref
! package ref number from PKG in eda/data file, 0~n-1
wxString m_part_name
! Part identification is a single string of ASCII characters without spaces
void Write(std::ostream &ost) const
wxString m_comp_name
! Unique reference designator (component name)
std::map< wxString, wxString > m_prp
static std::string m_unitsStr
wxString wx_str() const
Definition utf8.cpp:41
#define _(s)
static constexpr EDA_ANGLE ANGLE_0
Definition eda_angle.h:411
static constexpr EDA_ANGLE ANGLE_360
Definition eda_angle.h:417
@ FP_SMD
Definition footprint.h:84
@ FP_THROUGH_HOLE
Definition footprint.h:83
Hashing functions for EDA_ITEMs.
wxString GenLegalComponentName(const wxString &aStr)
Definition odb_util.cpp:79
void RemoveWhitespace(wxString &aStr)
Definition odb_util.cpp:143
std::pair< wxString, wxString > AddXY(const VECTOR2I &aVec)
Definition odb_util.cpp:191
wxString Double2String(double aVal)
Definition odb_util.cpp:151
@ RPT_SEVERITY_WARNING
size_t m_subnet_num
! Number of subnet (SNT record TOP) in the referenced net
std::pair< wxString, wxString > m_center
! Board location of the pin.
void Write(std::ostream &ost) const
size_t m_net_num
! Number of NET record in the eda/data file.
wxString m_mirror
! equal to CMP m_mirror.
const size_t m_pin_num
! index of PIN record in the eda/data file, 0~n-1.
wxString m_toeprint_name
! Name of the pad in PIN record
@ REFERENCE
Field Reference of part, i.e. "IC21".
KIBIS_COMPONENT * comp
wxLogTrace helper definitions.