39    aStream << 
"Arc( P0=" << aArc.
GetP0() << 
" P1=" << aArc.
GetP1() << 
" Mid=" << aArc.
GetArcMid()
 
   40            << 
" Width=" << aArc.
GetWidth() << 
" )";
 
 
   46                      const EDA_ANGLE& aCenterAngle, 
int aWidth ) :
 
 
   67                      const VECTOR2I& aArcEnd, 
int aWidth ) :
 
 
  125    if( !p || aSegmentA.
Length() == 0 || aSegmentB.
Length() == 0 )
 
  128        wxASSERT_MSG( false, 
"The input segments do not intersect or one is zero length." );
 
  131        m_start = aSegmentA.A;
 
  135        VECTOR2I arcCenter = aSegmentA.Center();
 
  136        RotatePoint( m_mid, arcCenter, ANGLE_90 ); 
 
  140        VECTOR2I pToA = aSegmentA.B - *p;
 
  141        VECTOR2I pToB = aSegmentB.B - *p;
 
  143        if( pToA.EuclideanNorm() == 0 )
 
  144            pToA = aSegmentA.A - *p;
 
  146        if( pToB.EuclideanNorm() == 0 )
 
  147            pToB = aSegmentB.A - *p;
 
  149        EDA_ANGLE pToAangle( pToA );
 
  150        EDA_ANGLE pToBangle( pToB );
 
  152        EDA_ANGLE alpha = ( pToAangle - pToBangle ).Normalize180();
 
  154        double    distPC = (double) aRadius / abs( sin( alpha.AsRadians() / 2 ) );
 
  155        EDA_ANGLE angPC  = pToAangle - alpha / 2;
 
  158        arcCenter.x = p->x + KiROUND( distPC * angPC.Cos() );
 
  159        arcCenter.y = p->y + KiROUND( distPC * angPC.Sin() );
 
  163        m_start = aSegmentA.LineProject( arcCenter );
 
  164        m_end = aSegmentB.LineProject( arcCenter );
 
  167        VECTOR2I startVector = m_start - arcCenter;
 
  168        VECTOR2I endVector   = m_end - arcCenter;
 
  170        EDA_ANGLE startAngle( startVector );
 
  171        EDA_ANGLE endAngle( endVector );
 
  172        EDA_ANGLE midPointRotAngle = ( startAngle - endAngle ).Normalize180() / 2;
 
  175        RotatePoint( m_mid, arcCenter, midPointRotAngle );
 
 
  221                                                   const VECTOR2I& aCenter, 
bool aClockwise,
 
  224    VECTOR2I startLine = aStart - aCenter;
 
 
  257    return v1.ApproxCollinear( 
v2 ) && (
v1.B - 
v1.A).Dot(
v2.B - 
v2.A) > 0;
 
 
  270        && ( 
m_start - 
m_end ).SquaredEuclideanNorm() < clearance_sq )
 
  272        ecoord   a_dist_sq = ( aSeg.
A - 
center ).SquaredEuclideanNorm();
 
  273        ecoord   b_dist_sq = ( aSeg.
B - 
center ).SquaredEuclideanNorm();
 
  276        if( a_dist_sq < radius_sq && b_dist_sq < radius_sq )
 
  280        return circle.Collide( aSeg, aClearance, aActual, aLocation );
 
  289    std::vector<VECTOR2I> candidatePts = 
circle.GetCircle().Intersect( aSeg );
 
  294    candidatePts.push_back( aSeg.
A );
 
  295    candidatePts.push_back( aSeg.
B );
 
  297    bool any_collides = 
false;
 
  299    for( 
const VECTOR2I& candidate : candidatePts )
 
  301        bool collides = 
Collide( candidate, aClearance, aActual, aLocation );
 
  302        any_collides |= collides;
 
  304        if( collides && ( !aActual || *aActual == 0 ) )
 
 
  314    if( aSeg.
A == aSeg.
B )      
 
  319    std::vector<VECTOR2I> intersections = circ.
