Pcbnew: fix 45-degree snapping of ruler and dimension tools

This introduces a new util function in geometry_utils which snaps a vector
to axes or 45 degree lines. This can be used whenever you want to
snap a vector to these angles, but still want it to stay on a grid.

This snapping is used for the dimension tool and the ruler tool.

This is substantially simpler for two-point tools that the method
used by the line tool, which uses DIRECTION_45.

Fixes: lp:1780826
https://bugs.launchpad.net/kicad/+bug/1780826
This commit is contained in:
John Beard 2018-07-12 13:05:18 +01:00 committed by Jeff Young
parent 9d15e58462
commit 7acc0b89f9
3 changed files with 47 additions and 11 deletions

View File

@ -30,6 +30,8 @@
#ifndef GEOMETRY_UTILS_H #ifndef GEOMETRY_UTILS_H
#define GEOMETRY_UTILS_H #define GEOMETRY_UTILS_H
#include <math/vector2d.h>
/** /**
* @return the number of segments to approximate a arc by segments * @return the number of segments to approximate a arc by segments
* with a given max error (this number is >= 1) * with a given max error (this number is >= 1)
@ -53,6 +55,45 @@ int GetArcToSegmentCount( int aRadius, int aErrorMax, double aArcAngleDegree );
*/ */
double GetCircletoPolyCorrectionFactor( int aSegCountforCircle ); double GetCircletoPolyCorrectionFactor( int aSegCountforCircle );
/**
* Snap a vector onto the nearest 0, 45 or 90 degree line.
*
* The magnitude of the vector is NOT kept, instead the co-ordinates are
* set equal (and/or opposite) or to zero as needed. The effect of this is
* that if the starting vector is on a square grid, the resulting snapped
* vector will still be on the same grid.
* @param a vector to be snapped
* @return the snapped vector
*/
template<typename T>
VECTOR2<T> GetVectorSnapped45( const VECTOR2<T>& aVec )
{
auto newVec = aVec;
const VECTOR2<T> absVec { std::abs( aVec.x ), std::abs( aVec.y ) };
if ( absVec.x > absVec.y * 2 )
{
// snap along x-axis
newVec.y = 0;
}
else if ( absVec.y > absVec.x * 2 )
{
// snap onto y-axis
newVec.x = 0;
}
else if ( absVec.x > absVec.y )
{
// snap away from x-axis towards 45
newVec.y = std::copysign( aVec.x, aVec.y );
} else
{
// snap away from y-axis towards 45
newVec.x = std::copysign( aVec.y, aVec.x );
}
return newVec;
}
#endif // #ifndef GEOMETRY_UTILS_H #endif // #ifndef GEOMETRY_UTILS_H

View File

@ -25,7 +25,7 @@
#define PREVIEW_ITEMS_TWO_POINT_GEOMETRY_MANAGER_H #define PREVIEW_ITEMS_TWO_POINT_GEOMETRY_MANAGER_H
#include <math/vector2d.h> #include <math/vector2d.h>
#include <common.h> #include <geometry/geometry_utils.h>
namespace KIGFX namespace KIGFX
{ {
@ -63,11 +63,7 @@ public:
{ {
if( m_angleSnap ) if( m_angleSnap )
{ {
const auto vec = aEnd - m_origin; m_end = GetVectorSnapped45( aEnd - m_origin ) + m_origin;
const auto len = vec.EuclideanNorm();
const auto angle = KiROUND( vec.Angle() / M_PI_4 ) * M_PI_4;
m_end = m_origin + VECTOR2I( len, 0 ).Rotate( angle );
} }
else else
{ {

View File

@ -40,6 +40,7 @@
#include <gal/graphics_abstraction_layer.h> #include <gal/graphics_abstraction_layer.h>
#include <tool/tool_manager.h> #include <tool/tool_manager.h>
#include <geometry/direction45.h> #include <geometry/direction45.h>
#include <geometry/geometry_utils.h>
#include <ratsnest_data.h> #include <ratsnest_data.h>
#include <board_commit.h> #include <board_commit.h>
#include <scoped_set_reset.h> #include <scoped_set_reset.h>
@ -478,12 +479,10 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent )
void DRAWING_TOOL::constrainDimension( DIMENSION* dimension ) void DRAWING_TOOL::constrainDimension( DIMENSION* dimension )
{ {
VECTOR2I lineVector( dimension->GetEnd() - dimension->GetOrigin() ); const VECTOR2I lineVector{ dimension->GetEnd() - dimension->GetOrigin() };
double angle = lineVector.Angle();
double newAngle = KiROUND( angle / M_PI_4 ) * M_PI_4;
VECTOR2I newLineVector = lineVector.Rotate( newAngle - angle );
dimension->SetEnd( dimension->GetOrigin() + static_cast<wxPoint>( newLineVector ) ); dimension->SetEnd( wxPoint(
VECTOR2I( dimension->GetOrigin() ) + GetVectorSnapped45( lineVector ) ) );
} }