cyphesis/tests/ShapeTest.cpp

830 lines
18 KiB
C++
Raw Permalink Normal View History

2011-01-12 18:39:39 +00:00
// Cyphesis Online RPG Server and AI Engine
// Copyright (C) 2011 Alistair Riddoch
//
// This program 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 2 of the License, or
// (at your option) any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2011-02-15 09:30:46 +00:00
#ifdef NDEBUG
#undef NDEBUG
#endif
#ifndef DEBUG
#define DEBUG
#endif
2011-01-12 18:39:39 +00:00
#include "physics/Shape.h"
#include "physics/Course.h"
2011-01-12 18:39:39 +00:00
#include <Atlas/Message/Element.h>
2011-02-21 19:32:30 +00:00
#include <wfmath/axisbox.h>
#include <wfmath/intersect.h>
2012-04-02 09:23:56 +01:00
#include <wfmath/line.h>
2011-02-21 19:32:30 +00:00
#include <wfmath/point.h>
#include <wfmath/polygon.h>
2011-02-21 19:32:30 +00:00
#include <iostream>
2011-01-12 18:39:39 +00:00
#include <cassert>
2011-02-20 21:23:30 +00:00
using Atlas::Message::ListType;
using Atlas::Message::MapType;
2012-04-02 09:03:00 +01:00
using WFMath::AxisBox;
using WFMath::Ball;
2012-04-02 09:23:56 +01:00
using WFMath::Line;
2012-04-02 09:03:00 +01:00
using WFMath::Point;
using WFMath::Polygon;
using WFMath::RotBox;
using WFMath::RotMatrix;
using WFMath::Vector;
2012-04-05 19:36:27 +01:00
void test_conversion(Shape * s)
{
Atlas::Message::MapType data;
s->toAtlas(data);
assert(!data.empty());
assert(data.find("type") != data.end());
assert(data["type"] != "unknown");
Shape * copy = Shape::newFromAtlas(data);
assert(copy != 0);
std::cout << "A: " << *s << std::endl
<< "B: " << *copy << std::endl;
2012-04-05 20:05:25 +01:00
assert(*s == *copy);
2012-04-05 19:36:27 +01:00
}
// FIXME Use a C++11 template typedef once the are supported
template<int dim> class LinearCourse : public Course<dim, WFMath::Line>
{
};
2011-01-12 18:39:39 +00:00
int main()
{
{
2011-02-20 21:23:30 +00:00
MapType m;
2011-01-12 18:39:39 +00:00
Shape * s = Shape::newFromAtlas(m);
2011-01-14 20:44:49 +00:00
assert(s == 0);
2011-01-12 18:39:39 +00:00
}
2011-02-22 21:29:01 +00:00
// The AxisBox is a little different, and is not covered by the
// name constructor
{
2012-04-02 09:03:00 +01:00
Shape * s = new MathShape<AxisBox, 2>(AxisBox<2>());
assert(s != 0);
assert(!s->isValid());
}
{
2012-04-02 09:03:00 +01:00
Shape * s = new MathShape<AxisBox, 2>(AxisBox<2>(Point<2>(0,0),
Point<2>(1,1)));
assert(s != 0);
assert(s->isValid());
}
{
2012-04-02 09:03:00 +01:00
Area * s = new MathShape<AxisBox, 2>(AxisBox<2>(Point<2>(0,0),
Point<2>(1,1)));
assert(s != 0);
assert(s->isValid());
2012-04-02 09:03:00 +01:00
assert(s->intersect(Point<2>(0.5, 0.5)));
assert(!s->intersect(Point<2>(1.5, 0.5)));
assert(!s->intersect(Point<2>(1.5, 1.5)));
assert(!s->intersect(Point<2>(0.5, 1.5)));
assert(!s->intersect(Point<2>(-0.5, 1.5)));
assert(!s->intersect(Point<2>(-0.5, 0.5)));
assert(!s->intersect(Point<2>(-0.5, -0.5)));
assert(!s->intersect(Point<2>(0.5, -0.5)));
assert(!s->intersect(Point<2>(1.5, -0.5)));
}
2011-02-22 21:29:01 +00:00
{
MapType m;
2012-04-02 09:03:00 +01:00
Shape * s = new MathShape<AxisBox, 2>(AxisBox<2>());
2011-02-22 21:29:01 +00:00
s->fromAtlas(m);
assert(s != 0);
2011-02-23 08:15:48 +00:00
assert(!s->isValid());
2011-02-22 21:29:01 +00:00
}
{
2012-04-02 09:03:00 +01:00
Shape * s = new MathShape<AxisBox, 2>(AxisBox<2>());
s->fromAtlas(ListType(2, 1.));
2011-02-22 21:29:01 +00:00
assert(s != 0);
2011-02-23 08:15:48 +00:00
assert(s->isValid());
2011-02-22 21:29:01 +00:00
}
2011-02-22 19:23:24 +00:00
{
2012-04-02 09:03:00 +01:00
Shape * s = new MathShape<AxisBox, 2>(AxisBox<2>());
s->fromAtlas(ListType(2, 1.));
2011-02-22 19:23:24 +00:00
assert(s != 0);
2011-02-23 08:15:48 +00:00
assert(s->isValid());
2011-02-22 19:23:24 +00:00
2011-02-22 21:29:01 +00:00
MapType dest;
s->toAtlas(dest);
2011-02-22 19:23:24 +00:00
}
{
Shape * s = new MathShape<AxisBox, 2>(AxisBox<2>());
s->fromAtlas(std::string("bad_string_value"));
assert(s != 0);
assert(!s->isValid());
}
2011-02-22 19:23:24 +00:00
{
2012-04-02 09:03:00 +01:00
Area * s = new MathShape<AxisBox, 2>(AxisBox<2>());
s->fromAtlas(ListType(2, 1.));
2011-02-22 19:23:24 +00:00
assert(s != 0);
2011-02-23 08:15:48 +00:00
assert(s->isValid());
2011-02-22 19:23:24 +00:00
2012-04-02 09:03:00 +01:00
Point<2> low = s->lowCorner();
Point<2> high = s->highCorner();
2011-02-22 19:23:24 +00:00
assert(low.isValid());
assert(high.isValid());
}
{
2012-04-02 09:03:00 +01:00
Area * s = new MathShape<AxisBox, 2>(AxisBox<2>(Point<2>(0,0),
Point<2>(2,2)));
assert(s != 0);
assert(s->isValid());
2012-04-02 09:03:00 +01:00
Point<2> centre = s->centre();
assert(Equal(centre, Point<2>(1,1)));
}
2012-04-05 19:36:27 +01:00
{
Area * s = new MathShape<AxisBox, 2>(AxisBox<2>(Point<2>(1,1),
Point<2>(2,2)));
assert(s != 0);
assert(s->isValid());
test_conversion(s);
}
// Point
{
Shape * s = new MathShape<Point, 2>();
assert(s != 0);
assert(!s->isValid());
}
{
Shape * s = new MathShape<Point, 2>(Point<2>(1,2));
assert(s != 0);
assert(s->isValid());
}
{
MapType m;
m["pos"] = ListType(2, 2.0);
Shape * s = new MathShape<Point, 2>();
assert(s != 0);
assert(!s->isValid());
s->fromAtlas(m);
assert(s->isValid());
}
{
ListType l(2, 2.0);
Shape * s = new MathShape<Point, 2>();
assert(s != 0);
assert(!s->isValid());
s->fromAtlas(l);
assert(s->isValid());
}
{
ListType l(1, 2.0); // Wrong length
Shape * s = new MathShape<Point, 2>();
assert(s != 0);
assert(!s->isValid());
s->fromAtlas(l);
assert(!s->isValid());
}
{
ListType l(2, "bad_string"); // Wrong type
Shape * s = new MathShape<Point, 2>();
assert(s != 0);
assert(!s->isValid());
s->fromAtlas(l);
assert(!s->isValid());
}
{
Shape * s = new MathShape<Point, 2>(Point<2>(1,2));
assert(s != 0);
assert(s->isValid());
test_conversion(s);
}
{
Form<2> * s = new MathShape<Point, 2>(Point<2>(1,2));
assert(s != 0);
assert(s->isValid());
assert(s->intersect(Point<2>(1, 2)));
assert(!s->intersect(Point<2>(0.75, 0.25)));
}
2011-02-20 21:23:30 +00:00
// The Polygon conversion functions throw if there isn't complete valid
// polygon data
{
2012-04-02 09:03:00 +01:00
Shape * s = new MathShape<Polygon, 2>(Polygon<2>());
assert(s != 0);
assert(s->isValid());
}
{
2012-04-02 09:03:00 +01:00
Polygon<2> p;
p.addCorner(0, Point<2>(1,1));
p.addCorner(0, Point<2>(1,0));
p.addCorner(0, Point<2>(0,0));
2012-04-02 09:23:33 +01:00
Shape * s = new MathShape<Polygon, 2>(p);
assert(s != 0);
assert(s->isValid());
}
{
2012-04-02 09:03:00 +01:00
Polygon<2> p;
p.addCorner(0, Point<2>(1,1));
p.addCorner(0, Point<2>(1,0));
p.addCorner(0, Point<2>(0,0));
// Make sure the underlying Intersect works
2012-04-02 09:03:00 +01:00
assert(Intersect(p, Point<2>(0.75, 0.25), true));
2012-04-02 09:03:00 +01:00
Area * s = new MathShape<Polygon, 2>(p);
assert(s != 0);
assert(s->isValid());
2012-04-02 09:03:00 +01:00
assert(s->intersect(Point<2>(0.75, 0.25)));
assert(!s->intersect(Point<2>(1.5, 0.5)));
assert(!s->intersect(Point<2>(1.5, 1.5)));
assert(!s->intersect(Point<2>(0.5, 1.5)));
assert(!s->intersect(Point<2>(-0.5, 1.5)));
assert(!s->intersect(Point<2>(-0.5, 0.5)));
assert(!s->intersect(Point<2>(-0.5, -0.5)));
assert(!s->intersect(Point<2>(0.5, -0.5)));
assert(!s->intersect(Point<2>(1.5, -0.5)));
}
2012-04-05 20:07:24 +01:00
{
Polygon<2> p;
p.addCorner(0, Point<2>(1,1));
p.addCorner(0, Point<2>(1,0));
p.addCorner(0, Point<2>(0,0));
// Make sure the underlying Intersect works
Area * s = new MathShape<Polygon, 2>(p);
assert(s != 0);
assert(s->isValid());
test_conversion(s);
}
2011-02-20 17:27:29 +00:00
{
2011-02-20 21:23:30 +00:00
MapType m;
2011-02-20 17:27:29 +00:00
m["type"] = "polygon";
Shape * s = Shape::newFromAtlas(m);
2011-02-20 21:23:30 +00:00
assert(s == 0);
}
{
MapType m;
m["type"] = "polygon";
m["points"] = ListType(3, ListType(2, 1.f));
Shape * s = Shape::newFromAtlas(m);
2011-02-20 17:27:29 +00:00
assert(s != 0);
2011-02-23 08:15:48 +00:00
assert(s->isValid());
2011-02-20 17:27:29 +00:00
}
2011-02-22 21:29:01 +00:00
{
MapType m;
m["type"] = "polygon";
m["points"] = ListType(3, ListType(2, 1.f));
Shape * s = Shape::newFromAtlas(m);
assert(s != 0);
2011-02-23 08:15:48 +00:00
assert(s->isValid());
2011-02-22 21:29:01 +00:00
MapType dest;
s->toAtlas(dest);
}
{
MapType m;
m["type"] = "polygon";
ListType points;
points.push_back(ListType(2, -1.));
points.push_back(ListType(2, 1.));
ListType point(1, 1.);
point.push_back(-1.);
points.push_back(point);
m["points"] = points;
Shape * s = Shape::newFromAtlas(m);
assert(s != 0);
2011-02-23 08:15:48 +00:00
assert(s->isValid());
2011-02-21 19:20:33 +00:00
assert(s->area() > 1.9);
assert(s->area() < 2.1);
}
{
MapType m;
m["type"] = "polygon";
ListType points;
points.push_back(ListType(2, -1.));
points.push_back(ListType(2, 1.));
ListType point(1, 1.);
point.push_back(-1.);
points.push_back(point);
m["points"] = points;
Shape * s = Shape::newFromAtlas(m);
assert(s != 0);
2011-02-23 08:15:48 +00:00
assert(s->isValid());
2011-02-21 19:20:33 +00:00
double area = s->area();
s->scale(2);
2011-02-23 08:15:48 +00:00
assert(s->isValid());
2011-02-21 19:20:33 +00:00
assert(area < s->area());
}
2011-02-21 19:32:30 +00:00
{
MapType m;
m["type"] = "polygon";
ListType points;
points.push_back(ListType(2, -1.));
points.push_back(ListType(2, 1.));
ListType point(1, 1.);
point.push_back(-1.);
points.push_back(point);
m["points"] = points;
Shape * s = Shape::newFromAtlas(m);
assert(s != 0);
2011-02-23 08:15:48 +00:00
assert(s->isValid());
2012-04-02 09:03:00 +01:00
AxisBox<2> rect = s->footprint();
2011-02-21 19:32:30 +00:00
std::cout << rect << std::endl;
assert(rect.isValid());
}
2011-02-22 19:23:24 +00:00
{
MapType m;
m["type"] = "polygon";
ListType points;
points.push_back(ListType(2, -1.));
points.push_back(ListType(2, 1.));
ListType point(1, 1.);
point.push_back(-1.);
points.push_back(point);
m["points"] = points;
Shape * s = Shape::newFromAtlas(m);
assert(s != 0);
Area * a = dynamic_cast<Area *>(s);
assert(a != 0);
2012-04-02 09:03:00 +01:00
Point<2> low = a->lowCorner();
Point<2> high = a->highCorner();
2011-02-22 19:23:24 +00:00
assert(low.isValid());
assert(high.isValid());
}
2011-02-20 21:23:30 +00:00
// The Ball conversion functions don't seem to require valid Atlas
// data
{
2012-04-02 09:03:00 +01:00
Shape * s = new MathShape<Ball, 2>(Ball<2>());
assert(s != 0);
assert(!s->isValid());
}
{
2012-04-02 09:03:00 +01:00
Shape * s = new MathShape<Ball, 2>(
Ball<2>(Point<2>(1,1), 23.f));
assert(s != 0);
assert(s->isValid());
}
2011-02-20 17:27:29 +00:00
{
2011-02-20 21:23:30 +00:00
MapType m;
m["type"] = "circle";
2011-02-20 17:27:29 +00:00
Shape * s = Shape::newFromAtlas(m);
assert(s != 0);
2011-02-23 08:15:48 +00:00
assert(!s->isValid());
2011-02-20 17:27:29 +00:00
}
{
MapType m;
m["radius"] = 23.9;
m["position"] = ListType(2, 1.f);
Shape * s = new MathShape<Ball, 2>;
s->fromAtlas(m);
assert(s != 0);
assert(s->isValid());
}
{
MapType m;
m["radius"] = 23.9;
m["position"] = ListType(2, "bad_string"); // bad type here
Shape * s = new MathShape<Ball, 2>;
s->fromAtlas(m);
assert(s != 0);
assert(!s->isValid());
}
{
ListType l(2, 1.f); // Wrong type
Shape * s = new MathShape<Ball, 2>;
s->fromAtlas(l);
assert(s != 0);
assert(!s->isValid());
}
2011-02-22 21:29:01 +00:00
{
MapType m;
m["type"] = "circle";
2011-02-23 08:15:48 +00:00
m["radius"] = 23.9;
m["position"] = ListType(2, 1.f);
Shape * s = Shape::newFromAtlas(m);
assert(s != 0);
assert(s->isValid());
}
{
MapType m;
m["type"] = "circle";
2011-02-23 08:15:48 +00:00
m["radius"] = 23.9;
m["position"] = ListType(2, 1.f);
2011-02-22 21:29:01 +00:00
Shape * s = Shape::newFromAtlas(m);
assert(s != 0);
MapType dest;
s->toAtlas(dest);
}
2011-02-22 19:23:24 +00:00
{
MapType m;
m["type"] = "circle";
2011-02-23 08:15:48 +00:00
m["radius"] = 23.9;
m["position"] = ListType(2, 1.f);
2011-02-22 19:23:24 +00:00
Shape * s = Shape::newFromAtlas(m);
assert(s != 0);
Area * a = dynamic_cast<Area *>(s);
assert(a != 0);
2012-04-02 09:03:00 +01:00
Point<2> low = a->lowCorner();
Point<2> high = a->highCorner();
2011-02-22 19:23:24 +00:00
assert(low.isValid());
assert(high.isValid());
}
{
MapType m;
m["type"] = "circle";
m["radius"] = 23.9;
m["position"] = ListType(2, 1.f);
Shape * s = Shape::newFromAtlas(m);
assert(s != 0);
test_conversion(s);
}
2011-02-22 19:23:24 +00:00
// The RotBox conversion functions throw if there isn't complete valid
2011-02-20 21:23:30 +00:00
// polygon data
{
2012-04-02 09:03:00 +01:00
Shape * s = new MathShape<RotBox, 2>(RotBox<2>());
assert(s != 0);
assert(!s->isValid());
}
{
2012-04-02 09:03:00 +01:00
Shape * s = new MathShape<RotBox, 2>(
RotBox<2>(Point<2>(0,0),
Vector<2>(1,1),
RotMatrix<2>().identity()));
assert(s != 0);
assert(s->isValid());
}
2011-02-20 17:27:29 +00:00
{
2011-02-20 21:23:30 +00:00
MapType m;
2011-02-20 17:27:29 +00:00
m["type"] = "rotbox";
Shape * s = Shape::newFromAtlas(m);
2011-02-20 21:23:30 +00:00
assert(s == 0);
2011-02-20 17:27:29 +00:00
}
2011-02-20 21:33:25 +00:00
{
MapType m;
m["type"] = "rotbox";
m["point"] = ListType(2, 1.f);
m["size"] = ListType(2, 1.f);
Shape * s = Shape::newFromAtlas(m);
assert(s != 0);
2011-02-23 08:15:48 +00:00
assert(s->isValid());
2011-02-20 21:33:25 +00:00
}
2011-02-22 21:29:01 +00:00
{
MapType m;
m["type"] = "rotbox";
m["point"] = ListType(2, 1.f);
m["size"] = ListType(2, 1.f);
Shape * s = Shape::newFromAtlas(m);
assert(s != 0);
2011-02-23 08:15:48 +00:00
assert(s->isValid());
2011-02-22 21:29:01 +00:00
MapType dest;
s->toAtlas(dest);
}
2011-02-22 19:23:24 +00:00
{
MapType m;
m["type"] = "rotbox";
m["point"] = ListType(2, 1.f);
m["size"] = ListType(2, 1.f);
Shape * s = Shape::newFromAtlas(m);
assert(s != 0);
Area * a = dynamic_cast<Area *>(s);
assert(a != 0);
2012-04-02 09:03:00 +01:00
Point<2> low = a->lowCorner();
Point<2> high = a->highCorner();
2011-02-22 19:23:24 +00:00
assert(low.isValid());
assert(high.isValid());
}
{
MapType m;
m["type"] = "rotbox";
m["point"] = ListType(2, 1.f);
m["size"] = ListType(2, 1.f);
Shape * s = Shape::newFromAtlas(m);
assert(s != 0);
// FIXME This doesn't work with an actual rotated box, as the underlying
// wfmath functions don't support them yet
test_conversion(s);
}
// Line functions
2012-04-02 09:23:56 +01:00
{
Shape * s = new MathShape<Line, 2>;
2012-04-02 09:23:56 +01:00
assert(s != 0);
assert(!s->isValid());
}
{
Line<2> p;
p.addCorner(0, Point<2>(1,0));
p.addCorner(0, Point<2>(0,0));
Shape * s = new MathShape<Line, 2>(p);
assert(s != 0);
assert(s->isValid());
}
{
Line<2> p;
p.addCorner(0, Point<2>(1,1));
p.addCorner(0, Point<2>(1,0));
p.addCorner(0, Point<2>(0,0));
Area * s = new MathShape<Line, 2>(p);
assert(s != 0);
assert(s->isValid());
assert(!s->intersect(Point<2>(0.75, 0.25)));
assert(!s->intersect(Point<2>(1.5, 0.5)));
assert(!s->intersect(Point<2>(1.5, 1.5)));
assert(!s->intersect(Point<2>(0.5, 1.5)));
assert(!s->intersect(Point<2>(-0.5, 1.5)));
assert(!s->intersect(Point<2>(-0.5, 0.5)));
assert(!s->intersect(Point<2>(-0.5, -0.5)));
assert(!s->intersect(Point<2>(0.5, -0.5)));
assert(!s->intersect(Point<2>(1.5, -0.5)));
}
2012-04-05 20:47:14 +01:00
{
Line<2> p;
p.addCorner(0, Point<2>(1,1));
p.addCorner(0, Point<2>(1,0));
p.addCorner(0, Point<2>(0,0));
Area * s = new MathShape<Line, 2>(p);
assert(s != 0);
assert(s->isValid());
test_conversion(s);
}
2012-04-02 09:23:56 +01:00
{
MapType m;
m["type"] = "line";
Shape * s = Shape::newFromAtlas(m);
assert(s == 0);
}
{
MapType m;
m["type"] = "line";
m["points"] = ListType(3, ListType(2, 1.f));
Shape * s = Shape::newFromAtlas(m);
assert(s != 0);
assert(s->isValid());
}
{
MapType m;
m["type"] = "line";
m["points"] = ListType(3, ListType(2, 1.f));
Shape * s = Shape::newFromAtlas(m);
assert(s != 0);
assert(s->isValid());
MapType dest;
s->toAtlas(dest);
}
{
MapType m;
m["type"] = "line";
ListType points;
points.push_back(ListType(2, -1.));
points.push_back(ListType(2, 1.));
ListType point(1, 1.);
point.push_back(-1.);
points.push_back(point);
m["points"] = points;
Shape * s = Shape::newFromAtlas(m);
assert(s != 0);
assert(s->isValid());
s->area();
}
{
MapType m;
m["type"] = "line";
ListType points;
points.push_back(ListType(2, -1.));
points.push_back(ListType(2, 1.));
ListType point(1, 1.);
point.push_back(-1.);
points.push_back(point);
m["points"] = points;
Shape * s = Shape::newFromAtlas(m);
s->scale(2);
}
{
MapType m;
m["type"] = "line";
ListType points;
points.push_back(ListType(2, -1.));
points.push_back(ListType(2, 1.));
ListType point(1, 1.);
point.push_back(-1.);
points.push_back(point);
m["points"] = points;
Shape * s = Shape::newFromAtlas(m);
assert(s != 0);
assert(s->isValid());
AxisBox<2> rect = s->footprint();
std::cout << rect << std::endl;
assert(rect.isValid());
}
{
MapType m;
m["type"] = "line";
ListType points;
points.push_back(ListType(2, -1.));
points.push_back(ListType(2, 1.));
ListType point(1, 1.);
point.push_back(-1.);
points.push_back(point);
m["points"] = points;
Shape * s = Shape::newFromAtlas(m);
assert(s != 0);
Area * a = dynamic_cast<Area *>(s);
assert(a != 0);
Point<2> low = a->lowCorner();
Point<2> high = a->highCorner();
assert(low.isValid());
assert(high.isValid());
}
// Course functions
{
Shape * s = new MathShape<LinearCourse, 2>;
assert(s != 0);
assert(!s->isValid());
}
2011-01-12 18:39:39 +00:00
return 0;
}
2012-04-02 09:23:56 +01:00