trigo.cpp File Reference

Trigonometric and geometric basic functions. More...

`#include <limits>`
`#include <stdlib.h>`
`#include <type_traits>`
`#include <geometry/seg.h>`
`#include <math/util.h>`
`#include <math/vector2d.h>`
`#include <trigo.h>`

Go to the source code of this file.

## Functions

bool IsPointOnSegment (const wxPoint &aSegStart, const wxPoint &aSegEnd, const wxPoint &aTestPoint)
Test if aTestPoint is on line defined by aSegStart and aSegEnd. More...

bool SegmentIntersectsSegment (const wxPoint &a_p1_l1, const wxPoint &a_p2_l1, const wxPoint &a_p1_l2, const wxPoint &a_p2_l2, wxPoint *aIntersectionPoint)
Test if two lines intersect. More...

bool TestSegmentHit (const wxPoint &aRefPoint, const wxPoint &aStart, const wxPoint &aEnd, int aDist)
Test if aRefPoint is with aDistance on the line defined by aStart and aEnd. More...

const VECTOR2I CalcArcMid (const VECTOR2I &aStart, const VECTOR2I &aEnd, const VECTOR2I &aCenter, bool aMinArcAngle)
Return the middle point of an arc, half-way between aStart and aEnd. More...

double ArcTangente (int dy, int dx)

void RotatePoint (int *pX, int *pY, double angle)

void RotatePoint (int *pX, int *pY, int cx, int cy, double angle)

void RotatePoint (wxPoint *point, const wxPoint &centre, double angle)

void RotatePoint (VECTOR2I &point, const VECTOR2I &centre, double angle)

void RotatePoint (double *pX, double *pY, double cx, double cy, double angle)

void RotatePoint (double *pX, double *pY, double angle)

const VECTOR2D CalcArcCenter (const VECTOR2D &aStart, const VECTOR2D &aEnd, double aAngle)

const VECTOR2D CalcArcCenter (const VECTOR2D &aStart, const VECTOR2D &aMid, const VECTOR2D &aEnd)

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. More...

const wxPoint CalcArcCenter (const wxPoint &aStart, const wxPoint &aMid, const wxPoint &aEnd)

