Improved way of drawing 45-degree lines.

This commit is contained in:
Maciej Suminski 2014-02-17 11:33:03 +01:00
parent c1c8f54e8b
commit f82e07849b
4 changed files with 103 additions and 41 deletions

View File

@ -415,7 +415,7 @@ public:
* @param aP the point to be looked for
* @return index of the correspoinding point in the line chain or negative when not found.
*/
int Find ( const VECTOR2I& aP ) const;
int Find( const VECTOR2I& aP ) const;
/**
* Function Slice()

View File

@ -133,10 +133,7 @@ public:
*/
DIRECTION_45 Opposite() const
{
if( m_dir == UNDEFINED )
return UNDEFINED;
const Directions OppositeMap[] = { S, SW, W, NW, N, NE, E, SE };
const Directions OppositeMap[] = { S, SW, W, NW, N, NE, E, SE, UNDEFINED };
return OppositeMap[m_dir];
}

View File

@ -32,6 +32,7 @@
#include <view/view_controls.h>
#include <gal/graphics_abstraction_layer.h>
#include <tool/tool_manager.h>
#include <router/direction.h>
#include <class_board.h>
#include <class_drawsegment.h>
@ -641,12 +642,13 @@ int DRAWING_TOOL::drawSegment( int aShape, bool aContinous )
// Only two shapes are currently supported
assert( aShape == S_SEGMENT || aShape == S_CIRCLE );
DRAWSEGMENT* graphic = new DRAWSEGMENT( m_board );
// Init the new item attributes
DRAWSEGMENT* graphic = new DRAWSEGMENT( m_board );
graphic->SetShape( (STROKE_T) aShape );
graphic->SetWidth( m_board->GetDesignSettings().m_DrawSegmentWidth );
DRAWSEGMENT line45( *graphic ); // used only for direction 45 mode with lines
// Add a VIEW_GROUP that serves as a preview for the new item
KIGFX::VIEW_GROUP preview( m_view );
m_view->Add( &preview );
@ -657,19 +659,43 @@ int DRAWING_TOOL::drawSegment( int aShape, bool aContinous )
Activate();
bool started = false;
bool direction45 = false; // 45 degrees only mode
int addedSegments = 0;
// Main loop: keep receiving events
while( OPT_TOOL_EVENT evt = Wait() )
{
// Enable 45 degrees lines only mode by holding shift
bool linesAngle45 = evt->Modifier( MD_SHIFT );
bool updatePreview = false; // should preview be updated
VECTOR2I cursorPos = m_controls->GetCursorPosition();
// Enable 45 degrees lines only mode by holding control
if( direction45 != ( evt->Modifier( MD_CTRL ) && aShape == S_SEGMENT && started ) )
{
direction45 = evt->Modifier( MD_CTRL );
if( direction45 )
{
preview.Add( &line45 );
make45DegLine( graphic, &line45 );
}
else
{
preview.Remove( &line45 );
graphic->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
}
updatePreview = true;
}
if( evt->IsCancel() )
{
if( direction45 )
preview.Remove( &line45 );
preview.FreeItems();
if( !started ) // TODO check it
if( !started )
delete graphic;
break;
}
@ -683,7 +709,7 @@ int DRAWING_TOOL::drawSegment( int aShape, bool aContinous )
else if( evt->KeyCode() == '=' )
graphic->SetWidth( width + WIDTH_STEP );
preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
updatePreview = true;
}
else if( evt->IsClick( BUT_LEFT ) )
@ -701,7 +727,9 @@ int DRAWING_TOOL::drawSegment( int aShape, bool aContinous )
m_controls->SetAutoPan( true );
graphic->SetStart( wxPoint( cursorPos.x, cursorPos.y ) );
graphic->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
graphic->SetLayer( layer );
line45.SetLayer( layer );
preview.Add( graphic );
started = true;
@ -709,7 +737,7 @@ int DRAWING_TOOL::drawSegment( int aShape, bool aContinous )
}
else
{
if( wxPoint( cursorPos.x, cursorPos.y ) != graphic->GetStart() )
if( graphic->GetEnd() != graphic->GetStart() )
{
assert( graphic->GetLength() > 0 );
assert( graphic->GetWidth() > 0 );
@ -725,6 +753,10 @@ int DRAWING_TOOL::drawSegment( int aShape, bool aContinous )
graphic = new DRAWSEGMENT( *graphic );
// Start the new line in the same spot where the previous one has ended
graphic->SetStart( graphic->GetEnd() );
if( direction45 )
graphic->SetEnd( line45.GetEnd() );
preview.Add( graphic );
}
else
@ -743,14 +775,16 @@ int DRAWING_TOOL::drawSegment( int aShape, bool aContinous )
else if( evt->IsMotion() && started )
{
// 45 degree lines
if( linesAngle45 && aShape == S_SEGMENT )
make45DegLine( graphic );
if( direction45 && aShape == S_SEGMENT )
make45DegLine( graphic, &line45 );
else
graphic->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
// Show a preview of the item
preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
updatePreview = true;
}
if( updatePreview )
preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
}
m_controls->ShowCursor( false );
@ -800,6 +834,7 @@ int DRAWING_TOOL::drawZone( bool aKeepout )
helperLine->SetShape( S_SEGMENT );
helperLine->SetLayer( zoneInfo.m_CurrentZone_Layer );
helperLine->SetWidth( 1 );
DRAWSEGMENT line45( *helperLine );
// Add a VIEW_GROUP that serves as a preview for the new item
KIGFX::VIEW_GROUP preview( m_view );
@ -814,17 +849,37 @@ int DRAWING_TOOL::drawZone( bool aKeepout )
VECTOR2I lastCursorPos = m_controls->GetCursorPosition();
VECTOR2I origin;
int numPoints = 0;
bool direction45 = false; // 45 degrees only mode
bool cancelled = false;
// Main loop: keep receiving events
while( OPT_TOOL_EVENT evt = Wait() )
{
// Enable 45 degrees lines only mode by holding shift
bool linesAngle45 = evt->Modifier( MD_SHIFT );
bool updatePreview = false; // should preview be updated
VECTOR2I cursorPos = m_controls->GetCursorPosition();
// Enable 45 degrees lines only mode by holding control
if( direction45 != ( evt->Modifier( MD_CTRL ) && numPoints > 0 ) )
{
direction45 = evt->Modifier( MD_CTRL );
if( direction45 )
{
preview.Add( &line45 );
make45DegLine( helperLine, &line45 );
}
else
{
preview.Remove( &line45 );
helperLine->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
}
updatePreview = true;
}
if( evt->IsCancel() )
{
delete zone;
cancelled = true;
break;
}
@ -851,7 +906,7 @@ int DRAWING_TOOL::drawZone( bool aKeepout )
else
{
// If there are less than 3 points, then it is not a valid zone
delete zone;
cancelled = true;
}
break;
@ -877,7 +932,7 @@ int DRAWING_TOOL::drawZone( bool aKeepout )
}
++numPoints;
preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
updatePreview = true;
}
lastCursorPos = cursorPos;
@ -886,14 +941,17 @@ int DRAWING_TOOL::drawZone( bool aKeepout )
else if( evt->IsMotion() )
{
// 45 degree lines
if( linesAngle45 )
make45DegLine( helperLine );
if( direction45 )
make45DegLine( helperLine, &line45 );
else
helperLine->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
// Show a preview of the item
preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
updatePreview = true;
}
if( updatePreview )
preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
}
m_controls->ShowCursor( false );
@ -901,7 +959,11 @@ int DRAWING_TOOL::drawZone( bool aKeepout )
m_controls->SetAutoPan( false );
m_view->Remove( &preview );
// Delete helper lines
// Clean
if( cancelled )
delete zone;
if( direction45 )
preview.Remove( &line45 );
preview.FreeItems();
setTransitions();
@ -910,24 +972,25 @@ int DRAWING_TOOL::drawZone( bool aKeepout )
}
void DRAWING_TOOL::make45DegLine( DRAWSEGMENT* aSegment ) const
void DRAWING_TOOL::make45DegLine( DRAWSEGMENT* aSegment, DRAWSEGMENT* aHelper ) const
{
VECTOR2I cursorPos = m_controls->GetCursorPosition();
VECTOR2I origin( aSegment->GetStart() );
DIRECTION_45 direction( origin - cursorPos );
SHAPE_LINE_CHAIN newChain = direction.BuildInitialTrace( origin, cursorPos );
// Current line vector
VECTOR2D lineVector( wxPoint( cursorPos.x, cursorPos.y ) - aSegment->GetStart() );
double angle = lineVector.Angle();
// Find the closest angle, which is a multiple of 45 degrees
double newAngle = round( angle / ( M_PI / 4.0 ) ) * M_PI / 4.0;
VECTOR2D newLineVector = lineVector.Rotate( newAngle - angle );
VECTOR2D newLineEnd = VECTOR2D( aSegment->GetStart() ) + newLineVector;
// Snap the new line to the grid
newLineEnd = m_view->GetGAL()->GetGridPoint( newLineEnd );
aSegment->SetEnd( wxPoint( newLineEnd.x, newLineEnd.y ) );
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( cursorPos.x, cursorPos.y ) );
aHelper->SetStart( wxPoint( cursorPos.x, cursorPos.y ) );
aHelper->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
}
}

View File

@ -133,7 +133,9 @@ private:
///> 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.
void make45DegLine( DRAWSEGMENT* aSegment ) const;
///> @param aSegment is the segment that is currently drawn.
///> @param aHelper is a helper line that shows the next possible segment.
void make45DegLine( DRAWSEGMENT* aSegment, DRAWSEGMENT* aHelper ) const;
///> Sets up handlers for various events.
void setTransitions();