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 The 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#include <pcb_barcode.h>
36
37#include <macros.h>
38#include <functional>
39#include <algorithm>
40#include <vector>
41
42#include <wx/log.h>
43
44using namespace std;
45
46// Common calculation part for all BOARD_ITEMs
47static inline size_t hash_board_item( const BOARD_ITEM* aItem, int aFlags )
48{
49 size_t ret = 0;
50
51 if( aFlags & HASH_LAYER )
52 ret = hash<BASE_SET>{}( aItem->GetLayerSet() );
53
54 return ret;
55}
56
57
58size_t hash_fp_item( const EDA_ITEM* aItem, int aFlags )
59{
60 size_t ret = 0;
61
62 switch( aItem->Type() )
63 {
64 case PCB_FOOTPRINT_T:
65 {
66 const FOOTPRINT* footprint = static_cast<const FOOTPRINT*>( aItem );
67
68 ret = hash_board_item( footprint, aFlags );
69
70 if( aFlags & HASH_POS )
71 hash_combine( ret, footprint->GetPosition().x, footprint->GetPosition().y );
72
73 if( aFlags & HASH_ROT )
74 hash_combine( ret, footprint->GetOrientation().AsDegrees() );
75
76 std::vector<size_t> hashes;
77
78 for( BOARD_ITEM* item : footprint->GraphicalItems() )
79 hashes.push_back( hash_fp_item( item, aFlags ) );
80
81 for( PAD* pad : footprint->Pads() )
82 hashes.push_back( hash_fp_item( static_cast<EDA_ITEM*>( pad ), aFlags ) );
83
84 std::sort( hashes.begin(), hashes.end() );
85
86 for( size_t h : hashes )
87 hash_combine( ret, h );
88 }
89 break;
90
91 case PCB_VIA_T:
92 {
93 const PCB_VIA* via = static_cast<const PCB_VIA*>( aItem );
94
95 ret = hash<int>{}( via->GetDrillValue() );
96 hash_combine( ret, via->TopLayer() );
97 hash_combine( ret, via->BottomLayer() );
98
99 via->GetLayerSet().RunOnLayers(
100 [&]( PCB_LAYER_ID layer )
101 {
102 hash_combine( ret, via->GetWidth( layer ) );
103 hash_combine( ret, via->FlashLayer( layer ) );
104 } );
105
106 break;
107 }
108
109 case PCB_PAD_T:
110 {
111 const PAD* pad = static_cast<const PAD*>( aItem );
112
113 ret = hash<int>{}( static_cast<int>( pad->GetAttribute() ) );
114
115 auto hashPadLayer =
116 [&]( PCB_LAYER_ID aLayer )
117 {
118 hash_combine( ret, pad->GetShape( aLayer ) );
119 hash_combine( ret, pad->GetSize( aLayer ).x, pad->GetSize( aLayer ).y );
120 hash_combine( ret, pad->GetOffset( aLayer ).x, pad->GetOffset( aLayer ).y );
121
122 switch( pad->GetShape( PADSTACK::ALL_LAYERS ) )
123 {
125 hash_combine( ret, pad->GetChamferPositions( aLayer ) );
126 hash_combine( ret, pad->GetChamferRectRatio( aLayer ) );
127 break;
128
130 hash_combine( ret, pad->GetRoundRectCornerRadius( aLayer ) );
131 break;
132
134 hash_combine( ret, pad->GetDelta( aLayer ).x, pad->GetDelta( aLayer ).y );
135 break;
136
138 {
139 auto poly = pad->GetEffectivePolygon( aLayer, ERROR_INSIDE );
140
141 for( int ii = 0; ii < poly->VertexCount(); ++ii )
142 {
143 VECTOR2I point = poly->CVertex( ii ) - pad->GetPosition();
144 hash_combine( ret, point.x, point.y );
145 }
146
147 break;
148 }
149 default:
150 break;
151 }
152 };
153
154 pad->Padstack().ForEachUniqueLayer( hashPadLayer );
155
156 if( pad->GetAttribute() == PAD_ATTRIB::PTH || pad->GetAttribute() == PAD_ATTRIB::NPTH )
157 {
158 hash_combine( ret, pad->GetDrillSizeX(), pad->GetDrillSizeY() );
159 hash_combine( ret, pad->GetDrillShape() );
160
161 pad->GetLayerSet().RunOnLayers(
162 [&]( PCB_LAYER_ID layer )
163 {
164 hash_combine( ret, pad->FlashLayer( layer ) );
165 } );
166 }
167
168 hash_combine( ret, hash_board_item( pad, aFlags ) );
169
170 if( aFlags & HASH_POS )
171 {
172 if( aFlags & REL_COORD )
173 hash_combine( ret, pad->GetFPRelativePosition().x, pad->GetFPRelativePosition().y );
174 else
175 hash_combine( ret, pad->GetPosition().x, pad->GetPosition().y );
176 }
177
178 if( aFlags & HASH_ROT )
179 hash_combine( ret, pad->GetOrientation().AsDegrees() );
180
181 if( aFlags & HASH_NET )
182 hash_combine( ret, pad->GetNetCode() );
183 }
184 break;
185
186 case PCB_FIELD_T:
187 if( !( aFlags & HASH_REF ) && static_cast<const PCB_FIELD*>( aItem )->IsReference() )
188 break;
189
190 if( !( aFlags & HASH_VALUE ) && static_cast<const PCB_FIELD*>( aItem )->IsValue() )
191 break;
192
194 case PCB_TEXT_T:
195 {
196 const PCB_TEXT* text = static_cast<const PCB_TEXT*>( aItem );
197
198 ret = hash_board_item( text, aFlags );
199 hash_combine( ret, text->GetText().ToStdString() );
200 hash_combine( ret, text->IsItalic() );
201 hash_combine( ret, text->IsBold() );
202 hash_combine( ret, text->IsMirrored() );
203 hash_combine( ret, text->GetTextWidth() );
204 hash_combine( ret, text->GetTextHeight() );
205 hash_combine( ret, text->GetHorizJustify() );
206 hash_combine( ret, text->GetVertJustify() );
207
208 if( aFlags & HASH_POS )
209 {
210 VECTOR2I pos = ( aFlags & REL_COORD ) ? text->GetFPRelativePosition()
211 : text->GetPosition();
212
213 hash_combine( ret, pos.x, pos.y );
214 }
215
216 if( aFlags & HASH_ROT )
217 hash_combine( ret, text->GetTextAngle().AsDegrees() );
218
219 break;
220 }
221
222 case PCB_BARCODE_T:
223 {
224 const PCB_BARCODE* barcode = static_cast<const PCB_BARCODE*>( aItem );
225
226 ret = hash_board_item( barcode, aFlags );
227 hash_combine( ret, barcode->GetWidth(), barcode->GetHeight() );
228 hash_combine( ret, barcode->GetPosition().x, barcode->GetPosition().y );
229 hash_combine( ret, barcode->GetMargin().x, barcode->GetMargin().y );
230 hash_combine( ret, barcode->Text().GetText().ToStdString() );
231 hash_combine( ret, barcode->Text().GetTextHeight() );
232 hash_combine( ret, barcode->GetKind() );
233 hash_combine( ret, barcode->GetAngle().AsDegrees() );
234 hash_combine( ret, barcode->GetErrorCorrection() );
235 break;
236 }
237
238 case PCB_SHAPE_T:
239 {
240 const PCB_SHAPE* shape = static_cast<const PCB_SHAPE*>( aItem );
241 ret = hash_board_item( shape, aFlags );
242 hash_combine( ret, shape->GetShape() );
243 hash_combine( ret, shape->GetWidth() );
244 hash_combine( ret, shape->GetFillMode() );
245 hash_combine( ret, shape->GetLineStyle() );
246
247 if( shape->GetShape() == SHAPE_T::ARC || shape->GetShape() == SHAPE_T::CIRCLE )
248 hash_combine( ret, shape->GetRadius() );
249
250 if( aFlags & HASH_POS )
251 {
252 std::vector<VECTOR2I> points;
253
254 points.push_back( shape->GetStart() );
255 points.push_back( shape->GetEnd() );
256
257 if( shape->GetShape() == SHAPE_T::CIRCLE )
258 points.push_back( shape->GetCenter() );
259
260 if( shape->GetShape() == SHAPE_T::ARC )
261 points.push_back( shape->GetArcMid() );
262
263 FOOTPRINT* parentFP = shape->GetParentFootprint();
264
265 if( shape->GetShape() == SHAPE_T::POLY )
266 {
267 const SHAPE_POLY_SET& poly = shape->GetPolyShape();
268
269 for( auto it = poly.CIterateWithHoles(); it; it++ )
270 points.push_back( *it );
271 }
272
273 if( shape->GetShape() == SHAPE_T::BEZIER )
274 {
275 points.push_back( shape->GetBezierC1() );
276 points.push_back( shape->GetBezierC2() );
277 }
278
279 if( parentFP && ( aFlags & REL_COORD ) )
280 {
281 for( VECTOR2I& point : points )
282 {
283 point -= parentFP->GetPosition();
284 RotatePoint( point, -parentFP->GetOrientation() );
285 }
286 }
287
288 if( aFlags & REL_POS )
289 {
290 for( VECTOR2I& point : points )
291 point -= shape->GetPosition();
292 }
293
294 //Basic sort of start/end points to try to always draw the same direction (left to right, down to up)
295 //The hashes are summed, so it doesn't matter what order the lines are drawn, only that the same points are used
296 if( points.size() > 1 )
297 {
298 if( points[0].x > points[1].x || points[0].y > points[1].y )
299 {
300 std::swap( points[0], points[1] );
301 }
302 }
303
304 for( VECTOR2I& point : points )
305 hash_combine( ret, point.x, point.y );
306 }
307 }
308 break;
309
310 case PCB_TABLECELL_T:
311 case PCB_TEXTBOX_T:
312 {
313 const PCB_TEXTBOX* textbox = static_cast<const PCB_TEXTBOX*>( aItem );
314
315 ret = hash_board_item( textbox, aFlags );
316 hash_combine( ret, textbox->GetText().ToStdString() );
317 hash_combine( ret, textbox->IsItalic() );
318 hash_combine( ret, textbox->IsBold() );
319 hash_combine( ret, textbox->IsMirrored() );
320 hash_combine( ret, textbox->GetTextWidth() );
321 hash_combine( ret, textbox->GetTextHeight() );
322 hash_combine( ret, textbox->GetHorizJustify() );
323 hash_combine( ret, textbox->GetVertJustify() );
324
325 if( aFlags & HASH_ROT )
326 hash_combine( ret, textbox->GetTextAngle().AsDegrees() );
327
328 hash_combine( ret, textbox->GetShape() );
329 hash_combine( ret, textbox->GetWidth() );
330 hash_combine( ret, textbox->GetLineStyle() );
331
332 if( aFlags & HASH_POS )
333 {
334 VECTOR2I start = textbox->GetStart();
335 VECTOR2I end = textbox->GetEnd();
336
337 FOOTPRINT* parentFP = textbox->GetParentFootprint();
338
339 if( parentFP && ( aFlags & REL_COORD ) )
340 {
341 start -= parentFP->GetPosition();
342 end -= parentFP->GetPosition();
343
344 RotatePoint( start, -parentFP->GetOrientation() );
345 RotatePoint( end, -parentFP->GetOrientation() );
346 }
347
348 hash_combine( ret, start.x );
349 hash_combine( ret, start.y );
350 hash_combine( ret, end.x );
351 hash_combine( ret, end.y );
352 }
353 }
354 break;
355
356 case PCB_TABLE_T:
357 {
358 const PCB_TABLE* table = static_cast<const PCB_TABLE*>( aItem );
359
360 ret = hash_board_item( table, aFlags );
361
362 hash_combine( ret, table->StrokeExternal() );
363 hash_combine( ret, table->StrokeHeaderSeparator() );
364 hash_combine( ret, table->StrokeColumns() );
365 hash_combine( ret, table->StrokeRows() );
366
367 auto hash_stroke =
368 [&]( const STROKE_PARAMS& stroke )
369 {
370 hash_combine( ret, stroke.GetColor() );
371 hash_combine( ret, stroke.GetWidth() );
372 hash_combine( ret, stroke.GetLineStyle() );
373 };
374
375 hash_stroke( table->GetSeparatorsStroke() );
376 hash_stroke( table->GetBorderStroke() );
377 }
378 break;
379
380 default:
381 UNIMPLEMENTED_FOR( aItem->GetClass() );
382 }
383
384 return ret;
385}
@ ERROR_INSIDE
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
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition board_item.h:252
double AsDegrees() const
Definition eda_angle.h:116
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:98
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
const VECTOR2I & GetBezierC2() const
Definition eda_shape.h:258
FILL_T GetFillMode() const
Definition eda_shape.h:142
SHAPE_POLY_SET & GetPolyShape()
Definition eda_shape.h:337
int GetRadius() const
SHAPE_T GetShape() const
Definition eda_shape.h:168
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition eda_shape.h:215
LINE_STYLE GetLineStyle() const
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition eda_shape.h:173
const VECTOR2I & GetBezierC1() const
Definition eda_shape.h:255
VECTOR2I GetArcMid() const
int GetTextHeight() const
Definition eda_text.h:267
bool IsItalic() const
Definition eda_text.h:169
const EDA_ANGLE & GetTextAngle() const
Definition eda_text.h:147
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:264
GR_TEXT_H_ALIGN_T GetHorizJustify() const
Definition eda_text.h:200
bool IsMirrored() const
Definition eda_text.h:190
bool IsBold() const
Definition eda_text.h:184
GR_TEXT_V_ALIGN_T GetVertJustify() const
Definition eda_text.h:203
EDA_ANGLE GetOrientation() const
Definition footprint.h:248
std::deque< PAD * > & Pads()
Definition footprint.h:224
VECTOR2I GetPosition() const override
Definition footprint.h:245
DRAWINGS & GraphicalItems()
Definition footprint.h:227
virtual wxString GetClass() const =0
Return the class name.
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
Definition padstack.h:145
Definition pad.h:54
PCB_TEXT & Text()
Access the internal PCB_TEXT object used for showing the human-readable text.
const VECTOR2I & GetMargin() const
Get the barcode margin (in internal units).
VECTOR2I GetPosition() const override
Get the position (center) of the barcode in internal units.
int GetHeight() const
Get the barcode height (in internal units).
BARCODE_ECC_T GetErrorCorrection() const
EDA_ANGLE GetAngle() const
BARCODE_T GetKind() const
Returns the type of the barcode (QR, CODE_39, etc.).
int GetWidth() const
Get the barcode width (in internal units).
VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
Definition pcb_shape.h:81
int GetWidth() const override
VECTOR2I GetPosition() const override
Definition pcb_shape.h:79
Represent a set of closed polygons.
CONST_ITERATOR CIterateWithHoles(int aOutline) const
Simple container to manage line stroke parameters.
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:58
static size_t hash_board_item(const BOARD_ITEM *aItem, int aFlags)
Definition hash_eda.cpp:47
Hashing functions for EDA_ITEMs.
@ HASH_POS
Definition hash_eda.h:47
@ HASH_VALUE
Definition hash_eda.h:58
@ REL_COORD
Use coordinates relative to the parent object.
Definition hash_eda.h:50
@ HASH_LAYER
Definition hash_eda.h:55
@ HASH_REF
Definition hash_eda.h:57
@ REL_POS
Use coordinates relative to the shape position.
Definition hash_eda.h:53
@ HASH_ROT
Definition hash_eda.h:54
@ HASH_NET
Definition hash_eda.h:56
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
#define UNIMPLEMENTED_FOR(type)
Definition macros.h:96
STL namespace.
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
Definition padstack.h:87
@ PTH
Plated through hole pad.
Definition padstack.h:82
@ CHAMFERED_RECT
Definition padstack.h:60
@ ROUNDRECT
Definition padstack.h:57
@ TRAPEZOID
Definition padstack.h:56
BARCODE class definition.
VECTOR2I end
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_BARCODE_T
class PCB_BARCODE, a barcode (graphic item)
Definition typeinfo.h:101
@ 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
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695