cyphesis/tests/ShapeTest.cpp
Erik Ogenvik 1c69b3aae6 Use camel casing for tests.
This makes it much easier to find them in various editors.
2016-06-26 20:17:18 +02:00

829 lines
18 KiB
C++

// 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
#ifdef NDEBUG
#undef NDEBUG
#endif
#ifndef DEBUG
#define DEBUG
#endif
#include "physics/Shape.h"
#include "physics/Course.h"
#include <Atlas/Message/Element.h>
#include <wfmath/axisbox.h>
#include <wfmath/intersect.h>
#include <wfmath/line.h>
#include <wfmath/point.h>
#include <wfmath/polygon.h>
#include <iostream>
#include <cassert>
using Atlas::Message::ListType;
using Atlas::Message::MapType;
using WFMath::AxisBox;
using WFMath::Ball;
using WFMath::Line;
using WFMath::Point;
using WFMath::Polygon;
using WFMath::RotBox;
using WFMath::RotMatrix;
using WFMath::Vector;
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;
assert(*s == *copy);
}
// FIXME Use a C++11 template typedef once the are supported
template<int dim> class LinearCourse : public Course<dim, WFMath::Line>
{
};
int main()
{
{
MapType m;
Shape * s = Shape::newFromAtlas(m);
assert(s == 0);
}
// The AxisBox is a little different, and is not covered by the
// name constructor
{
Shape * s = new MathShape<AxisBox, 2>(AxisBox<2>());
assert(s != 0);
assert(!s->isValid());
}
{
Shape * s = new MathShape<AxisBox, 2>(AxisBox<2>(Point<2>(0,0),
Point<2>(1,1)));
assert(s != 0);
assert(s->isValid());
}
{
Area * s = new MathShape<AxisBox, 2>(AxisBox<2>(Point<2>(0,0),
Point<2>(1,1)));
assert(s != 0);
assert(s->isValid());
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)));
}
{
MapType m;
Shape * s = new MathShape<AxisBox, 2>(AxisBox<2>());
s->fromAtlas(m);
assert(s != 0);
assert(!s->isValid());
}
{
Shape * s = new MathShape<AxisBox, 2>(AxisBox<2>());
s->fromAtlas(ListType(2, 1.));
assert(s != 0);
assert(s->isValid());
}
{
Shape * s = new MathShape<AxisBox, 2>(AxisBox<2>());
s->fromAtlas(ListType(2, 1.));
assert(s != 0);
assert(s->isValid());
MapType dest;
s->toAtlas(dest);
}
{
Shape * s = new MathShape<AxisBox, 2>(AxisBox<2>());
s->fromAtlas(std::string("bad_string_value"));
assert(s != 0);
assert(!s->isValid());
}
{
Area * s = new MathShape<AxisBox, 2>(AxisBox<2>());
s->fromAtlas(ListType(2, 1.));
assert(s != 0);
assert(s->isValid());
Point<2> low = s->lowCorner();
Point<2> high = s->highCorner();
assert(low.isValid());
assert(high.isValid());
}
{
Area * s = new MathShape<AxisBox, 2>(AxisBox<2>(Point<2>(0,0),
Point<2>(2,2)));
assert(s != 0);
assert(s->isValid());
Point<2> centre = s->centre();
assert(Equal(centre, Point<2>(1,1)));
}
{
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)));
}
// The Polygon conversion functions throw if there isn't complete valid
// polygon data
{
Shape * s = new MathShape<Polygon, 2>(Polygon<2>());
assert(s != 0);
assert(s->isValid());
}
{
Polygon<2> p;
p.addCorner(0, Point<2>(1,1));
p.addCorner(0, Point<2>(1,0));
p.addCorner(0, Point<2>(0,0));
Shape * s = new MathShape<Polygon, 2>(p);
assert(s != 0);
assert(s->isValid());
}
{
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
assert(Intersect(p, Point<2>(0.75, 0.25), true));
Area * s = new MathShape<Polygon, 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)));
}
{
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);
}
{
MapType m;
m["type"] = "polygon";
Shape * s = Shape::newFromAtlas(m);
assert(s == 0);
}
{
MapType m;
m["type"] = "polygon";
m["points"] = ListType(3, ListType(2, 1.f));
Shape * s = Shape::newFromAtlas(m);
assert(s != 0);
assert(s->isValid());
}
{
MapType m;
m["type"] = "polygon";
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"] = "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);
assert(s->isValid());
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);
assert(s->isValid());
double area = s->area();
s->scale(2);
assert(s->isValid());
assert(area < s->area());
}
{
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);
assert(s->isValid());
AxisBox<2> rect = s->footprint();
std::cout << rect << std::endl;
assert(rect.isValid());
}
{
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);
Point<2> low = a->lowCorner();
Point<2> high = a->highCorner();
assert(low.isValid());
assert(high.isValid());
}
// The Ball conversion functions don't seem to require valid Atlas
// data
{
Shape * s = new MathShape<Ball, 2>(Ball<2>());
assert(s != 0);
assert(!s->isValid());
}
{
Shape * s = new MathShape<Ball, 2>(
Ball<2>(Point<2>(1,1), 23.f));
assert(s != 0);
assert(s->isValid());
}
{
MapType m;
m["type"] = "circle";
Shape * s = Shape::newFromAtlas(m);
assert(s != 0);
assert(!s->isValid());
}
{
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());
}
{
MapType m;
m["type"] = "circle";
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";
m["radius"] = 23.9;
m["position"] = ListType(2, 1.f);
Shape * s = Shape::newFromAtlas(m);
assert(s != 0);
MapType dest;
s->toAtlas(dest);
}
{
MapType m;
m["type"] = "circle";
m["radius"] = 23.9;
m["position"] = ListType(2, 1.f);
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());
}
{
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);
}
// The RotBox conversion functions throw if there isn't complete valid
// polygon data
{
Shape * s = new MathShape<RotBox, 2>(RotBox<2>());
assert(s != 0);
assert(!s->isValid());
}
{
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());
}
{
MapType m;
m["type"] = "rotbox";
Shape * s = Shape::newFromAtlas(m);
assert(s == 0);
}
{
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);
assert(s->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);
assert(s->isValid());
MapType dest;
s->toAtlas(dest);
}
{
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);
Point<2> low = a->lowCorner();
Point<2> high = a->highCorner();
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
{
Shape * s = new MathShape<Line, 2>;
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)));
}
{
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);
}
{
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());
}
return 0;
}