7
mirror of https://gitlab.com/kicad/code/kicad.git synced 2025-04-11 10:00:13 +00:00

More EDA_ANGLE.

This commit is contained in:
Jeff Young 2022-01-14 15:34:41 +00:00
parent 1b19ff5f42
commit 07013d00e1
55 changed files with 424 additions and 410 deletions

View File

@ -289,7 +289,7 @@ unsigned int BOARD_ADAPTER::GetCircleSegmentCount( int aDiameterBIU ) const
{
wxASSERT( aDiameterBIU > 0 );
return GetArcToSegmentCount( aDiameterBIU / 2, ARC_HIGH_DEF, 360.0 );
return GetArcToSegmentCount( aDiameterBIU / 2, ARC_HIGH_DEF, FULL_CIRCLE );
}

View File

@ -242,11 +242,11 @@ void BOARD_ADAPTER::createTrack( const PCB_TRACK* aTrack, CONTAINER_2D_BASE* aDs
{
const PCB_ARC* arc = static_cast<const PCB_ARC*>( aTrack );
VECTOR2D center( arc->GetCenter() );
double arc_angle = arc->GetAngle();
double radius = arc->GetRadius();
int arcsegcount = GetArcToSegmentCount( radius, ARC_HIGH_DEF, arc_angle / 10 );
int circlesegcount;
VECTOR2D center( arc->GetCenter() );
EDA_ANGLE arc_angle = arc->GetAngle();
double radius = arc->GetRadius();
int arcsegcount = GetArcToSegmentCount( radius, ARC_HIGH_DEF, arc_angle );
int circlesegcount;
// We need a circle to segment count. However, the arc angle can be small, and the
// radius very big. so we calculate a reasonable value for circlesegcount.
@ -256,12 +256,13 @@ void BOARD_ADAPTER::createTrack( const PCB_TRACK* aTrack, CONTAINER_2D_BASE* aDs
}
else
{
circlesegcount = KiROUND( arcsegcount * 3600 / std::abs( arc_angle ) );
circlesegcount = KiROUND( arcsegcount * 360.0 / std::abs( arc_angle.AsDegrees() ) );
circlesegcount = std::max( 1, std::min( circlesegcount, 128 ) );
}
transformArcToSegments( VECTOR2I( center.x, center.y ), arc->GetStart(), arc_angle,
circlesegcount, arc->GetWidth(), aDstContainer, *arc );
transformArcToSegments( VECTOR2I( center.x, center.y ), arc->GetStart(),
arc_angle.AsTenthsOfADegree(), circlesegcount, arc->GetWidth(),
aDstContainer, *arc );
break;
}
@ -658,8 +659,9 @@ void BOARD_ADAPTER::addShape( const PCB_SHAPE* aShape, CONTAINER_2D_BASE* aDstCo
{
unsigned int segCount = GetCircleSegmentCount( aShape->GetBoundingBox().GetSizeMax() );
transformArcToSegments( aShape->GetCenter(), aShape->GetStart(), aShape->GetArcAngle(),
segCount, linewidth, aDstContainer, *aShape );
transformArcToSegments( aShape->GetCenter(), aShape->GetStart(),
aShape->GetArcAngle().AsTenthsOfADegree(), segCount, linewidth,
aDstContainer, *aShape );
}
break;

View File

@ -451,12 +451,12 @@ std::string FormatInternalUnits( int aValue )
}
std::string FormatAngle( double aAngle )
std::string FormatAngle( const EDA_ANGLE& aAngle )
{
char temp[50];
int len;
len = snprintf( temp, sizeof(temp), "%.10g", aAngle / 10.0 );
len = snprintf( temp, sizeof(temp), "%.10g", aAngle.AsDegrees() );
return std::string( temp, len );
}

View File

@ -76,19 +76,19 @@ int EDA_ANGLE::normalize( int aValue, EDA_ANGLE_T aAngleType, bool n720 ) const
break;
case RADIANS_T:
/* ?? should not get here */
assert( 1 == 0 );
wxFAIL_MSG( "should be unreachable..." );
}
/* if n720 == false, clamp between 0..full_circle_upper
* if n720 == true, clamp between +/- full_circle_upper
*/
/*
* if n720 == false, clamp between 0..full_circle_upper
* if n720 == true, clamp between +/- full_circle_upper
*/
int full_circle_lower = n720 ? 0 : -full_circle_upper;
while( aValue < full_circle_lower )
aValue += full_circle_upper;
while( aValue > full_circle_upper )
while( aValue >= full_circle_upper )
aValue -= full_circle_upper;
return aValue;
@ -101,9 +101,9 @@ double EDA_ANGLE::normalize( double aValue, EDA_ANGLE_T aAngleType, bool n720 )
switch( aAngleType )
{
case DEGREES_T: full_circle_upper = DEGREES_FULL_CIRCLE; break;
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;
case RADIANS_T: full_circle_upper = RADIANS_FULL_CIRCLE; break;
}
double full_circle_lower = n720 ? 0 : -full_circle_upper;
@ -111,7 +111,7 @@ double EDA_ANGLE::normalize( double aValue, EDA_ANGLE_T aAngleType, bool n720 )
while( aValue < full_circle_lower )
aValue += full_circle_upper;
while( aValue > full_circle_upper )
while( aValue >= full_circle_upper )
aValue -= full_circle_upper;
return aValue;

View File

