Pcbnew: board editor: allows pad edition by hotkey 'E' (was accessible only by mouse button right click)

All: minor code cleaning and very minor bug fixes.
This commit is contained in:
jean-pierre charras 2012-12-27 17:42:41 +01:00
parent c39ca125d4
commit 8653e362b2
10 changed files with 77 additions and 191 deletions

View File

@ -8,12 +8,12 @@
#include <trigo.h>
#include <common.h>
static bool DistanceTest( int seuil, int dx, int dy, int spot_cX, int spot_cY );
bool TestSegmentHit( wxPoint aRefPoint, wxPoint aStart, wxPoint aEnd, int aDist )
{
// make coordinates relatives to aStart:
aEnd -= aStart;
aRefPoint -= aStart;
return DistanceTest( aDist, aEnd.x, aEnd.y, aRefPoint.x, aRefPoint.y );
return DistanceTest( aDist, aEnd.x - aStart.x, aEnd.y - aStart.y,
aRefPoint.x - aStart.x, aRefPoint.y - aStart.y );
}
@ -347,41 +347,34 @@ void RotatePoint( double* pX, double* pY, double angle )
double EuclideanNorm( wxPoint vector )
{
return sqrt( (double) vector.x * (double) vector.x + (double) vector.y * (double) vector.y );
return hypot( (double) vector.x, (double) vector.y );
}
wxPoint TwoPointVector( wxPoint startPoint, wxPoint endPoint )
{
return endPoint - startPoint;
}
double DistanceLinePoint( wxPoint linePointA, wxPoint linePointB, wxPoint referencePoint )
{
return fabs( (double) ( (linePointB.x - linePointA.x) * (linePointA.y - referencePoint.y) -
(linePointA.x - referencePoint.x ) * (linePointB.y - linePointA.y) )
/ EuclideanNorm( TwoPointVector( linePointA, linePointB ) ) );
/ EuclideanNorm( linePointB - linePointA ) );
}
bool HitTestPoints( wxPoint pointA, wxPoint pointB, double threshold )
{
wxPoint vectorAB = TwoPointVector( pointA, pointB );
wxPoint vectorAB = pointB - pointA;
double distance = EuclideanNorm( vectorAB );
return distance < threshold;
}
int CrossProduct( wxPoint vectorA, wxPoint vectorB )
double CrossProduct( wxPoint vectorA, wxPoint vectorB )
{
return vectorA.x * vectorB.y - vectorA.y * vectorB.x;
return (double)vectorA.x * vectorB.y - (double)vectorA.y * vectorB.x;
}
double GetLineLength( const wxPoint& aPointA, const wxPoint& aPointB )
{
return sqrt( pow( (double) aPointA.x - (double) aPointB.x, 2 ) +
pow( (double) aPointA.y - (double) aPointB.y, 2 ) );
return hypot( (double) aPointA.x - (double) aPointB.x,
(double) aPointA.y - (double) aPointB.y );
}

View File

