2016-03-03 19:53:58 +01:00
|
|
|
|
2015-04-24 14:40:22 +02:00
|
|
|
#include "catch.hpp"
|
2016-09-06 17:15:28 +02:00
|
|
|
#include "fake_path.hpp"
|
2015-04-24 14:40:22 +02:00
|
|
|
|
|
|
|
// mapnik
|
2018-07-13 17:03:54 +02:00
|
|
|
#include <mapnik/util/math.hpp>
|
2015-04-24 14:40:22 +02:00
|
|
|
#include <mapnik/vertex_cache.hpp>
|
|
|
|
|
|
|
|
// stl
|
|
|
|
#include <iostream>
|
|
|
|
|
2022-01-26 23:25:53 +01:00
|
|
|
double dist(mapnik::pixel_position const& a, mapnik::pixel_position const& b)
|
2015-04-24 14:40:22 +02:00
|
|
|
{
|
|
|
|
mapnik::pixel_position d = a - b;
|
2022-01-26 23:25:53 +01:00
|
|
|
return std::sqrt(d.x * d.x + d.y * d.y);
|
2015-04-24 14:40:22 +02:00
|
|
|
}
|
|
|
|
|
2022-01-26 23:25:53 +01:00
|
|
|
void test_simple_segment(double const& offset)
|
2015-04-24 14:40:22 +02:00
|
|
|
{
|
|
|
|
const double dx = 0.01;
|
|
|
|
fake_path path = {0, 0, 1, 0}, off_path = {0, offset, 1, offset};
|
|
|
|
mapnik::vertex_cache vc(path), off_vc(off_path);
|
|
|
|
|
2022-01-26 23:25:53 +01:00
|
|
|
vc.reset();
|
|
|
|
vc.next_subpath();
|
|
|
|
off_vc.reset();
|
|
|
|
off_vc.next_subpath();
|
2015-04-24 14:40:22 +02:00
|
|
|
|
2022-01-26 23:25:53 +01:00
|
|
|
while (vc.move(dx))
|
|
|
|
{
|
2015-04-24 14:40:22 +02:00
|
|
|
double pos = vc.linear_position();
|
|
|
|
double off_pos = off_vc.position_closest_to(vc.current_position());
|
|
|
|
REQUIRE(std::abs(pos - off_pos) < 1.0e-6);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-26 23:25:53 +01:00
|
|
|
void test_straight_line(double const& offset)
|
|
|
|
{
|
2015-04-24 14:40:22 +02:00
|
|
|
const double dx = 0.01;
|
2022-01-26 23:25:53 +01:00
|
|
|
fake_path path = {0, 0, 0.1, 0, 0.9, 0, 1, 0}, off_path = {0, offset, 0.4, offset, 0.6, offset, 1, offset};
|
2015-04-24 14:40:22 +02:00
|
|
|
mapnik::vertex_cache vc(path), off_vc(off_path);
|
|
|
|
|
2022-01-26 23:25:53 +01:00
|
|
|
vc.reset();
|
|
|
|
vc.next_subpath();
|
|
|
|
off_vc.reset();
|
|
|
|
off_vc.next_subpath();
|
2015-04-24 14:40:22 +02:00
|
|
|
|
2022-01-26 23:25:53 +01:00
|
|
|
while (vc.move(dx))
|
|
|
|
{
|
2015-04-24 14:40:22 +02:00
|
|
|
double pos = vc.linear_position();
|
|
|
|
double off_pos = off_vc.position_closest_to(vc.current_position());
|
|
|
|
REQUIRE(std::abs(pos - off_pos) < 1.0e-6);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-26 23:25:53 +01:00
|
|
|
void test_offset_curve(double const& offset)
|
|
|
|
{
|
2015-04-24 14:40:22 +02:00
|
|
|
const double dx = 0.01;
|
|
|
|
const double r = (1.0 + offset);
|
|
|
|
|
|
|
|
std::vector<double> pos, off_pos;
|
|
|
|
const size_t max_i = 1000;
|
2022-01-26 23:25:53 +01:00
|
|
|
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;
|
2022-01-26 23:25:53 +01: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));
|
2015-04-24 14:40:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fake_path path(pos), off_path(off_pos);
|
|
|
|
mapnik::vertex_cache vc(path), off_vc(off_path);
|
|
|
|
|
2022-01-26 23:25:53 +01:00
|
|
|
vc.reset();
|
|
|
|
vc.next_subpath();
|
|
|
|
off_vc.reset();
|
|
|
|
off_vc.next_subpath();
|
2015-04-24 14:40:22 +02:00
|
|
|
|
2022-01-26 23:25:53 +01:00
|
|
|
while (vc.move(dx))
|
|
|
|
{
|
2015-06-16 05:04:23 +02:00
|
|
|
double mpos = vc.linear_position();
|
|
|
|
double moff_pos = off_vc.position_closest_to(vc.current_position());
|
2015-04-24 14:40:22 +02:00
|
|
|
{
|
|
|
|
mapnik::vertex_cache::scoped_state s(off_vc);
|
2015-06-16 05:04:23 +02:00
|
|
|
off_vc.move(moff_pos);
|
2015-04-24 14:40:22 +02:00
|
|
|
auto eps = (1.001 * offset);
|
|
|
|
auto actual = dist(vc.current_position(), off_vc.current_position());
|
|
|
|
REQUIRE(actual < eps);
|
|
|
|
}
|
2015-06-16 05:04:23 +02:00
|
|
|
REQUIRE(std::abs((mpos / vc.length()) - (moff_pos / off_vc.length())) < 1.0e-3);
|
2015-04-24 14:40:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-26 23:25:53 +01:00
|
|
|
void test_s_shaped_curve(double const& offset)
|
|
|
|
{
|
2015-04-24 14:40:22 +02:00
|
|
|
const double dx = 0.01;
|
|
|
|
const double r = (1.0 + offset);
|
|
|
|
const double r2 = (1.0 - offset);
|
|
|
|
|
|
|
|
std::vector<double> pos, off_pos;
|
|
|
|
const size_t max_i = 1000;
|
2022-01-26 23:25:53 +01:00
|
|
|
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;
|
2022-01-26 23:25:53 +01: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));
|
2015-04-24 14:40:22 +02:00
|
|
|
}
|
2022-01-26 23:25:53 +01:00
|
|
|
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;
|
2022-01-26 23:25:53 +01: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));
|
2015-04-24 14:40:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fake_path path(pos), off_path(off_pos);
|
|
|
|
mapnik::vertex_cache vc(path), off_vc(off_path);
|
|
|
|
|
2022-01-26 23:25:53 +01:00
|
|
|
vc.reset();
|
|
|
|
vc.next_subpath();
|
|
|
|
off_vc.reset();
|
|
|
|
off_vc.next_subpath();
|
2015-04-24 14:40:22 +02:00
|
|
|
|
2022-01-26 23:25:53 +01:00
|
|
|
while (vc.move(dx))
|
|
|
|
{
|
2015-06-16 05:04:23 +02:00
|
|
|
double moff_pos = off_vc.position_closest_to(vc.current_position());
|
2015-04-24 14:40:22 +02:00
|
|
|
{
|
|
|
|
mapnik::vertex_cache::scoped_state s(off_vc);
|
2015-06-16 05:04:23 +02:00
|
|
|
off_vc.move(moff_pos);
|
2015-04-24 14:40:22 +02:00
|
|
|
REQUIRE(dist(vc.current_position(), off_vc.current_position()) < (1.002 * offset));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-26 23:25:53 +01:00
|
|
|
TEST_CASE("offsets")
|
|
|
|
{
|
|
|
|
SECTION("line")
|
2015-04-24 14:40:22 +02:00
|
|
|
{
|
2022-01-26 23:25:53 +01:00
|
|
|
try
|
|
|
|
{
|
|
|
|
std::vector<double> offsets = {0.01, 0.02, 0.1, 0.2};
|
|
|
|
for (double offset : offsets)
|
|
|
|
{
|
|
|
|
// test simple straight line segment - should be easy to
|
|
|
|
// find the correspondance here.
|
|
|
|
test_simple_segment(offset);
|
|
|
|
|
|
|
|
// test straight line consisting of more than one segment.
|
|
|
|
test_straight_line(offset);
|
|
|
|
|
|
|
|
// test an offset outer curve
|
|
|
|
test_offset_curve(offset);
|
|
|
|
|
|
|
|
// test an offset along an S-shaped curve, which is harder
|
|
|
|
// because the positions along the offset are no longer
|
|
|
|
// linearly related to the positions along the original
|
|
|
|
// curve.
|
|
|
|
test_s_shaped_curve(offset);
|
|
|
|
}
|
|
|
|
} catch (std::exception const& ex)
|
|
|
|
{
|
|
|
|
std::cerr << ex.what() << "\n";
|
|
|
|
REQUIRE(false);
|
|
|
|
}
|
2015-04-24 14:40:22 +02:00
|
|
|
}
|
|
|
|
}
|