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
|
/* Intersects
|
||||||
* test for a common area between 2 rect.
|
* test for a common area between 2 rect.
|
||||||
* return true if at least a common point is found
|
* return true if at least a common point is found
|
||||||
|
|
|
@ -9,6 +9,71 @@
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <math_for_graphics.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
|
/* Function TestSegmentHit
|
||||||
* test for hit on line segment
|
* test for hit on line segment
|
||||||
* i.e. a reference point is within a given distance from segment
|
* i.e. a reference point is within a given distance from segment
|
||||||
|
|
|
@ -300,11 +300,25 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function Intersects
|
* 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.
|
* @return bool - true if the argument rectangle intersects this rectangle.
|
||||||
* (i.e. if the 2 rectangles have at least a common point)
|
* (i.e. if the 2 rectangles have at least a common point)
|
||||||
*/
|
*/
|
||||||
bool Intersects( const EDA_RECT& aRect ) const;
|
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)
|
* Function operator(wxRect)
|
||||||
* overloads the cast operator to return a wxRect
|
* overloads the cast operator to return a wxRect
|
||||||
|
@ -530,18 +544,6 @@ public:
|
||||||
return false; // derived classes should override this function
|
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
|
* Function GetBoundingBox
|
||||||
|
|
|
@ -223,6 +223,26 @@ public:
|
||||||
*/
|
*/
|
||||||
wxString GetLayerName() const;
|
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
|
* Function FormatInternalUnits
|
||||||
|
|
|
@ -31,6 +31,19 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <wx/gdicmn.h> // For wxPoint
|
#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,
|
* Calculate the new point of coord coord pX, pY,
|
||||||
* for a rotation center 0, 0, and angle in (1 / 10 degree)
|
* 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()
|
void PCB_EDIT_FRAME::Block_SelectItems()
|
||||||
{
|
{
|
||||||
LAYER_MSK layerMask;
|
LAYER_MSK layerMask;
|
||||||
|
bool selectOnlyComplete = GetScreen()->m_BlockLocate.GetWidth() > 0 ;
|
||||||
|
|
||||||
GetScreen()->m_BlockLocate.Normalize();
|
GetScreen()->m_BlockLocate.Normalize();
|
||||||
|
|
||||||
|
@ -395,7 +396,7 @@ void PCB_EDIT_FRAME::Block_SelectItems()
|
||||||
{
|
{
|
||||||
LAYER_NUM layer = module->GetLayer();
|
LAYER_NUM layer = module->GetLayer();
|
||||||
|
|
||||||
if( module->HitTest( GetScreen()->m_BlockLocate )
|
if( module->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete )
|
||||||
&& ( !module->IsLocked() || blockIncludeLockedModules ) )
|
&& ( !module->IsLocked() || blockIncludeLockedModules ) )
|
||||||
{
|
{
|
||||||
if( blockIncludeItemsOnInvisibleLayers || m_Pcb->IsModuleLayerVisible( layer ) )
|
if( blockIncludeItemsOnInvisibleLayers || m_Pcb->IsModuleLayerVisible( layer ) )
|
||||||
|
@ -410,14 +411,14 @@ void PCB_EDIT_FRAME::Block_SelectItems()
|
||||||
// Add tracks and vias
|
// Add tracks and vias
|
||||||
if( blockIncludeTracks )
|
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
|
if( blockIncludeItemsOnInvisibleLayers
|
||||||
|| m_Pcb->IsLayerVisible( pt_segm->GetLayer() ) )
|
|| m_Pcb->IsLayerVisible( track->GetLayer() ) )
|
||||||
{
|
{
|
||||||
picker.SetItem ( pt_segm );
|
picker.SetItem ( track );
|
||||||
itemsList->PushItem( picker );
|
itemsList->PushItem( picker );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -446,7 +447,7 @@ void PCB_EDIT_FRAME::Block_SelectItems()
|
||||||
if( (GetLayerMask( PtStruct->GetLayer() ) & layerMask) == 0 )
|
if( (GetLayerMask( PtStruct->GetLayer() ) & layerMask) == 0 )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if( !PtStruct->HitTest( GetScreen()->m_BlockLocate ) )
|
if( !PtStruct->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete ) )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
select_me = true; // This item is in bloc: select it
|
select_me = true; // This item is in bloc: select it
|
||||||
|
@ -456,7 +457,7 @@ void PCB_EDIT_FRAME::Block_SelectItems()
|
||||||
if( !blockIncludePcbTexts )
|
if( !blockIncludePcbTexts )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if( !PtStruct->HitTest( GetScreen()->m_BlockLocate ) )
|
if( !PtStruct->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete ) )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
select_me = true; // This item is in bloc: select it
|
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 )
|
if( ( GetLayerMask( PtStruct->GetLayer() ) & layerMask ) == 0 )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if( !PtStruct->HitTest( GetScreen()->m_BlockLocate ) )
|
if( !PtStruct->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete ) )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
select_me = true; // This item is in bloc: select it
|
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 )
|
if( ( GetLayerMask( PtStruct->GetLayer() ) & layerMask ) == 0 )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if( !PtStruct->HitTest( GetScreen()->m_BlockLocate ) )
|
if( !PtStruct->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete ) )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
select_me = true; // This item is in bloc: select it
|
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 );
|
ZONE_CONTAINER* area = m_Pcb->GetArea( ii );
|
||||||
|
|
||||||
if( area->HitTest( GetScreen()->m_BlockLocate ) )
|
if( area->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete ) )
|
||||||
{
|
{
|
||||||
if( blockIncludeItemsOnInvisibleLayers
|
if( blockIncludeItemsOnInvisibleLayers
|
||||||
|| m_Pcb->IsLayerVisible( area->GetLayer() ) )
|
|| 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() ) )
|
EDA_RECT arect = aRect;
|
||||||
return true;
|
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 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
|
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 )
|
switch( m_Shape )
|
||||||
{
|
{
|
||||||
case S_CIRCLE:
|
case S_CIRCLE:
|
||||||
{
|
// Test if area intersects or contains the circle:
|
||||||
int radius = GetRadius();
|
if( aContained )
|
||||||
|
return arect.Contains( GetBoundingBox() );
|
||||||
// Text if area intersects the circle:
|
else
|
||||||
EDA_RECT area = aRect;
|
return arect.Intersects( GetBoundingBox() );
|
||||||
area.Inflate( radius );
|
|
||||||
|
|
||||||
if( area.Contains( m_Start ) )
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case S_ARC:
|
case S_ARC:
|
||||||
case S_SEGMENT:
|
radius = hypot( (double)( GetEnd().x - GetStart().x ),
|
||||||
if( aRect.Contains( GetStart() ) )
|
(double)( GetEnd().y - GetStart().y ) );
|
||||||
return true;
|
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;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -172,7 +172,10 @@ public:
|
||||||
|
|
||||||
virtual bool HitTest( const wxPoint& aPosition );
|
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
|
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 ) )
|
EDA_RECT arect = aRect;
|
||||||
return true;
|
arect.Inflate( aAccuracy );
|
||||||
|
|
||||||
|
if( aContained )
|
||||||
|
return arect.Contains( GetBoundingBox() );
|
||||||
|
else
|
||||||
|
return GetBoundingBox().Intersects( arect );
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,7 +93,10 @@ public:
|
||||||
|
|
||||||
bool HitTest( const wxPoint& aPosition );
|
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;
|
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() )
|
EDA_RECT arect = aRect;
|
||||||
return false;
|
arect.Inflate( aAccuracy );
|
||||||
|
|
||||||
if( m_BoundaryBox.GetY() < aRect.GetY() )
|
if( aContained )
|
||||||
return false;
|
return arect.Contains( m_BoundaryBox );
|
||||||
|
else
|
||||||
if( m_BoundaryBox.GetRight() > aRect.GetRight() )
|
return m_BoundaryBox.Intersects( arect );
|
||||||
return false;
|
|
||||||
|
|
||||||
if( m_BoundaryBox.GetBottom() > aRect.GetBottom() )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -318,7 +318,10 @@ public:
|
||||||
|
|
||||||
bool HitTest( const wxPoint& aPosition );
|
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
|
* Function GetReference
|
||||||
|
|
|
@ -71,9 +71,12 @@ public:
|
||||||
return TextHitTest( aPosition );
|
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
|
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 ) )
|
EDA_RECT box;
|
||||||
return true;
|
EDA_RECT arect = aRect;
|
||||||
|
arect.Inflate( aAccuracy );
|
||||||
|
|
||||||
if( aRect.Contains( m_End ) )
|
if( Type() == PCB_VIA_T )
|
||||||
return true;
|
{
|
||||||
|
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 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
|
* 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() )
|
if( aContained )
|
||||||
is_out_of_box = true;
|
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() )
|
// aRect is inside the polygon bounding box,
|
||||||
is_out_of_box = true;
|
// 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() )
|
if( HitTestInsideZone( corner ) )
|
||||||
is_out_of_box = true;
|
return true;
|
||||||
|
|
||||||
if( rect.bottom > aRect.GetBottom() )
|
corner.x = arect.GetEnd().x;
|
||||||
is_out_of_box = true;
|
|
||||||
|
|
||||||
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,
|
void DrawWhileCreateOutline( EDA_DRAW_PANEL* panel, wxDC* DC,
|
||||||
GR_DRAWMODE draw_mode = GR_OR );
|
GR_DRAWMODE draw_mode = GR_OR );
|
||||||
|
|
||||||
/* Function GetBoundingBox
|
/** Function GetBoundingBox
|
||||||
* @return an EDA_RECT that is the bounding box of the zone outline
|
* @return an EDA_RECT that is the bounding box of the zone outline
|
||||||
*/
|
*/
|
||||||
EDA_RECT GetBoundingBox() const;
|
EDA_RECT GetBoundingBox() const;
|
||||||
|
@ -253,8 +253,26 @@ public:
|
||||||
|
|
||||||
void SetOutline( CPolyLine* aOutline ) { m_Poly = aOutline; }
|
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 );
|
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
|
* Function HitTestFilledArea
|
||||||
* tests if the given wxPoint is within the bounds of a filled area of this zone.
|
* 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 );
|
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
|
* Function Fill_Zone
|
||||||
|
|
|
@ -102,7 +102,7 @@ bool BOARD::CombineAllAreasInNet( PICKED_ITEMS_LIST* aDeletedList, int aNetCode,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// legal polygon
|
// legal polygon
|
||||||
CRect b1 = curr_area->Outline()->GetCornerBounds();
|
CRect b1 = curr_area->Outline()->GetBoundingBox();
|
||||||
bool mod_ia1 = false;
|
bool mod_ia1 = false;
|
||||||
|
|
||||||
for( unsigned ia2 = m_ZoneDescriptorList.size() - 1; ia2 > ia1; ia2-- )
|
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() )
|
if( curr_area->GetLayer() != area2->GetLayer() )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
CRect b2 = area2->Outline()->GetCornerBounds();
|
CRect b2 = area2->Outline()->GetBoundingBox();
|
||||||
|
|
||||||
if( !( b1.left > b2.right || b1.right < b2.left
|
if( !( b1.left > b2.right || b1.right < b2.left
|
||||||
|| b1.bottom > b2.top || b1.top < b2.bottom ) )
|
|| 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();
|
CPolyLine* poly2 = area_to_test->Outline();
|
||||||
|
|
||||||
// test bounding rects
|
// test bounding rects
|
||||||
CRect b1 = poly1->GetCornerBounds();
|
CRect b1 = poly1->GetBoundingBox();
|
||||||
CRect b2 = poly2->GetCornerBounds();
|
CRect b2 = poly2->GetBoundingBox();
|
||||||
|
|
||||||
if( b1.bottom > b2.top || b1.top < b2.bottom ||
|
if( b1.bottom > b2.top || b1.top < b2.bottom ||
|
||||||
b1.left > b2.right || b1.right < b2.left )
|
b1.left > b2.right || b1.right < b2.left )
|
||||||
|
|
|
@ -582,14 +582,7 @@ int CPolyLine::GetEndContour( int ic )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CRect CPolyLine::GetBounds()
|
CRect CPolyLine::GetBoundingBox()
|
||||||
{
|
|
||||||
CRect r = GetCornerBounds();
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
CRect CPolyLine::GetCornerBounds()
|
|
||||||
{
|
{
|
||||||
CRect r;
|
CRect r;
|
||||||
|
|
||||||
|
@ -608,7 +601,7 @@ CRect CPolyLine::GetCornerBounds()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CRect CPolyLine::GetCornerBounds( int icont )
|
CRect CPolyLine::GetBoundingBox( int icont )
|
||||||
{
|
{
|
||||||
CRect r;
|
CRect r;
|
||||||
|
|
||||||
|
@ -1381,7 +1374,7 @@ bool CPolyLine::IsPolygonSelfIntersecting()
|
||||||
cr.reserve( n_cont );
|
cr.reserve( n_cont );
|
||||||
|
|
||||||
for( int icont = 0; icont<n_cont; icont++ )
|
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++ )
|
for( int icont = 0; icont<n_cont; icont++ )
|
||||||
{
|
{
|
||||||
|
|
|
@ -296,9 +296,8 @@ public:
|
||||||
void MoveOrigin( int x_off, int y_off );
|
void MoveOrigin( int x_off, int y_off );
|
||||||
|
|
||||||
// misc. functions
|
// misc. functions
|
||||||
CRect GetBounds();
|
CRect GetBoundingBox();
|
||||||
CRect GetCornerBounds();
|
CRect GetBoundingBox( int icont );
|
||||||
CRect GetCornerBounds( int icont );
|
|
||||||
void Copy( const CPolyLine* src );
|
void Copy( const CPolyLine* src );
|
||||||
bool TestPointInside( int x, int y );
|
bool TestPointInside( int x, int y );
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue