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
19 #include "elementarytypes.h"
20 #include "functiontypes.h" // this is a trick to avoid #include problems...
21 #include "elementarycoords.h"
24 using namespace Shapes
;
26 Concrete::UnitFloatPair
27 Concrete::UnitFloatPair::unnormalizedScaling( double a
) const
29 return Concrete::UnitFloatPair( a
* x_
, a
* y_
, true );
32 Concrete::Coords2D::Coords2D( const Lang::Coords2D
& orig
)
33 : x_( orig
.x_
.get( ) ), y_( orig
.y_
.get( ) )
36 Concrete::Coords2D::Coords2D( const Concrete::Coords2D
& base
, const Lang::Coords2D
& orig
)
37 : x_( orig
.x_
.get( base
.x_
) ), y_( orig
.y_
.get( base
.y_
) )
40 Concrete::Coords2D::operator Lang::Coords2D ( ) const
42 return Lang::Coords2D( Lang::Length( x_
), Lang::Length( y_
) );
46 Concrete::Coords2D::transformedPtr( const Lang::Transform2D
& tf
) const
48 return new Concrete::Coords2D( tf
.xx_
* x_
+ tf
.xy_
* y_
+ tf
.xt_
, tf
.yx_
* x_
+ tf
.yy_
* y_
+ tf
.yt_
);
52 Concrete::Coords2D::transformed( const Lang::Transform2D
& tf
) const
54 return Concrete::Coords2D( tf
.xx_
* x_
+ tf
.xy_
* y_
+ tf
.xt_
, tf
.yx_
* x_
+ tf
.yy_
* y_
+ tf
.yt_
);
58 Concrete::Coords2D::transformedPtr( const Lang::Transform3D
& tf
) const
60 return new Concrete::Coords3D( tf
.xx_
* x_
+ tf
.xy_
* y_
+ tf
.xt_
,
61 tf
.yx_
* x_
+ tf
.yy_
* y_
+ tf
.yt_
,
62 tf
.zx_
* x_
+ tf
.zy_
* y_
+ tf
.zt_
);
66 Concrete::Coords2D::norm( ) const
68 return hypotPhysical( x_
, y_
);
72 Concrete::Coords2D::normScalar( ) const
74 return hypotPhysical( x_
, y_
).offtype
< 1, 0 >( );
77 Concrete::UnitFloatPair
78 Concrete::Coords2D::direction( ) const
80 return Concrete::UnitFloatPair( x_
.offtype
< 1, 0 >( ), y_
.offtype
< 1, 0 >( ) );
84 Concrete::Coords2D::angleCosineSignSquared( const Concrete::Coords2D
& b
) const
86 /* Squaring the angle cosine fraction with sign is basically a matter of squaring numerator and denominator, keeping the sign of the numerator
87 * (as the sign of the denominator is always positive).
88 * Since the denominator is the product of the legths of the vectors, squaring the denominator yields the product of the lengths squared.
90 double num
= Concrete::Length::offtype( x_
) * Concrete::Length::offtype( b
.x_
) + Concrete::Length::offtype( y_
) * Concrete::Length::offtype( b
.y_
);
92 ( Concrete::Length::offtype( x_
) * Concrete::Length::offtype( x_
) + Concrete::Length::offtype( y_
) * Concrete::Length::offtype( y_
) )
94 ( Concrete::Length::offtype( b
.x_
) * Concrete::Length::offtype( b
.x_
) + Concrete::Length::offtype( b
.y_
) * Concrete::Length::offtype( b
.y_
) );
95 return num
* ( num
>= 0 ? num
: -num
) / den2
;
98 Concrete::UnitFloatPair
99 Concrete::Coords2D::direction( Concrete::Length precomputedLength
) const
101 return Concrete::UnitFloatPair( x_
.offtype
< 1, 0 >( ), y_
.offtype
< 1, 0 >( ), precomputedLength
.offtype
< 1, 0 >( ) );
106 Concrete::operator << ( std::ostream
& os
, const Concrete::Coords2D
& self
)
109 sprintf( buf
, "%.2f %.2f", double( self
.x_
.offtype
< 1, 0 >( ) ), double( self
.y_
.offtype
< 1, 0 >( ) ) );
115 Concrete::operator * ( double scalar
, const Concrete::Coords2D
& coords
)
117 return Concrete::Coords2D( scalar
* coords
.x_
, scalar
* coords
.y_
);
121 Concrete::operator * ( const Concrete::Coords2D
& coords
, double scalar
)
123 return Concrete::Coords2D( scalar
* coords
.x_
, scalar
* coords
.y_
);
127 Concrete::operator + ( const Concrete::Coords2D
& coords1
, const Concrete::Coords2D
& coords2
)
129 return Concrete::Coords2D( coords1
.x_
+ coords2
.x_
, coords1
.y_
+ coords2
.y_
);
133 Concrete::operator - ( const Concrete::Coords2D
& coords1
, const Concrete::Coords2D
& coords2
)
135 return Concrete::Coords2D( coords1
.x_
- coords2
.x_
, coords1
.y_
- coords2
.y_
);
141 Concrete::operator * ( Concrete::Length length
, const Concrete::UnitFloatPair
& direction
)
143 return Concrete::Coords2D( length
* direction
.x_
, length
* direction
.y_
);
147 Concrete::operator * ( const Concrete::UnitFloatPair
& direction
, Concrete::Length length
)
149 return Concrete::Coords2D( length
* direction
.x_
, length
* direction
.y_
);
152 // Concrete::UnitFloatPair
153 // Concrete::operator + ( const Concrete::UnitFloatPair & coords1, const Concrete::UnitFloatPair & coords2 )
155 // return Concrete::UnitFloatPair( coords1.x_ + coords2.x_, coords1.y_ + coords2.y_ );
158 // Concrete::UnitFloatPair
159 // Concrete::operator - ( const Concrete::UnitFloatPair & coords1, const Concrete::UnitFloatPair & coords2 )
161 // return Concrete::UnitFloatPair( coords1.x_ - coords2.x_, coords1.y_ - coords2.y_ );
167 Concrete::Coords3D::transformedPtr( const Lang::Transform3D
& tf
) const
169 return new Concrete::Coords3D( tf
.xx_
* x_
+ tf
.xy_
* y_
+ tf
.xz_
* z_
+ tf
.xt_
,
170 tf
.yx_
* x_
+ tf
.yy_
* y_
+ tf
.yz_
* z_
+ tf
.yt_
,
171 tf
.zx_
* x_
+ tf
.zy_
* y_
+ tf
.zz_
* z_
+ tf
.zt_
);
175 Concrete::Coords3D::transformed( const Lang::Transform3D
& tf
) const
177 return Concrete::Coords3D( tf
.xx_
* x_
+ tf
.xy_
* y_
+ tf
.xz_
* z_
+ tf
.xt_
,
178 tf
.yx_
* x_
+ tf
.yy_
* y_
+ tf
.yz_
* z_
+ tf
.yt_
,
179 tf
.zx_
* x_
+ tf
.zy_
* y_
+ tf
.zz_
* z_
+ tf
.zt_
);
183 Concrete::Coords3D::make2D( Concrete::Length eyez
) const
185 if( eyez
== HUGE_LENGTH
)
187 return new Concrete::Coords2D( x_
, y_
);
190 return new Concrete::Coords2D( x_
* ( eyez
/ ( eyez
- z_
) ),
191 y_
* ( eyez
/ ( eyez
- z_
) ) );
195 Concrete::Coords3D::make2DAutomatic( Concrete::Length eyez
) const
197 if( eyez
== HUGE_LENGTH
)
199 return Concrete::Coords2D( x_
, y_
);
202 return Concrete::Coords2D( x_
* eyez
/ ( eyez
- z_
),
203 y_
* eyez
/ ( eyez
- z_
) );
207 Concrete::operator << ( std::ostream
& os
, const Concrete::Coords3D
& self
)
210 sprintf( buf
, "%.2f %.2f %.2f", double( self
.x_
.offtype
< 1, 0 >( ) ), double( self
.y_
.offtype
< 1, 0 >( ) ), double( self
.z_
.offtype
< 1, 0 >( ) ) );
215 Concrete::Coords3D::Coords3D( const Lang::Coords3D
& orig
)
216 : x_( orig
.x_
.getScalar( ) ), y_( orig
.y_
.getScalar( ) ), z_( orig
.z_
.getScalar( ) )
219 Concrete::Coords3D::Coords3D( const Concrete::Coords3D
& base
, const Lang::Coords3D
& orig
)
220 : x_( orig
.x_
.getScalar( base
.x_
) ), y_( orig
.y_
.getScalar( base
.y_
) ), z_( orig
.z_
.getScalar( base
.z_
) )
223 Concrete::Coords3D::operator Lang::Coords3D ( ) const
225 return Lang::Coords3D( Lang::Length( x_
), Lang::Length( y_
), Lang::Length( z_
) );
230 Concrete::operator * ( double scalar
, const Concrete::Coords3D
& coords
)
232 return Concrete::Coords3D( scalar
* coords
.x_
, scalar
* coords
.y_
, scalar
* coords
.z_
);
236 Concrete::operator * ( const Concrete::Coords3D
& coords
, double scalar
)
238 return Concrete::Coords3D( scalar
* coords
.x_
, scalar
* coords
.y_
, scalar
* coords
.z_
);
242 Concrete::operator + ( const Concrete::Coords3D
& coords1
, const Concrete::Coords3D
& coords2
)
244 return Concrete::Coords3D( coords1
.x_
+ coords2
.x_
, coords1
.y_
+ coords2
.y_
, coords1
.z_
+ coords2
.z_
);
248 Concrete::operator - ( const Concrete::Coords3D
& coords1
, const Concrete::Coords3D
& coords2
)
250 return Concrete::Coords3D( coords1
.x_
- coords2
.x_
, coords1
.y_
- coords2
.y_
, coords1
.z_
- coords2
.z_
);
254 Concrete::Coords3D::normalizedInner( const Concrete::Coords3D
& b
) const
256 return ( ( x_
* b
.x_
+ y_
* b
.y_
+ z_
* b
.z_
) / hypotPhysical( x_
, y_
, z_
) ).offtype
< 1, 0 >( );
260 Concrete::Coords3D::norm( ) const
262 return hypotPhysical( x_
, y_
, z_
);
266 Concrete::Coords3D::normScalar( ) const
268 return hypotPhysical( x_
, y_
, z_
).offtype
< 1, 0 >( );
271 Concrete::UnitFloatTriple
272 Concrete::Coords3D::direction( ) const
274 return Concrete::UnitFloatTriple( x_
.offtype
< 1, 0 >( ), y_
.offtype
< 1, 0 >( ), z_
.offtype
< 1, 0 >( ) );
277 Concrete::UnitFloatTriple
278 Concrete::Coords3D::directionNoFail( ) const
284 catch( Exceptions::InternalError
& ball
)
286 return UnitFloatTriple( bool( ) );
290 Concrete::UnitFloatTriple
291 Concrete::Coords3D::direction( Concrete::Length precomputedLength
) const
293 return Concrete::UnitFloatTriple( x_
.offtype
< 1, 0 >( ), y_
.offtype
< 1, 0 >( ), z_
.offtype
< 1, 0 >( ), precomputedLength
.offtype
< 1, 0 >( ) );
298 Concrete::UnitFloatTriple::UnitFloatTriple( double x
, double y
, double z
)
300 double len
= Concrete::Scalar::hypot3( x
, y
, z
);
303 throw Exceptions::InternalError( "A concrete UnitFloatTriple was initialized with a very short vector." );
305 double tmp
= 1. / Concrete::Scalar::hypot3( x
, y
, z
);
311 Concrete::UnitFloatTriple
312 Concrete::UnitFloatTriple::unnormalizedScaling( double a
) const
314 return Concrete::UnitFloatTriple( a
* x_
, a
* y_
, a
* z_
, true );
318 Concrete::UnitFloatTriple
319 Concrete::UnitFloatTriple::reflect( const Concrete::UnitFloatTriple dir
) const
321 double a
= 2 * Concrete::inner( *this, dir
);
322 return Concrete::UnitFloatTriple( a
* x_
- dir
.x_
,
325 bool( ) ); // the bool( ) means it's already normalized
328 Concrete::UnitFloatTriple
329 Concrete::UnitFloatTriple::rotate( const Concrete::UnitFloatTriple dir
, const double angle
) const
331 // The following may not be efficient, but it was easy to code by copying code from Core_rotate3D.
332 // I've got the feeling that this is much better done using geometric algebra based on Clifford algebra.
340 double c
= cos( angle
);
341 double s
= sin( angle
);
342 return Concrete::UnitFloatTriple( (x2
+(y2
+z2
)*c
)*x_
+ (x
*y
*(1-c
)+z
*s
)*y_
+ (x
*z
*(1-c
)-y
*s
)*z_
,
343 (x
*y
*(1-c
)-z
*s
)*x_
+ (y2
+(x2
+z2
)*c
)*y_
+ (y
*z
*(1-c
)+x
*s
)*z_
,
344 (x
*z
*(1-c
)+y
*s
)*x_
+ (y
*z
*(1-c
)-x
*s
)*y_
+ (z2
+(x2
+y2
)*c
)*z_
,
351 Concrete::operator * ( Concrete::Length length
, const Concrete::UnitFloatTriple
& direction
)
353 return Concrete::Coords3D( length
* direction
.x_
, length
* direction
.y_
, length
* direction
.z_
);
357 Concrete::operator * ( const Concrete::UnitFloatTriple
& direction
, Concrete::Length length
)
359 return Concrete::Coords3D( length
* direction
.x_
, length
* direction
.y_
, length
* direction
.z_
);
362 // Concrete::UnitFloatTriple
363 // Concrete::operator + ( const Concrete::UnitFloatTriple & coords1, const Concrete::UnitFloatTriple & coords2 )
365 // return Concrete::UnitFloatTriple( coords1.x_ + coords2.x_, coords1.y_ + coords2.y_, coords1.z_ + coords2.z_ );
368 // Concrete::UnitFloatTriple
369 // Concrete::operator - ( const Concrete::UnitFloatTriple & coords1, const Concrete::UnitFloatTriple & coords2 )
371 // return Concrete::UnitFloatTriple( coords1.x_ - coords2.x_, coords1.y_ - coords2.y_, coords1.z_ - coords2.z_ );
375 Concrete::crossMagnitude( const Concrete::Coords3D
& a
, const Concrete::Coords3D
& b
)
377 return hypotPhysical( a
.y_
* b
.z_
- a
.z_
* b
.y_
,
378 a
.z_
* b
.x_
- a
.x_
* b
.z_
,
379 a
.x_
* b
.y_
- a
.y_
* b
.x_
);