double CalcArcAngle (const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Return the subtended angle for a given arc. More...

## Detailed Description

Trigonometric and geometric basic functions.

Definition in file trigo.cpp.

## ◆ ArcTangente()

 double ArcTangente ( int dy, int dx )

Definition at line 183 of file trigo.cpp.

184 {
185
186  /* gcc is surprisingly smart in optimizing these conditions in
187  a tree! */
188
189  if( dx == 0 && dy == 0 )
190  return 0;
191
192  if( dy == 0 )
193  {
194  if( dx >= 0 )
195  return 0;
196  else
197  return -1800;
198  }
199
200  if( dx == 0 )
201  {
202  if( dy >= 0 )
203  return 900;
204  else
205  return -900;
206  }
207
208  if( dx == dy )
209  {
210  if( dx >= 0 )
211  return 450;
212  else
213  return -1800 + 450;
214  }
215
216  if( dx == -dy )
217  {
218  if( dx >= 0 )
219  return -450;
220  else
221  return 1800 - 450;
222  }
223
224  // Of course dy and dx are treated as double
225  return RAD2DECIDEG( std::atan2( (double) dy, (double) dx ) );
226 }
Definition: trigo.h:234

## ◆ CalcArcAngle()

 double CalcArcAngle ( const VECTOR2I & aStart, const VECTOR2I & aMid, const VECTOR2I & aEnd )

Return the subtended angle for a given arc.

Definition at line 567 of file trigo.cpp.

568 {
569  VECTOR2I center = CalcArcCenter( aStart, aMid, aEnd );
570
571  // Check if the new arc is CW or CCW
572  VECTOR2D startLine = aStart - center;
573  VECTOR2D endLine = aEnd - center;
574  double angle = RAD2DECIDEG( endLine.Angle() - startLine.Angle() );
575
576  VECTOR2D v1, v2;
577  v1 = aStart - aMid;
578  v2 = aEnd - aMid;
579  double theta = RAD2DECIDEG( v1.Angle() );
580
581  RotatePoint( &( v1.x ), &( v1.y ), theta );
582  RotatePoint( &( v2.x ), &( v2.y ), theta );
583
584  bool clockwise = ( ( v1.Angle() - v2.Angle() ) > 0 );
585
586  // Normalize the angle
587  if( clockwise && angle < 0.0 )
588  angle += 3600.0;
589  else if( !clockwise && angle > 0.0 )
590  angle -= 3600.0;
591
592  return angle;
593 }
VECTOR2I v2(1, 0)
Test suite for KiCad math code.
Define a general 2D-vector/point.
Definition: vector2d.h:61
Definition: trigo.h:234
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:229
double Angle() const
Compute the angle of the vector.
Definition: vector2d.h:307
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
const VECTOR2D CalcArcCenter(const VECTOR2D &aStart, const VECTOR2D &aEnd, double aAngle)
Definition: trigo.cpp:362

## ◆ CalcArcCenter() [1/4]

 const VECTOR2D CalcArcCenter ( const VECTOR2D & aStart, const VECTOR2D & aEnd, double aAngle )

Definition at line 362 of file trigo.cpp.

363 {
364  VECTOR2D start = aStart;
365  VECTOR2D end = aEnd;
366
367  if( aAngle < 0 )
368  {
369  std::swap( start, end );
370  aAngle = abs( aAngle );
371  }
372
373  if( aAngle > 180 )
374  {
375  std::swap( start, end );
376  aAngle = 360 - aAngle;
377  }
378
379  double chord = ( start - end ).EuclideanNorm();
380  double r = chord / ( 2.0 * sin( ( aAngle / 2.0 ) * M_PI / 180.0 ) );
381
382  VECTOR2D vec = end - start;
383  vec = vec.Resize( r );
384  vec = vec.Rotate( ( 90.0 - aAngle / 2.0 ) * M_PI / 180.0 );
385
386  return start + vec;
387 }
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:146
E_SERIE r
Definition: eserie.cpp:41
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
Definition: vector2d.h:404
VECTOR2< T > Rotate(double aAngle) const
Rotate the vector by a given angle.
Definition: vector2d.h:371

References EuclideanNorm(), r, VECTOR2< T >::Resize(), and VECTOR2< T >::Rotate().

Referenced by CalcArcAngle(), and CalcArcCenter().

## ◆ CalcArcCenter() [2/4]

 const VECTOR2D CalcArcCenter ( const VECTOR2D & aStart, const VECTOR2D & aMid, const VECTOR2D & aEnd )

Definition at line 390 of file trigo.cpp.

391 {
392  VECTOR2D center;
393  double yDelta_21 = aMid.y - aStart.y;
394  double xDelta_21 = aMid.x - aStart.x;
395  double yDelta_32 = aEnd.y - aMid.y;
396  double xDelta_32 = aEnd.x - aMid.x;
397
398  // This is a special case for aMid as the half-way point when aSlope = 0 and bSlope = inf
399  // or the other way around. In that case, the center lies in a straight line between
400  // aStart and aEnd
401  if( ( ( xDelta_21 == 0.0 ) && ( yDelta_32 == 0.0 ) ) ||
402  ( ( yDelta_21 == 0.0 ) && ( xDelta_32 == 0.0 ) ) )
403  {
404  center.x = ( aStart.x + aEnd.x ) / 2.0;
405  center.y = ( aStart.y + aEnd.y ) / 2.0 ;
406  return center;
407  }
408
409  // Prevent div=0 errors
410  if( xDelta_21 == 0.0 )
411  xDelta_21 = std::numeric_limits<double>::epsilon();
412
413  if( xDelta_32 == 0.0 )
414  xDelta_32 = -std::numeric_limits<double>::epsilon();
415
416  double aSlope = yDelta_21 / xDelta_21;
417  double bSlope = yDelta_32 / xDelta_32;
418
419  double daSlope = aSlope * VECTOR2D( 0.5 / yDelta_21, 0.5 / xDelta_21 ).EuclideanNorm();
420  double dbSlope = bSlope * VECTOR2D( 0.5 / yDelta_32, 0.5 / xDelta_32 ).EuclideanNorm();
421
422  if( aSlope == bSlope )
423  {
424  if( aStart == aEnd )
425  {
426  // This is a special case for a 360 degrees arc. In this case, the center is halfway between
427  // the midpoint and either end point
428  center.x = ( aStart.x + aMid.x ) / 2.0;
429  center.y = ( aStart.y + aMid.y ) / 2.0 ;
430  return center;
431  }
432  else
433  {
434  // If the points are colinear, the center is at infinity, so offset
435  // the slope by a minimal amount
436  // Warning: This will induce a small error in the center location
437  aSlope += std::numeric_limits<double>::epsilon();
438  bSlope -= std::numeric_limits<double>::epsilon();
439  }
440  }
441
442  // Prevent divide by zero error
443  if( aSlope == 0.0 )
444  aSlope = std::numeric_limits<double>::epsilon();
445
446  // What follows is the calculation of the center using the slope of the two lines as well as
447  // the propagated error that occurs when rounding to the nearest nanometer. The error can be
448  // ±0.5 units but can add up to multiple nanometers after the full calculation is performed.
449  // All variables starting with `d` are the delta of that variable. This is approximately equal
450  // to the standard deviation.
451  // We ignore the possible covariance between variables. We also truncate our series expansion
452  // at the first term. These are reasonable assumptions as the worst-case scenario is that we
453  // underestimate the potential uncertainty, which would potentially put us back at the status quo
454  double abSlopeStartEndY = aSlope * bSlope * ( aStart.y - aEnd.y );
455  double dabSlopeStartEndY = abSlopeStartEndY * std::sqrt( ( daSlope / aSlope * daSlope / aSlope )
456  + ( dbSlope / bSlope * dbSlope / bSlope )
457  + ( M_SQRT1_2 / ( aStart.y - aEnd.y )
458  * M_SQRT1_2 / ( aStart.y - aEnd.y ) ) );
459
460  double bSlopeStartMidX = bSlope * ( aStart.x + aMid.x );
461  double dbSlopeStartMidX = bSlopeStartMidX * std::sqrt( ( dbSlope / bSlope * dbSlope / bSlope )
462  + ( M_SQRT1_2 / ( aStart.x + aMid.x )
463  * M_SQRT1_2 / ( aStart.x + aMid.x ) ) );
464
465  double aSlopeMidEndX = aSlope * ( aMid.x + aEnd.x );
466  double daSlopeMidEndX = aSlopeMidEndX * std::sqrt( ( daSlope / aSlope * daSlope / aSlope )
467  + ( M_SQRT1_2 / ( aMid.x + aEnd.x )
468  * M_SQRT1_2 / ( aMid.x + aEnd.x ) ) );
469
470  double twiceBASlopeDiff = 2 * ( bSlope - aSlope );
471  double dtwiceBASlopeDiff = 2 * std::sqrt( dbSlope * dbSlope + daSlope * daSlope );
472
473  double centerNumeratorX = abSlopeStartEndY + bSlopeStartMidX - aSlopeMidEndX;
474  double dCenterNumeratorX = std::sqrt( dabSlopeStartEndY * dabSlopeStartEndY
475  + dbSlopeStartMidX * dbSlopeStartMidX
476  + daSlopeMidEndX * daSlopeMidEndX );
477
478  double centerX = ( abSlopeStartEndY + bSlopeStartMidX - aSlopeMidEndX ) / twiceBASlopeDiff;
479
480  double dCenterX = centerX * std::sqrt( ( dCenterNumeratorX / centerNumeratorX * dCenterNumeratorX / centerNumeratorX )
481  + ( dtwiceBASlopeDiff / twiceBASlopeDiff * dtwiceBASlopeDiff / twiceBASlopeDiff ) );
482
483
484  double centerNumeratorY = ( ( aStart.x + aMid.x ) / 2.0 - centerX );
485  double dCenterNumeratorY = std::sqrt( 1.0 / 8.0 + dCenterX * dCenterX );
486
487  double centerFirstTerm = centerNumeratorY / aSlope;
488  double dcenterFirstTermY = centerFirstTerm * std::sqrt(
489  ( dCenterNumeratorY/ centerNumeratorY * dCenterNumeratorY / centerNumeratorY )
490  + ( daSlope / aSlope * daSlope / aSlope ) );
491
492  double centerY = centerFirstTerm + ( aStart.y + aMid.y ) / 2.0;
493  double dCenterY = std::sqrt( dcenterFirstTermY * dcenterFirstTermY + 1.0 / 8.0 );
494
495  double rounded100CenterX = std::floor( ( centerX + 50.0 ) / 100.0 ) * 100.0;
496  double rounded100CenterY = std::floor( ( centerY + 50.0 ) / 100.0 ) * 100.0;
497  double rounded10CenterX = std::floor( ( centerX + 5.0 ) / 10.0 ) * 10.0;
498  double rounded10CenterY = std::floor( ( centerY + 5.0 ) / 10.0 ) * 10.0;
499
500  // The last step is to find the nice, round numbers near our baseline estimate and see if they are within our uncertainty
501  // range. If they are, then we use this round value as the true value. This is justified because ALL values within the
502  // uncertainty range are equally true. Using a round number will make sure that we are on a multiple of 1mil or 100nm
503  // when calculating centers.
504  if( std::abs( rounded100CenterX - centerX ) < dCenterX && std::abs( rounded100CenterY - centerY ) < dCenterY )
505  {
506  center.x = rounded100CenterX;
507  center.y = rounded100CenterY;
508  }
509  else if( std::abs( rounded10CenterX - centerX ) < dCenterX && std::abs( rounded10CenterY - centerY ) < dCenterY )
510  {
511  center.x = rounded10CenterX;
512  center.y = rounded10CenterY;
513  }
514  else
515  {
516  center.x = centerX;
517  center.y = centerY;
518  }
519
520
521  return center;
522 }
VECTOR2< double > VECTOR2D
Definition: vector2d.h:621
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h:293

References VECTOR2< T >::EuclideanNorm(), VECTOR2< T >::x, and VECTOR2< T >::y.

## ◆ CalcArcCenter() [3/4]

 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.

Parameters
 aStart The starting point of the circle (equivalent to aEnd) aMid The point on the arc, half-way between aStart and aEnd aEnd The ending point of the circle (equivalent to aStart)
Returns
The center of the circle

Definition at line 525 of file trigo.cpp.

526 {
527  VECTOR2D dStart( static_cast<double>( aStart.x ), static_cast<double>( aStart.y ) );
528  VECTOR2D dMid( static_cast<double>( aMid.x ), static_cast<double>( aMid.y ) );
529  VECTOR2D dEnd( static_cast<double>( aEnd.x ), static_cast<double>( aEnd.y ) );
530  VECTOR2D dCenter = CalcArcCenter( dStart, dMid, dEnd );
531
532  VECTOR2I iCenter;
533
534  iCenter.x = KiROUND( Clamp<double>( double( std::numeric_limits<int>::min() / 2.0 ),
535  dCenter.x,
536  double( std::numeric_limits<int>::max() / 2.0 ) ) );
537
538  iCenter.y = KiROUND( Clamp<double>( double( std::numeric_limits<int>::min() / 2.0 ),
539  dCenter.y,
540  double( std::numeric_limits<int>::max() / 2.0 ) ) );
541
542  return iCenter;
543 }
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
const VECTOR2D CalcArcCenter(const VECTOR2D &aStart, const VECTOR2D &aEnd, double aAngle)
Definition: trigo.cpp:362

References CalcArcCenter(), KiROUND(), VECTOR2< T >::x, and VECTOR2< T >::y.

## ◆ CalcArcCenter() [4/4]

 const wxPoint CalcArcCenter ( const wxPoint & aStart, const wxPoint & aMid, const wxPoint & aEnd )

Definition at line 546 of file trigo.cpp.

547 {
548  VECTOR2D dStart( static_cast<double>( aStart.x ), static_cast<double>( aStart.y ) );
549  VECTOR2D dMid( static_cast<double>( aMid.x ), static_cast<double>( aMid.y ) );
550  VECTOR2D dEnd( static_cast<double>( aEnd.x ), static_cast<double>( aEnd.y ) );
551  VECTOR2D dCenter = CalcArcCenter( dStart, dMid, dEnd );
552
553  wxPoint iCenter;
554
555  iCenter.x = KiROUND( Clamp<double>( double( std::numeric_limits<int>::min() / 2.0 ),
556  dCenter.x,
557  double( std::numeric_limits<int>::max() / 2.0 ) ) );
558
559  iCenter.y = KiROUND( Clamp<double>( double( std::numeric_limits<int>::min() / 2.0 ),
560  dCenter.y,
561  double( std::numeric_limits<int>::max() / 2.0 ) ) );
562
563  return iCenter;
564 }
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
const VECTOR2D CalcArcCenter(const VECTOR2D &aStart, const VECTOR2D &aEnd, double aAngle)
Definition: trigo.cpp:362

References CalcArcCenter(), KiROUND(), VECTOR2< T >::x, and VECTOR2< T >::y.

## ◆ CalcArcMid()

 const VECTOR2I CalcArcMid ( const VECTOR2I & aStart, const VECTOR2I & aEnd, const VECTOR2I & aCenter, bool aMinArcAngle = `true` )

Return the middle point of an arc, half-way between aStart and aEnd.

There are two possible solutions which can be found by toggling aMinArcAngle. The behaviour is undefined for semicircles (i.e. 180 degree arcs).

Parameters
 aStart The starting point of the arc (for calculating the radius) aEnd The end point of the arc (for determining the arc angle) aCenter The center point of the arc aMinArcAngle If true, returns the point that results in the smallest arc angle.
Returns
The middle point of the arc

Definition at line 163 of file trigo.cpp.

165 {
166  VECTOR2I startVector = aStart - aCenter;
167  VECTOR2I endVector = aEnd - aCenter;
168
169  double startAngle = ArcTangente( startVector.y, startVector.x );
170  double endAngle = ArcTangente( endVector.y, endVector.x );
171  double midPointRotAngleDeciDeg = NormalizeAngle180( startAngle - endAngle ) / 2;
172
173  if( !aMinArcAngle )
174  midPointRotAngleDeciDeg += 1800.0;
175
176  VECTOR2I newMid = aStart;
177  RotatePoint( newMid, aCenter, midPointRotAngleDeciDeg );
178
179  return newMid;
180 }
Define a general 2D-vector/point.
Definition: vector2d.h:61
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:229
T NormalizeAngle180(T Angle)
Normalize angle to be in the -180.0 .. 180.0 range.
Definition: trigo.h:387
double ArcTangente(int dy, int dx)
Definition: trigo.cpp:183

References ArcTangente(), NormalizeAngle180(), RotatePoint(), VECTOR2< T >::x, and VECTOR2< T >::y.

## ◆ IsPointOnSegment()

 bool IsPointOnSegment ( const wxPoint & aSegStart, const wxPoint & aSegEnd, const wxPoint & aTestPoint )

Test if aTestPoint is on line defined by aSegStart and aSegEnd.

This function is faster than TestSegmentHit() because aTestPoint should be exactly on the line. This works fine only for H, V and 45 degree line segments.

Parameters
 aSegStart The first point of the line segment. aSegEnd The second point of the line segment. aTestPoint The point to test.
Returns
true if the point is on the line segment.

Definition at line 42 of file trigo.cpp.

44 {
45  wxPoint vectSeg = aSegEnd - aSegStart; // Vector from S1 to S2
46  wxPoint vectPoint = aTestPoint - aSegStart; // Vector from S1 to P
47
48  // Use long long here to avoid overflow in calculations
49  if( (long long) vectSeg.x * vectPoint.y - (long long) vectSeg.y * vectPoint.x )
50  return false; /* Cross product non-zero, vectors not parallel */
51
52  if( ( (long long) vectSeg.x * vectPoint.x + (long long) vectSeg.y * vectPoint.y ) <
53  ( (long long) vectPoint.x * vectPoint.x + (long long) vectPoint.y * vectPoint.y ) )
54  return false; /* Point not on segment */
55
56  return true;
57 }

## ◆ RotatePoint() [1/6]

 void RotatePoint ( int * pX, int * pY, double angle )

Definition at line 229 of file trigo.cpp.

230 {
231  int tmp;
232
234
235  // Cheap and dirty optimizations for 0, 90, 180, and 270 degrees.
236  if( angle == 0 )
237  return;
238
239  if( angle == 900 ) /* sin = 1, cos = 0 */
240  {
241  tmp = *pX;
242  *pX = *pY;
243  *pY = -tmp;
244  }
245  else if( angle == 1800 ) /* sin = 0, cos = -1 */
246  {
247  *pX = -*pX;
248  *pY = -*pY;
249  }
250  else if( angle == 2700 ) /* sin = -1, cos = 0 */
251  {
252  tmp = *pX;
253  *pX = -*pY;
254  *pY = tmp;
255  }
256  else
257  {
258  double fangle = DECIDEG2RAD( angle );
259  double sinus = sin( fangle );
260  double cosinus = cos( fangle );
261  double fpx = (*pY * sinus ) + (*pX * cosinus );
262  double fpy = (*pY * cosinus ) - (*pX * sinus );
263  *pX = KiROUND( fpx );
264  *pY = KiROUND( fpy );
265  }
266 }
void NORMALIZE_ANGLE_POS(T &Angle)
Definition: trigo.h:290
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
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

References PNS::angle(), DECIDEG2RAD(), KiROUND(), and NORMALIZE_ANGLE_POS().

## ◆ RotatePoint() [2/6]

 void RotatePoint ( int * pX, int * pY, int cx, int cy, double angle )

Definition at line 269 of file trigo.cpp.

270 {
271  int ox, oy;
272
273  ox = *pX - cx;
274  oy = *pY - cy;
275
276  RotatePoint( &ox, &oy, angle );
277
278  *pX = ox + cx;
279  *pY = oy + cy;
280 }
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:229
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)

