Added some 2d geometry classes.

This commit is contained in:
Giulio Camuffo 2011-08-30 18:38:33 +02:00
parent 049e29d42d
commit 589ca13702
7 changed files with 595 additions and 85 deletions

197
graphics/line2d.cpp Normal file
View File

@ -0,0 +1,197 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
* $URL$
* $Id$
*/
#include "graphics/line2d.h"
#include "graphics/rect2d.h"
namespace Graphics {
Line2d::Line2d() :
_a(0), _b(0), _c(0) {
}
Line2d::Line2d(const Vector2d &direction, const Vector2d &point) {
Vector2d d = direction;
_a = d._y / d._x;
_b = -1;
if (_b == 0) {
_c = -point._x;
} else {
_c = point._y - (d._y / d._x) * point._x;
}
}
Line2d Line2d::getPerpendicular(const Vector2d &point) const {
Vector2d v(1, _b / _a);
return Line2d(v, point);
}
Vector2d Line2d::getDirection() const {
return Vector2d(1, _a);
}
bool Line2d::intersectsLine(const Line2d &line, Vector2d *pos) const {
// if (*this == line) {
// return false;
// }
float a = _a;
float b = _b;
float c = _c;
float d = line._a;
float e = line._b;
float f = line._c;
float x, y;
if (d * b - a * e == 0 || a == 0) {
return false;
}
if (!pos) {
return true;
}
/*
* {ax + by + c = 0 -> x = -(by + c) / a
* {dx + ey + f = 0 -> y = (-dc + af) / (db - ae)
*/
y = (-d * c + a * f) / (d * b - a * e);
x = -(b * y + c) / a;
*pos = Vector2d(x, y);
return true;
}
bool Line2d::containsPoint(const Vector2d &point) const {
float n = _a * point._x + _b * point._y + _c;
return (n < 0.0001 && n > -0.0001);
}
float Line2d::getYatX(float x) const {
return -(_a * x + _c) / _b;
}
Segment2d::Segment2d() {
}
Segment2d::Segment2d(const Vector2d &b, const Vector2d &e) :
_begin(b), _end(e) {
}
Segment2d::Segment2d(const Segment2d &other) {
*this = other;
}
Vector2d Segment2d::begin() const {
return _begin;
}
Vector2d Segment2d::end() const {
return _end;
}
Vector2d Segment2d::middle() const {
return (_begin + _end) / 2.f;
}
Line2d Segment2d::getLine() const {
float y = _end._y - _begin._y;
float x = _end._x - _begin._x;
Vector2d v(x, y);
return Line2d(v, _begin);
}
Line2d Segment2d::getPerpendicular(const Vector2d &point) const {
return getLine().getPerpendicular(point);
}
bool Segment2d::intersectsSegment(const Segment2d &other, Vector2d *pos) {
float denom = ((other._end._y - other._begin._y) * (_end._x - _begin._x)) -
((other._end._x - other._begin._x) * (_end._y - _begin._y));
float d = ((_end._y - _begin._y) * (other._end._x - other._begin._x)) -
((_end._x - _begin._x) * (other._end._y - other._begin._y));
float nume_a = ((other._end._x - other._begin._x) * (_begin._y - other._begin._y)) -
((other._end._y - other._begin._y) * (_begin._x - other._begin._x));
float nume_b = ((_end._x - _begin._x) * (other._begin._y - _begin._y)) -
((_end._y - _begin._y) * (other._begin._x - _begin._x));
if (denom == 0.0f) {
return false;
}
float ua = nume_a / denom;
float ub = nume_b / d;
if (ua < 0 || ua > 1 || ub < 0 || ub > 1) {
return false;
}
// Get the intersection point.
if (pos)
*pos = _begin + (_end - _begin) * ua;
return true;
}
bool Segment2d::intersectsLine(const Line2d &line, Vector2d *pos) {
Vector2d p;
if (getLine().intersectsLine(line, &p) && containsPoint(p)) {
if (pos)
*pos = p;
return true;
}
return false;
}
bool Segment2d::containsPoint(const Vector2d &point) const {
if (getLine().containsPoint(point)) {
return Rect2d(_begin, _end).containsPoint(point);
}
return false;
}
void Segment2d::operator=(const Segment2d &other) {
_begin = other._begin;
_end = other._end;
}
}

