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
28#include <pcb_generator.h>
29
30struct VIA_STACK_PRESET;
31class PCB_VIA;
32
33
34enum class VIA_STACK_STYLE : int
35{
38};
39
40
47{
48public:
49 static const wxString GENERATOR_TYPE;
50 static const wxString DISPLAY_NAME;
51
52 PCB_VIA_STACK( BOARD_ITEM* aParent = nullptr, PCB_LAYER_ID aLayer = F_Cu );
53
54 wxString GetGeneratorType() const override { return GENERATOR_TYPE; }
55
56 // A stack's members span the whole layer range, so its own layer is the start layer and
57 // must not be taken from whichever member the loader sees first.
58 bool LayerFollowsMembers() const override { return false; }
59
60 wxString GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const override
61 {
62 return _( "Microvia Stack" );
63 }
64
65 wxString GetFriendlyName() const override { return _( "Microvia Stack" ); }
66 wxString GetPluralName() const override { return _( "Microvia Stacks" ); }
67 wxString GetCommitMessage() const override { return _( "Edit Microvia Stack" ); }
68
69 EDA_ITEM* Clone() const override { return new PCB_VIA_STACK( *this ); }
70
71 // The PCB_GENERATOR base returns an empty box, which breaks click selection and the
72 // view index. Use the member union like a plain group.
73 const BOX2I GetBoundingBox() const override { return PCB_GROUP::GetBoundingBox(); }
74 const BOX2I ViewBBox() const override { return GetBoundingBox(); }
75
76 // The group base registers only on LAYER_ANCHOR, which VIEW::Query skips, so box
77 // select and select-all would never see the stack. Register on the copper layer too.
78 std::vector<int> ViewGetLayers() const override { return { LAYER_ANCHOR, GetLayer() }; }
79
80 // Generator members are not selectable on their own, the selection tool expects the
81 // generator itself to hit test. Delegate to the members.
82 bool HitTest( const VECTOR2I& aPosition, int aAccuracy = 0 ) const override
83 {
84 for( BOARD_ITEM* item : GetBoardItems() )
85 {
86 if( item->HitTest( aPosition, aAccuracy ) )
87 return true;
88 }
89
90 return false;
91 }
92
93 bool HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const override
94 {
95 bool anyItems = false;
96
97 for( BOARD_ITEM* item : GetBoardItems() )
98 {
99 anyItems = true;
100
101 if( aContained )
102 {
103 if( !item->HitTest( aRect, true, aAccuracy ) )
104 return false;
105 }
106 else if( item->HitTest( aRect, false, aAccuracy ) )
107 {
108 return true;
109 }
110 }
111
112 return anyItems && aContained;
113 }
114
115 bool HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const override
116 {
117 bool anyItems = false;
118
119 for( BOARD_ITEM* item : GetBoardItems() )
120 {
121 anyItems = true;
122
123 if( aContained )
124 {
125 if( !item->HitTest( aPoly, true ) )
126 return false;
127 }
128 else if( item->HitTest( aPoly, false ) )
129 {
130 return true;
131 }
132 }
133
134 return anyItems && aContained;
135 }
136
137 void EditStart( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_COMMIT* aCommit ) override;
138 bool Update( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_COMMIT* aCommit ) override;
139 void EditFinish( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_COMMIT* aCommit ) override;
140 void EditCancel( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_COMMIT* aCommit ) override;
141 void Remove( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_COMMIT* aCommit ) override;
142
143 // The hop polyline stores absolute positions, so it must follow every transform or a
144 // later regenerate snaps the vias back to the old location.
145 void Move( const VECTOR2I& aMoveVector ) override;
146 void Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle ) override;
147 void Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection ) override;
148 void Mirror( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection ) override;
149
150 const STRING_ANY_MAP GetProperties() const override;
151 void SetProperties( const STRING_ANY_MAP& aProps ) override;
152
153 void ShowPropertiesDialog( PCB_BASE_EDIT_FRAME* aEditFrame ) override;
154
155 void ApplyPreset( const VIA_STACK_PRESET& aPreset );
157
167 static PCB_VIA_STACK* CreateFromItems( const std::vector<BOARD_ITEM*>& aItems, BOARD* aBoard,
168 std::vector<BOARD_ITEM*>* aMembers = nullptr );
169
175 static bool IsSpanValid( BOARD* aBoard, PCB_LAYER_ID aStart, PCB_LAYER_ID aEnd );
176
183 static int ExpandMultiHopMicrovias( BOARD* aBoard, BOARD_COMMIT* aCommit,
184 const std::function<const VIA_STACK_PRESET*( PCB_VIA* )>& aMatcher = nullptr );
185
190 static std::set<KIID> CollectExpandableMicrovias( BOARD* aBoard );
191
197 static int FindNetAtPosition( BOARD* aBoard, const VECTOR2I& aPosition, PCB_LAYER_ID aLayer );
198
203 static int FindNetAtPosition( BOARD* aBoard, const VECTOR2I& aPosition, const LSET& aLayers );
204
210 void Regenerate( BOARD* aBoard, BOARD_COMMIT* aCommit );
211
217 std::vector<BOARD_ITEM*> BuildMembers( BOARD* aBoard, int aNetCode ) const;
218
219 // The net shared by every hop. Read from a member when present, else the stored value.
220 // Setting it applies the net to every existing member as well.
221 int GetNetCode() const;
222 void SetNetCode( int aNet );
223
224 // Stack level settings.
226
227 // The stack registers in the view on its own layer, so it tracks the start layer.
229 {
230 m_startLayer = aLayer;
231 SetLayer( aLayer );
232 }
233
235 void SetEndLayer( PCB_LAYER_ID aLayer ) { m_endLayer = aLayer; }
236
237 VIA_STACK_STYLE GetStyle() const { return m_style; }
238 void SetStyle( VIA_STACK_STYLE aStyle ) { m_style = aStyle; }
239
240 int GetPitch() const { return m_pitch; }
241 void SetPitch( int aPitch ) { m_pitch = aPitch; }
242
243 bool IsFilled() const { return m_filled; }
244 void SetFilled( bool aFilled ) { m_filled = aFilled; }
245
246 bool CanDuplicate() const override { return true; }
247
248 bool IsCapped() const { return m_capped; }
249 void SetCapped( bool aCapped ) { m_capped = aCapped; }
250
251 int GetViaSize() const { return m_viaSize; }
252 void SetViaSize( int aSize ) { m_viaSize = aSize; }
253
254 int GetViaDrill() const { return m_viaDrill; }
255 void SetViaDrill( int aDrill ) { m_viaDrill = aDrill; }
256
257 bool GetUseNetclass() const { return m_useNetclass; }
258 void SetUseNetclass( bool aUse ) { m_useNetclass = aUse; }
259
260 const std::optional<SHAPE_LINE_CHAIN>& GetHops() const { return m_hops; }
261 void SetHops( const SHAPE_LINE_CHAIN& aHops ) { m_hops = aHops; }
262 void ClearHops() { m_hops.reset(); }
263
264 const wxString& GetPresetName() const { return m_presetName; }
265 void SetPresetName( const wxString& aName ) { m_presetName = aName; }
266
267protected:
268 void swapData( BOARD_ITEM* aImage ) override
269 {
270 PCB_VIA_STACK* image = dynamic_cast<PCB_VIA_STACK*>( aImage );
271
272 wxCHECK( image, /* void */ );
273
274 std::swap( *this, *image );
275
276 // Regenerating an edit replaces every member, so the swapped-in member set is
277 // always a different one. Without this the restored vias still name the image.
279 }
280
281 // Add a freshly built member to the board (or commit) and to this generator.
282 void addMember( BOARD* aBoard, BOARD_COMMIT* aCommit, BOARD_ITEM* aItem );
283
284 // Reshape the current members to match aRebuilt. False when the hops themselves changed,
285 // leaving the caller to replace the members outright.
286 bool reuseMembers( BOARD_COMMIT* aCommit, const std::vector<BOARD_ITEM*>& aRebuilt );
287
291 int m_pitch; // center to center distance, staggered only
292 bool m_filled; // copper filled hops, forced on when stacked
294 int m_viaSize; // 0 means take from netclass / board defaults
297 int m_netCode; // net used when building hops, before members exist
298 wxString m_presetName; // the preset this stack was placed from, if any
299
300 // Hop center positions for a staggered stack. Empty for a stacked (coaxial) stack.
301 std::optional<SHAPE_LINE_CHAIN> m_hops;
302};
303
304
306
307#endif // PCB_VIA_STACK_H
BOX2< VECTOR2I > BOX2I
Definition box2.h:927
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:409
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_LAYER_ID GetLayer() const override
Return the primary 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)
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
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
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 aPosition is inside or on the boundary of 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 aPosition is inside or on the boundary of 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
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)
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)
@ LAYER_ANCHOR
Anchor of items having an anchor point (texts, footprints).
Definition layer_ids.h:244
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:838
A named microvia stack definition, chosen while routing instead of entering the values each time.
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683