Change board bounding box calculation to include all board items by default in pcbnew. Add a parameter to look for board edges only.

This commit is contained in:
Marco Mattila 2011-02-25 18:23:24 +02:00
parent e07643f070
commit 97003fefae
24 changed files with 216 additions and 168 deletions

View File

@ -121,7 +121,7 @@ GLuint Pcb3D_GLCanvas::CreateDrawGL_List()
m_gllist = glGenLists( 1 );
pcb->ComputeBoundaryBox();
pcb->ComputeBoundingBox();
g_Parm_3D_Visu.m_BoardSettings = pcb->GetBoardDesignSettings();
g_Parm_3D_Visu.m_BoardSize = pcb->m_BoundaryBox.GetSize();
g_Parm_3D_Visu.m_BoardPos = pcb->m_BoundaryBox.Centre();

View File

@ -107,7 +107,7 @@ static bool WriteGeneralDescrPcb( BOARD* Pcb, FILE* File )
fprintf( File, "LayerCount %d\n", NbLayers );
/* Compute and print the board bounding box */
Pcb->ComputeBoundaryBox();
Pcb->ComputeBoundingBox();
fprintf( File, "Di %d %d %d %d\n",
Pcb->m_BoundaryBox.GetX(), Pcb->m_BoundaryBox.GetY(),
Pcb->m_BoundaryBox.GetRight(),

View File

@ -1108,7 +1108,6 @@ public:
bool include_fixe );
void FixeModule( MODULE* Module, bool Fixe );
void AutoMoveModulesOnPcb( bool PlaceModulesHorsPcb );
bool SetBoardBoundaryBoxFromEdgesOnly();
void AutoPlaceModule( MODULE* Module, int place_mode, wxDC* DC );
int RecherchePlacementModule( MODULE* Module, wxDC* DC );
void GenModuleOnBoard( MODULE* Module );

View File

