← Back to team overview

kicad-developers team mailing list archive

[PATCH] GerbView: More accurate selection of arc shapes

 

This patch implements accurate hit testing for arc shapes.  Previously,
they were just checked against their bounding box, which creates annoying
rates of false positives in some scenarios (with round board outlines, for
example)

-Jon
From 79af644bbfea071528b4d85c4ff48b353019d8b1 Mon Sep 17 00:00:00 2001
From: Jon Evans <jon@xxxxxxxxxxxxx>
Date: Tue, 27 Feb 2018 22:17:42 -0500
Subject: [PATCH] GerbView: More accurate selection of arc shapes

---
 gerbview/gerber_draw_item.cpp | 37 ++++++++++++++++++++++++++++++++++++-
 include/trigo.h               | 10 ++++++++++
 2 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/gerbview/gerber_draw_item.cpp b/gerbview/gerber_draw_item.cpp
index d6df6d55b..18c8ba850 100644
--- a/gerbview/gerber_draw_item.cpp
+++ b/gerbview/gerber_draw_item.cpp
@@ -769,9 +769,44 @@ bool GERBER_DRAW_ITEM::HitTest( const wxPoint& aRefPos ) const
         return poly.Contains( VECTOR2I( ref_pos ), 0 );
 
     case GBR_SPOT_RECT:
-    case GBR_ARC:
         return GetBoundingBox().Contains( aRefPos );
 
+    case GBR_ARC:
+        {
+            double radius = GetLineLength( m_Start, m_ArcCentre );
+            VECTOR2D test_radius = VECTOR2D( ref_pos ) - VECTOR2D( m_ArcCentre );
+
+            // Are we within m_Size.x of the radius?
+            bool radius_hit = ( std::fabs( test_radius.EuclideanNorm() - radius) < m_Size.x );
+
+            if( radius_hit )
+            {
+                // Now check that we are within the arc angle
+
+                VECTOR2D start = VECTOR2D( m_Start ) - VECTOR2D( m_ArcCentre );
+                VECTOR2D end = VECTOR2D( m_End ) - VECTOR2D( m_ArcCentre );
+
+                double start_angle = NormalizeAngleRadiansPos( start.Angle() );
+                double end_angle = NormalizeAngleRadiansPos( end.Angle() );
+
+                if( m_Start == m_End )
+                {
+                    start_angle = 0;
+                    end_angle = 2 * M_PI;
+                }
+                else if( end_angle < start_angle )
+                {
+                    end_angle += 2 * M_PI;
+                }
+
+                double test_angle = NormalizeAngleRadiansPos( test_radius.Angle() );
+
+                return ( test_angle > start_angle && test_angle < end_angle );
+            }
+
+            return false;
+        }
+
     case GBR_SPOT_MACRO:
         // Aperture macro polygons are already in absolute coordinates
         auto p = GetDcodeDescr()->GetMacro()->GetApertureMacroShape( this, m_Start );
diff --git a/include/trigo.h b/include/trigo.h
index 5cb93f93b..f8da175bf 100644
--- a/include/trigo.h
+++ b/include/trigo.h
@@ -261,6 +261,16 @@ inline void NORMALIZE_ANGLE_DEGREES_POS( double& Angle )
     Angle = NormalizeAngleDegreesPos( Angle );
 }
 
+
+inline double NormalizeAngleRadiansPos( double Angle )
+{
+    while( Angle < 0 )
+        Angle += (2 * M_PI );
+    while( Angle >= ( 2 * M_PI ) )
+        Angle -= ( 2 * M_PI );
+    return Angle;
+}
+
 /// Add two angles (keeping the result normalized). T2 is here
 // because most of the time it's an int (and templates don't promote in
 // that way)
-- 
2.14.1


Follow ups