KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcb_via_stack.h
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 The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20#ifndef PCB_VIA_STACK_H
21#define PCB_VIA_STACK_H
22
23#include <functional>
24#include <optional>
25#include <set>
26#include <utility>
27
29#include <pcb_generator.h>
30
31struct VIA_STACK_PRESET;
32class PCB_VIA;
33
34
35enum class VIA_STACK_STYLE : int
36{
39};
40
41
48{
49public:
50 static const wxString GENERATOR_TYPE;
51 static const wxString DISPLAY_NAME;
52
53 PCB_VIA_STACK( BOARD_ITEM* aParent = nullptr, PCB_LAYER_ID aLayer = F_Cu );
54
55 wxString GetGeneratorType() const override { return GENERATOR_TYPE; }
56
57 // A stack's members span the whole layer range, so its own layer is the start layer and
58 // must not be taken from whichever member the loader sees first.
59 bool LayerFollowsMembers() const override { return false; }
60
61 wxString GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const override
62 {
63 return _( "Microvia Stack" );
64 }
65
66 wxString GetFriendlyName() const override { return _( "Microvia Stack" ); }
67 wxString GetPluralName() const override { return _( "Microvia Stacks" ); }
68 wxString GetCommitMessage() const override { return _( "Edit Microvia Stack" ); }
69
70 EDA_ITEM* Clone() const override { return new PCB_VIA_STACK( *this ); }
71
72 // The PCB_GENERATOR base returns an empty box, which breaks click selection and the
73 // view index. Use the member union like a plain group.
74 const BOX2I GetBoundingBox() const override { return PCB_GROUP::GetBoundingBox(); }
75 const BOX2I ViewBBox() const override { return GetBoundingBox(); }
76
77 // The group base registers only on LAYER_ANCHOR, which VIEW::Query skips, so box select
78 // and select-all would never see the stack. Register on every layer it spans, or hiding
79 // one of them takes the stack out of the view index.
80 std::vector<int> ViewGetLayers() const override;
81
82 // Generator members are not selectable on their own, the selection tool expects the
83 // generator itself to hit test. Delegate to the members.
84 bool HitTest( const VECTOR2I& aPosition, int aAccuracy = 0 ) const override
85 {
86 for( BOARD_ITEM* item : GetBoardItems() )
87 {
88 if( item->HitTest( aPosition, aAccuracy ) )
89 return true;
90 }
91
92 return false;
93 }
94
95 bool HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const override
96 {
97 bool anyItems = false;
98
99 for( BOARD_ITEM* item : GetBoardItems() )
100 {
101 anyItems = true;
102
103 if( aContained )
104 {
105 if( !item->HitTest( aRect, true, aAccuracy ) )
106 return false;
107 }
108 else if( item->HitTest( aRect, false, aAccuracy ) )
109 {
110 return true;
111 }
112 }
113
114 return anyItems && aContained;
115 }
116
117 bool HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const override
118 {
119 bool anyItems = false;
120
121 for( BOARD_ITEM* item : GetBoardItems() )
122 {
123 anyItems = true;
124
125 if( aContained )
126 {
127 if( !item->HitTest( aPoly, true ) )
128 return false;
129 }
130 else if( item->HitTest( aPoly, false ) )
131 {
132 return true;
133 }
134 }
135
136 return anyItems && aContained;
137 }
138
139 void EditStart( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_COMMIT* aCommit ) override;
140 bool Update( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_COMMIT* aCommit ) override;
141 void EditFinish( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_COMMIT* aCommit ) override;
142 void EditCancel( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_COMMIT* aCommit ) override;
143 void Remove( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_COMMIT* aCommit ) override;
144
145 // The hop polyline stores absolute positions, so it must follow every transform or a
146 // later regenerate snaps the vias back to the old location.
147 void Move( const VECTOR2I& aMoveVector ) override;
148 void Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle ) override;
149 void Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection ) override;
150 void Mirror( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection ) override;
151
152 const STRING_ANY_MAP GetProperties() const override;
153 void SetProperties( const STRING_ANY_MAP& aProps ) override;
154
155 void Serialize( google::protobuf::Any& aContainer ) const override;
156 bool Deserialize( const google::protobuf::Any& aContainer ) override;
157
158 void ShowPropertiesDialog( PCB_BASE_EDIT_FRAME* aEditFrame ) override;
159
160 void ApplyPreset( const VIA_STACK_PRESET& aPreset );
162
173 static PCB_VIA_STACK* CreateFromItems( const std::vector<BOARD_ITEM*>& aItems, BOARD* aBoard,
174 std::vector<BOARD_ITEM*>* aMembers = nullptr, wxString* aError = nullptr );
175
181 static bool IsSpanValid( BOARD* aBoard, PCB_LAYER_ID aStart, PCB_LAYER_ID aEnd );
182
189 static int ExpandMultiHopMicrovias( BOARD* aBoard, BOARD_COMMIT* aCommit,
190 const std::function<const VIA_STACK_PRESET*( PCB_VIA* )>& aMatcher = nullptr );
191
196 static std::set<KIID> CollectExpandableMicrovias( BOARD* aBoard );
197
203 static int FindNetAtPosition( BOARD* aBoard, const VECTOR2I& aPosition, PCB_LAYER_ID aLayer );
204
209 static int FindNetAtPosition( BOARD* aBoard, const VECTOR2I& aPosition, const LSET& aLayers );
210
216 void Regenerate( BOARD* aBoard, BOARD_COMMIT* aCommit );
217
223 std::vector<BOARD_ITEM*> BuildMembers( BOARD* aBoard, int aNetCode ) const;
224
229 static std::pair<int, int> GetNetclassViaSize( BOARD* aBoard, int aNetCode );
230
231 // The net shared by every hop. Read from a member when present, else the stored value.
232 // Setting it applies the net to every existing member as well.
233 int GetNetCode() const;
234 void SetNetCode( int aNet );
235
236 // Stack level settings.
238
239 // The stack registers in the view on its own layer, so it tracks the start layer.
241 {
242 m_startLayer = aLayer;
243 SetLayer( aLayer );
244 }
245
247 void SetEndLayer( PCB_LAYER_ID aLayer ) { m_endLayer = aLayer; }
248
249 VIA_STACK_STYLE GetStyle() const { return m_style; }
250 void SetStyle( VIA_STACK_STYLE aStyle ) { m_style = aStyle; }
251
252 int GetPitch() const { return m_pitch; }
253 void SetPitch( int aPitch ) { m_pitch = aPitch; }
254
255 bool IsFilled() const { return m_filled; }
256 void SetFilled( bool aFilled ) { m_filled = aFilled; }
257
258 bool CanDuplicate() const override { return true; }
259
260 bool IsCapped() const { return m_capped; }
261 void SetCapped( bool aCapped ) { m_capped = aCapped; }
262
263 int GetViaSize() const { return m_viaSize; }
264 void SetViaSize( int aSize ) { m_viaSize = aSize; }
265
266 int GetViaDrill() const { return m_viaDrill; }
267 void SetViaDrill( int aDrill ) { m_viaDrill = aDrill; }
268
269 bool GetUseNetclass() const { return m_useNetclass; }
270 void SetUseNetclass( bool aUse ) { m_useNetclass = aUse; }
271
272 const std::optional<SHAPE_LINE_CHAIN>& GetHops() const { return m_hops; }
273 void SetHops( const SHAPE_LINE_CHAIN& aHops ) { m_hops = aHops; }
274 void ClearHops() { m_hops.reset(); }
275
276 const wxString& GetPresetName() const { return m_presetName; }
277 void SetPresetName( const wxString& aName ) { m_presetName = aName; }
278
279protected:
280 void swapData( BOARD_ITEM* aImage ) override
281 {
282 PCB_VIA_STACK* image = dynamic_cast<PCB_VIA_STACK*>( aImage );
283
284 wxCHECK( image, /* void */ );
285
286 std::swap( *this, *image );
287
288 // Regenerating an edit replaces every member, so the swapped-in member set is
289 // always a different one. Without this the restored vias still name the image.
291 }
292
293 // Add a freshly built member to the board (or commit) and to this generator.
294 void addMember( BOARD* aBoard, BOARD_COMMIT* aCommit, BOARD_ITEM* aItem );
295
296 // Reshape the current members to match aRebuilt. False when the hops themselves changed,
297 // leaving the caller to replace the members outright.
298 bool reuseMembers( BOARD_COMMIT* aCommit, const std::vector<BOARD_ITEM*>& aRebuilt );
299
303 int m_pitch; // center to center distance, staggered only
304 bool m_filled; // copper filled hops, forced on when stacked
306 int m_viaSize; // 0 means take from netclass / board defaults
309 int m_netCode; // net used when building hops, before members exist
310 wxString m_presetName; // the preset this stack was placed from, if any
311
312 // Hop center positions for a staggered stack. Empty for a stacked (coaxial) stack.
313 std::optional<SHAPE_LINE_CHAIN> m_hops;
314};
315
316
318
319#endif // PCB_VIA_STACK_H
BOX2< VECTOR2I > BOX2I
Definition box2.h:914
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:84
BOARD_ITEM(BOARD_ITEM *aParent, KICAD_T idtype, PCB_LAYER_ID aLayer=F_Cu)
Definition board_item.h:86
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:410
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:98
Handle actions specific to filling copper zones.
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
Common, abstract interface for edit frames.
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
PCB_GENERATOR(BOARD_ITEM *aParent, PCB_LAYER_ID aLayer)
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
std::unordered_set< BOARD_ITEM * > GetBoardItems() const
void swapChildOwnership(PCB_GROUP *aImage)
Re-point the children of this group and aImage at whichever group now holds them.
A microvia stack: several single hop microvias, plus connecting traces for staggered stacks,...
VIA_STACK_PRESET ToPreset() const
void SetHops(const SHAPE_LINE_CHAIN &aHops)
void EditCancel(GENERATOR_TOOL *aTool, BOARD *aBoard, BOARD_COMMIT *aCommit) override
void swapData(BOARD_ITEM *aImage) override
bool Update(GENERATOR_TOOL *aTool, BOARD *aBoard, BOARD_COMMIT *aCommit) override
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
void ApplyPreset(const VIA_STACK_PRESET &aPreset)
wxString m_presetName
static int ExpandMultiHopMicrovias(BOARD *aBoard, BOARD_COMMIT *aCommit, const std::function< const VIA_STACK_PRESET *(PCB_VIA *)> &aMatcher=nullptr)
Replace loose microvias spanning more than one hop with stacks of single hop microvias.
void SetProperties(const STRING_ANY_MAP &aProps) override
void SetPitch(int aPitch)
static PCB_VIA_STACK * CreateFromItems(const std::vector< BOARD_ITEM * > &aItems, BOARD *aBoard, std::vector< BOARD_ITEM * > *aMembers=nullptr, wxString *aError=nullptr)
Build a stack from existing board items (microvias plus optional connecting traces).
bool LayerFollowsMembers() const override
static std::set< KIID > CollectExpandableMicrovias(BOARD *aBoard)
Ids of the vias ExpandMultiHopMicrovias would consider right now.
static const wxString GENERATOR_TYPE
void EditStart(GENERATOR_TOOL *aTool, BOARD *aBoard, BOARD_COMMIT *aCommit) override
void Mirror(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Mirror this object relative to a given horizontal axis the layer is not changed.
PCB_LAYER_ID m_endLayer
static int FindNetAtPosition(BOARD *aBoard, const VECTOR2I &aPosition, PCB_LAYER_ID aLayer)
Net of the copper under a point on the given layer, pads first, then tracks, then filled zones.
VIA_STACK_STYLE m_style
void Flip(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Flip this object, i.e.
wxString GetFriendlyName() const override
std::optional< SHAPE_LINE_CHAIN > m_hops
void EditFinish(GENERATOR_TOOL *aTool, BOARD *aBoard, BOARD_COMMIT *aCommit) override
void Remove(GENERATOR_TOOL *aTool, BOARD *aBoard, BOARD_COMMIT *aCommit) override
bool IsCapped() const
void Regenerate(BOARD *aBoard, BOARD_COMMIT *aCommit)
Rebuild the member vias (and, for a staggered stack, the connecting traces) from the current stack se...
wxString GetPluralName() const override
void addMember(BOARD *aBoard, BOARD_COMMIT *aCommit, BOARD_ITEM *aItem)
int GetViaDrill() const
bool IsFilled() const
bool reuseMembers(BOARD_COMMIT *aCommit, const std::vector< BOARD_ITEM * > &aRebuilt)
const std::optional< SHAPE_LINE_CHAIN > & GetHops() const
static const wxString DISPLAY_NAME
const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
VIA_STACK_STYLE GetStyle() const
std::vector< int > ViewGetLayers() const override
Return the all the layers within the VIEW the object is painted on.
void SetFilled(bool aFilled)
void SetPresetName(const wxString &aName)
wxString GetGeneratorType() const override
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
const wxString & GetPresetName() const
PCB_LAYER_ID m_startLayer
int GetNetCode() const
PCB_LAYER_ID GetStartLayer() const
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
void SetStartLayer(PCB_LAYER_ID aLayer)
bool HitTest(const SHAPE_LINE_CHAIN &aPoly, bool aContained) const override
Test if aPoly intersects this item.
PCB_LAYER_ID GetEndLayer() const
bool GetUseNetclass() const
std::vector< BOARD_ITEM * > BuildMembers(BOARD *aBoard, int aNetCode) const
Build the member vias/traces for the current settings and return them without adding them anywhere.
static bool IsSpanValid(BOARD *aBoard, PCB_LAYER_ID aStart, PCB_LAYER_ID aEnd)
True when both span ends are copper layers within the board's copper layer count.
void SetViaSize(int aSize)
bool HitTest(const BOX2I &aRect, bool aContained, int aAccuracy) const override
Test if aRect intersects this item.
void SetCapped(bool aCapped)
void SetViaDrill(int aDrill)
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
int GetPitch() const
void ShowPropertiesDialog(PCB_BASE_EDIT_FRAME *aEditFrame) override
const STRING_ANY_MAP GetProperties() const override
void SetUseNetclass(bool aUse)
bool CanDuplicate() const override
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
void SetStyle(VIA_STACK_STYLE aStyle)
wxString GetCommitMessage() const override
PCB_VIA_STACK(BOARD_ITEM *aParent=nullptr, PCB_LAYER_ID aLayer=F_Cu)
int GetViaSize() const
void Move(const VECTOR2I &aMoveVector) override
Move this object.
void SetEndLayer(PCB_LAYER_ID aLayer)
void SetNetCode(int aNet)
static std::pair< int, int > GetNetclassViaSize(BOARD *aBoard, int aNetCode)
The microvia diameter and drill that "use netclass values" gives hops on aNetCode,...
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
A name/value tuple with unique names and wxAny values.
#define _(s)
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
@ F_Cu
Definition layer_ids.h:60
FLIP_DIRECTION
Definition mirror.h:23
VIA_STACK_STYLE
#define DECLARE_ENUM_TO_WXANY(type)
Definition property.h:851
A named microvia stack definition, chosen while routing instead of entering the values each time.
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708