Updating the changelog in the VERSION file, and version_sync.
[shapes.git] / source / elementarycoords.h
blobe0cfae6ae3fb647d5c1298f029e374f130ba7bea
1 /* This file is part of Shapes.
3 * Shapes is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * any later version.
8 * Shapes is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with Shapes. If not, see <http://www.gnu.org/licenses/>.
16 * Copyright 2008, 2009 Henrik Tidefelt
19 #pragma once
21 #include <cmath>
23 #include "Shapes_Concrete_decls.h"
24 #include "Shapes_Lang_decls.h"
26 #include "elementarylength.h"
27 #include "shapesexceptions.h"
30 namespace Shapes
33 namespace Concrete
36 class UnitFloatPair
38 public:
39 double x_;
40 double y_;
41 UnitFloatPair( double x, double y )
43 if( x == 0 && y == 0 )
45 throw Exceptions::InternalError( "A UnitFloatPair was initialized with a zero vector." );
47 double tmp = 1. / hypot( x, y );
48 x_ = tmp * x;
49 y_ = tmp * y;
51 UnitFloatPair( bool ) : x_( 1 ), y_( 0 ) { }
52 UnitFloatPair( bool, bool ) : x_( 0 ), y_( 1 ) { }
53 explicit UnitFloatPair( double x, double y, double precomputedNorm )
55 double tmp = 1. / precomputedNorm;
56 x_ = tmp * x;
57 y_ = tmp * y;
59 explicit UnitFloatPair( double x, double y, bool )
61 x_ = x;
62 y_ = y;
64 double normSquaredThatOughtToBeOne( ) const
66 return x_ * x_ + y_ * y_;
68 Concrete::UnitFloatPair unnormalizedScaling( double a ) const;
69 Concrete::UnitFloatPair reverse( ) const /* Does not normalize the result! Result will have same normSquaredThatOughtToBeOne( ) as *this.*/
71 return Concrete::UnitFloatPair( - x_, - y_, bool ( ) );
73 Concrete::UnitFloatPair quarterTurnCounterClockwise( ) const /* Does not normalize the result! Result will have same normSquaredThatOughtToBeOne( ) as *this.*/
75 return Concrete::UnitFloatPair( - y_, x_, bool ( ) );
79 class Coords2D
81 public:
82 Length x_;
83 Length y_;
84 Coords2D( Concrete::Length x, Concrete::Length y ) : x_( x ), y_( y ) { }
85 Coords2D( double x, double y ) : x_( x ), y_( y ) { }
86 Coords2D( const Concrete::Coords2D & orig ) : x_( orig.x_ ), y_( orig.y_ ) { }
87 Coords2D( const Lang::Coords2D & orig );
88 Coords2D( const Concrete::Coords2D & base, const Lang::Coords2D & orig );
89 operator Lang::Coords2D ( ) const;
90 Coords2D * transformedPtr( const Lang::Transform2D & tf ) const;
91 Coords2D transformed( const Lang::Transform2D & tf ) const;
92 Concrete::Coords3D * transformedPtr( const Lang::Transform3D & tf ) const; // treat as z = 0
93 friend std::ostream & operator << ( std::ostream & os, const Coords2D & self );
94 Concrete::Length norm( ) const;
95 Concrete::LengthSquared normSquared( ) const { return x_ * x_ + y_ * y_; }
96 double normScalar( ) const;
97 Concrete::UnitFloatPair direction( ) const;
98 Concrete::UnitFloatPair direction( Concrete::Length precomputedNorm ) const;
99 double angleCosineSignSquared( const Concrete::Coords2D & b ) const; /* Like the ordinary angle cosine, but avoids the use of sqrt. */
100 Concrete::UnitFloatPair normalizedOrthogonal( const Coords2D & b ) const
102 // We return the counter-clockwise orthogonal to the normalized vector from ourselves to b
103 return UnitFloatPair( y_.offtype< 1, 0 >( ) - b.y_.offtype< 1, 0 >( ),
104 b.x_.offtype< 1, 0 >( ) - x_.offtype< 1, 0 >( ) );
106 Concrete::UnitFloatPair normalizedOrthogonalNoFail( const Coords2D & b ) const
108 // We return the counter-clockwise orthogonal to the normalized vector from ourselves to b
111 return normalizedOrthogonal( b );
113 catch( Exceptions::InternalError & ball )
115 return UnitFloatPair( bool( ) );
118 Concrete::UnitFloatPair unNormalizedOrthogonal( const Coords2D & b ) const
120 // Warning! This is the same as normalizedOrthogonal, but the result is really not normalized!
121 return UnitFloatPair( y_.offtype< 1, 0 >( ) - b.y_.offtype< 1, 0 >( ),
122 b.x_.offtype< 1, 0 >( ) - x_.offtype< 1, 0 >( ),
123 bool( ) );
125 Concrete::Coords2D quarterTurnCounterClockwise( ) const
127 return Concrete::Coords2D( - y_, x_ );
129 Concrete::Length distanceTo( const Concrete::Coords2D & other ) const
131 return hypotPhysical( x_ - other.x_, y_ - other.y_ );
135 /* The Bezier template classes requires the interface to a vector space with inner product.
137 Concrete::Coords2D operator * ( double scalar, const Concrete::Coords2D & coords );
138 Concrete::Coords2D operator * ( const Concrete::Coords2D & coords, double scalar );
139 Concrete::Coords2D operator + ( const Concrete::Coords2D & coords1, const Concrete::Coords2D & coords2 );
140 Concrete::Coords2D operator - ( const Concrete::Coords2D & coords1, const Concrete::Coords2D & coords2 );
142 Concrete::Coords2D operator * ( Concrete::Length length, const Concrete::UnitFloatPair & direction );
143 Concrete::Coords2D operator * ( const Concrete::UnitFloatPair & direction, Concrete::Length length );
145 // Concrete::UnitFloatPair operator + ( const Concrete::UnitFloatPair & coords1, const Concrete::UnitFloatPair & coords2 );
146 // Concrete::UnitFloatPair operator - ( const Concrete::UnitFloatPair & coords1, const Concrete::UnitFloatPair & coords2 );
148 inline Concrete::Coords2D operator / ( const Concrete::Coords2D & coords, double denom )
150 double tmp = 1. / denom;
151 return Concrete::Coords2D( tmp * coords.x_, tmp * coords.y_ );
153 // inline Concrete::UnitFloatPair operator / ( const Concrete::Coords2D & coords, const Concrete::Length & denom )
154 // {
155 // double tmp = 1. / denom.x_;
156 // return Concrete::UnitFloatPair( tmp * coords.x_.x_, tmp * coords.y_.x_ );
157 // }
158 // inline Concrete::UnitFloatPair operator / ( const Concrete::UnitFloatPair & coords, double denom )
159 // {
160 // double tmp = 1. / denom;
161 // return Concrete::UnitFloatPair( tmp * coords.x_, tmp * coords.y_ );
162 // }
164 inline bool operator == ( const Concrete::Coords2D & coords1, const Concrete::Coords2D & coords2 )
166 return coords1.x_ == coords2.x_ && coords1.y_ == coords2.y_;
168 inline bool operator != ( const Concrete::Coords2D & coords1, const Concrete::Coords2D & coords2 )
170 return ! ( coords1 == coords2 );
173 inline double inner( const UnitFloatPair & a, const UnitFloatPair & b )
175 return a.x_ * b.x_ + a.y_ * b.y_;
178 inline Length inner( const UnitFloatPair & a, const Coords2D & b )
180 return a.x_ * b.x_ + a.y_ * b.y_;
183 inline Length inner( const Coords2D & a, const UnitFloatPair & b )
185 return a.x_ * b.x_ + a.y_ * b.y_;
188 inline double innerScalar( const UnitFloatPair & a, const Coords2D & b )
190 return ( a.x_ * b.x_ + a.y_ * b.y_ ).offtype< 1, 0 >( );
193 inline double innerScalar( const Coords2D & a, const UnitFloatPair & b )
195 return ( a.x_ * b.x_ + a.y_ * b.y_ ).offtype< 1, 0 >( );
198 inline double innerScalar( const Coords2D & a, const Coords2D & b )
200 return ( a.x_ * b.x_ + a.y_ * b.y_ ).offtype< 2, 0 >( );
204 class UnitFloatTriple
206 public:
207 double x_;
208 double y_;
209 double z_;
210 UnitFloatTriple( double x, double y, double z );
211 UnitFloatTriple( bool ) : x_( 1 ), y_( 0 ), z_( 0 ) { }
212 UnitFloatTriple( bool, bool ) : x_( 0 ), y_( 1 ), z_( 0 ) { }
213 UnitFloatTriple( bool, bool, bool ) : x_( 0 ), y_( 0 ), z_( 1 ) { }
214 explicit UnitFloatTriple( double x, double y, double z, double precomputedNorm )
216 double tmp = 1. / precomputedNorm;
217 x_ = tmp * x;
218 y_ = tmp * y;
219 z_ = tmp * z;
221 explicit UnitFloatTriple( double x, double y, double z, bool )
223 x_ = x;
224 y_ = y;
225 z_ = z;
227 double normSquaredThatOughtToBeOne( ) const
229 return x_ * x_ + y_ * y_ + z_ * z_;
231 Concrete::UnitFloatTriple reflect( const Concrete::UnitFloatTriple dir ) const; /* Does not normalize the result! Result will have same normSquaredThatOughtToBeOne( ) as *this.*/
232 Concrete::UnitFloatTriple unnormalizedScaling( double a ) const; /* Does not normalize the result! Result will have same normSquaredThatOughtToBeOne( ) as *this.*/
233 Concrete::UnitFloatTriple reverse( ) const /* Does not normalize the result! Result will have same normSquaredThatOughtToBeOne( ) as *this.*/
235 return Concrete::UnitFloatTriple( - x_, - y_, - z_, bool( ) );
237 Concrete::UnitFloatTriple rotate( const Concrete::UnitFloatTriple dir, const double angle ) const;
240 class Coords3D
242 public:
243 Length x_;
244 Length y_;
245 Length z_;
246 Coords3D( Concrete::Length x, Concrete::Length y, Concrete::Length z ) : x_( x ), y_( y ), z_( z ) { }
247 Coords3D( double x, double y, double z ) : x_( x ), y_( y ), z_( z ) { }
248 Coords3D( const Concrete::Coords3D & orig ) : x_( orig.x_ ), y_( orig.y_ ), z_( orig.z_ ) { }
249 Coords3D( const Concrete::Coords2D & orig ) : x_( orig.x_ ), y_( orig.y_ ), z_( 0 ) { }
250 Coords3D( const Lang::Coords3D & orig );
251 Coords3D( const Concrete::Coords3D & base, const Lang::Coords3D & orig );
252 operator Lang::Coords3D ( ) const;
253 Coords3D * transformedPtr( const Lang::Transform3D & tf ) const;
254 Coords3D transformed( const Lang::Transform3D & tf ) const;
255 Coords2D * make2D( Concrete::Length eyez ) const;
256 Coords2D make2DAutomatic( Concrete::Length eyez ) const;
257 friend std::ostream & operator << ( std::ostream & os, const Coords3D & self );
258 void negate( ) { x_ = -x_; y_ = -y_; z_ = -z_; }
259 double normalizedInner( const Coords3D & b ) const;
260 Concrete::Length norm( ) const;
261 Concrete::LengthSquared normSquared( ) const { return x_ * x_ + y_ * y_ + z_ * z_; }
262 double normScalar( ) const;
263 UnitFloatTriple direction( ) const;
264 UnitFloatTriple directionNoFail( ) const; /* This function returns an arbitrary direction when direction would fail. */
265 Concrete::UnitFloatTriple direction( Concrete::Length precomputedNorm ) const;
268 /* The Bezier template classes requires the interface to a vector space.
270 Concrete::Coords3D operator * ( double scalar, const Concrete::Coords3D & coords );
271 Concrete::Coords3D operator * ( const Concrete::Coords3D & coords, double scalar );
272 Concrete::Coords3D operator + ( const Concrete::Coords3D & coords1, const Concrete::Coords3D & coords2 );
273 Concrete::Coords3D operator - ( const Concrete::Coords3D & coords1, const Concrete::Coords3D & coords2 );
275 Concrete::Coords3D operator * ( Concrete::Length length, const Concrete::UnitFloatTriple & direction );
276 Concrete::Coords3D operator * ( const Concrete::UnitFloatTriple & direction, Concrete::Length length );
278 // Concrete::UnitFloatTriple operator + ( const Concrete::UnitFloatTriple & coords1, const Concrete::UnitFloatTriple & coords2 );
279 // Concrete::UnitFloatTriple operator - ( const Concrete::UnitFloatTriple & coords1, const Concrete::UnitFloatTriple & coords2 );
281 inline Concrete::Coords3D operator / ( const Concrete::Coords3D & coords, double denom )
283 double tmp = 1. / denom;
284 return Concrete::Coords3D( tmp * coords.x_, tmp * coords.y_, tmp * coords.z_ );
286 // inline Concrete::UnitFloatTriple operator / ( const Concrete::Coords3D & coords, const Concrete::Length & denom )
287 // {
288 // double tmp = 1. / denom.x_;
289 // return Concrete::UnitFloatTriple( tmp * coords.x_.x_, tmp * coords.y_.x_, tmp * coords.z_.x_ );
290 // }
291 // inline Concrete::UnitFloatTriple operator / ( const Concrete::UnitFloatTriple & coords, double denom )
292 // {
293 // double tmp = 1. / denom;
294 // return Concrete::UnitFloatTriple( tmp * coords.x_, tmp * coords.y_, tmp * coords.z_ );
295 // }
297 inline bool operator == ( const Concrete::Coords3D & coords1, const Concrete::Coords3D & coords2 )
299 return coords1.x_ == coords2.x_ && coords1.y_ == coords2.y_ && coords1.z_ == coords2.z_;
301 inline bool operator != ( const Concrete::Coords3D & coords1, const Concrete::Coords3D & coords2 )
303 return ! ( coords1 == coords2 );
306 inline double inner( const UnitFloatTriple & a, const UnitFloatTriple & b )
308 return a.x_ * b.x_ + a.y_ * b.y_ + a.z_ * b.z_;
311 inline Length inner( const UnitFloatTriple & a, const Coords3D & b )
313 return a.x_ * b.x_ + a.y_ * b.y_ + a.z_ * b.z_;
316 inline Length inner( const Coords3D & a, const UnitFloatTriple & b )
318 return a.x_ * b.x_ + a.y_ * b.y_ + a.z_ * b.z_;
321 inline LengthSquared inner( const Coords3D & a, const Coords3D & b )
323 return a.x_ * b.x_ + a.y_ * b.y_ + a.z_ * b.z_;
326 inline double innerScalar( const UnitFloatTriple & a, const Coords3D & b )
328 return ( a.x_ * b.x_ + a.y_ * b.y_ + a.z_ * b.z_ ).offtype< 1, 0 >( );
331 inline double innerScalar( const Coords3D & a, const UnitFloatTriple & b )
333 return ( a.x_ * b.x_ + a.y_ * b.y_ + a.z_ * b.z_ ).offtype< 1, 0 >( );
336 inline double innerScalar( const Coords3D & a, const Coords3D & b )
338 return ( a.x_ * b.x_ + a.y_ * b.y_ + a.z_ * b.z_ ).offtype< 2, 0 >( );
341 /* inline Coords3D cross( const Coords3D & a, const Coords3D & b ) */
342 /* { */
343 /* return Coords3D( a.y_ * b.z_ - a.z_ * b.y_, */
344 /* a.z_ * b.x_ - a.x_ * b.z_, */
345 /* a.x_ * b.y_ - a.y_ * b.x_ ); */
346 /* } */
348 inline UnitFloatTriple crossDirection( const UnitFloatTriple & a, const UnitFloatTriple & b )
352 return UnitFloatTriple( a.y_ * b.z_ - a.z_ * b.y_,
353 a.z_ * b.x_ - a.x_ * b.z_,
354 a.x_ * b.y_ - a.y_ * b.x_ );
356 catch( const Exceptions::InternalError & ball )
358 throw NonLocalExit::CrossDirectionOfParallel( );
362 inline Coords3D cross( const UnitFloatTriple & a, const Coords3D & b )
364 return Coords3D( a.y_ * b.z_ - a.z_ * b.y_,
365 a.z_ * b.x_ - a.x_ * b.z_,
366 a.x_ * b.y_ - a.y_ * b.x_ );
369 inline Coords3D cross( const Coords3D & a, const UnitFloatTriple & b )
371 return Coords3D( a.y_ * b.z_ - a.z_ * b.y_,
372 a.z_ * b.x_ - a.x_ * b.z_,
373 a.x_ * b.y_ - a.y_ * b.x_ );
376 inline UnitFloatTriple crossDirection( const Coords3D & a, const Coords3D & b )
380 return UnitFloatTriple( ( a.y_ * b.z_ - a.z_ * b.y_ ).offtype< 2, 0 >( ),
381 ( a.z_ * b.x_ - a.x_ * b.z_ ).offtype< 2, 0 >( ),
382 ( a.x_ * b.y_ - a.y_ * b.x_ ).offtype< 2, 0 >( ) );
384 catch( const Exceptions::InternalError & ball )
386 throw NonLocalExit::CrossDirectionOfParallel( );
390 // inline Coords3D crossCoords3D( const Coords3D & a, const Coords3D & b )
391 // {
392 // return Coords3D( a.y_.x_ * b.z_.x_ - a.z_.x_ * b.y_.x_,
393 // a.z_.x_ * b.x_.x_ - a.x_.x_ * b.z_.x_,
394 // a.x_.x_ * b.y_.x_ - a.y_.x_ * b.x_.x_ );
395 // }
397 Area crossMagnitude( const Coords3D & a, const Coords3D & b );