From 5cc3368b14ab4cb5145147ba9c2f1c3aaa7a0e5a Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Sun, 16 Jan 2022 23:54:59 +0000 Subject: [PATCH] Fix bounding boxes and hittesting for arcs in eeschema. --- common/eda_shape.cpp | 100 +++++++++++++++++------------------------ eeschema/sch_shape.cpp | 2 +- include/eda_shape.h | 14 +++--- 3 files changed, 48 insertions(+), 68 deletions(-) diff --git a/common/eda_shape.cpp b/common/eda_shape.cpp index 6df2602ea2..0bd225897b 100644 --- a/common/eda_shape.cpp +++ b/common/eda_shape.cpp @@ -37,14 +37,14 @@ #include -EDA_SHAPE::EDA_SHAPE( SHAPE_T aType, int aLineWidth, FILL_T aFill, bool eeWinding ) : - m_endsSwapped( false ), - m_shape( aType ), - m_stroke( aLineWidth, PLOT_DASH_TYPE::DEFAULT, COLOR4D::UNSPECIFIED ), - m_fill( aFill ), - m_fillColor( COLOR4D::UNSPECIFIED ), - m_editState( 0 ), - m_eeWinding( eeWinding ) +EDA_SHAPE::EDA_SHAPE( SHAPE_T aType, int aLineWidth, FILL_T aFill, bool upsideDownCoords ) : + m_endsSwapped( false ), + m_shape( aType ), + m_stroke( aLineWidth, PLOT_DASH_TYPE::DEFAULT, COLOR4D::UNSPECIFIED ), + m_fill( aFill ), + m_fillColor( COLOR4D::UNSPECIFIED ), + m_editState( 0 ), + m_upsideDownCoords( upsideDownCoords ) { } @@ -711,7 +711,7 @@ bool EDA_SHAPE::hitTest( const VECTOR2I& aPosition, int aAccuracy ) const EDA_ANGLE endAngle; CalcArcAngles( startAngle, endAngle ); - if( m_eeWinding && ( startAngle - endAngle ).Normalize180() > ANGLE_0 ) + if( m_upsideDownCoords && ( startAngle - endAngle ).Normalize180() > ANGLE_0 ) std::swap( startAngle, endAngle ); EDA_ANGLE relPosAngle( relPos ); @@ -993,70 +993,50 @@ std::vector EDA_SHAPE::GetRectCorners() const void EDA_SHAPE::computeArcBBox( EDA_RECT& aBBox ) const { - VECTOR2I start = m_start; - VECTOR2I end = m_end; + int radius = GetRadius(); EDA_ANGLE t1, t2; CalcArcAngles( t1, t2 ); - if( m_eeWinding && ( t1 - t2 ).Normalize180() > ANGLE_0 ) - std::swap( start, end ); + if( m_upsideDownCoords && ( t1 - t2 ).Normalize180() > ANGLE_0 ) + std::swap( t1, t2 ); - // Do not include the center, which is not necessarily inside the BB of an arc with a small - // included angle - aBBox.SetOrigin( start ); - aBBox.Merge( end ); + t1.Normalize(); + t2.Normalize(); - // Determine the starting quarter - // 0 right-bottom - // 1 left-bottom - // 2 left-top - // 3 right-top - unsigned int quarter; + // Start, end, and each inflection point the arc crosses will enclose the entire arc + // Do not include the center, which is not necessarily inside the BB of an arc with a + // small included angle + aBBox.SetOrigin( m_start ); + aBBox.Merge( m_end ); - if( start.x < m_arcCenter.x ) + if( t2 > t1 ) { - if( start.y <= m_arcCenter.y ) - quarter = 2; - else - quarter = 1; - } - else if( start.x == m_arcCenter.x ) - { - if( start.y < m_arcCenter.y ) - quarter = 3; - else - quarter = 1; + if( t1 < ANGLE_0 && t2 > ANGLE_0 ) + aBBox.Merge( VECTOR2I( m_arcCenter.x + radius, m_arcCenter.y ) ); // right + + if( t1 < ANGLE_90 && t2 > ANGLE_90 ) + aBBox.Merge( VECTOR2I( m_arcCenter.x, m_arcCenter.y + radius ) ); // down + + if( t1 < ANGLE_180 && t2 > ANGLE_180 ) + aBBox.Merge( VECTOR2I( m_arcCenter.x - radius, m_arcCenter.y ) ); // left + + if( t1 < ANGLE_270 && t2 > ANGLE_270 ) + aBBox.Merge( VECTOR2I( m_arcCenter.x, m_arcCenter.y - radius ) ); // up } else { - if( start.y < m_arcCenter.y ) - quarter = 3; - else - quarter = 0; - } + if( t1 < ANGLE_0 || t2 > ANGLE_0 ) + aBBox.Merge( VECTOR2I( m_arcCenter.x + radius, m_arcCenter.y ) ); // right - int radius = GetRadius(); - VECTOR2I startRadial = start - m_arcCenter; - EDA_ANGLE angle = EDA_ANGLE( startRadial ).Normalize(); + if( t1 < ANGLE_90 || t2 > ANGLE_90 ) + aBBox.Merge( VECTOR2I( m_arcCenter.x, m_arcCenter.y + radius ) ); // down - while( angle >= ANGLE_90 ) - angle -= ANGLE_90; + if( t1 < ANGLE_180 || t2 > ANGLE_180 ) + aBBox.Merge( VECTOR2I( m_arcCenter.x - radius, m_arcCenter.y ) ); // left - angle += GetArcAngle(); - - 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; + if( t1 < ANGLE_270 || t2 > ANGLE_270 ) + aBBox.Merge( VECTOR2I( m_arcCenter.x, m_arcCenter.y - radius ) ); // up } } @@ -1431,7 +1411,7 @@ void EDA_SHAPE::SwapShape( EDA_SHAPE* aImage ) SWAPITEM( m_poly ); SWAPITEM( m_fill ); SWAPITEM( m_fillColor ); - SWAPITEM( m_eeWinding ); + SWAPITEM( m_upsideDownCoords ); SWAPITEM( m_editState ); SWAPITEM( m_endsSwapped ); #undef SWAPITEM diff --git a/eeschema/sch_shape.cpp b/eeschema/sch_shape.cpp index f87282ed23..6a90ed7d6e 100644 --- a/eeschema/sch_shape.cpp +++ b/eeschema/sch_shape.cpp @@ -36,7 +36,7 @@ SCH_SHAPE::SCH_SHAPE( SHAPE_T aShape, int aLineWidth, FILL_T aFillType ) : SCH_ITEM( nullptr, SCH_SHAPE_T ), - EDA_SHAPE( aShape, aLineWidth, aFillType, true ) + EDA_SHAPE( aShape, aLineWidth, aFillType, false ) { SetLayer( LAYER_NOTES ); } diff --git a/include/eda_shape.h b/include/eda_shape.h index 45477780f9..39c8fdefe5 100644 --- a/include/eda_shape.h +++ b/include/eda_shape.h @@ -310,19 +310,19 @@ protected: FILL_T m_fill; COLOR4D m_fillColor; - VECTOR2I m_start; // Line start point or Circle center - VECTOR2I m_end; // Line end point or Circle 3 o'clock point + VECTOR2I m_start; // Line start point or Circle center + VECTOR2I m_end; // Line end point or Circle 3 o'clock point - VECTOR2I m_arcCenter; // Used only for Arcs: arc end point + VECTOR2I m_arcCenter; // Used only for Arcs: arc end point - VECTOR2I m_bezierC1; // Bezier Control Point 1 - VECTOR2I m_bezierC2; // Bezier Control Point 2 + VECTOR2I m_bezierC1; // Bezier Control Point 1 + VECTOR2I m_bezierC2; // Bezier Control Point 2 std::vector m_bezierPoints; - SHAPE_POLY_SET m_poly; // Stores the S_POLYGON shape + SHAPE_POLY_SET m_poly; // Stores the S_POLYGON shape int m_editState; - bool m_eeWinding; // Awful hack + bool m_upsideDownCoords; // Awful hack }; #endif // EDA_SHAPE_H