KiCad PCB EDA Suite
Loading...
Searching...
No Matches
trigo.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) 2014 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
25
26#include <algorithm> // for std::clamp
27#include <limits> // for numeric_limits
28#include <cstdlib> // for abs
29#include <type_traits> // for swap
30
31#include <geometry/seg.h>
32#include <math/util.h>
33#include <math/vector2d.h> // for VECTOR2I
34#include <trigo.h>
35
36
37/*
38CircleCenterFrom3Points calculate the center of a circle defined by 3 points
39It is similar to CalcArcCenter( const VECTOR2D& aStart, const VECTOR2D& aMid, const VECTOR2D& aEnd )
40but it was needed to debug CalcArcCenter, so I keep it available for other issues in CalcArcCenter
41
42The perpendicular bisector of the segment between two points is the
43set of all points equidistant from both. So if you take the
44perpendicular bisector of (x1,y1) and (x2,y2) and the perpendicular
45bisector of the segment from (x2,y2) to (x3,y3) and find the
46intersection of those lines, that point will be the center.
47
48To find the equation of the perpendicular bisector of (x1,y1) to (x2,y2),
49you know that it passes through the midpoint of the segment:
50((x1+x2)/2,(y1+y2)/2), and if the slope of the line
51connecting (x1,y1) to (x2,y2) is m, the slope of the perpendicular
52bisector is -1/m. Work out the equations for the two lines, find
53their intersection, and bingo! You've got the coordinates of the center.
54
55An error should occur if the three points lie on a line, and you'll
56need special code to check for the case where one of the slopes is zero.
57
58see https://web.archive.org/web/20171223103555/http://mathforum.org/library/drmath/view/54323.html
59*/
60
61//#define USE_ALTERNATE_CENTER_ALGO
62
63#ifdef USE_ALTERNATE_CENTER_ALGO
64bool CircleCenterFrom3Points( const VECTOR2D& p1, const VECTOR2D& p2, const VECTOR2D& p3, VECTOR2D* aCenter )
65{
66 // Move coordinate origin to p2, to simplify calculations
67 VECTOR2D b = p1 - p2;
68 VECTOR2D d = p3 - p2;
69 double bc = ( b.x*b.x + b.y*b.y ) / 2.0;
70 double cd = ( -d.x*d.x - d.y*d.y ) / 2.0;
71 double det = -b.x*d.y + d.x*b.y;
72
73 if( fabs(det) < 1.0e-6 ) // arbitrary limit to avoid divide by 0
74 return false;
75
76 det = 1/det;
77 aCenter->x = ( -bc*d.y - cd*b.y ) * det;
78 aCenter->y = ( b.x*cd + d.x*bc ) * det;
79 *aCenter += p2;
80
81 return true;
82}
83#endif
84
85bool IsPointOnSegment( const VECTOR2I& aSegStart, const VECTOR2I& aSegEnd,
86 const VECTOR2I& aTestPoint )
87{
88 VECTOR2I vectSeg = aSegEnd - aSegStart; // Vector from S1 to S2
89 VECTOR2I vectPoint = aTestPoint - aSegStart; // Vector from S1 to P
90
91 // Use long long here to avoid overflow in calculations
92 if( (long long) vectSeg.x * vectPoint.y - (long long) vectSeg.y * vectPoint.x )
93 return false; /* Cross product non-zero, vectors not parallel */
94
95 if( ( (long long) vectSeg.x * vectPoint.x + (long long) vectSeg.y * vectPoint.y ) <
96 ( (long long) vectPoint.x * vectPoint.x + (long long) vectPoint.y * vectPoint.y ) )
97 return false; /* Point not on segment */
98
99 return true;
100}
101
102
103bool SegmentIntersectsSegment( const VECTOR2I& a_p1_l1, const VECTOR2I& a_p2_l1,
104 const VECTOR2I& a_p1_l2, const VECTOR2I& a_p2_l2,
105 VECTOR2I* aIntersectionPoint )
106{
107
108 // We are forced to use 64bit ints because the internal units can overflow 32bit ints when
109 // multiplied with each other, the alternative would be to scale the units down (i.e. divide
110 // by a fixed number).
111 int64_t dX_a, dY_a, dX_b, dY_b, dX_ab, dY_ab;
112 int64_t num_a, num_b, den;
113
114 // Test for intersection within the bounds of both line segments using line equations of the
115 // form:
116 // x_k(u_k) = u_k * dX_k + x_k(0)
117 // y_k(u_k) = u_k * dY_k + y_k(0)
118 // with 0 <= u_k <= 1 and k = [ a, b ]
119
120 dX_a = int64_t{ a_p2_l1.x } - a_p1_l1.x;
121 dY_a = int64_t{ a_p2_l1.y } - a_p1_l1.y;
122 dX_b = int64_t{ a_p2_l2.x } - a_p1_l2.x;
123 dY_b = int64_t{ a_p2_l2.y } - a_p1_l2.y;
124 dX_ab = int64_t{ a_p1_l2.x } - a_p1_l1.x;
125 dY_ab = int64_t{ a_p1_l2.y } - a_p1_l1.y;
126
127 den = dY_a * dX_b - dY_b * dX_a ;
128
129 // Check if lines are parallel.
130 if( den == 0 )
131 return false;
132
133 num_a = dY_ab * dX_b - dY_b * dX_ab;
134 num_b = dY_ab * dX_a - dY_a * dX_ab;
135
136 // Only compute the intersection point if requested.
137 if( aIntersectionPoint )
138 {
139 *aIntersectionPoint = a_p1_l1;
140 aIntersectionPoint->x += KiROUND( dX_a * ( double )num_a / ( double )den );
141 aIntersectionPoint->y += KiROUND( dY_a * ( double )num_b / ( double )den );
142 }
143
144 if( den < 0 )
145 {
146 den = -den;
147 num_a = -num_a;
148 num_b = -num_b;
149 }
150
151 // Test sign( u_a ) and return false if negative.
152 if( num_a < 0 )
153 return false;
154
155 // Test sign( u_b ) and return false if negative.
156 if( num_b < 0 )
157 return false;
158
159 // Test to ensure (u_a <= 1).
160 if( num_a > den )
161 return false;
162
163 // Test to ensure (u_b <= 1).
164 if( num_b > den )
165 return false;
166
167 return true;
168}
169
170
171bool TestSegmentHit( const VECTOR2I& aRefPoint, const VECTOR2I& aStart, const VECTOR2I& aEnd,
172 int aDist )
173{
174 int xmin = aStart.x;
175 int xmax = aEnd.x;
176 int ymin = aStart.y;
177 int ymax = aEnd.y;
178 VECTOR2I delta = aStart - aRefPoint;
179
180 if( xmax < xmin )
181 std::swap( xmax, xmin );
182
183 if( ymax < ymin )
184 std::swap( ymax, ymin );
185
186 // Check if we are outside of the bounding box.
187 if( ( ymin - aRefPoint.y > aDist ) || ( aRefPoint.y - ymax > aDist ) )
188 return false;
189
190 if( ( xmin - aRefPoint.x > aDist ) || ( aRefPoint.x - xmax > aDist ) )
191 return false;
192
193 // Eliminate easy cases.
194 if( aStart.x == aEnd.x && aRefPoint.y > ymin && aRefPoint.y < ymax )
195 return std::abs( delta.x ) <= aDist;
196
197 if( aStart.y == aEnd.y && aRefPoint.x > xmin && aRefPoint.x < xmax )
198 return std::abs( delta.y ) <= aDist;
199
200 SEG segment( aStart, aEnd );
201 return segment.SquaredDistance( aRefPoint ) < SEG::Square( aDist + 1 );
202}
203
204
205const VECTOR2I CalcArcMid( const VECTOR2I& aStart, const VECTOR2I& aEnd, const VECTOR2I& aCenter,
206 bool aMinArcAngle )
207{
208 VECTOR2I startVector = aStart - aCenter;
209 VECTOR2I endVector = aEnd - aCenter;
210
211 EDA_ANGLE startAngle( startVector );
212 EDA_ANGLE endAngle( endVector );
213 EDA_ANGLE midPointRotAngle = ( startAngle - endAngle ).Normalize180() / 2;
214
215 if( !aMinArcAngle )
216 midPointRotAngle += ANGLE_180;
217
218 VECTOR2I newMid = aStart;
219 RotatePoint( newMid, aCenter, midPointRotAngle );
220
221 return newMid;
222}
223
224
225void RotatePoint( int* pX, int* pY, const EDA_ANGLE& aAngle )
226{
227 VECTOR2I pt;
228 EDA_ANGLE angle = aAngle;
229
230 angle.Normalize();
231
232 // Cheap and dirty optimizations for 0, 90, 180, and 270 degrees.
233 if( angle == ANGLE_0 )
234 {
235 pt = VECTOR2I( *pX, *pY );
236 }
237 else if( angle == ANGLE_90 ) /* sin = 1, cos = 0 */
238 {
239 pt = VECTOR2I( *pY, -*pX );
240 }
241 else if( angle == ANGLE_180 ) /* sin = 0, cos = -1 */
242 {
243 pt = VECTOR2I( -*pX, -*pY );
244 }
245 else if( angle == ANGLE_270 ) /* sin = -1, cos = 0 */
246 {
247 pt = VECTOR2I( -*pY, *pX );
248 }
249 else
250 {
251 double sinus = angle.Sin();
252 double cosinus = angle.Cos();
253
254 pt.x = KiROUND( ( *pY * sinus ) + ( *pX * cosinus ) );
255 pt.y = KiROUND( ( *pY * cosinus ) - ( *pX * sinus ) );
256 }
257
258 *pX = pt.x;
259 *pY = pt.y;
260}
261
262
263void RotatePoint( int* pX, int* pY, int cx, int cy, const EDA_ANGLE& angle )
264{
265 int ox, oy;
266
267 ox = *pX - cx;
268 oy = *pY - cy;
269
270 RotatePoint( &ox, &oy, angle );
271
272 *pX = ox + cx;
273 *pY = oy + cy;
274}
275
276
277void RotatePoint( double* pX, double* pY, double cx, double cy, const EDA_ANGLE& angle )
278{
279 double ox, oy;
280
281 ox = *pX - cx;
282 oy = *pY - cy;
283
284 RotatePoint( &ox, &oy, angle );
285
286 *pX = ox + cx;
287 *pY = oy + cy;
288}
289
290
291void RotatePoint( double* pX, double* pY, const EDA_ANGLE& aAngle )
292{
293 EDA_ANGLE angle = aAngle;
294 VECTOR2D pt;
295
296 angle.Normalize();
297
298 // Cheap and dirty optimizations for 0, 90, 180, and 270 degrees.
299 if( angle == ANGLE_0 )
300 {
301 pt = VECTOR2D( *pX, *pY );
302 }
303 else if( angle == ANGLE_90 ) /* sin = 1, cos = 0 */
304 {
305 pt = VECTOR2D( *pY, -*pX );
306 }
307 else if( angle == ANGLE_180 ) /* sin = 0, cos = -1 */
308 {
309 pt = VECTOR2D( -*pX, -*pY );
310 }
311 else if( angle == ANGLE_270 ) /* sin = -1, cos = 0 */
312 {
313 pt = VECTOR2D( -*pY, *pX );
314 }
315 else
316 {
317 double sinus = angle.Sin();
318 double cosinus = angle.Cos();
319
320 pt.x = ( *pY * sinus ) + ( *pX * cosinus );
321 pt.y = ( *pY * cosinus ) - ( *pX * sinus );
322 }
323
324 *pX = pt.x;
325 *pY = pt.y;
326}
327
328
329const VECTOR2D CalcArcCenter( const VECTOR2D& aStart, const VECTOR2D& aEnd,
330 const EDA_ANGLE& aAngle )
331{
332 EDA_ANGLE angle( aAngle );
333 VECTOR2D start = aStart;
334 VECTOR2D end = aEnd;
335
336 if( angle < ANGLE_0 )
337 {
338 std::swap( start, end );
339 angle = -angle;
340 }
341
342 if( angle > ANGLE_180 )
343 {
344 std::swap( start, end );
345 angle = ANGLE_360 - angle;
346 }
347
348 double chord = ( start - end ).EuclideanNorm();
349 double r = ( chord / 2.0 ) / ( angle / 2.0 ).Sin();
350 double d_squared = r * r - chord* chord / 4.0;
351 double d = 0.0;
352
353 if( d_squared > 0.0 )
354 d = sqrt( d_squared );
355
356 VECTOR2D vec2 = VECTOR2D(end - start).Resize( d );
357 VECTOR2D vc = VECTOR2D(end - start).Resize( chord / 2 );
358
359 RotatePoint( vec2, -ANGLE_90 );
360
361 return VECTOR2D( start + vc + vec2 );
362}
363
364
365const VECTOR2D CalcArcCenter( const VECTOR2D& aStart, const VECTOR2D& aMid, const VECTOR2D& aEnd )
366{
367 // If the three input points are clustered within a 10 IU bounding box, no
368 // meaningful circumcircle exists so return the centroid
369 constexpr double kCoincidentRadius = 5.0;
370
371 auto [minX, maxX] = std::minmax( { aStart.x, aMid.x, aEnd.x } );
372 auto [minY, maxY] = std::minmax( { aStart.y, aMid.y, aEnd.y } );
373
374 if( maxX - minX < kCoincidentRadius && maxY - minY < kCoincidentRadius )
375 {
376 return VECTOR2D( ( aStart.x + aMid.x + aEnd.x ) / 3.0,
377 ( aStart.y + aMid.y + aEnd.y ) / 3.0 );
378 }
379
381
382 double yDelta_21 = aMid.y - aStart.y;
383 double xDelta_21 = aMid.x - aStart.x;
384 double yDelta_32 = aEnd.y - aMid.y;
385 double xDelta_32 = aEnd.x - aMid.x;
386
387 // This is a special case for aMid as the half-way point when aSlope = 0 and bSlope = inf
388 // or the other way around. In that case, the center lies in a straight line between
389 // aStart and aEnd
390 if( ( ( xDelta_21 == 0.0 ) && ( yDelta_32 == 0.0 ) ) ||
391 ( ( yDelta_21 == 0.0 ) && ( xDelta_32 == 0.0 ) ) )
392 {
393 center.x = ( aStart.x + aEnd.x ) / 2.0;
394 center.y = ( aStart.y + aEnd.y ) / 2.0 ;
395 return center;
396 }
397
398 // Prevent div-by-0 errors
399 if( xDelta_21 == 0.0 )
400 xDelta_21 = std::numeric_limits<double>::epsilon();
401
402 if( xDelta_32 == 0.0 )
403 xDelta_32 = -std::numeric_limits<double>::epsilon();
404
405 double aSlope = yDelta_21 / xDelta_21;
406 double bSlope = yDelta_32 / xDelta_32;
407
408 double daSlope = aSlope * VECTOR2D( 0.5 / yDelta_21, 0.5 / xDelta_21 ).EuclideanNorm();
409 double dbSlope = bSlope * VECTOR2D( 0.5 / yDelta_32, 0.5 / xDelta_32 ).EuclideanNorm();
410
411 if( aSlope == bSlope )
412 {
413 if( aStart == aEnd )
414 {
415 // This is a special case for a 360 degrees arc. In this case, the center is
416 // halfway between the midpoint and either end point.
417 center.x = ( aStart.x + aMid.x ) / 2.0;
418 center.y = ( aStart.y + aMid.y ) / 2.0 ;
419 return center;
420 }
421 else
422 {
423 // If the points are colinear, the center is at infinity, so offset
424 // the slope by a minimal amount
425 // Warning: This will induce a small error in the center location
426 aSlope += std::numeric_limits<double>::epsilon();
427 bSlope -= std::numeric_limits<double>::epsilon();
428 }
429 }
430#ifdef USE_ALTERNATE_CENTER_ALGO
431 // We can call ArcCenterFrom3Points from here because special cases are filtered.
432 CircleCenterFrom3Points( aStart, aMid, aEnd, &center );
433 return center;
434#endif
435
436 // Prevent divide by zero error
437 // a small value is used. std::numeric_limits<double>::epsilon() is too small and
438 // generate false results
439 if( aSlope == 0.0 )
440 aSlope = 1e-10;
441 if( bSlope == 0.0 )
442 bSlope = 1e-10;
443
444 // What follows is the calculation of the center using the slope of the two lines as well as
445 // the propagated error that occurs when rounding to the nearest nanometer. The error can be
446 // ±0.5 units but can add up to multiple nanometers after the full calculation is performed.
447 // All variables starting with `d` are the delta of that variable. This is approximately equal
448 // to the standard deviation.
449 // We ignore the possible covariance between variables. We also truncate our series expansion
450 // at the first term. These are reasonable assumptions as the worst-case scenario is that we
451 // underestimate the potential uncertainty, which would potentially put us back at the status
452 // quo.
453 double abSlopeStartEndY = aSlope * bSlope * ( aStart.y - aEnd.y );
454 double dabSlopeStartEndY = abSlopeStartEndY *
455 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 double dCenterX = centerX * std::sqrt( ( dCenterNumeratorX / centerNumeratorX *
480 dCenterNumeratorX / centerNumeratorX )
481 + ( dtwiceBASlopeDiff / twiceBASlopeDiff *
482 dtwiceBASlopeDiff / twiceBASlopeDiff ) );
483
484
485 double centerNumeratorY = ( ( aStart.x + aMid.x ) / 2.0 - centerX );
486 double dCenterNumeratorY = std::sqrt( 1.0 / 8.0 + dCenterX * dCenterX );
487
488 double centerFirstTerm = centerNumeratorY / aSlope;
489 double dcenterFirstTermY = centerFirstTerm * std::sqrt(
490 ( dCenterNumeratorY/ centerNumeratorY *
491 dCenterNumeratorY / centerNumeratorY )
492 + ( daSlope / aSlope * daSlope / aSlope ) );
493
494 double centerY = centerFirstTerm + ( aStart.y + aMid.y ) / 2.0;
495 double dCenterY = std::sqrt( dcenterFirstTermY * dcenterFirstTermY + 1.0 / 8.0 );
496
497 double rounded100CenterX = std::floor( ( centerX + 50.0 ) / 100.0 ) * 100.0;
498 double rounded100CenterY = std::floor( ( centerY + 50.0 ) / 100.0 ) * 100.0;
499 double rounded10CenterX = std::floor( ( centerX + 5.0 ) / 10.0 ) * 10.0;
500 double rounded10CenterY = std::floor( ( centerY + 5.0 ) / 10.0 ) * 10.0;
501
502 // The last step is to find the nice, round numbers near our baseline estimate and see if
503 // they are within our uncertainty range. If they are, then we use this round value as the
504 // true value. This is justified because ALL values within the uncertainty range are equally
505 // true. Using a round number will make sure that we are on a multiple of 1mil or 100nm
506 // when calculating centers.
507 if( std::abs( rounded100CenterX - centerX ) < dCenterX &&
508 std::abs( rounded100CenterY - centerY ) < dCenterY )
509 {
510 center.x = rounded100CenterX;
511 center.y = rounded100CenterY;
512 }
513 else if( std::abs( rounded10CenterX - centerX ) < dCenterX &&
514 std::abs( rounded10CenterY - centerY ) < dCenterY )
515 {
516 center.x = rounded10CenterX;
517 center.y = rounded10CenterY;
518 }
519 else
520 {
521 center.x = centerX;
522 center.y = centerY;
523 }
524
525
526 return center;
527}
528
529
530const VECTOR2I CalcArcCenter( const VECTOR2I& aStart, const VECTOR2I& aMid, const VECTOR2I& aEnd )
531{
532 VECTOR2D dStart( static_cast<double>( aStart.x ), static_cast<double>( aStart.y ) );
533 VECTOR2D dMid( static_cast<double>( aMid.x ), static_cast<double>( aMid.y ) );
534 VECTOR2D dEnd( static_cast<double>( aEnd.x ), static_cast<double>( aEnd.y ) );
535 VECTOR2D dCenter = CalcArcCenter( dStart, dMid, dEnd );
536
537 VECTOR2I iCenter;
538
539 iCenter.x = KiROUND( std::clamp( dCenter.x,
540 double( std::numeric_limits<int>::min() + 100 ),
541 double( std::numeric_limits<int>::max() - 100 ) ) );
542
543 iCenter.y = KiROUND( std::clamp( dCenter.y,
544 double( std::numeric_limits<int>::min() + 100 ),
545 double( std::numeric_limits<int>::max() - 100 ) ) );
546
547 return iCenter;
548}
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:986
EDA_ANGLE Normalize()
Definition eda_angle.h:229
double Sin() const
Definition eda_angle.h:178
double Cos() const
Definition eda_angle.h:197
Definition seg.h:38
ecoord SquaredDistance(const SEG &aSeg) const
Definition seg.cpp:76
static SEG::ecoord Square(int a)
Definition seg.h:119
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition vector2d.h:279
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
Definition vector2d.h:381
static constexpr EDA_ANGLE ANGLE_0
Definition eda_angle.h:411
static constexpr EDA_ANGLE ANGLE_90
Definition eda_angle.h:413
static constexpr EDA_ANGLE ANGLE_270
Definition eda_angle.h:416
static constexpr EDA_ANGLE ANGLE_360
Definition eda_angle.h:417
static constexpr EDA_ANGLE ANGLE_180
Definition eda_angle.h:415
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:400
static VECTOR2D CircleCenterFrom3Points(const VECTOR2D &p1, const VECTOR2D &p2, const VECTOR2D &p3)
VECTOR2I center
VECTOR2I end
int delta
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.
Definition trigo.cpp:205
bool TestSegmentHit(const VECTOR2I &aRefPoint, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aDist)
Test if aRefPoint is with aDistance on the line defined by aStart and aEnd.
Definition trigo.cpp:171
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:225
bool SegmentIntersectsSegment(const VECTOR2I &a_p1_l1, const VECTOR2I &a_p2_l1, const VECTOR2I &a_p1_l2, const VECTOR2I &a_p2_l2, VECTOR2I *aIntersectionPoint)
Test if two lines intersect.
Definition trigo.cpp:103
bool IsPointOnSegment(const VECTOR2I &aSegStart, const VECTOR2I &aSegEnd, const VECTOR2I &aTestPoint)
Test if aTestPoint is on line defined by aSegStart and aSegEnd.
Definition trigo.cpp:85
const VECTOR2D CalcArcCenter(const VECTOR2D &aStart, const VECTOR2D &aEnd, const EDA_ANGLE &aAngle)
Definition trigo.cpp:329
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683
VECTOR2< double > VECTOR2D
Definition vector2d.h:682