From 1e461c2259c0c982b77dc0eeece20a61b9c079e0 Mon Sep 17 00:00:00 2001 From: Seth Hillbrand Date: Thu, 27 Aug 2020 10:31:53 -0700 Subject: [PATCH] ADDED: Improved center point dragging The center point on polygons now maintains the axis of the dragged line and, optionally with Ctrl pressed, maintains the slope of the adjacent segments as well. This also fixes a longstanding issue that prevented the ctrl-snapping from using the original point rather than the last updated point when constraining. Fixes https://gitlab.com/kicad/code/kicad/issues/2465 --- common/tool/edit_constraints.cpp | 23 ++++++++++++++++++ include/tool/edit_constraints.h | 24 +++++++++++++++++++ pcbnew/tools/point_editor.cpp | 40 +++++++++++++++++++++----------- 3 files changed, 74 insertions(+), 13 deletions(-) diff --git a/common/tool/edit_constraints.cpp b/common/tool/edit_constraints.cpp index 4b2c791b24..0a0089e0d6 100644 --- a/common/tool/edit_constraints.cpp +++ b/common/tool/edit_constraints.cpp @@ -196,3 +196,26 @@ void EC_SNAPLINE::Apply( EDIT_LINE& aHandle ) aHandle.GetOrigin().SetPosition( m_snapFun( aHandle.GetOrigin().GetPosition() ) ); aHandle.GetEnd().SetPosition( aHandle.GetOrigin().GetPosition() + delta ); } + + +EC_PERPLINE::EC_PERPLINE( EDIT_LINE& aLine ) : + EDIT_CONSTRAINT( aLine ) +{ + m_mid = aLine.GetPosition(); + m_line = ( aLine.GetEnd().GetPosition() - aLine.GetOrigin().GetPosition() ).Perpendicular(); +} + + +void EC_PERPLINE::Apply( EDIT_LINE& aHandle ) +{ + SEG main( m_mid, m_mid + m_line ); + SEG projection( aHandle.GetPosition(), aHandle.GetPosition() + m_line.Perpendicular() ); + + if( OPT_VECTOR2I intersect = projection.IntersectLines( main ) ) + aHandle.SetPosition( *intersect ); + + VECTOR2D delta = aHandle.GetEnd().GetPosition() - aHandle.GetOrigin().GetPosition(); + + aHandle.GetOrigin().SetPosition( aHandle.GetOrigin().GetPosition() ); + aHandle.GetEnd().SetPosition( aHandle.GetOrigin().GetPosition() + delta ); +} diff --git a/include/tool/edit_constraints.h b/include/tool/edit_constraints.h index e6caa17ad8..7c4423c765 100644 --- a/include/tool/edit_constraints.h +++ b/include/tool/edit_constraints.h @@ -264,4 +264,28 @@ private: V2D_TRANSFORM_FUN m_snapFun; }; + +/** + * EC_PERPLINE + * + * EDIT_CONSTRAINT for a EDIT_LINE, that constrains the line to move perpendicular + * to the line itself. + */ +class EC_PERPLINE : public EDIT_CONSTRAINT +{ +public: + + EC_PERPLINE( EDIT_LINE& aLine ); + + virtual ~EC_PERPLINE() + {} + + ///> @copydoc EDIT_CONSTRAINT::Apply() + virtual void Apply( EDIT_LINE& aHandle ) override; + +private: + VECTOR2I m_mid; + VECTOR2I m_line; +}; + #endif /* EDIT_CONSTRAINTS_H_ */ diff --git a/pcbnew/tools/point_editor.cpp b/pcbnew/tools/point_editor.cpp index cc5b0a3f7b..977ece06f7 100644 --- a/pcbnew/tools/point_editor.cpp +++ b/pcbnew/tools/point_editor.cpp @@ -114,8 +114,7 @@ private: points->AddLine( points->Point( i ), points->Point( i + 1 ) ); } - points->Line( i ).SetConstraint( new EC_SNAPLINE( points->Line( i ), - std::bind( &KIGFX::GAL::GetGridPoint, aGal, _1 ) ) ); + points->Line( i ).SetConstraint( new EC_PERPLINE( points->Line( i ) ) ); } // The last missing line, connecting the last and the first polygon point @@ -123,8 +122,7 @@ private: points->Point( points->GetContourStartIdx( cornersCount - 1 ) ) ); points->Line( points->LinesSize() - 1 ).SetConstraint( - new EC_SNAPLINE( points->Line( points->LinesSize() - 1 ), - std::bind( &KIGFX::GAL::GetGridPoint, aGal, _1 ) ) ); + new EC_PERPLINE( points->Line( points->LinesSize() - 1 ) ) ); } public: @@ -402,6 +400,7 @@ int POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent ) controls->SetAutoPan( true ); inDrag = true; grid.SetAuxAxes( true, m_original.GetPosition() ); + setAltConstraint( true ); m_editedPoint->SetActive(); } @@ -412,16 +411,15 @@ int POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent ) // The alternative constraint limits to 45° bool enableAltConstraint = !!evt->Modifier( MD_CTRL ); - if( enableAltConstraint != (bool) m_altConstraint ) // alternative constraint - setAltConstraint( enableAltConstraint ); - - if( m_altConstraint ) + if( enableAltConstraint ) m_altConstraint->Apply(); else m_editedPoint->ApplyConstraint(); - m_editedPoint->SetPosition( grid.BestSnapAnchor( m_editedPoint->GetPosition(), - snapLayers, { item } ) ); + // Don't snap the line center to the grid + if( !dynamic_cast( m_editedPoint) ) + m_editedPoint->SetPosition( grid.BestSnapAnchor( m_editedPoint->GetPosition(), + snapLayers, { item } ) ); updateItem(); updatePoints(); @@ -913,6 +911,12 @@ void POINT_EDITOR::updateItem() const for( int i = 0; i < outline.TotalVertices(); ++i ) outline.SetVertex( i, m_editPoints->Point( i ).GetPosition() ); + for( unsigned i = 0; i < m_editPoints->LinesSize(); ++i ) + { + if( !isModified( m_editPoints->Line( i ) ) ) + m_editPoints->Line( i ).SetConstraint( new EC_PERPLINE( m_editPoints->Line( i ) ) ); + } + validatePolygon( outline ); } break; @@ -1390,10 +1394,20 @@ void POINT_EDITOR::setAltConstraint( bool aEnabled ) if( aEnabled ) { EDIT_LINE* line = dynamic_cast( m_editedPoint ); + bool isPoly = false; - if( line && - ( m_editPoints->GetParent()->Type() == PCB_ZONE_AREA_T - || m_editPoints->GetParent()->Type() == PCB_MODULE_ZONE_AREA_T ) ) + if( m_editPoints->GetParent()->Type() == PCB_ZONE_AREA_T + || m_editPoints->GetParent()->Type() == PCB_MODULE_ZONE_AREA_T ) + isPoly = true; + + else if( m_editPoints->GetParent()->Type() == PCB_LINE_T + || m_editPoints->GetParent()->Type() == PCB_MODULE_EDGE_T ) + { + DRAWSEGMENT* seg = static_cast( m_editPoints->GetParent() ); + isPoly = seg->GetShape() == S_POLYGON; + } + + if( line && isPoly ) { m_altConstraint.reset( (EDIT_CONSTRAINT*)( new EC_CONVERGING( *line, *m_editPoints ) ) ); }