@ -41,6 +41,12 @@
#include <lib_arc.h>
#include <transform.h>
// Helper function
static inline wxPoint twoPointVector( wxPoint startPoint, wxPoint endPoint )
{
return endPoint - startPoint;
}
//! @brief Given three points A B C, compute the circumcenter of the resulting triangle
//! reference: http://en.wikipedia.org/wiki/Circumscribed_circle
@ -188,7 +194,7 @@ bool LIB_ARC::HitTest( wxPoint aPosition, int aThreshold, const TRANSFORM& aTran
NEGATE( relativePosition.y ); // reverse Y axis
int distance = KiROUND( EuclideanNorm( TwoPointVector( m_Pos, relativePosition ) ) );
int distance = KiROUND( EuclideanNorm( twoPointVector( m_Pos, relativePosition ) ) );
if( abs( distance - m_Radius ) > aThreshold )
return false;
@ -196,16 +202,16 @@ bool LIB_ARC::HitTest( wxPoint aPosition, int aThreshold, const TRANSFORM& aTran
// We are on the circle, ensure we are only on the arc, i.e. between
// m_ArcStart and m_ArcEnd
wxPoint startEndVector = TwoPointVector( m_ArcStart, m_ArcEnd);
wxPoint startRelativePositionVector = TwoPointVector( m_ArcStart, relativePosition );
wxPoint startEndVector = twoPointVector( m_ArcStart, m_ArcEnd);
wxPoint startRelativePositionVector = twoPointVector( m_ArcStart, relativePosition );
wxPoint centerStartVector = TwoPointVector( m_Pos, m_ArcStart );
wxPoint centerEndVector = TwoPointVector( m_Pos, m_ArcEnd );
wxPoint centerRelativePositionVector = TwoPointVector( m_Pos, relativePosition );
wxPoint centerStartVector = twoPointVector( m_Pos, m_ArcStart );
wxPoint centerEndVector = twoPointVector( m_Pos, m_ArcEnd );
wxPoint centerRelativePositionVector = twoPointVector( m_Pos, relativePosition );
// Compute the cross product to check if the point is in the sector
int crossProductStart = CrossProduct( centerStartVector, centerRelativePositionVector );
int crossProductEnd = CrossProduct( centerEndVector, centerRelativePositionVector );
double crossProductStart = CrossProduct( centerStartVector, centerRelativePositionVector );
double crossProductEnd = CrossProduct( centerEndVector, centerRelativePositionVector );
// The cross products need to be exchanged, depending on which side the center point
// relative to the start point to end point vector lies
@ -553,7 +559,7 @@ void LIB_ARC::BeginEdit( int aEditMode, const wxPoint aPosition )
wxPoint middlePoint = wxPoint( (m_ArcStart.x + m_ArcEnd.x) / 2,
(m_ArcStart.y + m_ArcEnd.y) / 2 );
wxPoint centerVector = m_Pos - middlePoint;
wxPoint startEndVector = TwoPointVector( m_ArcStart, m_ArcEnd );
wxPoint startEndVector = twoPointVector( m_ArcStart, m_ArcEnd );
m_editCenterDistance = EuclideanNorm( centerVector );
// Determine on which side is the center point
@ -650,10 +656,10 @@ void LIB_ARC::calcEdit( const wxPoint& aPosition )
// Determine if the arc angle is larger than 180 degrees -> this happens if both
// points (cursor position, center point) lie on the same side of the vector
// start-end
int crossA = CrossProduct( TwoPointVector( startPos, endPos ),
TwoPointVector( endPos, aPosition ) );
int crossB = CrossProduct( TwoPointVector( startPos, endPos ),
TwoPointVector( endPos, newCenterPoint ) );
double crossA = CrossProduct( twoPointVector( startPos, endPos ),
twoPointVector( endPos, aPosition ) );
double crossB = CrossProduct( twoPointVector( startPos, endPos ),
twoPointVector( endPos, newCenterPoint ) );
if( ( crossA < 0 && crossB < 0 ) || ( crossA >= 0 && crossB >= 0 ) )
newCenterPoint = m_Pos;
@ -665,7 +671,7 @@ void LIB_ARC::calcEdit( const wxPoint& aPosition )
wxPoint middlePoint = wxPoint( (startPos.x + endPos.x) / 2,
(startPos.y + endPos.y) / 2 );
wxPoint startEndVector = TwoPointVector( startPos, endPos );
wxPoint startEndVector = twoPointVector( startPos, endPos );
wxPoint perpendicularVector = wxPoint( -startEndVector.y, startEndVector.x );
double lengthPerpendicularVector = EuclideanNorm( perpendicularVector );
@ -736,8 +742,8 @@ void LIB_ARC::calcEdit( const wxPoint& aPosition )
void LIB_ARC::calcRadiusAngles()
{
wxPoint centerStartVector = TwoPointVector( m_Pos, m_ArcStart );
wxPoint centerEndVector = TwoPointVector( m_Pos, m_ArcEnd );
wxPoint centerStartVector = twoPointVector( m_Pos, m_ArcStart );
wxPoint centerEndVector = twoPointVector( m_Pos, m_ArcEnd );
m_Radius = KiROUND( EuclideanNorm( centerStartVector ) );

View File

@ -587,23 +587,10 @@ bool GERBER_DRAW_ITEM::HitTest( const wxPoint& aRefPos )
// TODO: a better analyze of the shape (perhaps create a D_CODE::HitTest for flashed items)
int radius = std::min( m_Size.x, m_Size.y ) >> 1;
// delta is a vector from m_Start to m_End (an origin of m_Start)
wxPoint delta = m_End - m_Start;
// dist is a vector from m_Start to ref_pos (an origin of m_Start)
wxPoint dist = ref_pos - m_Start;
if( m_Flashed )
{
return (double) dist.x * dist.x + (double) dist.y * dist.y <= (double) radius * radius;
}
return HitTestPoints( m_Start, ref_pos, radius );
else
{
if( DistanceTest( radius, delta.x, delta.y, dist.x, dist.y ) )
return true;
}
return false;
return TestSegmentHit( ref_pos, m_Start, m_End, radius );
}

View File

@ -44,13 +44,6 @@ void RotatePoint( double *pX, double *pY, double cx, double cy, double angle );
*/
int ArcTangente( int dy, int dx );
/**
* Function DistanceTest
* Calculate the distance from mouse cursor to a line segment.
* @return False if distance > threshold or true if distance <= threshold.
*/
bool DistanceTest( int seuil, int dx, int dy, int spot_cX, int spot_cY );
//! @brief Compute the distance between a line and a reference point
//! Reference: http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html
//! @param linePointA Point on line
@ -63,12 +56,6 @@ double DistanceLinePoint( wxPoint linePointA, wxPoint linePointB, wxPoint refere
//! @return Euclidean norm of the vector
double EuclideanNorm( wxPoint vector );
//! @brief Vector between two points
//! @param startPoint The start point
//! @param endPoint The end point
//! @return Vector between the points
wxPoint TwoPointVector( wxPoint startPoint, wxPoint endPoint );
//! @brief Test, if two points are near each other
//! @param pointA First point
//! @param pointB Second point
@ -79,7 +66,7 @@ bool HitTestPoints( wxPoint pointA, wxPoint pointB, double threshold );
//! @brief Determine the cross product
//! @param vectorA Two-dimensional vector
//! @param vectorB Two-dimensional vector
int CrossProduct( wxPoint vectorA, wxPoint vectorB );
double CrossProduct( wxPoint vectorA, wxPoint vectorB );
/**
@ -100,28 +87,4 @@ bool TestSegmentHit( wxPoint aRefPoint, wxPoint aStart, wxPoint aEnd, int aDist
*/
double GetLineLength( const wxPoint& aPointA, const wxPoint& aPointB );
/*******************/
/* Macro NEW_COORD */
/*******************/
/* Calculate coordinates to rotate around an axis
* coord: xrot = y + x * sin * cos
* yrot = y * cos - sin * x
* either: xrot = (y + x * tg) * cos
* yrot = (y - x * tg) * cos
*
* Cosine coefficients are loaded from a trigonometric table by 16 bit values.
*/
#define NEW_COORD( x0, y0 ) \
do { \
int itmp; \
itmp = x0; \
x0 = x0 + (int)( y0 * tg ); \
y0 = y0 - (int)( itmp * tg ); \
x0 = ( x0 * cosinus ) >> 8; \
y0 = ( y0 * cosinus ) >> 8; \
} while( 0 );
#endif

View File

@ -398,96 +398,32 @@ void DIMENSION::DisplayInfo( EDA_DRAW_FRAME* frame )
bool DIMENSION::HitTest( const wxPoint& aPosition )
{
int ux0, uy0;
int dx, dy, spot_cX, spot_cY;
if( m_Text.TextHitTest( aPosition ) )
return true;
// Locate SEGMENTS?
ux0 = m_crossBarO.x;
uy0 = m_crossBarO.y;
int dist_max = m_Width / 2;
// Recalculate coordinates with ux0, uy0 = origin.
dx = m_crossBarF.x - ux0;
dy = m_crossBarF.y - uy0;
// Locate SEGMENTS
spot_cX = aPosition.x - ux0;
spot_cY = aPosition.y - uy0;
if( DistanceTest( m_Width / 2, dx, dy, spot_cX, spot_cY ) )
if( TestSegmentHit( aPosition, m_crossBarO, m_crossBarF, dist_max ) )
return true;
ux0 = m_featureLineGO.x;
uy0 = m_featureLineGO.y;
dx = m_featureLineGF.x - ux0;
dy = m_featureLineGF.y - uy0;
spot_cX = aPosition.x - ux0;
spot_cY = aPosition.y - uy0;
if( DistanceTest( m_Width / 2, dx, dy, spot_cX, spot_cY ) )
if( TestSegmentHit( aPosition, m_featureLineGO, m_featureLineGF, dist_max ) )
return true;
ux0 = m_featureLineDO.x;
uy0 = m_featureLineDO.y;
dx = m_featureLineDF.x - ux0;
dy = m_featureLineDF.y - uy0;
spot_cX = aPosition.x - ux0;
spot_cY = aPosition.y - uy0;
if( DistanceTest( m_Width / 2, dx, dy, spot_cX, spot_cY ) )
if( TestSegmentHit( aPosition, m_featureLineDO, m_featureLineDF, dist_max ) )
return true;
ux0 = m_arrowD1O.x;
uy0 = m_arrowD1O.y;
dx = m_arrowD1F.x - ux0;
dy = m_arrowD1F.y - uy0;
spot_cX = aPosition.x - ux0;
spot_cY = aPosition.y - uy0;
if( DistanceTest( m_Width / 2, dx, dy, spot_cX, spot_cY ) )
if( TestSegmentHit( aPosition, m_arrowD1O, m_arrowD1F, dist_max ) )
return true;
ux0 = m_arrowD2O.x;
uy0 = m_arrowD2O.y;
dx = m_arrowD2F.x - ux0;
dy = m_arrowD2F.y - uy0;
spot_cX = aPosition.x - ux0;
spot_cY = aPosition.y - uy0;
if( DistanceTest( m_Width / 2, dx, dy, spot_cX, spot_cY ) )
if( TestSegmentHit( aPosition, m_arrowD2O, m_arrowD2F, dist_max ) )
return true;
ux0 = m_arrowG1O.x;
uy0 = m_arrowG1O.y;
dx = m_arrowG1F.x - ux0;
dy = m_arrowG1F.y - uy0;
spot_cX = aPosition.x - ux0;
spot_cY = aPosition.y - uy0;
if( DistanceTest( m_Width / 2, dx, dy, spot_cX, spot_cY ) )
if( TestSegmentHit( aPosition, m_arrowG1O, m_arrowG1F, dist_max ) )
return true;
ux0 = m_arrowG2O.x;
uy0 = m_arrowG2O.y;
dx = m_arrowG2F.x - ux0;
dy = m_arrowG2F.y - uy0;
spot_cX = aPosition.x - ux0;
spot_cY = aPosition.y - uy0;
if( DistanceTest( m_Width / 2, dx, dy, spot_cX, spot_cY ) )
if( TestSegmentHit( aPosition, m_arrowG2O, m_arrowG2F, dist_max ) )
return true;
return false;

View File

@ -1163,27 +1163,17 @@ void TRACK::DisplayInfoBase( EDA_DRAW_FRAME* frame )
bool TRACK::HitTest( const wxPoint& aPosition )
{
int radius = m_Width >> 1;
// (dx, dy) is a vector from m_Start to m_End (an origin of m_Start)
int dx = m_End.x - m_Start.x;
int dy = m_End.y - m_Start.y;
// (spot_cX, spot_cY) is a vector from m_Start to ref_pos (an origin of m_Start)
int spot_cX = aPosition.x - m_Start.x;
int spot_cY = aPosition.y - m_Start.y;
int max_dist = m_Width >> 1;
if( Type() == PCB_VIA_T )
{
return (double) spot_cX * spot_cX + (double) spot_cY * spot_cY <= (double) radius * radius;
}
else
{
if( DistanceTest( radius, dx, dy, spot_cX, spot_cY ) )
return true;
// rel_pos is aPosition relative to m_Start (or the center of the via)
wxPoint rel_pos = aPosition - m_Start;
double dist = (double) rel_pos.x * rel_pos.x + (double) rel_pos.y * rel_pos.y;
return dist <= (double) max_dist * max_dist;
}
return false;
return TestSegmentHit( aPosition, m_Start, m_End, max_dist );
}

View File

@ -556,17 +556,16 @@ TRACK* LocateIntrusion( TRACK* listStart, TRACK* aTrack, int aLayer, const wxPoi
continue;
// TRACK::HitTest
int dist = (width + track->m_Width) / 2 + aTrack->GetClearance( track );
int dist = (width + track->m_Width) / 2 + aTrack->GetClearance( track );
wxPoint pos = aRef - track->m_Start;
wxPoint vec = track->m_End - track->m_Start;
if( !DistanceTest( dist, vec.x, vec.y, pos.x, pos.y ) )
if( !TestSegmentHit( aRef, track->m_Start, track->m_End, dist ) )
continue;
found = track;
// prefer intrusions from the side, not the end
wxPoint pos = aRef - track->m_Start;
wxPoint vec = track->m_End - track->m_Start;
double tmp = (double) pos.x * vec.x + (double) pos.y * vec.y;
if( tmp >= 0 && tmp <= (double) vec.x * vec.x + (double) vec.y * vec.y )

View File

@ -51,6 +51,7 @@
static const wxString backupFileExtensionSuffix( wxT( "-bak" ) );
static const wxString autosaveFilePrefix( wxT( "_autosave-" ) );
void PCB_EDIT_FRAME::OnFileHistory( wxCommandEvent& event )
{
@ -92,7 +93,7 @@ void PCB_EDIT_FRAME::Files_io( wxCommandEvent& event )
wxFileName fn = currfn;
if( id == ID_MENU_RECOVER_BOARD_AUTOSAVE )
{
wxString rec_name = wxT("$") + fn.GetName();
wxString rec_name = autosaveFilePrefix + fn.GetName();
fn.SetName( rec_name );
}
else
@ -532,7 +533,13 @@ bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool aCreateBackupF
{
GetBoard()->SetFileName( pcbFileName.GetFullPath() );
UpdateTitle();
UpdateFileHistory( GetBoard()->GetFileName() );
// Put the saved file in File History, unless aCreateBackupFile
// is false.
// aCreateBackupFile == false is mainly used to write autosave files
// and not need to have an autosave file in file history
if( aCreateBackupFile )
UpdateFileHistory( GetBoard()->GetFileName() );
}
// Display the file names:
@ -542,7 +549,7 @@ bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool aCreateBackupF
{
// Delete auto save file on successful save.
wxFileName autoSaveFileName = pcbFileName;
autoSaveFileName.SetName( wxT( "$" ) + pcbFileName.GetName() );
autoSaveFileName.SetName( autosaveFilePrefix + pcbFileName.GetName() );
if( autoSaveFileName.FileExists() )
wxRemoveFile( autoSaveFileName.GetFullPath() );
@ -571,8 +578,9 @@ bool PCB_EDIT_FRAME::doAutoSave()
wxFileName tmpFileName = GetBoard()->GetFileName();
wxFileName fn = tmpFileName;
// Auto save file name is the normal file name prepended with $.
fn.SetName( wxT( "$" ) + fn.GetName() );
// Auto save file name is the normal file name prepended with
// autosaveFilePrefix string.
fn.SetName( autosaveFilePrefix + fn.GetName() );
wxLogTrace( traceAutoSave,
wxT( "Creating auto save file <" + fn.GetFullPath() ) + wxT( ">" ) );

View File

@ -661,12 +661,15 @@ bool PCB_EDIT_FRAME::OnHotkeyEditItem( int aIdCommand )
break;
case PCB_PAD_T:
// Post a EDIT_MODULE event here to prevent pads
// Until dec 2012 a EDIT_MODULE event is posted here to prevent pads
// from being edited by hotkeys.
// Process_Special_Functions takes care of finding
// the parent.
// Process_Special_Functions takes care of finding the parent.
// After dec 2012 a EDIT_PAD event is posted, because there is no
// reason to not allow pad edit by hotkey
// (pad coordinates are no more modified by rounding, in nanometer version
// when using inches or mm in dialog)
if( aIdCommand == HK_EDIT_ITEM )
evt_type = ID_POPUP_PCB_EDIT_MODULE;
evt_type = ID_POPUP_PCB_EDIT_PAD;
break;

View File

@ -813,7 +813,8 @@ void PCB_EDIT_FRAME::createPopUpMenuForFpPads( D_PAD* Pad, wxMenu* menu )
AddMenuItem( sub_menu_Pad, ID_POPUP_PCB_DRAG_PAD_REQUEST, _( "Drag" ),
KiBitmap( drag_pad_xpm ) );
AddMenuItem( sub_menu_Pad, ID_POPUP_PCB_EDIT_PAD, _( "Edit" ), KiBitmap( options_pad_xpm ) );
msg = AddHotkeyName( _( "Edit" ), g_Board_Editor_Hokeys_Descr, HK_EDIT_ITEM );
AddMenuItem( sub_menu_Pad, ID_POPUP_PCB_EDIT_PAD, msg, KiBitmap( options_pad_xpm ) );
sub_menu_Pad->AppendSeparator();
AddMenuItem( sub_menu_Pad, ID_POPUP_PCB_IMPORT_PAD_SETTINGS,