diff --git a/common/origin_viewitem.cpp b/common/origin_viewitem.cpp index 20150ac619..956bada814 100644 --- a/common/origin_viewitem.cpp +++ b/common/origin_viewitem.cpp @@ -2,6 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2015 CERN + * Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors. * @author Maciej Suminski * * This program is free software; you can redistribute it and/or @@ -23,6 +24,7 @@ */ #include +#include #include #include @@ -95,6 +97,40 @@ void ORIGIN_VIEWITEM::ViewDraw( int, VIEW* aView ) const m_position + VECTOR2D( 0, scaledSize.y ) ); break; + case DASH_LINE: + { + gal->DrawCircle( m_position, scaledSize.x / 4 ); + + VECTOR2D start( m_position ); + VECTOR2D end( m_end ); + EDA_RECT clip( wxPoint( start ), wxSize( end.x - start.x, end.y - start.y ) ); + clip.Normalize(); + + double theta = atan2( end.y - start.y, end.x - start.x ); + std::array strokes( { DASH_MARK_LEN( 1 ), DASH_GAP_LEN( 1 ) } ); + + for( size_t i = 0; i < 10000; ++i ) + { + VECTOR2D next( start.x + strokes[ i % 2 ] * cos( theta ), + start.y + strokes[ i % 2 ] * sin( theta ) ); + + // Drawing each segment can be done rounded to ints. + wxPoint segStart( KiROUND( start.x ), KiROUND( start.y ) ); + wxPoint segEnd( KiROUND( next.x ), KiROUND( next.y ) ); + + if( ClipLine( &clip, segStart.x, segStart.y, segEnd.x, segEnd.y ) ) + break; + else if( i % 2 == 0 ) + gal->DrawLine( segStart, segEnd ); + + start = next; + } + + gal->DrawLine( m_position, m_end ); + gal->DrawCircle( m_end, scaledSize.x / 4 ); + break; + } + case X: case CIRCLE_X: gal->DrawLine( m_position - scaledSize, m_position + scaledSize ); diff --git a/include/origin_viewitem.h b/include/origin_viewitem.h index c38a89929b..37ec74687f 100644 --- a/include/origin_viewitem.h +++ b/include/origin_viewitem.h @@ -2,6 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2013-2016 CERN + * Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors. * @author Maciej Suminski * * This program is free software; you can redistribute it and/or @@ -44,7 +45,10 @@ class ORIGIN_VIEWITEM : public BOARD_ITEM { public: ///> Marker symbol styles - enum MARKER_STYLE { NO_GRAPHIC, CROSS, X, DOT, CIRCLE_CROSS, CIRCLE_X, CIRCLE_DOT }; + enum MARKER_STYLE + { + NO_GRAPHIC, CROSS, X, DOT, CIRCLE_CROSS, CIRCLE_X, CIRCLE_DOT, DASH_LINE + }; ORIGIN_VIEWITEM( const COLOR4D& aColor = COLOR4D( 1.0, 1.0, 1.0, 1.0 ), MARKER_STYLE aStyle = CIRCLE_X, int aSize = 16, @@ -109,6 +113,21 @@ public: return wxPoint( m_position.x, m_position.y ); } + inline void SetEndPosition( const VECTOR2D& aPosition ) + { + m_end = aPosition; + } + + inline void SetEndPosition( const wxPoint& aPosition ) + { + m_end = VECTOR2D( aPosition ); + } + + inline const wxPoint GetEndPosition() const + { + return wxPoint( m_end.x, m_end.y ); + } + inline void SetSize( int aSize ) { m_size = aSize; @@ -143,6 +162,9 @@ protected: ///> Marker coordinates. VECTOR2D m_position; + ///> Marker end position for markers that stretch between points + VECTOR2D m_end; + ///> Marker size (in pixels). int m_size; diff --git a/pcbnew/tools/drawing_tool.cpp b/pcbnew/tools/drawing_tool.cpp index 54e487b5a0..cfd3e15409 100644 --- a/pcbnew/tools/drawing_tool.cpp +++ b/pcbnew/tools/drawing_tool.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2014-2017 CERN - * Copyright (C) 2018-2019 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2018-2020 KiCad Developers, see AUTHORS.txt for contributors. * @author Maciej Suminski * * This program is free software; you can redistribute it and/or @@ -1050,6 +1050,7 @@ bool DRAWING_TOOL::drawSegment( const std::string& aTool, int aShape, DRAWSEGMEN aGraphic->SetStart( (wxPoint) cursorPos ); aGraphic->SetEnd( (wxPoint) cursorPos ); aGraphic->SetLayer( getDrawingLayer() ); + grid.SetSkipPoint( cursorPos ); if( !isLocalOriginSet ) m_frame->GetScreen()->m_LocalOrigin = cursorPos; @@ -1463,6 +1464,7 @@ int DRAWING_TOOL::DrawZone( const TOOL_EVENT& aEvent ) auto cleanup = [&] () { polyGeomMgr.Reset(); started = false; + grid.ClearSkipPoint(); m_controls->SetAutoPan( false ); m_controls->CaptureCursor( false ); }; diff --git a/pcbnew/tools/grid_helper.cpp b/pcbnew/tools/grid_helper.cpp index 4e1fdf6df7..62509798df 100644 --- a/pcbnew/tools/grid_helper.cpp +++ b/pcbnew/tools/grid_helper.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2014 CERN - * Copyright (C) 2018-2019 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2018-2020 KiCad Developers, see AUTHORS.txt for contributors. * @author Tomasz Wlostowski * * This program is free software; you can redistribute it and/or @@ -51,6 +51,7 @@ GRID_HELPER::GRID_HELPER( PCB_BASE_FRAME* aFrame ) : { m_enableSnap = true; m_enableGrid = true; + m_enableSnapLine = true; m_snapSize = 100; m_snapItem = nullptr; KIGFX::VIEW* view = m_frame->GetCanvas()->GetView(); @@ -67,6 +68,12 @@ GRID_HELPER::GRID_HELPER( PCB_BASE_FRAME* aFrame ) : 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 ); } @@ -284,6 +291,8 @@ VECTOR2I GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, const LSET& aLaye if( !m_enableGrid || snapDist <= gridDist ) { m_viewSnapPoint.SetPosition( nearest->pos ); + m_viewSnapLine.SetPosition( nearest->pos ); + m_frame->GetCanvas()->GetView()->SetVisible( &m_viewSnapLine, false ); if( m_frame->GetCanvas()->GetView()->IsVisible( &m_viewSnapPoint ) ) m_frame->GetCanvas()->GetView()->Update( &m_viewSnapPoint, KIGFX::GEOMETRY); @@ -295,8 +304,39 @@ VECTOR2I GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, const LSET& aLaye } } + if( m_snapItem && m_enableSnapLine ) + { + bool snapLine = false; + + if( std::abs( m_viewSnapLine.GetPosition().x - aOrigin.x ) < GetGrid().x ) + { + nearestGrid.x = m_viewSnapLine.GetPosition().x; + snapLine = true; + } + + if( std::abs( m_viewSnapLine.GetPosition().y - aOrigin.y ) < GetGrid().y ) + { + nearestGrid.y = m_viewSnapLine.GetPosition().y; + snapLine = true; + } + + if( snapLine && m_skipPoint != VECTOR2I( m_viewSnapLine.GetPosition() ) ) + { + m_viewSnapLine.SetEndPosition( nearestGrid ); + m_frame->GetCanvas()->GetView()->SetVisible( &m_viewSnapPoint, false ); + + if( m_frame->GetCanvas()->GetView()->IsVisible( &m_viewSnapLine ) ) + m_frame->GetCanvas()->GetView()->Update( &m_viewSnapLine, KIGFX::GEOMETRY ); + else + m_frame->GetCanvas()->GetView()->SetVisible( &m_viewSnapLine, true ); + + return nearestGrid; + } + } + m_snapItem = nullptr; m_frame->GetCanvas()->GetView()->SetVisible( &m_viewSnapPoint, false ); + m_frame->GetCanvas()->GetView()->SetVisible( &m_viewSnapLine, false ); return nearestGrid; } diff --git a/pcbnew/tools/grid_helper.h b/pcbnew/tools/grid_helper.h index 8510198976..afc212bf97 100644 --- a/pcbnew/tools/grid_helper.h +++ b/pcbnew/tools/grid_helper.h @@ -2,6 +2,7 @@ * 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 * * This program is free software; you can redistribute it and/or @@ -63,11 +64,29 @@ public: VECTOR2I BestSnapAnchor( const VECTOR2I& aOrigin, const LSET& aLayers, const std::vector& 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::min(), std::numeric_limits::min() ); + } + void SetSnap( bool aSnap ) { m_enableSnap = aSnap; } + void SetSnapLine( bool aSnap ) + { + m_enableSnapLine = aSnap; + } + void SetUseGrid( bool aGrid = true ) { m_enableGrid = aGrid; @@ -127,14 +146,17 @@ private: } PCB_BASE_FRAME* m_frame; - OPT m_auxAxis; + OPT m_auxAxis; - bool m_enableSnap; ///< If true, allow snapping to other items on the layers - bool m_enableGrid; ///< If true, allow snapping to grid - 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) + bool m_enableSnap; ///< If true, allow snapping to other items on the layers + bool m_enableGrid; ///< If true, allow snapping to grid + 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; };