Fix some issues with rotated oval pads.

This commit is contained in:
Jeff Young 2020-04-27 17:22:42 +01:00
parent 5c8d712a56
commit 874f13e29e
10 changed files with 66 additions and 86 deletions

View File

@ -590,7 +590,7 @@ COBJECT2D *BOARD_ADAPTER::createNewPadDrill( const D_PAD* aPad, int aInflateValu
wxPoint start, end;
int width;
aPad->GetOblongDrillGeometry( start, end, width );
aPad->GetOblongGeometry( aPad->GetDrillSize(), &start, &end, &width );
width += aInflateValue * 2;
start += aPad->GetPosition();

View File

@ -360,20 +360,8 @@ void SCH_BASE_FRAME::FocusOnItem( SCH_ITEM* aItem )
RefreshItem( aItem );
lastBrightenedItemID = aItem->m_Uuid;
wxPoint position = aItem->GetPosition();
if( aItem->GetParent() && aItem->GetParent()->Type() == SCH_COMPONENT_T )
{
SCH_COMPONENT* comp = static_cast<SCH_COMPONENT*>( aItem->GetParent() );
// for a pin, GetPosition() is relative to the symbol, not rotated, not mirrored
// calculate the physical position:
wxPoint delta;
delta = comp->GetTransform().TransformCoordinate( position );
position = delta + comp->GetPosition();
}
FocusOnLocation( position );
// JEY TODO: test this with pins and fields (and with rotated symbols) ....
FocusOnLocation( aItem->GetFocusPosition() );
}
}

View File

@ -342,6 +342,13 @@ public:
virtual const wxPoint GetPosition() const { return wxPoint(); }
/**
* Function GetFocusPosition
* similar to GetPosition, but allows items to return their visual center rather
* than their anchor.
*/
virtual const wxPoint GetFocusPosition() const { return GetPosition(); }
/**
* Function Clone
* creates a duplicate of this item with linked list members set to NULL.

View File

@ -679,8 +679,8 @@ void D_PAD::BuildPadShapePolygon( SHAPE_POLY_SET& aCornerBuffer, wxSize aInflate
}
bool D_PAD::BuildPadDrillShapePolygon(
SHAPE_POLY_SET& aCornerBuffer, int aInflateValue, int aError ) const
bool D_PAD::BuildPadDrillShapePolygon( SHAPE_POLY_SET& aCornerBuffer, int aInflateValue,
int aError ) const
{
wxSize drillsize = GetDrillSize();
@ -697,7 +697,7 @@ bool D_PAD::BuildPadDrillShapePolygon(
wxPoint start, end;
int width;
GetOblongDrillGeometry( start, end, width );
GetOblongGeometry( GetDrillSize(), &start, &end, &width );
start += GetPosition();
end += GetPosition();

View File

@ -1047,37 +1047,36 @@ void D_PAD::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>
}
void D_PAD::GetOblongDrillGeometry( wxPoint& aStartPoint,
wxPoint& aEndPoint, int& aWidth ) const
void D_PAD::GetOblongGeometry( const wxSize& aDrillOrPadSize,
wxPoint* aStartPoint, wxPoint* aEndPoint, int* aWidth ) const
{
// calculates the start point, end point and width
// of an equivalent segment which have the same position and width as the hole
// of an equivalent segment which have the same position and width as the pad or hole
int delta_cx, delta_cy;
wxSize halfsize = GetDrillSize();
halfsize.x /= 2;
halfsize.y /= 2;
wxSize halfsize = aDrillOrPadSize / 2;
wxPoint offset;
if( m_Drill.x > m_Drill.y ) // horizontal
if( aDrillOrPadSize.x > aDrillOrPadSize.y ) // horizontal
{
delta_cx = halfsize.x - halfsize.y;
delta_cy = 0;
aWidth = m_Drill.y;
*aWidth = aDrillOrPadSize.y;
}
else // vertical
else // vertical
{
delta_cx = 0;
delta_cy = halfsize.y - halfsize.x;
aWidth = m_Drill.x;
*aWidth = aDrillOrPadSize.x;
}
RotatePoint( &delta_cx, &delta_cy, m_Orient );
aStartPoint.x = delta_cx;
aStartPoint.y = delta_cy;
aStartPoint->x = delta_cx + offset.x;
aStartPoint->y = delta_cy + offset.y;
aEndPoint.x = - delta_cx;
aEndPoint.y = - delta_cy;
aEndPoint->x = - delta_cx + offset.x;
aEndPoint->y = - delta_cy + offset.y;
}

View File

@ -408,15 +408,19 @@ public:
PAD_DRILL_SHAPE_T GetDrillShape() const { return m_drillShape; }
/**
* Function GetOblongDrillGeometry calculates the start point, end point and width
* of an equivalent segment which have the same position and width as the hole
* Usefull to plot/draw oblong holes like segments with rounded ends
* used in draw and plot functions
* Function GetOblongGeometry calculates the start point, end point and width of an
* equivalent segment which have the same position and width as the pad (for circular
* of oval pads) or hole
*
* NB: points returned are RELATIVE to the PAD POSITION. For board coordinates holes
* will need to be offset by GetPosition() and pads by ShapePos().
*
* @param aStartPoint = first point of the equivalent segment, relative to the pad position.
* @param aEndPoint = second point of the equivalent segment, relative to the pad position.
* @param aWidth = width equivalent segment.
*/
void GetOblongDrillGeometry( wxPoint& aStartPoint, wxPoint& aEndPoint, int& aWidth ) const;
void GetOblongGeometry( const wxSize& aDrillOrPadSize,
wxPoint* aStartPoint, wxPoint* aEndPoint, int* aWidth ) const;
void SetLayerSet( LSET aLayerMask ) { m_layerMask = aLayerMask; }
LSET GetLayerSet() const override { return m_layerMask; }

