From 7acc0b89f9bbbd59365bc3845b2f3fa827d509e9 Mon Sep 17 00:00:00 2001 From: John Beard Date: Thu, 12 Jul 2018 13:05:18 +0100 Subject: [PATCH] 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 --- include/geometry/geometry_utils.h | 41 +++++++++++++++++++ .../preview_items/two_point_geom_manager.h | 8 +--- pcbnew/tools/drawing_tool.cpp | 9 ++-- 3 files changed, 47 insertions(+), 11 deletions(-) diff --git a/include/geometry/geometry_utils.h b/include/geometry/geometry_utils.h index a2d4f1d3c4..bad991971a 100644 --- a/include/geometry/geometry_utils.h +++ b/include/geometry/geometry_utils.h @@ -30,6 +30,8 @@ #ifndef GEOMETRY_UTILS_H #define GEOMETRY_UTILS_H +#include + /** * @return the number of segments to approximate a arc by segments * 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 ); +/** + * 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 +VECTOR2 GetVectorSnapped45( const VECTOR2& aVec ) +{ + auto newVec = aVec; + const VECTOR2 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 diff --git a/include/preview_items/two_point_geom_manager.h b/include/preview_items/two_point_geom_manager.h index 4d218cb027..00f0002fc5 100644 --- a/include/preview_items/two_point_geom_manager.h +++ b/include/preview_items/two_point_geom_manager.h @@ -25,7 +25,7 @@ #define PREVIEW_ITEMS_TWO_POINT_GEOMETRY_MANAGER_H #include -#include +#include namespace KIGFX { @@ -63,11 +63,7 @@ public: { if( m_angleSnap ) { - const auto vec = aEnd - 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 ); + m_end = GetVectorSnapped45( aEnd - m_origin ) + m_origin; } else { diff --git a/pcbnew/tools/drawing_tool.cpp b/pcbnew/tools/drawing_tool.cpp index 89d67128f4..e30f85577d 100644 --- a/pcbnew/tools/drawing_tool.cpp +++ b/pcbnew/tools/drawing_tool.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -478,12 +479,10 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent ) void DRAWING_TOOL::constrainDimension( DIMENSION* dimension ) { - 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 ); + const VECTOR2I lineVector{ dimension->GetEnd() - dimension->GetOrigin() }; - dimension->SetEnd( dimension->GetOrigin() + static_cast( newLineVector ) ); + dimension->SetEnd( wxPoint( + VECTOR2I( dimension->GetOrigin() ) + GetVectorSnapped45( lineVector ) ) ); }