KiCad PCB EDA Suite
Loading...
Searching...
No Matches
grid_helper.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 GRID_HELPER_H
21#define GRID_HELPER_H
22
23#include <vector>
24#include <optional>
25
27#include <geometry/seg.h>
28#include <kiid.h>
29#include <math/vector2d.h>
33#include <snap/snap_resolver.h>
35#include <tool/selection.h>
36#include <origin_viewitem.h>
37
38class TOOL_MANAGER; // Forward declaration to avoid hard dependency in tests
39
40class EDA_ITEM;
41
49inline SNAP_TARGET_ID SnapTargetId( const KIID& aId )
50{
51 return aId.AsBytes();
52}
53
55{
56 // When the item doesn't match an override, use the current user grid
58
64};
65
67{
68 friend void TEST_CLEAR_ANCHORS( GRID_HELPER& helper );
69
70public:
72 GRID_HELPER( TOOL_MANAGER* aToolMgr, int aConstructionLayer );
73 virtual ~GRID_HELPER();
74
75 VECTOR2I GetGrid() const;
77 VECTOR2I GetOrigin() const;
78
83 virtual void FullReset()
84 {
85 m_constructionGeomPreview.ClearSnapLine();
86 m_snapManager.Clear();
87 m_anchors.clear();
89 m_stickySnapIds.clear();
91 }
92
93 // Manual setters used when no TOOL_MANAGER/View is available (e.g. in tests)
94 void SetGridSize( const VECTOR2D& aGrid ) { m_manualGrid = aGrid; }
95 void SetVisibleGridSize( const VECTOR2D& aGrid ) { m_manualVisibleGrid = aGrid; }
96 void SetOrigin( const VECTOR2I& aOrigin ) { m_manualOrigin = aOrigin; }
97 void SetGridSnapping( bool aEnable ) { m_manualGridSnapping = aEnable; }
98
99 void SetAuxAxes( bool aEnable, const VECTOR2I& aOrigin = VECTOR2I( 0, 0 ) );
100
101 virtual VECTOR2I Align( const VECTOR2I& aPoint, GRID_HELPER_GRIDS aGrid ) const
102 {
103 return Align( aPoint, GetGridSize( aGrid ), GetOrigin() );
104 }
105
106 virtual VECTOR2I AlignGrid( const VECTOR2I& aPoint, GRID_HELPER_GRIDS aGrid ) const
107 {
108 return AlignGrid( aPoint, GetGridSize( aGrid ), GetOrigin() );
109 }
110
111 virtual VECTOR2I Align( const VECTOR2I& aPoint ) const;
112 virtual VECTOR2I Align( const VECTOR2I& aPoint, const VECTOR2D& aGrid,
113 const VECTOR2D& aOffset ) const;
114
115 VECTOR2I AlignGrid( const VECTOR2I& aPoint ) const;
116 VECTOR2I AlignGrid( const VECTOR2I& aPoint, const VECTOR2D& aGrid,
117 const VECTOR2D& aOffset ) const;
118
122 virtual GRID_HELPER_GRIDS GetSelectionGrid( const SELECTION& aSelection ) const;
123
127 virtual GRID_HELPER_GRIDS GetItemGrid( const EDA_ITEM* aItem ) const { return GRID_CURRENT; }
128
132 virtual VECTOR2D GetGridSize( GRID_HELPER_GRIDS aGrid ) const;
133
134 void SetSkipPoint( const VECTOR2I& aPoint )
135 {
136 m_skipPoint = aPoint;
137 }
138
143 {
144 m_skipPoint = VECTOR2I( std::numeric_limits<int>::min(), std::numeric_limits<int>::min() );
145 }
146
147 void SetSnap( bool aSnap ) { m_enableSnap = aSnap; }
148 bool GetSnap() const { return m_enableSnap; }
149
150 void SetUseGrid( bool aSnapToGrid ) { m_enableGrid = aSnapToGrid; }
151 bool GetUseGrid() const { return m_enableGrid; }
152
153 void SetSnapLine( bool aSnap ) { m_enableSnapLine = aSnap; }
154 void SetSnapLineDirections( const std::vector<VECTOR2I>& aDirections );
155 void SetSnapLineOrigin( const VECTOR2I& aOrigin );
156 void SetSnapLineEnd( const std::optional<VECTOR2I>& aEnd );
157 void ClearSnapLine();
158 std::optional<VECTOR2I> SnapToConstructionLines( const VECTOR2I& aPoint,
159 const VECTOR2I& aNearestGrid,
160 const VECTOR2D& aGrid,
161 double aSnapRange ) const;
162
163 void SetMask( int aMask ) { m_maskTypes = aMask; }
164 void SetMaskFlag( int aFlag ) { m_maskTypes |= aFlag; }
165 void ClearMaskFlag( int aFlag ) { m_maskTypes = m_maskTypes & ~aFlag; }
166
167 std::optional<VECTOR2I> GetSnappedPoint() const;
168
175 void SetAngleRestriction( std::optional<VECTOR2I> aOrigin, double aStepDegrees )
176 {
177 m_angleOrigin = aOrigin;
178 m_angleStepDegrees = aStepDegrees;
179
180 if( !m_angleOrigin )
181 m_retainedAngleBranch.reset();
182 }
183
184 void SetPointEditProfile( bool aEnabled ) { m_pointEditProfile = aEnabled; }
185
186 void SetStationarySelfGeometry( std::vector<VECTOR2I> aPoints, std::vector<SEG> aSegments )
187 {
188 m_stationarySelfPoints = std::move( aPoints );
189 m_stationarySelfSegments = std::move( aSegments );
190 }
191
193 {
194 m_feasibilityCallback = std::move( aCallback );
195 }
196
198 {
205
206 // This anchor comes from 'constructed' geometry (e.g. an intersection
207 // with something else), and not from some intrinsic point of an item
208 // (e.g. an endpoint)
211 };
212
213protected:
214 struct ANCHOR
215 {
224 ANCHOR( const VECTOR2I& aPos, int aFlags, int aPointTypes, std::vector<EDA_ITEM*> aItems ) :
225 pos( aPos ), flags( aFlags ), pointTypes( aPointTypes ),
226 items( std::move( aItems ) )
227 {
228 }
229
231 int flags;
233
236 std::vector<EDA_ITEM*> items;
237
238 double Distance( const VECTOR2I& aP ) const
239 {
240 return VECTOR2D( (double) aP.x - pos.x, (double) aP.y - pos.y ).EuclideanNorm();
241 }
242
243 bool InvolvesItem( const EDA_ITEM& aItem ) const
244 {
245 return std::find( items.begin(), items.end(), &aItem ) != items.end();
246 }
247 };
248
249 void addAnchor( const VECTOR2I& aPos, int aFlags, EDA_ITEM* aItem,
250 int aPointTypes = POINT_TYPE::PT_NONE )
251 {
252 addAnchor( aPos, aFlags, std::vector<EDA_ITEM*>{ aItem }, aPointTypes );
253 }
254
255 void addAnchor( const VECTOR2I& aPos, int aFlags, std::vector<EDA_ITEM*> aItems,
256 int aPointTypes )
257 {
258 if( ( aFlags & m_maskTypes ) == aFlags )
259 m_anchors.emplace_back( ANCHOR( aPos, aFlags, aPointTypes, std::move( aItems ) ) );
260 }
261
263 {
264 m_anchors.clear();
265 }
266
271 bool canUseGrid() const;
272
273 VECTOR2I computeNearest( const VECTOR2I& aPoint, const VECTOR2I& aGrid, const VECTOR2I& aOffset ) const;
274
277 {
278 double scale;
279 int range;
280 int in;
281 int out;
283 };
284
293 SNAP_RANGES computeSnapRanges( bool aClampToVisibleGrid ) const;
294
300 void emitAngleBranchCandidates( std::vector<SNAP_CANDIDATE>& aCandidates, const VECTOR2I& aOrigin,
301 double aSnapScale ) const;
302
309 void emitSelfAndGridCandidates( std::vector<SNAP_CANDIDATE>& aCandidates, const SNAP_SOURCE_CONTEXT& aContext,
310 const VECTOR2I& aOrigin, const VECTOR2I& aNearestGrid, double aSnapScale,
311 int aSnapRange, bool aUseGrid ) const;
312
314
319 void retainAcceptedSnaps( const SNAP_RESULT& aResult );
320
321protected:
322 void applySnapResultGuides( const SNAP_RESULT& aResult );
323
324 void showConstructionGeometry( bool aShow );
325
327
328 void updateSnapPoint( const TYPED_POINT2I& aPoint );
329
336
337 std::vector<ANCHOR> m_anchors;
338
340 std::optional<VECTOR2I> m_auxAxis;
341
342 int m_maskTypes; // Mask of allowed snap types
343
344 bool m_enableSnap; // Allow snapping to other items on the layers
345 bool m_enableGrid; // If true, allow snapping to grid
346 bool m_enableSnapLine; // Allow drawing lines from snap points
347 std::optional<ANCHOR> m_snapItem; // Pointer to the currently snapped item in m_anchors
348 // (NULL if not snapped)
349 VECTOR2I m_skipPoint; // When drawing a line, we avoid snapping to the
350 // source point
353
354 // Manual grid parameters used when no TOOL_MANAGER is provided
359
360 // Snap-resolver integration state shared by the derived helpers
361 std::optional<VECTOR2I> m_angleOrigin;
362 double m_angleStepDegrees = 0.0;
363 std::optional<SNAP_STABLE_ID> m_retainedAngleBranch;
364 std::vector<SNAP_STABLE_ID> m_stickySnapIds;
366 std::vector<VECTOR2I> m_stationarySelfPoints;
367 std::vector<SEG> m_stationarySelfSegments;
368 bool m_pointEditProfile = false;
370
383 static SNAP_REFERENCE_PREFERENCE classifyReference( const VECTOR2I& aPoint, const BOX2I& aBounds,
384 bool aAnchorPoint );
385
387 void setLayoutReference( const VECTOR2I& aPoint, const std::optional<BOX2I>& aBounds, bool aAnchorPoint );
388
389private:
392
395
397 std::unique_ptr<KIGFX::ANCHOR_DEBUG> m_anchorDebug;
398};
399
400#endif
BOX2< VECTOR2I > BOX2I
Definition box2.h:918
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:96
KIGFX::CONSTRUCTION_GEOM m_constructionGeomPreview
Show construction geometry (if any) on the canvas.
std::optional< VECTOR2I > m_auxAxis
VECTOR2I computeNearest(const VECTOR2I &aPoint, const VECTOR2I &aGrid, const VECTOR2I &aOffset) const
void retainAcceptedSnaps(const SNAP_RESULT &aResult)
Record which snaps the resolver accepted so they can be re-biased on the next resolve,...
std::optional< VECTOR2I > SnapToConstructionLines(const VECTOR2I &aPoint, const VECTOR2I &aNearestGrid, const VECTOR2D &aGrid, double aSnapRange) const
void SetSnapLineDirections(const std::vector< VECTOR2I > &aDirections)
void addAnchor(const VECTOR2I &aPos, int aFlags, EDA_ITEM *aItem, int aPointTypes=POINT_TYPE::PT_NONE)
SNAP_MANAGER & getSnapManager()
VECTOR2I m_skipPoint
bool GetSnap() const
bool m_enableGrid
SNAP_RANGES computeSnapRanges(bool aClampToVisibleGrid) const
Compute the snap thresholds.
void SetSnap(bool aSnap)
void emitAngleBranchCandidates(std::vector< SNAP_CANDIDATE > &aCandidates, const VECTOR2I &aOrigin, double aSnapScale) const
Emit the angle-restriction snap candidates (the two branches bracketing the cursor angle) into the cu...
virtual GRID_HELPER_GRIDS GetItemGrid(const EDA_ITEM *aItem) const
Get the coarsest grid that applies to an item.
void SetSkipPoint(const VECTOR2I &aPoint)
void showConstructionGeometry(bool aShow)
SNAP_RESOLVER::FEASIBILITY_CALLBACK m_feasibilityCallback
void SetAngleRestriction(std::optional< VECTOR2I > aOrigin, double aStepDegrees)
Restrict snapping to a set of angle branches emanating from an origin.
SNAP_MANAGER m_snapManager
Manage the construction geometry, snap lines, reference points, etc.
bool GetUseGrid() const
std::vector< SEG > m_stationarySelfSegments
virtual ~GRID_HELPER()
double m_angleStepDegrees
VECTOR2D m_manualVisibleGrid
void addAnchor(const VECTOR2I &aPos, int aFlags, std::vector< EDA_ITEM * > aItems, int aPointTypes)
void SetOrigin(const VECTOR2I &aOrigin)
Definition grid_helper.h:96
void SetSnapLineOrigin(const VECTOR2I &aOrigin)
void SetVisibleGridSize(const VECTOR2D &aGrid)
Definition grid_helper.h:95
void ClearSkipPoint()
Clear the skip point by setting it to an unreachable position, thereby preventing matching.
bool m_manualGridSnapping
void SetGridSnapping(bool aEnable)
Definition grid_helper.h:97
friend void TEST_CLEAR_ANCHORS(GRID_HELPER &helper)
VECTOR2I m_manualOrigin
virtual GRID_HELPER_GRIDS GetSelectionGrid(const SELECTION &aSelection) const
Gets the coarsest grid that applies to a selecion of items.
TOOL_MANAGER * m_toolMgr
void SetUseGrid(bool aSnapToGrid)
std::optional< VECTOR2I > GetSnappedPoint() const
void SetAuxAxes(bool aEnable, const VECTOR2I &aOrigin=VECTOR2I(0, 0))
VECTOR2D GetVisibleGrid() const
std::unique_ptr< KIGFX::ANCHOR_DEBUG > m_anchorDebug
#VIEW_ITEM for visualising anchor points, if enabled.
std::vector< VECTOR2I > m_stationarySelfPoints
virtual VECTOR2D GetGridSize(GRID_HELPER_GRIDS aGrid) const
Return the size of the specified grid.
SNAP_RESOLVER::TRACE_CALLBACK snapTraceCallback(const SNAP_SOURCE_CONTEXT &aContext) const
VECTOR2I GetGrid() const
static SNAP_REFERENCE_PREFERENCE classifyReference(const VECTOR2I &aPoint, const BOX2I &aBounds, bool aAnchorPoint)
Classify the point a drag was started from against the moving object's bounds.
bool m_enableSnapLine
bool m_enableSnap
VECTOR2I GetOrigin() const
bool canUseGrid() const
Check whether it is possible to use the grid – this depends both on local grid helper settings and gl...
void ClearSnapLine()
void SetGridSize(const VECTOR2D &aGrid)
Definition grid_helper.h:94
std::optional< SNAP_STABLE_ID > m_retainedAngleBranch
void clearAnchors()
std::optional< ANCHOR > m_snapItem
SNAP_REFERENCE_PREFERENCE m_layoutReferencePreference
void SetFeasibilityCallback(SNAP_RESOLVER::FEASIBILITY_CALLBACK aCallback)
virtual void FullReset()
Reset all internal state.
Definition grid_helper.h:83
KIGFX::ANCHOR_DEBUG * enableAndGetAnchorDebug()
Enable the anchor debug if permitted and return it.
void SetMaskFlag(int aFlag)
void SetMask(int aMask)
void SetSnapLineEnd(const std::optional< VECTOR2I > &aEnd)
KIGFX::SNAP_INDICATOR m_viewSnapPoint
virtual VECTOR2I Align(const VECTOR2I &aPoint, GRID_HELPER_GRIDS aGrid) const
void updateSnapPoint(const TYPED_POINT2I &aPoint)
void SetStationarySelfGeometry(std::vector< VECTOR2I > aPoints, std::vector< SEG > aSegments)
KIGFX::ORIGIN_VIEWITEM m_viewAxis
std::optional< VECTOR2I > m_angleOrigin
bool m_pointEditProfile
void ClearMaskFlag(int aFlag)
std::vector< SNAP_STABLE_ID > m_stickySnapIds
void SetSnapLine(bool aSnap)
void setLayoutReference(const VECTOR2I &aPoint, const std::optional< BOX2I > &aBounds, bool aAnchorPoint)
Record the classified drag reference and trace it.
void emitSelfAndGridCandidates(std::vector< SNAP_CANDIDATE > &aCandidates, const SNAP_SOURCE_CONTEXT &aContext, const VECTOR2I &aOrigin, const VECTOR2I &aNearestGrid, double aSnapScale, int aSnapRange, bool aUseGrid) const
Emit the point editor's unchanged self-geometry and the independent grid axes.
void SetPointEditProfile(bool aEnabled)
VECTOR2D m_manualGrid
void applySnapResultGuides(const SNAP_RESULT &aResult)
std::vector< ANCHOR > m_anchors
virtual VECTOR2I AlignGrid(const VECTOR2I &aPoint, GRID_HELPER_GRIDS aGrid) const
View item to draw debug items for anchors.
Shows construction geometry for things like line extensions, arc centers, etc.
View item to draw an origin marker with an optional snap type indicator.
Definition kiid.h:46
std::array< uint8_t, 16 > AsBytes() const
Definition kiid.cpp:276
A SNAP_MANAGER glues together the snap line manager and construction manager., along with some other ...
std::function< SNAP_RESULT(const SNAP_SOURCE_CONTEXT &, const std::vector< SNAP_CANDIDATE > &)> FEASIBILITY_CALLBACK
std::function< void(const std::string &)> TRACE_CALLBACK
Master controller class:
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition vector2d.h:279
SNAP_TARGET_ID SnapTargetId(const KIID &aId)
The snap identity of a document item.
Definition grid_helper.h:49
GRID_HELPER_GRIDS
Definition grid_helper.h:55
@ GRID_VIAS
Definition grid_helper.h:61
@ GRID_TEXT
Definition grid_helper.h:62
@ GRID_CURRENT
Definition grid_helper.h:57
@ GRID_GRAPHICS
Definition grid_helper.h:63
@ GRID_CONNECTABLE
Definition grid_helper.h:59
@ GRID_WIRES
Definition grid_helper.h:60
STL namespace.
@ PT_NONE
No specific point type.
Definition point_types.h:38
std::array< uint8_t, 16 > SNAP_TARGET_ID
ANCHOR(const VECTOR2I &aPos, int aFlags, int aPointTypes, std::vector< EDA_ITEM * > aItems)
std::vector< EDA_ITEM * > items
Items that are associated with this anchor (can be more than one, e.g.
double Distance(const VECTOR2I &aP) const
bool InvolvesItem(const EDA_ITEM &aItem) const
World-space snap thresholds derived from the screen-space snap radius.
int range
Snap radius, optionally clamped to the visible grid.
int in
Distance at which a candidate is picked up.
double scale
SNAP_SCREEN_RADIUS in world units.
int out
Distance at which a held candidate is released.
double rankingHysteresis
Resolver ranking stickiness, as a fraction of the radius.
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683
VECTOR2< double > VECTOR2D
Definition vector2d.h:682