KiCad PCB EDA Suite
ee_grid_helper.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) 2014 CERN
5 * Copyright (C) 2018-2021 KiCad Developers, see AUTHORS.txt for contributors.
6 * @author Tomasz Wlostowski <[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 <functional>
27#include <macros.h>
28#include <sch_item.h>
29#include <sch_line.h>
30#include <sch_painter.h>
31#include <tool/tool_manager.h>
32#include <trigo.h>
33#include <view/view.h>
34#include "ee_grid_helper.h"
35
36
38 GRID_HELPER( aToolMgr )
39{
40 KIGFX::VIEW* view = m_toolMgr->GetView();
41
42 m_viewAxis.SetSize( 20000 );
44 m_viewAxis.SetColor( COLOR4D( 0.0, 0.1, 0.4, 0.8 ) );
46 view->Add( &m_viewAxis );
47 view->SetVisible( &m_viewAxis, false );
48
50 m_viewSnapPoint.SetColor( COLOR4D( 0.0, 0.1, 0.4, 1.0 ) );
52 view->Add( &m_viewSnapPoint );
53 view->SetVisible( &m_viewSnapPoint, false );
54
56 m_viewSnapLine.SetColor( COLOR4D( 0.33, 0.55, 0.95, 1.0 ) );
58 view->Add( &m_viewSnapLine );
59 view->SetVisible( &m_viewSnapLine, false );
60}
61
62
63VECTOR2I EE_GRID_HELPER::BestDragOrigin( const VECTOR2I& aMousePos, int aLayer,
64 const EE_SELECTION& aItems )
65{
67
68 // Text anchors are often off the connectivity grid. For now, this means
69 // we can only consider anchors from text objects if they are the only thing
70 // selected.
71 bool includeText = ( aItems.Size() == 1
73
74 for( EDA_ITEM* item : aItems )
75 computeAnchors( static_cast<SCH_ITEM*>( item ), aMousePos, true, includeText );
76
77 double worldScale = m_toolMgr->GetView()->GetGAL()->GetWorldScale();
78 double lineSnapMinCornerDistance = 50.0 / worldScale;
79
80 ANCHOR* nearestOutline = nearestAnchor( aMousePos, OUTLINE, aLayer );
81 ANCHOR* nearestCorner = nearestAnchor( aMousePos, CORNER, aLayer );
82 ANCHOR* nearestOrigin = nearestAnchor( aMousePos, ORIGIN, aLayer );
83 ANCHOR* best = nullptr;
84 double minDist = std::numeric_limits<double>::max();
85
86 if( nearestOrigin )
87 {
88 minDist = nearestOrigin->Distance( aMousePos );
89 best = nearestOrigin;
90 }
91
92 if( nearestCorner )
93 {
94 double dist = nearestCorner->Distance( aMousePos );
95
96 if( dist < minDist )
97 {
98 minDist = dist;
99 best = nearestCorner;
100 }
101 }
102
103 if( nearestOutline )
104 {
105 double dist = nearestOutline->Distance( aMousePos );
106
107 if( minDist > lineSnapMinCornerDistance && dist < minDist )
108 best = nearestOutline;
109 }
110
111 return best ? best->pos : aMousePos;
112}
113
114
115VECTOR2I EE_GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, int aLayer, SCH_ITEM* aSkip )
116{
117 EE_SELECTION skipItems;
118 skipItems.Add( aSkip );
119
120 return BestSnapAnchor( aOrigin, aLayer, skipItems );
121}
122
123
125 const EE_SELECTION& aSkip )
126{
127 constexpr int snapRange = SNAP_RANGE * schIUScale.IU_PER_MILS;
128
129 VECTOR2I pt = aOrigin;
130 VECTOR2I snapDist( snapRange, snapRange );
131 bool snapLineX = false;
132 bool snapLineY = false;
133 bool snapPoint = false;
134 bool gridChecked = false;
135
136 BOX2I bb( VECTOR2I( aOrigin.x - snapRange / 2, aOrigin.y - snapRange / 2 ),
137 VECTOR2I( snapRange, snapRange ) );
138
139 clearAnchors();
140
141 for( SCH_ITEM* item : queryVisible( bb, aSkip ) )
142 computeAnchors( item, aOrigin );
143
144 ANCHOR* nearest = nearestAnchor( aOrigin, SNAPPABLE, aLayer );
145 VECTOR2I nearestGrid = Align( aOrigin );
146
148 {
149 if( std::abs( m_viewSnapLine.GetPosition().x - aOrigin.x ) < snapDist.x )
150 {
152 snapDist.x = std::abs( m_viewSnapLine.GetPosition().x - aOrigin.x );
153 snapLineX = true;
154 }
155
156 if( std::abs( m_viewSnapLine.GetPosition().y - aOrigin.y ) < snapDist.y )
157 {
159 snapDist.y = std::abs( m_viewSnapLine.GetPosition().y - aOrigin.y );
160 snapLineY = true;
161 }
162
163 if( canUseGrid() && std::abs( nearestGrid.x - aOrigin.x ) < snapDist.x )
164 {
165 pt.x = nearestGrid.x;
166 snapDist.x = std::abs( nearestGrid.x - aOrigin.x );
167 snapLineX = false;
168 }
169
170 if( canUseGrid() && std::abs( nearestGrid.y - aOrigin.y ) < snapDist.y )
171 {
172 pt.y = nearestGrid.y;
173 snapDist.y = std::abs( nearestGrid.y - aOrigin.y );
174 snapLineY = false;
175 }
176
177 gridChecked = true;
178 }
179
180 if( m_enableSnap && nearest && nearest->Distance( aOrigin ) < snapDist.EuclideanNorm() )
181 {
182
183 if( canUseGrid() && ( nearestGrid - aOrigin ).EuclideanNorm() < snapDist.EuclideanNorm() )
184 {
185 pt = nearestGrid;
186 snapDist.x = std::abs( nearestGrid.x - aOrigin.x );
187 snapDist.y = std::abs( nearestGrid.y - aOrigin.y );
188 snapPoint = false;
189 }
190 else
191 {
192 pt = nearest->pos;
193 snapDist.x = std::abs( nearest->pos.x - aOrigin.x );
194 snapDist.y = std::abs( nearest->pos.y - aOrigin.y );
195 snapPoint = true;
196 }
197
198 snapLineX = snapLineY = false;
199 gridChecked = true;
200 }
201
202 if( canUseGrid() && !gridChecked )
203 pt = nearestGrid;
204
205 if( snapLineX || snapLineY )
206 {
208
211 else
213 }
214 else if( snapPoint )
215 {
216 m_snapItem = nearest;
219
221
224 else
226 }
227 else
228 {
231 }
232
233 return pt;
234}
235
237{
238 if( !m_snapItem )
239 return nullptr;
240
241 return static_cast<SCH_ITEM*>( m_snapItem->item );
242}
243
244
245std::set<SCH_ITEM*> EE_GRID_HELPER::queryVisible( const BOX2I& aArea,
246 const EE_SELECTION& aSkipList ) const
247{
248 std::set<SCH_ITEM*> items;
249 std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> selectedItems;
250
251 KIGFX::VIEW* view = m_toolMgr->GetView();
252
253 view->Query( aArea, selectedItems );
254
255 for( const KIGFX::VIEW::LAYER_ITEM_PAIR& it : selectedItems )
256 {
257 SCH_ITEM* item = static_cast<SCH_ITEM*>( it.first );
258
259 // The item must be visible and on an active layer
260 if( view->IsVisible( item ) && item->ViewGetLOD( it.second, view ) < view->GetScale() )
261 items.insert ( item );
262 }
263
264 for( EDA_ITEM* skipItem : aSkipList )
265 items.erase( static_cast<SCH_ITEM*>( skipItem ) );
266
267 return items;
268}
269
270
271void EE_GRID_HELPER::computeAnchors( SCH_ITEM *aItem, const VECTOR2I &aRefPos, bool aFrom,
272 bool aIncludeText )
273{
274 switch( aItem->Type() )
275 {
276 case SCH_TEXT_T:
277 case SCH_TEXTBOX_T:
278 case SCH_FIELD_T:
279 {
280 if( aIncludeText )
281 addAnchor( aItem->GetPosition(), ORIGIN, aItem );
282
283 break;
284 }
285
286 case SCH_SYMBOL_T:
287 case SCH_SHEET_T:
288 addAnchor( aItem->GetPosition(), ORIGIN, aItem );
290
291 case SCH_JUNCTION_T:
292 case SCH_NO_CONNECT_T:
293 case SCH_LINE_T:
295 case SCH_HIER_LABEL_T:
296 case SCH_LABEL_T:
299 case SCH_SHEET_PIN_T:
300 {
301 std::vector<VECTOR2I> pts = aItem->GetConnectionPoints();
302
303 for( const VECTOR2I& pt : pts )
304 addAnchor( VECTOR2I( pt ), SNAPPABLE | CORNER, aItem );
305
306 break;
307 }
308
309 default:
310 break;
311 }
312
313 if( SCH_LINE* line = dyn_cast<SCH_LINE*>( aItem ) )
314 {
315 VECTOR2I pt = Align( aRefPos );
316
317 if( line->GetStartPoint().x == line->GetEndPoint().x )
318 {
319 VECTOR2I possible( line->GetStartPoint().x, pt.y );
320
321 if( TestSegmentHit( possible, line->GetStartPoint(), line->GetEndPoint(), 0 ) )
322 addAnchor( possible, SNAPPABLE | VERTICAL, aItem );
323 }
324 else if( line->GetStartPoint().y == line->GetEndPoint().y )
325 {
326 VECTOR2I possible( pt.x, line->GetStartPoint().y );
327
328 if( TestSegmentHit( possible, line->GetStartPoint(), line->GetEndPoint(), 0 ) )
329 addAnchor( possible, SNAPPABLE | HORIZONTAL, aItem );
330 }
331
332 }
333}
334
335
337 int aMatchLayer )
338{
339 double minDist = std::numeric_limits<double>::max();
340 ANCHOR* best = nullptr;
341
342 for( ANCHOR& a : m_anchors )
343 {
344 SCH_ITEM* item = static_cast<SCH_ITEM*>( a.item );
345
346 if( ( aFlags & a.flags ) != aFlags )
347 continue;
348
349 if( aMatchLayer == LAYER_CONNECTABLE && !item->IsConnectable() )
350 continue;
351 else if( aMatchLayer == LAYER_GRAPHICS && item->IsConnectable() )
352 continue;
353
354 double dist = a.Distance( aPos );
355
356 if( dist < minDist )
357 {
358 minDist = dist;
359 best = &a;
360 }
361 }
362
363 return best;
364}
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:111
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:85
virtual VECTOR2I GetPosition() const
Definition: eda_item.h:251
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
VECTOR2I BestSnapAnchor(const VECTOR2I &aOrigin, int aLayer, SCH_ITEM *aDraggedItem)
std::set< SCH_ITEM * > queryVisible(const BOX2I &aArea, const EE_SELECTION &aSkipList) const
SCH_ITEM * GetSnapped() const
Function GetSnapped If the EE_GRID_HELPER has highlighted a snap point (target shown),...
VECTOR2I BestDragOrigin(const VECTOR2I &aMousePos, int aLayer, const EE_SELECTION &aItems)
EE_GRID_HELPER(TOOL_MANAGER *aToolMgr)
void computeAnchors(SCH_ITEM *aItem, const VECTOR2I &aRefPos, bool aFrom=false, bool aIncludeText=false)
Insert the local anchor points in to the grid helper for the specified schematic item,...
ANCHOR * nearestAnchor(const VECTOR2I &aPos, int aFlags, int aMatchLayer)
VECTOR2I m_skipPoint
Definition: grid_helper.h:140
virtual VECTOR2I Align(const VECTOR2I &aPoint) const
Definition: grid_helper.cpp:95
TOOL_MANAGER * m_toolMgr
Definition: grid_helper.h:130
ANCHOR * m_snapItem
Definition: grid_helper.h:138
bool m_enableSnapLine
Definition: grid_helper.h:137
bool m_enableSnap
Definition: grid_helper.h:135
void addAnchor(const VECTOR2I &aPos, int aFlags, EDA_ITEM *aItem)
Definition: grid_helper.h:106
bool canUseGrid() const
Check whether it is possible to use the grid – this depends both on local grid helper settings and gl...
Definition: grid_helper.h:122
void clearAnchors()
Definition: grid_helper.h:112
KIGFX::ORIGIN_VIEWITEM m_viewSnapPoint
Definition: grid_helper.h:142
KIGFX::ORIGIN_VIEWITEM m_viewSnapLine
Definition: grid_helper.h:143
KIGFX::ORIGIN_VIEWITEM m_viewAxis
Definition: grid_helper.h:144
std::vector< ANCHOR > m_anchors
Definition: grid_helper.h:128
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
double GetWorldScale() const
Get the world scale.
void SetPosition(const VECTOR2I &aPosition) override
void SetColor(const KIGFX::COLOR4D &aColor)
VECTOR2I GetPosition() const override
void SetStyle(MARKER_STYLE aStyle)
void SetSize(int aSize)
void SetDrawAtZero(bool aDrawFlag)
Set the draw at zero flag.
void SetEndPosition(const VECTOR2D &aPosition)
virtual double ViewGetLOD(int aLayer, VIEW *aView) const
Return the level of detail (LOD) of the item.
Definition: view_item.h:132
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:69
double GetScale() const
Definition: view.h:269
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:316
virtual int Query(const BOX2I &aRect, std::vector< LAYER_ITEM_PAIR > &aResult) const
Find all visible items that touch or are within the rectangle aRect.
Definition: view.cpp:422
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition: view.cpp:1575
GAL * GetGAL() const
Return the #GAL this view is using to draw graphical primitives.
Definition: view.h:195
std::pair< VIEW_ITEM *, int > LAYER_ITEM_PAIR
Definition: view.h:73
bool IsVisible(const VIEW_ITEM *aItem) const
Return information if the item is visible (or not).
Definition: view.cpp:1553
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition: view.cpp:1513
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:147
virtual bool IsConnectable() const
Definition: sch_item.h:349
virtual std::vector< VECTOR2I > GetConnectionPoints() const
Add all the connection points for this item to aPoints.
Definition: sch_item.h:364
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:40
virtual void Add(EDA_ITEM *aItem)
Definition: selection.cpp:32
int Size() const
Returns the number of selected parts.
Definition: selection.h:113
bool OnlyContains(std::vector< KICAD_T > aList) const
Checks if all items in the selection have a type in aList.
Definition: selection.cpp:181
Master controller class:
Definition: tool_manager.h:55
KIGFX::VIEW * GetView() const
Definition: tool_manager.h:285
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h:293
#define SNAP_RANGE
@ LAYER_CONNECTABLE
@ LAYER_GRAPHICS
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
@ GEOMETRY
Position or shape has changed.
Definition: view_item.h:49
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:401
const double IU_PER_MILS
Definition: base_units.h:78
double Distance(const VECTOR2I &aP) const
Definition: grid_helper.h:100
bool TestSegmentHit(const VECTOR2I &aRefPoint, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aDist)
Test if aRefPoint is with aDistance on the line defined by aStart and aEnd.
Definition: trigo.cpp:129
double EuclideanNorm(const VECTOR2I &vector)
Definition: trigo.h:129
@ SCH_LINE_T
Definition: typeinfo.h:146
@ SCH_NO_CONNECT_T
Definition: typeinfo.h:143
@ SCH_SYMBOL_T
Definition: typeinfo.h:156
@ SCH_FIELD_T
Definition: typeinfo.h:155
@ SCH_DIRECTIVE_LABEL_T
Definition: typeinfo.h:154
@ SCH_LABEL_T
Definition: typeinfo.h:151
@ SCH_SHEET_T
Definition: typeinfo.h:158
@ SCH_HIER_LABEL_T
Definition: typeinfo.h:153
@ SCH_SHEET_PIN_T
Definition: typeinfo.h:157
@ SCH_TEXT_T
Definition: typeinfo.h:150
@ SCH_BUS_WIRE_ENTRY_T
Definition: typeinfo.h:144
@ SCH_TEXTBOX_T
Definition: typeinfo.h:149
@ SCH_GLOBAL_LABEL_T
Definition: typeinfo.h:152
@ SCH_JUNCTION_T
Definition: typeinfo.h:142
VECTOR2< int > VECTOR2I
Definition: vector2d.h:618