References PNS::angle(), and RotatePoint().

## ◆ RotatePoint() [3/6]

 void RotatePoint ( wxPoint * point, const wxPoint & centre, double angle )

Definition at line 283 of file trigo.cpp.

284 {
285  int ox, oy;
286
287  ox = point->x - centre.x;
288  oy = point->y - centre.y;
289
290  RotatePoint( &ox, &oy, angle );
291  point->x = ox + centre.x;
292  point->y = oy + centre.y;
293 }
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:229
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)

References PNS::angle(), and RotatePoint().

## ◆ RotatePoint() [4/6]

 void RotatePoint ( VECTOR2I & point, const VECTOR2I & centre, double angle )

Definition at line 295 of file trigo.cpp.

296 {
297  wxPoint c( centre.x, centre.y );
298  wxPoint p( point.x, point.y );
299
300  RotatePoint(&p, c, angle);
301
302  point.x = p.x;
303  point.y = p.y;
304 }
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:229
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)

References PNS::angle(), RotatePoint(), VECTOR2< T >::x, and VECTOR2< T >::y.

## ◆ RotatePoint() [5/6]

 void RotatePoint ( double * pX, double * pY, double cx, double cy, double angle )

Definition at line 307 of file trigo.cpp.

308 {
309  double ox, oy;
310
311  ox = *pX - cx;
312  oy = *pY - cy;
313
314  RotatePoint( &ox, &oy, angle );
315
316  *pX = ox + cx;
317  *pY = oy + cy;
318 }
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:229
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)

