pcbnew: Graphic lines snap as single segments

Graphic lines and polygons are drawn to fit specific areas for which it
is helpful to have the endpoint controlled by the cursor even when
constraining the angle.

Fixes: lp:1805502
* https://bugs.launchpad.net/kicad/+bug/1805502
This commit is contained in:
Seth Hillbrand 2018-12-07 22:07:53 -08:00
parent c7998cfc23
commit 4fc81bb923
3 changed files with 21 additions and 79 deletions

View File

@ -23,7 +23,7 @@
#include <preview_items/polygon_geom_manager.h> #include <preview_items/polygon_geom_manager.h>
#include <geometry/direction45.h> #include <geometry/geometry_utils.h>
POLYGON_GEOM_MANAGER::POLYGON_GEOM_MANAGER( CLIENT& aClient ): POLYGON_GEOM_MANAGER::POLYGON_GEOM_MANAGER( CLIENT& aClient ):
@ -144,24 +144,16 @@ void POLYGON_GEOM_MANAGER::updateLeaderPoints( const VECTOR2I& aEndPoint, LEADER
{ {
wxCHECK( m_lockedPoints.PointCount() > 0, /*void*/ ); wxCHECK( m_lockedPoints.PointCount() > 0, /*void*/ );
const VECTOR2I& lastPt = m_lockedPoints.CLastPoint(); const VECTOR2I& lastPt = m_lockedPoints.CLastPoint();
auto newEnd = VECTOR2I( lastPt );
if( m_leaderMode == LEADER_MODE::DEG45 || aModifier == LEADER_MODE::DEG45 ) if( m_leaderMode == LEADER_MODE::DEG45 || aModifier == LEADER_MODE::DEG45 )
{ {
const VECTOR2I lineVector( aEndPoint - lastPt );
// get a restricted 45/H/V line from the last fixed point to the cursor // get a restricted 45/H/V line from the last fixed point to the cursor
DIRECTION_45 direction( lastPt - aEndPoint ); newEnd += GetVectorSnapped45( lineVector );
m_leaderPts = direction.BuildInitialTrace( lastPt, aEndPoint );
// Can also add chain back to start, but this rearely produces
// usable result
//SHAPE_LINE_CHAIN newChain;
//DIRECTION_45 directionToStart( aEndPoint - m_lockedPoints.front() );
//newChain.Append( directionToStart.BuildInitialTrace( aEndPoint, m_lockedPoints.front() ) );
}
else
{
// direct segment
m_leaderPts = SHAPE_LINE_CHAIN( lastPt, aEndPoint );
} }
// direct segment
m_leaderPts = SHAPE_LINE_CHAIN( lastPt, newEnd );
m_client.OnGeometryChange( *this ); m_client.OnGeometryChange( *this );
} }

View File

@ -40,7 +40,6 @@
#include <view/view.h> #include <view/view.h>
#include <gal/graphics_abstraction_layer.h> #include <gal/graphics_abstraction_layer.h>
#include <tool/tool_manager.h> #include <tool/tool_manager.h>
#include <geometry/direction45.h>
#include <geometry/geometry_utils.h> #include <geometry/geometry_utils.h>
#include <ratsnest_data.h> #include <ratsnest_data.h>
#include <board_commit.h> #include <board_commit.h>
@ -933,8 +932,6 @@ bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic,
{ {
// Only two shapes are currently supported // Only two shapes are currently supported
assert( aShape == S_SEGMENT || aShape == S_CIRCLE ); assert( aShape == S_SEGMENT || aShape == S_CIRCLE );
DRAWSEGMENT line45;
GRID_HELPER grid( m_frame ); GRID_HELPER grid( m_frame );
m_lineWidth = getSegmentWidth( getDrawingLayer() ); m_lineWidth = getSegmentWidth( getDrawingLayer() );
@ -966,9 +963,6 @@ bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic,
m_controls->ForceCursorPosition( true, cursorPos ); m_controls->ForceCursorPosition( true, cursorPos );
aGraphic->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) ); aGraphic->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
if( aShape == S_SEGMENT )
line45 = *aGraphic; // used only for direction 45 mode with lines
preview.Add( aGraphic ); preview.Add( aGraphic );
m_controls->SetAutoPan( true ); m_controls->SetAutoPan( true );
m_controls->CaptureCursor( true ); m_controls->CaptureCursor( true );
@ -997,12 +991,15 @@ bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic,
if( direction45 ) if( direction45 )
{ {
preview.Add( &line45 ); const VECTOR2I lineVector( cursorPos - VECTOR2I( aGraphic->GetStart() ) );
make45DegLine( aGraphic, &line45, cursorPos );
// get a restricted 45/H/V line from the last fixed point to the cursor
auto newEnd = GetVectorSnapped45( lineVector );
aGraphic->SetEnd( aGraphic->GetStart() + wxPoint( newEnd.x, newEnd.y ) );
m_controls->ForceCursorPosition( true, VECTOR2I( aGraphic->GetEnd() ) );
} }
else else
{ {
preview.Remove( &line45 );
aGraphic->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) ); aGraphic->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
} }
@ -1048,9 +1045,6 @@ bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic,
if( !IsOCurseurSet ) if( !IsOCurseurSet )
m_frame->GetScreen()->m_O_Curseur = wxPoint( cursorPos.x, cursorPos.y ); m_frame->GetScreen()->m_O_Curseur = wxPoint( cursorPos.x, cursorPos.y );
if( aShape == S_SEGMENT )
line45 = *aGraphic; // used only for direction 45 mode with lines
preview.Add( aGraphic ); preview.Add( aGraphic );
frame()->SetMsgPanel( aGraphic ); frame()->SetMsgPanel( aGraphic );
m_controls->SetAutoPan( true ); m_controls->SetAutoPan( true );
@ -1071,26 +1065,9 @@ bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic,
{ {
BOARD_COMMIT commit( m_frame ); BOARD_COMMIT commit( m_frame );
// a clear sign that the current drawing is finished
// Now we have to add the helper line as well, unless it is zero-length
if( direction45 && line45.GetStart() != aGraphic->GetStart() )
{
DRAWSEGMENT* l = m_editModules ? new EDGE_MODULE( mod ) : new DRAWSEGMENT;
// Copy coordinates, layer, etc.
*l = line45;
// If snapping, add both paths
if( snapItem && l->GetLength() > 0.0 )
commit.Add( l->Clone() );
l->SetEnd( aGraphic->GetStart() );
commit.Add( l );
}
// If the user clicks on an existing snap point from a drawsegment // If the user clicks on an existing snap point from a drawsegment
// we finish the segment as they are likely closing a path // we finish the segment as they are likely closing a path
else if( snapItem && aGraphic->GetLength() > 0.0 ) if( snapItem && aGraphic->GetLength() > 0.0 )
{ {
DRAWSEGMENT* l = m_editModules ? new EDGE_MODULE( mod ) : new DRAWSEGMENT; DRAWSEGMENT* l = m_editModules ? new EDGE_MODULE( mod ) : new DRAWSEGMENT;
@ -1113,7 +1090,14 @@ bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic,
{ {
// 45 degree lines // 45 degree lines
if( direction45 && aShape == S_SEGMENT ) if( direction45 && aShape == S_SEGMENT )
make45DegLine( aGraphic, &line45, cursorPos ); {
const VECTOR2I lineVector( cursorPos - VECTOR2I( aGraphic->GetStart() ) );
// get a restricted 45/H/V line from the last fixed point to the cursor
auto newEnd = GetVectorSnapped45( lineVector );
aGraphic->SetEnd( aGraphic->GetStart() + wxPoint( newEnd.x, newEnd.y ) );
m_controls->ForceCursorPosition( true, VECTOR2I( aGraphic->GetEnd() ) );
}
else else
aGraphic->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) ); aGraphic->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
@ -1128,7 +1112,6 @@ bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic,
{ {
m_lineWidth += WIDTH_STEP; m_lineWidth += WIDTH_STEP;
aGraphic->SetWidth( m_lineWidth ); aGraphic->SetWidth( m_lineWidth );
line45.SetWidth( m_lineWidth );
m_view->Update( &preview ); m_view->Update( &preview );
frame()->SetMsgPanel( aGraphic ); frame()->SetMsgPanel( aGraphic );
} }
@ -1136,7 +1119,6 @@ bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic,
{ {
m_lineWidth -= WIDTH_STEP; m_lineWidth -= WIDTH_STEP;
aGraphic->SetWidth( m_lineWidth ); aGraphic->SetWidth( m_lineWidth );
line45.SetWidth( m_lineWidth );
m_view->Update( &preview ); m_view->Update( &preview );
frame()->SetMsgPanel( aGraphic ); frame()->SetMsgPanel( aGraphic );
} }
@ -1503,28 +1485,6 @@ int DRAWING_TOOL::drawZone( bool aKeepout, ZONE_MODE aMode )
} }
void DRAWING_TOOL::make45DegLine( DRAWSEGMENT* aSegment, DRAWSEGMENT* aHelper,
VECTOR2I& aPos ) const
{
VECTOR2I origin( aSegment->GetStart() );
DIRECTION_45 direction( origin - aPos );
SHAPE_LINE_CHAIN newChain = direction.BuildInitialTrace( origin, aPos );
if( newChain.PointCount() > 2 )
{
aSegment->SetEnd( wxPoint( newChain.Point( -2 ).x, newChain.Point( -2 ).y ) );
aHelper->SetStart( wxPoint( newChain.Point( -2 ).x, newChain.Point( -2 ).y ) );
aHelper->SetEnd( wxPoint( newChain.Point( -1 ).x, newChain.Point( -1 ).y ) );
}
else
{
aSegment->SetEnd( wxPoint( aPos.x, aPos.y ) );
aHelper->SetStart( wxPoint( aPos.x, aPos.y ) );
aHelper->SetEnd( wxPoint( aPos.x, aPos.y ) );
}
}
int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent ) int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
{ {
struct VIA_PLACER : public INTERACTIVE_PLACER_BASE struct VIA_PLACER : public INTERACTIVE_PLACER_BASE

View File

@ -245,16 +245,6 @@ private:
*/ */
void runPolygonEventLoop( POLYGON_GEOM_MANAGER& aPolyGeomMgr ); void runPolygonEventLoop( POLYGON_GEOM_MANAGER& aPolyGeomMgr );
/**
* Function make45DegLine()
* Forces a DRAWSEGMENT to be drawn at multiple of 45 degrees. The origin stays the same,
* the end of the aSegment is modified according to the current cursor position.
* @param aSegment is the segment that is currently drawn.
* @param aHelper is a helper line that shows the next possible segment.
* @param aPos is the position of the cursor for this event
*/
void make45DegLine( DRAWSEGMENT* aSegment, DRAWSEGMENT* aHelper, VECTOR2I& aPos ) const;
/** /**
* Function constrainDimension() * Function constrainDimension()
* Forces the dimension lime to be drawn on multiple of 45 degrees * Forces the dimension lime to be drawn on multiple of 45 degrees