41SEG GetBisectorOfCornerSegments( 
const SEG& aSegA, 
const SEG& aSegB, 
int aLength )
 
   49    const auto getSegVectorPointingAwayFrom = []( 
const SEG&      aSeg,
 
   52        const int distA = ( aSeg.
A - aPoint ).EuclideanNorm();
 
   53        const int distB = ( aSeg.
B - aPoint ).EuclideanNorm();
 
   57        return ( distA < distB ) ? ( aSeg.
B - aSeg.
A ) : ( aSeg.
A - aSeg.
B );
 
   61    const int      maxLen = std::max( aSegA.
Length(), aSegB.
Length() );
 
   62    const VECTOR2I aVecOutward = getSegVectorPointingAwayFrom( aSegA, *corner ).Resize( maxLen );
 
   63    const VECTOR2I bVecOutward = getSegVectorPointingAwayFrom( aSegB, *corner ).Resize( maxLen );
 
   64    const VECTOR2I bisectorOutward = aVecOutward + bVecOutward;
 
   66    return SEG( *corner, *corner + bisectorOutward.
Resize( aLength ) );
 
   77    if( line_a_setback == 0 && line_b_setback == 0 )
 
   85    if( aSegA.
Length() < line_a_setback || aSegB.
Length() < line_b_setback )
 
  109    SEG setback_a( *corner, *corner + 
VECTOR2I( a_end_pt - *corner ).Resize( line_a_setback ) );
 
  110    SEG setback_b( *corner, *corner + 
VECTOR2I( b_end_pt - *corner ).Resize( line_b_setback ) );
 
  117    std::optional<SEG> new_a;
 
  122    std::optional<SEG> new_b;
 
 
  132                                              int aDogboneRadius, 
bool aAddSlots )
 
  142    const SEG bisector = GetBisectorOfCornerSegments( aSegA, aSegB, aDogboneRadius );
 
  145    const VECTOR2I dogboneCenter = bisector.
B;
 
  152    const std::vector<VECTOR2I> segAIntersections = 
circle.Intersect( aSegA );
 
  153    const std::vector<VECTOR2I> segBIntersections = 
circle.Intersect( aSegB );
 
  156    static int s_epsilon = 8;
 
  158    const auto getPointNotOnCorner =
 
  159            [&]( 
const std::vector<VECTOR2I>& aIntersections, 
const VECTOR2I& aCorner )
 
  161        std::optional<VECTOR2I> 
result;
 
  162        for( 
const VECTOR2I& pt : aIntersections )
 
  164            if( aCorner.Distance( pt ) > s_epsilon )
 
  173    const std::optional<VECTOR2I> ptOnSegA = getPointNotOnCorner( segAIntersections, *corner );
 
  174    const std::optional<VECTOR2I> ptOnSegB = getPointNotOnCorner( segBIntersections, *corner );
 
  177    if( !ptOnSegA || !ptOnSegB )
 
  182    SHAPE_ARC arc( *ptOnSegA, *corner, *ptOnSegB, 0 );
 
  193        std::optional<SEG> new_a, new_b;
 
  194        if( aOtherPtA != *ptOnSegA )
 
  195            new_a = 
SEG{ aOtherPtA, *ptOnSegA };
 
  197        if( aOtherPtB != *ptOnSegB )
 
  198            new_b = 
SEG{ aOtherPtB, *ptOnSegB };
 
  201        if( !small_arc_mouth || !aAddSlots )
 
  227        slotArc.
GetP0() + ( dogboneCenter - *corner ),
 
  231        slotArc.
GetP1() + ( dogboneCenter - *corner ),
 
  234    const OPT_VECTOR2I ext_a_intersect = arc_extension_a.Intersect( aSegA );
 
  235    const OPT_VECTOR2I ext_b_intersect = arc_extension_b.Intersect( aSegB );
 
  237    if( !ext_a_intersect || !ext_b_intersect )
 
  246        std::optional<SEG> new_a, new_b;
 
  247        if( aOtherPtA != *ext_a_intersect )
 
  248            new_a = 
SEG{ aOtherPtA, *ext_a_intersect };
 
  250        if( aOtherPtB != *ext_b_intersect )
 
  251            new_b = 
SEG{ aOtherPtB, *ext_b_intersect };
 
 
  264                                                              unsigned int aDistance,
 
  265                                                              int aIndex, 
int aErrorMax )
 
  286        for( 
int currVertex = 0; currVertex < currContour.PointCount(); currVertex++ )
 
  289            int x1 = currContour.CPoint( currVertex ).x;
 
  290            int y1 = currContour.CPoint( currVertex ).y;
 
  299            prevVertex = currVertex == 0 ? currContour.PointCount() - 1 : currVertex - 1;
 
  302            nextVertex = currVertex == currContour.PointCount() - 1 ? 0 : currVertex + 1;
 
  305            double xa = currContour.CPoint( prevVertex ).x - x1;
 
  306            double ya = currContour.CPoint( prevVertex ).y - y1;
 
  309            double xb = currContour.CPoint( nextVertex ).x - x1;
 
  310            double yb = currContour.CPoint( nextVertex ).y - y1;
 
  313            if( 
std::abs( xa + xb ) < std::numeric_limits<double>::epsilon()
 
  314                    && 
std::abs( ya + yb ) < std::numeric_limits<double>::epsilon() )
 
  320            double  lena    = hypot( xa, ya );
 
  321            double  lenb    = hypot( xb, yb );
 
  338                newContour.
Append( x1 + nx1, y1 + ny1 );
 
  343                newContour.
