I have attached a patch-set that implements "partial selection" of objects when the selection box is dragged right-to-left.
L -> R = Objects must be completely enclosed to be selected R -> L = Objects that intersect the selection rectangle will be selected. To achieve this I had to fix a lot of the HitTest implementations as this was broken for most shapes, under a variety of edge cases (some HitTest code did not work at all). There are two issues I see as outstanding, and am unsure how to proceed: 1. When editing a PCB, selecting part of a footprint (e.g. a line of the courtyard) selects both that line and the entire footprint. This causes some issues when the footprint is dragged around the PCB. I believe that the line should not be selected separately, but the entire footprint should. 2. The inverse of 1. In the footprint editor, selecting a single graphical item selects the entire footprint. Somehow I would like to filter the selection such that individual items are selected but NOT the entire footprint. Feedback please! :) I have fixed hit testing (both for wxPoint and EDA_RECT comparison) for: - Pads (all shapes) - Lines - Circles - Arcs - Text items - Zones - Footprints Cheers, Oliver
From 688d986602189b24877dd3296f12d8adb2a5fd9f Mon Sep 17 00:00:00 2001 From: Oliver Walters <[email protected]> Date: Fri, 21 Apr 2017 00:20:56 +1000 Subject: [PATCH 01/12] Alter selection mode based on drag direction LEFT > RIGHT = Enclosed selection RIGHT > LEFT = Touching selection --- include/preview_items/selection_area.h | 4 ++++ pcbnew/tools/selection_tool.cpp | 37 ++++++++++++++++++++++++++++++---- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/include/preview_items/selection_area.h b/include/preview_items/selection_area.h index c860ee4..d45924b 100644 --- a/include/preview_items/selection_area.h +++ b/include/preview_items/selection_area.h @@ -76,6 +76,10 @@ public: return wxT( "SELECTION_AREA" ); } + VECTOR2I GetOrigin() const { return m_origin; } + + VECTOR2I GetEnd() const { return m_end; } + private: /** diff --git a/pcbnew/tools/selection_tool.cpp b/pcbnew/tools/selection_tool.cpp index 494fb1c..d31eee7 100644 --- a/pcbnew/tools/selection_tool.cpp +++ b/pcbnew/tools/selection_tool.cpp @@ -500,21 +500,50 @@ bool SELECTION_TOOL::selectMultiple() // Mark items within the selection box as selected std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> selectedItems; + + // Filter the view items based on the selection box BOX2I selectionBox = area.ViewBBox(); view->Query( selectionBox, selectedItems ); // Get the list of selected items std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR>::iterator it, it_end; + int width = area.GetEnd().x - area.GetOrigin().x; + int height = area.GetEnd().y - area.GetOrigin().y; + + // Construct an EDA_RECT to determine BOARD_ITEM selection + EDA_RECT selectionRect( wxPoint( area.GetOrigin().x, area.GetOrigin().y ), + wxSize( width, height ) ); + + selectionRect.Normalize(); + for( it = selectedItems.begin(), it_end = selectedItems.end(); it != it_end; ++it ) { BOARD_ITEM* item = static_cast<BOARD_ITEM*>( it->first ); - // Add only those items that are visible and fully within the selection box - if( !item->IsSelected() && selectable( item ) && - selectionBox.Contains( item->ViewBBox() ) ) + /* Selection mode depends on direction of drag-selection: + * Left > Right : Select objects that are fully enclosed by selection + * Right > Left : Select objects that are crossed by selection + */ + + // Add only those items that are visible + if( !item->IsSelected() && selectable( item ) ) { - select( item ); + if( item->HitTest( selectionRect, width >= 0) ) + { + select( item ); + } + } + /* + // Selecting left->right requires full enclosure + if ( xDelta >= 0 && selectionBox.Contains( item->ViewBBox() ) ) + { + select( item ); + } + + // Selecting right->left requires only + else if + */ } if( m_selection.Size() == 1 ) -- 2.7.4
From db7ac6f20c515c590b652284f4a59645f664beb1 Mon Sep 17 00:00:00 2001 From: Oliver Walters <[email protected]> Date: Fri, 21 Apr 2017 00:53:57 +1000 Subject: [PATCH 02/12] Fixed ::HitTest for Circle shape - Testing against rectangle intersection now works correctly - Previously tested against BoundingBox() not circle outline --- common/base_struct.cpp | 60 +++++++++++++++++++++++++++++++++++++++++ include/class_eda_rect.h | 30 +++++++++++++++++++++ pcbnew/class_drawsegment.cpp | 15 ++++++++++- pcbnew/tools/selection_tool.cpp | 16 +++++------ 4 files changed, 110 insertions(+), 11 deletions(-) diff --git a/common/base_struct.cpp b/common/base_struct.cpp index 76f51fb..8839ad8 100644 --- a/common/base_struct.cpp +++ b/common/base_struct.cpp @@ -443,6 +443,66 @@ bool EDA_RECT::Intersects( const EDA_RECT& aRect ) const return rc; } +const wxPoint EDA_RECT::ClosestPointTo( const wxPoint& aPoint ) const +{ + EDA_RECT me(*this); + + me.Normalize(); // ensure size is >= 0 + + // Determine closest point to the circle centre within this rect + int nx = std::max( me.GetLeft(), std::min( aPoint.x, me.GetRight() ) ); + int ny = std::max( me.GetTop(), std::min( aPoint.y, me.GetBottom() ) ); + + return wxPoint( nx, ny ); +} + +const wxPoint EDA_RECT::FarthestPointTo( const wxPoint& aPoint ) const +{ + EDA_RECT me(*this); + + me.Normalize(); // ensure size is >= 0 + + int fx = std::max( std::abs( aPoint.x - me.GetLeft() ), std::abs( aPoint.x - me.GetRight() ) ); + int fy = std::max( std::abs( aPoint.y - me.GetTop() ), std::abs( aPoint.y - me.GetBottom() ) ); + + return wxPoint( fx, fy ); +} + +/* IntersectsCircle + * test for common area between this rect and a circle + */ +bool EDA_RECT::IntersectsCircle( const wxPoint& aCenter, const int aRadius ) const +{ + wxPoint closest = ClosestPointTo( aCenter ); + + double dx = aCenter.x - closest.x; + double dy = aCenter.y - closest.y; + + double r = (double) aRadius; + + return ( dx * dx + dy * dy ) <= ( r * r ); +} + +bool EDA_RECT::IntersectsCircleEdge( const wxPoint& aCenter, const int aRadius, const int aWidth ) const +{ + EDA_RECT me(*this); + me.Normalize(); // ensure size is >= 0 + + // Test if the circle intersects at all + if( !IntersectsCircle( aCenter, aRadius + aWidth / 2 ) ) + { + return false; + } + + wxPoint far = FarthestPointTo( aCenter ); + // Farthest point must be further than the inside of the line + double fx = (double) far.x; + double fy = (double) far.y; + + double r = (double) aRadius - (double) aWidth / 2; + + return ( fx * fx + fy * fy ) > ( r * r ); +} EDA_RECT& EDA_RECT::Inflate( int aDelta ) { diff --git a/include/class_eda_rect.h b/include/class_eda_rect.h index 8849942..d9a67c1 100644 --- a/include/class_eda_rect.h +++ b/include/class_eda_rect.h @@ -169,6 +169,36 @@ public: bool Intersects( const wxPoint& aPoint1, const wxPoint& aPoint2 ) const; /** + * Return the point in this rect that is closest to the provided point + */ + const wxPoint ClosestPointTo( const wxPoint& aPoint ) const; + + /** + * Return the point in this rect that is farthest from the provided point + */ + const wxPoint FarthestPointTo( const wxPoint& aPoint ) const; + + /** + * Function IntersectsCircle + * tests for a common area between a circle and this rectangle + * + * @param aCenter center of the circle + * @param aRadius radius of the circle + */ + bool IntersectsCircle( const wxPoint& aCenter, const int aRadius ) const; + + + /** + * IntersectsCircleEdge + * Tests for intersection between this rect and the edge (radius) of a circle + * + * @param aCenter center of the circle + * @param aRadius radius of the circle + * @param aWidth width of the circle edge + */ + bool IntersectsCircleEdge( const wxPoint& aCenter, const int aRadius, const int aWidth ) const; + + /** * Function operator(wxRect) * overloads the cast operator to return a wxRect * wxRect does not accept negative values for size, so ensure the diff --git a/pcbnew/class_drawsegment.cpp b/pcbnew/class_drawsegment.cpp index 568c8be..89947ae 100644 --- a/pcbnew/class_drawsegment.cpp +++ b/pcbnew/class_drawsegment.cpp @@ -522,6 +522,8 @@ bool DRAWSEGMENT::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy EDA_RECT arect = aRect; arect.Inflate( aAccuracy ); + EDA_RECT arcRect; + switch( m_Shape ) { case S_CIRCLE: @@ -529,7 +531,18 @@ bool DRAWSEGMENT::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy if( aContained ) return arect.Contains( GetBoundingBox() ); else - return arect.Intersects( GetBoundingBox() ); + { + // If the rectangle does not intersect the bounding box, this is a much quicker test + if( !aRect.Intersects( GetBoundingBox() ) ) + { + return false; + } + else + { + return arect.IntersectsCircleEdge( GetCenter(), GetRadius(), GetWidth() ); + } + + } break; case S_ARC: diff --git a/pcbnew/tools/selection_tool.cpp b/pcbnew/tools/selection_tool.cpp index d31eee7..0ea9529 100644 --- a/pcbnew/tools/selection_tool.cpp +++ b/pcbnew/tools/selection_tool.cpp @@ -525,25 +525,21 @@ bool SELECTION_TOOL::selectMultiple() * Right > Left : Select objects that are crossed by selection */ - // Add only those items that are visible - if( !item->IsSelected() && selectable( item ) ) + if( width >= 0 ) { - if( item->HitTest( selectionRect, width >= 0) ) + if( selectionBox.Contains( item->ViewBBox() ) ) { select( item ); } - } - /* - // Selecting left->right requires full enclosure - if ( xDelta >= 0 && selectionBox.Contains( item->ViewBBox() ) ) + else + { + if( item->HitTest( selectionRect, false ) ) { select( item ); } - // Selecting right->left requires only - else if - */ + } } if( m_selection.Size() == 1 ) -- 2.7.4
From 58b8a4be78972b2d2890b4e3ab41024108d160eb Mon Sep 17 00:00:00 2001 From: Oliver Walters <[email protected]> Date: Sat, 22 Apr 2017 15:03:06 +1000 Subject: [PATCH 03/12] Fixed HitTest for Arc segment --- pcbnew/class_drawsegment.cpp | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/pcbnew/class_drawsegment.cpp b/pcbnew/class_drawsegment.cpp index 89947ae..c3fab97 100644 --- a/pcbnew/class_drawsegment.cpp +++ b/pcbnew/class_drawsegment.cpp @@ -516,9 +516,6 @@ bool DRAWSEGMENT::HitTest( const wxPoint& aPosition ) const bool DRAWSEGMENT::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const { - wxPoint p1, p2; - int radius; - float theta; EDA_RECT arect = aRect; arect.Inflate( aAccuracy ); @@ -546,24 +543,28 @@ bool DRAWSEGMENT::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy break; case S_ARC: - radius = hypot( (double)( GetEnd().x - GetStart().x ), - (double)( GetEnd().y - GetStart().y ) ); - theta = std::atan2( (double)( GetEnd().y - GetStart().y ), - (double)( GetEnd().x - GetStart().x ) ); - //Approximate the arc with two lines. This should be accurate enough for selection. - p1.x = radius * std::cos( theta + M_PI/4 ) + GetStart().x; - p1.y = radius * std::sin( theta + M_PI/4 ) + GetStart().y; - p2.x = radius * std::cos( theta + M_PI/2 ) + GetStart().x; - p2.y = radius * std::sin( theta + M_PI/2 ) + GetStart().y; + computeArcBBox( arcRect ); + // Test for full containment of this arc in the rect if( aContained ) - return arect.Contains( GetEnd() ) && aRect.Contains( p1 ) && aRect.Contains( p2 ); + { + return arect.Contains( arcRect ); + } + // Test if the rect crosses the arc else - return arect.Intersects( GetEnd(), p1 ) || aRect.Intersects( p1, p2 ); - + { + arcRect = arcRect.Common( arect ); + //arcRect.Inflate( GetWidth() ); + + /* All following tests must pass: + * 1. Rectangle must intersect arc BoundingBox + * 2. Rectangle must cross the outside of the arc + */ + return arcRect.Intersects( arect ) && + arcRect.IntersectsCircleEdge( GetCenter(), GetRadius(), GetWidth() ); + } break; - case S_SEGMENT: if( aContained ) return arect.Contains( GetStart() ) && aRect.Contains( GetEnd() ); -- 2.7.4
From 06ac9516a685e8727085a26e5efd560630a62fbe Mon Sep 17 00:00:00 2001 From: Oliver Walters <[email protected]> Date: Sat, 22 Apr 2017 16:49:15 +1000 Subject: [PATCH 04/12] HitTest for pads - Circular pads --- pcbnew/class_drawsegment.cpp | 1 + pcbnew/class_pad.cpp | 30 ++++++++++++++++++++++++++++++ pcbnew/class_pad.h | 2 ++ 3 files changed, 33 insertions(+) diff --git a/pcbnew/class_drawsegment.cpp b/pcbnew/class_drawsegment.cpp index c3fab97..53293ff 100644 --- a/pcbnew/class_drawsegment.cpp +++ b/pcbnew/class_drawsegment.cpp @@ -517,6 +517,7 @@ bool DRAWSEGMENT::HitTest( const wxPoint& aPosition ) const bool DRAWSEGMENT::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const { EDA_RECT arect = aRect; + arect.Normalize(); arect.Inflate( aAccuracy ); EDA_RECT arcRect; diff --git a/pcbnew/class_pad.cpp b/pcbnew/class_pad.cpp index 1d2b81a..ba17744 100644 --- a/pcbnew/class_pad.cpp +++ b/pcbnew/class_pad.cpp @@ -776,6 +776,36 @@ bool D_PAD::HitTest( const wxPoint& aPosition ) const return false; } +bool D_PAD::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const +{ + EDA_RECT arect = aRect; + arect.Normalize(); + arect.Inflate( aAccuracy ); + + if( !arect.Intersects( GetBoundingBox() ) ) + return false; + + if( aContained ) + return arect.Contains( GetBoundingBox() ); + + switch( GetShape() ) + { + case PAD_SHAPE_CIRCLE: + return arect.IntersectsCircle( GetPosition(), GetBoundingRadius() ); + case PAD_SHAPE_RECT: + break; + case PAD_SHAPE_OVAL: + break; + case PAD_SHAPE_TRAPEZOID: + break; + case PAD_SHAPE_ROUNDRECT: + break; + default: + break; + } + + return false; +} int D_PAD::Compare( const D_PAD* padref, const D_PAD* padcmp ) { diff --git a/pcbnew/class_pad.h b/pcbnew/class_pad.h index 4dd2233..53900dd 100644 --- a/pcbnew/class_pad.h +++ b/pcbnew/class_pad.h @@ -483,6 +483,8 @@ public: bool HitTest( const wxPoint& aPosition ) const override; + bool HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy = 0 ) const override; + wxString GetClass() const override { return wxT( "PAD" ); -- 2.7.4
From c47454c352a6f7f74383b7816bd7f2b46a81175c Mon Sep 17 00:00:00 2001 From: Oliver Walters <[email protected]> Date: Sun, 23 Apr 2017 10:06:56 +1000 Subject: [PATCH 05/12] HitTest for Rectangular pads HitTest for Rectangular pads - Works at any rotation, even with Shape Offset - Fixed bugs in D_PAD BoundingBox calculation --- common/base_struct.cpp | 104 +++++++++++++++++++++++++++++++++++++++++++ include/class_eda_rect.h | 9 ++++ pcbnew/class_drawsegment.cpp | 7 ++- pcbnew/class_pad.cpp | 30 +++++++++---- 4 files changed, 141 insertions(+), 9 deletions(-) diff --git a/common/base_struct.cpp b/common/base_struct.cpp index 8839ad8..e44d496 100644 --- a/common/base_struct.cpp +++ b/common/base_struct.cpp @@ -443,6 +443,110 @@ bool EDA_RECT::Intersects( const EDA_RECT& aRect ) const return rc; } +bool EDA_RECT::Intersects( const EDA_RECT& aRect, double aRot ) const +{ + /* Most rectangles will be axis aligned. + * It is quicker to check for this case and pass the rect + * to the simpler intersection test + */ + + // Prevent floating point comparison errors + static const double ROT_EPS = 0.000000001; + + static const double ROT_PARALLEL[] = { -3600, -1800, 0, 1800, 3600 }; + static const double ROT_PERPENDICULAR[] = { -2700, -900, 0, 900, 2700 }; + + NORMALIZE_ANGLE_POS<double>( aRot ); + + // Test for non-rotated rectangle + for( int ii=0; ii<5; ii++ ) + { + if( std::fabs( aRot - ROT_PARALLEL[ii] ) < ROT_EPS ) + { + return Intersects( aRect ); + } + } + + // Test for rectangle rotated by multiple of 90 degrees + for( int jj=0; jj<4; jj++ ) + { + if( std::fabs( aRot - ROT_PERPENDICULAR[jj] ) < ROT_EPS ) + { + EDA_RECT rotRect; + + // Rotate the supplied rect by 90 degrees + rotRect.SetOrigin( aRect.Centre() ); + rotRect.Inflate( aRect.GetHeight(), aRect.GetWidth() ); + return Intersects( rotRect ); + } + } + + /* There is some non-orthogonal rotation. + * There are three cases to test: + * A) One point of this rect is inside the rotated rect + * B) One point of the rotated rect is inside this rect + * C) One of the sides of the rotated rect intersect this + */ + + wxPoint corners[4]; + + /* Test A : Any corners exist in rotated rect? */ + + corners[0] = m_Pos; + corners[1] = m_Pos + wxPoint( m_Size.x, 0 ); + corners[2] = m_Pos + wxPoint( m_Size.x, m_Size.y ); + corners[3] = m_Pos + wxPoint( 0, m_Size.y ); + + wxPoint rCentre = aRect.Centre(); + + for( int i=0; i<4; i++ ) + { + wxPoint delta = corners[i] - rCentre; + RotatePoint( &delta, -aRot ); + delta += rCentre; + + if( aRect.Contains( delta ) ) + { + return true; + } + } + + /* Test B : Any corners of rotated rect exist in this one? */ + int w = aRect.GetWidth() / 2; + int h = aRect.GetHeight() / 2; + + // Construct corners around center of shape + corners[0] = wxPoint( -w, -h ); + corners[1] = wxPoint( w, -h ); + corners[2] = wxPoint( w, h ); + corners[3] = wxPoint( -w, h ); + + // Rotate and test each corner + for( int j=0; j<4; j++ ) + { + RotatePoint( &corners[j], aRot ); + corners[j] += rCentre; + + if( Contains( corners[j] ) ) + { + return true; + } + } + + /* Test C : Any sides of rotated rect intersect this */ + + if( Intersects( corners[0], corners[1] ) || + Intersects( corners[1], corners[2] ) || + Intersects( corners[2], corners[3] ) || + Intersects( corners[3], corners[0] ) ) + { + return true; + } + + + return false; +} + const wxPoint EDA_RECT::ClosestPointTo( const wxPoint& aPoint ) const { EDA_RECT me(*this); diff --git a/include/class_eda_rect.h b/include/class_eda_rect.h index d9a67c1..c14c3b1 100644 --- a/include/class_eda_rect.h +++ b/include/class_eda_rect.h @@ -158,6 +158,15 @@ public: bool Intersects( const EDA_RECT& aRect ) const; /** + * Tests for a common area between this rectangle, + * and a rectangle with arbitrary rotation + * + * @param aRect a rectangle to test intersection with + * @param aRot rectangle rotation (in 1/10 degrees) + */ + bool Intersects( const EDA_RECT& aRect, double aRot ) const; + + /** * Function Intersects * tests for a common area between a segment and this rectangle. * diff --git a/pcbnew/class_drawsegment.cpp b/pcbnew/class_drawsegment.cpp index 53293ff..30f234a 100644 --- a/pcbnew/class_drawsegment.cpp +++ b/pcbnew/class_drawsegment.cpp @@ -556,7 +556,6 @@ bool DRAWSEGMENT::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy else { arcRect = arcRect.Common( arect ); - //arcRect.Inflate( GetWidth() ); /* All following tests must pass: * 1. Rectangle must intersect arc BoundingBox @@ -568,9 +567,15 @@ bool DRAWSEGMENT::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy break; case S_SEGMENT: if( aContained ) + { return arect.Contains( GetStart() ) && aRect.Contains( GetEnd() ); + } else + { + // Account for the width of the line + arect.Inflate( GetWidth() / 2 ); return arect.Intersects( GetStart(), GetEnd() ); + } break; diff --git a/pcbnew/class_pad.cpp b/pcbnew/class_pad.cpp index ba17744..64d42c4 100644 --- a/pcbnew/class_pad.cpp +++ b/pcbnew/class_pad.cpp @@ -178,6 +178,9 @@ int D_PAD::GetRoundRectCornerRadius( const wxSize& aSize ) const } +/** + * Return the BoundingBox for a D_PAD + */ const EDA_RECT D_PAD::GetBoundingBox() const { EDA_RECT area; @@ -192,7 +195,7 @@ const EDA_RECT D_PAD::GetBoundingBox() const break; case PAD_SHAPE_OVAL: - // Calculate the position of each rounded ent + // Calculate the position of each rounded end quadrant1.x = m_Size.x/2; quadrant1.y = 0; quadrant2.x = 0; @@ -207,7 +210,7 @@ const EDA_RECT D_PAD::GetBoundingBox() const dy = std::max( std::abs( quadrant1.y ) , std::abs( quadrant2.y ) ); // Set the bbox - area.SetOrigin( m_Pos ); + area.SetOrigin( ShapePos() ); area.Inflate( dx, dy ); break; @@ -226,7 +229,7 @@ const EDA_RECT D_PAD::GetBoundingBox() const dy = std::max( std::abs( quadrant1.y ) , std::abs( quadrant2.y ) ); // Set the bbox - area.SetOrigin( m_Pos ); + area.SetOrigin( ShapePos() ); area.Inflate( dx, dy ); break; @@ -251,6 +254,7 @@ const EDA_RECT D_PAD::GetBoundingBox() const y = std::min( quadrant1.y, std::min( quadrant2.y, std::min( quadrant3.y, quadrant4.y) ) ); dx = std::max( quadrant1.x, std::max( quadrant2.x, std::max( quadrant3.x, quadrant4.x) ) ); dy = std::max( quadrant1.y, std::max( quadrant2.y, std::max( quadrant3.y, quadrant4.y) ) ); + area.SetOrigin( m_Pos.x+x, m_Pos.y+y ); area.SetSize( dx-x, dy-y ); break; @@ -782,18 +786,28 @@ bool D_PAD::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) con arect.Normalize(); arect.Inflate( aAccuracy ); - if( !arect.Intersects( GetBoundingBox() ) ) - return false; + EDA_RECT shapeRect; - if( aContained ) - return arect.Contains( GetBoundingBox() ); + shapeRect.SetOrigin( ShapePos() ); + shapeRect.Inflate( GetSize().x / 2, GetSize().y / 2 ); + + EDA_RECT bb = GetBoundingBox(); + + if( !arect.Intersects( bb ) ) + return false; + + int dist; + + // This covers total containment for all test cases + if( arect.Contains( bb ) ) + return true; switch( GetShape() ) { case PAD_SHAPE_CIRCLE: return arect.IntersectsCircle( GetPosition(), GetBoundingRadius() ); case PAD_SHAPE_RECT: - break; + return arect.Intersects( shapeRect, m_Orient ); case PAD_SHAPE_OVAL: break; case PAD_SHAPE_TRAPEZOID: -- 2.7.4
From 3cdd41b9de5f12b29ac203621f6b3aa5d466d52d Mon Sep 17 00:00:00 2001 From: Oliver Walters <[email protected]> Date: Mon, 24 Apr 2017 21:54:53 +1000 Subject: [PATCH 06/12] HitTest for Oval pads HitTest for Oval pads Required fix for GetBoundingBox method for Oval Pad shape --- pcbnew/class_pad.cpp | 137 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 116 insertions(+), 21 deletions(-) diff --git a/pcbnew/class_pad.cpp b/pcbnew/class_pad.cpp index 64d42c4..958e969 100644 --- a/pcbnew/class_pad.cpp +++ b/pcbnew/class_pad.cpp @@ -185,33 +185,79 @@ const EDA_RECT D_PAD::GetBoundingBox() const { EDA_RECT area; wxPoint quadrant1, quadrant2, quadrant3, quadrant4; - int x, y, dx, dy; + int x, y, r, dx, dy; + + wxPoint center = ShapePos(); + wxPoint endPoint; + + EDA_RECT endRect; switch( GetShape() ) { case PAD_SHAPE_CIRCLE: - area.SetOrigin( m_Pos ); + area.SetOrigin( center ); area.Inflate( m_Size.x / 2 ); break; case PAD_SHAPE_OVAL: - // Calculate the position of each rounded end - quadrant1.x = m_Size.x/2; - quadrant1.y = 0; - quadrant2.x = 0; - quadrant2.y = m_Size.y/2; + /* To get the BoundingBox of an oval pad: + * a) If the pad is ROUND, see method for PAD_SHAPE_CIRCLE above + * OTHERWISE: + * b) Construct EDA_RECT for portion between circular ends + * c) Rotate that EDA_RECT + * d) Add the circular ends to the EDA_RECT + */ + + // Test if the shape is circular + if( m_Size.x == m_Size.y ) + { + area.SetOrigin( center ); + area.Inflate( m_Size.x / 2 ); + break; + } - RotatePoint( &quadrant1, m_Orient ); - RotatePoint( &quadrant2, m_Orient ); + if( m_Size.x > m_Size.y ) + { + // Pad is horizontal + dx = ( m_Size.x - m_Size.y ) / 2; + dy = m_Size.y / 2; + + // Location of end-points + x = dx; + y = 0; + r = dy; + } + else + { + // Pad is vertical + dx = m_Size.x / 2; + dy = ( m_Size.y - m_Size.x ) / 2; - // Calculate the max position of each end, relative to the pad position - // (the min position is symetrical) - dx = std::max( std::abs( quadrant1.x ) , std::abs( quadrant2.x ) ); - dy = std::max( std::abs( quadrant1.y ) , std::abs( quadrant2.y ) ); + x = 0; + y = dy; + r = dx; + } - // Set the bbox - area.SetOrigin( ShapePos() ); + // Construct the center rectangle and rotate + area.SetOrigin( center ); area.Inflate( dx, dy ); + area = area.GetBoundingBoxRotated( center, m_Orient ); + + endPoint = wxPoint( x, y ); + RotatePoint( &endPoint, m_Orient ); + + // Add points at each quadrant of circular regions + endRect.SetOrigin( center + endPoint ); + endRect.Inflate( r ); + + area.Merge( endRect ); + + endRect.SetSize( 0, 0 ); + endRect.SetOrigin( center - endPoint ); + endRect.Inflate( r ); + + area.Merge( endRect ); + break; case PAD_SHAPE_RECT: @@ -786,17 +832,17 @@ bool D_PAD::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) con arect.Normalize(); arect.Inflate( aAccuracy ); - EDA_RECT shapeRect; + wxPoint shapePos = ShapePos(); - shapeRect.SetOrigin( ShapePos() ); - shapeRect.Inflate( GetSize().x / 2, GetSize().y / 2 ); + EDA_RECT shapeRect; EDA_RECT bb = GetBoundingBox(); - if( !arect.Intersects( bb ) ) - return false; + wxPoint endCenter; + int radius; - int dist; + if( !arect.Intersects( bb ) ) + return false; // This covers total containment for all test cases if( arect.Contains( bb ) ) @@ -807,8 +853,57 @@ bool D_PAD::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) con case PAD_SHAPE_CIRCLE: return arect.IntersectsCircle( GetPosition(), GetBoundingRadius() ); case PAD_SHAPE_RECT: + shapeRect.SetOrigin( shapePos ); + shapeRect.Inflate( m_Size.x / 2, m_Size.y / 2 ); return arect.Intersects( shapeRect, m_Orient ); case PAD_SHAPE_OVAL: + + // Circlular test if dimensions are equal + if( m_Size.x == m_Size.y ) + return arect.IntersectsCircle( shapePos, GetBoundingRadius() ); + + shapeRect.SetOrigin( shapePos ); + + // Horizontal dimension is greater + if( m_Size.x > m_Size.y ) + { + radius = m_Size.y / 2; + + shapeRect.Inflate( m_Size.x / 2 - radius, radius ); + + endCenter = wxPoint( m_Size.x / 2 - radius, 0 ); + RotatePoint( &endCenter, m_Orient ); + + // Test circular ends + if( arect.IntersectsCircle( shapePos + endCenter, radius ) || + arect.IntersectsCircle( shapePos - endCenter, radius ) ) + { + return true; + } + } + else + { + radius = m_Size.x / 2; + + shapeRect.Inflate( radius, m_Size.y / 2 - radius ); + + endCenter = wxPoint( 0, m_Size.y / 2 - radius ); + RotatePoint( &endCenter, m_Orient ); + + // Test circular ends + if( arect.IntersectsCircle( shapePos + endCenter, radius ) || + arect.IntersectsCircle( shapePos - endCenter, radius ) ) + { + return true; + } + } + + // Test rectangular portion between rounded ends + if( arect.Intersects( shapeRect, m_Orient ) ) + { + return true; + } + break; case PAD_SHAPE_TRAPEZOID: break; -- 2.7.4
From 428f0f4a2c5a62f0c3dc5ccec7c2ba517daf55da Mon Sep 17 00:00:00 2001 From: Oliver Walters <[email protected]> Date: Mon, 24 Apr 2017 22:54:44 +1000 Subject: [PATCH 07/12] HitTest for RoundRect pad --- pcbnew/class_pad.cpp | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/pcbnew/class_pad.cpp b/pcbnew/class_pad.cpp index 958e969..096d22f 100644 --- a/pcbnew/class_pad.cpp +++ b/pcbnew/class_pad.cpp @@ -749,7 +749,7 @@ void D_PAD::GetOblongDrillGeometry( wxPoint& aStartPoint, bool D_PAD::HitTest( const wxPoint& aPosition ) const { - int dx, dy; + int dx, dy; wxPoint shape_pos = ShapePos(); @@ -826,6 +826,9 @@ bool D_PAD::HitTest( const wxPoint& aPosition ) const return false; } +/** + * Test if an x,y axis-aligned rectangle hits this pad + */ bool D_PAD::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const { EDA_RECT arect = aRect; @@ -836,6 +839,8 @@ bool D_PAD::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) con EDA_RECT shapeRect; + int r; + EDA_RECT bb = GetBoundingBox(); wxPoint endCenter; @@ -908,6 +913,59 @@ bool D_PAD::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) con case PAD_SHAPE_TRAPEZOID: break; case PAD_SHAPE_ROUNDRECT: + /* RoundRect intersection can be broken up into simple tests: + * a) Test intersection of horizontal rect + * b) Test intersection of vertical rect + * c) Test intersection of each corner + */ + + + r = GetRoundRectCornerRadius(); + + /* Test A - intersection of horizontal rect */ + shapeRect.SetSize( 0, 0 ); + shapeRect.SetOrigin( shapePos ); + shapeRect.Inflate( m_Size.x / 2, m_Size.y / 2 - r ); + + // Short-circuit test for zero width or height + if( shapeRect.GetWidth() > 0 && shapeRect.GetHeight() > 0 && + arect.Intersects( shapeRect, m_Orient ) ) + { + return true; + } + + /* Test B - intersection of vertical rect */ + shapeRect.SetSize( 0, 0 ); + shapeRect.SetOrigin( shapePos ); + shapeRect.Inflate( m_Size.x / 2 - r, m_Size.y / 2 ); + + // Short-circuit test for zero width or height + if( shapeRect.GetWidth() > 0 && shapeRect.GetHeight() > 0 && + arect.Intersects( shapeRect, m_Orient ) ) + { + return true; + } + + /* Test C - intersection of each corner */ + + endCenter = wxPoint( m_Size.x / 2 - r, m_Size.y / 2 - r ); + RotatePoint( &endCenter, m_Orient ); + + if( arect.IntersectsCircle( shapePos + endCenter, r ) || + arect.IntersectsCircle( shapePos - endCenter, r ) ) + { + return true; + } + + endCenter = wxPoint( m_Size.x / 2 - r, -m_Size.y / 2 + r ); + RotatePoint( &endCenter, m_Orient ); + + if( arect.IntersectsCircle( shapePos + endCenter, r ) || + arect.IntersectsCircle( shapePos - endCenter, r ) ) + { + return true; + } + break; default: break; -- 2.7.4
From f6cd8ef81450ce1572982275197f3ecae3572751 Mon Sep 17 00:00:00 2001 From: Oliver Walters <[email protected]> Date: Wed, 26 Apr 2017 19:05:44 +1000 Subject: [PATCH 08/12] HitTest for trapezoid pad --- pcbnew/class_pad.cpp | 54 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/pcbnew/class_pad.cpp b/pcbnew/class_pad.cpp index 096d22f..300e642 100644 --- a/pcbnew/class_pad.cpp +++ b/pcbnew/class_pad.cpp @@ -280,14 +280,18 @@ const EDA_RECT D_PAD::GetBoundingBox() const break; case PAD_SHAPE_TRAPEZOID: - //Use the four corners and track their rotation + // Use the four corners and track their rotation // (Trapezoids will not be symmetric) + quadrant1.x = (m_Size.x + m_DeltaSize.y)/2; quadrant1.y = (m_Size.y - m_DeltaSize.x)/2; + quadrant2.x = -(m_Size.x + m_DeltaSize.y)/2; quadrant2.y = (m_Size.y + m_DeltaSize.x)/2; + quadrant3.x = -(m_Size.x - m_DeltaSize.y)/2; quadrant3.y = -(m_Size.y + m_DeltaSize.x)/2; + quadrant4.x = (m_Size.x - m_DeltaSize.y)/2; quadrant4.y = -(m_Size.y - m_DeltaSize.x)/2; @@ -301,7 +305,7 @@ const EDA_RECT D_PAD::GetBoundingBox() const dx = std::max( quadrant1.x, std::max( quadrant2.x, std::max( quadrant3.x, quadrant4.x) ) ); dy = std::max( quadrant1.y, std::max( quadrant2.y, std::max( quadrant3.y, quadrant4.y) ) ); - area.SetOrigin( m_Pos.x+x, m_Pos.y+y ); + area.SetOrigin( ShapePos().x + x, ShapePos().y + y ); area.SetSize( dx-x, dy-y ); break; @@ -777,6 +781,7 @@ bool D_PAD::HitTest( const wxPoint& aPosition ) const wxPoint poly[4]; BuildPadPolygon( poly, wxSize(0,0), 0 ); RotatePoint( &delta, -m_Orient ); + return TestPointInsidePolygon( poly, 4, delta ); } @@ -911,7 +916,50 @@ bool D_PAD::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) con break; case PAD_SHAPE_TRAPEZOID: - break; + /* Trapezoid intersection tests: + * A) Any points of rect inside trapezoid + * B) Any points of trapezoid inside rect + * C) Any sides of trapezoid cross rect + */ + { + + wxPoint poly[4]; + BuildPadPolygon( poly, wxSize( 0, 0 ), 0 ); + + wxPoint corners[4]; + + corners[0] = wxPoint( arect.GetLeft(), arect.GetTop() ); + corners[1] = wxPoint( arect.GetRight(), arect.GetTop() ); + corners[2] = wxPoint( arect.GetRight(), arect.GetBottom() ); + corners[3] = wxPoint( arect.GetLeft(), arect.GetBottom() ); + + for( int i=0; i<4; i++ ) + { + RotatePoint( &poly[i], m_Orient ); + poly[i] += shapePos; + } + + for( int ii=0; ii<4; ii++ ) + { + if( TestPointInsidePolygon( poly, 4, corners[ii] ) ) + { + return true; + } + + if( arect.Contains( poly[ii] ) ) + { + return true; + } + + if( arect.Intersects( poly[ii], poly[(ii+1) % 4] ) ) + { + return true; + } + } + + return false; + + } case PAD_SHAPE_ROUNDRECT: /* RoundRect intersection can be broken up into simple tests: * a) Test intersection of horizontal rect -- 2.7.4
From cb1b21a9e33f9bf85ff2131a0cd05d5fc8c118c4 Mon Sep 17 00:00:00 2001 From: Oliver Walters <[email protected]> Date: Wed, 26 Apr 2017 22:38:41 +1000 Subject: [PATCH 09/12] Updated HitTest for PCB_TEXT and TEXT_MOD --- pcbnew/class_pcb_text.h | 4 ++-- pcbnew/class_text_mod.cpp | 19 ------------------- pcbnew/class_text_mod.h | 10 +++++++++- 3 files changed, 11 insertions(+), 22 deletions(-) diff --git a/pcbnew/class_pcb_text.h b/pcbnew/class_pcb_text.h index 3a2e0e5..ae54a6a 100644 --- a/pcbnew/class_pcb_text.h +++ b/pcbnew/class_pcb_text.h @@ -81,7 +81,7 @@ public: void GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ) override; - bool HitTest( const wxPoint& aPosition ) const override + virtual bool HitTest( const wxPoint& aPosition ) const override { return TextHitTest( aPosition ); } @@ -89,7 +89,7 @@ public: /** @copydoc BOARD_ITEM::HitTest(const EDA_RECT& aRect, * bool aContained = true, int aAccuracy ) const */ - bool HitTest( const EDA_RECT& aRect, bool aContained = true, int aAccuracy = 0 ) const override + virtual bool HitTest( const EDA_RECT& aRect, bool aContained = true, int aAccuracy = 0 ) const override { return TextHitTest( aRect, aContained, aAccuracy ); } diff --git a/pcbnew/class_text_mod.cpp b/pcbnew/class_text_mod.cpp index 0e6bbb7..8aec446 100644 --- a/pcbnew/class_text_mod.cpp +++ b/pcbnew/class_text_mod.cpp @@ -181,25 +181,6 @@ void TEXTE_MODULE::SetLocalCoord() } } - -bool TEXTE_MODULE::HitTest( const wxPoint& aPosition ) const -{ - wxPoint rel_pos; - EDA_RECT area = GetTextBox( -1, -1 ); - - /* Rotate refPos to - angle to test if refPos is within area (which - * is relative to an horizontal text) - */ - rel_pos = aPosition; - RotatePoint( &rel_pos, GetTextPos(), -GetDrawRotation() ); - - if( area.Contains( rel_pos ) ) - return true; - - return false; -} - - const EDA_RECT TEXTE_MODULE::GetBoundingBox() const { double angle = GetDrawRotation(); diff --git a/pcbnew/class_text_mod.h b/pcbnew/class_text_mod.h index df07ac8..9c4c9ae 100644 --- a/pcbnew/class_text_mod.h +++ b/pcbnew/class_text_mod.h @@ -184,7 +184,15 @@ public: void GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ) override; - bool HitTest( const wxPoint& aPosition ) const override; + virtual bool HitTest( const wxPoint& aPosition ) const override + { + return TextHitTest( aPosition ); + } + + virtual bool HitTest( const EDA_RECT& aRect, bool aContained = false, int aAccuracy = 0 ) const override + { + return TextHitTest( aRect, aContained, aAccuracy ); + } wxString GetClass() const override { -- 2.7.4
From 81202eefe9330817e8e0e0cf6b1ac60b3720cfcc Mon Sep 17 00:00:00 2001 From: Oliver Walters <[email protected]> Date: Mon, 1 May 2017 22:10:24 +1000 Subject: [PATCH 10/12] Fixed HitTest for ZONE_CONTAINER --- pcbnew/class_zone.cpp | 55 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/pcbnew/class_zone.cpp b/pcbnew/class_zone.cpp index ccaa1db..48aa445 100644 --- a/pcbnew/class_zone.cpp +++ b/pcbnew/class_zone.cpp @@ -539,53 +539,62 @@ bool ZONE_CONTAINER::HitTestForEdge( const wxPoint& refPos ) const bool ZONE_CONTAINER::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const { - // Convert to BOX2I - BOX2I aBox = aRect; - aBox.Inflate( aAccuracy ); - BOX2I bbox = m_Poly->BBox(); + // Calculate bounding box for zone + EDA_RECT bbox = GetBoundingBox(); bbox.Normalize(); + EDA_RECT arect = aRect; + arect.Normalize(); + arect.Inflate( aAccuracy ); + if( aContained ) - return aBox.Contains( bbox ); + { + return arect.Contains( bbox ); + } else // Test for intersection between aBox and the polygon // For a polygon, using its bounding box has no sense here { // Fast test: if aBox is outside the polygon bounding box, // rectangles cannot intersect - if( ! bbox.Intersects( aBox ) ) + if( !arect.Intersects( bbox ) ) return false; // aBox is inside the polygon bounding box, // and can intersect the polygon: use a fine test. // aBox intersects the polygon if at least one aBox corner // is inside the polygon - wxPoint corner = static_cast<wxPoint>( aBox.GetOrigin() ); - - if( HitTestInsideZone( corner ) ) - return true; - - corner.x = aBox.GetEnd().x; - - if( HitTestInsideZone( corner ) ) - return true; - - corner = static_cast<wxPoint>( aBox.GetEnd() ); - - if( HitTestInsideZone( corner ) ) - return true; + wxPoint origin = arect.GetOrigin(); - corner.x = aBox.GetOrigin().x; + int w = arect.GetWidth(); + int h = arect.GetHeight(); - if( HitTestInsideZone( corner ) ) + if ( HitTestInsideZone( origin ) || + HitTestInsideZone( origin + wxPoint( w, 0 ) ) || + HitTestInsideZone( origin + wxPoint( w, h ) ) || + HitTestInsideZone( origin + wxPoint( 0, h ) ) ) + { return true; + } // No corner inside aBox, but outlines can intersect aBox // if one of outline corners is inside aBox int count = m_Poly->TotalVertices(); for( int ii =0; ii < count; ii++ ) { - if( aBox.Contains( m_Poly->Vertex( ii ) ) ) + auto vertex = m_Poly->Vertex( ii ); + auto vertexNext = m_Poly->Vertex( ( ii + 1 ) % count ); + + // Test if the point is within the rect + if( arect.Contains( ( wxPoint ) vertex ) ) + { return true; + } + + // Test if this edge intersects the rect + if( arect.Intersects( ( wxPoint ) vertex, ( wxPoint ) vertexNext ) ) + { + return true; + } } return false; -- 2.7.4
From a19355b9e87ed81de3e66297719bb52758da2208 Mon Sep 17 00:00:00 2001 From: Oliver Walters <[email protected]> Date: Tue, 2 May 2017 16:44:41 +1000 Subject: [PATCH 11/12] Fixed HitTest for text and modules --- include/eda_text.h | 4 ++-- pcbnew/class_module.cpp | 22 +++++++++++++++++++++- pcbnew/class_text_mod.cpp | 29 +++++++++++++++++++++++++++++ pcbnew/class_text_mod.h | 4 ++++ 4 files changed, 56 insertions(+), 3 deletions(-) diff --git a/include/eda_text.h b/include/eda_text.h index a20aacc..e0bbf59 100644 --- a/include/eda_text.h +++ b/include/eda_text.h @@ -260,7 +260,7 @@ public: * @param aAccuracy - Amount to inflate the bounding box. * @return bool - true if a hit, else false */ - bool TextHitTest( const wxPoint& aPoint, int aAccuracy = 0 ) const; + virtual bool TextHitTest( const wxPoint& aPoint, int aAccuracy = 0 ) const; /** * Function TextHitTest (overloaded) @@ -271,7 +271,7 @@ public: * @param aAccuracy - Amount to inflate the bounding box. * @return bool - true if a hit, else false */ - bool TextHitTest( const EDA_RECT& aRect, bool aContains = false, int aAccuracy = 0 ) const; + virtual bool TextHitTest( const EDA_RECT& aRect, bool aContains = false, int aAccuracy = 0 ) const; /** * Function LenSize diff --git a/pcbnew/class_module.cpp b/pcbnew/class_module.cpp index ecfcd9a..b79ae81 100644 --- a/pcbnew/class_module.cpp +++ b/pcbnew/class_module.cpp @@ -614,7 +614,27 @@ bool MODULE::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) co if( aContained ) return arect.Contains( m_BoundaryBox ); else - return m_BoundaryBox.Intersects( arect ); + { + // If the rect does not intersect the bounding box, skip any tests + if( !aRect.Intersects( GetBoundingBox() ) ) + return false; + + // Determine if any elements in the MODULE intersect the rect + for( D_PAD* pad = m_Pads; pad; pad = pad->Next() ) + { + if( pad->HitTest( arect, false, 0 ) ) + return true; + } + + for( BOARD_ITEM* item = m_Drawings; item; item = item->Next() ) + { + if( item->HitTest( arect, false, 0 ) ) + return true; + } + + // No items were hit + return false; + } } diff --git a/pcbnew/class_text_mod.cpp b/pcbnew/class_text_mod.cpp index 8aec446..9d807b5 100644 --- a/pcbnew/class_text_mod.cpp +++ b/pcbnew/class_text_mod.cpp @@ -89,6 +89,35 @@ void TEXTE_MODULE::SetTextAngle( double aAngle ) EDA_TEXT::SetTextAngle( NormalizeAngle360( aAngle ) ); } +bool TEXTE_MODULE::TextHitTest( const wxPoint& aPoint, int aAccuracy ) const +{ + EDA_RECT rect = GetTextBox( -1 ); + wxPoint location = aPoint; + + rect.Inflate( aAccuracy ); + + RotatePoint( &location, GetTextPos(), -GetDrawRotation() ); + + return rect.Contains( location ); +} + +bool TEXTE_MODULE::TextHitTest( const EDA_RECT& aRect, bool aContains, int aAccuracy ) const +{ + EDA_RECT rect = aRect; + + rect.Inflate( aAccuracy ); + + if( aContains ) + { + return rect.Contains( GetBoundingBox() ); + } + else + { + return rect.Intersects( GetTextBox( -1 ), GetDrawRotation() ); + } + +} + void TEXTE_MODULE::Rotate( const wxPoint& aRotCentre, double aAngle ) { diff --git a/pcbnew/class_text_mod.h b/pcbnew/class_text_mod.h index 9c4c9ae..80d24b7 100644 --- a/pcbnew/class_text_mod.h +++ b/pcbnew/class_text_mod.h @@ -184,6 +184,10 @@ public: void GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ) override; + virtual bool TextHitTest( const wxPoint& aPoint, int aAccuracy = 0 ) const override; + + virtual bool TextHitTest( const EDA_RECT& aRect, bool aContains = false, int aAccuracy = 0 ) const override; + virtual bool HitTest( const wxPoint& aPosition ) const override { return TextHitTest( aPosition ); -- 2.7.4
From ad33940b358b4aaf07e98b2e2101d5eb3b184c9c Mon Sep 17 00:00:00 2001 From: Oliver Walters <[email protected]> Date: Tue, 2 May 2017 17:14:07 +1000 Subject: [PATCH 12/12] Adjusted selection for ZONE --- pcbnew/class_zone.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pcbnew/class_zone.cpp b/pcbnew/class_zone.cpp index 48aa445..0c4f4e3 100644 --- a/pcbnew/class_zone.cpp +++ b/pcbnew/class_zone.cpp @@ -563,11 +563,14 @@ bool ZONE_CONTAINER::HitTest( const EDA_RECT& aRect, bool aContained, int aAccur // and can intersect the polygon: use a fine test. // aBox intersects the polygon if at least one aBox corner // is inside the polygon + + /* wxPoint origin = arect.GetOrigin(); int w = arect.GetWidth(); int h = arect.GetHeight(); + if ( HitTestInsideZone( origin ) || HitTestInsideZone( origin + wxPoint( w, 0 ) ) || HitTestInsideZone( origin + wxPoint( w, h ) ) || @@ -575,6 +578,7 @@ bool ZONE_CONTAINER::HitTest( const EDA_RECT& aRect, bool aContained, int aAccur { return true; } + */ // No corner inside aBox, but outlines can intersect aBox // if one of outline corners is inside aBox -- 2.7.4
_______________________________________________ Mailing list: https://launchpad.net/~kicad-developers Post to : [email protected] Unsubscribe : https://launchpad.net/~kicad-developers More help : https://help.launchpad.net/ListHelp

