KiCad PCB EDA Suite
Loading...
Searching...
No Matches
drill_symbol_assigner.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 *
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 2
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 <set>
23
24#include <board.h>
28
29
30void AssignDrillSymbols( std::vector<DRILL_CHART_GROUP>& aGroups, DRILL_SYMBOL_PROFILE& aProfile )
31{
32 const int shapeCount = DRILL_MARKERS::CuratedShapeCount();
33
34 std::set<int> usedShapes;
35 std::set<wxString> usedLetters;
36
37 if( aProfile.GetFreezeAssignments() )
38 {
39 for( DRILL_CHART_GROUP& group : aGroups )
40 {
41 if( const DRILL_SYMBOL_ASSIGNMENT* existing = aProfile.GetAssignment( group.m_SymbolKey ) )
42 {
43 group.m_Symbol = *existing;
44
45 if( existing->m_MarkMode == DRILL_MARK_MODE::SHAPE )
46 usedShapes.insert( existing->m_ShapeIndex );
47 else if( existing->m_MarkMode == DRILL_MARK_MODE::LETTER )
48 usedLetters.insert( existing->m_Letter );
49 }
50 }
51 }
52
53 auto nextLetter =
54 [&]() -> wxString
55 {
56 for( int i = 0; i < 26 * 27; ++i )
57 {
58 wxString candidate;
59
60 if( i < 26 )
61 candidate = wxString::Format( "%c", 'A' + i );
62 else
63 candidate = wxString::Format( "%c%c", 'A' + ( i / 26 ) - 1, 'A' + ( i % 26 ) );
64
65 if( !usedLetters.count( candidate ) )
66 return candidate;
67 }
68
69 return wxT( "?" );
70 };
71
72 for( DRILL_CHART_GROUP& group : aGroups )
73 {
74 if( aProfile.GetFreezeAssignments() && aProfile.GetAssignment( group.m_SymbolKey ) )
75 continue;
76
77 DRILL_SYMBOL_ASSIGNMENT assignment;
78
79 switch( aProfile.GetMarkPolicy() )
80 {
83 break;
84
87 assignment.m_Letter = nextLetter();
88 usedLetters.insert( assignment.m_Letter );
89 break;
90
93 {
94 int shape = -1;
95
96 for( int i = 0; i < shapeCount; ++i )
97 {
98 if( !usedShapes.count( i ) )
99 {
100 shape = i;
101 break;
102 }
103 }
104
105 if( shape >= 0 )
106 {
108 assignment.m_ShapeIndex = shape;
109 usedShapes.insert( shape );
110 }
112 {
114 assignment.m_Letter = nextLetter();
115 usedLetters.insert( assignment.m_Letter );
116 }
117 else
118 {
119 // Out of distinguishable shapes, so reuse from the start rather than draw
120 // nothing at all
122 assignment.m_ShapeIndex = 0;
123 }
124
125 break;
126 }
127 }
128
129 group.m_Symbol = assignment;
130 aProfile.SetAssignment( group.m_SymbolKey, assignment );
131 }
132}
133
134
135std::map<std::string, DRILL_SYMBOL_ASSIGNMENT> ResolveDrillSymbols( const BOARD& aBoard )
136{
138
139 DRILL_CHART_MODEL model( profile );
140 model.Build( aBoard, EnumerateDrillSpans( aBoard ) );
141
142 std::vector<DRILL_CHART_GROUP> groups = model.Groups();
143 AssignDrillSymbols( groups, profile );
144
145 std::map<std::string, DRILL_SYMBOL_ASSIGNMENT> resolved;
146
147 for( const DRILL_CHART_GROUP& group : groups )
148 resolved[group.m_SymbolKey] = group.m_Symbol;
149
150 return resolved;
151}
152
153
154std::map<KIID, std::vector<DRILL_SYMBOL_ENTRY>> ResolveDrillSymbolsByItem(
155 const BOARD& aBoard, const std::map<std::string, DRILL_SYMBOL_ASSIGNMENT>& aResolved )
156{
158
159 std::map<KIID, std::vector<DRILL_SYMBOL_ENTRY>> byItem;
160
161 DRILL_QUERY query;
162 query.m_MergePTHNPTH = true;
163
164 for( const DRILL_SPAN& span : EnumerateDrillSpans( aBoard ) )
165 {
166 query.m_Span = span;
167
168 for( const DRILL_OPERATION& op : EnumerateDrillOperations( aBoard, query ) )
169 {
170 const auto it = aResolved.find( profile.GroupKeyString( op ) );
171
172 if( it == aResolved.end() )
173 continue;
174
175 DRILL_SYMBOL_ENTRY entry;
176 entry.m_Symbol = it->second;
177 entry.m_Span = span;
178 entry.m_Position = op.m_Position;
179 entry.m_Kind = op.m_Kind;
180 entry.m_Diameter = op.m_Diameter;
181 entry.m_SizeXY = op.m_SizeXY;
182 entry.m_Orientation = op.m_Orientation;
183 entry.m_IsSlot = op.m_IsSlot;
184
185 byItem[op.m_SourceId].push_back( entry );
186 }
187 }
188
189 return byItem;
190}
DRILL_SYMBOL_PROFILE & GetDrillSymbolProfile()
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:409
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition board.cpp:1299
Grouping rules and symbol assignments, shared by reference so a chart and its map can never disagree ...
std::string GroupKeyString(const DRILL_OPERATION &aOperation) const
Stable identity for a group under the currently enabled keys.
const DRILL_SYMBOL_ASSIGNMENT * GetAssignment(const std::string &aKey) const
void SetAssignment(const std::string &aKey, const DRILL_SYMBOL_ASSIGNMENT &aAssignment)
DRILL_MARK_POLICY GetMarkPolicy() const
std::vector< DRILL_SPAN > EnumerateDrillSpans(const BOARD &aBoard)
Every drill span present on the board, through-holes first.
std::vector< DRILL_OPERATION > EnumerateDrillOperations(const BOARD &aBoard, const DRILL_QUERY &aQuery)
The one place that decides what the board's holes are.
std::map< KIID, std::vector< DRILL_SYMBOL_ENTRY > > ResolveDrillSymbolsByItem(const BOARD &aBoard, const std::map< std::string, DRILL_SYMBOL_ASSIGNMENT > &aResolved)
The same answer keyed by the item that owns the holes.
std::map< std::string, DRILL_SYMBOL_ASSIGNMENT > ResolveDrillSymbols(const BOARD &aBoard)
The symbol every hole should carry, without touching the board.
void AssignDrillSymbols(std::vector< DRILL_CHART_GROUP > &aGroups, DRILL_SYMBOL_PROFILE &aProfile)
Give every group a mark, keeping the ones the profile already records.
int CuratedShapeCount()
Marks that stay legible at chart size and in monochrome.
One machining action, which is also one NC hit and one tool assignment.
Selects which operations EnumerateDrillOperations() returns.
bool m_MergePTHNPTH
Emit plated and non-plated together, as the merged drill file does.
DRILL_SPAN m_Span
One drawable mark, with the geometry the renderer needs to place it.
int m_Diameter
bool m_IsSlot
DRILL_OP_KIND m_Kind
VECTOR2I m_Position
Where the mark is drawn, which is the hole itself.
VECTOR2I m_SizeXY
DRILL_SPAN m_Span
EDA_ANGLE m_Orientation
DRILL_SYMBOL_ASSIGNMENT m_Symbol
KIBIS_MODEL * model