Move EDA_ANGLE from int to double.

This commit is contained in:
Jeff Young 2022-01-17 20:49:48 +00:00
parent 010b705ecd
commit 8c246a761d
6 changed files with 123 additions and 258 deletions

View File

@ -868,7 +868,7 @@ int EDA_TEXT::Compare( const EDA_TEXT* aOther ) const
TEST_PT( m_attributes.m_Size, aOther->m_attributes.m_Size );
TEST_E( m_attributes.m_StrokeWidth, aOther->m_attributes.m_StrokeWidth );
TEST( m_attributes.m_Angle.AsTenthsOfADegree(), aOther->m_attributes.m_Angle.AsTenthsOfADegree() );
TEST( m_attributes.m_Angle.AsDegrees(), aOther->m_attributes.m_Angle.AsDegrees() );
TEST( m_attributes.m_LineSpacing, aOther->m_attributes.m_LineSpacing );
TEST( m_attributes.m_Halign, aOther->m_attributes.m_Halign );

View File

@ -62,7 +62,7 @@ size_t hash_fp_item( const EDA_ITEM* aItem, int aFlags )
hash_combine( ret, footprint->GetPosition().x, footprint->GetPosition().y );
if( aFlags & HASH_ROT )
hash_combine( ret, footprint->GetOrientation().AsTenthsOfADegree() );
hash_combine( ret, footprint->GetOrientation().AsDegrees() );
for( BOARD_ITEM* item : footprint->GraphicalItems() )
hash_combine( ret, hash_fp_item( item, aFlags ) );
@ -96,7 +96,7 @@ size_t hash_fp_item( const EDA_ITEM* aItem, int aFlags )
}
if( aFlags & HASH_ROT )
hash_combine( ret, pad->GetOrientation().AsTenthsOfADegree() );
hash_combine( ret, pad->GetOrientation().AsDegrees() );
if( aFlags & HASH_NET )
hash_combine( ret, pad->GetNetCode() );
@ -132,7 +132,7 @@ size_t hash_fp_item( const EDA_ITEM* aItem, int aFlags )
}
if( aFlags & HASH_ROT )
hash_combine( ret, text->GetTextAngle().AsTenthsOfADegree() );
hash_combine( ret, text->GetTextAngle().AsDegrees() );
}
break;

View File

