Loading pcbnew/autorouter/autoplac.cpp +69 −56 Original line number Diff line number Diff line /** * @file autoplac.cpp * @brief Routiness to automatically place MODULES on a board. * @brief Functions to automatically place Footprints on a board. */ /* Loading Loading @@ -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] = { Loading @@ -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 Loading Loading @@ -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, Loading Loading @@ -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 ) Loading Loading @@ -255,7 +258,6 @@ void PCB_EDIT_FRAME::AutoPlaceModule( MODULE* Module, int place_mode, wxDC* DC ) break; } if( Module->NeedsPlaced() ) // Erase from screen { moduleCount++; Loading @@ -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 ) Loading @@ -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 ) Loading @@ -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 ) Loading @@ -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(); Loading Loading @@ -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; Loading Loading @@ -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 ) { Loading @@ -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; Loading Loading @@ -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 ??" ) ); Loading @@ -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; Loading Loading @@ -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 ) { Loading Loading @@ -801,7 +814,7 @@ int TstRectangle( BOARD* Pcb, const EDA_RECT& aRect, int side ) } } return 0; return FREE_CELL; } Loading Loading @@ -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; } Loading Loading
pcbnew/autorouter/autoplac.cpp +69 −56 Original line number Diff line number Diff line /** * @file autoplac.cpp * @brief Routiness to automatically place MODULES on a board. * @brief Functions to automatically place Footprints on a board. */ /* Loading Loading @@ -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] = { Loading @@ -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 Loading Loading @@ -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, Loading Loading @@ -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 ) Loading Loading @@ -255,7 +258,6 @@ void PCB_EDIT_FRAME::AutoPlaceModule( MODULE* Module, int place_mode, wxDC* DC ) break; } if( Module->NeedsPlaced() ) // Erase from screen { moduleCount++; Loading @@ -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 ) Loading @@ -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 ) Loading @@ -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 ) Loading @@ -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(); Loading Loading @@ -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; Loading Loading @@ -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 ) { Loading @@ -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; Loading Loading @@ -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 ??" ) ); Loading @@ -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; Loading Loading @@ -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 ) { Loading Loading @@ -801,7 +814,7 @@ int TstRectangle( BOARD* Pcb, const EDA_RECT& aRect, int side ) } } return 0; return FREE_CELL; } Loading Loading @@ -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; } Loading