Commits

Christian Fischer committed 54c5970

extended dimension and rectangle classes, added according unit tests

Comments (0)

Files changed (6)

src/base/wiesel/geometry.cpp

 using namespace wiesel;
 
 
-dimension::dimension() 
+dimension::dimension()
 : width(0.0f), height(0.0f) {
 	return;
 }
 
-dimension::dimension(float width, float height) 
+dimension::dimension(float width, float height)
 : width(width), height(height) {
 	return;
 }
 
-dimension::dimension(const dimension &other) 
+dimension::dimension(const dimension &other)
 : width(other.width), height(other.height) {
 	return;
 }
 }
 
 
+const dimension& dimension::operator=(const dimension &other) {
+	this->width  = other.width;
+	this->height = other.height;
+	return *this;
+}
+
+
+bool dimension::operator==(const dimension &other) const {
+	return
+			this->width  == other.width
+		&&	this->height == other.height
+	;
+}
+
+bool dimension::operator!=(const dimension &other) const {
+	return
+			this->width  != other.width
+		||	this->height != other.height
+	;
+}
+
+
 
 
 
 }
 
 
+bool rectangle::isNormalized() const {
+	return
+			this->size.width  >= 0
+		&&	this->size.height >= 0
+	;
+}
+
+
 float rectangle::getMinX() const {
 	return position.x;
 }
 }
 
 
