KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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-2023 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>
29#include <sch_item.h>
30#include <sch_line.h>
31#include <sch_painter.h>
32#include <tool/tool_manager.h>
34#include <trigo.h>
35#include <view/view.h>
36#include "ee_grid_helper.h"
37
38
40 GRID_HELPER( aToolMgr )
41{
42 KIGFX::VIEW* view = m_toolMgr->GetView();
43
44 m_viewAxis.SetSize( 20000 );
46 m_viewAxis.SetColor( COLOR4D( 0.0, 0.1, 0.4, 0.8 ) );
48 view->Add( &m_viewAxis );
49 view->SetVisible( &m_viewAxis, false );
50
52 m_viewSnapPoint.SetColor( COLOR4D( 0.0, 0.1, 0.4, 1.0 ) );
54 view->Add( &m_viewSnapPoint );
55 view->SetVisible( &m_viewSnapPoint, false );
56
58 m_viewSnapLine.SetColor( COLOR4D( 0.33, 0.55, 0.95, 1.0 ) );
60 view->Add( &m_viewSnapLine );
61 view->SetVisible( &m_viewSnapLine, false );
62}
63
64
66 const EE_SELECTION& aItems )
67{
69
70 // If we're working with any connectable objects, skip non-connectable objects
71 // since they are often off-grid, e.g. text anchors
72 bool hasConnectables = false;
73
74 for( EDA_ITEM* item : aItems )
75 {
76 GRID_HELPER_GRIDS grid = GetItemGrid( static_cast<SCH_ITEM*>( item ) );
78 {
79 hasConnectables = true;
80 break;
81 }
82 }
83
84 for( EDA_ITEM* item : aItems )
85 computeAnchors( static_cast<SCH_ITEM*>( item ), aMousePos, true, !hasConnectables );
86
87 double worldScale = m_toolMgr->GetView()->GetGAL()->GetWorldScale();
88 double lineSnapMinCornerDistance = 50.0 / worldScale;
89
90 ANCHOR* nearestOutline = nearestAnchor( aMousePos, OUTLINE, aGrid );
91 ANCHOR* nearestCorner = nearestAnchor( aMousePos, CORNER, aGrid );
92 ANCHOR* nearestOrigin = nearestAnchor( aMousePos, ORIGIN, aGrid );
93 ANCHOR* best = nullptr;
94 double minDist = std::numeric_limits<double>::max();
95
96 if( nearestOrigin )
97 {
98 minDist = nearestOrigin->Distance( aMousePos );
99 best = nearestOrigin;
100 }
101
102 if( nearestCorner )
103 {
104 double dist = nearestCorner->Distance( aMousePos );
105
106 if( dist < minDist )
107 {
108 minDist = dist;
109 best = nearestCorner;
110 }
111 }
112
113 if( nearestOutline )
114 {
115 double dist = nearestOutline->Distance( aMousePos );
116
117 if( minDist > lineSnapMinCornerDistance && dist < minDist )
118 best = nearestOutline;
119 }
120
121 return best ? best->pos : aMousePos;
122}
123
124
126 SCH_ITEM* aSkip )
127{
128 EE_SELECTION skipItems;
129 skipItems.Add( aSkip );
130
131 return BestSnapAnchor( aOrigin, aGrid, skipItems );
132}
133
134
136 const EE_SELECTION& aSkip )
137{
138 constexpr int snapRange = SNAP_RANGE * schIUScale.IU_PER_MILS;
139
140 VECTOR2I pt = aOrigin;
141 VECTOR2I snapDist( snapRange, snapRange );
142 bool snapLineX = false;
143 bool snapLineY = false;
144 bool snapPoint = false;
145 bool gridChecked = false;
146
147 BOX2I bb( VECTOR2I( aOrigin.x - snapRange / 2, aOrigin.y - snapRange / 2 ),
148 VECTOR2I( snapRange, snapRange ) );
149
150 clearAnchors();
151
152 for( SCH_ITEM* item : queryVisible( bb, aSkip ) )
153 computeAnchors( item, aOrigin );
154
155 ANCHOR* nearest = nearestAnchor( aOrigin, SNAPPABLE, aGrid );
156 VECTOR2I nearestGrid = Align( aOrigin, aGrid );
157
159 {
160 if( std::abs( m_viewSnapLine.GetPosition().x - aOrigin.x ) < snapDist.x )
161 {
163 snapDist.x = std::abs( m_viewSnapLine.GetPosition().x - aOrigin.x );
164 snapLineX = true;
165 }
166
167 if( std::abs( m_viewSnapLine.GetPosition().y - aOrigin.y ) < snapDist.y )
168 {
170 snapDist.y = std::abs( m_viewSnapLine.GetPosition().y - aOrigin.y );
171 snapLineY = true;
172 }
173
174 if( canUseGrid() && std::abs( nearestGrid.x - aOrigin.x ) < snapDist.x )
175 {
176 pt.x = nearestGrid.x;
177 snapDist.x = std::abs( nearestGrid.x - aOrigin.x );
178 snapLineX = false;
179 }
180
181 if( canUseGrid() && std::abs( nearestGrid.y - aOrigin.y ) < snapDist.y )
182 {
183 pt.y = nearestGrid.y;
184 snapDist.y = std::abs( nearestGrid.y - aOrigin.y );
185 snapLineY = false;
186 }
187
188 gridChecked = true;
189 }
190
191 if( m_enableSnap && nearest && nearest->Distance( aOrigin ) < snapDist.EuclideanNorm() )
192 {
193
194 if( canUseGrid() && ( nearestGrid - aOrigin ).EuclideanNorm() < snapDist.EuclideanNorm() )
195 {
196 pt = nearestGrid;
197 snapDist.x = std::abs( nearestGrid.x - aOrigin.x );
198 snapDist.y = std::abs( nearestGrid.y - aOrigin.y );
199 snapPoint = false;
200 }
201 else
202 {
203 pt = nearest->pos;
204 snapDist.x = std::abs( nearest->pos.x - aOrigin.x );
205 snapDist.y = std::abs( nearest->pos.y - aOrigin.y );
206 snapPoint = true;
207 }
208
209 snapLineX = snapLineY = false;
210 gridChecked = true;
211 }
212
213 if( canUseGrid() && !gridChecked )
214 pt = nearestGrid;
215
216 if( snapLineX || snapLineY )
217 {
219
222 else
224 }
225 else if( snapPoint )
226 {
227 m_snapItem = nearest;
230
232
235 else
237 }
238 else
239 {
242 }
243
244 return pt;
245}
246
247
249{
251 int idx = -1;
252
254
255 if( !grid.overrides_enabled )
256 return g;
257
258 switch( aGrid )
259 {
260 case GRID_CONNECTABLE:
261 if( grid.override_connected )
262 idx = grid.override_connected_idx;
263
264 break;
265
266 case GRID_WIRES:
267 if( grid.override_wires )
268 idx = grid.override_wires_idx;
269
270 break;
271
272 case GRID_TEXT:
273 if( grid.override_text )
274 idx = grid.override_text_idx;
275
276 break;
277
278 case GRID_GRAPHICS:
279 if( grid.override_graphics )
280 idx = grid.override_graphics_idx;
281
282 break;
283
284 default:
285 break;
286 }
287
288 if( idx >= 0 && idx < (int) grid.grids.size() )
289 g = grid.grids[idx].ToDouble( schIUScale );
290
291 return g;
292}
293
294
296{
297 if( !m_snapItem )
298 return nullptr;
299
300 return static_cast<SCH_ITEM*>( m_snapItem->item );
301}
302
303
304std::set<SCH_ITEM*> EE_GRID_HELPER::queryVisible( const BOX2I& aArea,
305 const EE_SELECTION& aSkipList ) const
306{
307 std::set<SCH_ITEM*> items;
308 std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> selectedItems;
309
310 KIGFX::VIEW* view = m_toolMgr->GetView();
311
312 view->Query( aArea, selectedItems );
313
314 for( const KIGFX::VIEW::LAYER_ITEM_PAIR& it : selectedItems )
315 {
316 SCH_ITEM* item = static_cast<SCH_ITEM*>( it.first );
317
318 // The item must be visible and on an active layer
319 if( view->IsVisible( item ) && item->ViewGetLOD( it.second, view ) < view->GetScale() )
320 items.insert ( item );
321 }
322
323 for( EDA_ITEM* skipItem : aSkipList )
324 items.erase( static_cast<SCH_ITEM*>( skipItem ) );
325
326 return items;
327}
328
329
331{
332 GRID_HELPER_GRIDS grid = GetItemGrid( aSelection.Front() );
333
334 // Find the largest grid of all the items and use that
335 for( EDA_ITEM* item : aSelection )
336 {
337 GRID_HELPER_GRIDS itemGrid = GetItemGrid( item );
338
339 if( GetGridSize( itemGrid ) > GetGridSize( grid ) )
340 grid = itemGrid;
341 }
342
343 return grid;
344}
345
346
348{
349 if( !aItem )
350 return GRID_CURRENT;
351
352 switch( aItem->Type() )
353 {
354 case LIB_SYMBOL_T:
355 case LIB_PIN_T:
356 case SCH_SYMBOL_T:
357 case SCH_PIN_T:
358 case SCH_SHEET_PIN_T:
359 case SCH_SHEET_T:
360 case SCH_NO_CONNECT_T:
362 case SCH_HIER_LABEL_T:
363 case SCH_LABEL_T:
365 return GRID_CONNECTABLE;
366
367 case LIB_FIELD_T:
368 case SCH_FIELD_T:
369 case LIB_TEXT_T:
370 case SCH_TEXT_T:
371 return GRID_TEXT;
372
373 case LIB_SHAPE_T:
374 case SCH_SHAPE_T:
375 // The text box's border lines are what need to be on the graphic grid
376 case LIB_TEXTBOX_T:
377 case SCH_TEXTBOX_T:
378 case SCH_BITMAP_T:
379 return GRID_GRAPHICS;
380
381 case SCH_JUNCTION_T:
382 return GRID_WIRES;
383
384 case SCH_LINE_T:
385 if( static_cast<const SCH_LINE*>( aItem )->IsConnectable() )
386 return GRID_WIRES;
387 else
388 return GRID_GRAPHICS;
389
392 return GRID_WIRES;
393
394 default:
395 return GRID_CURRENT;
396 }
397}
398
399
400void EE_GRID_HELPER::computeAnchors( SCH_ITEM *aItem, const VECTOR2I &aRefPos, bool aFrom,
401 bool aIncludeText )
402{
403 bool isGraphicLine =
404 aItem->Type() == SCH_LINE_T && static_cast<SCH_LINE*>( aItem )->IsGraphicLine();
405
406 switch( aItem->Type() )
407 {
408 case SCH_TEXT_T:
409 case SCH_TEXTBOX_T:
410 case SCH_FIELD_T:
411 {
412 if( aIncludeText )
413 addAnchor( aItem->GetPosition(), ORIGIN, aItem );
414
415 break;
416 }
417
418 case SCH_SYMBOL_T:
419 case SCH_SHEET_T:
420 addAnchor( aItem->GetPosition(), ORIGIN, aItem );
422
423 case SCH_JUNCTION_T:
424 case SCH_NO_CONNECT_T:
425 case SCH_LINE_T:
426 // Don't add anchors for graphic lines unless we're including text,
427 // they may be on a non-connectable grid
428 if( isGraphicLine && !aIncludeText )
429 break;
430
433 case SCH_HIER_LABEL_T:
434 case SCH_LABEL_T:
437 case SCH_SHEET_PIN_T:
438 {
439 std::vector<VECTOR2I> pts = aItem->GetConnectionPoints();
440
441 for( const VECTOR2I& pt : pts )
442 addAnchor( VECTOR2I( pt ), SNAPPABLE | CORNER, aItem );
443
444 break;
445 }
446
447 default:
448 break;
449 }
450
451 // Don't add anchors for graphic lines unless we're including text,
452 // they may be on a non-connectable grid
453 if( aItem->Type() == SCH_LINE_T && ( aIncludeText || !isGraphicLine ) )
454 {
455 SCH_LINE* line = static_cast<SCH_LINE*>( aItem );
456 VECTOR2I pt = Align( aRefPos );
457
458 if( line->GetStartPoint().x == line->GetEndPoint().x )
459 {
460 VECTOR2I possible( line->GetStartPoint().x, pt.y );
461
462 if( TestSegmentHit( possible, line->GetStartPoint(), line->GetEndPoint(), 0 ) )
463 addAnchor( possible, SNAPPABLE | VERTICAL, aItem );
464 }
465 else if( line->GetStartPoint().y == line->GetEndPoint().y )
466 {
467 VECTOR2I possible( pt.x, line->GetStartPoint().y );
468
469 if( TestSegmentHit( possible, line->GetStartPoint(), line->GetEndPoint(), 0 ) )
470 addAnchor( possible, SNAPPABLE | HORIZONTAL, aItem );
471 }
472 }
473}
474
475
477 GRID_HELPER_GRIDS aGrid )
478{
479 double minDist = std::numeric_limits<double>::max();
480 ANCHOR* best = nullptr;
481
482 for( ANCHOR& a : m_anchors )
483 {
484 SCH_ITEM* item = static_cast<SCH_ITEM*>( a.item );
485
486 if( ( aFlags & a.flags ) != aFlags )
487 continue;
488
489 if( aGrid == GRID_CONNECTABLE && !item->IsConnectable() )
490 continue;
491 else if( aGrid == GRID_GRAPHICS && item->IsConnectable() )
492 continue;
493
494 double dist = a.Distance( aPos );
495
496 if( dist < minDist )
497 {
498 minDist = dist;
499 best = &a;
500 }
501 }
502
503 return best;
504}
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:111
WINDOW_SETTINGS m_Window
Definition: app_settings.h:169
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:239
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
GRID_HELPER_GRIDS GetSelectionGrid(const SELECTION &aItem) const override
Gets the coarsest grid that applies to a selecion of items.
GRID_HELPER_GRIDS GetItemGrid(const EDA_ITEM *aItem) const override
Gets the coarsest grid that applies to an item.
VECTOR2I BestDragOrigin(const VECTOR2I &aMousePos, GRID_HELPER_GRIDS aGrid, const EE_SELECTION &aItems)
std::set< SCH_ITEM * > queryVisible(const BOX2I &aArea, const EE_SELECTION &aSkipList) const
VECTOR2I BestSnapAnchor(const VECTOR2I &aOrigin, GRID_HELPER_GRIDS aGrid, SCH_ITEM *aSkip)
ANCHOR * nearestAnchor(const VECTOR2I &aPos, int aFlags, GRID_HELPER_GRIDS aGrid)
VECTOR2D GetGridSize(GRID_HELPER_GRIDS aGrid) const override
Return the size of the specified grid.
SCH_ITEM * GetSnapped() const
Function GetSnapped If the EE_GRID_HELPER has highlighted a snap point (target shown),...
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,...
VECTOR2I m_skipPoint
Definition: grid_helper.h:182
TOOL_MANAGER * m_toolMgr
Definition: grid_helper.h:172
ANCHOR * m_snapItem
Definition: grid_helper.h:180
bool m_enableSnapLine
Definition: grid_helper.h:179
bool m_enableSnap
Definition: grid_helper.h:177
void addAnchor(const VECTOR2I &aPos, int aFlags, EDA_ITEM *aItem)
Definition: grid_helper.h:148
bool canUseGrid() const
Check whether it is possible to use the grid – this depends both on local grid helper settings and gl...
void clearAnchors()
Definition: grid_helper.h:154
KIGFX::ORIGIN_VIEWITEM m_viewSnapPoint
Definition: grid_helper.h:184
KIGFX::ORIGIN_VIEWITEM m_viewSnapLine
Definition: grid_helper.h:185
virtual VECTOR2I Align(const VECTOR2I &aPoint, GRID_HELPER_GRIDS aGrid) const
Definition: grid_helper.h:60
KIGFX::ORIGIN_VIEWITEM m_viewAxis
Definition: grid_helper.h:186
std::vector< ANCHOR > m_anchors
Definition: grid_helper.h:170
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
const VECTOR2D & GetGridSize() const
Return the grid size.
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:134
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:314
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:1608
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:1586
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition: view.cpp:1546
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:150
virtual bool IsConnectable() const
Definition: sch_item.h:362
virtual std::vector< VECTOR2I > GetConnectionPoints() const
Add all the connection points for this item to aPoints.
Definition: sch_item.h:377
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:40
VECTOR2I GetEndPoint() const
Definition: sch_line.h:145
VECTOR2I GetStartPoint() const
Definition: sch_line.h:140
virtual void Add(EDA_ITEM *aItem)
Definition: selection.cpp:42
EDA_ITEM * Front() const
Definition: selection.h:208
Master controller class:
Definition: tool_manager.h:57
APP_SETTINGS_BASE * GetSettings() const
Definition: tool_manager.h:387
KIGFX::VIEW * GetView() const
Definition: tool_manager.h:378
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h:265
#define SNAP_RANGE
GRID_HELPER_GRIDS
Definition: grid_helper.h:37
@ GRID_TEXT
Definition: grid_helper.h:44
@ GRID_CURRENT
Definition: grid_helper.h:39
@ GRID_GRAPHICS
Definition: grid_helper.h:45
@ GRID_CONNECTABLE
Definition: grid_helper.h:41
@ GRID_WIRES
Definition: grid_helper.h:42
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:426
const double IU_PER_MILS
Definition: base_units.h:78
double Distance(const VECTOR2I &aP) const
Definition: grid_helper.h:142
GRID_SETTINGS grid
Definition: app_settings.h:81
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:145
@ LIB_SYMBOL_T
Definition: typeinfo.h:197
@ SCH_NO_CONNECT_T
Definition: typeinfo.h:142
@ LIB_TEXT_T
Definition: typeinfo.h:199
@ SCH_SYMBOL_T
Definition: typeinfo.h:155
@ LIB_TEXTBOX_T
Definition: typeinfo.h:200
@ SCH_FIELD_T
Definition: typeinfo.h:154
@ SCH_DIRECTIVE_LABEL_T
Definition: typeinfo.h:153
@ SCH_LABEL_T
Definition: typeinfo.h:150
@ SCH_SHEET_T
Definition: typeinfo.h:157
@ LIB_SHAPE_T
Definition: typeinfo.h:198
@ SCH_SHAPE_T
Definition: typeinfo.h:146
@ SCH_HIER_LABEL_T
Definition: typeinfo.h:152
@ SCH_BUS_BUS_ENTRY_T
Definition: typeinfo.h:144
@ LIB_PIN_T
Definition: typeinfo.h:201
@ SCH_SHEET_PIN_T
Definition: typeinfo.h:156
@ SCH_TEXT_T
Definition: typeinfo.h:149
@ LIB_FIELD_T
Definition: typeinfo.h:207
@ SCH_BUS_WIRE_ENTRY_T
Definition: typeinfo.h:143
@ SCH_BITMAP_T
Definition: typeinfo.h:147
@ SCH_TEXTBOX_T
Definition: typeinfo.h:148
@ SCH_GLOBAL_LABEL_T
Definition: typeinfo.h:151
@ SCH_JUNCTION_T
Definition: typeinfo.h:141
@ SCH_PIN_T
Definition: typeinfo.h:158
VECTOR2< int > VECTOR2I
Definition: vector2d.h:588