78
graphics/line2d.h Normal file
View File

@ -0,0 +1,78 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
* $URL$
* $Id$
*/
#ifndef GRAPHICS_LINE2D_H
#define GRAPHICS_LINE2D_H
#include "graphics/vector2d.h"
namespace Graphics {
class Line2d {
public:
Line2d();
Line2d(const Vector2d &direction, const Vector2d &point);
Line2d getPerpendicular(const Vector2d &point = Vector2d()) const;
Vector2d getDirection() const;
bool intersectsLine(const Line2d &line, Vector2d *pos) const;
bool containsPoint(const Vector2d &point) const;
float getYatX(float x) const;
private:
float _a, _b, _c;
};
class Segment2d {
public:
Segment2d();
Segment2d(const Vector2d &begin, const Vector2d &end);
Segment2d(const Segment2d &other);
Vector2d begin() const;
Vector2d end() const;
Vector2d middle() const;
Line2d getLine() const;
Line2d getPerpendicular(const Vector2d &point = Vector2d()) const;
bool containsPoint(const Vector2d &point) const;
bool intersectsLine(const Line2d &line, Vector2d *pos);
bool intersectsSegment(const Segment2d &line, Vector2d *pos);
void operator=(const Segment2d &other);
private:
Graphics::Vector2d _begin, _end;
};
}
#endif

View File

@ -18,7 +18,9 @@ MODULE_OBJS := \
matrix3.o \
matrix4.o \
line3d.o \
line2d.o \
rect2d.o \
vector2d.o \
tinygl/api.o \
tinygl/arrays.o \
tinygl/clear.o \

View File

