2015-02-18 01:29:54 +01:00
/*
* KiRouter - a push - and - ( sometimes - ) shove PCB router
*
* Copyright ( C ) 2013 CERN
2021-07-19 19:56:05 -04:00
* Copyright ( C ) 2016 - 2021 KiCad Developers , see AUTHORS . txt for contributors .
2015-02-18 01:29:54 +01:00
* Author : Tomasz Wlostowski < tomasz . wlostowski @ cern . ch >
*
* This program is free software : you can redistribute it and / or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation , either version 3 of the License , or ( at your
* option ) any later version .
*
* This program is distributed in the hope that it will be useful , but
* WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* General Public License for more details .
*
* You should have received a copy of the GNU General Public License along
* with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
2016-06-29 12:23:11 +02:00
# include <functional>
using namespace std : : placeholders ;
2015-02-18 01:29:54 +01:00
# include <pcb_painter.h>
2020-01-12 20:44:19 -05:00
# include <pcbnew_settings.h>
2015-02-18 01:29:54 +01:00
2021-01-16 23:17:32 +00:00
# include <tools/pcb_grid_helper.h>
2021-06-03 08:11:15 -04:00
# include <wx/log.h>
2015-02-18 01:29:54 +01:00
2016-08-15 17:16:47 +02:00
# include "pns_kicad_iface.h"
2015-02-18 01:29:54 +01:00
# include "pns_tool_base.h"
2021-03-21 11:24:55 +00:00
# include "pns_arc.h"
2016-08-15 17:16:51 +02:00
# include "pns_solid.h"
2016-08-15 17:16:47 +02:00
2016-12-02 18:58:12 +01:00
2015-02-18 01:29:54 +01:00
using namespace KIGFX ;
2016-08-29 16:38:11 +02:00
namespace PNS {
2015-02-18 01:29:54 +01:00
2016-08-29 19:31:13 +02:00
TOOL_BASE : : TOOL_BASE ( const std : : string & aToolName ) :
2019-05-12 12:49:58 +01:00
PCB_TOOL_BASE ( aToolName )
2015-02-18 01:29:54 +01:00
{
2016-09-29 18:59:11 +02:00
m_gridHelper = nullptr ;
m_iface = nullptr ;
m_router = nullptr ;
2019-05-16 17:13:21 -07:00
m_cancelled = false ;
2016-08-17 15:09:48 +02:00
2016-09-29 18:59:11 +02:00
m_startItem = nullptr ;
2015-03-10 15:38:27 +01:00
2016-09-29 18:59:11 +02:00
m_endItem = nullptr ;
m_gridHelper = nullptr ;
2020-01-11 00:11:31 +00:00
m_cancelled = false ;
2015-02-18 01:29:54 +01:00
}
2016-08-29 19:31:13 +02:00
TOOL_BASE : : ~ TOOL_BASE ( )
2015-02-18 01:29:54 +01:00
{
2015-11-03 11:19:42 -05:00
delete m_gridHelper ;
2016-08-17 15:09:48 +02:00
delete m_iface ;
delete m_router ;
2015-02-18 01:29:54 +01:00
}
2016-08-29 19:31:13 +02:00
void TOOL_BASE : : Reset ( RESET_REASON aReason )
2015-02-18 01:29:54 +01:00
{
2016-08-17 15:09:48 +02:00
delete m_gridHelper ;
delete m_iface ;
delete m_router ;
2016-08-15 17:16:47 +02:00
m_iface = new PNS_KICAD_IFACE ;
2017-08-03 17:53:07 +02:00
m_iface - > SetBoard ( board ( ) ) ;
2016-08-15 17:16:47 +02:00
m_iface - > SetView ( getView ( ) ) ;
2017-10-31 12:03:58 +01:00
m_iface - > SetHostTool ( this ) ;
2016-08-15 17:16:47 +02:00
2016-08-29 19:31:13 +02:00
m_router = new ROUTER ;
2017-08-03 17:53:07 +02:00
m_router - > SetInterface ( m_iface ) ;
2015-02-18 01:29:54 +01:00
m_router - > ClearWorld ( ) ;
m_router - > SyncWorld ( ) ;
2020-01-12 20:44:19 -05:00
2015-02-18 01:29:54 +01:00
m_router - > UpdateSizes ( m_savedSizes ) ;
2015-11-03 11:19:42 -05:00
2020-05-05 21:43:37 -04:00
PCBNEW_SETTINGS * settings = frame ( ) - > GetPcbNewSettings ( ) ;
2020-02-27 22:53:00 -05:00
if ( ! settings - > m_PnsSettings )
settings - > m_PnsSettings = std : : make_unique < ROUTING_SETTINGS > ( settings , " tools.pns " ) ;
m_router - > LoadSettings ( settings - > m_PnsSettings . get ( ) ) ;
2020-01-12 20:44:19 -05:00
2021-01-16 23:17:32 +00:00
m_gridHelper = new PCB_GRID_HELPER ( m_toolMgr , frame ( ) - > GetMagneticItemsSettings ( ) ) ;
2015-02-18 01:29:54 +01:00
}
2015-02-18 17:53:46 +01:00
2019-03-16 20:34:08 -07:00
ITEM * TOOL_BASE : : pickSingleItem ( const VECTOR2I & aWhere , int aNet , int aLayer , bool aIgnorePads ,
2020-07-02 22:52:37 +01:00
const std : : vector < ITEM * > aAvoidItems )
2015-02-18 01:29:54 +01:00
{
2020-11-10 23:12:28 +00:00
int tl = aLayer > 0 ? aLayer : getView ( ) - > GetTopLayer ( ) ;
2015-02-18 01:29:54 +01:00
2018-04-08 21:20:51 +01:00
static const int candidateCount = 5 ;
ITEM * prioritized [ candidateCount ] ;
2020-07-02 22:52:37 +01:00
SEG : : ecoord dist [ candidateCount ] ;
2015-02-18 01:29:54 +01:00
2018-04-08 21:20:51 +01:00
for ( int i = 0 ; i < candidateCount ; i + + )
2018-05-03 09:31:00 -07:00
{
2020-07-02 22:52:37 +01:00
prioritized [ i ] = nullptr ;
dist [ i ] = VECTOR2I : : ECOORD_MAX ;
2018-05-03 09:31:00 -07:00
}
2015-02-18 01:29:54 +01:00
2016-08-29 19:31:13 +02:00
ITEM_SET candidates = m_router - > QueryHoverItems ( aWhere ) ;
2015-02-18 01:29:54 +01:00
2021-06-06 14:16:31 -04:00
if ( candidates . Empty ( ) )
candidates = m_router - > QueryHoverItems ( aWhere , true ) ;
2016-08-29 19:31:13 +02:00
for ( ITEM * item : candidates . Items ( ) )
2015-02-18 01:29:54 +01:00
{
2018-02-03 10:39:46 +01:00
if ( ! item - > IsRoutable ( ) )
continue ;
2015-02-18 01:29:54 +01:00
if ( ! IsCopperLayer ( item - > Layers ( ) . Start ( ) ) )
continue ;
2019-08-15 00:21:48 -07:00
if ( ! m_iface - > IsAnyLayerVisible ( item - > Layers ( ) ) )
continue ;
2020-09-26 14:42:40 +01:00
if ( alg : : contains ( aAvoidItems , item ) )
2019-03-16 20:34:08 -07:00
continue ;
2015-02-18 01:29:54 +01:00
// fixme: this causes flicker with live loop removal...
//if( item->Parent() && !item->Parent()->ViewIsVisible() )
// continue;
2022-09-05 19:44:41 +01:00
if ( item - > OfKind ( ITEM : : SOLID_T ) & & aIgnorePads )
{
continue ;
}
else if ( aNet < = 0 | | item - > Net ( ) = = aNet )
2015-02-18 01:29:54 +01:00
{
2016-08-29 19:31:13 +02:00
if ( item - > OfKind ( ITEM : : VIA_T | ITEM : : SOLID_T ) )
2015-02-18 01:29:54 +01:00
{
2020-11-10 23:12:28 +00:00
SEG : : ecoord d = ( item - > Shape ( ) - > Centre ( ) - aWhere ) . SquaredEuclideanNorm ( ) ;
2018-05-03 09:31:00 -07:00
2020-11-10 23:12:28 +00:00
if ( d < dist [ 2 ] )
2018-05-03 09:31:00 -07:00
{
2015-02-18 01:29:54 +01:00
prioritized [ 2 ] = item ;
2020-11-10 23:12:28 +00:00
dist [ 2 ] = d ;
2018-05-03 09:31:00 -07:00
}
2020-11-10 23:12:28 +00:00
if ( item - > Layers ( ) . Overlaps ( tl ) & & d < dist [ 0 ] )
2018-05-03 09:31:00 -07:00
{
2015-02-18 01:29:54 +01:00
prioritized [ 0 ] = item ;
2020-11-10 23:12:28 +00:00
dist [ 0 ] = d ;
2018-05-03 09:31:00 -07:00
}
2015-02-18 01:29:54 +01:00
}
2020-11-10 23:12:28 +00:00
else // ITEM::SEGMENT_T | ITEM::ARC_T
2015-02-18 01:29:54 +01:00
{
2020-11-10 23:12:28 +00:00
LINKED_ITEM * li = static_cast < LINKED_ITEM * > ( item ) ;
SEG : : ecoord d = std : : min ( ( li - > Anchor ( 0 ) - aWhere ) . SquaredEuclideanNorm ( ) ,
( li - > Anchor ( 1 ) - aWhere ) . SquaredEuclideanNorm ( ) ) ;
if ( d < dist [ 3 ] )
{
2015-02-18 01:29:54 +01:00
prioritized [ 3 ] = item ;
2020-11-10 23:12:28 +00:00
dist [ 3 ] = d ;
}
if ( item - > Layers ( ) . Overlaps ( tl ) & & d < dist [ 1 ] )
{
2015-02-18 01:29:54 +01:00
prioritized [ 1 ] = item ;
2020-11-10 23:12:28 +00:00
dist [ 1 ] = d ;
}
2015-02-18 01:29:54 +01:00
}
}
2022-09-05 19:44:41 +01:00
else if ( item - > OfKind ( ITEM : : SOLID_T ) & & item - > IsFreePad ( ) )
{
// Allow free pads only when already inside pad
if ( item - > Shape ( ) - > Collide ( aWhere ) )
{
prioritized [ 0 ] = item ;
dist [ 0 ] = 0 ;
}
}
2018-04-08 21:20:51 +01:00
else if ( item - > Net ( ) = = 0 & & m_router - > Settings ( ) . Mode ( ) = = RM_MarkObstacles )
{
2021-07-19 19:56:05 -04:00
// Allow unconnected items as last resort in RM_MarkObstacles mode
2018-04-08 21:20:51 +01:00
if ( item - > Layers ( ) . Overlaps ( tl ) )
prioritized [ 4 ] = item ;
}
2015-02-18 01:29:54 +01:00
}
2021-07-19 19:56:05 -04:00
ITEM * rv = nullptr ;
2015-02-18 01:29:54 +01:00
2021-12-26 00:36:12 +00:00
bool highContrast = ( frame ( ) - > GetDisplayOptions ( ) . m_ContrastModeDisplay ! = HIGH_CONTRAST_MODE : : NORMAL ) ;
2020-07-11 13:40:23 -04:00
2018-04-08 21:20:51 +01:00
for ( int i = 0 ; i < candidateCount ; i + + )
2015-02-18 01:29:54 +01:00
{
2016-08-29 19:31:13 +02:00
ITEM * item = prioritized [ i ] ;
2015-02-18 01:29:54 +01:00
2020-07-11 13:40:23 -04:00
if ( highContrast & & item & & ! item - > Layers ( ) . Overlaps ( tl ) )
item = nullptr ;
2015-02-18 01:29:54 +01:00
2018-10-20 07:57:54 -07:00
if ( item & & ( aLayer < 0 | | item - > Layers ( ) . Overlaps ( aLayer ) ) )
2015-02-18 01:29:54 +01:00
{
rv = item ;
break ;
}
}
if ( rv )
2016-08-17 16:00:21 +02:00
{
2022-02-05 02:06:25 +00:00
wxLogTrace ( wxT ( " PNS " ) , wxT ( " %s, layer : %d, tl: %d " ) ,
rv - > KindStr ( ) . c_str ( ) ,
rv - > Layers ( ) . Start ( ) ,
2021-07-19 19:56:05 -04:00
tl ) ;
2016-08-17 16:00:21 +02:00
}
2015-02-18 01:29:54 +01:00
return rv ;
}
2022-12-06 05:24:09 +03:00
void TOOL_BASE : : highlightNets ( bool aEnabled , std : : set < int > aNetcodes )
2015-02-18 01:29:54 +01:00
{
RENDER_SETTINGS * rs = getView ( ) - > GetPainter ( ) - > GetSettings ( ) ;
2022-12-06 05:24:09 +03:00
if ( aNetcodes . size ( ) > 0 & & aEnabled )
2018-12-02 12:21:43 -07:00
{
2022-12-06 05:24:09 +03:00
// If the user has previously set some of the routed nets to be highlighted,
// we assume they want to keep them highlighted after routing
2018-12-02 12:21:43 -07:00
2022-12-06 05:24:09 +03:00
const std : : set < int > & currentNetCodes = rs - > GetHighlightNetCodes ( ) ;
bool keep = false ;
for ( const int & netcode : aNetcodes )
{
if ( currentNetCodes . find ( netcode ) ! = currentNetCodes . end ( ) )
{
keep = true ;
break ;
}
}
if ( rs - > IsHighlightEnabled ( ) & & keep )
m_startHighlightNetcodes = currentNetCodes ;
else
m_startHighlightNetcodes . clear ( ) ;
rs - > SetHighlight ( aNetcodes , true ) ;
2018-12-02 12:21:43 -07:00
}
2015-02-18 01:29:54 +01:00
else
2018-12-02 12:21:43 -07:00
{
2022-12-06 05:24:09 +03:00
rs - > SetHighlight ( m_startHighlightNetcodes , m_startHighlightNetcodes . size ( ) > 0 ) ;
2018-12-02 12:21:43 -07:00
}
2015-02-18 01:29:54 +01:00
2022-07-08 20:06:10 -07:00
// Do not remove this call. This is required to update the layers when we highlight a net.
// In this case, highlighting a net dims all other elements, so the colors need to update
getView ( ) - > UpdateAllLayersColor ( ) ;
2015-02-18 01:29:54 +01:00
}
2021-07-19 19:56:05 -04:00
2017-08-03 17:53:07 +02:00
bool TOOL_BASE : : checkSnap ( ITEM * aItem )
{
2019-06-01 11:39:39 +01:00
// Sync PNS engine settings with the general PCB editor options.
2017-08-03 17:53:07 +02:00
auto & pnss = m_router - > Settings ( ) ;
2022-12-29 12:16:25 +01:00
// If we're dragging a track segment, don't try to snap to items on the same copper layer with same nets. This is not a perfect heuristic, but seems to work reasonably well :-)
2021-12-15 01:46:03 +01:00
// This way we avoid 'flickery' behaviour for short segments when the snap algo is trying to
// snap to the corners of the segments next to the one being dragged.
if ( m_startItem & & aItem & & m_router - > GetState ( ) = = ROUTER : : DRAG_SEGMENT
& & aItem - > Layer ( ) = = m_startItem - > Layer ( ) & & aItem - > OfKind ( ITEM : : SEGMENT_T )
2022-12-29 12:16:25 +01:00
& & m_startItem - > OfKind ( ITEM : : SEGMENT_T )
& & aItem - > Net ( ) = = m_startItem - > Net ( ) )
2021-12-15 01:46:03 +01:00
return false ;
2020-01-12 20:44:19 -05:00
pnss . SetSnapToPads (
2020-05-22 19:27:05 +01:00
frame ( ) - > GetMagneticItemsSettings ( ) - > pads = = MAGNETIC_OPTIONS : : CAPTURE_CURSOR_IN_TRACK_TOOL | |
frame ( ) - > GetMagneticItemsSettings ( ) - > pads = = MAGNETIC_OPTIONS : : CAPTURE_ALWAYS ) ;
2017-08-03 17:53:07 +02:00
2020-01-12 20:44:19 -05:00
pnss . SetSnapToTracks (
2020-05-22 19:27:05 +01:00
frame ( ) - > GetMagneticItemsSettings ( ) - > tracks = = MAGNETIC_OPTIONS : : CAPTURE_CURSOR_IN_TRACK_TOOL
| | frame ( ) - > GetMagneticItemsSettings ( ) - > tracks = = MAGNETIC_OPTIONS : : CAPTURE_ALWAYS ) ;
2017-08-03 17:53:07 +02:00
if ( aItem )
{
2019-05-16 17:13:21 -07:00
if ( aItem - > OfKind ( ITEM : : VIA_T | ITEM : : SEGMENT_T | ITEM : : ARC_T ) )
2019-06-01 11:39:39 +01:00
return pnss . GetSnapToTracks ( ) ;
else if ( aItem - > OfKind ( ITEM : : SOLID_T ) )
return pnss . GetSnapToPads ( ) ;
2017-08-03 17:53:07 +02:00
}
2019-06-01 11:39:39 +01:00
return false ;
2017-08-03 17:53:07 +02:00
}
2015-02-18 17:53:46 +01:00
2021-07-19 19:56:05 -04:00
2018-07-26 23:35:11 +01:00
void TOOL_BASE : : updateStartItem ( const TOOL_EVENT & aEvent , bool aIgnorePads )
2015-02-18 01:29:54 +01:00
{
2020-12-11 13:11:20 +00:00
int tl = getView ( ) - > GetTopLayer ( ) ;
2022-03-29 13:43:00 +01:00
VECTOR2I cp = aEvent . IsPrime ( ) ? aEvent . Position ( )
: controls ( ) - > GetCursorPosition ( ! aEvent . Modifier ( MD_SHIFT ) ) ;
2015-08-04 11:37:16 +02:00
VECTOR2I p ;
2020-12-11 13:11:20 +00:00
GAL * gal = m_toolMgr - > GetView ( ) - > GetGAL ( ) ;
2015-08-04 11:37:16 +02:00
2017-08-16 14:11:07 +02:00
controls ( ) - > ForceCursorPosition ( false ) ;
2021-05-09 20:17:01 +01:00
m_gridHelper - > SetUseGrid ( gal - > GetGridSnapping ( ) & & ! aEvent . DisableGridSnapping ( ) ) ;
2019-01-29 07:16:11 -08:00
m_gridHelper - > SetSnap ( ! aEvent . Modifier ( MD_SHIFT ) ) ;
2017-08-16 14:11:07 +02:00
2015-02-18 01:29:54 +01:00
if ( aEvent . IsMotion ( ) | | aEvent . IsClick ( ) )
2015-08-04 11:37:16 +02:00
p = aEvent . Position ( ) ;
2016-08-15 17:16:53 +02:00
else
2015-08-04 11:37:16 +02:00
p = cp ;
2015-02-18 01:29:54 +01:00
2021-11-21 15:31:05 +01:00
m_startItem = pickSingleItem ( aEvent . IsClick ( ) ? cp : p , - 1 , - 1 , aIgnorePads ) ;
2015-02-18 01:29:54 +01:00
2021-01-25 21:19:26 -05:00
if ( ! m_gridHelper - > GetUseGrid ( ) & & m_startItem & & ! m_startItem - > Layers ( ) . Overlaps ( tl ) )
2016-09-29 18:59:11 +02:00
m_startItem = nullptr ;
2015-02-18 01:29:54 +01:00
2020-12-11 13:11:20 +00:00
m_startSnapPoint = snapToItem ( m_startItem , p ) ;
2021-05-25 21:55:57 +01:00
controls ( ) - > ForceCursorPosition ( true , m_startSnapPoint ) ;
2015-02-18 01:29:54 +01:00
}
2015-02-18 17:53:46 +01:00
2017-01-18 09:04:11 +01:00
void TOOL_BASE : : updateEndItem ( const TOOL_EVENT & aEvent )
2015-02-18 01:29:54 +01:00
{
2020-12-11 13:11:20 +00:00
int layer ;
GAL * gal = m_toolMgr - > GetView ( ) - > GetGAL ( ) ;
2021-05-09 20:17:01 +01:00
m_gridHelper - > SetUseGrid ( gal - > GetGridSnapping ( ) & & ! aEvent . DisableGridSnapping ( ) ) ;
2020-12-11 13:11:20 +00:00
m_gridHelper - > SetSnap ( ! aEvent . Modifier ( MD_SHIFT ) ) ;
2019-01-29 07:16:11 -08:00
controls ( ) - > ForceCursorPosition ( false ) ;
2022-12-06 05:24:09 +03:00
2022-11-09 13:09:08 +00:00
VECTOR2I mousePos = controls ( ) - > GetMousePosition ( ) ;
2022-12-06 05:24:09 +03:00
2022-11-09 13:09:08 +00:00
if ( m_router - > GetState ( ) = = ROUTER : : ROUTE_TRACK & & aEvent . IsDrag ( ) )
{
// If the user is moving the mouse quickly while routing then clicks will come in as
// short drags. In this case we want to use the drag origin rather than the current
// mouse position.
2022-06-03 23:11:34 +02:00
mousePos = aEvent . DragOrigin ( ) ;
2022-11-09 13:09:08 +00:00
}
2015-02-18 01:29:54 +01:00
2018-04-08 21:20:51 +01:00
if ( m_router - > Settings ( ) . Mode ( ) ! = RM_MarkObstacles & &
2020-12-04 16:57:19 +00:00
( m_router - > GetCurrentNets ( ) . empty ( ) | | m_router - > GetCurrentNets ( ) . front ( ) < 0 ) )
2015-02-18 01:29:54 +01:00
{
2020-12-11 13:11:20 +00:00
m_endSnapPoint = snapToItem ( nullptr , mousePos ) ;
2017-08-03 17:53:07 +02:00
controls ( ) - > ForceCursorPosition ( true , m_endSnapPoint ) ;
2016-09-29 18:59:11 +02:00
m_endItem = nullptr ;
2015-02-18 01:29:54 +01:00
return ;
}
if ( m_router - > IsPlacingVia ( ) )
layer = - 1 ;
else
layer = m_router - > GetCurrentLayer ( ) ;
2016-09-29 18:59:11 +02:00
ITEM * endItem = nullptr ;
2015-08-21 16:35:34 +02:00
std : : vector < int > nets = m_router - > GetCurrentNets ( ) ;
2016-06-29 16:07:55 -04:00
for ( int net : nets )
2015-08-21 16:35:34 +02:00
{
2019-03-16 20:34:08 -07:00
endItem = pickSingleItem ( mousePos , net , layer , false , { m_startItem } ) ;
2015-08-21 16:35:34 +02:00
if ( endItem )
break ;
}
2015-02-18 01:29:54 +01:00
2021-04-04 10:22:23 -04:00
if ( m_gridHelper - > GetSnap ( ) & & checkSnap ( endItem ) )
2017-08-03 17:53:07 +02:00
{
m_endItem = endItem ;
2020-12-11 13:11:20 +00:00
m_endSnapPoint = snapToItem ( endItem , mousePos ) ;
2020-10-31 15:41:50 +00:00
}
else
{
2017-08-03 17:53:07 +02:00
m_endItem = nullptr ;
2019-01-29 07:16:11 -08:00
m_endSnapPoint = m_gridHelper - > Align ( mousePos ) ;
2017-08-03 17:53:07 +02:00
}
2015-02-18 01:29:54 +01:00
2019-01-29 07:16:11 -08:00
controls ( ) - > ForceCursorPosition ( true , m_endSnapPoint ) ;
2015-02-18 01:29:54 +01:00
if ( m_endItem )
2016-08-17 16:00:21 +02:00
{
2022-02-05 02:06:25 +00:00
wxLogTrace ( wxT ( " PNS " ) , wxT ( " %s, layer : %d " ) ,
2020-10-31 15:41:50 +00:00
m_endItem - > KindStr ( ) . c_str ( ) ,
m_endItem - > Layers ( ) . Start ( ) ) ;
2016-08-17 16:00:21 +02:00
}
2015-02-18 01:29:54 +01:00
}
2016-08-15 17:16:53 +02:00
2016-08-29 19:31:13 +02:00
ROUTER * TOOL_BASE : : Router ( ) const
2016-08-15 17:16:47 +02:00
{
return m_router ;
}
2016-08-15 17:16:51 +02:00
2016-08-15 17:16:53 +02:00
2021-07-26 19:47:26 -04:00
const VECTOR2I TOOL_BASE : : snapToItem ( ITEM * aItem , const VECTOR2I & aP )
2016-08-15 17:16:51 +02:00
{
2020-12-11 13:11:20 +00:00
if ( ! aItem | | ! m_iface - > IsItemVisible ( aItem ) )
2016-08-15 17:16:51 +02:00
{
2016-09-29 18:59:11 +02:00
return m_gridHelper - > Align ( aP ) ;
2016-08-15 17:16:51 +02:00
}
switch ( aItem - > Kind ( ) )
{
2016-08-29 19:31:13 +02:00
case ITEM : : SOLID_T :
2020-12-11 13:11:20 +00:00
return static_cast < SOLID * > ( aItem ) - > Pos ( ) ;
2016-08-15 17:16:51 +02:00
2016-08-29 19:31:13 +02:00
case ITEM : : VIA_T :
2020-12-11 13:11:20 +00:00
return static_cast < VIA * > ( aItem ) - > Pos ( ) ;
2016-08-15 17:16:51 +02:00
2016-08-29 19:31:13 +02:00
case ITEM : : SEGMENT_T :
2019-05-16 17:13:21 -07:00
case ITEM : : ARC_T :
2016-08-15 17:16:51 +02:00
{
2019-05-16 17:13:21 -07:00
LINKED_ITEM * li = static_cast < LINKED_ITEM * > ( aItem ) ;
2020-11-10 23:12:28 +00:00
VECTOR2I A = li - > Anchor ( 0 ) ;
VECTOR2I B = li - > Anchor ( 1 ) ;
SEG : : ecoord w_sq = SEG : : Square ( li - > Width ( ) / 2 ) ;
SEG : : ecoord distA_sq = ( aP - A ) . SquaredEuclideanNorm ( ) ;
SEG : : ecoord distB_sq = ( aP - B ) . SquaredEuclideanNorm ( ) ;
2019-05-16 17:13:21 -07:00
2020-11-10 23:12:28 +00:00
if ( distA_sq < w_sq | | distB_sq < w_sq )
2020-10-31 15:41:50 +00:00
{
2020-12-11 13:11:20 +00:00
return ( distA_sq < distB_sq ) ? A : B ;
2020-10-31 15:41:50 +00:00
}
2020-12-11 13:11:20 +00:00
else if ( aItem - > Kind ( ) = = ITEM : : SEGMENT_T )
2020-10-31 15:41:50 +00:00
{
2021-07-19 19:56:05 -04:00
// TODO(snh): Clean this up
2020-12-11 13:11:20 +00:00
SEGMENT * seg = static_cast < SEGMENT * > ( li ) ;
return m_gridHelper - > AlignToSegment ( aP , seg - > Seg ( ) ) ;
}
else if ( aItem - > Kind ( ) = = ITEM : : ARC_T )
{
ARC * arc = static_cast < ARC * > ( li ) ;
return m_gridHelper - > AlignToArc ( aP , * static_cast < const SHAPE_ARC * > ( arc - > Shape ( ) ) ) ;
2020-10-31 15:41:50 +00:00
}
2021-07-19 19:56:05 -04:00
2020-12-11 13:11:20 +00:00
break ;
2021-07-19 19:56:05 -04:00
}
2016-08-15 17:16:51 +02:00
default :
break ;
}
2020-12-11 13:11:20 +00:00
return m_gridHelper - > Align ( aP ) ;
2016-08-15 17:16:51 +02:00
}
2016-08-29 16:38:11 +02:00
}