diff --git a/include/geometry/shape_line_chain.h b/include/geometry/shape_line_chain.h index 5108191bb7..da6494e91a 100644 --- a/include/geometry/shape_line_chain.h +++ b/include/geometry/shape_line_chain.h @@ -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() diff --git a/pcbnew/router/direction.h b/pcbnew/router/direction.h index 0b7d8cb62d..ad38fcbdef 100644 --- a/pcbnew/router/direction.h +++ b/pcbnew/router/direction.h @@ -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]; } diff --git a/pcbnew/tools/drawing_tool.cpp b/pcbnew/tools/drawing_tool.cpp index aefc7e3a3d..a80b605da4 100644 --- a/pcbnew/tools/drawing_tool.cpp +++ b/pcbnew/tools/drawing_tool.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -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 ) ); + } } diff --git a/pcbnew/tools/drawing_tool.h b/pcbnew/tools/drawing_tool.h index 2b759670c8..775351efaf 100644 --- a/pcbnew/tools/drawing_tool.h +++ b/pcbnew/tools/drawing_tool.h @@ -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();