Improved way of drawing 45-degree lines.
This commit is contained in:
parent
c1c8f54e8b
commit
f82e07849b
|
@ -415,7 +415,7 @@ public:
|
||||||
* @param aP the point to be looked for
|
* @param aP the point to be looked for
|
||||||
* @return index of the correspoinding point in the line chain or negative when not found.
|
* @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()
|
* Function Slice()
|
||||||
|
|
|
@ -133,10 +133,7 @@ public:
|
||||||
*/
|
*/
|
||||||
DIRECTION_45 Opposite() const
|
DIRECTION_45 Opposite() const
|
||||||
{
|
{
|
||||||
if( m_dir == UNDEFINED )
|
const Directions OppositeMap[] = { S, SW, W, NW, N, NE, E, SE, UNDEFINED };
|
||||||
return UNDEFINED;
|
|
||||||
|
|
||||||
const Directions OppositeMap[] = { S, SW, W, NW, N, NE, E, SE };
|
|
||||||
return OppositeMap[m_dir];
|
return OppositeMap[m_dir];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include <view/view_controls.h>
|
#include <view/view_controls.h>
|
||||||
#include <gal/graphics_abstraction_layer.h>
|
#include <gal/graphics_abstraction_layer.h>
|
||||||
#include <tool/tool_manager.h>
|
#include <tool/tool_manager.h>
|
||||||
|
#include <router/direction.h>
|
||||||
|
|
||||||
#include <class_board.h>
|
#include <class_board.h>
|
||||||
#include <class_drawsegment.h>
|
#include <class_drawsegment.h>
|
||||||
|
@ -641,12 +642,13 @@ int DRAWING_TOOL::drawSegment( int aShape, bool aContinous )
|
||||||
// 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* graphic = new DRAWSEGMENT( m_board );
|
|
||||||
|
|
||||||
// Init the new item attributes
|
// Init the new item attributes
|
||||||
|
DRAWSEGMENT* graphic = new DRAWSEGMENT( m_board );
|
||||||
graphic->SetShape( (STROKE_T) aShape );
|
graphic->SetShape( (STROKE_T) aShape );
|
||||||
graphic->SetWidth( m_board->GetDesignSettings().m_DrawSegmentWidth );
|
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
|
// Add a VIEW_GROUP that serves as a preview for the new item
|
||||||
KIGFX::VIEW_GROUP preview( m_view );
|
KIGFX::VIEW_GROUP preview( m_view );
|
||||||
m_view->Add( &preview );
|
m_view->Add( &preview );
|
||||||
|
@ -657,19 +659,43 @@ int DRAWING_TOOL::drawSegment( int aShape, bool aContinous )
|
||||||
Activate();
|
Activate();
|
||||||
|
|
||||||
bool started = false;
|
bool started = false;
|
||||||
|
bool direction45 = false; // 45 degrees only mode
|
||||||
int addedSegments = 0;
|
int addedSegments = 0;
|
||||||
|
|
||||||
// Main loop: keep receiving events
|
// Main loop: keep receiving events
|
||||||
while( OPT_TOOL_EVENT evt = Wait() )
|
while( OPT_TOOL_EVENT evt = Wait() )
|
||||||
{
|
{
|
||||||
// Enable 45 degrees lines only mode by holding shift
|
bool updatePreview = false; // should preview be updated
|
||||||
bool linesAngle45 = evt->Modifier( MD_SHIFT );
|
|
||||||
VECTOR2I cursorPos = m_controls->GetCursorPosition();
|
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( evt->IsCancel() )
|
||||||
{
|
{
|
||||||
|
if( direction45 )
|
||||||
|
preview.Remove( &line45 );
|
||||||
|
|
||||||
preview.FreeItems();
|
preview.FreeItems();
|
||||||
if( !started ) // TODO check it
|
if( !started )
|
||||||
delete graphic;
|
delete graphic;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -683,7 +709,7 @@ int DRAWING_TOOL::drawSegment( int aShape, bool aContinous )
|
||||||
else if( evt->KeyCode() == '=' )
|
else if( evt->KeyCode() == '=' )
|
||||||
graphic->SetWidth( width + WIDTH_STEP );
|
graphic->SetWidth( width + WIDTH_STEP );
|
||||||
|
|
||||||
preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
|
updatePreview = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if( evt->IsClick( BUT_LEFT ) )
|
else if( evt->IsClick( BUT_LEFT ) )
|
||||||
|
@ -701,7 +727,9 @@ int DRAWING_TOOL::drawSegment( int aShape, bool aContinous )
|
||||||
m_controls->SetAutoPan( true );
|
m_controls->SetAutoPan( true );
|
||||||
|
|
||||||
graphic->SetStart( wxPoint( cursorPos.x, cursorPos.y ) );
|
graphic->SetStart( wxPoint( cursorPos.x, cursorPos.y ) );
|
||||||
|
graphic->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
|
||||||
graphic->SetLayer( layer );
|
graphic->SetLayer( layer );
|
||||||
|
line45.SetLayer( layer );
|
||||||
preview.Add( graphic );
|
preview.Add( graphic );
|
||||||
|
|
||||||
started = true;
|
started = true;
|
||||||
|
@ -709,7 +737,7 @@ int DRAWING_TOOL::drawSegment( int aShape, bool aContinous )
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if( wxPoint( cursorPos.x, cursorPos.y ) != graphic->GetStart() )
|
if( graphic->GetEnd() != graphic->GetStart() )
|
||||||
{
|
{
|
||||||
assert( graphic->GetLength() > 0 );
|
assert( graphic->GetLength() > 0 );
|
||||||
assert( graphic->GetWidth() > 0 );
|
assert( graphic->GetWidth() > 0 );
|
||||||
|
@ -725,6 +753,10 @@ int DRAWING_TOOL::drawSegment( int aShape, bool aContinous )
|
||||||
graphic = new DRAWSEGMENT( *graphic );
|
graphic = new DRAWSEGMENT( *graphic );
|
||||||
// Start the new line in the same spot where the previous one has ended
|
// Start the new line in the same spot where the previous one has ended
|
||||||
graphic->SetStart( graphic->GetEnd() );
|
graphic->SetStart( graphic->GetEnd() );
|
||||||
|
|
||||||
|
if( direction45 )
|
||||||
|
graphic->SetEnd( line45.GetEnd() );
|
||||||
|
|
||||||
preview.Add( graphic );
|
preview.Add( graphic );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -743,14 +775,16 @@ int DRAWING_TOOL::drawSegment( int aShape, bool aContinous )
|
||||||
else if( evt->IsMotion() && started )
|
else if( evt->IsMotion() && started )
|
||||||
{
|
{
|
||||||
// 45 degree lines
|
// 45 degree lines
|
||||||
if( linesAngle45 && aShape == S_SEGMENT )
|
if( direction45 && aShape == S_SEGMENT )
|
||||||
make45DegLine( graphic );
|
make45DegLine( graphic, &line45 );
|
||||||
else
|
else
|
||||||
graphic->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
|
graphic->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
|
||||||
|
|
||||||
// Show a preview of the item
|
updatePreview = true;
|
||||||
preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( updatePreview )
|
||||||
|
preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
|
||||||
}
|
}
|
||||||
|
|
||||||
m_controls->ShowCursor( false );
|
m_controls->ShowCursor( false );
|
||||||
|
@ -800,6 +834,7 @@ int DRAWING_TOOL::drawZone( bool aKeepout )
|
||||||
helperLine->SetShape( S_SEGMENT );
|
helperLine->SetShape( S_SEGMENT );
|
||||||
helperLine->SetLayer( zoneInfo.m_CurrentZone_Layer );
|
helperLine->SetLayer( zoneInfo.m_CurrentZone_Layer );
|
||||||
helperLine->SetWidth( 1 );
|
helperLine->SetWidth( 1 );
|
||||||
|
DRAWSEGMENT line45( *helperLine );
|
||||||
|
|
||||||
// Add a VIEW_GROUP that serves as a preview for the new item
|
// Add a VIEW_GROUP that serves as a preview for the new item
|
||||||
KIGFX::VIEW_GROUP preview( m_view );
|
KIGFX::VIEW_GROUP preview( m_view );
|
||||||
|
@ -814,17 +849,37 @@ int DRAWING_TOOL::drawZone( bool aKeepout )
|
||||||
VECTOR2I lastCursorPos = m_controls->GetCursorPosition();
|
VECTOR2I lastCursorPos = m_controls->GetCursorPosition();
|
||||||
VECTOR2I origin;
|
VECTOR2I origin;
|
||||||
int numPoints = 0;
|
int numPoints = 0;
|
||||||
|
bool direction45 = false; // 45 degrees only mode
|
||||||
|
bool cancelled = false;
|
||||||
|
|
||||||
// Main loop: keep receiving events
|
// Main loop: keep receiving events
|
||||||
while( OPT_TOOL_EVENT evt = Wait() )
|
while( OPT_TOOL_EVENT evt = Wait() )
|
||||||
{
|
{
|
||||||
// Enable 45 degrees lines only mode by holding shift
|
bool updatePreview = false; // should preview be updated
|
||||||
bool linesAngle45 = evt->Modifier( MD_SHIFT );
|
|
||||||
VECTOR2I cursorPos = m_controls->GetCursorPosition();
|
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() )
|
if( evt->IsCancel() )
|
||||||
{
|
{
|
||||||
delete zone;
|
cancelled = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -851,7 +906,7 @@ int DRAWING_TOOL::drawZone( bool aKeepout )
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// If there are less than 3 points, then it is not a valid zone
|
// If there are less than 3 points, then it is not a valid zone
|
||||||
delete zone;
|
cancelled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -877,7 +932,7 @@ int DRAWING_TOOL::drawZone( bool aKeepout )
|
||||||
}
|
}
|
||||||
++numPoints;
|
++numPoints;
|
||||||
|
|
||||||
preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
|
updatePreview = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
lastCursorPos = cursorPos;
|
lastCursorPos = cursorPos;
|
||||||
|
@ -886,14 +941,17 @@ int DRAWING_TOOL::drawZone( bool aKeepout )
|
||||||
else if( evt->IsMotion() )
|
else if( evt->IsMotion() )
|
||||||
{
|
{
|
||||||
// 45 degree lines
|
// 45 degree lines
|
||||||
if( linesAngle45 )
|
if( direction45 )
|
||||||
make45DegLine( helperLine );
|
make45DegLine( helperLine, &line45 );
|
||||||
else
|
else
|
||||||
helperLine->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
|
helperLine->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
|
||||||
|
|
||||||
// Show a preview of the item
|
// 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 );
|
m_controls->ShowCursor( false );
|
||||||
|
@ -901,7 +959,11 @@ int DRAWING_TOOL::drawZone( bool aKeepout )
|
||||||
m_controls->SetAutoPan( false );
|
m_controls->SetAutoPan( false );
|
||||||
m_view->Remove( &preview );
|
m_view->Remove( &preview );
|
||||||
|
|
||||||
// Delete helper lines
|
// Clean
|
||||||
|
if( cancelled )
|
||||||
|
delete zone;
|
||||||
|
if( direction45 )
|
||||||
|
preview.Remove( &line45 );
|
||||||
preview.FreeItems();
|
preview.FreeItems();
|
||||||
|
|
||||||
setTransitions();
|
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 cursorPos = m_controls->GetCursorPosition();
|
||||||
|
VECTOR2I origin( aSegment->GetStart() );
|
||||||
|
DIRECTION_45 direction( origin - cursorPos );
|
||||||
|
SHAPE_LINE_CHAIN newChain = direction.BuildInitialTrace( origin, cursorPos );
|
||||||
|
|
||||||
// Current line vector
|
if( newChain.PointCount() > 2 )
|
||||||
VECTOR2D lineVector( wxPoint( cursorPos.x, cursorPos.y ) - aSegment->GetStart() );
|
{
|
||||||
double angle = lineVector.Angle();
|
aSegment->SetEnd( wxPoint( newChain.Point( -2 ).x, newChain.Point( -2 ).y ) );
|
||||||
|
aHelper->SetStart( wxPoint( newChain.Point( -2 ).x, newChain.Point( -2 ).y ) );
|
||||||
// Find the closest angle, which is a multiple of 45 degrees
|
aHelper->SetEnd( wxPoint( newChain.Point( -1 ).x, newChain.Point( -1 ).y ) );
|
||||||
double newAngle = round( angle / ( M_PI / 4.0 ) ) * M_PI / 4.0;
|
}
|
||||||
|
else
|
||||||
VECTOR2D newLineVector = lineVector.Rotate( newAngle - angle );
|
{
|
||||||
VECTOR2D newLineEnd = VECTOR2D( aSegment->GetStart() ) + newLineVector;
|
aSegment->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
|
||||||
|
aHelper->SetStart( wxPoint( cursorPos.x, cursorPos.y ) );
|
||||||
// Snap the new line to the grid
|
aHelper->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
|
||||||
newLineEnd = m_view->GetGAL()->GetGridPoint( newLineEnd );
|
}
|
||||||
|
|
||||||
aSegment->SetEnd( wxPoint( newLineEnd.x, newLineEnd.y ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -133,7 +133,9 @@ private:
|
||||||
///> Forces a DRAWSEGMENT to be drawn at multiple of 45 degrees. The origin
|
///> 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
|
///> stays the same, the end of the aSegment is modified according to the
|
||||||
///> current cursor position.
|
///> 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.
|
///> Sets up handlers for various events.
|
||||||
void setTransitions();
|
void setTransitions();
|
||||||
|
|
Loading…
Reference in New Issue