mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-14 02:03:12 +02:00
Stop converging at existing point
Prevents collapsing points into drag element when hitting convergence
This commit is contained in:
parent
77a2330a33
commit
2c4d792358
@ -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 ) )
|
||||||
{
|
{
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -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 );
|
||||||
|
Loading…
x
Reference in New Issue
Block a user