IntersectLine( aSeg );
 
  321    const size_t originalSize = aIpsBuffer->size();
 
  323    for( 
const VECTOR2I& intersection : intersections )
 
  326            aIpsBuffer->push_back( intersection );
 
  329    return aIpsBuffer->size() - originalSize;
 
 
  337    std::vector<VECTOR2I> intersections = thiscirc.
Intersect( aCircle );
 
  339    const size_t originalSize = aIpsBuffer->size();
 
  341    for( 
const VECTOR2I& intersection : intersections )
 
  344            aIpsBuffer->push_back( intersection );
 
  347    return aIpsBuffer->size() - originalSize;
 
 
  356    std::vector<VECTOR2I> intersections = thiscirc.
Intersect( othercirc );
 
  358    const size_t originalSize = aIpsBuffer->size();
 
  360    for( 
const VECTOR2I& intersection : intersections )
 
  363            aIpsBuffer->push_back( intersection );
 
  366    return aIpsBuffer->size() - originalSize;
 
 
  375    std::vector<VECTOR2I> points;
 
  378    points.push_back( 
m_end );
 
  384    if( start_angle > end_angle )
 
  385        std::swap( start_angle, end_angle );
 
  387    int quad_angle_start = std::ceil( start_angle.
AsDegrees() / 90.0 );
 
  388    int quad_angle_end = std::floor( end_angle.
AsDegrees() / 90.0 );
 
  393    if( 
m_radius < (
double)INT_MAX/2.0 )
 
  398        for( 
int quad_angle = quad_angle_start; quad_angle <= quad_angle_end; ++quad_angle )
 
  402            switch( quad_angle % 4 )
 
  404            case 0:          quad_pt += { 
radius, 0 };  
break;
 
  405            case 1: 
case -3: quad_pt += { 0, 
radius };  
break;
 
  406            case 2: 
case -2: quad_pt += { -
radius, 0 }; 
break;
 
  407            case 3: 
case -1: quad_pt += { 0, -
radius }; 
break;
 
  412            points.push_back( quad_pt );
 
 
  427    if( aClearance != 0 )
 
 
  436    const static int s_epsilon = 8;
 
  441    if( ( nearestPt - 
m_start ).SquaredEuclideanNorm() <= s_epsilon )
 
  444    if( ( nearestPt - 
m_end ).SquaredEuclideanNorm() <= s_epsilon )
 
  450    if( ( aP - 
m_start ).SquaredEuclideanNorm() <= ( aP - 
m_end ).SquaredEuclideanNorm() )
 
 
  458                               int64_t& aDistSq )
 const 
  462        aPtA = aPtB = 
GetP0();
 
  467    aDistSq = std::numeric_limits<int64_t>::max();
 
  471    std::vector<VECTOR2I> intersections = circle1.
Intersect( circle2 );
 
  473    for( 
const VECTOR2I& pt : intersections )
 
  492            if( distSq < aDistSq )
 
 
  515                               int64_t& aDistSq )
 const 
  517    aDistSq = std::numeric_limits<int64_t>::max();
 
  521    std::vector<VECTOR2I> intersections = 
circle.Intersect( aSeg );
 
  523    for( 
const VECTOR2I& pt : intersections )
 
  534    for( 
const VECTOR2I& pt : { aSeg.
A, aSeg.
B } )
 
  539            int64_t distSq = pt.SquaredDistance( nearestPt );
 
  541            if( distSq < aDistSq )
 
  556        if( distSq < aDistSq )
 
  572        if( distSq < aDistSq )
 
  576            aPtB = circleNearestPt;
 
 
  594                               int64_t& aDistSq )
 const 
  596    aDistSq = std::numeric_limits<int64_t>::max();
 
 
  608                               int64_t& aDistSq )
 const 
  610    auto adjustForArcWidths =
 
  618                dir = ( aPtA - aPtB ).Resize( aArc.
GetWidth() / 2 );
 
  627    aDistSq = std::numeric_limits<int64_t>::max();
 
  635    bool    colocated = center_dist_sq < center_epsilon * center_epsilon;
 
  639    std::vector<VECTOR2I> pts2 = { aArc.
GetP0(), aArc.
GetP1() };
 
  645            int64_t distSq = pt1.SquaredDistance( pt2 );
 
  647            if( distSq < aDistSq )
 
  665            aPtB = 
