mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-04-20 00:21:31 +00:00
Re-balance file sizes.
This commit is contained in:
parent
76a3d1c845
commit
e483c48fe6
libs/kimath/src/geometry
@ -26,8 +26,10 @@
|
||||
#include <geometry/circle.h>
|
||||
#include <geometry/half_line.h>
|
||||
#include <geometry/shape_arc.h>
|
||||
#include <geometry/shape_poly_set.h>
|
||||
#include <geometry/shape_utils.h>
|
||||
#include <geometry/vector_utils.h>
|
||||
#include <geometry/geometry_utils.h>
|
||||
#include <trigo.h>
|
||||
|
||||
namespace
|
||||
@ -255,4 +257,181 @@ std::optional<DOGBONE_RESULT> ComputeDogbone( const SEG& aSegA, const SEG& aSegB
|
||||
small_arc_mouth,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SHAPE_POLY_SET::POLYGON SHAPE_POLY_SET::chamferFilletPolygon( CORNER_MODE aMode,
|
||||
unsigned int aDistance,
|
||||
int aIndex, int aErrorMax )
|
||||
{
|
||||
// Null segments create serious issues in calculations. Remove them:
|
||||
RemoveNullSegments();
|
||||
|
||||
SHAPE_POLY_SET::POLYGON currentPoly = Polygon( aIndex );
|
||||
SHAPE_POLY_SET::POLYGON newPoly;
|
||||
|
||||
// If the chamfering distance is zero, then the polygon remain intact.
|
||||
if( aDistance == 0 )
|
||||
{
|
||||
return currentPoly;
|
||||
}
|
||||
|
||||
// Iterate through all the contours (outline and holes) of the polygon.
|
||||
for( SHAPE_LINE_CHAIN& currContour : currentPoly )
|
||||
{
|
||||
// Generate a new contour in the new polygon
|
||||
SHAPE_LINE_CHAIN newContour;
|
||||
|
||||
// Iterate through the vertices of the contour
|
||||
for( int currVertex = 0; currVertex < currContour.PointCount(); currVertex++ )
|
||||
{
|
||||
// Current vertex
|
||||
int x1 = currContour.CPoint( currVertex ).x;
|
||||
int y1 = currContour.CPoint( currVertex ).y;
|
||||
|
||||
// Indices for previous and next vertices.
|
||||
int prevVertex;
|
||||
int nextVertex;
|
||||
|
||||
// Previous and next vertices indices computation. Necessary to manage the edge cases.
|
||||
|
||||
// Previous vertex is the last one if the current vertex is the first one
|
||||
prevVertex = currVertex == 0 ? currContour.PointCount() - 1 : currVertex - 1;
|
||||
|
||||
// next vertex is the first one if the current vertex is the last one.
|
||||
nextVertex = currVertex == currContour.PointCount() - 1 ? 0 : currVertex + 1;
|
||||
|
||||
// Previous vertex computation
|
||||
double xa = currContour.CPoint( prevVertex ).x - x1;
|
||||
double ya = currContour.CPoint( prevVertex ).y - y1;
|
||||
|
||||
// Next vertex computation
|
||||
double xb = currContour.CPoint( nextVertex ).x - x1;
|
||||
double yb = currContour.CPoint( nextVertex ).y - y1;
|
||||
|
||||
// Avoid segments that will generate nans below
|
||||
if( std::abs( xa + xb ) < std::numeric_limits<double>::epsilon()
|
||||
&& std::abs( ya + yb ) < std::numeric_limits<double>::epsilon() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Compute the new distances
|
||||
double lena = hypot( xa, ya );
|
||||
double lenb = hypot( xb, yb );
|
||||
|
||||
// Make the final computations depending on the mode selected, chamfered or filleted.
|
||||
if( aMode == CORNER_MODE::CHAMFERED )
|
||||
{
|
||||
double distance = aDistance;
|
||||
|
||||
// Chamfer one half of an edge at most
|
||||
if( 0.5 * lena < distance )
|
||||
distance = 0.5 * lena;
|
||||
|
||||
if( 0.5 * lenb < distance )
|
||||
distance = 0.5 * lenb;
|
||||
|
||||
int nx1 = KiROUND( distance * xa / lena );
|
||||
int ny1 = KiROUND( distance * ya / lena );
|
||||
|
||||
newContour.Append( x1 + nx1, y1 + ny1 );
|
||||
|
||||
int nx2 = KiROUND( distance * xb / lenb );
|
||||
int ny2 = KiROUND( distance * yb / lenb );
|
||||
|
||||
newContour.Append( x1 + nx2, y1 + ny2 );
|
||||
}
|
||||
else // CORNER_MODE = FILLETED
|
||||
{
|
||||
double cosine = ( xa * xb + ya * yb ) / ( lena * lenb );
|
||||
|
||||
double radius = aDistance;
|
||||
double denom = sqrt( 2.0 / ( 1 + cosine ) - 1 );
|
||||
|
||||
// Do nothing in case of parallel edges
|
||||
if( std::isinf( denom ) )
|
||||
continue;
|
||||
|
||||
// Limit rounding distance to one half of an edge
|
||||
if( 0.5 * lena * denom < radius )
|
||||
radius = 0.5 * lena * denom;
|
||||
|
||||
if( 0.5 * lenb * denom < radius )
|
||||
radius = 0.5 * lenb * denom;
|
||||
|
||||
// Calculate fillet arc absolute center point (xc, yx)
|
||||
double k = radius / sqrt( .5 * ( 1 - cosine ) );
|
||||
double lenab = sqrt( ( xa / lena + xb / lenb ) * ( xa / lena + xb / lenb ) +
|
||||
( ya / lena + yb / lenb ) * ( ya / lena + yb / lenb ) );
|
||||
double xc = x1 + k * ( xa / lena + xb / lenb ) / lenab;
|
||||
double yc = y1 + k * ( ya / lena + yb / lenb ) / lenab;
|
||||
|
||||
// Calculate arc start and end vectors
|
||||
k = radius / sqrt( 2 / ( 1 + cosine ) - 1 );
|
||||
double xs = x1 + k * xa / lena - xc;
|
||||
double ys = y1 + k * ya / lena - yc;
|
||||
double xe = x1 + k * xb / lenb - xc;
|
||||
double ye = y1 + k * yb / lenb - yc;
|
||||
|
||||
// Cosine of arc angle
|
||||
double argument = ( xs * xe + ys * ye ) / ( radius * radius );
|
||||
|
||||
// Make sure the argument is in [-1,1], interval in which the acos function is
|
||||
// defined
|
||||
if( argument < -1 )
|
||||
argument = -1;
|
||||
else if( argument > 1 )
|
||||
argument = 1;
|
||||
|
||||
double arcAngle = acos( argument );
|
||||
int segments = GetArcToSegmentCount( radius, aErrorMax,
|
||||
EDA_ANGLE( arcAngle, RADIANS_T ) );
|
||||
|
||||
double deltaAngle = arcAngle / segments;
|
||||
double startAngle = atan2( -ys, xs );
|
||||
|
||||
// Flip arc for inner corners
|
||||
if( xa * yb - ya * xb <= 0 )
|
||||
deltaAngle *= -1;
|
||||
|
||||
double nx = xc + xs;
|
||||
double ny = yc + ys;
|
||||
|
||||
if( std::isnan( nx ) || std::isnan( ny ) )
|
||||
continue;
|
||||
|
||||
newContour.Append( KiROUND( nx ), KiROUND( ny ) );
|
||||
|
||||
// Store the previous added corner to make a sanity check
|
||||
int prevX = KiROUND( nx );
|
||||
int prevY = KiROUND( ny );
|
||||
|
||||
for( int j = 0; j < segments; j++ )
|
||||
{
|
||||
nx = xc + cos( startAngle + ( j + 1 ) * deltaAngle ) * radius;
|
||||
ny = yc - sin( startAngle + ( j + 1 ) * deltaAngle ) * radius;
|
||||
|
||||
if( std::isnan( nx ) || std::isnan( ny ) )
|
||||
continue;
|
||||
|
||||
// Sanity check: the rounding can produce repeated corners; do not add them.
|
||||
if( KiROUND( nx ) != prevX || KiROUND( ny ) != prevY )
|
||||
{
|
||||
newContour.Append( KiROUND( nx ), KiROUND( ny ) );
|
||||
prevX = KiROUND( nx );
|
||||
prevY = KiROUND( ny );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Close the current contour and add it the new polygon
|
||||
newContour.SetClosed( true );
|
||||
newPoly.push_back( newContour );
|
||||
}
|
||||
|
||||
return newPoly;
|
||||
}
|
||||
|
||||
|
||||
|
@ -57,9 +57,6 @@
|
||||
#include <geometry/shape_segment.h>
|
||||
#include <geometry/shape_circle.h>
|
||||
|
||||
// Do not keep this for release. Only for testing clipper
|
||||
#include <advanced_config.h>
|
||||
|
||||
#include <wx/log.h>
|
||||
|
||||
// ADVANCED_CFG::GetCfg() cannot be used on msys2/mingw builds (link failure)
|
||||
@ -2708,181 +2705,6 @@ SHAPE_POLY_SET SHAPE_POLY_SET::Fillet( int aRadius, int aErrorMax )
|
||||
}
|
||||
|
||||
|
||||
SHAPE_POLY_SET::POLYGON SHAPE_POLY_SET::chamferFilletPolygon( CORNER_MODE aMode,
|
||||
unsigned int aDistance,
|
||||
int aIndex, int aErrorMax )
|
||||
{
|
||||
// Null segments create serious issues in calculations. Remove them:
|
||||
RemoveNullSegments();
|
||||
|
||||
SHAPE_POLY_SET::POLYGON currentPoly = Polygon( aIndex );
|
||||
SHAPE_POLY_SET::POLYGON newPoly;
|
||||
|
||||
// If the chamfering distance is zero, then the polygon remain intact.
|
||||
if( aDistance == 0 )
|
||||
{
|
||||
return currentPoly;
|
||||
}
|
||||
|
||||
// Iterate through all the contours (outline and holes) of the polygon.
|
||||
for( SHAPE_LINE_CHAIN& currContour : currentPoly )
|
||||
{
|
||||
// Generate a new contour in the new polygon
|
||||
SHAPE_LINE_CHAIN newContour;
|
||||
|
||||
// Iterate through the vertices of the contour
|
||||
for( int currVertex = 0; currVertex < currContour.PointCount(); currVertex++ )
|
||||
{
|
||||
// Current vertex
|
||||
int x1 = currContour.CPoint( currVertex ).x;
|
||||
int y1 = currContour.CPoint( currVertex ).y;
|
||||
|
||||
// Indices for previous and next vertices.
|
||||
int prevVertex;
|
||||
int nextVertex;
|
||||
|
||||
// Previous and next vertices indices computation. Necessary to manage the edge cases.
|
||||
|
||||
// Previous vertex is the last one if the current vertex is the first one
|
||||
prevVertex = currVertex == 0 ? currContour.PointCount() - 1 : currVertex - 1;
|
||||
|
||||
// next vertex is the first one if the current vertex is the last one.
|
||||
nextVertex = currVertex == currContour.PointCount() - 1 ? 0 : currVertex + 1;
|
||||
|
||||
// Previous vertex computation
|
||||
double xa = currContour.CPoint( prevVertex ).x - x1;
|
||||
double ya = currContour.CPoint( prevVertex ).y - y1;
|
||||
|
||||
// Next vertex computation
|
||||
double xb = currContour.CPoint( nextVertex ).x - x1;
|
||||
double yb = currContour.CPoint( nextVertex ).y - y1;
|
||||
|
||||
// Avoid segments that will generate nans below
|
||||
if( std::abs( xa + xb ) < std::numeric_limits<double>::epsilon()
|
||||
&& std::abs( ya + yb ) < std::numeric_limits<double>::epsilon() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Compute the new distances
|
||||
double lena = hypot( xa, ya );
|
||||
double lenb = hypot( xb, yb );
|
||||
|
||||
// Make the final computations depending on the mode selected, chamfered or filleted.
|
||||
if( aMode == CORNER_MODE::CHAMFERED )
|
||||
{
|
||||
double distance = aDistance;
|
||||
|
||||
// Chamfer one half of an edge at most
|
||||
if( 0.5 * lena < distance )
|
||||
distance = 0.5 * lena;
|
||||
|
||||
if( 0.5 * lenb < distance )
|
||||
distance = 0.5 * lenb;
|
||||
|
||||
int nx1 = KiROUND( distance * xa / lena );
|
||||
int ny1 = KiROUND( distance * ya / lena );
|
||||
|
||||
newContour.Append( x1 + nx1, y1 + ny1 );
|
||||
|
||||
int nx2 = KiROUND( distance * xb / lenb );
|
||||
int ny2 = KiROUND( distance * yb / lenb );
|
||||
|
||||
newContour.Append( x1 + nx2, y1 + ny2 );
|
||||
}
|
||||
else // CORNER_MODE = FILLETED
|
||||
{
|
||||
double cosine = ( xa * xb + ya * yb ) / ( lena * lenb );
|
||||
|
||||
double radius = aDistance;
|
||||
double denom = sqrt( 2.0 / ( 1 + cosine ) - 1 );
|
||||
|
||||
// Do nothing in case of parallel edges
|
||||
if( std::isinf( denom ) )
|
||||
continue;
|
||||
|
||||
// Limit rounding distance to one half of an edge
|
||||
if( 0.5 * lena * denom < radius )
|
||||
radius = 0.5 * lena * denom;
|
||||
|
||||
if( 0.5 * lenb * denom < radius )
|
||||
radius = 0.5 * lenb * denom;
|
||||
|
||||
// Calculate fillet arc absolute center point (xc, yx)
|
||||
double k = radius / sqrt( .5 * ( 1 - cosine ) );
|
||||
double lenab = sqrt( ( xa / lena + xb / lenb ) * ( xa / lena + xb / lenb ) +
|
||||
( ya / lena + yb / lenb ) * ( ya / lena + yb / lenb ) );
|
||||
double xc = x1 + k * ( xa / lena + xb / lenb ) / lenab;
|
||||
double yc = y1 + k * ( ya / lena + yb / lenb ) / lenab;
|
||||
|
||||
// Calculate arc start and end vectors
|
||||
k = radius / sqrt( 2 / ( 1 + cosine ) - 1 );
|
||||
double xs = x1 + k * xa / lena - xc;
|
||||
double ys = y1 + k * ya / lena - yc;
|
||||
double xe = x1 + k * xb / lenb - xc;
|
||||
double ye = y1 + k * yb / lenb - yc;
|
||||
|
||||
// Cosine of arc angle
|
||||
double argument = ( xs * xe + ys * ye ) / ( radius * radius );
|
||||
|
||||
// Make sure the argument is in [-1,1], interval in which the acos function is
|
||||
// defined
|
||||
if( argument < -1 )
|
||||
argument = -1;
|
||||
else if( argument > 1 )
|
||||
argument = 1;
|
||||
|
||||
double arcAngle = acos( argument );
|
||||
int segments = GetArcToSegmentCount( radius, aErrorMax,
|
||||
EDA_ANGLE( arcAngle, RADIANS_T ) );
|
||||
|
||||
double deltaAngle = arcAngle / segments;
|
||||
double startAngle = atan2( -ys, xs );
|
||||
|
||||
// Flip arc for inner corners
|
||||
if( xa * yb - ya * xb <= 0 )
|
||||
deltaAngle *= -1;
|
||||
|
||||
double nx = xc + xs;
|
||||
double ny = yc + ys;
|
||||
|
||||
if( std::isnan( nx ) || std::isnan( ny ) )
|
||||
continue;
|
||||
|
||||
newContour.Append( KiROUND( nx ), KiROUND( ny ) );
|
||||
|
||||
// Store the previous added corner to make a sanity check
|
||||
int prevX = KiROUND( nx );
|
||||
int prevY = KiROUND( ny );
|
||||
|
||||
for( int j = 0; j < segments; j++ )
|
||||
{
|
||||
nx = xc + cos( startAngle + ( j + 1 ) * deltaAngle ) * radius;
|
||||
ny = yc - sin( startAngle + ( j + 1 ) * deltaAngle ) * radius;
|
||||
|
||||
if( std::isnan( nx ) || std::isnan( ny ) )
|
||||
continue;
|
||||
|
||||
// Sanity check: the rounding can produce repeated corners; do not add them.
|
||||
if( KiROUND( nx ) != prevX || KiROUND( ny ) != prevY )
|
||||
{
|
||||
newContour.Append( KiROUND( nx ), KiROUND( ny ) );
|
||||
prevX = KiROUND( nx );
|
||||
prevY = KiROUND( ny );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Close the current contour and add it the new polygon
|
||||
newContour.SetClosed( true );
|
||||
newPoly.push_back( newContour );
|
||||
}
|
||||
|
||||
return newPoly;
|
||||
}
|
||||
|
||||
|
||||
SHAPE_POLY_SET &SHAPE_POLY_SET::operator=( const SHAPE_POLY_SET& aOther )
|
||||
{
|
||||
SHAPE::operator=( aOther );
|
||||
|
Loading…
Reference in New Issue
Block a user