1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373
|
//##########################################################################
//# #
//# CCLIB #
//# #
//# This program is free software; you can redistribute it and/or modify #
//# it under the terms of the GNU Library General Public License as #
//# published by the Free Software Foundation; version 2 or later of the #
//# License. #
//# #
//# This program is distributed in the hope that it will be useful, #
//# but WITHOUT ANY WARRANTY; without even the implied warranty of #
//# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
//# GNU General Public License for more details. #
//# #
//# COPYRIGHT: EDF R&D / TELECOM ParisTech (ENST-TSI) #
//# #
//##########################################################################
#ifndef CC_GEOM_HEADER
#define CC_GEOM_HEADER
//Local
#include "CCCoreLib.h"
#include "CCTypes.h"
//system
#include <cmath>
#include <limits>
#include <algorithm>
//! 2D Vector
template <typename Type> class Vector2Tpl
{
public:
union
{
struct
{
Type x, y;
};
Type u[2];
};
//! Default constructor
/** Inits vector to (0,0).
\param s default init value for both coordinates
**/
inline explicit Vector2Tpl(Type s = 0) : x(s), y(s) {}
//! Constructor from a couple of coordinates
/** Inits vector to (x,y).
\param _x x coordinate
\param _y y coordinate
**/
inline Vector2Tpl(Type _x, Type _y) : x(_x), y(_y) {}
//! Returns vector square norm
inline Type norm2() const { return (x*x) + (y*y); }
//! Returns vector norm
inline Type norm() const { return std::sqrt(norm2()); }
//! Sets vector norm to unity
inline void normalize() { Type n = norm2(); if (n > 0) *this /= std::sqrt(n); }
//! Dot product
inline Type dot(const Vector2Tpl& v) const { return (x*v.x) + (y*v.y); }
//! Cross product
/** \return a positive value if (u,v) makes a counter-clockwise turn, negative for clockwise turn, and zero if the vectors are parallel
**/
inline Type cross(const Vector2Tpl& v) const { return x * v.y - y * v.x; }
//! Inverse operator
inline Vector2Tpl& operator - () { x = -x; y = -y; return *this; }
//! In-place addition operator
inline Vector2Tpl& operator += (const Vector2Tpl& v) { x += v.x; y += v.y; return *this; }
//! In-place subtraction operator
inline Vector2Tpl& operator -= (const Vector2Tpl& v) { x -= v.x; y -= v.y; return *this; }
//! In-place multiplication (by a scalar) operator
inline Vector2Tpl& operator *= (Type v) { x *= v; y *= v; return *this; }
//! In-place division (by a scalar) operator
inline Vector2Tpl& operator /= (Type v) { x /= v; y /= v; return *this; }
//! Addition operator
inline Vector2Tpl operator + (const Vector2Tpl& v) const { return Vector2Tpl(x + v.x, y + v.y); }
//! Subtraction operator
inline Vector2Tpl operator - (const Vector2Tpl& v) const { return Vector2Tpl(x - v.x, y - v.y); }
//! Multiplication operator
inline Vector2Tpl operator * (Type s) const { return Vector2Tpl(x*s, y*s); }
//! Division operator
inline Vector2Tpl operator / (Type s) const { return Vector2Tpl(x / s, y / s); }
//! Direct coordinate access
inline Type& operator [] (unsigned i) { return u[i]; }
//! Direct coordinate access (const)
inline const Type& operator [] (unsigned i) const { return u[i]; }
};
//! 3-Tuple structure (templated version)
template <class Type> class Tuple3Tpl
{
public:
// The 3 tuple values as a union (array/separate values)
union
{
struct
{
Type x, y, z;
};
Type u[3];
};
//! Default constructor
/** Inits tuple to (0, 0, 0).
**/
inline Tuple3Tpl() : x(0), y(0), z(0) {}
//! Constructor from a triplet of values
/** Inits typle to (a,b,c).
**/
inline Tuple3Tpl(Type a, Type b, Type c) : x(a), y(b), z(c) {}
//! Constructor from an array of 3 elements
inline explicit Tuple3Tpl(const Type p[]) : x(p[0]), y(p[1]), z(p[2]) {}
//! Inverse operator
inline Tuple3Tpl operator - () const { Tuple3Tpl V(-x, -y, -z); return V; }
//! In-place addition operator
inline Tuple3Tpl& operator += (const Tuple3Tpl& v) { x += v.x; y += v.y; z += v.z; return *this; }
//! In-place subtraction operator
inline Tuple3Tpl& operator -= (const Tuple3Tpl& v) { x -= v.x; y -= v.y; z -= v.z; return *this; }
//! In-place multiplication (by a scalar) operator
inline Tuple3Tpl& operator *= (Type v) { x *= v; y *= v; z *= v; return *this; }
//! In-place division (by a scalar) operator
inline Tuple3Tpl& operator /= (Type v) { x /= v; y /= v; z /= v; return *this; }
//! Addition operator
inline Tuple3Tpl operator + (const Tuple3Tpl& v) const { return Tuple3Tpl(x + v.x, y + v.y, z + v.z); }
//! Subtraction operator
inline Tuple3Tpl operator - (const Tuple3Tpl& v) const { return Tuple3Tpl(x - v.x, y - v.y, z - v.z); }
//! Multiplication operator
inline Tuple3Tpl operator * (Type s) const { return Tuple3Tpl(x*s, y*s, z*s); }
//! Division operator
inline Tuple3Tpl operator / (Type s) const { return Tuple3Tpl(x/s, y/s, z/s); }
};
//! Tuple of 3 unsigned bytes
using Tuple3ub = Tuple3Tpl<unsigned char>;
//! Tuple of 3 short values
using Tuple3s = Tuple3Tpl<short>;
//! Tuple of 3 int values
using Tuple3i = Tuple3Tpl<int>;
//! Tuple of 3 unsigned int values
using Tuple3ui = Tuple3Tpl<unsigned int>;
//! 3D Vector (templated version)
template <typename Type> class Vector3Tpl : public Tuple3Tpl<Type>
{
public:
//Don't ask me what other x, y, z or u members this class could
//use but it seems necessary for compilation on some platforms...
using Tuple3Tpl<Type>::x;
using Tuple3Tpl<Type>::y;
using Tuple3Tpl<Type>::z;
using Tuple3Tpl<Type>::u;
//! Default constructor
/** Inits vector to (0, 0, 0).
**/
inline Vector3Tpl() : Tuple3Tpl<Type>() {}
//! Constructor from a triplet of coordinates
/** Inits vector to (x,y,z).
**/
inline Vector3Tpl(Type _x, Type _y, Type _z) : Tuple3Tpl<Type>(_x, _y, _z) {}
//! Constructor from an array of 3 elements
inline explicit Vector3Tpl(const Type p[]) : Tuple3Tpl<Type>(p) {}
//! Constructor from a 2D vector (and a third value)
inline explicit Vector3Tpl(const Vector2Tpl<Type>& t2D, Type c) : Tuple3Tpl<Type>(t2D.x, t2D.y, c) {}
//! Constructor from an int array
static inline Vector3Tpl fromArray(const int a[3]) { return Vector3Tpl(static_cast<Type>(a[0]), static_cast<Type>(a[1]), static_cast<Type>(a[2])); }
//! Constructor from a float array
static inline Vector3Tpl fromArray(const float a[3]) { return Vector3Tpl(static_cast<Type>(a[0]), static_cast<Type>(a[1]), static_cast<Type>(a[2])); }
//! Constructor from a double array
static inline Vector3Tpl fromArray(const double a[3]) { return Vector3Tpl(static_cast<Type>(a[0]), static_cast<Type>(a[1]), static_cast<Type>(a[2])); }
//! Dot product
inline Type dot(const Vector3Tpl& v) const { return x*v.x + y*v.y + z*v.z; }
//! Cross product
inline Vector3Tpl cross(const Vector3Tpl &v) const { return Vector3Tpl((y*v.z) - (z*v.y), (z*v.x) - (x*v.z), (x*v.y) - (y*v.x)); }
//! Returns vector square norm
inline Type norm2() const { return x*x + y*y + z*z; }
//! Returns vector square norm (forces double precision output)
inline double norm2d() const { return static_cast<double>(x)*x + static_cast<double>(y)*y + static_cast<double>(z)*z; }
//! Returns vector norm
inline Type norm() const { return static_cast<Type>(std::sqrt(norm2d())); }
//! Returns vector norm (forces double precision output)
inline double normd() const { return std::sqrt(norm2d()); }
//! Sets vector norm to unity
inline void normalize() { Type n = norm(); if (n > std::numeric_limits<Type>::epsilon()) *this /= n; }
//! Returns a normalized vector which is orthogonal to this one
inline Vector3Tpl orthogonal() const { Vector3Tpl ort; vorthogonal(u, ort.u); return ort; }
//! Inverse operator
inline Vector3Tpl operator - () const { Vector3Tpl V(-x, -y, -z); return V; }
//! In-place addition operator
inline Vector3Tpl& operator += (const Vector3Tpl& v) { x += v.x; y += v.y; z += v.z; return *this; }
//! In-place subtraction operator
inline Vector3Tpl& operator -= (const Vector3Tpl& v) { x -= v.x; y -= v.y; z -= v.z; return *this; }
//! In-place multiplication (by a scalar) operator
inline Vector3Tpl& operator *= (Type v) { x *= v; y *= v; z *= v; return *this; }
//! In-place division (by a scalar) operator
inline Vector3Tpl& operator /= (Type v) { x /= v; y /= v; z /= v; return *this; }
//! Addition operator
inline Vector3Tpl operator + (const Vector3Tpl& v) const { return Vector3Tpl(x + v.x, y + v.y, z + v.z); }
//! Subtraction operator
inline Vector3Tpl operator - (const Vector3Tpl& v) const { return Vector3Tpl(x - v.x, y - v.y, z - v.z); }
//! Multiplication operator
inline Vector3Tpl operator * (Type s) const { return Vector3Tpl(x*s, y*s, z*s); }
//! Division operator
inline Vector3Tpl operator / (Type s) const { return Vector3Tpl(x/s, y/s, z/s); }
//! Cross product operator
inline Vector3Tpl operator * (const Vector3Tpl& v) const { return cross(v); }
//! Dot product operator
inline Type operator && (const Vector3Tpl& v) const { return dot(v); }
//! Direct coordinate access
inline Type& operator [] (unsigned i) { return u[i]; }
//! Direct coordinate access (const)
inline const Type& operator [] (unsigned i) const { return u[i]; }
//! Returns the angle to another vector (in radians - in [0, pi]
Type angle_rad(const Vector3Tpl& v) const { return vangle_rad(u, v.u); }
double angle_radd(const Vector3Tpl& v) const { return vangle_radd(u, v.u); }
static inline void vdivide(const Type p[], Type s, Type r[]) { r[0] = p[0] / s; r[1] = p[1] / s; r[2] = p[2] / s; }
static inline void vdivide(Type p[], Type s) { p[0] /= s; p[1] /= s; p[2] /= s; }
static inline void vmultiply(const Type p[], Type s, Type r[]) { r[0] = p[0] * s; r[1] = p[1] * s; r[2] = p[2] * s; }
static inline void vmultiply(Type p[], Type s) { p[0] *= s; p[1] *= s; p[2] *= s; }
static inline Type vdot(const Type p[], const Type q[]) { return (p[0] * q[0]) + (p[1] * q[1]) + (p[2] * q[2]); }
static inline double vdotd(const Type p[], const Type q[]) { return (static_cast<double>(p[0])* q[0]) + (static_cast<double>(p[1])* q[1]) + (static_cast<double>(p[2])* q[2]); }
static inline void vcross(const Type p[], const Type q[], Type r[]) { r[0] = (p[1] * q[2]) - (p[2] * q[1]); r[1] = (p[2] * q[0]) - (p[0] * q[2]); r[2] = (p[0] * q[1]) - (p[1] * q[0]); }
static inline void vcopy(const Type p[], Type q[]) { q[0] = p[0]; q[1] = p[1]; q[2] = p[2]; }
static inline void vset(Type p[], Type s) { p[0] = p[1] = p[2] = s; }
static inline void vset(Type p[], Type x, Type y, Type z) { p[0] = x; p[1] = y; p[2] = z; }
static inline void vadd(const Type p[], const Type q[], Type r[]) { r[0] = p[0] + q[0]; r[1] = p[1] + q[1]; r[2] = p[2] + q[2]; }
// note misspelling: should be vsubtract
static inline void vsubstract(const Type p[], const Type q[], Type r[]) { r[0] = p[0] - q[0]; r[1] = p[1] - q[1]; r[2] = p[2] - q[2]; }
static inline void vcombination(Type a, const Type p[], Type b, const Type q[], Type r[]) { r[0] = (a*p[0]) + (b*q[0]); r[1] = (a*p[1]) + (b*q[1]); r[2] = (a*p[2]) + (b*q[2]); }
static inline void vcombination(const Type p[], Type b, const Type q[], Type r[]) { r[0] = p[0] + (b*q[0]); r[1] = p[1] + (b*q[1]); r[2] = p[2] + (b*q[2]); }
static inline void vnormalize(Type p[]) { Type n = vnorm2(p); if (n > 0) vdivide(p, std::sqrt(n)); }
static inline Type vnorm2(const Type p[]) { return (p[0] * p[0]) + (p[1] * p[1]) + (p[2] * p[2]); }
static inline double vnorm2d(const Type p[]) { return (static_cast<double>(p[0]) * p[0]) + (static_cast<double>(p[1]) * p[1]) + (static_cast<double>(p[2]) * p[2]); }
static inline Type vdistance2(const Type p[], const Type q[]) { return ((p[0] - q[0])*(p[0] - q[0])) + ((p[1] - q[1])*(p[1] - q[1])) + ((p[2] - q[2])*(p[2] - q[2])); }
static inline double vdistance2d(const Type p[], const Type q[]) { return ((static_cast<double>(p[0]) - q[0]) * (static_cast<double>(p[0]) - q[0])) + ((static_cast<double>(p[1]) - q[1]) * (static_cast<double>(p[1]) - q[1])) + ((static_cast<double>(p[2]) - q[2]) * (static_cast<double>(p[2]) - q[2])); }
static inline Type vnorm(const Type p[]) { return std::sqrt(vnorm2(p)); }
static inline double vnormd(const Type p[]) { return std::sqrt(vnorm2d(p)); }
static inline Type vdistance(const Type p[], const Type q[]) { return std::sqrt(vdistance2(p, q)); }
static inline double vdistanced(const Type p[], const Type q[]) { return std::sqrt(vdistance2d(p, q)); }
static void vorthogonal(const Type p[], Type q[])
{
if (std::abs(p[0]) <= std::abs(p[1]) && std::abs(p[0]) <= std::abs(p[2]))
{
q[0] = 0; q[1] = p[2]; q[2] = -p[1];
}
else if (std::abs(p[1]) <= std::abs(p[0]) && std::abs(p[1]) <= std::abs(p[2]))
{
q[0] = -p[2]; q[1] = 0; q[2] = p[0];
}
else
{
q[0] = p[1]; q[1] = -p[0]; q[2] = 0;
}
vnormalize(q);
}
static Type vangle_rad(const Type p[], const Type q[])
{
Type productNorm = vnorm(p) * vnorm(q);
if (productNorm < std::numeric_limits<Type>::epsilon())
{
return std::numeric_limits<Type>::quiet_NaN();
}
Type cosAngle = vdot(p, q) / productNorm;
return acos(std::max(std::min(cosAngle, static_cast<Type>(1.0)), static_cast<Type>(-1.0)));
}
static double vangle_radd(const Type p[], const Type q[])
{
double productNorm = vnormd(p) * vnormd(q);
if (productNorm < std::numeric_limits<double>::epsilon())
{
return std::numeric_limits<double>::quiet_NaN();
}
double cosAngle = vdotd(p, q) / productNorm;
return acos(std::max(std::min(cosAngle, 1.0), -1.0));
}
};
//! 4-Tuple structure (templated version)
template <class Type> class Tuple4Tpl
{
public:
// The 4 tuple values as a union (array/separate values)
union
{
struct
{
Type x, y, z, w;
};
Type u[4];
};
//! Default constructor
/** Inits tuple to (0, 0, 0, 0).
**/
inline Tuple4Tpl() : x(0), y(0), z(0), w(0) {}
//! Constructor from a triplet of values
/** Inits typle to (a,b,c).
**/
inline Tuple4Tpl(Type a, Type b, Type c, Type d) : x(a), y(b), z(c), w(d) {}
//! Constructor from an array of 4 elements
inline explicit Tuple4Tpl(const Type p[]) : x(p[0]), y(p[1]), z(p[2]), w(p[3]) {}
//! Inverse operator
inline Tuple4Tpl operator - () const { Tuple4Tpl V(-x, -y, -z, -w); return V; }
//! In-place addition operator
inline Tuple4Tpl& operator += (const Tuple4Tpl& v) { x += v.x; y += v.y; z += v.z; w += v.w; return *this; }
//! In-place subtraction operator
inline Tuple4Tpl& operator -= (const Tuple4Tpl& v) { x -= v.x; y -= v.y; z -= v.z; w -= v.w; return *this; }
//! In-place multiplication (by a scalar) operator
inline Tuple4Tpl& operator *= (Type v) { x *= v; y *= v; z *= v; w *= v; return *this; }
//! In-place division (by a scalar) operator
inline Tuple4Tpl& operator /= (Type v) { x /= v; y /= v; z /= v; w /= v; return *this; }
//! Addition operator
inline Tuple4Tpl operator + (const Tuple4Tpl& v) const { return Tuple4Tpl(x + v.x, y + v.y, z + v.z, w + v.w); }
//! Subtraction operator
inline Tuple4Tpl operator - (const Tuple4Tpl& v) const { return Tuple4Tpl(x - v.x, y - v.y, z - v.z, w - v.w); }
//! Multiplication operator
inline Tuple4Tpl operator * (Type s) const { return Tuple4Tpl(x*s, y*s, z*s, w*s); }
//! Division operator
inline Tuple4Tpl operator / (Type s) const { return Tuple4Tpl(x / s, y / s, z / s, w / s); }
};
//! Default 2D Vector
using CCVector2 = Vector2Tpl<PointCoordinateType>;
//! Double 2D Vector
using CCVector2d = Vector2Tpl<double>;
//! Int 2D Vector
using CCVector2i = Vector2Tpl<int>;
//! Multiplication of a 3D vector by a scalar (front) operator (float version)
inline Vector3Tpl<float> operator * (float s, const Vector3Tpl<float> &v) { return v*s; }
// Multiplication of a 3D vector by a scalar (front) operator (double version)
inline Vector3Tpl<double> operator * (double s, const Vector3Tpl<double> &v) { return v*s; }
//! Default 3D Vector
using CCVector3 = Vector3Tpl<PointCoordinateType>;
//! Double 3D Vector
using CCVector3f = Vector3Tpl<float>;
//! Double 3D Vector
using CCVector3d = Vector3Tpl<double>;
#endif //CC_GEOM_HEADER
|