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 ) bool ZONE_CONTAINER::HitTest( const wxPoint& refPos )
{ {
if( HitTestForCorner( refPos ) >= 0 ) if( HitTestForCorner( refPos ) )
return true; return true;
if( HitTestForEdge( refPos ) >= 0 ) if( HitTestForEdge( refPos ) )
return true; return true;
return false; return false;
@ -807,34 +807,40 @@ bool ZONE_CONTAINER::HitTest( const wxPoint& refPos )
* Function HitTestForCorner * Function HitTestForCorner
* tests if the given wxPoint near a corner, or near the segment define by 2 corners. * tests if the given wxPoint near a corner, or near the segment define by 2 corners.
* Choose the nearest corner * Choose the nearest corner
* "near" means CORNER_MIN_DIST_IN_PIXELS pixels * "near" means grid size (or CORNER_MIN_DIST if grid is not known)
* @return -1 if none, corner index in .corner &ltvector&gt * 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 * @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 m_CornerSelection = -1; // Set to not found
int dist, min_dist;
unsigned item_pos, lim;
lim = m_Poly->corner.size();
m_CornerSelection = -1;
min_dist = CORNER_MIN_DIST; #define CORNER_MIN_DIST 100 // distance (in internal units) to detect a corner in a zone outline
for( item_pos = 0; item_pos < lim; item_pos++ ) int min_dist = CORNER_MIN_DIST + 1;
if( GetBoard() && GetBoard()->m_PcbFrame )
{ {
dist = abs( m_Poly->corner[item_pos].x - refPos.x ) + abs( // Use grid size because it is known
m_Poly->corner[item_pos].y - refPos.y ); wxRealPoint grid = GetBoard()->m_PcbFrame->DrawPanel->GetGrid();
if( dist <= min_dist ) 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; m_CornerSelection = item_pos;
min_dist = dist; min_dist = dist;
} }
} }
if( m_CornerSelection >= 0 ) return m_CornerSelection >= 0;
return item_pos;
return -1;
} }
@ -842,25 +848,31 @@ int ZONE_CONTAINER::HitTestForCorner( const wxPoint& refPos )
* Function HitTestForEdge * Function HitTestForEdge
* tests if the given wxPoint near a corner, or near the segment define by 2 corners. * tests if the given wxPoint near a corner, or near the segment define by 2 corners.
* choose the nearest segment * choose the nearest segment
* "near" means EDGE_MIN_DIST_IN_PIXELS pixels * "near" means grid size (or EDGE_MIN_DIST if grid is not known)
* @return -1 if none, or index of the starting corner in .corner &ltvector&gt * 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 * @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 #define EDGE_MIN_DIST 200 // distance (in internal units) to detect a zone outline
int dist, min_dist; int min_dist = EDGE_MIN_DIST+1;
unsigned item_pos, lim; if( GetBoard() && GetBoard()->m_PcbFrame )
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++ )
{ {
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 corner of the current outline is tested
* the last segment of the current outline starts at current corner, and ends * 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 */ /* test the dist between segment and ref point */
dist = (int) GetPointToLineSegmentDistance( refPos.x, int dist = (int) GetPointToLineSegmentDistance( refPos.x,
refPos.y, refPos.y,
m_Poly->corner[item_pos].x, m_Poly->corner[item_pos].x,
m_Poly->corner[item_pos].y, m_Poly->corner[item_pos].y,
m_Poly->corner[end_segm].x, m_Poly->corner[end_segm].x,
m_Poly->corner[end_segm].y ); m_Poly->corner[end_segm].y );
if( dist <= min_dist ) if( dist < min_dist )
{ {
m_CornerSelection = item_pos; m_CornerSelection = item_pos;
min_dist = dist; min_dist = dist;
} }
} }
if( m_CornerSelection >= 0 ) return m_CornerSelection >= 0;
return item_pos;
return -1;
} }

View File

@ -242,19 +242,21 @@ public:
/** /**
* Function HitTestForCorner * Function HitTestForCorner
* tests if the given wxPoint near a corner, or near the segment define by 2 corners. * tests if the given wxPoint near a corner
* @return -1 if none, corner index in .corner &ltvector&gt * Set m_CornerSelection to -1 if nothing found, or index of corner
* @return true if found
* @param refPos : A wxPoint to test * @param refPos : A wxPoint to test
*/ */
int HitTestForCorner( const wxPoint& refPos ); bool HitTestForCorner( const wxPoint& refPos );
/** /**
* Function HitTestForEdge * Function HitTestForEdge
* tests if the given wxPoint near a corner, or near the segment define by 2 corners. * tests if the given wxPoint is near a segment defined by 2 corners.
* @return -1 if none, or index of the starting corner in .corner &ltvector&gt * 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 * @param refPos : A wxPoint to test
*/ */
int HitTestForEdge( const wxPoint& refPos ); bool HitTestForEdge( const wxPoint& refPos );
/** /**
* Function HitTest (overlayed) * 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) // We have a hit under mouse (a zone outline corner or segment)
// test for a corner only because want to move corners only. // test for a corner only because want to move corners only.
ZONE_CONTAINER* edge_zone = (ZONE_CONTAINER*) DrawStruct; 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; hit_on_corner = true;
} }
if( hit_on_corner ) 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, ADD_MENUITEM_WITH_SUBMENU( aPopMenu, zones_menu,
-1, _( "Zones" ), add_zone_xpm ); -1, _( "Zones" ), add_zone_xpm );
int index; if( edge_zone->HitTestForCorner( GetScreen()->RefPos( true ) ) )
if( ( index = edge_zone->HitTestForCorner( GetScreen()->RefPos( true ) ) ) >= 0 )
{ {
ADD_MENUITEM( zones_menu, ID_POPUP_PCB_MOVE_ZONE_CORNER, ADD_MENUITEM( zones_menu, ID_POPUP_PCB_MOVE_ZONE_CORNER,
_( "Move Corner" ), move_xpm ); _( "Move Corner" ), move_xpm );
ADD_MENUITEM( zones_menu, ID_POPUP_PCB_DELETE_ZONE_CORNER, ADD_MENUITEM( zones_menu, ID_POPUP_PCB_DELETE_ZONE_CORNER,
_( "Delete Corner" ), delete_xpm ); _( "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, ADD_MENUITEM( zones_menu, ID_POPUP_PCB_ADD_ZONE_CORNER,
_( "Create Corner" ), add_corner_xpm ); _( "Create Corner" ), add_corner_xpm );
@ -610,7 +609,8 @@ void WinEDA_PcbFrame::createPopUpMenuForZones( ZONE_CONTAINER* edge_zone, wxMenu
msg, edit_xpm ); msg, edit_xpm );
zones_menu->AppendSeparator(); 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, ADD_MENUITEM( zones_menu, ID_POPUP_PCB_DELETE_ZONE_CUTOUT,
_( "Delete Cutout" ), delete_xpm ); _( "Delete Cutout" ), delete_xpm );