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.
This commit is contained in:
parent
ab76e809ac
commit
1c4d925d1f
|
@ -4,6 +4,10 @@
|
|||
#include "hotkeys_basic.h"
|
||||
#include <wx/bmpcbox.h>
|
||||
|
||||
|
||||
class EDA_TOOLBAR;
|
||||
|
||||
|
||||
/* class to display a layer list.
|
||||
*
|
||||
*/
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
#define _DIALOG_HELPERS_H_
|
||||
|
||||
|
||||
#include "common.h" // EDA_UNITS_T
|
||||
|
||||
|
||||
/**
|
||||
* class EDA_LIST_DIALOG
|
||||
*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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.
|
||||
* <p>
|
||||
* 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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
||||
/*************/
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
395
pcbnew/track.cpp
395
pcbnew/track.cpp
|
@ -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*> 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<TRACK>* list = (DLIST<TRACK>*)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;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue