Switch zone fillets to absolute-error algorithm.
And some general cleanup to related constants, etc.
This commit is contained in:
parent
d2d0660647
commit
fbf10e941b
|
@ -38,6 +38,7 @@
|
|||
#include <md5_hash.h>
|
||||
#include <map>
|
||||
|
||||
#include <geometry/geometry_utils.h>
|
||||
#include <geometry/shape.h>
|
||||
#include <geometry/shape_line_chain.h>
|
||||
#include <geometry/shape_poly_set.h>
|
||||
|
@ -1575,10 +1576,10 @@ SHAPE_POLY_SET::POLYGON SHAPE_POLY_SET::ChamferPolygon( unsigned int aDistance,
|
|||
|
||||
|
||||
SHAPE_POLY_SET::POLYGON SHAPE_POLY_SET::FilletPolygon( unsigned int aRadius,
|
||||
unsigned int aSegments,
|
||||
int aErrorMax,
|
||||
int aIndex )
|
||||
{
|
||||
return chamferFilletPolygon( CORNER_MODE::FILLETED, aRadius, aIndex, aSegments );
|
||||
return chamferFilletPolygon( CORNER_MODE::FILLETED, aRadius, aIndex, aErrorMax );
|
||||
}
|
||||
|
||||
|
||||
|
@ -1703,12 +1704,12 @@ SHAPE_POLY_SET SHAPE_POLY_SET::Chamfer( int aDistance )
|
|||
}
|
||||
|
||||
|
||||
SHAPE_POLY_SET SHAPE_POLY_SET::Fillet( int aRadius, int aSegments )
|
||||
SHAPE_POLY_SET SHAPE_POLY_SET::Fillet( int aRadius, int aErrorMax )
|
||||
{
|
||||
SHAPE_POLY_SET filleted;
|
||||
|
||||
for( size_t polygonIdx = 0; polygonIdx < m_polys.size(); polygonIdx++ )
|
||||
filleted.m_polys.push_back( FilletPolygon( aRadius, aSegments, polygonIdx ) );
|
||||
filleted.m_polys.push_back( FilletPolygon( aRadius, aErrorMax, polygonIdx ) );
|
||||
|
||||
return filleted;
|
||||
}
|
||||
|
@ -1717,7 +1718,7 @@ SHAPE_POLY_SET SHAPE_POLY_SET::Fillet( int aRadius, int aSegments )
|
|||
SHAPE_POLY_SET::POLYGON SHAPE_POLY_SET::chamferFilletPolygon( CORNER_MODE aMode,
|
||||
unsigned int aDistance,
|
||||
int aIndex,
|
||||
int aSegments )
|
||||
int aErrorMax )
|
||||
{
|
||||
// Null segments create serious issues in calculations. Remove them:
|
||||
RemoveNullSegments();
|
||||
|
@ -1833,9 +1834,8 @@ SHAPE_POLY_SET::POLYGON SHAPE_POLY_SET::chamferFilletPolygon( CORNER_MODE aMode,
|
|||
argument = 1;
|
||||
|
||||
double arcAngle = acos( argument );
|
||||
|
||||
// Calculate the number of segments
|
||||
unsigned int segments = ceil( (double) aSegments * ( arcAngle / ( 2 * M_PI ) ) );
|
||||
double arcAngleDegrees = arcAngle * 180.0 / M_PI;
|
||||
int segments = GetArcToSegmentCount( radius, aErrorMax, arcAngleDegrees );
|
||||
|
||||
double deltaAngle = arcAngle / segments;
|
||||
double startAngle = atan2( -ys, xs );
|
||||
|
|
|
@ -98,6 +98,15 @@ constexpr inline double Iu2Mils( int iu )
|
|||
{
|
||||
return iu / IU_PER_MILS;
|
||||
}
|
||||
|
||||
// The max error is the distance between the middle of a segment, and the circle
|
||||
// for circle/arc to segment approximation.
|
||||
// Warning: too small values can create very long calculation time in zone filling
|
||||
// 0.05 to 0.005 mm are reasonable values
|
||||
|
||||
constexpr int ARC_LOW_DEF = Millimeter2iu( 0.02 );
|
||||
constexpr int ARC_HIGH_DEF = Millimeter2iu( 0.005 );
|
||||
|
||||
#endif
|
||||
|
||||
#endif // CONVERT_TO_BIU_H_
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
int GetArcToSegmentCount( int aRadius, int aErrorMax, double aArcAngleDegree );
|
||||
|
||||
/**
|
||||
* @return the correction factor to approximate a circle by segùments
|
||||
* @return the correction factor to approximate a circle by segments
|
||||
* @param aSegCountforCircle is the number of segments to approximate the circle
|
||||
*
|
||||
* When creating a polygon from a circle, the polygon is inside the circle.
|
||||
|
|
|
@ -1002,11 +1002,11 @@ class SHAPE_POLY_SET : public SHAPE
|
|||
* Function Fillet
|
||||
* returns a filleted version of the aIndex-th polygon.
|
||||
* @param aRadius is the fillet radius.
|
||||
* @param aSegments is the number of segments / fillet.
|
||||
* @param aErrorMax is the maximum allowable deviation of the polygon from the circle
|
||||
* @param aIndex is the index of the polygon to be filleted
|
||||
* @return POLYGON - A polygon containing the filleted version of the aIndex-th polygon.
|
||||
*/
|
||||
POLYGON FilletPolygon( unsigned int aRadius, unsigned int aSegments, int aIndex = 0 );
|
||||
POLYGON FilletPolygon( unsigned int aRadius, int aErrorMax, int aIndex = 0 );
|
||||
|
||||
/**
|
||||
* Function Chamfer
|
||||
|
@ -1020,10 +1020,10 @@ class SHAPE_POLY_SET : public SHAPE
|
|||
* Function Fillet
|
||||
* returns a filleted version of the polygon set.
|
||||
* @param aRadius is the fillet radius.
|
||||
* @param aSegments is the number of segments / fillet.
|
||||
* @param aErrorMax is the maximum allowable deviation of the polygon from the circle
|
||||
* @return SHAPE_POLY_SET - A set containing the filleted version of this set.
|
||||
*/
|
||||
SHAPE_POLY_SET Fillet( int aRadius, int aSegments );
|
||||
SHAPE_POLY_SET Fillet( int aRadius, int aErrorMax );
|
||||
|
||||
/**
|
||||
* Function DistanceToPolygon
|
||||
|
@ -1147,12 +1147,12 @@ class SHAPE_POLY_SET : public SHAPE
|
|||
* @param aDistance is the chamfering distance if aMode = CHAMFERED; if aMode = FILLETED,
|
||||
* is the filleting radius.
|
||||
* @param aIndex is the index of the polygon that will be chamfered/filleted.
|
||||
* @param aSegments is the number of filleting segments if aMode = FILLETED. If aMode =
|
||||
* CHAMFERED, it is unused.
|
||||
* @param aErrorMax is the maximum allowable deviation of the polygon from the circle
|
||||
* if aMode = FILLETED. If aMode = CHAMFERED, it is unused.
|
||||
* @return POLYGON - the chamfered/filleted version of the polygon.
|
||||
*/
|
||||
POLYGON chamferFilletPolygon( CORNER_MODE aMode, unsigned int aDistance,
|
||||
int aIndex, int aSegments = -1 );
|
||||
int aIndex, int aErrorMax = -1 );
|
||||
|
||||
///> Returns true if the polygon set has any holes that touch share a vertex.
|
||||
bool hasTouchingHoles( const POLYGON& aPoly ) const;
|
||||
|
|
|
@ -1328,7 +1328,12 @@ bool ZONE_CONTAINER::BuildSmoothedPoly( SHAPE_POLY_SET& aSmoothedPoly ) const
|
|||
break;
|
||||
|
||||
case ZONE_SETTINGS::SMOOTHING_FILLET:
|
||||
aSmoothedPoly = m_Poly->Fillet( m_cornerRadius, m_ArcToSegmentsCount );
|
||||
// Note: we're now using m_ArcToSegmentsCount only as a hint to determine accuracy
|
||||
// vs. speed.
|
||||
if( m_ArcToSegmentsCount > SEGMENT_COUNT_CROSSOVER )
|
||||
aSmoothedPoly = m_Poly->Fillet( m_cornerRadius, ARC_HIGH_DEF );
|
||||
else
|
||||
aSmoothedPoly = m_Poly->Fillet( m_cornerRadius, ARC_LOW_DEF );
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -38,12 +38,6 @@
|
|||
#include <geometry/geometry_utils.h>
|
||||
|
||||
|
||||
// Error max when converting a circle or arc to segments.
|
||||
// Avoid too small values that create a very long calculation time
|
||||
// in zone fillings
|
||||
#define ARC_ACCURACY ( 0.05 * IU_PER_MM )
|
||||
|
||||
|
||||
/**
|
||||
* Function close_ness
|
||||
* is a non-exact distance (also called Manhattan distance) used to approximate
|
||||
|
@ -234,8 +228,8 @@ bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList,
|
|||
wxPoint pstart = graphic->GetArcStart();
|
||||
wxPoint center = graphic->GetCenter();
|
||||
double angle = -graphic->GetAngle();
|
||||
int steps = GetArcToSegmentCount( graphic->GetRadius(), ARC_ACCURACY,
|
||||
(double)angle / 10.0 );
|
||||
double radius = graphic->GetRadius();
|
||||
int steps = GetArcToSegmentCount( radius, ARC_LOW_DEF, angle / 10.0 );
|
||||
wxPoint pt;
|
||||
|
||||
for( int step = 1; step<=steps; ++step )
|
||||
|
@ -293,7 +287,7 @@ bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList,
|
|||
// Output the Edge.Cuts perimeter as circle or polygon.
|
||||
if( graphic->GetShape() == S_CIRCLE )
|
||||
{
|
||||
int steps = GetArcToSegmentCount( graphic->GetRadius(), ARC_ACCURACY, 360.0 );
|
||||
int steps = GetArcToSegmentCount( graphic->GetRadius(), ARC_LOW_DEF, 360.0 );
|
||||
TransformCircleToPolygon( aPolygons, graphic->GetCenter(), graphic->GetRadius(), steps );
|
||||
}
|
||||
else
|
||||
|
@ -340,8 +334,8 @@ bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList,
|
|||
wxPoint pend = graphic->GetArcEnd();
|
||||
wxPoint pcenter = graphic->GetCenter();
|
||||
double angle = -graphic->GetAngle();
|
||||
int steps = GetArcToSegmentCount( graphic->GetRadius(), ARC_ACCURACY,
|
||||
(double)angle / 10.0 );
|
||||
double radius = graphic->GetRadius();
|
||||
int steps = GetArcToSegmentCount( radius, ARC_LOW_DEF, angle / 10.0 );
|
||||
|
||||
if( !close_enough( prevPt, pstart, prox ) )
|
||||
{
|
||||
|
@ -431,9 +425,9 @@ bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList,
|
|||
// make a circle by segments;
|
||||
wxPoint center = graphic->GetCenter();
|
||||
double angle = 3600.0;
|
||||
wxPoint start = center;
|
||||
wxPoint start = center;
|
||||
int radius = graphic->GetRadius();
|
||||
int steps = GetArcToSegmentCount( graphic->GetRadius(), ARC_ACCURACY, 360.0 );
|
||||
int steps = GetArcToSegmentCount( radius, ARC_LOW_DEF, 360.0 );
|
||||
wxPoint nextPt;
|
||||
|
||||
start.x += radius;
|
||||
|
@ -491,8 +485,8 @@ bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList,
|
|||
wxPoint pend = graphic->GetArcEnd();
|
||||
wxPoint pcenter = graphic->GetCenter();
|
||||
double angle = -graphic->GetAngle();
|
||||
int steps = GetArcToSegmentCount( graphic->GetRadius(), ARC_ACCURACY,
|
||||
(double)angle / 10.0 );
|
||||
int radius = graphic->GetRadius();
|
||||
int steps = GetArcToSegmentCount( radius, ARC_LOW_DEF, angle / 10.0 );
|
||||
|
||||
if( !close_enough( prevPt, pstart, prox ) )
|
||||
{
|
||||
|
|
|
@ -41,6 +41,10 @@
|
|||
#define ARC_APPROX_SEGMENTS_COUNT_LOW_DEF 16
|
||||
#define ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF 32
|
||||
|
||||
// The new absolute-error-based algorithm uses the stored segment count as a hint on whether
|
||||
// to use ARC_HIGH_DEF or ARC_LOW_DEF. This defines the crossover point.
|
||||
#define SEGMENT_COUNT_CROSSOVER 24
|
||||
|
||||
/* Flag used in locate functions. The locate ref point is the on grid cursor or the off
|
||||
* grid mouse cursor. */
|
||||
#define CURSEUR_ON_GRILLE (0 << 0)
|
||||
|
|
|
@ -767,8 +767,7 @@ IMAGE* SPECCTRA_DB::makeIMAGE( BOARD* aBoard, MODULE* aModule )
|
|||
double radius = GetLineLength( graphic->GetStart(), graphic->GetEnd() );
|
||||
|
||||
// seg count to approximate circle by line segments
|
||||
int err_max = Millimeter2iu( 0.05 );
|
||||
int seg_per_circle = GetArcToSegmentCount( radius, err_max, 360.0 );
|
||||
int seg_per_circle = GetArcToSegmentCount( radius, ARC_LOW_DEF, 360.0 );
|
||||
|
||||
for( int ii = 0; ii < seg_per_circle; ++ii )
|
||||
{
|
||||
|
|
|
@ -293,7 +293,7 @@ void ZONE_FILLER::buildZoneFeatureHoleList( const ZONE_CONTAINER* aZone,
|
|||
double correctionFactor;
|
||||
|
||||
// Set the number of segments in arc approximations
|
||||
if( aZone->GetArcSegmentCount() == ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF )
|
||||
if( aZone->GetArcSegmentCount() > SEGMENT_COUNT_CROSSOVER )
|
||||
segsPerCircle = ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF;
|
||||
else
|
||||
segsPerCircle = ARC_APPROX_SEGMENTS_COUNT_LOW_DEF;
|
||||
|
|
Loading…
Reference in New Issue