drc: more code cleaning. Added comments and fixed some erroneous comments. Fixed bug 638839.

fixed bug 641982 (I hope)
This commit is contained in:
jean-pierre charras 2010-09-18 19:55:08 +02:00
parent 577a79bc59
commit ed54bdfc9d
12 changed files with 333 additions and 264 deletions

View File

@ -10,7 +10,7 @@ else(ZLIB_FOUND)
# and we try to use it
# Unfortunately, we have no way to know exactlty the path of zlib.h becuase this file
# is in wxWidgets sources, not in wxWidgets include path.
find_path(ZLIB_INCLUDE_DIR PATHS ${wxWidgets_ROOT_DIR}/../src/zlib/ ${wxWidgets_ROOT_DIR}/src/zlib/ DOC "location of zlib include files")
find_path(ZLIB_INCLUDE_DIR zlib.h PATHS ${wxWidgets_ROOT_DIR}/../src/zlib/ ${wxWidgets_ROOT_DIR}/src/zlib/ DOC "location of zlib include files")
find_file(ZLIB_LIBRARIES NAMES ${wxWidgets_LIB_DIR}/libwxzlib-2.8.a ZLIB_LIBRARIES NAMES ${wxWidgets_LIB_DIR}/libwxzlib-2.9.a libwxzlib.a PATHS ${wxWidgets_ROOT_DIR}/lib/ PATH_SUFFIXES gcc_dll DOC "location of wxzlib library file")
endif(ZLIB_FOUND)

View File

