From 1c4d925d1f84bc9d2b005d55eb15c18fa01c81c0 Mon Sep 17 00:00:00 2001 From: Wayne Stambaugh Date: Fri, 16 Sep 2011 14:54:04 -0400 Subject: [PATCH] PCBNew locate footprint code refactoring and other minor fixes. * Refactor locate footprint function into the board object. * Remove locate.cpp as it is no longer needed. * Actually remove track.cpp from repo that I missed on the last commit. * Increase the size of the layer pair tool bar bitmap so that it looks better with the new larger tool bar images. * Fixes to prevent common headers from complaining when not included in the correct order in source files. --- include/class_layer_box_selector.h | 4 + include/dialog_helpers.h | 3 + pcbnew/CMakeLists.txt | 1 - pcbnew/class_board.cpp | 78 ++++++ pcbnew/class_board.h | 17 ++ pcbnew/hotkeys_board_editor.cpp | 4 +- pcbnew/locate.cpp | 109 -------- pcbnew/protos.h | 9 - pcbnew/tool_pcb.cpp | 101 ++++---- pcbnew/track.cpp | 395 ----------------------------- 10 files changed, 153 insertions(+), 568 deletions(-) delete mode 100644 pcbnew/locate.cpp delete mode 100644 pcbnew/track.cpp diff --git a/include/class_layer_box_selector.h b/include/class_layer_box_selector.h index 23a9401754..a75b5e9349 100644 --- a/include/class_layer_box_selector.h +++ b/include/class_layer_box_selector.h @@ -4,6 +4,10 @@ #include "hotkeys_basic.h" #include + +class EDA_TOOLBAR; + + /* class to display a layer list. * */ diff --git a/include/dialog_helpers.h b/include/dialog_helpers.h index 8120e775df..120a3a77b7 100644 --- a/include/dialog_helpers.h +++ b/include/dialog_helpers.h @@ -8,6 +8,9 @@ #define _DIALOG_HELPERS_H_ +#include "common.h" // EDA_UNITS_T + + /** * class EDA_LIST_DIALOG * diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index 4df661e2c9..19898e5af4 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -137,7 +137,6 @@ set(PCBNEW_SRCS layer_widget.cpp librairi.cpp loadcmp.cpp - locate.cpp magnetic_tracks_functions.cpp menubar_modedit.cpp menubar_pcbframe.cpp diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp index f0f35a7041..9422d2fdef 100644 --- a/pcbnew/class_board.cpp +++ b/pcbnew/class_board.cpp @@ -2017,6 +2017,84 @@ TRACK* BOARD::MarkTrace( TRACK* aTrace, } +MODULE* BOARD::GetFootprint( const wxPoint& aPosition, int aActiveLayer, + bool aVisibleOnly, bool aIgnoreLocked ) +{ + MODULE* pt_module; + MODULE* module = NULL; + MODULE* Altmodule = NULL; + int min_dim = 0x7FFFFFFF; + int alt_min_dim = 0x7FFFFFFF; + int layer; + + for( pt_module = m_Modules; pt_module; pt_module = (MODULE*) pt_module->Next() ) + { + // is the ref point within the module's bounds? + if( !pt_module->HitTest( aPosition ) ) + continue; + + // if caller wants to ignore locked modules, and this one is locked, skip it. + if( aIgnoreLocked && pt_module->IsLocked() ) + continue; + + /* Calculate priority: the priority is given to the layer of the + * module and the copper layer if the module layer is indelible, + * adhesive copper, a layer if cmp module layer is indelible, + * adhesive component. + */ + layer = pt_module->GetLayer(); + + if( layer==ADHESIVE_N_BACK || layer==SILKSCREEN_N_BACK ) + layer = LAYER_N_BACK; + else if( layer==ADHESIVE_N_FRONT || layer==SILKSCREEN_N_FRONT ) + layer = LAYER_N_FRONT; + + /* Test of minimum size to choosing the best candidate. */ + + EDA_RECT bb = pt_module->GetFootPrintRect(); + int offx = bb.GetX() + bb.GetWidth() / 2; + int offy = bb.GetY() + bb.GetHeight() / 2; + + //off x & offy point to the middle of the box. + int dist = abs( aPosition.x - offx ) + abs( aPosition.y - offy ); + + //int dist = MIN(lx, ly); // to pick the smallest module (kinda + // screwy with same-sized modules -- this is bad!) + + if( aActiveLayer == layer ) + { + if( dist <= min_dim ) + { + /* better footprint shown on the active layer */ + module = pt_module; + min_dim = dist; + } + } + else if( aVisibleOnly && IsModuleLayerVisible( layer ) ) + { + if( dist <= alt_min_dim ) + { + /* better footprint shown on other layers */ + Altmodule = pt_module; + alt_min_dim = dist; + } + } + } + + if( module ) + { + return module; + } + + if( Altmodule ) + { + return Altmodule; + } + + return NULL; +} + + #if defined(DEBUG) void BOARD::Show( int nestLevel, std::ostream& os ) diff --git a/pcbnew/class_board.h b/pcbnew/class_board.h index 3086d92c58..ab4a872036 100644 --- a/pcbnew/class_board.h +++ b/pcbnew/class_board.h @@ -1196,6 +1196,23 @@ public: */ TRACK* MarkTrace( TRACK* aTrace, int* aCount, int* aTraceLength, int* aDieLength, bool aReorder ); + + /** + * Function GetFootprint + * get a footprint by its bounding rectangle at \a aPosition on \a aLayer. + *

