diff --git a/common/trigo.cpp b/common/trigo.cpp index 12fb0014f2..8465feb699 100644 --- a/common/trigo.cpp +++ b/common/trigo.cpp @@ -8,12 +8,12 @@ #include #include +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 ); } diff --git a/eeschema/lib_arc.cpp b/eeschema/lib_arc.cpp index b9bd9f7592..b536f0a8d7 100644 --- a/eeschema/lib_arc.cpp +++ b/eeschema/lib_arc.cpp @@ -41,6 +41,12 @@ #include #include +// 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 ) ); diff --git a/gerbview/class_gerber_draw_item.cpp b/gerbview/class_gerber_draw_item.cpp index 1604d897dc..7a3b37d6e2 100644 --- a/gerbview/class_gerber_draw_item.cpp +++ b/gerbview/class_gerber_draw_item.cpp @@ -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 ); } diff --git a/include/trigo.h b/include/trigo.h index 1d74abb92e..886f88eeb8 100644 --- a/include/trigo.h +++ b/include/trigo.h @@ -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 diff --git a/pcbnew/class_dimension.cpp b/pcbnew/class_dimension.cpp index 06336d5897..a8441912e3 100644 --- a/pcbnew/class_dimension.cpp +++ b/pcbnew/class_dimension.cpp @@ -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; diff --git a/pcbnew/class_track.cpp b/pcbnew/class_track.cpp index c902787c61..f1cbb8f2ff 100644 --- a/pcbnew/class_track.cpp +++ b/pcbnew/class_track.cpp @@ -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 ); } diff --git a/pcbnew/editrack.cpp b/pcbnew/editrack.cpp index b1b122ef12..df7d6192b2 100644 --- a/pcbnew/editrack.cpp +++ b/pcbnew/editrack.cpp @@ -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 ) diff --git a/pcbnew/files.cpp b/pcbnew/files.cpp index 31ab352399..2ca7cf9b60 100644 --- a/pcbnew/files.cpp +++ b/pcbnew/files.cpp @@ -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( ">" ) ); diff --git a/pcbnew/hotkeys_board_editor.cpp b/pcbnew/hotkeys_board_editor.cpp index ed9748a46f..8a5faebe84 100644 --- a/pcbnew/hotkeys_board_editor.cpp +++ b/pcbnew/hotkeys_board_editor.cpp @@ -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; diff --git a/pcbnew/onrightclick.cpp b/pcbnew/onrightclick.cpp index 5b6eeccf98..fb86dbb402 100644 --- a/pcbnew/onrightclick.cpp +++ b/pcbnew/onrightclick.cpp @@ -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,