222 lines
5.3 KiB
C++

/*
* This file is part of RawTherapee.
*
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
*
* RawTherapee 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.
*
* RawTherapee 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 RawTherapee. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __COORD__
#define __COORD__
#include "rt_math.h"
namespace rtengine
{
class PolarCoord;
// Do not confuse with rtengine::Coord2D, this one is for the GUI
class Coord
{
public:
int x;
int y;
Coord() : x(-1), y(-1) {}
Coord(int x, int y) : x(x), y(y) {}
void set (int x, int y)
{
this->x = x;
this->y = y;
}
void setFromPolar(PolarCoord polar);
/// @brief Clip the coord to stay in the width x height bounds
/// @return true if the x or y coordinate has changed
bool clip(int width, int height)
{
int trimmedX = rtengine::LIM<int>(x, 0, width);
int trimmedY = rtengine::LIM<int>(y, 0, height);
bool retval = trimmedX != x || trimmedY != y;
x = trimmedX;
y = trimmedY;
return retval;
}
bool operator== (const Coord& other) const
{
return other.x == x && other.y == y;
}
bool operator!= (const Coord& other) const
{
return other.x != x || other.y != y;
}
void operator+=(const Coord & rhs)
{
x += rhs.x;
y += rhs.y;
}
void operator-=(const Coord & rhs)
{
x -= rhs.x;
y -= rhs.y;
}
void operator*=(double scale)
{
x *= scale;
y *= scale;
}
Coord operator+(Coord & rhs)
{
Coord result(x + rhs.x, y + rhs.y);
return result;
}
Coord operator-(Coord & rhs)
{
Coord result(x - rhs.x, y - rhs.y);
return result;
}
Coord operator*(double scale)
{
Coord result(x * scale, y * scale);
return result;
}
};
class PolarCoord
{
public:
double radius;
double angle; // degree
PolarCoord() : radius(1.), angle(0.) {}
PolarCoord(double radius, double angle) : radius(radius), angle(angle) {}
PolarCoord(Coord start, Coord end) : radius(1.), angle(0.)
{
setFromCartesian(start, end);
}
PolarCoord(Coord delta) : radius(1.), angle(0.)
{
setFromCartesian(delta);
}
void set (double radius, double angle)
{
this->radius = radius;
this->angle = angle;
}
void setFromCartesian(Coord start, Coord end)
{
Coord delta(end.x - start.x, end.y - start.y);
setFromCartesian(delta);
}
void setFromCartesian(Coord delta)
{
if (!delta.x && !delta.y) {
// null vector, we set to a default value
radius = 1.;
angle = 0.;
return;
}
double x_ = double(delta.x);
double y_ = double(delta.y);
radius = sqrt(x_ * x_ + y_ * y_);
if (delta.x > 0.) {
if (delta.y >= 0.) {
angle = atan(y_ / x_) / (2 * M_PI) * 360.;
} else if (delta.y < 0.) {
angle = (atan(y_ / x_) + 2 * M_PI) / (2 * M_PI) * 360.;
}
} else if (delta.x < 0.) {
angle = (atan(y_ / x_) + M_PI) / (2 * M_PI) * 360.;
} else if (delta.x == 0.) {
if (delta.y > 0.) {
angle = 90.;
} else {
angle = 270.;
}
}
}
bool operator== (const PolarCoord& other) const
{
return other.radius == radius && other.angle == angle;
}
bool operator!= (const PolarCoord& other) const
{
return other.radius != radius || other.angle != angle;
}
void operator+=(const PolarCoord & rhs)
{
Coord thisCoord, rhsCoord;
thisCoord.setFromPolar(*this);
rhsCoord.setFromPolar(rhs);
thisCoord += rhsCoord;
setFromCartesian(thisCoord);
}
void operator-=(const PolarCoord & rhs)
{
Coord thisCoord, rhsCoord;
thisCoord.setFromPolar(*this);
rhsCoord.setFromPolar(rhs);
thisCoord -= rhsCoord;
setFromCartesian(thisCoord);
}
void operator*=(double scale)
{
radius *= scale;
}
PolarCoord operator+(PolarCoord & rhs)
{
Coord thisCoord, rhsCoord;
thisCoord.setFromPolar(*this);
rhsCoord.setFromPolar(rhs);
thisCoord += rhsCoord;
PolarCoord result;
result.setFromCartesian(thisCoord);
return result;
}
PolarCoord operator-(PolarCoord & rhs)
{
Coord thisCoord, rhsCoord;
thisCoord.setFromPolar(*this);
rhsCoord.setFromPolar(rhs);
thisCoord -= rhsCoord;
PolarCoord result;
result.setFromCartesian(thisCoord);
return result;
}
Coord operator*(double scale)
{
Coord result(radius * scale, angle);
return result;
}
};
}
#endif