Fix bugs in autoplac.cpp

This commit is contained in:
jean-pierre charras 2013-11-25 12:29:16 +01:00
parent 1b58582e25
commit 18616d7782
1 changed files with 69 additions and 56 deletions

View File

@ -1,6 +1,6 @@
/**
* @file autoplac.cpp
* @brief Routiness to automatically place MODULES on a board.
* @brief Functions to automatically place Footprints on a board.
*/
/*
@ -57,9 +57,8 @@
#define KEEP_OUT_MARGIN 500
/* Penalty for guidance given by CntRot90 and CntRot180:
* graduated from 0 (rotation allowed) to 10 (rotation not allowed)
* the count is increased.
/* Penalty (cost) for CntRot90 and CntRot180:
* CntRot90 and CntRot180 are from 0 (rotation allowed) to 10 (rotation not allowed)
*/
static const double OrientPenality[11] =
{
@ -79,6 +78,7 @@ static const double OrientPenality[11] =
// Cell states.
#define OUT_OF_BOARD -2
#define OCCUPED_By_MODULE -1
#define FREE_CELL 0
static wxPoint CurrPosition; // Current position of the current module placement
@ -114,8 +114,11 @@ static double compute_Ratsnest_PlaceModule( BOARD* aBrd );
/* Place a footprint on the Routing matrix.
*/
void genModuleOnRoutingMatrix( MODULE* Module );
/*
* Displays the Placement/Routing matrix on the screen
*/
static void drawPlacementRoutingMatrix( BOARD* aBrd, wxDC* DC );
static void drawInfoPlace( BOARD* aBrd, wxDC* DC );
static int TstModuleOnBoard( BOARD* Pcb, MODULE* Module, bool TstOtherSide );
static void CreateKeepOutRectangle( int ux0, int uy0, int ux1, int uy1,
@ -180,8 +183,8 @@ void PCB_EDIT_FRAME::AutoPlaceModule( MODULE* Module, int place_mode, wxDC* DC )
RoutingMatrix.m_GridRouting = (int) GetScreen()->GetGridSize().x;
// Ensure Board.m_GridRouting has a reasonable value:
if( RoutingMatrix.m_GridRouting < 10 * IU_PER_MILS )
RoutingMatrix.m_GridRouting = 10 * IU_PER_MILS; // Min value = 1/100 inch
if( RoutingMatrix.m_GridRouting < Millimeter2iu( 0.25 ) )
RoutingMatrix.m_GridRouting = Millimeter2iu( 0.25 );
// Compute module parameters used in auto place
if( genPlacementRoutingMatrix( GetBoard(), m_messagePanel ) == 0 )
@ -255,7 +258,6 @@ void PCB_EDIT_FRAME::AutoPlaceModule( MODULE* Module, int place_mode, wxDC* DC )
break;
}
if( Module->NeedsPlaced() ) // Erase from screen
{
moduleCount++;
@ -267,12 +269,11 @@ void PCB_EDIT_FRAME::AutoPlaceModule( MODULE* Module, int place_mode, wxDC* DC )
}
}
// Undo command: commit list
// Undo command: prepare list
if( newList.GetCount() )
SaveCopyInUndoList( newList, UR_CHANGED );
int cnt = 0;
int ii;
wxString msg;
while( ( Module = PickModule( this, DC ) ) != NULL )
@ -281,36 +282,37 @@ void PCB_EDIT_FRAME::AutoPlaceModule( MODULE* Module, int place_mode, wxDC* DC )
msg.Printf( _( "Place module %d of %d" ), cnt, moduleCount );
SetStatusText( msg );
double initialOrient = Module->GetOrientation();
// Display fill area of interest, barriers, penalties.
drawInfoPlace( GetBoard(), DC );
drawPlacementRoutingMatrix( GetBoard(), DC );
error = getOptimalModulePlacement( this, Module, DC );
double BestScore = MinCout;
double bestScore = MinCout;
double bestRotation = 0.0;
int rotAllowed;
PosOK = CurrPosition;
if( error == ESC )
goto end_of_tst;
// Determine if the best orientation of a module is 180.
ii = Module->GetPlacementCost180() & 0x0F;
// Try orientations 90, 180, 270 degrees from initial orientation
rotAllowed = Module->GetPlacementCost180();
if( ii != 0 )
if( rotAllowed != 0 )
{
int Angle_Rot_Module = 1800;
Rotate_Module( DC, Module, Angle_Rot_Module, false );
Module->CalculateBoundingBox();
Rotate_Module( DC, Module, 1800.0, true );
error = getOptimalModulePlacement( this, Module, DC );
MinCout *= OrientPenality[ii];
MinCout *= OrientPenality[rotAllowed];
if( BestScore > MinCout ) // This orientation is best.
if( bestScore > MinCout ) // This orientation is better.
{
PosOK = CurrPosition;
BestScore = MinCout;
bestScore = MinCout;
bestRotation = 1800.0;
}
else
{
Angle_Rot_Module = -1800;
Rotate_Module( DC, Module, Angle_Rot_Module, false );
Rotate_Module( DC, Module, initialOrient, false );
}
if( error == ESC )
@ -318,49 +320,45 @@ void PCB_EDIT_FRAME::AutoPlaceModule( MODULE* Module, int place_mode, wxDC* DC )
}
// Determine if the best orientation of a module is 90.
ii = Module->GetPlacementCost90() & 0x0F;
rotAllowed = Module->GetPlacementCost90();
if( ii != 0 )
if( rotAllowed != 0 )
{
int Angle_Rot_Module = 900;
Rotate_Module( DC, Module, Angle_Rot_Module, false );
Rotate_Module( DC, Module, 900.0, true );
error = getOptimalModulePlacement( this, Module, DC );
MinCout *= OrientPenality[ii];
MinCout *= OrientPenality[rotAllowed];
if( BestScore > MinCout ) // This orientation is best.
if( bestScore > MinCout ) // This orientation is better.
{
PosOK = CurrPosition;
BestScore = MinCout;
bestScore = MinCout;
bestRotation = 900.0;
}
else
{
Angle_Rot_Module = -900;
Rotate_Module( DC, Module, Angle_Rot_Module, false );
Rotate_Module( DC, Module, initialOrient, false );
}
if( error == ESC )
goto end_of_tst;
}
// Determine if the best orientation of a module is 270.
ii = (Module->GetPlacementCost90() >> 4 ) & 0x0F;
if( ii != 0 )
// Determine if the best orientation of a module is -90.
if( rotAllowed != 0 )
{
int Angle_Rot_Module = 2700;
Rotate_Module( DC, Module, Angle_Rot_Module, false );
Rotate_Module( DC, Module, 2700.0, true );
error = getOptimalModulePlacement( this, Module, DC );
MinCout *= OrientPenality[ii];
MinCout *= OrientPenality[rotAllowed];
if( BestScore > MinCout ) // This orientation is best.
if( bestScore > MinCout ) // This orientation is better.
{
PosOK = CurrPosition;
BestScore = MinCout;
bestScore = MinCout;
bestRotation = 2700.0;
}
else
{
Angle_Rot_Module = -2700;
Rotate_Module( DC, Module, Angle_Rot_Module, false );
Rotate_Module( DC, Module, initialOrient, false );
}
if( error == ESC )
@ -375,7 +373,14 @@ end_of_tst:
// Place module.
CurrPosition = GetCrossHairPosition();
SetCrossHairPosition( PosOK );
PlaceModule( Module, DC );
bestRotation += initialOrient;
if( bestRotation != Module->GetOrientation() )
Rotate_Module( DC, Module, bestRotation, false );
SetCrossHairPosition( CurrPosition );
Module->CalculateBoundingBox();
@ -405,7 +410,7 @@ end_of_tst:
}
void drawInfoPlace( BOARD* aBrd, wxDC* DC )
void drawPlacementRoutingMatrix( BOARD* aBrd, wxDC* DC )
{
int ii, jj;
EDA_COLOR_T color;
@ -608,6 +613,13 @@ void genModuleOnRoutingMatrix( MODULE* Module )
CreateKeepOutRectangle( ox, oy, fx, fy, margin, KEEP_OUT_MARGIN, layerMask );
}
// A minor helper function to draw a bounding box:
inline void draw_FootprintRect(EDA_RECT * aClipBox, wxDC* aDC, EDA_RECT& fpBBox, EDA_COLOR_T aColor)
{
#ifndef USE_WX_OVERLAY
GRRect( aClipBox, aDC, fpBBox, 0, aColor );
#endif
}
int getOptimalModulePlacement( PCB_EDIT_FRAME* aFrame, MODULE* aModule, wxDC* aDC )
{
@ -618,6 +630,8 @@ int getOptimalModulePlacement( PCB_EDIT_FRAME* aFrame, MODULE* aModule, wxDC* aD
bool showRats = g_Show_Module_Ratsnest;
BOARD* brd = aFrame->GetBoard();
aModule->CalculateBoundingBox();
g_Show_Module_Ratsnest = false;
brd->m_Status_Pcb &= ~RATSNEST_ITEM_LOCAL_OK;
@ -674,8 +688,9 @@ int getOptimalModulePlacement( PCB_EDIT_FRAME* aFrame, MODULE* aModule, wxDC* aD
}
// Draw the initial bounding box position
EDA_COLOR_T color = BROWN;
fpBBox.SetOrigin( fpBBoxOrg + CurrPosition );
GRRect( aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, 0, BROWN );
draw_FootprintRect(aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, color);
min_cost = -1.0;
aFrame->SetStatusText( wxT( "Score ??, pos ??" ) );
@ -696,19 +711,17 @@ int getOptimalModulePlacement( PCB_EDIT_FRAME* aFrame, MODULE* aModule, wxDC* aD
for( ; CurrPosition.y < xylimit.y; CurrPosition.y += RoutingMatrix.m_GridRouting )
{
#ifndef USE_WX_OVERLAY
// Erase traces.
GRRect( aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, 0, BROWN );
#endif
draw_FootprintRect( aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, color );
fpBBox.SetOrigin( fpBBoxOrg + CurrPosition );
g_Offset_Module = mod_pos - CurrPosition;
#ifndef USE_WX_OVERLAY
// Draw at new place
GRRect( aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, 0, BROWN );
#endif
int keepOutCost = TstModuleOnBoard( brd, aModule, TstOtherSide );
// Draw at new place
color = keepOutCost >= 0 ? BROWN : RED;
draw_FootprintRect( aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, color );
if( keepOutCost >= 0 ) // i.e. if the module can be put here
{
error = 0;
@ -750,7 +763,7 @@ int getOptimalModulePlacement( PCB_EDIT_FRAME* aFrame, MODULE* aModule, wxDC* aD
* - is a free zone (except OCCUPED_By_MODULE returns)
* - is on the working surface of the board (otherwise returns OUT_OF_BOARD)
*
* Returns OUT_OF_BOARD, or, OCCUPED_By_MODULE or 0 if OK
* Returns OUT_OF_BOARD, or OCCUPED_By_MODULE or FREE_CELL if OK
*/
int TstRectangle( BOARD* Pcb, const EDA_RECT& aRect, int side )
{
@ -801,7 +814,7 @@ int TstRectangle( BOARD* Pcb, const EDA_RECT& aRect, int side )
}
}
return 0;
return FREE_CELL;
}
@ -877,14 +890,14 @@ int TstModuleOnBoard( BOARD* Pcb, MODULE* aModule, bool TstOtherSide )
int diag = TstRectangle( Pcb, fpBBox, side );
if( diag < 0 )
if( diag != FREE_CELL )
return diag;
if( TstOtherSide )
{
diag = TstRectangle( Pcb, fpBBox, otherside );
if( diag < 0 )
if( diag != FREE_CELL )
return diag;
}