@ -1,3 +1,26 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
* $URL$
* $Id$
*/
#include "common/scummsys.h"
@ -5,73 +28,22 @@
namespace Graphics {
Vector2d::Vector2d() :
_x(0), _y(0) {
}
Vector2d::Vector2d(float x, float y) :
_x(x), _y(y) {
}
Vector2d::Vector2d(const Vector2d &vec) :
_x(vec._x), _y(vec._y) {
}
Vector2d &Vector2d::operator=(const Vector2d &vec) {
_x = vec._x;
_y = vec._y;
return *this;
}
Vector2d &Vector2d::operator+(const Vector2d &vec) {
_x += vec._x;
_y += vec._y;
return *this;
}
Vector2d &Vector2d::operator-(const Vector2d &vec) {
_x -= vec._x;
_y -= vec._y;
return *this;
}
void Vector2d::rotateAround(const Vector2d &point, float angle) {
_x -= point._x;
_y -= point._y;
float a = angle * LOCAL_PI / 180.0;
float x = _x * cos(a) - _y * sin(a);
_y = _x * sin(a) + _y * cos(a);
_x = x;
_x += point._x;
_y += point._y;
}
float Vector2d::getAngle() const {
const float mag = sqrt(_x * _x + _y * _y);
float a = _x / mag;
float b = _y / mag;
float yaw;
// find the angle on the upper half of the unit circle
yaw = acos(a) * (180.0f / LOCAL_PI);
if (b < 0.0f)
// adjust for the lower half of the unit circle
return 360.0f - yaw;
else
// no adjustment, angle is on the upper half
return yaw;
}
Rect2d::Rect2d() {
}
Rect2d::Rect2d(const Vector2d &topLeft, const Vector2d &bottomRight) {
float left = (topLeft._x <= bottomRight._x ? topLeft._x : bottomRight._x);
float right = (topLeft._x <= bottomRight._x ? bottomRight._x : topLeft._x);
float top = (topLeft._y <= bottomRight._y ? topLeft._y : bottomRight._y);
float bottom = (topLeft._y <= bottomRight._y ? bottomRight._y : topLeft._y);
_topLeft = Vector2d(left, top);
_topRight = Vector2d(right, top);
_bottomLeft = Vector2d(left, bottom);
_bottomRight = Vector2d(right, bottom);
}
Rect2d::Rect2d(const Vector2d &topLeft, const Vector2d &topRight,
const Vector2d &bottomLeft, const Vector2d &bottomRight) :
_topLeft(topLeft), _topRight(topRight),
@ -132,6 +104,11 @@ bool Rect2d::intersectsCircle(const Vector2d &center, float radius) const {
}
}
bool Rect2d::containsPoint(const Vector2d &point) const {
return (point._x >= _topLeft._x && point._x <= _bottomRight._x &&
point._y >= _topLeft._y && point._y <= _bottomRight._y);
}
Vector2d Rect2d::getCenter() const {
Vector2d sum;
sum._x = _topLeft._x + _topRight._x + _bottomLeft._x + _bottomRight._x;
@ -142,6 +119,22 @@ Vector2d Rect2d::getCenter() const {
return sum;
}
Vector2d Rect2d::getTopLeft() const {
return _topLeft;
}
Vector2d Rect2d::getTopRight() const {
return _topRight;
}
Vector2d Rect2d::getBottomLeft() const {
return _bottomLeft;
}
Vector2d Rect2d::getBottomRight() const {
return _bottomRight;
}
float Rect2d::getWidth() const {
float x = _topRight._x - _topLeft._x;
float y = _topRight._y - _topLeft._y;
@ -156,4 +149,45 @@ float Rect2d::getHeight() const {
return sqrt(x * x + y * y);
}
Vector2d Rect2d::getIntersection(const Vector2d &start, const Vector2d &dir, Segment2d *edge) const {
float w = getWidth();
float h = getHeight();
float d = sqrt(w * w + h * h);
Segment2d line(start, start + dir.getNormalized() * 2*d);
Vector2d intersection;
Segment2d l(_topLeft, _topRight);
if (line.intersectsSegment(l, &intersection)) {
if (edge) {
*edge = l;
}
return intersection;
}
l = Segment2d(_topRight, _bottomRight);
if (line.intersectsSegment(l, &intersection)) {
if (edge) {
*edge = l;
}
return intersection;
}
l = Segment2d(_bottomRight, _bottomLeft);
if (line.intersectsSegment(l, &intersection)) {
if (edge) {
*edge = l;
}
return intersection;
}
l = Segment2d(_bottomLeft, _topLeft);
if (line.intersectsSegment(l, &intersection)) {
if (edge) {
*edge = l;
}
return intersection;
}
return intersection;
}
}

View File

@ -1,35 +1,41 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
* $URL$
* $Id$
*/
#ifndef GRAPHICS_RECT2D_H
#define GRAPHICS_RECT2D_H
#include "graphics/vector2d.h"
#include "graphics/line2d.h"
namespace Graphics {
class Vector2d {
public:
Vector2d();
Vector2d(float x, float y);
Vector2d(const Vector2d &vec);
Vector2d &operator=(const Vector2d &vec);
Vector2d &operator-(const Vector2d &vec);
Vector2d &operator+(const Vector2d &vec);
void rotateAround(const Vector2d &point, float angle);
float getAngle() const;
// private:
float _x;
float _y;
};
inline Vector2d operator-(const Vector2d& v1, const Vector2d& v2) {
Vector2d result(v1._x - v2._x, v1._y - v2._y);;
return result;
}
class Segment2d;
class Rect2d {
public:
Rect2d();
Rect2d(const Vector2d &topLeft, const Vector2d &bottomRight);
Rect2d(const Vector2d &topLeft, const Vector2d &topRight,
const Vector2d &bottomLeft, const Vector2d &bottomRight);
@ -37,10 +43,16 @@ public:
void rotateAroundCenter(float angle);
bool intersectsRect(const Rect2d &rect) const;
bool intersectsCircle(const Vector2d &center, float radius) const;
bool containsPoint(const Vector2d &point) const;
Vector2d getCenter() const;
Vector2d getTopLeft() const;
Vector2d getTopRight() const;
Vector2d getBottomLeft() const;
Vector2d getBottomRight() const;
float getWidth() const;
float getHeight() const;
Vector2d getIntersection(const Vector2d &start, const Vector2d &direction, Segment2d *edge) const;
// private:
Vector2d _topLeft;

106
graphics/vector2d.cpp Normal file
View File

@ -0,0 +1,106 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
* $URL$
* $Id$
*/
#include "graphics/vector2d.h"
namespace Graphics {
Vector2d::Vector2d() :
_x(0), _y(0) {
}
Vector2d::Vector2d(float x, float y) :
_x(x), _y(y) {
}
Vector2d::Vector2d(const Vector2d &vec) :
_x(vec._x), _y(vec._y) {
}
Vector2d &Vector2d::operator=(const Vector2d &vec) {
_x = vec._x;
_y = vec._y;
return *this;
}
void Vector2d::rotateAround(const Vector2d &point, float angle) {
_x -= point._x;
_y -= point._y;
float a = angle * LOCAL_PI / 180.0;
float x = _x * cos(a) - _y * sin(a);
_y = _x * sin(a) + _y * cos(a);
_x = x;
_x += point._x;
_y += point._y;
}
float Vector2d::getAngle() const {
const float mag = sqrt(_x * _x + _y * _y);
float a = _x / mag;
float b = _y / mag;
float yaw;
// find the angle on the upper half of the unit circle
yaw = acos(a) * (180.0f / LOCAL_PI);
if (b < 0.0f)
// adjust for the lower half of the unit circle
return 360.0f - yaw;
else
// no adjustment, angle is on the upper half
return yaw;
}
float Vector2d::getMagnitude() const {
return sqrt(_x * _x + _y * _y);
}
void Vector2d::normalize() {
float mag = getMagnitude();
_x /= mag;
_y /= mag;
}
Vector2d Vector2d::getNormalized() const {
float mag = getMagnitude();
Vector2d v(_x / mag, _y / mag);
return v;
}
float Vector2d::getDistanceTo(const Vector2d &point) const {
float x = point._x - _x;
float y = point._y - _y;
return sqrt(x * x + y * y);
}
Vector3d Vector2d::toVector3d() const {
Vector3d v(_x, _y, 0);
return v;
}
}

81
graphics/vector2d.h Normal file
View File

@ -0,0 +1,81 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
* $URL$
* $Id$
*/
#ifndef GRAPHICS_VECTOR2D_H
#define GRAPHICS_VECTOR2D_H
#include "graphics/vector3d.h"
namespace Graphics {
class Vector2d {
public:
Vector2d();
Vector2d(float x, float y);
Vector2d(const Vector2d &vec);
Vector2d &operator=(const Vector2d &vec);
void normalize();
Vector2d getNormalized() const;
void rotateAround(const Vector2d &point, float angle);
float getAngle() const;
float getMagnitude() const;
float getDistanceTo(const Vector2d &point) const;
Vector3d toVector3d() const;
// private:
float _x;
float _y;
};
inline Vector2d operator-(const Vector2d& v1, const Vector2d& v2) {
Vector2d result(v1._x - v2._x, v1._y - v2._y);
return result;
}
inline Vector2d operator+(const Vector2d &v1, const Vector2d &v2) {
Vector2d result(v1._x + v2._x, v1._y + v2._y);
return result;
}
inline Vector2d operator*(const Vector2d &v1, float factor) {
Vector2d result(v1._x * factor, v1._y * factor);
return result;
}
inline Vector2d operator/(const Vector2d &v1, float factor) {
Vector2d result(v1._x / factor, v1._y / factor);
return result;
}
inline Vector2d operator-(const Vector2d &v) {
return Vector2d(-v._x, -v._y);
}
}
#endif