diff --git a/common/advanced_config.cpp b/common/advanced_config.cpp index bfe14b4469..819340b37f 100644 --- a/common/advanced_config.cpp +++ b/common/advanced_config.cpp @@ -300,6 +300,8 @@ ADVANCED_CFG::ADVANCED_CFG() m_MaximumThreads = 0; + m_MinimumMarkerSeparationDistance = 0.15; + loadFromConfigFile(); } diff --git a/include/advanced_config.h b/include/advanced_config.h index 1421b5e05b..fc34e0cdd9 100644 --- a/include/advanced_config.h +++ b/include/advanced_config.h @@ -731,6 +731,15 @@ public: */ int m_MaximumThreads; + /** + * When finding overlapped marker a minium distance (in mm) between two DRC markers required + * to mark it as overlapped + * + * Setting name: "MinimumMarkerSeparationDistance" + * Default value: 0.15 + */ + double m_MinimumMarkerSeparationDistance; + ///@} private: diff --git a/pcbnew/dialogs/dialog_drc.cpp b/pcbnew/dialogs/dialog_drc.cpp index d6c97f2ebf..c0f11cb2d5 100644 --- a/pcbnew/dialogs/dialog_drc.cpp +++ b/pcbnew/dialogs/dialog_drc.cpp @@ -55,6 +55,7 @@ #include #include #include +#include // wxWidgets spends *far* too long calcuating column widths (most of it, believe it or // not, in repeatedly creating/destroying a wxDC to do the measurement in). @@ -400,6 +401,38 @@ void DIALOG_DRC::UpdateData() } +/** + * @brief Checks if two board items are overlapping. + * + * This function determines if the selected marker item and the unselected marker item + * are overlapping based on their positions. Overlapping is defined by their positions being + * equal or by the distance between them being less than a specified minimum difference. + * + * @param aSelectedMarkerItem Pointer to the selected board item. + * @param aUnSelectedMarkerItem Pointer to the unselected board item. + * @return true if the items are overlapping, false otherwise. + */ +bool IsOverlapping( BOARD_ITEM* aSelectedMarkerItem, BOARD_ITEM* aUnSelectedMarkerItem ) +{ + double selectedItemX = (double) aSelectedMarkerItem->GetX() / PCB_IU_PER_MM; + double selectedItemY = (double) aSelectedMarkerItem->GetY() / PCB_IU_PER_MM; + double unSelectedItemX = (double) aUnSelectedMarkerItem->GetX() / PCB_IU_PER_MM; + double unSelectedItemY = (double) aUnSelectedMarkerItem->GetY() / PCB_IU_PER_MM; + + double xDiff = selectedItemX > unSelectedItemX ? selectedItemX - unSelectedItemX + : unSelectedItemX - selectedItemX; + double yDiff = selectedItemY > unSelectedItemY ? selectedItemY - unSelectedItemY + : unSelectedItemY - selectedItemY; + double minimumMarkerSeparationDistance = + ADVANCED_CFG::GetCfg().m_MinimumMarkerSeparationDistance; + + return ( selectedItemX == unSelectedItemX && selectedItemY == unSelectedItemY ) + || ( xDiff < minimumMarkerSeparationDistance && yDiff < minimumMarkerSeparationDistance ) + || ( xDiff < minimumMarkerSeparationDistance && selectedItemY == unSelectedItemY ) + || ( yDiff < minimumMarkerSeparationDistance && selectedItemX == unSelectedItemX ); +} + + void DIALOG_DRC::OnDRCItemSelected( wxDataViewEvent& aEvent ) { BOARD* board = m_frame->GetBoard(); @@ -596,7 +629,25 @@ void DIALOG_DRC::OnDRCItemSelected( wxDataViewEvent& aEvent ) } else { - m_frame->FocusOnItem( item, principalLayer ); + if( item->Type() == PCB_MARKER_T ) + { + std::vector items; + + for( BOARD_ITEM* boardMarkerItem : board->Markers() ) + { + if( item->m_Uuid != boardMarkerItem->m_Uuid && IsOverlapping( item, boardMarkerItem ) ) + { + items.push_back( boardMarkerItem ); + } + } + + items.push_back( item ); + m_frame->FocusOnItems( items, principalLayer ); + } + else + { + m_frame->FocusOnItem( item, principalLayer ); + } } aEvent.Skip(); diff --git a/pcbnew/pcb_base_frame.cpp b/pcbnew/pcb_base_frame.cpp index 751524b5b6..3725537dd3 100644 --- a/pcbnew/pcb_base_frame.cpp +++ b/pcbnew/pcb_base_frame.cpp @@ -365,12 +365,16 @@ void PCB_BASE_FRAME::FocusOnItems( std::vector aItems, PCB_LAYER_ID break; case PCB_PAD_T: - case PCB_MARKER_T: case PCB_VIA_T: FocusOnLocation( item->GetFocusPosition() ); GetCanvas()->Refresh(); return; + case PCB_MARKER_T: + FocusOnLocation( item->GetFocusPosition() ); + GetCanvas()->Refresh(); + break; + case PCB_SHAPE_T: case PCB_FIELD_T: case PCB_TEXT_T: