mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-04-11 10:20:11 +00:00
Add snapping to eeschema
This generalizes both the SetPosition() function and ORIGIN_VIEWITEM class away from the pcbnew-centric.
This commit is contained in:
parent
467aa47bbb
commit
173b4ff588
common
cvpcb
eeschema
CMakeLists.txtlib_item.hlib_pin.hlib_view_frame.cpp
libedit
sch_draw_panel.cppsch_item.hsch_preview_panel.cpptools
gerbview
include
pagelayout_editor/tools
pcbnew
@ -398,6 +398,8 @@ list( APPEND COMMON_SRCS
|
||||
set( COMMON_SRCS
|
||||
${COMMON_SRCS}
|
||||
|
||||
origin_viewitem.cpp
|
||||
|
||||
view/view.cpp
|
||||
view/view_item.cpp
|
||||
view/view_group.cpp
|
||||
@ -477,7 +479,6 @@ set( PCB_COMMON_SRCS
|
||||
eda_text.cpp
|
||||
fp_lib_table.cpp
|
||||
hash_eda.cpp
|
||||
origin_viewitem.cpp
|
||||
page_info.cpp
|
||||
${CMAKE_SOURCE_DIR}/pcbnew/pcb_base_frame.cpp
|
||||
${CMAKE_SOURCE_DIR}/pcbnew/pcb_expr_evaluator.cpp
|
||||
|
@ -32,7 +32,7 @@
|
||||
using namespace KIGFX;
|
||||
|
||||
ORIGIN_VIEWITEM::ORIGIN_VIEWITEM( const COLOR4D& aColor, MARKER_STYLE aStyle, int aSize, const VECTOR2D& aPosition ) :
|
||||
BOARD_ITEM( nullptr, NOT_USED ), // this item is never added to a BOARD so it needs no type
|
||||
EDA_ITEM( nullptr, NOT_USED ), // this item is never added to a BOARD/SCHEMATIC so it needs no type
|
||||
m_position( aPosition ),
|
||||
m_size( aSize ),
|
||||
m_color( aColor ),
|
||||
@ -43,7 +43,7 @@ ORIGIN_VIEWITEM::ORIGIN_VIEWITEM( const COLOR4D& aColor, MARKER_STYLE aStyle, in
|
||||
|
||||
|
||||
ORIGIN_VIEWITEM::ORIGIN_VIEWITEM( const VECTOR2D& aPosition, STATUS_FLAGS flags ) :
|
||||
BOARD_ITEM( nullptr, NOT_USED ), // this item is never added to a BOARD so it needs no type
|
||||
EDA_ITEM( nullptr, NOT_USED ), // this item is never added to a BOARD/SCHEMATIC so it needs no type
|
||||
m_position( aPosition ),
|
||||
m_size( NOT_USED ),
|
||||
m_color( UNSPECIFIED_COLOR ),
|
||||
@ -108,7 +108,7 @@ void ORIGIN_VIEWITEM::ViewDraw( int, VIEW* aView ) const
|
||||
clip.Normalize();
|
||||
|
||||
double theta = atan2( end.y - start.y, end.x - start.x );
|
||||
std::array<double,2> strokes = { DASH_MARK_LEN( 1 ), DASH_GAP_LEN( 1 ) };
|
||||
std::array<double,2> strokes = { scaledSize.x, scaledSize.x / 2 };
|
||||
|
||||
for( size_t i = 0; i < 10000; ++i )
|
||||
{
|
||||
|
@ -216,7 +216,7 @@ void WS_DRAW_ITEM_POLYPOLYGONS::PrintWsItem( RENDER_SETTINGS* aSettings, const w
|
||||
}
|
||||
|
||||
|
||||
void WS_DRAW_ITEM_POLYPOLYGONS::SetPosition( wxPoint aPos )
|
||||
void WS_DRAW_ITEM_POLYPOLYGONS::SetPosition( const wxPoint& aPos )
|
||||
{
|
||||
// Note: m_pos is the anchor point of the shape.
|
||||
wxPoint move_vect = aPos - m_pos;
|
||||
|
@ -87,7 +87,7 @@ void VIEW_CONTROLS::ApplySettings( const VC_SETTINGS& aSettings )
|
||||
{
|
||||
ShowCursor( aSettings.m_showCursor );
|
||||
CaptureCursor( aSettings.m_cursorCaptured );
|
||||
SetSnapping( aSettings.m_snappingEnabled );
|
||||
SetGridSnapping( aSettings.m_snappingEnabled );
|
||||
SetGrabMouse( aSettings.m_grabMouse );
|
||||
SetAutoPan( aSettings.m_autoPanEnabled );
|
||||
SetAutoPanMargin( aSettings.m_autoPanMargin );
|
||||
|
@ -93,7 +93,7 @@ public:
|
||||
* currently: do nothing in CvPcb.
|
||||
* but but be defined because it is a pure virtual in PCB_BASE_FRAME
|
||||
*/
|
||||
void SaveCopyInUndoList( BOARD_ITEM* aItemToCopy, UNDO_REDO aTypeCommand = UNDO_REDO::UNSPECIFIED,
|
||||
void SaveCopyInUndoList( EDA_ITEM* aItemToCopy, UNDO_REDO aTypeCommand = UNDO_REDO::UNSPECIFIED,
|
||||
const wxPoint& aTransformPoint = wxPoint( 0, 0 ) ) override
|
||||
{
|
||||
}
|
||||
|
@ -243,6 +243,7 @@ set( EESCHEMA_SRCS
|
||||
tools/backannotate.cpp
|
||||
tools/backanno.cpp
|
||||
tools/ee_actions.cpp
|
||||
tools/ee_grid_helper.cpp
|
||||
tools/ee_inspection_tool.cpp
|
||||
tools/ee_point_editor.cpp
|
||||
tools/ee_selection.cpp
|
||||
|
@ -245,7 +245,7 @@ public:
|
||||
*/
|
||||
virtual void MoveTo( const wxPoint& aPosition ) = 0;
|
||||
|
||||
void SetPosition( const wxPoint& aPosition ) { MoveTo( aPosition ); }
|
||||
void SetPosition( const wxPoint& aPosition ) override { MoveTo( aPosition ); }
|
||||
|
||||
/**
|
||||
* Mirror the draw object along the horizontal (X) axis about \a aCenter point.
|
||||
|
@ -252,7 +252,7 @@ public:
|
||||
void MoveTo( const wxPoint& aPosition ) override;
|
||||
|
||||
wxPoint GetPosition() const override { return m_position; }
|
||||
void SetPosition( const wxPoint& aPos ) { m_position = aPos; }
|
||||
void SetPosition( const wxPoint& aPos ) override { m_position = aPos; }
|
||||
|
||||
void MirrorHorizontal( const wxPoint& aCenter ) override;
|
||||
void MirrorVertical( const wxPoint& aCenter ) override;
|
||||
|
@ -194,7 +194,7 @@ LIB_VIEW_FRAME::LIB_VIEW_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrame
|
||||
}
|
||||
|
||||
SyncView();
|
||||
GetCanvas()->GetViewControls()->SetSnapping( true );
|
||||
GetCanvas()->GetViewControls()->SetGridSnapping( true );
|
||||
GetCanvas()->SetCanFocus( false );
|
||||
|
||||
// Set the working/draw area size to display a symbol to a reasonable value:
|
||||
|
@ -175,7 +175,7 @@ LIB_EDIT_FRAME::LIB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
|
||||
Show( true );
|
||||
|
||||
SyncView();
|
||||
GetCanvas()->GetViewControls()->SetSnapping( true );
|
||||
GetCanvas()->GetViewControls()->SetGridSnapping( true );
|
||||
GetCanvas()->GetView()->UseDrawPriority( true );
|
||||
GetCanvas()->GetGAL()->SetAxesEnabled( true );
|
||||
|
||||
|
@ -91,7 +91,7 @@ SCH_DRAW_PANEL::SCH_DRAW_PANEL( wxWindow* aParentWindow, wxWindowID aWindowId,
|
||||
// on updated viewport data.
|
||||
m_viewControls = new KIGFX::WX_VIEW_CONTROLS( m_view, this );
|
||||
|
||||
m_viewControls->SetSnapping( true );
|
||||
m_viewControls->SetGridSnapping( true );
|
||||
|
||||
SetEvtHandlerEnabled( true );
|
||||
SetFocus();
|
||||
|
@ -482,13 +482,6 @@ public:
|
||||
*/
|
||||
virtual void Plot( PLOTTER* aPlotter );
|
||||
|
||||
/**
|
||||
* Set the schematic item position to \a aPosition.
|
||||
*
|
||||
* @param aPosition A reference to a wxPoint object containing the new position.
|
||||
*/
|
||||
virtual void SetPosition( const wxPoint& aPosition ) = 0;
|
||||
|
||||
virtual bool operator <( const SCH_ITEM& aItem ) const;
|
||||
|
||||
private:
|
||||
|
@ -70,7 +70,7 @@ SCH_PREVIEW_PANEL::SCH_PREVIEW_PANEL( wxWindow* aParentWindow, wxWindowID aWindo
|
||||
m_gal->SetCursorEnabled( false );
|
||||
m_gal->SetGridSize( VECTOR2D( Mils2iu( 100.0 ), Mils2iu( 100.0 ) ) );
|
||||
|
||||
m_viewControls->SetSnapping( true );
|
||||
m_viewControls->SetGridSnapping( true );
|
||||
|
||||
SetEvtHandlerEnabled( true );
|
||||
SetFocus();
|
||||
|
385
eeschema/tools/ee_grid_helper.cpp
Normal file
385
eeschema/tools/ee_grid_helper.cpp
Normal file
@ -0,0 +1,385 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2014 CERN
|
||||
* Copyright (C) 2018-2020 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* @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 2
|
||||
* 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, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <functional>
|
||||
using namespace std::placeholders;
|
||||
|
||||
#include <geometry/shape_line_chain.h>
|
||||
#include <macros.h>
|
||||
#include <math/util.h> // for KiROUND
|
||||
#include <math/vector2d.h>
|
||||
#include <sch_item.h>
|
||||
#include <sch_painter.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <view/view.h>
|
||||
#include <view/view_controls.h>
|
||||
|
||||
#include "ee_grid_helper.h"
|
||||
|
||||
|
||||
EE_GRID_HELPER::EE_GRID_HELPER( TOOL_MANAGER* aToolMgr ) :
|
||||
m_toolMgr( aToolMgr )
|
||||
{
|
||||
m_enableSnap = true;
|
||||
m_enableSnapLine = true;
|
||||
m_snapSize = 100;
|
||||
m_snapItem = nullptr;
|
||||
KIGFX::VIEW* view = m_toolMgr->GetView();
|
||||
|
||||
m_viewAxis.SetSize( 20000 );
|
||||
m_viewAxis.SetStyle( KIGFX::ORIGIN_VIEWITEM::CROSS );
|
||||
m_viewAxis.SetColor( COLOR4D( 0.0, 0.1, 0.4, 0.8 ) );
|
||||
m_viewAxis.SetDrawAtZero( true );
|
||||
view->Add( &m_viewAxis );
|
||||
view->SetVisible( &m_viewAxis, false );
|
||||
|
||||
m_viewSnapPoint.SetStyle( KIGFX::ORIGIN_VIEWITEM::CIRCLE_CROSS );
|
||||
m_viewSnapPoint.SetColor( COLOR4D( 0.0, 0.1, 0.4, 1.0 ) );
|
||||
m_viewSnapPoint.SetDrawAtZero( true );
|
||||
view->Add( &m_viewSnapPoint );
|
||||
view->SetVisible( &m_viewSnapPoint, false );
|
||||
|
||||
m_viewSnapLine.SetStyle( KIGFX::ORIGIN_VIEWITEM::DASH_LINE );
|
||||
m_viewSnapLine.SetColor( COLOR4D( 0.33, 0.55, 0.95, 1.0 ) );
|
||||
m_viewSnapLine.SetDrawAtZero( true );
|
||||
view->Add( &m_viewSnapLine );
|
||||
view->SetVisible( &m_viewSnapLine, false );
|
||||
}
|
||||
|
||||
|
||||
EE_GRID_HELPER::~EE_GRID_HELPER()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
VECTOR2I EE_GRID_HELPER::GetGrid() const
|
||||
{
|
||||
VECTOR2D size = m_toolMgr->GetView()->GetGAL()->GetGridSize();
|
||||
|
||||
return VECTOR2I( KiROUND( size.x ), KiROUND( size.y ) );
|
||||
}
|
||||
|
||||
|
||||
VECTOR2I EE_GRID_HELPER::GetOrigin() const
|
||||
{
|
||||
VECTOR2D origin = m_toolMgr->GetView()->GetGAL()->GetGridOrigin();
|
||||
|
||||
return VECTOR2I( origin );
|
||||
}
|
||||
|
||||
|
||||
void EE_GRID_HELPER::SetAuxAxes( bool aEnable, const VECTOR2I& aOrigin )
|
||||
{
|
||||
if( aEnable )
|
||||
{
|
||||
m_auxAxis = aOrigin;
|
||||
m_viewAxis.SetPosition( wxPoint( aOrigin ) );
|
||||
m_toolMgr->GetView()->SetVisible( &m_viewAxis, true );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_auxAxis = OPT<VECTOR2I>();
|
||||
m_toolMgr->GetView()->SetVisible( &m_viewAxis, false );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
VECTOR2I EE_GRID_HELPER::Align( const VECTOR2I& aPoint ) const
|
||||
{
|
||||
if( !m_toolMgr->GetView()->GetGAL()->GetGridVisibility() )
|
||||
return aPoint;
|
||||
|
||||
const VECTOR2D gridOffset( GetOrigin() );
|
||||
const VECTOR2D grid( GetGrid() );
|
||||
|
||||
VECTOR2I nearest( KiROUND( ( aPoint.x - gridOffset.x ) / grid.x ) * grid.x + gridOffset.x,
|
||||
KiROUND( ( aPoint.y - gridOffset.y ) / grid.y ) * grid.y + gridOffset.y );
|
||||
|
||||
if( !m_auxAxis )
|
||||
return nearest;
|
||||
|
||||
if( std::abs( m_auxAxis->x - aPoint.x ) < std::abs( nearest.x - aPoint.x ) )
|
||||
nearest.x = m_auxAxis->x;
|
||||
|
||||
if( std::abs( m_auxAxis->y - aPoint.y ) < std::abs( nearest.y - aPoint.y ) )
|
||||
nearest.y = m_auxAxis->y;
|
||||
|
||||
return nearest;
|
||||
}
|
||||
|
||||
|
||||
VECTOR2I EE_GRID_HELPER::AlignToWire( const VECTOR2I& aPoint, const SEG& aSeg )
|
||||
{
|
||||
OPT_VECTOR2I pts[6];
|
||||
|
||||
if( !m_enableSnap )
|
||||
return aPoint;
|
||||
|
||||
const VECTOR2D gridOffset( GetOrigin() );
|
||||
const VECTOR2D gridSize( GetGrid() );
|
||||
|
||||
VECTOR2I nearest( KiROUND( ( aPoint.x - gridOffset.x ) / gridSize.x ) * gridSize.x + gridOffset.x,
|
||||
KiROUND( ( aPoint.y - gridOffset.y ) / gridSize.y ) * gridSize.y + gridOffset.y );
|
||||
|
||||
pts[0] = aSeg.A;
|
||||
pts[1] = aSeg.B;
|
||||
pts[2] = aSeg.IntersectLines( SEG( nearest + VECTOR2I( -1, 0 ), nearest + VECTOR2I( 1, 0 ) ) );
|
||||
pts[3] = aSeg.IntersectLines( SEG( nearest + VECTOR2I( 0, -1 ), nearest + VECTOR2I( 0, 1 ) ) );
|
||||
|
||||
int min_d = std::numeric_limits<int>::max();
|
||||
|
||||
for( int i = 0; i < 4; i++ )
|
||||
{
|
||||
if( pts[i] && aSeg.Contains( *pts[i] ) )
|
||||
{
|
||||
int d = (*pts[i] - aPoint).EuclideanNorm();
|
||||
|
||||
if( d < min_d )
|
||||
{
|
||||
min_d = d;
|
||||
nearest = *pts[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nearest;
|
||||
}
|
||||
|
||||
VECTOR2I EE_GRID_HELPER::BestDragOrigin( const VECTOR2I &aMousePos, std::vector<SCH_ITEM*>& aItems )
|
||||
{
|
||||
clearAnchors();
|
||||
|
||||
for( SCH_ITEM* item : aItems )
|
||||
computeAnchors( item, aMousePos, true );
|
||||
|
||||
double worldScale = m_toolMgr->GetView()->GetGAL()->GetWorldScale();
|
||||
double lineSnapMinCornerDistance = 50.0 / worldScale;
|
||||
|
||||
ANCHOR* nearestOutline = nearestAnchor( aMousePos, OUTLINE, LSET::AllLayersMask() );
|
||||
ANCHOR* nearestCorner = nearestAnchor( aMousePos, CORNER, LSET::AllLayersMask() );
|
||||
ANCHOR* nearestOrigin = nearestAnchor( aMousePos, ORIGIN, LSET::AllLayersMask() );
|
||||
ANCHOR* best = NULL;
|
||||
double minDist = std::numeric_limits<double>::max();
|
||||
|
||||
if( nearestOrigin )
|
||||
{
|
||||
minDist = nearestOrigin->Distance( aMousePos );
|
||||
best = nearestOrigin;
|
||||
}
|
||||
|
||||
if( nearestCorner )
|
||||
{
|
||||
double dist = nearestCorner->Distance( aMousePos );
|
||||
|
||||
if( dist < minDist )
|
||||
{
|
||||
minDist = dist;
|
||||
best = nearestCorner;
|
||||
}
|
||||
}
|
||||
|
||||
if( nearestOutline )
|
||||
{
|
||||
double dist = nearestOutline->Distance( aMousePos );
|
||||
|
||||
if( minDist > lineSnapMinCornerDistance && dist < minDist )
|
||||
best = nearestOutline;
|
||||
}
|
||||
|
||||
return best ? best->pos : aMousePos;
|
||||
}
|
||||
|
||||
|
||||
std::set<SCH_ITEM*> EE_GRID_HELPER::queryVisible( const BOX2I& aArea,
|
||||
const std::vector<SCH_ITEM*>& aSkip ) const
|
||||
{
|
||||
std::set<SCH_ITEM*> items;
|
||||
std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> selectedItems;
|
||||
|
||||
KIGFX::VIEW* view = m_toolMgr->GetView();
|
||||
|
||||
view->Query( aArea, selectedItems );
|
||||
|
||||
for( const KIGFX::VIEW::LAYER_ITEM_PAIR& it : selectedItems )
|
||||
{
|
||||
SCH_ITEM* item = static_cast<SCH_ITEM*>( it.first );
|
||||
|
||||
// The item must be visible and on an active layer
|
||||
if( view->IsVisible( item )
|
||||
&& item->ViewGetLOD( it.second, view ) < view->GetScale() )
|
||||
{
|
||||
items.insert ( item );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for( SCH_ITEM* skipItem : aSkip )
|
||||
items.erase( skipItem );
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
|
||||
VECTOR2I EE_GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, SCH_ITEM* aDraggedItem )
|
||||
{
|
||||
return BestSnapAnchor( aOrigin, LSET::AllLayersMask(), { aDraggedItem } );
|
||||
}
|
||||
|
||||
|
||||
VECTOR2I EE_GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, const LSET& aLayers,
|
||||
const std::vector<SCH_ITEM*>& aSkip )
|
||||
{
|
||||
double worldScale = m_toolMgr->GetView()->GetGAL()->GetWorldScale();
|
||||
int snapRange = (int) ( m_snapSize / worldScale );
|
||||
|
||||
BOX2I bb( VECTOR2I( aOrigin.x - snapRange / 2, aOrigin.y - snapRange / 2 ),
|
||||
VECTOR2I( snapRange, snapRange ) );
|
||||
|
||||
clearAnchors();
|
||||
|
||||
for( SCH_ITEM* item : queryVisible( bb, aSkip ) )
|
||||
computeAnchors( item, aOrigin );
|
||||
|
||||
ANCHOR* nearest = nearestAnchor( aOrigin, SNAPPABLE, aLayers );
|
||||
VECTOR2I nearestGrid = Align( aOrigin );
|
||||
|
||||
if( nearest && m_enableSnap )
|
||||
{
|
||||
double snapDist = nearest->Distance( aOrigin );
|
||||
|
||||
if( snapDist <= snapRange )
|
||||
{
|
||||
m_viewSnapPoint.SetPosition( wxPoint( nearest->pos ) );
|
||||
m_viewSnapLine.SetPosition( wxPoint( nearest->pos ) );
|
||||
m_toolMgr->GetView()->SetVisible( &m_viewSnapLine, false );
|
||||
|
||||
if( m_toolMgr->GetView()->IsVisible( &m_viewSnapPoint ) )
|
||||
m_toolMgr->GetView()->Update( &m_viewSnapPoint, KIGFX::GEOMETRY);
|
||||
else
|
||||
m_toolMgr->GetView()->SetVisible( &m_viewSnapPoint, true );
|
||||
|
||||
m_snapItem = nearest;
|
||||
return nearest->pos;
|
||||
}
|
||||
}
|
||||
|
||||
if( m_snapItem && m_enableSnapLine && m_enableSnap )
|
||||
{
|
||||
bool snapLine = false;
|
||||
|
||||
if( std::abs( m_viewSnapLine.GetPosition().x - aOrigin.x ) < snapRange )
|
||||
{
|
||||
nearestGrid.x = m_viewSnapLine.GetPosition().x;
|
||||
snapLine = true;
|
||||
}
|
||||
|
||||
if( std::abs( m_viewSnapLine.GetPosition().y - aOrigin.y ) < snapRange )
|
||||
{
|
||||
nearestGrid.y = m_viewSnapLine.GetPosition().y;
|
||||
snapLine = true;
|
||||
}
|
||||
|
||||
if( snapLine && m_skipPoint != VECTOR2I( m_viewSnapLine.GetPosition() ) )
|
||||
{
|
||||
m_viewSnapLine.SetEndPosition( nearestGrid );
|
||||
m_toolMgr->GetView()->SetVisible( &m_viewSnapPoint, false );
|
||||
|
||||
if( m_toolMgr->GetView()->IsVisible( &m_viewSnapLine ) )
|
||||
m_toolMgr->GetView()->Update( &m_viewSnapLine, KIGFX::GEOMETRY );
|
||||
else
|
||||
m_toolMgr->GetView()->SetVisible( &m_viewSnapLine, true );
|
||||
|
||||
return nearestGrid;
|
||||
}
|
||||
}
|
||||
|
||||
m_snapItem = nullptr;
|
||||
m_toolMgr->GetView()->SetVisible( &m_viewSnapPoint, false );
|
||||
m_toolMgr->GetView()->SetVisible( &m_viewSnapLine, false );
|
||||
return nearestGrid;
|
||||
}
|
||||
|
||||
|
||||
SCH_ITEM* EE_GRID_HELPER::GetSnapped() const
|
||||
{
|
||||
if( !m_snapItem )
|
||||
return nullptr;
|
||||
|
||||
return m_snapItem->item;
|
||||
}
|
||||
|
||||
|
||||
void EE_GRID_HELPER::computeAnchors( SCH_ITEM* aItem, const VECTOR2I& aRefPos, bool aFrom )
|
||||
{
|
||||
switch( aItem->Type() )
|
||||
{
|
||||
case SCH_COMPONENT_T:
|
||||
case SCH_SHEET_T:
|
||||
addAnchor( aItem->GetPosition(), ORIGIN, aItem );
|
||||
KI_FALLTHROUGH;
|
||||
case SCH_JUNCTION_T:
|
||||
case SCH_NO_CONNECT_T:
|
||||
case SCH_LINE_T:
|
||||
case SCH_GLOBAL_LABEL_T:
|
||||
case SCH_HIER_LABEL_T:
|
||||
case SCH_LABEL_T:
|
||||
case SCH_BUS_WIRE_ENTRY_T:
|
||||
{
|
||||
std::vector<wxPoint> pts = aItem->GetConnectionPoints();
|
||||
|
||||
for( auto pt : pts )
|
||||
addAnchor( VECTOR2I( pt ), SNAPPABLE | CORNER, aItem );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
EE_GRID_HELPER::ANCHOR* EE_GRID_HELPER::nearestAnchor( const VECTOR2I& aPos, int aFlags,
|
||||
LSET aMatchLayers )
|
||||
{
|
||||
double minDist = std::numeric_limits<double>::max();
|
||||
ANCHOR* best = NULL;
|
||||
|
||||
for( ANCHOR& a : m_anchors )
|
||||
{
|
||||
if( ( aFlags & a.flags ) != aFlags )
|
||||
continue;
|
||||
|
||||
double dist = a.Distance( aPos );
|
||||
|
||||
if( dist < minDist )
|
||||
{
|
||||
minDist = dist;
|
||||
best = &a;
|
||||
}
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
160
eeschema/tools/ee_grid_helper.h
Normal file
160
eeschema/tools/ee_grid_helper.h
Normal file
@ -0,0 +1,160 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2014 CERN
|
||||
* Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* @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 2
|
||||
* 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, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef __GRID_HELPER_H
|
||||
#define __GRID_HELPER_H
|
||||
|
||||
#include <vector>
|
||||
#include <math/vector2d.h>
|
||||
#include <origin_viewitem.h>
|
||||
|
||||
class LSET;
|
||||
class SCH_ITEM;
|
||||
class SEG;
|
||||
|
||||
class EE_GRID_HELPER {
|
||||
public:
|
||||
|
||||
EE_GRID_HELPER( TOOL_MANAGER* aToolMgr );
|
||||
~EE_GRID_HELPER();
|
||||
|
||||
VECTOR2I GetGrid() const;
|
||||
VECTOR2I GetOrigin() const;
|
||||
|
||||
/**
|
||||
* Function GetSnapped
|
||||
* If the EE_GRID_HELPER has highlighted a snap point (target shown), this function
|
||||
* will return a pointer to the item to which it snapped.
|
||||
*
|
||||
* @return NULL if not snapped. Pointer to snapped item otherwise
|
||||
*/
|
||||
SCH_ITEM* GetSnapped() const;
|
||||
|
||||
void SetAuxAxes( bool aEnable, const VECTOR2I& aOrigin = VECTOR2I( 0, 0 ) );
|
||||
|
||||
VECTOR2I Align( const VECTOR2I& aPoint ) const;
|
||||
|
||||
VECTOR2I AlignToWire( const VECTOR2I& aPoint, const SEG& aSeg );
|
||||
|
||||
VECTOR2I BestDragOrigin( const VECTOR2I& aMousePos, std::vector<SCH_ITEM*>& aItem );
|
||||
|
||||
VECTOR2I BestSnapAnchor( const VECTOR2I& aOrigin, SCH_ITEM* aDraggedItem );
|
||||
VECTOR2I BestSnapAnchor( const VECTOR2I& aOrigin, const LSET& aLayers,
|
||||
const std::vector<SCH_ITEM*>& aSkip = {} );
|
||||
|
||||
void SetSkipPoint( const VECTOR2I& aPoint )
|
||||
{
|
||||
m_skipPoint = aPoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* We clear the skip point by setting it to an unreachable position, thereby preventing matching
|
||||
*/
|
||||
void ClearSkipPoint()
|
||||
{
|
||||
m_skipPoint = VECTOR2I( std::numeric_limits<int>::min(), std::numeric_limits<int>::min() );
|
||||
}
|
||||
|
||||
void SetSnap( bool aSnap )
|
||||
{
|
||||
m_enableSnap = aSnap;
|
||||
}
|
||||
|
||||
void SetSnapLine( bool aSnap )
|
||||
{
|
||||
m_enableSnapLine = aSnap;
|
||||
}
|
||||
|
||||
private:
|
||||
enum ANCHOR_FLAGS {
|
||||
CORNER = 1,
|
||||
OUTLINE = 2,
|
||||
SNAPPABLE = 4,
|
||||
ORIGIN = 8,
|
||||
VERTICAL = 16,
|
||||
HORIZONTAL = 32
|
||||
};
|
||||
|
||||
struct ANCHOR
|
||||
{
|
||||
ANCHOR( VECTOR2I aPos, int aFlags = CORNER | SNAPPABLE, SCH_ITEM* aItem = NULL ) :
|
||||
pos( aPos ),
|
||||
flags( aFlags ),
|
||||
item( aItem )
|
||||
{ };
|
||||
|
||||
VECTOR2I pos;
|
||||
int flags;
|
||||
SCH_ITEM* item;
|
||||
|
||||
double Distance( const VECTOR2I& aP ) const
|
||||
{
|
||||
return ( aP - pos ).EuclideanNorm();
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<ANCHOR> m_anchors;
|
||||
|
||||
std::set<SCH_ITEM*> queryVisible( const BOX2I& aArea,
|
||||
const std::vector<SCH_ITEM*>& aSkip ) const;
|
||||
|
||||
void addAnchor( const VECTOR2I& aPos, int aFlags, SCH_ITEM* aItem )
|
||||
{
|
||||
m_anchors.emplace_back( ANCHOR( aPos, aFlags, aItem ) );
|
||||
}
|
||||
|
||||
ANCHOR* nearestAnchor( const VECTOR2I& aPos, int aFlags, LSET aMatchLayers );
|
||||
|
||||
/**
|
||||
* computeAnchors inserts the local anchor points in to the grid helper for the specified
|
||||
* schematic item, given the reference point and the direction of use for the point.
|
||||
*
|
||||
* @param aItem The schematic item for which to compute the anchors
|
||||
* @param aRefPos The point for which to compute the anchors (if used by the component)
|
||||
* @param aFrom Is this for an anchor that is designating a source point (aFrom=true) or not
|
||||
*/
|
||||
void computeAnchors( SCH_ITEM* aItem, const VECTOR2I& aRefPos, bool aFrom = false );
|
||||
|
||||
void clearAnchors()
|
||||
{
|
||||
m_anchors.clear();
|
||||
}
|
||||
|
||||
TOOL_MANAGER* m_toolMgr;
|
||||
OPT<VECTOR2I> m_auxAxis;
|
||||
|
||||
bool m_enableSnap; // If true, allow snapping to other items on the layers
|
||||
bool m_enableSnapLine; // If true, allow drawing lines from snap points
|
||||
int m_snapSize; // Sets the radius in screen units for snapping to items
|
||||
ANCHOR* m_snapItem; // Pointer to the currently snapped item in m_anchors
|
||||
// (NULL if not snapped)
|
||||
VECTOR2I m_skipPoint; // When drawing a line, we avoid snapping to the source point
|
||||
|
||||
KIGFX::ORIGIN_VIEWITEM m_viewSnapPoint;
|
||||
KIGFX::ORIGIN_VIEWITEM m_viewSnapLine;
|
||||
KIGFX::ORIGIN_VIEWITEM m_viewAxis;
|
||||
};
|
||||
|
||||
#endif
|
@ -397,7 +397,7 @@ int LIB_DRAWING_TOOLS::DrawShape( const TOOL_EVENT& aEvent )
|
||||
int LIB_DRAWING_TOOLS::PlaceAnchor( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
getViewControls()->ShowCursor( true );
|
||||
getViewControls()->SetSnapping( true );
|
||||
getViewControls()->SetGridSnapping( true );
|
||||
|
||||
std::string tool = aEvent.GetCommandStr().get();
|
||||
m_frame->PushTool( tool );
|
||||
|
@ -70,7 +70,7 @@ void LIB_MOVE_TOOL::Reset( RESET_REASON aReason )
|
||||
int LIB_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
KIGFX::VIEW_CONTROLS* controls = getViewControls();
|
||||
controls->SetSnapping( true );
|
||||
controls->SetGridSnapping( true );
|
||||
|
||||
m_anchorPos = { 0, 0 };
|
||||
|
||||
@ -103,7 +103,7 @@ int LIB_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
|
||||
do
|
||||
{
|
||||
m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_ARROW );
|
||||
controls->SetSnapping( !evt->Modifier( MD_ALT ) );
|
||||
controls->SetGridSnapping( !evt->Modifier( MD_ALT ) );
|
||||
|
||||
if( evt->IsAction( &EE_ACTIONS::move ) || evt->IsMotion() || evt->IsDrag( BUT_LEFT )
|
||||
|| evt->IsAction( &ACTIONS::refreshPreview )
|
||||
@ -271,7 +271,7 @@ int LIB_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
|
||||
|
||||
controls->ForceCursorPosition( false );
|
||||
controls->ShowCursor( false );
|
||||
controls->SetSnapping( false );
|
||||
controls->SetGridSnapping( false );
|
||||
controls->SetAutoPan( false );
|
||||
|
||||
if( !chain_commands )
|
||||
|
@ -449,7 +449,7 @@ int SCH_DRAWING_TOOLS::SingleClickPlace( const TOOL_EVENT& aEvent )
|
||||
|
||||
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
|
||||
getViewControls()->ShowCursor( true );
|
||||
getViewControls()->SetSnapping( true );
|
||||
getViewControls()->SetGridSnapping( true );
|
||||
|
||||
SCH_ITEM* previewItem;
|
||||
switch( type )
|
||||
|
@ -63,6 +63,7 @@
|
||||
#include <schematic.h>
|
||||
|
||||
#include <ee_actions.h>
|
||||
#include <ee_grid_helper.h>
|
||||
#include <ee_point_editor.h>
|
||||
#include <ee_selection.h>
|
||||
#include <ee_selection_tool.h>
|
||||
@ -462,9 +463,14 @@ int SCH_LINE_WIRE_BUS_TOOL::doDrawSegments( const std::string& aTool, int aType
|
||||
SCH_SCREEN* screen = m_frame->GetScreen();
|
||||
EE_POINT_EDITOR* pointEditor = m_toolMgr->GetTool<EE_POINT_EDITOR>();
|
||||
SCH_LINE* segment = nullptr;
|
||||
EE_GRID_HELPER grid( m_toolMgr );
|
||||
|
||||
KIGFX::VIEW_CONTROLS* controls = getViewControls();
|
||||
|
||||
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
|
||||
getViewControls()->ShowCursor( true );
|
||||
controls->ShowCursor( true );
|
||||
controls->SetGridSnapping( m_frame->IsGridVisible() );
|
||||
|
||||
|
||||
Activate();
|
||||
|
||||
@ -482,7 +488,12 @@ int SCH_LINE_WIRE_BUS_TOOL::doDrawSegments( const std::string& aTool, int aType
|
||||
if( !pointEditor->HasPoint() ) // Set wxCursor shape when starting the tool
|
||||
m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_PENCIL );
|
||||
|
||||
wxPoint cursorPos = (wxPoint) getViewControls()->GetCursorPosition( !evt->Modifier( MD_ALT ) );
|
||||
grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
|
||||
controls->SetGridSnapping( m_frame->IsGridVisible() );
|
||||
wxPoint cursorPos = wxPoint( grid.BestSnapAnchor(
|
||||
evt->IsPrime() ? evt->Position() : controls->GetMousePosition(), nullptr ) );
|
||||
controls->ForceCursorPosition( true, cursorPos );
|
||||
|
||||
bool forceHV = m_frame->eeconfig()->m_Drawing.hv_lines_only;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
@ -692,8 +703,8 @@ int SCH_LINE_WIRE_BUS_TOOL::doDrawSegments( const std::string& aTool, int aType
|
||||
evt->SetPassEvent();
|
||||
|
||||
// Enable autopanning and cursor capture only when there is a segment to be placed
|
||||
getViewControls()->SetAutoPan( segment != nullptr );
|
||||
getViewControls()->CaptureCursor( segment != nullptr );
|
||||
controls->SetAutoPan( segment != nullptr );
|
||||
controls->CaptureCursor( segment != nullptr );
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -109,7 +109,7 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
|
||||
|
||||
EESCHEMA_SETTINGS* cfg = Pgm().GetSettingsManager().GetAppSettings<EESCHEMA_SETTINGS>();
|
||||
KIGFX::VIEW_CONTROLS* controls = getViewControls();
|
||||
controls->SetSnapping( true );
|
||||
controls->SetGridSnapping( true );
|
||||
|
||||
m_anchorPos.reset();
|
||||
|
||||
@ -171,7 +171,7 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
|
||||
do
|
||||
{
|
||||
m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_ARROW );
|
||||
controls->SetSnapping( !evt->Modifier( MD_ALT ) );
|
||||
controls->SetGridSnapping( !evt->Modifier( MD_ALT ) );
|
||||
|
||||
if( evt->IsAction( &EE_ACTIONS::moveActivate ) || evt->IsAction( &EE_ACTIONS::restartMove )
|
||||
|| evt->IsAction( &EE_ACTIONS::move ) || evt->IsAction( &EE_ACTIONS::drag )
|
||||
@ -428,7 +428,7 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
|
||||
|
||||
controls->ForceCursorPosition( false );
|
||||
controls->ShowCursor( false );
|
||||
controls->SetSnapping( false );
|
||||
controls->SetGridSnapping( false );
|
||||
controls->SetAutoPan( false );
|
||||
|
||||
if( !chain_commands )
|
||||
|
@ -194,8 +194,8 @@ public:
|
||||
* @return const wxPoint& - The position of this object.
|
||||
* This function exists mainly to satisfy the virtual GetPosition() in parent class
|
||||
*/
|
||||
wxPoint GetPosition() const override { return m_Start; }
|
||||
void SetPosition( const wxPoint& aPos ) { m_Start = aPos; }
|
||||
wxPoint GetPosition() const override { return m_Start; }
|
||||
void SetPosition( const wxPoint& aPos ) override { m_Start = aPos; }
|
||||
|
||||
/**
|
||||
* Function GetABPosition
|
||||
|
@ -571,7 +571,7 @@ int GERBVIEW_SELECTION_TOOL::MeasureTool( const TOOL_EVENT& aEvent )
|
||||
bool originSet = false;
|
||||
|
||||
controls.ShowCursor( true );
|
||||
controls.SetSnapping( true );
|
||||
controls.SetGridSnapping( true );
|
||||
|
||||
while( TOOL_EVENT* evt = Wait() )
|
||||
{
|
||||
|
@ -335,6 +335,7 @@ public:
|
||||
virtual const EDA_RECT GetBoundingBox() const;
|
||||
|
||||
virtual wxPoint GetPosition() const { return wxPoint(); }
|
||||
virtual void SetPosition( const wxPoint& aPos ) {};
|
||||
|
||||
/**
|
||||
* Function GetFocusPosition
|
||||
|
@ -144,8 +144,6 @@ public:
|
||||
*/
|
||||
virtual wxPoint GetCenter() const { return GetPosition(); }
|
||||
|
||||
virtual void SetPosition( const wxPoint& aPos ) = 0;
|
||||
|
||||
void SetX( int aX )
|
||||
{
|
||||
wxPoint p( aX, GetY() );
|
||||
|
@ -28,12 +28,9 @@
|
||||
|
||||
#include <math/box2.h>
|
||||
#include <view/view.h>
|
||||
#include <class_board_item.h>
|
||||
#include <layers_id_colors_and_visibility.h>
|
||||
#include <gal/color4d.h>
|
||||
|
||||
class PCB_BASE_FRAME;
|
||||
|
||||
/**
|
||||
* ORIGIN_VIEWITEM
|
||||
*
|
||||
@ -41,7 +38,7 @@ class PCB_BASE_FRAME;
|
||||
*/
|
||||
namespace KIGFX {
|
||||
|
||||
class ORIGIN_VIEWITEM : public BOARD_ITEM
|
||||
class ORIGIN_VIEWITEM : public EDA_ITEM
|
||||
{
|
||||
public:
|
||||
///> Marker symbol styles
|
||||
@ -93,17 +90,12 @@ public:
|
||||
m_drawAtZero = aDrawFlag;
|
||||
}
|
||||
|
||||
inline void SetPosition( const VECTOR2D& aPosition )
|
||||
{
|
||||
m_position = aPosition;
|
||||
}
|
||||
|
||||
inline void SetPosition( const wxPoint& aPosition ) override
|
||||
void SetPosition( const wxPoint& aPosition ) override
|
||||
{
|
||||
m_position = VECTOR2D( aPosition );
|
||||
}
|
||||
|
||||
inline wxPoint GetPosition() const override
|
||||
wxPoint GetPosition() const override
|
||||
{
|
||||
return wxPoint( m_position.x, m_position.y );
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user