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
36#include <macros.h>
37#include <functional>
38#include <algorithm>
39#include <vector>
40
41#include <wx/log.h>
42
43using namespace std;
44
45// Common calculation part for all BOARD_ITEMs
46static inline size_t hash_board_item( const BOARD_ITEM* aItem, int aFlags )
47{
48 size_t ret = 0;
49
50 if( aFlags & HASH_LAYER )
51 ret = hash<BASE_SET>{}( aItem->GetLayerSet() );
52
53 return ret;
54}
55
56
57size_t hash_fp_item( const EDA_ITEM* aItem, int aFlags )
58{
59 size_t ret = 0;
60
61 switch( aItem->Type() )
62 {
63 case PCB_FOOTPRINT_T:
64 {
65 const FOOTPRINT* footprint = static_cast<const FOOTPRINT*>( aItem );
66
67 ret = hash_board_item( footprint, aFlags );
68
69 if( aFlags & HASH_POS )
70 hash_combine( ret, footprint->GetPosition().x, footprint->GetPosition().y );
71
72 if( aFlags & HASH_ROT )
73 hash_combine( ret, footprint->GetOrientation().AsDegrees() );
74
75 std::vector<size_t> hashes;
76
77 for( BOARD_ITEM* item : footprint->GraphicalItems() )
78 hashes.push_back( hash_fp_item( item, aFlags ) );
79
80 for( PAD* pad : footprint->Pads() )
81 hashes.push_back( hash_fp_item( static_cast<EDA_ITEM*>( pad ), aFlags ) );
82
83 std::sort( hashes.begin(), hashes.end() );
84
85 for( size_t h : hashes )
86 hash_combine( ret, h );
87 }
88 break;
89
90 case PCB_VIA_T:
91 {
92 const PCB_VIA* via = static_cast<const PCB_VIA*>( aItem );
93
94 ret = hash<int>{}( via->GetDrillValue() );
95 hash_combine( ret, via->TopLayer() );
96 hash_combine( ret, via->BottomLayer() );
97
98 via->GetLayerSet().RunOnLayers(
99 [&]( PCB_LAYER_ID layer )
100 {
101 hash_combine( ret, via->GetWidth( layer ) );
102 hash_combine( ret, via->FlashLayer( layer ) );
103 } );
104
105 break;
106 }
107
108 case PCB_PAD_T:
109 {
110 const PAD* pad = static_cast<const PAD*>( aItem );
111
112 ret = hash<int>{}( static_cast<int>( pad->GetAttribute() ) );
113
114 auto hashPadLayer =
115 [&]( PCB_LAYER_ID aLayer )
116 {
117 hash_combine( ret, pad->GetShape( aLayer ) );
118 hash_combine( ret, pad->GetSize( aLayer ).x, pad->GetSize( aLayer ).y );
119 hash_combine( ret, pad->GetOffset( aLayer ).x, pad->GetOffset( aLayer ).y );
120
121 switch( pad->GetShape( PADSTACK::ALL_LAYERS ) )
122 {
124 hash_combine( ret, pad->GetChamferPositions( aLayer ) );
125 hash_combine( ret, pad->GetChamferRectRatio( aLayer ) );
126 break;
127
129 hash_combine( ret, pad->GetRoundRectCornerRadius( aLayer ) );
130 break;
131
133 hash_combine( ret, pad->GetDelta( aLayer ).x, pad->GetDelta( aLayer ).y );
134 break;
135
137 {
138 auto poly = pad->GetEffectivePolygon( aLayer, ERROR_INSIDE );
139
140 for( int ii = 0; ii < poly->VertexCount(); ++ii )
141 {
142 VECTOR2I point = poly->CVertex( ii ) - pad->GetPosition();
143 hash_combine( ret, point.x, point.y );
144 }
145
146 break;
147 }
148 default:
149 break;
150 }
151 };
152
153 pad->Padstack().ForEachUniqueLayer( hashPadLayer );
154
155 if( pad->GetAttribute() == PAD_ATTRIB::PTH || pad->GetAttribute() == PAD_ATTRIB::NPTH )
156 {
157 hash_combine( ret, pad->GetDrillSizeX(), pad->GetDrillSizeY() );
158 hash_combine( ret, pad->GetDrillShape() );
159
160 pad->GetLayerSet().RunOnLayers(
161 [&]( PCB_LAYER_ID layer )
162 {
163 hash_combine( ret, pad->FlashLayer( layer ) );
164 } );
165 }
166
167 hash_combine( ret, hash_board_item( pad, aFlags ) );
168
169 if( aFlags & HASH_POS )
170 {
171 if( aFlags & REL_COORD )
172 hash_combine( ret, pad->GetFPRelativePosition().x, pad->GetFPRelativePosition().y );
173 else
174 hash_combine( ret, pad->GetPosition().x, pad->GetPosition().y );
175 }
176
177 if( aFlags & HASH_ROT )
178 hash_combine( ret, pad->GetOrientation().AsDegrees() );
179
180 if( aFlags & HASH_NET )
181 hash_combine( ret, pad->GetNetCode() );
182 }
183 break;
184
185 case PCB_FIELD_T:
186 if( !( aFlags & HASH_REF ) && static_cast<const PCB_FIELD*>( aItem )->IsReference() )
187 break;
188
189 if( !( aFlags & HASH_VALUE ) && static_cast<const PCB_FIELD*>( aItem )->IsValue() )
190 break;
191
193 case PCB_TEXT_T:
194 {
195 const PCB_TEXT* text = static_cast<const PCB_TEXT*>( aItem );
196
197 ret = hash_board_item( text, aFlags );
198 hash_combine( ret, text->GetText().ToStdString() );
199 hash_combine( ret, text->IsItalic() );
200 hash_combine( ret, text->IsBold() );
201 hash_combine( ret, text->IsMirrored() );
202 hash_combine( ret, text->GetTextWidth() );
203 hash_combine( ret, text->GetTextHeight() );
204 hash_combine( ret, text->GetHorizJustify() );
205 hash_combine( ret, text->GetVertJustify() );
206
207 if( aFlags & HASH_POS )
208 {
209 VECTOR2I pos = ( aFlags & REL_COORD ) ? text->GetFPRelativePosition()
210 : text->GetPosition();
211
212 hash_combine( ret, pos.x, pos.y );
213 }
214
215 if( aFlags & HASH_ROT )
216 hash_combine( ret, text->GetTextAngle().AsDegrees() );
217 }
218 break;
219
220 case PCB_SHAPE_T:
221 {
222 const PCB_SHAPE* shape = static_cast<const PCB_SHAPE*>( aItem );
223 ret = hash_board_item( shape, aFlags );
224 hash_combine( ret, shape->GetShape() );
225 hash_combine( ret, shape->GetWidth() );
226 hash_combine( ret, shape->GetFillMode() );
227 hash_combine( ret, shape->GetLineStyle() );
228
229 if( shape->GetShape() == SHAPE_T::ARC || shape->GetShape() == SHAPE_T::CIRCLE )
230 hash_combine( ret, shape->GetRadius() );
231
232 if( aFlags & HASH_POS )
233 {
234 std::vector<VECTOR2I> points;
235
236 points.push_back( shape->GetStart() );
237 points.push_back( shape->GetEnd() );
238
239 if( shape->GetShape() == SHAPE_T::CIRCLE )
240 points.push_back( shape->GetCenter() );
241
242 if( shape->GetShape() == SHAPE_T::ARC )
243 points.push_back( shape->GetArcMid() );
244
245 FOOTPRINT* parentFP = shape->GetParentFootprint();
246
247 if( shape->GetShape() == SHAPE_T::POLY )
248 {
249 const SHAPE_POLY_SET& poly = shape->GetPolyShape();
250
251 for( auto it = poly.CIterateWithHoles(); it; it++ )
252 points.push_back( *it );
253 }
254
255 if( shape->GetShape() == SHAPE_T::BEZIER )
256 {
257 points.push_back( shape->GetBezierC1() );
258 points.push_back( shape->GetBezierC2() );
259 }
260
261 if( parentFP && ( aFlags & REL_COORD ) )
262 {
263 for( VECTOR2I& point : points )
264 {
265 point -= parentFP->GetPosition();
266 RotatePoint( point, -parentFP->GetOrientation() );
267 }
268 }
269
270 if( aFlags & REL_POS )
271 {
272 for( VECTOR2I& point : points )
273 point -= shape->GetPosition();
274 }
275
276 //Basic sort of start/end points to try to always draw the same direction (left to right, down to up)
277 //The hashes are summed, so it doesn't matter what order the lines are drawn, only that the same points are used
278 if( points.size() > 1 )
279 {
280 if( points[0].x > points[1].x || points[0].y > points[1].y )
281 {
282 std::swap( points[0], points[1] );
283 }
284 }
285
286 for( VECTOR2I& point : points )
287 hash_combine( ret, point.x, point.y );
288 }
289 }
290 break;
291
292 case PCB_TABLECELL_T:
293 case PCB_TEXTBOX_T:
294 {
295 const PCB_TEXTBOX* textbox = static_cast<const PCB_TEXTBOX*>( aItem );
296
297 ret = hash_board_item( textbox, aFlags );
298 hash_combine( ret, textbox->GetText().ToStdString() );
299 hash_combine( ret, textbox->IsItalic() );
300 hash_combine( ret, textbox->IsBold() );
301 hash_combine( ret, textbox->IsMirrored() );
302 hash_combine( ret, textbox->GetTextWidth() );
303 hash_combine( ret, textbox->GetTextHeight() );
304 hash_combine( ret, textbox->GetHorizJustify() );
305 hash_combine( ret, textbox->GetVertJustify() );
306
307 if( aFlags & HASH_ROT )
308 hash_combine( ret, textbox->GetTextAngle().AsDegrees() );
309
310 hash_combine( ret, textbox->GetShape() );
311 hash_combine( ret, textbox->GetWidth() );
312 hash_combine( ret, textbox->GetLineStyle() );
313
314 if( aFlags & HASH_POS )
315 {
316 VECTOR2I start = textbox->GetStart();
317 VECTOR2I end = textbox->GetEnd();
318
319 FOOTPRINT* parentFP = textbox->GetParentFootprint();
320
321 if( parentFP && ( aFlags & REL_COORD ) )
322 {
323 start -= parentFP->GetPosition();
324 end -= parentFP->GetPosition();
325
326 RotatePoint( start, -parentFP->GetOrientation() );
327 RotatePoint( end, -parentFP->GetOrientation() );
328 }
329
330 hash_combine( ret, start.x );
331 hash_combine( ret, start.y );
332 hash_combine( ret, end.x );
333 hash_combine( ret, end.y );
334 }
335 }
336 break;
337
338 case PCB_TABLE_T:
339 {
340 const PCB_TABLE* table = static_cast<const PCB_TABLE*>( aItem );
341
342 ret = hash_board_item( table, aFlags );
343
344 hash_combine( ret, table->StrokeExternal() );
345 hash_combine( ret, table->StrokeHeaderSeparator() );
346 hash_combine( ret, table->StrokeColumns() );
347 hash_combine( ret, table->StrokeRows() );
348
349 auto hash_stroke =
350 [&]( const STROKE_PARAMS& stroke )
351 {
352 hash_combine( ret, stroke.GetColor() );
353 hash_combine( ret, stroke.GetWidth() );
354 hash_combine( ret, stroke.GetLineStyle() );
355 };
356
357 hash_stroke( table->GetSeparatorsStroke() );
358 hash_stroke( table->GetBorderStroke() );
359 }
360 break;
361
362 default:
363 UNIMPLEMENTED_FOR( aItem->GetClass() );
364 }
365
366 return ret;
367}
@ 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:266
bool IsItalic() const
Definition eda_text.h:168
const EDA_ANGLE & GetTextAngle() const
Definition eda_text.h:146
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:97
int GetTextWidth() const
Definition eda_text.h:263
GR_TEXT_H_ALIGN_T GetHorizJustify() const
Definition eda_text.h:199
bool IsMirrored() const
Definition eda_text.h:189
bool IsBold() const
Definition eda_text.h:183
GR_TEXT_V_ALIGN_T GetVertJustify() const
Definition eda_text.h:202
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
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:57
static size_t hash_board_item(const BOARD_ITEM *aItem, int aFlags)
Definition hash_eda.cpp:46
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
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_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