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<unsigned long long>{}( aItem->GetLayerSet().to_ullong() );
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 for( PCB_LAYER_ID layer : via->GetLayerSet().Seq() )
87 hash_combine( ret, via->FlashLayer( layer ) );
88
89 break;
90 }
91
92 case PCB_PAD_T:
93 {
94 const PAD* pad = static_cast<const PAD*>( aItem );
95
96 ret = hash<int>{}( static_cast<int>( pad->GetShape() ) );
97
98 hash_combine( ret, pad->GetAttribute() );
99
100 if( pad->GetAttribute() == PAD_ATTRIB::PTH || pad->GetAttribute() == PAD_ATTRIB::NPTH )
101 {
102 hash_combine( ret, pad->GetDrillSizeX(), pad->GetDrillSizeY() );
103 hash_combine( ret, pad->GetDrillShape() );
104
105 for( PCB_LAYER_ID layer : pad->GetLayerSet().Seq() )
106 hash_combine( ret, pad->FlashLayer( layer ) );
107 }
108
109 hash_combine( ret, pad->GetSize().x, pad->GetSize().y );
110 hash_combine( ret, pad->GetOffset().x, pad->GetOffset().y );
111
112 switch( pad->GetShape() )
113 {
115 hash_combine( ret, pad->GetChamferPositions() );
116 hash_combine( ret, pad->GetChamferRectRatio() );
117 break;
119 hash_combine( ret, pad->GetRoundRectCornerRadius() );
120 break;
122 hash_combine( ret, pad->GetDelta().x, pad->GetDelta().y );
123 break;
125 {
126 auto poly = pad->GetEffectivePolygon( ERROR_INSIDE );
127
128 for( int ii = 0; ii < poly->VertexCount(); ++ii )
129 {
130 VECTOR2I point = poly->CVertex( ii ) - pad->GetPosition();
131 hash_combine( ret, point.x, point.y );
132 }
133 break;
134 }
135 default:
136 break;
137 }
138
139 hash_combine( ret, hash_board_item( pad, aFlags ) );
140
141 if( aFlags & HASH_POS )
142 {
143 if( aFlags & REL_COORD )
144 hash_combine( ret, pad->GetFPRelativePosition().x, pad->GetFPRelativePosition().y );
145 else
146 hash_combine( ret, pad->GetPosition().x, pad->GetPosition().y );
147 }
148
149 if( aFlags & HASH_ROT )
150 hash_combine( ret, pad->GetOrientation().AsDegrees() );
151
152 if( aFlags & HASH_NET )
153 hash_combine( ret, pad->GetNetCode() );
154 }
155 break;
156
157 case PCB_FIELD_T:
158 if( !( aFlags & HASH_REF ) && static_cast<const PCB_FIELD*>( aItem )->IsReference() )
159 break;
160
161 if( !( aFlags & HASH_VALUE ) && static_cast<const PCB_FIELD*>( aItem )->IsValue() )
162 break;
163
165 case PCB_TEXT_T:
166 {
167 const PCB_TEXT* text = static_cast<const PCB_TEXT*>( aItem );
168
169 ret = hash_board_item( text, aFlags );
170 hash_combine( ret, text->GetText().ToStdString() );
171 hash_combine( ret, text->IsItalic() );
172 hash_combine( ret, text->IsBold() );
173 hash_combine( ret, text->IsMirrored() );
174 hash_combine( ret, text->GetTextWidth() );
175 hash_combine( ret, text->GetTextHeight() );
176 hash_combine( ret, text->GetHorizJustify() );
177 hash_combine( ret, text->GetVertJustify() );
178
179 if( aFlags & HASH_POS )
180 {
181 VECTOR2I pos = ( aFlags & REL_COORD ) ? text->GetFPRelativePosition()
182 : text->GetPosition();
183
184 hash_combine( ret, pos.x, pos.y );
185 }
186
187 if( aFlags & HASH_ROT )
188 hash_combine( ret, text->GetTextAngle().AsDegrees() );
189 }
190 break;
191
192 case PCB_SHAPE_T:
193 {
194 const PCB_SHAPE* shape = static_cast<const PCB_SHAPE*>( aItem );
195 ret = hash_board_item( shape, aFlags );
196 hash_combine( ret, shape->GetShape() );
197 hash_combine( ret, shape->GetWidth() );
198 hash_combine( ret, shape->IsFilled() );
199 hash_combine( ret, shape->GetLineStyle() );
200
201 if( shape->GetShape() == SHAPE_T::ARC || shape->GetShape() == SHAPE_T::CIRCLE )
202 hash_combine( ret, shape->GetRadius() );
203
204 if( aFlags & HASH_POS )
205 {
206 std::vector<VECTOR2I> points;
207
208 points.push_back( shape->GetStart() );
209 points.push_back( shape->GetEnd() );
210
211 if( shape->GetShape() == SHAPE_T::CIRCLE )
212 points.push_back( shape->GetCenter() );
213
214 if( shape->GetShape() == SHAPE_T::ARC )
215 points.push_back( shape->GetArcMid() );
216
217 FOOTPRINT* parentFP = shape->GetParentFootprint();
218
219 if( shape->GetShape() == SHAPE_T::POLY )
220 {
221 const SHAPE_POLY_SET& poly = shape->GetPolyShape();
222
223 for( auto it = poly.CIterateWithHoles(); it; it++ )
224 points.push_back( *it );
225 }
226
227 if( shape->GetShape() == SHAPE_T::BEZIER )
228 {
229 points.push_back( shape->GetBezierC1() );
230 points.push_back( shape->GetBezierC2() );
231 }
232
233 if( parentFP && ( aFlags & REL_COORD ) )
234 {
235 for( VECTOR2I& point : points )
236 {
237 point -= parentFP->GetPosition();
238 RotatePoint( point, -parentFP->GetOrientation() );
239 }
240 }
241
242 if( aFlags & REL_POS )
243 {
244 for( VECTOR2I& point : points )
245 point -= shape->GetPosition();
246 }
247
248 for( VECTOR2I& point : points )
249 hash_combine( ret, point.x, point.y );
250 }
251 }
252 break;
253
254 case PCB_TEXTBOX_T:
255 {
256 const PCB_TEXTBOX* textbox = static_cast<const PCB_TEXTBOX*>( aItem );
257
258 ret = hash_board_item( textbox, aFlags );
259 hash_combine( ret, textbox->GetText().ToStdString() );
260 hash_combine( ret, textbox->IsItalic() );
261 hash_combine( ret, textbox->IsBold() );
262 hash_combine( ret, textbox->IsMirrored() );
263 hash_combine( ret, textbox->GetTextWidth() );
264 hash_combine( ret, textbox->GetTextHeight() );
265 hash_combine( ret, textbox->GetHorizJustify() );
266 hash_combine( ret, textbox->GetVertJustify() );
267
268 if( aFlags & HASH_ROT )
269 hash_combine( ret, textbox->GetTextAngle().AsDegrees() );
270
271 hash_combine( ret, textbox->GetShape() );
272 hash_combine( ret, textbox->GetWidth() );
273 hash_combine( ret, textbox->GetLineStyle() );
274
275 if( aFlags & HASH_POS )
276 {
277 VECTOR2I start = textbox->GetStart();
278 VECTOR2I end = textbox->GetEnd();
279
280 FOOTPRINT* parentFP = textbox->GetParentFootprint();
281
282 if( parentFP && ( aFlags & REL_COORD ) )
283 {
284 start -= parentFP->GetPosition();
285 end -= parentFP->GetPosition();
286
287 RotatePoint( start, -parentFP->GetOrientation() );
288 RotatePoint( end, -parentFP->GetOrientation() );
289 }
290
291 hash_combine( ret, start.x );
292 hash_combine( ret, start.y );
293 hash_combine( ret, end.x );
294 hash_combine( ret, end.y );
295 }
296 }
297 break;
298
299 case PCB_TABLE_T:
300 // JEY TODO: tables
301 break;
302
303 default:
304 wxASSERT_MSG( false, "Unhandled type in function hash_fp_item() (exporter_gencad.cpp)" );
305 }
306
307 return ret;
308}
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:77
FOOTPRINT * GetParentFootprint() const
Definition: board_item.cpp:248
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:231
double AsDegrees() const
Definition: eda_angle.h:155
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:88
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:100
const VECTOR2I & GetBezierC2() const
Definition: eda_shape.h:189
SHAPE_POLY_SET & GetPolyShape()
Definition: eda_shape.h:262
bool IsFilled() const
Definition: eda_shape.h:91
int GetRadius() const
Definition: eda_shape.cpp:593
SHAPE_T GetShape() const
Definition: eda_shape.h:120
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition: eda_shape.h:150
LINE_STYLE GetLineStyle() const
Definition: eda_shape.cpp:1794
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition: eda_shape.h:125
const VECTOR2I & GetBezierC1() const
Definition: eda_shape.h:186
VECTOR2I GetArcMid() const
Definition: eda_shape.cpp:563
int GetTextHeight() const
Definition: eda_text.h:228
bool IsItalic() const
Definition: eda_text.h:144
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:134
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:225
GR_TEXT_H_ALIGN_T GetHorizJustify() const
Definition: eda_text.h:164
bool IsMirrored() const
Definition: eda_text.h:154
bool IsBold() const
Definition: eda_text.h:148
GR_TEXT_V_ALIGN_T GetVertJustify() const
Definition: eda_text.h:167
EDA_ANGLE GetOrientation() const
Definition: footprint.h:212
PADS & Pads()
Definition: footprint.h:191
VECTOR2I GetPosition() const override
Definition: footprint.h:209
DRAWINGS & GraphicalItems()
Definition: footprint.h:194
Definition: pad.h:59
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:367
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