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-2021 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 
35 std::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 
43 SHAPE_ARC::SHAPE_ARC( const VECTOR2I& aArcCenter, const VECTOR2I& aArcStartPoint,
44  double aCenterAngle, int aWidth ) :
45  SHAPE( SH_ARC ), m_width( aWidth )
46 {
47  m_start = aArcStartPoint;
48  m_mid = aArcStartPoint;
49  m_end = aArcStartPoint;
50 
51  RotatePoint( m_mid, aArcCenter, -aCenterAngle * 10.0 / 2.0 );
52  RotatePoint( m_end, aArcCenter, -aCenterAngle * 10.0 );
53 
54  update_bbox();
55 }
56 
57 
58 SHAPE_ARC::SHAPE_ARC( const VECTOR2I& aArcStart, const VECTOR2I& aArcMid,
59  const VECTOR2I& aArcEnd, int aWidth ) :
60  SHAPE( SH_ARC ), m_start( aArcStart ), m_mid( aArcMid ), m_end( aArcEnd ),
61  m_width( aWidth )
62 {
63  update_bbox();
64 }
65 
66 
67 SHAPE_ARC::SHAPE_ARC( const SEG& aSegmentA, const SEG& aSegmentB, int aRadius, int aWidth )
68  : SHAPE( SH_ARC )
69 {
70  m_width = aWidth;
71 
72  /*
73  * Construct an arc that is tangent to two segments with a given radius.
74  *
75  * p
76  * A
77  * A \
78  * / \
79  * / . . \ segB
80  * /. .\
81  * segA / c \
82  * / B
83  * /
84  * /
85  * B
86  *
87  *
88  * segA is the fist segment (with its points A and B)
89  * segB is the second segment (with its points A and B)
90  * p is the point at which segA and segB would intersect if they were projected
91  * c is the centre of the arc to be constructed
92  * rad is the radius of the arc to be constructed
93  *
94  * We can create two vectors, between point p and segA /segB
95  * pToA = p - segA.B //< note that segA.A would also be valid as it is colinear
96  * pToB = p - segB.B //< note that segB.A would also be valid as it is colinear
97  *
98  * Let the angle formed by segA and segB be called 'alpha':
99  * alpha = angle( pToA ) - angle( pToB )
100  *
101  * The distance PC can be computed as
102  * distPC = rad / abs( sin( alpha / 2 ) )
103  *
104  * The polar angle of the vector PC can be computed as:
105  * anglePC = angle( pToA ) + alpha / 2
106  *
107  * Therefore:
108  * C.x = P.x + distPC*cos( anglePC )
109  * C.y = P.y + distPC*sin( anglePC )
110  */
111 
112  OPT_VECTOR2I p = aSegmentA.Intersect( aSegmentB, true, true );
113 
114  if( !p || aSegmentA.Length() == 0 || aSegmentB.Length() == 0 )
115  {
116  // Catch bugs in debug
117  wxASSERT_MSG( false, "The input segments do not intersect or one is zero length." );
118 
119  // Make a 180 degree arc around aSegmentA in case we end up here in release
120  m_start = aSegmentA.A;
121  m_end = aSegmentA.B;
122  m_mid = m_start;
123 
124  VECTOR2I arcCenter = aSegmentA.Center();
125  RotatePoint( m_mid, arcCenter, 900.0 ); // mid point at 90 degrees
126  }
127  else
128  {
129  VECTOR2I pToA = aSegmentA.B - p.get();
130  VECTOR2I pToB = aSegmentB.B - p.get();
131 
132  if( pToA.EuclideanNorm() == 0 )
133  pToA = aSegmentA.A - p.get();
134 
135  if( pToB.EuclideanNorm() == 0 )
136  pToB = aSegmentB.A - p.get();
137 
138  double pToAangle = ArcTangente( pToA.y, pToA.x );
139  double pToBangle = ArcTangente( pToB.y, pToB.x );
140 
141  double alpha = NormalizeAngle180( pToAangle - pToBangle );
142 
143  double distPC = (double) aRadius / abs( sin( DECIDEG2RAD( alpha / 2 ) ) );
144  double angPC = pToAangle - alpha / 2;
145 
146  VECTOR2I arcCenter;
147 
148  arcCenter.x = p.get().x + KiROUND( distPC * cos( DECIDEG2RAD( angPC ) ) );
149  arcCenter.y = p.get().y + KiROUND( distPC * sin( DECIDEG2RAD( angPC ) ) );
150 
151  // The end points of the arc are the orthogonal projected lines from the line segments
152  // to the center of the arc
153  m_start = aSegmentA.LineProject( arcCenter );
154  m_end = aSegmentB.LineProject( arcCenter );
155 
156  //The mid point is rotated start point around center, half the angle of the arc.
157  VECTOR2I startVector = m_start - arcCenter;
158  VECTOR2I endVector = m_end - arcCenter;
159 
160  double startAngle = ArcTangente( startVector.y, startVector.x );
161  double endAngle = ArcTangente( endVector.y, endVector.x );
162 
163  double midPointRotAngle = NormalizeAngle180( startAngle - endAngle ) / 2;
164  m_mid = m_start;
165  RotatePoint( m_mid, arcCenter, midPointRotAngle );
166  }
167 
168  update_bbox();
169 }
170 
171 
173  : SHAPE( SH_ARC )
174 {
175  m_start = aOther.m_start;
176  m_end = aOther.m_end;
177  m_mid = aOther.m_mid;
178  m_width = aOther.m_width;
179  m_bbox = aOther.m_bbox;
180 }
181 
182 
184  double aAngle, double aWidth )
185 {
186  m_start = aStart;
187  m_mid = aStart;
188  m_end = aEnd;
189  m_width = aWidth;
190 
191  VECTOR2I center( CalcArcCenter( aStart, aEnd, aAngle ) );
192 
193  RotatePoint( m_mid, center, -aAngle * 10.0 / 2.0 );
194 
195  update_bbox();
196 
197  return *this;
198 }
199 
200 
202  const VECTOR2I& aCenter, bool aClockwise,
203  double aWidth )
204 {
205  VECTOR2I startLine = aStart - aCenter;
206  VECTOR2I endLine = aEnd - aCenter;
207 
208  double startangle = NormalizeAnglePos(RAD2DECIDEG( startLine.Angle() ));
209  double endangle = NormalizeAnglePos(RAD2DECIDEG( endLine.Angle() ));
210  double angle = endangle - startangle;
211 
212  if( aClockwise )
214  else
216 
217  m_start = aStart;
218  m_end = aEnd;
219  m_mid = aStart;
220 
221  RotatePoint( m_mid, aCenter, -angle / 2.0 );
222 
223  update_bbox();
224 
225  return *this;
226 }
227 
228 
229 bool SHAPE_ARC::Collide( const SEG& aSeg, int aClearance, int* aActual, VECTOR2I* aLocation ) const
230 {
231  if( aSeg.A == aSeg.B )
232  return Collide( aSeg.A, aClearance, aActual, aLocation );
233 
234  VECTOR2I center = GetCenter();
235  CIRCLE circle( center, GetRadius() );
236 
237  // Possible points of the collision are:
238  // 1. Intersetion of the segment with the full circle
239  // 2. Closest point on the segment to the center of the circle
240  // 3. Closest point on the segment to the end points of the arc
241  // 4. End points of the segment
242 
243  std::vector<VECTOR2I> candidatePts = circle.Intersect( aSeg );
244 
245  candidatePts.push_back( aSeg.NearestPoint( center ) );
246  candidatePts.push_back( aSeg.NearestPoint( m_start ) );
247  candidatePts.push_back( aSeg.NearestPoint( m_end ) );
248  candidatePts.push_back( aSeg.A );
249  candidatePts.push_back( aSeg.B );
250 
251  for( const VECTOR2I& candidate : candidatePts )
252  {
253  if( Collide( candidate, aClearance, aActual, aLocation ) )
254  return true;
255  }
256 
257  return false;
258 }
259 
260 
261 int SHAPE_ARC::IntersectLine( const SEG& aSeg, std::vector<VECTOR2I>* aIpsBuffer ) const
262 {
263  CIRCLE circ( GetCenter(), GetRadius() );
264 
265  std::vector<VECTOR2I> intersections = circ.IntersectLine( aSeg );
266 
267  size_t originalSize = aIpsBuffer->size();
268 
269  for( const VECTOR2I& intersection : intersections )
270  {
271  if( sliceContainsPoint( intersection ) )
272  aIpsBuffer->push_back( intersection );
273  }
274 
275  return aIpsBuffer->size() - originalSize;
276 }
277 
278 
279 int SHAPE_ARC::Intersect( const SHAPE_ARC& aArc, std::vector<VECTOR2I>* aIpsBuffer ) const
280 {
281  CIRCLE thiscirc( GetCenter(), GetRadius() );
282  CIRCLE othercirc( aArc.GetCenter(), aArc.GetRadius() );
283 
284  std::vector<VECTOR2I> intersections = thiscirc.Intersect( othercirc );
285 
286  size_t originalSize = aIpsBuffer->size();
287 
288  for( const VECTOR2I& intersection : intersections )
289  {
290  if( sliceContainsPoint( intersection ) && aArc.sliceContainsPoint( intersection ) )
291  aIpsBuffer->push_back( intersection );
292  }
293 
294  return aIpsBuffer->size() - originalSize;
295 }
296 
297 
299 {
300  std::vector<VECTOR2I> points;
301  // Put start and end points in the point list
302  points.push_back( m_start );
303  points.push_back( m_end );
304 
305  double start_angle = GetStartAngle();
306  double end_angle = start_angle + GetCentralAngle();
307 
308  // we always count quadrants clockwise (increasing angle)
309  if( start_angle > end_angle )
310  std::swap( start_angle, end_angle );
311 
312  int quad_angle_start = std::ceil( start_angle / 90.0 );
313  int quad_angle_end = std::floor( end_angle / 90.0 );
314 
315  // count through quadrants included in arc
316  for( int quad_angle = quad_angle_start; quad_angle <= quad_angle_end; ++quad_angle )
317  {
318  const int radius = KiROUND( GetRadius() );
319  VECTOR2I quad_pt = GetCenter();
320 
321  switch( quad_angle % 4 )
322  {
323  case 0: quad_pt += { radius, 0 }; break;
324  case 1:
325  case -3: quad_pt += { 0, radius }; break;
326  case 2:
327  case -2: quad_pt += { -radius, 0 }; break;
328  case 3:
329  case -1: quad_pt += { 0, -radius }; break;
330  default: assert( false );
331  }
332 
333  points.push_back( quad_pt );
334  }
335 
336  m_bbox.Compute( points );
337 }
338 
339 
340 const BOX2I SHAPE_ARC::BBox( int aClearance ) const
341 {
342  BOX2I bbox( m_bbox );
343 
344  if( aClearance != 0 )
345  bbox.Inflate( aClearance );
346 
347  return bbox;
348 }
349 
350 
352 {
353  return GetCentralAngle() < 0;
354 }
355 
356 
357 bool SHAPE_ARC::Collide( const VECTOR2I& aP, int aClearance, int* aActual,
358  VECTOR2I* aLocation ) const
359 {
360  int minDist = aClearance + m_width / 2;
361  auto bbox = BBox( minDist );
362 
363  // Fast check using bounding box:
364  if( !bbox.Contains( aP ) )
365  return false;
366 
367  VECTOR2I center = GetCenter();
368  VECTOR2I vec = aP - center;
369 
370  int dist = abs( vec.EuclideanNorm() - GetRadius() );
371 
372  // If not a 360 degree arc, need to use arc angles to decide if point collides
373  if( m_start != m_end )
374  {
375  bool ccw = GetCentralAngle() > 0.0;
376  double rotatedVecAngle = NormalizeAngleDegreesPos( NormalizeAngleDegreesPos( RAD2DEG( vec.Angle() ) )
377  - GetStartAngle() );
378  double rotatedEndAngle = NormalizeAngleDegreesPos( GetEndAngle() - GetStartAngle() );
379 
380  if( ( ccw && rotatedVecAngle > rotatedEndAngle )
381  || ( !ccw && rotatedVecAngle < rotatedEndAngle ) )
382  {
383  int distStartpt = ( aP - m_start ).EuclideanNorm();
384  int distEndpt = ( aP - m_end ).EuclideanNorm();
385  dist = std::min( distStartpt, distEndpt );
386  }
387  }
388 
389  if( dist <= minDist )
390  {
391  if( aLocation )
392  *aLocation = ( aP + GetCenter() ) / 2;
393 
394  if( aActual )
395  *aActual = std::max( 0, dist - m_width / 2 );
396 
397  return true;
398  }
399 
400  return false;
401 }
402 
403 
405 {
406  VECTOR2D d( m_start - GetCenter() );
407 
408  auto ang = 180.0 / M_PI * atan2( d.y, d.x );
409 
410  return NormalizeAngleDegrees( ang, 0.0, 360.0 );
411 }
412 
413 
415 {
416  VECTOR2D d( m_end - GetCenter() );
417 
418  auto ang = 180.0 / M_PI * atan2( d.y, d.x );
419 
420  return NormalizeAngleDegrees( ang, 0.0, 360.0 );
421 }
422 
423 
425 {
426  return CalcArcCenter( m_start, m_mid, m_end );
427 }
428 
429 
430 double SHAPE_ARC::GetLength() const
431 {
432  double radius = GetRadius();
433  double includedAngle = std::abs( GetCentralAngle() );
434 
435  return radius * M_PI * includedAngle / 180.0;
436 }
437 
438 
440 {
441  VECTOR2I center = GetCenter();
442  VECTOR2I p0 = m_start - center;
443  VECTOR2I p1 = m_mid - center;
444  VECTOR2I p2 = m_end - center;
445  double angle1 = ArcTangente( p1.y, p1.x ) - ArcTangente( p0.y, p0.x );
446  double angle2 = ArcTangente( p2.y, p2.x ) - ArcTangente( p1.y, p1.x );
447 
448  return ( NormalizeAngle180( angle1 ) + NormalizeAngle180( angle2 ) ) / 10.0;
449 }
450 
451 
452 double SHAPE_ARC::GetRadius() const
453 {
454  return ( m_start - GetCenter() ).EuclideanNorm();
455 }
456 
457 
459  double* aEffectiveAccuracy ) const
460 {
461  SHAPE_LINE_CHAIN rv;
462  double r = GetRadius();
463  double sa = GetStartAngle();
464  VECTOR2I c = GetCenter();
465  double ca = GetCentralAngle();
466 
467  int n;
468 
469  // To calculate the arc to segment count, use the external radius instead of the radius.
470  // for a arc with small radius and large width, the difference can be significant
471  double external_radius = r+(m_width/2);
472  double effectiveAccuracy;
473 
474  if( external_radius < aAccuracy/2 ) // Should be a very rare case
475  {
476  // In this case, the arc is approximated by one segment, with a effective error
477  // between -aAccuracy/2 and +aAccuracy/2, as expected.
478  n = 0;
479  effectiveAccuracy = external_radius;
480  }
481  else
482  {
483  double arc_angle = std::abs( ca );
484  n = GetArcToSegmentCount( external_radius, aAccuracy, arc_angle );
485 
486  // Recalculate the effective error of approximation, that can be < aAccuracy
487  int seg360 = n * 360.0 / arc_angle;
488  effectiveAccuracy = CircleToEndSegmentDeltaRadius( external_radius, seg360 );
489  }
490 
491  // Split the error on either side of the arc. Since we want the start and end points
492  // to be exactly on the arc, the first and last segments need to be shorter to stay within
493  // the error band (since segments normally start 1/2 the error band outside the arc).
494  r += effectiveAccuracy / 2;
495  n = n * 2;
496 
497  rv.Append( m_start );
498 
499  for( int i = 1; i < n ; i += 2 )
500  {
501  double a = sa;
502 
503  if( n != 0 )
504  a += ( ca * i ) / n;
505 
506  double x = c.x + r * cos( a * M_PI / 180.0 );
507  double y = c.y + r * sin( a * M_PI / 180.0 );
508 
509  rv.Append( KiROUND( x ), KiROUND( y ) );
510  }
511 
512  rv.Append( m_end );
513 
514  if( aEffectiveAccuracy )
515  *aEffectiveAccuracy = effectiveAccuracy;
516 
517  return rv;
518 }
519 
520 
521 void SHAPE_ARC::Move( const VECTOR2I& aVector )
522 {
523  m_start += aVector;
524  m_end += aVector;
525  m_mid += aVector;
526  update_bbox();
527 }
528 
529 
530 void SHAPE_ARC::Rotate( double aAngle, const VECTOR2I& aCenter )
531 {
532  m_start -= aCenter;
533  m_end -= aCenter;
534  m_mid -= aCenter;
535 
536  m_start = m_start.Rotate( aAngle );
537  m_end = m_end.Rotate( aAngle );
538  m_mid = m_mid.Rotate( aAngle );
539 
540  m_start += aCenter;
541  m_end += aCenter;
542  m_mid += aCenter;
543 
544  update_bbox();
545 }
546 
547 
548 void SHAPE_ARC::Mirror( bool aX, bool aY, const VECTOR2I& aVector )
549 {
550  if( aX )
551  {
552  m_start.x = -m_start.x + 2 * aVector.x;
553  m_end.x = -m_end.x + 2 * aVector.x;
554  m_mid.x = -m_mid.x + 2 * aVector.x;
555  }
556 
557  if( aY )
558  {
559  m_start.y = -m_start.y + 2 * aVector.y;
560  m_end.y = -m_end.y + 2 * aVector.y;
561  m_mid.y = -m_mid.y + 2 * aVector.y;
562  }
563 
564  update_bbox();
565 }
566 
567 
568 void SHAPE_ARC::Mirror( const SEG& axis )
569 {
570  m_start = axis.ReflectPoint( m_start );
571  m_end = axis.ReflectPoint( m_end );
572  m_mid = axis.ReflectPoint( m_mid );
573 
574  update_bbox();
575 }
576 
577 
579 {
580  std::swap( m_start, m_end );
581 }
582 
583 
585 {
586  return SHAPE_ARC( m_end, m_mid, m_start, m_width );
587 }
588 
589 
591 {
592  VECTOR2I center = GetCenter();
593  double phi = 180.0 / M_PI * atan2( p.y - center.y, p.x - center.x );
594  double ca = GetCentralAngle();
595  double sa = GetStartAngle();
596  double ea;
597 
598  if( ca >= 0 )
599  {
600  ea = sa + ca;
601  }
602  else
603  {
604  ea = sa;
605  sa += ca;
606  }
607 
608  return alg::within_wrapped_range( phi, sa, ea, 360.0 );
609 }
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:146
int Length() const
Return the length (this).
Definition: seg.h:350
void Mirror(bool aX=true, bool aY=false, const VECTOR2I &aVector={ 0, 0 })
Definition: shape_arc.cpp:548
T NormalizeAngleNeg(T Angle)
Normalize angle to be in the 0.0 .. -360.0 range: angle is in 1/10 degrees.
Definition: trigo.h:268
int CircleToEndSegmentDeltaRadius(int aInnerCircleRadius, int aSegCount)
void Rotate(double aAngle, const VECTOR2I &aCenter) override
Rotate the arc by a given angle about a point.
Definition: shape_arc.cpp:530
bool IsClockwise() const
Definition: shape_arc.cpp:351
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:229
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:154
double GetRadius() const
Definition: shape_arc.cpp:452
VECTOR2I m_end
Definition: shape_arc.h:260
double RAD2DEG(double rad)
Definition: trigo.h:230
const VECTOR2I ReflectPoint(const VECTOR2I &aP) const
Reflect a point using this segment as axis.
Definition: seg.cpp:249
SHAPE_ARC & ConstructFromStartEndAngle(const VECTOR2I &aStart, const VECTOR2I &aEnd, double aAngle, double aWidth=0)
Construct this arc from the given start, end and angle.
Definition: shape_arc.cpp:183
double RAD2DECIDEG(double rad)
Definition: trigo.h:234
void Compute(const Container &aPointList)
Compute the bounding box from a given list of points.
Definition: box2.h:75
bool ccw(const VECTOR2I &aA, const VECTOR2I &aB, const VECTOR2I &aC) const
Definition: shape_arc.h:247
double GetStartAngle() const
Definition: shape_arc.cpp:404
bool sliceContainsPoint(const VECTOR2I &p) const
Definition: shape_arc.cpp:590
VECTOR2I Center() const
Definition: seg.h:386
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:229
int Intersect(const SHAPE_ARC &aArc, std::vector< VECTOR2I > *aIpsBuffer) const
Find intersection points between this arc and aArc.
Definition: shape_arc.cpp:279
std::ostream & operator<<(std::ostream &aStream, const SHAPE_ARC &aArc)
Definition: shape_arc.cpp:35
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
T NormalizeAngle180(T Angle)
Normalize angle to be in the -180.0 .. 180.0 range.
Definition: trigo.h:387
VECTOR2I m_mid
Definition: shape_arc.h:259
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:268
double NormalizeAngleDegreesPos(double Angle)
Normalize angle to be in the 0.0 .. 360.0 range: angle is in degrees.
Definition: trigo.h:297
OPT< VECTOR2I > OPT_VECTOR2I
Definition: seg.h:38
const VECTOR2I & GetP0() const
Definition: shape_arc.h:111
std::vector< VECTOR2I > IntersectLine(const SEG &aLine) const
Compute the intersection points between this circle and aLine.
Definition: circle.cpp:288
const VECTOR2I & GetArcMid() const
Definition: shape_arc.h:113
const VECTOR2I NearestPoint(const VECTOR2I &aP) const
Compute a point on the segment (this) that is closest to point aP.
Definition: seg.cpp:227
circular arc
Definition: shape.h:50
a few functions useful in geometry calculations.
An abstract shape on 2D plane.
Definition: shape.h:116
Represent basic circle geometry with utility geometry functions.
Definition: circle.h:32
double Angle() const
Compute the angle of the vector.
Definition: vector2d.h:307
E_SERIE r
Definition: eserie.cpp:41
double GetEndAngle() const
Definition: shape_arc.cpp:414
void update_bbox()
Definition: shape_arc.cpp:298
void Reverse()
Definition: shape_arc.cpp:578
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:261
Definition: seg.h:40
void Move(const VECTOR2I &aVector) override
Definition: shape_arc.cpp:521
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:281
int GetWidth() const
Definition: shape_arc.h:156
VECTOR2< T > Rotate(double aAngle) const
Rotate the vector by a given angle.
Definition: vector2d.h:371
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:458
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:201
std::vector< VECTOR2I > Intersect(const CIRCLE &aCircle) const
Compute the intersection points between this circle and aCircle.
Definition: circle.cpp:209
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
VECTOR2I m_start
Definition: shape_arc.h:258
T NormalizeAnglePos(T Angle)
Normalize angle to be in the 0.0 .. 360.0 range: angle is in 1/10 degrees.
Definition: trigo.h:281
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
VECTOR2I A
Definition: seg.h:48
double GetCentralAngle() const
Definition: shape_arc.cpp:439
double DECIDEG2RAD(double deg)
Definition: trigo.h:233
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:73
SHAPE_ARC()
Definition: shape_arc.h:39
double NormalizeAngleDegrees(double Angle, double aMin, double aMax)
Normalize angle to be aMin < angle <= aMax angle is in degrees.
Definition: trigo.h:327
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:340
SHAPE_ARC Reversed() const
Definition: shape_arc.cpp:584
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h:293
double ArcTangente(int dy, int dx)
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:525
double GetLength() const
Definition: shape_arc.cpp:430
int m_width
Definition: shape_arc.h:262
int GetArcToSegmentCount(int aRadius, int aErrorMax, double aArcAngleDegree)
BOX2I m_bbox
Definition: shape_arc.h:263
const VECTOR2I & GetP1() const
Definition: shape_arc.h:112
VECTOR2I GetCenter() const
Definition: shape_arc.cpp:424
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
VECTOR2I B
Definition: seg.h:49