Refactor PCBNew lock point and sorted pad list functions into board object.

This commit is contained in:
Wayne Stambaugh 2011-09-16 21:22:26 -04:00
parent 1c4d925d1f
commit 5427a68a7b
8 changed files with 212 additions and 233 deletions

View File

@ -19,6 +19,19 @@ wxPoint BOARD_ITEM::ZeroOffset( 0, 0 );
BOARD_DESIGN_SETTINGS boardDesignSettings;
/**
* Function SortPadsByXCoord
* is used to Sort a pad list by x coordinate value.
*/
static int sortPadsByXCoord( const void* pt_ref, const void* pt_comp )
{
D_PAD* ref = *(LISTE_PAD*) pt_ref;
D_PAD* comp = *(LISTE_PAD*) pt_comp;
return ref->m_Pos.x - comp->m_Pos.x;
}
BOARD::BOARD( EDA_ITEM* parent, PCB_BASE_FRAME* frame ) :
BOARD_ITEM( (BOARD_ITEM*)parent, TYPE_PCB ),
m_NetClasses( this )
@ -1744,6 +1757,15 @@ D_PAD* BOARD::GetPad( LISTE_PAD* aPad, const wxPoint& aPosition, int aLayerMask
}
void BOARD::GetSortedPadListByXCoord( std::vector<D_PAD*>& aVector )
{
aVector.insert( aVector.end(), m_NetInfo->m_PadsFullList.begin(),
m_NetInfo->m_PadsFullList.end() );
qsort( &aVector[0], GetPadsCount(), sizeof( D_PAD*), sortPadsByXCoord );
}
TRACK* BOARD::GetTrace( TRACK* aTrace, const wxPoint& aPosition, int aLayerMask )
{
for( TRACK* track = aTrace; track; track = track->Next() )
@ -2095,6 +2117,122 @@ MODULE* BOARD::GetFootprint( const wxPoint& aPosition, int aActiveLayer,
}
BOARD_ITEM* BOARD::GetLockPoint( const wxPoint& aPosition, int aLayerMask )
{
for( MODULE* module = m_Modules; module; module = module->Next() )
{
D_PAD* pad = module->GetPad( aPosition, aLayerMask );
if( pad )
return pad;
}
/* No pad has been located so check for a segment of the trace. */
TRACK* segment = ::GetTrace( m_Track, NULL, aPosition, aLayerMask );
if( segment == NULL )
segment = GetTrace( m_Track, aPosition, aLayerMask );
return segment;
}
TRACK* BOARD::CreateLockPoint( wxPoint& aPosition, TRACK* aSegment, PICKED_ITEMS_LIST* aList )
{
if( aSegment->m_Start == aPosition || aSegment->m_End == aPosition )
return NULL;
/* A via is a good lock point */
if( aSegment->Type() == TYPE_VIA )
{
aPosition = aSegment->m_Start;
return aSegment;
}
// Calculation coordinate of intermediate point relative to the start point of aSegment
wxPoint delta = aSegment->m_End - aSegment->m_Start;
// Not yet in use:
#if 0
int ox, oy, fx, fy;
if( aRefSegm )
{
ox = aRefSegm->m_Start.x - aSegment->m_Start.x;
oy = aRefSegm->m_Start.y - aSegment->m_Start.y;
fx = aRefSegm->m_End.x - aSegment->m_Start.x;
fy = aRefSegm->m_End.y - aSegment->m_Start.y;
}
#endif
// calculate coordinates of aPosition relative to aSegment->m_Start
wxPoint newPoint = aPosition - aSegment->m_Start;
// newPoint must be on aSegment:
// Ensure newPoint.y/newPoint.y = delta.y/delta.x
if( delta.x == 0 )
newPoint.x = 0; /* horizontal segment*/
else
newPoint.y = wxRound( ( (double)newPoint.x * delta.y ) / delta.x );
/* Create the intermediate point (that is to say creation of a new
* segment, beginning at the intermediate point.
*/
newPoint.x += aSegment->m_Start.x;
newPoint.y += aSegment->m_Start.y;
TRACK* newTrack = aSegment->Copy();
if( aList )
{
ITEM_PICKER picker( newTrack, UR_NEW );
aList->PushItem( picker );
}
DLIST<TRACK>* list = (DLIST<TRACK>*)aSegment->GetList();
wxASSERT( list );
list->Insert( newTrack, aSegment->Next() );
if( aList )
{
ITEM_PICKER picker( aSegment, UR_CHANGED );
picker.m_Link = aSegment->Copy();
aList->PushItem( picker );
}
/* Correct pointer at the end of the new segment. */
newTrack->end = aSegment->end;
newTrack->SetState( END_ONPAD, aSegment->GetState( END_ONPAD ) );
/* Set connections info relative to the new point
*/
/* Old segment now ends at new point. */
aSegment->m_End = newPoint;
aSegment->end = newTrack;
aSegment->SetState( END_ONPAD, OFF );
/* The new segment begins at the new point. */
newTrack->m_Start = newPoint;
newTrack->start = aSegment;
newTrack->SetState( BEGIN_ONPAD, OFF );
D_PAD * pad = GetPad( newTrack, START );
if ( pad )
{
newTrack->start = pad;
newTrack->SetState( BEGIN_ONPAD, ON );
aSegment->end = pad;
aSegment->SetState( END_ONPAD, ON );
}
aPosition = newPoint;
return newTrack;
}
#if defined(DEBUG)
void BOARD::Show( int nestLevel, std::ostream& os )

View File

@ -1157,6 +1157,17 @@ public:
*/
D_PAD* GetPad( LISTE_PAD* aPad, const wxPoint& aPosition, int aLayerMask );
/**
* Function GetSortedPadListByXCoord
* first empties then fills the vector with all pads and sorts them by
* increasing x coordinate. The vector only holds pointers to the pads and
* those pointers are only references to pads which are owned by the BOARD
* through other links.
* @param aVector Where to put the pad pointers.
*/
void GetSortedPadListByXCoord( std::vector<D_PAD*>& aVector );
/**
* Function GetTrace
* find the segment of \a aTrace at \a aPosition on \a aLayer if \a Layer is visible.
@ -1205,7 +1216,7 @@ public:
* 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 aPosition A wxPoint object containing the position to test.
* @param aActiveLayer Layer to test.
* @param aVisibleOnly Search only the visible layers if true.
* @param aIgnoreLocked Ignore locked modules when true.
@ -1213,6 +1224,40 @@ public:
*/
MODULE* GetFootprint( const wxPoint& aPosition, int aActiveLayer,
bool aVisibleOnly, bool aIgnoreLocked = false );
/**
* Function GetLockPoint
* returns the item at the "attachment" point at the end of a trace at \a aPosition
* on \a aLayerMask.
* <p>
* This may be a PAD or another trace segment.
* </p>
*
* @param aPosition A wxPoint object containing the position to test.
* @param aLayerMask A layer or layers to mask the hit test. Use -1 to ignore
* layer mask.
* @return A pointer to a BOARD_ITEM object if found otherwise NULL.
*/
BOARD_ITEM* GetLockPoint( const wxPoint& aPosition, int aLayerMask );
/**
* Function CreateLockPoint
* creates an intermediate point on \a aSegment and break it into two segments
* at \a aPoition.
* <p>
* The new segment starts from \a aPosition and ends at the end point of \a
* aSegement. The original segment now ends at \a aPosition.
* </p>
*
* @param aPosition A wxPoint object containing the position to test and the new
* segment start position if the return value is not NULL.
* @param aSegment The trace segment to create the lock point on.
* @param aList The pick list to add the created items to.
* @return NULL if no new point was created or a pointer to a TRACK ojbect of the
* created segment. If \a aSegment points to a via the exact value of \a
* aPosition and a pointer to the via are returned.
*/
TRACK* CreateLockPoint( wxPoint& aPosition, TRACK* aSegment, PICKED_ITEMS_LIST* aList );
};
#endif // #ifndef CLASS_BOARD_H