References PNS::angle(), and RotatePoint().

## ◆ RotatePoint() [6/6]

 void RotatePoint ( double * pX, double * pY, double angle )

Definition at line 321 of file trigo.cpp.

322 {
323  double tmp;
324
326
327  // Cheap and dirty optimizations for 0, 90, 180, and 270 degrees.
328  if( angle == 0 )
329  return;
330
331  if( angle == 900 ) /* sin = 1, cos = 0 */
332  {
333  tmp = *pX;
334  *pX = *pY;
335  *pY = -tmp;
336  }
337  else if( angle == 1800 ) /* sin = 0, cos = -1 */
338  {
339  *pX = -*pX;
340  *pY = -*pY;
341  }
342  else if( angle == 2700 ) /* sin = -1, cos = 0 */
343  {
344  tmp = *pX;
345  *pX = -*pY;
346  *pY = tmp;
347  }
348  else
349  {
350  double fangle = DECIDEG2RAD( angle );
351  double sinus = sin( fangle );
352  double cosinus = cos( fangle );
353
354  double fpx = (*pY * sinus ) + (*pX * cosinus );
355  double fpy = (*pY * cosinus ) - (*pX * sinus );
356  *pX = fpx;
357  *pY = fpy;
358  }
359 }
void NORMALIZE_ANGLE_POS(T &Angle)
Definition: trigo.h:290
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
Definition: trigo.h:233

