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->GetText() );
231 hash_combine( ret, barcode->GetTextSize() );
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( shape->GetShape() == SHAPE_T::ELLIPSE || shape->GetShape() == SHAPE_T::ELLIPSE_ARC )
251 {
252 hash_combine( ret, shape->GetEllipseMajorRadius() );
253 hash_combine( ret, shape->GetEllipseMinorRadius() );
254 hash_combine( ret, shape->GetEllipseRotation().AsDegrees() );
255
256 if( shape->GetShape() == SHAPE_T::ELLIPSE_ARC )
257 {
259 hash_combine( ret, shape->GetEllipseEndAngle().AsDegrees() );
260 }
261 }
262
263 if( aFlags & HASH_POS )
264 {
265 std::vector<VECTOR2I> points;
266
267 points.push_back( shape->GetStart() );
268 points.push_back( shape->GetEnd() );
269
270 if( shape->GetShape() == SHAPE_T::CIRCLE )
271 points.push_back( shape->GetCenter() );
272
273 if( shape->GetShape() == SHAPE_T::ARC )
274 points.push_back( shape->GetArcMid() );
275
276 if( shape->GetShape() == SHAPE_T::ELLIPSE || shape->GetShape() == SHAPE_T::ELLIPSE_ARC )
277 {
278 points.push_back( shape->GetEllipseCenter() );
279 }
280
281 FOOTPRINT* parentFP = shape->GetParentFootprint();
282
283 if( shape->GetShape() == SHAPE_T::POLY )
284 {
285 const SHAPE_POLY_SET& poly = shape->GetPolyShape();
286
287 for( auto it = poly.CIterateWithHoles(); it; it++ )
288 points.push_back( *it );
289 }
290
291 if( shape->GetShape() == SHAPE_T::BEZIER )
292 {
293 points.push_back( shape->GetBezierC1() );
294 points.push_back( shape->GetBezierC2() );
295 }
296
297 if( parentFP && ( aFlags & REL_COORD ) )
298 {
299 for( VECTOR2I& point : points )
300 {
301 point -= parentFP->GetPosition();
302 RotatePoint( point, -parentFP->GetOrientation() );
303 }
304 }
305
306 if( aFlags & REL_POS )
307 {
308 for( VECTOR2I& point : points )
309 point -= shape->GetPosition();
310 }
311
312 //Basic sort of start/end points to try to always draw the same direction (left to right, down to up)
313 //The hashes are summed, so it doesn't matter what order the lines are drawn, only that the same points are used
314 if( points.size() > 1 )
315 {
316 if( points[0].x > points[1].x || points[0].y > points[1].y )
317 {
318 std::swap( points[0], points[1] );
319 }
320 }
321
322 for( VECTOR2I& point : points )
323 hash_combine( ret, point.x, point.y );
324 }
325 }
326 break;
327
328 case PCB_TABLECELL_T:
329 case PCB_TEXTBOX_T:
330 {
331 const PCB_TEXTBOX* textbox = static_cast<const PCB_TEXTBOX*>( aItem );
332
333 ret = hash_board_item( textbox, aFlags );
334 hash_combine( ret, textbox->GetText().ToStdString() );
335 hash_combine( ret, textbox->IsItalic() );
336 hash_combine( ret, textbox->IsBold() );
337 hash_combine( ret, textbox->IsMirrored() );
338 hash_combine( ret, textbox->GetTextWidth() );
339 hash_combine( ret, textbox->GetTextHeight() );
340 hash_combine( ret, textbox->GetHorizJustify() );
341 hash_combine( ret, textbox->GetVertJustify() );
342
343 if( aFlags & HASH_ROT )
344 hash_combine( ret, textbox->GetTextAngle().AsDegrees() );
345
346 hash_combine( ret, textbox->GetShape() );
347 hash_combine( ret, textbox->GetWidth() );
348 hash_combine( ret, textbox->GetLineStyle() );
349
350 if( aFlags & HASH_POS )
351 {
352 VECTOR2I start = textbox->GetStart();
353 VECTOR2I end = textbox->GetEnd();
354
355 FOOTPRINT* parentFP = textbox->GetParentFootprint();
356
357 if( parentFP && ( aFlags & REL_COORD ) )
358 {
359 start -= parentFP->GetPosition();
360 end -= parentFP->GetPosition();
361
362 RotatePoint( start, -parentFP->GetOrientation() );
363 RotatePoint( end, -parentFP->GetOrientation() );
364 }
365
366 hash_combine( ret, start.x );
367 hash_combine( ret, start.y );
368 hash_combine( ret, end.x );
369 hash_combine( ret, end.y );
370 }
371 }
372 break;
373
374 case PCB_TABLE_T:
375 {
376 const PCB_TABLE* table = static_cast<const PCB_TABLE*>( aItem );
377
378 ret = hash_board_item( table, aFlags );
379
380 hash_combine( ret, table->StrokeExternal() );
381 hash_combine( ret, table->StrokeHeaderSeparator() );
382 hash_combine( ret, table->StrokeColumns() );
383 hash_combine( ret, table->StrokeRows() );
384
385 auto hash_stroke =
386 [&]( const STROKE_PARAMS& stroke )
387 {
388 hash_combine( ret, stroke.GetColor() );
389 hash_combine( ret, stroke.GetWidth() );
390 hash_combine( ret, stroke.GetLineStyle() );
391 };
392
393 hash_stroke( table->GetSeparatorsStroke() );
394 hash_stroke( table->GetBorderStroke() );
395 }
396 break;
397
398 default:
399 UNIMPLEMENTED_FOR( aItem->GetClass() );
400 }
401
402 return ret;
403}
@ ERROR_INSIDE
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:84
FOOTPRINT * GetParentFootprint() const
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition board_item.h:288
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:100
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:112
int GetEllipseMinorRadius() const
Definition eda_shape.h:306
const VECTOR2I & GetBezierC2() const
Definition eda_shape.h:279
const VECTOR2I & GetEllipseCenter() const
Definition eda_shape.h:288
EDA_ANGLE GetEllipseEndAngle() const
Definition eda_shape.h:334
FILL_T GetFillMode() const
Definition eda_shape.h:162
int GetEllipseMajorRadius() const
Definition eda_shape.h:297
SHAPE_POLY_SET & GetPolyShape()
EDA_ANGLE GetEllipseRotation() const
Definition eda_shape.h:315
int GetRadius() const
SHAPE_T GetShape() const
Definition eda_shape.h:189
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition eda_shape.h:236
LINE_STYLE GetLineStyle() const
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition eda_shape.h:194
EDA_ANGLE GetEllipseStartAngle() const
Definition eda_shape.h:325
const VECTOR2I & GetBezierC1() const
Definition eda_shape.h:276
VECTOR2I GetArcMid() const
int GetTextHeight() const
Definition eda_text.h:292
bool IsItalic() const
Definition eda_text.h:194
const EDA_ANGLE & GetTextAngle() const
Definition eda_text.h:172
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:114
int GetTextWidth() const
Definition eda_text.h:289
GR_TEXT_H_ALIGN_T GetHorizJustify() const
Definition eda_text.h:225
bool IsMirrored() const
Definition eda_text.h:215
bool IsBold() const
Definition eda_text.h:209
GR_TEXT_V_ALIGN_T GetVertJustify() const
Definition eda_text.h:228
EDA_ANGLE GetOrientation() const
Definition footprint.h:408
std::deque< PAD * > & Pads()
Definition footprint.h:377
VECTOR2I GetPosition() const override
Definition footprint.h:405
DRAWINGS & GraphicalItems()
Definition footprint.h:380
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:177
Definition pad.h:55
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.
wxString GetText() const
int GetTextSize() const
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.
@ ELLIPSE
Definition eda_shape.h:56
@ ELLIPSE_ARC
Definition eda_shape.h:57
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:103
@ PTH
Plated through hole pad.
Definition padstack.h:98
@ CHAMFERED_RECT
Definition padstack.h:60
@ ROUNDRECT
Definition padstack.h:57
@ TRAPEZOID
Definition padstack.h:56
BARCODE class definition.
std::vector< std::vector< std::string > > table
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:85
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition typeinfo.h:94
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition typeinfo.h:90
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition typeinfo.h:89
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
Definition typeinfo.h:87
@ PCB_BARCODE_T
class PCB_BARCODE, a barcode (graphic item)
Definition typeinfo.h:98
@ PCB_TABLECELL_T
class PCB_TABLECELL, PCB_TEXTBOX for use in tables
Definition typeinfo.h:92
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
Definition typeinfo.h:83
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition typeinfo.h:84
@ PCB_TABLE_T
class PCB_TABLE, table of PCB_TABLECELLs
Definition typeinfo.h:91
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:687