KiCad PCB EDA Suite
shape_arc.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2017 CERN
5 * Copyright (C) 2019-2022 KiCad Developers, see AUTHORS.txt for contributors.
6 * @author Tomasz Wlostowski <[email protected]>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26#include <core/kicad_algo.h>
27#include <geometry/circle.h>
29#include <geometry/seg.h> // for SEG
30#include <geometry/shape_arc.h>
32#include <trigo.h>
33
34
35std::ostream& operator<<( std::ostream& aStream, const SHAPE_ARC& aArc )
36{
37 aStream << "Arc( P0=" << aArc.GetP0() << " P1=" << aArc.GetP1() << " Mid=" << aArc.GetArcMid()
38 << " Width=" << aArc.GetWidth() << " )";
39 return aStream;
40}
41
42
43SHAPE_ARC::SHAPE_ARC( const VECTOR2I& aArcCenter, const VECTOR2I& aArcStartPoint,
44 const EDA_ANGLE& aCenterAngle, int aWidth ) :
45 SHAPE( SH_ARC ),
46 m_width( aWidth )
47{
48 m_start = aArcStartPoint;
49
50 VECTOR2D mid = aArcStartPoint;
51 VECTOR2D end = aArcStartPoint;
52 VECTOR2D center = aArcCenter;
53
54 RotatePoint( mid, center, -aCenterAngle / 2.0 );
55 RotatePoint( end, center, -aCenterAngle );
56
57 m_mid = VECTOR2I( KiROUND( mid.x ), KiROUND( mid.y ) );
58 m_end = VECTOR2I( KiROUND( end.x ), KiROUND( end.y ) );
59
61}
62
63
64SHAPE_ARC::SHAPE_ARC( const VECTOR2I& aArcStart, const VECTOR2I& aArcMid,
65 const VECTOR2I& aArcEnd, int aWidth ) :
66 SHAPE( SH_ARC ),
67 m_start( aArcStart ),
68 m_mid( aArcMid ),
69 m_end( aArcEnd ),
70 m_width( aWidth )
71{
73}
74
75
76SHAPE_ARC::SHAPE_ARC( const SEG& aSegmentA, const SEG& aSegmentB, int aRadius, int aWidth ) :
77 SHAPE( SH_ARC )
78{
79 m_width = aWidth;
80
81 /*
82 * Construct an arc that is tangent to two segments with a given radius.
83 *
84 * p
85 * A
86 * A \
87 * / \
88 * / . . \ segB
89 * /. .\
90 * segA / c \
91 * / B
92 * /
93 * /
94 * B
95 *
96 *
97 * segA is the fist segment (with its points A and B)
98 * segB is the second segment (with its points A and B)
99 * p is the point at which segA and segB would intersect if they were projected
100 * c is the centre of the arc to be constructed
101 * rad is the radius of the arc to be constructed
102 *
103 * We can create two vectors, between point p and segA /segB
104 * pToA = p - segA.B //< note that segA.A would also be valid as it is colinear
105 * pToB = p - segB.B //< note that segB.A would also be valid as it is colinear
106 *
107 * Let the angle formed by segA and segB be called 'alpha':
108 * alpha = angle( pToA ) - angle( pToB )
109 *
110 * The distance PC can be computed as
111 * distPC = rad / abs( sin( alpha / 2 ) )
112 *
113 * The polar angle of the vector PC can be computed as:
114 * anglePC = angle( pToA ) + alpha / 2
115 *
116 * Therefore:
117 * C.x = P.x + distPC*cos( anglePC )
118 * C.y = P.y + distPC*sin( anglePC )
119 */
120
121 OPT_VECTOR2I p = aSegmentA.Intersect( aSegmentB, true, true );
122
123 if( !p || aSegmentA.Length() == 0 || aSegmentB.Length() == 0 )
124 {
125 // Catch bugs in debug
126 wxASSERT_MSG( false, "The input segments do not intersect or one is zero length." );
127
128 // Make a 180 degree arc around aSegmentA in case we end up here in release
129 m_start = aSegmentA.A;
130 m_end = aSegmentA.B;
131 m_mid = m_start;
132
133 VECTOR2I arcCenter = aSegmentA.Center();
134 RotatePoint( m_mid, arcCenter, ANGLE_90 ); // mid point at 90 degrees
135 }
136 else
137 {
138 VECTOR2I pToA = aSegmentA.B - *p;
139 VECTOR2I pToB = aSegmentB.B - *p;
140
141 if( pToA.EuclideanNorm() == 0 )
142 pToA = aSegmentA.A - *p;
143
144 if( pToB.EuclideanNorm() == 0 )
145 pToB = aSegmentB.A - *p;
146
147 EDA_ANGLE pToAangle( pToA );
148 EDA_ANGLE pToBangle( pToB );
149
150 EDA_ANGLE alpha = ( pToAangle - pToBangle ).Normalize180();
151
152 double distPC = (double) aRadius / abs( sin( alpha.AsRadians() / 2 ) );
153 EDA_ANGLE angPC = pToAangle - alpha / 2;
154 VECTOR2I arcCenter;
155
156 arcCenter.x = p->x + KiROUND( distPC * angPC.Cos() );
157 arcCenter.y = p->y + KiROUND( distPC * angPC.Sin() );
158
159 // The end points of the arc are the orthogonal projected lines from the line segments
160 // to the center of the arc
161 m_start = aSegmentA.LineProject( arcCenter );
162 m_end = aSegmentB.LineProject( arcCenter );
163
164 //The mid point is rotated start point around center, half the angle of the arc.
165 VECTOR2I startVector = m_start - arcCenter;
166 VECTOR2I endVector = m_end - arcCenter;
167
168 EDA_ANGLE startAngle( startVector );
169 EDA_ANGLE endAngle( endVector );
170 EDA_ANGLE midPointRotAngle = ( startAngle - endAngle ).Normalize180() / 2;
171
172 m_mid = m_start;
173 RotatePoint( m_mid, arcCenter, midPointRotAngle );
174 }
175
176 update_bbox();
177}
178
179
181 : SHAPE( SH_ARC )
182{
183 m_start = aOther.m_start;
184 m_end = aOther.m_end;
185 m_mid = aOther.m_mid;
186 m_width = aOther.m_width;
187 m_bbox = aOther.m_bbox;
188}
189
190
192 const EDA_ANGLE& aAngle, double aWidth )
193{
194 m_start = aStart;
195 m_mid = aStart;
196 m_end = aEnd;
197 m_width = aWidth;
198
199 VECTOR2I center( CalcArcCenter( aStart, aEnd, aAngle ) );
200
201 RotatePoint( m_mid, center, -aAngle / 2.0 );
202
203 update_bbox();
204
205 return *this;
206}
207
208
210 const VECTOR2I& aCenter, bool aClockwise,
211 double aWidth )
212{
213 VECTOR2I startLine = aStart - aCenter;
214 VECTOR2I endLine = aEnd - aCenter;
215
216 EDA_ANGLE startAngle( startLine );
217 EDA_ANGLE endAngle( endLine );
218
219 startAngle.Normalize();
220 endAngle.Normalize();
221
222 EDA_ANGLE angle = endAngle - startAngle;
223
224 if( aClockwise )
225 angle = angle.Normalize() - ANGLE_360;
226 else
227 angle = angle.Normalize();
228
229 m_start = aStart;
230 m_end = aEnd;
231 m_mid = aStart;
232
233 RotatePoint( m_mid, aCenter, -angle / 2.0 );
234
235 update_bbox();
236
237 return *this;
238}
239
240
241bool SHAPE_ARC::Collide( const SEG& aSeg, int aClearance, int* aActual, VECTOR2I* aLocation ) const
242{
243 if( aSeg.A == aSeg.B )
244 return Collide( aSeg.A, aClearance, aActual, aLocation );
245
246 VECTOR2I center = GetCenter();
247 CIRCLE circle( center, GetRadius() );
248
249 // Possible points of the collision are:
250 // 1. Intersetion of the segment with the full circle
251 // 2. Closest point on the segment to the center of the circle
252 // 3. Closest point on the segment to the end points of the arc
253 // 4. End points of the segment
254
255 std::vector<VECTOR2I> candidatePts = circle.Intersect( aSeg );
256
257 candidatePts.push_back( aSeg.NearestPoint( center ) );
258 candidatePts.push_back( aSeg.NearestPoint( m_start ) );
259 candidatePts.push_back( aSeg.NearestPoint( m_end ) );
260 candidatePts.push_back( aSeg.A );
261 candidatePts.push_back( aSeg.B );
262
263 for( const VECTOR2I& candidate : candidatePts )
264 {
265 if( Collide( candidate, aClearance, aActual, aLocation ) )
266 return true;
267 }
268
269 return false;
270}
271
272
273int SHAPE_ARC::IntersectLine( const SEG& aSeg, std::vector<VECTOR2I>* aIpsBuffer ) const
274{
275 if( aSeg.A == aSeg.B ) // One point does not define a line....
276 return 0;
277
278 CIRCLE circ( GetCenter(), GetRadius() );
279
280 std::vector<VECTOR2I> intersections = circ.IntersectLine( aSeg );
281
282 size_t originalSize = aIpsBuffer->size();
283
284 for( const VECTOR2I& intersection : intersections )
285 {
286 if( sliceContainsPoint( intersection ) )
287 aIpsBuffer->push_back( intersection );
288 }
289
290 return aIpsBuffer->size() - originalSize;
291}
292
293
294int SHAPE_ARC::Intersect( const SHAPE_ARC& aArc, std::vector<VECTOR2I>* aIpsBuffer ) const
295{
296 CIRCLE thiscirc( GetCenter(), GetRadius() );
297 CIRCLE othercirc( aArc.GetCenter(), aArc.GetRadius() );
298
299 std::vector<VECTOR2I> intersections = thiscirc.Intersect( othercirc );
300
301 size_t originalSize = aIpsBuffer->size();
302
303 for( const VECTOR2I& intersection : intersections )
304 {
305 if( sliceContainsPoint( intersection ) && aArc.sliceContainsPoint( intersection ) )
306 aIpsBuffer->push_back( intersection );
307 }
308
309 return aIpsBuffer->size() - originalSize;
310}
311
312
314{
315 std::vector<VECTOR2I> points;
316 // Put start and end points in the point list
317 points.push_back( m_start );
318 points.push_back( m_end );
319
320 EDA_ANGLE start_angle = GetStartAngle();
321 EDA_ANGLE end_angle = start_angle + GetCentralAngle();
322
323 // we always count quadrants clockwise (increasing angle)
324 if( start_angle > end_angle )
325 std::swap( start_angle, end_angle );
326
327 int quad_angle_start = std::ceil( start_angle.AsDegrees() / 90.0 );
328 int quad_angle_end = std::floor( end_angle.AsDegrees() / 90.0 );
329
330 VECTOR2I center = GetCenter();
331 const int radius = KiROUND( GetRadius() );
332
333 // count through quadrants included in arc
334 for( int quad_angle = quad_angle_start; quad_angle <= quad_angle_end; ++quad_angle )
335 {
336 VECTOR2I quad_pt = center;
337
338 switch( quad_angle % 4 )
339 {
340 case 0: quad_pt += { radius, 0 }; break;
341 case 1: case -3: quad_pt += { 0, radius }; break;
342 case 2: case -2: quad_pt += { -radius, 0 }; break;
343 case 3: case -1: quad_pt += { 0, -radius }; break;
344 default:
345 assert( false );
346 }
347
348 points.push_back( quad_pt );
349 }
350
351 m_bbox.Compute( points );
352}
353
354
355const BOX2I SHAPE_ARC::BBox( int aClearance ) const
356{
357 BOX2I bbox( m_bbox );
358
359 if( aClearance != 0 )
360 bbox.Inflate( aClearance );
361
362 return bbox;
363}
364
365
367{
368 return GetCentralAngle() < ANGLE_0;
369}
370
371
372bool SHAPE_ARC::Collide( const VECTOR2I& aP, int aClearance, int* aActual,
373 VECTOR2I* aLocation ) const
374{
375 int minDist = aClearance + m_width / 2;
376 auto bbox = BBox( minDist );
377
378 // Fast check using bounding box:
379 if( !bbox.Contains( aP ) )
380 return false;
381
382 CIRCLE fullCircle( GetCenter(), GetRadius() );
383 VECTOR2I nearestPt = fullCircle.NearestPoint( aP );
384
385 int dist = ( nearestPt - aP ).EuclideanNorm();
386
387 // If not a 360 degree arc, need to use arc angles to decide if point collides
388 if( m_start != m_end )
389 {
390 bool ccw = GetCentralAngle() > ANGLE_0;
391 EDA_ANGLE angleToPt( aP - fullCircle.Center ); // Angle from center to the point
392 EDA_ANGLE rotatedPtAngle = ( angleToPt.Normalize() - GetStartAngle() ).Normalize();
393 EDA_ANGLE rotatedEndAngle = ( GetEndAngle() - GetStartAngle() ).Normalize();
394
395 if( ( ccw && rotatedPtAngle > rotatedEndAngle )
396 || ( !ccw && rotatedPtAngle < rotatedEndAngle ) )
397 {
398 int distStartpt = ( aP - m_start ).EuclideanNorm();
399 int distEndpt = ( aP - m_end ).EuclideanNorm();
400 dist = std::min( distStartpt, distEndpt );
401 }
402 }
403
404 if( dist <= minDist )
405 {
406 if( aLocation )
407 *aLocation = ( aP + GetCenter() ) / 2;
408
409 if( aActual )
410 *aActual = std::max( 0, dist - m_width / 2 );
411
412 return true;
413 }
414
415 return false;
416}
417
418
420{
422 return angle.Normalize();
423}
424
425
427{
429 return angle.Normalize();
430}
431
432
434{
435 return CalcArcCenter( m_start, m_mid, m_end );
436}
437
438
440{
441 double radius = GetRadius();
442 EDA_ANGLE includedAngle = GetCentralAngle();
443
444 return std::abs( radius * includedAngle.AsRadians() );
445}
446
447
449{
450 VECTOR2I center = GetCenter();
451 EDA_ANGLE angle1 = EDA_ANGLE( m_mid - center ) - EDA_ANGLE( m_start - center );
452 EDA_ANGLE angle2 = EDA_ANGLE( m_end - center ) - EDA_ANGLE( m_mid - center );
453
454 return angle1.Normalize180() + angle2.Normalize180();
455}
456
457
459{
460 return ( m_start - GetCenter() ).EuclideanNorm();
461}
462
463
465 double* aEffectiveAccuracy ) const
466{
468 double r = GetRadius();
470 VECTOR2I c = GetCenter();
472
473 int n;
474
475 // To calculate the arc to segment count, use the external radius instead of the radius.
476 // for a arc with small radius and large width, the difference can be significant
477 double external_radius = r+(m_width/2);
478 double effectiveAccuracy;
479
480 if( external_radius < aAccuracy/2 ) // Should be a very rare case
481 {
482 // In this case, the arc is approximated by one segment, with a effective error
483 // between -aAccuracy/2 and +aAccuracy/2, as expected.
484 n = 0;
485 effectiveAccuracy = external_radius;
486 }
487 else
488 {
489 n = GetArcToSegmentCount( external_radius, aAccuracy, ca );
490
491 // Recalculate the effective error of approximation, that can be < aAccuracy
492 int seg360 = n * 360.0 / fabs( ca.AsDegrees() );
493 effectiveAccuracy = CircleToEndSegmentDeltaRadius( external_radius, seg360 );
494 }
495
496 // Split the error on either side of the arc. Since we want the start and end points
497 // to be exactly on the arc, the first and last segments need to be shorter to stay within
498 // the error band (since segments normally start 1/2 the error band outside the arc).
499 r += effectiveAccuracy / 2;
500 n = n * 2;
501
502 rv.Append( m_start );
503
504 for( int i = 1; i < n ; i += 2 )
505 {
506 EDA_ANGLE a = sa;
507
508 if( n != 0 )
509 a += ( ca * i ) / n;
510
511 double x = c.x + r * a.Cos();
512 double y = c.y + r * a.Sin();
513
514 rv.Append( KiROUND( x ), KiROUND( y ) );
515 }
516
517 rv.Append( m_end );
518
519 if( aEffectiveAccuracy )
520 *aEffectiveAccuracy = effectiveAccuracy;
521
522 return rv;
523}
524
525
526void SHAPE_ARC::Move( const VECTOR2I& aVector )
527{
528 m_start += aVector;
529 m_end += aVector;
530 m_mid += aVector;
531 update_bbox();
532}
533
534
535void SHAPE_ARC::Rotate( const EDA_ANGLE& aAngle, const VECTOR2I& aCenter )
536{
537 RotatePoint( m_start, aCenter, aAngle );
538 RotatePoint( m_end, aCenter, aAngle );
539 RotatePoint( m_mid, aCenter, aAngle );
540
541 update_bbox();
542}
543
544
545void SHAPE_ARC::Mirror( bool aX, bool aY, const VECTOR2I& aVector )
546{
547 if( aX )
548 {
549 m_start.x = -m_start.x + 2 * aVector.x;
550 m_end.x = -m_end.x + 2 * aVector.x;
551 m_mid.x = -m_mid.x + 2 * aVector.x;
552 }
553
554 if( aY )
555 {
556 m_start.y = -m_start.y + 2 * aVector.y;
557 m_end.y = -m_end.y + 2 * aVector.y;
558 m_mid.y = -m_mid.y + 2 * aVector.y;
559 }
560
561 update_bbox();
562}
563
564
565void SHAPE_ARC::Mirror( const SEG& axis )
566{
567 m_start = axis.ReflectPoint( m_start );
568 m_end = axis.ReflectPoint( m_end );
569 m_mid = axis.ReflectPoint( m_mid );
570
571 update_bbox();
572}
573
574
576{
577 std::swap( m_start, m_end );
578}
579
580
582{
583 return SHAPE_ARC( m_end, m_mid, m_start, m_width );
584}
585
586
588{
589 VECTOR2I center = GetCenter();
590 EDA_ANGLE phi( p - center );
593 EDA_ANGLE ea;
594
595 if( ca >= ANGLE_0 )
596 {
597 ea = sa + ca;
598 }
599 else
600 {
601 ea = sa;
602 sa += ca;
603 }
604
605 return alg::within_wrapped_range( phi.AsDegrees(), sa.AsDegrees(), ea.AsDegrees(), 360.0 );
606}
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:506
void Compute(const Container &aPointList)
Compute the bounding box from a given list of points.
Definition: box2.h:82
Represent basic circle geometry with utility geometry functions.
Definition: circle.h:33
VECTOR2I Center
Public to make access simpler.
Definition: circle.h:116
std::vector< VECTOR2I > Intersect(const CIRCLE &aCircle) const
Compute the intersection points between this circle and aCircle.
Definition: circle.cpp:209
std::vector< VECTOR2I > IntersectLine(const SEG &aLine) const
Compute the intersection points between this circle and aLine.
Definition: circle.cpp:288
VECTOR2I NearestPoint(const VECTOR2I &aP) const
Compute the point on the circumference of the circle that is the closest to aP.
Definition: circle.cpp:197
EDA_ANGLE Normalize()
Definition: eda_angle.h:249
double Sin() const
Definition: eda_angle.h:206
double AsDegrees() const
Definition: eda_angle.h:149
EDA_ANGLE Normalize180()
Definition: eda_angle.h:271
double AsRadians() const
Definition: eda_angle.h:153
double Cos() const
Definition: eda_angle.h:221
Definition: seg.h:42
const VECTOR2I ReflectPoint(const VECTOR2I &aP) const
Reflect a point using this segment as axis.
Definition: seg.cpp:283
VECTOR2I A
Definition: seg.h:49
VECTOR2I B
Definition: seg.h:50
const VECTOR2I NearestPoint(const VECTOR2I &aP) const
Compute a point on the segment (this) that is closest to point aP.
Definition: seg.cpp:261
int Length() const
Return the length (this).
Definition: seg.h:326
OPT_VECTOR2I Intersect(const SEG &aSeg, bool aIgnoreEndpoints=false, bool aLines=false) const
Compute intersection point of segment (this) with segment aSeg.
Definition: seg.cpp:188
VECTOR2I Center() const
Definition: seg.h:362
VECTOR2I LineProject(const VECTOR2I &aP) const
Compute the perpendicular projection point of aP on a line passing through ends of the segment.
Definition: seg.cpp:302
EDA_ANGLE GetCentralAngle() const
Definition: shape_arc.cpp:448
const VECTOR2I & GetArcMid() const
Definition: shape_arc.h:114
bool IsClockwise() const
Definition: shape_arc.cpp:366
void Move(const VECTOR2I &aVector) override
Definition: shape_arc.cpp:526
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.
Definition: shape_arc.cpp:191
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
Definition: shape_arc.cpp:355
EDA_ANGLE GetEndAngle() const
Definition: shape_arc.cpp:426
double GetLength() const
Definition: shape_arc.cpp:439
BOX2I m_bbox
Definition: shape_arc.h:264
void Rotate(const EDA_ANGLE &aAngle, const VECTOR2I &aCenter) override
Rotate the arc by a given angle about a point.
Definition: shape_arc.cpp:535
bool sliceContainsPoint(const VECTOR2I &p) const
Definition: shape_arc.cpp:587
SHAPE_ARC()
Definition: shape_arc.h:40
int GetWidth() const
Definition: shape_arc.h:157
VECTOR2I m_mid
Definition: shape_arc.h:260
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.
Definition: shape_arc.cpp:209
SHAPE_ARC Reversed() const
Definition: shape_arc.cpp:581
int m_width
Definition: shape_arc.h:263
const VECTOR2I & GetP1() const
Definition: shape_arc.h:113
int IntersectLine(const SEG &aSeg, std::vector< VECTOR2I > *aIpsBuffer) const
Find intersection points between this arc and aSeg, treating aSeg as an infinite line.
Definition: shape_arc.cpp:273
VECTOR2I m_end
Definition: shape_arc.h:261
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,...
Definition: shape_arc.cpp:241
const SHAPE_LINE_CHAIN ConvertToPolyline(double aAccuracy=DefaultAccuracyForPCB(), double *aEffectiveAccuracy=nullptr) const
Construct a SHAPE_LINE_CHAIN of segments from a given arc.
Definition: shape_arc.cpp:464
int Intersect(const SHAPE_ARC &aArc, std::vector< VECTOR2I > *aIpsBuffer) const
Find intersection points between this arc and aArc.
Definition: shape_arc.cpp:294
double GetRadius() const
Definition: shape_arc.cpp:458
EDA_ANGLE GetStartAngle() const
Definition: shape_arc.cpp:419
void update_bbox()
Definition: shape_arc.cpp:313
void Reverse()
Definition: shape_arc.cpp:575
VECTOR2I GetCenter() const
Definition: shape_arc.cpp:433
void Mirror(bool aX=true, bool aY=false, const VECTOR2I &aVector={ 0, 0 })
Definition: shape_arc.cpp:545
bool ccw(const VECTOR2I &aA, const VECTOR2I &aB, const VECTOR2I &aC) const
Definition: shape_arc.h:248
const VECTOR2I & GetP0() const
Definition: shape_arc.h:112
VECTOR2I m_start
Definition: shape_arc.h:259
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.
An abstract shape on 2D plane.
Definition: shape.h:123
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h:293
static constexpr EDA_ANGLE & ANGLE_360
Definition: eda_angle.h:418
static constexpr EDA_ANGLE & ANGLE_90
Definition: eda_angle.h:414
static constexpr EDA_ANGLE & ANGLE_0
Definition: eda_angle.h:412
E_SERIE r
Definition: eserie.cpp:41
a few functions useful in geometry calculations.
int CircleToEndSegmentDeltaRadius(int aInnerCircleRadius, int aSegCount)
int GetArcToSegmentCount(int aRadius, int aErrorMax, const EDA_ANGLE &aArcAngle)
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
bool within_wrapped_range(T __val, T __minval, T __maxval, T __wrap)
Test if __val lies within __minval and __maxval in a wrapped range.
Definition: kicad_algo.h:128
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:401
std::optional< VECTOR2I > OPT_VECTOR2I
Definition: seg.h:39
@ SH_ARC
circular arc
Definition: shape.h:51
std::ostream & operator<<(std::ostream &aStream, const SHAPE_ARC &aArc)
Definition: shape_arc.cpp:35
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Definition: trigo.cpp:183
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.
Definition: trigo.cpp:472
double EuclideanNorm(const VECTOR2I &vector)
Definition: trigo.h:129
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:85
VECTOR2< int > VECTOR2I
Definition: vector2d.h:618