circle.NearestPoint( pt );
 
  668            if( colocated || aDistSq == 0 )
 
  671                    adjustForArcWidths();
 
  683            aPtA = 
circle.NearestPoint( pt );
 
  687            if( colocated || aDistSq == 0 )
 
  690                    adjustForArcWidths();
 
  705    std::vector<VECTOR2I> intersections = circle1.
Intersect( circle2 );
 
  707    for( 
const VECTOR2I& pt : intersections )
 
  724    if( pt1InSlice && pt2InSlice )
 
  728        if( distSq < aDistSq )
 
  735        adjustForArcWidths();
 
  744            int64_t distSq = pt.SquaredDistance( pt2 );
 
  746            if( distSq < aDistSq )
 
  760            int64_t distSq = pt.SquaredDistance( pt1 );
 
  762            if( distSq < aDistSq )
 
  771    adjustForArcWidths();
 
 
  779    int minDist = aClearance + 
m_width / 2;
 
  780    auto bbox = 
BBox( minDist );
 
  783    if( !bbox.Contains( aP ) )
 
  809        if( ( ccw && rotatedPtAngle > rotatedEndAngle )
 
  810            || ( !ccw && rotatedPtAngle < rotatedEndAngle ) )
 
  812            int distStartpt = ( aP - 
m_start ).EuclideanNorm();
 
  813            int distEndpt = ( aP - 
m_end ).EuclideanNorm();
 
  815            if( distStartpt < distEndpt )
 
  828    if( dist <= minDist )
 
  831            *aLocation = nearestPt;
 
  834            *aActual = std::max( 0, dist - 
m_width / 2 );
 
 
  919    double halfMaxError = std::max( 1.0, aMaxError / 2.0 );
 
  925    double external_radius = r + ( 
m_width / 2.0 );
 
  926    double effectiveError;
 
  928    if( external_radius < halfMaxError
 
  934        effectiveError = external_radius;
 
  941        int seg360 = n * 360.0 / fabs( ca.
AsDegrees() );
 
  948    r += effectiveError / 2;
 
  953    for( 
int i = 1; i < n ; i += 2 )
 
  960        double x = c.
x + r * a.
Cos();
 
  961        double y = c.
y + r * a.
Sin();
 
  969        *aActualError = 
KiROUND( effectiveError );
 
 
 1049        return phi >= sa && phi <= ea;
 
 1056        return phi <= sa && phi >= ea;
 
 
ERROR_LOC
When approximating an arc or circle, should the error be placed on the outside or inside of the curve...
 
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
 
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
 
Represent basic circle geometry with utility geometry functions.
 
VECTOR2I Center
Public to make access simpler.
 
std::vector< VECTOR2I > Intersect(const CIRCLE &aCircle) const
Compute the intersection points between this circle and aCircle.
 
std::vector< VECTOR2I > IntersectLine(const SEG &aLine) const
Compute the intersection points between this circle and aLine.
 
VECTOR2I NearestPoint(const VECTOR2I &aP) const
Compute the point on the circumference of the circle that is the closest to aP.
 
const VECTOR2I ReflectPoint(const VECTOR2I &aP) const
Reflect a point using this segment as axis.
 
const VECTOR2I NearestPoint(const VECTOR2I &aP) const
Compute a point on the segment (this) that is closest to point aP.
 
int Length() const
Return the length (this).
 
OPT_VECTOR2I Intersect(const SEG &aSeg, bool aIgnoreEndpoints=false, bool aLines=false) const
Compute intersection point of segment (this) with segment aSeg.
 
static SEG::ecoord Square(int a)
 
int Distance(const SEG &aSeg) const
Compute minimum Euclidean distance to segment aSeg.
 
EDA_ANGLE GetCentralAngle() const
Get the "central angle" of the arc - this is the angle at the point of the "pie slice".
 
const VECTOR2I & GetArcMid() const
 
void TransformToPolygon(SHAPE_POLY_SET &aBuffer, int aMaxError, ERROR_LOC aErrorLoc) const override
Fills a SHAPE_POLY_SET with a polygon representation of this shape.
 
void Move(const VECTOR2I &aVector) override
 
SHAPE_ARC & ConstructFromStartEndAngle(const VECTOR2I &aStart, const VECTOR2I &aEnd, const EDA_ANGLE &aAngle, double aWidth=0)
Construct this arc from the given start, end and angle.
 
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
 
int GetWidth() const override
 
EDA_ANGLE GetEndAngle() const
 
void Rotate(const EDA_ANGLE &aAngle, const VECTOR2I &aCenter) override
Rotate the arc by a given angle about a point.
 
bool sliceContainsPoint(const VECTOR2I &p) const
 
const SHAPE_LINE_CHAIN ConvertToPolyline(int aMaxError=DefaultAccuracyForPCB(), int *aActualError=nullptr) const
Construct a SHAPE_LINE_CHAIN of segments from a given arc.
 
VECTOR2I NearestPoint(const VECTOR2I &aP) const
 
int Intersect(const CIRCLE &aArc, std::vector< VECTOR2I > *aIpsBuffer) const
Find intersection points between this arc and a CIRCLE.
 
SHAPE_ARC & ConstructFromStartEndCenter(const VECTOR2I &aStart, const VECTOR2I &aEnd, const VECTOR2I &aCenter, bool aClockwise=false, double aWidth=0)
Constructs this arc from the given start, end and center.
 
void Mirror(const VECTOR2I &aRef, FLIP_DIRECTION aFlipDirection)
 
SHAPE_ARC Reversed() const
 
const VECTOR2I & GetP1() const
 
int IntersectLine(const SEG &aSeg, std::vector< VECTOR2I > *aIpsBuffer) const
Find intersection points between this arc and aSeg, treating aSeg as an infinite line.
 
bool Collide(const SEG &aSeg, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const override
Check if the boundary of shape (this) lies closer to the segment aSeg than aClearance,...
 
EDA_ANGLE GetStartAngle() const
 
bool IsEffectiveLine() const
 
bool NearestPoints(const SHAPE_ARC &aArc, VECTOR2I &aPtA, VECTOR2I &aPtB, int64_t &aDistSq) const
Compute closest points between this arc and aArc.
 
const VECTOR2I & GetP0() const
 
const VECTOR2I & GetCenter() const
 
const CIRCLE GetCircle() const
 
const VECTOR2I GetCenter() const
 
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
 
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
 
Represent a set of closed polygons.
 
const SHAPE_LINE_CHAIN Outline() const
 
VECTOR2I::extended_type ecoord
 
SHAPE(SHAPE_TYPE aType)
Create an empty shape of type aType.
 
bool NearestPoints(const SHAPE *aOther, VECTOR2I &aPtThis, VECTOR2I &aPtOther) const
Return the two points that mark the closest distance between this shape and aOther.
 
double Distance(const VECTOR2< extended_type > &aVector) const
Compute the distance between two vectors.
 
constexpr extended_type SquaredDistance(const VECTOR2< T > &aVector) const
Compute the squared distance between two vectors.
 
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
 
void TransformArcToPolygon(SHAPE_POLY_SET &aBuffer, const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc)
Convert arc to multiple straight segments.
 
static constexpr EDA_ANGLE ANGLE_0
 
static constexpr EDA_ANGLE ANGLE_360
 
a few functions useful in geometry calculations.
 
int CircleToEndSegmentDeltaRadius(int aInnerCircleRadius, int aSegCount)
 
int GetArcToSegmentCount(int aRadius, int aErrorMax, const EDA_ANGLE &aArcAngle)
 
@ LEFT_RIGHT
Flip left to right (around the Y axis)
 
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
 
std::optional< VECTOR2I > OPT_VECTOR2I
 
std::ostream & operator<<(std::ostream &aStream, const SHAPE_ARC &aArc)
 
SHAPE_CIRCLE circle(c.m_circle_center, c.m_circle_radius)
 
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
 
const VECTOR2I CalcArcCenter(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Determine the center of an arc or circle given three points on its circumference.
 
VECTOR2< int32_t > VECTOR2I
 
VECTOR2< double > VECTOR2D
 
VECTOR2< int64_t > VECTOR2L