Append( x1 + nx2, y1 + ny2 );
 
  347                double cosine = ( xa * xb + ya * yb ) / ( lena * lenb );
 
  349                double  radius  = aDistance;
 
  350                double  denom   = sqrt( 2.0 / ( 1 + cosine ) - 1 );
 
  353                if( std::isinf( denom ) )
 
  357                if( 0.5 * lena * denom < 
radius )
 
  358                    radius = 0.5 * lena * denom;
 
  360                if( 0.5 * lenb * denom < 
radius )
 
  361                    radius = 0.5 * lenb * denom;
 
  364                double  k = 
radius / sqrt( .5 * ( 1 - cosine ) );
 
  365                double  lenab = sqrt( ( xa / lena + xb / lenb ) * ( xa / lena + xb / lenb ) +
 
  366                        ( ya / lena + yb / lenb ) * ( ya / lena + yb / lenb ) );
 
  367                double  xc  = x1 + k * ( xa / lena + xb / lenb ) / lenab;
 
  368                double  yc  = y1 + k * ( ya / lena + yb / lenb ) / lenab;
 
  371                k = 
radius / sqrt( 2 / ( 1 + cosine ) - 1 );
 
  372                double  xs  = x1 + k * xa / lena - xc;
 
  373                double  ys  = y1 + k * ya / lena - yc;
 
  374                double  xe  = x1 + k * xb / lenb - xc;
 
  375                double  ye  = y1 + k * yb / lenb - yc;
 
  378                double argument = ( xs * xe + ys * ye ) / ( 
radius * 
radius );
 
  384                else if( argument > 1 )
 
  387                double arcAngle = acos( argument );
 
  391                double deltaAngle = arcAngle / segments;
 
  392                double startAngle = atan2( -ys, xs );
 
  395                if( xa * yb - ya * xb <= 0 )
 
  401                if( std::isnan( nx ) || std::isnan( ny ) )
 
  410                for( 
int j = 0; j < segments; j++ )
 
  412                    nx = xc + cos( startAngle + ( j + 1 ) * deltaAngle ) * 
radius;
 
  413                    ny = yc - sin( startAngle + ( j + 1 ) * deltaAngle ) * 
radius;
 
  415                    if( std::isnan( nx ) || std::isnan( ny ) )
 
  431        newPoly.push_back( newContour );
 
 
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
 
Represent basic circle geometry with utility geometry functions.
 
bool IsHorizontal() const
 
int Length() const
Return the length (this).
 
EDA_ANGLE Angle(const SEG &aOther) const
Determine the smallest angle between two segments.
 
EDA_ANGLE GetCentralAngle() const
Get the "central angle" of the arc - this is the angle at the point of the "pie slice".
 
const VECTOR2I & GetP1() const
 
const VECTOR2I & GetP0() const
 
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
 
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
 
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
 
CORNER_MODE
Operation ChamferPolygon and FilletPolygon are computed under the private chamferFillet method; this ...
 
POLYGON & Polygon(int aIndex)
Return the aIndex-th subpolygon in the set.
 
int RemoveNullSegments()
Look for null segments; ie, segments whose ends are exactly the same and deletes them.
 
std::vector< SHAPE_LINE_CHAIN > POLYGON
represents a single polygon outline with holes.
 
POLYGON chamferFilletPolygon(CORNER_MODE aMode, unsigned int aDistance, int aIndex, int aErrorMax)
Return the chamfered or filleted version of the aIndex-th polygon in the set, depending on the aMode ...
 
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
 
std::optional< CHAMFER_RESULT > ComputeChamferPoints(const SEG &aSegA, const SEG &aSegB, const CHAMFER_PARAMS &aChamferParams)
Compute the chamfer points for a given line pair and chamfer parameters.
 
std::optional< DOGBONE_RESULT > ComputeDogbone(const SEG &aSegA, const SEG &aSegB, int aDogboneRadius, bool aAddSlots)
Compute the dogbone geometry for a given line pair and dogbone parameters.
 
static constexpr EDA_ANGLE ANGLE_90
 
static constexpr EDA_ANGLE ANGLE_180
 
a few functions useful in geometry calculations.
 
int GetArcToSegmentCount(int aRadius, int aErrorMax, const EDA_ANGLE &aArcAngle)
 
OPT_VECTOR2I GetSharedEndpoint(const SEG &aSegA, const SEG &aSegB)
Get the shared endpoint of two segments, if it exists, or std::nullopt if the segments are not connec...
 
bool PointsAreInSameDirection(const VECTOR2< T > &aPointA, const VECTOR2< T > &aPointB, const VECTOR2< T > &aFrom)
Check that the two given points are in the same direction from some other point.
 
const VECTOR2I & GetOtherEnd(const SEG &aSeg, const VECTOR2I &aPoint)
Get the end point of the segment that is not the given point.
 
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
 
static float distance(const SFVEC2UI &a, const SFVEC2UI &b)
 
std::optional< VECTOR2I > OPT_VECTOR2I
 
Utility functions for working with shapes.
 
Parameters that define a simple chamfer operation.
 
int m_chamfer_setback_b
Chamfer set-back distance along the second line.
 
int m_chamfer_setback_a
Chamfer set-back distance along the first line.
 
SHAPE_CIRCLE circle(c.m_circle_center, c.m_circle_radius)
 
wxString result
Test unit parsing edge cases and error handling.
 
VECTOR2I GetRotated(const VECTOR2I &aVector, const EDA_ANGLE &aAngle)
Return a new VECTOR2I that is the result of rotating aVector by aAngle.
 
VECTOR2< int32_t > VECTOR2I
 
Supplemental functions for working with vectors and simple objects that interact with vectors.