Pcbnew: Better selection of corners and edges in zones. Usefull when selecting edge/corner by right clicking on a zone outline, for hight density boards.

This commit is contained in:
jean-pierre charras 2011-03-01 14:59:21 +01:00
parent e39522975a
commit cdffc3d15f
4 changed files with 61 additions and 50 deletions

View File

@ -794,9 +794,9 @@ void ZONE_CONTAINER::DrawWhileCreateOutline( EDA_DRAW_PANEL* panel, wxDC* DC, in
*/
bool ZONE_CONTAINER::HitTest( const wxPoint& refPos )
{
if( HitTestForCorner( refPos ) >= 0 )
if( HitTestForCorner( refPos ) )
return true;
if( HitTestForEdge( refPos ) >= 0 )
if( HitTestForEdge( refPos ) )
return true;
return false;
@ -807,34 +807,40 @@ bool ZONE_CONTAINER::HitTest( const wxPoint& refPos )
* Function HitTestForCorner
* tests if the given wxPoint near a corner, or near the segment define by 2 corners.
* Choose the nearest corner
* "near" means CORNER_MIN_DIST_IN_PIXELS pixels
* @return -1 if none, corner index in .corner &ltvector&gt
* "near" means grid size (or CORNER_MIN_DIST if grid is not known)
* Set m_CornerSelection to corner index in .m_Poly-&gtcorner or -1 if no corner found
* @return true if a corner found
* @param refPos : A wxPoint to test
*/
int ZONE_CONTAINER::HitTestForCorner( const wxPoint& refPos )
bool ZONE_CONTAINER::HitTestForCorner( const wxPoint& refPos )
{
#define CORNER_MIN_DIST 500 // distance (in internal units) to detect a corner in a zone outline
int dist, min_dist;
unsigned item_pos, lim;
lim = m_Poly->corner.size();
m_CornerSelection = -1;
m_CornerSelection = -1; // Set to not found
min_dist = CORNER_MIN_DIST;
for( item_pos = 0; item_pos < lim; item_pos++ )
#define CORNER_MIN_DIST 100 // distance (in internal units) to detect a corner in a zone outline
int min_dist = CORNER_MIN_DIST + 1;
if( GetBoard() && GetBoard()->m_PcbFrame )
{
dist = abs( m_Poly->corner[item_pos].x - refPos.x ) + abs(
m_Poly->corner[item_pos].y - refPos.y );
if( dist <= min_dist )
// Use grid size because it is known
wxRealPoint grid = GetBoard()->m_PcbFrame->DrawPanel->GetGrid();
min_dist = wxRound( MIN( grid.x, grid.y ) );
}
wxPoint delta;
unsigned lim = m_Poly->corner.size();
for( unsigned item_pos = 0; item_pos < lim; item_pos++ )
{
delta.x = refPos.x - m_Poly->corner[item_pos].x;
delta.y = refPos.y - m_Poly->corner[item_pos].y;
// Calculate a distance:
int dist = MAX( abs( delta.x ), abs( delta.y ) );
if( dist < min_dist ) // this corner is a candidate:
{
m_CornerSelection = item_pos;
min_dist = dist;
}
}
if( m_CornerSelection >= 0 )
return item_pos;
return -1;
return m_CornerSelection >= 0;
}
@ -842,25 +848,31 @@ int ZONE_CONTAINER::HitTestForCorner( const wxPoint& refPos )
* Function HitTestForEdge
* tests if the given wxPoint near a corner, or near the segment define by 2 corners.
* choose the nearest segment
* "near" means EDGE_MIN_DIST_IN_PIXELS pixels
* @return -1 if none, or index of the starting corner in .corner &ltvector&gt
* "near" means grid size (or EDGE_MIN_DIST if grid is not known)
* Set m_CornerSelection to -1 if nothing found, or index of the starting corner of edge
* in .m_Poly-&gtcorner
* @return true if found
* @param refPos : A wxPoint to test
*/
int ZONE_CONTAINER::HitTestForEdge( const wxPoint& refPos )
bool ZONE_CONTAINER::HitTestForEdge( const wxPoint& refPos )
{
unsigned lim = m_Poly->corner.size();
m_CornerSelection = -1; // Set to not found
#define EDGE_MIN_DIST 200 // distance (in internal units) to detect a zone outline
int dist, min_dist;
unsigned item_pos, lim;
lim = m_Poly->corner.size();
/* Test for an entire segment */
unsigned first_corner_pos = 0, end_segm;
m_CornerSelection = -1;
min_dist = EDGE_MIN_DIST;
for( item_pos = 0; item_pos < lim; item_pos++ )
int min_dist = EDGE_MIN_DIST+1;
if( GetBoard() && GetBoard()->m_PcbFrame )
{
end_segm = item_pos + 1;
// Use grid size because it is known
wxRealPoint grid = GetBoard()->m_PcbFrame->DrawPanel->GetGrid();
min_dist = wxRound( MIN( grid.x, grid.y ) );
}
unsigned first_corner_pos = 0;
for( unsigned item_pos = 0; item_pos < lim; item_pos++ )
{
unsigned end_segm = item_pos + 1;
/* the last corner of the current outline is tested
* the last segment of the current outline starts at current corner, and ends
@ -874,23 +886,20 @@ int ZONE_CONTAINER::HitTestForEdge( const wxPoint& refPos )
}
/* test the dist between segment and ref point */
dist = (int) GetPointToLineSegmentDistance( refPos.x,
int dist = (int) GetPointToLineSegmentDistance( refPos.x,
refPos.y,
m_Poly->corner[item_pos].x,
m_Poly->corner[item_pos].y,
m_Poly->corner[end_segm].x,
m_Poly->corner[end_segm].y );
if( dist <= min_dist )
if( dist < min_dist )
{
m_CornerSelection = item_pos;
min_dist = dist;
}
}
if( m_CornerSelection >= 0 )
return item_pos;
return -1;
return m_CornerSelection >= 0;
}

View File

@ -242,19 +242,21 @@ public:
/**
* Function HitTestForCorner
* tests if the given wxPoint near a corner, or near the segment define by 2 corners.
* @return -1 if none, corner index in .corner &ltvector&gt
* tests if the given wxPoint near a corner
* Set m_CornerSelection to -1 if nothing found, or index of corner
* @return true if found
* @param refPos : A wxPoint to test
*/
int HitTestForCorner( const wxPoint& refPos );
bool HitTestForCorner( const wxPoint& refPos );
/**
* Function HitTestForEdge
* tests if the given wxPoint near a corner, or near the segment define by 2 corners.
* @return -1 if none, or index of the starting corner in .corner &ltvector&gt
* tests if the given wxPoint is near a segment defined by 2 corners.
* Set m_CornerSelection to -1 if nothing found, or index of the starting corner of vertice
* @return true if found
* @param refPos : A wxPoint to test
*/
int HitTestForEdge( const wxPoint& refPos );
bool HitTestForEdge( const wxPoint& refPos );
/**
* Function HitTest (overlayed)

View File

@ -256,7 +256,7 @@ void WinEDA_PcbFrame::OnLeftClick( wxDC* aDC, const wxPoint& aPosition )
// We have a hit under mouse (a zone outline corner or segment)
// test for a corner only because want to move corners only.
ZONE_CONTAINER* edge_zone = (ZONE_CONTAINER*) DrawStruct;
if( edge_zone->HitTestForCorner( GetScreen()->RefPos( true ) ) >= 0 ) // corner located!
if( edge_zone->HitTestForCorner( GetScreen()->RefPos( true ) ) ) // corner located!
hit_on_corner = true;
}
if( hit_on_corner )

View File

@ -567,15 +567,14 @@ void WinEDA_PcbFrame::createPopUpMenuForZones( ZONE_CONTAINER* edge_zone, wxMenu
ADD_MENUITEM_WITH_SUBMENU( aPopMenu, zones_menu,
-1, _( "Zones" ), add_zone_xpm );
int index;
if( ( index = edge_zone->HitTestForCorner( GetScreen()->RefPos( true ) ) ) >= 0 )
if( edge_zone->HitTestForCorner( GetScreen()->RefPos( true ) ) )
{
ADD_MENUITEM( zones_menu, ID_POPUP_PCB_MOVE_ZONE_CORNER,
_( "Move Corner" ), move_xpm );
ADD_MENUITEM( zones_menu, ID_POPUP_PCB_DELETE_ZONE_CORNER,
_( "Delete Corner" ), delete_xpm );
}
else if( ( index = edge_zone->HitTestForEdge( GetScreen()->RefPos( true ) ) ) >= 0 )
else if( edge_zone->HitTestForEdge( GetScreen()->RefPos( true ) ) )
{
ADD_MENUITEM( zones_menu, ID_POPUP_PCB_ADD_ZONE_CORNER,
_( "Create Corner" ), add_corner_xpm );
@ -610,7 +609,8 @@ void WinEDA_PcbFrame::createPopUpMenuForZones( ZONE_CONTAINER* edge_zone, wxMenu
msg, edit_xpm );
zones_menu->AppendSeparator();
if( index >= 0 && edge_zone->m_Poly->IsCutoutContour( edge_zone->m_CornerSelection ) )
if( edge_zone->m_CornerSelection >= 0 &&
edge_zone->m_Poly->IsCutoutContour( edge_zone->m_CornerSelection ) )
ADD_MENUITEM( zones_menu, ID_POPUP_PCB_DELETE_ZONE_CUTOUT,
_( "Delete Cutout" ), delete_xpm );