@ -126,7 +126,7 @@ double EDA_SHAPE::GetLength() const
return length;
case SHAPE_T::ARC:
return 2 * M_PI * GetRadius() * ( GetArcAngle() / 3600.0 );
return GetRadius() * GetArcAngle().AsRadians();
default:
UNIMPLEMENTED_FOR( SHAPE_T_asString() );
@ -512,14 +512,14 @@ void EDA_SHAPE::SetArcGeometry( const VECTOR2I& aStart, const VECTOR2I& aMid, co
}
double EDA_SHAPE::GetArcAngle() const
EDA_ANGLE EDA_SHAPE::GetArcAngle() const
{
double startAngle;
double endAngle;
CalcArcAngles( startAngle, endAngle );
return ( endAngle - startAngle ) * 10;
return EDA_ANGLE( endAngle - startAngle, DEGREES_T );
}
@ -556,7 +556,7 @@ void EDA_SHAPE::ShapeGetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PA
case SHAPE_T::ARC:
aList.emplace_back( shape, _( "Arc" ) );
msg.Printf( wxT( "%.1f" ), GetArcAngle() / 10.0 );
msg.Printf( wxT( "%.1f" ), GetArcAngle().AsDegrees() );
aList.emplace_back( _( "Angle" ), msg );
msg = MessageTextFromValue( units, GetRadius() );
@ -1078,7 +1078,7 @@ std::vector<SHAPE*> EDA_SHAPE::MakeEffectiveShapes( bool aEdgeOnly ) const
switch( m_shape )
{
case SHAPE_T::ARC:
effectiveShapes.emplace_back( new SHAPE_ARC( m_arcCenter, m_start, GetArcAngle() / 10.0,
effectiveShapes.emplace_back( new SHAPE_ARC( m_arcCenter, m_start, GetArcAngle(),
GetWidth() ) );
break;
@ -1109,7 +1109,7 @@ std::vector<SHAPE*> EDA_SHAPE::MakeEffectiveShapes( bool aEdgeOnly ) const
effectiveShapes.emplace_back( new SHAPE_CIRCLE( getCenter(), GetRadius() ) );
if( GetWidth() > 0 || !IsFilled() || aEdgeOnly )
effectiveShapes.emplace_back( new SHAPE_ARC( getCenter(), GetEnd(), 360.0 ) );
effectiveShapes.emplace_back( new SHAPE_ARC( getCenter(), GetEnd(), ANGLE_360 ) );
break;
}
@ -1344,12 +1344,11 @@ void EDA_SHAPE::calcEdit( const VECTOR2I& aPosition )
case 1:
{
// Keep center clockwise from chord while drawing
VECTOR2I chordVector = m_end - m_start;
double chordAngle = ArcTangente( chordVector.y, chordVector.x );
NORMALIZE_ANGLE_POS( chordAngle );
VECTOR2I chordVector = m_end - m_start;
EDA_ANGLE chordAngle( chordVector );
VECTOR2I c1Test = c1;
RotatePoint( c1Test, m_start, -chordAngle );
RotatePoint( c1Test, m_start, -chordAngle.Normalize() );
m_arcCenter = c1Test.x > 0 ? c2 : c1;
}
@ -1365,7 +1364,7 @@ void EDA_SHAPE::calcEdit( const VECTOR2I& aPosition )
// Pick the one closer to the mouse position
m_arcCenter = GetLineLength( c1, aPosition ) < GetLineLength( c2, aPosition ) ? c1 : c2;
if( GetArcAngle() > 1800 )
if( GetArcAngle() > ANGLE_180 )
std::swap( m_start, m_end );
break;

View File

@ -889,7 +889,7 @@ void OPENGL_GAL::DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadius,
SWAP( aStartAngle, >, aEndAngle );
// Calculate the seg count to approximate the arc with aMaxError or less
int segCount360 = GetArcToSegmentCount( aRadius, aMaxError, 360.0 );
int segCount360 = GetArcToSegmentCount( aRadius, aMaxError, FULL_CIRCLE );
segCount360 = std::max( SEG_PER_CIRCLE_COUNT, segCount360 );
double alphaIncrement = 2.0 * M_PI / segCount360;

View File

@ -252,7 +252,10 @@ void GRCSegm( EDA_RECT* ClipBox, wxDC* DC, int x1, int y1, int x2, int y2, int w
int radius = ( width + 1 ) >> 1;
int dx = x2 - x1;
int dy = y2 - y1;
double angle = -ArcTangente( dy, dx );
EDA_ANGLE angle( VECTOR2I( dx, dy ) );
angle = -angle;
VECTOR2I start;
VECTOR2I end;
VECTOR2I org( x1, y1 );

View File

@ -462,21 +462,14 @@ void PLOTTER::Marker( const VECTOR2I& position, int diametre, unsigned aShapeId
void PLOTTER::segmentAsOval( const VECTOR2I& start, const VECTOR2I& end, int width,
OUTLINE_MODE tracemode )
{
VECTOR2I center( ( start.x + end.x ) / 2, ( start.y + end.y ) / 2 );
VECTOR2I size( end.x - start.x, end.y - start.y );
double orient;
if( size.y == 0 )
orient = 0;
else if( size.x == 0 )
orient = 900;
else
orient = -ArcTangente( size.y, size.x );
VECTOR2I center( ( start.x + end.x ) / 2, ( start.y + end.y ) / 2 );
VECTOR2I size( end.x - start.x, end.y - start.y );
EDA_ANGLE orient( size );
size.x = KiROUND( EuclideanNorm( size ) ) + width;
size.y = width;
FlashPadOval( center, size, orient, tracemode, nullptr );
FlashPadOval( center, size, orient.AsTenthsOfADegree(), tracemode, nullptr );
}

View File

@ -1092,11 +1092,8 @@ void CADSTAR_SCH_ARCHIVE_LOADER::loadNets()
{
secondPt = false;
VECTOR2I kiLast = last;
VECTOR2I kiCurrent = pt;
double wireangleDeciDeg = getPolarAngle( kiLast - kiCurrent );
fixNetLabelsAndSheetPins( wireangleDeciDeg, conn.StartNode );
EDA_ANGLE wireAngle( last - pt );
fixNetLabelsAndSheetPins( wireAngle.AsTenthsOfADegree(), conn.StartNode );
}
wire = new SCH_LINE();
@ -1116,10 +1113,8 @@ void CADSTAR_SCH_ARCHIVE_LOADER::loadNets()
//Fix labels on the end wire
if( wire )
{
VECTOR2I kiLast = wire->GetEndPoint();
VECTOR2I kiCurrent = wire->GetStartPoint();
double wireangleDeciDeg = getPolarAngle( kiLast - kiCurrent );
fixNetLabelsAndSheetPins( wireangleDeciDeg, conn.EndNode );
EDA_ANGLE wireAngle( wire->GetEndPoint() - wire->GetStartPoint() );
fixNetLabelsAndSheetPins( wireAngle.AsTenthsOfADegree(), conn.EndNode );
}
}
@ -2059,18 +2054,18 @@ void CADSTAR_SCH_ARCHIVE_LOADER::loadShapeVertices(
case VERTEX_TYPE::ANTICLOCKWISE_SEMICIRCLE:
case VERTEX_TYPE::ANTICLOCKWISE_ARC:
{
double arcStartAngle = getPolarAngle( startPoint - centerPoint );
double arcEndAngle = getPolarAngle( endPoint - centerPoint );
double arcAngleDeciDeg = arcEndAngle - arcStartAngle;
EDA_ANGLE arcStartAngle( startPoint - centerPoint );
EDA_ANGLE arcEndAngle( endPoint - centerPoint );
EDA_ANGLE arcAngle = arcEndAngle - arcStartAngle;
if( cw )
arcAngleDeciDeg = NormalizeAnglePos( arcAngleDeciDeg );
arcAngle = arcAngle.Normalize();
else
arcAngleDeciDeg = NormalizeAngleNeg( arcAngleDeciDeg );
arcAngle = -arcAngle.Normalize();
// JEY TODO: Load as arc...
// TODO: Load as arc...
SHAPE_ARC tempArc( centerPoint, startPoint, arcAngleDeciDeg / 10.0 );
SHAPE_ARC tempArc( centerPoint, startPoint, arcAngle );
SHAPE_LINE_CHAIN arcSegments = tempArc.ConvertToPolyline( Millimeter2iu( 0.1 ) );
// Load the arc as a series of piece-wise segments
@ -3058,12 +3053,6 @@ VECTOR2I CADSTAR_SCH_ARCHIVE_LOADER::applyTransform(
}
double CADSTAR_SCH_ARCHIVE_LOADER::getPolarAngle( const VECTOR2I& aPoint )
{
return NormalizeAnglePos( ArcTangente( aPoint.y, aPoint.x ) );
}
double CADSTAR_SCH_ARCHIVE_LOADER::getPolarRadius( const VECTOR2I& aPoint )
{
return sqrt( ( (double) aPoint.x * (double) aPoint.x )

View File

@ -289,13 +289,6 @@ private:
* aAngleTenthDegree );
}
/**
* @brief
* @param aPoint
* @return Angle in decidegrees of the polar representation of the point, scaled 0..360
*/
double getPolarAngle( const VECTOR2I& aPoint );
/**
* @brief
* @param aPoint

View File

@ -191,15 +191,15 @@ static const char* getPinShapeToken( GRAPHIC_PINSHAPE aShape )
}
static float getPinAngle( int aOrientation )
static EDA_ANGLE getPinAngle( int aOrientation )
{
switch( aOrientation )
{
case PIN_RIGHT: return 0.0;
case PIN_LEFT: return 180.0;
case PIN_UP: return 90.0;
case PIN_DOWN: return 270.0;
default: wxFAIL_MSG( "Missing symbol library pin orientation type" ); return 0.0;
case PIN_RIGHT: return ANGLE_0;
case PIN_LEFT: return ANGLE_180;
case PIN_UP: return ANGLE_90;
case PIN_DOWN: return ANGLE_270;
default: wxFAIL_MSG( "Missing symbol library pin orientation type" ); return ANGLE_0;
}
}
@ -222,21 +222,17 @@ static const char* getSheetPinShapeToken( LABEL_FLAG_SHAPE aShape )
}
static double getSheetPinAngle( SHEET_SIDE aSide )
static EDA_ANGLE getSheetPinAngle( SHEET_SIDE aSide )
{
double retv;
switch( aSide )
{
case SHEET_SIDE::UNDEFINED:
case SHEET_SIDE::LEFT: retv = 180.0; break;
case SHEET_SIDE::RIGHT: retv = 0.0; break;
case SHEET_SIDE::TOP: retv = 90.0; break;
case SHEET_SIDE::BOTTOM: retv = 270.0; break;
default: wxFAIL; retv = 0.0; break;
case SHEET_SIDE::LEFT: return ANGLE_180;
case SHEET_SIDE::RIGHT: return ANGLE_0;
case SHEET_SIDE::TOP: return ANGLE_90;
case SHEET_SIDE::BOTTOM: return ANGLE_270;
default: wxFAIL; return ANGLE_0;
}
return retv;
}
@ -1038,17 +1034,17 @@ void SCH_SEXPR_PLUGIN::saveSymbol( SCH_SYMBOL* aSymbol, SCH_SHEET_PATH* aSheetPa
libName = "_NONAME_";
}
double angle;
int orientation = aSymbol->GetOrientation() & ~( SYM_MIRROR_X | SYM_MIRROR_Y );
EDA_ANGLE angle;
int orientation = aSymbol->GetOrientation() & ~( SYM_MIRROR_X | SYM_MIRROR_Y );
if( orientation == SYM_ORIENT_90 )
angle = 90.0;
angle = ANGLE_90;
else if( orientation == SYM_ORIENT_180 )
angle = 180.0;
angle = ANGLE_180;
else if( orientation == SYM_ORIENT_270 )
angle = 270.0;
angle = ANGLE_270;
else
angle = 0.0;
angle = ANGLE_0;
m_out->Print( aNestLevel, "(symbol" );
@ -1062,7 +1058,7 @@ void SCH_SEXPR_PLUGIN::saveSymbol( SCH_SYMBOL* aSymbol, SCH_SHEET_PATH* aSheetPa
m_out->Quotew( aSymbol->GetLibId().Format().wx_str() ).c_str(),
FormatInternalUnits( aSymbol->GetPosition().x ).c_str(),
FormatInternalUnits( aSymbol->GetPosition().y ).c_str(),
FormatAngle( angle * 10.0 ).c_str() );
FormatAngle( angle ).c_str() );
bool mirrorX = aSymbol->GetOrientation() & SYM_MIRROR_X;
bool mirrorY = aSymbol->GetOrientation() & SYM_MIRROR_Y;
@ -1157,7 +1153,7 @@ void SCH_SEXPR_PLUGIN::saveField( SCH_FIELD* aField, int aNestLevel )
aField->GetId(),
FormatInternalUnits( aField->GetPosition().x ).c_str(),
FormatInternalUnits( aField->GetPosition().y ).c_str(),
FormatAngle( aField->GetTextAngle().AsTenthsOfADegree() ).c_str() );
FormatAngle( aField->GetTextAngle() ).c_str() );
if( !aField->IsDefaultFormatting()
|| ( aField->GetTextHeight() != Mils2iu( DEFAULT_SIZE_TEXT ) ) )
@ -1266,7 +1262,7 @@ void SCH_SEXPR_PLUGIN::saveSheet( SCH_SHEET* aSheet, int aNestLevel )
getSheetPinShapeToken( pin->GetShape() ),
FormatInternalUnits( pin->GetPosition().x ).c_str(),
FormatInternalUnits( pin->GetPosition().y ).c_str(),
FormatAngle( getSheetPinAngle( pin->GetSide() ) * 10.0 ).c_str() );
FormatAngle( getSheetPinAngle( pin->GetSide() ) ).c_str() );
pin->Format( m_out, aNestLevel + 1, 0 );
@ -1445,7 +1441,7 @@ void SCH_SEXPR_PLUGIN::saveText( SCH_TEXT* aText, int aNestLevel )
m_out->Print( 0, " (at %s %s %s)",
FormatInternalUnits( aText->GetPosition().x ).c_str(),
FormatInternalUnits( aText->GetPosition().y ).c_str(),
FormatAngle( aText->GetTextAngle().AsTenthsOfADegree() ).c_str() );
FormatAngle( aText->GetTextAngle() ).c_str() );
}
else
{
@ -1453,7 +1449,7 @@ void SCH_SEXPR_PLUGIN::saveText( SCH_TEXT* aText, int aNestLevel )
m_out->Print( aNestLevel + 1, "(at %s %s %s)",
FormatInternalUnits( aText->GetPosition().x ).c_str(),
FormatInternalUnits( aText->GetPosition().y ).c_str(),
FormatAngle( aText->GetTextAngle().AsTenthsOfADegree() ).c_str() );
FormatAngle( aText->GetTextAngle() ).c_str() );
}
if( aText->GetFieldsAutoplaced() != FIELDS_AUTOPLACED_NO )
@ -2058,7 +2054,7 @@ void SCH_SEXPR_PLUGIN_CACHE::savePin( LIB_PIN* aPin, OUTPUTFORMATTER& aFormatter
getPinShapeToken( aPin->GetShape() ),
FormatInternalUnits( aPin->GetPosition().x ).c_str(),
FormatInternalUnits( aPin->GetPosition().y ).c_str(),
FormatAngle( getPinAngle( aPin->GetOrientation() ) * 10.0 ).c_str(),
FormatAngle( getPinAngle( aPin->GetOrientation() ) ).c_str(),
FormatInternalUnits( aPin->GetLength() ).c_str() );
if( !aPin->IsVisible() )

View File

@ -275,19 +275,18 @@ const EDA_RECT GERBER_DRAW_ITEM::GetBoundingBox() const
case GBR_ARC:
{
double arc_angle =
atan2( double( m_End.y - m_ArcCentre.y ), double( m_End.x - m_ArcCentre.x ) )
- atan2( double( m_Start.y - m_ArcCentre.y ), double( m_Start.x - m_ArcCentre.x ) );
arc_angle *= 180.0 / M_PI;
if( arc_angle < 0.0 )
arc_angle += 360.0;
EDA_ANGLE angle( atan2( double( m_End.y - m_ArcCentre.y ),
double( m_End.x - m_ArcCentre.x ) )
- atan2( double( m_Start.y - m_ArcCentre.y ),
double( m_Start.x - m_ArcCentre.x ) ),
RADIANS_T );
if( m_End == m_Start ) // Arc with the end point = start point is expected to be a circle.
arc_angle = 360.0;
angle = ANGLE_360;
else
angle.Normalize();
SHAPE_ARC arc( m_ArcCentre, m_Start, arc_angle );
SHAPE_ARC arc( m_ArcCentre, m_Start, angle );
BOX2I arc_bbox = arc.BBox( m_Size.x / 2 ); // m_Size.x is the line thickness
bbox.SetOrigin( arc_bbox.GetX(), arc_bbox.GetY() );
bbox.SetWidth( arc_bbox.GetWidth() );

View File

@ -35,6 +35,7 @@
#include <string>
#include <eda_units.h>
#include <eda_angle.h>
#include <convert_to_biu.h>
#include <math/vector2d.h>
@ -194,7 +195,7 @@ std::string FormatInternalUnits( int aValue );
* @param aAngle A angle value to convert.
* @return A std::string object containing the converted angle.
*/
std::string FormatAngle( double aAngle );
std::string FormatAngle( const EDA_ANGLE& aAngle );
std::string FormatInternalUnits( const wxPoint& aPoint );

View File

@ -23,6 +23,7 @@
#include <cassert>
#include <cmath>
#include <math/vector2d.h> // for VECTOR2I
enum EDA_ANGLE_T
@ -36,11 +37,13 @@ enum EDA_ANGLE_T
class EDA_ANGLE
{
public:
// Angles can be created in degrees, 1/10ths of a degree, and radians,
// and read as any of the angle types
//
// Angle type must be explicitly specified at creation, because
// there is no other way of knowing what an int or a double represents
/**
* Angles can be created in degrees, 1/10ths of a degree, or radians, and read as any of
* the angle types.
*
* 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 ),
@ -75,6 +78,52 @@ public:
}
}
explicit EDA_ANGLE( const VECTOR2I& aVector ) :
m_value( 0 ),
m_radians( 0.0 ),
m_initial_type( TENTHS_OF_A_DEGREE_T )
{
/* gcc is surprisingly smart in optimizing these conditions in a tree! */
if( aVector.x == 0 && aVector.y == 0 )
{
m_value = 0;
}
else if( aVector.y == 0 )
{
if( aVector.x >= 0 )
m_value = 0;
else
m_value = -1800;
}
else if( aVector.x == 0 )
{
if( aVector.y >= 0 )
m_value = 900;
else
m_value = -900;
}
else if( aVector.x == aVector.y )
{
if( aVector.x >= 0 )
m_value = 450;
else
m_value = -1800 + 450;
}
else if( aVector.x == -aVector.y )
{
if( aVector.x >= 0 )
m_value = -450;
else
m_value = 1800 - 450;
}
else
{
m_value = atan2( (double) aVector.y, (double) aVector.x )
/ TENTHS_OF_A_DEGREE_TO_RADIANS;
}
}
EDA_ANGLE() :
m_value( 0 ),
m_radians( 0.0 ),
@ -149,11 +198,8 @@ public:
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
// of this angle
//int newAngle = normalize( AsTenthsOfADegree() + aAngle.AsTenthsOfADegree(),
//TENTHS_OF_A_DEGREE_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 )
@ -288,6 +334,30 @@ inline EDA_ANGLE operator+( const EDA_ANGLE& aAngleA, const EDA_ANGLE& aAngleB )
}
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 );
}
}
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 );
}
}
inline bool operator==( const EDA_ANGLE& aAngleA, const EDA_ANGLE& aAngleB )
{
return aAngleA.AsTenthsOfADegree() == aAngleB.AsTenthsOfADegree();

View File

@ -165,7 +165,7 @@ public:
*/
void SetArcAngleAndEnd( double aAngle, bool aCheckNegativeAngle = false );
double GetArcAngle() const;
EDA_ANGLE GetArcAngle() const;
/**
* Have the start and end points been swapped since they were set?

View File

@ -53,14 +53,14 @@ enum RECT_CHAMFER_POSITIONS : int
* @param aPolyline is a buffer to store the polyline.
* @param aCenter is the center of the arc.
* @param aRadius is the radius of the arc.
* @param aStartAngleDeg is the starting point (in degrees) of the arc.
* @param aArcAngleDeg is the angle (in degrees) of the arc.
* @param aStartAngleDeg is the starting point of the arc.
* @param aArcAngleDeg is the angle of the arc.
* @param aError is the internal units allowed for error approximation.
* @param aErrorLoc determines if the approximation error be placed outside or inside the polygon.
*/
int ConvertArcToPolyline( SHAPE_LINE_CHAIN& aPolyline, VECTOR2I aCenter, int aRadius,
double aStartAngleDeg, double aArcAngleDeg, double aAccuracy,
ERROR_LOC aErrorLoc );
const EDA_ANGLE& aStartAngleDeg, const EDA_ANGLE& aArcAngleDeg,
double aAccuracy, ERROR_LOC aErrorLoc );
/**

View File

@ -32,7 +32,7 @@
#include <math.h> // for copysign
#include <stdlib.h> // for abs
#include <eda_angle.h>
#include <math/vector2d.h>
class EDA_RECT;
@ -50,9 +50,9 @@ enum ERROR_LOC { ERROR_OUTSIDE, ERROR_INSIDE };
* @param aRadius is the radius od the circle or arc
* @param aErrorMax is the max error
* This is the max distance between the middle of a segment and the circle.
* @param aArcAngleDegree is the arc angle in degrees
* @param aArcAngleDegree is the arc angle
*/
int GetArcToSegmentCount( int aRadius, int aErrorMax, double aArcAngleDegree );
int GetArcToSegmentCount( int aRadius, int aErrorMax, const EDA_ANGLE& aArcAngle );
/**
* @return the radius diffence of the circle defined by segments inside the circle

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2018 CERN
* Copyright (C) 2019-2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2019-2022 KiCad Developers, see AUTHORS.txt for contributors.
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software; you can redistribute it and/or
@ -28,6 +28,7 @@
#include <geometry/shape.h>
#include <convert_to_biu.h>
#include <eda_angle.h>
#include <math/vector2d.h> // for VECTOR2I
class SHAPE_LINE_CHAIN;
@ -49,11 +50,11 @@ public:
*
* @param aArcCenter is the arc center.
* @param aArcStartPoint is the arc start point.
* @param aCenterAngle is the arc angle in degrees.
* @param aCenterAngle is the arc angle.
* @param aWidth is the arc line thickness.
*/
SHAPE_ARC( const VECTOR2I& aArcCenter, const VECTOR2I& aArcStartPoint, double aCenterAngle,
int aWidth = 0 );
SHAPE_ARC( const VECTOR2I& aArcCenter, const VECTOR2I& aArcStartPoint,
const EDA_ANGLE& aCenterAngle, int aWidth = 0 );
/**
* @param aArcStart is the arc start point.

View File

@ -43,7 +43,7 @@ void TransformCircleToPolygon( SHAPE_LINE_CHAIN& aCornerBuffer, const VECTOR2I&
int aRadius, int aError, ERROR_LOC aErrorLoc, int aMinSegCount )
{
VECTOR2I corner_position;
int numSegs = GetArcToSegmentCount( aRadius, aError, 360.0 );
int numSegs = GetArcToSegmentCount( aRadius, aError, FULL_CIRCLE );
numSegs = std::max( aMinSegCount, numSegs );
// The shape will be built with a even number of segs. Reason: the horizontal
@ -82,7 +82,7 @@ void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, const VECTOR2I& aC
int aError, ERROR_LOC aErrorLoc, int aMinSegCount )
{
VECTOR2I corner_position;
int numSegs = GetArcToSegmentCount( aRadius, aError, 360.0 );
int numSegs = GetArcToSegmentCount( aRadius, aError, FULL_CIRCLE );
numSegs = std::max( aMinSegCount, numSegs );
// The shape will be built with a even number of segs. Reason: the horizontal
@ -133,7 +133,7 @@ void TransformOvalToPolygon( SHAPE_POLY_SET& aCornerBuffer, const VECTOR2I& aSta
// so, later, we will clamp the polygonal shape with the bounding box
// of the segment.
int radius = aWidth / 2;
int numSegs = GetArcToSegmentCount( radius, aError, 360.0 );
int numSegs = GetArcToSegmentCount( radius, aError, FULL_CIRCLE );
numSegs = std::max( aMinSegCount, numSegs );
int delta = 3600 / numSegs; // rotate angle in 0.1 degree
@ -281,7 +281,7 @@ void CornerListToPolygon( SHAPE_POLY_SET& outline, std::vector<ROUNDED_CORNER>&
}
// Ensure 16+ segments per 360deg and ensure first & last segment are the same size
int numSegs = std::max( 16, GetArcToSegmentCount( radius, aError, 360.0 ) );
int numSegs = std::max( 16, GetArcToSegmentCount( radius, aError, FULL_CIRCLE ) );
int angDelta = 3600 / numSegs;
int lastSegLen = endAngle % angDelta; // or 0 if last seg length is angDelta
int angPos = lastSegLen ? ( angDelta + lastSegLen ) / 2 : angDelta;
@ -501,29 +501,28 @@ void TransformRoundChamferedRectToPolygon( SHAPE_POLY_SET& aCornerBuffer, const
int ConvertArcToPolyline( SHAPE_LINE_CHAIN& aPolyline, VECTOR2I aCenter, int aRadius,
double aStartAngleDeg, double aArcAngleDeg, double aAccuracy,
ERROR_LOC aErrorLoc )
const EDA_ANGLE& aStartAngle, const EDA_ANGLE& aArcAngle,
double aAccuracy, ERROR_LOC aErrorLoc )
{
double endAngle = aStartAngleDeg + aArcAngleDeg;
int n = 2;
if( aRadius >= aAccuracy )
n = GetArcToSegmentCount( aRadius, aAccuracy, aArcAngleDeg )+1; // n >= 3
n = GetArcToSegmentCount( aRadius, aAccuracy, aArcAngle ) + 1;
if( aErrorLoc == ERROR_OUTSIDE )
{
int seg360 = std::abs( KiROUND( n * 360.0 / aArcAngleDeg ) );
int seg360 = std::abs( KiROUND( n * 360.0 / aArcAngle.AsDegrees() ) );
int actual_delta_radius = CircleToEndSegmentDeltaRadius( aRadius, seg360 );
aRadius += actual_delta_radius;
}
for( int i = 0; i <= n ; i++ )
{
double rot = aStartAngleDeg;
rot += ( aArcAngleDeg * i ) / n;
EDA_ANGLE rot = aStartAngle;
rot += ( aArcAngle * i ) / n;
double x = aCenter.x + aRadius * cos( rot * M_PI / 180.0 );
double y = aCenter.y + aRadius * sin( rot * M_PI / 180.0 );
double x = aCenter.x + aRadius * cos( rot.AsRadians() );
double y = aCenter.y + aRadius * sin( rot.AsRadians() );
aPolyline.Append( KiROUND( x ), KiROUND( y ) );
}
@ -589,11 +588,13 @@ void TransformArcToPolygon( SHAPE_POLY_SET& aCornerBuffer, const VECTOR2I& aStar
polyshape.NewOutline();
ConvertArcToPolyline( polyshape.Outline(2), center, arc_outer_radius,
arc_angle_start_deg, arc_angle, aError, errorLocOuter );
EDA_ANGLE( arc_angle_start_deg, DEGREES_T ),
EDA_ANGLE( arc_angle, DEGREES_T ), aError, errorLocOuter );
if( arc_inner_radius > 0 )
ConvertArcToPolyline( polyshape.Outline(2), center, arc_inner_radius,
arc_angle_end_deg, -arc_angle, aError, errorLocInner );
EDA_ANGLE( arc_angle_end_deg, DEGREES_T ),
-EDA_ANGLE( arc_angle, DEGREES_T ), aError, errorLocInner );
else
polyshape.Append( center );
#else

View File

@ -188,7 +188,7 @@ const SHAPE_LINE_CHAIN DIRECTION_45::BuildInitialTrace( const VECTOR2I& aP0, con
{
// Negative tangentLength: arc goes at the start
VECTOR2I arcCenter = aP0 + centerDir.Resize( arcRadius );
SHAPE_ARC ca( arcCenter, aP0, 45 * rotationSign );
SHAPE_ARC ca( arcCenter, aP0, ANGLE_45 * rotationSign );
// Constructing with a center can lead to imprecise endpoint. We need to guarantee
// tangency of the endpoint.

View File

@ -40,7 +40,7 @@
// with a 0.01mm maximum deviation yields 11 segments.)
#define MIN_SEGCOUNT_FOR_CIRCLE 8
int GetArcToSegmentCount( int aRadius, int aErrorMax, double aArcAngleDegree )
int GetArcToSegmentCount( int aRadius, int aErrorMax, const EDA_ANGLE& aArcAngle )
{
// calculate the number of segments to approximate a circle by segments
// given the max distance between the middle of a segment and the circle
@ -57,7 +57,7 @@ int GetArcToSegmentCount( int aRadius, int aErrorMax, double aArcAngleDegree )
// (360.0 degrees). For very small radius values, this is mandatory.
arc_increment = std::min( 360.0/MIN_SEGCOUNT_FOR_CIRCLE, arc_increment );
int segCount = KiROUND( fabs( aArcAngleDegree ) / arc_increment );
int segCount = KiROUND( fabs( aArcAngle.AsDegrees() ) / arc_increment );
// Ensure at least two segments are used for algorithmic safety
return std::max( segCount, 2 );

View File

@ -41,15 +41,16 @@ std::ostream& operator<<( std::ostream& aStream, const SHAPE_ARC& aArc )
SHAPE_ARC::SHAPE_ARC( const VECTOR2I& aArcCenter, const VECTOR2I& aArcStartPoint,
double aCenterAngle, int aWidth ) :
SHAPE( SH_ARC ), m_width( aWidth )
const EDA_ANGLE& aCenterAngle, int aWidth ) :
SHAPE( SH_ARC ),
m_width( aWidth )
{
m_start = aArcStartPoint;
m_mid = aArcStartPoint;
m_end = aArcStartPoint;
RotatePoint( m_mid, aArcCenter, -aCenterAngle * 10.0 / 2.0 );
RotatePoint( m_end, aArcCenter, -aCenterAngle * 10.0 );
RotatePoint( m_mid, aArcCenter, -EDA_ANGLE( aCenterAngle.AsDegrees() / 2.0, DEGREES_T ) );
RotatePoint( m_end, aArcCenter, -aCenterAngle );
update_bbox();
}
@ -57,15 +58,18 @@ SHAPE_ARC::SHAPE_ARC( const VECTOR2I& aArcCenter, const VECTOR2I& aArcStartPoint
SHAPE_ARC::SHAPE_ARC( const VECTOR2I& aArcStart, const VECTOR2I& aArcMid,
const VECTOR2I& aArcEnd, int aWidth ) :
SHAPE( SH_ARC ), m_start( aArcStart ), m_mid( aArcMid ), m_end( aArcEnd ),
m_width( aWidth )
SHAPE( SH_ARC ),
m_start( aArcStart ),
m_mid( aArcMid ),
m_end( aArcEnd ),
m_width( aWidth )
{
update_bbox();
}
SHAPE_ARC::SHAPE_ARC( const SEG& aSegmentA, const SEG& aSegmentB, int aRadius, int aWidth )
: SHAPE( SH_ARC )
SHAPE_ARC::SHAPE_ARC( const SEG& aSegmentA, const SEG& aSegmentB, int aRadius, int aWidth ) :
SHAPE( SH_ARC )
{
m_width = aWidth;
@ -135,18 +139,17 @@ SHAPE_ARC::SHAPE_ARC( const SEG& aSegmentA, const SEG& aSegmentB, int aRadius, i
if( pToB.EuclideanNorm() == 0 )
pToB = aSegmentB.A - p.get();
double pToAangle = ArcTangente( pToA.y, pToA.x );
double pToBangle = ArcTangente( pToB.y, pToB.x );
EDA_ANGLE pToAangle( pToA );
EDA_ANGLE pToBangle( pToB );
double alpha = NormalizeAngle180( pToAangle - pToBangle );
EDA_ANGLE alpha = ( pToAangle - pToBangle ).Normalize180();
double distPC = (double) aRadius / abs( sin( DECIDEG2RAD( alpha / 2 ) ) );
double angPC = pToAangle - alpha / 2;
double distPC = (double) aRadius / abs( sin( alpha.AsRadians() / 2 ) );
EDA_ANGLE angPC = pToAangle - alpha / 2;
VECTOR2I arcCenter;
VECTOR2I arcCenter;
arcCenter.x = p.get().x + KiROUND( distPC * cos( DECIDEG2RAD( angPC ) ) );
arcCenter.y = p.get().y + KiROUND( distPC * sin( DECIDEG2RAD( angPC ) ) );
arcCenter.x = p.get().x + KiROUND( distPC * cos( angPC.AsRadians() ) );
arcCenter.y = p.get().y + KiROUND( distPC * sin( angPC.AsRadians() ) );
// The end points of the arc are the orthogonal projected lines from the line segments
// to the center of the arc
@ -157,10 +160,10 @@ SHAPE_ARC::SHAPE_ARC( const SEG& aSegmentA, const SEG& aSegmentB, int aRadius, i
VECTOR2I startVector = m_start - arcCenter;
VECTOR2I endVector = m_end - arcCenter;
double startAngle = ArcTangente( startVector.y, startVector.x );
double endAngle = ArcTangente( endVector.y, endVector.x );
EDA_ANGLE startAngle( startVector );
EDA_ANGLE endAngle( endVector );
EDA_ANGLE midPointRotAngle = ( startAngle - endAngle ).Normalize180() / 2;
double midPointRotAngle = NormalizeAngle180( startAngle - endAngle ) / 2;
m_mid = m_start;
RotatePoint( m_mid, arcCenter, midPointRotAngle );
}
@ -438,14 +441,11 @@ double SHAPE_ARC::GetLength() const
double SHAPE_ARC::GetCentralAngle() const
{
VECTOR2I center = GetCenter();
VECTOR2I p0 = m_start - center;
VECTOR2I p1 = m_mid - center;
VECTOR2I p2 = m_end - center;
double angle1 = ArcTangente( p1.y, p1.x ) - ArcTangente( p0.y, p0.x );
double angle2 = ArcTangente( p2.y, p2.x ) - ArcTangente( p1.y, p1.x );
VECTOR2I center = GetCenter();
EDA_ANGLE angle1 = EDA_ANGLE( m_mid - center ) - EDA_ANGLE( m_start - center );
EDA_ANGLE angle2 = EDA_ANGLE( m_end - center ) - EDA_ANGLE( m_mid - center );
return ( NormalizeAngle180( angle1 ) + NormalizeAngle180( angle2 ) ) / 10.0;
return ( angle1 + angle2 ).Normalize180().AsTenthsOfADegree();
}
@ -481,7 +481,7 @@ const SHAPE_LINE_CHAIN SHAPE_ARC::ConvertToPolyline( double aAccuracy,
else
{
double arc_angle = std::abs( ca );
n = GetArcToSegmentCount( external_radius, aAccuracy, arc_angle );
n = GetArcToSegmentCount( external_radius, aAccuracy, EDA_ANGLE( arc_angle, DEGREES_T ) );
// Recalculate the effective error of approximation, that can be < aAccuracy
int seg360 = n * 360.0 / arc_angle;

View File

@ -1907,7 +1907,7 @@ const std::string SHAPE_LINE_CHAIN::Format() const
for( size_t i = 0; i < m_arcs.size(); i++ )
ss << m_arcs[i].GetCenter().x << " " << m_arcs[i].GetCenter().y << " "
<< m_arcs[i].GetP0().x << " " << m_arcs[i].GetP0().y << " "
<< m_arcs[i].GetCentralAngle();
<< m_arcs[i].GetCentralAngle().AsDegrees();
return ss.str();*/
}
@ -1986,7 +1986,7 @@ bool SHAPE_LINE_CHAIN::Parse( std::stringstream& aStream )
aStream >> p0.y;
aStream >> angle;
m_arcs.emplace_back( pc, p0, angle );
m_arcs.emplace_back( pc, p0, EDA_ANGLE( angle, DEGREES_T ) );
}
return true;

