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