## ◆ SegmentIntersectsSegment()

 bool SegmentIntersectsSegment ( const wxPoint & a_p1_l1, const wxPoint & a_p2_l1, const wxPoint & a_p1_l2, const wxPoint & a_p2_l2, wxPoint * aIntersectionPoint = `nullptr` )

Test if two lines intersect.

Parameters
 a_p1_l1 The first point of the first line. a_p2_l1 The second point of the first line. a_p1_l2 The first point of the second line. a_p2_l2 The second point of the second line. aIntersectionPoint is filled with the intersection point if it exists
Returns
bool - true if the two segments defined by four points intersect. (i.e. if the 2 segments have at least a common point)

Definition at line 61 of file trigo.cpp.

64 {
65
66  //We are forced to use 64bit ints because the internal units can overflow 32bit ints when
67  // multiplied with each other, the alternative would be to scale the units down (i.e. divide
68  // by a fixed number).
69  int64_t dX_a, dY_a, dX_b, dY_b, dX_ab, dY_ab;
70  int64_t num_a, num_b, den;
71
72  //Test for intersection within the bounds of both line segments using line equations of the
73  // form:
74  // x_k(u_k) = u_k * dX_k + x_k(0)
75  // y_k(u_k) = u_k * dY_k + y_k(0)
76  // with 0 <= u_k <= 1 and k = [ a, b ]
77
78  dX_a = int64_t{ a_p2_l1.x } - a_p1_l1.x;
79  dY_a = int64_t{ a_p2_l1.y } - a_p1_l1.y;
80  dX_b = int64_t{ a_p2_l2.x } - a_p1_l2.x;
81  dY_b = int64_t{ a_p2_l2.y } - a_p1_l2.y;
82  dX_ab = int64_t{ a_p1_l2.x } - a_p1_l1.x;
83  dY_ab = int64_t{ a_p1_l2.y } - a_p1_l1.y;
84
85  den = dY_a * dX_b - dY_b * dX_a ;
86
87  //Check if lines are parallel
88  if( den == 0 )
89  return false;
90
91  num_a = dY_ab * dX_b - dY_b * dX_ab;
92  num_b = dY_ab * dX_a - dY_a * dX_ab;
93
94  // Only compute the intersection point if requested
95  if( aIntersectionPoint )
96  {
97  *aIntersectionPoint = a_p1_l1;
98  aIntersectionPoint->x += KiROUND( dX_a * ( double )num_a / ( double )den );
99  aIntersectionPoint->y += KiROUND( dY_a * ( double )num_b / ( double )den );
100  }
101
102  if( den < 0 )
103  {
104  den = -den;
105  num_a = -num_a;
106  num_b = -num_b;
107  }
108
109  //Test sign( u_a ) and return false if negative
110  if( num_a < 0 )
111  return false;
112
113  //Test sign( u_b ) and return false if negative
114  if( num_b < 0 )
115  return false;
116
117  //Test to ensure (u_a <= 1)
118  if( num_a > den )
119  return false;
120
121  //Test to ensure (u_b <= 1)
122  if( num_b > den )
123  return false;
124
125  return true;
126 }
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

