Pcbnew: Block selection enhancement, from Bug #593997 (whishlist)
1. block created from-left-to-right selects only 100%inside selection objects (as it now does) 2.block created from-right-to-left selects all overlapping objects inside selection From the patch sent by mathieulj (mathieulj), and some fixes and code cleaning.
This commit is contained in:
parent
d5ecafd5af
commit
e9713bb291
|
@ -320,6 +320,36 @@ bool EDA_RECT::Contains( const EDA_RECT& aRect ) const
|
|||
}
|
||||
|
||||
|
||||
/* Intersects
|
||||
* test for a common area between segment and rect.
|
||||
* return true if at least a common point is found
|
||||
*/
|
||||
bool EDA_RECT::Intersects( const wxPoint& aPoint1, const wxPoint& aPoint2 ) const
|
||||
{
|
||||
wxPoint point2, point4;
|
||||
|
||||
if( Contains( aPoint1 ) || Contains( aPoint2 ) )
|
||||
return true;
|
||||
|
||||
point2.x = GetEnd().x;
|
||||
point2.y = GetOrigin().y;
|
||||
point4.x = GetOrigin().x;
|
||||
point4.y = GetEnd().y;
|
||||
|
||||
//Only need to test 3 sides since a straight line cant enter and exit on same side
|
||||
if( SegmentIntersectsSegment( aPoint1, aPoint2, GetOrigin() , point2 ) )
|
||||
return true;
|
||||
|
||||
if( SegmentIntersectsSegment( aPoint1, aPoint2, point2 , GetEnd() ) )
|
||||
return true;
|
||||
|
||||
if( SegmentIntersectsSegment( aPoint1, aPoint2, GetEnd() , point4 ) )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* Intersects
|
||||
* test for a common area between 2 rect.
|
||||
* return true if at least a common point is found
|
||||
|
|
|
@ -9,6 +9,71 @@
|
|||
#include <common.h>
|
||||
#include <math_for_graphics.h>
|
||||
|
||||
|
||||
bool SegmentIntersectsSegment( const wxPoint &a_p1_l1, const wxPoint &a_p2_l1,
|
||||
const wxPoint &a_p1_l2, const wxPoint &a_p2_l2 )
|
||||
{
|
||||
|
||||
//We are forced to use 64bit ints because the internal units can oveflow 32bit ints when
|
||||
// multiplied with each other, the alternative would be to scale the units down (i.e. divide
|
||||
// by a fixed number).
|
||||
long long dX_a, dY_a, dX_b, dY_b, dX_ab, dY_ab;
|
||||
long long num_a, num_b, den;
|
||||
|
||||
//Test for intersection within the bounds of both line segments using line equations of the
|
||||
// form:
|
||||
// x_k(u_k) = u_k * dX_k + x_k(0)
|
||||
// y_k(u_k) = u_k * dY_k + y_k(0)
|
||||
// with 0 <= u_k <= 1 and k = [ a, b ]
|
||||
|
||||
dX_a = a_p2_l1.x - a_p1_l1.x;
|
||||
dY_a = a_p2_l1.y - a_p1_l1.y;
|
||||
dX_b = a_p2_l2.x - a_p1_l2.x;
|
||||
dY_b = a_p2_l2.y - a_p1_l2.y;
|
||||
dX_ab = a_p1_l2.x - a_p1_l1.x;
|
||||
dY_ab = a_p1_l2.y - a_p1_l1.y;
|
||||
|
||||
den = dY_a * dX_b - dY_b * dX_a ;
|
||||
|
||||
//Check if lines are parallel
|
||||
if( den == 0 )
|
||||
return false;
|
||||
|
||||
num_a = dY_ab * dX_b - dY_b * dX_ab;
|
||||
num_b = dY_ab * dX_a - dY_a * dX_ab;
|
||||
|
||||
//We wont calculate directly the u_k of the intersection point to avoid floating point
|
||||
// division but they could be calculated with:
|
||||
// u_a = (float) num_a / (float) den;
|
||||
// u_b = (float) num_b / (float) den;
|
||||
|
||||
if( den < 0 )
|
||||
{
|
||||
den = -den;
|
||||
num_a = -num_a;
|
||||
num_b = -num_b;
|
||||
}
|
||||
|
||||
//Test sign( u_a ) and return false if negative
|
||||
if( num_a < 0 )
|
||||
return false;
|
||||
|
||||
//Test sign( u_b ) and return false if negative
|
||||
if( num_b < 0 )
|
||||
return false;
|
||||
|
||||
//Test to ensure (u_a <= 1)
|
||||
if( num_a > den )
|
||||
return false;
|
||||
|
||||
//Test to ensure (u_b <= 1)
|
||||
if( num_b > den )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Function TestSegmentHit
|
||||
* test for hit on line segment
|
||||
* i.e. a reference point is within a given distance from segment
|
||||
|
@ -29,7 +94,7 @@ static inline double square( int x ) // helper function to calculate x*x
|
|||
{
|
||||
return (double) x * x;
|
||||
}
|
||||
bool TestSegmentHit( const wxPoint &aRefPoint, wxPoint aStart,
|
||||
bool TestSegmentHit( const wxPoint &aRefPoint, wxPoint aStart,
|
||||
wxPoint aEnd, int aDist )
|
||||
{
|
||||
// test for vertical or horizontal segment
|
||||
|
@ -163,7 +228,7 @@ double ArcTangente( int dy, int dx )
|
|||
|
||||
/* gcc is surprisingly smart in optimizing these conditions in
|
||||
a tree! */
|
||||
|
||||
|
||||
if( dx == 0 && dy == 0 )
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -300,11 +300,25 @@ public:
|
|||
|
||||
/**
|
||||
* Function Intersects
|
||||
* tests for a common area between rectangles.
|
||||
*
|
||||
* @param aRect A rectangle to test intersection with.
|
||||
* @return bool - true if the argument rectangle intersects this rectangle.
|
||||
* (i.e. if the 2 rectangles have at least a common point)
|
||||
*/
|
||||
bool Intersects( const EDA_RECT& aRect ) const;
|
||||
|
||||
/**
|
||||
* Function Intersects
|
||||
* tests for a common area between a segment and this rectangle.
|
||||
*
|
||||
* @param aPoint1 First point of the segment to test intersection with.
|
||||
* @param aPoint2 Second point of the segment to test intersection with.
|
||||
* @return bool - true if the argument segment intersects this rectangle.
|
||||
* (i.e. if the segment and rectangle have at least a common point)
|
||||
*/
|
||||
bool Intersects( const wxPoint& aPoint1, const wxPoint& aPoint2 ) const;
|
||||
|
||||
/**
|
||||
* Function operator(wxRect)
|
||||
* overloads the cast operator to return a wxRect
|
||||
|
@ -530,18 +544,6 @@ public:
|
|||
return false; // derived classes should override this function
|
||||
}
|
||||
|
||||
/**
|
||||
* Function HitTest
|
||||
* tests if the \a aRect intersects this object.
|
||||
* For now, an ending point must be inside \a aRect.
|
||||
*
|
||||
* @param aRect A reference to an EDA_RECT object containg the area to test.
|
||||
* @return True if \a aRect intersects the object, otherwise false.
|
||||
*/
|
||||
virtual bool HitTest( const EDA_RECT& aRect ) const
|
||||
{
|
||||
return false; // derived classes should override this function
|
||||
}
|
||||
|
||||
/**
|
||||
* Function GetBoundingBox
|
||||
|
|
|
@ -223,6 +223,26 @@ public:
|
|||
*/
|
||||
wxString GetLayerName() const;
|
||||
|
||||
virtual bool HitTest( const wxPoint& aPosition )
|
||||
{
|
||||
return EDA_ITEM::HitTest( aPosition );
|
||||
}
|
||||
|
||||
/**
|
||||
* Function HitTest
|
||||
* tests if the \a aRect intersects or contains this object (depending on \a aContained).
|
||||
*
|
||||
* @param aRect A reference to an EDA_RECT object containg the area to test.
|
||||
* @param aContained Test if \a aRect contains this object completly.
|
||||
* @param aAccuracy Increase the item bounding box by this amount.
|
||||
* @return bool - True if \a aRect contains this object completly or if \a aRect intersects
|
||||
* the object and \a aContained is False, otherwise false.
|
||||
*/
|
||||
virtual bool HitTest( const EDA_RECT& aRect, bool aContained = true, int aAccuracy = 0) const
|
||||
{
|
||||
return false; // derived classes should override this function
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function FormatInternalUnits
|
||||
|
|
|
@ -31,6 +31,19 @@
|
|||
#include <math.h>
|
||||
#include <wx/gdicmn.h> // For wxPoint
|
||||
|
||||
/**
|
||||
* Function SegmentIntersectsSegment
|
||||
*
|
||||
* @param a_p1_l1 The first point of the first line.
|
||||
* @param a_p2_l1 The second point of the first line.
|
||||
* @param a_p1_l2 The first point of the second line.
|
||||
* @param a_p2_l2 The second point of the second line.
|
||||
* @return bool - true if the two segments defined by four points intersect.
|
||||
* (i.e. if the 2 segments have at least a common point)
|
||||
*/
|
||||
bool SegmentIntersectsSegment( const wxPoint &a_p1_l1, const wxPoint &a_p2_l1,
|
||||
const wxPoint &a_p1_l2, const wxPoint &a_p2_l2 );
|
||||
|
||||
/*
|
||||
* Calculate the new point of coord coord pX, pY,
|
||||
* for a rotation center 0, 0, and angle in (1 / 10 degree)
|
||||
|
|
|
@ -382,6 +382,7 @@ bool PCB_EDIT_FRAME::HandleBlockEnd( wxDC* DC )
|
|||
void PCB_EDIT_FRAME::Block_SelectItems()
|
||||
{
|
||||
LAYER_MSK layerMask;
|
||||
bool selectOnlyComplete = GetScreen()->m_BlockLocate.GetWidth() > 0 ;
|
||||
|
||||
GetScreen()->m_BlockLocate.Normalize();
|
||||
|
||||
|
@ -395,7 +396,7 @@ void PCB_EDIT_FRAME::Block_SelectItems()
|
|||
{
|
||||
LAYER_NUM layer = module->GetLayer();
|
||||
|
||||
if( module->HitTest( GetScreen()->m_BlockLocate )
|
||||
if( module->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete )
|
||||
&& ( !module->IsLocked() || blockIncludeLockedModules ) )
|
||||
{
|
||||
if( blockIncludeItemsOnInvisibleLayers || m_Pcb->IsModuleLayerVisible( layer ) )
|
||||
|
@ -410,14 +411,14 @@ void PCB_EDIT_FRAME::Block_SelectItems()
|
|||
// Add tracks and vias
|
||||
if( blockIncludeTracks )
|
||||
{
|
||||
for( TRACK* pt_segm = m_Pcb->m_Track; pt_segm != NULL; pt_segm = pt_segm->Next() )
|
||||
for( TRACK* track = m_Pcb->m_Track; track != NULL; track = track->Next() )
|
||||
{
|
||||
if( pt_segm->HitTest( GetScreen()->m_BlockLocate ) )
|
||||
if( track->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete ) )
|
||||
{
|
||||
if( blockIncludeItemsOnInvisibleLayers
|
||||
|| m_Pcb->IsLayerVisible( pt_segm->GetLayer() ) )
|
||||
|| m_Pcb->IsLayerVisible( track->GetLayer() ) )
|
||||
{
|
||||
picker.SetItem ( pt_segm );
|
||||
picker.SetItem ( track );
|
||||
itemsList->PushItem( picker );
|
||||
}
|
||||
}
|
||||
|
@ -446,7 +447,7 @@ void PCB_EDIT_FRAME::Block_SelectItems()
|
|||
if( (GetLayerMask( PtStruct->GetLayer() ) & layerMask) == 0 )
|
||||
break;
|
||||
|
||||
if( !PtStruct->HitTest( GetScreen()->m_BlockLocate ) )
|
||||
if( !PtStruct->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete ) )
|
||||
break;
|
||||
|
||||
select_me = true; // This item is in bloc: select it
|
||||
|
@ -456,7 +457,7 @@ void PCB_EDIT_FRAME::Block_SelectItems()
|
|||
if( !blockIncludePcbTexts )
|
||||
break;
|
||||
|
||||
if( !PtStruct->HitTest( GetScreen()->m_BlockLocate ) )
|
||||
if( !PtStruct->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete ) )
|
||||
break;
|
||||
|
||||
select_me = true; // This item is in bloc: select it
|
||||
|
@ -466,7 +467,7 @@ void PCB_EDIT_FRAME::Block_SelectItems()
|
|||
if( ( GetLayerMask( PtStruct->GetLayer() ) & layerMask ) == 0 )
|
||||
break;
|
||||
|
||||
if( !PtStruct->HitTest( GetScreen()->m_BlockLocate ) )
|
||||
if( !PtStruct->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete ) )
|
||||
break;
|
||||
|
||||
select_me = true; // This item is in bloc: select it
|
||||
|
@ -476,7 +477,7 @@ void PCB_EDIT_FRAME::Block_SelectItems()
|
|||
if( ( GetLayerMask( PtStruct->GetLayer() ) & layerMask ) == 0 )
|
||||
break;
|
||||
|
||||
if( !PtStruct->HitTest( GetScreen()->m_BlockLocate ) )
|
||||
if( !PtStruct->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete ) )
|
||||
break;
|
||||
|
||||
select_me = true; // This item is in bloc: select it
|
||||
|
@ -500,7 +501,7 @@ void PCB_EDIT_FRAME::Block_SelectItems()
|
|||
{
|
||||
ZONE_CONTAINER* area = m_Pcb->GetArea( ii );
|
||||
|
||||
if( area->HitTest( GetScreen()->m_BlockLocate ) )
|
||||
if( area->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete ) )
|
||||
{
|
||||
if( blockIncludeItemsOnInvisibleLayers
|
||||
|| m_Pcb->IsLayerVisible( area->GetLayer() ) )
|
||||
|
|
|
@ -430,12 +430,19 @@ bool DIMENSION::HitTest( const wxPoint& aPosition )
|
|||
}
|
||||
|
||||
|
||||
bool DIMENSION::HitTest( const EDA_RECT& aRect ) const
|
||||
bool DIMENSION::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
|
||||
{
|
||||
if( aRect.Contains( GetPosition() ) )
|
||||
return true;
|
||||
EDA_RECT arect = aRect;
|
||||
arect.Inflate( aAccuracy );
|
||||
|
||||
return false;
|
||||
EDA_RECT rect = GetBoundingBox();
|
||||
if( aAccuracy )
|
||||
rect.Inflate( aAccuracy );
|
||||
|
||||
if( aContained )
|
||||
return arect.Contains( rect );
|
||||
|
||||
return arect.Intersects( rect );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -129,7 +129,10 @@ public:
|
|||
|
||||
bool HitTest( const wxPoint& aPosition );
|
||||
|
||||
bool HitTest( const EDA_RECT& aRect ) const;
|
||||
/** @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;
|
||||
|
||||
wxString GetClass() const
|
||||
{
|
||||
|
|
|
@ -494,30 +494,48 @@ bool DRAWSEGMENT::HitTest( const wxPoint& aPosition )
|
|||
}
|
||||
|
||||
|
||||
bool DRAWSEGMENT::HitTest( const EDA_RECT& aRect ) 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 );
|
||||
|
||||
switch( m_Shape )
|
||||
{
|
||||
case S_CIRCLE:
|
||||
{
|
||||
int radius = GetRadius();
|
||||
|
||||
// Text if area intersects the circle:
|
||||
EDA_RECT area = aRect;
|
||||
area.Inflate( radius );
|
||||
|
||||
if( area.Contains( m_Start ) )
|
||||
return true;
|
||||
}
|
||||
// Test if area intersects or contains the circle:
|
||||
if( aContained )
|
||||
return arect.Contains( GetBoundingBox() );
|
||||
else
|
||||
return arect.Intersects( GetBoundingBox() );
|
||||
break;
|
||||
|
||||
case S_ARC:
|
||||
case S_SEGMENT:
|
||||
if( aRect.Contains( GetStart() ) )
|
||||
return true;
|
||||
radius = hypot( (double)( GetEnd().x - GetStart().x ),
|
||||
(double)( GetEnd().y - GetStart().y ) );
|
||||
theta = std::atan2( GetEnd().y - GetStart().y , 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;
|
||||
|
||||
if( aContained )
|
||||
return arect.Contains( GetEnd() ) && aRect.Contains( p1 ) && aRect.Contains( p2 );
|
||||
else
|
||||
return arect.Intersects( GetEnd(), p1 ) || aRect.Intersects( p1, p2 );
|
||||
|
||||
break;
|
||||
|
||||
case S_SEGMENT:
|
||||
if( aContained )
|
||||
return arect.Contains( GetStart() ) && aRect.Contains( GetEnd() );
|
||||
else
|
||||
return arect.Intersects( GetStart(), GetEnd() );
|
||||
|
||||
if( aRect.Contains( GetEnd() ) )
|
||||
return true;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -172,7 +172,10 @@ public:
|
|||
|
||||
virtual bool HitTest( const wxPoint& aPosition );
|
||||
|
||||
virtual bool HitTest( const EDA_RECT& aRect ) const;
|
||||
/** @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;
|
||||
|
||||
wxString GetClass() const
|
||||
{
|
||||
|
|
|
@ -178,10 +178,15 @@ bool PCB_TARGET::HitTest( const wxPoint& aPosition )
|
|||
}
|
||||
|
||||
|
||||
bool PCB_TARGET::HitTest( const EDA_RECT& aRect ) const
|
||||
bool PCB_TARGET::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
|
||||
{
|
||||
if( aRect.Contains( m_Pos ) )
|
||||
return true;
|
||||
EDA_RECT arect = aRect;
|
||||
arect.Inflate( aAccuracy );
|
||||
|
||||
if( aContained )
|
||||
return arect.Contains( GetBoundingBox() );
|
||||
else
|
||||
return GetBoundingBox().Intersects( arect );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -93,7 +93,10 @@ public:
|
|||
|
||||
bool HitTest( const wxPoint& aPosition );
|
||||
|
||||
bool HitTest( const EDA_RECT& aRect ) const;
|
||||
/** @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;
|
||||
|
||||
EDA_RECT GetBoundingBox() const;
|
||||
|
||||
|
|
|
@ -555,21 +555,15 @@ bool MODULE::HitTest( const wxPoint& aPosition )
|
|||
}
|
||||
|
||||
|
||||
bool MODULE::HitTest( const EDA_RECT& aRect ) const
|
||||
bool MODULE::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
|
||||
{
|
||||
if( m_BoundaryBox.GetX() < aRect.GetX() )
|
||||
return false;
|
||||
EDA_RECT arect = aRect;
|
||||
arect.Inflate( aAccuracy );
|
||||
|
||||
if( m_BoundaryBox.GetY() < aRect.GetY() )
|
||||
return false;
|
||||
|
||||
if( m_BoundaryBox.GetRight() > aRect.GetRight() )
|
||||
return false;
|
||||
|
||||
if( m_BoundaryBox.GetBottom() > aRect.GetBottom() )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
if( aContained )
|
||||
return arect.Contains( m_BoundaryBox );
|
||||
else
|
||||
return m_BoundaryBox.Intersects( arect );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -318,7 +318,10 @@ public:
|
|||
|
||||
bool HitTest( const wxPoint& aPosition );
|
||||
|
||||
bool HitTest( const EDA_RECT& aRect ) const;
|
||||
/** @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;
|
||||
|
||||
/**
|
||||
* Function GetReference
|
||||
|
|
|
@ -71,9 +71,12 @@ public:
|
|||
return TextHitTest( aPosition );
|
||||
}
|
||||
|
||||
bool HitTest( const EDA_RECT& aRect ) const
|
||||
/** @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
|
||||
{
|
||||
return TextHitTest( aRect );
|
||||
return TextHitTest( aRect, aContained, aAccuracy );
|
||||
}
|
||||
|
||||
wxString GetClass() const
|
||||
|
|
|
@ -1186,15 +1186,32 @@ bool TRACK::HitTest( const wxPoint& aPosition )
|
|||
}
|
||||
|
||||
|
||||
bool TRACK::HitTest( const EDA_RECT& aRect ) const
|
||||
bool TRACK::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
|
||||
{
|
||||
if( aRect.Contains( m_Start ) )
|
||||
return true;
|
||||
EDA_RECT box;
|
||||
EDA_RECT arect = aRect;
|
||||
arect.Inflate( aAccuracy );
|
||||
|
||||
if( aRect.Contains( m_End ) )
|
||||
return true;
|
||||
if( Type() == PCB_VIA_T )
|
||||
{
|
||||
box.SetOrigin( GetStart() );
|
||||
box.Inflate( GetWidth() >> 1 );
|
||||
|
||||
return false;
|
||||
if(aContained)
|
||||
return arect.Contains( box );
|
||||
else
|
||||
return arect.Intersects( box );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( aContained )
|
||||
// Tracks are a specila case:
|
||||
// they are considered inside the rect if one end
|
||||
// is inside the rect
|
||||
return arect.Contains( GetStart() ) || arect.Contains( GetEnd() );
|
||||
else
|
||||
return arect.Intersects( GetStart(), GetEnd() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -257,7 +257,10 @@ public:
|
|||
|
||||
virtual bool HitTest( const wxPoint& aPosition );
|
||||
|
||||
virtual bool HitTest( const EDA_RECT& aRect ) const;
|
||||
/** @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;
|
||||
|
||||
/**
|
||||
* Function GetVia
|
||||
|
|
|
@ -557,25 +557,61 @@ bool ZONE_CONTAINER::HitTestForEdge( const wxPoint& refPos )
|
|||
}
|
||||
|
||||
|
||||
bool ZONE_CONTAINER::HitTest( const EDA_RECT& aRect ) const
|
||||
bool ZONE_CONTAINER::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
|
||||
{
|
||||
bool is_out_of_box = false;
|
||||
EDA_RECT arect = aRect;
|
||||
arect.Inflate( aAccuracy );
|
||||
CRect rect = m_Poly->GetBoundingBox();
|
||||
EDA_RECT bbox;
|
||||
|
||||
CRect rect = m_Poly->GetCornerBounds();
|
||||
bbox.SetOrigin( rect.left, rect.bottom );
|
||||
bbox.SetEnd( rect.right, rect.top );
|
||||
|
||||
if( rect.left < aRect.GetX() )
|
||||
is_out_of_box = true;
|
||||
if( aContained )
|
||||
return arect.Contains( bbox );
|
||||
else // Test for intersection between aRect and the polygon
|
||||
// For a polygon, using its bounding box has no sense here
|
||||
{
|
||||
// Fast test: if aRect is outside the polygon bounding box,
|
||||
// rectangles cannot intersect
|
||||
if( ! bbox.Intersects( arect ) )
|
||||
return false;
|
||||
|
||||
if( rect.top < aRect.GetY() )
|
||||
is_out_of_box = true;
|
||||
// aRect is inside the polygon bounding box,
|
||||
// and can intersect the polygon: use a fine test.
|
||||
// aRect intersects the polygon if at least one aRect corner
|
||||
// is inside the polygon
|
||||
wxPoint corner = arect.GetOrigin();
|
||||
|
||||
if( rect.right > aRect.GetRight() )
|
||||
is_out_of_box = true;
|
||||
if( HitTestInsideZone( corner ) )
|
||||
return true;
|
||||
|
||||
if( rect.bottom > aRect.GetBottom() )
|
||||
is_out_of_box = true;
|
||||
corner.x = arect.GetEnd().x;
|
||||
|
||||
return is_out_of_box ? false : true;
|
||||
if( HitTestInsideZone( corner ) )
|
||||
return true;
|
||||
|
||||
corner = arect.GetEnd();
|
||||
|
||||
if( HitTestInsideZone( corner ) )
|
||||
return true;
|
||||
|
||||
corner.x = arect.GetOrigin().x;
|
||||
|
||||
if( HitTestInsideZone( corner ) )
|
||||
return true;
|
||||
|
||||
// No corner inside arect, but outlines can intersect arect
|
||||
// if one of outline corners is inside arect
|
||||
int count = m_Poly->GetCornersCount();
|
||||
for( int ii =0; ii < count; ii++ )
|
||||
{
|
||||
if( arect.Contains( m_Poly->GetPos( ii ) ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -151,7 +151,7 @@ public:
|
|||
void DrawWhileCreateOutline( EDA_DRAW_PANEL* panel, wxDC* DC,
|
||||
GR_DRAWMODE draw_mode = GR_OR );
|
||||
|
||||
/* Function GetBoundingBox
|
||||
/** Function GetBoundingBox
|
||||
* @return an EDA_RECT that is the bounding box of the zone outline
|
||||
*/
|
||||
EDA_RECT GetBoundingBox() const;
|
||||
|
@ -253,8 +253,26 @@ public:
|
|||
|
||||
void SetOutline( CPolyLine* aOutline ) { m_Poly = aOutline; }
|
||||
|
||||
/**
|
||||
* Function HitTest
|
||||
* tests if a point is near an outline edge or a corner of this zone.
|
||||
* @param aRefPos A wxPoint to test
|
||||
* @return bool - true if a hit, else false
|
||||
*/
|
||||
virtual bool HitTest( const wxPoint& aPosition );
|
||||
|
||||
/**
|
||||
* Function HitTest
|
||||
* tests if a point is inside the zone area, i.e. inside the main outline
|
||||
* and outside holes.
|
||||
* @param aRefPos A wxPoint to test
|
||||
* @return bool - true if a hit, else false
|
||||
*/
|
||||
bool HitTestInsideZone( const wxPoint& aPosition ) const
|
||||
{
|
||||
return m_Poly->TestPointInside( aPosition.x, aPosition.y );
|
||||
}
|
||||
|
||||
/**
|
||||
* Function HitTestFilledArea
|
||||
* tests if the given wxPoint is within the bounds of a filled area of this zone.
|
||||
|
@ -360,7 +378,10 @@ public:
|
|||
*/
|
||||
bool HitTestForEdge( const wxPoint& refPos );
|
||||
|
||||
virtual bool HitTest( const EDA_RECT& aRect ) const;
|
||||
/** @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;
|
||||
|
||||
/**
|
||||
* Function Fill_Zone
|
||||
|
|
|
@ -102,7 +102,7 @@ bool BOARD::CombineAllAreasInNet( PICKED_ITEMS_LIST* aDeletedList, int aNetCode,
|
|||
continue;
|
||||
|
||||
// legal polygon
|
||||
CRect b1 = curr_area->Outline()->GetCornerBounds();
|
||||
CRect b1 = curr_area->Outline()->GetBoundingBox();
|
||||
bool mod_ia1 = false;
|
||||
|
||||
for( unsigned ia2 = m_ZoneDescriptorList.size() - 1; ia2 > ia1; ia2-- )
|
||||
|
@ -121,7 +121,7 @@ bool BOARD::CombineAllAreasInNet( PICKED_ITEMS_LIST* aDeletedList, int aNetCode,
|
|||
if( curr_area->GetLayer() != area2->GetLayer() )
|
||||
continue;
|
||||
|
||||
CRect b2 = area2->Outline()->GetCornerBounds();
|
||||
CRect b2 = area2->Outline()->GetBoundingBox();
|
||||
|
||||
if( !( b1.left > b2.right || b1.right < b2.left
|
||||
|| b1.bottom > b2.top || b1.top < b2.bottom ) )
|
||||
|
@ -194,8 +194,8 @@ bool BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area
|
|||
CPolyLine* poly2 = area_to_test->Outline();
|
||||
|
||||
// test bounding rects
|
||||
CRect b1 = poly1->GetCornerBounds();
|
||||
CRect b2 = poly2->GetCornerBounds();
|
||||
CRect b1 = poly1->GetBoundingBox();
|
||||
CRect b2 = poly2->GetBoundingBox();
|
||||
|
||||
if( b1.bottom > b2.top || b1.top < b2.bottom ||
|
||||
b1.left > b2.right || b1.right < b2.left )
|
||||
|
|
|
@ -582,14 +582,7 @@ int CPolyLine::GetEndContour( int ic )
|
|||
}
|
||||
|
||||
|
||||
CRect CPolyLine::GetBounds()
|
||||
{
|
||||
CRect r = GetCornerBounds();
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
CRect CPolyLine::GetCornerBounds()
|
||||
CRect CPolyLine::GetBoundingBox()
|
||||
{
|
||||
CRect r;
|
||||
|
||||
|
@ -608,7 +601,7 @@ CRect CPolyLine::GetCornerBounds()
|
|||
}
|
||||
|
||||
|
||||
CRect CPolyLine::GetCornerBounds( int icont )
|
||||
CRect CPolyLine::GetBoundingBox( int icont )
|
||||
{
|
||||
CRect r;
|
||||
|
||||
|
@ -1381,7 +1374,7 @@ bool CPolyLine::IsPolygonSelfIntersecting()
|
|||
cr.reserve( n_cont );
|
||||
|
||||
for( int icont = 0; icont<n_cont; icont++ )
|
||||
cr.push_back( GetCornerBounds( icont ) );
|
||||
cr.push_back( GetBoundingBox( icont ) );
|
||||
|
||||
for( int icont = 0; icont<n_cont; icont++ )
|
||||
{
|
||||
|
|
|
@ -296,9 +296,8 @@ public:
|
|||
void MoveOrigin( int x_off, int y_off );
|
||||
|
||||
// misc. functions
|
||||
CRect GetBounds();
|
||||
CRect GetCornerBounds();
|
||||
CRect GetCornerBounds( int icont );
|
||||
CRect GetBoundingBox();
|
||||
CRect GetBoundingBox( int icont );
|
||||
void Copy( const CPolyLine* src );
|
||||
bool TestPointInside( int x, int y );
|
||||
|
||||
|
|
Loading…
Reference in New Issue