View File

@ -100,6 +100,7 @@ public:
void SetPosition( const wxPoint& aPos ) override { m_Start = aPos; }
const wxPoint GetPosition() const override { return m_Start; }
const wxPoint GetFocusPosition() const override { return ( m_Start + m_End ) / 2; }
void SetWidth( int aWidth ) { m_Width = aWidth; }
int GetWidth() const { return m_Width; }

View File

@ -338,21 +338,23 @@ void DRC::doTrackDrc( TRACK* aRefSeg, TRACKS::iterator aStartIt, TRACKS::iterato
if( pad->GetDrillSize().x > 0 )
{
wxString clearanceSource;
int minClearance = aRefSeg->GetClearance( nullptr, &clearanceSource );
/* Treat an oval hole as a line segment along the hole's major axis,
* shortened by half its minor axis.
* A circular hole is just a degenerate case of an oval hole.
*/
wxPoint slotStart;
wxPoint slotEnd;
wxPoint slotStart, slotEnd;
int slotWidth;
pad->GetOblongDrillGeometry( slotStart, slotEnd, slotWidth );
pad->GetOblongGeometry( pad->GetDrillSize(), &slotStart, &slotEnd, &slotWidth );
slotStart += pad->GetPosition();
slotEnd += pad->GetPosition();
wxString clearanceSource;
int minClearance = aRefSeg->GetClearance( nullptr, &clearanceSource );
SEG slotSeg( slotStart, slotEnd );
int widths = ( slotWidth + refSegWidth ) / 2;
int center2centerAllowed = minClearance + widths;
SEG slotSeg( slotStart, slotEnd );
int widths = ( slotWidth + refSegWidth ) / 2;
int center2centerAllowed = minClearance + widths;
// Avoid square-roots if possible (for performance)
SEG::ecoord center2center_squared = refSeg.SquaredDistance( slotSeg );
@ -387,11 +389,11 @@ void DRC::doTrackDrc( TRACK* aRefSeg, TRACKS::iterator aStartIt, TRACKS::iterato
wxString clearanceSource;
int minClearance = aRefSeg->GetClearance( pad, &clearanceSource );
SEG padSeg( pad->GetPosition(), pad->GetPosition() );
int actual;
if( !checkClearanceSegmToPad( refSeg, refSegWidth, pad, minClearance, &actual ) )
{
SEG padSeg( pad->GetPosition(), pad->GetPosition() );
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_NEAR_PAD );
msg.Printf( drcItem->GetErrorText() + _( " (%s %s; actual %s)" ),
@ -666,22 +668,12 @@ bool DRC::checkClearancePadToPad( D_PAD* aRefPad, D_PAD* aPad, int aMinClearance
* shortened by half its minor axis.
* A circular pad is just a degenerate case of an oval hole.
*/
wxPoint refPadStart = aRefPad->GetPosition() + aRefPad->GetOffset();
wxPoint refPadEnd = aRefPad->GetPosition() + aRefPad->GetOffset();
wxPoint refPadStart, refPadEnd;
int refPadWidth;
if( aRefPad->GetSize().x > aRefPad->GetSize().y )
{
refPadWidth = aRefPad->GetSize().y;
refPadStart.x -= ( aRefPad->GetSize().x - refPadWidth ) / 2;
refPadEnd.x += ( aRefPad->GetSize().x - refPadWidth ) / 2;
}
else
{
refPadWidth = aRefPad->GetSize().x;
refPadStart.y -= ( aRefPad->GetSize().y - refPadWidth ) / 2;
refPadEnd.y += ( aRefPad->GetSize().y - refPadWidth ) / 2;
}
aRefPad->GetOblongGeometry( aRefPad->GetSize(), &refPadStart, &refPadEnd, &refPadWidth );
refPadStart += aRefPad->ShapePos();
refPadEnd += aRefPad->ShapePos();
SEG refPadSeg( refPadStart, refPadEnd );
diag = checkClearanceSegmToPad( refPadSeg, refPadWidth, aPad, aMinClearance, aActual );
@ -694,14 +686,6 @@ bool DRC::checkClearancePadToPad( D_PAD* aRefPad, D_PAD* aPad, int aMinClearance
wxPoint polyref[4];
// corners of aRefPad (used only for custom pad)
SHAPE_POLY_SET polysetref;
// corners of aPad (used only for rect/roundrect/trap pad)
wxPoint polycompare[4];
// corners of aPad (used only custom pad)
SHAPE_POLY_SET polysetcompare;
// pad_angle = pad orient relative to the aRefPad orient
double pad_angle = aRefPad->GetOrientation() + aPad->GetOrientation();
NORMALIZE_ANGLE_POS( pad_angle );
if( aRefPad->GetShape() == PAD_SHAPE_ROUNDRECT )
{
@ -739,6 +723,11 @@ bool DRC::checkClearancePadToPad( D_PAD* aRefPad, D_PAD* aPad, int aMinClearance
aRefPad->BuildPadPolygon( polyref, wxSize( 0, 0 ), aRefPad->GetOrientation() );
}
// corners of aPad (used only for rect/roundrect/trap pad)
wxPoint polycompare[4];
// corners of aPad (used only custom pad)
SHAPE_POLY_SET polysetcompare;
switch( aPad->GetShape() )
{
case PAD_SHAPE_ROUNDRECT:
@ -784,6 +773,7 @@ bool DRC::checkClearancePadToPad( D_PAD* aRefPad, D_PAD* aPad, int aMinClearance
for( int ii = 0; ii < 4; ii++ )
polycompare[ii] += relativePadPos;
}
// And now test polygons: We have 3 cases:
// one poly is complex and the other is basic (has only 4 corners)
// both polys are complex
@ -857,25 +847,15 @@ bool DRC::checkClearanceSegmToPad( const SEG& refSeg, int refSegWidth, const D_P
* shortened by half its minor axis.
* A circular pad is just a degenerate case of an oval hole.
*/
wxPoint padStart = pad->GetPosition() + pad->GetOffset(); // JEY TODO: needs to handle rotation....
wxPoint padEnd = pad->GetPosition() + pad->GetOffset();
int padHalfWidth;
wxPoint padStart, padEnd;
int padWidth;
if( pad->GetSize().x > pad->GetSize().y )
{
padHalfWidth = pad->GetSize().y / 2;
padStart.x -= ( pad->GetSize().x / 2 ) - padHalfWidth;
padEnd.x += ( pad->GetSize().x / 2 ) - padHalfWidth;
}
else
{
padHalfWidth = pad->GetSize().x / 2;
padStart.y -= ( pad->GetSize().y / 2 ) - padHalfWidth;
padEnd.y += ( pad->GetSize().y / 2 ) - padHalfWidth;
}
pad->GetOblongGeometry( pad->GetSize(), &padStart, &padEnd, &padWidth );
padStart += pad->ShapePos();
padEnd += pad->ShapePos();
SEG padSeg( padStart, padEnd );
int widths = padHalfWidth + ( refSegWidth / 2 );
int widths = ( padWidth + refSegWidth ) / 2;
int center2centerAllowed = minClearance + widths;
// Avoid square-roots if possible (for performance)

View File

@ -230,7 +230,7 @@ void PCB_BASE_FRAME::FocusOnItem( BOARD_ITEM* aItem )
GetCanvas()->GetView()->Update( aItem );
lastBrightenedItemID = aItem->m_Uuid;
FocusOnLocation( aItem->GetPosition() );
FocusOnLocation( aItem->GetFocusPosition() );
GetCanvas()->Refresh();
}
}

View File

@ -779,7 +779,8 @@ void PlotLayerOutlines( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
// Note: small drill marks have no significance when applied to slots
wxPoint drl_start, drl_end;
int width;
pad->GetOblongDrillGeometry( drl_start, drl_end, width );
pad->GetOblongGeometry( pad->GetDrillSize(), &drl_start, &drl_end, &width );
aPlotter->ThickSegment( pad->GetPosition() + drl_start,
pad->GetPosition() + drl_end, width, SKETCH, NULL );
}