References KiROUND().

Referenced by EDA_RECT::Intersects().

## ◆ TestSegmentHit()

 bool TestSegmentHit ( const wxPoint & aRefPoint, const wxPoint & aStart, const wxPoint & aEnd, int aDist )

Test if aRefPoint is with aDistance on the line defined by aStart and aEnd.

Parameters
 aRefPoint = reference point to test aStart is the first end-point of the line segment aEnd is the second end-point of the line segment aDist = maximum distance for hit

Definition at line 129 of file trigo.cpp.

131 {
132  int xmin = aStart.x;
133  int xmax = aEnd.x;
134  int ymin = aStart.y;
135  int ymax = aEnd.y;
136  wxPoint delta = aStart - aRefPoint;
137
138  if( xmax < xmin )
139  std::swap( xmax, xmin );
140
141  if( ymax < ymin )
142  std::swap( ymax, ymin );
143
144  // First, check if we are outside of the bounding box
145  if( ( ymin - aRefPoint.y > aDist ) || ( aRefPoint.y - ymax > aDist ) )
146  return false;
147
148  if( ( xmin - aRefPoint.x > aDist ) || ( aRefPoint.x - xmax > aDist ) )
149  return false;
150
151  // Next, eliminate easy cases
152  if( aStart.x == aEnd.x && aRefPoint.y > ymin && aRefPoint.y < ymax )
153  return std::abs( delta.x ) <= aDist;
154
155  if( aStart.y == aEnd.y && aRefPoint.x > xmin && aRefPoint.x < xmax )
156  return std::abs( delta.y ) <= aDist;
157
158  SEG segment( aStart, aEnd );
159  return segment.SquaredDistance( aRefPoint ) < SEG::Square( aDist + 1 );
160 }
static SEG::ecoord Square(int a)
Definition: seg.h:122
Definition: seg.h:40
constexpr int delta

References delta, SEG::Square(), and SEG::SquaredDistance().