@ -28,9 +28,9 @@
enum EDA_ANGLE_T
{
TENTHS_OF_A_DEGREE_T = 1,
DEGREES_T = 10,
RADIANS_T ///< enum value does not matter
TENTHS_OF_A_DEGREE_T,
DEGREES_T,
RADIANS_T
};
@ -44,88 +44,64 @@ public:
* Angle type must be explicitly specified at creation, because there is no other way of
* knowing what an int or a double represents.
*/
EDA_ANGLE( int aValue, EDA_ANGLE_T aAngleType ) :
m_value( 0 ),
m_radians( 0.0 ),
m_initial_type( aAngleType )
EDA_ANGLE( double aValue, EDA_ANGLE_T aAngleType )
{
switch( aAngleType )
{
case RADIANS_T:
m_radians = aValue;
m_value = KiROUND( aValue / TENTHS_OF_A_DEGREE_TO_RADIANS );
m_value = aValue / DEGREES_TO_RADIANS;
break;
case TENTHS_OF_A_DEGREE_T:
m_value = aValue * 10.0;
break;
default:
m_value = aValue * aAngleType;
m_value = aValue;
}
}
EDA_ANGLE( double aValue, EDA_ANGLE_T aAngleType ) :
m_value( 0 ),
m_radians( 0.0 ),
m_initial_type( aAngleType )
{
switch( aAngleType )
{
case RADIANS_T:
m_radians = aValue;
m_value = KiROUND( aValue / TENTHS_OF_A_DEGREE_TO_RADIANS );
break;
default:
m_value = int( aValue * aAngleType );
}
}
explicit EDA_ANGLE( const VECTOR2D& aVector ) :
m_value( 0 ),
m_radians( 0.0 ),
m_initial_type( TENTHS_OF_A_DEGREE_T )
explicit EDA_ANGLE( const VECTOR2D& aVector )
{
if( aVector.x == 0.0 && aVector.y == 0.0 )
{
m_value = 0;
m_value = 0.0;
}
else if( aVector.y == 0.0 )
{
if( aVector.x >= 0 )
m_value = 0;
m_value = 0.0;
else
m_value = -1800;
m_value = -180.0;
}
else if( aVector.x == 0.0 )
{
if( aVector.y >= 0.0 )
m_value = 900;
m_value = 90.0;
else
m_value = -900;
m_value = -90.0;
}
else if( aVector.x == aVector.y )
{
if( aVector.x >= 0.0 )
m_value = 450;
m_value = 45.0;
else
m_value = -1800 + 450;
m_value = -180.0 + 45.0;
}
else if( aVector.x == -aVector.y )
{
if( aVector.x >= 0.0 )
m_value = -450;
m_value = -45.0;
else
m_value = 1800 - 450;
m_value = 180.0 - 45.0;
}
else
{
m_value = KiROUND( atan2( (double) aVector.y, (double) aVector.x )
/ TENTHS_OF_A_DEGREE_TO_RADIANS );
*this = EDA_ANGLE( atan2( aVector.y, aVector.x ), RADIANS_T );
}
}
explicit EDA_ANGLE( const VECTOR2I& aVector ) :
m_value( 0 ),
m_radians( 0.0 ),
m_initial_type( TENTHS_OF_A_DEGREE_T )
explicit EDA_ANGLE( const VECTOR2I& aVector )
{
/* gcc is surprisingly smart in optimizing these conditions in a tree! */
@ -136,61 +112,46 @@ public:
else if( aVector.y == 0 )
{
if( aVector.x >= 0 )
m_value = 0;
m_value = 0.0;
else
m_value = -1800;
m_value = -180.0;
}
else if( aVector.x == 0 )
{
if( aVector.y >= 0 )
m_value = 900;
m_value = 90.0;
else
m_value = -900;
m_value = -90.0;
}
else if( aVector.x == aVector.y )
{
if( aVector.x >= 0 )
m_value = 450;
m_value = 45.0;
else
m_value = -1800 + 450;
m_value = -180.0 + 45.0;
}
else if( aVector.x == -aVector.y )
{
if( aVector.x >= 0 )
m_value = -450;
m_value = -45.0;
else
m_value = 1800 - 450;
m_value = 180.0 - 45.0;
}
else
{
m_value = KiROUND( atan2( (double) aVector.y, (double) aVector.x )
/ TENTHS_OF_A_DEGREE_TO_RADIANS );
*this = EDA_ANGLE( atan2( (double) aVector.y, (double) aVector.x ), RADIANS_T );
}
}
EDA_ANGLE() :
m_value( 0 ),
m_radians( 0.0 ),
m_initial_type( RADIANS_T )
m_value( 0.0 )
{}
inline double AsDegrees() const { return m_value / (double) DEGREES_T; }
inline double AsDegrees() const { return m_value; }
inline int AsTenthsOfADegree() const { return m_value; }
inline int AsTenthsOfADegree() const { return KiROUND( m_value * 10.0 ); }
inline double AsRadians() const
{
if( m_initial_type == RADIANS_T )
{
// if this was initialized with radians, return exact initial value
return m_radians;
}
else
{
// otherwise compute from value stored as 1/10ths of a degree
return m_value * TENTHS_OF_A_DEGREE_TO_RADIANS;
}
}
inline double AsRadians() const { return m_value * DEGREES_TO_RADIANS; }
inline double AsAngleType( EDA_ANGLE_T aAngleType ) const
{
@ -199,11 +160,11 @@ public:
case TENTHS_OF_A_DEGREE_T: return AsTenthsOfADegree();
case DEGREES_T: return AsDegrees();
case RADIANS_T: return AsRadians();
default: assert( 1 == 0 );
default: assert( false );
}
}
static constexpr double TENTHS_OF_A_DEGREE_TO_RADIANS = M_PI / 1800;
static constexpr double DEGREES_TO_RADIANS = M_PI / 180.0;
/**
* @return true if angle is one of the four cardinal directions (0/90/180/270 degrees),
@ -211,73 +172,66 @@ public:
*/
bool IsCardinal() const
{
return AsTenthsOfADegree() % 900 == 0;
double test = m_value;
while( test < 0.0 )
test += 90.0;
while( test > 90.0 )
test -= 90.0;
return test == 0.0;
}
bool IsZero() const
{
return AsTenthsOfADegree() == 0;
return m_value == 0.0;
}
bool IsHorizontal() const
{
return AsTenthsOfADegree() == 0 || AsTenthsOfADegree() == 1800;
return m_value == 0.0 || m_value == 180.0;
}
bool IsVertical() const
{
return AsTenthsOfADegree() == 900 || AsTenthsOfADegree() == 2700;
}
EDA_ANGLE Add( const EDA_ANGLE& aAngle ) const
{
EDA_ANGLE_T initialType = GetInitialAngleType();
// if both were given in radians, addition is exact
if( initialType == RADIANS_T
&& aAngle.GetInitialAngleType() == RADIANS_T )
{
//double newAngle = normalize( AsRadians() + aAngle.AsRadians(), RADIANS_T );
double newAngle = AsRadians() + aAngle.AsRadians();
return EDA_ANGLE( newAngle, RADIANS_T );
}
// if both were not given in radians, addition is done using 1/10ths of a degree, then
// converted to original angle type
int newAngle = AsTenthsOfADegree() + aAngle.AsTenthsOfADegree();
switch( initialType )
{
case DEGREES_T:
return EDA_ANGLE( newAngle / DEGREES_T, DEGREES_T );
case RADIANS_T:
return EDA_ANGLE( newAngle * TENTHS_OF_A_DEGREE_TO_RADIANS, RADIANS_T );
default:
case TENTHS_OF_A_DEGREE_T:
return EDA_ANGLE( newAngle, TENTHS_OF_A_DEGREE_T );
}
return m_value == 90.0 || m_value == 270.0;
}
EDA_ANGLE Invert() const
{
switch( GetInitialAngleType() )
{
case RADIANS_T:
return EDA_ANGLE( -m_radians, RADIANS_T );
default:
return EDA_ANGLE( -m_value / GetInitialAngleType(), GetInitialAngleType() );
}
return EDA_ANGLE( -AsDegrees(), DEGREES_T );
}
EDA_ANGLE Subtract( const EDA_ANGLE& aAngle ) const { return Add( aAngle.Invert() ); }
double Sin() const
{
EDA_ANGLE test = *this;
test.Normalize();
inline EDA_ANGLE_T GetInitialAngleType() const { return m_initial_type; }
if( test.m_value == 0.0 || test.m_value == 180.0 )
return 0.0;
else if( test.m_value == 90.0 )
return 1.0;
else if( test.m_value == 270.0 )
return -1.0;
else
return sin( AsRadians() );
}
double Sin() const { return sin( AsRadians() ); }
double Cos() const
{
EDA_ANGLE test = *this;
test.Normalize();
double Cos() const { return cos( AsRadians() ); }
if( test.m_value == 0.0 )
return 1.0;
else if( test.m_value == 180.0 )
return -1.0;
else if( test.m_value == 90.0 || test.m_value == 270.0 )
return 0.0;
else
return cos( AsRadians() );
}
double Tan() const { return tan( AsRadians() ); }
@ -294,43 +248,45 @@ public:
inline EDA_ANGLE Normalize()
{
normalize( false );
while( m_value < -0.0 )
m_value += 360.0;
while( m_value >= 360.0 )
m_value -= 360.0;
return *this;
}
inline EDA_ANGLE Normalize90()
{
int angle = AsTenthsOfADegree();
while( m_value < -90.0 )
m_value += 180.0;
while( angle < -900 )
angle += 1800;
while( angle > 900 )
angle -= 1800;
*this = EDA_ANGLE( angle, TENTHS_OF_A_DEGREE_T );
while( m_value > 90.0 )
m_value -= 180.0;
return *this;
}
inline EDA_ANGLE Normalize180()
{
int angle = AsTenthsOfADegree();
while( m_value <= -180.0 )
m_value += 360.0;
while( angle <= -1800 )
angle += 3600;
while( angle > 1800 )
angle -= 3600;
*this = EDA_ANGLE( angle, TENTHS_OF_A_DEGREE_T );
while( m_value > 180.0 )
m_value -= 360.0;
return *this;
}
inline EDA_ANGLE Normalize720()
{
normalize( true );
while( m_value < -360.0 )
m_value += 360.0;
while( m_value >= 360.0 )
m_value -= 360.0;
return *this;
}
@ -338,31 +294,18 @@ public:
EDA_ANGLE& operator+=( const EDA_ANGLE& aAngle )
{
*this = Add( aAngle );
*this = EDA_ANGLE( AsDegrees() + aAngle.AsDegrees(), DEGREES_T );
return *this;
}
EDA_ANGLE& operator-=( const EDA_ANGLE& aAngle )
{
EDA_ANGLE angle( aAngle );
*this = Add( angle.Invert() );
*this = EDA_ANGLE( AsDegrees() - aAngle.AsDegrees(), DEGREES_T );
return *this;
}
private:
void normalize( bool n720 = false );
int normalize( int aValue, EDA_ANGLE_T aAngleType, bool n720 = false ) const;
double normalize( double aValue, EDA_ANGLE_T aAngleType, bool n720 = false ) const;
private:
int m_value; ///< value is always stored in 1/10ths of a degree
double m_radians; ///< only used with as-radians constructor
EDA_ANGLE_T m_initial_type;
static constexpr int TENTHS_OF_A_DEGREE_FULL_CIRCLE = 3600;
static constexpr int DEGREES_FULL_CIRCLE = 360;
static constexpr double RADIANS_FULL_CIRCLE = 2 * M_PI;
double m_value; ///< value in degrees
public:
static EDA_ANGLE m_Angle0;
@ -383,70 +326,61 @@ inline EDA_ANGLE operator-( const EDA_ANGLE& aAngle )
inline EDA_ANGLE operator-( const EDA_ANGLE& aAngleA, const EDA_ANGLE& aAngleB )
{
return aAngleA.Add( aAngleB.Invert() );
return EDA_ANGLE( aAngleA.AsDegrees() - aAngleB.AsDegrees(), DEGREES_T );
}
inline EDA_ANGLE operator+( const EDA_ANGLE& aAngleA, const EDA_ANGLE& aAngleB )
{
return aAngleA.Add( aAngleB );
return EDA_ANGLE( aAngleA.AsDegrees() + aAngleB.AsDegrees(), DEGREES_T );
}
inline EDA_ANGLE operator*( const EDA_ANGLE& aAngleA, double aOperator )
{
switch( aAngleA.GetInitialAngleType() )
{
case RADIANS_T:
return EDA_ANGLE( aAngleA.AsRadians() * aOperator, RADIANS_T );
default:
return EDA_ANGLE( aAngleA.AsDegrees() * aOperator, DEGREES_T );
}
return EDA_ANGLE( aAngleA.AsDegrees() * aOperator, DEGREES_T );
}
inline EDA_ANGLE operator/( const EDA_ANGLE& aAngleA, double aOperator )
{
switch( aAngleA.GetInitialAngleType() )
{
case RADIANS_T:
return EDA_ANGLE( aAngleA.AsRadians() / aOperator, RADIANS_T );
default:
return EDA_ANGLE( aAngleA.AsDegrees() / aOperator, DEGREES_T );
}
return EDA_ANGLE( aAngleA.AsDegrees() / aOperator, DEGREES_T );
}
inline bool operator==( const EDA_ANGLE& aAngleA, const EDA_ANGLE& aAngleB )
{
return aAngleA.AsTenthsOfADegree() == aAngleB.AsTenthsOfADegree();
return aAngleA.AsDegrees() == aAngleB.AsDegrees();
}
inline bool operator!=( const EDA_ANGLE& aAngleA, const EDA_ANGLE& aAngleB )
{
return aAngleA.AsTenthsOfADegree() != aAngleB.AsTenthsOfADegree();
return aAngleA.AsDegrees() != aAngleB.AsDegrees();
}
inline bool operator>( const EDA_ANGLE& aAngleA, const EDA_ANGLE& aAngleB )
{
return aAngleA.AsTenthsOfADegree() > aAngleB.AsTenthsOfADegree();
return aAngleA.AsDegrees() > aAngleB.AsDegrees();
}
inline bool operator<( const EDA_ANGLE& aAngleA, const EDA_ANGLE& aAngleB )
{
return aAngleA.AsTenthsOfADegree() < aAngleB.AsTenthsOfADegree();
return aAngleA.AsDegrees() < aAngleB.AsDegrees();
}
inline bool operator<=( const EDA_ANGLE& aAngleA, const EDA_ANGLE& aAngleB )
{
return aAngleA.AsTenthsOfADegree() <= aAngleB.AsTenthsOfADegree();
return aAngleA.AsDegrees() <= aAngleB.AsDegrees();
}
inline bool operator>=( const EDA_ANGLE& aAngleA, const EDA_ANGLE& aAngleB )
{
return aAngleA.AsTenthsOfADegree() >= aAngleB.AsTenthsOfADegree();
return aAngleA.AsDegrees() >= aAngleB.AsDegrees();
}