+ * If more than one footprint is at \a aPosition, then the closest footprint on the + * active layer is returned. The distance is calculated via manhattan distance from + * the center of the bounding rectangle to \a aPosition. + * + * @param aPosition Flag bits, tuning the search, see pcbnew.h + * @param aActiveLayer Layer to test. + * @param aVisibleOnly Search only the visible layers if true. + * @param aIgnoreLocked Ignore locked modules when true. + * @return MODULE* The best module or NULL if none. + */ + MODULE* GetFootprint( const wxPoint& aPosition, int aActiveLayer, + bool aVisibleOnly, bool aIgnoreLocked = false ); }; #endif // #ifndef CLASS_BOARD_H diff --git a/pcbnew/hotkeys_board_editor.cpp b/pcbnew/hotkeys_board_editor.cpp index 949b8def10..199d702134 100644 --- a/pcbnew/hotkeys_board_editor.cpp +++ b/pcbnew/hotkeys_board_editor.cpp @@ -599,7 +599,7 @@ void PCB_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotkeyCode, const wxPoint& aPosit if( !itemCurrentlyEdited ) { pos = screen->RefPos( true ); - module = Locate_Prefered_Module( GetBoard(), pos, screen->m_Active_Layer, true ); + module = GetBoard()->GetFootprint( pos, screen->m_Active_Layer, true ); } else if( GetCurItem()->Type() == TYPE_MODULE ) { @@ -689,7 +689,7 @@ bool PCB_EDIT_FRAME::OnHotkeyDeleteItem( wxDC* aDC ) if( ItemFree ) { wxPoint pos = GetScreen()->RefPos( false ); - MODULE* module = Locate_Prefered_Module( GetBoard(), pos, ALL_LAYERS, false ); + MODULE* module = GetBoard()->GetFootprint( pos, ALL_LAYERS, false ); if( module == NULL ) return false; diff --git a/pcbnew/locate.cpp b/pcbnew/locate.cpp deleted file mode 100644 index 8188a81f62..0000000000 --- a/pcbnew/locate.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/*******************/ -/* Locate element. */ -/*******************/ - - -#include "fctsys.h" - -#include "common.h" -#include "pcbnew.h" -#include "class_board_design_settings.h" - -#include "protos.h" - - -/** - * Function Locate_Prefered_Module - * locates a footprint by its bounding rectangle. If several footprints - * are possible, then the priority is: the closest on the active layer, then - * closest. - * The current mouse or cursor coordinates are grabbed from the active window - * to perform hit-testing. - * distance is calculated via manhattan distance from the center of the - * bounding rectangle to the cursor position. - * - * @param aPcb The BOARD to search within. - * @param aPosition Flag bits, tuning the search, see pcbnew.h - * @param aActiveLayer Layer to test. - * @param aVisibleOnly Search only the visible layers if true. - * @param aIgnoreLocked Ignore locked modules when true. - * @return MODULE* The best module or NULL if none. - */ -MODULE* Locate_Prefered_Module( BOARD* aPcb, const wxPoint& aPosition, int aActiveLayer, - bool aVisibleOnly, bool aIgnoreLocked ) -{ - MODULE* pt_module; - MODULE* module = NULL; - MODULE* Altmodule = NULL; - int min_dim = 0x7FFFFFFF; - int alt_min_dim = 0x7FFFFFFF; - int layer; - - pt_module = aPcb->m_Modules; - - for( ; pt_module; pt_module = (MODULE*) pt_module->Next() ) - { - // is the ref point within the module's bounds? - if( !pt_module->HitTest( aPosition ) ) - continue; - - // if caller wants to ignore locked modules, and this one is locked, skip it. - if( aIgnoreLocked && pt_module->IsLocked() ) - continue; - - /* Calculate priority: the priority is given to the layer of the - * module and the copper layer if the module layer is indelible, - * adhesive copper, a layer if cmp module layer is indelible, - * adhesive component. - */ - layer = pt_module->GetLayer(); - - if( layer==ADHESIVE_N_BACK || layer==SILKSCREEN_N_BACK ) - layer = LAYER_N_BACK; - else if( layer==ADHESIVE_N_FRONT || layer==SILKSCREEN_N_FRONT ) - layer = LAYER_N_FRONT; - - /* Test of minimum size to choosing the best candidate. */ - - EDA_RECT bb = pt_module->GetFootPrintRect(); - int offx = bb.GetX() + bb.GetWidth() / 2; - int offy = bb.GetY() + bb.GetHeight() / 2; - - //off x & offy point to the middle of the box. - int dist = abs( aPosition.x - offx ) + abs( aPosition.y - offy ); - - //int dist = MIN(lx, ly); // to pick the smallest module (kinda - // screwy with same-sized modules -- this is bad!) - - if( aActiveLayer == layer ) - { - if( dist <= min_dim ) - { - /* better footprint shown on the active layer */ - module = pt_module; - min_dim = dist; - } - } - else if( aVisibleOnly && aPcb->IsModuleLayerVisible( layer ) ) - { - if( dist <= alt_min_dim ) - { - /* better footprint shown on other layers */ - Altmodule = pt_module; - alt_min_dim = dist; - } - } - } - - if( module ) - { - return module; - } - - if( Altmodule ) - { - return Altmodule; - } - - return NULL; -} diff --git a/pcbnew/protos.h b/pcbnew/protos.h index a821042a3f..893c36e32d 100644 --- a/pcbnew/protos.h +++ b/pcbnew/protos.h @@ -61,15 +61,6 @@ void DrawTraces( EDA_DRAW_PANEL* panel, int nbsegment, int mode_color ); - -/****************/ -/* LOCATE.CPP : */ -/****************/ - -/* Locate a footprint by its bounding rectangle. */ -MODULE* Locate_Prefered_Module( BOARD* aPcb, const wxPoint& aPosition, int aActiveLayer, - bool aVisibleOnly, bool aIgnoreLocked = false ); - /*************/ /* MODULES.C */ /*************/ diff --git a/pcbnew/tool_pcb.cpp b/pcbnew/tool_pcb.cpp index 5be20290f8..085af50d52 100644 --- a/pcbnew/tool_pcb.cpp +++ b/pcbnew/tool_pcb.cpp @@ -1,16 +1,22 @@ -/***************************************/ -/* tool_pcb.cpp: PCB editor tool bars */ -/***************************************/ +/** + * @file tool_pcb.cpp + * @brief PCB editor tool bars + */ #include "fctsys.h" -#include "wx/wupdlock.h" +#include "help_common_strings.h" +#include "dialog_helpers.h" +#include "class_layer_box_selector.h" +#include "colors_selection.h" #include "pcbnew.h" #include "wxPcbStruct.h" #include "class_board_design_settings.h" -#include "colors_selection.h" -#include "dialog_helpers.h" #include "pcbnew_id.h" +#include "hotkeys.h" + +#include "wx/wupdlock.h" + #ifdef __UNIX__ #define LISTBOX_WIDTH 150 @@ -18,42 +24,40 @@ #define LISTBOX_WIDTH 130 #endif -#include "wx/ownerdrw.h" -#include "wx/menuitem.h" - -#include "hotkeys.h" - -#include "help_common_strings.h" -#include "class_layer_box_selector.h" - #define SEL_LAYER_HELP _( \ "Show active layer selections\nand select layer pair for route and place via" ) + /* Data to build the layer pair indicator button */ static wxBitmap* LayerPairBitmap = NULL; -static const char s_BitmapLayerIcon[16][16] = { +static const char s_BitmapLayerIcon[24][24] = { // 0 = draw pixel with active layer color - // 1 = draw pixel with top layer color (top/bottom layer used in - // autoroute and place via) + // 1 = draw pixel with top layer color (top/bottom layer used inautoroute and place via) // 2 = draw pixel with bottom layer color // 3 = draw pixel with via color - { 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 1, 1, 1, 1, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 1, 1, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 3, 3, 0, 1, 1, 3, 3, 0, 0, 0, 0 }, - { 2, 2, 2, 2, 3, 3, 0, 1, 1, 1, 1, 3, 3, 2, 2, 2 }, - { 2, 2, 2, 2, 3, 3, 1, 1, 1, 0, 0, 3, 3, 2, 2, 2 }, - { 2, 2, 2, 2, 3, 3, 1, 1, 1, 1, 0, 3, 3, 2, 2, 2 }, - { 0, 0, 0, 0, 0, 3, 3, 1, 1, 0, 3, 3, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 1, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 1, 1, 3, 3, 3, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 } + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 0, 1, 1, 1, 1, 3, 0, 0, 0, 0, 0, 0, 0 }, + { 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 0, 1, 1, 1, 1, 3, 3, 2, 2, 2, 2, 2, 2, 2 }, + { 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 1, 1, 1, 1, 0, 3, 3, 2, 2, 2, 2, 2, 2, 2 }, + { 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 1, 1, 1, 1, 0, 3, 3, 2, 2, 2, 2, 2, 2, 2 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 1, 1, 1, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; @@ -111,7 +115,7 @@ void PCB_EDIT_FRAME::PrepareLayerIndicator() /* Create the bitmap too and its Memory DC, if not already made */ if( LayerPairBitmap == NULL ) { - LayerPairBitmap = new wxBitmap( 16, 16 ); + LayerPairBitmap = new wxBitmap( 24, 24 ); } /* Draw the icon, with colors according to the active layer and layer @@ -119,42 +123,36 @@ void PCB_EDIT_FRAME::PrepareLayerIndicator() */ wxMemoryDC iconDC; iconDC.SelectObject( *LayerPairBitmap ); - int buttcolor = -1; wxPen pen; + int buttonColor = -1; - for( ii = 0; ii < 16; ii++ ) + for( ii = 0; ii < 24; ii++ ) { - for( jj = 0; jj < 16; jj++ ) + for( jj = 0; jj < 24; jj++ ) { - if( s_BitmapLayerIcon[ii][jj] != buttcolor ) + if( s_BitmapLayerIcon[ii][jj] != buttonColor ) { - buttcolor = s_BitmapLayerIcon[ii][jj]; - int color; - - switch( buttcolor ) + switch( s_BitmapLayerIcon[ii][jj] ) { default: case 0: - color = active_layer_color; + pen.SetColour( MakeColour( active_layer_color ) ); break; case 1: - color = Route_Layer_TOP_color; + pen.SetColour( MakeColour( Route_Layer_TOP_color) ); break; case 2: - color = Route_Layer_BOTTOM_color; + pen.SetColour( MakeColour( Route_Layer_BOTTOM_color ) ); break; case 3: - color = via_color; + pen.SetColour( MakeColour( via_color ) ); break; } - color &= MASKCOLOR; - pen.SetColour( ColorRefs[color].m_Red, - ColorRefs[color].m_Green, - ColorRefs[color].m_Blue ); + buttonColor = s_BitmapLayerIcon[ii][jj]; iconDC.SetPen( pen ); } @@ -444,8 +442,7 @@ void PCB_EDIT_FRAME::ReCreateVToolbar() } -/* Create the auxiliary vertical right toolbar, showing tools for - * microwave applications +/* Create the auxiliary vertical right toolbar, showing tools for microwave applications */ void PCB_EDIT_FRAME::ReCreateMicrowaveVToolbar() { diff --git a/pcbnew/track.cpp b/pcbnew/track.cpp deleted file mode 100644 index 049e2cdae3..0000000000 --- a/pcbnew/track.cpp +++ /dev/null @@ -1,395 +0,0 @@ -/***************** -* track.cpp -*****************/ - -#include "fctsys.h" - -#include "common.h" -#include "pcbnew.h" - -#include "protos.h" - -/* Functions to recognize a track. - * A track is a list of connected segments (or/and vias) from a starting to an ending point - * starting and ending points are a pad or a point with more than 2 segments connected - * (and obviously a dangling segment end) - */ - -typedef std::vector TRACK_PTRS; // buffer of item candidates when - // search for items on the same track - - -/* Local functions */ -static void ChainMarkedSegments( BOARD* Pcb, wxPoint ref_pos, int masklayer, TRACK_PTRS* aList ); - - -TRACK* MarkTrace( BOARD* aPcb, - TRACK* aStartSegm, - int* aSegmCount, - int* aTrackLen, - int* aLengthDie, - bool aReorder ) -{ - int NbSegmBusy; - - TRACK_PTRS trackList; - - if( aSegmCount ) - *aSegmCount = 0; - - if( aTrackLen ) - *aTrackLen = 0; - - if( aStartSegm == NULL ) - return NULL; - - // Ensure the flag BUSY of all tracks of the board is cleared - // because we use it to mark segments of the track - for( TRACK* track = aPcb->m_Track; track; track = track->Next() ) - track->SetState( BUSY, OFF ); - - /* Set flags of the initial track segment */ - aStartSegm->SetState( BUSY, ON ); - int layerMask = aStartSegm->ReturnMaskLayer(); - - trackList.push_back( aStartSegm ); - - /* Examine the initial track segment : if it is really a segment, this is - * easy. - * If it is a via, one must search for connected segments. - * If <=2, this via connect 2 segments (or is connected to only one - * segment) and this via and these 2 segments are a part of a track. - * If > 2 only this via is flagged (the track has only this via) - */ - if( aStartSegm->Type() == TYPE_VIA ) - { - TRACK* Segm1, * Segm2 = NULL, * Segm3 = NULL; - Segm1 = GetTrace( aPcb->m_Track, NULL, aStartSegm->m_Start, layerMask ); - - if( Segm1 ) - { - Segm2 = GetTrace( Segm1->Next(), NULL, aStartSegm->m_Start, layerMask ); - } - - if( Segm2 ) - { - Segm3 = GetTrace( Segm2->Next(), NULL, aStartSegm->m_Start, layerMask ); - } - - if( Segm3 ) // More than 2 segments are connected to this via. the track" is only this via - { - if( aSegmCount ) - *aSegmCount = 1; - - return aStartSegm; - } - - if( Segm1 ) // search for others segments connected to the initial segment start point - { - layerMask = Segm1->ReturnMaskLayer(); - ChainMarkedSegments( aPcb, aStartSegm->m_Start, layerMask, &trackList ); - } - - if( Segm2 ) // search for others segments connected to the initial segment end point - { - layerMask = Segm2->ReturnMaskLayer(); - ChainMarkedSegments( aPcb, aStartSegm->m_Start, layerMask, &trackList ); - } - } - else // mark the chain using both ends of the initial segment - { - ChainMarkedSegments( aPcb, aStartSegm->m_Start, layerMask, &trackList ); - ChainMarkedSegments( aPcb, aStartSegm->m_End, layerMask, &trackList ); - } - - // Now examine selected vias and flag them if they are on the track - // If a via is connected to only one or 2 segments, it is flagged (is on the track) - // If a via is connected to more than 2 segments, it is a track end, and it - // is removed from the list - // go through the list backwards. - for( int i = trackList.size() - 1; i>=0; --i ) - { - TRACK* via = trackList[i]; - - if( via->Type() != TYPE_VIA ) - continue; - - if( via == aStartSegm ) - continue; - - via->SetState( BUSY, ON ); // Try to flag it. the flag will be cleared later if needed - - layerMask = via->ReturnMaskLayer(); - - TRACK* track = GetTrace( aPcb->m_Track, NULL, via->m_Start, layerMask ); - - // GetTrace does not consider tracks flagged BUSY. - // So if no connected track found, this via is on the current track - // only: keep it - if( track == NULL ) - continue; - - /* If a track is found, this via connects also others segments of an - * other track. This case happens when the vias ends the selected - * track but must we consider this via is on the selected track, or - * on an other track. - * (this is important when selecting a track for deletion: must this - * via be deleted or not?) - * We consider here this via on the track if others segment connected - * to this via remain connected when removing this via. - * We search for all others segment connected together: - * if there are on the same layer, the via is on the selected track - * if there are on different layers, the via is on an other track - */ - int layer = track->GetLayer(); - - while( ( track = GetTrace( track->Next(), NULL, via->m_Start, layerMask ) ) != NULL ) - { - if( layer != track->GetLayer() ) - { - // The via connects segments of an other track: it is removed - // from list because it is member of an other track - via->SetState( BUSY, OFF ); - break; - } - } - } - - /* Rearrange the track list in order to have flagged segments linked - * from firstTrack so the NbSegmBusy segments are consecutive segments - * in list, the first item in the full track list is firstTrack, and - * the NbSegmBusy-1 next items (NbSegmBusy when including firstTrack) - * are the flagged segments - */ - NbSegmBusy = 0; - TRACK* firstTrack; - - for( firstTrack = aPcb->m_Track; firstTrack; firstTrack = firstTrack->Next() ) - { - // Search for the first flagged BUSY segments - if( firstTrack->GetState( BUSY ) ) - { - NbSegmBusy = 1; - break; - } - } - - if( firstTrack == NULL ) - return NULL; - - double full_len = 0; - double lenDie = 0; - - if( aReorder ) - { - DLIST* list = (DLIST*)firstTrack->GetList(); - wxASSERT( list ); - - /* Rearrange the chain starting at firstTrack - * All others flagged items are moved from their position to the end - * of the flagged list - */ - TRACK* next; - - for( TRACK* track = firstTrack->Next(); track; track = next ) - { - next = track->Next(); - - if( track->GetState( BUSY ) ) // move it! - { - NbSegmBusy++; - track->UnLink(); - list->Insert( track, firstTrack->Next() ); - - if( aTrackLen ) - full_len += track->GetLength(); - - if( aLengthDie ) // Add now length die. - { - // In fact only 2 pads (maximum) will be taken in account: - // that are on each end of the track, if any - if( track->GetState( BEGIN_ONPAD ) ) - { - D_PAD * pad = (D_PAD *) track->start; - lenDie += (double) pad->m_LengthDie; - } - - if( track->GetState( END_ONPAD ) ) - { - D_PAD * pad = (D_PAD *) track->end; - lenDie += (double) pad->m_LengthDie; - } - } - } - } - } - else if( aTrackLen ) - { - NbSegmBusy = 0; - - for( TRACK* track = firstTrack; track; track = track->Next() ) - { - if( track->GetState( BUSY ) ) - { - NbSegmBusy++; - track->SetState( BUSY, OFF ); - full_len += track->GetLength(); - - // Add now length die. - // In fact only 2 pads (maximum) will be taken in account: - // that are on each end of the track, if any - if( track->GetState( BEGIN_ONPAD ) ) - { - D_PAD * pad = (D_PAD *) track->start; - lenDie += (double) pad->m_LengthDie; - } - - if( track->GetState( END_ONPAD ) ) - { - D_PAD * pad = (D_PAD *) track->end; - lenDie += (double) pad->m_LengthDie; - } - } - } - } - - if( aTrackLen ) - *aTrackLen = wxRound( full_len ); - - if( aLengthDie ) - *aLengthDie = wxRound( lenDie ); - - if( aSegmCount ) - *aSegmCount = NbSegmBusy; - - return firstTrack; -} - - -/** - * Function used by MarkTrace - * - Set the BUSY flag of connected segments, the first search point is - * ref_pos on layers allowed in masque_layer - * - Put segments fount in aList - * Vias are put in list but their flags BUSY is not set - * @param aPcb = the board - * @param aRef_pos = the reference coordinate of the starting search - * @param aLayerMask = the allowed layers for segments to search - * (1 layer when starting point is on a segment, but more than one when - * starting point is on a via) - * @param aList = the track list to fill with points of segments flagged - */ -static void ChainMarkedSegments( BOARD* aPcb, - wxPoint aRef_pos, - int aLayerMask, - TRACK_PTRS* aList ) -{ - TRACK* pt_segm, // The current segment being analyzed. - * pt_via, // The via identified, eventually destroy - - * SegmentCandidate; // The end segment to destroy (or NULL = pt_segm - int NbSegm; - - if( aPcb->m_Track == NULL ) - return; - - /* Set the BUSY flag of all connected segments, first search starting at - * aRef_pos - * Search ends when: - * - a pad is found (end of a track) - * - a segment end has more than one other segment end connected - * - and obviously when no connected item found - * Vias are a special case, because we must see others segment connected - * on others layers and they change the layer mask. They can be a track - * end or not - * They will be analyzer later, and vias on terminal points of the track - * will be considered as part of this track if they do not connect segments - * of an other track together and will be considered as part of an other - * track if when removing the via, the segments of that other track are - * disconnected - */ - for( ; ; ) - { - if( aPcb->GetPadFast( aRef_pos, aLayerMask ) != NULL ) - return; - - /* Test for a via: a via changes the layer mask and can connect a lot - * of segments at location aRef_pos. When found, the via is just - * pushed in list. Vias will be examined later, when all connected - * segment are found and push in list. This is because when a via - * is found we do not know at this time the number of connected items - * and we do not know if this via is on the track or finish the track - */ - pt_via = aPcb->m_Track->GetVia( NULL, aRef_pos, aLayerMask ); - - if( pt_via ) - { - aLayerMask = pt_via->ReturnMaskLayer(); - - aList->push_back( pt_via ); - } - - /* Now we search all segments connected to point aRef_pos - * if only 1 segment: this segment is candidate - * if > 1 segment: - * end of track (more than 2 segment connected at this location) - */ - pt_segm = aPcb->m_Track; SegmentCandidate = NULL; - NbSegm = 0; - - while( ( pt_segm = GetTrace( pt_segm, NULL, aRef_pos, aLayerMask ) ) != NULL ) - { - if( pt_segm->GetState( BUSY ) ) // already found and selected: skip it - { - pt_segm = pt_segm->Next(); - continue; - } - - if( pt_segm == pt_via ) // just previously found: skip it - { - pt_segm = pt_segm->Next(); - continue; - } - - NbSegm++; - - if( NbSegm == 1 ) /* First time we found a connected item: pt_segm is candidate */ - { - SegmentCandidate = pt_segm; - pt_segm = pt_segm->Next(); - } - else /* More than 1 segment connected -> this location is an end of the track */ - { - return; - } - } - - if( SegmentCandidate ) // A candidate is found: flag it an push it in list - { - /* Initialize parameters to search items connected to this - * candidate: - * we must analyze connections to its other end - */ - aLayerMask = SegmentCandidate->ReturnMaskLayer(); - - if( aRef_pos == SegmentCandidate->m_Start ) - { - aRef_pos = SegmentCandidate->m_End; - } - else - { - aRef_pos = SegmentCandidate->m_Start; - } - - pt_segm = aPcb->m_Track; /* restart list of tracks to analyze */ - - /* flag this item an push it in list of selected items */ - aList->push_back( SegmentCandidate ); - SegmentCandidate->SetState( BUSY, ON ); - } - else - { - return; - } - } -}