Partially integrate grid snapping with constraints.
Fixes https://gitlab.com/kicad/code/kicad/issues/10941
This commit is contained in:
parent
c7dda3fbec
commit
41f6e634c6
|
@ -2,7 +2,7 @@
|
||||||
* This program source code file is part of KICAD, a free EDA CAD application.
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2014 CERN
|
* Copyright (C) 2014 CERN
|
||||||
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
|
* Copyright (C) 2021-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
|
@ -29,45 +29,78 @@
|
||||||
#include <geometry/seg.h>
|
#include <geometry/seg.h>
|
||||||
#include <trigo.h>
|
#include <trigo.h>
|
||||||
|
|
||||||
#include <utility>
|
|
||||||
#include <geometry/geometry_utils.h>
|
#include <geometry/geometry_utils.h>
|
||||||
|
|
||||||
|
|
||||||
void EC_VERTICAL::Apply( EDIT_POINT& aHandle )
|
void EC_VERTICAL::Apply( EDIT_POINT& aHandle, const GRID_HELPER& aGrid )
|
||||||
{
|
{
|
||||||
VECTOR2I point = aHandle.GetPosition();
|
VECTOR2I point = aHandle.GetPosition();
|
||||||
|
|
||||||
|
if( aHandle.GetGridConstraint() == SNAP_TO_GRID )
|
||||||
|
point = aGrid.AlignGrid( point );
|
||||||
|
|
||||||
point.x = m_constrainer.GetPosition().x;
|
point.x = m_constrainer.GetPosition().x;
|
||||||
aHandle.SetPosition( point );
|
aHandle.SetPosition( point );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void EC_HORIZONTAL::Apply( EDIT_POINT& aHandle )
|
void EC_HORIZONTAL::Apply( EDIT_POINT& aHandle, const GRID_HELPER& aGrid )
|
||||||
{
|
{
|
||||||
VECTOR2I point = aHandle.GetPosition();
|
VECTOR2I point = aHandle.GetPosition();
|
||||||
|
|
||||||
|
if( aHandle.GetGridConstraint() == SNAP_TO_GRID )
|
||||||
|
point = aGrid.AlignGrid( point );
|
||||||
|
|
||||||
point.y = m_constrainer.GetPosition().y;
|
point.y = m_constrainer.GetPosition().y;
|
||||||
aHandle.SetPosition( point );
|
aHandle.SetPosition( point );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void EC_45DEGREE::Apply( EDIT_POINT& aHandle )
|
void EC_45DEGREE::Apply( EDIT_POINT& aHandle, const GRID_HELPER& aGrid )
|
||||||
{
|
{
|
||||||
VECTOR2I lineVector( aHandle.GetPosition() - m_constrainer.GetPosition() );
|
VECTOR2I lineVector( aHandle.GetPosition() - m_constrainer.GetPosition() );
|
||||||
VECTOR2I newLineVector = GetVectorSnapped45( lineVector );
|
VECTOR2I newLineVector = GetVectorSnapped45( lineVector );
|
||||||
|
|
||||||
aHandle.SetPosition( m_constrainer.GetPosition() + newLineVector );
|
if( aHandle.GetGridConstraint() == SNAP_TO_GRID
|
||||||
|
&& ( newLineVector.x == 0 || newLineVector.y == 0 ) )
|
||||||
|
{
|
||||||
|
VECTOR2I snap = aGrid.AlignGrid( m_constrainer.GetPosition() + newLineVector );
|
||||||
|
|
||||||
|
if( newLineVector.x == 0 )
|
||||||
|
aHandle.SetPosition( VECTOR2I( m_constrainer.GetPosition().x, snap.y ) );
|
||||||
|
else
|
||||||
|
aHandle.SetPosition( VECTOR2I( snap.x, m_constrainer.GetPosition().y ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aHandle.SetPosition( m_constrainer.GetPosition() + newLineVector );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EC_LINE::EC_LINE( EDIT_POINT& aConstrained, const EDIT_POINT& aConstrainer ) :
|
EC_LINE::EC_LINE( EDIT_POINT& aConstrained, const EDIT_POINT& aConstrainer ) :
|
||||||
EDIT_CONSTRAINT<EDIT_POINT>( aConstrained ), m_constrainer( aConstrainer )
|
EDIT_CONSTRAINT<EDIT_POINT>( aConstrained ),
|
||||||
|
m_constrainer( aConstrainer )
|
||||||
{
|
{
|
||||||
m_line = m_constrained.GetPosition() - m_constrainer.GetPosition();
|
m_line = m_constrained.GetPosition() - m_constrainer.GetPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void EC_LINE::Apply( EDIT_POINT& aHandle )
|
void EC_LINE::Apply( EDIT_POINT& aHandle, const GRID_HELPER& aGrid )
|
||||||
{
|
{
|
||||||
SEG main( m_constrainer.GetPosition(), m_constrainer.GetPosition() + m_line );
|
SEG main( m_constrainer.GetPosition(), m_constrainer.GetPosition() + m_line );
|
||||||
|
|
||||||
|
if( aHandle.GetGridConstraint() == SNAP_TO_GRID
|
||||||
|
&& ( m_line.x == 0 || m_line.y == 0 ) )
|
||||||
|
{
|
||||||
|
VECTOR2I snappedHandle = aGrid.AlignGrid( aHandle.GetPosition() );
|
||||||
|
|
||||||
|
if( m_line.x == 0 )
|
||||||
|
aHandle.SetPosition( VECTOR2I( aHandle.GetPosition().x, snappedHandle.y ) );
|
||||||
|
else
|
||||||
|
aHandle.SetPosition( VECTOR2I( snappedHandle.x, aHandle.GetPosition().y ) );
|
||||||
|
}
|
||||||
|
|
||||||
SEG projection( aHandle.GetPosition(), aHandle.GetPosition() + m_line.Perpendicular() );
|
SEG projection( aHandle.GetPosition(), aHandle.GetPosition() + m_line.Perpendicular() );
|
||||||
|
|
||||||
if( OPT_VECTOR2I intersect = projection.IntersectLines( main ) )
|
if( OPT_VECTOR2I intersect = projection.IntersectLines( main ) )
|
||||||
|
@ -75,7 +108,7 @@ void EC_LINE::Apply( EDIT_POINT& aHandle )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void EC_CIRCLE::Apply( EDIT_POINT& aHandle )
|
void EC_CIRCLE::Apply( EDIT_POINT& aHandle, const GRID_HELPER& aGrid )
|
||||||
{
|
{
|
||||||
VECTOR2I centerToEnd = m_end.GetPosition() - m_center.GetPosition();
|
VECTOR2I centerToEnd = m_end.GetPosition() - m_center.GetPosition();
|
||||||
VECTOR2I centerToPoint = aHandle.GetPosition() - m_center.GetPosition();
|
VECTOR2I centerToPoint = aHandle.GetPosition() - m_center.GetPosition();
|
||||||
|
@ -92,7 +125,8 @@ void EC_CIRCLE::Apply( EDIT_POINT& aHandle )
|
||||||
|
|
||||||
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_colinearConstraint( nullptr ), m_editPoints( aPoints )
|
m_colinearConstraint( nullptr ),
|
||||||
|
m_editPoints( aPoints )
|
||||||
{
|
{
|
||||||
// Dragged segment endings
|
// Dragged segment endings
|
||||||
EDIT_POINT& origin = aLine.GetOrigin();
|
EDIT_POINT& origin = aLine.GetOrigin();
|
||||||
|
@ -129,7 +163,7 @@ EC_CONVERGING::~EC_CONVERGING()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void EC_CONVERGING::Apply( EDIT_LINE& aHandle )
|
void EC_CONVERGING::Apply( EDIT_LINE& aHandle, const GRID_HELPER& aGrid )
|
||||||
{
|
{
|
||||||
// The dragged segment endpoints
|
// The dragged segment endpoints
|
||||||
EDIT_POINT& origin = aHandle.GetOrigin();
|
EDIT_POINT& origin = aHandle.GetOrigin();
|
||||||
|
@ -137,16 +171,16 @@ void EC_CONVERGING::Apply( EDIT_LINE& aHandle )
|
||||||
|
|
||||||
if( m_colinearConstraint )
|
if( m_colinearConstraint )
|
||||||
{
|
{
|
||||||
m_colinearConstraint->Apply( origin );
|
m_colinearConstraint->Apply( origin, aGrid );
|
||||||
m_colinearConstraint->Apply( end );
|
m_colinearConstraint->Apply( end, aGrid );
|
||||||
}
|
}
|
||||||
|
|
||||||
// The dragged segment
|
// The dragged segment
|
||||||
SEG dragged( origin.GetPosition(), origin.GetPosition() + m_draggedVector );
|
SEG dragged( origin.GetPosition(), origin.GetPosition() + m_draggedVector );
|
||||||
|
|
||||||
// Do not allow points on the adjacent segments move freely
|
// Do not allow points on the adjacent segments move freely
|
||||||
m_originSideConstraint->Apply();
|
m_originSideConstraint->Apply( aGrid );
|
||||||
m_endSideConstraint->Apply();
|
m_endSideConstraint->Apply( aGrid );
|
||||||
|
|
||||||
EDIT_POINT& prevOrigin = *m_editPoints.Previous( origin, false );
|
EDIT_POINT& prevOrigin = *m_editPoints.Previous( origin, false );
|
||||||
EDIT_POINT& nextEnd = *m_editPoints.Next( end, false );
|
EDIT_POINT& nextEnd = *m_editPoints.Next( end, false );
|
||||||
|
@ -180,20 +214,6 @@ void EC_CONVERGING::Apply( EDIT_LINE& aHandle )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EC_SNAPLINE::EC_SNAPLINE( EDIT_LINE& aLine, V2D_TRANSFORM_FUN aSnapFun ) :
|
|
||||||
EDIT_CONSTRAINT<EDIT_LINE>( aLine ), m_snapFun( std::move(aSnapFun) )
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
void EC_SNAPLINE::Apply( EDIT_LINE& aHandle )
|
|
||||||
{
|
|
||||||
VECTOR2D delta = aHandle.GetEnd().GetPosition() - aHandle.GetOrigin().GetPosition();
|
|
||||||
|
|
||||||
aHandle.GetOrigin().SetPosition( m_snapFun( aHandle.GetOrigin().GetPosition() ) );
|
|
||||||
aHandle.GetEnd().SetPosition( aHandle.GetOrigin().GetPosition() + delta );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
EC_PERPLINE::EC_PERPLINE( EDIT_LINE& aLine ) :
|
EC_PERPLINE::EC_PERPLINE( EDIT_LINE& aLine ) :
|
||||||
EDIT_CONSTRAINT<EDIT_LINE>( aLine )
|
EDIT_CONSTRAINT<EDIT_LINE>( aLine )
|
||||||
{
|
{
|
||||||
|
@ -202,7 +222,7 @@ EC_PERPLINE::EC_PERPLINE( EDIT_LINE& aLine ) :
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void EC_PERPLINE::Apply( EDIT_LINE& aHandle )
|
void EC_PERPLINE::Apply( EDIT_LINE& aHandle, const GRID_HELPER& aGrid )
|
||||||
{
|
{
|
||||||
SEG main( m_mid, m_mid + m_line );
|
SEG main( m_mid, m_mid + m_line );
|
||||||
SEG projection( aHandle.GetPosition(), aHandle.GetPosition() + m_line.Perpendicular() );
|
SEG projection( aHandle.GetPosition(), aHandle.GetPosition() + m_line.Perpendicular() );
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* This program source code file is part of KICAD, a free EDA CAD application.
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2014 CERN
|
* Copyright (C) 2014 CERN
|
||||||
* Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors.
|
* Copyright (C) 2020-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
*
|
*
|
||||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||||
*
|
*
|
||||||
|
@ -28,6 +28,7 @@
|
||||||
#define EDIT_CONSTRAINTS_H_
|
#define EDIT_CONSTRAINTS_H_
|
||||||
|
|
||||||
#include <math/vector2d.h>
|
#include <math/vector2d.h>
|
||||||
|
#include <tool/grid_helper.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
class EDIT_POINT;
|
class EDIT_POINT;
|
||||||
|
@ -43,6 +44,14 @@ enum GRID_CONSTRAINT_TYPE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum SNAP_CONSTRAINT_TYPE
|
||||||
|
{
|
||||||
|
IGNORE_SNAPS,
|
||||||
|
OBJECT_LAYERS,
|
||||||
|
ALL_LAYERS
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describe constraints between two edit handles.
|
* Describe constraints between two edit handles.
|
||||||
*
|
*
|
||||||
|
@ -56,21 +65,23 @@ public:
|
||||||
/**
|
/**
|
||||||
* @param aConstrained is EDIT_POINT to which the constraint is applied.
|
* @param aConstrained is EDIT_POINT to which the constraint is applied.
|
||||||
*/
|
*/
|
||||||
EDIT_CONSTRAINT( EDIT_TYPE& aConstrained ) : m_constrained( aConstrained ) {};
|
EDIT_CONSTRAINT( EDIT_TYPE& aConstrained ) :
|
||||||
|
m_constrained( aConstrained )
|
||||||
|
{};
|
||||||
|
|
||||||
virtual ~EDIT_CONSTRAINT() {};
|
virtual ~EDIT_CONSTRAINT() {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Correct coordinates of the constrained edit handle.
|
* Correct coordinates of the constrained edit handle.
|
||||||
*/
|
*/
|
||||||
virtual void Apply( EDIT_TYPE& aHandle ) = 0;
|
virtual void Apply( EDIT_TYPE& aHandle, const GRID_HELPER& aGrid ) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Correct coordinates of the constrained edit handle.
|
* Correct coordinates of the constrained edit handle.
|
||||||
*/
|
*/
|
||||||
void Apply()
|
void Apply( const GRID_HELPER& aGrid )
|
||||||
{
|
{
|
||||||
Apply( m_constrained );
|
Apply( m_constrained, aGrid );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -89,11 +100,12 @@ public:
|
||||||
* @param aConstrainer is the point that is the source of the constrain.
|
* @param aConstrainer is the point that is the source of the constrain.
|
||||||
*/
|
*/
|
||||||
EC_VERTICAL( EDIT_POINT& aConstrained, const EDIT_POINT& aConstrainer ) :
|
EC_VERTICAL( EDIT_POINT& aConstrained, const EDIT_POINT& aConstrainer ) :
|
||||||
EDIT_CONSTRAINT<EDIT_POINT>( aConstrained ), m_constrainer( aConstrainer )
|
EDIT_CONSTRAINT<EDIT_POINT>( aConstrained ),
|
||||||
|
m_constrainer( aConstrainer )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
///< @copydoc EDIT_CONSTRAINT::Apply()
|
///< @copydoc EDIT_CONSTRAINT::Apply()
|
||||||
virtual void Apply( EDIT_POINT& aHandle ) override;
|
virtual void Apply( EDIT_POINT& aHandle, const GRID_HELPER& aGrid ) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const EDIT_POINT& m_constrainer; ///< Point that imposes the constraint.
|
const EDIT_POINT& m_constrainer; ///< Point that imposes the constraint.
|
||||||
|
@ -111,11 +123,12 @@ public:
|
||||||
* @param aConstrainer is the point that is the source of the constrain.
|
* @param aConstrainer is the point that is the source of the constrain.
|
||||||
*/
|
*/
|
||||||
EC_HORIZONTAL( EDIT_POINT& aConstrained, const EDIT_POINT& aConstrainer ) :
|
EC_HORIZONTAL( EDIT_POINT& aConstrained, const EDIT_POINT& aConstrainer ) :
|
||||||
EDIT_CONSTRAINT<EDIT_POINT>( aConstrained ), m_constrainer( aConstrainer )
|
EDIT_CONSTRAINT<EDIT_POINT>( aConstrained ),
|
||||||
|
m_constrainer( aConstrainer )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
///< @copydoc EDIT_CONSTRAINT::Apply()
|
///< @copydoc EDIT_CONSTRAINT::Apply()
|
||||||
virtual void Apply( EDIT_POINT& aHandle ) override;
|
virtual void Apply( EDIT_POINT& aHandle, const GRID_HELPER& aGrid ) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const EDIT_POINT& m_constrainer; ///< Point that imposes the constraint.
|
const EDIT_POINT& m_constrainer; ///< Point that imposes the constraint.
|
||||||
|
@ -134,11 +147,12 @@ public:
|
||||||
* @param aConstrainer is the point that is the source of the constrain.
|
* @param aConstrainer is the point that is the source of the constrain.
|
||||||
*/
|
*/
|
||||||
EC_45DEGREE( EDIT_POINT& aConstrained, const EDIT_POINT& aConstrainer ) :
|
EC_45DEGREE( EDIT_POINT& aConstrained, const EDIT_POINT& aConstrainer ) :
|
||||||
EDIT_CONSTRAINT<EDIT_POINT>( aConstrained ), m_constrainer( aConstrainer )
|
EDIT_CONSTRAINT<EDIT_POINT>( aConstrained ),
|
||||||
|
m_constrainer( aConstrainer )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
///< @copydoc EDIT_CONSTRAINT::Apply()
|
///< @copydoc EDIT_CONSTRAINT::Apply()
|
||||||
virtual void Apply( EDIT_POINT& aHandle ) override;
|
virtual void Apply( EDIT_POINT& aHandle, const GRID_HELPER& aGrid ) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const EDIT_POINT& m_constrainer; ///< Point that imposes the constraint.
|
const EDIT_POINT& m_constrainer; ///< Point that imposes the constraint.
|
||||||
|
@ -155,7 +169,7 @@ public:
|
||||||
EC_LINE( EDIT_POINT& aConstrained, const EDIT_POINT& aConstrainer );
|
EC_LINE( EDIT_POINT& aConstrained, const EDIT_POINT& aConstrainer );
|
||||||
|
|
||||||
///< @copydoc EDIT_CONSTRAINT::Apply()
|
///< @copydoc EDIT_CONSTRAINT::Apply()
|
||||||
virtual void Apply( EDIT_POINT& aHandle ) override;
|
virtual void Apply( EDIT_POINT& aHandle, const GRID_HELPER& aGrid ) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const EDIT_POINT& m_constrainer; ///< Point that imposes the constraint.
|
const EDIT_POINT& m_constrainer; ///< Point that imposes the constraint.
|
||||||
|
@ -175,11 +189,13 @@ public:
|
||||||
* @param aEnd is the point that decides on the radius of the circle.
|
* @param aEnd is the point that decides on the radius of the circle.
|
||||||
*/
|
*/
|
||||||
EC_CIRCLE( EDIT_POINT& aConstrained, const EDIT_POINT& aCenter, const EDIT_POINT& aEnd ) :
|
EC_CIRCLE( EDIT_POINT& aConstrained, const EDIT_POINT& aCenter, const EDIT_POINT& aEnd ) :
|
||||||
EDIT_CONSTRAINT<EDIT_POINT>( aConstrained ), m_center( aCenter ), m_end( aEnd )
|
EDIT_CONSTRAINT<EDIT_POINT>( aConstrained ),
|
||||||
|
m_center( aCenter ),
|
||||||
|
m_end( aEnd )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
///< @copydoc EDIT_CONSTRAINT::Apply()
|
///< @copydoc EDIT_CONSTRAINT::Apply()
|
||||||
virtual void Apply( EDIT_POINT& aHandle ) override;
|
virtual void Apply( EDIT_POINT& aHandle, const GRID_HELPER& aGrid ) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
///< Point that imposes the constraint (center of the circle).
|
///< Point that imposes the constraint (center of the circle).
|
||||||
|
@ -202,7 +218,7 @@ public:
|
||||||
virtual ~EC_CONVERGING();
|
virtual ~EC_CONVERGING();
|
||||||
|
|
||||||
///< @copydoc EDIT_CONSTRAINT::Apply()
|
///< @copydoc EDIT_CONSTRAINT::Apply()
|
||||||
virtual void Apply( EDIT_LINE& aHandle ) override;
|
virtual void Apply( EDIT_LINE& aHandle, const GRID_HELPER& aGrid ) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
///< Constraint for origin side segment.
|
///< Constraint for origin side segment.
|
||||||
|
@ -223,31 +239,6 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* #EDIT_CONSTRAINT for a EDIT_LINE, one of the ends is snapped to a spot determined by a
|
|
||||||
* transform function passed as parameter (e.g. it can be snapped to a grid), instead of having
|
|
||||||
* the line center snapped to a point.
|
|
||||||
*/
|
|
||||||
class EC_SNAPLINE : public EDIT_CONSTRAINT<EDIT_LINE>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
///< Typedef for a function that determines snapping point.
|
|
||||||
typedef std::function<VECTOR2D( const VECTOR2D& )> V2D_TRANSFORM_FUN;
|
|
||||||
|
|
||||||
EC_SNAPLINE( EDIT_LINE& aLine, V2D_TRANSFORM_FUN aSnapFun );
|
|
||||||
|
|
||||||
virtual ~EC_SNAPLINE()
|
|
||||||
{}
|
|
||||||
|
|
||||||
///< @copydoc EDIT_CONSTRAINT::Apply()
|
|
||||||
virtual void Apply( EDIT_LINE& aHandle ) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
///< Function that determines snapping point.
|
|
||||||
V2D_TRANSFORM_FUN m_snapFun;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* #EDIT_CONSTRAINT for a EDIT_LINE, that constrains the line to move perpendicular
|
* #EDIT_CONSTRAINT for a EDIT_LINE, that constrains the line to move perpendicular
|
||||||
* to the line itself.
|
* to the line itself.
|
||||||
|
@ -262,7 +253,7 @@ public:
|
||||||
{}
|
{}
|
||||||
|
|
||||||
///< @copydoc EDIT_CONSTRAINT::Apply()
|
///< @copydoc EDIT_CONSTRAINT::Apply()
|
||||||
virtual void Apply( EDIT_LINE& aHandle ) override;
|
virtual void Apply( EDIT_LINE& aHandle, const GRID_HELPER& aGrid ) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VECTOR2I m_mid;
|
VECTOR2I m_mid;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* This program source code file is part of KICAD, a free EDA CAD application.
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2014-2017 CERN
|
* Copyright (C) 2014-2017 CERN
|
||||||
* Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
* Copyright (C) 2020-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
*
|
*
|
||||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||||
*
|
*
|
||||||
|
@ -55,6 +55,7 @@ public:
|
||||||
m_isActive( false ),
|
m_isActive( false ),
|
||||||
m_isHover( false ),
|
m_isHover( false ),
|
||||||
m_gridConstraint( SNAP_TO_GRID ),
|
m_gridConstraint( SNAP_TO_GRID ),
|
||||||
|
m_snapConstraint( OBJECT_LAYERS ),
|
||||||
m_connected( aConnected )
|
m_connected( aConnected )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -162,10 +163,10 @@ public:
|
||||||
/**
|
/**
|
||||||
* Correct coordinates of an EDIT_POINT by applying previously set constraint.
|
* Correct coordinates of an EDIT_POINT by applying previously set constraint.
|
||||||
*/
|
*/
|
||||||
virtual void ApplyConstraint()
|
virtual void ApplyConstraint( const GRID_HELPER& aGrid )
|
||||||
{
|
{
|
||||||
if( m_constraint )
|
if( m_constraint )
|
||||||
m_constraint->Apply();
|
m_constraint->Apply( aGrid );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsActive() const { return m_isActive; }
|
bool IsActive() const { return m_isActive; }
|
||||||
|
@ -177,6 +178,9 @@ public:
|
||||||
GRID_CONSTRAINT_TYPE GetGridConstraint() const { return m_gridConstraint; }
|
GRID_CONSTRAINT_TYPE GetGridConstraint() const { return m_gridConstraint; }
|
||||||
void SetGridConstraint( GRID_CONSTRAINT_TYPE aConstraint ) { m_gridConstraint = aConstraint; }
|
void SetGridConstraint( GRID_CONSTRAINT_TYPE aConstraint ) { m_gridConstraint = aConstraint; }
|
||||||
|
|
||||||
|
SNAP_CONSTRAINT_TYPE GetSnapConstraint() const { return m_snapConstraint; }
|
||||||
|
void SetSnapConstraint( SNAP_CONSTRAINT_TYPE aConstraint ) { m_snapConstraint = aConstraint; }
|
||||||
|
|
||||||
bool operator==( const EDIT_POINT& aOther ) const
|
bool operator==( const EDIT_POINT& aOther ) const
|
||||||
{
|
{
|
||||||
return m_position == aOther.m_position;
|
return m_position == aOther.m_position;
|
||||||
|
@ -196,6 +200,7 @@ private:
|
||||||
bool m_isActive; ///< True if this point is being manipulated.
|
bool m_isActive; ///< True if this point is being manipulated.
|
||||||
bool m_isHover; ///< True if this point is being hovered over.
|
bool m_isHover; ///< True if this point is being hovered over.
|
||||||
GRID_CONSTRAINT_TYPE m_gridConstraint; ///< Describe the grid snapping behavior.
|
GRID_CONSTRAINT_TYPE m_gridConstraint; ///< Describe the grid snapping behavior.
|
||||||
|
SNAP_CONSTRAINT_TYPE m_snapConstraint; ///< Describe the object snapping behavior.
|
||||||
|
|
||||||
///< An optional connected item record used to mimic polyLine behavior with individual
|
///< An optional connected item record used to mimic polyLine behavior with individual
|
||||||
///< line segments.
|
///< line segments.
|
||||||
|
@ -243,13 +248,13 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
///< @copydoc EDIT_POINT::ApplyConstraint()
|
///< @copydoc EDIT_POINT::ApplyConstraint()
|
||||||
virtual void ApplyConstraint() override
|
virtual void ApplyConstraint( const GRID_HELPER& aGrid ) override
|
||||||
{
|
{
|
||||||
if( m_constraint )
|
if( m_constraint )
|
||||||
m_constraint->Apply();
|
m_constraint->Apply( aGrid );
|
||||||
|
|
||||||
m_origin.ApplyConstraint();
|
m_origin.ApplyConstraint( aGrid );
|
||||||
m_end.ApplyConstraint();
|
m_end.ApplyConstraint( aGrid );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -836,6 +836,16 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
|
||||||
grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
|
grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
|
||||||
grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
|
grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
|
||||||
|
|
||||||
|
if( step == SET_HEIGHT )
|
||||||
|
{
|
||||||
|
if( dimension->GetStart().x != dimension->GetEnd().x
|
||||||
|
&& dimension->GetStart().y != dimension->GetEnd().y )
|
||||||
|
{
|
||||||
|
// Not cardinal. Grid snapping doesn't make sense for height.
|
||||||
|
grid.SetUseGrid( false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VECTOR2I cursorPos = evt->HasPosition() ? evt->Position() : m_controls->GetMousePosition();
|
VECTOR2I cursorPos = evt->HasPosition() ? evt->Position() : m_controls->GetMousePosition();
|
||||||
|
|
||||||
cursorPos = grid.BestSnapAnchor( cursorPos, nullptr );
|
cursorPos = grid.BestSnapAnchor( cursorPos, nullptr );
|
||||||
|
|
|
@ -322,6 +322,9 @@ std::shared_ptr<EDIT_POINTS> PCB_POINT_EDITOR::makePoints( EDA_ITEM* aItem )
|
||||||
points->AddPoint( dimension->GetCrossbarStart() );
|
points->AddPoint( dimension->GetCrossbarStart() );
|
||||||
points->AddPoint( dimension->GetCrossbarEnd() );
|
points->AddPoint( dimension->GetCrossbarEnd() );
|
||||||
|
|
||||||
|
points->Point( DIM_START ).SetSnapConstraint( ALL_LAYERS );
|
||||||
|
points->Point( DIM_END ).SetSnapConstraint( ALL_LAYERS );
|
||||||
|
|
||||||
if( aItem->Type() == PCB_DIM_ALIGNED_T )
|
if( aItem->Type() == PCB_DIM_ALIGNED_T )
|
||||||
{
|
{
|
||||||
// Dimension height setting - edit points should move only along the feature lines
|
// Dimension height setting - edit points should move only along the feature lines
|
||||||
|
@ -344,8 +347,11 @@ std::shared_ptr<EDIT_POINTS> PCB_POINT_EDITOR::makePoints( EDA_ITEM* aItem )
|
||||||
points->AddPoint( dimension->GetStart() );
|
points->AddPoint( dimension->GetStart() );
|
||||||
points->AddPoint( dimension->GetEnd() );
|
points->AddPoint( dimension->GetEnd() );
|
||||||
|
|
||||||
|
points->Point( DIM_START ).SetSnapConstraint( ALL_LAYERS );
|
||||||
|
|
||||||
points->Point( DIM_END ).SetConstraint( new EC_45DEGREE( points->Point( DIM_END ),
|
points->Point( DIM_END ).SetConstraint( new EC_45DEGREE( points->Point( DIM_END ),
|
||||||
points->Point( DIM_START ) ) );
|
points->Point( DIM_START ) ) );
|
||||||
|
points->Point( DIM_END ).SetSnapConstraint( IGNORE_SNAPS );
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -360,12 +366,16 @@ std::shared_ptr<EDIT_POINTS> PCB_POINT_EDITOR::makePoints( EDA_ITEM* aItem )
|
||||||
points->AddPoint( dimension->Text().GetPosition() );
|
points->AddPoint( dimension->Text().GetPosition() );
|
||||||
points->AddPoint( dimension->GetKnee() );
|
points->AddPoint( dimension->GetKnee() );
|
||||||
|
|
||||||
|
points->Point( DIM_START ).SetSnapConstraint( ALL_LAYERS );
|
||||||
|
points->Point( DIM_END ).SetSnapConstraint( ALL_LAYERS );
|
||||||
|
|
||||||
points->Point( DIM_KNEE ).SetConstraint( new EC_LINE( points->Point( DIM_START ),
|
points->Point( DIM_KNEE ).SetConstraint( new EC_LINE( points->Point( DIM_START ),
|
||||||
points->Point( DIM_END ) ) );
|
points->Point( DIM_END ) ) );
|
||||||
|
points->Point( DIM_KNEE ).SetSnapConstraint( IGNORE_SNAPS );
|
||||||
|
|
||||||
points->Point( DIM_TEXT ).SetConstraint( new EC_45DEGREE( points->Point( DIM_TEXT ),
|
points->Point( DIM_TEXT ).SetConstraint( new EC_45DEGREE( points->Point( DIM_TEXT ),
|
||||||
points->Point( DIM_KNEE ) ) );
|
points->Point( DIM_KNEE ) ) );
|
||||||
points->Point( DIM_TEXT ).SetGridConstraint( IGNORE_GRID );
|
points->Point( DIM_TEXT ).SetSnapConstraint( IGNORE_SNAPS );
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -379,9 +389,12 @@ std::shared_ptr<EDIT_POINTS> PCB_POINT_EDITOR::makePoints( EDA_ITEM* aItem )
|
||||||
points->AddPoint( dimension->GetEnd() );
|
points->AddPoint( dimension->GetEnd() );
|
||||||
points->AddPoint( dimension->Text().GetPosition() );
|
points->AddPoint( dimension->Text().GetPosition() );
|
||||||
|
|
||||||
|
points->Point( DIM_START ).SetSnapConstraint( ALL_LAYERS );
|
||||||
|
points->Point( DIM_END ).SetSnapConstraint( ALL_LAYERS );
|
||||||
|
|
||||||
points->Point( DIM_TEXT ).SetConstraint( new EC_45DEGREE( points->Point( DIM_TEXT ),
|
points->Point( DIM_TEXT ).SetConstraint( new EC_45DEGREE( points->Point( DIM_TEXT ),
|
||||||
points->Point( DIM_END ) ) );
|
points->Point( DIM_END ) ) );
|
||||||
points->Point( DIM_TEXT ).SetGridConstraint( IGNORE_GRID );
|
points->Point( DIM_TEXT ).SetSnapConstraint( IGNORE_SNAPS );
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -470,10 +483,6 @@ int PCB_POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent )
|
||||||
bool lock45 = false;
|
bool lock45 = false;
|
||||||
|
|
||||||
BOARD_COMMIT commit( editFrame );
|
BOARD_COMMIT commit( editFrame );
|
||||||
LSET snapLayers = item->GetLayerSet();
|
|
||||||
|
|
||||||
if( BaseType( item->Type() ) == PCB_DIMENSION_T )
|
|
||||||
snapLayers = LSET::AllLayersMask();
|
|
||||||
|
|
||||||
// Main loop: keep receiving events
|
// Main loop: keep receiving events
|
||||||
while( TOOL_EVENT* evt = Wait() )
|
while( TOOL_EVENT* evt = Wait() )
|
||||||
|
@ -524,19 +533,16 @@ int PCB_POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent )
|
||||||
}
|
}
|
||||||
|
|
||||||
VECTOR2I pos = evt->Position();
|
VECTOR2I pos = evt->Position();
|
||||||
|
LSET snapLayers;
|
||||||
|
|
||||||
//TODO: unify the constraints to solve simultaneously instead of sequentially
|
switch( m_editedPoint->GetSnapConstraint() )
|
||||||
switch( m_editedPoint->GetGridConstraint() )
|
|
||||||
{
|
{
|
||||||
case IGNORE_GRID:
|
case IGNORE_SNAPS: break;
|
||||||
m_editedPoint->SetPosition( pos );
|
case OBJECT_LAYERS: snapLayers = item->GetLayerSet(); break;
|
||||||
break;
|
case ALL_LAYERS: snapLayers = LSET::AllLayersMask(); break;
|
||||||
|
}
|
||||||
|
|
||||||
case SNAP_TO_GRID:
|
if( m_editedPoint->GetGridConstraint() == SNAP_BY_GRID )
|
||||||
m_editedPoint->SetPosition( grid.BestSnapAnchor( pos, snapLayers, { item } ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SNAP_BY_GRID:
|
|
||||||
{
|
{
|
||||||
if( grid.GetUseGrid() )
|
if( grid.GetUseGrid() )
|
||||||
{
|
{
|
||||||
|
@ -544,31 +550,31 @@ int PCB_POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent )
|
||||||
|
|
||||||
VECTOR2I last = m_editedPoint->GetPosition();
|
VECTOR2I last = m_editedPoint->GetPosition();
|
||||||
VECTOR2I delta = pos - last;
|
VECTOR2I delta = pos - last;
|
||||||
VECTOR2I deltaGrid = gridPt - grid.BestSnapAnchor( last, {}, { item } );
|
|
||||||
|
|
||||||
if( abs( delta.x ) > grid.GetGrid().x / 2 )
|
if( abs( delta.x ) > grid.GetGrid().x / 2 )
|
||||||
pos.x = last.x + deltaGrid.x;
|
pos.x = last.x + ( grid.GetGrid().x * sign( delta.x ) );
|
||||||
else
|
else
|
||||||
pos.x = last.x;
|
pos.x = last.x;
|
||||||
|
|
||||||
if( abs( delta.y ) > grid.GetGrid().y / 2 )
|
if( abs( delta.y ) > grid.GetGrid().y / 2 )
|
||||||
pos.y = last.y + deltaGrid.y;
|
pos.y = last.y + ( grid.GetGrid().y * sign( delta.y ) );
|
||||||
else
|
else
|
||||||
pos.y = last.y;
|
pos.y = last.y;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_editedPoint->SetPosition( pos );
|
m_editedPoint->SetPosition( pos );
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The alternative constraint limits to 45 degrees
|
// The alternative constraint limits to 45 degrees
|
||||||
if( lock45 )
|
if( lock45 )
|
||||||
m_altConstraint->Apply();
|
{
|
||||||
else
|
m_altConstraint->Apply( grid );
|
||||||
m_editedPoint->ApplyConstraint();
|
}
|
||||||
|
else if( m_editedPoint->IsConstrained() )
|
||||||
if( m_editedPoint->GetGridConstraint() == SNAP_TO_GRID )
|
{
|
||||||
|
m_editedPoint->ApplyConstraint( grid );
|
||||||
|
}
|
||||||
|
else if( m_editedPoint->GetGridConstraint() == SNAP_TO_GRID )
|
||||||
{
|
{
|
||||||
m_editedPoint->SetPosition( grid.BestSnapAnchor( m_editedPoint->GetPosition(),
|
m_editedPoint->SetPosition( grid.BestSnapAnchor( m_editedPoint->GetPosition(),
|
||||||
snapLayers, { item } ) );
|
snapLayers, { item } ) );
|
||||||
|
|
Loading…
Reference in New Issue