KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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-2024 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>
28#include <geometry/seg.h> // for SEG
29#include <geometry/shape_arc.h>
33#include <trigo.h>
34
35
36std::ostream& operator<<( std::ostream& aStream, const SHAPE_ARC& aArc )
37{
38 aStream << "Arc( P0=" << aArc.GetP0() << " P1=" << aArc.GetP1() << " Mid=" << aArc.GetArcMid()
39 << " Width=" << aArc.GetWidth() << " )";
40 return aStream;
41}
42
43
44SHAPE_ARC::SHAPE_ARC( const VECTOR2I& aArcCenter, const VECTOR2I& aArcStartPoint,
45 const EDA_ANGLE& aCenterAngle, int aWidth ) :
46 SHAPE( SH_ARC ),
47 m_width( aWidth )
48{
49 m_start = aArcStartPoint;
50
51 VECTOR2D mid = aArcStartPoint;
52 VECTOR2D end = aArcStartPoint;
53 VECTOR2D center = aArcCenter;
54
55 RotatePoint( mid, center, -aCenterAngle / 2.0 );
56 RotatePoint( end, center, -aCenterAngle );
57
58 m_mid = VECTOR2I( KiROUND( mid.x ), KiROUND( mid.y ) );
59 m_end = VECTOR2I( KiROUND( end.x ), KiROUND( end.y ) );
60
62}
63
64
65SHAPE_ARC::SHAPE_ARC( const VECTOR2I& aArcStart, const VECTOR2I& aArcMid,
66 const VECTOR2I& aArcEnd, int aWidth ) :
67 SHAPE( SH_ARC ),
68 m_start( aArcStart ),
69 m_mid( aArcMid ),
70 m_end( aArcEnd ),
71 m_width( aWidth )
72{
74}
75
76
77SHAPE_ARC::SHAPE_ARC( const SEG& aSegmentA, const SEG& aSegmentB, int aRadius, int aWidth ) :
78 SHAPE( SH_ARC )
79{
80 m_width = aWidth;
81
82 /*
83 * Construct an arc that is tangent to two segments with a given radius.
84 *
85 * p
86 * A
87 * A \
88 * / \
89 * / . . \ segB
90 * /. .\
91 * segA / c \
92 * / B
93 * /
94 * /
95 * B
96 *
97 *
98 * segA is the fist segment (with its points A and B)
99 * segB is the second segment (with its points A and B)
100 * p is the point at which segA and segB would intersect if they were projected
101 * c is the centre of the arc to be constructed
102 * rad is the radius of the arc to be constructed
103 *
104 * We can create two vectors, between point p and segA /segB
105 * pToA = p - segA.B //< note that segA.A would also be valid as it is colinear
106 * pToB = p - segB.B //< note that segB.A would also be valid as it is colinear
107 *
108 * Let the angle formed by segA and segB be called 'alpha':
109 * alpha = angle( pToA ) - angle( pToB )
110 *
111 * The distance PC can be computed as
112 * distPC = rad / abs( sin( alpha / 2 ) )
113 *
114 * The polar angle of the vector PC can be computed as:
115 * anglePC = angle( pToA ) + alpha / 2
116 *
117 * Therefore:
118 * C.x = P.x + distPC*cos( anglePC )
119 * C.y = P.y + distPC*sin( anglePC )
120 */
121
122 OPT_VECTOR2I p = aSegmentA.Intersect( aSegmentB, true, true );
123
124 if( !p || aSegmentA.Length() == 0 || aSegmentB.Length() == 0 )
125 {
126 // Catch bugs in debug
127 wxASSERT_MSG( false, "The input segments do not intersect or one is zero length." );
128
129 // Make a 180 degree arc around aSegmentA in case we end up here in release
130 m_start = aSegmentA.A;
131 m_end = aSegmentA.B;
132 m_mid = m_start;
133
134 VECTOR2I arcCenter = aSegmentA.Center();
135 RotatePoint( m_mid, arcCenter, ANGLE_90 ); // mid point at 90 degrees
136 }
137 else
138 {
139 VECTOR2I pToA = aSegmentA.B - *p;
140 VECTOR2I pToB = aSegmentB.B - *p;
141
142 if( pToA.EuclideanNorm() == 0 )
143 pToA = aSegmentA.A - *p;
144
145 if( pToB.EuclideanNorm() == 0 )
146 pToB = aSegmentB.A - *p;
147
148 EDA_ANGLE pToAangle( pToA );
149 EDA_ANGLE pToBangle( pToB );
150
151 EDA_ANGLE alpha = ( pToAangle - pToBangle ).Normalize180();
152
153 double distPC = (double) aRadius / abs( sin( alpha.AsRadians() / 2 ) );
154 EDA_ANGLE angPC = pToAangle - alpha / 2;
155 VECTOR2I arcCenter;
156
157 arcCenter.x = p->x + KiROUND( distPC * angPC.Cos() );
158 arcCenter.y = p->y + KiROUND( distPC * angPC.Sin() );
159
160 // The end points of the arc are the orthogonal projected lines from the line segments
161 // to the center of the arc
162 m_start = aSegmentA.LineProject( arcCenter );
163 m_end = aSegmentB.LineProject( arcCenter );
164
165 //The mid point is rotated start point around center, half the angle of the arc.
166 VECTOR2I startVector = m_start - arcCenter;
167 VECTOR2I endVector = m_end - arcCenter;
168
169 EDA_ANGLE startAngle( startVector );
170 EDA_ANGLE endAngle( endVector );
171 EDA_ANGLE midPointRotAngle = ( startAngle - endAngle ).Normalize180() / 2;
172
173 m_mid = m_start;
174 RotatePoint( m_mid, arcCenter, midPointRotAngle );
175 }
176
178}
179
180
182 : SHAPE( SH_ARC )
183{
184 m_start = aOther.m_start;
185 m_end = aOther.m_end;
186 m_mid = aOther.m_mid;
187 m_width = aOther.m_width;
188 m_bbox = aOther.m_bbox;
189 m_center = aOther.m_center;
190 m_radius = aOther.m_radius;
191}
192
193
195 const EDA_ANGLE& aAngle, double aWidth )
196{
197 m_start = aStart;
198 m_mid = aStart;
199 m_end = aEnd;
200 m_width = aWidth;
201
202 VECTOR2I center( CalcArcCenter( aStart, aEnd, aAngle ) );
203
204 RotatePoint( m_mid, center, -aAngle / 2.0 );
205
207
208 return *this;
209}
210
211
213 const VECTOR2I& aCenter, bool aClockwise,
214 double aWidth )
215{
216 VECTOR2I startLine = aStart - aCenter;
217 VECTOR2I endLine = aEnd - aCenter;
218
219 EDA_ANGLE startAngle( startLine );
220 EDA_ANGLE endAngle( endLine );
221
222 startAngle.Normalize();
223 endAngle.Normalize();
224
225 EDA_ANGLE angle = endAngle - startAngle;
226
227 if( aClockwise )
228 angle = angle.Normalize() - ANGLE_360;
229 else
230 angle = angle.Normalize();
231
232 m_start = aStart;
233 m_end = aEnd;
234 m_mid = aStart;
235
236 RotatePoint( m_mid, aCenter, -angle / 2.0 );
237
239
240 return *this;
241}
242
243
244bool SHAPE_ARC::Collide( const SEG& aSeg, int aClearance, int* aActual, VECTOR2I* aLocation ) const
245{
246 VECTOR2I center = GetCenter();
247 double radius = VECTOR2D( center - m_start ).EuclideanNorm();
248 SHAPE_CIRCLE circle( center, radius );
249 ecoord clearance_sq = SEG::Square( aClearance );
250
251 // Circle or at least an arc with less space remaining than the clearance
252 if( GetCentralAngle().AsDegrees() > 180.0
253 && ( m_start - m_end ).SquaredEuclideanNorm() < clearance_sq )
254 {
255 ecoord a_dist_sq = ( aSeg.A - center ).SquaredEuclideanNorm();
256 ecoord b_dist_sq = ( aSeg.B - center ).SquaredEuclideanNorm();
257 ecoord radius_sq = SEG::Square( radius - aClearance );
258
259 if( a_dist_sq < radius_sq && b_dist_sq < radius_sq )
260 return false;
261
262
263 return circle.Collide( aSeg, aClearance, aActual, aLocation );
264 }
265
266 // Possible points of the collision are:
267 // 1. Intersetion of the segment with the full circle
268 // 2. Closest point on the segment to the center of the circle
269 // 3. Closest point on the segment to the end points of the arc
270 // 4. End points of the segment
271
272 std::vector<VECTOR2I> candidatePts = circle.GetCircle().Intersect( aSeg );
273
274 candidatePts.push_back( aSeg.NearestPoint( center ) );
275 candidatePts.push_back( aSeg.NearestPoint( m_start ) );
276 candidatePts.push_back( aSeg.NearestPoint( m_end ) );
277 candidatePts.push_back( aSeg.A );
278 candidatePts.push_back( aSeg.B );
279
280 bool any_collides = false;
281
282 for( const VECTOR2I& candidate : candidatePts )
283 {
284 bool collides = Collide( candidate, aClearance, aActual, aLocation );
285 any_collides |= collides;
286
287 if( collides && ( !aActual || *aActual == 0 ) )
288 return true;
289 }
290
291 return any_collides;
292}
293
294
295int SHAPE_ARC::IntersectLine( const SEG& aSeg, std::vector<VECTOR2I>* aIpsBuffer ) const
296{
297 if( aSeg.A == aSeg.B ) // One point does not define a line....
298 return 0;
299
300 CIRCLE circ( GetCenter(), GetRadius() );
301
302 std::vector<VECTOR2I> intersections = circ.IntersectLine( aSeg );
303
304 const size_t originalSize = aIpsBuffer->size();
305
306 for( const VECTOR2I& intersection : intersections )
307 {
308 if( sliceContainsPoint( intersection ) )
309 aIpsBuffer->push_back( intersection );
310 }
311
312 return aIpsBuffer->size() - originalSize;
313}
314
315
316int SHAPE_ARC::Intersect( const CIRCLE& aCircle, std::vector<VECTOR2I>* aIpsBuffer ) const
317{
318 CIRCLE thiscirc( GetCenter(), GetRadius() );
319
320 std::vector<VECTOR2I> intersections = thiscirc.Intersect( aCircle );
321
322 const size_t originalSize = aIpsBuffer->size();
323
324 for( const VECTOR2I& intersection : intersections )
325 {
326 if( sliceContainsPoint( intersection ) )
327 aIpsBuffer->push_back( intersection );
328 }
329
330 return aIpsBuffer->size() - originalSize;
331}
332
333
334int SHAPE_ARC::Intersect( const SHAPE_ARC& aArc, std::vector<VECTOR2I>* aIpsBuffer ) const
335{
336 CIRCLE thiscirc( GetCenter(), GetRadius() );
337 CIRCLE othercirc( aArc.GetCenter(), aArc.GetRadius() );
338
339 std::vector<VECTOR2I> intersections = thiscirc.Intersect( othercirc );
340
341 const size_t originalSize = aIpsBuffer->size();
342
343 for( const VECTOR2I& intersection : intersections )
344 {
345 if( sliceContainsPoint( intersection ) && aArc.sliceContainsPoint( intersection ) )
346 aIpsBuffer->push_back( intersection );
347 }
348
349 return aIpsBuffer->size() - originalSize;
350}
351
352
354{
356 m_radius = std::sqrt( ( VECTOR2D( m_start ) - m_center ).SquaredEuclideanNorm() );
357
358 std::vector<VECTOR2I> points;
359 // Put start and end points in the point list
360 points.push_back( m_start );
361 points.push_back( m_end );
362
363 EDA_ANGLE start_angle = GetStartAngle();
364 EDA_ANGLE end_angle = start_angle + GetCentralAngle();
365
366 // we always count quadrants clockwise (increasing angle)
367 if( start_angle > end_angle )
368 std::swap( start_angle, end_angle );
369
370 int quad_angle_start = std::ceil( start_angle.AsDegrees() / 90.0 );
371 int quad_angle_end = std::floor( end_angle.AsDegrees() / 90.0 );
372
373 // very large radius means the arc is similar to a segment
374 // so do not try to add more points, center cannot be handled
375 // Very large is here > INT_MAX/2
376 if( m_radius < (double)INT_MAX/2.0 )
377 {
378 const int radius = KiROUND( m_radius );
379
380 // count through quadrants included in arc
381 for( int quad_angle = quad_angle_start; quad_angle <= quad_angle_end; ++quad_angle )
382 {
383 VECTOR2I quad_pt = m_center;
384
385 switch( quad_angle % 4 )
386 {
387 case 0: quad_pt += { radius, 0 }; break;
388 case 1: case -3: quad_pt += { 0, radius }; break;
389 case 2: case -2: quad_pt += { -radius, 0 }; break;
390 case 3: case -1: quad_pt += { 0, -radius }; break;
391 default:
392 assert( false );
393 }
394
395 points.push_back( quad_pt );
396 }
397 }
398
399 m_bbox.Compute( points );
400}
401
402
403const BOX2I SHAPE_ARC::BBox( int aClearance ) const
404{
405 BOX2I bbox( m_bbox );
406
407 if( m_width != 0 )
408 bbox.Inflate( KiROUND( m_width / 2.0 ) + 1 );
409
410 if( aClearance != 0 )
411 bbox.Inflate( aClearance );
412
413 return bbox;
414}
415
416
418{
419 const static int s_epsilon = 8;
420
421 CIRCLE fullCircle( GetCenter(), GetRadius() );
422 VECTOR2I nearestPt = fullCircle.NearestPoint( aP );
423
424 if( ( nearestPt - m_start ).SquaredEuclideanNorm() <= s_epsilon )
425 return m_start;
426
427 if( ( nearestPt - m_end ).SquaredEuclideanNorm() <= s_epsilon )
428 return m_end;
429
430 if( sliceContainsPoint( nearestPt ) )
431 return nearestPt;
432
433 if( ( aP - m_start ).SquaredEuclideanNorm() <= ( aP - m_end ).SquaredEuclideanNorm() )
434 return m_start;
435 else
436 return m_end;
437}
438
439
440bool SHAPE_ARC::Collide( const VECTOR2I& aP, int aClearance, int* aActual,
441 VECTOR2I* aLocation ) const
442{
443 int minDist = aClearance + m_width / 2;
444 auto bbox = BBox( minDist );
445
446 // Fast check using bounding box:
447 if( !bbox.Contains( aP ) )
448 return false;
449
450 VECTOR2L center = GetCenter();
451 double radius = VECTOR2D( center - m_start ).EuclideanNorm();
452 CIRCLE fullCircle( center, radius );
453 VECTOR2D nearestPt = fullCircle.NearestPoint( VECTOR2D( aP ) );
454 int dist = KiROUND( nearestPt.Distance( aP ) );
455 EDA_ANGLE angleToPt( aP - fullCircle.Center ); // Angle from center to the point
456
457 if( !dist )
458 {
459 // Be sure to keep the sqrt of the squared distance instead of allowing a EuclideanNorm
460 // because this trucates the distance to an integer before subtracting
461 dist = KiROUND( radius - sqrt( ( aP - center ).SquaredEuclideanNorm() ) );
462 nearestPt = center + VECTOR2I( radius, 0 );
463 RotatePoint( nearestPt, center, angleToPt );
464 }
465
466 // If not a 360 degree arc, need to use arc angles to decide if point collides
467 if( m_start != m_end )
468 {
469 bool ccw = GetCentralAngle() > ANGLE_0;
470 EDA_ANGLE rotatedPtAngle = ( angleToPt.Normalize() - GetStartAngle() ).Normalize();
471 EDA_ANGLE rotatedEndAngle = ( GetEndAngle() - GetStartAngle() ).Normalize();
472
473 if( ( ccw && rotatedPtAngle > rotatedEndAngle )
474 || ( !ccw && rotatedPtAngle < rotatedEndAngle ) )
475 {
476 int distStartpt = ( aP - m_start ).EuclideanNorm();
477 int distEndpt = ( aP - m_end ).EuclideanNorm();
478
479 if( distStartpt < distEndpt )
480 {
481 dist = distStartpt;
482 nearestPt = m_start;
483 }
484 else
485 {
486 dist = distEndpt;
487 nearestPt = m_end;
488 }
489 }
490 }
491
492 if( dist <= minDist )
493 {
494 if( aLocation )
495 *aLocation = nearestPt;
496
497 if( aActual )
498 *aActual = std::max( 0, dist - m_width / 2 );
499
500 return true;
501 }
502
503 return false;
504}
505
506
508{
509 VECTOR2L center = GetCenter();
510 EDA_ANGLE angle( m_start - center );
511 return angle.Normalize();
512}
513
514
516{
517 VECTOR2L center = GetCenter();
518 EDA_ANGLE angle( m_end - center );
519 return angle.Normalize();
520}
521
522
524{
525 return m_center;
526}
527
528
530{
531 double radius = GetRadius();
532 EDA_ANGLE includedAngle = GetCentralAngle();
533
534 return std::abs( radius * includedAngle.AsRadians() );
535}
536
537
539{
540 // Arcs with same start and end points can be 0 deg or 360 deg arcs.
541 // However, they are expected to be circles.
542 // So return 360 degrees as central arc:
543 if( m_start == m_end )
544 return ANGLE_360;
545
546 VECTOR2L center = GetCenter();
547 EDA_ANGLE angle1 = EDA_ANGLE( m_mid - center ) - EDA_ANGLE( m_start - center );
548 EDA_ANGLE angle2 = EDA_ANGLE( m_end - center ) - EDA_ANGLE( m_mid - center );
549
550 return angle1.Normalize180() + angle2.Normalize180();
551}
552
553
555{
556 return m_radius;
557}
558
559
561 double* aEffectiveAccuracy ) const
562{
564 double r = GetRadius();
566 VECTOR2I c = GetCenter();
568
569 SEG startToEnd( GetP0(), GetP1() );
570 double halfAccuracy = std::max( 1.0, aAccuracy / 2 );
571
572 int n;
573
574 // To calculate the arc to segment count, use the external radius instead of the radius.
575 // for a arc with small radius and large width, the difference can be significant
576 double external_radius = r+(m_width/2);
577 double effectiveAccuracy;
578
579 if( external_radius < halfAccuracy
580 || startToEnd.Distance( GetArcMid() ) < halfAccuracy ) // Should be a very rare case
581 {
582 // In this case, the arc is approximated by one segment, with a effective error
583 // between -aAccuracy/2 and +aAccuracy/2, as expected.
584 n = 0;
585 effectiveAccuracy = external_radius;
586 }
587 else
588 {
589 n = GetArcToSegmentCount( external_radius, aAccuracy, ca );
590
591 // Recalculate the effective error of approximation, that can be < aAccuracy
592 int seg360 = n * 360.0 / fabs( ca.AsDegrees() );
593 effectiveAccuracy = CircleToEndSegmentDeltaRadius( external_radius, seg360 );
594 }
595
596 // Split the error on either side of the arc. Since we want the start and end points
597 // to be exactly on the arc, the first and last segments need to be shorter to stay within
598 // the error band (since segments normally start 1/2 the error band outside the arc).
599 r += effectiveAccuracy / 2;
600 n = n * 2;
601
602 rv.Append( m_start );
603
604 for( int i = 1; i < n ; i += 2 )
605 {
606 EDA_ANGLE a = sa;
607
608 if( n != 0 )
609 a += ( ca * i ) / n;
610
611 double x = c.x + r * a.Cos();
612 double y = c.y + r * a.Sin();
613
614 rv.Append( KiROUND( x ), KiROUND( y ) );
615 }
616
617 rv.Append( m_end );
618
619 if( aEffectiveAccuracy )
620 *aEffectiveAccuracy = effectiveAccuracy;
621
622 return rv;
623}
624
625
626void SHAPE_ARC::Move( const VECTOR2I& aVector )
627{
628 m_start += aVector;
629 m_end += aVector;
630 m_mid += aVector;
632}
633
634
635void SHAPE_ARC::Rotate( const EDA_ANGLE& aAngle, const VECTOR2I& aCenter )
636{
637 RotatePoint( m_start, aCenter, aAngle );
638 RotatePoint( m_end, aCenter, aAngle );
639 RotatePoint( m_mid, aCenter, aAngle );
640
642}
643
644
645void SHAPE_ARC::Mirror( const VECTOR2I& aVector, FLIP_DIRECTION aFlipDirection )
646{
647 if( aFlipDirection == FLIP_DIRECTION::LEFT_RIGHT )
648 {
649 m_start.x = -m_start.x + 2 * aVector.x;
650 m_end.x = -m_end.x + 2 * aVector.x;
651 m_mid.x = -m_mid.x + 2 * aVector.x;
652 }
653 else
654 {
655 m_start.y = -m_start.y + 2 * aVector.y;
656 m_end.y = -m_end.y + 2 * aVector.y;
657 m_mid.y = -m_mid.y + 2 * aVector.y;
658 }
659
661}
662
663
664void SHAPE_ARC::Mirror( const SEG& axis )
665{
666 m_start = axis.ReflectPoint( m_start );
667 m_end = axis.ReflectPoint( m_end );
668 m_mid = axis.ReflectPoint( m_mid );
669
671}
672
673
675{
676 std::swap( m_start, m_end );
677}
678
679
681{
682 return SHAPE_ARC( m_end, m_mid, m_start, m_width );
683}
684
685
687{
690 EDA_ANGLE ea = sa + ca;
691
692 EDA_ANGLE phi( p - GetCenter() ); // Angle from center to the point
693 phi.Normalize();
694
695 if( ca >= ANGLE_0 )
696 {
697 while( phi < sa )
698 phi += ANGLE_360;
699
700 return phi >= sa && phi <= ea;
701 }
702 else
703 {
704 while( phi > sa )
705 phi -= ANGLE_360;
706
707 return phi <= sa && phi >= ea;
708 }
709}
710
711
712void SHAPE_ARC::TransformToPolygon( SHAPE_POLY_SET& aBuffer, int aError, ERROR_LOC aErrorLoc ) const
713{
714 TransformArcToPolygon( aBuffer, m_start, m_mid, m_end, m_width, aError, aErrorLoc );
715}
ERROR_LOC
When approximating an arc or circle, should the error be placed on the outside or inside of the curve...
Definition: approximation.h:32
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition: box2.h:990
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:558
void Compute(const Container &aPointList)
Compute the bounding box from a given list of points.
Definition: box2.h:109
Represent basic circle geometry with utility geometry functions.
Definition: circle.h:33
VECTOR2I Center
Public to make access simpler.
Definition: circle.h:130
std::vector< VECTOR2I > Intersect(const CIRCLE &aCircle) const
Compute the intersection points between this circle and aCircle.
Definition: circle.cpp:221
std::vector< VECTOR2I > IntersectLine(const SEG &aLine) const
Compute the intersection points between this circle and aLine.
Definition: circle.cpp:300
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:221
double Sin() const
Definition: eda_angle.h:170
double AsDegrees() const
Definition: eda_angle.h:113
EDA_ANGLE Normalize180()
Definition: eda_angle.h:260
double AsRadians() const
Definition: eda_angle.h:117
double Cos() const
Definition: eda_angle.h:189
Definition: seg.h:42
const VECTOR2I ReflectPoint(const VECTOR2I &aP) const
Reflect a point using this segment as axis.
Definition: seg.cpp:350
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:327
int Length() const
Return the length (this).
Definition: seg.h:333
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:254
static SEG::ecoord Square(int a)
Definition: seg.h:123
VECTOR2I Center() const
Definition: seg.h:369
int Distance(const SEG &aSeg) const
Compute minimum Euclidean distance to segment aSeg.
Definition: seg.cpp:388
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:371
EDA_ANGLE GetCentralAngle() const
Definition: shape_arc.cpp:538
double m_radius
Definition: shape_arc.h:288
const VECTOR2I & GetArcMid() const
Definition: shape_arc.h:116
void update_values()
Definition: shape_arc.cpp:353
void Move(const VECTOR2I &aVector) override
Definition: shape_arc.cpp:626
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:194
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:403
EDA_ANGLE GetEndAngle() const
Definition: shape_arc.cpp:515
double GetLength() const
Definition: shape_arc.cpp:529
BOX2I m_bbox
Definition: shape_arc.h:286
void Rotate(const EDA_ANGLE &aAngle, const VECTOR2I &aCenter) override
Rotate the arc by a given angle about a point.
Definition: shape_arc.cpp:635
bool sliceContainsPoint(const VECTOR2I &p) const
Definition: shape_arc.cpp:686
VECTOR2I NearestPoint(const VECTOR2I &aP) const
Definition: shape_arc.cpp:417
SHAPE_ARC()
Definition: shape_arc.h:41
int Intersect(const CIRCLE &aArc, std::vector< VECTOR2I > *aIpsBuffer) const
Find intersection points between this arc and a CIRCLE.
Definition: shape_arc.cpp:316
int GetWidth() const
Definition: shape_arc.h:168
VECTOR2I m_mid
Definition: shape_arc.h:282
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:212
void Mirror(const VECTOR2I &aRef, FLIP_DIRECTION aFlipDirection)
Definition: shape_arc.cpp:645
SHAPE_ARC Reversed() const
Definition: shape_arc.cpp:680
VECTOR2I m_center
Definition: shape_arc.h:287
int m_width
Definition: shape_arc.h:284
const VECTOR2I & GetP1() const
Definition: shape_arc.h:115
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:295
VECTOR2I m_end
Definition: shape_arc.h:283
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:244
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:560
double GetRadius() const
Definition: shape_arc.cpp:554
EDA_ANGLE GetStartAngle() const
Definition: shape_arc.cpp:507
void TransformToPolygon(SHAPE_POLY_SET &aBuffer, int aError, ERROR_LOC aErrorLoc) const override
Fills a SHAPE_POLY_SET with a polygon representation of this shape.
Definition: shape_arc.cpp:712
void Reverse()
Definition: shape_arc.cpp:674
const VECTOR2I & GetP0() const
Definition: shape_arc.h:114
VECTOR2I m_start
Definition: shape_arc.h:281
const VECTOR2I & GetCenter() const
Definition: shape_arc.cpp:523
const CIRCLE GetCircle() const
Definition: shape_circle.h:128
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_circle.h:77
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.
An abstract shape on 2D plane.
Definition: shape.h:126
VECTOR2I::extended_type ecoord
Definition: shape.h:284
double Distance(const VECTOR2< extended_type > &aVector) const
Compute the distance between two vectors.
Definition: vector2d.h:557
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h:283
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
Definition: eda_angle.h:401
static constexpr EDA_ANGLE ANGLE_90
Definition: eda_angle.h:403
static constexpr EDA_ANGLE ANGLE_360
Definition: eda_angle.h:407
std::ostream & operator<<(std::ostream &aStream, const EDA_TEXT &aText)
Definition: eda_text.cpp:1210
a few functions useful in geometry calculations.
int CircleToEndSegmentDeltaRadius(int aInnerCircleRadius, int aSegCount)
int GetArcToSegmentCount(int aRadius, int aErrorMax, const EDA_ANGLE &aArcAngle)
FLIP_DIRECTION
Definition: mirror.h:27
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:390
std::optional< VECTOR2I > OPT_VECTOR2I
Definition: seg.h:39
@ SH_ARC
circular arc
Definition: shape.h:54
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.
Definition: trigo.cpp:229
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:521
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:691
VECTOR2< double > VECTOR2D
Definition: vector2d.h:690