Validate arc output when editing

Handles checking output of the arc to ensure we don't end up generating
an invalid arc.  Also keeps the limit of the arc angle to be (360,360)
excluding 0.

Fixes https://gitlab.com/kicad/code/kicad/issues/10070

(cherry picked from commit 8fc831cbc2)
This commit is contained in:
Seth Hillbrand 2022-02-06 17:16:28 -08:00
parent 2485648a54
commit 162545ddf0
4 changed files with 32 additions and 12 deletions

View File

@ -109,7 +109,7 @@ inline void RotatePoint( VECTOR2D& point, const VECTOR2D& aCenter, const EDA_ANG
*/
const VECTOR2I CalcArcCenter( const VECTOR2I& aStart, const VECTOR2I& aMid, const VECTOR2I& aEnd );
const VECTOR2D CalcArcCenter( const VECTOR2D& aStart, const VECTOR2D& aMid, const VECTOR2D& aEnd );
const VECTOR2I CalcArcCenter( const VECTOR2I& aStart, const VECTOR2I& aEnd,
const VECTOR2D CalcArcCenter( const VECTOR2D& aStart, const VECTOR2D& aEnd,
const EDA_ANGLE& aAngle );
/**

View File

@ -298,7 +298,7 @@ void RotatePoint( double* pX, double* pY, const EDA_ANGLE& aAngle )
}
const VECTOR2I CalcArcCenter( const VECTOR2I& aStart, const VECTOR2I& aEnd,
const VECTOR2D CalcArcCenter( const VECTOR2D& aStart, const VECTOR2D& aEnd,
const EDA_ANGLE& aAngle )
{
EDA_ANGLE angle( aAngle );
@ -317,14 +317,14 @@ const VECTOR2I CalcArcCenter( const VECTOR2I& aStart, const VECTOR2I& aEnd,
angle = ANGLE_360 - angle;
}
int chord = ( start - end ).EuclideanNorm();
int r = ( chord / 2 ) / ( angle / 2 ).Sin();
double chord = ( start - end ).EuclideanNorm();
double r = ( chord / 2.0 ) / ( angle / 2.0 ).Sin();
VECTOR2I vec = end - start;
VECTOR2D vec = end - start;
vec = vec.Resize( r );
RotatePoint( vec, -( ANGLE_180 - angle ) / 2 );
return VECTOR2I( start + vec );
return VECTOR2D( start + vec );
}

View File

@ -358,10 +358,10 @@ bool DIALOG_GRAPHIC_ITEM_PROPERTIES::TransferDataFromWindow()
if( m_item->GetShape() == SHAPE_T::ARC )
{
m_item->SetCenter( CalcArcCenter( m_item->GetStart(), m_item->GetEnd(),
m_angle.GetAngleValue() ) );
}
VECTOR2D center = CalcArcCenter( m_item->GetStart(), m_item->GetEnd(), m_angle.GetAngleValue() );
m_item->SetCenter( center );
}
if( m_fp_item )
{
// We are editing a footprint; init the item coordinates relative to the footprint anchor.
@ -429,10 +429,28 @@ bool DIALOG_GRAPHIC_ITEM_PROPERTIES::Validate()
error_msgs.Add( _( "The arc angle cannot be zero." ) );
if( m_startX.GetValue() == m_endX.GetValue() && m_startY.GetValue() == m_endY.GetValue() )
error_msgs.Add( _( "The radius cannot be zero." ) );
{
error_msgs.Add( wxString::Format( _( "Invalid Arc with radius %f and angle %f" ),
0.0, m_angle.GetDoubleValue() ) );
}
else
{
VECTOR2D start( m_startX.GetValue(), m_startY.GetValue() );
VECTOR2D end( m_endX.GetValue(), m_endY.GetValue() );
VECTOR2D center = CalcArcCenter( start, end, m_angle.GetAngleValue() );
double radius = ( center - start ).EuclideanNorm();
double max_offset = std::max( std::abs( center.x ) + radius,
std::abs( center.y ) + radius );
if( max_offset >= ( std::numeric_limits<VECTOR2I::coord_type>::max() / 2 )
|| center == start || center == end )
{
error_msgs.Add( wxString::Format( _( "Invalid Arc with radius %f and angle %f" ),
radius, m_angle.GetDoubleValue() ) );
}
}
break;
case SHAPE_T::CIRCLE:
// Check radius.
if( m_endX.GetValue() == 0 )

View File

@ -1984,7 +1984,9 @@ bool DRAWING_TOOL::drawArc( const std::string& aTool, PCB_SHAPE** aGraphic, bool
frame()->SetMsgPanel( graphic );
break;
}
else if( arcManager.GetStep() == KIGFX::PREVIEW::ARC_GEOM_MANAGER::SET_ANGLE )
// Don't show the edit panel if we can't represent the arc with it
else if( ( arcManager.GetStep() == KIGFX::PREVIEW::ARC_GEOM_MANAGER::SET_ANGLE )
&& ( arcManager.GetStartRadiusEnd() != arcManager.GetEndRadiusEnd() ) )
{
frame()->OnEditItemRequest( graphic );
m_view->Update( &preview );