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_textbox.h>
31#include <pcb_shape.h>
32#include <pad.h>
33#include <pcb_track.h>
34
35#include <macros.h>
36#include <functional>
37
38#include <wx/log.h>
39
40using namespace std;
41
42// Common calculation part for all BOARD_ITEMs
43static inline size_t hash_board_item( const BOARD_ITEM* aItem, int aFlags )
44{
45 size_t ret = 0;
46
47 if( aFlags & HASH_LAYER )
48 ret = hash<BASE_SET>{}( aItem->GetLayerSet() );
49
50 return ret;
51}
52
53
54size_t hash_fp_item( const EDA_ITEM* aItem, int aFlags )
55{
56 size_t ret = 0;
57
58 switch( aItem->Type() )
59 {
60 case PCB_FOOTPRINT_T:
61 {
62 const FOOTPRINT* footprint = static_cast<const FOOTPRINT*>( aItem );
63
64 ret = hash_board_item( footprint, aFlags );
65
66 if( aFlags & HASH_POS )
67 hash_combine( ret, footprint->GetPosition().x, footprint->GetPosition().y );
68
69 if( aFlags & HASH_ROT )
70 hash_combine( ret, footprint->GetOrientation().AsDegrees() );
71
72 for( BOARD_ITEM* item : footprint->GraphicalItems() )
73 hash_combine( ret, hash_fp_item( item, aFlags ) );
74
75 for( PAD* pad : footprint->Pads() )
76 hash_combine( ret, hash_fp_item( static_cast<EDA_ITEM*>( pad ), aFlags ) );
77 }
78 break;
79
80 case PCB_VIA_T:
81 {
82 const PCB_VIA* via = static_cast<const PCB_VIA*>( aItem );
83
84 ret = hash<int>{}( via->GetDrillValue() );
85 hash_combine( ret, via->TopLayer() );
86 hash_combine( ret, via->BottomLayer() );
87
88 via->GetLayerSet().RunOnLayers(
89 [&]( PCB_LAYER_ID layer )
90 {
91 hash_combine( ret, via->GetWidth( layer ) );
92 hash_combine( ret, via->FlashLayer( layer ) );
93 } );
94
95 break;
96 }
97
98 case PCB_PAD_T:
99 {
100 const PAD* pad = static_cast<const PAD*>( aItem );
101
102 ret = hash<int>{}( static_cast<int>( pad->GetAttribute() ) );
103
104 auto hashPadLayer =
105 [&]( PCB_LAYER_ID aLayer )
106 {
107 hash_combine( ret, pad->GetShape( aLayer ) );
108 hash_combine( ret, pad->GetSize( aLayer ).x, pad->GetSize( aLayer ).y );
109 hash_combine( ret, pad->GetOffset( aLayer ).x, pad->GetOffset( aLayer ).y );
110
111 switch( pad->GetShape( PADSTACK::ALL_LAYERS ) )
112 {
114 hash_combine( ret, pad->GetChamferPositions( aLayer ) );
115 hash_combine( ret, pad->GetChamferRectRatio( aLayer ) );
116 break;
117
119 hash_combine( ret, pad->GetRoundRectCornerRadius( aLayer ) );
120 break;
121
123 hash_combine( ret, pad->GetDelta( aLayer ).x, pad->GetDelta( aLayer ).y );
124 break;
125
127 {
128 auto poly = pad->GetEffectivePolygon( aLayer, ERROR_INSIDE );
129
130 for( int ii = 0; ii < poly->VertexCount(); ++ii )
131 {
132 VECTOR2I point = poly->CVertex( ii ) - pad->GetPosition();
133 hash_combine( ret, point.x, point.y );
134 }
135
136 break;
137 }
138 default:
139 break;
140 }
141 };
142
143 pad->Padstack().ForEachUniqueLayer( hashPadLayer );
144
145 if( pad->GetAttribute() == PAD_ATTRIB::PTH || pad->GetAttribute() == PAD_ATTRIB::NPTH )
146 {
147 hash_combine( ret, pad->GetDrillSizeX(), pad->GetDrillSizeY() );
148 hash_combine( ret, pad->GetDrillShape() );
149
150 pad->GetLayerSet().RunOnLayers(
151 [&]( PCB_LAYER_ID layer )
152 {
153 hash_combine( ret, pad->FlashLayer( layer ) );
154 } );
155 }
156
157 hash_combine( ret, hash_board_item( pad, aFlags ) );
158
159 if( aFlags & HASH_POS )
160 {
161 if( aFlags & REL_COORD )
162 hash_combine( ret, pad->GetFPRelativePosition().x, pad->GetFPRelativePosition().y );
163 else
164 hash_combine( ret, pad->GetPosition().x, pad->GetPosition().y );
165 }
166
167 if( aFlags & HASH_ROT )
168 hash_combine( ret, pad->GetOrientation().AsDegrees() );
169
170 if( aFlags & HASH_NET )
171 hash_combine( ret, pad->GetNetCode() );
172 }
173 break;
174
175 case PCB_FIELD_T:
176 if( !( aFlags & HASH_REF ) && static_cast<const PCB_FIELD*>( aItem )->IsReference() )
177 break;
178
179 if( !( aFlags & HASH_VALUE ) && static_cast<const PCB_FIELD*>( aItem )->IsValue() )
180 break;
181
183 case PCB_TEXT_T:
184 {
185 const PCB_TEXT* text = static_cast<const PCB_TEXT*>( aItem );
186
187 ret = hash_board_item( text, aFlags );
188 hash_combine( ret, text->GetText().ToStdString() );
189 hash_combine( ret, text->IsItalic() );
190 hash_combine( ret, text->IsBold() );
191 hash_combine( ret, text->IsMirrored() );
192 hash_combine( ret, text->GetTextWidth() );
193 hash_combine( ret, text->GetTextHeight() );
194 hash_combine( ret, text->GetHorizJustify() );
195 hash_combine( ret, text->GetVertJustify() );
196
197 if( aFlags & HASH_POS )
198 {
199 VECTOR2I pos = ( aFlags & REL_COORD ) ? text->GetFPRelativePosition()
200 : text->GetPosition();
201
202 hash_combine( ret, pos.x, pos.y );
203 }
204
205 if( aFlags & HASH_ROT )
206 hash_combine( ret, text->GetTextAngle().AsDegrees() );
207 }
208 break;
209
210 case PCB_SHAPE_T:
211 {
212 const PCB_SHAPE* shape = static_cast<const PCB_SHAPE*>( aItem );
213 ret = hash_board_item( shape, aFlags );
214 hash_combine( ret, shape->GetShape() );
215 hash_combine( ret, shape->GetWidth() );
216 hash_combine( ret, shape->IsFilled() );
217 hash_combine( ret, shape->GetLineStyle() );
218
219 if( shape->GetShape() == SHAPE_T::ARC || shape->GetShape() == SHAPE_T::CIRCLE )
220 hash_combine( ret, shape->GetRadius() );
221
222 if( aFlags & HASH_POS )
223 {
224 std::vector<VECTOR2I> points;
225
226 points.push_back( shape->GetStart() );
227 points.push_back( shape->GetEnd() );
228
229 if( shape->GetShape() == SHAPE_T::CIRCLE )
230 points.push_back( shape->GetCenter() );
231
232 if( shape->GetShape() == SHAPE_T::ARC )
233 points.push_back( shape->GetArcMid() );
234
235 FOOTPRINT* parentFP = shape->GetParentFootprint();
236
237 if( shape->GetShape() == SHAPE_T::POLY )
238 {
239 const SHAPE_POLY_SET& poly = shape->GetPolyShape();
240
241 for( auto it = poly.CIterateWithHoles(); it; it++ )
242 points.push_back( *it );
243 }
244
245 if( shape->GetShape() == SHAPE_T::BEZIER )
246 {
247 points.push_back( shape->GetBezierC1() );
248 points.push_back( shape->GetBezierC2() );
249 }
250
251 if( parentFP && ( aFlags & REL_COORD ) )
252 {
253 for( VECTOR2I& point : points )
254 {
255 point -= parentFP->GetPosition();
256 RotatePoint( point, -parentFP->GetOrientation() );
257 }
258 }
259
260 if( aFlags & REL_POS )
261 {
262 for( VECTOR2I& point : points )
263 point -= shape->GetPosition();
264 }
265
266 for( VECTOR2I& point : points )
267 hash_combine( ret, point.x, point.y );
268 }
269 }
270 break;
271
272 case PCB_TEXTBOX_T:
273 {
274 const PCB_TEXTBOX* textbox = static_cast<const PCB_TEXTBOX*>( aItem );
275
276 ret = hash_board_item( textbox, aFlags );
277 hash_combine( ret, textbox->GetText().ToStdString() );
278 hash_combine( ret, textbox->IsItalic() );
279 hash_combine( ret, textbox->IsBold() );
280 hash_combine( ret, textbox->IsMirrored() );
281 hash_combine( ret, textbox->GetTextWidth() );
282 hash_combine( ret, textbox->GetTextHeight() );
283 hash_combine( ret, textbox->GetHorizJustify() );
284 hash_combine( ret, textbox->GetVertJustify() );
285
286 if( aFlags & HASH_ROT )
287 hash_combine( ret, textbox->GetTextAngle().AsDegrees() );
288
289 hash_combine( ret, textbox->GetShape() );
290 hash_combine( ret, textbox->GetWidth() );
291 hash_combine( ret, textbox->GetLineStyle() );
292
293 if( aFlags & HASH_POS )
294 {
295 VECTOR2I start = textbox->GetStart();
296 VECTOR2I end = textbox->GetEnd();
297
298 FOOTPRINT* parentFP = textbox->GetParentFootprint();
299
300 if( parentFP && ( aFlags & REL_COORD ) )
301 {
302 start -= parentFP->GetPosition();
303 end -= parentFP->GetPosition();
304
305 RotatePoint( start, -parentFP->GetOrientation() );
306 RotatePoint( end, -parentFP->GetOrientation() );
307 }
308
309 hash_combine( ret, start.x );
310 hash_combine( ret, start.y );
311 hash_combine( ret, end.x );
312 hash_combine( ret, end.y );
313 }
314 }
315 break;
316
317 case PCB_TABLE_T:
318 // JEY TODO: tables
319 break;
320
321 default:
322 wxASSERT_MSG( false, "Unhandled type in function hash_fp_item() (exporter_gencad.cpp)" );
323 }
324
325 return ret;
326}
@ 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:80
FOOTPRINT * GetParentFootprint() const
Definition: board_item.cpp:299
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:258
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:206
SHAPE_POLY_SET & GetPolyShape()
Definition: eda_shape.h:279
bool IsFilled() const
Definition: eda_shape.h:91
int GetRadius() const
Definition: eda_shape.cpp:575
SHAPE_T GetShape() const
Definition: eda_shape.h:125
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition: eda_shape.h:167
LINE_STYLE GetLineStyle() const
Definition: eda_shape.cpp:1789
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition: eda_shape.h:130
const VECTOR2I & GetBezierC1() const
Definition: eda_shape.h:203
VECTOR2I GetArcMid() const
Definition: eda_shape.cpp:545
int GetTextHeight() const
Definition: eda_text.h:247
bool IsItalic() const
Definition: eda_text.h:152
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:130
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:94
int GetTextWidth() const
Definition: eda_text.h:244
GR_TEXT_H_ALIGN_T GetHorizJustify() const
Definition: eda_text.h:183
bool IsMirrored() const
Definition: eda_text.h:173
bool IsBold() const
Definition: eda_text.h:167
GR_TEXT_V_ALIGN_T GetVertJustify() const
Definition: eda_text.h:186
EDA_ANGLE GetOrientation() const
Definition: footprint.h:226
std::deque< PAD * > & Pads()
Definition: footprint.h:205
VECTOR2I GetPosition() const override
Definition: footprint.h:223
DRAWINGS & GraphicalItems()
Definition: footprint.h:208
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
Definition: padstack.h:138
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:457
VECTOR2I GetPosition() const override
Definition: pcb_shape.h:77
Represent a set of closed polygons.
CONST_ITERATOR CIterateWithHoles(int aOutline) const
@ 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:54
static size_t hash_board_item(const BOARD_ITEM *aItem, int aFlags)
Definition: hash_eda.cpp:43
@ 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_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