+const rectangle& rectangle::operator=(const rectangle &other) {
+	this->position = other.position;
+	this->size     = other.size;
+	return *this;
+}
+
+
+bool rectangle::operator==(const rectangle &other) const {
+	return
+			this->position == other.position
+		&&	this->size     == other.size
+	;
+}
+
+bool rectangle::operator!=(const rectangle &other) const {
+	return
+			this->position != other.position
+		||	this->size     != other.size
+	;
+}
+
+
 bool rectangle::contains(float x, float y) const {
 	if (
 			x >= getMinX()
 
 bool rectangle::contains(const rectangle& r) const {
 	if (
-			r.getMinX() < this->getMaxX()
-		&&	r.getMinY() < this->getMaxY()
-		&&	r.getMaxX() > this->getMinX()
-		&&	r.getMaxY() > this->getMinY()
+			r.getMinX() < this->getMinX()
+		||	r.getMinY() < this->getMinY()
+		||	r.getMaxX() > this->getMaxX()
+		||	r.getMaxY() > this->getMaxY()
 	) {
-		return true;
+		return false;
 	}
 
-	return false;
+	return true;
 }
 
 

src/base/wiesel/geometry.h

 	public:
 		/// constructs a new dimension object with zero width and height
 		dimension();
-		
+
 		/// constructs a new dimension object with width and height
 		dimension(float width, float height);
-		
+
 		/// copy-constructor
 		dimension(const dimension &other);
-		
+
 	// operations
 	public:
 		/// get the smallest dimension, either width or height.
 
 		/// scale width and height with factor \c s
 		void scale(float s);
-		
+
 		/// scale width and height with separate factors
 		void scale(float sx, float sy);
 
+	// operators
+	public:
+		const dimension& operator=(const dimension &other);
+
+		bool operator ==(const dimension &other) const;
+		bool operator !=(const dimension &other) const;
+
 	// members
 	public:
 		float width;
 		float height;
 	};
-	
-	
+
+
 	inline dimension operator*(const dimension &dim, float s) {
 		return dimension(dim.width * s, dim.height * s);
 	}
-	
+
 	inline dimension& operator*=(dimension &dim, float s) {
 		dim.width  *= s;
 		dim.height *= s;
 		rectangle(float with, float height);
 
 		/// creates a new rectangle with a given size and zero position.
-		rectangle(const dimension &size);
+		explicit rectangle(const dimension &size);
 
 		/// deconstructor
 		~rectangle();
 		/// get the normalized version of this rectangle. Keeps the original rectangle unchanged.
 		rectangle normalized() const;
 
+		/// checks, if this rectangle is normalized.
+		bool isNormalized() const;
+
 	// getters
 	public:
 		/// get the smallest x-position
 		/// get the centre y-position
 		float getCenterY() const;
 
+	// operators
+	public:
+		const rectangle& operator=(const rectangle &other);
+
+		bool operator ==(const rectangle &other) const;
+		bool operator !=(const rectangle &other) const;
+
 	// tests
 	public:
 		/// tests, if this rectangle contains a specific point.

tests/base/dimension.cpp

+/**
+ * Copyright (C) 2012
+ * Christian Fischer
+ *
+ * https://bitbucket.org/baldur/wiesel/
+ *
+ * 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 3 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
+ */
+#include "gtest/gtest.h"
+#include "test_utils.h"
+
+#include <wiesel/geometry.h>
+
+
+using namespace wiesel;
+
+
+
+// some predefined dimension objects used to testing
+static const float Aw = 17;
+static const float Ah = 39;
+static const dimension A    ( Aw,  Ah);
+
+
+
+/**
+ * Checks if the dimension class has the exact size we expect -> 2 * sizeof(float)
+ * When this test fails, there's maybe some hidden data, like a unwanted vtable.
+ */
+TEST(Dimension, Sizeof) {
+	EXPECT_EQ((2 * sizeof(float)), sizeof(dimension));
+}
+
+
+/**
+ * Checks the comparision operators
+ */
+TEST(Dimension, Comparision) {
+	dimension dim1(0, 0);
+	dimension dim2(0, 0);
+
+	EXPECT_TRUE (dim1 == dim2);
+	EXPECT_FALSE(dim1 != dim2);
+	EXPECT_DIMENSION_EQ(dim1, dim2);
+	EXPECT_DIMENSION_EQ(dimension(17, 39), dimension(17, 39));
+
+	// various tests, only one component different
+	EXPECT_NE(dimension(7, 39), dimension(17, 39));
+	EXPECT_NE(dimension(17, 9), dimension(17, 39));
+
+	// various tests, only one component different
+	EXPECT_FALSE(dimension( 7, 39) == dimension(17, 39));
+	EXPECT_FALSE(dimension(17,  9) == dimension(17, 39));
+	EXPECT_FALSE(dimension(17, 39) == dimension( 7, 39));
+	EXPECT_FALSE(dimension(17, 39) == dimension(17,  9));
+
+	EXPECT_TRUE (dimension( 7, 39) != dimension(17, 39));
+	EXPECT_TRUE (dimension(17,  9) != dimension(17, 39));
+	EXPECT_TRUE (dimension(17, 39) != dimension( 7, 39));
+	EXPECT_TRUE (dimension(17, 39) != dimension(17,  9));
+}
+
+
+/**
+ * Test creating a new dimension.
+ */
+TEST(Dimension, Create) {
+	dimension dim(Aw, Ah);
+	EXPECT_EQ(Aw, dim.width);
+	EXPECT_EQ(Ah, dim.height);
+}
+
+
+/**
+ * Checks copying of a dimension using copy constructor.
+ */
+TEST(Dimension, CopyConstructor) {
+	// prepare first dimension
+	dimension dim1(Aw, Ah);
+
+	// create second dimension as a copy of the first one
+	dimension dim2(dim1);
+
+	// both dimensions should be equal
+	EXPECT_DIMENSION_EQ(dim1, dim2);
+	EXPECT_EQ(dim1, dim2);
+}
+
+
+/**
+ * Checks assigning a dimension object to another.
+ */
+TEST(Dimension, Assign) {
+	// prepare first dimension
+	dimension dim1(10, 20);
+
+	// create second dimension
+	dimension dim2;
+
+	// v1 and v2 should not be eqal
+	EXPECT_DIMENSION_NE(dim1, dim2);
+
+	// assign the first dimension to the second one
+	dim2 = dim1;
+
+	// and both should be equal
+	EXPECT_DIMENSION_EQ(dim1, dim2);
+	EXPECT_EQ(dim1, dim2);
+}
+
+
+/**
+ * Test Properties of a dimension object.
+ */
+TEST(Dimension, Properties) {
+	dimension dim1(480, 320);
+	EXPECT_EQ(320,   dim1.getMin());
+	EXPECT_EQ(480,   dim1.getMax());
+	EXPECT_EQ(400,   dim1.getAverage());
+	EXPECT_FLOAT_EQ(1.5,   dim1.getRatio());
+
+	dimension dim2(320, 480);
+	EXPECT_EQ(320,   dim2.getMin());
+	EXPECT_EQ(480,   dim2.getMax());
+	EXPECT_EQ(400,   dim2.getAverage());
+	EXPECT_FLOAT_EQ(1/1.5, dim2.getRatio());
+}
+
+
+/**
+ * Test scale function.
+ */
+TEST(Dimension, Scale) {
+	dimension dim1(100, 100);
+	dim1.scale(5);
+	EXPECT_DIMENSION_EQ(dimension(500, 500), dim1);
+
+	dimension dim2(100, 100);
+	dim2.scale(1, 5);
+	EXPECT_DIMENSION_EQ(dimension(100, 500), dim2);
+
+	dimension dim3(100, 100);
+	dim3.scale(5, 1);
+	EXPECT_DIMENSION_EQ(dimension(500, 100), dim3);
+}
+
+
+
+
+
+/**
+ * Operators
+ */
+TEST(Dimension, OpMul) {
+	EXPECT_DIMENSION_EQ(dimension(34, 78), (A * 2));
+}
+
+TEST(Dimension, OpMulNegative) {
+	EXPECT_DIMENSION_EQ(dimension(-34, -78), (A * -2));
+}
+
+TEST(Dimension, OpMulAssign) {
+	dimension dim = A;
+
+	EXPECT_DIMENSION_EQ(dimension(34, 78), dim *= 2);		// return value should contain the correct result
+	EXPECT_DIMENSION_EQ(dimension(34, 78), dim);			// dim should contain the correct result after processing
+}
+
+TEST(Dimension, OpMulAssignNegative) {
+	dimension dim = A;
+
+	EXPECT_DIMENSION_EQ(dimension(-34, -78), dim *= -2);	// return value should contain the correct result
+	EXPECT_DIMENSION_EQ(dimension(-34, -78), dim);			// v should contain the correct result after processing
+}
+

tests/base/rectangle.cpp

+/**
+ * Copyright (C) 2012
+ * Christian Fischer
+ *
+ * https://bitbucket.org/baldur/wiesel/
+ *
+ * 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 3 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
+ */
+#include "gtest/gtest.h"
+#include "test_utils.h"
+
+#include <wiesel/geometry.h>
+
+
+using namespace wiesel;
+
+
+
+// some predefined rectangle objects used to testing
+static const float Ax =  -8;
+static const float Ay = -13;
+static const float Aw =  17;
+static const float Ah =  39;
+static const rectangle A    ( Ax,  Ay,  Aw,  Ah);
+
+
+
+/**
+ * Checks if the rectangle class has the exact size we expect -> 4 * sizeof(float)
+ * When this test fails, there's maybe some hidden data, like a unwanted vtable.
+ */
+TEST(Rectangle, Sizeof) {
+	EXPECT_EQ((4 * sizeof(float)), sizeof(rectangle));
+}
+
+
+/**
+ * Checks the comparision operators
+ */
+TEST(Rectangle, Comparision) {
+	rectangle r1(0, 0, 1, 1);
+	rectangle r2(0, 0, 1, 1);
+
+	EXPECT_TRUE (r1 == r2);
+	EXPECT_FALSE(r1 != r2);
+	EXPECT_RECT_EQ(r1, r2);
+	EXPECT_RECT_EQ(rectangle(10, 20, 30, 40), rectangle(10, 20, 30, 40));
+
+	// various tests, only one component different
+	EXPECT_NE(rectangle( 0, -13, 17, 39), rectangle(-8, -13, 17, 39));
+	EXPECT_NE(rectangle(-8,   0, 17, 39), rectangle(-8, -13, 17, 39));
+	EXPECT_NE(rectangle(-8, -13,  7, 39), rectangle(-8, -13, 17, 39));
+	EXPECT_NE(rectangle(-8, -13, 17,  9), rectangle(-8, -13, 17, 39));
+
+	// various tests, only one component different
+	EXPECT_FALSE(rectangle( 0, -13, 17, 39) == rectangle(-8, -13, 17, 39));
+	EXPECT_FALSE(rectangle(-8,   0, 17, 39) == rectangle(-8, -13, 17, 39));
+	EXPECT_FALSE(rectangle(-8, -13,  7, 39) == rectangle(-8, -13, 17, 39));
+	EXPECT_FALSE(rectangle(-8, -13, 17,  9) == rectangle(-8, -13, 17, 39));
+	EXPECT_FALSE(rectangle(-8, -13, 17, 39) == rectangle( 0, -13, 17, 39));
+	EXPECT_FALSE(rectangle(-8, -13, 17, 39) == rectangle(-8,   0, 17, 39));
+	EXPECT_FALSE(rectangle(-8, -13, 17, 39) == rectangle(-8, -13,  7, 39));
+	EXPECT_FALSE(rectangle(-8, -13, 17, 39) == rectangle(-8, -13, 17,  9));
+
+	EXPECT_TRUE (rectangle( 0, -13, 17, 39) != rectangle(-8, -13, 17, 39));
+	EXPECT_TRUE (rectangle(-8,   0, 17, 39) != rectangle(-8, -13, 17, 39));
+	EXPECT_TRUE (rectangle(-8, -13,  7, 39) != rectangle(-8, -13, 17, 39));
+	EXPECT_TRUE (rectangle(-8, -13, 17,  9) != rectangle(-8, -13, 17, 39));
+	EXPECT_TRUE (rectangle(-8, -13, 17, 39) != rectangle( 0, -13, 17, 39));
+	EXPECT_TRUE (rectangle(-8, -13, 17, 39) != rectangle(-8,   0, 17, 39));
+	EXPECT_TRUE (rectangle(-8, -13, 17, 39) != rectangle(-8, -13,  7, 39));
+	EXPECT_TRUE (rectangle(-8, -13, 17, 39) != rectangle(-8, -13, 17,  9));
+}
+
+
+/**
+ * Test creating a new rectangle.
+ */
+TEST(Rectangle, Create) {
+	rectangle r1(Ax, Ay, Aw, Ah);
+	EXPECT_EQ(Ax, r1.position.x);
+	EXPECT_EQ(Ay, r1.position.y);
+	EXPECT_EQ(Aw, r1.size.width);
+	EXPECT_EQ(Ah, r1.size.height);
+
+	rectangle r2(vector2d(Ax, Ay), dimension(Aw, Ah));
+	EXPECT_EQ(Ax, r2.position.x);
+	EXPECT_EQ(Ay, r2.position.y);
+	EXPECT_EQ(Aw, r2.size.width);
+	EXPECT_EQ(Ah, r2.size.height);
+
+	EXPECT_EQ(r1, r2);
+}
+
+
+/**
+ * Checks copying of a rectangle using copy constructor.
+ */
+TEST(Rectangle, CopyConstructor) {
+	// prepare first rectangle
+	rectangle r1(Ax, Ay, Aw, Ah);
+
+	// create second rectangle as a copy of the first one
+	rectangle r2(r1);
+
+	// both rectangles should be equal
+	EXPECT_RECT_EQ(r1, r2);
+	EXPECT_EQ(r1, r2);
+}
+
+
+/**
+ * Checks assigning a rectangle to another.
+ */
+TEST(Rectangle, Assign) {
+	// prepare first rectangle
+	rectangle r1(Ax, Ay, Aw, Ah);
+
+	// create second rectangle
+	rectangle r2;
+
+	// v1 and v2 should not be eqal
+	EXPECT_RECT_NE(r1, r2);
+
+	// assign the first rectangle to the second one
+	r2 = r1;
+
+	// and both should be equal
+	EXPECT_RECT_EQ(r1, r2);
+	EXPECT_EQ(r1, r2);
+}
+
+
+/**
+ * Test rectangle properties
+ */
+TEST(Rectangle, Properties) {
+	EXPECT_VECTOR_EQ   (vector2d(-8, -13), A.position);
+	EXPECT_DIMENSION_EQ(dimension(17, 39), A.size);
+
+	EXPECT_EQ( -8,   A.getMinX());
+	EXPECT_EQ(  9,   A.getMaxX());
+	EXPECT_EQ(  0.5, A.getCenterX());
+	EXPECT_EQ(-13,   A.getMinY());
+	EXPECT_EQ( 26,   A.getMaxY());
+	EXPECT_EQ(  6.5, A.getCenterY());
+}
+
+
+/**
+ * Test normalization of rectangles.
+ */
+TEST(Rectangle, Normalization) {
+	rectangle rect(25, 35, -10, -15);
+
+	// this rect should not be normalized
+	EXPECT_FALSE(rect.isNormalized());
+
+	// try to get the normalized version of this rect
+	rectangle n_rect = rect.normalized();
+
+	EXPECT_TRUE(n_rect.isNormalized());
+	EXPECT_EQ(rectangle(15, 20, 10, 15), n_rect);
+
+	// the original should still be not normalized
+	EXPECT_FALSE(rect.isNormalized());
+
+	// now we try to normalize the original
+	rect.normalize();
+
+	EXPECT_TRUE(rect.isNormalized());
+
+	// this rect should now be equal to the previously normalized version
+	EXPECT_EQ(n_rect, rect);
+}
+
+
+/**
+ * Test if a rectangle contains various points.
+ */
+TEST(Rectangle, ContainsPoint) {
+	rectangle rect(-2, -1, 3, 3);
+
+	// all these points should be within the rect
+	EXPECT_TRUE(rect.contains( 0,  0));
+	EXPECT_TRUE(rect.contains(-2, -1));
+	EXPECT_TRUE(rect.contains( 1,  2));
+	EXPECT_TRUE(rect.contains( 1, -1));
+	EXPECT_TRUE(rect.contains(-2,  2));
+
+	// these points should NOT be within the rect
+	EXPECT_FALSE(rect.contains(-3, -1));
+	EXPECT_FALSE(rect.contains(-2, -2));
+	EXPECT_FALSE(rect.contains( 2,  2));
+	EXPECT_FALSE(rect.contains( 1,  3));
+	EXPECT_FALSE(rect.contains( 2, -1));
+	EXPECT_FALSE(rect.contains( 1, -2));
+	EXPECT_FALSE(rect.contains(-3,  2));
+	EXPECT_FALSE(rect.contains(-2,  3));
+}
+
+
+/**
+ * Test if a rectangle contains various points.
+ */
+TEST(Rectangle, ContainsVector) {
+	rectangle rect(-2, -1, 3, 3);
+
+	// all these points should be within the rect
+	EXPECT_TRUE (rect.contains(vector2d( 0,  0)));
+	EXPECT_TRUE (rect.contains(vector2d(-2, -1)));
+	EXPECT_TRUE (rect.contains(vector2d( 1,  2)));
+	EXPECT_TRUE (rect.contains(vector2d( 1, -1)));
+	EXPECT_TRUE (rect.contains(vector2d(-2,  2)));
+
+	// these points should NOT be within the rect
+	EXPECT_FALSE(rect.contains(vector2d(-3, -1)));
+	EXPECT_FALSE(rect.contains(vector2d(-2, -2)));
+	EXPECT_FALSE(rect.contains(vector2d( 2,  2)));
+	EXPECT_FALSE(rect.contains(vector2d( 1,  3)));
+	EXPECT_FALSE(rect.contains(vector2d( 2, -1)));
+	EXPECT_FALSE(rect.contains(vector2d( 1, -2)));
+	EXPECT_FALSE(rect.contains(vector2d(-3,  2)));
+	EXPECT_FALSE(rect.contains(vector2d(-2,  3)));
+}
+
+
+/**
+ * Test if a rectangle contains another rectangle.
+ */
+TEST(Rectangle, ContainsRect) {
+	rectangle rect(-2, -1, 3, 3);
+
+	// rect contains itself
+	EXPECT_TRUE (rect.contains(rect));
+
+	// rect contains partial rectangles
+	EXPECT_TRUE (rect.contains(rectangle(-2, -1, 1, 1)));
+	EXPECT_TRUE (rect.contains(rectangle( 0,  1, 1, 1)));
+
+	// rect does not contain intersecting rectangles
+	EXPECT_FALSE(rect.contains(rectangle(-3, -1, 2, 2)));
+	EXPECT_FALSE(rect.contains(rectangle(-2, -2, 2, 2)));
+	EXPECT_FALSE(rect.contains(rectangle( 0,  1, 2, 2)));
+	EXPECT_FALSE(rect.contains(rectangle(-3,  1, 2, 2)));
+	EXPECT_FALSE(rect.contains(rectangle( 0, -2, 2, 2)));
+
+	// rect does not contain rectangles completely outside
+	EXPECT_FALSE(rect.contains(rectangle(-9, -9, 3, 3)));
+	EXPECT_FALSE(rect.contains(rectangle( 9,  9, 3, 3)));
+	EXPECT_FALSE(rect.contains(rectangle( 9, -9, 3, 3)));
+	EXPECT_FALSE(rect.contains(rectangle(-9,  9, 3, 3)));
+}
+
+
+/**
+ * Test if two rectangles intersects each other.
+ */
+TEST(Rectangle, Intersects) {
+	rectangle rect(-2, -1, 3, 3);
+
+	// rect intersects itself
+	EXPECT_TRUE (rect.intersects(rect));
+
+	// rect intersects partial rectangles
+	EXPECT_TRUE (rect.intersects(rectangle(-2, -1, 1, 1)));
+	EXPECT_TRUE (rect.intersects(rectangle( 0,  1, 1, 1)));
+
+	// rect intersects partial intersections
+	EXPECT_TRUE (rect.intersects(rectangle(-3, -1, 2, 2)));
+	EXPECT_TRUE (rect.intersects(rectangle(-2, -2, 2, 2)));
+	EXPECT_TRUE (rect.intersects(rectangle( 0,  1, 2, 2)));
+	EXPECT_TRUE (rect.intersects(rectangle(-3,  1, 2, 2)));
+	EXPECT_TRUE (rect.intersects(rectangle( 0, -2, 2, 2)));
+
+	// rect does not intersect rectangles completely outside
+	EXPECT_FALSE(rect.intersects(rectangle(-9, -9, 3, 3)));
+	EXPECT_FALSE(rect.intersects(rectangle( 9,  9, 3, 3)));
+	EXPECT_FALSE(rect.intersects(rectangle( 9, -9, 3, 3)));
+	EXPECT_FALSE(rect.intersects(rectangle(-9,  9, 3, 3)));
+}
+

tests/base/test_utils.cpp

 
 namespace wiesel {
 
+	bool compareDimensionUsingEpsilon(
+							const dimension &expected,
+							const dimension &actual,
+							float epsilon
+	) {
+		return
+				compareFloatsUsingEpsilon(expected.width,  actual.width,  epsilon)
+			&&	compareFloatsUsingEpsilon(expected.height, actual.height, epsilon)
+		;
+	}
+
+
+
+
+	bool compareRectangleUsingEpsilon(
+							const rectangle &expected,
+							const rectangle &actual,
+							float epsilon
+	) {
+		return
+				compareVectorUsingEpsilon   (expected.position, actual.position, epsilon)
+			&&	compareDimensionUsingEpsilon(expected.size,     actual.size,     epsilon)
+		;
+	}
+
+
+
+
 	bool compareVectorUsingEpsilon(
 							const vector2d &expected,
 							const vector2d &actual,
 
 
 
+	::testing::AssertionResult compareDimensionUsingEpsilon(
+							const char* expected_expression,
+							const char* actual_expression,
+							const dimension &expected,
+							const dimension &actual,
+							float epsilon
+	) {
+		if (compareDimensionUsingEpsilon(expected, actual) == false) {
+			return ::testing::internal::EqFailure(
+								expected_expression,
+								actual_expression,
+								::testing::internal::FormatForComparisonFailureMessage(expected, actual),
+								::testing::internal::FormatForComparisonFailureMessage(actual, expected),
+								false
+			);
+		}
+
+		return ::testing::AssertionSuccess();
+	}
+
+
+	::testing::AssertionResult compareRectangleUsingEpsilon(
+							const char* expected_expression,
+							const char* actual_expression,
+							const rectangle &expected,
+							const rectangle &actual,
+							float epsilon
+	) {
+		if (compareRectangleUsingEpsilon(expected, actual) == false) {
+			return ::testing::internal::EqFailure(
+								expected_expression,
+								actual_expression,
+								::testing::internal::FormatForComparisonFailureMessage(expected, actual),
+								::testing::internal::FormatForComparisonFailureMessage(actual, expected),
+								false
+			);
+		}
+
+		return ::testing::AssertionSuccess();
+	}
+
+
 	::testing::AssertionResult compareVectorUsingEpsilon(
 							const char* expected_expression,
 							const char* actual_expression,

tests/base/test_utils.h

 #include <wiesel/math/matrix.h>
 #include <wiesel/math/vector2d.h>
 #include <wiesel/math/vector3d.h>
+#include <wiesel/geometry.h>
 
 #include <gtest/gtest.h>
 #include <cmath>
 
 
 // create googletest-like macros
+#define EXPECT_DIMENSION_EQ(expected, actual)	EXPECT_PRED_FORMAT2(compareDimensionUsingEpsilon, expected, actual)
+#define EXPECT_DIMENSION_NE(expected, actual)	EXPECT_FALSE(compareDimensionUsingEpsilon(expected, actual))
+#define EXPECT_RECT_EQ(expected, actual)		EXPECT_PRED_FORMAT2(compareRectangleUsingEpsilon, expected, actual)
+#define EXPECT_RECT_NE(expected, actual)		EXPECT_FALSE(compareRectangleUsingEpsilon(expected, actual))
+
 #define EXPECT_VECTOR_EQ(expected, actual)		EXPECT_PRED_FORMAT2(compareVectorUsingEpsilon, expected, actual)
 #define EXPECT_VECTOR_NE(expected, actual)		EXPECT_FALSE(compareVectorUsingEpsilon(expected, actual))
 #define EXPECT_MATRIX_EQ(expected, actual)		EXPECT_PRED_FORMAT2(compareMatrixUsingEpsilon, expected, actual)
 #define EXPECT_MATRIX_NE(expected, actual)		EXPECT_FALSE(compareMatrixUsingEpsilon(expected, actual))
 #define EXPECT_MATRIX_IDENTITY(actual)			EXPECT_MATRIX_EQ(::wiesel::matrix4x4::identity, actual)
-#define EXPECT_MATRIX_NOT_IDENTITY(actual)		EXPECT_MATRIX_NE(::wiesel::matrix4x4::identity, actual)
+#define EXPECT_MATRIX_NOT_IDENTITY(actual)		EXPECT_MATRIX_NE(::wiesel::matrix4x4::identity, actual)
+
 
 
 namespace wiesel {
 
 
 	/**
-	 * @brief GoogleTest helper function for comparing two vectors using an epsilon value.
+	 * @brief helper function for comparing two dimensions using an epsilon value.
+	 */
+	bool compareDimensionUsingEpsilon(
+							const ::wiesel::dimension &expected,
+							const ::wiesel::dimension &actual,
+							float epsilon=UNITTEST_EPSILON
+	);
+
+
+	/**
+	 * @brief helper function for comparing two rectangles using an epsilon value.
+	 */
+	bool compareRectangleUsingEpsilon(
+							const ::wiesel::rectangle &expected,
+							const ::wiesel::rectangle &actual,
+							float epsilon=UNITTEST_EPSILON
+	);
+
+
+	/**
+	 * @brief helper function for comparing two vectors using an epsilon value.
 	 */
 	bool compareVectorUsingEpsilon(
 							const ::wiesel::vector2d &expected,
 
 
 	/**
-	 * @brief GoogleTest helper function for comparing two vectors using an epsilon value.
+	 * @brief helper function for comparing two vectors using an epsilon value.
 	 */
 	bool compareVectorUsingEpsilon(
 							const ::wiesel::vector3d &expected,
 
 
 	/**
-	 * @brief GoogleTest helper function for comparing two matrices using an epsilon value.
+	 * @brief helper function for comparing two matrices using an epsilon value.
 	 */
 	bool compareMatrixUsingEpsilon(
 							const ::wiesel::matrix4x4 &expected,
 
 
 	/**
+	 * @brief GoogleTest helper function for comparing two dimensions.
+	 */
+	::testing::AssertionResult compareDimensionUsingEpsilon(
+							const char* expected_expression,
+							const char* actual_expression,
+							const ::wiesel::dimension &expected,
+							const ::wiesel::dimension &actual,
+							float epsilon=UNITTEST_EPSILON
+	);
+
+
+	/**
+	 * @brief GoogleTest helper function for comparing two rectangles.
+	 */
+	::testing::AssertionResult compareRectangleUsingEpsilon(
+							const char* expected_expression,
+							const char* actual_expression,
+							const ::wiesel::rectangle &expected,
+							const ::wiesel::rectangle &actual,
+							float epsilon=UNITTEST_EPSILON
+	);
+
+
+	/**
 	 * @brief GoogleTest helper function for comparing two vectors.
 	 */
 	::testing::AssertionResult compareVectorUsingEpsilon(