View File

@ -469,27 +469,6 @@ static void Build_Pads_Info_Connections_By_Tracks( TRACK* pt_start_conn, TRACK*
#define POS_AFF_CHREF 62
/**
* Function SortPadsByXCoord
* is used to Sort a pad list by x coordinate value.
*/
static int SortPadsByXCoord( const void* pt_ref, const void* pt_comp )
{
D_PAD* ref = *(LISTE_PAD*) pt_ref;
D_PAD* comp = *(LISTE_PAD*) pt_comp;
return ref->m_Pos.x - comp->m_Pos.x;
}
void CreateSortedPadListByXCoord( BOARD* aBoard, std::vector<D_PAD*>* aVector )
{
aVector->insert( aVector->end(), aBoard->m_NetInfo->m_PadsFullList.begin(),
aBoard->m_NetInfo->m_PadsFullList.end() );
qsort( &(*aVector)[0], aBoard->GetPadsCount(), sizeof( D_PAD*), SortPadsByXCoord );
}
void PCB_BASE_FRAME::RecalculateAllTracksNetcode()
{
@ -523,7 +502,7 @@ void PCB_BASE_FRAME::RecalculateAllTracksNetcode()
/**************************************************************/
/* Pass 1: search the connections between track ends and pads */
/**************************************************************/
CreateSortedPadListByXCoord( m_Pcb, &sortedPads );
m_Pcb->GetSortedPadListByXCoord( sortedPads );
/* Reset variables and flags used in computation */
pt_trace = m_Pcb->m_Track;

View File

@ -25,7 +25,7 @@
*/
/****************************/
/* DRC control */
/* DRC control */
/****************************/
#include "fctsys.h"
@ -121,9 +121,7 @@ DRC::~DRC()
}
/*********************************************/
int DRC::Drc( TRACK* aRefSegm, TRACK* aList )
/*********************************************/
{
updatePointers();
@ -411,7 +409,7 @@ void DRC::testPad2Pad()
{
std::vector<D_PAD*> sortedPads;
CreateSortedPadListByXCoord( m_pcb, &sortedPads );
m_pcb->GetSortedPadListByXCoord( sortedPads );
// find the max size of the pads (used to stop the test)
int max_size = 0;
@ -420,7 +418,8 @@ void DRC::testPad2Pad()
{
D_PAD* pad = sortedPads[i];
if( pad->m_ShapeMaxRadius > max_size ) // m_ShapeMaxRadius is the radius value of the circle containing the pad
// m_ShapeMaxRadius is the radius value of the circle containing the pad
if( pad->m_ShapeMaxRadius > max_size )
max_size = pad->m_ShapeMaxRadius;
}
@ -491,7 +490,7 @@ void DRC::testUnconnected()
void DRC::testZones( bool adoTestFillSegments )
{
// Test copper areas for valide netcodes
// Test copper areas for valid netcodes
// if a netcode is < 0 the netname was not found when reading a netlist
// if a netcode is == 0 the netname is void, and the zone is not connected.
// This is allowed, but i am not sure this is a good idea
@ -558,7 +557,7 @@ bool DRC::doPadToPadsDrc( D_PAD* aRefPad, LISTE_PAD* aStart, LISTE_PAD* aEnd, in
MODULE dummymodule( m_pcb ); // Creates a dummy parent
D_PAD dummypad( &dummymodule );
dummypad.m_layerMask |= ALL_CU_LAYERS; // Ensure the hole is on all copper layers
dummypad.m_LocalClearance = 1; /* Use the minimal local clerance value for the dummy pad
dummypad.m_LocalClearance = 1; /* Use the minimal local clearance value for the dummy pad
* the clearance of the active pad will be used
* as minimum distance to a hole
* (a value = 0 means use netclass value)
@ -577,7 +576,7 @@ bool DRC::doPadToPadsDrc( D_PAD* aRefPad, LISTE_PAD* aStart, LISTE_PAD* aEnd, in
break;
// No problem if pads are on different copper layers,
// but their hole (if any ) can create RDC error because they are on all
// but their hole (if any ) can create DRC error because they are on all
// copper layers, so we test them
if( (pad->m_layerMask & layerMask ) == 0 )
{
@ -590,20 +589,24 @@ bool DRC::doPadToPadsDrc( D_PAD* aRefPad, LISTE_PAD* aStart, LISTE_PAD* aEnd, in
if( aRefPad->m_DrillShape == PAD_CIRCLE )
continue;
if( pad->m_Orient == aRefPad->m_Orient ) // for oval holes: must also have the same orientation
// for oval holes: must also have the same orientation
if( pad->m_Orient == aRefPad->m_Orient )
continue;
}
/* Here, we must test clearance between holes and pads
* dummypad size and shape is adjusted to pad drill size and shape
* dummy pad size and shape is adjusted to pad drill size and shape
*/
if( pad->m_Drill.x ) // pad under testing has a hole, test this hole against pad reference
if( pad->m_Drill.x )
{
// pad under testing has a hole, test this hole against pad reference
dummypad.SetPosition( pad->GetPosition() );
dummypad.m_Size = pad->m_Drill;
dummypad.m_PadShape = (pad->m_DrillShape == PAD_OVAL) ? PAD_OVAL : PAD_CIRCLE;
dummypad.m_Orient = pad->m_Orient;
dummypad.ComputeShapeMaxRadius(); // compute the radius of the circle containing this pad
// compute the radius of the circle containing this pad
dummypad.ComputeShapeMaxRadius();
if( !checkClearancePadToPad( aRefPad, &dummypad ) )
{
@ -620,10 +623,13 @@ bool DRC::doPadToPadsDrc( D_PAD* aRefPad, LISTE_PAD* aStart, LISTE_PAD* aEnd, in
dummypad.m_Size = aRefPad->m_Drill;
dummypad.m_PadShape = (aRefPad->m_DrillShape == PAD_OVAL) ? PAD_OVAL : PAD_CIRCLE;
dummypad.m_Orient = aRefPad->m_Orient;
dummypad.ComputeShapeMaxRadius(); // compute the radius of the circle containing this pad
// compute the radius of the circle containing this pad
dummypad.ComputeShapeMaxRadius();
if( !checkClearancePadToPad( pad, &dummypad ) )
{
// here we have a drc erroron aRefPad!
// here we have a drc error on aRefPad!
m_currentMarker = fillMarker( aRefPad, pad,
DRCE_HOLE_NEAR_PAD, m_currentMarker );
return false;

View File

@ -1001,7 +1001,7 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
wxPoint pos = GetScreen()->GetCrossHairPosition();
track->Draw( DrawPanel, &dc, GR_XOR );
PICKED_ITEMS_LIST itemsListPicker;
TRACK* newtrack = CreateLockPoint( GetBoard(), pos, track, &itemsListPicker );
TRACK* newtrack = GetBoard()->CreateLockPoint( pos, track, &itemsListPicker );
SaveCopyInUndoList( itemsListPicker, UR_UNSPECIFIED );
track->Draw( DrawPanel, &dc, GR_XOR );
newtrack->Draw( DrawPanel, &dc, GR_XOR );

View File

@ -89,7 +89,7 @@ TRACK* PCB_EDIT_FRAME::Begin_Route( TRACK* aTrack, wxDC* aDC )
GetBoard()->SetHighLightNet( 0 );
// Search for a starting point of the new track, a track or pad
LockPoint = LocateLockPoint( GetBoard(), pos, layerMask );
LockPoint = GetBoard()->GetLockPoint( pos, layerMask );
if( LockPoint ) // An item (pad or track) is found
{
@ -105,7 +105,7 @@ TRACK* PCB_EDIT_FRAME::Begin_Route( TRACK* aTrack, wxDC* aDC )
{
TrackOnStartPoint = (TRACK*) LockPoint;
GetBoard()->SetHighLightNet( TrackOnStartPoint->GetNet() );
CreateLockPoint( GetBoard(), pos, TrackOnStartPoint, &s_ItemsListPicker );
GetBoard()->CreateLockPoint( pos, TrackOnStartPoint, &s_ItemsListPicker );
}
}
else
@ -420,7 +420,7 @@ bool PCB_EDIT_FRAME::End_Route( TRACK* aTrack, wxDC* aDC )
* This helps to reduce the computing time */
/* Attaching the end of the track. */
BOARD_ITEM* LockPoint = LocateLockPoint( GetBoard(), pos, layerMask );
BOARD_ITEM* LockPoint = GetBoard()->GetLockPoint( pos, layerMask );
if( LockPoint ) /* End of trace is on a pad. */
{
@ -434,10 +434,9 @@ bool PCB_EDIT_FRAME::End_Route( TRACK* aTrack, wxDC* aDC )
GetBoard()->SetHighLightNet( adr_buf->GetNet() );
/* Possible establishment of a hanging point. */
LockPoint = CreateLockPoint( GetBoard(),
g_CurrentTrackSegment->m_End,
adr_buf,
&s_ItemsListPicker );
LockPoint = GetBoard()->CreateLockPoint( g_CurrentTrackSegment->m_End,
adr_buf,
&s_ItemsListPicker );
}
}

View File

@ -1038,148 +1038,3 @@ bool PCB_EDIT_FRAME::PlaceDraggedOrMovedTrackSegment( TRACK* Track, wxDC* DC )
return true;
}
/* Find the point "attachment" of the end of a trace.
* This may be a TBP or another segment of the trace
* Returns:
* - Pointer to the PAD or:
* - Pointer to the segment or:
* - NULL
* Parameters:
* - position to test
* - mask layers to be tested
*/
BOARD_ITEM* LocateLockPoint( BOARD* Pcb, wxPoint pos, int LayerMask )
{
for( MODULE* module = Pcb->m_Modules; module; module = module->Next() )
{
D_PAD* pad = module->GetPad( pos, LayerMask );
if( pad )
return pad;
}
/* No pad has been located so check for a segment of the trace. */
TRACK* ptsegm = GetTrace( Pcb->m_Track, NULL, pos, LayerMask );
if( ptsegm == NULL )
ptsegm = Pcb->GetTrace( Pcb->m_Track, pos, LayerMask );
return ptsegm;
}
/* Create an intermediate point on a segment
* aSegm segment is broken into 2 segments connecting point pX, pY
* After insertion:
* The new segment starts from to new point, and ends to initial aSegm ending point
* the old segment aSegm ends to new point
* Returns:
* NULL if no new point (ie if aRefPoint already corresponded at one end of aSegm
* or
* Pointer to the segment created
* Returns the exact value of aRefPoint
* If aSegm points to a via:
* Returns the exact value of aRefPoint and a pointer to the via,
* But does not create extra point
*/
TRACK* CreateLockPoint( BOARD* aPcb,
wxPoint& aRefPoint,
TRACK* aSegm,
PICKED_ITEMS_LIST* aItemsListPicker )
{
if( aSegm->m_Start == aRefPoint || aSegm->m_End == aRefPoint )
return NULL;
/* A via is a good lock point */
if( aSegm->Type() == TYPE_VIA )
{
aRefPoint = aSegm->m_Start;
return aSegm;
}
/* Calculation coordinate of intermediate point relative to
* the start point of aSegm
*/
wxPoint delta = aSegm->m_End - aSegm->m_Start;
// Not yet in use:
#if 0
int ox, oy, fx, fy;
if( aRefSegm )
{
ox = aRefSegm->m_Start.x - aSegm->m_Start.x;
oy = aRefSegm->m_Start.y - aSegm->m_Start.y;
fx = aRefSegm->m_End.x - aSegm->m_Start.x;
fy = aRefSegm->m_End.y - aSegm->m_Start.y;
}
#endif
// calculate coordinates of aRefPoint relative to aSegm->m_Start
wxPoint newPoint = aRefPoint - aSegm->m_Start;
// newPoint must be on aSegm:
// Ensure newPoint.y/newPoint.y = delta.y/delta.x
if( delta.x == 0 )
newPoint.x = 0; /* horizontal segment*/
else
newPoint.y = wxRound(( (double)newPoint.x * delta.y ) / delta.x);
/* Create the intermediate point (that is to say creation of a new
* segment, beginning at the intermediate point.
*/
newPoint.x += aSegm->m_Start.x;
newPoint.y += aSegm->m_Start.y;
TRACK* newTrack = aSegm->Copy();
if( aItemsListPicker )
{
ITEM_PICKER picker( newTrack, UR_NEW );
aItemsListPicker->PushItem( picker );
}
DLIST<TRACK>* list = (DLIST<TRACK>*)aSegm->GetList();
wxASSERT( list );
list->Insert( newTrack, aSegm->Next() );
if( aItemsListPicker )
{
ITEM_PICKER picker( aSegm, UR_CHANGED );
picker.m_Link = aSegm->Copy();
aItemsListPicker->PushItem( picker );
}
/* Correct pointer at the end of the new segment. */
newTrack->end = aSegm->end;
newTrack->SetState( END_ONPAD, aSegm->GetState( END_ONPAD ) );
/* Set connections info relative to the new point
*/
/* Old segment now ends at new point. */
aSegm->m_End = newPoint;
aSegm->end = newTrack;
aSegm->SetState( END_ONPAD, OFF );
/* The new segment begins at the new point. */
newTrack->m_Start = newPoint;
newTrack->start = aSegm;
newTrack->SetState( BEGIN_ONPAD, OFF );
D_PAD * pad = aPcb->GetPad( newTrack, START );
if ( pad )
{
newTrack->start = pad;
newTrack->SetState( BEGIN_ONPAD, ON );
aSegm->end = pad;
aSegm->SetState( END_ONPAD, ON );
}
aRefPoint = newPoint;
return newTrack;
}

View File

@ -28,17 +28,6 @@ void SwapData( BOARD_ITEM* aItem, BOARD_ITEM* aImage );
class D_PAD;
/**
* Function CreateSortedPadListByXCoord
* first empties then fills the vector with all pads and sorts them by
* increasing x coordinate. The vector only holds pointers to the pads and
* those pointers are only references to pads which are owned by the BOARD
* through other links.
* @param aBoard Which board to gather pads from.
* @param aVector Where to put the pad pointers.
*/
void CreateSortedPadListByXCoord( BOARD* aBoard, std::vector<D_PAD*>* aVector );
/***************/
/* TRPISTE.CPP */
@ -84,38 +73,6 @@ void ShowNewTrackWhenMovingCursor( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPo
void CalculateSegmentEndPoint( const wxPoint& aPosition, int ox, int oy, int* fx, int* fy );
/* Routine to find the point "attachment" at the end of a trace.
* This may be a PAD or another trace segment.
* Returns:
* - Pointer to the PAD or:
* - Pointer to the segment or:
* - NULL
* Parameters:
* - aPos - coordinate point test
* ALayerMask of mask layers to be tested
*/
BOARD_ITEM* LocateLockPoint( BOARD* aPcb, wxPoint aPos, int aLayerMask );
/* Create an intermediate point on a segment
* aSegm segment is broken into 2 segments connecting point pX, pY
* After insertion:
* The new segment starts from to new point, and ends to initial aSegm ending point
* the old segment aSegm ends to new point
* Returns:
* NULL if no new point (ie if aRefPoint already corresponded at one end of aSegm
* or
* Pointer to the segment created
* Returns the exact value of aRefPoint
* If aSegm points to a via:
* Returns the exact value of aRefPoint and a pointer to the via,
* But does not create extra point
*/
TRACK* CreateLockPoint( BOARD* aPcb,
wxPoint& aRefPoint,
TRACK* aSegm,
PICKED_ITEMS_LIST* aItemsListPicker );
/****************/
/* CONTROLE.CPP */
/****************/