@ -186,7 +186,7 @@ void WinEDA_PcbFrame::AutoMoveModulesOnPcb( bool PlaceModulesHorsPcb )
if( !IsOK( this, _( "Move modules?" ) ) )
return;
edgesExists = SetBoardBoundaryBoxFromEdgesOnly();
edgesExists = GetBoard()->ComputeBoundingBox( true );
if( PlaceModulesHorsPcb && !edgesExists )
{

View File

@ -382,7 +382,7 @@ int WinEDA_PcbFrame::GenPlaceBoard()
Board.UnInitBoard();
if( !SetBoardBoundaryBoxFromEdgesOnly() )
if( !GetBoard()->ComputeBoundingBox( true ) )
{
DisplayError( this, _( "No PCB edge found, unknown board size!" ) );
return 0;
@ -1086,73 +1086,6 @@ static MODULE* PickModule( WinEDA_PcbFrame* pcbframe, wxDC* DC )
}
/*
* Determine the rectangle of the pcb, according to the contours
* layer (EDGE) only
* Output:
* GetBoard()->m_BoundaryBox updated
* Returns FALSE if no contour
*/
bool WinEDA_PcbFrame::SetBoardBoundaryBoxFromEdgesOnly()
{
int rayon, cx, cy, d;
int xmax, ymax;
BOARD_ITEM* PtStruct;
DRAWSEGMENT* ptr;
bool succes = FALSE;
if( GetBoard() == NULL )
return FALSE;
GetBoard()->m_BoundaryBox.m_Pos.x = GetBoard()->m_BoundaryBox.m_Pos.y =
0x7FFFFFFFl;
xmax = ymax = -0x7FFFFFFFl;
PtStruct = GetBoard()->m_Drawings;
for( ; PtStruct != NULL; PtStruct = PtStruct->Next() )
{
if( PtStruct->Type() != TYPE_DRAWSEGMENT )
continue;
succes = TRUE;
ptr = (DRAWSEGMENT*) PtStruct;
d = (ptr->m_Width / 2) + 1;
if( ptr->m_Shape == S_CIRCLE )
{
cx = ptr->m_Start.x; cy = ptr->m_Start.y;
rayon =
(int) hypot( (double) ( ptr->m_End.x - cx ),
(double) ( ptr->m_End.y - cy ) );
rayon += d;
GetBoard()->m_BoundaryBox.m_Pos.x = MIN(
GetBoard()->m_BoundaryBox.m_Pos.x, cx - rayon );
GetBoard()->m_BoundaryBox.m_Pos.y = MIN(
GetBoard()->m_BoundaryBox.m_Pos.y, cy - rayon );
xmax = MAX( xmax, cx + rayon );
ymax = MAX( ymax, cy + rayon );
}
else
{
cx = MIN( ptr->m_Start.x, ptr->m_End.x );
cy = MIN( ptr->m_Start.y, ptr->m_End.y );
GetBoard()->m_BoundaryBox.m_Pos.x = MIN(
GetBoard()->m_BoundaryBox.m_Pos.x, cx - d );
GetBoard()->m_BoundaryBox.m_Pos.y = MIN(
GetBoard()->m_BoundaryBox.m_Pos.y, cy - d );
cx = MAX( ptr->m_Start.x, ptr->m_End.x );
cy = MAX( ptr->m_Start.y, ptr->m_End.y );
xmax = MAX( xmax, cx + d );
ymax = MAX( ymax, cy + d );
}
}
GetBoard()->m_BoundaryBox.SetWidth(
xmax - GetBoard()->m_BoundaryBox.m_Pos.x );
GetBoard()->m_BoundaryBox.SetHeight(
ymax - GetBoard()->m_BoundaryBox.m_Pos.y );
return succes;
}
/********************************************/
int Propagation( WinEDA_PcbFrame* frame )
/********************************************/

View File

@ -110,7 +110,7 @@ int WinEDA_BasePcbFrame::BestZoom( void )
if( m_Pcb == NULL )
return 32 * GetScreen()->m_ZoomScalar;
m_Pcb->ComputeBoundaryBox();
m_Pcb->ComputeBoundingBox();
dx = m_Pcb->m_BoundaryBox.GetWidth();
dy = m_Pcb->m_BoundaryBox.GetHeight();

View File

@ -36,7 +36,7 @@ bool ComputeMatriceSize( WinEDA_BasePcbFrame* frame, int g_GridRoutingSize )
{
BOARD* pcb = frame->GetBoard();
pcb->ComputeBoundaryBox();
pcb->ComputeBoundingBox();
/* The boundary box must have its start point on routing grid: */
pcb->m_BoundaryBox.m_Pos.x -= pcb->m_BoundaryBox.m_Pos.x % g_GridRoutingSize;

View File

@ -1,6 +1,7 @@
/*******************************************/
/* class_board.cpp - BOARD class functions */
/*******************************************/
#include <limits.h>
#include "fctsys.h"
#include "common.h"
@ -741,34 +742,28 @@ unsigned BOARD::GetNodesCount()
}
/**
* Function ComputeBoundaryBox
* Calculate the bounding box of the board
* This box contains pcb edges, pads , vias and tracks
* Update m_PcbBox member
*
* @return 0 for an empty board (no items), else 1
*/
bool BOARD::ComputeBoundaryBox()
bool BOARD::ComputeBoundingBox( bool aBoardEdgesOnly )
{
int rayon, cx, cy, d, xmin, ymin, xmax, ymax;
bool hasItems = FALSE;
EDA_ITEM* PtStruct;
DRAWSEGMENT* ptr;
bool hasItems = false;
xmin = ymin = 0x7FFFFFFFl;
xmax = ymax = -0x7FFFFFFFl;
xmin = ymin = INT_MAX;
xmax = ymax = INT_MIN;
/* Analyze PCB edges*/
PtStruct = m_Drawings;
for( ; PtStruct != NULL; PtStruct = PtStruct->Next() )
// Check segments, dimensions, texts, and fiducials
for( EDA_ITEM* PtStruct = m_Drawings; PtStruct != NULL; PtStruct = PtStruct->Next() )
{
if( PtStruct->Type() != TYPE_DRAWSEGMENT )
continue;
switch( PtStruct->Type() )
{
case TYPE_DRAWSEGMENT:
{
DRAWSEGMENT* ptr;
ptr = (DRAWSEGMENT*) PtStruct;
d = (ptr->m_Width / 2) + 1;
if( aBoardEdgesOnly && ptr->GetLayer() != EDGE_N )
break;
if( ptr->m_Shape == S_CIRCLE )
{
cx = ptr->m_Start.x; cy = ptr->m_Start.y;
@ -779,7 +774,7 @@ bool BOARD::ComputeBoundaryBox()
ymin = MIN( ymin, cy - rayon );
xmax = MAX( xmax, cx + rayon );
ymax = MAX( ymax, cy + rayon );
hasItems = TRUE;
hasItems = true;
}
else
{
@ -791,23 +786,68 @@ bool BOARD::ComputeBoundaryBox()
cy = MAX( ptr->m_Start.y, ptr->m_End.y );
xmax = MAX( xmax, cx + d );
ymax = MAX( ymax, cy + d );
hasItems = TRUE;
hasItems = true;
}
break;
}
case TYPE_DIMENSION:
{
if( aBoardEdgesOnly )
break;
EDA_Rect rect = ((DIMENSION*) PtStruct)->GetBoundingBox();
xmin = MIN( xmin, rect.GetX() );
ymin = MIN( ymin, rect.GetY() );
xmax = MAX( xmax, rect.GetRight() );
ymax = MAX( ymax, rect.GetBottom() );
hasItems = true;
break;
}
case TYPE_TEXTE:
{
if( aBoardEdgesOnly )
break;
EDA_Rect rect = ((TEXTE_PCB*) PtStruct)->GetTextBox( -1 );
xmin = MIN( xmin, rect.GetX() );
ymin = MIN( ymin, rect.GetY() );
xmax = MAX( xmax, rect.GetRight() );
ymax = MAX( ymax, rect.GetBottom() );
hasItems = true;
break;
}
case TYPE_MIRE:
{
if( aBoardEdgesOnly )
break;
EDA_Rect rect = ((DIMENSION*) PtStruct)->GetBoundingBox();
xmin = MIN( xmin, rect.GetX() );
ymin = MIN( ymin, rect.GetY() );
xmax = MAX( xmax, rect.GetRight() );
ymax = MAX( ymax, rect.GetBottom() );
hasItems = true;
break;
}
default:
break;
}
}
/* Analyze footprints */
if( !aBoardEdgesOnly )
{
// Check modules
for( MODULE* module = m_Modules; module; module = module->Next() )
{
hasItems = TRUE;
EDA_Rect box = module->GetBoundingBox();
xmin = MIN( xmin, box.GetX() );
ymin = MIN( ymin, box.GetY() );
xmax = MAX( xmax, box.GetRight() );
ymax = MAX( ymax, box.GetBottom() );
EDA_Rect bBox = module->GetBoundingBox();
xmin = MIN( xmin, bBox.GetX() );
ymin = MIN( ymin, bBox.GetY() );
xmax = MAX( xmax, bBox.GetRight() );
ymax = MAX( ymax, bBox.GetBottom() );
hasItems = true;
}
/* Analize track and zones */
// Check tracks
for( TRACK* track = m_Track; track; track = track->Next() )
{
d = ( track->m_Width / 2 ) + 1;
@ -819,9 +859,10 @@ bool BOARD::ComputeBoundaryBox()
cy = MAX( track->m_Start.y, track->m_End.y );
xmax = MAX( xmax, cx + d );
ymax = MAX( ymax, cy + d );
hasItems = TRUE;
hasItems = true;
}
// Check segment zones
for( TRACK* track = m_Zone; track; track = track->Next() )
{
d = ( track->m_Width / 2 ) + 1;
@ -833,7 +874,20 @@ bool BOARD::ComputeBoundaryBox()
cy = MAX( track->m_Start.y, track->m_End.y );
xmax = MAX( xmax, cx + d );
ymax = MAX( ymax, cy + d );
hasItems = TRUE;
hasItems = true;
}
// Check polygonal zones
for( unsigned int i = 0; i < m_ZoneDescriptorList.size(); i++ )
{
ZONE_CONTAINER* aZone = m_ZoneDescriptorList[i];
EDA_Rect bBox = aZone->GetBoundingBox();
xmin = MIN( xmin, bBox.GetX() );
ymin = MIN( ymin, bBox.GetY() );
xmax = MAX( xmax, bBox.GetRight() );
ymax = MAX( ymax, bBox.GetBottom() );
hasItems = true;
}
}
if( !hasItems && m_PcbFrame )

View File

@ -499,9 +499,13 @@ public:
return m_NetInfo->GetPadsCount();
}
bool ComputeBoundaryBox();
/**
* Function ComputeBoundingBox
* calculates the bounding box containing all board items (or board edge segments).
* @param aBoardEdgesOnly is true if we are interested in board edge segments only.
* @return bool - True if items (or board edge segments) were found.
*/
bool ComputeBoundingBox( bool aBoardEdgesOnly = false );
/**
* Function DisplayInfo

View File

@ -737,3 +737,43 @@ bool DIMENSION::HitTest( EDA_Rect& refArea )
return true;
return false;
}
EDA_Rect DIMENSION::GetBoundingBox() const
{
EDA_Rect bBox;
int xmin, xmax, ymin, ymax;
bBox = m_Text->GetTextBox( -1 );
xmin = bBox.GetX();
xmax = bBox.GetRight();
ymin = bBox.GetY();
ymax = bBox.GetBottom();
xmin = MIN( xmin, Barre_ox );
xmin = MIN( xmin, Barre_fx );
ymin = MIN( ymin, Barre_oy );
ymin = MIN( ymin, Barre_fy );
xmax = MAX( xmax, Barre_ox );
xmax = MAX( xmax, Barre_fx );
ymax = MAX( ymax, Barre_oy );
ymax = MAX( ymax, Barre_fy );
xmin = MIN( xmin, TraitG_ox );
xmin = MIN( xmin, TraitG_fx );
ymin = MIN( ymin, TraitG_oy );
ymin = MIN( ymin, TraitG_fy );
xmax = MAX( xmax, TraitG_ox );
xmax = MAX( xmax, TraitG_fx );
ymax = MAX( ymax, TraitG_oy );
ymax = MAX( ymax, TraitG_fy );
bBox.SetX( xmin );
bBox.SetY( ymin );
bBox.SetWidth( xmax - xmin + 1 );
bBox.SetHeight( ymax - ymin + 1 );
bBox.Normalize();
return bBox;
}

View File

@ -132,6 +132,8 @@ public:
{
return wxT( "DIMENSION" );
}
EDA_Rect GetBoundingBox() const;
};
#endif // #define DIMENSION_H

View File

@ -222,3 +222,15 @@ void MIREPCB::Flip(const wxPoint& aCentre )
m_Pos.y = aCentre.y - ( m_Pos.y - aCentre.y );
SetLayer( ChangeSideNumLayer( GetLayer() ) );
}
EDA_Rect MIREPCB::GetBoundingBox() const
{
EDA_Rect bBox;
bBox.SetX( m_Pos.x - m_Size/2 );
bBox.SetY( m_Pos.y - m_Size/2 );
bBox.SetWidth( m_Size );
bBox.SetHeight( m_Size );
return bBox;
}

View File

@ -87,6 +87,7 @@ public:
*/
bool HitTest( EDA_Rect& refArea );
EDA_Rect GetBoundingBox() const;
};