@ -96,6 +96,7 @@ set(PCBNEW_SRCS
dist.cpp
dragsegm.cpp
drc.cpp
drc_marker_functions.cpp
edgemod.cpp
edit.cpp
editedge.cpp

View File

@ -697,7 +697,7 @@ void MODULE::Set_Rectangle_Encadrement()
*/
for( D_PAD* pad = m_Pads; pad; pad = pad->Next() )
{
rayon = pad->m_Rayon;
rayon = pad->m_ShapeMaxRadius;
cx = pad->m_Pos0.x;
cy = pad->m_Pos0.y;
xmin = MIN( xmin, cx - rayon );

View File

@ -44,7 +44,7 @@ D_PAD::D_PAD( MODULE* parent ) : BOARD_CONNECTED_ITEM( parent, TYPE_PAD )
SetSubRatsnest( 0 ); // used in ratsnest
// calculations
ComputeRayon();
ComputeShapeMaxRadius();
}
@ -53,25 +53,33 @@ D_PAD::~D_PAD()
}
/* Calculate the radius of the pad.
/* Calculate the radius of the circle containing the pad.
*/
void D_PAD::ComputeRayon()
void D_PAD::ComputeShapeMaxRadius()
{
switch( m_PadShape & 0x7F )
{
case PAD_CIRCLE:
m_Rayon = m_Size.x / 2;
m_ShapeMaxRadius = m_Size.x / 2;
break;
case PAD_OVAL:
m_Rayon = MAX( m_Size.x, m_Size.y ) / 2;
m_ShapeMaxRadius = MAX( m_Size.x, m_Size.y ) / 2;
break;
case PAD_RECT:
case PAD_TRAPEZOID:
m_Rayon = (int) ( sqrt( (double) m_Size.y * m_Size.y
m_ShapeMaxRadius = 1 + (int) ( sqrt( (double) m_Size.y * m_Size.y
+ (double) m_Size.x * m_Size.x ) / 2 );
break;
case PAD_TRAPEZOID:
{ wxSize fullsize = m_Size;
fullsize.x += ABS(m_DeltaSize.y); // Remember: m_DeltaSize.y is the m_Size.x change
fullsize.y += ABS(m_DeltaSize.x); // Remember: m_DeltaSize.x is the m_Size.y change
m_ShapeMaxRadius = 1 + (int) ( sqrt( (double) m_Size.y * m_Size.y
+ (double) m_Size.x * m_Size.x ) / 2 );
}
break;
}
}
@ -84,11 +92,11 @@ void D_PAD::ComputeRayon()
EDA_Rect D_PAD::GetBoundingBox()
{
// Calculate area:
ComputeRayon(); // calculate the radius of the area, considered as a
ComputeShapeMaxRadius(); // calculate the radius of the area, considered as a
// circle
EDA_Rect area;
area.SetOrigin( m_Pos );
area.Inflate( m_Rayon, m_Rayon );
area.Inflate( m_ShapeMaxRadius, m_ShapeMaxRadius );
return area;
}
@ -185,7 +193,7 @@ void D_PAD::Copy( D_PAD* source )
m_Size = source->m_Size;
m_DeltaSize = source->m_DeltaSize;
m_Pos0 = source->m_Pos0;
m_Rayon = source->m_Rayon;
m_ShapeMaxRadius = source->m_ShapeMaxRadius;
m_PadShape = source->m_PadShape;
m_Attribut = source->m_Attribut;
m_Orient = source->m_Orient;
@ -401,7 +409,7 @@ int D_PAD::ReadDescr( FILE* File, int* LineNum )
m_PadShape = PAD_TRAPEZOID; break;
}
ComputeRayon();
ComputeShapeMaxRadius();
break;
case 'D':
@ -766,7 +774,7 @@ bool D_PAD::HitTest( const wxPoint& ref_pos )
deltaY = ref_pos.y - shape_pos.y;
/* Quick test: a test point must be inside the circle. */
if( ( abs( deltaX ) > m_Rayon ) || ( abs( deltaY ) > m_Rayon ) )
if( ( abs( deltaX ) > m_ShapeMaxRadius ) || ( abs( deltaY ) > m_ShapeMaxRadius ) )
return false;
dx = m_Size.x >> 1; // dx also is the radius for rounded pads

View File

@ -95,7 +95,7 @@ public:
wxPoint m_Pos0; // Initial Pad position (i.e. pas position relative to the module anchor, orientation 0
int m_Rayon; // radius of pad circle
int m_ShapeMaxRadius; // radius of the circle containing the pad shape
int m_Attribut; // NORMAL, PAD_SMD, PAD_CONN
int m_Orient; // in 1/10 degrees
static int m_PadSketchModePenSize; // Pen size used to draw pads in sketch mode
@ -252,7 +252,7 @@ public:
void SetPadName( const wxString& name ); // Change pad name
wxString ReturnStringPadName(); // Return pad name as string in a wxString
void ReturnStringPadName( wxString& text ); // Return pad name as string in a buffer
void ComputeRayon(); // compute radius
void ComputeShapeMaxRadius(); // compute radius
const wxPoint ReturnShapePos();

View File

@ -647,7 +647,7 @@ void DIALOG_PAD_PROPERTIES::PadPropertiesAccept( wxCommandEvent& event )
m_CurrentPad->m_LocalSolderPasteMargin = g_Pad_Master.m_LocalSolderPasteMargin;
m_CurrentPad->m_LocalSolderPasteMarginRatio = g_Pad_Master.m_LocalSolderPasteMarginRatio;
m_CurrentPad->ComputeRayon();
m_CurrentPad->ComputeShapeMaxRadius();
Module->Set_Rectangle_Encadrement();
m_CurrentPad->DisplayInfo( m_Parent );

View File

@ -2,7 +2,7 @@
/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 2004-2007 Jean-Pierre Charras, jean-pierre.charras@inpg.fr
* Copyright (C) 2004-2007 Jean-Pierre Charras, jean-pierre.charras@gipsa-lab.inpg.fr
* Copyright (C) 2007 Dick Hollenbeck, dick@softplc.com
* Copyright (C) 2007 Kicad Developers, see change_log.txt for contributors.
*
@ -24,7 +24,6 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/****************************/
/* DRC control */
/****************************/
@ -94,7 +93,6 @@ void DRC::DestroyDialog( int aReason )
DRC::DRC( WinEDA_PcbFrame* aPcbWindow )
{
m_mainWindow = aPcbWindow;
m_drawPanel = aPcbWindow->DrawPanel;
m_pcb = aPcbWindow->GetBoard();
m_ui = 0;
@ -116,8 +114,6 @@ DRC::DRC( WinEDA_PcbFrame* aPcbWindow )
m_ycliplo = 0;
m_xcliphi = 0;
m_ycliphi = 0;
m_drawPanel = 0;
}
@ -288,13 +284,11 @@ void DRC::ListUnconnectedPads()
void DRC::updatePointers()
{
// update my pointers, m_mainWindow is the only unchangable one
m_drawPanel = m_mainWindow->DrawPanel;
m_pcb = m_mainWindow->GetBoard();
if( m_ui ) // Use diag list boxes only in DRC dialog
{
m_ui->m_ClearanceListBox->SetList( new DRC_LIST_MARKERS( m_pcb ) );
m_ui->m_UnconnectedListBox->SetList( new DRC_LIST_UNCONNECTED( &m_unconnected ) );
}
}
@ -450,8 +444,8 @@ void DRC::testPad2Pad()
{
D_PAD* pad = sortedPads[i];
if( pad->m_Rayon > max_size ) // m_Rayon is the radius value of the circle containing the pad
max_size = pad->m_Rayon;
if( pad->m_ShapeMaxRadius > max_size ) // m_ShapeMaxRadius is the radius value of the circle containing the pad
max_size = pad->m_ShapeMaxRadius;
}
// Test the pads
@ -462,7 +456,7 @@ void DRC::testPad2Pad()
D_PAD* pad = sortedPads[i];
int x_limit = max_size + pad->GetClearance() +
pad->m_Rayon + pad->GetPosition().x;
pad->m_ShapeMaxRadius + pad->GetPosition().x;
if( !doPadToPadsDrc( pad, &sortedPads[i], listEnd, x_limit ) )
{
@ -558,137 +552,6 @@ void DRC::testZones( bool adoTestFillSegments )
}
MARKER_PCB* DRC::fillMarker( TRACK* aTrack, BOARD_ITEM* aItem, int aErrorCode, MARKER_PCB* fillMe )
{
wxString textA = aTrack->MenuText( m_pcb );
wxString textB;
wxPoint position;
wxPoint posB;
if( aItem ) // aItem might be NULL
{
textB = aItem->MenuText( m_pcb );
posB = aItem->GetPosition();
if( aItem->Type() == TYPE_PAD )
position = aItem->GetPosition();
else if( aItem->Type() == TYPE_VIA )
position = aItem->GetPosition();
else if( aItem->Type() == TYPE_TRACK )
{
TRACK* track = (TRACK*) aItem;
wxPoint endPos = track->m_End;
// either of aItem's start or end will be used for the marker position
// first assume start, then switch at end if needed. decision made on
// distance from end of aTrack.
position = track->m_Start;
double dToEnd = hypot( endPos.x - aTrack->m_End.x,
endPos.y - aTrack->m_End.y );
double dToStart = hypot( position.x - aTrack->m_End.x,
position.y - aTrack->m_End.y );
if( dToEnd < dToStart )
position = endPos;
}
}
else
position = aTrack->GetPosition();
if( fillMe )
{
if( aItem )
fillMe->SetData( aErrorCode, position,
textA, aTrack->GetPosition(),
textB, posB );
else
fillMe->SetData( aErrorCode, position,
textA, aTrack->GetPosition() );
}
else
{
if( aItem )
fillMe = new MARKER_PCB( aErrorCode, position,
textA, aTrack->GetPosition(),
textB, posB );
else
fillMe = new MARKER_PCB( aErrorCode, position,
textA, aTrack->GetPosition() );
}
return fillMe;
}
MARKER_PCB* DRC::fillMarker( D_PAD* aPad, D_PAD* bPad, int aErrorCode, MARKER_PCB* fillMe )
{
wxString textA = aPad->MenuText( m_pcb );
wxString textB = bPad->MenuText( m_pcb );
wxPoint posA = aPad->GetPosition();
wxPoint posB = bPad->GetPosition();
if( fillMe )
fillMe->SetData( aErrorCode, posA, textA, posA, textB, posB );
else
fillMe = new MARKER_PCB( aErrorCode, posA, textA, posA, textB, posB );
return fillMe;
}
MARKER_PCB* DRC::fillMarker( ZONE_CONTAINER* aArea, int aErrorCode, MARKER_PCB* fillMe )
{
wxString textA = aArea->MenuText( m_pcb );
wxPoint posA = aArea->GetPosition();
if( fillMe )
fillMe->SetData( aErrorCode, posA, textA, posA );
else
fillMe = new MARKER_PCB( aErrorCode, posA, textA, posA );
return fillMe;
}
MARKER_PCB* DRC::fillMarker( const ZONE_CONTAINER* aArea,
const wxPoint& aPos,
int aErrorCode,
MARKER_PCB* fillMe )
{
wxString textA = aArea->MenuText( m_pcb );
wxPoint posA = aPos;
if( fillMe )
fillMe->SetData( aErrorCode, posA, textA, posA );
else
fillMe = new MARKER_PCB( aErrorCode, posA, textA, posA );
return fillMe;
}
MARKER_PCB* DRC::fillMarker( int aErrorCode, const wxString& aMessage, MARKER_PCB* fillMe )
{
wxPoint posA; // not displayed
if( fillMe )
fillMe->SetData( aErrorCode, posA, aMessage, posA );
else
fillMe = new MARKER_PCB( aErrorCode, posA, aMessage, posA );
fillMe->SetShowNoCoordinate();
return fillMe;
}
/***********************************************************************/
bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
/***********************************************************************/
@ -801,11 +664,12 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
/* Phase 1 : test DRC track to pads : */
/******************************************/
D_PAD pseudo_pad( (MODULE*) NULL ); // construct this once outside following loop
// Use a dummy pad to test DRC tracks versus holes, for pads not on all copper layers
// but having a hole
D_PAD dummypad( (MODULE*) NULL ); // construct this once outside following loop
dummypad.m_Masque_Layer = ALL_CU_LAYERS; // Ensure the hole is on all layers
// Compute the min distance to pads
int refsegm_half_width = aRefSeg->m_Width >> 1;
if( testPads )
{
for( unsigned ii = 0; ii<m_pcb->GetPadsCount(); ++ii )
@ -818,22 +682,21 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
*/
if( (pad->m_Masque_Layer & layerMask ) == 0 )
{
/* We must test the pad hole. In order to use the function "checkClearanceSegmToPad",
/* We must test the pad hole. In order to use the function checkClearanceSegmToPad(),
* a pseudo pad is used, with a shape and a size like the hole
*/
if( pad->m_Drill.x == 0 )
continue;
pseudo_pad.m_Size = pad->m_Drill;
pseudo_pad.SetPosition( pad->GetPosition() );
pseudo_pad.m_PadShape = pad->m_DrillShape;
pseudo_pad.m_Orient = pad->m_Orient;
pseudo_pad.ComputeRayon(); // compute the radius
dummypad.m_Size = pad->m_Drill;
dummypad.SetPosition( pad->GetPosition() );
dummypad.m_PadShape = pad->m_DrillShape;
dummypad.m_Orient = pad->m_Orient;
dummypad.ComputeShapeMaxRadius(); // compute the radius of the circle containing this pad
m_padToTestPos.x = dummypad.GetPosition().x - origin.x;
m_padToTestPos.y = dummypad.GetPosition().y - origin.y;
m_padToTestPos.x = pseudo_pad.GetPosition().x - origin.x;
m_padToTestPos.y = pseudo_pad.GetPosition().y - origin.y;
if( !checkClearanceSegmToPad( &pseudo_pad, refsegm_half_width,
if( !checkClearanceSegmToPad( &dummypad, aRefSeg->m_Width,
netclass->GetClearance() ) )
{
m_currentMarker = fillMarker( aRefSeg, pad,
@ -852,10 +715,10 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
// DRC for the pad
shape_pos = pad->ReturnShapePos();
m_padToTestPos.x = shape_pos.x - origin.x;
m_padToTestPos.y = shape_pos.y - origin.y;
m_padToTestPos.x = shape_pos.x - origin.x;
m_padToTestPos.y = shape_pos.y - origin.y;
if( !checkClearanceSegmToPad( pad, refsegm_half_width, aRefSeg->GetClearance( pad ) ) )
if( !checkClearanceSegmToPad( pad, aRefSeg->m_Width, aRefSeg->GetClearance( pad ) ) )
{
m_currentMarker = fillMarker( aRefSeg, pad,
DRCE_TRACK_NEAR_PAD, m_currentMarker );
@ -1118,11 +981,18 @@ bool DRC::doPadToPadsDrc( D_PAD* aRefPad, LISTE_PAD* aStart, LISTE_PAD* aEnd,
int x_limit )
/*****************************************************************************/
{
int layerMask = aRefPad->m_Masque_Layer & ALL_CU_LAYERS;
int layerMask = aRefPad->m_Masque_Layer & ALL_CU_LAYERS;
static D_PAD dummypad( (MODULE*) NULL ); // used to test DRC pad to holes: this dummypad is the hole to test
dummypad.m_Masque_Layer = ALL_CU_LAYERS;
// used to test DRC pad to holes: this dummypad is a pad hole to test
// pad to pad hole DRC, using pad to pad DRC test.
// this dummy pad is a circle or an oval.
static D_PAD dummypad( (MODULE*) NULL );
dummypad.m_Masque_Layer = ALL_CU_LAYERS; // za hole is on all layers
dummypad.m_LocalClearance = 1; /* Use the minimal local clerance 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)
*/
for( LISTE_PAD* pad_list = aStart; pad_list<aEnd; ++pad_list )
{
@ -1148,19 +1018,20 @@ bool DRC::doPadToPadsDrc( D_PAD* aRefPad, LISTE_PAD* aStart, LISTE_PAD* aEnd,
{
if( aRefPad->m_DrillShape == PAD_CIRCLE )
continue;
if( pad->m_Orient == aRefPad->m_Orient ) // for oval holes: must also have the same orientation
if( pad->m_Orient == aRefPad->m_Orient ) // for oval holes: must also have the same orientation
continue;
}
/* Here, we must test clearance between holes and pads
* dummypad 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_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
if( !checkClearancePadToPad( aRefPad, &dummypad ) )
{
// here we have a drc error on pad!
@ -1174,8 +1045,9 @@ bool DRC::doPadToPadsDrc( D_PAD* aRefPad, LISTE_PAD* aStart, LISTE_PAD* aEnd,
{
dummypad.SetPosition( aRefPad->GetPosition() );
dummypad.m_Size = aRefPad->m_Drill;
dummypad.m_PadShape = aRefPad->m_DrillShape == PAD_OVAL ? PAD_OVAL : PAD_CIRCLE;
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
if( !checkClearancePadToPad( pad, &dummypad ) )
{
// here we have a drc erroron aRefPad!
@ -1187,6 +1059,7 @@ bool DRC::doPadToPadsDrc( D_PAD* aRefPad, LISTE_PAD* aStart, LISTE_PAD* aEnd,
continue;
}
// The pad must be in a net (i.e pt_pad->GetNet() != 0 ),
// But no problem if pads have the same netcode (same net)
if( pad->GetNet() && ( aRefPad->GetNet() == pad->GetNet() ) )
@ -1229,28 +1102,29 @@ wxPoint rotate( wxPoint p, int angle )
}
/* test DRC between 2 pads.
* this function can be also used to test DRC between a pas and a hole,
* because a hole is like a round pad.
*/
bool DRC::checkClearancePadToPad( D_PAD* aRefPad, D_PAD* aPad )
{
wxPoint rel_pos;
int dist;;
int dist;
wxPoint shape_pos;
int pad_angle;
// Get the clerance between the 2 pads. this is the min distance between aRefPad and aPad
int dist_min = aRefPad->GetClearance( aPad );
rel_pos = aPad->ReturnShapePos();
shape_pos = aRefPad->ReturnShapePos();
// relativePadPos is the aPad shape position relative to the aRefPad shape position
wxPoint relativePadPos = aPad->ReturnShapePos() - aRefPad->ReturnShapePos();
// rel_pos is the aPad position relative to the aRefPad position
rel_pos -= shape_pos;
dist = (int) hypot( rel_pos.x, rel_pos.y );
dist = (int) hypot( relativePadPos.x, relativePadPos.y );
// return true if clearance between aRefPad and aPad is >= dist_min, else false
bool diag = true;
// Quick test: Clearance is OK if the bounding circles are further away than "dist_min"
if( (dist - aRefPad->m_Rayon - aPad->m_Rayon) >= dist_min )
if( (dist - aRefPad->m_ShapeMaxRadius - aPad->m_ShapeMaxRadius) >= dist_min )
goto exit;
/* Here, pads are near and DRC depend on the pad shapes
@ -1268,7 +1142,7 @@ bool DRC::checkClearancePadToPad( D_PAD* aRefPad, D_PAD* aPad )
if( swap_pads )
{
EXCHG( aRefPad, aPad );
rel_pos = -rel_pos;
relativePadPos = -relativePadPos;
}
/* Because pad exchange, aRefPad shape is PAD_CIRCLE or PAD_OVAL,
@ -1278,20 +1152,22 @@ bool DRC::checkClearancePadToPad( D_PAD* aRefPad, D_PAD* aPad )
*/
switch( aRefPad->m_PadShape )
{
case PAD_CIRCLE: // aRefPad is like a track segment with a null lenght
case PAD_CIRCLE:
/* One can use checkClearanceSegmToPad to test clearance
* aRefPad is like a track segment with a null lenght and a witdth = m_Size.x
*/
m_segmLength = 0;
m_segmAngle = 0;
m_segmEnd.x = m_segmEnd.y = 0;
m_padToTestPos.x = rel_pos.x;
m_padToTestPos.y = rel_pos.y;
diag = checkClearanceSegmToPad( aPad, aRefPad->m_Rayon, dist_min );
m_padToTestPos.x = relativePadPos.x;
m_padToTestPos.y = relativePadPos.y;
diag = checkClearanceSegmToPad( aPad, aRefPad->m_Size.x, dist_min );
break;
case PAD_RECT:
RotatePoint( &rel_pos, aRefPad->m_Orient );
RotatePoint( &relativePadPos, aRefPad->m_Orient );
// pad_angle = pad orient relative to the aRefPad orient
pad_angle = aRefPad->m_Orient + aPad->m_Orient;
@ -1315,13 +1191,13 @@ bool DRC::checkClearancePadToPad( D_PAD* aRefPad, D_PAD* aPad )
// Test DRC:
diag = false;
rel_pos.x = ABS( rel_pos.x );
rel_pos.y = ABS( rel_pos.y );
relativePadPos.x = ABS( relativePadPos.x );
relativePadPos.y = ABS( relativePadPos.y );
if( ( rel_pos.x - ( (size.x + aRefPad->m_Size.x) / 2 ) ) >= dist_min )
if( ( relativePadPos.x - ( (size.x + aRefPad->m_Size.x) / 2 ) ) >= dist_min )
diag = true;
if( ( rel_pos.y - ( (size.y + aRefPad->m_Size.y) / 2 ) ) >= dist_min )
if( ( relativePadPos.y - ( (size.y + aRefPad->m_Size.y) / 2 ) ) >= dist_min )
diag = true;
}
else // al least on pad has any other orient. Test is more tricky
@ -1405,10 +1281,10 @@ bool DRC::checkClearancePadToPad( D_PAD* aRefPad, D_PAD* aPad )
{
/* Create a track segment with same dimensions as the oval aRefPad
* and use checkClearanceSegmToPad function to test aPad to aRefPad clearance
*/
*/
int segm_width;
m_segmAngle = aRefPad->m_Orient; // Segment orient.
if( aRefPad->m_Size.y < aRefPad->m_Size.x ) // Build an horizontal equiv segment
m_segmAngle = aRefPad->m_Orient; // Segment orient.
if( aRefPad->m_Size.y < aRefPad->m_Size.x ) // Build an horizontal equiv segment
{
segm_width = aRefPad->m_Size.y;
m_segmLength = aRefPad->m_Size.x - aRefPad->m_Size.y;
@ -1420,19 +1296,20 @@ bool DRC::checkClearancePadToPad( D_PAD* aRefPad, D_PAD* aPad )
m_segmAngle += 900;
}
/* the start point must be 0,0 and currently rel_pos
/* the start point must be 0,0 and currently relativePadPos
* is relative the center of pad coordinate */
wxPoint segstart;
segstart.x = -m_segmLength / 2; // Start point coordinate of the horizontal equivalent segment
segstart.x = -m_segmLength / 2; // Start point coordinate of the horizontal equivalent segment
RotatePoint( &segstart, m_segmAngle ); // True start point coordinate of the equivalent segment
RotatePoint( &segstart, m_segmAngle ); // True start point coordinate of the equivalent segment
// move pad position relative to the segment origin
m_padToTestPos = rel_pos - segstart;
m_padToTestPos = relativePadPos - segstart;
// Calculate segment end
m_segmEnd.x = -2 * segstart.x;
m_segmEnd.y = -2 * segstart.y; // end of segment coordinate
diag = checkClearanceSegmToPad( aPad, segm_width / 2, dist_min );
diag = checkClearanceSegmToPad( aPad, segm_width, dist_min );
break;
}
@ -1448,28 +1325,39 @@ exit: // the only way out (hopefully) for simpler debugging
}
bool DRC::checkClearanceSegmToPad( const D_PAD* pad_to_test, int w_segm, int aMinDist )
/* test if distance between a segment is > aMinDist
* segment start point is assumed in (0,0) and segment start point in m_segmEnd
* and have aSegmentWidth.
*/
bool DRC::checkClearanceSegmToPad( const D_PAD* aPad, int aSegmentWidth, int aMinDist )
{
wxSize padHalfsize; // half the dimension of the pad
int orient;
int x0, y0, xf, yf;
int seuil;
int deltay;
int orient;
int x0, y0, xf, yf;
int seuil;
int deltay;
seuil = w_segm + aMinDist;
padHalfsize.x = pad_to_test->m_Size.x >> 1;
padHalfsize.y = pad_to_test->m_Size.y >> 1;
int segmHalfWidth = aSegmentWidth / 2;
seuil = segmHalfWidth + aMinDist;
padHalfsize.x = aPad->m_Size.x >> 1;
padHalfsize.y = aPad->m_Size.y >> 1;
if( pad_to_test->m_PadShape == PAD_CIRCLE )
if( aPad->m_PadShape == PAD_CIRCLE )
{
/* calcul des coord centre du pad dans le repere axe X confondu
* avec le segment en tst */
/* Easy case: just test the distance between segment and pad centre
* calculate pad coordinates in the X,Y axis with X axis = segment to test
*/
RotatePoint( &m_padToTestPos.x, &m_padToTestPos.y, m_segmAngle );
return checkMarginToCircle( m_padToTestPos.x, m_padToTestPos.y, seuil + padHalfsize.x, m_segmLength );
return checkMarginToCircle( m_padToTestPos.x, m_padToTestPos.y,
seuil + padHalfsize.x, m_segmLength );
}
else
{
/* calcul de la "surface de securite" du pad de reference */
/* calculate the bounding box of the pad, including the clearance and the segment width
* if the line from 0 to m_segmEnd does not intersect this bounding box,
* the clearance is always OK
* But if intersect, a better analysis of the pad shape must be done.
*/
m_xcliplo = m_padToTestPos.x - seuil - padHalfsize.x;
m_ycliplo = m_padToTestPos.y - seuil - padHalfsize.y;
m_xcliphi = m_padToTestPos.x + seuil + padHalfsize.x;
@ -1480,7 +1368,7 @@ bool DRC::checkClearanceSegmToPad( const D_PAD* pad_to_test, int w_segm, int aMi
xf = m_segmEnd.x;
yf = m_segmEnd.y;
orient = pad_to_test->m_Orient;
orient = aPad->m_Orient;
RotatePoint( &x0, &y0, m_padToTestPos.x, m_padToTestPos.y, -orient );
RotatePoint( &xf, &yf, m_padToTestPos.x, m_padToTestPos.y, -orient );
@ -1488,15 +1376,19 @@ bool DRC::checkClearanceSegmToPad( const D_PAD* pad_to_test, int w_segm, int aMi
if( checkLine( x0, y0, xf, yf ) )
return true;
/* Erreur DRC : analyse fine de la forme de la pastille */
switch( pad_to_test->m_PadShape )
/* segment intersects the bounding box. But there is not always a DRC error.
* A fine analysis of the pad shape must be done.
*/
switch( aPad->m_PadShape )
{
default:
return false;
case PAD_OVAL:
/* test de la pastille ovale ramenee au type ovale vertical */
/* an oval is a complex shape, but is a rectangle and 2 circles
* these 3 basic shapes are more easy to test.
*/
/* We use a vertical oval shape. for horizontal ovals, swap x and y size and rotate the shape*/
if( padHalfsize.x > padHalfsize.y )
{
EXCHG( padHalfsize.x, padHalfsize.y );
@ -1506,28 +1398,30 @@ bool DRC::checkClearanceSegmToPad( const D_PAD* pad_to_test, int w_segm, int aMi
}
deltay = padHalfsize.y - padHalfsize.x;
/* ici: padHalfsize.x = rayon,
* delta = dist centre cercles a centre pad */
// ici: padHalfsize.x = rayon, delta = dist centre cercles a centre pad
/* Test du rectangle separant les 2 demi cercles */
// Test the rectangle area between the two circles
m_xcliplo = m_padToTestPos.x - seuil - padHalfsize.x;
m_ycliplo = m_padToTestPos.y - w_segm - deltay;
m_ycliplo = m_padToTestPos.y - segmHalfWidth - deltay;
m_xcliphi = m_padToTestPos.x + seuil + padHalfsize.x;
m_ycliphi = m_padToTestPos.y + w_segm + deltay;
m_ycliphi = m_padToTestPos.y + segmHalfWidth + deltay;
if( !checkLine( x0, y0, xf, yf ) )
return false;
/* test des 2 cercles */
x0 = m_padToTestPos.x; /* x0,y0 = centre du cercle superieur du pad ovale */
// test the first circle
x0 = m_padToTestPos.x; // x0,y0 = centre of the upper circle of the oval shape
y0 = m_padToTestPos.y + deltay;
RotatePoint( &x0, &y0, m_padToTestPos.x, m_padToTestPos.y, orient );
RotatePoint( &x0, &y0, m_segmAngle );
// Calculate the actual position of the circle, given the pad orientation:
RotatePoint( &x0, &y0, m_padToTestPos.x, m_padToTestPos.y, orient );
// Calculate the actual position of the circle in the new X,Y axis:
RotatePoint( &x0, &y0, m_segmAngle );
if( !checkMarginToCircle( x0, y0, padHalfsize.x + seuil, m_segmLength ) )
return false;
x0 = m_padToTestPos.x; /* x0,y0 = centre du cercle inferieur du pad ovale */
// test the second circle
x0 = m_padToTestPos.x; // x0,y0 = centre of the lower circle of the oval shape
y0 = m_padToTestPos.y - deltay;
RotatePoint( &x0, &y0, m_padToTestPos.x, m_padToTestPos.y, orient );
RotatePoint( &x0, &y0, m_segmAngle );

View File

@ -0,0 +1,172 @@
/*
* drc_marker_functions.cpp
*/
/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 2010 Dick Hollenbeck, dick@softplc.com
* Copyright (C) 2004-2010 Jean-Pierre Charras, jean-pierre.charras@gipsa-lab.inpg.fr
* Copyright (C) 2007 Kicad Developers, see change_log.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/* Methods of class DRC to initialize drc markers with messages
* according to items and error ode
*/
#include "fctsys.h"
#include "common.h"
//#include "class_drawpanel.h"
#include "pcbnew.h"
//#include "wxPcbStruct.h"
#include "class_board_design_settings.h"
#include "drc_stuff.h"
MARKER_PCB* DRC::fillMarker( TRACK* aTrack, BOARD_ITEM* aItem, int aErrorCode, MARKER_PCB* fillMe )
{
wxString textA = aTrack->MenuText( m_pcb );
wxString textB;
wxPoint position;
wxPoint posB;
if( aItem ) // aItem might be NULL
{
textB = aItem->MenuText( m_pcb );
posB = aItem->GetPosition();
if( aItem->Type() == TYPE_PAD )
position = aItem->GetPosition();
else if( aItem->Type() == TYPE_VIA )
position = aItem->GetPosition();
else if( aItem->Type() == TYPE_TRACK )
{
TRACK* track = (TRACK*) aItem;
wxPoint endPos = track->m_End;
// either of aItem's start or end will be used for the marker position
// first assume start, then switch at end if needed. decision made on
// distance from end of aTrack.
position = track->m_Start;
double dToEnd = hypot( endPos.x - aTrack->m_End.x,
endPos.y - aTrack->m_End.y );
double dToStart = hypot( position.x - aTrack->m_End.x,
position.y - aTrack->m_End.y );
if( dToEnd < dToStart )
position = endPos;
}
}
else
position = aTrack->GetPosition();
if( fillMe )
{
if( aItem )
fillMe->SetData( aErrorCode, position,
textA, aTrack->GetPosition(),
textB, posB );
else
fillMe->SetData( aErrorCode, position,
textA, aTrack->GetPosition() );
}
else
{
if( aItem )
fillMe = new MARKER_PCB( aErrorCode, position,
textA, aTrack->GetPosition(),
textB, posB );
else
fillMe = new MARKER_PCB( aErrorCode, position,
textA, aTrack->GetPosition() );
}
return fillMe;
}
MARKER_PCB* DRC::fillMarker( D_PAD* aPad, D_PAD* bPad, int aErrorCode, MARKER_PCB* fillMe )
{
wxString textA = aPad->MenuText( m_pcb );
wxString textB = bPad->MenuText( m_pcb );
wxPoint posA = aPad->GetPosition();
wxPoint posB = bPad->GetPosition();
if( fillMe )
fillMe->SetData( aErrorCode, posA, textA, posA, textB, posB );
else
fillMe = new MARKER_PCB( aErrorCode, posA, textA, posA, textB, posB );
return fillMe;
}
MARKER_PCB* DRC::fillMarker( ZONE_CONTAINER* aArea, int aErrorCode, MARKER_PCB* fillMe )
{
wxString textA = aArea->MenuText( m_pcb );
wxPoint posA = aArea->GetPosition();
if( fillMe )
fillMe->SetData( aErrorCode, posA, textA, posA );
else
fillMe = new MARKER_PCB( aErrorCode, posA, textA, posA );
return fillMe;
}
MARKER_PCB* DRC::fillMarker( const ZONE_CONTAINER* aArea,
const wxPoint& aPos,
int aErrorCode,
MARKER_PCB* fillMe )
{
wxString textA = aArea->MenuText( m_pcb );
wxPoint posA = aPos;
if( fillMe )
fillMe->SetData( aErrorCode, posA, textA, posA );
else
fillMe = new MARKER_PCB( aErrorCode, posA, textA, posA );
return fillMe;
}
MARKER_PCB* DRC::fillMarker( int aErrorCode, const wxString& aMessage, MARKER_PCB* fillMe )
{
wxPoint posA; // not displayed
if( fillMe )
fillMe->SetData( aErrorCode, posA, aMessage, posA );
else
fillMe = new MARKER_PCB( aErrorCode, posA, aMessage, posA );
fillMe->SetShowNoCoordinate();
return fillMe;
}

View File

@ -179,7 +179,6 @@ private:
int m_ycliphi;
WinEDA_PcbFrame* m_mainWindow;
WinEDA_DrawPanel* m_drawPanel;
BOARD* m_pcb;
DIALOG_DRC_CONTROL* m_ui;
@ -306,7 +305,7 @@ private:
* Function checkClearancePadToPad
* @param aRefPad The reference pad to check
* @param aPad Another pad to check against
* @return bool - true if clearance between aRefPad and pad is >= dist_min, else false
* @return bool - true if clearance between aRefPad and aPad is >= dist_min, else false
*/
bool checkClearancePadToPad( D_PAD* aRefPad, D_PAD* aPad );
@ -315,18 +314,18 @@ private:
* Function checkClearanceSegmToPad
* check the distance from a pad to segment. This function uses several
* instance variable not passed in:
* segmLength = length of the segment being tested
* segmAngle = angle d'inclinaison du segment;
* finx, finy = end coordinate of the segment
* spot_cX, spot_cY = position of pad / origin of segment
* @param pad_to_test Is the pad involved in the check
* @param w_segm Hhalf width of the segment to test
* @param dist_min Is the minimum clearance needed
* m_segmLength = length of the segment being tested
* m_segmAngle = angle of the segment with the X axis;
* m_segmEnd = end coordinate of the segment
* m_padToTestPos = position of pad relative to the origin of segment
* @param aPad Is the pad involved in the check
* @param aSegmentWidth width of the segment to test
* @param aMinDist Is the minimum clearance needed
*
* @return false distance >= dist_min,
* true if distance < dist_min
* @return true distance >= dist_min,
* false if distance < dist_min
*/
bool checkClearanceSegmToPad( const D_PAD* pad_to_test, int w_segm, int dist_min );
bool checkClearanceSegmToPad( const D_PAD* aPad, int aSegmentWidth, int aMinDist );
/**

View File

@ -4,17 +4,10 @@
#include "fctsys.h"
//#include "gr_basic.h"
#include "common.h"
#include "class_drawpanel.h"
#include "confirm.h"
#include "pcbnew.h"
//#include "trigo.h"
//#include "drag.h"
//#include "protos.h"
#include "dialog_global_pads_edition_base.h"
@ -104,6 +97,8 @@ void DIALOG_GLOBAL_PADS_EDITION::PadPropertiesAccept( wxCommandEvent& event )
EndModal( returncode );
break;
}
m_Parent->OnModify();
}
@ -272,7 +267,7 @@ void WinEDA_BasePcbFrame::Global_Import_Pad_Settings( D_PAD* aPad, bool aDraw )
break;
}
pt_pad->ComputeRayon();
pt_pad->ComputeShapeMaxRadius();
}
Module->Set_Rectangle_Encadrement();

View File

@ -110,7 +110,7 @@ void WinEDA_BasePcbFrame::Export_Pad_Settings( D_PAD* pt_pad )
( (MODULE*) pt_pad->GetParent() )->m_Orient;
g_Pad_Master.m_Size = pt_pad->m_Size;
g_Pad_Master.m_DeltaSize = pt_pad->m_DeltaSize;
pt_pad->ComputeRayon();
pt_pad->ComputeShapeMaxRadius();
g_Pad_Master.m_Offset = pt_pad->m_Offset;
g_Pad_Master.m_Drill = pt_pad->m_Drill;
@ -163,7 +163,7 @@ void WinEDA_BasePcbFrame::Import_Pad_Settings( D_PAD* aPad, bool aDraw )
aPad->m_Offset.y = 0;
}
aPad->ComputeRayon();
aPad->ComputeShapeMaxRadius();
if( aDraw )
DrawPanel->PostDirtyRect( aPad->GetBoundingBox() );
@ -234,7 +234,7 @@ void WinEDA_BasePcbFrame::AddPad( MODULE* Module, bool draw )
void WinEDA_BasePcbFrame::DeletePad( D_PAD* aPad, bool aQuery )
{
MODULE* Module;
if( aPad == NULL )
return;

View File

@ -265,7 +265,7 @@ MODULE* WinEDA_PcbFrame::Genere_Self( wxDC* DC )
PtPad->m_Masque_Layer = g_TabOneLayerMask[Module->GetLayer()];
PtPad->m_Attribut = PAD_SMD;
PtPad->m_PadShape = PAD_CIRCLE;
PtPad->m_Rayon = PtPad->m_Size.x / 2;
PtPad->ComputeShapeMaxRadius();
D_PAD* newpad = new D_PAD( Module );
newpad->Copy( PtPad );