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
This commit is contained in:
Seth Hillbrand 2020-08-27 10:31:53 -07:00
parent baeb4abd18
commit 1e461c2259
3 changed files with 74 additions and 13 deletions

View File

@ -196,3 +196,26 @@ void EC_SNAPLINE::Apply( EDIT_LINE& aHandle )
aHandle.GetOrigin().SetPosition( m_snapFun( aHandle.GetOrigin().GetPosition() ) ); aHandle.GetOrigin().SetPosition( m_snapFun( aHandle.GetOrigin().GetPosition() ) );
aHandle.GetEnd().SetPosition( aHandle.GetOrigin().GetPosition() + delta ); aHandle.GetEnd().SetPosition( aHandle.GetOrigin().GetPosition() + delta );
} }
EC_PERPLINE::EC_PERPLINE( EDIT_LINE& aLine ) :
EDIT_CONSTRAINT<EDIT_LINE>( 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 );
}

View File

@ -264,4 +264,28 @@ private:
V2D_TRANSFORM_FUN m_snapFun; 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<EDIT_LINE>
{
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_ */ #endif /* EDIT_CONSTRAINTS_H_ */

View File

@ -114,8 +114,7 @@ private:
points->AddLine( points->Point( i ), points->Point( i + 1 ) ); points->AddLine( points->Point( i ), points->Point( i + 1 ) );
} }
points->Line( i ).SetConstraint( new EC_SNAPLINE( points->Line( i ), points->Line( i ).SetConstraint( new EC_PERPLINE( points->Line( i ) ) );
std::bind( &KIGFX::GAL::GetGridPoint, aGal, _1 ) ) );
} }
// The last missing line, connecting the last and the first polygon point // The last missing line, connecting the last and the first polygon point
@ -123,8 +122,7 @@ private:
points->Point( points->GetContourStartIdx( cornersCount - 1 ) ) ); points->Point( points->GetContourStartIdx( cornersCount - 1 ) ) );
points->Line( points->LinesSize() - 1 ).SetConstraint( points->Line( points->LinesSize() - 1 ).SetConstraint(
new EC_SNAPLINE( points->Line( points->LinesSize() - 1 ), new EC_PERPLINE( points->Line( points->LinesSize() - 1 ) ) );
std::bind( &KIGFX::GAL::GetGridPoint, aGal, _1 ) ) );
} }
public: public:
@ -402,6 +400,7 @@ int POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent )
controls->SetAutoPan( true ); controls->SetAutoPan( true );
inDrag = true; inDrag = true;
grid.SetAuxAxes( true, m_original.GetPosition() ); grid.SetAuxAxes( true, m_original.GetPosition() );
setAltConstraint( true );
m_editedPoint->SetActive(); m_editedPoint->SetActive();
} }
@ -412,16 +411,15 @@ int POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent )
// The alternative constraint limits to 45° // The alternative constraint limits to 45°
bool enableAltConstraint = !!evt->Modifier( MD_CTRL ); bool enableAltConstraint = !!evt->Modifier( MD_CTRL );
if( enableAltConstraint != (bool) m_altConstraint ) // alternative constraint if( enableAltConstraint )
setAltConstraint( enableAltConstraint );
if( m_altConstraint )
m_altConstraint->Apply(); m_altConstraint->Apply();
else else
m_editedPoint->ApplyConstraint(); m_editedPoint->ApplyConstraint();
m_editedPoint->SetPosition( grid.BestSnapAnchor( m_editedPoint->GetPosition(), // Don't snap the line center to the grid
snapLayers, { item } ) ); if( !dynamic_cast<EDIT_LINE*>( m_editedPoint) )
m_editedPoint->SetPosition( grid.BestSnapAnchor( m_editedPoint->GetPosition(),
snapLayers, { item } ) );
updateItem(); updateItem();
updatePoints(); updatePoints();
@ -913,6 +911,12 @@ void POINT_EDITOR::updateItem() const
for( int i = 0; i < outline.TotalVertices(); ++i ) for( int i = 0; i < outline.TotalVertices(); ++i )
outline.SetVertex( i, m_editPoints->Point( i ).GetPosition() ); 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 ); validatePolygon( outline );
} }
break; break;
@ -1390,10 +1394,20 @@ void POINT_EDITOR::setAltConstraint( bool aEnabled )
if( aEnabled ) if( aEnabled )
{ {
EDIT_LINE* line = dynamic_cast<EDIT_LINE*>( m_editedPoint ); EDIT_LINE* line = dynamic_cast<EDIT_LINE*>( m_editedPoint );
bool isPoly = false;
if( line && if( m_editPoints->GetParent()->Type() == PCB_ZONE_AREA_T
( m_editPoints->GetParent()->Type() == PCB_ZONE_AREA_T || m_editPoints->GetParent()->Type() == PCB_MODULE_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<DRAWSEGMENT*>( m_editPoints->GetParent() );
isPoly = seg->GetShape() == S_POLYGON;
}
if( line && isPoly )
{ {
m_altConstraint.reset( (EDIT_CONSTRAINT<EDIT_POINT>*)( new EC_CONVERGING( *line, *m_editPoints ) ) ); m_altConstraint.reset( (EDIT_CONSTRAINT<EDIT_POINT>*)( new EC_CONVERGING( *line, *m_editPoints ) ) );
} }