ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

rect2d.cpp

Go to the documentation of this file.
00001 /* ResidualVM - A 3D game interpreter
00002  *
00003  * ResidualVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "common/scummsys.h"
00024 #include "common/textconsole.h"
00025 
00026 #include "math/rect2d.h"
00027 
00028 namespace Math {
00029 
00030 Rect2d::Rect2d() {
00031 
00032 }
00033 
00034 Rect2d::Rect2d(const Vector2d &topLeft, const Vector2d &bottomRight) {
00035     float left = (topLeft.getX() <= bottomRight.getX() ? topLeft.getX() : bottomRight.getX());
00036     float right = (topLeft.getX() <= bottomRight.getX() ? bottomRight.getX() : topLeft.getX());
00037     float top = (topLeft.getY() <= bottomRight.getY() ? topLeft.getY() : bottomRight.getY());
00038     float bottom = (topLeft.getY() <= bottomRight.getY() ? bottomRight.getY() : topLeft.getY());
00039 
00040     _topLeft = Vector2d(left, top);
00041     _topRight = Vector2d(right, top);
00042     _bottomLeft = Vector2d(left, bottom);
00043     _bottomRight = Vector2d(right, bottom);
00044 }
00045 
00046 Rect2d::Rect2d(const Vector2d &topLeft, const Vector2d &topRight,
00047                const Vector2d &bottomLeft, const Vector2d &bottomRight) :
00048     _topLeft(topLeft), _topRight(topRight),
00049     _bottomLeft(bottomLeft), _bottomRight(bottomRight) {
00050 
00051 }
00052 
00053 void Rect2d::rotateAround(const Vector2d &point, const Angle &angle) {
00054     _topLeft.rotateAround(point, angle);
00055     _topRight.rotateAround(point, angle);
00056     _bottomLeft.rotateAround(point, angle);
00057     _bottomRight.rotateAround(point, angle);
00058 }
00059 
00060 void Rect2d::rotateAroundCenter(const Angle &angle) {
00061     Vector2d center = getCenter();
00062     rotateAround(center, angle);
00063 }
00064 
00065 void Rect2d::moveCenterTo(const Vector2d &pos) {
00066     Vector2d vec(pos - getCenter());
00067     translate(vec);
00068 }
00069 
00070 void Rect2d::scale(float amount) {
00071     Vector2d c = getCenter();
00072     moveCenterTo(Vector2d(0, 0));
00073 
00074     _topLeft *= amount;
00075     _topRight *= amount;
00076     _bottomLeft *= amount;
00077     _bottomRight *= amount;
00078 
00079     moveCenterTo(c);
00080 }
00081 
00082 void Rect2d::translate(const Vector2d &vec) {
00083     _topLeft += vec;
00084     _topRight += vec;
00085     _bottomLeft += vec;
00086     _bottomRight += vec;
00087 }
00088 
00089 bool Rect2d::intersectsRect(const Rect2d &rect) const {
00090     // TODO: implement this;
00091     error("Rect2d::intersectsRect not implemented");
00092     return false;
00093 }
00094 
00095 bool Rect2d::intersectsCircle(const Vector2d &center, float radius) const {
00096     Vector2d c = getCenter();
00097     float w = getWidth();
00098     float h = getHeight();
00099 
00100     Math::Angle angle = (_topRight - _topLeft).getAngle();
00101 
00102     if (angle == 0) {
00103         Vector2d circleDistance(fabs(center.getX() - c.getX()), fabs(center.getY() - c.getY()));
00104 
00105         if (circleDistance.getX() > (w / 2.f + radius)) {
00106             return false;
00107         }
00108         if (circleDistance.getY() > (h / 2.f + radius)) {
00109             return false;
00110         }
00111 
00112         if (circleDistance.getX() <= (w / 2.f)) {
00113             return true;
00114         }
00115         if (circleDistance.getY() <= (h / 2.f)) {
00116             return true;
00117         }
00118 
00119         float cornerDistance_sq = pow(circleDistance.getX() - w / 2.f, 2.f) +
00120                                 pow(circleDistance.getY() - h / 2.f, 2.f);
00121 
00122         return (cornerDistance_sq <= radius * radius);
00123     } else { //The rectangle was rotated
00124         Rect2d r(_topLeft, _topRight, _bottomLeft, _bottomRight);
00125         r.rotateAroundCenter(-angle);
00126         Vector2d circle(center);
00127         circle.rotateAround(r.getCenter(), -angle);
00128         return r.intersectsCircle(circle, radius);
00129     }
00130 }
00131 
00132 inline bool le(float a, float b) {
00133     return (a < b || (fabsf(a - b) < 0.0001f));
00134 }
00135 
00136 inline bool ge(float a, float b) {
00137     return (a > b || (fabsf(a - b) < 0.0001f));
00138 }
00139 
00140 bool Rect2d::containsPoint(const Vector2d &point) const {
00141     return ge(point.getX(), _topLeft.getX()) && le(point.getX(), _bottomRight.getX()) &&
00142            ge(point.getY(), _topLeft.getY()) && le(point.getY(), _bottomRight.getY());
00143 }
00144 
00145 Vector2d Rect2d::getCenter() const {
00146     Vector2d sum = _topLeft + _topRight + _bottomLeft + _bottomRight;
00147     sum /= 4;
00148 
00149     return sum;
00150 }
00151 
00152 Vector2d Rect2d::getTopLeft() const {
00153     return _topLeft;
00154 }
00155 
00156 Vector2d Rect2d::getTopRight() const {
00157     return _topRight;
00158 }
00159 
00160 Vector2d Rect2d::getBottomLeft() const {
00161     return _bottomLeft;
00162 }
00163 
00164 Vector2d Rect2d::getBottomRight() const {
00165     return _bottomRight;
00166 }
00167 
00168 float Rect2d::getWidth() const {
00169     float x = _topRight.getX() - _topLeft.getX();
00170     float y = _topRight.getY() - _topLeft.getY();
00171 
00172     return sqrt(x * x + y * y);
00173 }
00174 
00175 float Rect2d::getHeight() const {
00176     float x = _bottomLeft.getX() - _topLeft.getX();
00177     float y = _bottomLeft.getY() - _topLeft.getY();
00178 
00179     return sqrt(x * x + y * y);
00180 }
00181 
00182 Vector2d Rect2d::getIntersection(const Vector2d &start, const Vector2d &dir, Segment2d *edge) const {
00183     float w = getWidth();
00184     float h = getHeight();
00185     float d = sqrt(w * w + h * h);
00186 
00187     Segment2d line(start, start + dir.getNormalized() * 2*d);
00188     Vector2d intersection;
00189 
00190     Segment2d l(_topLeft, _topRight);
00191     if (line.intersectsSegment(l, &intersection)) {
00192         if (edge) {
00193             *edge = l;
00194         }
00195         return intersection;
00196     }
00197     l = Segment2d(_topRight, _bottomRight);
00198     if (line.intersectsSegment(l, &intersection)) {
00199         if (edge) {
00200             *edge = l;
00201         }
00202         return intersection;
00203     }
00204     l = Segment2d(_bottomRight, _bottomLeft);
00205     if (line.intersectsSegment(l, &intersection)) {
00206         if (edge) {
00207             *edge = l;
00208         }
00209         return intersection;
00210     }
00211     l = Segment2d(_bottomLeft, _topLeft);
00212     if (line.intersectsSegment(l, &intersection)) {
00213         if (edge) {
00214             *edge = l;
00215         }
00216         return intersection;
00217     }
00218 
00219     return intersection;
00220 
00221 }
00222 
00223 }


Generated on Sat Feb 16 2019 05:01:02 for ResidualVM by doxygen 1.7.1
curved edge   curved edge