Fix bugs in PCB arc editing.

This commit is contained in:
Alex 2022-11-11 14:59:09 +05:00
parent 46d4861187
commit 0b4fc8f50d
1 changed files with 38 additions and 77 deletions

View File

@ -945,65 +945,57 @@ void PCB_POINT_EDITOR::editArcEndpointKeepCenter( PCB_SHAPE* aArc, const VECTOR2
const VECTOR2I& aEnd, const VECTOR2I& aEnd,
const VECTOR2I& aCursor ) const const VECTOR2I& aCursor ) const
{ {
int minRadius = EDA_UNIT_UTILS::Mils2IU( pcbIUScale, 1 );
bool movingStart; bool movingStart;
VECTOR2I p1, p2; VECTOR2I p1, p2, prev_p1;
VECTOR2I target;
// p1 does not move, p2 does. // user is moving p1, we want to move p2 to the new radius.
if( aStart != aArc->GetStart() ) if( aStart != aArc->GetStart() )
{ {
p1 = aEnd; prev_p1 = aArc->GetStart();
p2 = aStart; p1 = aStart;
p2 = aEnd;
movingStart = true; movingStart = true;
} }
else else
{ {
p1 = aStart; prev_p1 = aArc->GetEnd();
p2 = aEnd; p1 = aEnd;
p2 = aStart;
movingStart = false; movingStart = false;
} }
target = p2 - aCenter;
double sqRadius = ( p1 - aCenter ).SquaredEuclideanNorm();
p1 = p1 - aCenter; p1 = p1 - aCenter;
p2 = p2 - aCenter; p2 = p2 - aCenter;
// Circle : x^2 + y^2 = R ^ 2 if( p1.x == 0 && p1.y == 0 )
// In this coordinate system, the angular position of the cursor is (r, theta) p1 = prev_p1 - aCenter;
// The line coming from the center of the circle is y = start.y / start.x * x
// The intersection fulfills : x^2 = R^2 / ( 1 + ( start.y / start.x ) ^ 2 )
if( target.x == 0 ) if( p2.x == 0 && p2.y == 0 )
{ p2 = { 1, 0 };
p2.x = 0;
p2.y = ( target.y > 0 ) ? sqrt( sqRadius ) : -sqrt( sqRadius );
}
else
{
double tan = target.y / static_cast<double>( target.x );
// The divider is always greater than 1 ( cannot be 0 ) double radius = p1.EuclideanNorm();
double tmp = sqrt( sqRadius / ( 1.0 + tan * tan ) );
// Move to the correct quadrant if( radius < minRadius )
tmp = target.x > 0 ? tmp : -tmp; radius = minRadius;
p2.y = target.y / static_cast<double>( target.x ) * tmp;
p2.x = tmp;
}
p1 = p1 + aCenter; p1 = aCenter + p1.Resize( radius );
p2 = p2 + aCenter; p2 = aCenter + p2.Resize( radius );
aArc->SetCenter( aCenter ); aArc->SetCenter( aCenter );
if( movingStart ) if( movingStart )
aArc->SetStart( aStart ); {
aArc->SetStart( p1 );
aArc->SetEnd( p2 );
}
else else
aArc->SetEnd( aEnd ); {
aArc->SetStart( p2 );
aArc->SetEnd( p1 );
}
} }
@ -1011,57 +1003,26 @@ void PCB_POINT_EDITOR::editArcMidKeepCenter( PCB_SHAPE* aArc, const VECTOR2I& aC
const VECTOR2I& aStart, const VECTOR2I& aMid, const VECTOR2I& aStart, const VECTOR2I& aMid,
const VECTOR2I& aEnd, const VECTOR2I& aCursor ) const const VECTOR2I& aEnd, const VECTOR2I& aCursor ) const
{ {
int minRadius = EDA_UNIT_UTILS::Mils2IU( pcbIUScale, 1 );
SEG chord( aStart, aEnd );
int newSide = chord.Side( aMid );
// Now, update the edit point position // Now, update the edit point position
// Express the point in a circle-centered coordinate system. // Express the point in a circle-centered coordinate system.
VECTOR2I start = aStart - aCenter; VECTOR2I start = aStart - aCenter;
VECTOR2I end = aEnd - aCenter; VECTOR2I end = aEnd - aCenter;
double sqRadius = ( aCursor - aCenter ).SquaredEuclideanNorm(); double radius = ( aCursor - aCenter ).EuclideanNorm();
// Special case, because the tangent would lead to +/- infinity if( radius < minRadius )
if( start.x == 0 ) radius = minRadius;
{
start.y = aCursor.y > 0 ? sqrt( sqRadius ) : -sqrt( sqRadius );
}
else
{
// Circle : x^2 + y^2 = R ^ 2
// In this coordinate system, the angular position of the cursor is (r, theta)
// The line coming from the center of the circle is y = start.y / start.x * x
// The intersection fulfills : x^2 = R^2 / ( 1 + ( start.y / start.x ) ^ 2 )
double tan = aStart.y / static_cast<double>( start.x ); start = start.Resize( radius );
double tmp = sqrt( sqRadius / ( 1.0 + tan * tan ) ); end = end.Resize( radius );
// Move to the correct quadrant
tmp = start.x > 0 ? tmp : -tmp;
start.y = start.y / static_cast<double>( start.x ) * tmp;
start.x = tmp;
}
// Special case, because the tangent would lead to +/- infinity
if( end.x == 0 )
{
end.y = aMid.y > 0 ? sqrt( sqRadius ) : -sqrt( sqRadius );
}
else
{
// Circle : x^2 + y^2 = R ^ 2
// In this coordinate system, the angular position of the cursor is (r, theta)
// The line coming from the center of the circle is y = start.y / start.x * x
// The intersection fulfills : x^2 = R^2 / ( 1 + ( start.y / start.x ) ^ 2 )
double tan = end.y / static_cast<double>( end.x );
double tmp = sqrt( sqRadius / ( 1.0 + tan * tan ) );
// Move to the correct quadrant
tmp = end.x > 0 ? tmp : -tmp;
end.y = end.y / static_cast<double>( end.x ) * tmp;
end.x = tmp;
}
start = start + aCenter; start = start + aCenter;
end = end + aCenter; end = end + aCenter;
aArc->SetStart( start ); aArc->SetStart( start );
aArc->SetEnd( end ); aArc->SetEnd( end );