Fix aDRC issue: sometimes DRC did not detect a track collision with long oval pads.

This commit is contained in:
jean-pierre charras 2018-01-23 11:48:04 +01:00
parent 76885169c4
commit 6436b70176
1 changed files with 42 additions and 34 deletions

View File

@ -5,9 +5,9 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2004-2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2004-2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2007 Dick Hollenbeck, dick@softplc.com
* Copyright (C) 2017 KiCad Developers, see change_log.txt for contributors.
* Copyright (C) 2018 KiCad Developers, see AUTHORS.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
@ -1044,55 +1044,63 @@ bool DRC::checkClearanceSegmToPad( const D_PAD* aPad, int aSegmentWidth, int aMi
/* an oval is a complex shape, but is a rectangle and 2 circles
* these 3 basic shapes are more easy to test.
*
* In calculations we are using a vertical oval shape
* (i.e. a vertical rounded segment)
* for horizontal oval shapes, swap x and y size and rotate the shape
* In calculations we are using a vertical or horizontal oval shape
* (i.e. a vertical or horizontal rounded segment)
*/
if( padHalfsize.x > padHalfsize.y )
wxPoint cstart = m_padToTestPos;
wxPoint cend = m_padToTestPos; // center of each circle
int delta = std::abs( padHalfsize.y - padHalfsize.x );
int radius = std::min( padHalfsize.y, padHalfsize.x );
if( padHalfsize.x > padHalfsize.y ) // horizontal equivalent segment
{
std::swap( padHalfsize.x, padHalfsize.y );
orient = AddAngles( orient, 900 );
cstart.x -= delta;
cend.x += delta;
// Build the rectangular clearance area between the two circles
// the rect starts at cstart.x and ends at cend.x and its height
// is (radius + distToLine)*2
m_xcliplo = cstart.x;
m_ycliplo = cstart.y - radius - distToLine;
m_xcliphi = cend.x;
m_ycliphi = cend.y + radius + distToLine;
}
else // vertical equivalent segment
{
cstart.y -= delta;
cend.y += delta;
// Build the rectangular clearance area between the two circles
// the rect starts at cstart.y and ends at cend.y and its width
// is (radius + distToLine)*2
m_xcliplo = cstart.x - distToLine - radius;
m_ycliplo = cstart.y;
m_xcliphi = cend.x + distToLine +radius;
m_ycliphi = cend.y;
}
// here, padHalfsize.x is the radius of rounded ends.
int deltay = padHalfsize.y - padHalfsize.x;
// here: padHalfsize.x = radius,
// deltay = dist between the centre pad and the centre of a rounded end
// Test the rectangular area between the two circles (the rounded ends)
m_xcliplo = m_padToTestPos.x - distToLine - padHalfsize.x;
m_ycliplo = m_padToTestPos.y - deltay;
m_xcliphi = m_padToTestPos.x + distToLine + padHalfsize.x;
m_ycliphi = m_padToTestPos.y + deltay;
// Test the rectangular clearance area between the two circles (the rounded ends)
if( !checkLine( startPoint, endPoint ) )
{
return false;
}
// test the first circle
startPoint.x = m_padToTestPos.x; // startPoint = centre of the upper circle of the oval shape
startPoint.y = m_padToTestPos.y + deltay;
// test the first end
// Calculate the actual position of the circle, given the pad orientation:
RotatePoint( &startPoint, m_padToTestPos, orient );
RotatePoint( &cstart, m_padToTestPos, orient );
// Calculate the actual position of the circle in the new X,Y axis:
RotatePoint( &startPoint, m_segmAngle );
// Calculate the actual position of the circle in the new X,Y axis, relative
// to the segment:
RotatePoint( &cstart, m_segmAngle );
if( !checkMarginToCircle( startPoint, padHalfsize.x + distToLine, m_segmLength ) )
if( !checkMarginToCircle( cstart, radius + distToLine, m_segmLength ) )
{
return false;
}
// test the second circle
startPoint.x = m_padToTestPos.x; // startPoint = centre of the lower circle of the oval shape
startPoint.y = m_padToTestPos.y - deltay;
RotatePoint( &startPoint, m_padToTestPos, orient );
RotatePoint( &startPoint, m_segmAngle );
// test the second end
RotatePoint( &cend, m_padToTestPos, orient );
RotatePoint( &cend, m_segmAngle );
if( !checkMarginToCircle( startPoint, padHalfsize.x + distToLine, m_segmLength ) )
if( !checkMarginToCircle( cend, radius + distToLine, m_segmLength ) )
{
return false;
}