Commit 18616d77 authored by jean-pierre charras's avatar jean-pierre charras

Fix bugs in autoplac.cpp

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