Refinements in Arc to Polygon transform: slightly better shapes of arc ends.

Note also the transform is still not good: the same parameters are applied
to convert inner arc, outer arc and middle arc of a thick arc to segments.
But these parameters depend on arc radius (or circle radius) value.
This commit is contained in:
jean-pierre charras 2021-06-26 13:18:46 +02:00
parent e50eaed7b9
commit 3c81403424
2 changed files with 44 additions and 2 deletions

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-2020 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2019-2021 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
@ -61,7 +61,7 @@ public:
*/
SHAPE_ARC( const VECTOR2I& aArcStart, const VECTOR2I& aArcMid, const VECTOR2I& aArcEnd,
int aWidth );
/**
* SHAPE_ARC ctor.
* Builds a SHAPE_ARC which is tangent to two segments and a given radius
@ -144,8 +144,19 @@ public:
return SEG( m_start, m_end );
}
/**
* @return the central angle of the arc shape in degrees, normalized between 0.0, 360.0 deg
*/
double GetCentralAngle() const;
/**
* @return the start angle of the arc shape in degrees, normalized between 0.0, 360.0 deg
*/
double GetStartAngle() const;
/**
* @return the end angle of the arc shape in degrees, normalized between 0.0, 360.0 deg
*/
double GetEndAngle() const;
/**

View File

@ -43,6 +43,14 @@ void TransformCircleToPolygon( SHAPE_LINE_CHAIN& aCornerBuffer, wxPoint aCenter,
{
wxPoint corner_position;
int numSegs = GetArcToSegmentCount( aRadius, aError, 360.0 );
// The shape will be built with a even number of segs. Reason: the horizontal
// diameter begins and ends to points on the actual circle, or circle
// expanded by aError if aErrorLoc == ERROR_OUTSIDE.
// This is used by Arc to Polygon shape convert.
if( numSegs & 1 )
numSegs++;
int delta = 3600 / numSegs; // rotate angle in 0.1 degree
int radius = aRadius;
@ -67,6 +75,14 @@ void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCenter, i
{
wxPoint corner_position;
int numSegs = GetArcToSegmentCount( aRadius, aError, 360.0 );
// The shape will be built with a even number of segs. Reason: the horizontal
// diameter begins and ends to points on the actual circle, or circle
// expanded by aError if aErrorLoc == ERROR_OUTSIDE.
// This is used by Arc to Polygon shape convert.
if( numSegs & 1 )
numSegs++;
int delta = 3600 / numSegs; // rotate angle in 0.1 degree
int radius = aRadius;
@ -367,6 +383,21 @@ void TransformArcToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aStart, wxPoi
wxPoint( arcSpine.GetPoint( -1 ).x, arcSpine.GetPoint( -1 ).y ), radial_offset, aError,
aErrorLoc );
// The circle polygon is built with a even number of segments, so the
// horizontal diameter has 2 corners on the biggest diameter
// Rotate these 2 corners to match the start and ens points of inner and outer
// end points of the arc appoximation outlines, build below.
// The final shape is much better.
double arc_angle_end_deg = arc.GetStartAngle();
if( arc_angle_end_deg != 0 & arc_angle_end_deg != 180.0 )
polyshape.Outline(0).Rotate( arc_angle_end_deg * M_PI/180.0, arcSpine.GetPoint( 0 ) );
arc_angle_end_deg = arc.GetEndAngle();
if( arc_angle_end_deg != 0 & arc_angle_end_deg != 180.0 )
polyshape.Outline(1).Rotate( arc_angle_end_deg * M_PI/180.0, arcSpine.GetPoint( -1 ) );
if( aErrorLoc == ERROR_OUTSIDE )
radial_offset += aError;
else