2016-03-03 19:53:58 +01:00
|
|
|
|
2015-06-09 00:13:02 +02:00
|
|
|
#include "catch.hpp"
|
2016-09-06 17:15:28 +02:00
|
|
|
#include "fake_path.hpp"
|
2015-06-09 00:13:02 +02:00
|
|
|
|
|
|
|
// mapnik
|
|
|
|
#include <mapnik/offset_converter.hpp>
|
2018-07-13 17:03:54 +02:00
|
|
|
#include <mapnik/util/math.hpp>
|
2015-06-09 00:13:02 +02:00
|
|
|
|
|
|
|
// stl
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
namespace offset_test {
|
|
|
|
|
|
|
|
static double DELTA_BUFF = 0.5;
|
|
|
|
|
|
|
|
double dist(double x0, double y0, double x1, double y1)
|
|
|
|
{
|
|
|
|
double dx = x0 - x1;
|
|
|
|
double dy = y0 - y1;
|
|
|
|
return std::sqrt(dx*dx + dy*dy);
|
|
|
|
}
|
|
|
|
|
2015-07-01 05:23:44 +02:00
|
|
|
void test_null_segment(double const &offset)
|
|
|
|
{
|
|
|
|
fake_path path = {};
|
|
|
|
mapnik::offset_converter<fake_path> off_path_new(path);
|
|
|
|
off_path_new.set_offset(offset);
|
|
|
|
double x0 = 0;
|
|
|
|
double y0 = 0;
|
|
|
|
REQUIRE(off_path_new.vertex(&x0, &y0) == mapnik::SEG_END);
|
|
|
|
REQUIRE(off_path_new.vertex(&x0, &y0) == mapnik::SEG_END);
|
|
|
|
REQUIRE(off_path_new.vertex(&x0, &y0) == mapnik::SEG_END);
|
|
|
|
}
|
|
|
|
|
|
|
|
void test_invalid_segment(double const &offset)
|
|
|
|
{
|
|
|
|
std::vector<double> v_path = {1, 1, 1, 2};
|
|
|
|
fake_path path(v_path, true);
|
|
|
|
mapnik::offset_converter<fake_path> off_path_new(path);
|
|
|
|
off_path_new.set_offset(offset);
|
|
|
|
double x0 = 0;
|
|
|
|
double y0 = 0;
|
|
|
|
REQUIRE(off_path_new.vertex(&x0, &y0) == mapnik::SEG_END);
|
|
|
|
REQUIRE(off_path_new.vertex(&x0, &y0) == mapnik::SEG_END);
|
|
|
|
REQUIRE(off_path_new.vertex(&x0, &y0) == mapnik::SEG_END);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-06-09 00:13:02 +02:00
|
|
|
void test_simple_segment(double const &offset)
|
|
|
|
{
|
|
|
|
fake_path path = {0, 0, 1, 0}, off_path = {0, offset, 1, offset};
|
|
|
|
mapnik::offset_converter<fake_path> off_path_new(path);
|
2015-06-09 16:18:52 +02:00
|
|
|
off_path_new.set_offset(offset);
|
2015-06-09 00:13:02 +02:00
|
|
|
|
|
|
|
double x0, y0, x1, y1;
|
|
|
|
unsigned cmd0 = off_path_new.vertex(&x0, &y0);
|
|
|
|
unsigned cmd1 = off_path.vertex(&x1,&y1);
|
|
|
|
double d = dist(x0, y0, x1, y1);
|
|
|
|
while (true) {
|
|
|
|
if (d > (std::abs(offset) + DELTA_BUFF))
|
|
|
|
{
|
|
|
|
cmd0 = off_path_new.vertex(&x0,&y0);
|
|
|
|
REQUIRE(cmd0 != mapnik::SEG_END);
|
|
|
|
d = dist(x0, y0, x1, y1);
|
|
|
|
REQUIRE(d <= (std::abs(offset) + DELTA_BUFF));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
REQUIRE(d <= (std::abs(offset) + DELTA_BUFF));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
cmd1 = off_path.vertex(&x1,&y1);
|
2015-06-09 03:32:21 +02:00
|
|
|
if (cmd1 == mapnik::SEG_END) break;
|
2015-06-09 00:13:02 +02:00
|
|
|
d = dist(x0, y0, x1, y1);
|
|
|
|
bool done = false;
|
|
|
|
while (d <= (std::abs(offset) + DELTA_BUFF))
|
|
|
|
{
|
|
|
|
CHECK(true);
|
|
|
|
cmd0 = off_path_new.vertex(&x0,&y0);
|
|
|
|
if (cmd0 == mapnik::SEG_END)
|
|
|
|
{
|
|
|
|
done = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (done) break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void test_straight_line(double const &offset) {
|
|
|
|
fake_path path = {0, 0, 1, 0, 9, 0, 10, 0},
|
|
|
|
off_path = {0, offset, 1, offset, 9, offset, 10, offset};
|
|
|
|
mapnik::offset_converter<fake_path> off_path_new(path);
|
2015-06-09 16:18:52 +02:00
|
|
|
off_path_new.set_offset(offset);
|
2015-06-09 00:13:02 +02:00
|
|
|
|
|
|
|
double x0, y0, x1, y1;
|
|
|
|
unsigned cmd0 = off_path_new.vertex(&x0, &y0);
|
|
|
|
unsigned cmd1 = off_path.vertex(&x1,&y1);
|
|
|
|
double d = dist(x0, y0, x1, y1);
|
|
|
|
while (true) {
|
|
|
|
if (d > (std::abs(offset) + DELTA_BUFF))
|
|
|
|
{
|
|
|
|
cmd0 = off_path_new.vertex(&x0,&y0);
|
|
|
|
REQUIRE(cmd0 != mapnik::SEG_END);
|
|
|
|
d = dist(x0, y0, x1, y1);
|
|
|
|
REQUIRE(d <= (std::abs(offset) + DELTA_BUFF));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
REQUIRE(d <= (std::abs(offset) + DELTA_BUFF));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
cmd1 = off_path.vertex(&x1,&y1);
|
|
|
|
d = dist(x0, y0, x1, y1);
|
|
|
|
bool done = false;
|
|
|
|
while (d <= (std::abs(offset) + DELTA_BUFF))
|
|
|
|
{
|
|
|
|
CHECK(true);
|
|
|
|
cmd0 = off_path_new.vertex(&x0,&y0);
|
|
|
|
if (cmd0 == mapnik::SEG_END)
|
|
|
|
{
|
|
|
|
done = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (done) break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void test_offset_curve(double const &offset) {
|
|
|
|
const double r = (1.0 + offset);
|
|
|
|
|
|
|
|
std::vector<double> pos, off_pos;
|
|
|
|
const size_t max_i = 1000;
|
|
|
|
for (size_t i = 0; i <= max_i; ++i) {
|
2018-07-13 17:03:54 +02:00
|
|
|
double x = mapnik::util::pi * double(i) / max_i;
|
2015-06-09 00:13:02 +02:00
|
|
|
pos.push_back(-std::cos(x)); pos.push_back(std::sin(x));
|
|
|
|
off_pos.push_back(-r * std::cos(x)); off_pos.push_back(r * std::sin(x));
|
|
|
|
}
|
|
|
|
|
|
|
|
fake_path path(pos), off_path(off_pos);
|
|
|
|
mapnik::offset_converter<fake_path> off_path_new(path);
|
2015-06-09 16:18:52 +02:00
|
|
|
off_path_new.set_offset(offset);
|
2015-06-09 00:13:02 +02:00
|
|
|
|
|
|
|
double x0, y0, x1, y1;
|
|
|
|
unsigned cmd0 = off_path_new.vertex(&x0, &y0);
|
|
|
|
unsigned cmd1 = off_path.vertex(&x1,&y1);
|
|
|
|
double d = dist(x0, y0, x1, y1);
|
|
|
|
while (true) {
|
|
|
|
if (d > (std::abs(offset) + DELTA_BUFF))
|
|
|
|
{
|
|
|
|
cmd0 = off_path_new.vertex(&x0,&y0);
|
|
|
|
REQUIRE(cmd0 != mapnik::SEG_END);
|
|
|
|
d = dist(x0, y0, x1, y1);
|
|
|
|
REQUIRE(d <= (std::abs(offset) + DELTA_BUFF));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
REQUIRE(d <= (std::abs(offset) + DELTA_BUFF));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
cmd1 = off_path.vertex(&x1,&y1);
|
|
|
|
d = dist(x0, y0, x1, y1);
|
|
|
|
bool done = false;
|
|
|
|
while (d <= (std::abs(offset) + DELTA_BUFF))
|
|
|
|
{
|
|
|
|
CHECK(true);
|
|
|
|
cmd0 = off_path_new.vertex(&x0,&y0);
|
|
|
|
if (cmd0 == mapnik::SEG_END)
|
|
|
|
{
|
|
|
|
done = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (done) break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void test_s_shaped_curve(double const &offset) {
|
|
|
|
const double r = (1.0 + offset);
|
|
|
|
const double r2 = (1.0 - offset);
|
|
|
|
|
|
|
|
std::vector<double> pos, off_pos;
|
|
|
|
const size_t max_i = 1000;
|
|
|
|
for (size_t i = 0; i <= max_i; ++i) {
|
2018-07-13 17:03:54 +02:00
|
|
|
double x = mapnik::util::pi * double(i) / max_i;
|
2015-06-09 00:13:02 +02:00
|
|
|
pos.push_back(-std::cos(x) - 1); pos.push_back(std::sin(x));
|
|
|
|
off_pos.push_back(-r * std::cos(x) - 1); off_pos.push_back(r * std::sin(x));
|
|
|
|
}
|
|
|
|
for (size_t i = 0; i <= max_i; ++i) {
|
2018-07-13 17:03:54 +02:00
|
|
|
double x = mapnik::util::pi * double(i) / max_i;
|
2015-06-09 00:13:02 +02:00
|
|
|
pos.push_back(-std::cos(x) + 1); pos.push_back(-std::sin(x));
|
|
|
|
off_pos.push_back(-r2 * std::cos(x) + 1); off_pos.push_back(-r2 * std::sin(x));
|
|
|
|
}
|
|
|
|
|
|
|
|
fake_path path(pos), off_path(off_pos);
|
|
|
|
mapnik::offset_converter<fake_path> off_path_new(path);
|
2015-06-09 16:18:52 +02:00
|
|
|
off_path_new.set_offset(offset);
|
2015-06-09 00:13:02 +02:00
|
|
|
|
|
|
|
double x0, y0, x1, y1;
|
|
|
|
unsigned cmd0 = off_path_new.vertex(&x0, &y0);
|
|
|
|
unsigned cmd1 = off_path.vertex(&x1,&y1);
|
|
|
|
double d = dist(x0, y0, x1, y1);
|
|
|
|
while (true) {
|
|
|
|
if (d > (std::abs(offset) + DELTA_BUFF))
|
|
|
|
{
|
|
|
|
cmd0 = off_path_new.vertex(&x0,&y0);
|
|
|
|
REQUIRE(cmd0 != mapnik::SEG_END);
|
|
|
|
d = dist(x0, y0, x1, y1);
|
|
|
|
REQUIRE(d <= (std::abs(offset) + DELTA_BUFF));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
REQUIRE(d <= (std::abs(offset) + DELTA_BUFF));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
cmd1 = off_path.vertex(&x1,&y1);
|
|
|
|
d = dist(x0, y0, x1, y1);
|
|
|
|
bool done = false;
|
|
|
|
while (d <= (std::abs(offset) + DELTA_BUFF))
|
|
|
|
{
|
|
|
|
CHECK(true);
|
|
|
|
cmd0 = off_path_new.vertex(&x0,&y0);
|
|
|
|
if (cmd0 == mapnik::SEG_END)
|
|
|
|
{
|
|
|
|
done = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (done) break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} // END NS
|
|
|
|
|
|
|
|
TEST_CASE("offset converter") {
|
|
|
|
|
2015-07-01 05:23:44 +02:00
|
|
|
SECTION("null segment") {
|
|
|
|
try {
|
|
|
|
|
|
|
|
std::vector<double> offsets = { 1, -1 };
|
|
|
|
for (double offset : offsets) {
|
|
|
|
// test simple straight line segment - should be easy to
|
|
|
|
// find the correspondance here.
|
|
|
|
offset_test::test_null_segment(offset);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (std::exception const& ex)
|
|
|
|
{
|
|
|
|
std::cerr << ex.what() << "\n";
|
|
|
|
REQUIRE(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("invalid segment") {
|
|
|
|
try {
|
|
|
|
|
|
|
|
std::vector<double> offsets = { 1, -1 };
|
|
|
|
for (double offset : offsets) {
|
|
|
|
// test simple straight line segment - should be easy to
|
|
|
|
// find the correspondance here.
|
|
|
|
offset_test::test_invalid_segment(offset);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (std::exception const& ex)
|
|
|
|
{
|
|
|
|
std::cerr << ex.what() << "\n";
|
|
|
|
REQUIRE(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-06-09 00:13:02 +02:00
|
|
|
SECTION("simple segment") {
|
|
|
|
try {
|
|
|
|
|
|
|
|
std::vector<double> offsets = { 1, -1 };
|
|
|
|
for (double offset : offsets) {
|
|
|
|
// test simple straight line segment - should be easy to
|
|
|
|
// find the correspondance here.
|
|
|
|
offset_test::test_simple_segment(offset);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (std::exception const& ex)
|
|
|
|
{
|
|
|
|
std::cerr << ex.what() << "\n";
|
|
|
|
REQUIRE(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("straight line") {
|
|
|
|
try {
|
|
|
|
|
|
|
|
std::vector<double> offsets = { 1, -1 };
|
|
|
|
for (double offset : offsets) {
|
|
|
|
// test straight line consisting of more than one segment.
|
|
|
|
offset_test::test_straight_line(offset);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (std::exception const& ex)
|
|
|
|
{
|
|
|
|
std::cerr << ex.what() << "\n";
|
|
|
|
REQUIRE(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("curve") {
|
|
|
|
try {
|
|
|
|
|
|
|
|
std::vector<double> offsets = { 1, -1 };
|
|
|
|
for (double offset : offsets) {
|
|
|
|
offset_test::test_offset_curve(offset);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (std::exception const& ex)
|
|
|
|
{
|
|
|
|
std::cerr << ex.what() << "\n";
|
|
|
|
REQUIRE(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("s curve") {
|
|
|
|
try {
|
|
|
|
|
|
|
|
std::vector<double> offsets = { 1, -1 };
|
|
|
|
for (double offset : offsets) {
|
|
|
|
offset_test::test_s_shaped_curve(offset);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (std::exception const& ex)
|
|
|
|
{
|
|
|
|
std::cerr << ex.what() << "\n";
|
|
|
|
REQUIRE(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-25 14:28:47 +01:00
|
|
|
SECTION("offsect converter does not skip SEG_MOVETO or SEG_CLOSE vertices") {
|
|
|
|
|
|
|
|
const double offset = 0.2;
|
|
|
|
|
|
|
|
fake_path path = {};
|
|
|
|
path.vertices_.emplace_back(-2, -2, mapnik::SEG_MOVETO);
|
|
|
|
path.vertices_.emplace_back( 2, -2, mapnik::SEG_LINETO);
|
|
|
|
path.vertices_.emplace_back( 2, 2, mapnik::SEG_LINETO);
|
|
|
|
path.vertices_.emplace_back(-2, 2, mapnik::SEG_LINETO);
|
|
|
|
path.vertices_.emplace_back(-2, -1.9, mapnik::SEG_LINETO);
|
|
|
|
path.vertices_.emplace_back( 0, 0, mapnik::SEG_CLOSE);
|
|
|
|
path.vertices_.emplace_back(-1.9, -1.9, mapnik::SEG_MOVETO);
|
|
|
|
path.vertices_.emplace_back( 1, -1, mapnik::SEG_LINETO);
|
|
|
|
path.vertices_.emplace_back( 1, 1, mapnik::SEG_LINETO);
|
|
|
|
path.vertices_.emplace_back(-1, 1, mapnik::SEG_LINETO);
|
|
|
|
path.vertices_.emplace_back(-1, -1, mapnik::SEG_LINETO);
|
|
|
|
path.vertices_.emplace_back( 0, 0, mapnik::SEG_CLOSE);
|
|
|
|
path.rewind(0);
|
|
|
|
|
|
|
|
mapnik::offset_converter<fake_path> off_path(path);
|
|
|
|
off_path.set_offset(offset);
|
|
|
|
|
|
|
|
unsigned cmd;
|
|
|
|
double x, y;
|
|
|
|
|
|
|
|
unsigned move_to_count = 0;
|
|
|
|
unsigned close_count = 0;
|
|
|
|
|
|
|
|
while((cmd = off_path.vertex(&x, &y)) != mapnik::SEG_END)
|
|
|
|
{
|
|
|
|
switch (cmd)
|
|
|
|
{
|
|
|
|
case mapnik::SEG_MOVETO:
|
|
|
|
move_to_count++;
|
|
|
|
break;
|
|
|
|
case mapnik::SEG_CLOSE:
|
|
|
|
close_count++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CHECK(move_to_count == 2);
|
|
|
|
CHECK(close_count == 2);
|
|
|
|
}
|
|
|
|
|
2015-06-09 00:13:02 +02:00
|
|
|
}
|