35double crossZ(
double aX,
double aY,
double bX,
double bY )
37 const double p = aY * bX;
38 const double e = std::fma( aY, bX, -p );
39 return std::fma( aX, bY, -p ) - e;
46 constexpr double limit = std::numeric_limits<int>::max() - 1;
48 if( !std::isfinite( aPt.
x ) || !std::isfinite( aPt.
y ) ||
std::abs( aPt.
x ) > limit
67 const VECTOR2D chord(
static_cast<double>( aEnd.
x ) - aStart.
x,
static_cast<double>( aEnd.
y ) - aStart.
y );
68 const double len = chord.EuclideanNorm();
70 if( len <= 0.0 || !std::isfinite( aRadius ) || aRadius <= 0.0 )
74 const VECTOR2D chordMid( (
static_cast<double>( aStart.
x ) + aEnd.
x ) * 0.5,
75 (
static_cast<double>( aStart.
y ) + aEnd.
y ) * 0.5 );
76 const double half = len * 0.5;
77 const double offset =
std::abs( aCenterT );
80 const double height = aSide * aCenterT <= 0.0 ? half * half / ( aRadius + offset ) : aRadius + offset;
82 if( !toIU( chordMid +
normal * ( aSide * height ), sol.mid ) )
86 if( crossZ( chord.x, chord.y,
static_cast<double>( sol.mid.x ) - aStart.
x,
87 static_cast<double>( sol.mid.y ) - aStart.
y ) == 0.0 )
92 sol.center = chordMid +
normal * aCenterT;
103 const VECTOR2D chord(
static_cast<double>( aEnd.
x ) - aStart.
x,
static_cast<double>( aEnd.
y ) - aStart.
y );
110 const VECTOR2D chordMid( (
static_cast<double>( aStart.
x ) + aEnd.
x ) * 0.5,
111 (
static_cast<double>( aStart.
y ) + aEnd.
y ) * 0.5 );
112 const VECTOR2D rel( aCursor.
x - chordMid.
x, aCursor.
y - chordMid.
y );
125 const VECTOR2D b(
static_cast<double>( aEnd.
x ) - aStart.
x,
static_cast<double>( aEnd.
y ) - aStart.
y );
126 const VECTOR2D c(
static_cast<double>( aOnArc.
x ) - aStart.
x,
static_cast<double>( aOnArc.
y ) - aStart.
y );
127 const double d = crossZ( b.
x, b.
y, c.
x, c.
y );
136 const VECTOR2D rel( ( c.
y * bb - b.
y * cc ) / ( 2.0 * d ), ( b.
x * cc - c.
x * bb ) / ( 2.0 * d ) );
140 const double centerT = ( -rel.
x * b.
y + rel.
y * b.
x ) / len;
142 return buildOnChord( aStart, aEnd, d > 0.0 ? 1.0 : -1.0, centerT, rel.
EuclideanNorm() );
162 const VECTOR2D chord(
static_cast<double>( aEnd.
x ) - aStart.
x,
static_cast<double>( aEnd.
y ) - aStart.
y );
169 const VECTOR2D chordMid( (
static_cast<double>( aStart.
x ) + aEnd.
x ) * 0.5,
170 (
static_cast<double>( aStart.
y ) + aEnd.
y ) * 0.5 );
174 double side = centerT < 0.0 ? -1.0 : 1.0;
179 return buildOnChord( aStart, aEnd, side, centerT, std::hypot( len * 0.5, centerT ) );
187 if( tangentLen <= 0.0 || !std::isfinite( tangentLen ) )
190 const VECTOR2D t( aTangent.
x / tangentLen, aTangent.
y / tangentLen );
191 const VECTOR2D d(
static_cast<double>( aEnd.
x ) - aStart.
x,
static_cast<double>( aEnd.
y ) - aStart.
y );
193 const double cross = crossZ( d.
x, d.
y, t.
x, t.
y );
195 if( dd <= 0.0 || cross == 0.0 )
199 const double k = -dd / ( 2.0 * cross );
201 const double len = std::sqrt( dd );
202 const VECTOR2D chordNormal( -d.
y / len, d.
x / len );
204 return buildOnChord( aStart, aEnd, cross > 0.0 ? 1.0 : -1.0, k * n.
Dot( chordNormal ),
std::abs( k ) );
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
constexpr extended_type SquaredEuclideanNorm() const
Compute the squared euclidean norm of the vector, which is defined as (x ** 2 + y ** 2).
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
constexpr extended_type Dot(const VECTOR2< T > &aVector) const
Compute dot product of self with aVector.
Construction helpers for the interactive arc drawing modes.
ARC_SOLUTION ArcFromStartEndCenterDrag(const VECTOR2I &aStart, const VECTOR2I &aEnd, const VECTOR2I &aCursor, bool aMajor)
Arc from aStart to aEnd centered on aCursor projected onto the chord bisector.
VECTOR2I ProjectToChordBisector(const VECTOR2I &aStart, const VECTOR2I &aEnd, const VECTOR2I &aCursor)
Project aCursor onto the perpendicular bisector of the chord aStart - aEnd.
ARC_SOLUTION ArcFromStartTangentEnd(const VECTOR2I &aStart, const VECTOR2D &aTangent, const VECTOR2I &aEnd)
Arc leaving aStart along aTangent and ending at aEnd.
ARC_SOLUTION ArcFromStartEndMidDrag(const VECTOR2I &aStart, const VECTOR2I &aEnd, const VECTOR2I &aCursor)
Arc from aStart to aEnd whose midpoint is aCursor projected onto the chord bisector.
ARC_SOLUTION ArcThroughPoints(const VECTOR2I &aStart, const VECTOR2I &aOnArc, const VECTOR2I &aEnd)
Arc from aStart to aEnd that passes through aOnArc.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
bool valid
False for degenerate input (collinear points, zero chord, etc)
VECTOR2I mid
The point on the arc halfway along the sweep.
VECTOR2< int32_t > VECTOR2I
VECTOR2< double > VECTOR2D