Fix bounding boxes and hittesting for arcs in eeschema.

This commit is contained in:
Jeff Young 2022-01-16 23:54:59 +00:00
parent e61144d45a
commit 5cc3368b14
3 changed files with 48 additions and 68 deletions

View File

@ -37,14 +37,14 @@
#include <plotters/plotter.h> #include <plotters/plotter.h>
EDA_SHAPE::EDA_SHAPE( SHAPE_T aType, int aLineWidth, FILL_T aFill, bool eeWinding ) : EDA_SHAPE::EDA_SHAPE( SHAPE_T aType, int aLineWidth, FILL_T aFill, bool upsideDownCoords ) :
m_endsSwapped( false ), m_endsSwapped( false ),
m_shape( aType ), m_shape( aType ),
m_stroke( aLineWidth, PLOT_DASH_TYPE::DEFAULT, COLOR4D::UNSPECIFIED ), m_stroke( aLineWidth, PLOT_DASH_TYPE::DEFAULT, COLOR4D::UNSPECIFIED ),
m_fill( aFill ), m_fill( aFill ),
m_fillColor( COLOR4D::UNSPECIFIED ), m_fillColor( COLOR4D::UNSPECIFIED ),
m_editState( 0 ), m_editState( 0 ),
m_eeWinding( eeWinding ) m_upsideDownCoords( upsideDownCoords )
{ {
} }
@ -711,7 +711,7 @@ bool EDA_SHAPE::hitTest( const VECTOR2I& aPosition, int aAccuracy ) const
EDA_ANGLE endAngle; EDA_ANGLE endAngle;
CalcArcAngles( startAngle, endAngle ); CalcArcAngles( startAngle, endAngle );
if( m_eeWinding && ( startAngle - endAngle ).Normalize180() > ANGLE_0 ) if( m_upsideDownCoords && ( startAngle - endAngle ).Normalize180() > ANGLE_0 )
std::swap( startAngle, endAngle ); std::swap( startAngle, endAngle );
EDA_ANGLE relPosAngle( relPos ); EDA_ANGLE relPosAngle( relPos );
@ -993,70 +993,50 @@ std::vector<VECTOR2I> EDA_SHAPE::GetRectCorners() const
void EDA_SHAPE::computeArcBBox( EDA_RECT& aBBox ) const void EDA_SHAPE::computeArcBBox( EDA_RECT& aBBox ) const
{ {
VECTOR2I start = m_start; int radius = GetRadius();
VECTOR2I end = m_end;
EDA_ANGLE t1, t2; EDA_ANGLE t1, t2;
CalcArcAngles( t1, t2 ); CalcArcAngles( t1, t2 );
if( m_eeWinding && ( t1 - t2 ).Normalize180() > ANGLE_0 ) if( m_upsideDownCoords && ( t1 - t2 ).Normalize180() > ANGLE_0 )
std::swap( start, end ); std::swap( t1, t2 );
// Do not include the center, which is not necessarily inside the BB of an arc with a small t1.Normalize();
// included angle t2.Normalize();
aBBox.SetOrigin( start );
aBBox.Merge( end );
// Determine the starting quarter // Start, end, and each inflection point the arc crosses will enclose the entire arc
// 0 right-bottom // Do not include the center, which is not necessarily inside the BB of an arc with a
// 1 left-bottom // small included angle
// 2 left-top aBBox.SetOrigin( m_start );
// 3 right-top aBBox.Merge( m_end );
unsigned int quarter;
if( start.x < m_arcCenter.x ) if( t2 > t1 )
{ {
if( start.y <= m_arcCenter.y ) if( t1 < ANGLE_0 && t2 > ANGLE_0 )
quarter = 2; aBBox.Merge( VECTOR2I( m_arcCenter.x + radius, m_arcCenter.y ) ); // right
else
quarter = 1; if( t1 < ANGLE_90 && t2 > ANGLE_90 )
} aBBox.Merge( VECTOR2I( m_arcCenter.x, m_arcCenter.y + radius ) ); // down
else if( start.x == m_arcCenter.x )
{ if( t1 < ANGLE_180 && t2 > ANGLE_180 )
if( start.y < m_arcCenter.y ) aBBox.Merge( VECTOR2I( m_arcCenter.x - radius, m_arcCenter.y ) ); // left
quarter = 3;
else if( t1 < ANGLE_270 && t2 > ANGLE_270 )
quarter = 1; aBBox.Merge( VECTOR2I( m_arcCenter.x, m_arcCenter.y - radius ) ); // up
} }
else else
{ {
if( start.y < m_arcCenter.y ) if( t1 < ANGLE_0 || t2 > ANGLE_0 )
quarter = 3; aBBox.Merge( VECTOR2I( m_arcCenter.x + radius, m_arcCenter.y ) ); // right
else
quarter = 0;
}
int radius = GetRadius(); if( t1 < ANGLE_90 || t2 > ANGLE_90 )
VECTOR2I startRadial = start - m_arcCenter; aBBox.Merge( VECTOR2I( m_arcCenter.x, m_arcCenter.y + radius ) ); // down
EDA_ANGLE angle = EDA_ANGLE( startRadial ).Normalize();
while( angle >= ANGLE_90 ) if( t1 < ANGLE_180 || t2 > ANGLE_180 )
angle -= ANGLE_90; aBBox.Merge( VECTOR2I( m_arcCenter.x - radius, m_arcCenter.y ) ); // left
angle += GetArcAngle(); if( t1 < ANGLE_270 || t2 > ANGLE_270 )
aBBox.Merge( VECTOR2I( m_arcCenter.x, m_arcCenter.y - radius ) ); // up
while( angle > ANGLE_90 )
{
switch( quarter )
{
case 0: aBBox.Merge( VECTOR2I( m_arcCenter.x, m_arcCenter.y + radius ) ); break; // down
case 1: aBBox.Merge( VECTOR2I( m_arcCenter.x - radius, m_arcCenter.y ) ); break; // left
case 2: aBBox.Merge( VECTOR2I( m_arcCenter.x, m_arcCenter.y - radius ) ); break; // up
case 3: aBBox.Merge( VECTOR2I( m_arcCenter.x + radius, m_arcCenter.y ) ); break; // right
}
++quarter %= 4;
angle -= ANGLE_90;
} }
} }
@ -1431,7 +1411,7 @@ void EDA_SHAPE::SwapShape( EDA_SHAPE* aImage )
SWAPITEM( m_poly ); SWAPITEM( m_poly );
SWAPITEM( m_fill ); SWAPITEM( m_fill );
SWAPITEM( m_fillColor ); SWAPITEM( m_fillColor );
SWAPITEM( m_eeWinding ); SWAPITEM( m_upsideDownCoords );
SWAPITEM( m_editState ); SWAPITEM( m_editState );
SWAPITEM( m_endsSwapped ); SWAPITEM( m_endsSwapped );
#undef SWAPITEM #undef SWAPITEM

View File

@ -36,7 +36,7 @@
SCH_SHAPE::SCH_SHAPE( SHAPE_T aShape, int aLineWidth, FILL_T aFillType ) : SCH_SHAPE::SCH_SHAPE( SHAPE_T aShape, int aLineWidth, FILL_T aFillType ) :
SCH_ITEM( nullptr, SCH_SHAPE_T ), SCH_ITEM( nullptr, SCH_SHAPE_T ),
EDA_SHAPE( aShape, aLineWidth, aFillType, true ) EDA_SHAPE( aShape, aLineWidth, aFillType, false )
{ {
SetLayer( LAYER_NOTES ); SetLayer( LAYER_NOTES );
} }

View File

@ -322,7 +322,7 @@ protected:
SHAPE_POLY_SET m_poly; // Stores the S_POLYGON shape SHAPE_POLY_SET m_poly; // Stores the S_POLYGON shape
int m_editState; int m_editState;
bool m_eeWinding; // Awful hack bool m_upsideDownCoords; // Awful hack
}; };
#endif // EDA_SHAPE_H #endif // EDA_SHAPE_H