Stop converging at existing point

Prevents collapsing points into drag element when hitting convergence
This commit is contained in:
Seth Hillbrand 2025-08-31 17:08:06 -07:00
parent 77a2330a33
commit 2c4d792358
3 changed files with 52 additions and 16 deletions

View File

@ -30,6 +30,8 @@
#include <trigo.h> #include <trigo.h>
#include <geometry/geometry_utils.h> #include <geometry/geometry_utils.h>
#include <math/vector2d.h>
#include <math/util.h>
void EC_VERTICAL::Apply( EDIT_POINT& aHandle, const GRID_HELPER& aGrid ) void EC_VERTICAL::Apply( EDIT_POINT& aHandle, const GRID_HELPER& aGrid )
@ -145,6 +147,8 @@ void EC_CIRCLE::Apply( EDIT_POINT& aHandle, const GRID_HELPER& aGrid )
EC_CONVERGING::EC_CONVERGING( EDIT_LINE& aLine, EDIT_POINTS& aPoints ) : EC_CONVERGING::EC_CONVERGING( EDIT_LINE& aLine, EDIT_POINTS& aPoints ) :
EDIT_CONSTRAINT<EDIT_LINE>( aLine ), EDIT_CONSTRAINT<EDIT_LINE>( aLine ),
m_prevOrigin( aPoints.Previous( aLine.GetOrigin(), false ) ),
m_nextEnd( aPoints.Next( aLine.GetEnd(), false ) ),
m_colinearConstraint( nullptr ), m_colinearConstraint( nullptr ),
m_editPoints( aPoints ) m_editPoints( aPoints )
{ {
@ -152,20 +156,16 @@ EC_CONVERGING::EC_CONVERGING( EDIT_LINE& aLine, EDIT_POINTS& aPoints ) :
EDIT_POINT& origin = aLine.GetOrigin(); EDIT_POINT& origin = aLine.GetOrigin();
EDIT_POINT& end = aLine.GetEnd(); EDIT_POINT& end = aLine.GetEnd();
// Previous and next points, to make constraining lines (adjacent to the dragged line)
EDIT_POINT& prevOrigin = *aPoints.Previous( origin, false );
EDIT_POINT& nextEnd = *aPoints.Next( end, false );
// Constraints for segments adjacent to the dragged one // Constraints for segments adjacent to the dragged one
m_originSideConstraint = std::make_unique<EC_LINE>( origin, prevOrigin ); m_originSideConstraint = std::make_unique<EC_LINE>( origin, *m_prevOrigin );
m_endSideConstraint = std::make_unique<EC_LINE>( end, nextEnd ); m_endSideConstraint = std::make_unique<EC_LINE>( end, *m_nextEnd );
// Store the current vector of the line // Store the current vector of the line
m_draggedVector = end.GetPosition() - origin.GetPosition(); m_draggedVector = end.GetPosition() - origin.GetPosition();
// Check for colinearity // Check for colinearity
SEG originSide( origin.GetPosition(), prevOrigin.GetPosition() ); SEG originSide( origin.GetPosition(), m_prevOrigin->GetPosition() );
SEG endSide( end.GetPosition(), nextEnd.GetPosition() ); SEG endSide( end.GetPosition(), m_nextEnd->GetPosition() );
SEG dragged( origin.GetPosition(), end.GetPosition() ); SEG dragged( origin.GetPosition(), end.GetPosition() );
// Used to align lines that are almost collinear // Used to align lines that are almost collinear
@ -178,6 +178,13 @@ EC_CONVERGING::EC_CONVERGING( EDIT_LINE& aLine, EDIT_POINTS& aPoints ) :
m_colinearConstraint = m_originSideConstraint.get(); m_colinearConstraint = m_originSideConstraint.get();
else if( m_endCollinear ) else if( m_endCollinear )
m_colinearConstraint = m_endSideConstraint.get(); m_colinearConstraint = m_endSideConstraint.get();
if( OPT_VECTOR2I intersect = originSide.IntersectLines( endSide ) )
m_convergencePoint = *intersect;
else
m_convergencePoint = aLine.GetPosition();
m_midVector = aLine.GetPosition() - m_convergencePoint;
} }
@ -189,6 +196,21 @@ EC_CONVERGING::~EC_CONVERGING()
void EC_CONVERGING::Apply( EDIT_LINE& aHandle, const GRID_HELPER& aGrid ) void EC_CONVERGING::Apply( EDIT_LINE& aHandle, const GRID_HELPER& aGrid )
{ {
VECTOR2I handlePos = aHandle.GetPosition();
VECTOR2I convToHandle = handlePos - m_convergencePoint;
double t = 0.0;
if( m_midVector.SquaredEuclideanNorm() )
t = double( convToHandle.Dot( m_midVector ) )
/ double( m_midVector.SquaredEuclideanNorm() );
if( t < 0.0 )
t = 0.0;
VECTOR2D newCenterD = VECTOR2D( m_convergencePoint ) + VECTOR2D( m_midVector ) * t;
VECTOR2I newCenter( KiROUND( newCenterD.x ), KiROUND( newCenterD.y ) );
aHandle.SetPosition( newCenter );
// The dragged segment endpoints // The dragged segment endpoints
EDIT_POINT& origin = aHandle.GetOrigin(); EDIT_POINT& origin = aHandle.GetOrigin();
EDIT_POINT& end = aHandle.GetEnd(); EDIT_POINT& end = aHandle.GetEnd();
@ -209,12 +231,9 @@ void EC_CONVERGING::Apply( EDIT_LINE& aHandle, const GRID_HELPER& aGrid )
m_originSideConstraint->Apply( aGrid ); m_originSideConstraint->Apply( aGrid );
m_endSideConstraint->Apply( aGrid ); m_endSideConstraint->Apply( aGrid );
EDIT_POINT& prevOrigin = *m_editPoints.Previous( origin, false );
EDIT_POINT& nextEnd = *m_editPoints.Next( end, false );
// Two segments adjacent to the dragged segment // Two segments adjacent to the dragged segment
SEG originSide = SEG( origin.GetPosition(), prevOrigin.GetPosition() ); SEG originSide = SEG( origin.GetPosition(), m_prevOrigin->GetPosition() );
SEG endSide = SEG( end.GetPosition(), nextEnd.GetPosition() ); SEG endSide = SEG( end.GetPosition(), m_nextEnd->GetPosition() );
// First intersection point (dragged segment against origin side) // First intersection point (dragged segment against origin side)
if( OPT_VECTOR2I originIntersect = dragged.IntersectLines( originSide ) ) if( OPT_VECTOR2I originIntersect = dragged.IntersectLines( originSide ) )
@ -226,8 +245,8 @@ void EC_CONVERGING::Apply( EDIT_LINE& aHandle, const GRID_HELPER& aGrid )
// Check if adjacent segments intersect (did we dragged the line to the point that it may // Check if adjacent segments intersect (did we dragged the line to the point that it may
// create a selfintersecting polygon?) // create a selfintersecting polygon?)
originSide = SEG( origin.GetPosition(), prevOrigin.GetPosition() ); originSide = SEG( origin.GetPosition(), m_prevOrigin->GetPosition() );
endSide = SEG( end.GetPosition(), nextEnd.GetPosition() ); endSide = SEG( end.GetPosition(), m_nextEnd->GetPosition() );
if( OPT_VECTOR2I originEndIntersect = endSide.Intersect( originSide ) ) if( OPT_VECTOR2I originEndIntersect = endSide.Intersect( originSide ) )
{ {

View File

@ -263,6 +263,16 @@ private:
/// Flags to indicate when dragged and neighbouring lines are (almost) collinear. /// Flags to indicate when dragged and neighbouring lines are (almost) collinear.
bool m_originCollinear; bool m_originCollinear;
bool m_endCollinear; bool m_endCollinear;
/// Previous and next points to keep drag endpoints fixed.
EDIT_POINT* m_prevOrigin;
EDIT_POINT* m_nextEnd;
/// Original convergence point of adjacent segments.
VECTOR2I m_convergencePoint;
/// Vector from the convergence point to the mid-line point.
VECTOR2I m_midVector;
}; };

View File

@ -2084,6 +2084,7 @@ int PCB_POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent )
setEditedPoint( nullptr ); setEditedPoint( nullptr );
updateEditedPoint( aEvent ); updateEditedPoint( aEvent );
bool inDrag = false; bool inDrag = false;
bool isConstrained = false;
BOARD_COMMIT commit( editFrame ); BOARD_COMMIT commit( editFrame );
@ -2163,7 +2164,13 @@ int PCB_POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent )
grid.AddConstructionItems( { clone }, false, true ); grid.AddConstructionItems( { clone }, false, true );
} }
setAltConstraint( Is45Limited() || Is90Limited() ); bool need_constraint = Is45Limited() || Is90Limited();
if( isConstrained != need_constraint )
{
setAltConstraint( need_constraint );
isConstrained = need_constraint;
}
// Keep point inside of limits with some padding // Keep point inside of limits with some padding
VECTOR2I pos = GetClampedCoords<double, int>( evt->Position(), COORDS_PADDING ); VECTOR2I pos = GetClampedCoords<double, int>( evt->Position(), COORDS_PADDING );