View File

@ -550,7 +550,7 @@ void TransformArcToPolygon( SHAPE_POLY_SET& aCornerBuffer, const VECTOR2I& aStar
// and arc inner to polyline and merge shapes.
int radial_offset = ( aWidth + 1 ) / 2;
SHAPE_POLY_SET polyshape;
SHAPE_POLY_SET polyshape;
std::vector<VECTOR2I> outside_pts;
/// We start by making rounded ends on the arc
@ -626,7 +626,7 @@ void TransformArcToPolygon( SHAPE_POLY_SET& aCornerBuffer, const VECTOR2I& aStar
if( arc_angle_end != ANGLE_0 && arc_angle_end != ANGLE_180 )
polyshape.Outline(0).Rotate( arc_angle_end.AsRadians(), arcSpine.GetPoint( 0 ) );
arc_angle_end_deg = arc.GetEndAngle();
arc_angle_end = arc.GetEndAngle();
if( arc_angle_end != ANGLE_0 && arc_angle_end != ANGLE_180 )
polyshape.Outline(1).Rotate( arc_angle_end.AsRadians(), arcSpine.GetPoint( -1 ) );

View File

@ -47,72 +47,3 @@ EDA_ANGLE EDA_ANGLE::KeepUpright() const
}
void EDA_ANGLE::normalize( bool n720 )
{
if( GetInitialAngleType() == RADIANS_T )
{
m_radians = normalize( m_radians, RADIANS_T, n720 );
m_value = int( m_radians / TENTHS_OF_A_DEGREE_TO_RADIANS );
}
else
{
m_value = normalize( m_value, TENTHS_OF_A_DEGREE_T, n720 );
}
}
int EDA_ANGLE::normalize( int aValue, EDA_ANGLE_T aAngleType, bool n720 ) const
{
int full_circle_upper = DEGREES_FULL_CIRCLE;
switch( aAngleType )
{
case DEGREES_T:
full_circle_upper = DEGREES_FULL_CIRCLE;
break;
case TENTHS_OF_A_DEGREE_T:
full_circle_upper = TENTHS_OF_A_DEGREE_FULL_CIRCLE;
break;
case RADIANS_T:
wxFAIL_MSG( "should be unreachable..." );
}
/*
* if n720 == false, clamp between 0..full_circle_upper
* if n720 == true, clamp between +/- full_circle_upper
*/
int full_circle_lower = n720 ? -full_circle_upper : 0;
while( aValue < full_circle_lower )
aValue += full_circle_upper;
while( aValue >= full_circle_upper )
aValue -= full_circle_upper;
return aValue;
}
double EDA_ANGLE::normalize( double aValue, EDA_ANGLE_T aAngleType, bool n720 ) const
{
double full_circle_upper = DEGREES_FULL_CIRCLE;
switch( aAngleType )
{
case DEGREES_T: full_circle_upper = DEGREES_FULL_CIRCLE; break;
case TENTHS_OF_A_DEGREE_T: full_circle_upper = TENTHS_OF_A_DEGREE_FULL_CIRCLE; break;
case RADIANS_T: full_circle_upper = RADIANS_FULL_CIRCLE; break;
}
double full_circle_lower = n720 ? 0 : -full_circle_upper;
while( aValue < full_circle_lower )
aValue += full_circle_upper;
while( aValue >= full_circle_upper )
aValue -= full_circle_upper;
return aValue;
}

View File

@ -95,7 +95,7 @@ bool primitivesNeedUpdate( const std::shared_ptr<PCB_SHAPE>& a,
TEST( a->GetStart(), b->GetStart() );
TEST( a->GetEnd(), b->GetEnd() );
TEST( a->GetCenter(), b->GetCenter() );
TEST( a->GetArcAngle().AsTenthsOfADegree(), b->GetArcAngle().AsTenthsOfADegree() );
TEST( a->GetArcAngle().AsDegrees(), b->GetArcAngle().AsDegrees() );
break;
case SHAPE_T::BEZIER:
@ -147,8 +147,8 @@ bool padsNeedUpdate( const PAD* a, const PAD* b )
TEST( a->GetProperty(), b->GetProperty() );
// The pad orientation, for historical reasons is the pad rotation + parent rotation.
TEST( ( a->GetOrientation() - a->GetParent()->GetOrientation() ).Normalize().AsTenthsOfADegree(),
( b->GetOrientation() - b->GetParent()->GetOrientation() ).Normalize().AsTenthsOfADegree() );
TEST( ( a->GetOrientation() - a->GetParent()->GetOrientation() ).Normalize().AsDegrees(),
( b->GetOrientation() - b->GetParent()->GetOrientation() ).Normalize().AsDegrees() );
TEST( a->GetSize(), b->GetSize() );
TEST( a->GetDelta(), b->GetDelta() );
@ -169,7 +169,7 @@ bool padsNeedUpdate( const PAD* a, const PAD* b )
TEST( a->GetZoneConnection(), b->GetZoneConnection() );
TEST( a->GetThermalGap(), b->GetThermalGap() );
TEST( a->GetThermalSpokeWidth(), b->GetThermalSpokeWidth() );
TEST( a->GetThermalSpokeAngle().AsTenthsOfADegree(), b->GetThermalSpokeAngle().AsTenthsOfADegree() );
TEST( a->GetThermalSpokeAngle().AsDegrees(), b->GetThermalSpokeAngle().AsDegrees() );
TEST( a->GetCustomShapeInZoneOpt(), b->GetCustomShapeInZoneOpt() );
TEST( a->GetPrimitives().size(), b->GetPrimitives().size() );
@ -198,7 +198,7 @@ bool shapesNeedUpdate( const FP_SHAPE* a, const FP_SHAPE* b )
TEST( a->GetStart0(), b->GetStart0() );
TEST( a->GetEnd0(), b->GetEnd0() );
TEST( a->GetCenter0(), b->GetCenter0() );
TEST( a->GetArcAngle().AsTenthsOfADegree(), b->GetArcAngle().AsTenthsOfADegree() );
TEST( a->GetArcAngle().AsDegrees(), b->GetArcAngle().AsDegrees() );
break;
case SHAPE_T::BEZIER: