138 lines
3.6 KiB
C++
138 lines
3.6 KiB
C++
/*
|
||
* © Copyright 2014 – Urheberrechtshinweis
|
||
* Alle Rechte vorbehalten / All Rights Reserved
|
||
*
|
||
* Programmcode ist urheberrechtlich geschuetzt.
|
||
* Das Urheberrecht liegt, soweit nicht ausdruecklich anders gekennzeichnet, bei Frank Ebner.
|
||
* Keine Verwendung ohne explizite Genehmigung.
|
||
* (vgl. § 106 ff UrhG / § 97 UrhG)
|
||
*/
|
||
|
||
#ifndef HEADING_H
|
||
#define HEADING_H
|
||
|
||
#include <cmath>
|
||
#include <random>
|
||
|
||
#include "Angle.h"
|
||
|
||
struct Heading {
|
||
|
||
#define _2PI (2*(float)M_PI)
|
||
|
||
private:
|
||
|
||
/** heading in radians. 0 = to-the-right */
|
||
float rad;
|
||
|
||
public:
|
||
|
||
/** ctor with radians */
|
||
Heading(const float rad) : rad(rad) {
|
||
Assert::isBetween(rad, 0.0f, (float)_2PI, "radians out of bounds");
|
||
}
|
||
|
||
/** ctor from(x1,y1) to(x2,y2) */
|
||
Heading(const float x1, const float y1, const float x2, const float y2) : rad(Angle::getRAD_2PI(x1,y1,x2,y2)) {
|
||
Assert::isBetween(rad, 0.0f, (float)_2PI, "radians out of bounds");
|
||
}
|
||
|
||
/** ctor from(x,y) -> to(x,y) */
|
||
Heading(const Point2 from, const Point2 to) : Heading(from.x, from.y, to.x, to.y) {
|
||
;
|
||
}
|
||
|
||
/** POSITIVE angular difference [0:PI] */
|
||
float getDiffHalfRAD(const Heading other) const {
|
||
return Angle::getDiffRAD_2PI_PI(rad, other.rad);
|
||
}
|
||
|
||
/** signled angular difference [-PI:+PI] */
|
||
// float getSignedDiff(const Heading other) const {
|
||
// return Angle::getSignedDiffRAD_2PI(other.rad, rad);
|
||
// }
|
||
static float getSignedDiff(const Heading from, const Heading to) {
|
||
return Angle::getSignedDiffRAD_2PI(from.rad, to.rad);
|
||
}
|
||
|
||
/** update the angle but ensure we stay within [0:2PI] */
|
||
Heading& operator += (const float _rad) {
|
||
// Assert::isBetween(_rad, float(-_2PI*0.999), float(+_2PI*0.999), "radians out of bounds");
|
||
// Assert::isBetween(_rad, float(-_2PI), float(+_2PI), "radians out of bounds");
|
||
rad += _rad;
|
||
while (rad >= _2PI) {rad -= _2PI;}
|
||
while (rad < 0) {rad += _2PI;}
|
||
return *this;
|
||
}
|
||
|
||
/** update the angle but ensure we stay within [0:2PI] */
|
||
Heading& operator -= (const float _rad) {
|
||
return *this += (-_rad);
|
||
}
|
||
|
||
/** update the angle but ensure we stay within [0:2PI] */
|
||
Heading operator + (const float _rad) const {
|
||
return (Heading(*this) += _rad);
|
||
}
|
||
|
||
/** update the angle but ensure we stay within [0:2PI] */
|
||
Heading operator - (const float _rad) const {
|
||
return (Heading(*this) -= _rad);
|
||
}
|
||
|
||
|
||
/** update the angle but ensure we stay within [0:2PI] */
|
||
Heading operator - (const Heading head) const {
|
||
return *this - head.rad;
|
||
}
|
||
|
||
/** update the angle but ensure we stay within [0:2PI] */
|
||
Heading operator + (const Heading head) const {
|
||
return *this + head.rad;
|
||
}
|
||
|
||
|
||
Heading& operator = (const float _rad) {
|
||
rad = _rad;
|
||
return *this;
|
||
}
|
||
|
||
/** compare two headings */
|
||
bool operator == (const Heading other) const {return rad == other.rad;}
|
||
bool operator != (const Heading other) const {return rad != other.rad;}
|
||
|
||
/** get an inverted version of this heading (upwards -> downwards, left -> right, ...) */
|
||
Heading getInverted() const {
|
||
Heading out(rad);
|
||
out += M_PI;
|
||
return out;
|
||
}
|
||
|
||
float getRAD() const {return rad;}
|
||
|
||
/** convert heading into a direction-vector */
|
||
Point2 asVector() const {
|
||
return Point2(std::cos(rad), std::sin(rad));
|
||
}
|
||
|
||
// /** get a random heading */
|
||
// static Heading rnd() {
|
||
// static std::minstd_rand gen(1234);
|
||
// static std::uniform_real_distribution<float> dist(0, _2PI);
|
||
// const float rnd = dist(gen);
|
||
// return Heading(rnd);
|
||
// }
|
||
|
||
#undef _2PI
|
||
|
||
};
|
||
|
||
namespace Headings {
|
||
static const Heading RIGHT = Heading((float)M_PI*0.0f/2.0f);
|
||
static const Heading UP = Heading((float)M_PI*1.0f/2.0f);
|
||
static const Heading LEFT = Heading((float)M_PI*2.0f/2.0f);
|
||
static const Heading DOWN = Heading((float)M_PI*3.0f/2.0f);
|
||
}
|
||
|
||
#endif // HEADING_H
|