View File

@ -89,7 +89,7 @@ void WinEDA_PcbFrame::ExportToGenCAD( wxCommandEvent& event )
}
/* Update some board data, to ensure a reliable gencad export: */
GetBoard()->ComputeBoundaryBox();
GetBoard()->ComputeBoundingBox();
offsetX = m_Auxiliary_Axis_Position.x;
offsetY = m_Auxiliary_Axis_Position.y;

View File

@ -1214,7 +1214,7 @@ bool WinEDA_PcbFrame::ExportVRML_File( const wxString & aFullFileName,
/* Define the translation to have the board centre to the 2D axis origin
* more easy for rotations...
*/
pcb->ComputeBoundaryBox();
pcb->ComputeBoundingBox();
double dx = board_scaling_factor * pcb->m_BoundaryBox.Centre().x * aScale;
double dy = board_scaling_factor * pcb->m_BoundaryBox.Centre().y * aScale;
fprintf(output_file, " translation %g %g 0.0\n", -dx, dy );

View File

@ -40,8 +40,9 @@ void GenDrillMapFile( BOARD* aPcb, FILE* aFile, const wxString& aFullFileName,
PLOTTER* plotter = NULL;
SetLocaleTo_C_standard(); // Use the standard notation for float numbers
/* Calculate dimensions and center of PCB */
aPcb->ComputeBoundaryBox();
// Calculate dimensions and center of PCB
aPcb->ComputeBoundingBox();
dX = aPcb->m_BoundaryBox.GetWidth();
dY = aPcb->m_BoundaryBox.GetHeight();

View File

@ -347,7 +347,7 @@ void WinEDA_PcbFrame::GenModuleReport( wxCommandEvent& event )
fputs( "##\n", rptfile );
fputs( "\n$BeginDESCRIPTION\n", rptfile );
GetBoard()->ComputeBoundaryBox();
GetBoard()->ComputeBoundingBox();
fputs( "\n$BOARD\n", rptfile );
fputs( "unit INCH\n", rptfile );
sprintf( line, "upper_left_corner %9.6f %9.6f\n",

View File

@ -789,7 +789,7 @@ bool WinEDA_PcbFrame::WriteGeneralDescrPcb( FILE* File )
fprintf( File, "NoConn %d\n", GetBoard()->m_NbNoconnect );
/* Write Bounding box info */
GetBoard()->ComputeBoundaryBox();
GetBoard()->ComputeBoundingBox();
fprintf( File, "Di %d %d %d %d\n",
GetBoard()->m_BoundaryBox.GetX(),
GetBoard()->m_BoundaryBox.GetY(),

View File

@ -1002,7 +1002,7 @@ void LoadListeModules( WinEDA_PcbFrame* aPcbFrame )
ref = cmp = s_ModuleToLoad_List;
// Calculate the footprint "best" position:
if( aPcbFrame->SetBoardBoundaryBoxFromEdgesOnly() )
if( aPcbFrame->GetBoard()->ComputeBoundingBox( true ) )
{
ModuleBestPosition.x =
aPcbFrame->GetBoard()->m_BoundaryBox.GetRight() + 5000;

View File

@ -55,7 +55,7 @@ bool WinEDA_BasePcbFrame::Genere_HPGL( const wxString& FullFileName, int Layer,
SheetSize.y = currentsheet->m_Size.y * U_PCB;
/* Calculate the center of the PCB. */
m_Pcb->ComputeBoundaryBox();
m_Pcb->ComputeBoundingBox();
BoardSize = m_Pcb->m_BoundaryBox.GetSize();
BoardCenter = m_Pcb->m_BoundaryBox.Centre();

View File

@ -62,7 +62,7 @@ bool WinEDA_BasePcbFrame::Genere_PS( const wxString& FullFileName, int Layer,
paperscale = 1;
}
m_Pcb->ComputeBoundaryBox();
m_Pcb->ComputeBoundingBox();
BoardSize = m_Pcb->m_BoundaryBox.GetSize();
BoardCenter = m_Pcb->m_BoundaryBox.Centre();

View File

@ -138,8 +138,9 @@ void BOARD_PRINTOUT_CONTROLER::DrawPage()
SheetSize.y *= m_Parent->m_InternalUnits / 1000; // size in internal units
WinEDA_BasePcbFrame* pcbframe = (WinEDA_BasePcbFrame*) m_Parent;
pcbframe->GetBoard()->ComputeBoundaryBox();
pcbframe->GetBoard()->ComputeBoundingBox();
EDA_Rect brd_BBox = pcbframe->GetBoard()->m_BoundaryBox;
// In module editor, the module is located at 0,0 but for printing
// it is moved to SheetSize.x/2, SheetSize.y/2.
// So the equivalent board must be moved:

View File

@ -882,7 +882,7 @@ void SPECCTRA_DB::fillBOUNDARY( BOARD* aBoard, BOUNDARY* boundary ) throw( IO_ER
}
else
{
aBoard->ComputeBoundaryBox();
aBoard->ComputeBoundingBox();
RECTANGLE* rect = new RECTANGLE( boundary );
boundary->rectangle = rect;

View File

@ -102,7 +102,8 @@ int WinEDA_PcbFrame::Fill_Zone( ZONE_CONTAINER* zone_container, bool verbose )
wxString msg;
MsgPanel->EraseMsgBox();
if( GetBoard()->ComputeBoundaryBox() == false )
if( GetBoard()->ComputeBoundingBox() == false )
{
if( verbose )
wxMessageBox( wxT( "Board is empty!" ) );