mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 13:06:59 -04:00
Be explicit about type of angles: either Radians or Degrees.
Angles are always doubles. Internally use radians as much as possible. git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@1605 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
//+----------------------------------------------------------------------------+
|
||||
//| Description: Magic Set Editor - Program to make Magic (tm) cards |
|
||||
//| Copyright: (C) 2001 - 2010 Twan van Laarhoven and Sean Hunt |
|
||||
//| License: GNU General Public License 2 or later (see file COPYING) |
|
||||
//+----------------------------------------------------------------------------+
|
||||
|
||||
#ifndef HEADER_UTIL_ANGLE
|
||||
#define HEADER_UTIL_ANGLE
|
||||
|
||||
// ----------------------------------------------------------------------------- : Includes
|
||||
|
||||
#include <util/prec.hpp>
|
||||
|
||||
// ----------------------------------------------------------------------------- : Degrees & radians
|
||||
|
||||
typedef double Degrees;
|
||||
typedef double Radians;
|
||||
|
||||
/// Convert radians to degrees
|
||||
inline Degrees rad_to_deg(Radians rad) { return rad * (180.0 / M_PI); }
|
||||
/// Convert degrees to radians
|
||||
inline Radians deg_to_rad(Degrees deg) { return deg * (M_PI / 180.0); }
|
||||
|
||||
// ----------------------------------------------------------------------------- : Angle constants
|
||||
|
||||
const Radians rad0 = 0;
|
||||
const Radians rad45 = 0.25*M_PI;
|
||||
const Radians rad90 = 0.5*M_PI;
|
||||
const Radians rad180 = M_PI;
|
||||
const Radians rad270 = 1.5*M_PI;
|
||||
const Radians rad360 = 2.0*M_PI;
|
||||
|
||||
/// Are two floating point numbers equal up to a small epsilon?
|
||||
inline bool almost_equal(double x, double y) {
|
||||
return fabs(x-y) < 1e-10;
|
||||
}
|
||||
inline bool is_rad0(double x) {
|
||||
return almost_equal(x,0) || almost_equal(x,rad360);
|
||||
}
|
||||
inline bool is_rad90(double x) {
|
||||
return almost_equal(x,rad90);
|
||||
}
|
||||
inline bool is_rad180(double x) {
|
||||
return almost_equal(x,rad180);
|
||||
}
|
||||
inline bool is_rad270(double x) {
|
||||
return almost_equal(x,rad270);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Angle functions
|
||||
|
||||
// mod as it should be: answer in range [0..m)
|
||||
inline double sane_fmod(double x, double m) {
|
||||
double ans = fmod(x,m);
|
||||
if (ans < 0) return ans + m;
|
||||
else return ans;
|
||||
}
|
||||
|
||||
// constrain an angle to [0..2pi)
|
||||
inline Radians constrain_radians(Radians angle) {
|
||||
return sane_fmod(angle, 2*M_PI);
|
||||
}
|
||||
|
||||
/// Is an angle a multiple of 90 degrees?
|
||||
inline bool is_straight(Radians angle) {
|
||||
return almost_equal(sane_fmod(angle+rad45,rad90), rad45);
|
||||
}
|
||||
|
||||
/// Is an angle sideways (i.e. closer to 90 or 270 degrees than to 0 or 180 degrees)?
|
||||
inline bool is_sideways(Radians angle) {
|
||||
double a = sane_fmod(angle,M_PI);
|
||||
return (a > 0.25*M_PI && a < 0.75*M_PI);
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------- : EOF
|
||||
#endif
|
||||
+42
-67
@@ -13,13 +13,8 @@
|
||||
|
||||
// ----------------------------------------------------------------------------- : Rotation
|
||||
|
||||
// constrain an angle to [0..360)
|
||||
int constrain_angle(int angle) {
|
||||
return (angle + 3600) % 360;
|
||||
}
|
||||
|
||||
Rotation::Rotation(int angle, const RealRect& rect, double zoom, double stretch, RotationFlags flags)
|
||||
: angle(constrain_angle(angle))
|
||||
Rotation::Rotation(Radians angle, const RealRect& rect, double zoom, double stretch, RotationFlags flags)
|
||||
: angle(constrain_radians(angle))
|
||||
, size(rect.size())
|
||||
, origin(rect.position())
|
||||
, zoomX(zoom * stretch)
|
||||
@@ -30,8 +25,7 @@ Rotation::Rotation(int angle, const RealRect& rect, double zoom, double stretch,
|
||||
}
|
||||
// set origin
|
||||
if (flags & ROTATION_ATTACH_TOP_LEFT) {
|
||||
if (revX()) origin.x += zoom * (sideways() ? size.height : size.width);
|
||||
if (revY()) origin.y += zoom * (sideways() ? size.width : size.height);
|
||||
origin -= boundingBoxCorner(size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,59 +36,58 @@ void Rotation::setStretch(double s) {
|
||||
|
||||
|
||||
RealPoint Rotation::tr(const RealPoint& p) const {
|
||||
double a = deg_to_rad(angle), s = sin(a), c = cos(a);
|
||||
double s = sin(angle), c = cos(angle);
|
||||
double x = p.x * zoomX, y = p.y * zoomY;
|
||||
return RealPoint(c * x + s * y + origin.x,
|
||||
-s * x + c * y + origin.y);
|
||||
}
|
||||
RealPoint Rotation::trPixel(const RealPoint& p) const {
|
||||
double a = deg_to_rad(angle), s = sin(a), c = cos(a);
|
||||
double s = sin(angle), c = cos(angle);
|
||||
double x = p.x * zoomX + 0.5, y = p.y * zoomY + 0.5;
|
||||
return RealPoint(c * x + s * y + origin.x - 0.5,
|
||||
-s * x + c * y + origin.y - 0.5);
|
||||
}
|
||||
RealPoint Rotation::trNoZoom(const RealPoint& p) const {
|
||||
double a = deg_to_rad(angle), s = sin(a), c = cos(a);
|
||||
double s = sin(angle), c = cos(angle);
|
||||
double x = p.x, y = p.y;
|
||||
return RealPoint(c * x + s * y + origin.x,
|
||||
-s * x + c * y + origin.y);
|
||||
}
|
||||
RealPoint Rotation::trPixelNoZoom(const RealPoint& p) const {
|
||||
double a = deg_to_rad(angle), s = sin(a), c = cos(a);
|
||||
double s = sin(angle), c = cos(angle);
|
||||
double x = p.x + 0.5, y = p.y + 0.5;
|
||||
return RealPoint(c * x + s * y + origin.x - 0.5,
|
||||
-s * x + c * y + origin.y - 0.5);
|
||||
}
|
||||
/*
|
||||
RealSize Rotation::trSize(const RealSize& size) const {
|
||||
double a = deg_to_rad(angle), s = sin(a), c = cos(a);
|
||||
double x = size.width * zoomX, y = size.height * zoomY;
|
||||
return RealSize(c * x + s * y, s * x + c * y);
|
||||
}
|
||||
*/
|
||||
|
||||
RealSize Rotation::trSizeToBB(const RealSize& size) const {
|
||||
if (straight()) {
|
||||
if (sideways()) {
|
||||
if (is_straight(angle)) {
|
||||
if (is_sideways(angle)) {
|
||||
return RealSize(size.height * zoomY, size.width * zoomX);
|
||||
} else {
|
||||
return RealSize(size.width * zoomX, size.height * zoomY);
|
||||
}
|
||||
} else {
|
||||
double a = deg_to_rad(angle), s = sin(a), c = cos(a);
|
||||
double s = sin(angle), c = cos(angle);
|
||||
double x = size.width * zoomX, y = size.height * zoomY;
|
||||
return RealSize(fabs(c * x) + fabs(s * y), fabs(s * x) + fabs(c * y));
|
||||
}
|
||||
}
|
||||
|
||||
RealRect Rotation::trRectToBB(const RealRect& r) const {
|
||||
if (straight()) {
|
||||
RealSize s = trSizeToBB(r.size());
|
||||
return RealRect(tr(r.position()) - RealSize(revX()?s.width:0, revY()?s.height:0), s);
|
||||
double x = r.x * zoomX, y = r.y * zoomY;
|
||||
double w = r.width * zoomX, h = r.height * zoomY;
|
||||
const bool special_case_optimization = false;
|
||||
if (special_case_optimization && is_rad0(angle)) {
|
||||
return RealRect(origin.x + x, origin.y + y, w, h);
|
||||
} else if (special_case_optimization && is_rad180(angle)) {
|
||||
return RealRect(origin.x - x - w, origin.y - y - h, w, h);
|
||||
} else if (special_case_optimization && is_rad90(angle)) {
|
||||
return RealRect(origin.x + y, origin.y - x - w, h, w);
|
||||
} else if (special_case_optimization && is_rad270(angle)) {
|
||||
return RealRect(origin.x - y - h, origin.y + x, h, w);
|
||||
} else {
|
||||
double a = deg_to_rad(angle), s = sin(a), c = cos(a);
|
||||
double x = r.x * zoomX, y = r.y * zoomY;
|
||||
double w = r.width * zoomX, h = r.height * zoomY;
|
||||
double s = sin(angle), c = cos(angle);
|
||||
RealRect result(c * x + s * y + origin.x,
|
||||
-s * x + c * y + origin.y,
|
||||
0,0);
|
||||
@@ -120,13 +113,8 @@ RealRect Rotation::trRectToBB(const RealRect& r) const {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RealRect Rotation::trRectStraight(const RealRect& r) const {
|
||||
assert(angle == 0);
|
||||
return RealRect(r.position() + origin, r.size());
|
||||
}
|
||||
wxRegion Rotation::trRectToRegion(const RealRect& r) const {
|
||||
if (straight()) {
|
||||
if (is_straight(angle)) {
|
||||
return trRectToBB(r).toRect();
|
||||
} else {
|
||||
wxPoint points[4] = {trPixel(RealPoint(r.left(), r.top() ))
|
||||
@@ -138,13 +126,13 @@ wxRegion Rotation::trRectToRegion(const RealRect& r) const {
|
||||
}
|
||||
|
||||
RealPoint Rotation::trInv(const RealPoint& p) const {
|
||||
double a = deg_to_rad(angle), s = sin(a), c = cos(a);
|
||||
double s = sin(angle), c = cos(angle);
|
||||
double x = p.x - origin.x, y = p.y - origin.y;
|
||||
return RealPoint((c * x - s * y) / zoomX,
|
||||
(s * x + c * y) / zoomY);
|
||||
}
|
||||
RealSize Rotation::trInv(const RealSize& x) const {
|
||||
double a = deg_to_rad(angle), s = sin(a), c = cos(a);
|
||||
double s = sin(angle), c = cos(angle);
|
||||
return RealSize((c * x.width - s * x.height) / zoomX,
|
||||
(s * x.width + c * x.height) / zoomY);
|
||||
}
|
||||
@@ -153,26 +141,13 @@ RealPoint Rotation::boundingBoxCorner(const RealSize& size) const {
|
||||
// This function is a bit tricky,
|
||||
// I derived it by drawing the four cases.
|
||||
// Two succeeding cases must agree where they overlap (0,90,180,270 degrees)
|
||||
double a = deg_to_rad(angle), s = sin(a), c = cos(a);
|
||||
double s = sin(angle), c = cos(angle);
|
||||
double w = size.width * zoomX, h = size.height * zoomY;
|
||||
if (angle <= 90) return RealPoint(0, -w * s);
|
||||
if (angle <= 180) return RealPoint(w * c, h * c - w * s);
|
||||
if (angle <= 270) return RealPoint(w * c + h * s, h * c);
|
||||
else return RealPoint(h * s, 0);
|
||||
if (angle <= rad90) return RealPoint(0, -w * s);
|
||||
if (angle <= rad180) return RealPoint(w * c, h * c - w * s);
|
||||
if (angle <= rad270) return RealPoint(w * c + h * s, h * c);
|
||||
else return RealPoint(h * s, 0);
|
||||
}
|
||||
/*
|
||||
RealPoint Rotation::boundingBoxCorner(const RealSize& size) const {
|
||||
//if(true)return RealPoint(0,0);
|
||||
// This function is a bit tricky,
|
||||
// I derived it by drawing the four cases.
|
||||
// Two succeeding cases must agree where they overlap (0,90,180,270 degrees)
|
||||
double a = deg_to_rad(angle), s = sin(a), c = cos(a);
|
||||
if (angle <= 90) return RealPoint( + size.width * s * s, - size.width * s * c);
|
||||
if (angle <= 180) return RealPoint(size.width - size.height * s * c, size.height * c * c);
|
||||
if (angle <= 270) return RealPoint(size.width - size.width * s * s, size.height + size.width * s * c);
|
||||
else return RealPoint( size.height * s * c, size.height - size.height * c * c);
|
||||
}
|
||||
*/
|
||||
|
||||
// ----------------------------------------------------------------------------- : Rotater
|
||||
|
||||
@@ -183,7 +158,7 @@ Rotater::Rotater(Rotation& rot, const Rotation& by)
|
||||
// apply rotation
|
||||
rot.origin = rot.tr(by.origin);
|
||||
rot.size = by.size;
|
||||
rot.angle = constrain_angle(rot.angle + by.angle);
|
||||
rot.angle = constrain_radians(rot.angle + by.angle);
|
||||
// zooming is not really correct if rot.zoomX != rot.zoomY
|
||||
rot.zoomX *= by.zoomX;
|
||||
rot.zoomY *= by.zoomY;
|
||||
@@ -195,7 +170,7 @@ Rotater::~Rotater() {
|
||||
|
||||
// ----------------------------------------------------------------------------- : RotatedDC
|
||||
|
||||
RotatedDC::RotatedDC(DC& dc, int angle, const RealRect& rect, double zoom, RenderQuality quality, RotationFlags flags)
|
||||
RotatedDC::RotatedDC(DC& dc, Radians angle, const RealRect& rect, double zoom, RenderQuality quality, RotationFlags flags)
|
||||
: Rotation(angle, rect, zoom, 1.0, flags)
|
||||
, dc(dc), quality(quality)
|
||||
{}
|
||||
@@ -234,12 +209,12 @@ void RotatedDC::DrawText (const String& text, const RealPoint& pos, AColor colo
|
||||
dc.GetUserScale(&usx, &usy);
|
||||
dc.SetUserScale(usx/text_scaling, usy/text_scaling);
|
||||
dc.SetTextForeground(color);
|
||||
dc.DrawRotatedText(text, (int) p_ext.x, (int) p_ext.y, angle);
|
||||
dc.DrawRotatedText(text, (int) p_ext.x, (int) p_ext.y, rad_to_deg(angle));
|
||||
dc.SetUserScale(usx, usy);
|
||||
} else {
|
||||
RealPoint p_ext = tr(pos);
|
||||
dc.SetTextForeground(color);
|
||||
dc.DrawRotatedText(text, (int) p_ext.x, (int) p_ext.y, angle);
|
||||
dc.DrawRotatedText(text, (int) p_ext.x, (int) p_ext.y, rad_to_deg(angle));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,7 +224,7 @@ void RotatedDC::DrawTextWithShadow(const String& text, const Font& font, const R
|
||||
}
|
||||
|
||||
void RotatedDC::DrawBitmap(const Bitmap& bitmap, const RealPoint& pos) {
|
||||
if (angle == 0) {
|
||||
if (is_rad0(angle)) {
|
||||
RealPoint p_ext = tr(pos);
|
||||
dc.DrawBitmap(bitmap, to_int(p_ext.x), to_int(p_ext.y), true);
|
||||
} else {
|
||||
@@ -275,7 +250,7 @@ void RotatedDC::DrawLine (const RealPoint& p1, const RealPoint& p2) {
|
||||
}
|
||||
|
||||
void RotatedDC::DrawRectangle(const RealRect& r) {
|
||||
if (straight()) {
|
||||
if (is_straight(angle)) {
|
||||
wxRect r_ext = trRectToBB(r);
|
||||
dc.DrawRectangle(r_ext.x, r_ext.y, r_ext.width, r_ext.height);
|
||||
} else {
|
||||
@@ -288,7 +263,7 @@ void RotatedDC::DrawRectangle(const RealRect& r) {
|
||||
}
|
||||
|
||||
void RotatedDC::DrawRoundedRectangle(const RealRect& r, double radius) {
|
||||
if (straight()) {
|
||||
if (is_straight(angle)) {
|
||||
wxRect r_ext = trRectToBB(r);
|
||||
dc.DrawRoundedRectangle(r_ext.x, r_ext.y, r_ext.width, r_ext.height, trS(radius));
|
||||
} else {
|
||||
@@ -307,16 +282,16 @@ void RotatedDC::DrawEllipse(const RealPoint& center, const RealSize& size) {
|
||||
wxSize s_ext = trSizeToBB(size);
|
||||
dc.DrawEllipse(c_ext.x, c_ext.y, s_ext.x, s_ext.y);
|
||||
}
|
||||
void RotatedDC::DrawEllipticArc(const RealPoint& center, const RealSize& size, double start, double end) {
|
||||
void RotatedDC::DrawEllipticArc(const RealPoint& center, const RealSize& size, Radians start, Radians end) {
|
||||
wxPoint c_ext = tr(center - size/2);
|
||||
wxSize s_ext = trSizeToBB(size);
|
||||
dc.DrawEllipticArc(c_ext.x, c_ext.y, s_ext.x, s_ext.y, rad_to_deg(start) + angle, rad_to_deg(end) + angle);
|
||||
dc.DrawEllipticArc(c_ext.x, c_ext.y, s_ext.x, s_ext.y, rad_to_deg(start + angle), rad_to_deg(end + angle));
|
||||
}
|
||||
void RotatedDC::DrawEllipticSpoke(const RealPoint& center, const RealSize& size, double angle) {
|
||||
void RotatedDC::DrawEllipticSpoke(const RealPoint& center, const RealSize& size, Radians angle) {
|
||||
wxPoint c_ext = tr(center - size/2);
|
||||
wxSize s_ext = trSizeToBB(size);
|
||||
double rot_angle = angle + deg_to_rad(this->angle);
|
||||
double sin_angle = sin(rot_angle), cos_angle = cos(rot_angle);
|
||||
Radians rot_angle = angle + this->angle;
|
||||
Radians sin_angle = sin(rot_angle), cos_angle = cos(rot_angle);
|
||||
// position of center and of point on the boundary can vary because of rounding errors,
|
||||
// this code matches DrawEllipticArc (at least on windows xp).
|
||||
dc.DrawLine(
|
||||
|
||||
+9
-22
@@ -33,7 +33,7 @@ class Rotation {
|
||||
/** with the given rectangle of external coordinates and a given rotation angle and zoom factor.
|
||||
* if is_internal then the rect gives the internal coordinates, its origin should be (0,0)
|
||||
*/
|
||||
Rotation(int angle, const RealRect& rect = RealRect(0,0,0,0), double zoom = 1.0, double strectch = 1.0, RotationFlags flags = ROTATION_NORMAL);
|
||||
Rotation(Radians angle = 0, const RealRect& rect = RealRect(0,0,0,0), double zoom = 1.0, double strectch = 1.0, RotationFlags flags = ROTATION_NORMAL);
|
||||
|
||||
/// Change the zoom factor
|
||||
inline void setZoom(double z) { zoomX = zoomY = z; }
|
||||
@@ -44,7 +44,7 @@ class Rotation {
|
||||
/// Stretch factor
|
||||
inline double getStretch() const { return zoomX / zoomY; }
|
||||
/// Get the angle
|
||||
inline int getAngle() const { return angle; }
|
||||
inline Radians getAngle() const { return angle; }
|
||||
/// Change the origin
|
||||
inline void setOrigin(const RealPoint& o) { origin = o; }
|
||||
|
||||
@@ -67,7 +67,7 @@ class Rotation {
|
||||
inline RealSize trS(const RealSize& s) const { return RealSize(s.width * zoomX, s.height * zoomY); }
|
||||
|
||||
/// Translate an angle
|
||||
inline int trAngle(int a) { return (angle + a) % 360; }
|
||||
inline Radians trAngle(Radians a) { return constrain_radians(angle + a); }
|
||||
|
||||
/// Translate a single point
|
||||
RealPoint tr(const RealPoint& p) const;
|
||||
@@ -81,12 +81,9 @@ class Rotation {
|
||||
RealSize trSize(const RealSize& s) const;
|
||||
/// Translate a single size, returns the bounding box size (non-negative)
|
||||
RealSize trSizeToBB(const RealSize& s) const;
|
||||
/// Translate a rectangle, returns the bounding box
|
||||
/* //%%the size of the result may be negative*/
|
||||
/// Translate a rectangle, returns the bounding box, the size will be non-negative
|
||||
RealRect trRectToBB(const RealRect& r) const;
|
||||
/// Translate a rectangle, can only be used when not rotating
|
||||
RealRect trRectStraight(const RealRect& r) const;
|
||||
/// Translate a rectangle into a region (supports rotation
|
||||
/// Translate a rectangle into a region (supports rotation)
|
||||
wxRegion trRectToRegion(const RealRect& rect) const;
|
||||
|
||||
/// Translate a size or length back to internal 'coordinates'
|
||||
@@ -102,7 +99,7 @@ class Rotation {
|
||||
RealSize trInv(const RealSize& p) const;
|
||||
|
||||
protected:
|
||||
int angle; ///< The angle of rotation in degrees (counterclockwise)
|
||||
Radians angle; ///< The angle of rotation in radians (counterclockwise)
|
||||
RealSize size; ///< Size of the rectangle, in internal coordinates
|
||||
RealPoint origin; ///< tr(0,0)
|
||||
double zoomX; ///< Zoom factor, zoom = 2.0 means that 1 internal = 2 external
|
||||
@@ -110,16 +107,6 @@ class Rotation {
|
||||
|
||||
friend class Rotater;
|
||||
|
||||
/// Is the x axis 'reversed' (after turning sideways)?
|
||||
inline bool revX() const { return angle >= 180; }
|
||||
/// Is the y axis 'reversed' (after turning sideways)?
|
||||
inline bool revY() const { return angle == 90 || angle == 180; }
|
||||
/// Is the rotation 'simple', i.e. a multiple of 90 degrees?
|
||||
inline bool straight() const { return ::straight(angle); }
|
||||
/// Is the rotation sideways (90 or 270 degrees)?
|
||||
// Note: angle & 2 == 0 for angle in {0, 180} and != 0 for angle in {90, 270)
|
||||
inline bool sideways() const { return (angle & 2) != 0; }
|
||||
|
||||
/// Determine the top-left corner of the bounding box around the rotated box s (in external coordinates)
|
||||
RealPoint boundingBoxCorner(const RealSize& s) const;
|
||||
};
|
||||
@@ -165,7 +152,7 @@ enum RenderQuality {
|
||||
*/
|
||||
class RotatedDC : public Rotation {
|
||||
public:
|
||||
RotatedDC(DC& dc, int angle, const RealRect& rect, double zoom, RenderQuality quality, RotationFlags flags = ROTATION_NORMAL);
|
||||
RotatedDC(DC& dc, Radians angle, const RealRect& rect, double zoom, RenderQuality quality, RotationFlags flags = ROTATION_NORMAL);
|
||||
RotatedDC(DC& dc, const Rotation& rotation, RenderQuality quality);
|
||||
|
||||
// --------------------------------------------------- : Drawing
|
||||
@@ -190,9 +177,9 @@ class RotatedDC : public Rotation {
|
||||
void DrawCircle(const RealPoint& center, double radius);
|
||||
void DrawEllipse(const RealPoint& center, const RealSize& size);
|
||||
/// Draw an arc of an ellipse, angles are in radians
|
||||
void DrawEllipticArc(const RealPoint& center, const RealSize& size, double start, double end);
|
||||
void DrawEllipticArc(const RealPoint& center, const RealSize& size, Radians start, Radians end);
|
||||
/// Draw spokes of an ellipse
|
||||
void DrawEllipticSpoke(const RealPoint& center, const RealSize& size, double start);
|
||||
void DrawEllipticSpoke(const RealPoint& center, const RealSize& size, Radians start);
|
||||
|
||||
// Fill the dc with the color of the current brush
|
||||
void Fill();
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
// ----------------------------------------------------------------------------- : Includes
|
||||
|
||||
#include <util/prec.hpp>
|
||||
#include <util/angle.hpp>
|
||||
#include <limits>
|
||||
|
||||
// ----------------------------------------------------------------------------- : Rounding
|
||||
@@ -100,7 +101,7 @@ class Vector2D {
|
||||
return *this / length();
|
||||
}
|
||||
/// Angle between this vector and the x axis
|
||||
inline double angle() const {
|
||||
inline Radians angle() const {
|
||||
return atan2(y,x);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user