View File

@ -2155,11 +2155,11 @@ SHAPE_POLY_SET::POLYGON SHAPE_POLY_SET::chamferFilletPolygon( CORNER_MODE aMode,
argument = 1;
double arcAngle = acos( argument );
double arcAngleDegrees = arcAngle * 180.0 / M_PI;
int segments = GetArcToSegmentCount( radius, aErrorMax, arcAngleDegrees );
int segments = GetArcToSegmentCount( radius, aErrorMax,
EDA_ANGLE( arcAngle, RADIANS_T ) );
double deltaAngle = arcAngle / segments;
double startAngle = atan2( -ys, xs );
double deltaAngle = arcAngle / segments;
double startAngle = atan2( -ys, xs );
// Flip arc for inner corners
if( xa * yb - ya * xb <= 0 )

View File

@ -345,18 +345,7 @@ void AR_MATRIX::drawSegmentQcq( int ux0, int uy0, int ux1, int uy1, int lg, int
dx = ux1 - ux0;
dy = uy1 - uy0;
double angle;
if( dx )
{
angle = ArcTangente( dy, dx );
}
else
{
angle = 900;
if( dy < 0 )
angle = -900;
}
EDA_ANGLE angle( VECTOR2I( dx, dy ) );
RotatePoint( &dx, &dy, angle ); // dx = length, dy = 0
@ -789,7 +778,8 @@ void AR_MATRIX::TraceSegmentPcb( PCB_SHAPE* aShape, int aColor, int aMargin,
int ux1 = aShape->GetStart().x - GetBrdCoordOrigin().x;
int uy1 = aShape->GetStart().y - GetBrdCoordOrigin().y;
traceArc( ux0, uy0, ux1, uy1, aShape->GetArcAngle(), half_width, layer, aColor, op_logic );
traceArc( ux0, uy0, ux1, uy1, aShape->GetArcAngle().AsTenthsOfADegree(), half_width,
layer, aColor, op_logic );
}
}

Some files were not shown because too many files have changed in this diff Show More