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
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
23 #include "Shapes_Concrete_decls.h"
24 #include "Shapes_Lang_decls.h"
26 #include "elementarylength.h"
27 #include "shapesexceptions.h"
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
);
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
;
59 explicit UnitFloatPair( double x
, double y
, bool )
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 ( ) );
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 >( ),
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 )
155 // double tmp = 1. / denom.x_;
156 // return Concrete::UnitFloatPair( tmp * coords.x_.x_, tmp * coords.y_.x_ );
158 // inline Concrete::UnitFloatPair operator / ( const Concrete::UnitFloatPair & coords, double denom )
160 // double tmp = 1. / denom;
161 // return Concrete::UnitFloatPair( tmp * coords.x_, tmp * coords.y_ );
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
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
;
221 explicit UnitFloatTriple( double x
, double y
, double z
, bool )
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;
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 )
288 // double tmp = 1. / denom.x_;
289 // return Concrete::UnitFloatTriple( tmp * coords.x_.x_, tmp * coords.y_.x_, tmp * coords.z_.x_ );
291 // inline Concrete::UnitFloatTriple operator / ( const Concrete::UnitFloatTriple & coords, double denom )
293 // double tmp = 1. / denom;
294 // return Concrete::UnitFloatTriple( tmp * coords.x_, tmp * coords.y_, tmp * coords.z_ );
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 ) */
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_ ); */
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 )
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_ );
397 Area
crossMagnitude( const Coords3D
& a
, const Coords3D
& b
);