KiCad PCB EDA Suite
Loading...
Searching...
No Matches
vector2d.h
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) 2010 Virtenio GmbH, Torsten Hueter, torsten.hueter <at> virtenio.de
5 * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
6 * Copyright (C) 2012-2021 KiCad Developers, see AUTHORS.txt for contributors.
7 * Copyright (C) 2013 CERN
8 * @author Tomasz Wlostowski <[email protected]>
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, you may find one here:
22 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
23 * or you may search the http://www.gnu.org website for the version 2 license,
24 * or you may write to the Free Software Foundation, Inc.,
25 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
26 */
27
28#ifndef VECTOR2D_H_
29#define VECTOR2D_H_
30
31#include <limits>
32#include <iostream>
33#include <sstream>
34#include <type_traits>
35
36#include <math/util.h>
37
41template <class T>
43{
46 typedef T extended_type;
47};
48
49template <>
50struct VECTOR2_TRAITS<int>
51{
52 typedef int64_t extended_type;
53};
54
55// Forward declarations for template friends
56template <class T>
57class VECTOR2;
58template <class T>
59std::ostream& operator<<( std::ostream& aStream, const VECTOR2<T>& aVector );
60
68template <class T = int>
70{
71public:
73 typedef T coord_type;
74
75 static constexpr extended_type ECOORD_MAX = std::numeric_limits<extended_type>::max();
76 static constexpr extended_type ECOORD_MIN = std::numeric_limits<extended_type>::min();
77
78 T x, y;
79
82
84 VECTOR2( T x, T y );
85
87 template <typename CastingType>
89 {
90 if( std::is_same<T, int>::value )
91 {
92 CastingType minI = static_cast<CastingType>( std::numeric_limits<int>::min() );
93 CastingType maxI = static_cast<CastingType>( std::numeric_limits<int>::max() );
94
95 x = static_cast<int>( Clamp( minI, aVec.x, maxI ) );
96 y = static_cast<int>( Clamp( minI, aVec.y, maxI ) );
97 }
98 else
99 {
100 x = static_cast<T>( aVec.x );
101 y = static_cast<T>( aVec.y );
102 }
103 }
104
106 VECTOR2( const VECTOR2<T>& aVec )
107 {
108 x = aVec.x;
109 y = aVec.y;
110 }
111
113 template <typename CastedType>
115 {
116 if( std::is_same<CastedType, int>::value )
117 {
118 T minI = static_cast<T>( std::numeric_limits<int>::min() );
119 T maxI = static_cast<T>( std::numeric_limits<int>::max() );
120
121 return VECTOR2<int>( static_cast<int>( Clamp( minI, x, maxI ) ),
122 static_cast<int>( Clamp( minI, y, maxI ) ) );
123 }
124 else
125 {
126 return VECTOR2<CastedType>( static_cast<CastedType>( x ), static_cast<CastedType>( y ) );
127 }
128 }
129
130 // virtual ~VECTOR2();
131
139 T EuclideanNorm() const;
140
149
150
157
164 VECTOR2<T> Resize( T aNewLength ) const;
165
171 const std::string Format() const;
172
176 extended_type Cross( const VECTOR2<T>& aVector ) const;
177
181 extended_type Dot( const VECTOR2<T>& aVector ) const;
182
183
184 // Operators
185
187 VECTOR2<T>& operator=( const VECTOR2<T>& aVector );
188
190 VECTOR2<T> operator+( const VECTOR2<T>& aVector ) const;
191
193 VECTOR2<T> operator+( const T& aScalar ) const;
194
196 VECTOR2<T>& operator+=( const VECTOR2<T>& aVector );
197
199 VECTOR2<T>& operator*=( const VECTOR2<T>& aVector );
200
201 VECTOR2<T>& operator*=( const T& aScalar );
202
204 VECTOR2<T>& operator+=( const T& aScalar );
205
207 VECTOR2<T> operator-( const VECTOR2<T>& aVector ) const;
208
210 VECTOR2<T> operator-( const T& aScalar ) const;
211
213 VECTOR2<T>& operator-=( const VECTOR2<T>& aVector );
214
216 VECTOR2<T>& operator-=( const T& aScalar );
217
220
222 extended_type operator*( const VECTOR2<T>& aVector ) const;
223
225 VECTOR2<T> operator*( const T& aFactor ) const;
226
228 VECTOR2<T> operator/( double aFactor ) const;
229
231 bool operator==( const VECTOR2<T>& aVector ) const;
232
234 bool operator!=( const VECTOR2<T>& aVector ) const;
235
237 bool operator<( const VECTOR2<T>& aVector ) const;
238 bool operator<=( const VECTOR2<T>& aVector ) const;
239
241 bool operator>( const VECTOR2<T>& aVector ) const;
242 bool operator>=( const VECTOR2<T>& aVector ) const;
243};
244
245
246// ----------------------
247// --- Implementation ---
248// ----------------------
249
250template <class T>
252{
253}
254
255
256template <class T>
258{
259 x = aX;
260 y = aY;
261}
262
263
264template <class T>
266{
267 // 45° are common in KiCad, so we can optimize the calculation
268 if( std::abs( x ) == std::abs( y ) )
269 return static_cast<T>( std::abs( x ) * M_SQRT2 );
270
271 return static_cast<T>( sqrt( (extended_type) x * x + (extended_type) y * y ) );
272}
273
274
275template <class T>
277{
278 return (extended_type) x * x + (extended_type) y * y;
279}
280
281
282template <class T>
284{
285 VECTOR2<T> perpendicular( -y, x );
286 return perpendicular;
287}
288
289
290template <class T>
292{
293 x = aVector.x;
294 y = aVector.y;
295 return *this;
296}
297
298
299template <class T>
301{
302 x += aVector.x;
303 y += aVector.y;
304 return *this;
305}
306
307
308template <class T>
310{
311 x *= aVector.x;
312 y *= aVector.y;
313 return *this;
314}
315
316
317template <class T>
319{
320 x *= aScalar;
321 y *= aScalar;
322 return *this;
323}
324
325
326template <class T>
328{
329 x += aScalar;
330 y += aScalar;
331 return *this;
332}
333
334
335template <class T>
337{
338 x -= aVector.x;
339 y -= aVector.y;
340 return *this;
341}
342
343
344template <class T>
346{
347 x -= aScalar;
348 y -= aScalar;
349 return *this;
350}
351
352
353template <class T>
354VECTOR2<T> VECTOR2<T>::Resize( T aNewLength ) const
355{
356 if( x == 0 && y == 0 )
357 return VECTOR2<T> ( 0, 0 );
358
359 double newX;
360 double newY;
361
362 if( std::abs( x ) == std::abs( y ) )
363 {
364 newX = newY = std::abs( aNewLength ) * M_SQRT1_2;
365 }
366 else
367 {
368 extended_type x_sq = (extended_type) x * x;
369 extended_type y_sq = (extended_type) y * y;
370 extended_type l_sq = x_sq + y_sq;
371 extended_type newLength_sq = (extended_type) aNewLength * aNewLength;
372 newX = std::sqrt( rescale( newLength_sq, x_sq, l_sq ) );
373 newY = std::sqrt( rescale( newLength_sq, y_sq, l_sq ) );
374 }
375
376 if( std::is_integral<T>::value )
377 {
378 return VECTOR2<T>( static_cast<T>( x < 0 ? -KiROUND( newX ) : KiROUND( newX ) ),
379 static_cast<T>( y < 0 ? -KiROUND( newY ) : KiROUND( newY ) ) )
380 * sign( aNewLength );
381 }
382 else
383 {
384 return VECTOR2<T>( static_cast<T>( x < 0 ? -newX : newX ),
385 static_cast<T>( y < 0 ? -newY : newY ) )
386 * sign( aNewLength );
387 }
388}
389
390
391template <class T>
392const std::string VECTOR2<T>::Format() const
393{
394 std::stringstream ss;
395
396 ss << "( xy " << x << " " << y << " )";
397
398 return ss.str();
399}
400
401
402template <class T>
404{
405 return VECTOR2<T> ( x + aVector.x, y + aVector.y );
406}
407
408
409template <class T>
410VECTOR2<T> VECTOR2<T>::operator+( const T& aScalar ) const
411{
412 return VECTOR2<T> ( x + aScalar, y + aScalar );
413}
414
415
416template <class T>
418{
419 return VECTOR2<T> ( x - aVector.x, y - aVector.y );
420}
421
422
423template <class T>
424VECTOR2<T> VECTOR2<T>::operator-( const T& aScalar ) const
425{
426 return VECTOR2<T> ( x - aScalar, y - aScalar );
427}
428
429
430template <class T>
432{
433 return VECTOR2<T> ( -x, -y );
434}
435
436
437template <class T>
439{
440 return (extended_type)aVector.x * x + (extended_type)aVector.y * y;
441}
442
443
444template <class T>
445VECTOR2<T> VECTOR2<T>::operator*( const T& aFactor ) const
446{
447 VECTOR2<T> vector( x * aFactor, y * aFactor );
448 return vector;
449}
450
451
452template <class T>
453VECTOR2<T> VECTOR2<T>::operator/( double aFactor ) const
454{
455 if( std::is_integral<T>::value )
456 return VECTOR2<T>( KiROUND( x / aFactor ), KiROUND( y / aFactor ) );
457 else
458 return VECTOR2<T>( static_cast<T>( x / aFactor ), static_cast<T>( y / aFactor ) );
459}
460
461
462template <class T>
463VECTOR2<T> operator*( const T& aFactor, const VECTOR2<T>& aVector )
464{
465 VECTOR2<T> vector( aVector.x * aFactor, aVector.y * aFactor );
466 return vector;
467}
468
469
470template <class T>
472{
473 return (extended_type) x * (extended_type) aVector.y -
474 (extended_type) y * (extended_type) aVector.x;
475}
476
477
478template <class T>
480{
481 return (extended_type) x * (extended_type) aVector.x +
482 (extended_type) y * (extended_type) aVector.y;
483}
484
485
486template <class T>
487bool VECTOR2<T>::operator<( const VECTOR2<T>& aVector ) const
488{
489 return ( *this * *this ) < ( aVector * aVector );
490}
491
492
493template <class T>
494bool VECTOR2<T>::operator<=( const VECTOR2<T>& aVector ) const
495{
496 return ( *this * *this ) <= ( aVector * aVector );
497}
498
499
500template <class T>
501bool VECTOR2<T>::operator>( const VECTOR2<T>& aVector ) const
502{
503 return ( *this * *this ) > ( aVector * aVector );
504}
505
506
507template <class T>
508bool VECTOR2<T>::operator>=( const VECTOR2<T>& aVector ) const
509{
510 return ( *this * *this ) >= ( aVector * aVector );
511}
512
513
514template <class T>
515bool VECTOR2<T>::operator==( VECTOR2<T> const& aVector ) const
516{
517 return ( aVector.x == x ) && ( aVector.y == y );
518}
519
520
521template <class T>
522bool VECTOR2<T>::operator!=( VECTOR2<T> const& aVector ) const
523{
524 return ( aVector.x != x ) || ( aVector.y != y );
525}
526
527
528template <class T>
530{
531 if( aA.x > aB.x )
532 return aA;
533 else if( aA.x == aB.x && aA.y > aB.y )
534 return aA;
535
536 return aB;
537}
538
539
540template <class T>
542{
543 if( aA.x < aB.x )
544 return aA;
545 else if( aA.x == aB.x && aA.y < aB.y )
546 return aA;
547
548 return aB;
549}
550
551
552template <class T>
554{
555 if( aA.x < aB.x )
556 return -1;
557 else if( aA.x > aB.x )
558 return 1;
559 else // aA.x == aB.x
560 {
561 if( aA.y < aB.y )
562 return -1;
563 else if( aA.y > aB.y )
564 return 1;
565 else
566 return 0;
567 }
568}
569
570
579template <class T>
580typename std::enable_if<!std::numeric_limits<T>::is_integer, bool>::type
581equals( VECTOR2<T> const& aFirst, VECTOR2<T> const& aSecond,
582 T aEpsilon = std::numeric_limits<T>::epsilon() )
583{
584 if( !equals( aFirst.x, aSecond.x, aEpsilon ) )
585 {
586 return false;
587 }
588
589 return equals( aFirst.y, aSecond.y, aEpsilon );
590}
591
592
593template <class T>
594std::ostream& operator<<( std::ostream& aStream, const VECTOR2<T>& aVector )
595{
596 aStream << "[ " << aVector.x << " | " << aVector.y << " ]";
597 return aStream;
598}
599
600/* Default specializations */
604
605/* KiROUND specialization for vectors */
606inline VECTOR2I KiROUND( const VECTOR2D& vec )
607{
608 return VECTOR2I( KiROUND( vec.x ), KiROUND( vec.y ) );
609}
610
611/* STL specializations */
612namespace std
613{
614 // Required to enable correct use in std::map/unordered_map
615 // DO NOT USE hash tables with VECTOR2 elements. It is inefficient
616 // and degenerates to a linear search. Use the std::map/std::set
617 // trees instead that utilize the less operator below
618 // This function is purposely deleted after substantial testing
619 template <>
620 struct hash<VECTOR2I>
621 {
622 size_t operator()( const VECTOR2I& k ) const = delete;
623 };
624
625 // Required to enable use of std::hash with maps.
626 template <>
627 struct less<VECTOR2I>
628 {
629 bool operator()( const VECTOR2I& aA, const VECTOR2I& aB ) const;
630 };
631}
632
633#endif // VECTOR2D_H_
Define a general 2D-vector/point.
Definition: vector2d.h:70
VECTOR2< T > operator-(const T &aScalar) const
Scalar subtraction operator.
Definition: vector2d.h:424
VECTOR2< T > & operator+=(const T &aScalar)
Compound assignment operator.
Definition: vector2d.h:327
VECTOR2(const VECTOR2< CastingType > &aVec)
Initializes a vector from another specialization. Beware of rounding issues.
Definition: vector2d.h:88
VECTOR2< T > & operator*=(const T &aScalar)
Definition: vector2d.h:318
extended_type SquaredEuclideanNorm() const
Compute the squared euclidean norm of the vector, which is defined as (x ** 2 + y ** 2).
Definition: vector2d.h:276
VECTOR2< T > & operator*=(const VECTOR2< T > &aVector)
Compound assignment operator.
Definition: vector2d.h:309
const std::string Format() const
Return the vector formatted as a string.
Definition: vector2d.h:392
VECTOR2()
Construct a 2D-vector with x, y = 0.
Definition: vector2d.h:251
VECTOR2< T > operator/(double aFactor) const
Division with a factor.
Definition: vector2d.h:453
VECTOR2(T x, T y)
Construct a vector with given components x, y.
Definition: vector2d.h:257
bool operator>=(const VECTOR2< T > &aVector) const
Definition: vector2d.h:508
static constexpr extended_type ECOORD_MAX
Definition: vector2d.h:75
VECTOR2< T > & operator+=(const VECTOR2< T > &aVector)
Compound assignment operator.
Definition: vector2d.h:300
VECTOR2(const VECTOR2< T > &aVec)
Copy a vector.
Definition: vector2d.h:106
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h:265
VECTOR2_TRAITS< T >::extended_type extended_type
Definition: vector2d.h:72
bool operator==(const VECTOR2< T > &aVector) const
Equality operator.
Definition: vector2d.h:515
VECTOR2< T > Perpendicular() const
Compute the perpendicular vector.
Definition: vector2d.h:283
bool operator<=(const VECTOR2< T > &aVector) const
Definition: vector2d.h:494
VECTOR2< T > & operator=(const VECTOR2< T > &aVector)
Assignment operator.
Definition: vector2d.h:291
VECTOR2< T > & operator-=(const T &aScalar)
Compound assignment operator.
Definition: vector2d.h:345
bool operator!=(const VECTOR2< T > &aVector) const
Not equality operator.
Definition: vector2d.h:522
static constexpr extended_type ECOORD_MIN
Definition: vector2d.h:76
extended_type Cross(const VECTOR2< T > &aVector) const
Compute cross product of self with aVector.
Definition: vector2d.h:471
VECTOR2< CastedType > operator()() const
Cast a vector to another specialized subclass. Beware of rounding issues.
Definition: vector2d.h:114
bool operator>(const VECTOR2< T > &aVector) const
Greater than operator.
Definition: vector2d.h:501
extended_type Dot(const VECTOR2< T > &aVector) const
Compute dot product of self with aVector.
Definition: vector2d.h:479
extended_type operator*(const VECTOR2< T > &aVector) const
Scalar product operator.
Definition: vector2d.h:438
VECTOR2< T > operator+(const VECTOR2< T > &aVector) const
Vector addition operator.
Definition: vector2d.h:403
VECTOR2< T > operator-(const VECTOR2< T > &aVector) const
Vector subtraction operator.
Definition: vector2d.h:417
VECTOR2< T > operator*(const T &aFactor) const
Multiplication with a factor.
Definition: vector2d.h:445
VECTOR2< T > operator+(const T &aScalar) const
Scalar addition operator.
Definition: vector2d.h:410
VECTOR2< T > & operator-=(const VECTOR2< T > &aVector)
Compound assignment operator.
Definition: vector2d.h:336
bool operator<(const VECTOR2< T > &aVector) const
Smaller than operator.
Definition: vector2d.h:487
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
Definition: vector2d.h:354
VECTOR2< T > operator-()
Negate Vector operator.
Definition: vector2d.h:431
T coord_type
Definition: vector2d.h:73
STL namespace.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:424
int64_t extended_type
Definition: vector2d.h:52
Traits class for VECTOR2.
Definition: vector2d.h:43
T extended_type
extended range/precision types used by operations involving multiple multiplications to prevent overf...
Definition: vector2d.h:46
size_t operator()(const VECTOR2I &k) const =delete
int sign(T val)
Definition: util.h:168
T rescale(T aNumerator, T aValue, T aDenominator)
Scale a number (value) by rational (numerator/denominator).
Definition: util.h:162
constexpr T Clamp(const T &lower, const T &value, const T &upper)
Limit value within the range lower <= value <= upper.
Definition: util.h:64
VECTOR2< double > VECTOR2D
Definition: vector2d.h:601
std::ostream & operator<<(std::ostream &aStream, const VECTOR2< T > &aVector)
Definition: vector2d.h:594
VECTOR2< long long int > VECTOR2L
Definition: vector2d.h:603
const VECTOR2< T > LexicographicalMax(const VECTOR2< T > &aA, const VECTOR2< T > &aB)
Definition: vector2d.h:529
std::enable_if<!std::numeric_limits< T >::is_integer, bool >::type equals(VECTOR2< T > const &aFirst, VECTOR2< T > const &aSecond, T aEpsilon=std::numeric_limits< T >::epsilon())
Template to compare two VECTOR2<T> values for equality within a required epsilon.
Definition: vector2d.h:581
VECTOR2I KiROUND(const VECTOR2D &vec)
Definition: vector2d.h:606
const VECTOR2< T > LexicographicalMin(const VECTOR2< T > &aA, const VECTOR2< T > &aB)
Definition: vector2d.h:541
int LexicographicalCompare(const VECTOR2< T > &aA, const VECTOR2< T > &aB)
Definition: vector2d.h:553
VECTOR2< int > VECTOR2I
Definition: vector2d.h:602
VECTOR2< T > operator*(const T &aFactor, const VECTOR2< T > &aVector)
Definition: vector2d.h:463