KiCad PCB EDA Suite
Loading...
Searching...
No Matches
hash_eda.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) 2017 CERN
5 * Copyright (C) 2020-2023 KiCad Developers, see AUTHORS.txt for contributors.
6 * @author Maciej Suminski <[email protected]>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26#include <hash_eda.h>
27#include <hash.h>
28#include <footprint.h>
29#include <pcb_text.h>
30#include <pcb_table.h>
31#include <pcb_textbox.h>
32#include <pcb_shape.h>
33#include <pad.h>
34#include <pcb_track.h>
35
36#include <macros.h>
37#include <functional>
38
39#include <wx/log.h>
40
41using namespace std;
42
43// Common calculation part for all BOARD_ITEMs
44static inline size_t hash_board_item( const BOARD_ITEM* aItem, int aFlags )
45{
46 size_t ret = 0;
47
48 if( aFlags & HASH_LAYER )
49 ret = hash<BASE_SET>{}( aItem->GetLayerSet() );
50
51 return ret;
52}
53
54
55size_t hash_fp_item( const EDA_ITEM* aItem, int aFlags )
56{
57 size_t ret = 0;
58
59 switch( aItem->Type() )
60 {
61 case PCB_FOOTPRINT_T:
62 {
63 const FOOTPRINT* footprint = static_cast<const FOOTPRINT*>( aItem );
64
65 ret = hash_board_item( footprint, aFlags );
66
67 if( aFlags & HASH_POS )
68 hash_combine( ret, footprint->GetPosition().x, footprint->GetPosition().y );
69
70 if( aFlags & HASH_ROT )
71 hash_combine( ret, footprint->GetOrientation().AsDegrees() );
72
73 for( BOARD_ITEM* item : footprint->GraphicalItems() )
74 hash_combine( ret, hash_fp_item( item, aFlags ) );
75
76 for( PAD* pad : footprint->Pads() )
77 hash_combine( ret, hash_fp_item( static_cast<EDA_ITEM*>( pad ), aFlags ) );
78 }
79 break;
80
81 case PCB_VIA_T:
82 {
83 const PCB_VIA* via = static_cast<const PCB_VIA*>( aItem );
84
85 ret = hash<int>{}( via->GetDrillValue() );
86 hash_combine( ret, via->TopLayer() );
87 hash_combine( ret, via->BottomLayer() );
88
89 via->GetLayerSet().RunOnLayers(
90 [&]( PCB_LAYER_ID layer )
91 {
92 hash_combine( ret, via->GetWidth( layer ) );
93 hash_combine( ret, via->FlashLayer( layer ) );
94 } );
95
96 break;
97 }
98
99 case PCB_PAD_T:
100 {
101 const PAD* pad = static_cast<const PAD*>( aItem );
102
103 ret = hash<int>{}( static_cast<int>( pad->GetAttribute() ) );
104
105 auto hashPadLayer =
106 [&]( PCB_LAYER_ID aLayer )
107 {
108 hash_combine( ret, pad->GetShape( aLayer ) );
109 hash_combine( ret, pad->GetSize( aLayer ).x, pad->GetSize( aLayer ).y );
110 hash_combine( ret, pad->GetOffset( aLayer ).x, pad->GetOffset( aLayer ).y );
111
112 switch( pad->GetShape( PADSTACK::ALL_LAYERS ) )
113 {
115 hash_combine( ret, pad->GetChamferPositions( aLayer ) );
116 hash_combine( ret, pad->GetChamferRectRatio( aLayer ) );
117 break;
118
120 hash_combine( ret, pad->GetRoundRectCornerRadius( aLayer ) );
121 break;
122
124 hash_combine( ret, pad->GetDelta( aLayer ).x, pad->GetDelta( aLayer ).y );
125 break;
126
128 {
129 auto poly = pad->GetEffectivePolygon( aLayer, ERROR_INSIDE );
130
131 for( int ii = 0; ii < poly->VertexCount(); ++ii )
132 {
133 VECTOR2I point = poly->CVertex( ii ) - pad->GetPosition();
134 hash_combine( ret, point.x, point.y );
135 }
136
137 break;
138 }
139 default:
140 break;
141 }
142 };
143
144 pad->Padstack().ForEachUniqueLayer( hashPadLayer );
145
146 if( pad->GetAttribute() == PAD_ATTRIB::PTH || pad->GetAttribute() == PAD_ATTRIB::NPTH )
147 {
148 hash_combine( ret, pad->GetDrillSizeX(), pad->GetDrillSizeY() );
149 hash_combine( ret, pad->GetDrillShape() );
150
151 pad->GetLayerSet().RunOnLayers(
152 [&]( PCB_LAYER_ID layer )
153 {
154 hash_combine( ret, pad->FlashLayer( layer ) );
155 } );
156 }
157
158 hash_combine( ret, hash_board_item( pad, aFlags ) );
159
160 if( aFlags & HASH_POS )
161 {
162 if( aFlags & REL_COORD )
163 hash_combine( ret, pad->GetFPRelativePosition().x, pad->GetFPRelativePosition().y );
164 else
165 hash_combine( ret, pad->GetPosition().x, pad->GetPosition().y );
166 }
167
168 if( aFlags & HASH_ROT )
169 hash_combine( ret, pad->GetOrientation().AsDegrees() );
170
171 if( aFlags & HASH_NET )
172 hash_combine( ret, pad->GetNetCode() );
173 }
174 break;
175
176 case PCB_FIELD_T:
177 if( !( aFlags & HASH_REF ) && static_cast<const PCB_FIELD*>( aItem )->IsReference() )
178 break;
179
180 if( !( aFlags & HASH_VALUE ) && static_cast<const PCB_FIELD*>( aItem )->IsValue() )
181 break;
182
184 case PCB_TEXT_T:
185 {
186 const PCB_TEXT* text = static_cast<const PCB_TEXT*>( aItem );
187
188 ret = hash_board_item( text, aFlags );
189 hash_combine( ret, text->GetText().ToStdString() );
190 hash_combine( ret, text->IsItalic() );
191 hash_combine( ret, text->IsBold() );
192 hash_combine( ret, text->IsMirrored() );
193 hash_combine( ret, text->GetTextWidth() );
194 hash_combine( ret, text->GetTextHeight() );
195 hash_combine( ret, text->GetHorizJustify() );
196 hash_combine( ret, text->GetVertJustify() );
197
198 if( aFlags & HASH_POS )
199 {
200 VECTOR2I pos = ( aFlags & REL_COORD ) ? text->GetFPRelativePosition()
201 : text->GetPosition();
202
203 hash_combine( ret, pos.x, pos.y );
204 }
205
206 if( aFlags & HASH_ROT )
207 hash_combine( ret, text->GetTextAngle().AsDegrees() );
208 }
209 break;
210
211 case PCB_SHAPE_T:
212 {
213 const PCB_SHAPE* shape = static_cast<const PCB_SHAPE*>( aItem );
214 ret = hash_board_item( shape, aFlags );
215 hash_combine( ret, shape->GetShape() );
216 hash_combine( ret, shape->GetWidth() );
217 hash_combine( ret, shape->IsFilled() );
218 hash_combine( ret, shape->GetLineStyle() );
219
220 if( shape->GetShape() == SHAPE_T::ARC || shape->GetShape() == SHAPE_T::CIRCLE )
221 hash_combine( ret, shape->GetRadius() );
222
223 if( aFlags & HASH_POS )
224 {
225 std::vector<VECTOR2I> points;
226
227 points.push_back( shape->GetStart() );
228 points.push_back( shape->GetEnd() );
229
230 if( shape->GetShape() == SHAPE_T::CIRCLE )
231 points.push_back( shape->GetCenter() );
232
233 if( shape->GetShape() == SHAPE_T::ARC )
234 points.push_back( shape->GetArcMid() );
235
236 FOOTPRINT* parentFP = shape->GetParentFootprint();
237
238 if( shape->GetShape() == SHAPE_T::POLY )
239 {
240 const SHAPE_POLY_SET& poly = shape->GetPolyShape();
241
242 for( auto it = poly.CIterateWithHoles(); it; it++ )
243 points.push_back( *it );
244 }
245
246 if( shape->GetShape() == SHAPE_T::BEZIER )
247 {
248 points.push_back( shape->GetBezierC1() );
249 points.push_back( shape->GetBezierC2() );
250 }
251
252 if( parentFP && ( aFlags & REL_COORD ) )
253 {
254 for( VECTOR2I& point : points )
255 {
256 point -= parentFP->GetPosition();
257 RotatePoint( point, -parentFP->GetOrientation() );
258 }
259 }
260
261 if( aFlags & REL_POS )
262 {
263 for( VECTOR2I& point : points )
264 point -= shape->GetPosition();
265 }
266
267 for( VECTOR2I& point : points )
268 hash_combine( ret, point.x, point.y );
269 }
270 }
271 break;
272
273 case PCB_TABLECELL_T:
274 case PCB_TEXTBOX_T:
275 {
276 const PCB_TEXTBOX* textbox = static_cast<const PCB_TEXTBOX*>( aItem );
277
278 ret = hash_board_item( textbox, aFlags );
279 hash_combine( ret, textbox->GetText().ToStdString() );
280 hash_combine( ret, textbox->IsItalic() );
281 hash_combine( ret, textbox->IsBold() );
282 hash_combine( ret, textbox->IsMirrored() );
283 hash_combine( ret, textbox->GetTextWidth() );
284 hash_combine( ret, textbox->GetTextHeight() );
285 hash_combine( ret, textbox->GetHorizJustify() );
286 hash_combine( ret, textbox->GetVertJustify() );
287
288 if( aFlags & HASH_ROT )
289 hash_combine( ret, textbox->GetTextAngle().AsDegrees() );
290
291 hash_combine( ret, textbox->GetShape() );
292 hash_combine( ret, textbox->GetWidth() );
293 hash_combine( ret, textbox->GetLineStyle() );
294
295 if( aFlags & HASH_POS )
296 {
297 VECTOR2I start = textbox->GetStart();
298 VECTOR2I end = textbox->GetEnd();
299
300 FOOTPRINT* parentFP = textbox->GetParentFootprint();
301
302 if( parentFP && ( aFlags & REL_COORD ) )
303 {
304 start -= parentFP->GetPosition();
305 end -= parentFP->GetPosition();
306
307 RotatePoint( start, -parentFP->GetOrientation() );
308 RotatePoint( end, -parentFP->GetOrientation() );
309 }
310
311 hash_combine( ret, start.x );
312 hash_combine( ret, start.y );
313 hash_combine( ret, end.x );
314 hash_combine( ret, end.y );
315 }
316 }
317 break;
318
319 case PCB_TABLE_T:
320 {
321 const PCB_TABLE* table = static_cast<const PCB_TABLE*>( aItem );
322
323 ret = hash_board_item( table, aFlags );
324
325 hash_combine( ret, table->StrokeExternal() );
326 hash_combine( ret, table->StrokeHeader() );
327 hash_combine( ret, table->StrokeColumns() );
328 hash_combine( ret, table->StrokeRows() );
329
330 auto hash_stroke =
331 [&]( const STROKE_PARAMS& stroke )
332 {
333 hash_combine( ret, stroke.GetColor() );
334 hash_combine( ret, stroke.GetWidth() );
335 hash_combine( ret, stroke.GetLineStyle() );
336 };
337
338 hash_stroke( table->GetSeparatorsStroke() );
339 hash_stroke( table->GetBorderStroke() );
340 }
341 break;
342
343 default:
344 wxASSERT_MSG( false, "Unhandled type in function hash_fp_item() (exporter_gencad.cpp)" );
345 }
346
347 return ret;
348}
@ ERROR_INSIDE
Definition: approximation.h:34
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:79
FOOTPRINT * GetParentFootprint() const
Definition: board_item.cpp:298
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:257
double AsDegrees() const
Definition: eda_angle.h:113
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:89
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:101
const VECTOR2I & GetBezierC2() const
Definition: eda_shape.h:213
SHAPE_POLY_SET & GetPolyShape()
Definition: eda_shape.h:286
bool IsFilled() const
Definition: eda_shape.h:98
int GetRadius() const
Definition: eda_shape.cpp:826
SHAPE_T GetShape() const
Definition: eda_shape.h:132
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition: eda_shape.h:174
LINE_STYLE GetLineStyle() const
Definition: eda_shape.cpp:2041
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition: eda_shape.h:137
const VECTOR2I & GetBezierC1() const
Definition: eda_shape.h:210
VECTOR2I GetArcMid() const
Definition: eda_shape.cpp:796
int GetTextHeight() const
Definition: eda_text.h:251
bool IsItalic() const
Definition: eda_text.h:156
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:134
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:98
int GetTextWidth() const
Definition: eda_text.h:248
GR_TEXT_H_ALIGN_T GetHorizJustify() const
Definition: eda_text.h:187
bool IsMirrored() const
Definition: eda_text.h:177
bool IsBold() const
Definition: eda_text.h:171
GR_TEXT_V_ALIGN_T GetVertJustify() const
Definition: eda_text.h:190
EDA_ANGLE GetOrientation() const
Definition: footprint.h:227
std::deque< PAD * > & Pads()
Definition: footprint.h:206
VECTOR2I GetPosition() const override
Definition: footprint.h:224
DRAWINGS & GraphicalItems()
Definition: footprint.h:209
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
Definition: padstack.h:144
Definition: pad.h:54
VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
Definition: pcb_shape.h:79
int GetWidth() const override
Definition: pcb_shape.cpp:301
VECTOR2I GetPosition() const override
Definition: pcb_shape.h:77
bool StrokeRows() const
Definition: pcb_table.h:86
bool StrokeColumns() const
Definition: pcb_table.h:83
bool StrokeExternal() const
Definition: pcb_table.h:53
bool StrokeHeader() const
Definition: pcb_table.h:56
const STROKE_PARAMS & GetSeparatorsStroke() const
Definition: pcb_table.h:71
const STROKE_PARAMS & GetBorderStroke() const
Definition: pcb_table.h:59
Represent a set of closed polygons.
CONST_ITERATOR CIterateWithHoles(int aOutline) const
Simple container to manage line stroke parameters.
Definition: stroke_params.h:79
@ ARC
use RECTANGLE instead of RECT to avoid collision in a Windows header
static constexpr void hash_combine(std::size_t &seed)
This is a dummy function to take the final case of hash_combine below.
Definition: hash.h:32
size_t hash_fp_item(const EDA_ITEM *aItem, int aFlags)
Calculate hash of an EDA_ITEM.
Definition: hash_eda.cpp:55
static size_t hash_board_item(const BOARD_ITEM *aItem, int aFlags)
Definition: hash_eda.cpp:44
@ HASH_POS
use coordinates relative to the parent object
Definition: hash_eda.h:43
@ HASH_VALUE
Definition: hash_eda.h:53
@ REL_COORD
use coordinates relative to the shape position
Definition: hash_eda.h:46
@ HASH_LAYER
Definition: hash_eda.h:50
@ HASH_REF
Definition: hash_eda.h:52
@ REL_POS
Definition: hash_eda.h:48
@ HASH_ROT
Definition: hash_eda.h:49
@ HASH_NET
Definition: hash_eda.h:51
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
This file contains miscellaneous commonly used macros and functions.
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition: macros.h:83
STL namespace.
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
@ PTH
Plated through hole pad.
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition: trigo.cpp:229
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:88
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition: typeinfo.h:93
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition: typeinfo.h:92
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
Definition: typeinfo.h:90
@ PCB_TABLECELL_T
class PCB_TABLECELL, PCB_TEXTBOX for use in tables
Definition: typeinfo.h:95
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
Definition: typeinfo.h:86
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition: typeinfo.h:87
@ PCB_TABLE_T
class PCB_TABLE, table of PCB_TABLECELLs
Definition: typeinfo.h:94