/*
* Copyright (C) 2010-2011 Dmitry Marakasov
*
* This file is part of glosm.
*
* glosm is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* glosm 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.
*
* You should have received a copy of the GNU General Public License
* along with glosm. If not, see .
*/
#ifndef MATH_HH
#define MATH_HH
#include
#include
#include
/**
* Long type trait
*
* For type T this defines type that can hold result of T*T (e.g.
* results of LengthSquare, DotProduct, area etc.)
*/
template
struct LongType {
typedef T type;
};
/**
* Long type for osmint_t
*/
template<>
struct LongType {
typedef osmlong_t type;
};
template
struct Vector3;
/**
* Template 2D vector class
*/
template
struct Vector2 {
typedef typename LongType::type LT;
/* ctors */
Vector2(): x(0), y(0) {}
Vector2(T x_, T y_): x(x_), y(y_) {}
Vector2(const Vector2& v): x(v.x), y(v.y) {}
Vector2(const Vector3& v): x(v.x), y(v.y) {}
/* static ctoroids */
template
static Vector2 FromYaw(const TT yaw) { return Vector2(std::sin(yaw), std::cos(yaw)); }
template
Vector2(const Vector2& v): x(v.x), y(v.y) {}
/* */
Vector2 LongVector() const {
return Vector2(*this);
}
/* operators */
Vector2 operator- () const { return Vector2(-x, -y); }
Vector2 operator+ (const Vector2& other) const { return Vector2(x + other.x, y + other.y); }
Vector2 operator- (const Vector2& other) const { return Vector2(x - other.x, y - other.y); }
Vector2 operator* (const Vector2& other) const { return Vector2(x * other.x, y * other.y); }
Vector2 operator/ (const Vector2& other) const { return Vector2(x / other.x, y / other.y); }
Vector2 operator+ (const T v) const { return Vector2(x + v, y + v); }
Vector2 operator- (const T v) const { return Vector2(x - v, y - v); }
Vector2 operator* (const T v) const { return Vector2(x * v, y * v); }
Vector2 operator/ (const T v) const { return Vector2(x / v, y / v); }
/* mutating operators */
Vector2& operator= (const Vector2& other) { x = other.x; y = other.y; return *this; }
Vector2& operator+= (const Vector2& other) { x += other.x; y += other.y; return *this; }
Vector2& operator-= (const Vector2& other) { x -= other.x; y -= other.y; return *this; }
Vector2& operator*= (const Vector2& other) { x *= other.x; y *= other.y; return *this; }
Vector2& operator/= (const Vector2& other) { x /= other.x; y /= other.y; return *this; }
Vector2& operator+= (const T& v) { x += v; y += v; return *this; }
Vector2& operator-= (const T& v) { x -= v; y -= v; return *this; }
Vector2& operator*= (const T& v) { x *= v; y *= v; return *this; }
Vector2& operator/= (const T& v) { x /= v; y /= v; return *this; }
/* comparison */
bool operator== (const Vector2& other) const { return x == other.x && y == other.y; }
bool operator!= (const Vector2& other) const { return x != other.x || y != other.y; }
/* validity check */
bool IsValid() const {
return std::isnormal(x) && std::isnormal(y);
}
/* functions */
T Length() { return std::sqrt((LT)x*(LT)x + (LT)y*(LT)y); }
LT LengthSquare() { return (LT)x*(LT)x + (LT)y*(LT)y; }
LT DotProduct(const Vector2& other) const { return (LT)x*(LT)other.x + (LT)y*(LT)other.y; }
LT CrossProduct(const Vector2& other) const { return (LT)x*(LT)other.y - (LT)y*(LT)other.x; }
void Normalize() {
T len = Length();
if (len == 0)
return;
x /= len;
y /= len;
}
Vector2 Normalized() {
T len = Length();
if (len == 0)
return Vector2(); /* Zero vector */
return Vector2(x / len, y / len);
}
bool IsInTriangle(const Vector2& v1, const Vector2& v2, const Vector2& v3) {
LT a = (v2-v1).CrossProduct(*this - v1);
LT b = (v3-v2).CrossProduct(*this - v2);
LT c = (v1-v3).CrossProduct(*this - v3);
return (a < 0 && b < 0 && c < 0) || (a > 0 && b > 0 && c > 0);
}
/* data */
T x;
T y;
};
/**
* Template 3D vector class
*/
template
struct Vector3 {
typedef typename LongType::type LT;
/* ctors */
Vector3(): x(0), y(0), z(0) {}
Vector3(T x_, T y_): x(x_), y(y_), z(0) {}
Vector3(T x_, T y_, T z_): x(x_), y(y_), z(z_) {}
Vector3(const Vector2& v): x(v.x), y(v.y), z(0) {}
Vector3(const Vector2& v, T z_): x(v.x), y(v.y), z(z_) {}
Vector3(const Vector3& v): x(v.x), y(v.y), z(v.z) {}
template
Vector3(const Vector3& v): x(v.x), y(v.y), z(v.z) {}
/* static ctoroids */
template
static Vector3 FromYawPitch(const TT yaw, const TT pitch) { return Vector3(sin(yaw)*cos(pitch), cos(yaw)*cos(pitch), sin(pitch)); }
/* */
Vector3 LongVector() const {
return Vector3(*this);
}
/* operators */
Vector3 operator- () const { return Vector3(-x, -y, -z); }
Vector3 operator+ (const Vector3& other) const { return Vector3(x + other.x, y + other.y, z + other.z); }
Vector3 operator- (const Vector3& other) const { return Vector3(x - other.x, y - other.y, z - other.z); }
Vector3 operator* (const Vector3& other) const { return Vector3(x * other.x, y * other.y, z * other.z); }
Vector3 operator/ (const Vector3& other) const { return Vector3(x / other.x, y / other.y, z / other.z); }
Vector3 operator* (const T v) const { return Vector3(x * v, y * v, z * v); }
Vector3 operator/ (const T v) const { return Vector3(x / v, y / v, z / v); }
/* mutating operators */
Vector3& operator= (const Vector3& other) { x = other.x; y = other.y; z = other.z; return *this; }
Vector3& operator+= (const Vector3& other) { x += other.x; y += other.y; z += other.z; return *this; }
Vector3& operator-= (const Vector3& other) { x -= other.x; y -= other.y; z -= other.z; return *this; }
Vector3& operator*= (const Vector3& other) { x *= other.x; y *= other.y; z *= other.z; return *this; }
Vector3& operator/= (const Vector3& other) { x /= other.x; y /= other.y; z /= other.z; return *this; }
Vector3& operator*= (const T& v) { x *= v; y *= v; z *= v; return *this; }
Vector3& operator/= (const T& v) { x /= v; y /= v; z /= v; return *this; }
/* comparison */
bool operator== (const Vector3& other) const { return x == other.x && y == other.y && z == other.z; }
bool operator!= (const Vector3& other) const { return x != other.x || y != other.y || z != other.z; }
/* validity check */
bool IsValid() const {
return std::isnormal(x) && std::isnormal(y) && std::isnormal(z);
}
/* functions */
T Length() const { return std::sqrt((LT)x*(LT)x + (LT)y*(LT)y + (LT)z*(LT)z); }
LT LengthSquare() const { return (LT)x*(LT)x + (LT)y*(LT)y + (LT)z*(LT)z; }
LT DotProduct(const Vector3& other) const { return (LT)x*(LT)other.x + (LT)y*(LT)other.y + (LT)z*(LT)other.z; }
Vector3 CrossProduct(const Vector3& other) const { return Vector3((LT)y*(LT)other.z - (LT)z*(LT)other.y, (LT)z*(LT)other.x - (LT)x*(LT)other.z, (LT)x*(LT)other.y - (LT)y*(LT)other.x); }
void Normalize() {
T len = Length();
if (len == 0)
return;
x /= len;
y /= len;
z /= len;
}
Vector3 Normalized() const {
T len = Length();
if (len == 0)
return Vector3(); /* Zero vector */
return Vector3(x / len, y / len, z / len);
}
Vector3 Flattened() const {
return Vector3(x, y, 0);
}
/* data */
T x;
T y;
T z;
};
typedef Vector2 Vector2i;
typedef Vector2 Vector2l;
typedef Vector2 Vector2f;
typedef Vector2 Vector2d;
typedef Vector3 Vector3i;
typedef Vector3 Vector3l;
typedef Vector3 Vector3f;
typedef Vector3 Vector3d;
#endif