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; wxPoint start, end;
int width; int width;
aPad->GetOblongDrillGeometry( start, end, width ); aPad->GetOblongGeometry( aPad->GetDrillSize(), &start, &end, &width );
width += aInflateValue * 2; width += aInflateValue * 2;
start += aPad->GetPosition(); start += aPad->GetPosition();

View File

@ -360,20 +360,8 @@ void SCH_BASE_FRAME::FocusOnItem( SCH_ITEM* aItem )
RefreshItem( aItem ); RefreshItem( aItem );
lastBrightenedItemID = aItem->m_Uuid; lastBrightenedItemID = aItem->m_Uuid;
wxPoint position = aItem->GetPosition(); // JEY TODO: test this with pins and fields (and with rotated symbols) ....
FocusOnLocation( aItem->GetFocusPosition() );
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 );
} }
} }

View File

@ -342,6 +342,13 @@ public:
virtual const wxPoint GetPosition() const { return wxPoint(); } 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 * Function Clone
* creates a duplicate of this item with linked list members set to NULL. * 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( bool D_PAD::BuildPadDrillShapePolygon( SHAPE_POLY_SET& aCornerBuffer, int aInflateValue,
SHAPE_POLY_SET& aCornerBuffer, int aInflateValue, int aError ) const int aError ) const
{ {
wxSize drillsize = GetDrillSize(); wxSize drillsize = GetDrillSize();
@ -697,7 +697,7 @@ bool D_PAD::BuildPadDrillShapePolygon(
wxPoint start, end; wxPoint start, end;
int width; int width;
GetOblongDrillGeometry( start, end, width ); GetOblongGeometry( GetDrillSize(), &start, &end, &width );
start += GetPosition(); start += GetPosition();
end += 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, void D_PAD::GetOblongGeometry( const wxSize& aDrillOrPadSize,
wxPoint& aEndPoint, int& aWidth ) const wxPoint* aStartPoint, wxPoint* aEndPoint, int* aWidth ) const
{ {
// calculates the start point, end point and width // 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; int delta_cx, delta_cy;
wxSize halfsize = GetDrillSize(); wxSize halfsize = aDrillOrPadSize / 2;
halfsize.x /= 2; wxPoint offset;
halfsize.y /= 2;
if( m_Drill.x > m_Drill.y ) // horizontal if( aDrillOrPadSize.x > aDrillOrPadSize.y ) // horizontal
{ {
delta_cx = halfsize.x - halfsize.y; delta_cx = halfsize.x - halfsize.y;
delta_cy = 0; delta_cy = 0;
aWidth = m_Drill.y; *aWidth = aDrillOrPadSize.y;
} }
else // vertical else // vertical
{ {
delta_cx = 0; delta_cx = 0;
delta_cy = halfsize.y - halfsize.x; delta_cy = halfsize.y - halfsize.x;
aWidth = m_Drill.x; *aWidth = aDrillOrPadSize.x;
} }
RotatePoint( &delta_cx, &delta_cy, m_Orient ); RotatePoint( &delta_cx, &delta_cy, m_Orient );
aStartPoint.x = delta_cx; aStartPoint->x = delta_cx + offset.x;
aStartPoint.y = delta_cy; aStartPoint->y = delta_cy + offset.y;
aEndPoint.x = - delta_cx; aEndPoint->x = - delta_cx + offset.x;
aEndPoint.y = - delta_cy; aEndPoint->y = - delta_cy + offset.y;
} }

View File

@ -408,15 +408,19 @@ public:
PAD_DRILL_SHAPE_T GetDrillShape() const { return m_drillShape; } PAD_DRILL_SHAPE_T GetDrillShape() const { return m_drillShape; }
/** /**
* Function GetOblongDrillGeometry calculates the start point, end point and width * Function GetOblongGeometry calculates the start point, end point and width of an
* of an equivalent segment which have the same position and width as the hole * equivalent segment which have the same position and width as the pad (for circular
* Usefull to plot/draw oblong holes like segments with rounded ends * of oval pads) or hole
* used in draw and plot functions *
* 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 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 aEndPoint = second point of the equivalent segment, relative to the pad position.
* @param aWidth = width equivalent segment. * @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; } void SetLayerSet( LSET aLayerMask ) { m_layerMask = aLayerMask; }
LSET GetLayerSet() const override { return m_layerMask; } LSET GetLayerSet() const override { return m_layerMask; }

View File

@ -100,6 +100,7 @@ public:
void SetPosition( const wxPoint& aPos ) override { m_Start = aPos; } void SetPosition( const wxPoint& aPos ) override { m_Start = aPos; }
const wxPoint GetPosition() const override { return m_Start; } 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; } void SetWidth( int aWidth ) { m_Width = aWidth; }
int GetWidth() const { return m_Width; } int GetWidth() const { return m_Width; }

View File

@ -338,18 +338,20 @@ void DRC::doTrackDrc( TRACK* aRefSeg, TRACKS::iterator aStartIt, TRACKS::iterato
if( pad->GetDrillSize().x > 0 ) 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, /* Treat an oval hole as a line segment along the hole's major axis,
* shortened by half its minor axis. * shortened by half its minor axis.
* A circular hole is just a degenerate case of an oval hole. * A circular hole is just a degenerate case of an oval hole.
*/ */
wxPoint slotStart; wxPoint slotStart, slotEnd;
wxPoint slotEnd;
int slotWidth; 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 ); SEG slotSeg( slotStart, slotEnd );
int widths = ( slotWidth + refSegWidth ) / 2; int widths = ( slotWidth + refSegWidth ) / 2;
int center2centerAllowed = minClearance + widths; int center2centerAllowed = minClearance + widths;
@ -387,11 +389,11 @@ void DRC::doTrackDrc( TRACK* aRefSeg, TRACKS::iterator aStartIt, TRACKS::iterato
wxString clearanceSource; wxString clearanceSource;
int minClearance = aRefSeg->GetClearance( pad, &clearanceSource ); int minClearance = aRefSeg->GetClearance( pad, &clearanceSource );
SEG padSeg( pad->GetPosition(), pad->GetPosition() );
int actual; int actual;
if( !checkClearanceSegmToPad( refSeg, refSegWidth, pad, minClearance, &actual ) ) if( !checkClearanceSegmToPad( refSeg, refSegWidth, pad, minClearance, &actual ) )
{ {
SEG padSeg( pad->GetPosition(), pad->GetPosition() );
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_NEAR_PAD ); DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_NEAR_PAD );
msg.Printf( drcItem->GetErrorText() + _( " (%s %s; actual %s)" ), 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. * shortened by half its minor axis.
* A circular pad is just a degenerate case of an oval hole. * A circular pad is just a degenerate case of an oval hole.
*/ */
wxPoint refPadStart = aRefPad->GetPosition() + aRefPad->GetOffset(); wxPoint refPadStart, refPadEnd;
wxPoint refPadEnd = aRefPad->GetPosition() + aRefPad->GetOffset();
int refPadWidth; int refPadWidth;
if( aRefPad->GetSize().x > aRefPad->GetSize().y ) aRefPad->GetOblongGeometry( aRefPad->GetSize(), &refPadStart, &refPadEnd, &refPadWidth );
{ refPadStart += aRefPad->ShapePos();
refPadWidth = aRefPad->GetSize().y; refPadEnd += aRefPad->ShapePos();
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;
}
SEG refPadSeg( refPadStart, refPadEnd ); SEG refPadSeg( refPadStart, refPadEnd );
diag = checkClearanceSegmToPad( refPadSeg, refPadWidth, aPad, aMinClearance, aActual ); 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]; wxPoint polyref[4];
// corners of aRefPad (used only for custom pad) // corners of aRefPad (used only for custom pad)
SHAPE_POLY_SET polysetref; 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 ) 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() ); 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() ) switch( aPad->GetShape() )
{ {
case PAD_SHAPE_ROUNDRECT: 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++ ) for( int ii = 0; ii < 4; ii++ )
polycompare[ii] += relativePadPos; polycompare[ii] += relativePadPos;
} }
// And now test polygons: We have 3 cases: // And now test polygons: We have 3 cases:
// one poly is complex and the other is basic (has only 4 corners) // one poly is complex and the other is basic (has only 4 corners)
// both polys are complex // 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. * shortened by half its minor axis.
* A circular pad is just a degenerate case of an oval hole. * 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 padStart, padEnd;
wxPoint padEnd = pad->GetPosition() + pad->GetOffset(); int padWidth;
int padHalfWidth;
if( pad->GetSize().x > pad->GetSize().y ) pad->GetOblongGeometry( pad->GetSize(), &padStart, &padEnd, &padWidth );
{ padStart += pad->ShapePos();
padHalfWidth = pad->GetSize().y / 2; padEnd += pad->ShapePos();
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;
}
SEG padSeg( padStart, padEnd ); SEG padSeg( padStart, padEnd );
int widths = padHalfWidth + ( refSegWidth / 2 ); int widths = ( padWidth + refSegWidth ) / 2;
int center2centerAllowed = minClearance + widths; int center2centerAllowed = minClearance + widths;
// Avoid square-roots if possible (for performance) // 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 ); GetCanvas()->GetView()->Update( aItem );
lastBrightenedItemID = aItem->m_Uuid; lastBrightenedItemID = aItem->m_Uuid;
FocusOnLocation( aItem->GetPosition() ); FocusOnLocation( aItem->GetFocusPosition() );
GetCanvas()->Refresh(); 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 // Note: small drill marks have no significance when applied to slots
wxPoint drl_start, drl_end; wxPoint drl_start, drl_end;
int width; int width;
pad->GetOblongDrillGeometry( drl_start, drl_end, width );
pad->GetOblongGeometry( pad->GetDrillSize(), &drl_start, &drl_end, &width );
aPlotter->ThickSegment( pad->GetPosition() + drl_start, aPlotter->ThickSegment( pad->GetPosition() + drl_start,
pad->GetPosition() + drl_end, width, SKETCH, NULL ); pad->GetPosition() + drl_end, width, SKETCH, NULL );
} }