format dir test

format dir test

fix
This commit is contained in:
Mathis Logemann 2022-01-26 23:25:53 +01:00
parent d5a873e81c
commit 6dcf754077
101 changed files with 9420 additions and 9408 deletions

View file

@ -261,6 +261,10 @@ auto const feature_part_def = feature_type
|
(omit[geojson_string] > lit(':') > omit[value])
;
auto const feature_rule_def = lit('{') > feature_part % lit(',') > lit('}');
auto const geometry_rule_def = (lit('{') > geometry_tuple[create_geometry] > lit('}')) | lit("null");
// clang-format on
#include <mapnik/warning.hpp>

View file

@ -46,6 +46,6 @@ inline void run_cleanup()
u_cleanup();
}
}
} // namespace testing
#endif

View file

@ -14,51 +14,57 @@
#include <iostream>
// geojson box of the world
const std::string geojson("{ \"type\": \"Feature\", \"properties\": { }, \"geometry\": { \"type\": \"Polygon\", \"coordinates\": [ [ [ -17963313.143242701888084, -6300857.11560364998877 ], [ -17963313.143242701888084, 13071343.332991421222687 ], [ 7396658.353099936619401, 13071343.332991421222687 ], [ 7396658.353099936619401, -6300857.11560364998877 ], [ -17963313.143242701888084, -6300857.11560364998877 ] ] ] } }");
const std::string
geojson("{ \"type\": \"Feature\", \"properties\": { }, \"geometry\": { \"type\": \"Polygon\", \"coordinates\": [ [ [ "
"-17963313.143242701888084, -6300857.11560364998877 ], [ -17963313.143242701888084, 13071343.332991421222687 "
"], [ 7396658.353099936619401, 13071343.332991421222687 ], [ 7396658.353099936619401, "
"-6300857.11560364998877 ], [ -17963313.143242701888084, -6300857.11560364998877 ] ] ] } }");
TEST_CASE("agg_rasterizer_integer_overflow") {
TEST_CASE("agg_rasterizer_integer_overflow")
{
SECTION("coordinates_do_not_overflow_and_polygon_is_rendered")
{
auto expected_color = mapnik::color("white");
SECTION("coordinates_do_not_overflow_and_polygon_is_rendered") {
auto expected_color = mapnik::color("white");
mapnik::Map m(256, 256);
m.set_background(mapnik::color("black"));
mapnik::Map m(256,256);
m.set_background(mapnik::color("black"));
mapnik::feature_type_style s;
{
mapnik::rule r;
mapnik::polygon_symbolizer sym;
mapnik::put(sym, mapnik::keys::fill, expected_color);
mapnik::put(sym, mapnik::keys::clip, false);
r.append(std::move(sym));
s.add_rule(std::move(r));
}
m.insert_style("style", std::move(s));
mapnik::feature_type_style s;
{
mapnik::rule r;
mapnik::polygon_symbolizer sym;
mapnik::put(sym, mapnik::keys::fill, expected_color);
mapnik::put(sym, mapnik::keys::clip, false);
r.append(std::move(sym));
s.add_rule(std::move(r));
}
m.insert_style("style",std::move(s));
mapnik::layer lyr("Layer");
lyr.styles().emplace_back("style");
{
auto ds = std::make_shared<mapnik::memory_datasource>(mapnik::parameters());
auto context = std::make_shared<mapnik::context_type>();
auto f = std::make_shared<mapnik::feature_impl>(context, 0);
REQUIRE(mapnik::json::from_geojson(geojson, *f));
ds->push(f);
lyr.set_datasource(ds);
}
m.add_layer(std::move(lyr));
mapnik::layer lyr("Layer");
lyr.styles().emplace_back("style");
{
auto ds = std::make_shared<mapnik::memory_datasource>(mapnik::parameters());
auto context = std::make_shared<mapnik::context_type>();
auto f = std::make_shared<mapnik::feature_impl>(context, 0);
REQUIRE(mapnik::json::from_geojson(geojson, *f));
ds->push(f);
lyr.set_datasource(ds);
}
m.add_layer(std::move(lyr));
// 17/20864/45265.png
m.zoom_to_box(
mapnik::box2d<double>(-13658379.710221574, 6197514.253362091, -13657768.213995293, 6198125.749588372));
// 17/20864/45265.png
m.zoom_to_box(mapnik::box2d<double>(-13658379.710221574,6197514.253362091,-13657768.213995293,6198125.749588372));
// works 15/5216/11316.png
// m.zoom_to_box(mapnik::box2d<double>(-13658379.710221574,6195679.764683247,-13655933.72531645,6198125.749588372));
// works 15/5216/11316.png
//m.zoom_to_box(mapnik::box2d<double>(-13658379.710221574,6195679.764683247,-13655933.72531645,6198125.749588372));
mapnik::image_rgba8 im(256, 256);
{
mapnik::agg_renderer<mapnik::image_rgba8> ren(m, im);
ren.apply();
}
mapnik::image_rgba8 im(256, 256);
{
mapnik::agg_renderer<mapnik::image_rgba8> ren(m, im);
ren.apply();
}
REQUIRE(im(128,128) == expected_color.rgba());
} // SECTION
REQUIRE(im(128, 128) == expected_color.rgba());
} // SECTION
} // TEST_CASE

View file

@ -9,44 +9,43 @@
#include <vector>
#include <algorithm>
TEST_CASE("datasource_cache") {
SECTION("registration") {
try
TEST_CASE("datasource_cache")
{
SECTION("registration")
{
mapnik::logger logger;
mapnik::logger::severity_type original_severity = logger.get_severity();
bool success = false;
auto &cache = mapnik::datasource_cache::instance();
// registering a directory without any plugins should return false
success = cache.register_datasources("test/data/vrt");
CHECK(success == false);
// use existence of shape.input as proxy for whether any datasource plugins are available
std::string shape_plugin("./plugins/input/shape.input");
if (mapnik::util::exists(shape_plugin))
try
{
// registering a directory for the first time should return true
success = cache.register_datasources("plugins/input");
REQUIRE(success == true);
mapnik::logger logger;
mapnik::logger::severity_type original_severity = logger.get_severity();
bool success = false;
auto& cache = mapnik::datasource_cache::instance();
// registering the same directory again should now return false
success = cache.register_datasources("plugins/input");
// registering a directory without any plugins should return false
success = cache.register_datasources("test/data/vrt");
CHECK(success == false);
// registering the same directory again, but recursively should
// still return false - even though there are subdirectories, they
// do not contain any more plugins.
success = cache.register_datasources("plugins/input", true);
CHECK(success == false);
// use existence of shape.input as proxy for whether any datasource plugins are available
std::string shape_plugin("./plugins/input/shape.input");
if (mapnik::util::exists(shape_plugin))
{
// registering a directory for the first time should return true
success = cache.register_datasources("plugins/input");
REQUIRE(success == true);
// registering the same directory again should now return false
success = cache.register_datasources("plugins/input");
CHECK(success == false);
// registering the same directory again, but recursively should
// still return false - even though there are subdirectories, they
// do not contain any more plugins.
success = cache.register_datasources("plugins/input", true);
CHECK(success == false);
}
} catch (std::exception const& ex)
{
std::clog << ex.what() << "\n";
REQUIRE(false);
}
}
catch (std::exception const & ex)
{
std::clog << ex.what() << "\n";
REQUIRE(false);
}
}
}

View file

@ -11,165 +11,164 @@
#include <vector>
#include <algorithm>
TEST_CASE("font") {
SECTION("registration") {
try
TEST_CASE("font")
{
SECTION("registration")
{
mapnik::logger logger;
mapnik::logger::severity_type original_severity = logger.get_severity();
// grab references to global statics of registered/cached fonts
auto const& global_mapping = mapnik::freetype_engine::get_mapping();
auto const& global_cache = mapnik::freetype_engine::get_cache();
// mapnik.Map object has parallel structure for localized fonts
mapnik::Map m(1,1);
auto const& local_mapping = m.get_font_file_mapping();
auto const& local_cache = m.get_font_memory_cache();
// should be empty to start
REQUIRE( global_mapping.empty() );
REQUIRE( global_cache.empty() );
REQUIRE( local_mapping.empty() );
REQUIRE( local_cache.empty() );
std::string fontdir("fonts/");
REQUIRE( mapnik::util::exists( fontdir ) );
REQUIRE( mapnik::util::is_directory( fontdir ) );
// test map cached fonts
REQUIRE( m.register_fonts(fontdir , true ) );
REQUIRE( m.get_font_file_mapping().size() == 22 );
REQUIRE( m.load_fonts() );
REQUIRE( m.get_font_memory_cache().size() == 22 );
// copy discards memory cache but not file mapping
mapnik::Map m2(m);
REQUIRE( m2.get_font_memory_cache().size() == 0 );
REQUIRE( m2.get_font_file_mapping().size() == 22 );
REQUIRE( m2.load_fonts() );
REQUIRE( m2.get_font_memory_cache().size() == 22 );
// test font-directory from XML
mapnik::Map m3(1,1);
mapnik::load_map_string(m3,"<Map font-directory=\"test/data/fonts/Noto/\"></Map>");
REQUIRE( m3.get_font_memory_cache().size() == 0 );
REQUIRE( m3.load_fonts() );
REQUIRE( m3.get_font_memory_cache().size() == 2 );
std::vector<std::string> face_names;
std::string foo("foo");
// fake directories
REQUIRE( !mapnik::freetype_engine::register_fonts(foo , true ) );
face_names = mapnik::freetype_engine::face_names();
REQUIRE( face_names.size() == 0 );
REQUIRE( !mapnik::freetype_engine::register_fonts(foo) );
face_names = mapnik::freetype_engine::face_names();
REQUIRE( face_names.size() == 0 );
// directories without fonts
// silence warnings here by altering the logging severity
logger.set_severity(mapnik::logger::none);
std::string src("src");
// an empty directory will not return true
// we need to register at least one font and not fail on any
// to return true
REQUIRE( mapnik::freetype_engine::register_font(src) == false );
REQUIRE( mapnik::freetype_engine::register_fonts(src, true) == false );
REQUIRE( mapnik::freetype_engine::face_names().size() == 0 );
// bogus, emtpy file that looks like font
REQUIRE( mapnik::freetype_engine::register_font("test/data/fonts/fake.ttf") == false );
REQUIRE( mapnik::freetype_engine::register_fonts("test/data/fonts/fake.ttf") == false );
REQUIRE( mapnik::freetype_engine::face_names().size() == 0 );
REQUIRE( mapnik::freetype_engine::register_font("test/data/fonts/intentionally-broken.ttf") == false );
REQUIRE( mapnik::freetype_engine::register_fonts("test/data/fonts/intentionally-broken.ttf") == false );
REQUIRE( mapnik::freetype_engine::face_names().size() == 0 );
// now restore the original severity
logger.set_severity(original_severity);
// single dejavu font in separate location
std::string dejavu_bold_oblique("test/data/fonts/DejaVuSansMono-BoldOblique.ttf");
REQUIRE( mapnik::freetype_engine::register_font(dejavu_bold_oblique) );
face_names = mapnik::freetype_engine::face_names();
REQUIRE( face_names.size() == 1 );
// now, inspect font mapping and confirm the correct 'DejaVu Sans Mono Bold Oblique' is registered
using font_file_mapping = std::map<std::string, std::pair<int,std::string> >;
font_file_mapping const& name2file = mapnik::freetype_engine::get_mapping();
bool found_dejavu = false;
for (auto const& item : name2file)
try
{
if (item.first == "DejaVu Sans Mono Bold Oblique")
mapnik::logger logger;
mapnik::logger::severity_type original_severity = logger.get_severity();
// grab references to global statics of registered/cached fonts
auto const& global_mapping = mapnik::freetype_engine::get_mapping();
auto const& global_cache = mapnik::freetype_engine::get_cache();
// mapnik.Map object has parallel structure for localized fonts
mapnik::Map m(1, 1);
auto const& local_mapping = m.get_font_file_mapping();
auto const& local_cache = m.get_font_memory_cache();
// should be empty to start
REQUIRE(global_mapping.empty());
REQUIRE(global_cache.empty());
REQUIRE(local_mapping.empty());
REQUIRE(local_cache.empty());
std::string fontdir("fonts/");
REQUIRE(mapnik::util::exists(fontdir));
REQUIRE(mapnik::util::is_directory(fontdir));
// test map cached fonts
REQUIRE(m.register_fonts(fontdir, true));
REQUIRE(m.get_font_file_mapping().size() == 22);
REQUIRE(m.load_fonts());
REQUIRE(m.get_font_memory_cache().size() == 22);
// copy discards memory cache but not file mapping
mapnik::Map m2(m);
REQUIRE(m2.get_font_memory_cache().size() == 0);
REQUIRE(m2.get_font_file_mapping().size() == 22);
REQUIRE(m2.load_fonts());
REQUIRE(m2.get_font_memory_cache().size() == 22);
// test font-directory from XML
mapnik::Map m3(1, 1);
mapnik::load_map_string(m3, "<Map font-directory=\"test/data/fonts/Noto/\"></Map>");
REQUIRE(m3.get_font_memory_cache().size() == 0);
REQUIRE(m3.load_fonts());
REQUIRE(m3.get_font_memory_cache().size() == 2);
std::vector<std::string> face_names;
std::string foo("foo");
// fake directories
REQUIRE(!mapnik::freetype_engine::register_fonts(foo, true));
face_names = mapnik::freetype_engine::face_names();
REQUIRE(face_names.size() == 0);
REQUIRE(!mapnik::freetype_engine::register_fonts(foo));
face_names = mapnik::freetype_engine::face_names();
REQUIRE(face_names.size() == 0);
// directories without fonts
// silence warnings here by altering the logging severity
logger.set_severity(mapnik::logger::none);
std::string src("src");
// an empty directory will not return true
// we need to register at least one font and not fail on any
// to return true
REQUIRE(mapnik::freetype_engine::register_font(src) == false);
REQUIRE(mapnik::freetype_engine::register_fonts(src, true) == false);
REQUIRE(mapnik::freetype_engine::face_names().size() == 0);
// bogus, emtpy file that looks like font
REQUIRE(mapnik::freetype_engine::register_font("test/data/fonts/fake.ttf") == false);
REQUIRE(mapnik::freetype_engine::register_fonts("test/data/fonts/fake.ttf") == false);
REQUIRE(mapnik::freetype_engine::face_names().size() == 0);
REQUIRE(mapnik::freetype_engine::register_font("test/data/fonts/intentionally-broken.ttf") == false);
REQUIRE(mapnik::freetype_engine::register_fonts("test/data/fonts/intentionally-broken.ttf") == false);
REQUIRE(mapnik::freetype_engine::face_names().size() == 0);
// now restore the original severity
logger.set_severity(original_severity);
// single dejavu font in separate location
std::string dejavu_bold_oblique("test/data/fonts/DejaVuSansMono-BoldOblique.ttf");
REQUIRE(mapnik::freetype_engine::register_font(dejavu_bold_oblique));
face_names = mapnik::freetype_engine::face_names();
REQUIRE(face_names.size() == 1);
// now, inspect font mapping and confirm the correct 'DejaVu Sans Mono Bold Oblique' is registered
using font_file_mapping = std::map<std::string, std::pair<int, std::string>>;
font_file_mapping const& name2file = mapnik::freetype_engine::get_mapping();
bool found_dejavu = false;
for (auto const& item : name2file)
{
found_dejavu = true;
REQUIRE( item.second.first == 0 );
REQUIRE( item.second.second == dejavu_bold_oblique );
if (item.first == "DejaVu Sans Mono Bold Oblique")
{
found_dejavu = true;
REQUIRE(item.second.first == 0);
REQUIRE(item.second.second == dejavu_bold_oblique);
}
}
}
REQUIRE( found_dejavu );
REQUIRE(found_dejavu);
// recurse to find all dejavu fonts
REQUIRE( mapnik::freetype_engine::register_fonts(fontdir, true) );
face_names = mapnik::freetype_engine::face_names();
REQUIRE( face_names.size() == 22 );
// recurse to find all dejavu fonts
REQUIRE(mapnik::freetype_engine::register_fonts(fontdir, true));
face_names = mapnik::freetype_engine::face_names();
REQUIRE(face_names.size() == 22);
// we should have re-registered 'DejaVu Sans Mono Bold Oblique' again,
// but now at a new path
bool found_dejavu2 = false;
for (auto const& item : name2file)
// we should have re-registered 'DejaVu Sans Mono Bold Oblique' again,
// but now at a new path
bool found_dejavu2 = false;
for (auto const& item : name2file)
{
if (item.first == "DejaVu Sans Mono Bold Oblique")
{
found_dejavu2 = true;
REQUIRE(item.second.first == 0);
// path should be different
REQUIRE(item.second.second != dejavu_bold_oblique);
}
}
REQUIRE(found_dejavu2);
// now that global registry is populated
// now test that a map only loads new fonts
mapnik::Map m4(1, 1);
REQUIRE(m4.register_fonts(fontdir, true));
REQUIRE(m4.get_font_memory_cache().size() == 0);
REQUIRE(m4.get_font_file_mapping().size() == 22);
REQUIRE(!m4.load_fonts());
REQUIRE(m4.get_font_memory_cache().size() == 0);
REQUIRE(m4.register_fonts(dejavu_bold_oblique, false));
REQUIRE(m4.load_fonts());
REQUIRE(m4.get_font_memory_cache().size() == 1);
// check that we can correctly read a .ttc containing
// multiple valid faces
// https://github.com/mapnik/mapnik/issues/2274
REQUIRE(mapnik::freetype_engine::register_font("test/data/fonts/NotoSans-Regular.ttc"));
face_names = mapnik::freetype_engine::face_names();
REQUIRE(face_names.size() == 24);
// now blindly register as many system fonts as possible
// the goal here to make sure we don't crash
// linux
mapnik::freetype_engine::register_fonts("/usr/share/fonts/", true);
mapnik::freetype_engine::register_fonts("/usr/local/share/fonts/", true);
// osx
mapnik::freetype_engine::register_fonts("/Library/Fonts/", true);
mapnik::freetype_engine::register_fonts("/System/Library/Fonts/", true);
// windows
mapnik::freetype_engine::register_fonts("C:\\Windows\\Fonts", true);
face_names = mapnik::freetype_engine::face_names();
REQUIRE(face_names.size() > 22);
} catch (std::exception const& ex)
{
if (item.first == "DejaVu Sans Mono Bold Oblique")
{
found_dejavu2 = true;
REQUIRE( item.second.first == 0 );
// path should be different
REQUIRE( item.second.second != dejavu_bold_oblique );
}
std::clog << ex.what() << "\n";
REQUIRE(false);
}
REQUIRE( found_dejavu2 );
// now that global registry is populated
// now test that a map only loads new fonts
mapnik::Map m4(1,1);
REQUIRE( m4.register_fonts(fontdir , true ) );
REQUIRE( m4.get_font_memory_cache().size() == 0 );
REQUIRE( m4.get_font_file_mapping().size() == 22 );
REQUIRE( !m4.load_fonts() );
REQUIRE( m4.get_font_memory_cache().size() == 0 );
REQUIRE( m4.register_fonts(dejavu_bold_oblique, false) );
REQUIRE( m4.load_fonts() );
REQUIRE( m4.get_font_memory_cache().size() == 1 );
// check that we can correctly read a .ttc containing
// multiple valid faces
// https://github.com/mapnik/mapnik/issues/2274
REQUIRE( mapnik::freetype_engine::register_font("test/data/fonts/NotoSans-Regular.ttc") );
face_names = mapnik::freetype_engine::face_names();
REQUIRE( face_names.size() == 24 );
// now blindly register as many system fonts as possible
// the goal here to make sure we don't crash
// linux
mapnik::freetype_engine::register_fonts("/usr/share/fonts/", true);
mapnik::freetype_engine::register_fonts("/usr/local/share/fonts/", true);
// osx
mapnik::freetype_engine::register_fonts("/Library/Fonts/", true);
mapnik::freetype_engine::register_fonts("/System/Library/Fonts/", true);
// windows
mapnik::freetype_engine::register_fonts("C:\\Windows\\Fonts", true);
face_names = mapnik::freetype_engine::face_names();
REQUIRE( face_names.size() > 22 );
}
catch (std::exception const & ex)
{
std::clog << ex.what() << "\n";
REQUIRE(false);
}
}
}

View file

@ -17,17 +17,20 @@ namespace bfs = boost::filesystem;
namespace {
class tmp_dir {
private:
class tmp_dir
{
private:
bfs::path m_path;
public:
public:
tmp_dir()
: m_path(bfs::temp_directory_path() / bfs::unique_path("mapnik-test-%%%%-%%%%-%%%%-%%%%")) {
: m_path(bfs::temp_directory_path() / bfs::unique_path("mapnik-test-%%%%-%%%%-%%%%-%%%%"))
{
bfs::create_directories(m_path);
}
~tmp_dir() {
~tmp_dir()
{
// files might be deleted by other things while the test is
// running, which isn't necessarily an error as far as this
// code is concerned - it just wants to delete everything
@ -35,38 +38,40 @@ public:
boost::system::error_code err;
// catch all errors - we don't want to throw in the destructor
try {
try
{
// but loop while the path exists and the errors are
// ignorable.
while (bfs::exists(m_path)) {
while (bfs::exists(m_path))
{
bfs::remove_all(m_path, err);
// for any non-ignorable error, there's not much we can
// do from the destructor. it's in /tmp anyway, so it'll
// get reclaimed next boot.
if (err && (err != boost::system::errc::no_such_file_or_directory)) {
if (err && (err != boost::system::errc::no_such_file_or_directory))
{
break;
}
}
} catch (const std::exception &e) {
} catch (const std::exception& e)
{
std::cerr << "Exception caught while trying to remove "
<< "temporary directory " << m_path
<< ": " << e.what() << "\n";
<< "temporary directory " << m_path << ": " << e.what() << "\n";
} catch (...) {
} catch (...)
{
std::cerr << "Unknown exception caught while trying to "
<< "remove temporary directory " << m_path
<< "\n";
<< "remove temporary directory " << m_path << "\n";
}
}
bfs::path path() const {
return m_path;
}
bfs::path path() const { return m_path; }
};
void compare_map(bfs::path xml) {
void compare_map(bfs::path xml)
{
tmp_dir dir;
mapnik::Map m(256, 256);
REQUIRE(m.register_fonts("fonts", true));
@ -94,34 +99,37 @@ void compare_map(bfs::path xml) {
REQUIRE(bfs::is_regular_file(test_map2));
REQUIRE(bfs::file_size(test_map1) == bfs::file_size(test_map2));
std::ifstream in_map1(test_map1.native()), in_map2(test_map2.native());
REQUIRE(std::equal(std::istream_iterator<char>(in_map1), std::istream_iterator<char>(),
REQUIRE(std::equal(std::istream_iterator<char>(in_map1),
std::istream_iterator<char>(),
std::istream_iterator<char>(in_map2)));
}
void add_xml_files(bfs::path dir, std::vector<bfs::path> &xml_files) {
for (auto const &entry : boost::make_iterator_range(
bfs::directory_iterator(dir), bfs::directory_iterator())) {
void add_xml_files(bfs::path dir, std::vector<bfs::path>& xml_files)
{
for (auto const& entry : boost::make_iterator_range(bfs::directory_iterator(dir), bfs::directory_iterator()))
{
auto path = entry.path();
if (path.extension().generic_string() == ".xml") {
if (path.extension().generic_string() == ".xml")
{
xml_files.emplace_back(path);
}
}
}
void load_map(mapnik::Map &m, bfs::path const &path) {
void load_map(mapnik::Map& m, bfs::path const& path)
{
try
{
mapnik::load_map(m, path.generic_string());
}
catch (std::exception const &ex)
} catch (std::exception const& ex)
{
// errors which come from the datasource not being loaded or
// database not being set up aren't really useful - they're
// more likely to be spurious than meaningful, so ignore them.
std::string what = ex.what();
if ((what.find("Could not create datasource") == std::string::npos) &&
(what.find("Postgis Plugin: could not connect to server") == std::string::npos)) {
(what.find("Postgis Plugin: could not connect to server") == std::string::npos))
{
throw;
}
}
@ -129,9 +137,11 @@ void load_map(mapnik::Map &m, bfs::path const &path) {
} // anonymous namespace
const bool registered = mapnik::datasource_cache::instance().register_datasources((bfs::path("plugins") / "input").generic_string());
const bool registered =
mapnik::datasource_cache::instance().register_datasources((bfs::path("plugins") / "input").generic_string());
TEST_CASE("map xml I/O") {
TEST_CASE("map xml I/O")
{
// make sure plugins are loaded
REQUIRE(registered);
@ -139,11 +149,13 @@ TEST_CASE("map xml I/O") {
auto const severity = mapnik::logger::instance().get_severity();
mapnik::logger::instance().set_severity(mapnik::logger::none);
SECTION("good maps") {
SECTION("good maps")
{
std::vector<bfs::path> good_maps;
add_xml_files(bfs::path("test") / "data" / "good_maps", good_maps);
for (auto const &path : good_maps) {
for (auto const& path : good_maps)
{
CAPTURE(path.generic_string());
// check that it can load
@ -156,8 +168,10 @@ TEST_CASE("map xml I/O") {
}
} // END SECTION
SECTION("duplicate styles only throw in strict mode") {
std::string duplicate_stylename((bfs::path("test") / "data" / "broken_maps" / "duplicate_stylename.xml").generic_string());
SECTION("duplicate styles only throw in strict mode")
{
std::string duplicate_stylename(
(bfs::path("test") / "data" / "broken_maps" / "duplicate_stylename.xml").generic_string());
CAPTURE(duplicate_stylename);
mapnik::Map m(256, 256);
REQUIRE(m.register_fonts("fonts", true));
@ -167,12 +181,14 @@ TEST_CASE("map xml I/O") {
REQUIRE_THROWS(mapnik::load_map(m2, duplicate_stylename, true));
} // END SECTION
SECTION("broken maps") {
SECTION("broken maps")
{
std::vector<bfs::path> broken_maps;
add_xml_files(bfs::path("test") / "data" / "broken_maps", broken_maps);
broken_maps.emplace_back(bfs::path("test") / "data" / "broken_maps" / "does_not_exist.xml");
for (auto const &path : broken_maps) {
for (auto const& path : broken_maps)
{
CAPTURE(path.generic_string());
mapnik::Map m(256, 256);

View file

@ -7,16 +7,16 @@
#include <sstream>
TEST_CASE("CSS color") {
TEST_CASE("CSS color")
{
SECTION("conversions")
{
using namespace mapnik::css_color_grammar;
CHECK( percent_converter::call(1.0) == 3 );
CHECK( percent_converter::call(60.0) == 153 );
CHECK(percent_converter::call(1.0) == 3);
CHECK(percent_converter::call(60.0) == 153);
// should not overflow on invalid input
CHECK( percent_converter::call(100000.0) == 255 );
CHECK( percent_converter::call(-100000.0) == 0 );
CHECK(percent_converter::call(100000.0) == 255);
CHECK(percent_converter::call(-100000.0) == 0);
}
SECTION("CSS colors")
@ -27,61 +27,61 @@ TEST_CASE("CSS color") {
// rgb
std::string s("rgb(128,0,255)");
mapnik::color c;
CHECK( boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c) );
CHECK( c.alpha() == 0xff );
CHECK( c.red() == 0x80 );
CHECK( c.green() == 0x00 );
CHECK( c.blue() == 0xff );
CHECK(boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c));
CHECK(c.alpha() == 0xff);
CHECK(c.red() == 0x80);
CHECK(c.green() == 0x00);
CHECK(c.blue() == 0xff);
}
{
// rgb (percent)
std::string s("rgb(50%,0%,100%)");
mapnik::color c;
CHECK( boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c) );
CHECK( c.alpha() == 0xff );
CHECK( c.red() == 0x80 );
CHECK( c.green() == 0x00 );
CHECK( c.blue() == 0xff );
CHECK(boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c));
CHECK(c.alpha() == 0xff);
CHECK(c.red() == 0x80);
CHECK(c.green() == 0x00);
CHECK(c.blue() == 0xff);
}
{
// rgba
std::string s("rgba(128,0,255,0.5)");
mapnik::color c;
CHECK( boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c) );
CHECK( c.alpha() == 0x80 );
CHECK( c.red() == 0x80 );
CHECK( c.green() == 0x00 );
CHECK( c.blue() == 0xff );
CHECK(boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c));
CHECK(c.alpha() == 0x80);
CHECK(c.red() == 0x80);
CHECK(c.green() == 0x00);
CHECK(c.blue() == 0xff);
}
{
// rgba (percent)
std::string s("rgba(50%,0%,100%,0.5)");
mapnik::color c;
CHECK( boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c) );
CHECK( c.alpha() == 0x80 );
CHECK( c.red() == 0x80 );
CHECK( c.green() == 0x00 );
CHECK( c.blue() == 0xff );
CHECK(boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c));
CHECK(c.alpha() == 0x80);
CHECK(c.red() == 0x80);
CHECK(c.green() == 0x00);
CHECK(c.blue() == 0xff);
}
{
// named colours
std::string s("darksalmon");
mapnik::color c;
CHECK( boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c) );
CHECK( c.alpha() == 255 );
CHECK( c.red() == 233 );
CHECK( c.green() == 150 );
CHECK( c.blue() == 122 );
CHECK(boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c));
CHECK(c.alpha() == 255);
CHECK(c.red() == 233);
CHECK(c.green() == 150);
CHECK(c.blue() == 122);
}
// hsl
{
std::string s("hsl(240,50%,50%)");
mapnik::color c;
CHECK( boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c) );
CHECK( c.alpha() == 255 );
CHECK( c.red() == 64 );
CHECK( c.green() == 64 );
CHECK( c.blue() == 191 );
CHECK(boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c));
CHECK(c.alpha() == 255);
CHECK(c.red() == 64);
CHECK(c.green() == 64);
CHECK(c.blue() == 191);
}
// hsl (hue range 0..360)
{
@ -93,12 +93,12 @@ TEST_CASE("CSS color") {
std::string s6("hsl(600, 100%, 50%)"); // normalised to fit into 0..360
mapnik::color c1, c2, c3, c4, c5, c6;
CHECK( boost::spirit::x3::phrase_parse(s1.cbegin(), s1.cend(), color_grammar, space, c1) );
CHECK( boost::spirit::x3::phrase_parse(s2.cbegin(), s2.cend(), color_grammar, space, c2) );
CHECK( boost::spirit::x3::phrase_parse(s3.cbegin(), s3.cend(), color_grammar, space, c3) );
CHECK( boost::spirit::x3::phrase_parse(s4.cbegin(), s4.cend(), color_grammar, space, c4) );
CHECK( boost::spirit::x3::phrase_parse(s5.cbegin(), s5.cend(), color_grammar, space, c5) );
CHECK( boost::spirit::x3::phrase_parse(s6.cbegin(), s6.cend(), color_grammar, space, c6) );
CHECK(boost::spirit::x3::phrase_parse(s1.cbegin(), s1.cend(), color_grammar, space, c1));
CHECK(boost::spirit::x3::phrase_parse(s2.cbegin(), s2.cend(), color_grammar, space, c2));
CHECK(boost::spirit::x3::phrase_parse(s3.cbegin(), s3.cend(), color_grammar, space, c3));
CHECK(boost::spirit::x3::phrase_parse(s4.cbegin(), s4.cend(), color_grammar, space, c4));
CHECK(boost::spirit::x3::phrase_parse(s5.cbegin(), s5.cend(), color_grammar, space, c5));
CHECK(boost::spirit::x3::phrase_parse(s6.cbegin(), s6.cend(), color_grammar, space, c6));
CHECK(c1 == mapnik::color("red"));
CHECK(c2 == mapnik::color("lime"));
CHECK(c3 == mapnik::color("blue"));
@ -110,11 +110,11 @@ TEST_CASE("CSS color") {
{
std::string s("hsla(240,50%,50%,0.5)");
mapnik::color c;
CHECK( boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c) );
CHECK( c.alpha() == 128 );
CHECK( c.red() == 64 );
CHECK( c.green() == 64 );
CHECK( c.blue() == 191 );
CHECK(boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c));
CHECK(c.alpha() == 128);
CHECK(c.red() == 64);
CHECK(c.green() == 64);
CHECK(c.blue() == 191);
}
// hsla (hue range 0..360)
{
@ -126,12 +126,12 @@ TEST_CASE("CSS color") {
std::string s6("hsla(600, 100%, 50%, 1)"); // normalised to fit into 0..360
mapnik::color c1, c2, c3, c4, c5, c6;
CHECK( boost::spirit::x3::phrase_parse(s1.cbegin(), s1.cend(), color_grammar, space, c1) );
CHECK( boost::spirit::x3::phrase_parse(s2.cbegin(), s2.cend(), color_grammar, space, c2) );
CHECK( boost::spirit::x3::phrase_parse(s3.cbegin(), s3.cend(), color_grammar, space, c3) );
CHECK( boost::spirit::x3::phrase_parse(s4.cbegin(), s4.cend(), color_grammar, space, c4) );
CHECK( boost::spirit::x3::phrase_parse(s5.cbegin(), s5.cend(), color_grammar, space, c5) );
CHECK( boost::spirit::x3::phrase_parse(s6.cbegin(), s6.cend(), color_grammar, space, c6) );
CHECK(boost::spirit::x3::phrase_parse(s1.cbegin(), s1.cend(), color_grammar, space, c1));
CHECK(boost::spirit::x3::phrase_parse(s2.cbegin(), s2.cend(), color_grammar, space, c2));
CHECK(boost::spirit::x3::phrase_parse(s3.cbegin(), s3.cend(), color_grammar, space, c3));
CHECK(boost::spirit::x3::phrase_parse(s4.cbegin(), s4.cend(), color_grammar, space, c4));
CHECK(boost::spirit::x3::phrase_parse(s5.cbegin(), s5.cend(), color_grammar, space, c5));
CHECK(boost::spirit::x3::phrase_parse(s6.cbegin(), s6.cend(), color_grammar, space, c6));
CHECK(c1 == mapnik::color("red"));
CHECK(c2 == mapnik::color("lime"));
CHECK(c3 == mapnik::color("blue"));
@ -143,64 +143,64 @@ TEST_CASE("CSS color") {
{
std::string s("#abcdef");
mapnik::color c;
CHECK( boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c) );
CHECK( c.alpha() == 0xff );
CHECK( c.red() == 0xab );
CHECK( c.green() == 0xcd );
CHECK( c.blue() == 0xef );
CHECK(boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c));
CHECK(c.alpha() == 0xff);
CHECK(c.red() == 0xab);
CHECK(c.green() == 0xcd);
CHECK(c.blue() == 0xef);
}
{
std::string s("#abcdef12");
mapnik::color c;
CHECK( boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c) );
CHECK( c.alpha() == 0x12 );
CHECK( c.red() == 0xab );
CHECK( c.green() == 0xcd );
CHECK( c.blue() == 0xef );
CHECK(boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c));
CHECK(c.alpha() == 0x12);
CHECK(c.red() == 0xab);
CHECK(c.green() == 0xcd);
CHECK(c.blue() == 0xef);
}
{
std::string s(" #abcdef");
mapnik::color c;
CHECK( boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c) );
CHECK( c.alpha() == 0xff );
CHECK( c.red() == 0xab );
CHECK( c.green() == 0xcd );
CHECK( c.blue() == 0xef );
CHECK(boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c));
CHECK(c.alpha() == 0xff);
CHECK(c.red() == 0xab);
CHECK(c.green() == 0xcd);
CHECK(c.blue() == 0xef);
}
{
std::string s(" #abcdef12");
mapnik::color c;
CHECK( boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c) );
CHECK( c.alpha() == 0x12 );
CHECK( c.red() == 0xab );
CHECK( c.green() == 0xcd );
CHECK( c.blue() == 0xef );
CHECK(boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c));
CHECK(c.alpha() == 0x12);
CHECK(c.red() == 0xab);
CHECK(c.green() == 0xcd);
CHECK(c.blue() == 0xef);
}
{
std::string s("# abcdef");
mapnik::color c;
CHECK( !boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c) );
CHECK(!boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c));
}
{
std::string s("# abcdef12");
mapnik::color c;
CHECK( !boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c) );
CHECK(!boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c));
}
{
std::string s("#ab cdef");
mapnik::color c;
CHECK( !boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c) );
CHECK(!boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c));
}
{
std::string s("#ab cdef12");
mapnik::color c;
CHECK( !boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c) );
CHECK(!boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c));
}
// hex_color_small
@ -208,65 +208,65 @@ TEST_CASE("CSS color") {
{
std::string s("#abc");
mapnik::color c;
CHECK( boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c) );
CHECK( c.alpha() == 0xff );
CHECK( c.red() == 0xaa );
CHECK( c.green() == 0xbb );
CHECK( c.blue() == 0xcc );
CHECK(boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c));
CHECK(c.alpha() == 0xff);
CHECK(c.red() == 0xaa);
CHECK(c.green() == 0xbb);
CHECK(c.blue() == 0xcc);
}
{
std::string s("#abcd");
mapnik::color c;
CHECK( boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c) );
CHECK( c.alpha() == 0xdd );
CHECK( c.red() == 0xaa );
CHECK( c.green() == 0xbb );
CHECK( c.blue() == 0xcc );
CHECK(boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c));
CHECK(c.alpha() == 0xdd);
CHECK(c.red() == 0xaa);
CHECK(c.green() == 0xbb);
CHECK(c.blue() == 0xcc);
}
{
std::string s(" #abc");
mapnik::color c;
CHECK( boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c) );
CHECK( c.alpha() == 0xff );
CHECK( c.red() == 0xaa );
CHECK( c.green() == 0xbb );
CHECK( c.blue() == 0xcc );
CHECK(boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c));
CHECK(c.alpha() == 0xff);
CHECK(c.red() == 0xaa);
CHECK(c.green() == 0xbb);
CHECK(c.blue() == 0xcc);
}
{
std::string s(" #abcd");
mapnik::color c;
CHECK( boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c) );
CHECK( c.alpha() == 0xdd );
CHECK( c.red() == 0xaa );
CHECK( c.green() == 0xbb );
CHECK( c.blue() == 0xcc );
CHECK(boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c));
CHECK(c.alpha() == 0xdd);
CHECK(c.red() == 0xaa);
CHECK(c.green() == 0xbb);
CHECK(c.blue() == 0xcc);
}
{
std::string s("# abc");
mapnik::color c;
CHECK( !boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c) );
CHECK(!boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c));
}
{
std::string s("# abcd");
mapnik::color c;
CHECK( !boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c) );
CHECK(!boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c));
}
{
std::string s("#a bc");
mapnik::color c;
CHECK( !boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c) );
CHECK(!boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c));
}
{
std::string s("#a bcd");
mapnik::color c;
CHECK( !boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c) );
CHECK(!boost::spirit::x3::phrase_parse(s.cbegin(), s.cend(), color_grammar, space, c));
}
}
@ -274,11 +274,11 @@ TEST_CASE("CSS color") {
{
mapnik::color c("salmon");
std::ostringstream ss;
ss << c ;
ss << c;
CHECK(ss.str() == "rgb(250,128,114)");
c.set_alpha(127);
ss.seekp(0);
ss << c ;
ss << c;
CHECK(ss.str() == "rgba(250,128,114,0.498)");
}
SECTION("operator= operator==")

View file

@ -4,218 +4,225 @@
#include <mapnik/geometry/box2d.hpp>
#include "agg_trans_affine.h"
TEST_CASE("box2d") {
SECTION("coord init") {
auto c = mapnik::coord2d(100, 100);
REQUIRE(c.x == 100);
REQUIRE(c.y == 100);
}
SECTION("coord multiplication") {
auto c = mapnik::coord2d(100, 100);
c *= 2;
REQUIRE(c.x == 200);
REQUIRE(c.y == 200);
}
SECTION("envelope init") {
auto e = mapnik::box2d<double>(100, 100, 200, 200);
REQUIRE(e.contains(100, 100));
REQUIRE(e.contains(100, 200));
REQUIRE(e.contains(200, 200));
REQUIRE(e.contains(200, 100));
REQUIRE(e.contains(e.center()));
REQUIRE(!e.contains(99.9, 99.9));
REQUIRE(!e.contains(99.9, 200.1));
REQUIRE(!e.contains(200.1, 200.1));
REQUIRE(!e.contains(200.1, 99.9));
REQUIRE(e.width() == 100);
REQUIRE(e.height() == 100);
REQUIRE(e.minx() == 100);
REQUIRE(e.miny() == 100);
REQUIRE(e.maxx() == 200);
REQUIRE(e.maxy() == 200);
REQUIRE(e[0] == 100);
REQUIRE(e[1] == 100);
REQUIRE(e[2] == 200);
REQUIRE(e[3] == 200);
REQUIRE(e[0] == e[-4]);
REQUIRE(e[1] == e[-3]);
REQUIRE(e[2] == e[-2]);
REQUIRE(e[3] == e[-1]);
auto c = e.center();
REQUIRE(c.x == 150);
REQUIRE(c.y == 150);
}
SECTION("envelope static init") {
auto e = mapnik::box2d<double>(100, 100, 200, 200);
mapnik::box2d<double> e1, e2, e3;
REQUIRE(e1.from_string("100 100 200 200"));
REQUIRE(e2.from_string("100,100,200,200"));
REQUIRE(e3.from_string("100 , 100 , 200 , 200"));
REQUIRE(e == e1);
REQUIRE(e == e2);
REQUIRE(e == e3);
}
SECTION("envelope multiplication") {
// no width then no impact of multiplication
{
auto a = mapnik::box2d<int>(100, 100, 100, 100);
a *= 5;
REQUIRE(a.minx() == 100);
REQUIRE(a.miny() == 100);
REQUIRE(a.maxx() == 100);
REQUIRE(a.maxy() == 100);
}
{
auto a = mapnik::box2d<double>(100.0, 100.0, 100.0, 100.0);
a *= 5;
REQUIRE(a.minx() == 100);
REQUIRE(a.miny() == 100);
REQUIRE(a.maxx() == 100);
REQUIRE(a.maxy() == 100);
}
{
auto a = mapnik::box2d<double>(100.0, 100.0, 100.001, 100.001);
a *= 5;
REQUIRE(a.minx() == Approx( 99.9980));
REQUIRE(a.miny() == Approx( 99.9980));
REQUIRE(a.maxx() == Approx(100.0030));
REQUIRE(a.maxy() == Approx(100.0030));
}
{
auto e = mapnik::box2d<double>(100, 100, 200, 200);
e *= 2;
REQUIRE(e.minx() == 50);
REQUIRE(e.miny() == 50);
REQUIRE(e.maxx() == 250);
REQUIRE(e.maxy() == 250);
REQUIRE(e.contains(50, 50));
REQUIRE(e.contains(50, 250));
REQUIRE(e.contains(250, 250));
REQUIRE(e.contains(250, 50));
REQUIRE(!e.contains(49.9, 49.9));
REQUIRE(!e.contains(49.9, 250.1));
REQUIRE(!e.contains(250.1, 250.1));
REQUIRE(!e.contains(250.1, 49.9));
REQUIRE(e.contains(e.center()));
REQUIRE(e.width() == 200);
REQUIRE(e.height() == 200);
REQUIRE(e.minx() == 50);
REQUIRE(e.miny() == 50);
REQUIRE(e.maxx() == 250);
REQUIRE(e.maxy() == 250);
auto c = e.center();
REQUIRE(c.x == 150);
REQUIRE(c.y == 150);
}
}
SECTION("envelope clipping") {
auto e1 = mapnik::box2d<double>(-180,-90,180,90);
auto e2 = mapnik::box2d<double>(-120,40,-110,48);
e1.clip(e2);
REQUIRE(e1 == e2);
// madagascar in merc
e1 = mapnik::box2d<double>(4772116.5490, -2744395.0631, 5765186.4203, -1609458.0673);
e2 = mapnik::box2d<double>(5124338.3753, -2240522.1727, 5207501.8621, -2130452.8520);
e1.clip(e2);
REQUIRE(e1 == e2);
// nz in lon/lat
e1 = mapnik::box2d<double>(163.8062, -47.1897, 179.3628, -33.9069);
e2 = mapnik::box2d<double>(173.7378, -39.6395, 174.4849, -38.9252);
e1.clip(e2);
REQUIRE(e1 == e2);
}
SECTION("mapnik::box2d intersects")
TEST_CASE("box2d")
{
mapnik::box2d<double> b0(0,0,100,100);
// another box2d
mapnik::box2d<double> b1(100,100,200,200);
CHECK(b0.intersects(b1));
CHECK(b1.intersects(b0));
mapnik::box2d<double> b2(100.001,100,200,200);
CHECK(!b0.intersects(b2));
CHECK(!b2.intersects(b0));
// coord
CHECK(b0.intersects(mapnik::coord<double,2>(100,100)));
CHECK(!b0.intersects(mapnik::coord<double,2>(100.001,100)));
}
SECTION("coord init")
{
auto c = mapnik::coord2d(100, 100);
SECTION("mapnik::box2d intersect")
{
mapnik::box2d<double> b0(0,0,100,100);
mapnik::box2d<double> b1(100,100,200,200);
CHECK(b0.intersect(b1) == mapnik::box2d<double>(100,100,100,100));
CHECK(b1.intersect(b0) == mapnik::box2d<double>(100,100,100,100));
mapnik::box2d<double> b2(100.001,100,200,200);
CHECK(b0.intersect(b2) == mapnik::box2d<double>());
CHECK(b2.intersect(b0) == mapnik::box2d<double>());
}
REQUIRE(c.x == 100);
REQUIRE(c.y == 100);
}
SECTION("mapnik::box2d re_center")
{
mapnik::box2d<double> b(0, 0, 100, 100);
b.re_center(0, 0);
CHECK(b == mapnik::box2d<double>(-50, -50, 50, 50));
b.re_center(mapnik::coord2d(50,50));
CHECK(b == mapnik::box2d<double>(0, 0, 100, 100));
}
SECTION("coord multiplication")
{
auto c = mapnik::coord2d(100, 100);
c *= 2;
SECTION("mapnik::box2d operator+=")
{
mapnik::box2d<double> b(0, 0, 50, 50);
b += mapnik::box2d<double>(100, 100, 200, 200);
CHECK(b == mapnik::box2d<double>(0, 0, 200, 200));
b += 100;
CHECK(b == mapnik::box2d<double>(-100, -100, 300, 300));
}
REQUIRE(c.x == 200);
REQUIRE(c.y == 200);
}
SECTION("mapnik::box2d operator*= operator=/ ")
{
mapnik::box2d<double> b(0, 0, 100, 100);
b *= 2.0;
CHECK(b == mapnik::box2d<double>(-50, -50, 150, 150));
b /= 2.0;
CHECK(b == mapnik::box2d<double>(0, 0, 100, 100));
SECTION("envelope init")
{
auto e = mapnik::box2d<double>(100, 100, 200, 200);
agg::trans_affine tr;
tr.translate(-50,-50);
tr.scale(2.0);
b *= tr;
CHECK(b == mapnik::box2d<double>(-100, -100, 100, 100));
}
REQUIRE(e.contains(100, 100));
REQUIRE(e.contains(100, 200));
REQUIRE(e.contains(200, 200));
REQUIRE(e.contains(200, 100));
REQUIRE(e.contains(e.center()));
REQUIRE(!e.contains(99.9, 99.9));
REQUIRE(!e.contains(99.9, 200.1));
REQUIRE(!e.contains(200.1, 200.1));
REQUIRE(!e.contains(200.1, 99.9));
REQUIRE(e.width() == 100);
REQUIRE(e.height() == 100);
REQUIRE(e.minx() == 100);
REQUIRE(e.miny() == 100);
REQUIRE(e.maxx() == 200);
REQUIRE(e.maxy() == 200);
REQUIRE(e[0] == 100);
REQUIRE(e[1] == 100);
REQUIRE(e[2] == 200);
REQUIRE(e[3] == 200);
REQUIRE(e[0] == e[-4]);
REQUIRE(e[1] == e[-3]);
REQUIRE(e[2] == e[-2]);
REQUIRE(e[3] == e[-1]);
auto c = e.center();
REQUIRE(c.x == 150);
REQUIRE(c.y == 150);
}
SECTION("envelope static init")
{
auto e = mapnik::box2d<double>(100, 100, 200, 200);
mapnik::box2d<double> e1, e2, e3;
REQUIRE(e1.from_string("100 100 200 200"));
REQUIRE(e2.from_string("100,100,200,200"));
REQUIRE(e3.from_string("100 , 100 , 200 , 200"));
REQUIRE(e == e1);
REQUIRE(e == e2);
REQUIRE(e == e3);
}
SECTION("envelope multiplication")
{
// no width then no impact of multiplication
{
auto a = mapnik::box2d<int>(100, 100, 100, 100);
a *= 5;
REQUIRE(a.minx() == 100);
REQUIRE(a.miny() == 100);
REQUIRE(a.maxx() == 100);
REQUIRE(a.maxy() == 100);
}
{
auto a = mapnik::box2d<double>(100.0, 100.0, 100.0, 100.0);
a *= 5;
REQUIRE(a.minx() == 100);
REQUIRE(a.miny() == 100);
REQUIRE(a.maxx() == 100);
REQUIRE(a.maxy() == 100);
}
{
auto a = mapnik::box2d<double>(100.0, 100.0, 100.001, 100.001);
a *= 5;
REQUIRE(a.minx() == Approx(99.9980));
REQUIRE(a.miny() == Approx(99.9980));
REQUIRE(a.maxx() == Approx(100.0030));
REQUIRE(a.maxy() == Approx(100.0030));
}
{
auto e = mapnik::box2d<double>(100, 100, 200, 200);
e *= 2;
REQUIRE(e.minx() == 50);
REQUIRE(e.miny() == 50);
REQUIRE(e.maxx() == 250);
REQUIRE(e.maxy() == 250);
REQUIRE(e.contains(50, 50));
REQUIRE(e.contains(50, 250));
REQUIRE(e.contains(250, 250));
REQUIRE(e.contains(250, 50));
REQUIRE(!e.contains(49.9, 49.9));
REQUIRE(!e.contains(49.9, 250.1));
REQUIRE(!e.contains(250.1, 250.1));
REQUIRE(!e.contains(250.1, 49.9));
REQUIRE(e.contains(e.center()));
REQUIRE(e.width() == 200);
REQUIRE(e.height() == 200);
REQUIRE(e.minx() == 50);
REQUIRE(e.miny() == 50);
REQUIRE(e.maxx() == 250);
REQUIRE(e.maxy() == 250);
auto c = e.center();
REQUIRE(c.x == 150);
REQUIRE(c.y == 150);
}
}
SECTION("envelope clipping")
{
auto e1 = mapnik::box2d<double>(-180, -90, 180, 90);
auto e2 = mapnik::box2d<double>(-120, 40, -110, 48);
e1.clip(e2);
REQUIRE(e1 == e2);
// madagascar in merc
e1 = mapnik::box2d<double>(4772116.5490, -2744395.0631, 5765186.4203, -1609458.0673);
e2 = mapnik::box2d<double>(5124338.3753, -2240522.1727, 5207501.8621, -2130452.8520);
e1.clip(e2);
REQUIRE(e1 == e2);
// nz in lon/lat
e1 = mapnik::box2d<double>(163.8062, -47.1897, 179.3628, -33.9069);
e2 = mapnik::box2d<double>(173.7378, -39.6395, 174.4849, -38.9252);
e1.clip(e2);
REQUIRE(e1 == e2);
}
SECTION("mapnik::box2d intersects")
{
mapnik::box2d<double> b0(0, 0, 100, 100);
// another box2d
mapnik::box2d<double> b1(100, 100, 200, 200);
CHECK(b0.intersects(b1));
CHECK(b1.intersects(b0));
mapnik::box2d<double> b2(100.001, 100, 200, 200);
CHECK(!b0.intersects(b2));
CHECK(!b2.intersects(b0));
// coord
CHECK(b0.intersects(mapnik::coord<double, 2>(100, 100)));
CHECK(!b0.intersects(mapnik::coord<double, 2>(100.001, 100)));
}
SECTION("mapnik::box2d intersect")
{
mapnik::box2d<double> b0(0, 0, 100, 100);
mapnik::box2d<double> b1(100, 100, 200, 200);
CHECK(b0.intersect(b1) == mapnik::box2d<double>(100, 100, 100, 100));
CHECK(b1.intersect(b0) == mapnik::box2d<double>(100, 100, 100, 100));
mapnik::box2d<double> b2(100.001, 100, 200, 200);
CHECK(b0.intersect(b2) == mapnik::box2d<double>());
CHECK(b2.intersect(b0) == mapnik::box2d<double>());
}
SECTION("mapnik::box2d re_center")
{
mapnik::box2d<double> b(0, 0, 100, 100);
b.re_center(0, 0);
CHECK(b == mapnik::box2d<double>(-50, -50, 50, 50));
b.re_center(mapnik::coord2d(50, 50));
CHECK(b == mapnik::box2d<double>(0, 0, 100, 100));
}
SECTION("mapnik::box2d operator+=")
{
mapnik::box2d<double> b(0, 0, 50, 50);
b += mapnik::box2d<double>(100, 100, 200, 200);
CHECK(b == mapnik::box2d<double>(0, 0, 200, 200));
b += 100;
CHECK(b == mapnik::box2d<double>(-100, -100, 300, 300));
}
SECTION("mapnik::box2d operator*= operator=/ ")
{
mapnik::box2d<double> b(0, 0, 100, 100);
b *= 2.0;
CHECK(b == mapnik::box2d<double>(-50, -50, 150, 150));
b /= 2.0;
CHECK(b == mapnik::box2d<double>(0, 0, 100, 100));
agg::trans_affine tr;
tr.translate(-50, -50);
tr.scale(2.0);
b *= tr;
CHECK(b == mapnik::box2d<double>(-100, -100, 100, 100));
}
} // TEST_CASE

View file

@ -7,9 +7,9 @@ TEST_CASE("comparison")
{
SECTION("operator==()")
{
mapnik::value v0 = 1; // mapnik::value_integer
mapnik::value v0 = 1; // mapnik::value_integer
mapnik::value v1 = 1.001; // mapnik::value_double
mapnik::value v2 = true; // mapnik::value_boolean
mapnik::value v2 = true; // mapnik::value_boolean
CHECK(v0.is<mapnik::value_integer>());
CHECK(v1.is<mapnik::value_double>());
@ -27,9 +27,9 @@ TEST_CASE("comparison")
SECTION("operator!=()")
{
mapnik::value v0 = 1; // mapnik::value_integer
mapnik::value v1 = 1.001; // mapnik::value_double
mapnik::value v2 = true; // mapnik::value_boolean
mapnik::value v0 = 1; // mapnik::value_integer
mapnik::value v1 = 1.001; // mapnik::value_double
mapnik::value v2 = true; // mapnik::value_boolean
mapnik::value v3 = mapnik::value_null(); //
CHECK(v0.is<mapnik::value_integer>());
@ -52,7 +52,6 @@ TEST_CASE("comparison")
REQUIRE(v0 != v3);
REQUIRE(v1 != v3);
REQUIRE(v2 != v3);
}
SECTION("operator<,<=,>,>=")
{

View file

@ -13,300 +13,298 @@
#include <cstdio>
#endif
TEST_CASE("conversions") {
SECTION("to string") {
#if defined(_MSC_VER) && _MSC_VER < 1900
unsigned int old = _set_output_format(_TWO_DIGIT_EXPONENT);
#endif
using mapnik::util::to_string;
using mapnik::util::string2bool;
try
TEST_CASE("conversions")
{
SECTION("to string")
{
std::string out;
#if defined(_MSC_VER) && _MSC_VER < 1900
unsigned int old = _set_output_format(_TWO_DIGIT_EXPONENT);
#endif
// Test double
to_string(out, double(0));
REQUIRE( out == "0" );
out.clear();
using mapnik::util::string2bool;
using mapnik::util::to_string;
to_string(out, double(1));
REQUIRE( out == "1" );
out.clear();
try
{
std::string out;
to_string(out, double(-1));
REQUIRE( out == "-1" );
out.clear();
// Test double
to_string(out, double(0));
REQUIRE(out == "0");
out.clear();
to_string(out, double(0.1));
REQUIRE( out == "0.1" );
out.clear();
to_string(out, double(1));
REQUIRE(out == "1");
out.clear();
to_string(out, double(-0.1));
REQUIRE( out == "-0.1" );
out.clear();
to_string(out, double(-1));
REQUIRE(out == "-1");
out.clear();
to_string(out, double(0.123));
REQUIRE( out == "0.123" );
out.clear();
to_string(out, double(0.1));
REQUIRE(out == "0.1");
out.clear();
to_string(out, double(-0.123));
REQUIRE( out == "-0.123" );
out.clear();
to_string(out, double(-0.1));
REQUIRE(out == "-0.1");
out.clear();
to_string(out, double(1e-06));
REQUIRE( out == "1e-06" );
out.clear();
to_string(out, double(0.123));
REQUIRE(out == "0.123");
out.clear();
to_string(out, double(-1e-06));
REQUIRE( out == "-1e-06" );
out.clear();
to_string(out, double(-0.123));
REQUIRE(out == "-0.123");
out.clear();
to_string(out, double(1e-05));
REQUIRE( out == "1e-05" );
out.clear();
to_string(out, double(1e-06));
REQUIRE(out == "1e-06");
out.clear();
to_string(out, double(-1e-05));
REQUIRE( out == "-1e-05" );
out.clear();
to_string(out, double(-1e-06));
REQUIRE(out == "-1e-06");
out.clear();
to_string(out, double(0.0001));
REQUIRE( out == "0.0001" );
out.clear();
to_string(out, double(1e-05));
REQUIRE(out == "1e-05");
out.clear();
to_string(out, double(-0.0001));
REQUIRE( out == "-0.0001" );
out.clear();
to_string(out, double(-1e-05));
REQUIRE(out == "-1e-05");
out.clear();
to_string(out, double(0.0001));
REQUIRE( out == "0.0001" );
out.clear();
to_string(out, double(0.0001));
REQUIRE(out == "0.0001");
out.clear();
to_string(out, double(0.00001));
REQUIRE( out == "1e-05" );
out.clear();
to_string(out, double(-0.0001));
REQUIRE(out == "-0.0001");
out.clear();
to_string(out, double(0.000001));
REQUIRE( out == "1e-06" );
out.clear();
to_string(out, double(0.0001));
REQUIRE(out == "0.0001");
out.clear();
to_string(out, double(0.0000001));
REQUIRE( out == "1e-07" );
out.clear();
to_string(out, double(0.00001));
REQUIRE(out == "1e-05");
out.clear();
to_string(out, double(0.00000001));
REQUIRE( out == "1e-08" );
out.clear();
to_string(out, double(0.000001));
REQUIRE(out == "1e-06");
out.clear();
to_string(out, double(0.000000001));
REQUIRE( out == "1e-09" );
out.clear();
to_string(out, double(0.0000001));
REQUIRE(out == "1e-07");
out.clear();
to_string(out, double(0.0000000001));
REQUIRE( out == "1e-10" );
out.clear();
to_string(out, double(0.00000001));
REQUIRE(out == "1e-08");
out.clear();
to_string(out, double(-1.234e+16));
REQUIRE( out == "-1.234e+16" );
out.clear();
to_string(out, double(0.000000001));
REQUIRE(out == "1e-09");
out.clear();
// critical failure when karam is used
// https://github.com/mapnik/mapnik/issues/1741
// https://github.com/mapbox/tilemill/issues/1456
to_string(out, double(8.3));
REQUIRE( out == "8.3" );
out.clear();
to_string(out, double(0.0000000001));
REQUIRE(out == "1e-10");
out.clear();
// non-critical failures if karma is used
to_string(out, double(0.0001234567890123456));
// TODO: https://github.com/mapnik/mapnik/issues/1676
REQUIRE( out == "0.000123457" );
out.clear();
to_string(out, double(-1.234e+16));
REQUIRE(out == "-1.234e+16");
out.clear();
to_string(out, double(0.00000000001));
REQUIRE( out == "1e-11" );
out.clear();
// critical failure when karam is used
// https://github.com/mapnik/mapnik/issues/1741
// https://github.com/mapbox/tilemill/issues/1456
to_string(out, double(8.3));
REQUIRE(out == "8.3");
out.clear();
to_string(out, double(0.000000000001));
REQUIRE( out == "1e-12" );
out.clear();
// non-critical failures if karma is used
to_string(out, double(0.0001234567890123456));
// TODO: https://github.com/mapnik/mapnik/issues/1676
REQUIRE(out == "0.000123457");
out.clear();
to_string(out, double(0.0000000000001));
REQUIRE( out == "1e-13" );
out.clear();
to_string(out, double(0.00000000001));
REQUIRE(out == "1e-11");
out.clear();
to_string(out, double(0.00000000000001));
REQUIRE( out == "1e-14" );
out.clear();
to_string(out, double(0.000000000001));
REQUIRE(out == "1e-12");
out.clear();
to_string(out, double(0.000000000000001));
REQUIRE( out == "1e-15" );
out.clear();
to_string(out, double(0.0000000000001));
REQUIRE(out == "1e-13");
out.clear();
to_string(out, double(100000));
REQUIRE( out == "100000" );
out.clear();
to_string(out, double(0.00000000000001));
REQUIRE(out == "1e-14");
out.clear();
to_string(out, double(1000000));
REQUIRE( out == "1e+06" );
out.clear();
to_string(out, double(0.000000000000001));
REQUIRE(out == "1e-15");
out.clear();
to_string(out, double(10000000));
REQUIRE( out == "1e+07" );
out.clear();
to_string(out, double(100000));
REQUIRE(out == "100000");
out.clear();
to_string(out, double(100000000));
REQUIRE( out == "1e+08" );
out.clear();
to_string(out, double(1000000));
REQUIRE(out == "1e+06");
out.clear();
to_string(out, double(1000000000));
REQUIRE( out == "1e+09" );
out.clear();
to_string(out, double(10000000));
REQUIRE(out == "1e+07");
out.clear();
to_string(out, double(10000000000));
REQUIRE( out == "1e+10" );
out.clear();
to_string(out, double(100000000));
REQUIRE(out == "1e+08");
out.clear();
to_string(out, double(100000000000));
REQUIRE( out == "1e+11" );
out.clear();
to_string(out, double(1000000000));
REQUIRE(out == "1e+09");
out.clear();
to_string(out, double(1000000000000));
REQUIRE( out == "1e+12" );
out.clear();
to_string(out, double(10000000000));
REQUIRE(out == "1e+10");
out.clear();
to_string(out, double(10000000000000));
REQUIRE( out == "1e+13" );
out.clear();
to_string(out, double(100000000000));
REQUIRE(out == "1e+11");
out.clear();
to_string(out, double(100000000000000));
REQUIRE( out == "1e+14" );
out.clear();
to_string(out, double(1000000000000));
REQUIRE(out == "1e+12");
out.clear();
to_string(out, double(1000000000000005));
REQUIRE( out == "1e+15" );
out.clear();
to_string(out, double(10000000000000));
REQUIRE(out == "1e+13");
out.clear();
to_string(out, double(-1000000000000000));
REQUIRE( out == "-1e+15" );
out.clear();
to_string(out, double(100000000000000));
REQUIRE(out == "1e+14");
out.clear();
to_string(out, double(100000000000000.1));
REQUIRE( out == "1e+14" );
out.clear();
to_string(out, double(1000000000000005));
REQUIRE(out == "1e+15");
out.clear();
to_string(out, double(1.00001));
REQUIRE( out == "1.00001" );
out.clear();
to_string(out, double(-1000000000000000));
REQUIRE(out == "-1e+15");
out.clear();
to_string(out, double(67.65));
REQUIRE( out == "67.65" );
out.clear();
to_string(out, double(100000000000000.1));
REQUIRE(out == "1e+14");
out.clear();
to_string(out, double(67.35));
REQUIRE( out == "67.35" );
out.clear();
to_string(out, double(1.00001));
REQUIRE(out == "1.00001");
out.clear();
to_string(out, double(1234000000000000));
REQUIRE( out == "1.234e+15" );
out.clear();
to_string(out, double(67.65));
REQUIRE(out == "67.65");
out.clear();
to_string(out, double(1e+16));
REQUIRE( out == "1e+16" );
out.clear();
to_string(out, double(67.35));
REQUIRE(out == "67.35");
out.clear();
to_string(out, double(1.234e+16));
REQUIRE( out == "1.234e+16" );
out.clear();
to_string(out, double(1234000000000000));
REQUIRE(out == "1.234e+15");
out.clear();
// int
to_string(out, int(2));
REQUIRE( out == "2" );
out.clear();
to_string(out, double(1e+16));
REQUIRE(out == "1e+16");
out.clear();
to_string(out, int(0));
REQUIRE( out == "0" );
out.clear();
to_string(out, double(1.234e+16));
REQUIRE(out == "1.234e+16");
out.clear();
to_string(out, int(-2));
REQUIRE( out == "-2" );
out.clear();
// int
to_string(out, int(2));
REQUIRE(out == "2");
out.clear();
to_string(out, int(2147483647));
REQUIRE( out == "2147483647" );
out.clear();
to_string(out, int(0));
REQUIRE(out == "0");
out.clear();
to_string(out, int(-2147483648));
REQUIRE( out == "-2147483648" );
out.clear();
to_string(out, int(-2));
REQUIRE(out == "-2");
out.clear();
// unsigned
to_string(out, unsigned(4294967295));
REQUIRE( out == "4294967295" );
out.clear();
to_string(out, int(2147483647));
REQUIRE(out == "2147483647");
out.clear();
to_string(out, int(-2147483648));
REQUIRE(out == "-2147483648");
out.clear();
// unsigned
to_string(out, unsigned(4294967295));
REQUIRE(out == "4294967295");
out.clear();
#ifdef BIGINT
// long long
to_string(out,mapnik::value_integer(-0));
REQUIRE( out == "0" );
out.clear();
// long long
to_string(out, mapnik::value_integer(-0));
REQUIRE(out == "0");
out.clear();
to_string(out,mapnik::value_integer(-2));
REQUIRE( out == "-2" );
out.clear();
to_string(out, mapnik::value_integer(-2));
REQUIRE(out == "-2");
out.clear();
to_string(out,mapnik::value_integer(9223372036854775807));
REQUIRE( out == "9223372036854775807" );
out.clear();
to_string(out, mapnik::value_integer(9223372036854775807));
REQUIRE(out == "9223372036854775807");
out.clear();
#else
#ifdef _MSC_VER
#pragma NOTE("BIGINT not defined so skipping large number conversion tests")
#else
#warning BIGINT not defined so skipping large number conversion tests
#endif
#ifdef _MSC_VER
#pragma NOTE("BIGINT not defined so skipping large number conversion tests")
#else
#warning BIGINT not defined so skipping large number conversion tests
#endif
// bool
to_string(out, true);
REQUIRE( out == "true" );
out.clear();
#endif
// bool
to_string(out, true);
REQUIRE(out == "true");
out.clear();
to_string(out, false);
REQUIRE( out == "false" );
out.clear();
to_string(out, false);
REQUIRE(out == "false");
out.clear();
bool val = false;
REQUIRE( !string2bool("this is invalid",val) );
REQUIRE( val == false );
REQUIRE( string2bool("true",val) );
REQUIRE( val == true );
bool val = false;
REQUIRE(!string2bool("this is invalid", val));
REQUIRE(val == false);
REQUIRE(string2bool("true", val));
REQUIRE(val == true);
// mapnik::value hash() and operator== works for all T in value<Types...>
mapnik::transcoder tr("utf8");
using values_container = std::unordered_map<mapnik::value, mapnik::value>;
values_container vc;
mapnik::value keys[5] = {true, 123456789, 3.14159f, tr.transcode("Мапник"), mapnik::value_null()} ;
for (auto const& k : keys)
// mapnik::value hash() and operator== works for all T in value<Types...>
mapnik::transcoder tr("utf8");
using values_container = std::unordered_map<mapnik::value, mapnik::value>;
values_container vc;
mapnik::value keys[5] = {true, 123456789, 3.14159f, tr.transcode("Мапник"), mapnik::value_null()};
for (auto const& k : keys)
{
vc.insert({k, k});
REQUIRE(vc[k] == k);
}
// mapnik::value << to ostream
std::stringstream s;
mapnik::value_unicode_string ustr = tr.transcode("hello world!");
mapnik::value streamable(ustr);
s << streamable;
CHECK(s.str() == std::string("hello world!"));
} catch (std::exception const& ex)
{
vc.insert({k, k});
REQUIRE( vc[k] == k );
std::clog << ex.what() << "\n";
REQUIRE(false);
}
// mapnik::value << to ostream
std::stringstream s;
mapnik::value_unicode_string ustr = tr.transcode("hello world!");
mapnik::value streamable(ustr);
s << streamable;
CHECK( s.str() == std::string("hello world!") );
}
catch (std::exception const & ex)
{
std::clog << ex.what() << "\n";
REQUIRE(false);
}
}
}

View file

@ -8,72 +8,70 @@
#include "catch.hpp"
TEST_CASE("copy") {
SECTION("layers") {
try
TEST_CASE("copy")
{
SECTION("layers")
{
mapnik::Map m0(100,100);
mapnik::Map m2(200,100);
std::string shape_plugin("./plugins/input/shape.input");
if (mapnik::util::exists(shape_plugin))
try
{
mapnik::parameters p;
p["type"]="shape";
p["file"]="demo/data/boundaries";
p["encoding"]="latin1";
auto ds0 = mapnik::datasource_cache::instance().create(p);
mapnik::Map m0(100, 100);
mapnik::Map m2(200, 100);
std::string shape_plugin("./plugins/input/shape.input");
if (mapnik::util::exists(shape_plugin))
{
mapnik::parameters p;
p["type"] = "shape";
p["file"] = "demo/data/boundaries";
p["encoding"] = "latin1";
auto ds0 = mapnik::datasource_cache::instance().create(p);
auto ds1 = ds0; // shared ptr copy
REQUIRE( (ds1 == ds0) );
REQUIRE( !(*ds1 != *ds0) );
REQUIRE( (ds1.get() == ds0.get()) );
ds1 = mapnik::datasource_cache::instance().create(p); // new with the same parameters
REQUIRE( (ds1 != ds0) );
REQUIRE( (*ds1 == *ds0) );
auto ds2 = std::move(ds1);
REQUIRE( (ds2 != ds0) );
REQUIRE( (*ds2 == *ds0) );
auto ds1 = ds0; // shared ptr copy
REQUIRE((ds1 == ds0));
REQUIRE(!(*ds1 != *ds0));
REQUIRE((ds1.get() == ds0.get()));
ds1 = mapnik::datasource_cache::instance().create(p); // new with the same parameters
REQUIRE((ds1 != ds0));
REQUIRE((*ds1 == *ds0));
auto ds2 = std::move(ds1);
REQUIRE((ds2 != ds0));
REQUIRE((*ds2 == *ds0));
// mapnik::layer
mapnik::layer l0("test-layer");
l0.set_datasource(ds0);
// mapnik::layer
mapnik::layer l0("test-layer");
l0.set_datasource(ds0);
mapnik::layer l1 = l0; // copy assignment
REQUIRE( (l1 == l0) );
mapnik::layer l2(l0); // copy ctor
REQUIRE( (l2 == l0) );
mapnik::layer l3(mapnik::layer("test-layer")); // move ctor
l3.set_datasource(ds2);
mapnik::layer l1 = l0; // copy assignment
REQUIRE((l1 == l0));
mapnik::layer l2(l0); // copy ctor
REQUIRE((l2 == l0));
mapnik::layer l3(mapnik::layer("test-layer")); // move ctor
l3.set_datasource(ds2);
REQUIRE( (l3 == l0) );
mapnik::layer l4 = std::move(l3);
REQUIRE( (l4 == l0) ); // move assignment
REQUIRE((l3 == l0));
mapnik::layer l4 = std::move(l3);
REQUIRE((l4 == l0)); // move assignment
m0.add_layer(l4);
m0.set_background(mapnik::color("skyblue"));
m2.set_background(mapnik::color("skyblue"));
m0.add_layer(l4);
m0.set_background(mapnik::color("skyblue"));
m2.set_background(mapnik::color("skyblue"));
auto m1 = m0; //copy
auto m1 = m0; // copy
REQUIRE( (m0 == m1) );
REQUIRE( (m0 != m2) );
REQUIRE((m0 == m1));
REQUIRE((m0 != m2));
m2 = m1; // copy
REQUIRE( (m2 == m1) );
m2 = std::move(m1);
REQUIRE( (m2 == m0) );
REQUIRE( (m1 != m0) );
m2 = m1; // copy
REQUIRE((m2 == m1));
m2 = std::move(m1);
REQUIRE((m2 == m0));
REQUIRE((m1 != m0));
REQUIRE( (m0 == m2) );
REQUIRE((m0 == m2));
}
} catch (std::exception const& ex)
{
std::clog << ex.what() << "\n";
REQUIRE(false);
}
}
catch (std::exception const & ex)
{
std::clog << ex.what() << "\n";
REQUIRE(false);
}
}
}

View file

@ -20,82 +20,94 @@
#include <vector>
#include <algorithm>
TEST_CASE("exceptions") {
SECTION("handling") {
try {
mapnik::projection srs("FAIL");
// to avoid unused variable warning
srs.params();
REQUIRE(false);
} catch (...) {
REQUIRE(true);
}
// https://github.com/mapnik/mapnik/issues/2170
try {
mapnik::projection srs("epsg:4326 foo",true);
REQUIRE(srs.is_geographic());
REQUIRE(true);
srs.init_proj();
// oddly init_proj does not throw with old proj/ubuntu precise
//REQUIRE(false);
} catch (...) {
REQUIRE(true);
}
try {
mapnik::transcoder tr("bogus encoding");
REQUIRE(false);
} catch (...) {
REQUIRE(true);
}
mapnik::Map map(256,256);
mapnik::rule r;
r.set_filter(mapnik::parse_expression("[foo]='bar'"));
r.append(mapnik::markers_symbolizer());
mapnik::feature_type_style style;
style.add_rule(std::move(r));
map.insert_style("style", std::move(style));
std::string csv_plugin("./plugins/input/csv.input");
if (mapnik::util::exists(csv_plugin)) {
try {
mapnik::parameters p;
p["type"]="csv";
p["inline"]="x,y\n0,0";
mapnik::datasource_ptr ds = mapnik::datasource_cache::instance().create(p);
mapnik::layer l("layer");
l.set_datasource(ds);
l.add_style("style");
mapnik::Map m = map;
m.add_layer(l);
m.zoom_all();
mapnik::image_rgba8 im(m.width(),m.height());
mapnik::agg_renderer<mapnik::image_rgba8> ren(m,im);
//std::clog << mapnik::save_map_to_string(m) << "\n";
REQUIRE(true);
// should throw here with "CSV Plugin: no attribute 'foo'. Valid attributes are: x,y."
ren.apply();
TEST_CASE("exceptions")
{
SECTION("handling")
{
try
{
mapnik::projection srs("FAIL");
// to avoid unused variable warning
srs.params();
REQUIRE(false);
} catch (...) {
} catch (...)
{
REQUIRE(true);
}
}
std::string shape_plugin("./plugins/input/shape.input");
if (mapnik::util::exists(shape_plugin)) {
try {
mapnik::parameters p2;
p2["type"]="shape";
p2["file"]="foo";
mapnik::datasource_cache::instance().create(p2);
REQUIRE(false);
} catch (...) {
// https://github.com/mapnik/mapnik/issues/2170
try
{
mapnik::projection srs("epsg:4326 foo", true);
REQUIRE(srs.is_geographic());
REQUIRE(true);
srs.init_proj();
// oddly init_proj does not throw with old proj/ubuntu precise
// REQUIRE(false);
} catch (...)
{
REQUIRE(true);
}
}
}
try
{
mapnik::transcoder tr("bogus encoding");
REQUIRE(false);
} catch (...)
{
REQUIRE(true);
}
mapnik::Map map(256, 256);
mapnik::rule r;
r.set_filter(mapnik::parse_expression("[foo]='bar'"));
r.append(mapnik::markers_symbolizer());
mapnik::feature_type_style style;
style.add_rule(std::move(r));
map.insert_style("style", std::move(style));
std::string csv_plugin("./plugins/input/csv.input");
if (mapnik::util::exists(csv_plugin))
{
try
{
mapnik::parameters p;
p["type"] = "csv";
p["inline"] = "x,y\n0,0";
mapnik::datasource_ptr ds = mapnik::datasource_cache::instance().create(p);
mapnik::layer l("layer");
l.set_datasource(ds);
l.add_style("style");
mapnik::Map m = map;
m.add_layer(l);
m.zoom_all();
mapnik::image_rgba8 im(m.width(), m.height());
mapnik::agg_renderer<mapnik::image_rgba8> ren(m, im);
// std::clog << mapnik::save_map_to_string(m) << "\n";
REQUIRE(true);
// should throw here with "CSV Plugin: no attribute 'foo'. Valid attributes are: x,y."
ren.apply();
REQUIRE(false);
} catch (...)
{
REQUIRE(true);
}
}
std::string shape_plugin("./plugins/input/shape.input");
if (mapnik::util::exists(shape_plugin))
{
try
{
mapnik::parameters p2;
p2["type"] = "shape";
p2["file"] = "foo";
mapnik::datasource_cache::instance().create(p2);
REQUIRE(false);
} catch (...)
{
REQUIRE(true);
}
}
}
}

View file

@ -14,7 +14,7 @@
namespace {
template <typename Properties>
template<typename Properties>
mapnik::feature_ptr make_test_feature(mapnik::value_integer id, std::string const& wkt, Properties const& prop)
{
auto ctx = std::make_shared<mapnik::context_type>();
@ -32,12 +32,12 @@ mapnik::feature_ptr make_test_feature(mapnik::value_integer id, std::string cons
return feature;
}
template <typename Feature, typename Expression>
template<typename Feature, typename Expression>
mapnik::value_type evaluate(Feature const& feature, Expression const& expr)
{
auto value = mapnik::util::apply_visitor(
mapnik::evaluate<Feature, mapnik::value_type, mapnik::attributes>(
feature, mapnik::attributes()), expr);
mapnik::evaluate<Feature, mapnik::value_type, mapnik::attributes>(feature, mapnik::attributes()),
expr);
return value;
}
@ -62,16 +62,16 @@ TEST_CASE("expressions")
using properties_type = std::map<std::string, mapnik::value>;
mapnik::transcoder tr("utf8");
properties_type prop = {{ "foo" , tr.transcode("bar") },
{ "name" , tr.transcode("Québec")},
{ "grass" , tr.transcode("grow")},
{ "wind" , tr.transcode("blow")},
{ "sky" , tr.transcode("is blue")},
{ "τ" , mapnik::value_double(6.2831853)},
{ "double", mapnik::value_double(1.23456)},
{ "int" , mapnik::value_integer(123)},
{ "bool" , mapnik::value_bool(true)},
{ "null" , mapnik::value_null()}};
properties_type prop = {{"foo", tr.transcode("bar")},
{"name", tr.transcode("Québec")},
{"grass", tr.transcode("grow")},
{"wind", tr.transcode("blow")},
{"sky", tr.transcode("is blue")},
{"τ", mapnik::value_double(6.2831853)},
{"double", mapnik::value_double(1.23456)},
{"int", mapnik::value_integer(123)},
{"bool", mapnik::value_bool(true)},
{"null", mapnik::value_null()}};
auto feature = make_test_feature(1, "POINT(100 200)", prop);
auto eval = std::bind(evaluate_string, feature, _1);
@ -142,7 +142,7 @@ TEST_CASE("expressions")
TRY_CHECK(eval(" [ mapnik::geometry_type ] neq collection ") == true);
TRY_CHECK(eval(" [mapnik::geometry_type] eq collection ") == false);
//unary expression
// unary expression
TRY_CHECK(eval(" -123.456 ") == -123.456);
TRY_CHECK(eval(" +123.456 ") == 123.456);
@ -157,8 +157,8 @@ TEST_CASE("expressions")
TRY_CHECK(eval(" [int] = 456 or [foo].match('foo') || length([foo]) = 3 ") == true);
TRY_CHECK(eval(" not true and not true ") == false); // (not true) and (not true)
TRY_CHECK(eval(" not false and not true ") == false); // (not false) and (not true)
TRY_CHECK(eval(" not true or not false ") == true); // (not true) or (not false)
TRY_CHECK(eval(" not false or not false ") == true); // (not false) or (not false)
TRY_CHECK(eval(" not true or not false ") == true); // (not true) or (not false)
TRY_CHECK(eval(" not false or not false ") == true); // (not false) or (not false)
// test not/and/or precedence using combinations of "not EQ1 OP1 not EQ2 OP2 not EQ3"
TRY_CHECK(eval(" not [grass] = 'grow' and not [wind] = 'blow' and not [sky] = 'is blue' ") == false);
@ -186,7 +186,7 @@ TEST_CASE("expressions")
// regex
// replace
TRY_CHECK(eval(" [foo].replace('(\\B)|( )','$1 ') ") == tr.transcode("b a r")); // single quotes
TRY_CHECK(eval(" [foo].replace('(\\B)|( )','$1 ') ") == tr.transcode("b a r")); // single quotes
TRY_CHECK(eval(" [foo].replace(\"(\\B)|( )\",\"$1 \") ") == tr.transcode("b a r")); // double quotes
// https://en.wikipedia.org/wiki/Chess_symbols_in_Unicode
@ -195,7 +195,7 @@ TEST_CASE("expressions")
auto val0 = eval(from_u8string(u8"'\u265C\u265E\u265D\u265B\u265A\u265D\u265E\u265C'.replace('\u265E','\u2658')"));
auto val1 = eval("'♜♞♝♛♚♝♞♜'.replace('♞','♘')"); // ==> expected ♜♘♝♛♚♝♘♜
TRY_CHECK(val0 == val1);
TRY_CHECK(val0.to_string() == val1.to_string()); // UTF-8
TRY_CHECK(val0.to_string() == val1.to_string()); // UTF-8
TRY_CHECK(val0.to_unicode() == val1.to_unicode()); // Unicode
// \u+NNNN \U+NNNNNNNN \xNN\xNN
// single quotes
@ -210,15 +210,14 @@ TEST_CASE("expressions")
TRY_CHECK(val3 == val4);
TRY_CHECK(val5 == val6);
TRY_CHECK(val3.to_string() == val4.to_string()); // UTF-8
TRY_CHECK(val3.to_string() == val4.to_string()); // UTF-8
TRY_CHECK(val3.to_unicode() == val4.to_unicode()); // Unicode
TRY_CHECK(val5.to_string() == val6.to_string()); // UTF-8
TRY_CHECK(val5.to_string() == val6.to_string()); // UTF-8
TRY_CHECK(val5.to_unicode() == val6.to_unicode()); // Unicode
TRY_CHECK(val7 == val8);
TRY_CHECK(val7.to_string() == val8.to_string()); // UTF-8
TRY_CHECK(val7.to_string() == val8.to_string()); // UTF-8
TRY_CHECK(val7.to_unicode() == val8.to_unicode()); // Unicode
// following test will fail if boost_regex is built without ICU support (unpaired surrogates in output)
TRY_CHECK(eval("[name].replace('(\\B)|( )',' ') ") == tr.transcode("Q u é b e c"));
TRY_CHECK(eval("'Москва'.replace('(?<!^)(\\B|b)(?!$)',' ')") == tr.transcode("М о с к в а"));

View file

@ -9,105 +9,104 @@
namespace detail {
class string_holder {
public:
string_holder() :
member_("member") {}
std::string const& get_string() const
{
return member_;
}
private:
class string_holder
{
public:
string_holder()
: member_("member")
{}
std::string const& get_string() const { return member_; }
private:
std::string member_;
};
}
} // namespace detail
TEST_CASE("parameters") {
SECTION("get/set") {
try
TEST_CASE("parameters")
{
SECTION("get/set")
{
mapnik::parameters params;
try
{
mapnik::parameters params;
// true
params["bool"] = mapnik::value_integer(true);
REQUIRE( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == true));
// true
params["bool"] = mapnik::value_integer(true);
REQUIRE((params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == true));
params["bool"] = "true";
REQUIRE( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == true));
params["bool"] = "true";
REQUIRE((params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == true));
params["bool"] = mapnik::value_integer(1);
REQUIRE( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == true));
params["bool"] = mapnik::value_integer(1);
REQUIRE((params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == true));
params["bool"] = "1";
REQUIRE( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == true));
params["bool"] = "1";
REQUIRE((params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == true));
params["bool"] = "True";
REQUIRE( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == true));
params["bool"] = "True";
REQUIRE((params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == true));
params["bool"] = "on";
REQUIRE( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == true));
params["bool"] = "on";
REQUIRE((params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == true));
params["bool"] = "yes";
REQUIRE( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == true));
params["bool"] = "yes";
REQUIRE((params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == true));
// false
params["bool"] = mapnik::value_integer(false);
REQUIRE( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == false) );
// false
params["bool"] = mapnik::value_integer(false);
REQUIRE((params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == false));
params["bool"] = "false";
REQUIRE( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == false) );
params["bool"] = "false";
REQUIRE((params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == false));
params["bool"] = mapnik::value_integer(0);
REQUIRE( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == false));
params["bool"] = mapnik::value_integer(0);
REQUIRE((params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == false));
params["bool"] = "0";
REQUIRE( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == false));
params["bool"] = "0";
REQUIRE((params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == false));
params["bool"] = "False";
REQUIRE( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == false));
params["bool"] = "False";
REQUIRE((params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == false));
params["bool"] = "off";
REQUIRE( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == false));
params["bool"] = "off";
REQUIRE((params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == false));
params["bool"] = "no";
REQUIRE( (params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == false));
params["bool"] = "no";
REQUIRE((params.get<mapnik::boolean_type>("bool") && *params.get<mapnik::boolean_type>("bool") == false));
// strings
params["string"] = "hello";
REQUIRE( (params.get<std::string>("string") && *params.get<std::string>("string") == "hello") );
// strings
params["string"] = "hello";
REQUIRE((params.get<std::string>("string") && *params.get<std::string>("string") == "hello"));
// int
params["int"] = mapnik::value_integer(1);
REQUIRE( (params.get<mapnik::value_integer>("int") && *params.get<mapnik::value_integer>("int") == 1) );
// int
params["int"] = mapnik::value_integer(1);
REQUIRE((params.get<mapnik::value_integer>("int") && *params.get<mapnik::value_integer>("int") == 1));
// double
params["double"] = 1.5;
REQUIRE( (params.get<double>("double") && *params.get<double>("double") == 1.5) );
// value_null
params["null"] = mapnik::value_null();
// https://github.com/mapnik/mapnik/issues/2471
//REQUIRE( (params.get<mapnik::value_null>("null") && *params.get<mapnik::value_null>("null") == mapnik::value_null()) );
// double
params["double"] = 1.5;
REQUIRE((params.get<double>("double") && *params.get<double>("double") == 1.5));
// value_null
params["null"] = mapnik::value_null();
// https://github.com/mapnik/mapnik/issues/2471
// REQUIRE( (params.get<mapnik::value_null>("null") && *params.get<mapnik::value_null>("null") ==
// mapnik::value_null()) );
std::string value("value");
params["value"] = value;
REQUIRE( (params.get<std::string>("value") == std::string("value")) ) ;
REQUIRE(value == std::string("value"));
std::string value("value");
params["value"] = value;
REQUIRE((params.get<std::string>("value") == std::string("value")));
REQUIRE(value == std::string("value"));
// ensure that const member is not moved incorrectly when added to params
detail::string_holder holder;
std::string const& holder_member = holder.get_string();
params["member"] = holder_member;
REQUIRE( (params.get<std::string>("member") == std::string("member")) );
REQUIRE( (holder_member == std::string("member")) );
// ensure that const member is not moved incorrectly when added to params
detail::string_holder holder;
std::string const& holder_member = holder.get_string();
params["member"] = holder_member;
REQUIRE((params.get<std::string>("member") == std::string("member")));
REQUIRE((holder_member == std::string("member")));
} catch (std::exception const& ex)
{
std::cerr << ex.what() << "\n";
REQUIRE(false);
}
}
catch (std::exception const& ex)
{
std::cerr << ex.what() << "\n";
REQUIRE(false);
}
}
}

View file

@ -5,14 +5,13 @@
namespace {
bool test_transform_expressions(std::string const& in, std::string const& out)
{
auto tr_list = mapnik::parse_transform(in);
return mapnik::to_expression_string(*tr_list) == out;
}
}
} // namespace
TEST_CASE("transform-expressions")
{
@ -56,5 +55,6 @@ TEST_CASE("transform-expressions")
// compound
CHECK(test_transform_expressions("translate([tx]) rotate([a])", "translate([tx]) rotate([a])"));
CHECK(test_transform_expressions("rotate(30+@global_value) scale(2*[sx],[sy])", "rotate((30+@global_value)) scale(2*[sx], [sy])"));
CHECK(test_transform_expressions("rotate(30+@global_value) scale(2*[sx],[sy])",
"rotate((30+@global_value)) scale(2*[sx], [sy])"));
}

View file

@ -7,9 +7,9 @@ TEST_CASE("mapnik::value")
{
SECTION("add/sub/mult/div")
{
mapnik::value v0 = 1; // mapnik::value_integer
mapnik::value v0 = 1; // mapnik::value_integer
mapnik::value v1 = 1.001; // mapnik::value_double
mapnik::value v2 = true; // mapnik::value_boolean
mapnik::value v2 = true; // mapnik::value_boolean
CHECK(v0.is<mapnik::value_integer>());
CHECK(v1.is<mapnik::value_double>());
@ -101,9 +101,9 @@ TEST_CASE("mapnik::value")
CHECK(div5.is<mapnik::value_integer>());
CHECK(div6.is<mapnik::value_integer>());
CHECK(div0 == 1.0/div1);
CHECK(div2 == 1.0/div3);
CHECK(div4 == 1.0/div5);
CHECK(div6 == v0/v0);
CHECK(div0 == 1.0 / div1);
CHECK(div2 == 1.0 / div3);
CHECK(div4 == 1.0 / div5);
CHECK(div6 == v0 / v0);
}
}

View file

@ -46,16 +46,14 @@ MAPNIK_DISABLE_WARNING_POP
#include <iostream>
namespace {
bool is_csv(std::string const& filename)
{
return boost::iends_with(filename,".csv")
|| boost::iends_with(filename,".tsv");
return boost::iends_with(filename, ".csv") || boost::iends_with(filename, ".tsv");
}
void add_csv_files(std::string dir, std::vector<std::string> &csv_files)
void add_csv_files(std::string dir, std::vector<std::string>& csv_files)
{
for (auto const& path : mapnik::util::list_directory(dir))
{
@ -66,7 +64,7 @@ void add_csv_files(std::string dir, std::vector<std::string> &csv_files)
}
}
mapnik::datasource_ptr get_csv_ds(std::string const& file_name, bool strict = true, std::string const& base="")
mapnik::datasource_ptr get_csv_ds(std::string const& file_name, bool strict = true, std::string const& base = "")
{
mapnik::parameters params;
params["type"] = std::string("csv");
@ -84,7 +82,8 @@ mapnik::datasource_ptr get_csv_ds(std::string const& file_name, bool strict = tr
} // anonymous namespace
TEST_CASE("csv") {
TEST_CASE("csv")
{
using mapnik::util::from_u8string;
std::string csv_plugin("./plugins/input/csv.input");
if (mapnik::util::exists(csv_plugin))
@ -94,15 +93,13 @@ TEST_CASE("csv") {
mapnik::logger::instance().set_severity(mapnik::logger::none);
// check the CSV datasource is loaded
const std::vector<std::string> plugin_names =
mapnik::datasource_cache::instance().plugin_names();
const bool have_csv_plugin =
std::find(plugin_names.begin(), plugin_names.end(), "csv") != plugin_names.end();
const std::vector<std::string> plugin_names = mapnik::datasource_cache::instance().plugin_names();
const bool have_csv_plugin = std::find(plugin_names.begin(), plugin_names.end(), "csv") != plugin_names.end();
SECTION("CSV I/O errors")
{
std::string filename = "does_not_exist.csv";
for (auto create_index : { true, false })
for (auto create_index : {true, false})
{
if (create_index)
{
@ -126,7 +123,7 @@ TEST_CASE("csv") {
SECTION("broken files")
{
for (auto create_index : { false, true })
for (auto create_index : {false, true})
{
if (have_csv_plugin)
{
@ -144,7 +141,7 @@ TEST_CASE("csv") {
int ret_posix = (ret >> 8) & 0x000000ff;
INFO(ret);
INFO(ret_posix);
require_fail = (boost::iends_with(path,"feature_id_counting.csv")) ? false : true;
require_fail = (boost::iends_with(path, "feature_id_counting.csv")) ? false : true;
if (!require_fail)
{
REQUIRE(mapnik::util::exists(path + ".index"));
@ -183,7 +180,7 @@ TEST_CASE("csv") {
{
mapnik::util::remove(path + ".index");
}
for (auto create_index : { false, true })
for (auto create_index : {false, true})
{
if (create_index)
{
@ -191,7 +188,9 @@ TEST_CASE("csv") {
int ret_posix = (ret >> 8) & 0x000000ff;
INFO(ret);
INFO(ret_posix);
if (!boost::iends_with(path,"more_headers_than_column_values.csv")) // mapnik-index won't create *.index for 0 features
if (!boost::iends_with(path,
"more_headers_than_column_values.csv")) // mapnik-index won't create
// *.index for 0 features
{
CHECK(mapnik::util::exists(path + ".index"));
}
@ -210,7 +209,7 @@ TEST_CASE("csv") {
SECTION("lon/lat detection")
{
for (auto create_index : { false, true })
for (auto create_index : {false, true})
{
for (auto const& lon_name : {std::string("lon"), std::string("lng")})
{
@ -236,17 +235,16 @@ TEST_CASE("csv") {
CHECK(ds->get_geometry_type() == mapnik::datasource_geometry_t::Point);
mapnik::query query(ds->envelope());
for (auto const &field : fields)
for (auto const& field : fields)
{
query.add_property_name(field.get_name());
}
auto features = ds->features(query);
auto feature = features->next();
REQUIRE_ATTRIBUTES(feature, {
attr { lon_name, mapnik::value_integer(0) },
attr { "lat", mapnik::value_integer(0) }
});
REQUIRE_ATTRIBUTES(
feature,
{attr{lon_name, mapnik::value_integer(0)}, attr{"lat", mapnik::value_integer(0)}});
if (mapnik::util::exists(filename + ".index"))
{
mapnik::util::remove(filename + ".index");
@ -257,7 +255,7 @@ TEST_CASE("csv") {
SECTION("type detection")
{
for (auto create_index : { false, true })
for (auto create_index : {false, true})
{
std::string base = "test/data/csv/";
std::string filename = "nypd.csv";
@ -275,31 +273,38 @@ TEST_CASE("csv") {
INFO(ret_posix);
CHECK(mapnik::util::exists(filepath + ".index"));
}
auto ds = get_csv_ds(filename,true,base);
auto ds = get_csv_ds(filename, true, base);
CHECK(ds->type() == mapnik::datasource::datasource_t::Vector);
auto fields = ds->get_descriptor().get_descriptors();
require_field_names(fields, {"Precinct", "Phone", "Address", "City", "geo_longitude", "geo_latitude", "geo_accuracy"});
require_field_types(fields, {mapnik::String, mapnik::String, mapnik::String, mapnik::String, mapnik::Double, mapnik::Double, mapnik::String});
require_field_names(
fields,
{"Precinct", "Phone", "Address", "City", "geo_longitude", "geo_latitude", "geo_accuracy"});
require_field_types(fields,
{mapnik::String,
mapnik::String,
mapnik::String,
mapnik::String,
mapnik::Double,
mapnik::Double,
mapnik::String});
CHECK(ds->get_geometry_type() == mapnik::datasource_geometry_t::Point);
CHECK(count_features(all_features(ds)) == 2);
auto fs = all_features(ds);
auto fs2 = ds->features_at_point(ds->envelope().center(),10000);
auto fs2 = ds->features_at_point(ds->envelope().center(), 10000);
REQUIRE(fs != nullptr);
auto feature = fs->next();
auto feature2 = fs2->next();
REQUIRE(feature != nullptr);
REQUIRE(feature2 != nullptr);
auto expected_attr = {
attr { "City", mapnik::value_unicode_string("New York, NY") }
, attr { "geo_accuracy", mapnik::value_unicode_string("house") }
, attr { "Phone", mapnik::value_unicode_string("(212) 334-0711") }
, attr { "Address", mapnik::value_unicode_string("19 Elizabeth Street") }
, attr { "Precinct", mapnik::value_unicode_string("5th Precinct") }
, attr { "geo_longitude", mapnik::value_double(-70.0) }
, attr { "geo_latitude", mapnik::value_double(40.0) }
};
auto expected_attr = {attr{"City", mapnik::value_unicode_string("New York, NY")},
attr{"geo_accuracy", mapnik::value_unicode_string("house")},
attr{"Phone", mapnik::value_unicode_string("(212) 334-0711")},
attr{"Address", mapnik::value_unicode_string("19 Elizabeth Street")},
attr{"Precinct", mapnik::value_unicode_string("5th Precinct")},
attr{"geo_longitude", mapnik::value_double(-70.0)},
attr{"geo_latitude", mapnik::value_double(40.0)}};
REQUIRE_ATTRIBUTES(feature, expected_attr);
REQUIRE_ATTRIBUTES(feature2, expected_attr);
if (mapnik::util::exists(filepath + ".index"))
@ -311,7 +316,7 @@ TEST_CASE("csv") {
SECTION("skipping blank rows")
{
for (auto create_index : { false, true })
for (auto create_index : {false, true})
{
std::string filename = "test/data/csv/blank_rows.csv";
// cleanup in the case of a failed previous run
@ -342,7 +347,7 @@ TEST_CASE("csv") {
SECTION("empty rows")
{
for (auto create_index : { false, true })
for (auto create_index : {false, true})
{
std::string filename = "test/data/csv/empty_rows.csv";
// cleanup in the case of a failed previous run
@ -361,28 +366,39 @@ TEST_CASE("csv") {
auto ds = get_csv_ds(filename);
auto fields = ds->get_descriptor().get_descriptors();
require_field_names(fields, {"x", "y", "text", "date", "integer", "boolean", "float", "time", "datetime", "empty_column"});
require_field_types(fields, {mapnik::Integer, mapnik::Integer, mapnik::String, mapnik::String,
mapnik::Integer, mapnik::Boolean, mapnik::Double, mapnik::String, mapnik::String, mapnik::String});
require_field_names(
fields,
{"x", "y", "text", "date", "integer", "boolean", "float", "time", "datetime", "empty_column"});
require_field_types(fields,
{mapnik::Integer,
mapnik::Integer,
mapnik::String,
mapnik::String,
mapnik::Integer,
mapnik::Boolean,
mapnik::Double,
mapnik::String,
mapnik::String,
mapnik::String});
CHECK(ds->get_geometry_type() == mapnik::datasource_geometry_t::Point);
CHECK(count_features(all_features(ds)) == 4);
auto featureset = all_features(ds);
auto feature = featureset->next();
REQUIRE_ATTRIBUTES(feature, {
attr { "x", mapnik::value_integer(0) }
, attr { "empty_column", mapnik::value_unicode_string("") }
, attr { "text", mapnik::value_unicode_string("a b") }
, attr { "float", mapnik::value_double(1.0) }
, attr { "datetime", mapnik::value_unicode_string("1971-01-01T04:14:00") }
, attr { "y", mapnik::value_integer(0) }
, attr { "boolean", mapnik::value_bool(true) }
, attr { "time", mapnik::value_unicode_string("04:14:00") }
, attr { "date", mapnik::value_unicode_string("1971-01-01") }
, attr { "integer", mapnik::value_integer(40) }
});
REQUIRE_ATTRIBUTES(feature,
{attr{"x", mapnik::value_integer(0)},
attr{"empty_column", mapnik::value_unicode_string("")},
attr{"text", mapnik::value_unicode_string("a b")},
attr{"float", mapnik::value_double(1.0)},
attr{"datetime", mapnik::value_unicode_string("1971-01-01T04:14:00")},
attr{"y", mapnik::value_integer(0)},
attr{"boolean", mapnik::value_bool(true)},
attr{"time", mapnik::value_unicode_string("04:14:00")},
attr{"date", mapnik::value_unicode_string("1971-01-01")},
attr{"integer", mapnik::value_integer(40)}});
while (bool(feature = featureset->next())) {
while (bool(feature = featureset->next()))
{
CHECK(feature->size() == 10);
CHECK(feature->get("empty_column") == mapnik::value_unicode_string(""));
}
@ -395,7 +411,7 @@ TEST_CASE("csv") {
SECTION("slashes")
{
for (auto create_index : { false, true })
for (auto create_index : {false, true})
{
std::string filename = "test/data/csv/has_attributes_with_slashes.csv";
// cleanup in the case of a failed previous run
@ -418,18 +434,12 @@ TEST_CASE("csv") {
require_field_types(fields, {mapnik::Integer, mapnik::Integer, mapnik::String});
auto featureset = all_features(ds);
REQUIRE_ATTRIBUTES(featureset->next(), {
attr{"x", 0}
, attr{"y", 0}
, attr{"name", mapnik::value_unicode_string("a/a") } });
REQUIRE_ATTRIBUTES(featureset->next(), {
attr{"x", 1}
, attr{"y", 4}
, attr{"name", mapnik::value_unicode_string("b/b") } });
REQUIRE_ATTRIBUTES(featureset->next(), {
attr{"x", 10}
, attr{"y", 2.5}
, attr{"name", mapnik::value_unicode_string("c/c") } });
REQUIRE_ATTRIBUTES(featureset->next(),
{attr{"x", 0}, attr{"y", 0}, attr{"name", mapnik::value_unicode_string("a/a")}});
REQUIRE_ATTRIBUTES(featureset->next(),
{attr{"x", 1}, attr{"y", 4}, attr{"name", mapnik::value_unicode_string("b/b")}});
REQUIRE_ATTRIBUTES(featureset->next(),
{attr{"x", 10}, attr{"y", 2.5}, attr{"name", mapnik::value_unicode_string("c/c")}});
if (mapnik::util::exists(filename + ".index"))
{
mapnik::util::remove(filename + ".index");
@ -439,7 +449,7 @@ TEST_CASE("csv") {
SECTION("wkt field")
{
for (auto create_index : { false, true })
for (auto create_index : {false, true})
{
std::string filename = "test/data/csv/wkt.csv";
// cleanup in the case of a failed previous run
@ -479,7 +489,7 @@ TEST_CASE("csv") {
SECTION("handling of missing header")
{
for (auto create_index : { false, true })
for (auto create_index : {false, true})
{
std::string filename = "test/data/csv/missing_header.csv";
// cleanup in the case of a failed previous run
@ -513,7 +523,7 @@ TEST_CASE("csv") {
SECTION("handling of headers that are numbers")
{
for (auto create_index : { false, true })
for (auto create_index : {false, true})
{
std::string filename = "test/data/csv/numbers_for_headers.csv";
// cleanup in the case of a failed previous run
@ -533,18 +543,14 @@ TEST_CASE("csv") {
auto fields = ds->get_descriptor().get_descriptors();
require_field_names(fields, {"x", "y", "1990", "1991", "1992"});
auto feature = all_features(ds)->next();
REQUIRE_ATTRIBUTES(feature, {
attr{"x", 0}
, attr{"y", 0}
, attr{"1990", 1}
, attr{"1991", 2}
, attr{"1992", 3}
});
REQUIRE_ATTRIBUTES(feature,
{attr{"x", 0}, attr{"y", 0}, attr{"1990", 1}, attr{"1991", 2}, attr{"1992", 3}});
auto expression = mapnik::parse_expression("[1991]=2");
REQUIRE(bool(expression));
auto value = mapnik::util::apply_visitor(
mapnik::evaluate<mapnik::feature_impl, mapnik::value_type, mapnik::attributes>(
*feature, mapnik::attributes()), *expression);
mapnik::evaluate<mapnik::feature_impl, mapnik::value_type, mapnik::attributes>(*feature,
mapnik::attributes()),
*expression);
CHECK(value == true);
if (mapnik::util::exists(filename + ".index"))
{
@ -556,7 +562,7 @@ TEST_CASE("csv") {
SECTION("quoted numbers")
{
using ustring = mapnik::value_unicode_string;
for (auto create_index : { false, true })
for (auto create_index : {false, true})
{
std::string filename = "test/data/csv/quoted_numbers.csv";
// cleanup in the case of a failed previous run
@ -577,16 +583,12 @@ TEST_CASE("csv") {
require_field_names(fields, {"x", "y", "label"});
auto featureset = all_features(ds);
REQUIRE_ATTRIBUTES(featureset->next(), {
attr{"x", 0}, attr{"y", 0}, attr{"label", ustring("0,0") } });
REQUIRE_ATTRIBUTES(featureset->next(), {
attr{"x", 5}, attr{"y", 5}, attr{"label", ustring("5,5") } });
REQUIRE_ATTRIBUTES(featureset->next(), {
attr{"x", 0}, attr{"y", 5}, attr{"label", ustring("0,5") } });
REQUIRE_ATTRIBUTES(featureset->next(), {
attr{"x", 5}, attr{"y", 0}, attr{"label", ustring("5,0") } });
REQUIRE_ATTRIBUTES(featureset->next(), {
attr{"x", 2.5}, attr{"y", 2.5}, attr{"label", ustring("2.5,2.5") } });
REQUIRE_ATTRIBUTES(featureset->next(), {attr{"x", 0}, attr{"y", 0}, attr{"label", ustring("0,0")}});
REQUIRE_ATTRIBUTES(featureset->next(), {attr{"x", 5}, attr{"y", 5}, attr{"label", ustring("5,5")}});
REQUIRE_ATTRIBUTES(featureset->next(), {attr{"x", 0}, attr{"y", 5}, attr{"label", ustring("0,5")}});
REQUIRE_ATTRIBUTES(featureset->next(), {attr{"x", 5}, attr{"y", 0}, attr{"label", ustring("5,0")}});
REQUIRE_ATTRIBUTES(featureset->next(),
{attr{"x", 2.5}, attr{"y", 2.5}, attr{"label", ustring("2.5,2.5")}});
if (mapnik::util::exists(filename + ".index"))
{
mapnik::util::remove(filename + ".index");
@ -596,7 +598,7 @@ TEST_CASE("csv") {
SECTION("reading newlines")
{
for (auto create_index : { false, true })
for (auto create_index : {false, true})
{
for (auto const& platform : {std::string("windows"), std::string("mac")})
{
@ -617,8 +619,7 @@ TEST_CASE("csv") {
auto ds = get_csv_ds(filename);
auto fields = ds->get_descriptor().get_descriptors();
require_field_names(fields, {"x", "y", "z"});
REQUIRE_ATTRIBUTES(all_features(ds)->next(), {
attr{"x", 1}, attr{"y", 10}, attr{"z", 9999.9999} });
REQUIRE_ATTRIBUTES(all_features(ds)->next(), {attr{"x", 1}, attr{"y", 10}, attr{"z", 9999.9999}});
if (mapnik::util::exists(filename + ".index"))
{
mapnik::util::remove(filename + ".index");
@ -630,14 +631,13 @@ TEST_CASE("csv") {
SECTION("mixed newlines")
{
using ustring = mapnik::value_unicode_string;
for (auto create_index : { false, true })
for (auto create_index : {false, true})
{
for (auto const& filename : {
std::string("test/data/csv/mac_newlines_with_unix_inline.csv")
, std::string("test/data/csv/mac_newlines_with_unix_inline_escaped.csv")
, std::string("test/data/csv/windows_newlines_with_unix_inline.csv")
, std::string("test/data/csv/windows_newlines_with_unix_inline_escaped.csv")
})
for (auto const& filename :
{std::string("test/data/csv/mac_newlines_with_unix_inline.csv"),
std::string("test/data/csv/mac_newlines_with_unix_inline_escaped.csv"),
std::string("test/data/csv/windows_newlines_with_unix_inline.csv"),
std::string("test/data/csv/windows_newlines_with_unix_inline_escaped.csv")})
{
// cleanup in the case of a failed previous run
if (mapnik::util::exists(filename + ".index"))
@ -655,9 +655,10 @@ TEST_CASE("csv") {
auto ds = get_csv_ds(filename);
auto fields = ds->get_descriptor().get_descriptors();
require_field_names(fields, {"x", "y", "line"});
REQUIRE_ATTRIBUTES(all_features(ds)->next(), {
attr{"x", 0}, attr{"y", 0}
, attr{"line", ustring("many\n lines\n of text\n with unix newlines")} });
REQUIRE_ATTRIBUTES(all_features(ds)->next(),
{attr{"x", 0},
attr{"y", 0},
attr{"line", ustring("many\n lines\n of text\n with unix newlines")}});
if (mapnik::util::exists(filename + ".index"))
{
mapnik::util::remove(filename + ".index");
@ -668,7 +669,7 @@ TEST_CASE("csv") {
SECTION("tabs")
{
for (auto create_index : { false, true })
for (auto create_index : {false, true})
{
std::string filename = "test/data/csv/tabs_in_csv.csv";
if (mapnik::util::exists(filename + ".index"))
@ -686,8 +687,7 @@ TEST_CASE("csv") {
auto ds = get_csv_ds(filename);
auto fields = ds->get_descriptor().get_descriptors();
require_field_names(fields, {"x", "y", "z"});
REQUIRE_ATTRIBUTES(all_features(ds)->next(), {
attr{"x", -122}, attr{"y", 48}, attr{"z", 0} });
REQUIRE_ATTRIBUTES(all_features(ds)->next(), {attr{"x", -122}, attr{"y", 48}, attr{"z", 0}});
if (mapnik::util::exists(filename + ".index"))
{
mapnik::util::remove(filename + ".index");
@ -698,12 +698,10 @@ TEST_CASE("csv") {
SECTION("separators")
{
using ustring = mapnik::value_unicode_string;
for (auto const& filename : {
std::string("test/data/csv/pipe_delimiters.csv")
, std::string("test/data/csv/semicolon_delimiters.csv")
})
for (auto const& filename : {std::string("test/data/csv/pipe_delimiters.csv"),
std::string("test/data/csv/semicolon_delimiters.csv")})
{
for (auto create_index : { false, true })
for (auto create_index : {false, true})
{
// cleanup in the case of a failed previous run
if (mapnik::util::exists(filename + ".index"))
@ -721,8 +719,8 @@ TEST_CASE("csv") {
auto ds = get_csv_ds(filename);
auto fields = ds->get_descriptor().get_descriptors();
require_field_names(fields, {"x", "y", "z"});
REQUIRE_ATTRIBUTES(all_features(ds)->next(), {
attr{"x", 0}, attr{"y", 0}, attr{"z", ustring("hello")} });
REQUIRE_ATTRIBUTES(all_features(ds)->next(),
{attr{"x", 0}, attr{"y", 0}, attr{"z", ustring("hello")}});
if (mapnik::util::exists(filename + ".index"))
{
mapnik::util::remove(filename + ".index");
@ -735,7 +733,7 @@ TEST_CASE("csv") {
{
using ustring = mapnik::value_unicode_string;
std::string filename = "test/data/csv/nulls_and_booleans_as_strings.csv";
for (auto create_index : { false, true })
for (auto create_index : {false, true})
{
// cleanup in the case of a failed previous run
if (mapnik::util::exists(filename + ".index"))
@ -756,10 +754,10 @@ TEST_CASE("csv") {
require_field_types(fields, {mapnik::Integer, mapnik::Integer, mapnik::String, mapnik::Boolean});
auto featureset = all_features(ds);
REQUIRE_ATTRIBUTES(featureset->next(), {
attr{"x", 0}, attr{"y", 0}, attr{"null", ustring("null")}, attr{"boolean", true}});
REQUIRE_ATTRIBUTES(featureset->next(), {
attr{"x", 0}, attr{"y", 0}, attr{"null", ustring("")}, attr{"boolean", false}});
REQUIRE_ATTRIBUTES(featureset->next(),
{attr{"x", 0}, attr{"y", 0}, attr{"null", ustring("null")}, attr{"boolean", true}});
REQUIRE_ATTRIBUTES(featureset->next(),
{attr{"x", 0}, attr{"y", 0}, attr{"null", ustring("")}, attr{"boolean", false}});
if (mapnik::util::exists(filename + ".index"))
{
@ -771,7 +769,7 @@ TEST_CASE("csv") {
SECTION("nonexistent query fields throw")
{
std::string filename = "test/data/csv/lon_lat.csv";
for (auto create_index : { false, true })
for (auto create_index : {false, true})
{
// cleanup in the case of a failed previous run
if (mapnik::util::exists(filename + ".index"))
@ -792,7 +790,7 @@ TEST_CASE("csv") {
require_field_types(fields, {mapnik::Integer, mapnik::Integer});
mapnik::query query(ds->envelope());
for (auto const &field : fields)
for (auto const& field : fields)
{
query.add_property_name(field.get_name());
}
@ -810,7 +808,7 @@ TEST_CASE("csv") {
{
using ustring = mapnik::value_unicode_string;
std::string filename = "test/data/csv/leading_zeros.csv";
for (auto create_index : { false, true })
for (auto create_index : {false, true})
{
// cleanup in the case of a failed previous run
if (mapnik::util::exists(filename + ".index"))
@ -831,12 +829,9 @@ TEST_CASE("csv") {
require_field_types(fields, {mapnik::Integer, mapnik::Integer, mapnik::String});
auto featureset = all_features(ds);
REQUIRE_ATTRIBUTES(featureset->next(), {
attr{"x", 0}, attr{"y", 0}, attr{"fips", ustring("001")}});
REQUIRE_ATTRIBUTES(featureset->next(), {
attr{"x", 0}, attr{"y", 0}, attr{"fips", ustring("003")}});
REQUIRE_ATTRIBUTES(featureset->next(), {
attr{"x", 0}, attr{"y", 0}, attr{"fips", ustring("005")}});
REQUIRE_ATTRIBUTES(featureset->next(), {attr{"x", 0}, attr{"y", 0}, attr{"fips", ustring("001")}});
REQUIRE_ATTRIBUTES(featureset->next(), {attr{"x", 0}, attr{"y", 0}, attr{"fips", ustring("003")}});
REQUIRE_ATTRIBUTES(featureset->next(), {attr{"x", 0}, attr{"y", 0}, attr{"fips", ustring("005")}});
if (mapnik::util::exists(filename + ".index"))
{
mapnik::util::remove(filename + ".index");
@ -847,12 +842,11 @@ TEST_CASE("csv") {
SECTION("advanced geometry detection")
{
using row = std::pair<std::string, mapnik::datasource_geometry_t>;
for (row r : {
row{"point", mapnik::datasource_geometry_t::Point}
, row{"poly", mapnik::datasource_geometry_t::Polygon}
, row{"multi_poly", mapnik::datasource_geometry_t::Polygon}
, row{"line", mapnik::datasource_geometry_t::LineString}
}) {
for (row r : {row{"point", mapnik::datasource_geometry_t::Point},
row{"poly", mapnik::datasource_geometry_t::Polygon},
row{"multi_poly", mapnik::datasource_geometry_t::Polygon},
row{"line", mapnik::datasource_geometry_t::LineString}})
{
std::string file_name = (boost::format("test/data/csv/%1%_wkt.csv") % r.first).str();
auto ds = get_csv_ds(file_name);
CHECK(ds->get_geometry_type() == r.second);
@ -863,12 +857,12 @@ TEST_CASE("csv") {
{
using ustring = mapnik::value_unicode_string;
for (auto const &name : {std::string("Winthrop, WA"), from_u8string(u8"Qu\u00e9bec")}) {
std::string csv_string =
(boost::format(
"wkt,Name\n"
"\"POINT (120.15 48.47)\",\"%1%\"\n"
) % name).str();
for (auto const& name : {std::string("Winthrop, WA"), from_u8string(u8"Qu\u00e9bec")})
{
std::string csv_string = (boost::format("wkt,Name\n"
"\"POINT (120.15 48.47)\",\"%1%\"\n") %
name)
.str();
mapnik::parameters params;
params["type"] = std::string("csv");
@ -883,7 +877,7 @@ TEST_CASE("csv") {
mapnik::transcoder tr("utf-8");
ustring expected_string = tr.transcode(name.c_str());
mapnik::value val(expected_string);
mapnik::to_utf8(expected_string,utf8);
mapnik::to_utf8(expected_string, utf8);
INFO(feature->get("Name"));
INFO(utf8);
INFO(val);
@ -898,23 +892,23 @@ TEST_CASE("csv") {
// should throw
params["inline"] = "latitude, longtitude, Name\n" // misspellt (!)
"120.15,48.47,Winhrop";
"120.15,48.47,Winhrop";
REQUIRE_THROWS(mapnik::datasource_cache::instance().create(params));
// should throw
params["strict"] = true;
params["inline"] = "latitude, longitude\n" // -- missing header
"120.15,48.47,Winhrop";
"120.15,48.47,Winhrop";
REQUIRE_THROWS(mapnik::datasource_cache::instance().create(params));
// should not throw
params["strict"] = false;
params["inline"] = "latitude, longitude,Name\n"
"0,0,Unknown, extra bogus field\n"
"120.15,48.47,Winhrop\n";
"0,0,Unknown, extra bogus field\n"
"120.15,48.47,Winhrop\n";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(bool(ds));
REQUIRE(ds->envelope() == mapnik::box2d<double>(48.47,120.15,48.47,120.15));
REQUIRE(ds->envelope() == mapnik::box2d<double>(48.47, 120.15, 48.47, 120.15));
auto feature = all_features(ds)->next();
REQUIRE(bool(feature));
REQUIRE(feature->has_key("Name"));
@ -922,19 +916,19 @@ TEST_CASE("csv") {
// should throw
params["strict"] = false;
params["inline"] = "x, Name\n" // -- missing required *geometry* header
"120.15,Winhrop";
"120.15,Winhrop";
REQUIRE_THROWS(mapnik::datasource_cache::instance().create(params));
} // END SECTION
SECTION("geojson quoting") {
SECTION("geojson quoting")
{
using mapnik::geometry::geometry_types;
for (auto const &file : {
std::string("test/data/csv/geojson_double_quote_escape.csv")
, std::string("test/data/csv/geojson_single_quote.csv")
, std::string("test/data/csv/geojson_2x_double_quote_filebakery_style.csv")
}) {
for (auto const& file : {std::string("test/data/csv/geojson_double_quote_escape.csv"),
std::string("test/data/csv/geojson_single_quote.csv"),
std::string("test/data/csv/geojson_2x_double_quote_filebakery_style.csv")})
{
auto ds = get_csv_ds(file);
auto fields = ds->get_descriptor().get_descriptors();
require_field_names(fields, {"type"});
@ -952,11 +946,13 @@ TEST_CASE("csv") {
}
} // END SECTION
SECTION("fewer headers than rows throws") {
SECTION("fewer headers than rows throws")
{
REQUIRE_THROWS(get_csv_ds("test/data/csv/more_column_values_than_headers.csv"));
} // END SECTION
SECTION("feature ID only incremented for valid rows") {
SECTION("feature ID only incremented for valid rows")
{
auto ds = get_csv_ds("test/data/csv/warns/feature_id_counting.csv", false);
auto fs = all_features(ds);
@ -974,14 +970,14 @@ TEST_CASE("csv") {
CHECK(!feature);
} // END SECTION
SECTION("dynamically defining headers") {
SECTION("dynamically defining headers")
{
using ustring = mapnik::value_unicode_string;
using row = std::pair<std::string, std::size_t>;
for (auto const& r : {
row{"test/data/csv/fails/needs_headers_two_lines.csv", 2},
row{"test/data/csv/fails/needs_headers_one_line.csv", 1},
row{"test/data/csv/fails/needs_headers_one_line_no_newline.csv", 1}})
for (auto const& r : {row{"test/data/csv/fails/needs_headers_two_lines.csv", 2},
row{"test/data/csv/fails/needs_headers_one_line.csv", 1},
row{"test/data/csv/fails/needs_headers_one_line_no_newline.csv", 1}})
{
mapnik::parameters params;
params["type"] = std::string("csv");
@ -992,17 +988,17 @@ TEST_CASE("csv") {
auto fields = ds->get_descriptor().get_descriptors();
require_field_names(fields, {"x", "y", "name"});
require_field_types(fields, {mapnik::Integer, mapnik::Integer, mapnik::String});
REQUIRE_ATTRIBUTES(all_features(ds)->next(), {
attr{"x", 0}, attr{"y", 0}, attr{"name", ustring("data_name")} });
REQUIRE_ATTRIBUTES(all_features(ds)->next(),
{attr{"x", 0}, attr{"y", 0}, attr{"name", ustring("data_name")}});
REQUIRE(count_features(all_features(ds)) == r.second);
CHECK(ds->get_geometry_type() == mapnik::datasource_geometry_t::Point);
}
} // END SECTION
MAPNIK_DISABLE_WARNING_PUSH
MAPNIK_DISABLE_LONG_LONG
SECTION("64bit int fields work") {
MAPNIK_DISABLE_WARNING_PUSH
MAPNIK_DISABLE_LONG_LONG
SECTION("64bit int fields work")
{
auto ds = get_csv_ds("test/data/csv/64bit_int.csv");
auto fields = ds->get_descriptor().get_descriptors();
require_field_names(fields, {"x", "y", "bigint"});
@ -1010,31 +1006,31 @@ MAPNIK_DISABLE_LONG_LONG
auto fs = all_features(ds);
auto feature = fs->next();
REQUIRE_ATTRIBUTES(feature, {
attr{"x", 0}, attr{"y", 0}, attr{"bigint", 2147483648} });
REQUIRE_ATTRIBUTES(feature, {attr{"x", 0}, attr{"y", 0}, attr{"bigint", 2147483648}});
feature = fs->next();
REQUIRE_ATTRIBUTES(feature, {
attr{"x", 0}, attr{"y", 0}, attr{"bigint", 9223372036854775807ll} });
REQUIRE_ATTRIBUTES(feature, {
attr{"x", 0}, attr{"y", 0}, attr{"bigint", 0x7FFFFFFFFFFFFFFFll} });
REQUIRE_ATTRIBUTES(feature, {attr{"x", 0}, attr{"y", 0}, attr{"bigint", 9223372036854775807ll}});
REQUIRE_ATTRIBUTES(feature, {attr{"x", 0}, attr{"y", 0}, attr{"bigint", 0x7FFFFFFFFFFFFFFFll}});
} // END SECTION
MAPNIK_DISABLE_WARNING_POP
MAPNIK_DISABLE_WARNING_POP
SECTION("various number types") {
SECTION("various number types")
{
auto ds = get_csv_ds("test/data/csv/number_types.csv");
auto fields = ds->get_descriptor().get_descriptors();
require_field_names(fields, {"x", "y", "floats"});
require_field_types(fields, {mapnik::Integer, mapnik::Integer, mapnik::Double});
auto fs = all_features(ds);
for (double d : { .0, +.0, 1e-06, -1e-06, 0.000001, 1.234e+16, 1.234e+16 }) {
for (double d : {.0, +.0, 1e-06, -1e-06, 0.000001, 1.234e+16, 1.234e+16})
{
auto feature = fs->next();
REQUIRE(bool(feature));
CHECK(feature->get("floats").get<mapnik::value_double>() == Approx(d));
}
} // END SECTION
SECTION("manually supplied extent") {
SECTION("manually supplied extent")
{
std::string csv_string("wkt,Name\n");
mapnik::parameters params;
params["type"] = std::string("csv");
@ -1044,12 +1040,13 @@ MAPNIK_DISABLE_WARNING_POP
REQUIRE(bool(ds));
auto box = ds->envelope();
CHECK(box.minx() == -180);
CHECK(box.miny() == -90);
CHECK(box.maxx() == 180);
CHECK(box.maxy() == 90);
CHECK(box.miny() == -90);
CHECK(box.maxx() == 180);
CHECK(box.maxy() == 90);
} // END SECTION
SECTION("inline geojson") {
SECTION("inline geojson")
{
std::string csv_string = "geojson\n'{\"coordinates\":[-92.22568,38.59553],\"type\":\"Point\"}'";
mapnik::parameters params;
params["type"] = std::string("csv");

View file

@ -20,7 +20,6 @@
*
*****************************************************************************/
#ifndef MAPNIK_UNIT_DATSOURCE_UTIL
#define MAPNIK_UNIT_DATSOURCE_UTIL
@ -34,7 +33,7 @@
namespace {
template <typename T>
template<typename T>
std::string vector_to_string(T const& vec)
{
std::stringstream s;
@ -45,7 +44,7 @@ std::string vector_to_string(T const& vec)
return s.str();
}
template <>
template<>
std::string vector_to_string(std::vector<mapnik::attribute_descriptor> const& vec)
{
std::stringstream s;
@ -56,50 +55,55 @@ std::string vector_to_string(std::vector<mapnik::attribute_descriptor> const& ve
return s.str();
}
#define REQUIRE_FIELD_NAMES(fields, names) \
INFO("fields:\n" + vector_to_string(fields) + "names:\n" + vector_to_string(names)); \
REQUIRE(fields.size() == names.size()); \
auto itr_a = fields.begin(); \
auto const end_a = fields.end(); \
auto itr_b = names.begin(); \
for (; itr_a != end_a; ++itr_a, ++itr_b) \
{ \
CHECK(itr_a->get_name() == *itr_b); \
} \
#define REQUIRE_FIELD_NAMES(fields, names) \
INFO("fields:\n" + vector_to_string(fields) + "names:\n" + vector_to_string(names)); \
REQUIRE(fields.size() == names.size()); \
auto itr_a = fields.begin(); \
auto const end_a = fields.end(); \
auto itr_b = names.begin(); \
for (; itr_a != end_a; ++itr_a, ++itr_b) \
{ \
CHECK(itr_a->get_name() == *itr_b); \
}
inline void require_field_names(std::vector<mapnik::attribute_descriptor> const &fields,
std::initializer_list<std::string> const &names)
inline void require_field_names(std::vector<mapnik::attribute_descriptor> const& fields,
std::initializer_list<std::string> const& names)
{
REQUIRE_FIELD_NAMES(fields,names);
REQUIRE_FIELD_NAMES(fields, names);
}
#define REQUIRE_FIELD_TYPES(fields, types) \
REQUIRE(fields.size() == types.size()); \
auto itr_a = fields.begin(); \
auto const end_a = fields.end(); \
auto itr_b = types.begin(); \
for (; itr_a != end_a; ++itr_a, ++itr_b) { \
CHECK(itr_a->get_type() == *itr_b); \
} \
#define REQUIRE_FIELD_TYPES(fields, types) \
REQUIRE(fields.size() == types.size()); \
auto itr_a = fields.begin(); \
auto const end_a = fields.end(); \
auto itr_b = types.begin(); \
for (; itr_a != end_a; ++itr_a, ++itr_b) \
{ \
CHECK(itr_a->get_type() == *itr_b); \
}
inline void require_field_types(std::vector<mapnik::attribute_descriptor> const &fields,
std::initializer_list<mapnik::eAttributeType> const &types)
inline void require_field_types(std::vector<mapnik::attribute_descriptor> const& fields,
std::initializer_list<mapnik::eAttributeType> const& types)
{
REQUIRE_FIELD_TYPES(fields, types);
}
inline mapnik::featureset_ptr all_features(mapnik::datasource_ptr ds) {
inline mapnik::featureset_ptr all_features(mapnik::datasource_ptr ds)
{
auto fields = ds->get_descriptor().get_descriptors();
mapnik::query query(ds->envelope());
for (auto const &field : fields) {
for (auto const& field : fields)
{
query.add_property_name(field.get_name());
}
return ds->features(query);
}
inline std::size_t count_features(mapnik::featureset_ptr features) {
inline std::size_t count_features(mapnik::featureset_ptr features)
{
std::size_t count = 0;
while (features->next()) {
while (features->next())
{
++count;
}
return count;
@ -107,71 +111,54 @@ inline std::size_t count_features(mapnik::featureset_ptr features) {
using attr = std::tuple<std::string, mapnik::value>;
#define REQUIRE_ATTRIBUTES(feature, ...) \
do { \
auto const& _feat = (feature); /* evaluate feature only once */ \
REQUIRE(_feat != nullptr); \
for (auto const& kv : __VA_ARGS__) { \
auto& key = std::get<0>(kv); \
auto& val = std::get<1>(kv); \
CAPTURE(key); \
CHECKED_IF(_feat->has_key(key)) { \
CHECK(_feat->get(key) == val); \
CHECK(_feat->get(key).which() == val.which()); \
} \
} \
#define REQUIRE_ATTRIBUTES(feature, ...) \
do \
{ \
auto const& _feat = (feature); /* evaluate feature only once */ \
REQUIRE(_feat != nullptr); \
for (auto const& kv : __VA_ARGS__) \
{ \
auto& key = std::get<0>(kv); \
auto& val = std::get<1>(kv); \
CAPTURE(key); \
CHECKED_IF(_feat->has_key(key)) \
{ \
CHECK(_feat->get(key) == val); \
CHECK(_feat->get(key).which() == val.which()); \
} \
} \
} while (0)
namespace detail {
template <typename T>
template<typename T>
struct feature_count
{
template <typename U>
std::size_t operator()(U const &geom) const
template<typename U>
std::size_t operator()(U const& geom) const
{
return mapnik::util::apply_visitor(*this, geom);
}
std::size_t operator()(mapnik::geometry::geometry_empty const &) const
{
return 0;
}
std::size_t operator()(mapnik::geometry::geometry_empty const&) const { return 0; }
std::size_t operator()(mapnik::geometry::point<T> const &) const
{
return 1;
}
std::size_t operator()(mapnik::geometry::point<T> const&) const { return 1; }
std::size_t operator()(mapnik::geometry::line_string<T> const &) const
{
return 1;
}
std::size_t operator()(mapnik::geometry::line_string<T> const&) const { return 1; }
std::size_t operator()(mapnik::geometry::polygon<T> const &) const
{
return 1;
}
std::size_t operator()(mapnik::geometry::polygon<T> const&) const { return 1; }
std::size_t operator()(mapnik::geometry::multi_point<T> const &mp) const
{
return mp.size();
}
std::size_t operator()(mapnik::geometry::multi_point<T> const& mp) const { return mp.size(); }
std::size_t operator()(mapnik::geometry::multi_line_string<T> const &mls) const
{
return mls.size();
}
std::size_t operator()(mapnik::geometry::multi_line_string<T> const& mls) const { return mls.size(); }
std::size_t operator()(mapnik::geometry::multi_polygon<T> const &mp) const
{
return mp.size();
}
std::size_t operator()(mapnik::geometry::multi_polygon<T> const& mp) const { return mp.size(); }
std::size_t operator()(mapnik::geometry::geometry_collection<T> const &col) const
std::size_t operator()(mapnik::geometry::geometry_collection<T> const& col) const
{
std::size_t sum = 0;
for (auto const &geom : col) {
for (auto const& geom : col)
{
sum += operator()(geom);
}
return sum;
@ -179,14 +166,14 @@ struct feature_count
};
} // namespace detail
template <typename T>
inline std::size_t feature_count(mapnik::geometry::geometry<T> const &g) {
template<typename T>
inline std::size_t feature_count(mapnik::geometry::geometry<T> const& g)
{
return detail::feature_count<T>()(g);
}
inline void require_geometry(mapnik::feature_ptr feature,
std::size_t num_parts,
mapnik::geometry::geometry_types type) {
inline void require_geometry(mapnik::feature_ptr feature, std::size_t num_parts, mapnik::geometry::geometry_types type)
{
REQUIRE(bool(feature));
CHECK(mapnik::geometry::geometry_type(feature->get_geometry()) == type);
CHECK(feature_count(feature->get_geometry()) == num_parts);
@ -215,6 +202,6 @@ inline int create_disk_index(std::string const& filename, bool silent = true)
return std::system(cmd.c_str());
}
}
} // namespace
#endif // MAPNIK_UNIT_DATSOURCE_UTIL

View file

@ -29,8 +29,7 @@
namespace {
mapnik::datasource_ptr get_gdal_ds(std::string const& file_name,
boost::optional<mapnik::value_integer> band)
mapnik::datasource_ptr get_gdal_ds(std::string const& file_name, boost::optional<mapnik::value_integer> band)
{
std::string gdal_plugin("./plugins/input/gdal.input");
if (!mapnik::util::exists(gdal_plugin))
@ -54,8 +53,8 @@ mapnik::datasource_ptr get_gdal_ds(std::string const& file_name,
} // anonymous namespace
TEST_CASE("gdal") {
TEST_CASE("gdal")
{
SECTION("upsampling")
{
std::string dataset = "test/data/tiff/ndvi_256x256_gray32f_tiled.tif";

View file

@ -35,9 +35,8 @@
#include <locale>
#include <boost/optional/optional_io.hpp>
TEST_CASE("Geobuf") {
TEST_CASE("Geobuf")
{
std::string geobuf_plugin("./plugins/input/geobuf.input");
if (mapnik::util::exists(geobuf_plugin))
{
@ -51,7 +50,7 @@ TEST_CASE("Geobuf") {
auto fs = all_features(ds);
auto f = fs->next();
auto const& geometry = f->get_geometry();
auto const& pt = mapnik::util::get<mapnik::geometry::point<double> >(geometry);
auto const& pt = mapnik::util::get<mapnik::geometry::point<double>>(geometry);
REQUIRE(pt.x == 102.0);
REQUIRE(pt.y == 0.5);
CHECK(fs->next() == nullptr);
@ -67,7 +66,7 @@ TEST_CASE("Geobuf") {
auto fs = all_features(ds);
auto f = fs->next();
auto const& geometry = f->get_geometry();
auto const& mpt = mapnik::util::get<mapnik::geometry::multi_point<double> >(geometry);
auto const& mpt = mapnik::util::get<mapnik::geometry::multi_point<double>>(geometry);
CHECK(mpt.size() == 2);
REQUIRE(mpt[0].x == 100.0);
REQUIRE(mpt[0].y == 0.0);
@ -86,7 +85,7 @@ TEST_CASE("Geobuf") {
auto fs = all_features(ds);
auto f = fs->next();
auto const& geometry = f->get_geometry();
auto const& line = mapnik::util::get<mapnik::geometry::line_string<double> >(geometry);
auto const& line = mapnik::util::get<mapnik::geometry::line_string<double>>(geometry);
CHECK(line.size() == 4);
REQUIRE(line[0].x == 102.0);
REQUIRE(line[0].y == 0);
@ -109,7 +108,7 @@ TEST_CASE("Geobuf") {
auto fs = all_features(ds);
auto f = fs->next();
auto const& geometry = f->get_geometry();
auto const& mline = mapnik::util::get<mapnik::geometry::multi_line_string<double> >(geometry);
auto const& mline = mapnik::util::get<mapnik::geometry::multi_line_string<double>>(geometry);
CHECK(mline.size() == 2);
auto const& line1 = mline[0];
REQUIRE(line1[0].x == 100.0);
@ -127,12 +126,9 @@ TEST_CASE("Geobuf") {
SECTION("Polygon")
{
//{"type":"Feature","id":1,"geometry":{"type":"Polygon","coordinates":[[[100,0],[101,0],[101,1],[100,1],[100,0]],[[100.8,0.8],[100.8,0.2],[100.2,0.2],[100.2,0.8],[100.8,0.8]]]},"properties":{"prop0":"value0","prop1":"{\"this\":\"that\"}"}}
auto files =
{
"./test/data/geobuf/polygon.geobuf",
"./test/data/geobuf/standalone-feature.geobuf",
"./test/data/geobuf/standalone-geometry.geobuf"
};
auto files = {"./test/data/geobuf/polygon.geobuf",
"./test/data/geobuf/standalone-feature.geobuf",
"./test/data/geobuf/standalone-geometry.geobuf"};
mapnik::parameters params;
params["type"] = "geobuf";
@ -144,7 +140,7 @@ TEST_CASE("Geobuf") {
auto fs = all_features(ds);
auto f = fs->next();
auto const& geometry = f->get_geometry();
auto const& poly = mapnik::util::get<mapnik::geometry::polygon<double> >(geometry);
auto const& poly = mapnik::util::get<mapnik::geometry::polygon<double>>(geometry);
CHECK(poly.size() == 2);
auto const& exterior = poly[0];
REQUIRE(exterior[0].x == 100);
@ -184,7 +180,7 @@ TEST_CASE("Geobuf") {
auto fs = all_features(ds);
auto f = fs->next();
auto const& geometry = f->get_geometry();
auto const& mpoly = mapnik::util::get<mapnik::geometry::multi_polygon<double> >(geometry);
auto const& mpoly = mapnik::util::get<mapnik::geometry::multi_polygon<double>>(geometry);
CHECK(mpoly.size() == 2);
{
auto const& poly = mpoly[0];
@ -238,12 +234,12 @@ TEST_CASE("Geobuf") {
auto fs = all_features(ds);
auto f = fs->next();
auto const& geometry = f->get_geometry();
auto const& collection = mapnik::util::get<mapnik::geometry::geometry_collection<double> >(geometry);
auto const& collection = mapnik::util::get<mapnik::geometry::geometry_collection<double>>(geometry);
CHECK(collection.size() == 2);
auto const& pt = mapnik::util::get<mapnik::geometry::point<double> >(collection[0]);
auto const& pt = mapnik::util::get<mapnik::geometry::point<double>>(collection[0]);
REQUIRE(pt.x == 100.0);
REQUIRE(pt.y == 0.0);
auto const& line = mapnik::util::get<mapnik::geometry::line_string<double> >(collection[1]);
auto const& line = mapnik::util::get<mapnik::geometry::line_string<double>>(collection[1]);
REQUIRE(line[0].x == 101.0);
REQUIRE(line[0].y == 0.0);
REQUIRE(line[1].x == 102.0);

View file

@ -48,7 +48,8 @@ clang++ -o test-geojson -g -I./test/ test/unit/run.cpp test/unit/datasource/geoj
namespace {
std::pair<mapnik::datasource_ptr,mapnik::feature_ptr> fetch_first_feature(std::string const& filename, bool cache_features)
std::pair<mapnik::datasource_ptr, mapnik::feature_ptr> fetch_first_feature(std::string const& filename,
bool cache_features)
{
mapnik::parameters params;
params["type"] = "geojson";
@ -64,10 +65,9 @@ std::pair<mapnik::datasource_ptr,mapnik::feature_ptr> fetch_first_feature(std::s
}
auto features = ds->features(query);
auto feature = features->next();
return std::make_pair(ds,feature);
return std::make_pair(ds, feature);
}
void iterate_over_features(mapnik::featureset_ptr features)
{
auto feature = features->next();
@ -77,17 +77,17 @@ void iterate_over_features(mapnik::featureset_ptr features)
}
}
}
TEST_CASE("geojson") {
} // namespace
TEST_CASE("geojson")
{
std::string geojson_plugin("./plugins/input/geojson.input");
if (mapnik::util::exists(geojson_plugin))
{
SECTION("GeoJSON I/O errors")
{
std::string filename = "does_not_exist.geojson";
for (auto create_index : { true, false })
for (auto create_index : {true, false})
{
if (create_index)
{
@ -124,17 +124,14 @@ TEST_CASE("geojson") {
SECTION("GeoJSON empty Geometries handling")
{
auto valid_empty_geometries =
{
"null", // Point can't be empty
"{ \"type\": \"LineString\", \"coordinates\": [] }",
"{ \"type\": \"Polygon\", \"coordinates\": [ [ ] ] } ",
"{ \"type\": \"MultiPoint\", \"coordinates\": [ ] }",
"{ \"type\": \"MultiLineString\", \"coordinates\": [ [] ] }",
"{ \"type\": \"MultiPolygon\", \"coordinates\": [[ []] ] }"
};
auto valid_empty_geometries = {"null", // Point can't be empty
"{ \"type\": \"LineString\", \"coordinates\": [] }",
"{ \"type\": \"Polygon\", \"coordinates\": [ [ ] ] } ",
"{ \"type\": \"MultiPoint\", \"coordinates\": [ ] }",
"{ \"type\": \"MultiLineString\", \"coordinates\": [ [] ] }",
"{ \"type\": \"MultiPolygon\", \"coordinates\": [[ []] ] }"};
for (auto const& in : valid_empty_geometries)
for (auto const& in : valid_empty_geometries)
{
std::string json(in);
mapnik::geometry::geometry<double> geom;
@ -142,24 +139,21 @@ TEST_CASE("geojson") {
// round trip
std::string json_out;
CHECK(mapnik::util::to_geojson(json_out, geom));
json.erase(std::remove_if(
std::begin(json), std::end(json),
[l = std::locale{}](auto ch) { return std::isspace(ch, l); }
), std::end(json));
json.erase(std::remove_if(std::begin(json),
std::end(json),
[l = std::locale{}](auto ch) { return std::isspace(ch, l); }),
std::end(json));
REQUIRE(json == json_out);
}
auto invalid_empty_geometries =
{
"{ \"type\": \"Point\", \"coordinates\": [] }",
"{ \"type\": \"LineString\", \"coordinates\": [[]] }"
"{ \"type\": \"Polygon\", \"coordinates\": [[[]]] }",
"{ \"type\": \"MultiPoint\", \"coordinates\": [[]] }",
"{ \"type\": \"MultiLineString\", \"coordinates\": [[[]]] }",
"{ \"type\": \"MultiPolygon\", \"coordinates\": [[[[]]]] }"
};
auto invalid_empty_geometries = {"{ \"type\": \"Point\", \"coordinates\": [] }",
"{ \"type\": \"LineString\", \"coordinates\": [[]] }"
"{ \"type\": \"Polygon\", \"coordinates\": [[[]]] }",
"{ \"type\": \"MultiPoint\", \"coordinates\": [[]] }",
"{ \"type\": \"MultiLineString\", \"coordinates\": [[[]]] }",
"{ \"type\": \"MultiPolygon\", \"coordinates\": [[[[]]]] }"};
for (auto const& json : invalid_empty_geometries)
for (auto const& json : invalid_empty_geometries)
{
mapnik::geometry::geometry<double> geom;
CHECK(!mapnik::json::from_geojson(json, geom));
@ -169,14 +163,14 @@ TEST_CASE("geojson") {
SECTION("GeoJSON num_features_to_query")
{
std::string filename = "./test/data/json/featurecollection-multipleprops.geojson";
for (mapnik::value_integer num_features_to_query : { mapnik::value_integer(-1),
mapnik::value_integer(0),
mapnik::value_integer(1),
mapnik::value_integer(2),
mapnik::value_integer(3),
std::numeric_limits<mapnik::value_integer>::max()})
for (mapnik::value_integer num_features_to_query : {mapnik::value_integer(-1),
mapnik::value_integer(0),
mapnik::value_integer(1),
mapnik::value_integer(2),
mapnik::value_integer(3),
std::numeric_limits<mapnik::value_integer>::max()})
{
for (auto create_index : { true, false })
for (auto create_index : {true, false})
{
if (create_index)
{
@ -260,7 +254,7 @@ TEST_CASE("geojson") {
CHECK(ds->get_geometry_type() == mapnik::datasource_geometry_t::Point);
auto const& geometry = feature->get_geometry();
REQUIRE(mapnik::geometry::geometry_type(geometry) == mapnik::geometry::Point);
auto const& pt = mapnik::util::get<mapnik::geometry::point<double> >(geometry);
auto const& pt = mapnik::util::get<mapnik::geometry::point<double>>(geometry);
REQUIRE(pt.x == 100);
REQUIRE(pt.y == 0);
}
@ -276,10 +270,9 @@ TEST_CASE("geojson") {
CHECK(ds->get_geometry_type() == mapnik::datasource_geometry_t::LineString);
auto const& geometry = feature->get_geometry();
REQUIRE(mapnik::geometry::geometry_type(geometry) == mapnik::geometry::LineString);
auto const& line = mapnik::util::get<mapnik::geometry::line_string<double> >(geometry);
auto const& line = mapnik::util::get<mapnik::geometry::line_string<double>>(geometry);
REQUIRE(line.size() == 2);
REQUIRE(mapnik::geometry::envelope(line) == mapnik::box2d<double>(100,0,101,1));
REQUIRE(mapnik::geometry::envelope(line) == mapnik::box2d<double>(100, 0, 101, 1));
}
}
@ -293,12 +286,11 @@ TEST_CASE("geojson") {
CHECK(ds->get_geometry_type() == mapnik::datasource_geometry_t::Polygon);
auto const& geometry = feature->get_geometry();
REQUIRE(mapnik::geometry::geometry_type(geometry) == mapnik::geometry::Polygon);
auto const& poly = mapnik::util::get<mapnik::geometry::polygon<double> >(geometry);
auto const& poly = mapnik::util::get<mapnik::geometry::polygon<double>>(geometry);
REQUIRE(poly.size() == 2);
REQUIRE(poly[0].size() == 5);
REQUIRE(poly[1].size() == 5);
REQUIRE(mapnik::geometry::envelope(poly) == mapnik::box2d<double>(100,0,101,1));
REQUIRE(mapnik::geometry::envelope(poly) == mapnik::box2d<double>(100, 0, 101, 1));
}
}
@ -312,9 +304,9 @@ TEST_CASE("geojson") {
CHECK(ds->get_geometry_type() == mapnik::datasource_geometry_t::Point);
auto const& geometry = feature->get_geometry();
REQUIRE(mapnik::geometry::geometry_type(geometry) == mapnik::geometry::MultiPoint);
auto const& multi_pt = mapnik::util::get<mapnik::geometry::multi_point<double> >(geometry);
auto const& multi_pt = mapnik::util::get<mapnik::geometry::multi_point<double>>(geometry);
REQUIRE(multi_pt.size() == 2);
REQUIRE(mapnik::geometry::envelope(multi_pt) == mapnik::box2d<double>(100,0,101,1));
REQUIRE(mapnik::geometry::envelope(multi_pt) == mapnik::box2d<double>(100, 0, 101, 1));
}
}
@ -328,12 +320,11 @@ TEST_CASE("geojson") {
CHECK(ds->get_geometry_type() == mapnik::datasource_geometry_t::LineString);
auto const& geometry = feature->get_geometry();
REQUIRE(mapnik::geometry::geometry_type(geometry) == mapnik::geometry::MultiLineString);
auto const& multi_line = mapnik::util::get<mapnik::geometry::multi_line_string<double> >(geometry);
auto const& multi_line = mapnik::util::get<mapnik::geometry::multi_line_string<double>>(geometry);
REQUIRE(multi_line.size() == 2);
REQUIRE(multi_line[0].size() == 2);
REQUIRE(multi_line[1].size() == 2);
REQUIRE(mapnik::geometry::envelope(multi_line) == mapnik::box2d<double>(100,0,103,3));
REQUIRE(mapnik::geometry::envelope(multi_line) == mapnik::box2d<double>(100, 0, 103, 3));
}
}
@ -348,19 +339,18 @@ TEST_CASE("geojson") {
// test
auto const& geometry = feature->get_geometry();
REQUIRE(mapnik::geometry::geometry_type(geometry) == mapnik::geometry::MultiPolygon);
auto const& multi_poly = mapnik::util::get<mapnik::geometry::multi_polygon<double> >(geometry);
auto const& multi_poly = mapnik::util::get<mapnik::geometry::multi_polygon<double>>(geometry);
REQUIRE(multi_poly.size() == 2);
REQUIRE(multi_poly[0].size() == 1);
REQUIRE(multi_poly[1].size() == 2);
REQUIRE(mapnik::geometry::envelope(multi_poly) == mapnik::box2d<double>(100,0,103,3));
REQUIRE(mapnik::geometry::envelope(multi_poly) == mapnik::box2d<double>(100, 0, 103, 3));
}
}
SECTION("GeoJSON GeometryCollection")
{
std::string filename("./test/data/json/geometrycollection.json");
for (auto create_index : { true, false })
for (auto create_index : {true, false})
{
if (create_index)
{
@ -381,11 +371,11 @@ TEST_CASE("geojson") {
// test
auto const& geometry = feature->get_geometry();
REQUIRE(mapnik::geometry::geometry_type(geometry) == mapnik::geometry::GeometryCollection);
auto const& collection = mapnik::util::get<mapnik::geometry::geometry_collection<double> >(geometry);
auto const& collection = mapnik::util::get<mapnik::geometry::geometry_collection<double>>(geometry);
REQUIRE(collection.size() == 2);
REQUIRE(mapnik::geometry::geometry_type(collection[0]) == mapnik::geometry::Point);
REQUIRE(mapnik::geometry::geometry_type(collection[1]) == mapnik::geometry::LineString);
REQUIRE(mapnik::geometry::envelope(collection) == mapnik::box2d<double>(100,0,102,1));
REQUIRE(mapnik::geometry::envelope(collection) == mapnik::box2d<double>(100, 0, 102, 1));
}
}
}
@ -400,7 +390,7 @@ TEST_CASE("geojson") {
params["base"] = base;
params["file"] = file;
std::string filename = base + file;
for (auto create_index : { true, false })
for (auto create_index : {true, false})
{
if (create_index)
{
@ -425,7 +415,7 @@ TEST_CASE("geojson") {
query.add_property_name(field.get_name());
}
auto features = ds->features(query);
auto features2 = ds->features_at_point(ds->envelope().center(),0);
auto features2 = ds->features_at_point(ds->envelope().center(), 0);
auto feature = features->next();
auto feature2 = features2->next();
REQUIRE(feature != nullptr);
@ -447,8 +437,8 @@ TEST_CASE("geojson") {
mapnik::parameters params;
params["type"] = "geojson";
for (auto const& c_str : {"./test/data/json/feature-null-properties.json",
"./test/data/json/feature-empty-properties.json"})
for (auto const& c_str :
{"./test/data/json/feature-null-properties.json", "./test/data/json/feature-empty-properties.json"})
{
std::string filename(c_str);
params["file"] = filename;
@ -459,7 +449,7 @@ TEST_CASE("geojson") {
mapnik::util::remove(filename + ".index");
}
for (auto create_index : { true, false })
for (auto create_index : {true, false})
{
if (create_index)
{
@ -500,7 +490,7 @@ TEST_CASE("geojson") {
mapnik::util::remove(filename + ".index");
}
for (auto create_index : { true, false })
for (auto create_index : {true, false})
{
if (create_index)
{
@ -528,7 +518,7 @@ TEST_CASE("geojson") {
query.add_property_name(field.get_name());
}
auto features = ds->features(query);
auto features2 = ds->features_at_point(ds->envelope().center(),10);
auto features2 = ds->features_at_point(ds->envelope().center(), 10);
auto bounding_box = ds->envelope();
mapnik::box2d<double> bbox;
mapnik::value_integer count = 0;
@ -536,9 +526,12 @@ TEST_CASE("geojson") {
{
auto feature = features->next();
auto feature2 = features2->next();
if (!feature || !feature2) break;
if (!bbox.valid()) bbox = feature->envelope();
else bbox.expand_to_include(feature->envelope());
if (!feature || !feature2)
break;
if (!bbox.valid())
bbox = feature->envelope();
else
bbox.expand_to_include(feature->envelope());
++count;
REQUIRE(feature->id() == count);
REQUIRE(feature2->id() == count);
@ -567,7 +560,7 @@ TEST_CASE("geojson") {
mapnik::util::remove(filename + ".index");
}
for (auto create_index : { true, false })
for (auto create_index : {true, false})
{
if (create_index)
{
@ -593,7 +586,7 @@ TEST_CASE("geojson") {
auto features = ds->features(query);
auto feature = features->next();
REQUIRE(feature != nullptr);
REQUIRE(feature->envelope() == mapnik::box2d<double>(123,456,123,456));
REQUIRE(feature->envelope() == mapnik::box2d<double>(123, 456, 123, 456));
}
// cleanup
@ -618,7 +611,7 @@ TEST_CASE("geojson") {
mapnik::util::remove(filename + ".index");
}
for (auto create_index : { true, false })
for (auto create_index : {true, false})
{
if (create_index)
{
@ -644,11 +637,11 @@ TEST_CASE("geojson") {
auto features = ds->features(query);
auto feature1 = features->next();
REQUIRE(feature1 != nullptr);
REQUIRE(feature1->envelope() == mapnik::box2d<double>(-122.0,48.0,-122.0,48.0));
REQUIRE(feature1->envelope() == mapnik::box2d<double>(-122.0, 48.0, -122.0, 48.0));
auto feature2 = features->next();
REQUIRE(feature2 != nullptr);
REQUIRE(feature2->envelope() == mapnik::box2d<double>(0.0,51.0,0.0,51.0));
REQUIRE(ds->envelope() == mapnik::box2d<double>(-122.0,48.0,0.0,51.0));
REQUIRE(feature2->envelope() == mapnik::box2d<double>(0.0, 51.0, 0.0, 51.0));
REQUIRE(ds->envelope() == mapnik::box2d<double>(-122.0, 48.0, 0.0, 51.0));
}
// cleanup
@ -665,8 +658,8 @@ TEST_CASE("geojson") {
params["type"] = "geojson";
for (auto const& c_str : {"./test/data/json/feature-malformed-1.geojson",
"./test/data/json/feature-malformed-2.geojson",
"./test/data/json/feature-malformed-3.geojson"})
"./test/data/json/feature-malformed-2.geojson",
"./test/data/json/feature-malformed-3.geojson"})
{
std::string filename(c_str);
params["file"] = filename;
@ -677,7 +670,7 @@ TEST_CASE("geojson") {
mapnik::util::remove(filename + ".index");
}
for (auto create_index : { true, false })
for (auto create_index : {true, false})
{
if (create_index)
{
@ -724,7 +717,7 @@ TEST_CASE("geojson") {
INFO(ret_posix);
CHECK(mapnik::util::exists(filename + ".index"));
for (auto cache_features : {true,false})
for (auto cache_features : {true, false})
{
params["cache_features"] = cache_features;
auto ds = mapnik::datasource_cache::instance().create(params);
@ -755,7 +748,7 @@ TEST_CASE("geojson") {
mapnik::util::remove(filename + ".index");
}
for (auto create_index : { true, false })
for (auto create_index : {true, false})
{
if (create_index)
{
@ -806,7 +799,7 @@ TEST_CASE("geojson") {
mapnik::util::remove(filename + ".index");
}
for (auto create_index : { true, false })
for (auto create_index : {true, false})
{
if (create_index)
{
@ -835,7 +828,7 @@ TEST_CASE("geojson") {
while (feature != nullptr)
{
// ids are in ascending order, starting from 1
mapnik::value val= feature->get("id");
mapnik::value val = feature->get("id");
REQUIRE(val.get<mapnik::value_integer>() == ++count);
feature = features->next();
}
@ -862,7 +855,7 @@ TEST_CASE("geojson") {
mapnik::util::remove(filename + ".index");
}
for (auto create_index : { true, false })
for (auto create_index : {true, false})
{
if (create_index)
{
@ -906,7 +899,7 @@ TEST_CASE("geojson") {
mapnik::util::remove(filename + ".index");
}
for (auto create_index : { true, false })
for (auto create_index : {true, false})
{
if (create_index)
{
@ -924,26 +917,40 @@ TEST_CASE("geojson") {
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(bool(ds));
auto fields = ds->get_descriptor().get_descriptors();
std::initializer_list<std::string> names = {"NOM_FR","array","boolean","description","double","empty_array", "empty_object","int","name","object","spaces"};
std::initializer_list<std::string> names = {"NOM_FR",
"array",
"boolean",
"description",
"double",
"empty_array",
"empty_object",
"int",
"name",
"object",
"spaces"};
REQUIRE_FIELD_NAMES(fields, names);
auto fs = all_features(ds);
std::initializer_list<attr> attrs = {
attr{"name", tr.transcode("Test")},
attr{"NOM_FR", tr.transcode("Québec")},
attr{"boolean", mapnik::value_bool(true)},
attr{"description", tr.transcode("Test: \u005C")},
attr{"double", mapnik::value_double(1.1)},
attr{"int", mapnik::value_integer(1)},
attr{"object", tr.transcode("{\"name\":\"waka\",\"spaces\":\"value with spaces\",\"int\":1,\"double\":1.1,\"boolean\":false"
",\"NOM_FR\":\"Québec\",\"array\":[\"string\",\"value with spaces\",3,1.1,null,true"
",\"Québec\"],\"another_object\":{\"name\":\"nested object\"}}")},
attr{"spaces", tr.transcode("this has spaces")},
attr{"array", tr.transcode("[\"string\",\"value with spaces\",3,1.1,null,true,"
"\"Québec\",{\"name\":\"object within an array\"},"
"[\"array\",\"within\",\"an\",\"array\"]]")},
attr{"empty_array", tr.transcode("[]")},
attr{"empty_object", tr.transcode("{}")},
attr{"name", tr.transcode("Test")},
attr{"NOM_FR", tr.transcode("Québec")},
attr{"boolean", mapnik::value_bool(true)},
attr{"description", tr.transcode("Test: \u005C")},
attr{"double", mapnik::value_double(1.1)},
attr{"int", mapnik::value_integer(1)},
attr{"object",
tr.transcode(
"{\"name\":\"waka\",\"spaces\":\"value with "
"spaces\",\"int\":1,\"double\":1.1,\"boolean\":false"
",\"NOM_FR\":\"Québec\",\"array\":[\"string\",\"value with spaces\",3,1.1,null,true"
",\"Québec\"],\"another_object\":{\"name\":\"nested object\"}}")},
attr{"spaces", tr.transcode("this has spaces")},
attr{"array",
tr.transcode("[\"string\",\"value with spaces\",3,1.1,null,true,"
"\"Québec\",{\"name\":\"object within an array\"},"
"[\"array\",\"within\",\"an\",\"array\"]]")},
attr{"empty_array", tr.transcode("[]")},
attr{"empty_object", tr.transcode("{}")},
};
auto feature = fs->next();
REQUIRE(bool(feature));

View file

@ -28,9 +28,8 @@
#include <mapnik/memory_datasource.hpp>
#include <mapnik/datasource_cache.hpp>
TEST_CASE("memory datasource") {
TEST_CASE("memory datasource")
{
SECTION("empty featureset")
{
mapnik::parameters params;

View file

@ -30,30 +30,30 @@
#include <mapnik/image_util.hpp>
#include <mapnik/util/fs.hpp>
TEST_CASE("ogr") {
TEST_CASE("ogr")
{
std::string geojson_plugin("./plugins/input/ogr.input");
if (mapnik::util::exists(geojson_plugin))
{
SECTION("ogr point feature")
{
mapnik::Map m(256,256);
mapnik::Map m(256, 256);
mapnik::load_map(m, "./test/data/good_maps/point_json.xml");
std::string fontdir("fonts/");
REQUIRE( m.register_fonts(fontdir , true ) );
REQUIRE(m.register_fonts(fontdir, true));
m.zoom_all();
mapnik::image_rgba8 im(256,256);
mapnik::image_rgba8 im(256, 256);
mapnik::agg_renderer<mapnik::image_rgba8> ren(m, im);
ren.apply();
std::string filename("./test/data/images/point_json.png");
if (std::getenv("UPDATE") != nullptr) {
if (std::getenv("UPDATE") != nullptr)
{
mapnik::save_to_file(im, filename);
}
std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(filename,"png"));
std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(filename, "png"));
mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
mapnik::image_rgba8 expected = mapnik::util::get<mapnik::image_rgba8>(data);
REQUIRE(mapnik::compare(expected, im) == 0);
}
}
}

View file

@ -32,7 +32,8 @@
/*
Compile and run just this test:
clang++ -o test-postgis -g -I./test/ test/unit/run.cpp test/unit/datasource/postgis.cpp `mapnik-config --all-flags` && ./test-postgis -d yes
clang++ -o test-postgis -g -I./test/ test/unit/run.cpp test/unit/datasource/postgis.cpp `mapnik-config --all-flags` &&
./test-postgis -d yes
*/
#include <boost/optional/optional_io.hpp>
@ -61,25 +62,24 @@ bool run(std::string const& command, bool okay_to_fail = false)
std::clog << "Running " << cmd << "\n";
}
bool worked = (std::system(cmd.c_str()) == 0);
if (okay_to_fail == true) return true;
if (okay_to_fail == true)
return true;
return worked;
}
std::string const dbname("mapnik-tmp-postgis-test-db");
bool status = false;
bool ping_postmaster()
{
return (run("psql --version")
&& run("dropdb --if-exists " + dbname)
&& run("createdb -T template_postgis " + dbname));
return (run("psql --version") && run("dropdb --if-exists " + dbname) &&
run("createdb -T template_postgis " + dbname));
}
}
TEST_CASE("postgis") {
} // namespace
TEST_CASE("postgis")
{
SECTION("Ping Postmaster (check if server is runnging and accessible")
{
if (!ping_postmaster())
@ -96,12 +96,12 @@ TEST_CASE("postgis") {
{
SECTION("Postgis data initialization")
{
//don't add 'true' here, to get error message, when drop fails. If it works nothing is output
// don't add 'true' here, to get error message, when drop fails. If it works nothing is output
REQUIRE(run("dropdb --if-exists " + dbname));
REQUIRE(run("createdb -T template_postgis " + dbname));
//REQUIRE(run("createdb " + dbname));
// Breaks when raster support is missing (unfortunately this is common)
//REQUIRE(run("psql -c 'CREATE EXTENSION postgis;' " + dbname, true));
// REQUIRE(run("createdb " + dbname));
// Breaks when raster support is missing (unfortunately this is common)
// REQUIRE(run("psql -c 'CREATE EXTENSION postgis;' " + dbname, true));
REQUIRE(run("psql -q -f ./test/data/sql/postgis-create-db-and-tables.sql " + dbname));
}
@ -165,7 +165,8 @@ TEST_CASE("postgis") {
CHECK_THROWS(mapnik::datasource_cache::instance().create(params));
}
SECTION("Postgis initialize dataset with persist_connection, schema, extent, geometry field, autodectect key field, simplify_geometries, row_limit")
SECTION("Postgis initialize dataset with persist_connection, schema, extent, geometry field, autodectect key "
"field, simplify_geometries, row_limit")
{
mapnik::parameters params(base_params);
params["persist_connection"] = "false";
@ -213,8 +214,28 @@ TEST_CASE("postgis") {
REQUIRE(ds != nullptr);
REQUIRE(ds->type() == mapnik::datasource::datasource_t::Vector);
auto fields = ds->get_descriptor().get_descriptors();
require_field_names(fields, { "gid", "colbigint", "col_text", "col-char", "col+bool", "colnumeric", "colsmallint", "colfloat4", "colfloat8", "colcharacter" });
require_field_types(fields, { mapnik::Integer, mapnik::Integer, mapnik::String, mapnik::String, mapnik::Boolean, mapnik::Double, mapnik::Integer, mapnik::Double, mapnik::Double, mapnik::String });
require_field_names(fields,
{"gid",
"colbigint",
"col_text",
"col-char",
"col+bool",
"colnumeric",
"colsmallint",
"colfloat4",
"colfloat8",
"colcharacter"});
require_field_types(fields,
{mapnik::Integer,
mapnik::Integer,
mapnik::String,
mapnik::String,
mapnik::Boolean,
mapnik::Double,
mapnik::Integer,
mapnik::Double,
mapnik::Double,
mapnik::String});
}
SECTION("Postgis iterate features")
@ -223,13 +244,14 @@ TEST_CASE("postgis") {
params["table"] = "test";
params["key_field"] = "gid";
params["max_async_connection"] = "2";
//params["cursor_size"] = "2";
// params["cursor_size"] = "2";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(ds != nullptr);
auto featureset = ds->features_at_point(mapnik::coord2d(1, 1));
mapnik::feature_ptr feature;
while ((bool(feature = featureset->next()))) {
while ((bool(feature = featureset->next())))
{
REQUIRE(feature->get(2).to_string() == feature->get("col_text").to_string());
REQUIRE(feature->get(4).to_bool() == feature->get("col+bool").to_bool());
REQUIRE(feature->get(5).to_double() == feature->get("colnumeric").to_double());
@ -238,12 +260,12 @@ TEST_CASE("postgis") {
featureset = all_features(ds);
feature = featureset->next();
//deactivate char tests for now: not yet implemented.
//add at postgis_datasource.cpp:423
//case 18: // char
//REQUIRE("A" == feature->get("col-char").to_string());
// deactivate char tests for now: not yet implemented.
// add at postgis_datasource.cpp:423
// case 18: // char
// REQUIRE("A" == feature->get("col-char").to_string());
feature = featureset->next();
//REQUIRE("B" == feature->get("col-char").to_string());
// REQUIRE("B" == feature->get("col-char").to_string());
feature = featureset->next();
REQUIRE(false == feature->get("col+bool").to_bool());
}
@ -260,7 +282,8 @@ TEST_CASE("postgis") {
featureset = all_features(ds);
mapnik::feature_ptr feature;
while (bool(feature = featureset->next())) {
while (bool(feature = featureset->next()))
{
CHECK(feature->size() == 10);
}
@ -283,7 +306,8 @@ TEST_CASE("postgis") {
REQUIRE(ds != nullptr);
mapnik::box2d<double> ext = ds->envelope();
CAPTURE(ext);
INFO(std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy());
INFO(std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/"
<< ext.maxy());
REQUIRE(ext.minx() == -2);
REQUIRE(ext.miny() == -2);
REQUIRE(ext.maxx() == 5);
@ -294,9 +318,9 @@ TEST_CASE("postgis") {
{
mapnik::parameters params(base_params);
params["table"] = "(SELECT geom,"
" pg_typeof(!pixel_width!)::text as t_pixel_width,"
" pg_typeof(!pixel_height!)::text as t_pixel_height,"
" pg_typeof(!scale_denominator!)::text as t_scale_denom"
" pg_typeof(!pixel_width!)::text as t_pixel_width,"
" pg_typeof(!pixel_height!)::text as t_pixel_height,"
" pg_typeof(!scale_denominator!)::text as t_scale_denom"
" FROM public.test LIMIT 1) as data";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(ds != nullptr);
@ -319,10 +343,7 @@ TEST_CASE("postgis") {
REQUIRE(ds != nullptr);
auto featureset = all_features(ds);
auto feature = featureset->next();
CHECKED_IF(feature != nullptr)
{
CHECK(feature->get("email").to_string() == "fake@mail.ru");
}
CHECKED_IF(feature != nullptr) { CHECK(feature->get("email").to_string() == "fake@mail.ru"); }
}
SECTION("Postgis interpolates !@uservar! tokens in query")
@ -361,35 +382,34 @@ TEST_CASE("postgis") {
SECTION("Postgis query extent: full dataset")
{
//include schema to increase coverage
// include schema to increase coverage
mapnik::parameters params(base_params);
params["table"] = "(SELECT * FROM public.test) as data";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(ds != nullptr);
mapnik::box2d<double> ext = ds->envelope();
CAPTURE(ext);
INFO(std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy());
INFO(std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/"
<< ext.maxy());
REQUIRE(ext.minx() == -2);
REQUIRE(ext.miny() == -2);
REQUIRE(ext.maxx() == 5);
REQUIRE(ext.maxy() == 4);
}
/* deactivated for merging: still investigating a proper fix
SECTION("Postgis query extent from subquery")
{
mapnik::parameters params(base_params);
params["table"] = "(SELECT * FROM test where gid=4) as data";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(ds != nullptr);
mapnik::box2d<double> ext = ds->envelope();
CAPTURE(ext);
INFO(std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy());
REQUIRE(ext.minx() == 0);
REQUIRE(ext.miny() == 0);
REQUIRE(ext.maxx() == 1);
REQUIRE(ext.maxy() == 2);
}
*/
/* deactivated for merging: still investigating a proper fix
SECTION("Postgis query extent from subquery")
{
mapnik::parameters params(base_params);
params["table"] = "(SELECT * FROM test where gid=4) as data";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(ds != nullptr);
mapnik::box2d<double> ext = ds->envelope();
CAPTURE(ext);
INFO(std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" <<
ext.maxy()); REQUIRE(ext.minx() == 0); REQUIRE(ext.miny() == 0); REQUIRE(ext.maxx() == 1); REQUIRE(ext.maxy()
== 2);
}
*/
SECTION("Postgis query extent: from subquery with 'extent_from_subquery=true'")
{
mapnik::parameters params(base_params);
@ -399,50 +419,47 @@ TEST_CASE("postgis") {
REQUIRE(ds != nullptr);
mapnik::box2d<double> ext = ds->envelope();
CAPTURE(ext);
INFO(std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy());
INFO(std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/"
<< ext.maxy());
REQUIRE(ext.minx() == 0);
REQUIRE(ext.miny() == 0);
REQUIRE(ext.maxx() == 1);
REQUIRE(ext.maxy() == 2);
}
/* deactivated for merging: still investigating a proper fix
SECTION("Postgis query extent: subset with 'extent_from_subquery=true' and 'scale_denominator'")
{
mapnik::parameters params(base_params);
// !!!! postgis-vt-util::z() returns 'null' when 'scale_denominator > 600000000'
// https://github.com/mapbox/postgis-vt-util/blob/559f073877696a6bfea41baf3e1065f9cf4d18d1/postgis-vt-util.sql#L615-L617
params["table"] = "(SELECT * FROM test where gid=4 AND z(!scale_denominator!) BETWEEN 0 AND 22) as data";
params["extent_from_subquery"] = "true";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(ds != nullptr);
mapnik::box2d<double> ext = ds->envelope();
CAPTURE(ext);
INFO("" << std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy());
REQUIRE(ext.minx() == 0);
REQUIRE(ext.miny() == 0);
REQUIRE(ext.maxx() == 1);
REQUIRE(ext.maxy() == 2);
}
*/
/* deactivated for merging: still investigating a proper fix
SECTION("Postgis query extent: subset with 'extent_from_subquery=true' and 'scale_denominator'")
{
mapnik::parameters params(base_params);
// !!!! postgis-vt-util::z() returns 'null' when 'scale_denominator > 600000000'
//
https://github.com/mapbox/postgis-vt-util/blob/559f073877696a6bfea41baf3e1065f9cf4d18d1/postgis-vt-util.sql#L615-L617
params["table"] = "(SELECT * FROM test where gid=4 AND z(!scale_denominator!) BETWEEN 0 AND 22) as data";
params["extent_from_subquery"] = "true";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(ds != nullptr);
mapnik::box2d<double> ext = ds->envelope();
CAPTURE(ext);
INFO("" << std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/"
<< ext.maxy()); REQUIRE(ext.minx() == 0); REQUIRE(ext.miny() == 0); REQUIRE(ext.maxx() == 1);
REQUIRE(ext.maxy() == 2);
}
*/
}
}
TEST_CASE("ConnectionCreator") {
SECTION("ConnectionCreator::id() should not expose password")
TEST_CASE("ConnectionCreator")
{
mapnik::parameters params;
params["host"] = "H";
params["port"] = "1234";
params["dbname"] = "D";
params["user"] = "U";
params["password"] = "SECRET";
params["connect_timeout"] = "5";
params["application_name"] = "A";
ConnectionCreator<Connection> creator(params);
CHECK(creator.id() == "host=H port=1234 dbname=D user=U connect_timeout=5 application_name=A");
}
SECTION("ConnectionCreator::id() should not expose password")
{
mapnik::parameters params;
params["host"] = "H";
params["port"] = "1234";
params["dbname"] = "D";
params["user"] = "U";
params["password"] = "SECRET";
params["connect_timeout"] = "5";
params["application_name"] = "A";
ConnectionCreator<Connection> creator(params);
CHECK(creator.id() == "host=H port=1234 dbname=D user=U connect_timeout=5 application_name=A");
}
}

View file

@ -80,7 +80,8 @@ int create_shapefile_index(std::string const& filename, bool index_parts, bool s
cmd += ".exe";
#endif
cmd += " ";
if (index_parts) cmd+= "--index-parts ";
if (index_parts)
cmd += "--index-parts ";
cmd += filename;
if (silent)
{
@ -93,7 +94,7 @@ int create_shapefile_index(std::string const& filename, bool index_parts, bool s
return std::system(cmd.c_str());
}
}
} // namespace
TEST_CASE("invalid shapeindex")
{
@ -102,8 +103,9 @@ TEST_CASE("invalid shapeindex")
{
SECTION("Invalid index")
{
for (auto val : {std::make_tuple(true, std::string("mapnik-invalid-index.................")), // invalid header
std::make_tuple(false, std::string("mapnik-index................."))}) // valid header + invalid index
for (auto val :
{std::make_tuple(true, std::string("mapnik-invalid-index.................")), // invalid header
std::make_tuple(false, std::string("mapnik-index................."))}) // valid header + invalid index
{
std::string path = "test/data/shp/boundaries.shp";
std::string index_path = path.substr(0, path.rfind(".")) + ".index";
@ -125,7 +127,8 @@ TEST_CASE("invalid shapeindex")
// ensure number of features are the same
CHECK(feature_count == feature_count_indexed);
}
else // the header is valid but index file itself is not - expect datasource to fail and return 0 features.
else // the header is valid but index file itself is not - expect datasource to fail and return 0
// features.
{
CHECK(feature_count_indexed == 0);
}
@ -145,9 +148,9 @@ TEST_CASE("shapeindex")
{
for (auto const& path : mapnik::util::list_directory("test/data/shp/"))
{
if (boost::iends_with(path,".shp"))
if (boost::iends_with(path, ".shp"))
{
for (bool index_parts : {false, true} )
for (bool index_parts : {false, true})
{
CAPTURE(path);
CAPTURE(index_parts);

View file

@ -34,14 +34,14 @@ TEST_CASE("spatial_index")
// value_type must have standard layout (http://en.cppreference.com/w/cpp/types/is_standard_layout)
using value_type = std::int32_t;
using mapnik::filter_in_box;
mapnik::box2d<double> extent(0,0,100,100);
mapnik::box2d<double> extent(0, 0, 100, 100);
mapnik::quad_tree<value_type> tree(extent);
REQUIRE(tree.extent() == extent);
// insert some items
tree.insert(1, mapnik::box2d<double>(10,10,20,20));
tree.insert(2, mapnik::box2d<double>(30,30,40,40));
tree.insert(3, mapnik::box2d<double>(30,10,40,20));
tree.insert(4, mapnik::box2d<double>(1,1,2,2));
tree.insert(1, mapnik::box2d<double>(10, 10, 20, 20));
tree.insert(2, mapnik::box2d<double>(30, 30, 40, 40));
tree.insert(3, mapnik::box2d<double>(30, 10, 40, 20));
tree.insert(4, mapnik::box2d<double>(1, 1, 2, 2));
tree.trim();
REQUIRE(tree.count() == 5);
@ -73,13 +73,19 @@ TEST_CASE("spatial_index")
// query first N elements interface
results.clear();
in.seekg(0, std::ios::beg);
mapnik::util::spatial_index<value_type, filter_in_box, std::istringstream>::query_first_n(filter, in, results, 2);
mapnik::util::spatial_index<value_type, filter_in_box, std::istringstream>::query_first_n(filter,
in,
results,
2);
REQUIRE(results.size() == 2);
REQUIRE(results[0] == 1);
REQUIRE(results[1] == 4);
results.clear();
in.seekg(0, std::ios::beg);
mapnik::util::spatial_index<value_type, filter_in_box, std::istringstream>::query_first_n(filter, in, results, 5);
mapnik::util::spatial_index<value_type, filter_in_box, std::istringstream>::query_first_n(filter,
in,
results,
5);
REQUIRE(results[0] == 1);
REQUIRE(results[1] == 4);
REQUIRE(results[2] == 3);

View file

@ -33,15 +33,16 @@
namespace {
bool parse_topology_string(std::string const& buffer, mapnik::topojson::topology & topo);
bool parse_topology_string(std::string const& buffer, mapnik::topojson::topology& topo);
bool parse_topology(std::string const& filename, mapnik::topojson::topology & topo)
bool parse_topology(std::string const& filename, mapnik::topojson::topology& topo)
{
mapnik::util::file file(filename);
std::string buffer;
buffer.resize(file.size());
std::fread(&buffer[0], buffer.size(), 1, file.get());
if (!file) return false;
if (!file)
return false;
return parse_topology_string(buffer, topo);
}
@ -51,16 +52,15 @@ bool parse_topology_string(std::string const& buffer)
return parse_topology_string(buffer, topo);
}
bool parse_topology_string(std::string const& buffer, mapnik::topojson::topology & topo)
bool parse_topology_string(std::string const& buffer, mapnik::topojson::topology& topo)
{
using space_type = boost::spirit::x3::standard::space_type;
char const* itr = buffer.c_str();
char const* end = itr + buffer.length();
try
{
boost::spirit::x3::phrase_parse(itr, end, mapnik::json::grammar::topology, space_type() , topo);
}
catch (boost::spirit::x3::expectation_failure<char const*> const& ex)
boost::spirit::x3::phrase_parse(itr, end, mapnik::json::grammar::topology, space_type(), topo);
} catch (boost::spirit::x3::expectation_failure<char const*> const& ex)
{
std::cerr << "failed to parse TopoJSON..." << std::endl;
std::cerr << ex.what() << std::endl;
@ -81,7 +81,7 @@ bool parse_topology_string(std::string const& buffer, mapnik::topojson::topology
return (itr == end);
}
}
} // namespace
TEST_CASE("TopoJSON")
{
@ -89,36 +89,12 @@ TEST_CASE("TopoJSON")
{
// + A topology must have a member with the name “objects” whose value is another object.
// + A topology must have a member with the name “arcs” whose value is an array of arcs.
CHECK(parse_topology_string(HEREDOC(
{
"type": "Topology", "objects": {}, "arcs": []
}
)));
CHECK(parse_topology_string(HEREDOC(
{
"type": "Topology", "arcs": [], "objects": {}
}
)));
CHECK(parse_topology_string(HEREDOC(
{
"objects": {}, "type": "Topology", "arcs": []
}
)));
CHECK(parse_topology_string(HEREDOC(
{
"objects": {}, "arcs": [], "type": "Topology"
}
)));
CHECK(parse_topology_string(HEREDOC(
{
"arcs": [], "type": "Topology", "objects": {}
}
)));
CHECK(parse_topology_string(HEREDOC(
{
"arcs": [], "objects": {}, "type": "Topology"
}
)));
CHECK(parse_topology_string(HEREDOC({"type" : "Topology", "objects" : {}, "arcs" : []})));
CHECK(parse_topology_string(HEREDOC({"type" : "Topology", "arcs" : [], "objects" : {}})));
CHECK(parse_topology_string(HEREDOC({"objects" : {}, "type" : "Topology", "arcs" : []})));
CHECK(parse_topology_string(HEREDOC({"objects" : {}, "arcs" : [], "type" : "Topology"})));
CHECK(parse_topology_string(HEREDOC({"arcs" : [], "type" : "Topology", "objects" : {}})));
CHECK(parse_topology_string(HEREDOC({"arcs" : [], "objects" : {}, "type" : "Topology"})));
}
SECTION("geometry parsing")
@ -132,7 +108,8 @@ TEST_CASE("TopoJSON")
REQUIRE(parse_topology(path, topo));
for (auto const& geom : topo.geometries)
{
mapnik::box2d<double> bbox = mapnik::util::apply_visitor(mapnik::topojson::bounding_box_visitor(topo), geom);
mapnik::box2d<double> bbox =
mapnik::util::apply_visitor(mapnik::topojson::bounding_box_visitor(topo), geom);
CHECK(bbox.valid());
mapnik::topojson::feature_generator<mapnik::context_ptr> visitor(ctx, tr, topo, feature_id++);
mapnik::feature_ptr feature = mapnik::util::apply_visitor(visitor, geom);
@ -152,31 +129,34 @@ TEST_CASE("TopoJSON")
mapnik::value_integer feature_id = 0;
for (auto const& geom : topo.geometries)
{
mapnik::box2d<double> bbox = mapnik::util::apply_visitor(mapnik::topojson::bounding_box_visitor(topo), geom);
mapnik::box2d<double> bbox =
mapnik::util::apply_visitor(mapnik::topojson::bounding_box_visitor(topo), geom);
CHECK(bbox.valid());
mapnik::topojson::feature_generator<mapnik::context_ptr> visitor(ctx, tr, topo, feature_id);
mapnik::feature_ptr feature = mapnik::util::apply_visitor(visitor, geom);
CHECK(feature);
CHECK(feature->envelope() == bbox);
std::initializer_list<attr> attrs = {
attr{"name", tr.transcode("Test")},
attr{"NOM_FR", tr.transcode("Québec")},
attr{"boolean", mapnik::value_bool(true)},
attr{"description", tr.transcode("Test: \u005C")},
attr{"double", mapnik::value_double(1.1)},
attr{"int", mapnik::value_integer(1)},
attr{"object", tr.transcode("{\"name\":\"waka\",\"spaces\":\"value with spaces\",\"int\":1,\"double\":1.1,\"boolean\":false"
",\"NOM_FR\":\"Québec\",\"array\":[\"string\",\"value with spaces\",3,1.1,null,true"
",\"Québec\"],\"another_object\":{\"name\":\"nested object\"}}")},
attr{"spaces", tr.transcode("this has spaces")},
attr{"array", tr.transcode("[\"string\",\"value with spaces\",3,1.1,null,true,"
"\"Québec\",{\"name\":\"object within an array\"},"
"[\"array\",\"within\",\"an\",\"array\"]]")},
attr{"empty_array", tr.transcode("[]")},
attr{"empty_object", tr.transcode("{}")},
attr{"name", tr.transcode("Test")},
attr{"NOM_FR", tr.transcode("Québec")},
attr{"boolean", mapnik::value_bool(true)},
attr{"description", tr.transcode("Test: \u005C")},
attr{"double", mapnik::value_double(1.1)},
attr{"int", mapnik::value_integer(1)},
attr{"object",
tr.transcode(
"{\"name\":\"waka\",\"spaces\":\"value with spaces\",\"int\":1,\"double\":1.1,\"boolean\":false"
",\"NOM_FR\":\"Québec\",\"array\":[\"string\",\"value with spaces\",3,1.1,null,true"
",\"Québec\"],\"another_object\":{\"name\":\"nested object\"}}")},
attr{"spaces", tr.transcode("this has spaces")},
attr{"array",
tr.transcode("[\"string\",\"value with spaces\",3,1.1,null,true,"
"\"Québec\",{\"name\":\"object within an array\"},"
"[\"array\",\"within\",\"an\",\"array\"]]")},
attr{"empty_array", tr.transcode("[]")},
attr{"empty_object", tr.transcode("{}")},
};
REQUIRE_ATTRIBUTES(feature, attrs);
}
}
}

View file

@ -16,56 +16,58 @@
#include <mapnik/text/placements/dummy.hpp>
#include <mapnik/text/formatting/text.hpp>
TEST_CASE("fontset") {
TEST_CASE("fontset")
{
SECTION("error")
{
try
{
// create a renderable map with a fontset and a text symbolizer
// and do not register any fonts, to ensure the error thrown is reasonable
mapnik::context_ptr ctx = std::make_shared<mapnik::context_type>();
ctx->push("name");
mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx, 1));
mapnik::transcoder tr("utf-8");
mapnik::value_unicode_string ustr = tr.transcode("hello world!");
feature->put("name", ustr);
mapnik::geometry::point<double> pt(128, 128);
feature->set_geometry(std::move(pt));
SECTION("error") {
try {
// create a renderable map with a fontset and a text symbolizer
// and do not register any fonts, to ensure the error thrown is reasonable
mapnik::context_ptr ctx = std::make_shared<mapnik::context_type>();
ctx->push("name");
mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx,1));
mapnik::transcoder tr("utf-8");
mapnik::value_unicode_string ustr = tr.transcode("hello world!");
feature->put("name",ustr);
mapnik::geometry::point<double> pt(128,128);
feature->set_geometry(std::move(pt));
mapnik::parameters params;
params["type"]="memory";
auto ds = std::make_shared<mapnik::memory_datasource>(params);
ds->push(feature);
mapnik::Map m(256,256);
mapnik::font_set fontset("fontset");
// NOTE: this is a valid font, but will fail because none are registered
fontset.add_face_name("DejaVu Sans Book");
m.insert_fontset("fontset", fontset);
mapnik::layer lyr("layer");
lyr.set_datasource(ds);
lyr.add_style("style");
m.add_layer(lyr);
mapnik::feature_type_style the_style;
mapnik::rule r;
mapnik::text_symbolizer text_sym;
mapnik::text_placements_ptr placement_finder = std::make_shared<mapnik::text_placements_dummy>();
placement_finder->defaults.format_defaults.face_name = "DejaVu Sans Book";
placement_finder->defaults.format_defaults.text_size = 10.0;
placement_finder->defaults.format_defaults.fill = mapnik::color(0,0,0);
placement_finder->defaults.format_defaults.fontset = fontset;
placement_finder->defaults.set_format_tree(std::make_shared<mapnik::formatting::text_node>(mapnik::parse_expression("[name]")));
mapnik::put<mapnik::text_placements_ptr>(text_sym, mapnik::keys::text_placements_, placement_finder);
r.append(std::move(text_sym));
the_style.add_rule(std::move(r));
m.insert_style("style", std::move(the_style) );
m.zoom_to_box(mapnik::box2d<double>(-256,-256,
256,256));
mapnik::image_rgba8 buf(m.width(),m.height());
mapnik::agg_renderer<mapnik::image_rgba8> ren(m,buf);
ren.apply();
} catch (std::exception const& ex) {
REQUIRE(std::string(ex.what()) == std::string("Unable to find specified font face 'DejaVu Sans Book' in font set: 'fontset'"));
mapnik::parameters params;
params["type"] = "memory";
auto ds = std::make_shared<mapnik::memory_datasource>(params);
ds->push(feature);
mapnik::Map m(256, 256);
mapnik::font_set fontset("fontset");
// NOTE: this is a valid font, but will fail because none are registered
fontset.add_face_name("DejaVu Sans Book");
m.insert_fontset("fontset", fontset);
mapnik::layer lyr("layer");
lyr.set_datasource(ds);
lyr.add_style("style");
m.add_layer(lyr);
mapnik::feature_type_style the_style;
mapnik::rule r;
mapnik::text_symbolizer text_sym;
mapnik::text_placements_ptr placement_finder = std::make_shared<mapnik::text_placements_dummy>();
placement_finder->defaults.format_defaults.face_name = "DejaVu Sans Book";
placement_finder->defaults.format_defaults.text_size = 10.0;
placement_finder->defaults.format_defaults.fill = mapnik::color(0, 0, 0);
placement_finder->defaults.format_defaults.fontset = fontset;
placement_finder->defaults.set_format_tree(
std::make_shared<mapnik::formatting::text_node>(mapnik::parse_expression("[name]")));
mapnik::put<mapnik::text_placements_ptr>(text_sym, mapnik::keys::text_placements_, placement_finder);
r.append(std::move(text_sym));
the_style.add_rule(std::move(r));
m.insert_style("style", std::move(the_style));
m.zoom_to_box(mapnik::box2d<double>(-256, -256, 256, 256));
mapnik::image_rgba8 buf(m.width(), m.height());
mapnik::agg_renderer<mapnik::image_rgba8> ren(m, buf);
ren.apply();
} catch (std::exception const& ex)
{
REQUIRE(std::string(ex.what()) ==
std::string("Unable to find specified font face 'DejaVu Sans Book' in font set: 'fontset'"));
}
}
}
}

View file

@ -2,152 +2,51 @@
#include <mapnik/geometry/centroid.hpp>
TEST_CASE("geometry centroid") {
TEST_CASE("geometry centroid")
{
SECTION("empty geometry")
{
mapnik::geometry::geometry_empty geom;
mapnik::geometry::point<double> centroid;
REQUIRE(!mapnik::geometry::centroid(geom, centroid));
}
SECTION("empty geometry") {
SECTION("geometry collection")
{
mapnik::geometry::geometry_collection<double> geom;
mapnik::geometry::point<double> centroid;
REQUIRE(!mapnik::geometry::centroid(geom, centroid));
}
mapnik::geometry::geometry_empty geom;
mapnik::geometry::point<double> centroid;
REQUIRE(!mapnik::geometry::centroid(geom, centroid));
}
SECTION("point")
{
mapnik::geometry::point<double> pt(10, 10);
mapnik::geometry::point<double> centroid;
REQUIRE(mapnik::geometry::centroid(pt, centroid));
REQUIRE(pt.x == centroid.x);
REQUIRE(pt.y == centroid.y);
}
SECTION("geometry collection") {
mapnik::geometry::geometry_collection<double> geom;
mapnik::geometry::point<double> centroid;
REQUIRE(!mapnik::geometry::centroid(geom, centroid));
}
SECTION("point") {
mapnik::geometry::point<double> pt(10, 10);
mapnik::geometry::point<double> centroid;
REQUIRE(mapnik::geometry::centroid(pt, centroid));
REQUIRE(pt.x == centroid.x);
REQUIRE(pt.y == centroid.y);
}
SECTION("linestring") {
mapnik::geometry::line_string<double> line;
line.emplace_back(0, 0);
line.emplace_back(25, 25);
line.emplace_back(50, 50);
mapnik::geometry::point<double> centroid;
REQUIRE(mapnik::geometry::centroid(line, centroid));
REQUIRE(centroid.x == 25);
REQUIRE(centroid.y == 25);
}
SECTION("empty linestring") {
mapnik::geometry::line_string<double> line;
mapnik::geometry::point<double> centroid;
REQUIRE(!mapnik::geometry::centroid(line, centroid));
}
SECTION("polygon") {
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0, 0);
ring.emplace_back(1, 0);
ring.emplace_back(1, 1);
ring.emplace_back(0, 1);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
mapnik::geometry::point<double> centroid;
REQUIRE(mapnik::geometry::centroid(poly, centroid));
REQUIRE(centroid.x == 0.5);
REQUIRE(centroid.y == 0.5);
}
SECTION("polygon with empty exterior ring") {
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
poly.push_back(std::move(ring));
mapnik::geometry::point<double> centroid;
REQUIRE(!mapnik::geometry::centroid(poly, centroid));
}
SECTION("empty polygon") {
mapnik::geometry::polygon<double> poly;
poly.emplace_back();
mapnik::geometry::point<double> centroid;
REQUIRE(!mapnik::geometry::centroid(poly, centroid));
}
SECTION("multi-point") {
mapnik::geometry::multi_point<double> geom;
geom.emplace_back(0, 0);
geom.emplace_back(25, 25);
geom.emplace_back(50, 50);
mapnik::geometry::point<double> centroid;
REQUIRE(mapnik::geometry::centroid(geom, centroid));
REQUIRE(centroid.x == 25);
REQUIRE(centroid.y == 25);
}
SECTION("empty multi-point") {
mapnik::geometry::multi_point<double> geom;
mapnik::geometry::point<double> centroid;
REQUIRE(!mapnik::geometry::centroid(geom, centroid));
}
SECTION("multi-linestring") {
mapnik::geometry::multi_line_string<double> geom;
SECTION("linestring")
{
mapnik::geometry::line_string<double> line;
line.emplace_back(0, 0);
line.emplace_back(0, 25);
line.emplace_back(0, 50);
geom.emplace_back(std::move(line));
line.emplace_back(25, 25);
line.emplace_back(50, 50);
mapnik::geometry::point<double> centroid;
REQUIRE(mapnik::geometry::centroid(line, centroid));
REQUIRE(centroid.x == 25);
REQUIRE(centroid.y == 25);
}
SECTION("empty linestring")
{
mapnik::geometry::line_string<double> line;
line.emplace_back(0, 0);
line.emplace_back(25, 0);
line.emplace_back(50, 0);
geom.emplace_back(std::move(line));
mapnik::geometry::point<double> centroid;
REQUIRE(!mapnik::geometry::centroid(line, centroid));
}
mapnik::geometry::point<double> centroid;
REQUIRE(mapnik::geometry::centroid(geom, centroid));
REQUIRE(centroid.x == 12.5);
REQUIRE(centroid.y == 12.5);
}
SECTION("multi-linestring: one component empty") {
mapnik::geometry::multi_line_string<double> geom;
mapnik::geometry::line_string<double> line;
line.emplace_back(0, 0);
line.emplace_back(0, 25);
line.emplace_back(0, 50);
geom.emplace_back(std::move(line));
geom.emplace_back();
mapnik::geometry::point<double> centroid;
REQUIRE(mapnik::geometry::centroid(geom, centroid));
REQUIRE(centroid.x == 0);
REQUIRE(centroid.y == 25);
}
SECTION("empty multi-linestring") {
mapnik::geometry::multi_line_string<double> geom;
mapnik::geometry::point<double> centroid;
REQUIRE(!mapnik::geometry::centroid(geom, centroid));
}
SECTION("multi-polygon") {
mapnik::geometry::multi_polygon<double> geom;
SECTION("polygon")
{
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
@ -157,50 +56,151 @@ SECTION("multi-polygon") {
ring.emplace_back(0, 1);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
geom.emplace_back(std::move(poly));
mapnik::geometry::point<double> centroid;
REQUIRE(mapnik::geometry::centroid(poly, centroid));
REQUIRE(centroid.x == 0.5);
REQUIRE(centroid.y == 0.5);
}
SECTION("polygon with empty exterior ring")
{
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(1, 1);
ring.emplace_back(2, 1);
ring.emplace_back(2, 2);
ring.emplace_back(1, 2);
ring.emplace_back(1, 1);
poly.push_back(std::move(ring));
geom.emplace_back(std::move(poly));
mapnik::geometry::point<double> centroid;
REQUIRE(!mapnik::geometry::centroid(poly, centroid));
}
mapnik::geometry::point<double> centroid;
REQUIRE(mapnik::geometry::centroid(geom, centroid));
REQUIRE(centroid.x == 1);
REQUIRE(centroid.y == 1);
}
SECTION("empty polygon")
{
mapnik::geometry::polygon<double> poly;
poly.emplace_back();
mapnik::geometry::point<double> centroid;
REQUIRE(!mapnik::geometry::centroid(poly, centroid));
}
SECTION("multi-polygon: one component empty") {
SECTION("multi-point")
{
mapnik::geometry::multi_point<double> geom;
geom.emplace_back(0, 0);
geom.emplace_back(25, 25);
geom.emplace_back(50, 50);
mapnik::geometry::point<double> centroid;
REQUIRE(mapnik::geometry::centroid(geom, centroid));
REQUIRE(centroid.x == 25);
REQUIRE(centroid.y == 25);
}
mapnik::geometry::multi_polygon<double> geom;
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0, 0);
ring.emplace_back(1, 0);
ring.emplace_back(1, 1);
ring.emplace_back(0, 1);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
geom.emplace_back(std::move(poly));
geom.emplace_back();
geom.back().emplace_back();
mapnik::geometry::point<double> centroid;
REQUIRE(mapnik::geometry::centroid(geom, centroid));
REQUIRE(centroid.x == 0.5);
REQUIRE(centroid.y == 0.5);
}
SECTION("empty multi-point")
{
mapnik::geometry::multi_point<double> geom;
mapnik::geometry::point<double> centroid;
REQUIRE(!mapnik::geometry::centroid(geom, centroid));
}
SECTION("empty multi-polygon") {
SECTION("multi-linestring")
{
mapnik::geometry::multi_line_string<double> geom;
{
mapnik::geometry::line_string<double> line;
line.emplace_back(0, 0);
line.emplace_back(0, 25);
line.emplace_back(0, 50);
geom.emplace_back(std::move(line));
}
{
mapnik::geometry::line_string<double> line;
line.emplace_back(0, 0);
line.emplace_back(25, 0);
line.emplace_back(50, 0);
geom.emplace_back(std::move(line));
}
mapnik::geometry::point<double> centroid;
REQUIRE(mapnik::geometry::centroid(geom, centroid));
REQUIRE(centroid.x == 12.5);
REQUIRE(centroid.y == 12.5);
}
mapnik::geometry::multi_polygon<double> geom;
mapnik::geometry::point<double> centroid;
REQUIRE(!mapnik::geometry::centroid(geom, centroid));
}
SECTION("multi-linestring: one component empty")
{
mapnik::geometry::multi_line_string<double> geom;
mapnik::geometry::line_string<double> line;
line.emplace_back(0, 0);
line.emplace_back(0, 25);
line.emplace_back(0, 50);
geom.emplace_back(std::move(line));
geom.emplace_back();
mapnik::geometry::point<double> centroid;
REQUIRE(mapnik::geometry::centroid(geom, centroid));
REQUIRE(centroid.x == 0);
REQUIRE(centroid.y == 25);
}
SECTION("empty multi-linestring")
{
mapnik::geometry::multi_line_string<double> geom;
mapnik::geometry::point<double> centroid;
REQUIRE(!mapnik::geometry::centroid(geom, centroid));
}
SECTION("multi-polygon")
{
mapnik::geometry::multi_polygon<double> geom;
{
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0, 0);
ring.emplace_back(1, 0);
ring.emplace_back(1, 1);
ring.emplace_back(0, 1);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
geom.emplace_back(std::move(poly));
}
{
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(1, 1);
ring.emplace_back(2, 1);
ring.emplace_back(2, 2);
ring.emplace_back(1, 2);
ring.emplace_back(1, 1);
poly.push_back(std::move(ring));
geom.emplace_back(std::move(poly));
}
mapnik::geometry::point<double> centroid;
REQUIRE(mapnik::geometry::centroid(geom, centroid));
REQUIRE(centroid.x == 1);
REQUIRE(centroid.y == 1);
}
SECTION("multi-polygon: one component empty")
{
mapnik::geometry::multi_polygon<double> geom;
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0, 0);
ring.emplace_back(1, 0);
ring.emplace_back(1, 1);
ring.emplace_back(0, 1);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
geom.emplace_back(std::move(poly));
geom.emplace_back();
geom.back().emplace_back();
mapnik::geometry::point<double> centroid;
REQUIRE(mapnik::geometry::centroid(geom, centroid));
REQUIRE(centroid.x == 0.5);
REQUIRE(centroid.y == 0.5);
}
SECTION("empty multi-polygon")
{
mapnik::geometry::multi_polygon<double> geom;
mapnik::geometry::point<double> centroid;
REQUIRE(!mapnik::geometry::centroid(geom, centroid));
}
}

View file

@ -2,88 +2,87 @@
#include <mapnik/geometry/closest_point.hpp>
TEST_CASE("geometry closest point") {
TEST_CASE("geometry closest point")
{
#if BOOST_VERSION >= 106200
SECTION("geometry_empty") {
mapnik::geometry::point<double> pt(0, 0);
mapnik::geometry::geometry_empty empty;
auto result = mapnik::geometry::closest_point(empty, pt);
REQUIRE(result.x == 0.0);
REQUIRE(result.y == 0.0);
REQUIRE(result.distance == -1.0);
}
SECTION("point") {
mapnik::geometry::point<double> pt(0, 0);
mapnik::geometry::point<double> geom(3.0, 4.0);
auto result = mapnik::geometry::closest_point(geom, pt);
REQUIRE(result.x == geom.x);
REQUIRE(result.y == geom.y);
REQUIRE(result.distance == 5.0);
}
SECTION("linestring") {
mapnik::geometry::line_string<double> line;
line.emplace_back(0, 0);
line.emplace_back(0, 100);
line.emplace_back(100, 100);
line.emplace_back(100, 0);
mapnik::geometry::point<double> pt(50, 50);
auto result = mapnik::geometry::closest_point(line, pt);
REQUIRE(result.x == 0.0);
REQUIRE(result.y == 50.0);
REQUIRE(result.distance == 50.0);
}
SECTION("polygon") {
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0, 0);
ring.emplace_back(1, 0);
ring.emplace_back(1, 1);
ring.emplace_back(0, 1);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
SECTION("geometry_empty")
{
// point inside polygon
mapnik::geometry::point<double> pt {0.5, 0.25};
auto result = mapnik::geometry::closest_point(poly, pt);
REQUIRE(result.x == 0.5);
REQUIRE(result.y == 0.25);
REQUIRE(result.distance == 0.0);
mapnik::geometry::point<double> pt(0, 0);
mapnik::geometry::geometry_empty empty;
auto result = mapnik::geometry::closest_point(empty, pt);
REQUIRE(result.x == 0.0);
REQUIRE(result.y == 0.0);
REQUIRE(result.distance == -1.0);
}
SECTION("point")
{
// point outside polygon
mapnik::geometry::point<double> pt {1.25, 0.5};
auto result = mapnik::geometry::closest_point(poly, pt);
REQUIRE(result.x == 1.0);
REQUIRE(result.y == 0.5);
REQUIRE(result.distance == 0.25);
}
{
// point outside polygon
mapnik::geometry::point<double> pt {4.0, 5.0};
auto result = mapnik::geometry::closest_point(poly, pt);
REQUIRE(result.x == 1.0);
REQUIRE(result.y == 1.0);
mapnik::geometry::point<double> pt(0, 0);
mapnik::geometry::point<double> geom(3.0, 4.0);
auto result = mapnik::geometry::closest_point(geom, pt);
REQUIRE(result.x == geom.x);
REQUIRE(result.y == geom.y);
REQUIRE(result.distance == 5.0);
}
SECTION("linestring")
{
// point on polygon boundary
mapnik::geometry::point<double> pt {0, 0.4};
auto result = mapnik::geometry::closest_point(poly, pt);
mapnik::geometry::line_string<double> line;
line.emplace_back(0, 0);
line.emplace_back(0, 100);
line.emplace_back(100, 100);
line.emplace_back(100, 0);
mapnik::geometry::point<double> pt(50, 50);
auto result = mapnik::geometry::closest_point(line, pt);
REQUIRE(result.x == 0.0);
REQUIRE(result.y == 0.4);
REQUIRE(result.distance == 0.0);
REQUIRE(result.y == 50.0);
REQUIRE(result.distance == 50.0);
}
SECTION("polygon")
{
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0, 0);
ring.emplace_back(1, 0);
ring.emplace_back(1, 1);
ring.emplace_back(0, 1);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
{
// point inside polygon
mapnik::geometry::point<double> pt{0.5, 0.25};
auto result = mapnik::geometry::closest_point(poly, pt);
REQUIRE(result.x == 0.5);
REQUIRE(result.y == 0.25);
REQUIRE(result.distance == 0.0);
}
{
// point outside polygon
mapnik::geometry::point<double> pt{1.25, 0.5};
auto result = mapnik::geometry::closest_point(poly, pt);
REQUIRE(result.x == 1.0);
REQUIRE(result.y == 0.5);
REQUIRE(result.distance == 0.25);
}
{
// point outside polygon
mapnik::geometry::point<double> pt{4.0, 5.0};
auto result = mapnik::geometry::closest_point(poly, pt);
REQUIRE(result.x == 1.0);
REQUIRE(result.y == 1.0);
REQUIRE(result.distance == 5.0);
}
{
// point on polygon boundary
mapnik::geometry::point<double> pt{0, 0.4};
auto result = mapnik::geometry::closest_point(poly, pt);
REQUIRE(result.x == 0.0);
REQUIRE(result.y == 0.4);
REQUIRE(result.distance == 0.0);
}
}
}
#endif
}

View file

@ -5,47 +5,49 @@
#include <mapnik/json/geometry_parser.hpp>
#include <mapnik/util/geometry_to_geojson.hpp>
TEST_CASE("geometry") {
TEST_CASE("geometry")
{
SECTION("json point")
{
mapnik::util::file input("./test/data/json/point1.json");
REQUIRE(input);
mapnik::geometry::geometry<double> geom;
REQUIRE(input.data());
std::string json_string(input.data().get(), input.size());
REQUIRE(mapnik::json::from_geojson(json_string, geom));
REQUIRE(geom.is<mapnik::geometry::point<double>>());
auto const& point = mapnik::util::get<mapnik::geometry::point<double>>(geom);
REQUIRE(point.x == 30);
REQUIRE(point.y == 10);
std::string new_json;
REQUIRE(mapnik::util::to_geojson(new_json, geom));
}
SECTION("json point") {
mapnik::util::file input("./test/data/json/point1.json");
REQUIRE( input );
mapnik::geometry::geometry<double> geom;
REQUIRE( input.data() );
std::string json_string(input.data().get(), input.size());
REQUIRE( mapnik::json::from_geojson(json_string, geom) );
REQUIRE( geom.is<mapnik::geometry::point<double> >() );
auto const& point = mapnik::util::get<mapnik::geometry::point<double> >(geom);
REQUIRE( point.x == 30 );
REQUIRE( point.y == 10 );
std::string new_json;
REQUIRE( mapnik::util::to_geojson(new_json, geom) );
}
SECTION("json point reversed") {
mapnik::util::file input("./test/data/json/point2.json");
REQUIRE( input );
mapnik::geometry::geometry<double> geom;
REQUIRE( input.data() );
std::string json_string(input.data().get(), input.size());
REQUIRE( mapnik::json::from_geojson(json_string,geom) );
REQUIRE( geom.is<mapnik::geometry::point<double> >() );
auto const& point = mapnik::util::get<mapnik::geometry::point<double> >(geom);
REQUIRE( point.x == 30 );
REQUIRE( point.y == 10 );
}
SECTION("json point reversed + extra attributes") {
mapnik::util::file input("./test/data/json/point3.json");
REQUIRE( input );
mapnik::geometry::geometry<double> geom;
REQUIRE( input.data() );
std::string json_string(input.data().get(), input.size());
REQUIRE( mapnik::json::from_geojson(json_string,geom) );
REQUIRE( geom.is<mapnik::geometry::point<double> >() );
auto const& point = mapnik::util::get<mapnik::geometry::point<double> >(geom);
REQUIRE( point.x == 30 );
REQUIRE( point.y == 10 );
}
SECTION("json point reversed")
{
mapnik::util::file input("./test/data/json/point2.json");
REQUIRE(input);
mapnik::geometry::geometry<double> geom;
REQUIRE(input.data());
std::string json_string(input.data().get(), input.size());
REQUIRE(mapnik::json::from_geojson(json_string, geom));
REQUIRE(geom.is<mapnik::geometry::point<double>>());
auto const& point = mapnik::util::get<mapnik::geometry::point<double>>(geom);
REQUIRE(point.x == 30);
REQUIRE(point.y == 10);
}
SECTION("json point reversed + extra attributes")
{
mapnik::util::file input("./test/data/json/point3.json");
REQUIRE(input);
mapnik::geometry::geometry<double> geom;
REQUIRE(input.data());
std::string json_string(input.data().get(), input.size());
REQUIRE(mapnik::json::from_geojson(json_string, geom));
REQUIRE(geom.is<mapnik::geometry::point<double>>());
auto const& point = mapnik::util::get<mapnik::geometry::point<double>>(geom);
REQUIRE(point.x == 30);
REQUIRE(point.y == 10);
}
}

View file

@ -5,148 +5,147 @@
namespace {
template <typename T>
template<typename T>
void envelope_test()
{
using namespace mapnik::geometry;
using coord_type = T;
{
geometry<coord_type> geom(point<coord_type>(1,2));
geometry<coord_type> geom(point<coord_type>(1, 2));
mapnik::box2d<coord_type> bbox = mapnik::geometry::envelope(geom);
REQUIRE( bbox.minx() == 1 );
REQUIRE( bbox.miny() == 2 );
REQUIRE( bbox.maxx() == 1 );
REQUIRE( bbox.maxy() == 2 );
REQUIRE(bbox.minx() == 1);
REQUIRE(bbox.miny() == 2);
REQUIRE(bbox.maxx() == 1);
REQUIRE(bbox.maxy() == 2);
}
{
// Test empty geom
geometry<coord_type> geom = mapnik::geometry::geometry_empty();
mapnik::box2d<coord_type> bbox = mapnik::geometry::envelope(geom);
REQUIRE_FALSE( bbox.valid() );
REQUIRE_FALSE(bbox.valid());
}
{
line_string<coord_type> line;
line.emplace_back(0,0);
line.emplace_back(1,1);
line.emplace_back(2,2);
line.emplace_back(0, 0);
line.emplace_back(1, 1);
line.emplace_back(2, 2);
geometry<coord_type> geom(line);
mapnik::box2d<coord_type> bbox = mapnik::geometry::envelope(geom);
REQUIRE( bbox.minx() == 0 );
REQUIRE( bbox.miny() == 0 );
REQUIRE( bbox.maxx() == 2 );
REQUIRE( bbox.maxy() == 2 );
REQUIRE(bbox.minx() == 0);
REQUIRE(bbox.miny() == 0);
REQUIRE(bbox.maxx() == 2);
REQUIRE(bbox.maxy() == 2);
}
{
line_string<coord_type> line;
line.emplace_back(0,0);
line.emplace_back(1,1);
line.emplace_back(2,2);
line.emplace_back(0, 0);
line.emplace_back(1, 1);
line.emplace_back(2, 2);
line_string<coord_type> line2;
line2.emplace_back(0,0);
line2.emplace_back(-1,-1);
line2.emplace_back(-2,-2);
line2.emplace_back(0, 0);
line2.emplace_back(-1, -1);
line2.emplace_back(-2, -2);
multi_line_string<coord_type> multi_line;
multi_line.emplace_back(std::move(line));
multi_line.emplace_back(std::move(line2));
geometry<coord_type> geom(multi_line);
mapnik::box2d<coord_type> bbox = mapnik::geometry::envelope(geom);
REQUIRE( bbox.minx() == -2 );
REQUIRE( bbox.miny() == -2 );
REQUIRE( bbox.maxx() == 2 );
REQUIRE( bbox.maxy() == 2 );
REQUIRE(bbox.minx() == -2);
REQUIRE(bbox.miny() == -2);
REQUIRE(bbox.maxx() == 2);
REQUIRE(bbox.maxy() == 2);
}
{
polygon<coord_type> poly;
linear_ring<coord_type> ring;
ring.emplace_back(0,0);
ring.emplace_back(-10,0);
ring.emplace_back(-10,10);
ring.emplace_back(0,10);
ring.emplace_back(0,0);
ring.emplace_back(0, 0);
ring.emplace_back(-10, 0);
ring.emplace_back(-10, 10);
ring.emplace_back(0, 10);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
geometry<coord_type> geom(poly);
mapnik::box2d<coord_type> bbox = mapnik::geometry::envelope(geom);
REQUIRE( bbox.minx() == -10 );
REQUIRE( bbox.miny() == 0 );
REQUIRE( bbox.maxx() == 0 );
REQUIRE( bbox.maxy() == 10 );
REQUIRE(bbox.minx() == -10);
REQUIRE(bbox.miny() == 0);
REQUIRE(bbox.maxx() == 0);
REQUIRE(bbox.maxy() == 10);
multi_polygon<coord_type> mp;
mp.push_back(poly);
geometry<coord_type> geom_mp(mp);
bbox = mapnik::geometry::envelope(geom_mp);
REQUIRE( bbox.minx() == -10 );
REQUIRE( bbox.miny() == 0 );
REQUIRE( bbox.maxx() == 0 );
REQUIRE( bbox.maxy() == 10 );
REQUIRE(bbox.minx() == -10);
REQUIRE(bbox.miny() == 0);
REQUIRE(bbox.maxx() == 0);
REQUIRE(bbox.maxy() == 10);
geometry_collection<coord_type> gc;
bbox = mapnik::geometry::envelope(gc);
REQUIRE_FALSE( bbox.valid() );
REQUIRE_FALSE(bbox.valid());
gc.push_back(geom_mp);
bbox = mapnik::geometry::envelope(gc);
REQUIRE( bbox.minx() == -10 );
REQUIRE( bbox.miny() == 0 );
REQUIRE( bbox.maxx() == 0 );
REQUIRE( bbox.maxy() == 10 );
gc.emplace_back(point<coord_type>(-50,-50));
REQUIRE(bbox.minx() == -10);
REQUIRE(bbox.miny() == 0);
REQUIRE(bbox.maxx() == 0);
REQUIRE(bbox.maxy() == 10);
gc.emplace_back(point<coord_type>(-50, -50));
bbox = mapnik::geometry::envelope(gc);
REQUIRE( bbox.minx() == -50 );
REQUIRE( bbox.miny() == -50 );
REQUIRE( bbox.maxx() == 0 );
REQUIRE( bbox.maxy() == 10 );
REQUIRE(bbox.minx() == -50);
REQUIRE(bbox.miny() == -50);
REQUIRE(bbox.maxx() == 0);
REQUIRE(bbox.maxy() == 10);
}
{
// polygon with hole
polygon<coord_type> poly;
linear_ring<coord_type> ring;
ring.emplace_back(0,0);
ring.emplace_back(-10,0);
ring.emplace_back(-10,10);
ring.emplace_back(0,10);
ring.emplace_back(0,0);
ring.emplace_back(0, 0);
ring.emplace_back(-10, 0);
ring.emplace_back(-10, 10);
ring.emplace_back(0, 10);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
linear_ring<coord_type> hole;
hole.emplace_back(-7,7);
hole.emplace_back(-7,3);
hole.emplace_back(-3,3);
hole.emplace_back(-3,7);
hole.emplace_back(-7,7);
hole.emplace_back(-7, 7);
hole.emplace_back(-7, 3);
hole.emplace_back(-3, 3);
hole.emplace_back(-3, 7);
hole.emplace_back(-7, 7);
poly.push_back(std::move(hole));
geometry<coord_type> geom(poly);
mapnik::box2d<coord_type> bbox = mapnik::geometry::envelope(poly);
REQUIRE( bbox.minx() == -10 );
REQUIRE( bbox.miny() == 0 );
REQUIRE( bbox.maxx() == 0 );
REQUIRE( bbox.maxy() == 10 );
REQUIRE(bbox.minx() == -10);
REQUIRE(bbox.miny() == 0);
REQUIRE(bbox.maxx() == 0);
REQUIRE(bbox.maxy() == 10);
// add another hole inside the first hole
// which should be considered a hit
linear_ring<coord_type> fill;
fill.emplace_back(-6,4);
fill.emplace_back(-6,6);
fill.emplace_back(-4,6);
fill.emplace_back(-4,4);
fill.emplace_back(-6,4);
fill.emplace_back(-6, 4);
fill.emplace_back(-6, 6);
fill.emplace_back(-4, 6);
fill.emplace_back(-4, 4);
fill.emplace_back(-6, 4);
poly.push_back(std::move(fill));
bbox = mapnik::geometry::envelope(poly);
REQUIRE( bbox.minx() == -10 );
REQUIRE( bbox.miny() == 0 );
REQUIRE( bbox.maxx() == 0 );
REQUIRE( bbox.maxy() == 10 );
REQUIRE(bbox.minx() == -10);
REQUIRE(bbox.miny() == 0);
REQUIRE(bbox.maxx() == 0);
REQUIRE(bbox.maxy() == 10);
}
}
}
} // namespace
TEST_CASE("geometry ops - envelope") {
SECTION("envelope_test")
TEST_CASE("geometry ops - envelope")
{
envelope_test<int>();
envelope_test<double>();
envelope_test<float>();
}
SECTION("envelope_test")
{
envelope_test<int>();
envelope_test<double>();
envelope_test<float>();
}
}

View file

@ -16,8 +16,8 @@ MAPNIK_DISABLE_WARNING_PUSH
MAPNIK_DISABLE_WARNING_POP
// helper namespace to ensure correct functionality
namespace aux{
namespace adl{
namespace aux {
namespace adl {
using std::begin;
using std::end;
@ -25,60 +25,57 @@ template<class T>
auto do_begin(T& v) -> decltype(begin(v));
template<class T>
auto do_end(T& v) -> decltype(end(v));
} // adl::
} // namespace adl
template<class... Its>
using zipper_it = boost::zip_iterator<boost::tuple<Its...>>;
template<class T>
T const& as_const(T const& v){ return v; }
} // aux::
T const& as_const(T const& v)
{
return v;
}
} // namespace aux
template<class... Conts>
auto zip_begin(Conts&... conts)
-> aux::zipper_it<decltype(aux::adl::do_begin(conts))...>
auto zip_begin(Conts&... conts) -> aux::zipper_it<decltype(aux::adl::do_begin(conts))...>
{
using std::begin;
return {boost::make_tuple(begin(conts)...)};
using std::begin;
return {boost::make_tuple(begin(conts)...)};
}
template<class... Conts>
auto zip_end(Conts&... conts)
-> aux::zipper_it<decltype(aux::adl::do_end(conts))...>
auto zip_end(Conts&... conts) -> aux::zipper_it<decltype(aux::adl::do_end(conts))...>
{
using std::end;
return {boost::make_tuple(end(conts)...)};
using std::end;
return {boost::make_tuple(end(conts)...)};
}
template<class... Conts>
auto zip_range(Conts&... conts)
-> boost::iterator_range<decltype(zip_begin(conts...))>
auto zip_range(Conts&... conts) -> boost::iterator_range<decltype(zip_begin(conts...))>
{
return {zip_begin(conts...), zip_end(conts...)};
return {zip_begin(conts...), zip_end(conts...)};
}
// for const access
template<class... Conts>
auto zip_cbegin(Conts&... conts)
-> decltype(zip_begin(aux::as_const(conts)...))
auto zip_cbegin(Conts&... conts) -> decltype(zip_begin(aux::as_const(conts)...))
{
using std::begin;
return zip_begin(aux::as_const(conts)...);
using std::begin;
return zip_begin(aux::as_const(conts)...);
}
template<class... Conts>
auto zip_cend(Conts&... conts)
-> decltype(zip_end(aux::as_const(conts)...))
auto zip_cend(Conts&... conts) -> decltype(zip_end(aux::as_const(conts)...))
{
using std::end;
return zip_end(aux::as_const(conts)...);
using std::end;
return zip_end(aux::as_const(conts)...);
}
template<class... Conts>
auto zip_crange(Conts&... conts)
-> decltype(zip_range(aux::as_const(conts)...))
auto zip_crange(Conts&... conts) -> decltype(zip_range(aux::as_const(conts)...))
{
return zip_range(aux::as_const(conts)...);
return zip_range(aux::as_const(conts)...);
}
// mapnik
@ -86,42 +83,42 @@ auto zip_crange(Conts&... conts)
#include <mapnik/util/variant.hpp>
using mapnik::geometry::geometry;
using mapnik::geometry::geometry_empty;
using mapnik::geometry::point;
using mapnik::geometry::line_string;
using mapnik::geometry::polygon;
using mapnik::geometry::multi_point;
using mapnik::geometry::multi_line_string;
using mapnik::geometry::multi_polygon;
using mapnik::geometry::geometry_collection;
using mapnik::geometry::geometry_empty;
using mapnik::geometry::line_string;
using mapnik::geometry::multi_line_string;
using mapnik::geometry::multi_point;
using mapnik::geometry::multi_polygon;
using mapnik::geometry::point;
using mapnik::geometry::polygon;
template <typename T>
template<typename T>
void assert_g_equal(geometry<T> const& g1, geometry<T> const& g2);
struct geometry_equal_visitor
{
template <typename T1, typename T2>
void operator() (T1 const&, T2 const&) const
template<typename T1, typename T2>
void operator()(T1 const&, T2 const&) const
{
// comparing two different types!
REQUIRE(false);
}
template <typename T>
void operator() (geometry_empty const&, geometry_empty const&) const
template<typename T>
void operator()(geometry_empty const&, geometry_empty const&) const
{
REQUIRE(true);
}
template <typename T>
void operator() (point<T> const& p1, point<T> const& p2) const
template<typename T>
void operator()(point<T> const& p1, point<T> const& p2) const
{
REQUIRE(p1.x == Approx(p2.x));
REQUIRE(p1.y == Approx(p2.y));
}
template <typename T>
void operator() (std::vector<point<T>> const& ls1, std::vector<point<T>> const& ls2) const
template<typename T>
void operator()(std::vector<point<T>> const& ls1, std::vector<point<T>> const& ls2) const
{
if (ls1.size() != ls2.size())
{
@ -135,8 +132,8 @@ struct geometry_equal_visitor
}
}
template <typename T>
void operator() (polygon<T> const& p1, polygon<T> const& p2) const
template<typename T>
void operator()(polygon<T> const& p1, polygon<T> const& p2) const
{
if (p1.size() != p2.size())
{
@ -150,23 +147,20 @@ struct geometry_equal_visitor
}
}
template <typename T>
void operator() (line_string<T> const& ls1, line_string<T> const& ls2) const
template<typename T>
void operator()(line_string<T> const& ls1, line_string<T> const& ls2) const
{
(*this)(static_cast<std::vector<point<T>> const&>(ls1),
static_cast<std::vector<point<T>> const&>(ls2));
(*this)(static_cast<std::vector<point<T>> const&>(ls1), static_cast<std::vector<point<T>> const&>(ls2));
}
template <typename T>
void operator() (multi_point<T> const& mp1, multi_point<T> const& mp2) const
template<typename T>
void operator()(multi_point<T> const& mp1, multi_point<T> const& mp2) const
{
(*this)(static_cast<std::vector<point<T>> const&>(mp1),
static_cast<std::vector<point<T>> const&>(mp2));
(*this)(static_cast<std::vector<point<T>> const&>(mp1), static_cast<std::vector<point<T>> const&>(mp2));
}
template <typename T>
void operator() (multi_line_string<T> const& mls1, multi_line_string<T> const& mls2) const
template<typename T>
void operator()(multi_line_string<T> const& mls1, multi_line_string<T> const& mls2) const
{
if (mls1.size() != mls2.size())
{
@ -175,12 +169,12 @@ struct geometry_equal_visitor
for (auto const ls : zip_crange(mls1, mls2))
{
(*this)(ls.template get<0>(),ls.template get<1>());
(*this)(ls.template get<0>(), ls.template get<1>());
}
}
template <typename T>
void operator() (multi_polygon<T> const& mpoly1, multi_polygon<T> const& mpoly2) const
template<typename T>
void operator()(multi_polygon<T> const& mpoly1, multi_polygon<T> const& mpoly2) const
{
if (mpoly1.size() != mpoly2.size())
{
@ -189,12 +183,13 @@ struct geometry_equal_visitor
for (auto const poly : zip_crange(mpoly1, mpoly2))
{
(*this)(poly.template get<0>(),poly.template get<1>());
(*this)(poly.template get<0>(), poly.template get<1>());
}
}
template <typename T>
void operator() (mapnik::util::recursive_wrapper<geometry_collection<T> > const& c1_, mapnik::util::recursive_wrapper<geometry_collection<T> > const& c2_) const
template<typename T>
void operator()(mapnik::util::recursive_wrapper<geometry_collection<T>> const& c1_,
mapnik::util::recursive_wrapper<geometry_collection<T>> const& c2_) const
{
geometry_collection<T> const& c1 = static_cast<geometry_collection<T> const&>(c1_);
geometry_collection<T> const& c2 = static_cast<geometry_collection<T> const&>(c2_);
@ -205,12 +200,12 @@ struct geometry_equal_visitor
for (auto const g : zip_crange(c1, c2))
{
assert_g_equal(g.template get<0>(),g.template get<1>());
assert_g_equal(g.template get<0>(), g.template get<1>());
}
}
template <typename T>
void operator() (geometry_collection<T> const& c1, geometry_collection<T> const& c2) const
template<typename T>
void operator()(geometry_collection<T> const& c1, geometry_collection<T> const& c2) const
{
if (c1.size() != c2.size())
{
@ -219,21 +214,21 @@ struct geometry_equal_visitor
for (auto const g : zip_crange(c1, c2))
{
assert_g_equal(g.template get<0>(),g.template get<1>());
assert_g_equal(g.template get<0>(), g.template get<1>());
}
}
};
template <typename T>
template<typename T>
void assert_g_equal(geometry<T> const& g1, geometry<T> const& g2)
{
return mapnik::util::apply_visitor(geometry_equal_visitor(), g1, g2);
}
template <typename T>
template<typename T>
void assert_g_equal(T const& g1, T const& g2)
{
return geometry_equal_visitor()(g1,g2);
return geometry_equal_visitor()(g1, g2);
}
#endif // MAPNIK_UNIT_GEOMETRY_EQUAL

View file

@ -4,105 +4,105 @@
#include <mapnik/hit_test_filter.hpp>
#include <mapnik/geometry/correct.hpp>
TEST_CASE("geometry ops") {
TEST_CASE("geometry ops")
{
SECTION("hit_test_filter - double")
{
using namespace mapnik::geometry;
{
geometry<double> geom(point<double>(0, 0));
REQUIRE(mapnik::hit_test(geom, 0, 0, 0));
}
{
geometry<double> geom(point<double>(0, 0));
REQUIRE(mapnik::hit_test(geom, 1, 0, 1));
}
{
geometry<double> geom(point<double>(0, 0));
REQUIRE(mapnik::hit_test(geom, 0, 1, 1));
}
{
geometry<double> geom(point<double>(0, 0));
REQUIRE(mapnik::hit_test(geom, 1, 1, 1.5));
}
{
line_string<double> line;
line.emplace_back(0, 0);
line.emplace_back(1, 1);
line.emplace_back(2, 2);
geometry<double> geom(line);
REQUIRE(mapnik::hit_test(geom, 0, 0, 1.5));
}
{
line_string<double> line;
line.emplace_back(0, 0);
line.emplace_back(1, 1);
line.emplace_back(2, 2);
multi_line_string<double> multi_line;
multi_line.emplace_back(std::move(line));
geometry<double> geom(multi_line);
REQUIRE(mapnik::hit_test(geom, 0, 0, 1.5));
}
{
polygon<double> poly;
linear_ring<double> ring;
ring.emplace_back(0, 0);
ring.emplace_back(-10, 0);
ring.emplace_back(-10, 10);
ring.emplace_back(0, 10);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
geometry<double> geom(poly);
REQUIRE(mapnik::hit_test(geom, -5, 5, 0));
SECTION("hit_test_filter - double") {
using namespace mapnik::geometry;
{
geometry<double> geom(point<double>(0,0));
REQUIRE( mapnik::hit_test(geom,0,0,0) );
}
{
geometry<double> geom(point<double>(0,0));
REQUIRE( mapnik::hit_test(geom,1,0,1) );
}
{
geometry<double> geom(point<double>(0,0));
REQUIRE( mapnik::hit_test(geom,0,1,1) );
}
{
geometry<double> geom(point<double>(0,0));
REQUIRE( mapnik::hit_test(geom,1,1,1.5) );
}
{
line_string<double> line;
line.emplace_back(0,0);
line.emplace_back(1,1);
line.emplace_back(2,2);
geometry<double> geom(line);
REQUIRE( mapnik::hit_test(geom,0,0,1.5) );
}
{
line_string<double> line;
line.emplace_back(0,0);
line.emplace_back(1,1);
line.emplace_back(2,2);
multi_line_string<double> multi_line;
multi_line.emplace_back(std::move(line));
geometry<double> geom(multi_line);
REQUIRE( mapnik::hit_test(geom,0,0,1.5) );
}
{
polygon<double> poly;
linear_ring<double> ring;
ring.emplace_back(0,0);
ring.emplace_back(-10,0);
ring.emplace_back(-10,10);
ring.emplace_back(0,10);
ring.emplace_back(0,0);
poly.push_back(std::move(ring));
geometry<double> geom(poly);
REQUIRE( mapnik::hit_test(geom,-5,5,0) );
multi_polygon<double> mp;
mp.push_back(poly);
geometry<double> geom_mp(mp);
REQUIRE(mapnik::hit_test(geom_mp, -5, 5, 0));
multi_polygon<double> mp;
mp.push_back(poly);
geometry<double> geom_mp(mp);
REQUIRE( mapnik::hit_test(geom_mp,-5,5,0) );
correct(geom);
REQUIRE(mapnik::hit_test(geom, -5, 5, 0));
correct(geom_mp);
REQUIRE(mapnik::hit_test(geom_mp, -5, 5, 0));
correct(geom);
REQUIRE( mapnik::hit_test(geom,-5,5,0) );
correct(geom_mp);
REQUIRE( mapnik::hit_test(geom_mp,-5,5,0) );
geometry_collection<double> gc;
REQUIRE(!mapnik::hit_test(geometry<double>(gc), -5, 5, 0));
gc.push_back(geom_mp);
REQUIRE(mapnik::hit_test(geometry<double>(gc), -5, 5, 0));
REQUIRE(!mapnik::hit_test(geometry<double>(gc), -50, -50, 0));
gc.emplace_back(point<double>(-50, -50));
REQUIRE(mapnik::hit_test(geometry<double>(gc), -50, -50, 0));
}
geometry_collection<double> gc;
REQUIRE( !mapnik::hit_test(geometry<double>(gc),-5,5,0) );
gc.push_back(geom_mp);
REQUIRE( mapnik::hit_test(geometry<double>(gc),-5,5,0) );
REQUIRE( !mapnik::hit_test(geometry<double>(gc),-50,-50,0) );
gc.emplace_back(point<double>(-50,-50));
REQUIRE( mapnik::hit_test(geometry<double>(gc),-50,-50,0) );
}
{
// polygon with hole
polygon<double> poly;
linear_ring<double> ring;
ring.emplace_back(0,0);
ring.emplace_back(-10,0);
ring.emplace_back(-10,10);
ring.emplace_back(0,10);
ring.emplace_back(0,0);
poly.push_back(std::move(ring));
linear_ring<double> hole;
hole.emplace_back(-7,7);
hole.emplace_back(-7,3);
hole.emplace_back(-3,3);
hole.emplace_back(-3,7);
hole.emplace_back(-7,7);
poly.push_back(std::move(hole));
geometry<double> geom(poly);
REQUIRE( !mapnik::hit_test(geom,-5,5,0) );
// add another hole inside the first hole
// which should be considered a hit
linear_ring<double> fill;
fill.emplace_back(-6,4);
fill.emplace_back(-6,6);
fill.emplace_back(-4,6);
fill.emplace_back(-4,4);
fill.emplace_back(-6,4);
poly.push_back(std::move(fill));
REQUIRE( mapnik::hit_test(geometry<double>(poly),-5,5,0) );
{
// polygon with hole
polygon<double> poly;
linear_ring<double> ring;
ring.emplace_back(0, 0);
ring.emplace_back(-10, 0);
ring.emplace_back(-10, 10);
ring.emplace_back(0, 10);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
linear_ring<double> hole;
hole.emplace_back(-7, 7);
hole.emplace_back(-7, 3);
hole.emplace_back(-3, 3);
hole.emplace_back(-3, 7);
hole.emplace_back(-7, 7);
poly.push_back(std::move(hole));
geometry<double> geom(poly);
REQUIRE(!mapnik::hit_test(geom, -5, 5, 0));
// add another hole inside the first hole
// which should be considered a hit
linear_ring<double> fill;
fill.emplace_back(-6, 4);
fill.emplace_back(-6, 6);
fill.emplace_back(-4, 6);
fill.emplace_back(-4, 4);
fill.emplace_back(-6, 4);
poly.push_back(std::move(fill));
REQUIRE(mapnik::hit_test(geometry<double>(poly), -5, 5, 0));
}
}
}
}

View file

@ -4,350 +4,382 @@
#include <mapnik/geometry.hpp>
#include <mapnik/geometry/is_simple.hpp>
TEST_CASE("geometry is_simple") {
TEST_CASE("geometry is_simple")
{
// only Boost >= 1.58 has the required is_valid function version
#if BOOST_VERSION >= 105800
SECTION("point") {
mapnik::geometry::geometry_empty empty;
CHECK( mapnik::geometry::is_simple(empty) );
}
SECTION("point")
{
mapnik::geometry::geometry_empty empty;
CHECK(mapnik::geometry::is_simple(empty));
}
SECTION("point") {
mapnik::geometry::point<double> pt(0,0);
CHECK( mapnik::geometry::is_simple(pt) );
}
SECTION("point")
{
mapnik::geometry::point<double> pt(0, 0);
CHECK(mapnik::geometry::is_simple(pt));
}
SECTION("point uninitialized") {
mapnik::geometry::point<double> pt2;
CHECK( mapnik::geometry::is_simple(pt2) );
}
SECTION("point uninitialized")
{
mapnik::geometry::point<double> pt2;
CHECK(mapnik::geometry::is_simple(pt2));
}
SECTION("point -- geometry object") {
mapnik::geometry::point<double> pt(0,0);
mapnik::geometry::geometry<double> geom(pt);
CHECK( mapnik::geometry::is_simple(geom) );
}
SECTION("point -- geometry object")
{
mapnik::geometry::point<double> pt(0, 0);
mapnik::geometry::geometry<double> geom(pt);
CHECK(mapnik::geometry::is_simple(geom));
}
// This is funky that boost geometry is_simple does not check for NAN when dealing with a point
// this test is here in case the logic ever changes
// Bug report on this: https://svn.boost.org/trac/boost/ticket/11711
SECTION("point NaN") {
mapnik::geometry::point<double> pt(std::numeric_limits<double>::quiet_NaN(),std::numeric_limits<double>::quiet_NaN());
CHECK( std::isnan(pt.x) );
CHECK( std::isnan(pt.y) );
CHECK( mapnik::geometry::is_simple(pt) );
}
// This is funky that boost geometry is_simple does not check for NAN when dealing with a point
// this test is here in case the logic ever changes
// Bug report on this: https://svn.boost.org/trac/boost/ticket/11711
SECTION("point NaN")
{
mapnik::geometry::point<double> pt(std::numeric_limits<double>::quiet_NaN(),
std::numeric_limits<double>::quiet_NaN());
CHECK(std::isnan(pt.x));
CHECK(std::isnan(pt.y));
CHECK(mapnik::geometry::is_simple(pt));
}
// This is funky that boost geometry is_simple does not check for infinity when dealing with a point
// this test is here in case the logic ever changes
// Bug report on this: https://svn.boost.org/trac/boost/ticket/11711
SECTION("point Infinity") {
mapnik::geometry::point<double> pt(std::numeric_limits<double>::infinity(),std::numeric_limits<double>::infinity());
CHECK( std::isinf(pt.x) );
CHECK( std::isinf(pt.y) );
CHECK( mapnik::geometry::is_simple(pt) );
}
// This is funky that boost geometry is_simple does not check for infinity when dealing with a point
// this test is here in case the logic ever changes
// Bug report on this: https://svn.boost.org/trac/boost/ticket/11711
SECTION("point Infinity")
{
mapnik::geometry::point<double> pt(std::numeric_limits<double>::infinity(),
std::numeric_limits<double>::infinity());
CHECK(std::isinf(pt.x));
CHECK(std::isinf(pt.y));
CHECK(mapnik::geometry::is_simple(pt));
}
SECTION("multi point") {
mapnik::geometry::multi_point<double> mpt;
mpt.emplace_back(0,0);
mpt.emplace_back(1,1);
CHECK( mapnik::geometry::is_simple(mpt) );
}
SECTION("multi point")
{
mapnik::geometry::multi_point<double> mpt;
mpt.emplace_back(0, 0);
mpt.emplace_back(1, 1);
CHECK(mapnik::geometry::is_simple(mpt));
}
SECTION("multi point empty") {
mapnik::geometry::multi_point<double> mpt;
CHECK( mapnik::geometry::is_simple(mpt) );
}
SECTION("multi point empty")
{
mapnik::geometry::multi_point<double> mpt;
CHECK(mapnik::geometry::is_simple(mpt));
}
SECTION("line_string") {
mapnik::geometry::line_string<double> line;
line.emplace_back(0,0);
line.emplace_back(1,1);
CHECK( mapnik::geometry::is_simple(line) );
}
SECTION("line_string")
{
mapnik::geometry::line_string<double> line;
line.emplace_back(0, 0);
line.emplace_back(1, 1);
CHECK(mapnik::geometry::is_simple(line));
}
// This fails while is_valid will not fail!
SECTION("line_string repeated points") {
mapnik::geometry::line_string<double> line;
line.emplace_back(0,0);
line.emplace_back(1,1);
line.emplace_back(1,1);
line.emplace_back(2,2);
CHECK( !mapnik::geometry::is_simple(line) );
}
// This fails while is_valid will not fail!
SECTION("line_string repeated points")
{
mapnik::geometry::line_string<double> line;
line.emplace_back(0, 0);
line.emplace_back(1, 1);
line.emplace_back(1, 1);
line.emplace_back(2, 2);
CHECK(!mapnik::geometry::is_simple(line));
}
SECTION("line_string empty") {
mapnik::geometry::line_string<double> line;
CHECK( mapnik::geometry::is_simple(line) );
}
SECTION("line_string empty")
{
mapnik::geometry::line_string<double> line;
CHECK(mapnik::geometry::is_simple(line));
}
SECTION("multi_line_string") {
mapnik::geometry::line_string<double> line1;
line1.emplace_back(0,0);
line1.emplace_back(1,1);
mapnik::geometry::line_string<double> line2;
line2.emplace_back(0,1);
line2.emplace_back(1,2);
mapnik::geometry::multi_line_string<double> lines;
lines.emplace_back(line1);
lines.emplace_back(line2);
CHECK( mapnik::geometry::is_simple(lines) );
}
SECTION("multi_line_string")
{
mapnik::geometry::line_string<double> line1;
line1.emplace_back(0, 0);
line1.emplace_back(1, 1);
mapnik::geometry::line_string<double> line2;
line2.emplace_back(0, 1);
line2.emplace_back(1, 2);
mapnik::geometry::multi_line_string<double> lines;
lines.emplace_back(line1);
lines.emplace_back(line2);
CHECK(mapnik::geometry::is_simple(lines));
}
SECTION("multi_line_string empty") {
mapnik::geometry::multi_line_string<double> lines;
CHECK( mapnik::geometry::is_simple(lines) );
}
SECTION("multi_line_string empty")
{
mapnik::geometry::multi_line_string<double> lines;
CHECK(mapnik::geometry::is_simple(lines));
}
SECTION("multi_line_string empty") {
mapnik::geometry::multi_line_string<double> lines;
mapnik::geometry::line_string<double> line;
lines.emplace_back(line);
CHECK( mapnik::geometry::is_simple(lines) );
}
SECTION("multi_line_string empty")
{
mapnik::geometry::multi_line_string<double> lines;
mapnik::geometry::line_string<double> line;
lines.emplace_back(line);
CHECK(mapnik::geometry::is_simple(lines));
}
SECTION("polygon") {
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0,0);
ring.emplace_back(1,0);
ring.emplace_back(1,1);
ring.emplace_back(0,1);
ring.emplace_back(0,0);
poly.push_back(std::move(ring));
CHECK( mapnik::geometry::is_simple(poly) );
}
SECTION("polygon")
{
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0, 0);
ring.emplace_back(1, 0);
ring.emplace_back(1, 1);
ring.emplace_back(0, 1);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
CHECK(mapnik::geometry::is_simple(poly));
}
SECTION("polygon invalid winding order") {
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0,0);
ring.emplace_back(0,1);
ring.emplace_back(1,1);
ring.emplace_back(1,0);
ring.emplace_back(0,0);
poly.push_back(std::move(ring));
CHECK( mapnik::geometry::is_simple(poly) );
}
SECTION("polygon invalid winding order")
{
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0, 0);
ring.emplace_back(0, 1);
ring.emplace_back(1, 1);
ring.emplace_back(1, 0);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
CHECK(mapnik::geometry::is_simple(poly));
}
// repeated points are not considered invalid in a polygon
// but they are considered not simple
SECTION("polygon 2 repeated points") {
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0,0);
ring.emplace_back(1,0);
ring.emplace_back(1,1);
ring.emplace_back(1,1);
ring.emplace_back(0,1);
ring.emplace_back(0,0);
poly.push_back(std::move(ring));
CHECK( !mapnik::geometry::is_simple(poly) );
}
// repeated points are not considered invalid in a polygon
// but they are considered not simple
SECTION("polygon 3 repeated points") {
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0,0);
ring.emplace_back(1,0);
ring.emplace_back(1,1);
ring.emplace_back(1,1);
ring.emplace_back(1,1);
ring.emplace_back(0,1);
ring.emplace_back(0,0);
poly.push_back(std::move(ring));
CHECK( !mapnik::geometry::is_simple(poly) );
}
// repeated points are not considered invalid in a polygon
// but they are considered not simple
SECTION("polygon 2 repeated points")
{
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0, 0);
ring.emplace_back(1, 0);
ring.emplace_back(1, 1);
ring.emplace_back(1, 1);
ring.emplace_back(0, 1);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
CHECK(!mapnik::geometry::is_simple(poly));
}
// repeated points are not considered invalid in a polygon
// but they are considered not simple
SECTION("polygon 3 repeated points")
{
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0, 0);
ring.emplace_back(1, 0);
ring.emplace_back(1, 1);
ring.emplace_back(1, 1);
ring.emplace_back(1, 1);
ring.emplace_back(0, 1);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
CHECK(!mapnik::geometry::is_simple(poly));
}
#if BOOST_VERSION >= 106000
SECTION("polygon that is empty") {
mapnik::geometry::polygon<double> poly;
poly.emplace_back();
CHECK( !mapnik::geometry::is_simple(poly) );
}
SECTION("polygon that is empty")
{
mapnik::geometry::polygon<double> poly;
poly.emplace_back();
CHECK(!mapnik::geometry::is_simple(poly));
}
SECTION("polygon that has empty exterior ring") {
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
poly.push_back(std::move(ring));
CHECK( !mapnik::geometry::is_simple(poly) );
}
SECTION("polygon that has empty exterior ring")
{
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
poly.push_back(std::move(ring));
CHECK(!mapnik::geometry::is_simple(poly));
}
SECTION("polygon that has empty interior ring") {
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0,0);
ring.emplace_back(1,0);
ring.emplace_back(1,1);
ring.emplace_back(0,1);
ring.emplace_back(0,0);
poly.push_back(std::move(ring));
mapnik::geometry::linear_ring<double> ring2;
poly.push_back(std::move(ring2));
CHECK( !mapnik::geometry::is_simple(poly) );
}
SECTION("polygon that has empty interior ring")
{
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0, 0);
ring.emplace_back(1, 0);
ring.emplace_back(1, 1);
ring.emplace_back(0, 1);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
mapnik::geometry::linear_ring<double> ring2;
poly.push_back(std::move(ring2));
CHECK(!mapnik::geometry::is_simple(poly));
}
#else // BOOST_VERSION >= 1.60
SECTION("polygon that is empty") {
mapnik::geometry::polygon<double> poly;
CHECK( mapnik::geometry::is_simple(poly) );
}
SECTION("polygon that is empty")
{
mapnik::geometry::polygon<double> poly;
CHECK(mapnik::geometry::is_simple(poly));
}
SECTION("polygon that has empty exterior ring") {
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
poly.push_back(std::move(ring));
CHECK( mapnik::geometry::is_simple(poly) );
}
SECTION("polygon that has empty exterior ring")
{
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
poly.push_back(std::move(ring));
CHECK(mapnik::geometry::is_simple(poly));
}
SECTION("polygon that has empty interior ring") {
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0,0);
ring.emplace_back(1,0);
ring.emplace_back(1,1);
ring.emplace_back(0,1);
ring.emplace_back(0,0);
poly.push_back(std::move(ring));
mapnik::geometry::linear_ring<double> ring2;
poly.push_back(std::move(ring2));
CHECK( mapnik::geometry::is_simple(poly) );
}
SECTION("polygon that has empty interior ring")
{
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0, 0);
ring.emplace_back(1, 0);
ring.emplace_back(1, 1);
ring.emplace_back(0, 1);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
mapnik::geometry::linear_ring<double> ring2;
poly.push_back(std::move(ring2));
CHECK(mapnik::geometry::is_simple(poly));
}
#endif // BOOST_VERSION >= 1.60
// A polygon with a spike can still be simple
SECTION("polygon with spike") {
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0,0);
ring.emplace_back(1,0);
ring.emplace_back(1,1);
ring.emplace_back(2,2);
ring.emplace_back(1,1);
ring.emplace_back(0,1);
ring.emplace_back(0,0);
poly.push_back(std::move(ring));
CHECK( mapnik::geometry::is_simple(poly) );
}
// A polygon with a spike can still be simple
SECTION("polygon with spike")
{
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0, 0);
ring.emplace_back(1, 0);
ring.emplace_back(1, 1);
ring.emplace_back(2, 2);
ring.emplace_back(1, 1);
ring.emplace_back(0, 1);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
CHECK(mapnik::geometry::is_simple(poly));
}
SECTION("polygon with hole") {
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0,0);
ring.emplace_back(3,0);
ring.emplace_back(3,3);
ring.emplace_back(0,3);
ring.emplace_back(0,0);
poly.push_back(std::move(ring));
mapnik::geometry::linear_ring<double> hole;
hole.emplace_back(1,1);
hole.emplace_back(1,2);
hole.emplace_back(2,2);
hole.emplace_back(2,1);
hole.emplace_back(1,1);
poly.push_back(std::move(hole));
CHECK( mapnik::geometry::is_simple(poly) );
}
SECTION("polygon with hole")
{
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0, 0);
ring.emplace_back(3, 0);
ring.emplace_back(3, 3);
ring.emplace_back(0, 3);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
mapnik::geometry::linear_ring<double> hole;
hole.emplace_back(1, 1);
hole.emplace_back(1, 2);
hole.emplace_back(2, 2);
hole.emplace_back(2, 1);
hole.emplace_back(1, 1);
poly.push_back(std::move(hole));
CHECK(mapnik::geometry::is_simple(poly));
}
// Polygons with reversed winding order still can be considered simple
SECTION("polygon with hole with invalid winding order") {
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0,0);
ring.emplace_back(3,0);
ring.emplace_back(3,3);
ring.emplace_back(0,3);
ring.emplace_back(0,0);
poly.push_back(std::move(ring));
mapnik::geometry::linear_ring<double> hole;
hole.emplace_back(1,1);
hole.emplace_back(2,1);
hole.emplace_back(2,2);
hole.emplace_back(1,2);
hole.emplace_back(1,1);
poly.push_back(std::move(hole));
CHECK( mapnik::geometry::is_simple(poly) );
}
// Polygons with reversed winding order still can be considered simple
SECTION("polygon with hole with invalid winding order")
{
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0, 0);
ring.emplace_back(3, 0);
ring.emplace_back(3, 3);
ring.emplace_back(0, 3);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
mapnik::geometry::linear_ring<double> hole;
hole.emplace_back(1, 1);
hole.emplace_back(2, 1);
hole.emplace_back(2, 2);
hole.emplace_back(1, 2);
hole.emplace_back(1, 1);
poly.push_back(std::move(hole));
CHECK(mapnik::geometry::is_simple(poly));
}
SECTION("multi polygon") {
mapnik::geometry::multi_polygon<double> mp;
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
SECTION("multi polygon")
{
mapnik::geometry::multi_polygon<double> mp;
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0,0);
ring.emplace_back(1,0);
ring.emplace_back(1,1);
ring.emplace_back(0,1);
ring.emplace_back(0,0);
poly.push_back(std::move(ring));
mapnik::geometry::polygon<double> poly2;
mapnik::geometry::linear_ring<double> ring2;
ring2.emplace_back(0,0);
ring2.emplace_back(-1,0);
ring2.emplace_back(-1,-1);
ring2.emplace_back(0,-1);
ring2.emplace_back(0,0);
poly2.push_back(std::move(ring2));
mp.emplace_back(poly);
mp.emplace_back(poly2);
CHECK( mapnik::geometry::is_simple(mp) );
}
ring.emplace_back(0, 0);
ring.emplace_back(1, 0);
ring.emplace_back(1, 1);
ring.emplace_back(0, 1);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
mapnik::geometry::polygon<double> poly2;
mapnik::geometry::linear_ring<double> ring2;
ring2.emplace_back(0, 0);
ring2.emplace_back(-1, 0);
ring2.emplace_back(-1, -1);
ring2.emplace_back(0, -1);
ring2.emplace_back(0, 0);
poly2.push_back(std::move(ring2));
mp.emplace_back(poly);
mp.emplace_back(poly2);
CHECK(mapnik::geometry::is_simple(mp));
}
SECTION("multi polygon with hole") {
mapnik::geometry::multi_polygon<double> mp;
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0,0);
ring.emplace_back(3,0);
ring.emplace_back(3,3);
ring.emplace_back(0,3);
ring.emplace_back(0,0);
poly.push_back(std::move(ring));
mapnik::geometry::linear_ring<double> hole;
hole.emplace_back(1,1);
hole.emplace_back(1,2);
hole.emplace_back(2,2);
hole.emplace_back(2,1);
hole.emplace_back(1,1);
poly.push_back(std::move(hole));
mapnik::geometry::polygon<double> poly2;
mapnik::geometry::linear_ring<double> ring2;
ring2.emplace_back(0,0);
ring2.emplace_back(-3,0);
ring2.emplace_back(-3,-3);
ring2.emplace_back(0,-3);
ring2.emplace_back(0,0);
poly2.push_back(std::move(ring2));
mapnik::geometry::linear_ring<double> hole2;
hole2.emplace_back(-1,-1);
hole2.emplace_back(-1,-2);
hole2.emplace_back(-2,-2);
hole2.emplace_back(-2,-1);
hole2.emplace_back(-1,-1);
poly2.push_back(std::move(hole2));
mp.emplace_back(poly);
mp.emplace_back(poly2);
CHECK( mapnik::geometry::is_simple(mp) );
}
SECTION("multi polygon with hole")
{
mapnik::geometry::multi_polygon<double> mp;
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0, 0);
ring.emplace_back(3, 0);
ring.emplace_back(3, 3);
ring.emplace_back(0, 3);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
mapnik::geometry::linear_ring<double> hole;
hole.emplace_back(1, 1);
hole.emplace_back(1, 2);
hole.emplace_back(2, 2);
hole.emplace_back(2, 1);
hole.emplace_back(1, 1);
poly.push_back(std::move(hole));
mapnik::geometry::polygon<double> poly2;
mapnik::geometry::linear_ring<double> ring2;
ring2.emplace_back(0, 0);
ring2.emplace_back(-3, 0);
ring2.emplace_back(-3, -3);
ring2.emplace_back(0, -3);
ring2.emplace_back(0, 0);
poly2.push_back(std::move(ring2));
mapnik::geometry::linear_ring<double> hole2;
hole2.emplace_back(-1, -1);
hole2.emplace_back(-1, -2);
hole2.emplace_back(-2, -2);
hole2.emplace_back(-2, -1);
hole2.emplace_back(-1, -1);
poly2.push_back(std::move(hole2));
mp.emplace_back(poly);
mp.emplace_back(poly2);
CHECK(mapnik::geometry::is_simple(mp));
}
SECTION("multi polygon empty") {
mapnik::geometry::multi_polygon<double> mp;
CHECK( mapnik::geometry::is_simple(mp) );
}
SECTION("multi polygon empty")
{
mapnik::geometry::multi_polygon<double> mp;
CHECK(mapnik::geometry::is_simple(mp));
}
#else // BOOST_VERSION >= 1.58
SECTION("skipped is_simple tests") {
WARN( "geometry simple tests disabled due to boost version older that 1.58 used" );
}
SECTION("skipped is_simple tests")
{
WARN("geometry simple tests disabled due to boost version older that 1.58 used");
}
#endif
}

View file

@ -3,481 +3,508 @@
#include <mapnik/geometry.hpp>
#include <mapnik/geometry/is_valid.hpp>
TEST_CASE("geometry is_valid") {
TEST_CASE("geometry is_valid")
{
// only Boost >= 1.56 has the is_valid function, but only after 1.58 is there support for returning what is invalid
#if BOOST_VERSION >= 105800
SECTION("empty geometry")
{
mapnik::geometry::geometry_empty empty;
CHECK(mapnik::geometry::is_valid(empty));
std::string message;
CHECK(mapnik::geometry::is_valid(empty, message));
CHECK(message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK(mapnik::geometry::is_valid(empty, failure));
CHECK(failure == boost::geometry::no_failure);
}
SECTION("empty geometry") {
mapnik::geometry::geometry_empty empty;
CHECK( mapnik::geometry::is_valid(empty) );
std::string message;
CHECK( mapnik::geometry::is_valid(empty, message) );
CHECK( message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK( mapnik::geometry::is_valid(empty, failure) );
CHECK( failure == boost::geometry::no_failure );
}
SECTION("point")
{
mapnik::geometry::point<double> pt(0, 0);
CHECK(mapnik::geometry::is_valid(pt));
std::string message;
CHECK(mapnik::geometry::is_valid(pt, message));
CHECK(message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK(mapnik::geometry::is_valid(pt, failure));
CHECK(failure == boost::geometry::no_failure);
}
SECTION("point") {
mapnik::geometry::point<double> pt(0,0);
CHECK( mapnik::geometry::is_valid(pt) );
std::string message;
CHECK( mapnik::geometry::is_valid(pt, message) );
CHECK( message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK( mapnik::geometry::is_valid(pt, failure) );
CHECK( failure == boost::geometry::no_failure );
}
SECTION("point -- geometry object") {
mapnik::geometry::point<double> pt(0,0);
mapnik::geometry::geometry<double> geom(pt);
CHECK( mapnik::geometry::is_valid(geom) );
std::string message;
CHECK( mapnik::geometry::is_valid(geom, message) );
CHECK( message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK( mapnik::geometry::is_valid(geom, failure) );
CHECK( failure == boost::geometry::no_failure );
}
SECTION("point -- geometry object")
{
mapnik::geometry::point<double> pt(0, 0);
mapnik::geometry::geometry<double> geom(pt);
CHECK(mapnik::geometry::is_valid(geom));
std::string message;
CHECK(mapnik::geometry::is_valid(geom, message));
CHECK(message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK(mapnik::geometry::is_valid(geom, failure));
CHECK(failure == boost::geometry::no_failure);
}
#if BOOST_VERSION < 106000
SECTION("point unitialized") {
mapnik::geometry::point<double> pt2;
CHECK( mapnik::geometry::is_valid(pt2) );
std::string message2;
CHECK( mapnik::geometry::is_valid(pt2, message2) );
CHECK( message2 == "Geometry is valid");
boost::geometry::validity_failure_type failure2;
CHECK( mapnik::geometry::is_valid(pt2, failure2) );
CHECK( failure2 == boost::geometry::no_failure );
}
SECTION("point unitialized")
{
mapnik::geometry::point<double> pt2;
CHECK(mapnik::geometry::is_valid(pt2));
std::string message2;
CHECK(mapnik::geometry::is_valid(pt2, message2));
CHECK(message2 == "Geometry is valid");
boost::geometry::validity_failure_type failure2;
CHECK(mapnik::geometry::is_valid(pt2, failure2));
CHECK(failure2 == boost::geometry::no_failure);
}
#endif
#if BOOST_VERSION >= 106000
SECTION("point NaN") {
mapnik::geometry::point<double> pt(std::numeric_limits<double>::quiet_NaN(),std::numeric_limits<double>::quiet_NaN());
CHECK( std::isnan(pt.x) );
CHECK( std::isnan(pt.y) );
CHECK( !mapnik::geometry::is_valid(pt) );
std::string message;
CHECK( !mapnik::geometry::is_valid(pt, message) );
CHECK( message == "Geometry has point(s) with invalid coordinate(s)");
boost::geometry::validity_failure_type failure;
CHECK( !mapnik::geometry::is_valid(pt, failure) );
CHECK( failure == boost::geometry::failure_invalid_coordinate );
}
SECTION("point NaN")
{
mapnik::geometry::point<double> pt(std::numeric_limits<double>::quiet_NaN(),
std::numeric_limits<double>::quiet_NaN());
CHECK(std::isnan(pt.x));
CHECK(std::isnan(pt.y));
CHECK(!mapnik::geometry::is_valid(pt));
std::string message;
CHECK(!mapnik::geometry::is_valid(pt, message));
CHECK(message == "Geometry has point(s) with invalid coordinate(s)");
boost::geometry::validity_failure_type failure;
CHECK(!mapnik::geometry::is_valid(pt, failure));
CHECK(failure == boost::geometry::failure_invalid_coordinate);
}
SECTION("point Infinity") {
mapnik::geometry::point<double> pt(std::numeric_limits<double>::infinity(),std::numeric_limits<double>::infinity());
CHECK( std::isinf(pt.x) );
CHECK( std::isinf(pt.y) );
CHECK( !mapnik::geometry::is_valid(pt) );
std::string message;
CHECK( !mapnik::geometry::is_valid(pt, message) );
CHECK( message == "Geometry has point(s) with invalid coordinate(s)");
boost::geometry::validity_failure_type failure;
CHECK( !mapnik::geometry::is_valid(pt, failure) );
CHECK( failure == boost::geometry::failure_invalid_coordinate );
}
SECTION("point Infinity")
{
mapnik::geometry::point<double> pt(std::numeric_limits<double>::infinity(),
std::numeric_limits<double>::infinity());
CHECK(std::isinf(pt.x));
CHECK(std::isinf(pt.y));
CHECK(!mapnik::geometry::is_valid(pt));
std::string message;
CHECK(!mapnik::geometry::is_valid(pt, message));
CHECK(message == "Geometry has point(s) with invalid coordinate(s)");
boost::geometry::validity_failure_type failure;
CHECK(!mapnik::geometry::is_valid(pt, failure));
CHECK(failure == boost::geometry::failure_invalid_coordinate);
}
#else // BOOST_VERSION >= 1.60
// This is funky that boost geometry is_valid does not check for NAN when dealing with a point
// this test is here in case the logic ever changes
// Bug report on this: https://svn.boost.org/trac/boost/ticket/11711
SECTION("point NaN") {
mapnik::geometry::point<double> pt(std::numeric_limits<double>::quiet_NaN(),std::numeric_limits<double>::quiet_NaN());
CHECK( std::isnan(pt.x) );
CHECK( std::isnan(pt.y) );
CHECK( mapnik::geometry::is_valid(pt) );
std::string message;
CHECK( mapnik::geometry::is_valid(pt, message) );
CHECK( message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK( mapnik::geometry::is_valid(pt, failure) );
CHECK( failure == boost::geometry::no_failure );
}
// This is funky that boost geometry is_valid does not check for NAN when dealing with a point
// this test is here in case the logic ever changes
// Bug report on this: https://svn.boost.org/trac/boost/ticket/11711
SECTION("point NaN")
{
mapnik::geometry::point<double> pt(std::numeric_limits<double>::quiet_NaN(),
std::numeric_limits<double>::quiet_NaN());
CHECK(std::isnan(pt.x));
CHECK(std::isnan(pt.y));
CHECK(mapnik::geometry::is_valid(pt));
std::string message;
CHECK(mapnik::geometry::is_valid(pt, message));
CHECK(message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK(mapnik::geometry::is_valid(pt, failure));
CHECK(failure == boost::geometry::no_failure);
}
// This is funky that boost geometry is_valid does not check for infinity when dealing with a point
// this test is here in case the logic ever changes
// Bug report on this: https://svn.boost.org/trac/boost/ticket/11711
SECTION("point Infinity") {
mapnik::geometry::point<double> pt(std::numeric_limits<double>::infinity(),std::numeric_limits<double>::infinity());
CHECK( std::isinf(pt.x) );
CHECK( std::isinf(pt.y) );
CHECK( mapnik::geometry::is_valid(pt) );
std::string message;
CHECK( mapnik::geometry::is_valid(pt, message) );
CHECK( message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK( mapnik::geometry::is_valid(pt, failure) );
CHECK( failure == boost::geometry::no_failure );
}
// This is funky that boost geometry is_valid does not check for infinity when dealing with a point
// this test is here in case the logic ever changes
// Bug report on this: https://svn.boost.org/trac/boost/ticket/11711
SECTION("point Infinity")
{
mapnik::geometry::point<double> pt(std::numeric_limits<double>::infinity(),
std::numeric_limits<double>::infinity());
CHECK(std::isinf(pt.x));
CHECK(std::isinf(pt.y));
CHECK(mapnik::geometry::is_valid(pt));
std::string message;
CHECK(mapnik::geometry::is_valid(pt, message));
CHECK(message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK(mapnik::geometry::is_valid(pt, failure));
CHECK(failure == boost::geometry::no_failure);
}
#endif // BOOST_VERSION >= 1.60
SECTION("multi point") {
mapnik::geometry::multi_point<double> mpt;
mpt.emplace_back(0,0);
mpt.emplace_back(1,1);
CHECK( mapnik::geometry::is_valid(mpt) );
std::string message;
CHECK( mapnik::geometry::is_valid(mpt, message) );
CHECK( message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK( mapnik::geometry::is_valid(mpt, failure) );
CHECK( failure == boost::geometry::no_failure );
}
SECTION("multi point")
{
mapnik::geometry::multi_point<double> mpt;
mpt.emplace_back(0, 0);
mpt.emplace_back(1, 1);
CHECK(mapnik::geometry::is_valid(mpt));
std::string message;
CHECK(mapnik::geometry::is_valid(mpt, message));
CHECK(message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK(mapnik::geometry::is_valid(mpt, failure));
CHECK(failure == boost::geometry::no_failure);
}
SECTION("multi point empty") {
mapnik::geometry::multi_point<double> mpt;
CHECK( mapnik::geometry::is_valid(mpt) );
std::string message;
CHECK( mapnik::geometry::is_valid(mpt, message) );
CHECK( message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK( mapnik::geometry::is_valid(mpt, failure) );
CHECK( failure == boost::geometry::no_failure );
}
SECTION("multi point empty")
{
mapnik::geometry::multi_point<double> mpt;
CHECK(mapnik::geometry::is_valid(mpt));
std::string message;
CHECK(mapnik::geometry::is_valid(mpt, message));
CHECK(message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK(mapnik::geometry::is_valid(mpt, failure));
CHECK(failure == boost::geometry::no_failure);
}
SECTION("line_string")
{
mapnik::geometry::line_string<double> line;
line.emplace_back(0, 0);
line.emplace_back(1, 1);
CHECK(mapnik::geometry::is_valid(line));
std::string message;
CHECK(mapnik::geometry::is_valid(line, message));
CHECK(message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK(mapnik::geometry::is_valid(line, failure));
CHECK(failure == boost::geometry::no_failure);
}
SECTION("line_string") {
mapnik::geometry::line_string<double> line;
line.emplace_back(0,0);
line.emplace_back(1,1);
CHECK( mapnik::geometry::is_valid(line) );
std::string message;
CHECK( mapnik::geometry::is_valid(line, message) );
CHECK( message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK( mapnik::geometry::is_valid(line, failure) );
CHECK( failure == boost::geometry::no_failure );
}
// This shouldn't fail -- test added in case logic ever changes
SECTION("line_string repeated points")
{
mapnik::geometry::line_string<double> line;
line.emplace_back(0, 0);
line.emplace_back(1, 1);
line.emplace_back(1, 1);
line.emplace_back(2, 2);
CHECK(mapnik::geometry::is_valid(line));
std::string message;
CHECK(mapnik::geometry::is_valid(line, message));
CHECK(message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK(mapnik::geometry::is_valid(line, failure));
CHECK(failure == boost::geometry::no_failure);
}
// This shouldn't fail -- test added in case logic ever changes
SECTION("line_string repeated points") {
mapnik::geometry::line_string<double> line;
line.emplace_back(0,0);
line.emplace_back(1,1);
line.emplace_back(1,1);
line.emplace_back(2,2);
CHECK( mapnik::geometry::is_valid(line) );
std::string message;
CHECK( mapnik::geometry::is_valid(line, message) );
CHECK( message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK( mapnik::geometry::is_valid(line, failure) );
CHECK( failure == boost::geometry::no_failure );
}
SECTION("line_string empty")
{
mapnik::geometry::line_string<double> line;
CHECK(!mapnik::geometry::is_valid(line));
std::string message;
CHECK(!mapnik::geometry::is_valid(line, message));
CHECK(message == "Geometry has too few points");
boost::geometry::validity_failure_type failure;
CHECK(!mapnik::geometry::is_valid(line, failure));
CHECK(failure == boost::geometry::failure_few_points);
}
SECTION("line_string empty") {
mapnik::geometry::line_string<double> line;
CHECK( !mapnik::geometry::is_valid(line) );
std::string message;
CHECK( !mapnik::geometry::is_valid(line, message) );
CHECK( message == "Geometry has too few points");
boost::geometry::validity_failure_type failure;
CHECK( !mapnik::geometry::is_valid(line, failure) );
CHECK( failure == boost::geometry::failure_few_points );
}
SECTION("multi_line_string")
{
mapnik::geometry::line_string<double> line1;
line1.emplace_back(0, 0);
line1.emplace_back(1, 1);
mapnik::geometry::line_string<double> line2;
line2.emplace_back(0, 1);
line2.emplace_back(1, 2);
mapnik::geometry::multi_line_string<double> lines;
lines.emplace_back(line1);
lines.emplace_back(line2);
CHECK(mapnik::geometry::is_valid(lines));
std::string message;
CHECK(mapnik::geometry::is_valid(lines, message));
CHECK(message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK(mapnik::geometry::is_valid(lines, failure));
CHECK(failure == boost::geometry::no_failure);
}
SECTION("multi_line_string") {
mapnik::geometry::line_string<double> line1;
line1.emplace_back(0,0);
line1.emplace_back(1,1);
mapnik::geometry::line_string<double> line2;
line2.emplace_back(0,1);
line2.emplace_back(1,2);
mapnik::geometry::multi_line_string<double> lines;
lines.emplace_back(line1);
lines.emplace_back(line2);
CHECK( mapnik::geometry::is_valid(lines) );
std::string message;
CHECK( mapnik::geometry::is_valid(lines, message) );
CHECK( message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK( mapnik::geometry::is_valid(lines, failure) );
CHECK( failure == boost::geometry::no_failure );
}
SECTION("multi_line_string empty")
{
mapnik::geometry::multi_line_string<double> lines;
CHECK(mapnik::geometry::is_valid(lines));
std::string message;
CHECK(mapnik::geometry::is_valid(lines, message));
CHECK(message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK(mapnik::geometry::is_valid(lines, failure));
CHECK(failure == boost::geometry::no_failure);
}
SECTION("multi_line_string empty") {
mapnik::geometry::multi_line_string<double> lines;
CHECK( mapnik::geometry::is_valid(lines) );
std::string message;
CHECK( mapnik::geometry::is_valid(lines, message) );
CHECK( message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK( mapnik::geometry::is_valid(lines, failure) );
CHECK( failure == boost::geometry::no_failure );
}
SECTION("polygon")
{
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0, 0);
ring.emplace_back(1, 0);
ring.emplace_back(1, 1);
ring.emplace_back(0, 1);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
CHECK(mapnik::geometry::is_valid(poly));
std::string message;
CHECK(mapnik::geometry::is_valid(poly, message));
CHECK(message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK(mapnik::geometry::is_valid(poly, failure));
CHECK(failure == boost::geometry::no_failure);
}
SECTION("polygon") {
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0,0);
ring.emplace_back(1,0);
ring.emplace_back(1,1);
ring.emplace_back(0,1);
ring.emplace_back(0,0);
poly.push_back(std::move(ring));
CHECK( mapnik::geometry::is_valid(poly) );
std::string message;
CHECK( mapnik::geometry::is_valid(poly, message) );
CHECK( message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK( mapnik::geometry::is_valid(poly, failure) );
CHECK( failure == boost::geometry::no_failure );
}
SECTION("polygon invalid winding order")
{
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0, 0);
ring.emplace_back(0, 1);
ring.emplace_back(1, 1);
ring.emplace_back(1, 0);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
CHECK(!mapnik::geometry::is_valid(poly));
std::string message;
CHECK(!mapnik::geometry::is_valid(poly, message));
CHECK(message == "Geometry has wrong orientation");
boost::geometry::validity_failure_type failure;
CHECK(!mapnik::geometry::is_valid(poly, failure));
CHECK(failure == boost::geometry::failure_wrong_orientation);
}
SECTION("polygon invalid winding order") {
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0,0);
ring.emplace_back(0,1);
ring.emplace_back(1,1);
ring.emplace_back(1,0);
ring.emplace_back(0,0);
poly.push_back(std::move(ring));
CHECK( !mapnik::geometry::is_valid(poly) );
std::string message;
CHECK( !mapnik::geometry::is_valid(poly, message) );
CHECK( message == "Geometry has wrong orientation" );
boost::geometry::validity_failure_type failure;
CHECK( !mapnik::geometry::is_valid(poly, failure) );
CHECK( failure == boost::geometry::failure_wrong_orientation );
}
// repeated points are not considered invalid in a polygon
SECTION("polygon 2 repeated points")
{
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0, 0);
ring.emplace_back(1, 0);
ring.emplace_back(1, 1);
ring.emplace_back(1, 1);
ring.emplace_back(0, 1);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
CHECK(mapnik::geometry::is_valid(poly));
std::string message;
CHECK(mapnik::geometry::is_valid(poly, message));
CHECK(message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK(mapnik::geometry::is_valid(poly, failure));
CHECK(failure == boost::geometry::no_failure);
}
// repeated points are not considered invalid in a polygon
SECTION("polygon 3 repeated points")
{
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0, 0);
ring.emplace_back(1, 0);
ring.emplace_back(1, 1);
ring.emplace_back(1, 1);
ring.emplace_back(1, 1);
ring.emplace_back(0, 1);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
CHECK(mapnik::geometry::is_valid(poly));
std::string message;
CHECK(mapnik::geometry::is_valid(poly, message));
CHECK(message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK(mapnik::geometry::is_valid(poly, failure));
CHECK(failure == boost::geometry::no_failure);
}
// repeated points are not considered invalid in a polygon
SECTION("polygon 2 repeated points") {
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0,0);
ring.emplace_back(1,0);
ring.emplace_back(1,1);
ring.emplace_back(1,1);
ring.emplace_back(0,1);
ring.emplace_back(0,0);
poly.push_back(std::move(ring));
CHECK( mapnik::geometry::is_valid(poly) );
std::string message;
CHECK( mapnik::geometry::is_valid(poly, message) );
CHECK( message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK( mapnik::geometry::is_valid(poly, failure) );
CHECK( failure == boost::geometry::no_failure );
}
// repeated points are not considered invalid in a polygon
SECTION("polygon 3 repeated points") {
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0,0);
ring.emplace_back(1,0);
ring.emplace_back(1,1);
ring.emplace_back(1,1);
ring.emplace_back(1,1);
ring.emplace_back(0,1);
ring.emplace_back(0,0);
poly.push_back(std::move(ring));
CHECK( mapnik::geometry::is_valid(poly) );
std::string message;
CHECK( mapnik::geometry::is_valid(poly, message) );
CHECK( message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK( mapnik::geometry::is_valid(poly, failure) );
CHECK( failure == boost::geometry::no_failure );
}
SECTION("polygon that is empty")
{
mapnik::geometry::polygon<double> poly;
poly.emplace_back();
CHECK(!mapnik::geometry::is_valid(poly));
std::string message;
CHECK(!mapnik::geometry::is_valid(poly, message));
CHECK(message == "Geometry has too few points");
boost::geometry::validity_failure_type failure;
CHECK(!mapnik::geometry::is_valid(poly, failure));
CHECK(failure == boost::geometry::failure_few_points);
}
SECTION("polygon that is empty") {
mapnik::geometry::polygon<double> poly;
poly.emplace_back();
CHECK( !mapnik::geometry::is_valid(poly) );
std::string message;
CHECK( !mapnik::geometry::is_valid(poly, message) );
CHECK( message == "Geometry has too few points");
boost::geometry::validity_failure_type failure;
CHECK( !mapnik::geometry::is_valid(poly, failure) );
CHECK( failure == boost::geometry::failure_few_points );
}
SECTION("polygon with spike")
{
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0, 0);
ring.emplace_back(1, 0);
ring.emplace_back(1, 1);
ring.emplace_back(2, 2);
ring.emplace_back(1, 1);
ring.emplace_back(0, 1);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
CHECK(!mapnik::geometry::is_valid(poly));
std::string message;
CHECK(!mapnik::geometry::is_valid(poly, message));
CHECK(message == "Geometry has spikes. A spike point was found with apex at (2, 2)");
boost::geometry::validity_failure_type failure;
CHECK(!mapnik::geometry::is_valid(poly, failure));
CHECK(failure == boost::geometry::failure_spikes);
}
SECTION("polygon with spike") {
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0,0);
ring.emplace_back(1,0);
ring.emplace_back(1,1);
ring.emplace_back(2,2);
ring.emplace_back(1,1);
ring.emplace_back(0,1);
ring.emplace_back(0,0);
poly.push_back(std::move(ring));
CHECK( !mapnik::geometry::is_valid(poly) );
std::string message;
CHECK( !mapnik::geometry::is_valid(poly, message) );
CHECK( message == "Geometry has spikes. A spike point was found with apex at (2, 2)");
boost::geometry::validity_failure_type failure;
CHECK( !mapnik::geometry::is_valid(poly, failure) );
CHECK( failure == boost::geometry::failure_spikes );
}
SECTION("polygon with hole")
{
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0, 0);
ring.emplace_back(3, 0);
ring.emplace_back(3, 3);
ring.emplace_back(0, 3);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
mapnik::geometry::linear_ring<double> hole;
hole.emplace_back(1, 1);
hole.emplace_back(1, 2);
hole.emplace_back(2, 2);
hole.emplace_back(2, 1);
hole.emplace_back(1, 1);
poly.push_back(std::move(hole));
CHECK(mapnik::geometry::is_valid(poly));
std::string message;
CHECK(mapnik::geometry::is_valid(poly, message));
CHECK(message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK(mapnik::geometry::is_valid(poly, failure));
CHECK(failure == boost::geometry::no_failure);
}
SECTION("polygon with hole") {
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0,0);
ring.emplace_back(3,0);
ring.emplace_back(3,3);
ring.emplace_back(0,3);
ring.emplace_back(0,0);
poly.push_back(std::move(ring));
mapnik::geometry::linear_ring<double> hole;
hole.emplace_back(1,1);
hole.emplace_back(1,2);
hole.emplace_back(2,2);
hole.emplace_back(2,1);
hole.emplace_back(1,1);
poly.push_back(std::move(hole));
CHECK( mapnik::geometry::is_valid(poly) );
std::string message;
CHECK( mapnik::geometry::is_valid(poly, message) );
CHECK( message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK( mapnik::geometry::is_valid(poly, failure) );
CHECK( failure == boost::geometry::no_failure );
}
SECTION("polygon with empty hole")
{
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0, 0);
ring.emplace_back(3, 0);
ring.emplace_back(3, 3);
ring.emplace_back(0, 3);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
mapnik::geometry::linear_ring<double> hole;
poly.push_back(std::move(hole));
CHECK(!mapnik::geometry::is_valid(poly));
std::string message;
CHECK(!mapnik::geometry::is_valid(poly, message));
CHECK(message == "Geometry has too few points");
boost::geometry::validity_failure_type failure;
CHECK(!mapnik::geometry::is_valid(poly, failure));
CHECK(failure == boost::geometry::failure_few_points);
}
SECTION("polygon with empty hole") {
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0,0);
ring.emplace_back(3,0);
ring.emplace_back(3,3);
ring.emplace_back(0,3);
ring.emplace_back(0,0);
poly.push_back(std::move(ring));
mapnik::geometry::linear_ring<double> hole;
poly.push_back(std::move(hole));
CHECK( !mapnik::geometry::is_valid(poly) );
std::string message;
CHECK( !mapnik::geometry::is_valid(poly, message) );
CHECK( message == "Geometry has too few points");
boost::geometry::validity_failure_type failure;
CHECK( !mapnik::geometry::is_valid(poly, failure) );
CHECK( failure == boost::geometry::failure_few_points );
}
SECTION("polygon with hole with invalid winding order")
{
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0, 0);
ring.emplace_back(3, 0);
ring.emplace_back(3, 3);
ring.emplace_back(0, 3);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
mapnik::geometry::linear_ring<double> hole;
hole.emplace_back(1, 1);
hole.emplace_back(2, 1);
hole.emplace_back(2, 2);
hole.emplace_back(1, 2);
hole.emplace_back(1, 1);
poly.push_back(std::move(hole));
CHECK(!mapnik::geometry::is_valid(poly));
std::string message;
CHECK(!mapnik::geometry::is_valid(poly, message));
CHECK(message == "Geometry has wrong orientation");
boost::geometry::validity_failure_type failure;
CHECK(!mapnik::geometry::is_valid(poly, failure));
CHECK(failure == boost::geometry::failure_wrong_orientation);
}
SECTION("multi polygon")
{
mapnik::geometry::multi_polygon<double> mp;
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0, 0);
ring.emplace_back(1, 0);
ring.emplace_back(1, 1);
ring.emplace_back(0, 1);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
mapnik::geometry::polygon<double> poly2;
mapnik::geometry::linear_ring<double> ring2;
ring2.emplace_back(0, 0);
ring2.emplace_back(-1, 0);
ring2.emplace_back(-1, -1);
ring2.emplace_back(0, -1);
ring2.emplace_back(0, 0);
poly2.push_back(std::move(ring2));
mp.emplace_back(poly);
mp.emplace_back(poly2);
CHECK(mapnik::geometry::is_valid(mp));
std::string message;
CHECK(mapnik::geometry::is_valid(mp, message));
CHECK(message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK(mapnik::geometry::is_valid(mp, failure));
CHECK(failure == boost::geometry::no_failure);
}
SECTION("polygon with hole with invalid winding order") {
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0,0);
ring.emplace_back(3,0);
ring.emplace_back(3,3);
ring.emplace_back(0,3);
ring.emplace_back(0,0);
poly.push_back(std::move(ring));
mapnik::geometry::linear_ring<double> hole;
hole.emplace_back(1,1);
hole.emplace_back(2,1);
hole.emplace_back(2,2);
hole.emplace_back(1,2);
hole.emplace_back(1,1);
poly.push_back(std::move(hole));
CHECK( !mapnik::geometry::is_valid(poly) );
std::string message;
CHECK( !mapnik::geometry::is_valid(poly, message) );
CHECK( message == "Geometry has wrong orientation" );
boost::geometry::validity_failure_type failure;
CHECK( !mapnik::geometry::is_valid(poly, failure) );
CHECK( failure == boost::geometry::failure_wrong_orientation );
}
SECTION("multi polygon with hole")
{
mapnik::geometry::multi_polygon<double> mp;
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0, 0);
ring.emplace_back(3, 0);
ring.emplace_back(3, 3);
ring.emplace_back(0, 3);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
mapnik::geometry::linear_ring<double> hole;
hole.emplace_back(1, 1);
hole.emplace_back(1, 2);
hole.emplace_back(2, 2);
hole.emplace_back(2, 1);
hole.emplace_back(1, 1);
poly.push_back(std::move(hole));
mapnik::geometry::polygon<double> poly2;
mapnik::geometry::linear_ring<double> ring2;
ring2.emplace_back(0, 0);
ring2.emplace_back(-3, 0);
ring2.emplace_back(-3, -3);
ring2.emplace_back(0, -3);
ring2.emplace_back(0, 0);
poly2.push_back(std::move(ring2));
mapnik::geometry::linear_ring<double> hole2;
hole2.emplace_back(-1, -1);
hole2.emplace_back(-1, -2);
hole2.emplace_back(-2, -2);
hole2.emplace_back(-2, -1);
hole2.emplace_back(-1, -1);
poly2.push_back(std::move(hole2));
mp.emplace_back(poly);
mp.emplace_back(poly2);
CHECK(mapnik::geometry::is_valid(mp));
std::string message;
CHECK(mapnik::geometry::is_valid(mp, message));
CHECK(message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK(mapnik::geometry::is_valid(mp, failure));
CHECK(failure == boost::geometry::no_failure);
}
SECTION("multi polygon") {
mapnik::geometry::multi_polygon<double> mp;
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0,0);
ring.emplace_back(1,0);
ring.emplace_back(1,1);
ring.emplace_back(0,1);
ring.emplace_back(0,0);
poly.push_back(std::move(ring));
mapnik::geometry::polygon<double> poly2;
mapnik::geometry::linear_ring<double> ring2;
ring2.emplace_back(0,0);
ring2.emplace_back(-1,0);
ring2.emplace_back(-1,-1);
ring2.emplace_back(0,-1);
ring2.emplace_back(0,0);
poly2.push_back(std::move(ring2));
mp.emplace_back(poly);
mp.emplace_back(poly2);
CHECK( mapnik::geometry::is_valid(mp) );
std::string message;
CHECK( mapnik::geometry::is_valid(mp, message) );
CHECK( message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK( mapnik::geometry::is_valid(mp, failure) );
CHECK( failure == boost::geometry::no_failure );
}
SECTION("multi polygon with hole") {
mapnik::geometry::multi_polygon<double> mp;
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0,0);
ring.emplace_back(3,0);
ring.emplace_back(3,3);
ring.emplace_back(0,3);
ring.emplace_back(0,0);
poly.push_back(std::move(ring));
mapnik::geometry::linear_ring<double> hole;
hole.emplace_back(1,1);
hole.emplace_back(1,2);
hole.emplace_back(2,2);
hole.emplace_back(2,1);
hole.emplace_back(1,1);
poly.push_back(std::move(hole));
mapnik::geometry::polygon<double> poly2;
mapnik::geometry::linear_ring<double> ring2;
ring2.emplace_back(0,0);
ring2.emplace_back(-3,0);
ring2.emplace_back(-3,-3);
ring2.emplace_back(0,-3);
ring2.emplace_back(0,0);
poly2.push_back(std::move(ring2));
mapnik::geometry::linear_ring<double> hole2;
hole2.emplace_back(-1,-1);
hole2.emplace_back(-1,-2);
hole2.emplace_back(-2,-2);
hole2.emplace_back(-2,-1);
hole2.emplace_back(-1,-1);
poly2.push_back(std::move(hole2));
mp.emplace_back(poly);
mp.emplace_back(poly2);
CHECK( mapnik::geometry::is_valid(mp) );
std::string message;
CHECK( mapnik::geometry::is_valid(mp, message) );
CHECK( message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK( mapnik::geometry::is_valid(mp, failure) );
CHECK( failure == boost::geometry::no_failure );
}
SECTION("multi polygon empty") {
mapnik::geometry::multi_polygon<double> mp;
CHECK( mapnik::geometry::is_valid(mp) );
std::string message;
CHECK( mapnik::geometry::is_valid(mp, message) );
CHECK( message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK( mapnik::geometry::is_valid(mp, failure) );
CHECK( failure == boost::geometry::no_failure );
}
SECTION("multi polygon empty")
{
mapnik::geometry::multi_polygon<double> mp;
CHECK(mapnik::geometry::is_valid(mp));
std::string message;
CHECK(mapnik::geometry::is_valid(mp, message));
CHECK(message == "Geometry is valid");
boost::geometry::validity_failure_type failure;
CHECK(mapnik::geometry::is_valid(mp, failure));
CHECK(failure == boost::geometry::no_failure);
}
#endif // BOOST_VERSION >= 1.58
}

File diff suppressed because it is too large Load diff

View file

@ -10,177 +10,183 @@
#include <mapnik/proj_strategy.hpp>
#include <mapnik/view_strategy.hpp>
TEST_CASE("geometry strategy tests")
{
SECTION("proj and view strategy")
{
using namespace mapnik::geometry;
mapnik::box2d<double> e(-20037508.342789, -20037508.342789, 20037508.342789, 20037508.342789);
mapnik::view_transform vt(256, 256, e);
mapnik::view_strategy vs(vt);
mapnik::unview_strategy uvs(vt);
mapnik::projection source("epsg:4326");
mapnik::projection dest("epsg:3857");
mapnik::proj_transform proj_trans(source, dest);
mapnik::proj_transform proj_trans_rev(dest, source);
mapnik::proj_strategy ps(proj_trans);
mapnik::proj_strategy ps_rev(proj_trans_rev);
{
// Test first that proj strategy works properly
point<double> p1(-97.553098, 35.523105);
point<double> r1(-1.08596e+07, 4.2352e+06);
point<double> p3 = transform<double>(p1, ps);
assert_g_equal(r1, p3);
}
{
// Test next that view_strategy works
point<double> p1(-1.08596e+07, 4.2352e+06);
point<double> r1(58.6287, 100.945);
point<double> p3 = transform<double>(p1, vs);
assert_g_equal(r1, p3);
}
{
// Test next that view_strategy works as single process in strategy group
point<double> p1(-1.08596e+07, 4.2352e+06);
point<double> r1(58.6287, 100.945);
using sg_type = strategy_group<mapnik::view_strategy>;
sg_type sg(vs);
point<double> p3 = transform<double>(p1, sg);
assert_g_equal(r1, p3);
}
{
// Test that both work grouped together in strategy group
using sg_type = strategy_group<mapnik::proj_strategy, mapnik::view_strategy>;
sg_type sg(ps, vs);
point<double> p1(-97.553098, 35.523105);
point<double> r1(58.6287, 100.945);
point<double> p3 = transform<double>(p1, sg);
assert_g_equal(r1, p3);
}
{
// Test that both work grouped together passing in geometry
using sg_type = strategy_group<mapnik::proj_strategy, mapnik::view_strategy>;
sg_type sg(ps, vs);
geometry<double> p1(point<double>(-97.553098, 35.523105));
point<double> r1(58.6287, 100.945);
geometry<double> p2 = transform<double>(p1, sg);
REQUIRE(p2.is<point<double>>());
point<double> p3 = mapnik::util::get<point<double>>(p2);
assert_g_equal(r1, p3);
}
{
// Test that it works pulling back int
using sg_type = strategy_group<mapnik::proj_strategy, mapnik::view_strategy>;
sg_type sg(ps, vs);
geometry<double> p1(point<double>(-97.553098, 35.523105));
point<std::int64_t> r1(58, 100);
geometry<std::int64_t> p2 = transform<std::int64_t>(p1, sg);
REQUIRE(p2.is<point<std::int64_t>>());
point<std::int64_t> p3 = mapnik::util::get<point<std::int64_t>>(p2);
assert_g_equal(r1, p3);
}
{
// Test with scaling as well. This would be like projection from 4326 to a vector tile.
mapnik::geometry::scale_rounding_strategy ss(16);
using sg_type =
strategy_group<mapnik::proj_strategy, mapnik::view_strategy, mapnik::geometry::scale_rounding_strategy>;
sg_type sg(ps, vs, ss);
geometry<double> p1(point<double>(-97.553098, 35.523105));
point<std::int64_t> r1(938, 1615);
geometry<std::int64_t> p2 = transform<std::int64_t>(p1, sg);
REQUIRE(p2.is<point<std::int64_t>>());
point<std::int64_t> p3 = mapnik::util::get<point<std::int64_t>>(p2);
assert_g_equal(r1, p3);
}
{
// Test the entire process in reverse! This would be like converting a vector tile coordinate to 4326.
mapnik::geometry::scale_strategy ss(1.0 / 16.0);
using sg_type =
strategy_group_first<mapnik::geometry::scale_strategy, mapnik::unview_strategy, mapnik::proj_strategy>;
sg_type sg(ss, uvs, ps_rev);
geometry<std::int64_t> p1(point<std::int64_t>(938, 1615));
point<double> r1(-97.5586, 35.5322);
geometry<double> p2 = transform<double>(p1, sg);
REQUIRE(p2.is<point<double>>());
point<double> p3 = mapnik::util::get<point<double>>(p2);
assert_g_equal(r1, p3);
}
{
// Test with scaling + offset as well. This would be like projection from 4326 to a vector tile.
mapnik::geometry::scale_rounding_strategy ss(16, 20);
using sg_type =
strategy_group<mapnik::proj_strategy, mapnik::view_strategy, mapnik::geometry::scale_rounding_strategy>;
sg_type sg(ps, vs, ss);
geometry<double> p1(point<double>(-97.553098, 35.523105));
point<std::int64_t> r1(958, 1635);
geometry<std::int64_t> p2 = transform<std::int64_t>(p1, sg);
REQUIRE(p2.is<point<std::int64_t>>());
point<std::int64_t> p3 = mapnik::util::get<point<std::int64_t>>(p2);
assert_g_equal(r1, p3);
}
{
// Test the entire scaling plus offset in reverse process in reverse! This would be like converting a vector
// tile coordinate to 4326.
mapnik::geometry::scale_strategy ss(1.0 / 16.0, -20.0 / 16.0);
using sg_type =
strategy_group_first<mapnik::geometry::scale_strategy, mapnik::unview_strategy, mapnik::proj_strategy>;
sg_type sg(ss, uvs, ps_rev);
geometry<std::int64_t> p1(point<std::int64_t>(958, 1635));
point<double> r1(-97.5586, 35.5322);
geometry<double> p2 = transform<double>(p1, sg);
REQUIRE(p2.is<point<double>>());
point<double> p3 = mapnik::util::get<point<double>>(p2);
assert_g_equal(r1, p3);
}
TEST_CASE("geometry strategy tests") {
SECTION("proj and view strategy") {
using namespace mapnik::geometry;
mapnik::box2d<double> e(-20037508.342789,-20037508.342789,20037508.342789,20037508.342789);
mapnik::view_transform vt(256, 256, e);
mapnik::view_strategy vs(vt);
mapnik::unview_strategy uvs(vt);
mapnik::projection source("epsg:4326");
mapnik::projection dest("epsg:3857");
mapnik::proj_transform proj_trans(source, dest);
mapnik::proj_transform proj_trans_rev(dest, source);
mapnik::proj_strategy ps(proj_trans);
mapnik::proj_strategy ps_rev(proj_trans_rev);
{
// Test first that proj strategy works properly
point<double> p1(-97.553098,35.523105);
point<double> r1(-1.08596e+07, 4.2352e+06);
point<double> p3 = transform<double>(p1, ps);
assert_g_equal(r1, p3);
}
{
// Test next that view_strategy works
point<double> p1(-1.08596e+07, 4.2352e+06);
point<double> r1(58.6287 , 100.945);
point<double> p3 = transform<double>(p1, vs);
assert_g_equal(r1, p3);
} // END SECTION
}
SECTION("scaling strategies - double to double")
{
// Test next that view_strategy works as single process in strategy group
point<double> p1(-1.08596e+07, 4.2352e+06);
point<double> r1(58.6287 , 100.945);
using sg_type = strategy_group<mapnik::view_strategy>;
sg_type sg(vs);
point<double> p3 = transform<double>(p1, sg);
assert_g_equal(r1, p3);
using namespace mapnik::geometry;
}
{
// Test that both work grouped together in strategy group
using sg_type = strategy_group<mapnik::proj_strategy, mapnik::view_strategy >;
sg_type sg(ps, vs);
point<double> p1(-97.553098,35.523105);
point<double> r1(58.6287 , 100.945);
point<double> p3 = transform<double>(p1, sg);
assert_g_equal(r1, p3);
}
{
// Test that both work grouped together passing in geometry
using sg_type = strategy_group<mapnik::proj_strategy, mapnik::view_strategy >;
sg_type sg(ps, vs);
geometry<double> p1(point<double>(-97.553098,35.523105));
point<double> r1(58.6287 , 100.945);
geometry<double> p2 = transform<double>(p1, sg);
REQUIRE(p2.is<point<double> >());
point<double> p3 = mapnik::util::get<point<double> >(p2);
assert_g_equal(r1, p3);
}
{
// Test that it works pulling back int
using sg_type = strategy_group<mapnik::proj_strategy, mapnik::view_strategy >;
sg_type sg(ps, vs);
geometry<double> p1(point<double>(-97.553098,35.523105));
point<std::int64_t> r1(58 , 100);
geometry<std::int64_t> p2 = transform<std::int64_t>(p1, sg);
REQUIRE(p2.is<point<std::int64_t> >());
point<std::int64_t> p3 = mapnik::util::get<point<std::int64_t> >(p2);
assert_g_equal(r1, p3);
}
{
// Test with scaling as well. This would be like projection from 4326 to a vector tile.
mapnik::geometry::scale_rounding_strategy ss(16);
using sg_type = strategy_group<mapnik::proj_strategy, mapnik::view_strategy, mapnik::geometry::scale_rounding_strategy >;
sg_type sg(ps, vs, ss);
geometry<double> p1(point<double>(-97.553098,35.523105));
point<std::int64_t> r1(938 , 1615);
geometry<std::int64_t> p2 = transform<std::int64_t>(p1, sg);
REQUIRE(p2.is<point<std::int64_t> >());
point<std::int64_t> p3 = mapnik::util::get<point<std::int64_t> >(p2);
assert_g_equal(r1, p3);
}
{
// Test the entire process in reverse! This would be like converting a vector tile coordinate to 4326.
mapnik::geometry::scale_strategy ss(1.0/16.0);
using sg_type = strategy_group_first<mapnik::geometry::scale_strategy, mapnik::unview_strategy, mapnik::proj_strategy >;
sg_type sg(ss, uvs, ps_rev);
geometry<std::int64_t> p1(point<std::int64_t>(938 , 1615));
point<double> r1(-97.5586 , 35.5322);
geometry<double> p2 = transform<double>(p1, sg);
REQUIRE(p2.is<point<double> >());
point<double> p3 = mapnik::util::get<point<double> >(p2);
assert_g_equal(r1, p3);
}
{
// Test with scaling + offset as well. This would be like projection from 4326 to a vector tile.
mapnik::geometry::scale_rounding_strategy ss(16, 20);
using sg_type = strategy_group<mapnik::proj_strategy, mapnik::view_strategy, mapnik::geometry::scale_rounding_strategy >;
sg_type sg(ps, vs, ss);
geometry<double> p1(point<double>(-97.553098,35.523105));
point<std::int64_t> r1(958 , 1635);
geometry<std::int64_t> p2 = transform<std::int64_t>(p1, sg);
REQUIRE(p2.is<point<std::int64_t> >());
point<std::int64_t> p3 = mapnik::util::get<point<std::int64_t> >(p2);
assert_g_equal(r1, p3);
}
{
// Test the entire scaling plus offset in reverse process in reverse! This would be like converting a vector tile coordinate to 4326.
mapnik::geometry::scale_strategy ss(1.0/16.0, -20.0/16.0);
using sg_type = strategy_group_first<mapnik::geometry::scale_strategy, mapnik::unview_strategy, mapnik::proj_strategy >;
sg_type sg(ss, uvs, ps_rev);
geometry<std::int64_t> p1(point<std::int64_t>(958 , 1635));
point<double> r1(-97.5586 , 35.5322);
geometry<double> p2 = transform<double>(p1, sg);
REQUIRE(p2.is<point<double> >());
point<double> p3 = mapnik::util::get<point<double> >(p2);
assert_g_equal(r1, p3);
}
{
scale_strategy ss(10.0);
point<double> p(-90.3, 35.5);
point<double> r(-903.0, 355.0);
point<double> o = transform<double>(p, ss);
assert_g_equal(r, o);
}
{
scale_strategy ss(0.5, -2.0);
point<double> p(-90.3, 35.5);
point<double> r(-47.15, 15.75);
point<double> o = transform<double>(p, ss);
assert_g_equal(r, o);
}
{
scale_rounding_strategy ss(0.5, -2.0);
point<double> p(-90.3, 35.5);
point<double> r(-47.0, 16.0);
point<double> o = transform<double>(p, ss);
assert_g_equal(r, o);
}
} // END SECTION
} // END SECTION
SECTION("scaling strategies - double to double") {
using namespace mapnik::geometry;
SECTION("scaling strategies - double to int64")
{
using namespace mapnik::geometry;
{
scale_strategy ss(10.0);
point<double> p(-90.3, 35.5);
point<double> r(-903.0, 355.0);
point<double> o = transform<double>(p, ss);
assert_g_equal(r, o);
}
{
scale_strategy ss(0.5, -2.0);
point<double> p(-90.3, 35.5);
point<double> r(-47.15, 15.75);
point<double> o = transform<double>(p, ss);
assert_g_equal(r, o);
}
{
scale_rounding_strategy ss(0.5, -2.0);
point<double> p(-90.3, 35.5);
point<double> r(-47.0, 16.0);
point<double> o = transform<double>(p, ss);
assert_g_equal(r, o);
}
} // END SECTION
SECTION("scaling strategies - double to int64") {
using namespace mapnik::geometry;
{
scale_strategy ss(10.0);
point<double> p(-90.31, 35.58);
point<std::int64_t> r(-903, 355);
point<std::int64_t> o = transform<std::int64_t>(p, ss);
assert_g_equal(r, o);
}
{
scale_strategy ss(0.5, -2.0);
point<double> p(-90.3, 35.5);
point<std::int64_t> r(-47, 15);
point<std::int64_t> o = transform<std::int64_t>(p, ss);
assert_g_equal(r, o);
}
{
scale_rounding_strategy ss(0.5, -2.0);
point<double> p(-90.3, 35.5);
point<std::int64_t> r(-47, 16);
point<std::int64_t> o = transform<std::int64_t>(p, ss);
assert_g_equal(r, o);
}
} // END SECTION
{
scale_strategy ss(10.0);
point<double> p(-90.31, 35.58);
point<std::int64_t> r(-903, 355);
point<std::int64_t> o = transform<std::int64_t>(p, ss);
assert_g_equal(r, o);
}
{
scale_strategy ss(0.5, -2.0);
point<double> p(-90.3, 35.5);
point<std::int64_t> r(-47, 15);
point<std::int64_t> o = transform<std::int64_t>(p, ss);
assert_g_equal(r, o);
}
{
scale_rounding_strategy ss(0.5, -2.0);
point<double> p(-90.3, 35.5);
point<std::int64_t> r(-47, 16);
point<std::int64_t> o = transform<std::int64_t>(p, ss);
assert_g_equal(r, o);
}
} // END SECTION
} // END TEST CASE

View file

@ -2,8 +2,8 @@
#include <mapnik/geometry/envelope.hpp>
#include <mapnik/geometry/envelope_impl.hpp>
namespace mapnik { namespace geometry {
namespace mapnik {
namespace geometry {
// instantiate types required by geometry_envelope_test
template mapnik::box2d<int> envelope(geometry<int> const& geom);
template mapnik::box2d<float> envelope(geometry<float> const& geom);
@ -12,4 +12,5 @@ template mapnik::box2d<float> envelope(polygon<float> const& geom);
template mapnik::box2d<int> envelope(geometry_collection<int> const& geom);
template mapnik::box2d<float> envelope(geometry_collection<float> const& geom);
}}
} // namespace geometry
} // namespace mapnik

View file

@ -2,120 +2,105 @@
#include <mapnik/grid_vertex_converter.hpp>
TEST_CASE("spiral_iterator") {
SECTION("sprial 3x3") {
mapnik::geometry::spiral_iterator si(3);
const mapnik::geometry::point<int> points[] = {
{ 0, 0 }, { 1, 0 }, { 1, -1 },
{ 0, -1 }, { -1, -1 }, { -1, 0 },
{ -1, 1 }, { 0, 1 }, { 1, 1 } };
const std::size_t points_size = std::extent<decltype(points)>::value;
int x, y;
std::size_t index = 0;
while (si.vertex(&x, &y))
TEST_CASE("spiral_iterator")
{
SECTION("sprial 3x3")
{
REQUIRE(index < points_size);
mapnik::geometry::spiral_iterator si(3);
const mapnik::geometry::point<int> points[] =
{{0, 0}, {1, 0}, {1, -1}, {0, -1}, {-1, -1}, {-1, 0}, {-1, 1}, {0, 1}, {1, 1}};
CHECK(x == points[index].x);
CHECK(y == points[index].y);
const std::size_t points_size = std::extent<decltype(points)>::value;
index++;
int x, y;
std::size_t index = 0;
while (si.vertex(&x, &y))
{
REQUIRE(index < points_size);
CHECK(x == points[index].x);
CHECK(y == points[index].y);
index++;
}
CHECK(index == points_size);
}
}
TEST_CASE("grid_vertex_converter")
{
SECTION("empty polygon")
{
mapnik::geometry::polygon<double> poly;
using path_type = mapnik::geometry::polygon_vertex_adapter<double>;
path_type path(poly);
using converter_type = mapnik::geometry::grid_vertex_converter<path_type, double>;
converter_type gvc(path, 10.0, 10.0, 1.0);
double x, y;
unsigned cmd = gvc.vertex(&x, &y);
CHECK(cmd == mapnik::SEG_END);
}
CHECK(index == points_size);
}
}
TEST_CASE("grid_vertex_converter") {
SECTION("empty polygon") {
mapnik::geometry::polygon<double> poly;
using path_type = mapnik::geometry::polygon_vertex_adapter<double>;
path_type path(poly);
using converter_type = mapnik::geometry::grid_vertex_converter<path_type, double>;
converter_type gvc(path, 10.0, 10.0, 1.0);
double x, y;
unsigned cmd = gvc.vertex(&x, &y);
CHECK(cmd == mapnik::SEG_END);
}
SECTION("empty polygon exterior ring") {
mapnik::geometry::polygon<double> poly;
poly.emplace_back();
using path_type = mapnik::geometry::polygon_vertex_adapter<double>;
path_type path(poly);
using converter_type = mapnik::geometry::grid_vertex_converter<path_type, double>;
converter_type gvc(path, 10.0, 10.0, 1.0);
double x, y;
unsigned cmd = gvc.vertex(&x, &y);
CHECK(cmd == mapnik::SEG_END);
}
SECTION("grid of a square") {
mapnik::geometry::polygon<double> poly;
poly.emplace_back();
auto & exterior_ring = poly.front();
exterior_ring.emplace_back(-10, -10);
exterior_ring.emplace_back( 10, -10);
exterior_ring.emplace_back( 10, 10);
exterior_ring.emplace_back(-10, 10);
exterior_ring.emplace_back(-10, -10);
using path_type = mapnik::geometry::polygon_vertex_adapter<double>;
path_type path(poly);
using converter_type = mapnik::geometry::grid_vertex_converter<path_type, double>;
converter_type gvc(path, 3.0, 3.0, 1.0);
const mapnik::geometry::point<double> points[] = {
{ 0, 0 }, { 3, 0 }, { 3, 3 }, { 0, 3 },
{ -3, 3 }, { -3, 0 }, { -3, -3 }, { 0, -3 },
{ 3, -3 }, { 6, -3 }, { 6, 0 }, { 6, 3 },
{ 6, 6 }, { 3, 6 }, { 0, 6 }, { -3, 6 },
{ -6, 6 }, { -6, 3 }, { -6, 0 }, { -6, -3 },
{ -6, -6 }, { -3, -6 }, { 0, -6 }, { 3, -6 },
{ 6, -6 }, { 9, -6 }, { 9, -3 }, { 9, 0 },
{ 9, 3 }, { 9, 6 }, { 9, 9 }, { 6, 9 },
{ 3, 9 }, { 0, 9 }, { -3, 9 }, { -6, 9 },
{ -9, 9 }, { -9, 6 }, { -9, 3 }, { -9, 0 },
{ -9, -3 }, { -9, -6 }, { -9, -9 }, { -6, -9 },
{ -3, -9 }, { 0, -9 }, { 3, -9 }, { 6, -9 },
{ 9, -9 } };
const std::size_t points_size = std::extent<decltype(points)>::value;
double x, y;
unsigned cmd = mapnik::SEG_END;
std::size_t index = 0;
while ((cmd = gvc.vertex(&x, &y)) != mapnik::SEG_END)
SECTION("empty polygon exterior ring")
{
REQUIRE(index < points_size);
mapnik::geometry::polygon<double> poly;
poly.emplace_back();
CHECK(cmd == mapnik::SEG_MOVETO);
CHECK(x == Approx(points[index].x));
CHECK(y == Approx(points[index].y));
using path_type = mapnik::geometry::polygon_vertex_adapter<double>;
path_type path(poly);
using converter_type = mapnik::geometry::grid_vertex_converter<path_type, double>;
converter_type gvc(path, 10.0, 10.0, 1.0);
index++;
double x, y;
unsigned cmd = gvc.vertex(&x, &y);
CHECK(cmd == mapnik::SEG_END);
}
CHECK(index == points_size);
CHECK(cmd == mapnik::SEG_END);
}
SECTION("grid of a square")
{
mapnik::geometry::polygon<double> poly;
poly.emplace_back();
auto& exterior_ring = poly.front();
exterior_ring.emplace_back(-10, -10);
exterior_ring.emplace_back(10, -10);
exterior_ring.emplace_back(10, 10);
exterior_ring.emplace_back(-10, 10);
exterior_ring.emplace_back(-10, -10);
}
using path_type = mapnik::geometry::polygon_vertex_adapter<double>;
path_type path(poly);
using converter_type = mapnik::geometry::grid_vertex_converter<path_type, double>;
converter_type gvc(path, 3.0, 3.0, 1.0);
const mapnik::geometry::point<double> points[] = {
{0, 0}, {3, 0}, {3, 3}, {0, 3}, {-3, 3}, {-3, 0}, {-3, -3}, {0, -3}, {3, -3}, {6, -3},
{6, 0}, {6, 3}, {6, 6}, {3, 6}, {0, 6}, {-3, 6}, {-6, 6}, {-6, 3}, {-6, 0}, {-6, -3},
{-6, -6}, {-3, -6}, {0, -6}, {3, -6}, {6, -6}, {9, -6}, {9, -3}, {9, 0}, {9, 3}, {9, 6},
{9, 9}, {6, 9}, {3, 9}, {0, 9}, {-3, 9}, {-6, 9}, {-9, 9}, {-9, 6}, {-9, 3}, {-9, 0},
{-9, -3}, {-9, -6}, {-9, -9}, {-6, -9}, {-3, -9}, {0, -9}, {3, -9}, {6, -9}, {9, -9}};
const std::size_t points_size = std::extent<decltype(points)>::value;
double x, y;
unsigned cmd = mapnik::SEG_END;
std::size_t index = 0;
while ((cmd = gvc.vertex(&x, &y)) != mapnik::SEG_END)
{
REQUIRE(index < points_size);
CHECK(cmd == mapnik::SEG_MOVETO);
CHECK(x == Approx(points[index].x));
CHECK(y == Approx(points[index].y));
index++;
}
CHECK(index == points_size);
CHECK(cmd == mapnik::SEG_END);
}
}

View file

@ -2,42 +2,41 @@
#include <mapnik/geometry/interior.hpp>
TEST_CASE("polygon interior") {
TEST_CASE("polygon interior")
{
SECTION("empty polygon")
{
mapnik::geometry::polygon<double> poly;
mapnik::geometry::point<double> pt;
SECTION("empty polygon") {
CHECK(!mapnik::geometry::interior(poly, 1.0, pt));
}
mapnik::geometry::polygon<double> poly;
mapnik::geometry::point<double> pt;
CHECK(!mapnik::geometry::interior(poly, 1.0, pt));
}
SECTION("empty exterior ring") {
mapnik::geometry::polygon<double> poly;
poly.emplace_back();
mapnik::geometry::point<double> pt;
CHECK(!mapnik::geometry::interior(poly, 1.0, pt));
}
SECTION("interior of a square") {
mapnik::geometry::polygon<double> poly;
poly.emplace_back();
auto & exterior_ring = poly.front();
exterior_ring.emplace_back(-1, -1);
exterior_ring.emplace_back( 1, -1);
exterior_ring.emplace_back( 1, 1);
exterior_ring.emplace_back(-1, 1);
exterior_ring.emplace_back(-1, -1);
mapnik::geometry::point<double> pt{ -3, -3 };
CHECK(mapnik::geometry::interior(poly, 1.0, pt));
CHECK(pt.x == Approx(0));
CHECK(pt.y == Approx(0));
}
SECTION("empty exterior ring")
{
mapnik::geometry::polygon<double> poly;
poly.emplace_back();
mapnik::geometry::point<double> pt;
CHECK(!mapnik::geometry::interior(poly, 1.0, pt));
}
SECTION("interior of a square")
{
mapnik::geometry::polygon<double> poly;
poly.emplace_back();
auto& exterior_ring = poly.front();
exterior_ring.emplace_back(-1, -1);
exterior_ring.emplace_back(1, -1);
exterior_ring.emplace_back(1, 1);
exterior_ring.emplace_back(-1, 1);
exterior_ring.emplace_back(-1, -1);
mapnik::geometry::point<double> pt{-3, -3};
CHECK(mapnik::geometry::interior(poly, 1.0, pt));
CHECK(pt.x == Approx(0));
CHECK(pt.y == Approx(0));
}
}

View file

@ -3,8 +3,8 @@
#include <mapnik/geometry.hpp>
#include <mapnik/util/is_clockwise.hpp>
TEST_CASE("Ring is_clockwise") {
TEST_CASE("Ring is_clockwise")
{
// Input is rather thin triangle to test precision issues aren't getting in the way.
SECTION("Clockwise")
{

View file

@ -2,116 +2,116 @@
#include <mapnik/geometry/is_empty.hpp>
TEST_CASE("geometry is_empty") {
SECTION("empty geometry") {
mapnik::geometry::geometry_empty geom;
REQUIRE(mapnik::geometry::is_empty(geom));
}
SECTION("geometry collection") {
TEST_CASE("geometry is_empty")
{
SECTION("empty geometry")
{
mapnik::geometry::geometry_collection<double> geom;
mapnik::geometry::geometry_empty geom;
REQUIRE(mapnik::geometry::is_empty(geom));
}
SECTION("geometry collection")
{
mapnik::geometry::geometry_collection<double> geom;
mapnik::geometry::geometry_empty geom1;
geom.emplace_back(std::move(geom1));
REQUIRE(!mapnik::geometry::is_empty(geom));
{
mapnik::geometry::geometry_collection<double> geom;
REQUIRE(mapnik::geometry::is_empty(geom));
}
{
mapnik::geometry::geometry_collection<double> geom;
mapnik::geometry::geometry_empty geom1;
geom.emplace_back(std::move(geom1));
REQUIRE(!mapnik::geometry::is_empty(geom));
}
}
SECTION("point")
{
mapnik::geometry::point<double> pt(10, 10);
REQUIRE(!mapnik::geometry::is_empty(pt));
}
SECTION("linestring")
{
{
mapnik::geometry::line_string<double> line;
REQUIRE(mapnik::geometry::is_empty(line));
}
{
mapnik::geometry::line_string<double> line;
line.emplace_back(0, 0);
line.emplace_back(25, 25);
line.emplace_back(50, 50);
REQUIRE(!mapnik::geometry::is_empty(line));
}
}
SECTION("polygon")
{
{
mapnik::geometry::polygon<double> poly;
REQUIRE(mapnik::geometry::is_empty(poly));
}
{
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
poly.push_back(std::move(ring));
REQUIRE(mapnik::geometry::is_empty(poly));
}
{
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0, 0);
ring.emplace_back(1, 0);
ring.emplace_back(1, 1);
ring.emplace_back(0, 1);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
REQUIRE(!mapnik::geometry::is_empty(poly));
}
}
SECTION("multi-point")
{
{
mapnik::geometry::multi_point<double> geom;
REQUIRE(mapnik::geometry::is_empty(geom));
}
{
mapnik::geometry::multi_point<double> geom;
geom.emplace_back(0, 0);
geom.emplace_back(25, 25);
geom.emplace_back(50, 50);
REQUIRE(!mapnik::geometry::is_empty(geom));
}
}
SECTION("multi-linestring")
{
{
mapnik::geometry::multi_line_string<double> geom;
REQUIRE(mapnik::geometry::is_empty(geom));
}
{
mapnik::geometry::multi_line_string<double> geom;
mapnik::geometry::line_string<double> line;
geom.emplace_back(std::move(line));
REQUIRE(!mapnik::geometry::is_empty(geom));
}
}
SECTION("multi-polygon")
{
{
mapnik::geometry::multi_polygon<double> geom;
REQUIRE(mapnik::geometry::is_empty(geom));
}
{
mapnik::geometry::multi_polygon<double> geom;
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
poly.push_back(std::move(ring));
geom.emplace_back(std::move(poly));
REQUIRE(!mapnik::geometry::is_empty(geom));
}
}
}
SECTION("point") {
mapnik::geometry::point<double> pt(10, 10);
REQUIRE(!mapnik::geometry::is_empty(pt));
}
SECTION("linestring") {
{
mapnik::geometry::line_string<double> line;
REQUIRE(mapnik::geometry::is_empty(line));
}
{
mapnik::geometry::line_string<double> line;
line.emplace_back(0, 0);
line.emplace_back(25, 25);
line.emplace_back(50, 50);
REQUIRE(!mapnik::geometry::is_empty(line));
}
}
SECTION("polygon") {
{
mapnik::geometry::polygon<double> poly;
REQUIRE(mapnik::geometry::is_empty(poly));
}
{
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
poly.push_back(std::move(ring));
REQUIRE(mapnik::geometry::is_empty(poly));
}
{
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0, 0);
ring.emplace_back(1, 0);
ring.emplace_back(1, 1);
ring.emplace_back(0, 1);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
REQUIRE(!mapnik::geometry::is_empty(poly));
}
}
SECTION("multi-point") {
{
mapnik::geometry::multi_point<double> geom;
REQUIRE(mapnik::geometry::is_empty(geom));
}
{
mapnik::geometry::multi_point<double> geom;
geom.emplace_back(0, 0);
geom.emplace_back(25, 25);
geom.emplace_back(50, 50);
REQUIRE(!mapnik::geometry::is_empty(geom));
}
}
SECTION("multi-linestring") {
{
mapnik::geometry::multi_line_string<double> geom;
REQUIRE(mapnik::geometry::is_empty(geom));
}
{
mapnik::geometry::multi_line_string<double> geom;
mapnik::geometry::line_string<double> line;
geom.emplace_back(std::move(line));
REQUIRE(!mapnik::geometry::is_empty(geom));
}
}
SECTION("multi-polygon") {
{
mapnik::geometry::multi_polygon<double> geom;
REQUIRE(mapnik::geometry::is_empty(geom));
}
{
mapnik::geometry::multi_polygon<double> geom;
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
poly.push_back(std::move(ring));
geom.emplace_back(std::move(poly));
REQUIRE(!mapnik::geometry::is_empty(geom));
}
}
}

View file

@ -3,60 +3,59 @@
#include <mapnik/geometry/polygon_vertex_processor.hpp>
TEST_CASE("polygon_vertex_processor") {
TEST_CASE("polygon_vertex_processor")
{
SECTION("empty polygon")
{
fake_path path = {};
mapnik::geometry::polygon_vertex_processor<double> proc;
proc.add_path(path);
CHECK(proc.polygon_.size() == 0);
}
SECTION("empty polygon") {
fake_path path = {};
mapnik::geometry::polygon_vertex_processor<double> proc;
proc.add_path(path);
CHECK(proc.polygon_.size() == 0);
}
SECTION("empty outer ring") {
fake_path path = {};
path.vertices_.emplace_back(0, 0, mapnik::SEG_CLOSE);
path.rewind(0);
mapnik::geometry::polygon_vertex_processor<double> proc;
proc.add_path(path);
REQUIRE(proc.polygon_.size() == 1);
REQUIRE(proc.polygon_.front().size() == 0);
}
SECTION("empty inner ring") {
fake_path path = {};
path.vertices_.emplace_back(-1, -1, 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( 0, 0, mapnik::SEG_CLOSE);
path.vertices_.emplace_back( 0, 0, mapnik::SEG_CLOSE);
path.rewind(0);
mapnik::geometry::polygon_vertex_processor<double> proc;
proc.add_path(path);
REQUIRE(proc.polygon_.size() == 2);
auto const& outer_ring = proc.polygon_.front();
REQUIRE(outer_ring.size() == 5);
CHECK(outer_ring[0].x == Approx(-1));
CHECK(outer_ring[0].y == Approx(-1));
CHECK(outer_ring[1].x == Approx( 1));
CHECK(outer_ring[1].y == Approx(-1));
CHECK(outer_ring[2].x == Approx( 1));
CHECK(outer_ring[2].y == Approx( 1));
CHECK(outer_ring[3].x == Approx(-1));
CHECK(outer_ring[3].y == Approx( 1));
CHECK(outer_ring[4].x == Approx(-1));
CHECK(outer_ring[4].y == Approx(-1));
}
SECTION("empty outer ring")
{
fake_path path = {};
path.vertices_.emplace_back(0, 0, mapnik::SEG_CLOSE);
path.rewind(0);
mapnik::geometry::polygon_vertex_processor<double> proc;
proc.add_path(path);
REQUIRE(proc.polygon_.size() == 1);
REQUIRE(proc.polygon_.front().size() == 0);
}
SECTION("empty inner ring")
{
fake_path path = {};
path.vertices_.emplace_back(-1, -1, 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(0, 0, mapnik::SEG_CLOSE);
path.vertices_.emplace_back(0, 0, mapnik::SEG_CLOSE);
path.rewind(0);
mapnik::geometry::polygon_vertex_processor<double> proc;
proc.add_path(path);
REQUIRE(proc.polygon_.size() == 2);
auto const& outer_ring = proc.polygon_.front();
REQUIRE(outer_ring.size() == 5);
CHECK(outer_ring[0].x == Approx(-1));
CHECK(outer_ring[0].y == Approx(-1));
CHECK(outer_ring[1].x == Approx(1));
CHECK(outer_ring[1].y == Approx(-1));
CHECK(outer_ring[2].x == Approx(1));
CHECK(outer_ring[2].y == Approx(1));
CHECK(outer_ring[3].x == Approx(-1));
CHECK(outer_ring[3].y == Approx(1));
CHECK(outer_ring[4].x == Approx(-1));
CHECK(outer_ring[4].y == Approx(-1));
}
}

View file

@ -2,42 +2,41 @@
#include <mapnik/geometry/polylabel.hpp>
TEST_CASE("polylabel") {
TEST_CASE("polylabel")
{
SECTION("empty polygon")
{
mapnik::geometry::polygon<double> poly;
mapnik::geometry::point<double> pt;
SECTION("empty polygon") {
CHECK(!mapnik::geometry::polylabel(poly, 1.0, pt));
}
mapnik::geometry::polygon<double> poly;
mapnik::geometry::point<double> pt;
CHECK(!mapnik::geometry::polylabel(poly, 1.0, pt));
}
SECTION("empty exterior ring") {
mapnik::geometry::polygon<double> poly;
poly.emplace_back();
mapnik::geometry::point<double> pt;
CHECK(!mapnik::geometry::polylabel(poly, 1.0, pt));
}
SECTION("polylabel with a square") {
mapnik::geometry::polygon<double> poly;
poly.emplace_back();
auto & exterior_ring = poly.front();
exterior_ring.emplace_back(-1, -1);
exterior_ring.emplace_back( 1, -1);
exterior_ring.emplace_back( 1, 1);
exterior_ring.emplace_back(-1, 1);
exterior_ring.emplace_back(-1, -1);
mapnik::geometry::point<double> pt{ -3, -3 };
CHECK(mapnik::geometry::polylabel(poly, 1.0, pt));
CHECK(pt.x == Approx(0));
CHECK(pt.y == Approx(0));
}
SECTION("empty exterior ring")
{
mapnik::geometry::polygon<double> poly;
poly.emplace_back();
mapnik::geometry::point<double> pt;
CHECK(!mapnik::geometry::polylabel(poly, 1.0, pt));
}
SECTION("polylabel with a square")
{
mapnik::geometry::polygon<double> poly;
poly.emplace_back();
auto& exterior_ring = poly.front();
exterior_ring.emplace_back(-1, -1);
exterior_ring.emplace_back(1, -1);
exterior_ring.emplace_back(1, 1);
exterior_ring.emplace_back(-1, 1);
exterior_ring.emplace_back(-1, -1);
mapnik::geometry::point<double> pt{-3, -3};
CHECK(mapnik::geometry::polylabel(poly, 1.0, pt));
CHECK(pt.x == Approx(0));
CHECK(pt.y == Approx(0));
}
}

View file

@ -2,52 +2,52 @@
#include <mapnik/geometry/remove_empty.hpp>
TEST_CASE("geometry remove_empty") {
TEST_CASE("geometry remove_empty")
{
SECTION("point")
{
using geom_type = mapnik::geometry::point<double>;
geom_type pt(10, 10);
geom_type pt2 = mapnik::geometry::remove_empty(pt);
REQUIRE(pt.x == pt2.x);
REQUIRE(pt.y == pt2.y);
}
SECTION("point") {
SECTION("multi-linestring")
{
using geom_type = mapnik::geometry::multi_line_string<double>;
geom_type geom;
mapnik::geometry::line_string<double> line;
line.emplace_back(0, 0);
line.emplace_back(0, 25);
line.emplace_back(0, 50);
geom.emplace_back(std::move(line));
geom.emplace_back();
using geom_type = mapnik::geometry::point<double>;
geom_type pt(10, 10);
geom_type pt2 = mapnik::geometry::remove_empty(pt);
REQUIRE(pt.x == pt2.x);
REQUIRE(pt.y == pt2.y);
}
SECTION("multi-linestring") {
using geom_type = mapnik::geometry::multi_line_string<double>;
geom_type geom;
mapnik::geometry::line_string<double> line;
line.emplace_back(0, 0);
line.emplace_back(0, 25);
line.emplace_back(0, 50);
geom.emplace_back(std::move(line));
geom.emplace_back();
REQUIRE(geom.size() == 2);
geom_type geom2 = mapnik::geometry::remove_empty(geom);
REQUIRE(geom2.size() == 1);
REQUIRE(geom2[0].size() == 3);
}
SECTION("multi-polygon") {
using geom_type = mapnik::geometry::multi_polygon<double>;
geom_type geom;
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0, 0);
ring.emplace_back(1, 0);
ring.emplace_back(1, 1);
ring.emplace_back(0, 1);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
geom.emplace_back(std::move(poly));
geom.emplace_back();
//geom.back().emplace_back(); //add an empty exterior ring
REQUIRE(geom.size() == 2);
geom_type geom2 = mapnik::geometry::remove_empty(geom);
REQUIRE(geom2.size() == 1);
REQUIRE(geom2.front().front().size() == 5);
}
REQUIRE(geom.size() == 2);
geom_type geom2 = mapnik::geometry::remove_empty(geom);
REQUIRE(geom2.size() == 1);
REQUIRE(geom2[0].size() == 3);
}
SECTION("multi-polygon")
{
using geom_type = mapnik::geometry::multi_polygon<double>;
geom_type geom;
mapnik::geometry::polygon<double> poly;
mapnik::geometry::linear_ring<double> ring;
ring.emplace_back(0, 0);
ring.emplace_back(1, 0);
ring.emplace_back(1, 1);
ring.emplace_back(0, 1);
ring.emplace_back(0, 0);
poly.push_back(std::move(ring));
geom.emplace_back(std::move(poly));
geom.emplace_back();
// geom.back().emplace_back(); //add an empty exterior ring
REQUIRE(geom.size() == 2);
geom_type geom2 = mapnik::geometry::remove_empty(geom);
REQUIRE(geom2.size() == 1);
REQUIRE(geom2.front().front().size() == 5);
}
}

View file

@ -8,385 +8,380 @@
#include <mapnik/color.hpp>
#include <mapnik/image_util.hpp>
TEST_CASE("image class") {
SECTION("test gray16") {
const mapnik::image_gray16 im(4,4);
mapnik::image_gray16 im2(im);
mapnik::image_gray16 im3(5,5);
CHECK(im == im);
CHECK_FALSE(im == im2);
CHECK_FALSE(im2 == im3);
CHECK(im < im3);
CHECK_FALSE(im < im2);
// Check that width is correct
CHECK(im.width() == 4);
CHECK(im2.width() == 4);
// Check that height is correct
CHECK(im.height() == 4);
CHECK(im2.height() == 4);
CHECK(im(0,0) == 0);
CHECK(im2(0,0) == 0);
im2(0,0) = 1;
CHECK(im2(0,0) == 1);
im2.set(514);
CHECK(im2(0,0) == 514);
CHECK(im2(1,1) == 514);
// Check that size is correct
CHECK(im.size() == 32);
CHECK(im2.size() == 32);
// Check that row_size is correct
CHECK(im.row_size() == 8);
CHECK(im2.row_size() == 8);
// Check that get_premultiplied is correct
CHECK_FALSE(im.get_premultiplied());
CHECK_FALSE(im2.get_premultiplied());
// Check that set premultiplied works
im2.set_premultiplied(true);
CHECK(im2.get_premultiplied());
// Check that painted is correct
CHECK_FALSE(im.painted());
CHECK_FALSE(im2.painted());
// Check that set premultiplied works
im2.painted(true);
CHECK(im2.painted());
// Check that offset is correct
CHECK(im.get_offset() == 0.0);
CHECK(im2.get_offset() == 0.0);
// Check that set offset works
im2.set_offset(2.3);
CHECK(im2.get_offset() == 2.3);
// Check that scaling is correct
CHECK(im.get_scaling() == 1.0);
CHECK(im2.get_scaling() == 1.0);
// Check that set scaling works
im2.set_scaling(1.1);
CHECK(im2.get_scaling() == 1.1);
// CHECK that image dtype is correct
CHECK(im.get_dtype() == mapnik::image_dtype_gray16);
CHECK(im2.get_dtype() == mapnik::image_dtype_gray16);
using pixel_type = mapnik::image_view_gray16::pixel_type;
pixel_type expected_val;
// Check that all data in the view is correct
// IM
expected_val = 0;
pixel_type const* data_im = im.data();
CHECK(*data_im == expected_val);
unsigned char const* data_b = im.bytes();
CHECK(*data_b == 0);
for (std::size_t y = 0; y < im.height(); ++y)
{
std::size_t width = im.width();
pixel_type const* data_1 = im.get_row(y);
pixel_type const* data_2 = im.get_row(y, 1);
for (std::size_t x = 0; x < width; ++x)
{
CHECK(*data_1 == expected_val);
++data_1;
}
for (std::size_t x = 1; x < width; ++x)
{
CHECK(*data_2 == expected_val);
++data_2;
}
}
// IM2
expected_val = 514;
pixel_type * data_im2 = im2.data();
CHECK(*data_im2 == expected_val);
unsigned char * data_b2 = im2.bytes();
CHECK(*data_b2 == 2);
++data_b;
CHECK(*data_b2 == 2);
for (std::size_t y = 0; y < im2.height(); ++y)
{
std::size_t width = im2.width();
pixel_type const* data_1 = im2.get_row(y);
pixel_type const* data_2 = im2.get_row(y, 1);
for (std::size_t x = 0; x < width; ++x)
{
CHECK(*data_1 == expected_val);
++data_1;
}
for (std::size_t x = 1; x < width; ++x)
{
CHECK(*data_2 == expected_val);
++data_2;
}
}
// Test set row
std::vector<pixel_type> v1(im2.width(), 30);
std::vector<pixel_type> v2(im2.width()-1, 50);
im2.set_row(0, v1.data(), v1.size());
im2.set_row(1, 1, v2.size(), v2.data());
CHECK(im2(0,0) == 30);
CHECK(im2(0,1) == 514);
CHECK(im2(1,1) == 50);
} // END SECTION
SECTION("image_null")
{
mapnik::image_null im_null;
const mapnik::image_null im_null2(2,2); // Actually doesn't really set any size
mapnik::image_null im_null3(im_null2);
mapnik::image_null im_null4(std::move(im_null3));
// All nulls are equal
CHECK(im_null == im_null4);
CHECK(im_null == im_null2);
// No null is greater
CHECK_FALSE(im_null < im_null4);
CHECK_FALSE(im_null < im_null2);
// Check defaults
CHECK(im_null.width() == 0);
CHECK(im_null.height() == 0);
CHECK(im_null.size() == 0);
CHECK(im_null.row_size() == 0);
// Setting offset does nothing
im_null.set_offset(10000000.0);
CHECK(im_null.get_offset() == 0.0);
// Setting scaling does nothing
im_null.set_scaling(123123123.0);
CHECK(im_null.get_scaling() == 1.0);
CHECK(im_null.get_dtype() == mapnik::image_dtype_null);
// Setting premultiplied does nothing
im_null.set_premultiplied(true);
CHECK_FALSE(im_null.get_premultiplied());
// Setting painted does nothing
im_null.painted(true);
CHECK_FALSE(im_null.painted());
// Should throw if we try to access or setdata.
REQUIRE_THROWS(im_null(0,0));
REQUIRE_THROWS(im_null2(0,0));
REQUIRE_THROWS(im_null(0,0) = 1);
unsigned char const* e1 = im_null.bytes();
unsigned char * e2 = im_null.bytes();
CHECK(e1 == nullptr);
CHECK(e2 == nullptr);
} // END SECTION
SECTION("image any")
{
mapnik::image_null null_im;
const mapnik::image_any im_any_null(null_im);
CHECK(im_any_null.get_dtype() == mapnik::image_dtype_null);
CHECK(im_any_null.bytes() == nullptr);
mapnik::image_gray16 im(4,4);
mapnik::fill(im, 514);
mapnik::image_any im_any(im);
CHECK(im_any.get_dtype() == mapnik::image_dtype_gray16);
unsigned char * foo = im_any.bytes();
CHECK(*foo == 2);
++foo;
CHECK(*foo == 2);
CHECK(im_any.width() == 4);
CHECK(im_any.height() == 4);
CHECK(im_any.size() == 32);
CHECK(im_any.row_size() == 8);
CHECK_FALSE(im_any.get_premultiplied());
im_any.set_offset(10.0);
CHECK(im_any.get_offset() == 10.0);
im_any.set_scaling(2.1);
CHECK(im_any.get_scaling() == 2.1);
CHECK_FALSE(im_any.painted());
} // END SECTION
SECTION("test image_any initialization")
TEST_CASE("image class")
{
SECTION("test gray16")
{
mapnik::image_any im(4,4);
CHECK(im.get_dtype() == mapnik::image_dtype_rgba8);
}
{
mapnik::image_any im(4, 4, mapnik::image_dtype_null);
CHECK(im.get_dtype() == mapnik::image_dtype_null);
}
{
mapnik::image_any im(4, 4, mapnik::image_dtype_gray8);
CHECK(im.get_dtype() == mapnik::image_dtype_gray8);
}
{
mapnik::image_any im(4, 4, mapnik::image_dtype_gray8s);
CHECK(im.get_dtype() == mapnik::image_dtype_gray8s);
}
{
mapnik::image_any im(4, 4, mapnik::image_dtype_gray16);
const mapnik::image_gray16 im(4, 4);
mapnik::image_gray16 im2(im);
mapnik::image_gray16 im3(5, 5);
CHECK(im == im);
CHECK_FALSE(im == im2);
CHECK_FALSE(im2 == im3);
CHECK(im < im3);
CHECK_FALSE(im < im2);
// Check that width is correct
CHECK(im.width() == 4);
CHECK(im2.width() == 4);
// Check that height is correct
CHECK(im.height() == 4);
CHECK(im2.height() == 4);
CHECK(im(0, 0) == 0);
CHECK(im2(0, 0) == 0);
im2(0, 0) = 1;
CHECK(im2(0, 0) == 1);
im2.set(514);
CHECK(im2(0, 0) == 514);
CHECK(im2(1, 1) == 514);
// Check that size is correct
CHECK(im.size() == 32);
CHECK(im2.size() == 32);
// Check that row_size is correct
CHECK(im.row_size() == 8);
CHECK(im2.row_size() == 8);
// Check that get_premultiplied is correct
CHECK_FALSE(im.get_premultiplied());
CHECK_FALSE(im2.get_premultiplied());
// Check that set premultiplied works
im2.set_premultiplied(true);
CHECK(im2.get_premultiplied());
// Check that painted is correct
CHECK_FALSE(im.painted());
CHECK_FALSE(im2.painted());
// Check that set premultiplied works
im2.painted(true);
CHECK(im2.painted());
// Check that offset is correct
CHECK(im.get_offset() == 0.0);
CHECK(im2.get_offset() == 0.0);
// Check that set offset works
im2.set_offset(2.3);
CHECK(im2.get_offset() == 2.3);
// Check that scaling is correct
CHECK(im.get_scaling() == 1.0);
CHECK(im2.get_scaling() == 1.0);
// Check that set scaling works
im2.set_scaling(1.1);
CHECK(im2.get_scaling() == 1.1);
// CHECK that image dtype is correct
CHECK(im.get_dtype() == mapnik::image_dtype_gray16);
}
CHECK(im2.get_dtype() == mapnik::image_dtype_gray16);
using pixel_type = mapnik::image_view_gray16::pixel_type;
pixel_type expected_val;
// Check that all data in the view is correct
// IM
expected_val = 0;
pixel_type const* data_im = im.data();
CHECK(*data_im == expected_val);
unsigned char const* data_b = im.bytes();
CHECK(*data_b == 0);
for (std::size_t y = 0; y < im.height(); ++y)
{
std::size_t width = im.width();
pixel_type const* data_1 = im.get_row(y);
pixel_type const* data_2 = im.get_row(y, 1);
for (std::size_t x = 0; x < width; ++x)
{
CHECK(*data_1 == expected_val);
++data_1;
}
for (std::size_t x = 1; x < width; ++x)
{
CHECK(*data_2 == expected_val);
++data_2;
}
}
// IM2
expected_val = 514;
pixel_type* data_im2 = im2.data();
CHECK(*data_im2 == expected_val);
unsigned char* data_b2 = im2.bytes();
CHECK(*data_b2 == 2);
++data_b;
CHECK(*data_b2 == 2);
for (std::size_t y = 0; y < im2.height(); ++y)
{
std::size_t width = im2.width();
pixel_type const* data_1 = im2.get_row(y);
pixel_type const* data_2 = im2.get_row(y, 1);
for (std::size_t x = 0; x < width; ++x)
{
CHECK(*data_1 == expected_val);
++data_1;
}
for (std::size_t x = 1; x < width; ++x)
{
CHECK(*data_2 == expected_val);
++data_2;
}
}
// Test set row
std::vector<pixel_type> v1(im2.width(), 30);
std::vector<pixel_type> v2(im2.width() - 1, 50);
im2.set_row(0, v1.data(), v1.size());
im2.set_row(1, 1, v2.size(), v2.data());
CHECK(im2(0, 0) == 30);
CHECK(im2(0, 1) == 514);
CHECK(im2(1, 1) == 50);
} // END SECTION
SECTION("image_null")
{
mapnik::image_any im(4, 4, mapnik::image_dtype_gray16s);
CHECK(im.get_dtype() == mapnik::image_dtype_gray16s);
}
mapnik::image_null im_null;
const mapnik::image_null im_null2(2, 2); // Actually doesn't really set any size
mapnik::image_null im_null3(im_null2);
mapnik::image_null im_null4(std::move(im_null3));
// All nulls are equal
CHECK(im_null == im_null4);
CHECK(im_null == im_null2);
// No null is greater
CHECK_FALSE(im_null < im_null4);
CHECK_FALSE(im_null < im_null2);
// Check defaults
CHECK(im_null.width() == 0);
CHECK(im_null.height() == 0);
CHECK(im_null.size() == 0);
CHECK(im_null.row_size() == 0);
// Setting offset does nothing
im_null.set_offset(10000000.0);
CHECK(im_null.get_offset() == 0.0);
// Setting scaling does nothing
im_null.set_scaling(123123123.0);
CHECK(im_null.get_scaling() == 1.0);
CHECK(im_null.get_dtype() == mapnik::image_dtype_null);
// Setting premultiplied does nothing
im_null.set_premultiplied(true);
CHECK_FALSE(im_null.get_premultiplied());
// Setting painted does nothing
im_null.painted(true);
CHECK_FALSE(im_null.painted());
// Should throw if we try to access or setdata.
REQUIRE_THROWS(im_null(0, 0));
REQUIRE_THROWS(im_null2(0, 0));
REQUIRE_THROWS(im_null(0, 0) = 1);
unsigned char const* e1 = im_null.bytes();
unsigned char* e2 = im_null.bytes();
CHECK(e1 == nullptr);
CHECK(e2 == nullptr);
} // END SECTION
SECTION("image any")
{
mapnik::image_any im(4, 4, mapnik::image_dtype_gray32);
CHECK(im.get_dtype() == mapnik::image_dtype_gray32);
}
mapnik::image_null null_im;
const mapnik::image_any im_any_null(null_im);
CHECK(im_any_null.get_dtype() == mapnik::image_dtype_null);
CHECK(im_any_null.bytes() == nullptr);
mapnik::image_gray16 im(4, 4);
mapnik::fill(im, 514);
mapnik::image_any im_any(im);
CHECK(im_any.get_dtype() == mapnik::image_dtype_gray16);
unsigned char* foo = im_any.bytes();
CHECK(*foo == 2);
++foo;
CHECK(*foo == 2);
CHECK(im_any.width() == 4);
CHECK(im_any.height() == 4);
CHECK(im_any.size() == 32);
CHECK(im_any.row_size() == 8);
CHECK_FALSE(im_any.get_premultiplied());
im_any.set_offset(10.0);
CHECK(im_any.get_offset() == 10.0);
im_any.set_scaling(2.1);
CHECK(im_any.get_scaling() == 2.1);
CHECK_FALSE(im_any.painted());
} // END SECTION
SECTION("test image_any initialization")
{
mapnik::image_any im(4, 4, mapnik::image_dtype_gray32s);
CHECK(im.get_dtype() == mapnik::image_dtype_gray32s);
}
{
mapnik::image_any im(4, 4);
CHECK(im.get_dtype() == mapnik::image_dtype_rgba8);
}
{
mapnik::image_any im(4, 4, mapnik::image_dtype_null);
CHECK(im.get_dtype() == mapnik::image_dtype_null);
}
{
mapnik::image_any im(4, 4, mapnik::image_dtype_gray8);
CHECK(im.get_dtype() == mapnik::image_dtype_gray8);
}
{
mapnik::image_any im(4, 4, mapnik::image_dtype_gray8s);
CHECK(im.get_dtype() == mapnik::image_dtype_gray8s);
}
{
mapnik::image_any im(4, 4, mapnik::image_dtype_gray16);
CHECK(im.get_dtype() == mapnik::image_dtype_gray16);
}
{
mapnik::image_any im(4, 4, mapnik::image_dtype_gray16s);
CHECK(im.get_dtype() == mapnik::image_dtype_gray16s);
}
{
mapnik::image_any im(4, 4, mapnik::image_dtype_gray32);
CHECK(im.get_dtype() == mapnik::image_dtype_gray32);
}
{
mapnik::image_any im(4, 4, mapnik::image_dtype_gray32s);
CHECK(im.get_dtype() == mapnik::image_dtype_gray32s);
}
{
mapnik::image_any im(4, 4, mapnik::image_dtype_gray32f);
CHECK(im.get_dtype() == mapnik::image_dtype_gray32f);
}
{
mapnik::image_any im(4, 4, mapnik::image_dtype_gray64);
CHECK(im.get_dtype() == mapnik::image_dtype_gray64);
}
{
mapnik::image_any im(4, 4, mapnik::image_dtype_gray64s);
CHECK(im.get_dtype() == mapnik::image_dtype_gray64s);
}
{
mapnik::image_any im(4, 4, mapnik::image_dtype_gray64f);
CHECK(im.get_dtype() == mapnik::image_dtype_gray64f);
}
} // END SECTION
SECTION("Image Buffer")
{
mapnik::image_any im(4, 4, mapnik::image_dtype_gray32f);
CHECK(im.get_dtype() == mapnik::image_dtype_gray32f);
}
mapnik::detail::buffer buf_zero(0);
CHECK(buf_zero.size() == 0);
CHECK(!buf_zero);
mapnik::detail::buffer buf(10);
CHECK(buf.size() == 10);
CHECK_FALSE(!buf);
unsigned char* d = buf.data();
*d = 9;
const mapnik::detail::buffer buf2 = buf;
CHECK(buf2.size() == 10);
unsigned char const* d2 = buf2.data();
CHECK(*d2 == 9);
} // END SECTION
SECTION("Image copy/move")
{
mapnik::image_any im(4, 4, mapnik::image_dtype_gray64);
CHECK(im.get_dtype() == mapnik::image_dtype_gray64);
mapnik::detail::buffer buf(16 * 16 * 4); // large enough to hold 16*16 RGBA image
CHECK(buf.size() == 16 * 16 * 4);
// fill buffer with 0xff
std::fill(buf.data(), buf.data() + buf.size(), 0xff);
// move buffer
mapnik::detail::buffer buf2(std::move(buf));
CHECK(buf.size() == 0);
CHECK(buf.data() == nullptr);
mapnik::image_rgba8 im(16, 16, buf2.data()); // shallow copy
std::size_t count = 0;
for (auto const& pixel : im)
{
// expect rgba(255,255,255,1.0)
CHECK(sizeof(pixel) == sizeof(mapnik::image_rgba8::pixel_type));
CHECK(pixel == 0xffffffff);
++count;
}
CHECK(count == im.width() * im.height());
CHECK(buf2.size() == im.width() * im.height() * sizeof(mapnik::image_rgba8::pixel_type));
// mutate buffer
// fill buffer with 0x7f - semi-transparent grey
std::fill(buf2.data(), buf2.data() + buf2.size(), 0x7f);
for (auto const& pixel : im)
{
// expect rgba(127,127,127,0.5)
CHECK(pixel == 0x7f7f7f7f);
}
// mutate image directly (buf)
for (auto& pixel : im)
{
pixel = mapnik::color(0, 255, 0).rgba(); // green
}
// move
mapnik::image_rgba8 im2(std::move(im));
CHECK(im.data() == nullptr);
CHECK(im.bytes() == nullptr);
CHECK(im.width() == 0);
CHECK(im.height() == 0);
for (auto const& pixel : im2)
{
// expect `green`
CHECK(pixel == mapnik::color(0, 255, 0).rgba());
}
mapnik::image_rgba8 im3(im2); // shallow copy
for (auto& pixel : im3)
{
// expect `green`
CHECK(pixel == mapnik::color(0, 255, 0).rgba());
// mutate
pixel = mapnik::color(255, 0, 0).rgba(); // red
}
for (auto const& pixel : im3)
{
// expect `red`
CHECK(pixel == mapnik::color(255, 0, 0).rgba());
}
for (auto const& pixel : im2)
{
// expect `red`
CHECK(pixel == mapnik::color(255, 0, 0).rgba());
}
}
SECTION("image::swap")
{
mapnik::image_any im(4, 4, mapnik::image_dtype_gray64s);
CHECK(im.get_dtype() == mapnik::image_dtype_gray64s);
auto blue = mapnik::color(50, 50, 250).rgba();
auto orange = mapnik::color(250, 150, 0).rgba();
mapnik::image_rgba8 im;
mapnik::image_rgba8 im2(16, 16);
mapnik::image_rgba8 im3(16, 16);
im2.set(blue);
im3.set(orange);
// swap two non-empty images
CHECK_NOTHROW(im2.swap(im3));
CHECK(im2(0, 0) == orange);
CHECK(im3(0, 0) == blue);
// swap empty <-> non-empty
CHECK_NOTHROW(im.swap(im3));
CHECK(im3.data() == nullptr);
CHECKED_IF(im.data() != nullptr) { CHECK(im(0, 0) == blue); }
}
{
mapnik::image_any im(4, 4, mapnik::image_dtype_gray64f);
CHECK(im.get_dtype() == mapnik::image_dtype_gray64f);
}
} // END SECTION
SECTION("Image Buffer")
{
mapnik::detail::buffer buf_zero(0);
CHECK(buf_zero.size() == 0);
CHECK(!buf_zero);
mapnik::detail::buffer buf(10);
CHECK(buf.size() == 10);
CHECK_FALSE(!buf);
unsigned char * d = buf.data();
*d = 9;
const mapnik::detail::buffer buf2 = buf;
CHECK(buf2.size() == 10);
unsigned char const* d2 = buf2.data();
CHECK(*d2 == 9);
} // END SECTION
SECTION("Image copy/move")
{
mapnik::detail::buffer buf(16 * 16 * 4); // large enough to hold 16*16 RGBA image
CHECK(buf.size() == 16 * 16 * 4);
// fill buffer with 0xff
std::fill(buf.data(), buf.data() + buf.size(), 0xff);
// move buffer
mapnik::detail::buffer buf2(std::move(buf));
CHECK (buf.size() == 0);
CHECK (buf.data() == nullptr);
mapnik::image_rgba8 im(16, 16, buf2.data()); // shallow copy
std::size_t count = 0;
for (auto const& pixel : im)
{
// expect rgba(255,255,255,1.0)
CHECK( sizeof(pixel) == sizeof(mapnik::image_rgba8::pixel_type));
CHECK( pixel == 0xffffffff);
++count;
}
CHECK( count == im.width() * im.height());
CHECK( buf2.size() == im.width() * im.height() * sizeof( mapnik::image_rgba8::pixel_type));
// mutate buffer
// fill buffer with 0x7f - semi-transparent grey
std::fill(buf2.data(), buf2.data() + buf2.size(), 0x7f);
for (auto const& pixel : im)
{
// expect rgba(127,127,127,0.5)
CHECK( pixel == 0x7f7f7f7f);
}
// mutate image directly (buf)
for (auto & pixel : im)
{
pixel = mapnik::color(0,255,0).rgba(); // green
}
// move
mapnik::image_rgba8 im2(std::move(im));
CHECK (im.data() == nullptr);
CHECK (im.bytes() == nullptr);
CHECK (im.width() == 0);
CHECK (im.height() == 0);
for (auto const& pixel : im2)
{
// expect `green`
CHECK( pixel == mapnik::color(0,255,0).rgba());
}
mapnik::image_rgba8 im3(im2); // shallow copy
for (auto & pixel : im3)
{
// expect `green`
CHECK( pixel == mapnik::color(0,255,0).rgba());
// mutate
pixel = mapnik::color(255,0,0).rgba(); //red
}
for (auto const& pixel : im3)
{
// expect `red`
CHECK( pixel == mapnik::color(255,0,0).rgba());
}
for (auto const& pixel : im2)
{
// expect `red`
CHECK( pixel == mapnik::color(255,0,0).rgba());
}
}
SECTION("image::swap")
{
auto blue = mapnik::color(50, 50, 250).rgba();
auto orange = mapnik::color(250, 150, 0).rgba();
mapnik::image_rgba8 im;
mapnik::image_rgba8 im2(16, 16);
mapnik::image_rgba8 im3(16, 16);
im2.set(blue);
im3.set(orange);
// swap two non-empty images
CHECK_NOTHROW(im2.swap(im3));
CHECK(im2(0, 0) == orange);
CHECK(im3(0, 0) == blue);
// swap empty <-> non-empty
CHECK_NOTHROW(im.swap(im3));
CHECK(im3.data() == nullptr);
CHECKED_IF(im.data() != nullptr)
{
CHECK(im(0, 0) == blue);
}
}
} // END TEST CASE

View file

@ -6,100 +6,100 @@
#include <mapnik/color.hpp>
#include <mapnik/image_util.hpp>
TEST_CASE("image apply_opacity") {
TEST_CASE("image apply_opacity")
{
SECTION("test rgba8")
{
mapnik::image_rgba8 im(4, 4);
mapnik::image_rgba8 im2(4, 4, true, true); // Initialize as already premultiplied
mapnik::image_any im_any(mapnik::image_rgba8(4, 4));
mapnik::image_any im2_any(mapnik::image_rgba8(4, 4, true, true));
SECTION("test rgba8") {
// Fill the images with meaningfull values
mapnik::color c1(57, 70, 128, 128); // This color is not premultiplied
mapnik::color c2(57, 70, 128, 128, true); // This color is premultiplied
mapnik::fill(im, c1); // Because c1 is not premultiplied it will make the image not premultiplied
mapnik::fill(im_any, c1); // Because c1 is not premultiplied it will make the image not premultiplied
mapnik::fill(im2, c2); // Because c1 is premultiplied it will make the image premultiplied
mapnik::fill(im2_any, c2); // Because c1 is premultiplied it will make the image premultiplied
mapnik::image_rgba8 im(4,4);
mapnik::image_rgba8 im2(4,4,true,true); // Initialize as already premultiplied
mapnik::image_any im_any(mapnik::image_rgba8(4,4));
mapnik::image_any im2_any(mapnik::image_rgba8(4,4,true,true));
mapnik::apply_opacity(im, 0.75);
mapnik::apply_opacity(im_any, 0.75);
mapnik::apply_opacity(im2, 0.75);
mapnik::apply_opacity(im2_any, 0.75);
// Fill the images with meaningfull values
mapnik::color c1(57,70,128,128); // This color is not premultiplied
mapnik::color c2(57,70,128,128, true); // This color is premultiplied
mapnik::fill(im, c1); // Because c1 is not premultiplied it will make the image not premultiplied
mapnik::fill(im_any, c1); // Because c1 is not premultiplied it will make the image not premultiplied
mapnik::fill(im2, c2); // Because c1 is premultiplied it will make the image premultiplied
mapnik::fill(im2_any, c2); // Because c1 is premultiplied it will make the image premultiplied
mapnik::color out;
// This should have only changed the alpha, as it was not premultipleid
out = mapnik::get_pixel<mapnik::color>(im, 0, 0);
CHECK(static_cast<int>(out.red()) == 57);
CHECK(static_cast<int>(out.green()) == 70);
CHECK(static_cast<int>(out.blue()) == 128);
CHECK(static_cast<int>(out.alpha()) == 96);
out = mapnik::get_pixel<mapnik::color>(im_any, 0, 0);
CHECK(static_cast<int>(out.red()) == 57);
CHECK(static_cast<int>(out.green()) == 70);
CHECK(static_cast<int>(out.blue()) == 128);
CHECK(static_cast<int>(out.alpha()) == 96);
// This will be different because it is demultiplied then premultiplied again after setting alpha
out = mapnik::get_pixel<mapnik::color>(im2, 0, 0);
CHECK(static_cast<int>(out.red()) == 43);
CHECK(static_cast<int>(out.green()) == 53);
CHECK(static_cast<int>(out.blue()) == 96);
CHECK(static_cast<int>(out.alpha()) == 96);
out = mapnik::get_pixel<mapnik::color>(im2_any, 0, 0);
CHECK(static_cast<int>(out.red()) == 43);
CHECK(static_cast<int>(out.green()) == 53);
CHECK(static_cast<int>(out.blue()) == 96);
CHECK(static_cast<int>(out.alpha()) == 96);
mapnik::apply_opacity(im, 0.75);
mapnik::apply_opacity(im_any, 0.75);
mapnik::apply_opacity(im2, 0.75);
mapnik::apply_opacity(im2_any, 0.75);
} // END SECTION
mapnik::color out;
// This should have only changed the alpha, as it was not premultipleid
out = mapnik::get_pixel<mapnik::color>(im, 0, 0);
CHECK(static_cast<int>(out.red()) == 57);
CHECK(static_cast<int>(out.green()) == 70);
CHECK(static_cast<int>(out.blue()) == 128);
CHECK(static_cast<int>(out.alpha()) == 96);
out = mapnik::get_pixel<mapnik::color>(im_any, 0, 0);
CHECK(static_cast<int>(out.red()) == 57);
CHECK(static_cast<int>(out.green()) == 70);
CHECK(static_cast<int>(out.blue()) == 128);
CHECK(static_cast<int>(out.alpha()) == 96);
// This will be different because it is demultiplied then premultiplied again after setting alpha
out = mapnik::get_pixel<mapnik::color>(im2, 0, 0);
CHECK(static_cast<int>(out.red()) == 43);
CHECK(static_cast<int>(out.green()) == 53);
CHECK(static_cast<int>(out.blue()) == 96);
CHECK(static_cast<int>(out.alpha()) == 96);
out = mapnik::get_pixel<mapnik::color>(im2_any, 0, 0);
CHECK(static_cast<int>(out.red()) == 43);
CHECK(static_cast<int>(out.green()) == 53);
CHECK(static_cast<int>(out.blue()) == 96);
CHECK(static_cast<int>(out.alpha()) == 96);
SECTION("test rgba8 overflow")
{
mapnik::image_rgba8 im(4, 4);
mapnik::color c(128, 128, 128, 128); // This color is premultiplied
mapnik::fill(im, c); // Because c1 is not premultiplied it will make the image not premultiplied
mapnik::color out;
out = mapnik::get_pixel<mapnik::color>(im, 0, 0);
CHECK(static_cast<int>(out.red()) == 128);
CHECK(static_cast<int>(out.green()) == 128);
CHECK(static_cast<int>(out.blue()) == 128);
CHECK(static_cast<int>(out.alpha()) == 128);
} // END SECTION
mapnik::apply_opacity(im, 2.5);
SECTION("test rgba8 overflow") {
out = mapnik::get_pixel<mapnik::color>(im, 0, 0);
CHECK(static_cast<int>(out.red()) == 128);
CHECK(static_cast<int>(out.green()) == 128);
CHECK(static_cast<int>(out.blue()) == 128);
CHECK(static_cast<int>(out.alpha()) == 128);
mapnik::image_rgba8 im(4,4);
mapnik::color c(128,128,128,128); // This color is premultiplied
mapnik::fill(im, c); // Because c1 is not premultiplied it will make the image not premultiplied
mapnik::color out;
out = mapnik::get_pixel<mapnik::color>(im, 0, 0);
CHECK(static_cast<int>(out.red()) == 128);
CHECK(static_cast<int>(out.green()) == 128);
CHECK(static_cast<int>(out.blue()) == 128);
CHECK(static_cast<int>(out.alpha()) == 128);
} // END SECTION
mapnik::apply_opacity(im, 2.5);
SECTION("test rgba8 underflow")
{
mapnik::image_rgba8 im(4, 4);
mapnik::color c(128, 128, 128, 128); // This color is premultiplied
mapnik::fill(im, c); // Because c1 is not premultiplied it will make the image not premultiplied
out = mapnik::get_pixel<mapnik::color>(im, 0, 0);
CHECK(static_cast<int>(out.red()) == 128);
CHECK(static_cast<int>(out.green()) == 128);
CHECK(static_cast<int>(out.blue()) == 128);
CHECK(static_cast<int>(out.alpha()) == 128);
mapnik::apply_opacity(im, -2.5);
} // END SECTION
mapnik::color out;
out = mapnik::get_pixel<mapnik::color>(im, 0, 0);
CHECK(static_cast<int>(out.red()) == 128);
CHECK(static_cast<int>(out.green()) == 128);
CHECK(static_cast<int>(out.blue()) == 128);
CHECK(static_cast<int>(out.alpha()) == 0);
SECTION("test rgba8 underflow") {
} // END SECTION
mapnik::image_rgba8 im(4,4);
mapnik::color c(128,128,128,128); // This color is premultiplied
mapnik::fill(im, c); // Because c1 is not premultiplied it will make the image not premultiplied
SECTION("test gray8")
{
mapnik::image_gray8 im(4, 4);
mapnik::image_any im_any(mapnik::image_gray8(4, 4));
mapnik::apply_opacity(im, -2.5);
CHECK_THROWS(mapnik::apply_opacity(im, 0.25));
CHECK_THROWS(mapnik::apply_opacity(im_any, 0.25));
mapnik::color out;
out = mapnik::get_pixel<mapnik::color>(im, 0, 0);
CHECK(static_cast<int>(out.red()) == 128);
CHECK(static_cast<int>(out.green()) == 128);
CHECK(static_cast<int>(out.blue()) == 128);
CHECK(static_cast<int>(out.alpha()) == 0);
} // END SECTION
SECTION("test gray8") {
mapnik::image_gray8 im(4,4);
mapnik::image_any im_any(mapnik::image_gray8(4,4));
CHECK_THROWS(mapnik::apply_opacity(im, 0.25));
CHECK_THROWS(mapnik::apply_opacity(im_any, 0.25));
} // END SECTION
} // END SECTION
} // END TEST_CASE

View file

@ -11,511 +11,512 @@
#include <sstream>
#include <array>
TEST_CASE("image filter") {
SECTION("test bad filter input") {
mapnik::image_rgba8 im(3,3);
mapnik::fill(im,mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("red"));
REQUIRE_THROWS( mapnik::filter::filter_image(im, "foo,asdfasdf()"));
REQUIRE_THROWS( mapnik::filter::filter_image(im, "colorize-alpha("));
REQUIRE_THROWS( mapnik::filter::filter_image(im, "color-to-alpha(blue"));
REQUIRE_THROWS( mapnik::filter::filter_image(im, "color-to-alpha(,blue)"));
REQUIRE_THROWS( mapnik::filter::filter_image(im, "colorize-alpha()"));
mapnik::image_rgba8 const& im2 = im;
REQUIRE_THROWS(mapnik::filter::filter_image(im2, "foo"));
CHECK(im(0,0) == 0xffff0000);
CHECK(im(0,1) == 0xffff0000);
CHECK(im(0,2) == 0xffff0000);
CHECK(im(1,0) == 0xffff0000);
CHECK(im(1,1) == 0xff0000ff);
CHECK(im(1,2) == 0xffff0000);
CHECK(im(2,0) == 0xffff0000);
CHECK(im(2,1) == 0xffff0000);
CHECK(im(2,2) == 0xffff0000);
} // END SECTION
SECTION("test blur") {
mapnik::image_rgba8 im(3,3);
mapnik::fill(im,mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("red"));
mapnik::filter::filter_image(im, "blur");
CHECK(im(0,0) == 0xffc60038);
CHECK(im(0,1) == 0xffe2001c);
CHECK(im(0,2) == 0xffc60038);
CHECK(im(1,0) == 0xffc60038);
CHECK(im(1,1) == 0xffe2001c);
CHECK(im(1,2) == 0xffc60038);
CHECK(im(2,0) == 0xffc60038);
CHECK(im(2,1) == 0xffe2001c);
CHECK(im(2,2) == 0xffc60038);
} // END SECTION
SECTION("test blur constant") {
mapnik::image_rgba8 im_orig(3,3);
mapnik::fill(im_orig,mapnik::color("blue"));
mapnik::set_pixel(im_orig, 1, 1, mapnik::color("red"));
mapnik::image_rgba8 const& im_new = im_orig;
mapnik::image_rgba8 im = mapnik::filter::filter_image(im_new, "blur");
CHECK(im(0,0) == 0xffc60038);
CHECK(im(0,1) == 0xffe2001c);
CHECK(im(0,2) == 0xffc60038);
CHECK(im(1,0) == 0xffc60038);
CHECK(im(1,1) == 0xffe2001c);
CHECK(im(1,2) == 0xffc60038);
CHECK(im(2,0) == 0xffc60038);
CHECK(im(2,1) == 0xffe2001c);
CHECK(im(2,2) == 0xffc60038);
} // END SECTION
SECTION("test gray") {
mapnik::image_rgba8 im(3,3);
mapnik::fill(im,mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("red"));
mapnik::filter::filter_image(im, "gray");
CHECK(im(0,0) == 0xff1c1c1c);
CHECK(im(0,1) == 0xff1c1c1c);
CHECK(im(0,2) == 0xff1c1c1c);
CHECK(im(1,0) == 0xff1c1c1c);
CHECK(im(1,1) == 0xff4c4c4c);
CHECK(im(1,2) == 0xff1c1c1c);
CHECK(im(2,0) == 0xff1c1c1c);
CHECK(im(2,1) == 0xff1c1c1c);
CHECK(im(2,2) == 0xff1c1c1c);
} // END SECTION
SECTION("test agg stack blur") {
mapnik::image_rgba8 im(3,3);
mapnik::fill(im,mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("red"));
mapnik::filter::filter_image(im, "agg-stack-blur(1,1)");
CHECK(im(0,0) == 0xffef000f);
CHECK(im(0,1) == 0xffdf001f);
CHECK(im(0,2) == 0xffef000f);
CHECK(im(1,0) == 0xffdf001f);
CHECK(im(1,1) == 0xffbf003f);
CHECK(im(1,2) == 0xffdf001f);
CHECK(im(2,0) == 0xffef000f);
CHECK(im(2,1) == 0xffdf001f);
CHECK(im(2,2) == 0xffef000f);
} // END SECTION
SECTION("test scale-hsla 1") {
mapnik::image_rgba8 im(3,3);
mapnik::fill(im,mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("red"));
mapnik::filter::filter_image(im, "scale-hsla(0.0,0.5,0.0,1.0,0.0,0.5,0.0,0.5)");
CHECK(im(0,0) == 0x80004000);
CHECK(im(0,1) == 0x80004000);
CHECK(im(0,2) == 0x80004000);
CHECK(im(1,0) == 0x80004000);
CHECK(im(1,1) == 0x80000040);
CHECK(im(1,2) == 0x80004000);
CHECK(im(2,0) == 0x80004000);
CHECK(im(2,1) == 0x80004000);
CHECK(im(2,2) == 0x80004000);
} // END SECTION
SECTION("test scale-hsla 2") {
mapnik::image_rgba8 im(3,3);
mapnik::set_pixel(im, 0, 0, mapnik::color(255, 0, 0));
mapnik::set_pixel(im, 0, 1, mapnik::color(147, 112, 219));
mapnik::set_pixel(im, 0, 2, mapnik::color(128, 128, 128));
mapnik::set_pixel(im, 1, 0, mapnik::color(72, 209, 204));
mapnik::set_pixel(im, 1, 1, mapnik::color(218, 112, 214));
mapnik::set_pixel(im, 1, 2, mapnik::color(30, 144, 255));
mapnik::set_pixel(im, 2, 0, mapnik::color(238, 130, 238));
mapnik::set_pixel(im, 2, 1, mapnik::color(154, 205, 50));
mapnik::set_pixel(im, 2, 2, mapnik::color(160, 82, 45));
// Should not throw on values out of [0, 1]
// https://github.com/mapnik/mapnik/issues/3052
REQUIRE_NOTHROW(mapnik::filter::filter_image(im, "scale-hsla(0.0,1.5,-1.0,1.0,-1.0,2.0,1.0,1.0)"));
CHECK(im(0,0) == 0xff0000ff);
CHECK(im(0,1) == 0xffefeff4);
CHECK(im(0,2) == 0xff818181);
CHECK(im(1,0) == 0xffb895a5);
CHECK(im(1,1) == 0xffededf3);
CHECK(im(1,2) == 0xffd75aff);
CHECK(im(2,0) == 0xffffffff);
CHECK(im(2,1) == 0xff649b64);
CHECK(im(2,2) == 0xff2e343b);
} // END SECTION
SECTION("test emboss") {
mapnik::image_rgba8 im(3,3);
mapnik::fill(im,mapnik::color("white"));
mapnik::set_pixel(im, 1, 1, mapnik::color("orange"));
mapnik::filter::filter_image(im, "emboss");
CHECK(im(0,0) == 0xff004bff);
CHECK(im(0,1) == 0xff00a5ff);
CHECK(im(0,2) == 0xff004bff);
CHECK(im(1,0) == 0xffffffff);
CHECK(im(1,1) == 0xff00a5ff);
CHECK(im(1,2) == 0xffffffff);
CHECK(im(2,0) == 0xffffffff);
CHECK(im(2,1) == 0xffffffff);
CHECK(im(2,2) == 0xffffffff);
} // END SECTION
SECTION("test sharpen") {
mapnik::image_rgba8 im(3,3);
mapnik::fill(im,mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("gray"));
mapnik::filter::filter_image(im, "sharpen");
CHECK(im(0,0) == 0xffff0000);
CHECK(im(0,1) == 0xffff0000);
CHECK(im(0,2) == 0xffff0000);
CHECK(im(1,0) == 0xffff0000);
CHECK(im(1,1) == 0xff00ffff);
CHECK(im(1,2) == 0xffff0000);
CHECK(im(2,0) == 0xffff0000);
CHECK(im(2,1) == 0xffff0000);
CHECK(im(2,2) == 0xffff0000);
} // END SECTION
SECTION("test edge detect") {
mapnik::image_rgba8 im(3,3);
mapnik::fill(im,mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("gray"));
mapnik::filter::filter_image(im, "edge-detect");
CHECK(im(0,0) == 0xff000000);
CHECK(im(0,1) == 0xff008080);
CHECK(im(0,2) == 0xff000000);
CHECK(im(1,0) == 0xff00ffff);
CHECK(im(1,1) == 0xffff0000);
CHECK(im(1,2) == 0xff00ffff);
CHECK(im(2,0) == 0xff000000);
CHECK(im(2,1) == 0xff008080);
CHECK(im(2,2) == 0xff000000);
} // END SECTION
SECTION("test sobel") {
mapnik::image_rgba8 im(3,3);
mapnik::fill(im,mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("gray"));
mapnik::filter::filter_image(im, "sobel");
CHECK(im(0,0) == 0xfffeffff);
CHECK(im(0,1) == 0xfffeffff);
CHECK(im(0,2) == 0xfffeffff);
CHECK(im(1,0) == 0xff000000);
CHECK(im(1,1) == 0xff000000);
CHECK(im(1,2) == 0xff000000);
CHECK(im(2,0) == 0xfffeffff);
CHECK(im(2,1) == 0xfffeffff);
CHECK(im(2,2) == 0xfffeffff);
} // END SECTION
SECTION("test x-gradient") {
mapnik::image_rgba8 im(3,3);
mapnik::fill(im,mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("gray"));
mapnik::filter::filter_image(im, "x-gradient");
CHECK(im(0,0) == 0xff808080);
CHECK(im(0,1) == 0xffbf4040);
CHECK(im(0,2) == 0xff808080);
CHECK(im(1,0) == 0xff808080);
CHECK(im(1,1) == 0xff808080);
CHECK(im(1,2) == 0xff808080);
CHECK(im(2,0) == 0xff808080);
CHECK(im(2,1) == 0xff41c0c0);
CHECK(im(2,2) == 0xff808080);
} // END SECTION
SECTION("test y-gradient") {
mapnik::image_rgba8 im(3,3);
mapnik::fill(im,mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("gray"));
mapnik::filter::filter_image(im, "y-gradient");
CHECK(im(0,0) == 0xff808080);
CHECK(im(0,1) == 0xff808080);
CHECK(im(0,2) == 0xff808080);
CHECK(im(1,0) == 0xffbf4040);
CHECK(im(1,1) == 0xff808080);
CHECK(im(1,2) == 0xff41c0c0);
CHECK(im(2,0) == 0xff808080);
CHECK(im(2,1) == 0xff808080);
CHECK(im(2,2) == 0xff808080);
} // END SECTION
SECTION("test invert") {
mapnik::image_rgba8 im(3,3);
mapnik::fill(im,mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("gray"));
mapnik::filter::filter_image(im, "invert");
CHECK(im(0,0) == 0xff00ffff);
CHECK(im(0,1) == 0xff00ffff);
CHECK(im(0,2) == 0xff00ffff);
CHECK(im(1,0) == 0xff00ffff);
CHECK(im(1,1) == 0xff7f7f7f);
CHECK(im(1,2) == 0xff00ffff);
CHECK(im(2,0) == 0xff00ffff);
CHECK(im(2,1) == 0xff00ffff);
CHECK(im(2,2) == 0xff00ffff);
} // END SECTION
SECTION("test colorize-alpha - one color") {
mapnik::image_rgba8 im(3,3);
mapnik::fill(im,mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("gray"));
mapnik::filter::filter_image(im, "colorize-alpha(blue)");
CHECK(im(0,0) == 0xffff0000);
CHECK(im(0,1) == 0xffff0000);
CHECK(im(0,2) == 0xffff0000);
CHECK(im(1,0) == 0xffff0000);
CHECK(im(1,1) == 0xffff0000);
CHECK(im(1,2) == 0xffff0000);
CHECK(im(2,0) == 0xffff0000);
CHECK(im(2,1) == 0xffff0000);
CHECK(im(2,2) == 0xffff0000);
} // END SECTION
SECTION("test colorize-alpha - two color") {
mapnik::image_rgba8 im(3,3);
mapnik::fill(im,mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("gray"));
mapnik::filter::filter_image(im, "colorize-alpha(green,blue)");
CHECK(im(0,0) == 0xfffd0000);
CHECK(im(0,1) == 0xfffd0000);
CHECK(im(0,2) == 0xfffd0000);
CHECK(im(1,0) == 0xfffd0000);
CHECK(im(1,1) == 0xfffd0000);
CHECK(im(1,2) == 0xfffd0000);
CHECK(im(2,0) == 0xfffd0000);
CHECK(im(2,1) == 0xfffd0000);
CHECK(im(2,2) == 0xfffd0000);
} // END SECTION
SECTION("test colorize-alpha - one color with transparency") {
mapnik::image_rgba8 im(3,3);
mapnik::fill(im,mapnik::color("#0000ffaa"));
mapnik::set_pixel(im, 1, 1, mapnik::color("#aaaaaaaa"));
mapnik::filter::filter_image(im, "colorize-alpha(#0000ff99)");
CHECK(im(0,0) == 0x66660000);
CHECK(im(0,1) == 0x66660000);
CHECK(im(0,2) == 0x66660000);
CHECK(im(1,0) == 0x66660000);
CHECK(im(1,1) == 0x66660000);
CHECK(im(1,2) == 0x66660000);
CHECK(im(2,0) == 0x66660000);
CHECK(im(2,1) == 0x66660000);
CHECK(im(2,2) == 0x66660000);
} // END SECTION
SECTION("test colorize-alpha - two color with transparency") {
mapnik::image_rgba8 im(3,3);
mapnik::fill(im,mapnik::color("#0000ffaa"));
mapnik::set_pixel(im, 1, 1, mapnik::color("#aaaaaaaa"));
mapnik::filter::filter_image(im, "colorize-alpha(#0000ff00,#00ff00ff)");
CHECK(im(0,0) == 0x70264a00);
CHECK(im(0,1) == 0x70264a00);
CHECK(im(0,2) == 0x70264a00);
CHECK(im(1,0) == 0x70264a00);
CHECK(im(1,1) == 0x70264a00);
CHECK(im(1,2) == 0x70264a00);
CHECK(im(2,0) == 0x70264a00);
CHECK(im(2,1) == 0x70264a00);
CHECK(im(2,2) == 0x70264a00);
} // END SECTION
SECTION("test parsing image-filters") {
std::string str = ""; // empty string
std::vector<mapnik::filter::filter_type> filters;
CHECK(parse_image_filters(str, filters));
CHECK(filters.size() == 0);
std::array<std::string,17> expected = {{ "emboss",
"emboss",
"blur",
"gray",
"edge-detect",
"sobel",
"sharpen",
"x-gradient",
"y-gradient",
"invert",
"color-blind-protanope",
"color-blind-deuteranope",
"color-blind-tritanope",
"agg-stack-blur(1,1)",
"agg-stack-blur(1,1)",
"agg-stack-blur(2,2)",
"agg-stack-blur(2,3)"}};
str += "emboss emboss() blur,gray ,edge-detect, sobel , , sharpen,,,x-gradient y-gradientinvert";
str += "color-blind-protanope color-blind-deuteranope color-blind-tritanope agg-stack-blur,agg-stack-blur(),agg-stack-blur(2),agg-stack-blur(2,3)" ;
CHECK(parse_image_filters(str, filters));
CHECK(filters.size() == expected.size());
std::size_t count = 0;
for (auto const& filter : filters)
TEST_CASE("image filter")
{
SECTION("test bad filter input")
{
std::stringstream ss;
ss << filter;
CHECK (expected[count++] == ss.str());
}
}
mapnik::image_rgba8 im(3, 3);
mapnik::fill(im, mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("red"));
SECTION("test colorize-alpha - parsing correct input") {
REQUIRE_THROWS(mapnik::filter::filter_image(im, "foo,asdfasdf()"));
REQUIRE_THROWS(mapnik::filter::filter_image(im, "colorize-alpha("));
REQUIRE_THROWS(mapnik::filter::filter_image(im, "color-to-alpha(blue"));
REQUIRE_THROWS(mapnik::filter::filter_image(im, "color-to-alpha(,blue)"));
REQUIRE_THROWS(mapnik::filter::filter_image(im, "colorize-alpha()"));
std::string s("colorize-alpha(#0000ff 0%, #00ff00 100%)");
std::vector<mapnik::filter::filter_type> f;
REQUIRE(parse_image_filters(s, f));
mapnik::filter::colorize_alpha const & ca = mapnik::util::get<mapnik::filter::colorize_alpha>(f.front());
CHECK(ca.size() == 2);
mapnik::image_rgba8 const& im2 = im;
REQUIRE_THROWS(mapnik::filter::filter_image(im2, "foo"));
CHECKED_IF(ca.size() > 0)
CHECK(im(0, 0) == 0xffff0000);
CHECK(im(0, 1) == 0xffff0000);
CHECK(im(0, 2) == 0xffff0000);
CHECK(im(1, 0) == 0xffff0000);
CHECK(im(1, 1) == 0xff0000ff);
CHECK(im(1, 2) == 0xffff0000);
CHECK(im(2, 0) == 0xffff0000);
CHECK(im(2, 1) == 0xffff0000);
CHECK(im(2, 2) == 0xffff0000);
} // END SECTION
SECTION("test blur")
{
mapnik::filter::color_stop const & s2 = ca[0];
CHECK( s2.color.alpha() == 0xff );
CHECK( s2.color.red() == 0x00 );
CHECK( s2.color.green() == 0x00 );
CHECK( s2.color.blue() == 0xff );
CHECK( s2.offset == 0.0 );
mapnik::image_rgba8 im(3, 3);
mapnik::fill(im, mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("red"));
mapnik::filter::filter_image(im, "blur");
CHECK(im(0, 0) == 0xffc60038);
CHECK(im(0, 1) == 0xffe2001c);
CHECK(im(0, 2) == 0xffc60038);
CHECK(im(1, 0) == 0xffc60038);
CHECK(im(1, 1) == 0xffe2001c);
CHECK(im(1, 2) == 0xffc60038);
CHECK(im(2, 0) == 0xffc60038);
CHECK(im(2, 1) == 0xffe2001c);
CHECK(im(2, 2) == 0xffc60038);
} // END SECTION
SECTION("test blur constant")
{
mapnik::image_rgba8 im_orig(3, 3);
mapnik::fill(im_orig, mapnik::color("blue"));
mapnik::set_pixel(im_orig, 1, 1, mapnik::color("red"));
mapnik::image_rgba8 const& im_new = im_orig;
mapnik::image_rgba8 im = mapnik::filter::filter_image(im_new, "blur");
CHECK(im(0, 0) == 0xffc60038);
CHECK(im(0, 1) == 0xffe2001c);
CHECK(im(0, 2) == 0xffc60038);
CHECK(im(1, 0) == 0xffc60038);
CHECK(im(1, 1) == 0xffe2001c);
CHECK(im(1, 2) == 0xffc60038);
CHECK(im(2, 0) == 0xffc60038);
CHECK(im(2, 1) == 0xffe2001c);
CHECK(im(2, 2) == 0xffc60038);
} // END SECTION
SECTION("test gray")
{
mapnik::image_rgba8 im(3, 3);
mapnik::fill(im, mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("red"));
mapnik::filter::filter_image(im, "gray");
CHECK(im(0, 0) == 0xff1c1c1c);
CHECK(im(0, 1) == 0xff1c1c1c);
CHECK(im(0, 2) == 0xff1c1c1c);
CHECK(im(1, 0) == 0xff1c1c1c);
CHECK(im(1, 1) == 0xff4c4c4c);
CHECK(im(1, 2) == 0xff1c1c1c);
CHECK(im(2, 0) == 0xff1c1c1c);
CHECK(im(2, 1) == 0xff1c1c1c);
CHECK(im(2, 2) == 0xff1c1c1c);
} // END SECTION
SECTION("test agg stack blur")
{
mapnik::image_rgba8 im(3, 3);
mapnik::fill(im, mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("red"));
mapnik::filter::filter_image(im, "agg-stack-blur(1,1)");
CHECK(im(0, 0) == 0xffef000f);
CHECK(im(0, 1) == 0xffdf001f);
CHECK(im(0, 2) == 0xffef000f);
CHECK(im(1, 0) == 0xffdf001f);
CHECK(im(1, 1) == 0xffbf003f);
CHECK(im(1, 2) == 0xffdf001f);
CHECK(im(2, 0) == 0xffef000f);
CHECK(im(2, 1) == 0xffdf001f);
CHECK(im(2, 2) == 0xffef000f);
} // END SECTION
SECTION("test scale-hsla 1")
{
mapnik::image_rgba8 im(3, 3);
mapnik::fill(im, mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("red"));
mapnik::filter::filter_image(im, "scale-hsla(0.0,0.5,0.0,1.0,0.0,0.5,0.0,0.5)");
CHECK(im(0, 0) == 0x80004000);
CHECK(im(0, 1) == 0x80004000);
CHECK(im(0, 2) == 0x80004000);
CHECK(im(1, 0) == 0x80004000);
CHECK(im(1, 1) == 0x80000040);
CHECK(im(1, 2) == 0x80004000);
CHECK(im(2, 0) == 0x80004000);
CHECK(im(2, 1) == 0x80004000);
CHECK(im(2, 2) == 0x80004000);
} // END SECTION
SECTION("test scale-hsla 2")
{
mapnik::image_rgba8 im(3, 3);
mapnik::set_pixel(im, 0, 0, mapnik::color(255, 0, 0));
mapnik::set_pixel(im, 0, 1, mapnik::color(147, 112, 219));
mapnik::set_pixel(im, 0, 2, mapnik::color(128, 128, 128));
mapnik::set_pixel(im, 1, 0, mapnik::color(72, 209, 204));
mapnik::set_pixel(im, 1, 1, mapnik::color(218, 112, 214));
mapnik::set_pixel(im, 1, 2, mapnik::color(30, 144, 255));
mapnik::set_pixel(im, 2, 0, mapnik::color(238, 130, 238));
mapnik::set_pixel(im, 2, 1, mapnik::color(154, 205, 50));
mapnik::set_pixel(im, 2, 2, mapnik::color(160, 82, 45));
// Should not throw on values out of [0, 1]
// https://github.com/mapnik/mapnik/issues/3052
REQUIRE_NOTHROW(mapnik::filter::filter_image(im, "scale-hsla(0.0,1.5,-1.0,1.0,-1.0,2.0,1.0,1.0)"));
CHECK(im(0, 0) == 0xff0000ff);
CHECK(im(0, 1) == 0xffefeff4);
CHECK(im(0, 2) == 0xff818181);
CHECK(im(1, 0) == 0xffb895a5);
CHECK(im(1, 1) == 0xffededf3);
CHECK(im(1, 2) == 0xffd75aff);
CHECK(im(2, 0) == 0xffffffff);
CHECK(im(2, 1) == 0xff649b64);
CHECK(im(2, 2) == 0xff2e343b);
} // END SECTION
SECTION("test emboss")
{
mapnik::image_rgba8 im(3, 3);
mapnik::fill(im, mapnik::color("white"));
mapnik::set_pixel(im, 1, 1, mapnik::color("orange"));
mapnik::filter::filter_image(im, "emboss");
CHECK(im(0, 0) == 0xff004bff);
CHECK(im(0, 1) == 0xff00a5ff);
CHECK(im(0, 2) == 0xff004bff);
CHECK(im(1, 0) == 0xffffffff);
CHECK(im(1, 1) == 0xff00a5ff);
CHECK(im(1, 2) == 0xffffffff);
CHECK(im(2, 0) == 0xffffffff);
CHECK(im(2, 1) == 0xffffffff);
CHECK(im(2, 2) == 0xffffffff);
} // END SECTION
SECTION("test sharpen")
{
mapnik::image_rgba8 im(3, 3);
mapnik::fill(im, mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("gray"));
mapnik::filter::filter_image(im, "sharpen");
CHECK(im(0, 0) == 0xffff0000);
CHECK(im(0, 1) == 0xffff0000);
CHECK(im(0, 2) == 0xffff0000);
CHECK(im(1, 0) == 0xffff0000);
CHECK(im(1, 1) == 0xff00ffff);
CHECK(im(1, 2) == 0xffff0000);
CHECK(im(2, 0) == 0xffff0000);
CHECK(im(2, 1) == 0xffff0000);
CHECK(im(2, 2) == 0xffff0000);
} // END SECTION
SECTION("test edge detect")
{
mapnik::image_rgba8 im(3, 3);
mapnik::fill(im, mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("gray"));
mapnik::filter::filter_image(im, "edge-detect");
CHECK(im(0, 0) == 0xff000000);
CHECK(im(0, 1) == 0xff008080);
CHECK(im(0, 2) == 0xff000000);
CHECK(im(1, 0) == 0xff00ffff);
CHECK(im(1, 1) == 0xffff0000);
CHECK(im(1, 2) == 0xff00ffff);
CHECK(im(2, 0) == 0xff000000);
CHECK(im(2, 1) == 0xff008080);
CHECK(im(2, 2) == 0xff000000);
} // END SECTION
SECTION("test sobel")
{
mapnik::image_rgba8 im(3, 3);
mapnik::fill(im, mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("gray"));
mapnik::filter::filter_image(im, "sobel");
CHECK(im(0, 0) == 0xfffeffff);
CHECK(im(0, 1) == 0xfffeffff);
CHECK(im(0, 2) == 0xfffeffff);
CHECK(im(1, 0) == 0xff000000);
CHECK(im(1, 1) == 0xff000000);
CHECK(im(1, 2) == 0xff000000);
CHECK(im(2, 0) == 0xfffeffff);
CHECK(im(2, 1) == 0xfffeffff);
CHECK(im(2, 2) == 0xfffeffff);
} // END SECTION
SECTION("test x-gradient")
{
mapnik::image_rgba8 im(3, 3);
mapnik::fill(im, mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("gray"));
mapnik::filter::filter_image(im, "x-gradient");
CHECK(im(0, 0) == 0xff808080);
CHECK(im(0, 1) == 0xffbf4040);
CHECK(im(0, 2) == 0xff808080);
CHECK(im(1, 0) == 0xff808080);
CHECK(im(1, 1) == 0xff808080);
CHECK(im(1, 2) == 0xff808080);
CHECK(im(2, 0) == 0xff808080);
CHECK(im(2, 1) == 0xff41c0c0);
CHECK(im(2, 2) == 0xff808080);
} // END SECTION
SECTION("test y-gradient")
{
mapnik::image_rgba8 im(3, 3);
mapnik::fill(im, mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("gray"));
mapnik::filter::filter_image(im, "y-gradient");
CHECK(im(0, 0) == 0xff808080);
CHECK(im(0, 1) == 0xff808080);
CHECK(im(0, 2) == 0xff808080);
CHECK(im(1, 0) == 0xffbf4040);
CHECK(im(1, 1) == 0xff808080);
CHECK(im(1, 2) == 0xff41c0c0);
CHECK(im(2, 0) == 0xff808080);
CHECK(im(2, 1) == 0xff808080);
CHECK(im(2, 2) == 0xff808080);
} // END SECTION
SECTION("test invert")
{
mapnik::image_rgba8 im(3, 3);
mapnik::fill(im, mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("gray"));
mapnik::filter::filter_image(im, "invert");
CHECK(im(0, 0) == 0xff00ffff);
CHECK(im(0, 1) == 0xff00ffff);
CHECK(im(0, 2) == 0xff00ffff);
CHECK(im(1, 0) == 0xff00ffff);
CHECK(im(1, 1) == 0xff7f7f7f);
CHECK(im(1, 2) == 0xff00ffff);
CHECK(im(2, 0) == 0xff00ffff);
CHECK(im(2, 1) == 0xff00ffff);
CHECK(im(2, 2) == 0xff00ffff);
} // END SECTION
SECTION("test colorize-alpha - one color")
{
mapnik::image_rgba8 im(3, 3);
mapnik::fill(im, mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("gray"));
mapnik::filter::filter_image(im, "colorize-alpha(blue)");
CHECK(im(0, 0) == 0xffff0000);
CHECK(im(0, 1) == 0xffff0000);
CHECK(im(0, 2) == 0xffff0000);
CHECK(im(1, 0) == 0xffff0000);
CHECK(im(1, 1) == 0xffff0000);
CHECK(im(1, 2) == 0xffff0000);
CHECK(im(2, 0) == 0xffff0000);
CHECK(im(2, 1) == 0xffff0000);
CHECK(im(2, 2) == 0xffff0000);
} // END SECTION
SECTION("test colorize-alpha - two color")
{
mapnik::image_rgba8 im(3, 3);
mapnik::fill(im, mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("gray"));
mapnik::filter::filter_image(im, "colorize-alpha(green,blue)");
CHECK(im(0, 0) == 0xfffd0000);
CHECK(im(0, 1) == 0xfffd0000);
CHECK(im(0, 2) == 0xfffd0000);
CHECK(im(1, 0) == 0xfffd0000);
CHECK(im(1, 1) == 0xfffd0000);
CHECK(im(1, 2) == 0xfffd0000);
CHECK(im(2, 0) == 0xfffd0000);
CHECK(im(2, 1) == 0xfffd0000);
CHECK(im(2, 2) == 0xfffd0000);
} // END SECTION
SECTION("test colorize-alpha - one color with transparency")
{
mapnik::image_rgba8 im(3, 3);
mapnik::fill(im, mapnik::color("#0000ffaa"));
mapnik::set_pixel(im, 1, 1, mapnik::color("#aaaaaaaa"));
mapnik::filter::filter_image(im, "colorize-alpha(#0000ff99)");
CHECK(im(0, 0) == 0x66660000);
CHECK(im(0, 1) == 0x66660000);
CHECK(im(0, 2) == 0x66660000);
CHECK(im(1, 0) == 0x66660000);
CHECK(im(1, 1) == 0x66660000);
CHECK(im(1, 2) == 0x66660000);
CHECK(im(2, 0) == 0x66660000);
CHECK(im(2, 1) == 0x66660000);
CHECK(im(2, 2) == 0x66660000);
} // END SECTION
SECTION("test colorize-alpha - two color with transparency")
{
mapnik::image_rgba8 im(3, 3);
mapnik::fill(im, mapnik::color("#0000ffaa"));
mapnik::set_pixel(im, 1, 1, mapnik::color("#aaaaaaaa"));
mapnik::filter::filter_image(im, "colorize-alpha(#0000ff00,#00ff00ff)");
CHECK(im(0, 0) == 0x70264a00);
CHECK(im(0, 1) == 0x70264a00);
CHECK(im(0, 2) == 0x70264a00);
CHECK(im(1, 0) == 0x70264a00);
CHECK(im(1, 1) == 0x70264a00);
CHECK(im(1, 2) == 0x70264a00);
CHECK(im(2, 0) == 0x70264a00);
CHECK(im(2, 1) == 0x70264a00);
CHECK(im(2, 2) == 0x70264a00);
} // END SECTION
SECTION("test parsing image-filters")
{
std::string str = ""; // empty string
std::vector<mapnik::filter::filter_type> filters;
CHECK(parse_image_filters(str, filters));
CHECK(filters.size() == 0);
std::array<std::string, 17> expected = {{"emboss",
"emboss",
"blur",
"gray",
"edge-detect",
"sobel",
"sharpen",
"x-gradient",
"y-gradient",
"invert",
"color-blind-protanope",
"color-blind-deuteranope",
"color-blind-tritanope",
"agg-stack-blur(1,1)",
"agg-stack-blur(1,1)",
"agg-stack-blur(2,2)",
"agg-stack-blur(2,3)"}};
str += "emboss emboss() blur,gray ,edge-detect, sobel , , sharpen,,,x-gradient y-gradientinvert";
str += "color-blind-protanope color-blind-deuteranope color-blind-tritanope "
"agg-stack-blur,agg-stack-blur(),agg-stack-blur(2),agg-stack-blur(2,3)";
CHECK(parse_image_filters(str, filters));
CHECK(filters.size() == expected.size());
std::size_t count = 0;
for (auto const& filter : filters)
{
std::stringstream ss;
ss << filter;
CHECK(expected[count++] == ss.str());
}
}
CHECKED_IF(ca.size() > 1)
SECTION("test colorize-alpha - parsing correct input")
{
mapnik::filter::color_stop const & s2 = ca[1];
CHECK( s2.color.alpha() == 0xff );
CHECK( s2.color.red() == 0x00 );
CHECK( s2.color.green() == 0xff );
CHECK( s2.color.blue() == 0x00 );
CHECK( s2.offset == 1.0 );
}
std::string s("colorize-alpha(#0000ff 0%, #00ff00 100%)");
std::vector<mapnik::filter::filter_type> f;
REQUIRE(parse_image_filters(s, f));
mapnik::filter::colorize_alpha const& ca = mapnik::util::get<mapnik::filter::colorize_alpha>(f.front());
CHECK(ca.size() == 2);
} // END SECTION
CHECKED_IF(ca.size() > 0)
{
mapnik::filter::color_stop const& s2 = ca[0];
CHECK(s2.color.alpha() == 0xff);
CHECK(s2.color.red() == 0x00);
CHECK(s2.color.green() == 0x00);
CHECK(s2.color.blue() == 0xff);
CHECK(s2.offset == 0.0);
}
SECTION("test colorize-alpha - parsing incorrect input") {
CHECKED_IF(ca.size() > 1)
{
mapnik::filter::color_stop const& s2 = ca[1];
CHECK(s2.color.alpha() == 0xff);
CHECK(s2.color.red() == 0x00);
CHECK(s2.color.green() == 0xff);
CHECK(s2.color.blue() == 0x00);
CHECK(s2.offset == 1.0);
}
std::string s("colorize-alpha(#0000ff 0%, #00ff00 00 100%)");
std::vector<mapnik::filter::filter_type> f;
CHECK(!parse_image_filters(s, f));
CHECK( f.empty() );
} // END SECTION
} // END SECTION
SECTION("test colorize-alpha - parsing incorrect input")
{
std::string s("colorize-alpha(#0000ff 0%, #00ff00 00 100%)");
std::vector<mapnik::filter::filter_type> f;
CHECK(!parse_image_filters(s, f));
CHECK(f.empty());
SECTION("test color-blind-protanope") {
} // END SECTION
mapnik::image_rgba8 im(2,2);
mapnik::fill(im,mapnik::color("blue"));
mapnik::set_pixel(im, 0, 1, mapnik::color("green"));
mapnik::set_pixel(im, 1, 0, mapnik::color("yellow"));
mapnik::set_pixel(im, 1, 1, mapnik::color("red"));
SECTION("test color-blind-protanope")
{
mapnik::image_rgba8 im(2, 2);
mapnik::fill(im, mapnik::color("blue"));
mapnik::set_pixel(im, 0, 1, mapnik::color("green"));
mapnik::set_pixel(im, 1, 0, mapnik::color("yellow"));
mapnik::set_pixel(im, 1, 1, mapnik::color("red"));
mapnik::filter::filter_image(im, "color-blind-protanope");
mapnik::filter::filter_image(im, "color-blind-protanope");
CHECK(im(0,0) == 0xff9a4a00);
CHECK(im(0,1) == 0xff006e7c);
CHECK(im(1,0) == 0xff00f7ff);
CHECK(im(1,1) == 0xff1d7e8e);
CHECK(im(0, 0) == 0xff9a4a00);
CHECK(im(0, 1) == 0xff006e7c);
CHECK(im(1, 0) == 0xff00f7ff);
CHECK(im(1, 1) == 0xff1d7e8e);
} // END SECTION
} // END SECTION
SECTION("test color-blind-deuteranope") {
SECTION("test color-blind-deuteranope")
{
mapnik::image_rgba8 im(2, 2);
mapnik::fill(im, mapnik::color("blue"));
mapnik::set_pixel(im, 0, 1, mapnik::color("green"));
mapnik::set_pixel(im, 1, 0, mapnik::color("yellow"));
mapnik::set_pixel(im, 1, 1, mapnik::color("red"));
mapnik::image_rgba8 im(2,2);
mapnik::fill(im,mapnik::color("blue"));
mapnik::set_pixel(im, 0, 1, mapnik::color("green"));
mapnik::set_pixel(im, 1, 0, mapnik::color("yellow"));
mapnik::set_pixel(im, 1, 1, mapnik::color("red"));
mapnik::filter::filter_image(im, "color-blind-deuteranope");
mapnik::filter::filter_image(im, "color-blind-deuteranope");
CHECK(im(0, 0) == 0xff824f00);
CHECK(im(0, 1) == 0xff1c688b);
CHECK(im(1, 0) == 0xff27e9ff);
CHECK(im(1, 1) == 0xff0077a0);
CHECK(im(0,0) == 0xff824f00);
CHECK(im(0,1) == 0xff1c688b);
CHECK(im(1,0) == 0xff27e9ff);
CHECK(im(1,1) == 0xff0077a0);
} // END SECTION
} // END SECTION
SECTION("test color-blind-tritanope")
{
mapnik::image_rgba8 im(2, 2);
mapnik::fill(im, mapnik::color("blue"));
mapnik::set_pixel(im, 0, 1, mapnik::color("green"));
mapnik::set_pixel(im, 1, 0, mapnik::color("yellow"));
mapnik::set_pixel(im, 1, 1, mapnik::color("red"));
SECTION("test color-blind-tritanope") {
mapnik::filter::filter_image(im, "color-blind-tritanope");
mapnik::image_rgba8 im(2,2);
mapnik::fill(im,mapnik::color("blue"));
mapnik::set_pixel(im, 0, 1, mapnik::color("green"));
mapnik::set_pixel(im, 1, 0, mapnik::color("yellow"));
mapnik::set_pixel(im, 1, 1, mapnik::color("red"));
CHECK(im(0, 0) == 0xff595500);
CHECK(im(0, 1) == 0xff80763a);
CHECK(im(1, 0) == 0xfffeecff);
CHECK(im(1, 1) == 0xff0017fd);
mapnik::filter::filter_image(im, "color-blind-tritanope");
CHECK(im(0,0) == 0xff595500);
CHECK(im(0,1) == 0xff80763a);
CHECK(im(1,0) == 0xfffeecff);
CHECK(im(1,1) == 0xff0017fd);
} // END SECTION
} // END SECTION
} // END TEST CASE

View file

@ -21,12 +21,13 @@ MAPNIK_DISABLE_WARNING_PUSH
MAPNIK_DISABLE_WARNING_POP
#include <mapnik/util/mapped_memory_file.hpp>
inline void make_directory(std::string const& dir) {
inline void make_directory(std::string const& dir)
{
boost::filesystem::create_directories(dir);
}
namespace {
template <typename T>
template<typename T>
void check_tiny_png_image_quantising(T const& im)
{
std::ostringstream ss(std::ios::binary);
@ -43,194 +44,193 @@ void check_tiny_png_image_quantising(T const& im)
{
for (std::size_t j = 0; j < h; ++j)
{
REQUIRE(im2(i,j) == im(i,j));
REQUIRE(im2(i, j) == im(i, j));
}
}
}
}
} // namespace
TEST_CASE("image io") {
SECTION("readers") {
std::string should_throw;
boost::optional<std::string> type;
try
TEST_CASE("image io")
{
SECTION("readers")
{
mapnik::image_rgba8 im_og;
auto im_size = mapnik::image_rgba8::pixel_size * im_og.width() * im_og.height();
mapnik::detail::buffer buf(im_og.bytes(), im_size);
mapnik::image_rgba8 im2(im_og.width(), im_og.height(), buf.data());
CHECK( im2.bytes() == im_og.bytes() );
#if defined(HAVE_JPEG)
should_throw = "./test/data/images/blank.jpg";
REQUIRE( mapnik::util::exists( should_throw ) );
type = mapnik::type_from_filename(should_throw);
REQUIRE( type );
REQUIRE_THROWS(mapnik::get_image_reader(should_throw,*type));
// actually a png so jpeg reader should throw
should_throw = "./test/data/images/landusepattern.jpg";
REQUIRE( mapnik::util::exists( should_throw ) );
type = mapnik::type_from_filename(should_throw);
REQUIRE( type );
std::string should_throw;
boost::optional<std::string> type;
try
{
std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(should_throw,*type));
REQUIRE(false);
}
catch (std::exception const& ex)
{
REQUIRE( std::string(ex.what()) == std::string("JPEG Reader: libjpeg could not read image: Not a JPEG file: starts with 0x89 0x50") );
}
mapnik::image_rgba8 im_og;
auto im_size = mapnik::image_rgba8::pixel_size * im_og.width() * im_og.height();
mapnik::detail::buffer buf(im_og.bytes(), im_size);
mapnik::image_rgba8 im2(im_og.width(), im_og.height(), buf.data());
CHECK(im2.bytes() == im_og.bytes());
#if defined(HAVE_JPEG)
should_throw = "./test/data/images/blank.jpg";
REQUIRE(mapnik::util::exists(should_throw));
type = mapnik::type_from_filename(should_throw);
REQUIRE(type);
REQUIRE_THROWS(mapnik::get_image_reader(should_throw, *type));
// actually a png so jpeg reader should throw
should_throw = "./test/data/images/landusepattern.jpg";
REQUIRE(mapnik::util::exists(should_throw));
type = mapnik::type_from_filename(should_throw);
REQUIRE(type);
try
{
std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(should_throw, *type));
REQUIRE(false);
} catch (std::exception const& ex)
{
REQUIRE(
std::string(ex.what()) ==
std::string("JPEG Reader: libjpeg could not read image: Not a JPEG file: starts with 0x89 0x50"));
}
#endif
REQUIRE_THROWS(mapnik::image_rgba8(-10,-10)); // should throw rather than overflow
REQUIRE_THROWS(mapnik::image_rgba8(-10, -10)); // should throw rather than overflow
#if defined(HAVE_CAIRO)
mapnik::cairo_surface_ptr image_surface(
cairo_image_surface_create(CAIRO_FORMAT_ARGB32,256,257),
mapnik::cairo_surface_closer());
mapnik::image_rgba8 im_data(cairo_image_surface_get_width(&*image_surface), cairo_image_surface_get_height(&*image_surface));
im_data.set(1);
REQUIRE( (unsigned)im_data(0,0) == unsigned(1) );
// Should set back to fully transparent
mapnik::cairo_image_to_rgba8(im_data, image_surface);
REQUIRE( (unsigned)im_data(0,0) == unsigned(0) );
mapnik::cairo_surface_ptr image_surface(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 256, 257),
mapnik::cairo_surface_closer());
mapnik::image_rgba8 im_data(cairo_image_surface_get_width(&*image_surface),
cairo_image_surface_get_height(&*image_surface));
im_data.set(1);
REQUIRE((unsigned)im_data(0, 0) == unsigned(1));
// Should set back to fully transparent
mapnik::cairo_image_to_rgba8(im_data, image_surface);
REQUIRE((unsigned)im_data(0, 0) == unsigned(0));
#endif
#if defined(HAVE_PNG)
should_throw = "./test/data/images/blank.png";
REQUIRE( mapnik::util::exists( should_throw ) );
type = mapnik::type_from_filename(should_throw);
REQUIRE( type );
REQUIRE_THROWS(mapnik::get_image_reader(should_throw,*type));
should_throw = "./test/data/images/blank.png";
REQUIRE(mapnik::util::exists(should_throw));
type = mapnik::type_from_filename(should_throw);
REQUIRE(type);
REQUIRE_THROWS(mapnik::get_image_reader(should_throw, *type));
should_throw = "./test/data/images/xcode-CgBI.png";
REQUIRE( mapnik::util::exists( should_throw ) );
type = mapnik::type_from_filename(should_throw);
REQUIRE( type );
REQUIRE_THROWS(mapnik::get_image_reader(should_throw,*type));
should_throw = "./test/data/images/xcode-CgBI.png";
REQUIRE(mapnik::util::exists(should_throw));
type = mapnik::type_from_filename(should_throw);
REQUIRE(type);
REQUIRE_THROWS(mapnik::get_image_reader(should_throw, *type));
#endif
#if defined(HAVE_TIFF)
should_throw = "./test/data/images/blank.tiff";
REQUIRE( mapnik::util::exists( should_throw ) );
type = mapnik::type_from_filename(should_throw);
REQUIRE( type );
REQUIRE_THROWS(mapnik::get_image_reader(should_throw,*type));
should_throw = "./test/data/images/blank.tiff";
REQUIRE(mapnik::util::exists(should_throw));
type = mapnik::type_from_filename(should_throw);
REQUIRE(type);
REQUIRE_THROWS(mapnik::get_image_reader(should_throw, *type));
#endif
#if defined(HAVE_WEBP)
should_throw = "./test/data/images/blank.webp";
REQUIRE( mapnik::util::exists( should_throw ) );
type = mapnik::type_from_filename(should_throw);
REQUIRE( type );
REQUIRE_THROWS(mapnik::get_image_reader(should_throw,*type));
should_throw = "./test/data/images/blank.webp";
REQUIRE(mapnik::util::exists(should_throw));
type = mapnik::type_from_filename(should_throw);
REQUIRE(type);
REQUIRE_THROWS(mapnik::get_image_reader(should_throw, *type));
#endif
}
catch (std::exception const & ex)
{
std::clog << ex.what() << "\n";
REQUIRE(false);
}
} // END SECTION
SECTION("writers options")
{
#if defined(HAVE_JPEG)
// test we can parse both jpegXX and quality=XX options
REQUIRE_THROWS(mapnik::detail::parse_jpeg_quality("jpegXX"));
REQUIRE_THROWS(mapnik::detail::parse_jpeg_quality("jpeg:quality=XX"));
int q0 = mapnik::detail::parse_jpeg_quality("jpeg50");
int q1 = mapnik::detail::parse_jpeg_quality("jpeg:quality=50");
REQUIRE(q0 == q1);
#endif
} // END SECTION
SECTION("image_util : save_to_file/save_to_stream/save_to_string")
{
mapnik::image_rgba8 im(256,256);
std::string named_color = "lightblue";
mapnik::fill(im, mapnik::color(named_color).rgba());
////////////////////////////////////////////////////
std::vector<std::tuple<std::string, std::string> > supported_types;
#if defined(HAVE_PNG)
supported_types.push_back(std::make_tuple("png","png"));
supported_types.push_back(std::make_tuple("png","png24"));
supported_types.push_back(std::make_tuple("png","png32"));
supported_types.push_back(std::make_tuple("png","png8"));
supported_types.push_back(std::make_tuple("png","png256"));
#endif
#if defined(HAVE_JPEG)
supported_types.push_back(std::make_tuple("jpeg","jpeg"));
supported_types.push_back(std::make_tuple("jpeg","jpeg80"));
supported_types.push_back(std::make_tuple("jpeg","jpeg90"));
#endif
#if defined(HAVE_TIFF)
supported_types.push_back(std::make_tuple("tiff","tiff"));
#endif
#if defined(HAVE_WEBP)
supported_types.push_back(std::make_tuple("webp","webp"));
#endif
std::string directory_name("/tmp/mapnik-tests/");
make_directory(directory_name);
REQUIRE(mapnik::util::exists(directory_name));
for (auto const& info : supported_types)
{
std::string extension;
std::string format;
std::tie(extension, format) = info;
std::string filename = (boost::format(directory_name + "mapnik-%1%.%2%") % named_color % extension).str();
mapnik::save_to_file(im, filename);
std::string str = mapnik::save_to_string(im, format);
std::ostringstream ss;
mapnik::save_to_stream(im, ss, format);
CHECK(str.length() == ss.str().length());
// wrap reader in scope to ensure the file handle is
// released before we try to remove the file
} catch (std::exception const& ex)
{
std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(filename, extension));
unsigned w = reader->width();
unsigned h = reader->height();
auto im2 = reader->read(0, 0, w, h);
CHECK(im2.size() == im.size());
if (extension == "png" || extension == "tiff")
{
CHECK(0 == std::memcmp(im2.bytes(), im.bytes(), im.width() * im.height()));
}
std::clog << ex.what() << "\n";
REQUIRE(false);
}
mapnik::util::mapped_memory_file::deleteFile(filename);
}
}
SECTION("Quantising small (less than 3 pixel images preserve original colours")
{
#if defined(HAVE_PNG)
{ // 1x1
mapnik::image_rgba8 im(1,1); // 1 pixel
im(0,0) = mapnik::color("green").rgba();
check_tiny_png_image_quantising(im);
}
{ // 1x2
mapnik::image_rgba8 im(1,2); // 2 pixels
mapnik::fill(im, mapnik::color("red").rgba());
im(0,0) = mapnik::color("green").rgba();
check_tiny_png_image_quantising(im);
}
{ // 2x1
mapnik::image_rgba8 im(2,1); // 2 pixels
mapnik::fill(im, mapnik::color("red").rgba());
im(0,0) = mapnik::color("green").rgba();
check_tiny_png_image_quantising(im);
}
} // END SECTION
SECTION("writers options")
{
#if defined(HAVE_JPEG)
// test we can parse both jpegXX and quality=XX options
REQUIRE_THROWS(mapnik::detail::parse_jpeg_quality("jpegXX"));
REQUIRE_THROWS(mapnik::detail::parse_jpeg_quality("jpeg:quality=XX"));
int q0 = mapnik::detail::parse_jpeg_quality("jpeg50");
int q1 = mapnik::detail::parse_jpeg_quality("jpeg:quality=50");
REQUIRE(q0 == q1);
#endif
} // END SECTION
} // END SECTION
SECTION("image_util : save_to_file/save_to_stream/save_to_string")
{
mapnik::image_rgba8 im(256, 256);
std::string named_color = "lightblue";
mapnik::fill(im, mapnik::color(named_color).rgba());
////////////////////////////////////////////////////
std::vector<std::tuple<std::string, std::string>> supported_types;
#if defined(HAVE_PNG)
supported_types.push_back(std::make_tuple("png", "png"));
supported_types.push_back(std::make_tuple("png", "png24"));
supported_types.push_back(std::make_tuple("png", "png32"));
supported_types.push_back(std::make_tuple("png", "png8"));
supported_types.push_back(std::make_tuple("png", "png256"));
#endif
#if defined(HAVE_JPEG)
supported_types.push_back(std::make_tuple("jpeg", "jpeg"));
supported_types.push_back(std::make_tuple("jpeg", "jpeg80"));
supported_types.push_back(std::make_tuple("jpeg", "jpeg90"));
#endif
#if defined(HAVE_TIFF)
supported_types.push_back(std::make_tuple("tiff", "tiff"));
#endif
#if defined(HAVE_WEBP)
supported_types.push_back(std::make_tuple("webp", "webp"));
#endif
std::string directory_name("/tmp/mapnik-tests/");
make_directory(directory_name);
REQUIRE(mapnik::util::exists(directory_name));
for (auto const& info : supported_types)
{
std::string extension;
std::string format;
std::tie(extension, format) = info;
std::string filename = (boost::format(directory_name + "mapnik-%1%.%2%") % named_color % extension).str();
mapnik::save_to_file(im, filename);
std::string str = mapnik::save_to_string(im, format);
std::ostringstream ss;
mapnik::save_to_stream(im, ss, format);
CHECK(str.length() == ss.str().length());
// wrap reader in scope to ensure the file handle is
// released before we try to remove the file
{
std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(filename, extension));
unsigned w = reader->width();
unsigned h = reader->height();
auto im2 = reader->read(0, 0, w, h);
CHECK(im2.size() == im.size());
if (extension == "png" || extension == "tiff")
{
CHECK(0 == std::memcmp(im2.bytes(), im.bytes(), im.width() * im.height()));
}
}
mapnik::util::mapped_memory_file::deleteFile(filename);
}
}
SECTION("Quantising small (less than 3 pixel images preserve original colours")
{
#if defined(HAVE_PNG)
{ // 1x1
mapnik::image_rgba8 im(1, 1); // 1 pixel
im(0, 0) = mapnik::color("green").rgba();
check_tiny_png_image_quantising(im);
}
{ // 1x2
mapnik::image_rgba8 im(1, 2); // 2 pixels
mapnik::fill(im, mapnik::color("red").rgba());
im(0, 0) = mapnik::color("green").rgba();
check_tiny_png_image_quantising(im);
}
{ // 2x1
mapnik::image_rgba8 im(2, 1); // 2 pixels
mapnik::fill(im, mapnik::color("red").rgba());
im(0, 0) = mapnik::color("green").rgba();
check_tiny_png_image_quantising(im);
}
#endif
} // END SECTION
} // END TEST_CASE

View file

@ -7,89 +7,88 @@
#include <mapnik/color.hpp>
#include <mapnik/image_util.hpp>
TEST_CASE("image is_solid")
{
SECTION("test rgba8")
{
mapnik::image_rgba8 im(4, 4);
mapnik::image_any im_any(mapnik::image_rgba8(4, 4));
TEST_CASE("image is_solid") {
CHECK(mapnik::is_solid(im));
CHECK(mapnik::is_solid(im_any));
SECTION("test rgba8") {
mapnik::image_view_rgba8 im_view(0, 0, 4, 4, im);
mapnik::image_view_any im_view_any(mapnik::image_view_rgba8(0, 0, 4, 4, im));
mapnik::image_rgba8 im(4,4);
mapnik::image_any im_any(mapnik::image_rgba8(4,4));
CHECK(mapnik::is_solid(im_view));
CHECK(mapnik::is_solid(im_view_any));
CHECK(mapnik::is_solid(im));
CHECK(mapnik::is_solid(im_any));
mapnik::color c1("green");
mapnik::color c2("blue");
mapnik::fill(im, c1);
mapnik::fill(im_any, c1);
mapnik::image_view_rgba8 im_view(0,0,4,4,im);
mapnik::image_view_any im_view_any(mapnik::image_view_rgba8(0,0,4,4,im));
CHECK(mapnik::is_solid(im));
CHECK(mapnik::is_solid(im_any));
CHECK(mapnik::is_solid(im_view));
CHECK(mapnik::is_solid(im_view_any));
CHECK(mapnik::is_solid(im_view));
CHECK(mapnik::is_solid(im_view_any));
mapnik::set_pixel(im, 0, 0, c2);
mapnik::set_pixel(im_any, 0, 0, c2);
mapnik::color c1("green");
mapnik::color c2("blue");
mapnik::fill(im, c1);
mapnik::fill(im_any, c1);
CHECK_FALSE(mapnik::is_solid(im));
CHECK_FALSE(mapnik::is_solid(im_any));
CHECK_FALSE(mapnik::is_solid(im_view));
CHECK_FALSE(mapnik::is_solid(im_view_any));
CHECK(mapnik::is_solid(im));
CHECK(mapnik::is_solid(im_any));
CHECK(mapnik::is_solid(im_view));
CHECK(mapnik::is_solid(im_view_any));
} // END SECTION
mapnik::set_pixel(im, 0, 0, c2);
mapnik::set_pixel(im_any, 0, 0, c2);
SECTION("test gray8")
{
mapnik::image_gray8 im(4, 4);
mapnik::image_any im_any(mapnik::image_gray8(4, 4));
CHECK_FALSE(mapnik::is_solid(im));
CHECK_FALSE(mapnik::is_solid(im_any));
CHECK_FALSE(mapnik::is_solid(im_view));
CHECK_FALSE(mapnik::is_solid(im_view_any));
CHECK(mapnik::is_solid(im));
CHECK(mapnik::is_solid(im_any));
} // END SECTION
mapnik::image_view_gray8 im_view(0, 0, 4, 4, im);
mapnik::image_view_any im_view_any(mapnik::image_view_gray8(0, 0, 4, 4, im));
SECTION("test gray8") {
CHECK(mapnik::is_solid(im_view));
CHECK(mapnik::is_solid(im_view_any));
mapnik::image_gray8 im(4,4);
mapnik::image_any im_any(mapnik::image_gray8(4,4));
mapnik::fill(im, 1);
mapnik::fill(im_any, 1);
CHECK(mapnik::is_solid(im));
CHECK(mapnik::is_solid(im_any));
CHECK(mapnik::is_solid(im));
CHECK(mapnik::is_solid(im_any));
CHECK(mapnik::is_solid(im_view));
CHECK(mapnik::is_solid(im_view_any));
mapnik::image_view_gray8 im_view(0,0,4,4,im);
mapnik::image_view_any im_view_any(mapnik::image_view_gray8(0,0,4,4,im));
mapnik::set_pixel(im, 0, 0, 2);
mapnik::set_pixel(im_any, 0, 0, 2);
CHECK(mapnik::is_solid(im_view));
CHECK(mapnik::is_solid(im_view_any));
CHECK_FALSE(mapnik::is_solid(im));
CHECK_FALSE(mapnik::is_solid(im_any));
CHECK_FALSE(mapnik::is_solid(im_view));
CHECK_FALSE(mapnik::is_solid(im_view_any));
mapnik::fill(im, 1);
mapnik::fill(im_any, 1);
} // END SECTION
CHECK(mapnik::is_solid(im));
CHECK(mapnik::is_solid(im_any));
CHECK(mapnik::is_solid(im_view));
CHECK(mapnik::is_solid(im_view_any));
SECTION("test image null")
{
mapnik::image_null im;
mapnik::image_any im_any;
mapnik::set_pixel(im, 0, 0, 2);
mapnik::set_pixel(im_any, 0, 0, 2);
CHECK(mapnik::is_solid(im));
CHECK(mapnik::is_solid(im_any));
CHECK_FALSE(mapnik::is_solid(im));
CHECK_FALSE(mapnik::is_solid(im_any));
CHECK_FALSE(mapnik::is_solid(im_view));
CHECK_FALSE(mapnik::is_solid(im_view_any));
mapnik::image_view_null im_view;
mapnik::image_view_any im_view_any;
} // END SECTION
CHECK(mapnik::is_solid(im_view));
CHECK(mapnik::is_solid(im_view_any));
SECTION("test image null") {
mapnik::image_null im;
mapnik::image_any im_any;
CHECK(mapnik::is_solid(im));
CHECK(mapnik::is_solid(im_any));
mapnik::image_view_null im_view;
mapnik::image_view_any im_view_any;
CHECK(mapnik::is_solid(im_view));
CHECK(mapnik::is_solid(im_view_any));
} // END SECTION
} // END SECTION
} // END TEST CASE

View file

@ -11,63 +11,61 @@
#include <mapnik/expression.hpp>
#include <mapnik/util/fs.hpp>
TEST_CASE("image") {
SECTION("painting") {
using namespace mapnik;
try
TEST_CASE("image")
{
SECTION("painting")
{
std::string csv_plugin("./plugins/input/csv.input");
if (mapnik::util::exists(csv_plugin))
using namespace mapnik;
try
{
Map m(256, 256);
feature_type_style lines_style;
std::string csv_plugin("./plugins/input/csv.input");
if (mapnik::util::exists(csv_plugin))
{
rule r;
line_symbolizer line_sym;
r.append(std::move(line_sym));
lines_style.add_rule(std::move(r));
Map m(256, 256);
feature_type_style lines_style;
{
rule r;
line_symbolizer line_sym;
r.append(std::move(line_sym));
lines_style.add_rule(std::move(r));
}
m.insert_style("lines", std::move(lines_style));
feature_type_style markers_style;
{
rule r;
r.set_filter(parse_expression("False"));
markers_symbolizer mark_sym;
r.append(std::move(mark_sym));
markers_style.add_rule(std::move(r));
}
m.insert_style("markers", std::move(markers_style));
parameters p;
p["type"] = "csv";
p["separator"] = "|";
p["inline"] = "wkt\nLINESTRING(-10 0, 0 20, 10 0, 15 5)";
layer lyr("layer");
lyr.set_datasource(datasource_cache::instance().create(p));
lyr.add_style("lines");
lyr.add_style("markers");
m.add_layer(lyr);
m.zoom_all();
image_rgba8 image(m.width(), m.height());
agg_renderer<image_rgba8> ren(m, image);
ren.apply();
REQUIRE(image.painted() == true);
}
m.insert_style("lines", std::move(lines_style));
feature_type_style markers_style;
{
rule r;
r.set_filter(parse_expression("False"));
markers_symbolizer mark_sym;
r.append(std::move(mark_sym));
markers_style.add_rule(std::move(r));
}
m.insert_style("markers", std::move(markers_style));
parameters p;
p["type"] = "csv";
p["separator"] = "|";
p["inline"] = "wkt\nLINESTRING(-10 0, 0 20, 10 0, 15 5)";
layer lyr("layer");
lyr.set_datasource(datasource_cache::instance().create(p));
lyr.add_style("lines");
lyr.add_style("markers");
m.add_layer(lyr);
m.zoom_all();
image_rgba8 image(m.width(), m.height());
agg_renderer<image_rgba8> ren(m, image);
ren.apply();
REQUIRE(image.painted() == true);
} catch (std::exception const& ex)
{
std::clog << ex.what() << std::endl;
REQUIRE(false);
}
}
catch (std::exception const & ex)
{
std::clog << ex.what() << std::endl;
REQUIRE(false);
}
}
}

View file

@ -6,142 +6,142 @@
#include <mapnik/color.hpp>
#include <mapnik/image_util.hpp>
TEST_CASE("image premultiply") {
TEST_CASE("image premultiply")
{
SECTION("test rgba8")
{
mapnik::image_rgba8 im(4, 4);
mapnik::image_rgba8 im2(4, 4, true, true); // Initialize as already premultiplied
mapnik::image_any im_any(mapnik::image_rgba8(4, 4));
mapnik::image_any im2_any(mapnik::image_rgba8(4, 4, true, true));
SECTION("test rgba8") {
// First test that the default state is correct for each
CHECK_FALSE(im.get_premultiplied());
CHECK_FALSE(im_any.get_premultiplied());
CHECK(im2.get_premultiplied());
CHECK(im2_any.get_premultiplied());
mapnik::image_rgba8 im(4,4);
mapnik::image_rgba8 im2(4,4,true,true); // Initialize as already premultiplied
mapnik::image_any im_any(mapnik::image_rgba8(4,4));
mapnik::image_any im2_any(mapnik::image_rgba8(4,4,true,true));
// Set the image to premultiplied
im.set_premultiplied(true);
CHECK(im.get_premultiplied());
// Set back to not premultiplied
im.set_premultiplied(false);
CHECK_FALSE(im.get_premultiplied());
// First test that the default state is correct for each
CHECK_FALSE(im.get_premultiplied());
CHECK_FALSE(im_any.get_premultiplied());
CHECK(im2.get_premultiplied());
CHECK(im2_any.get_premultiplied());
mapnik::set_premultiplied_alpha(im, true);
CHECK(im.get_premultiplied());
mapnik::set_premultiplied_alpha(im, false);
CHECK_FALSE(im.get_premultiplied());
// Set the image to premultiplied
im.set_premultiplied(true);
CHECK(im.get_premultiplied());
// Set back to not premultiplied
im.set_premultiplied(false);
CHECK_FALSE(im.get_premultiplied());
// Fill the images with meaningfull values
mapnik::color c1(57, 70, 128, 128); // This color is not premultiplied
mapnik::color c2(57, 70, 128, 128, true); // This color is premultiplied
mapnik::fill(im, c2); // Because c2 is premultiplied it will make the image premultiplied
mapnik::fill(im_any, c2); // Because c2 is premultiplied it will make the image premultiplied
mapnik::fill(im2, c1); // Because c1 is not premultiplied it will make the image not premultiplied
mapnik::fill(im2_any, c1); // Because c1 is not premultiplied it will make the image not premultiplied
mapnik::set_premultiplied_alpha(im, true);
CHECK(im.get_premultiplied());
mapnik::set_premultiplied_alpha(im, false);
CHECK_FALSE(im.get_premultiplied());
// Demultipled via image_util
CHECK(mapnik::demultiply_alpha(im)); // Should return true as was premultiplied
CHECK(mapnik::demultiply_alpha(im_any)); // Should return true as was premultiplied
CHECK_FALSE(mapnik::demultiply_alpha(im2)); // Should return false as was demultiplied
CHECK_FALSE(mapnik::demultiply_alpha(im2_any)); // Should return false as was demultiplied
// Fill the images with meaningfull values
mapnik::color c1(57,70,128,128); // This color is not premultiplied
mapnik::color c2(57,70,128,128, true); // This color is premultiplied
mapnik::fill(im, c2); // Because c2 is premultiplied it will make the image premultiplied
mapnik::fill(im_any, c2); // Because c2 is premultiplied it will make the image premultiplied
mapnik::fill(im2, c1); // Because c1 is not premultiplied it will make the image not premultiplied
mapnik::fill(im2_any, c1); // Because c1 is not premultiplied it will make the image not premultiplied
mapnik::color out;
// This will be higher because it became demultiplied!
out = mapnik::get_pixel<mapnik::color>(im, 0, 0);
CHECK(static_cast<int>(out.red()) == 113);
CHECK(static_cast<int>(out.green()) == 139);
CHECK(static_cast<int>(out.blue()) == 255);
CHECK(static_cast<int>(out.alpha()) == 128);
out = mapnik::get_pixel<mapnik::color>(im_any, 0, 0);
CHECK(static_cast<int>(out.red()) == 113);
CHECK(static_cast<int>(out.green()) == 139);
CHECK(static_cast<int>(out.blue()) == 255);
CHECK(static_cast<int>(out.alpha()) == 128);
// This will be the same because it was already demultiplied
out = mapnik::get_pixel<mapnik::color>(im2, 0, 0);
CHECK(static_cast<int>(out.red()) == 57);
CHECK(static_cast<int>(out.green()) == 70);
CHECK(static_cast<int>(out.blue()) == 128);
CHECK(static_cast<int>(out.alpha()) == 128);
out = mapnik::get_pixel<mapnik::color>(im2_any, 0, 0);
CHECK(static_cast<int>(out.red()) == 57);
CHECK(static_cast<int>(out.green()) == 70);
CHECK(static_cast<int>(out.blue()) == 128);
CHECK(static_cast<int>(out.alpha()) == 128);
// Demultipled via image_util
CHECK(mapnik::demultiply_alpha(im)); // Should return true as was premultiplied
CHECK(mapnik::demultiply_alpha(im_any)); // Should return true as was premultiplied
CHECK_FALSE(mapnik::demultiply_alpha(im2)); // Should return false as was demultiplied
CHECK_FALSE(mapnik::demultiply_alpha(im2_any)); // Should return false as was demultiplied
// Set back to im2s to "premultiplied" with out changing underlying values
mapnik::set_premultiplied_alpha(im2, true);
mapnik::set_premultiplied_alpha(im2_any, true);
mapnik::color out;
// This will be higher because it became demultiplied!
out = mapnik::get_pixel<mapnik::color>(im, 0, 0);
CHECK(static_cast<int>(out.red()) == 113);
CHECK(static_cast<int>(out.green()) == 139);
CHECK(static_cast<int>(out.blue()) == 255);
CHECK(static_cast<int>(out.alpha()) == 128);
out = mapnik::get_pixel<mapnik::color>(im_any, 0, 0);
CHECK(static_cast<int>(out.red()) == 113);
CHECK(static_cast<int>(out.green()) == 139);
CHECK(static_cast<int>(out.blue()) == 255);
CHECK(static_cast<int>(out.alpha()) == 128);
// This will be the same because it was already demultiplied
out = mapnik::get_pixel<mapnik::color>(im2, 0, 0);
CHECK(static_cast<int>(out.red()) == 57);
CHECK(static_cast<int>(out.green()) == 70);
CHECK(static_cast<int>(out.blue()) == 128);
CHECK(static_cast<int>(out.alpha()) == 128);
out = mapnik::get_pixel<mapnik::color>(im2_any, 0, 0);
CHECK(static_cast<int>(out.red()) == 57);
CHECK(static_cast<int>(out.green()) == 70);
CHECK(static_cast<int>(out.blue()) == 128);
CHECK(static_cast<int>(out.alpha()) == 128);
// Demultipled via image_util
CHECK(mapnik::premultiply_alpha(im)); // Should return true as was demultiplied
CHECK(mapnik::premultiply_alpha(im_any)); // Should return true as was demultiplied
CHECK_FALSE(mapnik::premultiply_alpha(im2)); // Should return false as was premultiplied
CHECK_FALSE(mapnik::premultiply_alpha(im2_any)); // Should return false as was premultiplied
// Set back to im2s to "premultiplied" with out changing underlying values
mapnik::set_premultiplied_alpha(im2, true);
mapnik::set_premultiplied_alpha(im2_any, true);
// This will be the same because it was already demultiplied
out = mapnik::get_pixel<mapnik::color>(im, 0, 0);
CHECK(static_cast<int>(out.red()) == 57);
CHECK(static_cast<int>(out.green()) == 70);
CHECK(static_cast<int>(out.blue()) == 128);
CHECK(static_cast<int>(out.alpha()) == 128);
out = mapnik::get_pixel<mapnik::color>(im_any, 0, 0);
CHECK(static_cast<int>(out.red()) == 57);
CHECK(static_cast<int>(out.green()) == 70);
CHECK(static_cast<int>(out.blue()) == 128);
CHECK(static_cast<int>(out.alpha()) == 128);
// This will be the same because it was already demultiplied
out = mapnik::get_pixel<mapnik::color>(im2, 0, 0);
CHECK(static_cast<int>(out.red()) == 57);
CHECK(static_cast<int>(out.green()) == 70);
CHECK(static_cast<int>(out.blue()) == 128);
CHECK(static_cast<int>(out.alpha()) == 128);
out = mapnik::get_pixel<mapnik::color>(im2_any, 0, 0);
CHECK(static_cast<int>(out.red()) == 57);
CHECK(static_cast<int>(out.green()) == 70);
CHECK(static_cast<int>(out.blue()) == 128);
CHECK(static_cast<int>(out.alpha()) == 128);
// Demultipled via image_util
CHECK(mapnik::premultiply_alpha(im)); // Should return true as was demultiplied
CHECK(mapnik::premultiply_alpha(im_any)); // Should return true as was demultiplied
CHECK_FALSE(mapnik::premultiply_alpha(im2)); // Should return false as was premultiplied
CHECK_FALSE(mapnik::premultiply_alpha(im2_any)); // Should return false as was premultiplied
} // END SECTION
// This will be the same because it was already demultiplied
out = mapnik::get_pixel<mapnik::color>(im, 0, 0);
CHECK(static_cast<int>(out.red()) == 57);
CHECK(static_cast<int>(out.green()) == 70);
CHECK(static_cast<int>(out.blue()) == 128);
CHECK(static_cast<int>(out.alpha()) == 128);
out = mapnik::get_pixel<mapnik::color>(im_any, 0, 0);
CHECK(static_cast<int>(out.red()) == 57);
CHECK(static_cast<int>(out.green()) == 70);
CHECK(static_cast<int>(out.blue()) == 128);
CHECK(static_cast<int>(out.alpha()) == 128);
// This will be the same because it was already demultiplied
out = mapnik::get_pixel<mapnik::color>(im2, 0, 0);
CHECK(static_cast<int>(out.red()) == 57);
CHECK(static_cast<int>(out.green()) == 70);
CHECK(static_cast<int>(out.blue()) == 128);
CHECK(static_cast<int>(out.alpha()) == 128);
out = mapnik::get_pixel<mapnik::color>(im2_any, 0, 0);
CHECK(static_cast<int>(out.red()) == 57);
CHECK(static_cast<int>(out.green()) == 70);
CHECK(static_cast<int>(out.blue()) == 128);
CHECK(static_cast<int>(out.alpha()) == 128);
SECTION("test gray8")
{
mapnik::image_gray8 im(4, 4);
mapnik::image_gray8 im2(4, 4, true, true); // Initialize as already premultiplied
mapnik::image_any im_any(mapnik::image_gray8(4, 4));
mapnik::image_any im2_any(mapnik::image_gray8(4, 4, true, true));
} // END SECTION
// First test that the default state is correct for each
CHECK_FALSE(im.get_premultiplied());
CHECK_FALSE(im_any.get_premultiplied());
CHECK(im2.get_premultiplied());
CHECK(im2_any.get_premultiplied());
SECTION("test gray8") {
// Set the image to premultiplied
im.set_premultiplied(true);
CHECK(im.get_premultiplied());
// Set back to not premultiplied
im.set_premultiplied(false);
CHECK_FALSE(im.get_premultiplied());
mapnik::image_gray8 im(4,4);
mapnik::image_gray8 im2(4,4,true,true); // Initialize as already premultiplied
mapnik::image_any im_any(mapnik::image_gray8(4,4));
mapnik::image_any im2_any(mapnik::image_gray8(4,4,true,true));
mapnik::set_premultiplied_alpha(im, true);
CHECK(im.get_premultiplied());
mapnik::set_premultiplied_alpha(im, false);
CHECK_FALSE(im.get_premultiplied());
// First test that the default state is correct for each
CHECK_FALSE(im.get_premultiplied());
CHECK_FALSE(im_any.get_premultiplied());
CHECK(im2.get_premultiplied());
CHECK(im2_any.get_premultiplied());
// Always fails on demultiply since its gray8
CHECK_FALSE(mapnik::demultiply_alpha(im));
CHECK_FALSE(mapnik::demultiply_alpha(im_any));
CHECK_FALSE(mapnik::demultiply_alpha(im2));
CHECK_FALSE(mapnik::demultiply_alpha(im2_any));
// Set the image to premultiplied
im.set_premultiplied(true);
CHECK(im.get_premultiplied());
// Set back to not premultiplied
im.set_premultiplied(false);
CHECK_FALSE(im.get_premultiplied());
// Always fails on premultiply since its gray8
CHECK_FALSE(mapnik::premultiply_alpha(im));
CHECK_FALSE(mapnik::premultiply_alpha(im_any));
CHECK_FALSE(mapnik::premultiply_alpha(im2));
CHECK_FALSE(mapnik::premultiply_alpha(im2_any));
mapnik::set_premultiplied_alpha(im, true);
CHECK(im.get_premultiplied());
mapnik::set_premultiplied_alpha(im, false);
CHECK_FALSE(im.get_premultiplied());
// Always fails on demultiply since its gray8
CHECK_FALSE(mapnik::demultiply_alpha(im));
CHECK_FALSE(mapnik::demultiply_alpha(im_any));
CHECK_FALSE(mapnik::demultiply_alpha(im2));
CHECK_FALSE(mapnik::demultiply_alpha(im2_any));
// Always fails on premultiply since its gray8
CHECK_FALSE(mapnik::premultiply_alpha(im));
CHECK_FALSE(mapnik::premultiply_alpha(im_any));
CHECK_FALSE(mapnik::premultiply_alpha(im2));
CHECK_FALSE(mapnik::premultiply_alpha(im2_any));
} // END SECTION
} // END SECTION
} // END TEST_CASE

View file

@ -5,23 +5,23 @@
#include <mapnik/image.hpp>
#include <mapnik/image_util.hpp>
TEST_CASE("image set_pixel")
{
SECTION("test gray32")
{
mapnik::image_gray32 im(256, 256);
mapnik::set_pixel(im, 0, 0, -1);
auto pixel = mapnik::get_pixel<mapnik::image_gray32::pixel_type>(im, 0, 0);
INFO(pixel);
CHECK(pixel == 0);
}
TEST_CASE("image set_pixel") {
SECTION("test gray32") {
mapnik::image_gray32 im(256,256);
mapnik::set_pixel(im, 0, 0, -1);
auto pixel = mapnik::get_pixel<mapnik::image_gray32::pixel_type>(im, 0, 0);
INFO( pixel );
CHECK( pixel == 0 );
}
SECTION("test gray8s") {
mapnik::image_gray8s im(256,256);
mapnik::set_pixel(im, 0, 0, std::numeric_limits<mapnik::image_gray8s::pixel_type>::max()+1);
auto pixel = mapnik::get_pixel<mapnik::image_gray8s::pixel_type>(im, 0, 0);
INFO( pixel );
CHECK( (int)pixel == (int)std::numeric_limits<mapnik::image_gray8s::pixel_type>::max() );
}
SECTION("test gray8s")
{
mapnik::image_gray8s im(256, 256);
mapnik::set_pixel(im, 0, 0, std::numeric_limits<mapnik::image_gray8s::pixel_type>::max() + 1);
auto pixel = mapnik::get_pixel<mapnik::image_gray8s::pixel_type>(im, 0, 0);
INFO(pixel);
CHECK((int)pixel == (int)std::numeric_limits<mapnik::image_gray8s::pixel_type>::max());
}
}

View file

@ -7,276 +7,276 @@
#include <mapnik/image_view_any.hpp>
#include <mapnik/image_util.hpp>
TEST_CASE("image view") {
SECTION("test rgba8") {
mapnik::image_rgba8 im(4,4);
mapnik::color c_red("red");
mapnik::color c_blue("blue");
mapnik::color c_green("green");
mapnik::color c_yellow("yellow");
mapnik::fill(im, c_red);
// Upper Left 2x2 is blue
mapnik::set_pixel(im, 0, 0, c_blue);
mapnik::set_pixel(im, 0, 1, c_blue);
mapnik::set_pixel(im, 1, 0, c_blue);
mapnik::set_pixel(im, 1, 1, c_blue);
// Upper Right 2x2 is green
mapnik::set_pixel(im, 2, 0, c_green);
mapnik::set_pixel(im, 2, 1, c_green);
mapnik::set_pixel(im, 3, 0, c_green);
mapnik::set_pixel(im, 3, 1, c_green);
// Lower Left 2x2 is yellow
mapnik::set_pixel(im, 0, 2, c_yellow);
mapnik::set_pixel(im, 0, 3, c_yellow);
mapnik::set_pixel(im, 1, 2, c_yellow);
mapnik::set_pixel(im, 1, 3, c_yellow);
mapnik::image_rgba8 im2(5,5);
mapnik::fill(im2, c_red);
// Now that we have test data run tests
mapnik::image_view_rgba8 view_all(0,0,4,4,im);
mapnik::image_view_rgba8 view_blue(0,0,2,2,im);
mapnik::image_view_rgba8 view_green(2,0,2,2,im);
mapnik::image_view_rgba8 view_yellow(0,2,2,2,im);
mapnik::image_view_rgba8 view_red(2,2,2,2,im);
mapnik::image_view_rgba8 view_bad(99,99,99,99,im);
const mapnik::image_view_rgba8 view_all_2(0,0,4,4,im2);
// Check that image_views all have the same underlying data
CHECK(view_all == view_blue);
CHECK(view_all == view_green);
CHECK(view_all == view_yellow);
CHECK(view_all == view_red);
CHECK(view_all.data() == im);
// Check that view_all and view_all_2 are not the same underlying data
CHECK_FALSE(view_all == view_all_2);
CHECK(view_all < view_all_2);
// Check that copy constructor works
mapnik::image_view_rgba8 view_all_3(view_all_2);
CHECK(view_all_2 == view_all_3);
// Check other constructor
mapnik::image_view_rgba8 view_all_4(std::move(view_all_3));
CHECK(view_all_2 == view_all_4);
// Check that x offset is correct
CHECK(view_all.x() == 0);
CHECK(view_blue.x() == 0);
CHECK(view_green.x() == 2);
CHECK(view_yellow.x() == 0);
CHECK(view_red.x() == 2);
CHECK(view_bad.x() == 3);
// Check that y offset is correct
CHECK(view_all.y() == 0);
CHECK(view_blue.y() == 0);
CHECK(view_green.y() == 0);
CHECK(view_yellow.y() == 2);
CHECK(view_red.y() == 2);
CHECK(view_bad.y() == 3);
// Check that width is correct
CHECK(view_all.width() == 4);
CHECK(view_blue.width() == 2);
CHECK(view_green.width() == 2);
CHECK(view_yellow.width() == 2);
CHECK(view_red.width() == 2);
CHECK(view_bad.width() == 1);
// Check that height is correct
CHECK(view_all.height() == 4);
CHECK(view_blue.height() == 2);
CHECK(view_green.height() == 2);
CHECK(view_yellow.height() == 2);
CHECK(view_red.height() == 2);
CHECK(view_bad.height() == 1);
// Check that size is correct
CHECK(view_all.size() == 64);
CHECK(view_blue.size() == 16);
CHECK(view_green.size() == 16);
CHECK(view_yellow.size() == 16);
CHECK(view_red.size() == 16);
// Check that row_size is correct
CHECK(view_all.row_size() == 16);
CHECK(view_blue.row_size() == 8);
CHECK(view_green.row_size() == 8);
CHECK(view_yellow.row_size() == 8);
CHECK(view_red.row_size() == 8);
// Check that get_premultiplied is correct
CHECK_FALSE(view_all.get_premultiplied());
CHECK_FALSE(view_blue.get_premultiplied());
CHECK_FALSE(view_green.get_premultiplied());
CHECK_FALSE(view_yellow.get_premultiplied());
CHECK_FALSE(view_red.get_premultiplied());
// Check that operator to retrieve value works properly
CHECK(view_all(0,0) == c_blue.rgba());
CHECK(view_blue(0,0) == c_blue.rgba());
CHECK(view_green(0,0) == c_green.rgba());
CHECK(view_yellow(0,0) == c_yellow.rgba());
CHECK(view_red.row_size() == 8);
// Check that offset is correct
CHECK(view_all.get_offset() == 0.0);
CHECK(view_blue.get_offset() == 0.0);
CHECK(view_green.get_offset() == 0.0);
CHECK(view_yellow.get_offset() == 0.0);
CHECK(view_red.get_offset() == 0.0);
// Check that scaling is correct
CHECK(view_all.get_scaling() == 1.0);
CHECK(view_blue.get_scaling() == 1.0);
CHECK(view_green.get_scaling() == 1.0);
CHECK(view_yellow.get_scaling() == 1.0);
CHECK(view_red.get_scaling() == 1.0);
// CHECK that image dtype is correct
CHECK(view_all.get_dtype() == mapnik::image_dtype_rgba8);
CHECK(view_blue.get_dtype() == mapnik::image_dtype_rgba8);
CHECK(view_green.get_dtype() == mapnik::image_dtype_rgba8);
CHECK(view_yellow.get_dtype() == mapnik::image_dtype_rgba8);
CHECK(view_red.get_dtype() == mapnik::image_dtype_rgba8);
unsigned expected_val;
using pixel_type = mapnik::image_view_rgba8::pixel_type;
// Check that all data in the view is correct
// Blue
expected_val = c_blue.rgba();
for (std::size_t y = 0; y < view_blue.height(); ++y)
{
std::size_t width = view_blue.width();
pixel_type const* data_1 = view_blue.get_row(y);
pixel_type const* data_2 = view_blue.get_row(y, 1);
for (std::size_t x = 0; x < width; ++x)
{
CHECK(*data_1 == expected_val);
++data_1;
}
for (std::size_t x = 1; x < width; ++x)
{
CHECK(*data_2 == expected_val);
++data_2;
}
}
// Green
expected_val = c_green.rgba();
for (std::size_t y = 0; y < view_green.height(); ++y)
{
std::size_t width = view_green.width();
pixel_type const* data_1 = view_green.get_row(y);
pixel_type const* data_2 = view_green.get_row(y, 1);
for (std::size_t x = 0; x < width; ++x)
{
CHECK(*data_1 == expected_val);
++data_1;
}
for (std::size_t x = 1; x < width; ++x)
{
CHECK(*data_2 == expected_val);
++data_2;
}
}
// Yellow
expected_val = c_yellow.rgba();
for (std::size_t y = 0; y < view_yellow.height(); ++y)
{
std::size_t width = view_yellow.width();
pixel_type const* data_1 = view_yellow.get_row(y);
pixel_type const* data_2 = view_yellow.get_row(y, 1);
for (std::size_t x = 0; x < width; ++x)
{
CHECK(*data_1 == expected_val);
++data_1;
}
for (std::size_t x = 1; x < width; ++x)
{
CHECK(*data_2 == expected_val);
++data_2;
}
}
// Red
expected_val = c_red.rgba();
for (std::size_t y = 0; y < view_red.height(); ++y)
{
std::size_t width = view_red.width();
pixel_type const* data_1 = view_red.get_row(y);
pixel_type const* data_2 = view_red.get_row(y, 1);
for (std::size_t x = 0; x < width; ++x)
{
CHECK(*data_1 == expected_val);
++data_1;
}
for (std::size_t x = 1; x < width; ++x)
{
CHECK(*data_2 == expected_val);
++data_2;
}
}
} // END SECTION
SECTION("image_view_null")
TEST_CASE("image view")
{
mapnik::image_view_null view_null;
const mapnik::image_view_null view_null2;
mapnik::image_view_null view_null3(view_null2);
mapnik::image_view_null & view_null4 = view_null3;
SECTION("test rgba8")
{
mapnik::image_rgba8 im(4, 4);
mapnik::color c_red("red");
mapnik::color c_blue("blue");
mapnik::color c_green("green");
mapnik::color c_yellow("yellow");
mapnik::fill(im, c_red);
// Upper Left 2x2 is blue
mapnik::set_pixel(im, 0, 0, c_blue);
mapnik::set_pixel(im, 0, 1, c_blue);
mapnik::set_pixel(im, 1, 0, c_blue);
mapnik::set_pixel(im, 1, 1, c_blue);
// Upper Right 2x2 is green
mapnik::set_pixel(im, 2, 0, c_green);
mapnik::set_pixel(im, 2, 1, c_green);
mapnik::set_pixel(im, 3, 0, c_green);
mapnik::set_pixel(im, 3, 1, c_green);
// Lower Left 2x2 is yellow
mapnik::set_pixel(im, 0, 2, c_yellow);
mapnik::set_pixel(im, 0, 3, c_yellow);
mapnik::set_pixel(im, 1, 2, c_yellow);
mapnik::set_pixel(im, 1, 3, c_yellow);
// All nulls are equal
CHECK(view_null == view_null4);
CHECK(view_null == view_null2);
mapnik::image_rgba8 im2(5, 5);
mapnik::fill(im2, c_red);
// No null is greater
CHECK_FALSE(view_null < view_null4);
CHECK_FALSE(view_null < view_null2);
// Now that we have test data run tests
mapnik::image_view_rgba8 view_all(0, 0, 4, 4, im);
mapnik::image_view_rgba8 view_blue(0, 0, 2, 2, im);
mapnik::image_view_rgba8 view_green(2, 0, 2, 2, im);
mapnik::image_view_rgba8 view_yellow(0, 2, 2, 2, im);
mapnik::image_view_rgba8 view_red(2, 2, 2, 2, im);
mapnik::image_view_rgba8 view_bad(99, 99, 99, 99, im);
const mapnik::image_view_rgba8 view_all_2(0, 0, 4, 4, im2);
// Check defaults
CHECK(view_null.x() == 0);
CHECK(view_null.y() == 0);
CHECK(view_null.width() == 0);
CHECK(view_null.height() == 0);
CHECK(view_null.size() == 0);
CHECK(view_null.row_size() == 0);
CHECK(view_null.get_offset() == 0.0);
CHECK(view_null.get_scaling() == 1.0);
CHECK(view_null.get_dtype() == mapnik::image_dtype_null);
CHECK_FALSE(view_null.get_premultiplied());
// Check that image_views all have the same underlying data
CHECK(view_all == view_blue);
CHECK(view_all == view_green);
CHECK(view_all == view_yellow);
CHECK(view_all == view_red);
// Should throw if we try to access data.
REQUIRE_THROWS(view_null(0,0));
CHECK(view_all.data() == im);
CHECK(view_null.get_row(0) == nullptr);
CHECK(view_null.get_row(0,0) == nullptr);
// Check that view_all and view_all_2 are not the same underlying data
CHECK_FALSE(view_all == view_all_2);
CHECK(view_all < view_all_2);
} // END SECTION
// Check that copy constructor works
mapnik::image_view_rgba8 view_all_3(view_all_2);
CHECK(view_all_2 == view_all_3);
SECTION("image view any")
{
mapnik::image_view_any im_any_null;
CHECK(im_any_null.get_dtype() == mapnik::image_dtype_null);
// Check other constructor
mapnik::image_view_rgba8 view_all_4(std::move(view_all_3));
CHECK(view_all_2 == view_all_4);
mapnik::image_gray8 im(4,4);
mapnik::image_view_gray8 im_view(0,0,4,4,im);
mapnik::image_view_any im_view_any(im_view);
// Check that x offset is correct
CHECK(view_all.x() == 0);
CHECK(view_blue.x() == 0);
CHECK(view_green.x() == 2);
CHECK(view_yellow.x() == 0);
CHECK(view_red.x() == 2);
CHECK(view_bad.x() == 3);
CHECK(im_view_any.get_dtype() == mapnik::image_dtype_gray8);
CHECK(im_view_any.width() == 4);
CHECK(im_view_any.height() == 4);
CHECK(im_view_any.size() == 16);
CHECK(im_view_any.row_size() == 4);
CHECK_FALSE(im_view_any.get_premultiplied());
CHECK(im_view_any.get_offset() == 0.0);
CHECK(im_view_any.get_scaling() == 1.0);
// Check that y offset is correct
CHECK(view_all.y() == 0);
CHECK(view_blue.y() == 0);
CHECK(view_green.y() == 0);
CHECK(view_yellow.y() == 2);
CHECK(view_red.y() == 2);
CHECK(view_bad.y() == 3);
} // END SECTION
// Check that width is correct
CHECK(view_all.width() == 4);
CHECK(view_blue.width() == 2);
CHECK(view_green.width() == 2);
CHECK(view_yellow.width() == 2);
CHECK(view_red.width() == 2);
CHECK(view_bad.width() == 1);
// Check that height is correct
CHECK(view_all.height() == 4);
CHECK(view_blue.height() == 2);
CHECK(view_green.height() == 2);
CHECK(view_yellow.height() == 2);
CHECK(view_red.height() == 2);
CHECK(view_bad.height() == 1);
// Check that size is correct
CHECK(view_all.size() == 64);
CHECK(view_blue.size() == 16);
CHECK(view_green.size() == 16);
CHECK(view_yellow.size() == 16);
CHECK(view_red.size() == 16);
// Check that row_size is correct
CHECK(view_all.row_size() == 16);
CHECK(view_blue.row_size() == 8);
CHECK(view_green.row_size() == 8);
CHECK(view_yellow.row_size() == 8);
CHECK(view_red.row_size() == 8);
// Check that get_premultiplied is correct
CHECK_FALSE(view_all.get_premultiplied());
CHECK_FALSE(view_blue.get_premultiplied());
CHECK_FALSE(view_green.get_premultiplied());
CHECK_FALSE(view_yellow.get_premultiplied());
CHECK_FALSE(view_red.get_premultiplied());
// Check that operator to retrieve value works properly
CHECK(view_all(0, 0) == c_blue.rgba());
CHECK(view_blue(0, 0) == c_blue.rgba());
CHECK(view_green(0, 0) == c_green.rgba());
CHECK(view_yellow(0, 0) == c_yellow.rgba());
CHECK(view_red.row_size() == 8);
// Check that offset is correct
CHECK(view_all.get_offset() == 0.0);
CHECK(view_blue.get_offset() == 0.0);
CHECK(view_green.get_offset() == 0.0);
CHECK(view_yellow.get_offset() == 0.0);
CHECK(view_red.get_offset() == 0.0);
// Check that scaling is correct
CHECK(view_all.get_scaling() == 1.0);
CHECK(view_blue.get_scaling() == 1.0);
CHECK(view_green.get_scaling() == 1.0);
CHECK(view_yellow.get_scaling() == 1.0);
CHECK(view_red.get_scaling() == 1.0);
// CHECK that image dtype is correct
CHECK(view_all.get_dtype() == mapnik::image_dtype_rgba8);
CHECK(view_blue.get_dtype() == mapnik::image_dtype_rgba8);
CHECK(view_green.get_dtype() == mapnik::image_dtype_rgba8);
CHECK(view_yellow.get_dtype() == mapnik::image_dtype_rgba8);
CHECK(view_red.get_dtype() == mapnik::image_dtype_rgba8);
unsigned expected_val;
using pixel_type = mapnik::image_view_rgba8::pixel_type;
// Check that all data in the view is correct
// Blue
expected_val = c_blue.rgba();
for (std::size_t y = 0; y < view_blue.height(); ++y)
{
std::size_t width = view_blue.width();
pixel_type const* data_1 = view_blue.get_row(y);
pixel_type const* data_2 = view_blue.get_row(y, 1);
for (std::size_t x = 0; x < width; ++x)
{
CHECK(*data_1 == expected_val);
++data_1;
}
for (std::size_t x = 1; x < width; ++x)
{
CHECK(*data_2 == expected_val);
++data_2;
}
}
// Green
expected_val = c_green.rgba();
for (std::size_t y = 0; y < view_green.height(); ++y)
{
std::size_t width = view_green.width();
pixel_type const* data_1 = view_green.get_row(y);
pixel_type const* data_2 = view_green.get_row(y, 1);
for (std::size_t x = 0; x < width; ++x)
{
CHECK(*data_1 == expected_val);
++data_1;
}
for (std::size_t x = 1; x < width; ++x)
{
CHECK(*data_2 == expected_val);
++data_2;
}
}
// Yellow
expected_val = c_yellow.rgba();
for (std::size_t y = 0; y < view_yellow.height(); ++y)
{
std::size_t width = view_yellow.width();
pixel_type const* data_1 = view_yellow.get_row(y);
pixel_type const* data_2 = view_yellow.get_row(y, 1);
for (std::size_t x = 0; x < width; ++x)
{
CHECK(*data_1 == expected_val);
++data_1;
}
for (std::size_t x = 1; x < width; ++x)
{
CHECK(*data_2 == expected_val);
++data_2;
}
}
// Red
expected_val = c_red.rgba();
for (std::size_t y = 0; y < view_red.height(); ++y)
{
std::size_t width = view_red.width();
pixel_type const* data_1 = view_red.get_row(y);
pixel_type const* data_2 = view_red.get_row(y, 1);
for (std::size_t x = 0; x < width; ++x)
{
CHECK(*data_1 == expected_val);
++data_1;
}
for (std::size_t x = 1; x < width; ++x)
{
CHECK(*data_2 == expected_val);
++data_2;
}
}
} // END SECTION
SECTION("image_view_null")
{
mapnik::image_view_null view_null;
const mapnik::image_view_null view_null2;
mapnik::image_view_null view_null3(view_null2);
mapnik::image_view_null& view_null4 = view_null3;
// All nulls are equal
CHECK(view_null == view_null4);
CHECK(view_null == view_null2);
// No null is greater
CHECK_FALSE(view_null < view_null4);
CHECK_FALSE(view_null < view_null2);
// Check defaults
CHECK(view_null.x() == 0);
CHECK(view_null.y() == 0);
CHECK(view_null.width() == 0);
CHECK(view_null.height() == 0);
CHECK(view_null.size() == 0);
CHECK(view_null.row_size() == 0);
CHECK(view_null.get_offset() == 0.0);
CHECK(view_null.get_scaling() == 1.0);
CHECK(view_null.get_dtype() == mapnik::image_dtype_null);
CHECK_FALSE(view_null.get_premultiplied());
// Should throw if we try to access data.
REQUIRE_THROWS(view_null(0, 0));
CHECK(view_null.get_row(0) == nullptr);
CHECK(view_null.get_row(0, 0) == nullptr);
} // END SECTION
SECTION("image view any")
{
mapnik::image_view_any im_any_null;
CHECK(im_any_null.get_dtype() == mapnik::image_dtype_null);
mapnik::image_gray8 im(4, 4);
mapnik::image_view_gray8 im_view(0, 0, 4, 4, im);
mapnik::image_view_any im_view_any(im_view);
CHECK(im_view_any.get_dtype() == mapnik::image_dtype_gray8);
CHECK(im_view_any.width() == 4);
CHECK(im_view_any.height() == 4);
CHECK(im_view_any.size() == 16);
CHECK(im_view_any.row_size() == 4);
CHECK_FALSE(im_view_any.get_premultiplied());
CHECK(im_view_any.get_offset() == 0.0);
CHECK(im_view_any.get_scaling() == 1.0);
} // END SECTION
} // END TEST CASE

View file

@ -20,66 +20,62 @@ using source_type = boost::interprocess::ibufferstream;
using source_type = std::filebuf;
#endif
#define TIFF_ASSERT(filename) \
mapnik::tiff_reader<source_type> tiff_reader(filename); \
REQUIRE( tiff_reader.width() == 256 ); \
REQUIRE( tiff_reader.height() == 256 ); \
REQUIRE( tiff_reader.planar_config() == PLANARCONFIG_CONTIG ); \
std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(filename,"tiff")); \
REQUIRE( reader->width() == 256 ); \
REQUIRE( reader->height() == 256 ); \
mapnik::util::file file(filename); \
mapnik::tiff_reader<mapnik::util::char_array_buffer> tiff_reader2(file.data().get(),file.size()); \
REQUIRE( tiff_reader2.width() == 256 ); \
REQUIRE( tiff_reader2.height() == 256 ); \
std::unique_ptr<mapnik::image_reader> reader2(mapnik::get_image_reader(file.data().get(),file.size())); \
REQUIRE( reader2->width() == 256 ); \
REQUIRE( reader2->height() == 256 ); \
#define TIFF_ASSERT(filename) \
mapnik::tiff_reader<source_type> tiff_reader(filename); \
REQUIRE(tiff_reader.width() == 256); \
REQUIRE(tiff_reader.height() == 256); \
REQUIRE(tiff_reader.planar_config() == PLANARCONFIG_CONTIG); \
std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(filename, "tiff")); \
REQUIRE(reader->width() == 256); \
REQUIRE(reader->height() == 256); \
mapnik::util::file file(filename); \
mapnik::tiff_reader<mapnik::util::char_array_buffer> tiff_reader2(file.data().get(), file.size()); \
REQUIRE(tiff_reader2.width() == 256); \
REQUIRE(tiff_reader2.height() == 256); \
std::unique_ptr<mapnik::image_reader> reader2(mapnik::get_image_reader(file.data().get(), file.size())); \
REQUIRE(reader2->width() == 256); \
REQUIRE(reader2->height() == 256);
#define TIFF_ASSERT_ALPHA( data ) \
REQUIRE( tiff_reader.has_alpha() == true ); \
REQUIRE( reader->has_alpha() == true ); \
REQUIRE( tiff_reader2.has_alpha() == true ); \
REQUIRE( reader2->has_alpha() == true ); \
REQUIRE( data.get_premultiplied() == true ); \
#define TIFF_ASSERT_ALPHA(data) \
REQUIRE(tiff_reader.has_alpha() == true); \
REQUIRE(reader->has_alpha() == true); \
REQUIRE(tiff_reader2.has_alpha() == true); \
REQUIRE(reader2->has_alpha() == true); \
REQUIRE(data.get_premultiplied() == true);
#define TIFF_ASSERT_NO_ALPHA_RGB( data ) \
REQUIRE( tiff_reader.has_alpha() == false ); \
REQUIRE( reader->has_alpha() == false ); \
REQUIRE( tiff_reader2.has_alpha() == false ); \
REQUIRE( reader2->has_alpha() == false ); \
REQUIRE( data.get_premultiplied() == true ); \
#define TIFF_ASSERT_NO_ALPHA_RGB(data) \
REQUIRE(tiff_reader.has_alpha() == false); \
REQUIRE(reader->has_alpha() == false); \
REQUIRE(tiff_reader2.has_alpha() == false); \
REQUIRE(reader2->has_alpha() == false); \
REQUIRE(data.get_premultiplied() == true);
#define TIFF_ASSERT_NO_ALPHA_GRAY( data ) \
REQUIRE( tiff_reader.has_alpha() == false ); \
REQUIRE( reader->has_alpha() == false ); \
REQUIRE( tiff_reader2.has_alpha() == false ); \
REQUIRE( reader2->has_alpha() == false ); \
REQUIRE( data.get_premultiplied() == false ); \
#define TIFF_ASSERT_NO_ALPHA_GRAY(data) \
REQUIRE(tiff_reader.has_alpha() == false); \
REQUIRE(reader->has_alpha() == false); \
REQUIRE(tiff_reader2.has_alpha() == false); \
REQUIRE(reader2->has_alpha() == false); \
REQUIRE(data.get_premultiplied() == false);
#define TIFF_ASSERT_SIZE( data,reader ) \
REQUIRE( data.width() == reader->width() ); \
REQUIRE( data.height() == reader->height() ); \
#define TIFF_READ_ONE_PIXEL \
mapnik::image_any subimage = reader->read(1, 1, 1, 1); \
REQUIRE( subimage.width() == 1 ); \
REQUIRE( subimage.height() == 1 ); \
#define TIFF_ASSERT_SIZE(data, reader) \
REQUIRE(data.width() == reader->width()); \
REQUIRE(data.height() == reader->height());
#define TIFF_READ_ONE_PIXEL \
mapnik::image_any subimage = reader->read(1, 1, 1, 1); \
REQUIRE(subimage.width() == 1); \
REQUIRE(subimage.height() == 1);
namespace {
template <typename Image>
template<typename Image>
struct test_image_traits
{
using value_type = mapnik::color;
static value_type const& get_value(mapnik::color const& c)
{
return c;
}
static value_type const& get_value(mapnik::color const& c) { return c; }
};
template <>
template<>
struct test_image_traits<mapnik::image_gray8>
{
using value_type = std::uint8_t;
@ -89,11 +85,9 @@ struct test_image_traits<mapnik::image_gray8>
}
};
template <typename Image>
template<typename Image>
Image generate_test_image()
{
std::size_t tile_size = 16;
Image im(64, 64);
mapnik::color colors[] = {{mapnik::color("red")},
@ -101,10 +95,10 @@ Image generate_test_image()
{mapnik::color("green")},
{mapnik::color("yellow")}};
std::size_t index = 0;
for (std::size_t j = 0; j < im.height()/tile_size; ++j)
for (std::size_t j = 0; j < im.height() / tile_size; ++j)
{
++index;
for (std::size_t i = 0; i < im.width()/tile_size; ++i)
for (std::size_t i = 0; i < im.width() / tile_size; ++i)
{
++index;
for (std::size_t x = 0; x < tile_size; ++x)
@ -112,7 +106,7 @@ Image generate_test_image()
for (std::size_t y = 0; y < tile_size; ++y)
{
auto value = test_image_traits<Image>::get_value(colors[index % 4]);
mapnik::set_pixel(im, i * tile_size + x, j * tile_size + y, value );
mapnik::set_pixel(im, i * tile_size + x, j * tile_size + y, value);
}
}
}
@ -120,7 +114,7 @@ Image generate_test_image()
return im;
}
template <typename Image1, typename Image2>
template<typename Image1, typename Image2>
bool identical(Image1 const& im1, Image2 const& im2)
{
if ((im1.width() != im2.width()) || (im1.height() != im2.height()))
@ -130,13 +124,14 @@ bool identical(Image1 const& im1, Image2 const& im2)
{
for (std::size_t j = 0; j < im1.height(); ++j)
{
if (im1(i,j) != im2(i,j)) return false;
if (im1(i, j) != im2(i, j))
return false;
}
}
return true;
}
template <typename Image>
template<typename Image>
void test_tiff_reader(std::string const& pattern)
{
// generate expected image (rgba8 or gray8)
@ -144,8 +139,7 @@ void test_tiff_reader(std::string const& pattern)
for (auto const& path : mapnik::util::list_directory("test/data/tiff/"))
{
if (boost::iends_with(path,".tif")
&& boost::istarts_with(mapnik::util::basename(path), pattern))
if (boost::iends_with(path, ".tif") && boost::istarts_with(mapnik::util::basename(path), pattern))
{
mapnik::tiff_reader<source_type> tiff_reader(path);
auto width = tiff_reader.width();
@ -169,241 +163,245 @@ void test_tiff_reader(std::string const& pattern)
}
}
}
} // namespace
TEST_CASE("tiff io")
{
SECTION("tiff-reader rgb8+rgba8")
{
test_tiff_reader<mapnik::image_rgba8>("tiff_rgb");
}
SECTION("tiff-reader rgb8+rgba8") { test_tiff_reader<mapnik::image_rgba8>("tiff_rgb"); }
SECTION("tiff-reader gray8")
{
test_tiff_reader<mapnik::image_gray8>("tiff_gray");
}
SECTION("tiff-reader gray8") { test_tiff_reader<mapnik::image_gray8>("tiff_gray"); }
SECTION("scan rgb8 striped")
{
std::string filename("./test/data/tiff/scan_512x512_rgb8_striped.tif");
mapnik::tiff_reader<source_type> tiff_reader(filename);
REQUIRE( tiff_reader.width() == 512 );
REQUIRE( tiff_reader.height() == 512 );
REQUIRE( tiff_reader.planar_config() == PLANARCONFIG_CONTIG );
REQUIRE( tiff_reader.rows_per_strip() == 16 );
REQUIRE( tiff_reader.bits_per_sample() == 8 );
REQUIRE( tiff_reader.is_tiled() == false );
REQUIRE( tiff_reader.tile_width() == 0 );
REQUIRE( tiff_reader.tile_height() == 0 );
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_PALETTE );
REQUIRE( tiff_reader.compression() == COMPRESSION_NONE );
std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(filename,"tiff"));
REQUIRE( reader->width() == 512 );
REQUIRE( reader->height() == 512 );
REQUIRE(tiff_reader.width() == 512);
REQUIRE(tiff_reader.height() == 512);
REQUIRE(tiff_reader.planar_config() == PLANARCONFIG_CONTIG);
REQUIRE(tiff_reader.rows_per_strip() == 16);
REQUIRE(tiff_reader.bits_per_sample() == 8);
REQUIRE(tiff_reader.is_tiled() == false);
REQUIRE(tiff_reader.tile_width() == 0);
REQUIRE(tiff_reader.tile_height() == 0);
REQUIRE(tiff_reader.photometric() == PHOTOMETRIC_PALETTE);
REQUIRE(tiff_reader.compression() == COMPRESSION_NONE);
std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(filename, "tiff"));
REQUIRE(reader->width() == 512);
REQUIRE(reader->height() == 512);
mapnik::util::file file(filename);
mapnik::tiff_reader<mapnik::util::char_array_buffer> tiff_reader2(file.data().get(),file.size());
REQUIRE( tiff_reader2.width() == 512 );
REQUIRE( tiff_reader2.height() == 512 );
std::unique_ptr<mapnik::image_reader> reader2(mapnik::get_image_reader(file.data().get(),file.size()));
REQUIRE( reader2->width() == 512 );
REQUIRE( reader2->height() == 512 );
mapnik::tiff_reader<mapnik::util::char_array_buffer> tiff_reader2(file.data().get(), file.size());
REQUIRE(tiff_reader2.width() == 512);
REQUIRE(tiff_reader2.height() == 512);
std::unique_ptr<mapnik::image_reader> reader2(mapnik::get_image_reader(file.data().get(), file.size()));
REQUIRE(reader2->width() == 512);
REQUIRE(reader2->height() == 512);
mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
REQUIRE( data.is<mapnik::image_rgba8>() == true );
TIFF_ASSERT_SIZE( data,reader );
TIFF_ASSERT_NO_ALPHA_RGB( data );
REQUIRE(data.is<mapnik::image_rgba8>() == true);
TIFF_ASSERT_SIZE(data, reader);
TIFF_ASSERT_NO_ALPHA_RGB(data);
TIFF_READ_ONE_PIXEL
}
SECTION("scan rgb8 tiled") {
SECTION("scan rgb8 tiled")
{
std::string filename("./test/data/tiff/scan_512x512_rgb8_tiled.tif");
mapnik::tiff_reader<source_type> tiff_reader(filename);
REQUIRE( tiff_reader.width() == 512 );
REQUIRE( tiff_reader.height() == 512 );
REQUIRE( tiff_reader.planar_config() == PLANARCONFIG_CONTIG );
REQUIRE( tiff_reader.rows_per_strip() == 0 );
REQUIRE( tiff_reader.bits_per_sample() == 8 );
REQUIRE( tiff_reader.is_tiled() == true );
REQUIRE( tiff_reader.tile_width() == 256 );
REQUIRE( tiff_reader.tile_height() == 256 );
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_PALETTE );
REQUIRE( tiff_reader.compression() == COMPRESSION_LZW );
std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(filename,"tiff"));
REQUIRE( reader->width() == 512 );
REQUIRE( reader->height() == 512 );
REQUIRE(tiff_reader.width() == 512);
REQUIRE(tiff_reader.height() == 512);
REQUIRE(tiff_reader.planar_config() == PLANARCONFIG_CONTIG);
REQUIRE(tiff_reader.rows_per_strip() == 0);
REQUIRE(tiff_reader.bits_per_sample() == 8);
REQUIRE(tiff_reader.is_tiled() == true);
REQUIRE(tiff_reader.tile_width() == 256);
REQUIRE(tiff_reader.tile_height() == 256);
REQUIRE(tiff_reader.photometric() == PHOTOMETRIC_PALETTE);
REQUIRE(tiff_reader.compression() == COMPRESSION_LZW);
std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(filename, "tiff"));
REQUIRE(reader->width() == 512);
REQUIRE(reader->height() == 512);
mapnik::util::file file(filename);
mapnik::tiff_reader<mapnik::util::char_array_buffer> tiff_reader2(file.data().get(),file.size());
REQUIRE( tiff_reader2.width() == 512 );
REQUIRE( tiff_reader2.height() == 512 );
std::unique_ptr<mapnik::image_reader> reader2(mapnik::get_image_reader(file.data().get(),file.size()));
REQUIRE( reader2->width() == 512 );
REQUIRE( reader2->height() == 512 );
mapnik::tiff_reader<mapnik::util::char_array_buffer> tiff_reader2(file.data().get(), file.size());
REQUIRE(tiff_reader2.width() == 512);
REQUIRE(tiff_reader2.height() == 512);
std::unique_ptr<mapnik::image_reader> reader2(mapnik::get_image_reader(file.data().get(), file.size()));
REQUIRE(reader2->width() == 512);
REQUIRE(reader2->height() == 512);
mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
REQUIRE( data.is<mapnik::image_rgba8>() == true );
TIFF_ASSERT_SIZE( data,reader );
TIFF_ASSERT_NO_ALPHA_RGB( data );
REQUIRE(data.is<mapnik::image_rgba8>() == true);
TIFF_ASSERT_SIZE(data, reader);
TIFF_ASSERT_NO_ALPHA_RGB(data);
TIFF_READ_ONE_PIXEL
}
SECTION("rgba8 striped") {
SECTION("rgba8 striped")
{
TIFF_ASSERT("./test/data/tiff/ndvi_256x256_rgba8_striped.tif")
REQUIRE( tiff_reader.rows_per_strip() == 1 );
REQUIRE( tiff_reader.bits_per_sample() == 8 );
REQUIRE( tiff_reader.is_tiled() == false );
REQUIRE( tiff_reader.tile_width() == 0 );
REQUIRE( tiff_reader.tile_height() == 0 );
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_RGB );
REQUIRE( tiff_reader.compression() == COMPRESSION_ADOBE_DEFLATE );
REQUIRE(tiff_reader.rows_per_strip() == 1);
REQUIRE(tiff_reader.bits_per_sample() == 8);
REQUIRE(tiff_reader.is_tiled() == false);
REQUIRE(tiff_reader.tile_width() == 0);
REQUIRE(tiff_reader.tile_height() == 0);
REQUIRE(tiff_reader.photometric() == PHOTOMETRIC_RGB);
REQUIRE(tiff_reader.compression() == COMPRESSION_ADOBE_DEFLATE);
mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
REQUIRE( data.is<mapnik::image_rgba8>() == true );
TIFF_ASSERT_SIZE( data,reader );
TIFF_ASSERT_ALPHA( data );
REQUIRE(data.is<mapnik::image_rgba8>() == true);
TIFF_ASSERT_SIZE(data, reader);
TIFF_ASSERT_ALPHA(data);
TIFF_READ_ONE_PIXEL
}
SECTION("rgba8 tiled") {
SECTION("rgba8 tiled")
{
TIFF_ASSERT("./test/data/tiff/ndvi_256x256_rgba8_tiled.tif")
REQUIRE( tiff_reader.rows_per_strip() == 0 );
REQUIRE( tiff_reader.bits_per_sample() == 8 );
REQUIRE( tiff_reader.is_tiled() == true );
REQUIRE( tiff_reader.tile_width() == 256 );
REQUIRE( tiff_reader.tile_height() == 256 );
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_RGB );
REQUIRE( tiff_reader.compression() == COMPRESSION_LZW );
REQUIRE(tiff_reader.rows_per_strip() == 0);
REQUIRE(tiff_reader.bits_per_sample() == 8);
REQUIRE(tiff_reader.is_tiled() == true);
REQUIRE(tiff_reader.tile_width() == 256);
REQUIRE(tiff_reader.tile_height() == 256);
REQUIRE(tiff_reader.photometric() == PHOTOMETRIC_RGB);
REQUIRE(tiff_reader.compression() == COMPRESSION_LZW);
mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
REQUIRE( data.is<mapnik::image_rgba8>() == true );
TIFF_ASSERT_SIZE( data,reader );
TIFF_ASSERT_ALPHA( data );
REQUIRE(data.is<mapnik::image_rgba8>() == true);
TIFF_ASSERT_SIZE(data, reader);
TIFF_ASSERT_ALPHA(data);
TIFF_READ_ONE_PIXEL
}
}
SECTION("rgb8 striped") {
SECTION("rgb8 striped")
{
TIFF_ASSERT("./test/data/tiff/ndvi_256x256_rgb8_striped.tif")
REQUIRE( tiff_reader.rows_per_strip() == 10 );
REQUIRE( tiff_reader.bits_per_sample() == 8 );
REQUIRE( tiff_reader.is_tiled() == false );
REQUIRE( tiff_reader.tile_width() == 0 );
REQUIRE( tiff_reader.tile_height() == 0 );
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_RGB );
REQUIRE( tiff_reader.compression() == COMPRESSION_NONE );
REQUIRE(tiff_reader.rows_per_strip() == 10);
REQUIRE(tiff_reader.bits_per_sample() == 8);
REQUIRE(tiff_reader.is_tiled() == false);
REQUIRE(tiff_reader.tile_width() == 0);
REQUIRE(tiff_reader.tile_height() == 0);
REQUIRE(tiff_reader.photometric() == PHOTOMETRIC_RGB);
REQUIRE(tiff_reader.compression() == COMPRESSION_NONE);
mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
REQUIRE( data.is<mapnik::image_rgba8>() == true );
TIFF_ASSERT_SIZE( data,reader );
TIFF_ASSERT_NO_ALPHA_RGB( data );
REQUIRE(data.is<mapnik::image_rgba8>() == true);
TIFF_ASSERT_SIZE(data, reader);
TIFF_ASSERT_NO_ALPHA_RGB(data);
TIFF_READ_ONE_PIXEL
}
SECTION("rgb8 tiled") {
SECTION("rgb8 tiled")
{
TIFF_ASSERT("./test/data/tiff/ndvi_256x256_rgb8_tiled.tif")
REQUIRE( tiff_reader.rows_per_strip() == 0 );
REQUIRE( tiff_reader.bits_per_sample() == 8 );
REQUIRE( tiff_reader.is_tiled() == true );
REQUIRE( tiff_reader.tile_width() == 32 );
REQUIRE( tiff_reader.tile_height() == 32 );
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_RGB );
REQUIRE( tiff_reader.compression() == COMPRESSION_LZW );
REQUIRE(tiff_reader.rows_per_strip() == 0);
REQUIRE(tiff_reader.bits_per_sample() == 8);
REQUIRE(tiff_reader.is_tiled() == true);
REQUIRE(tiff_reader.tile_width() == 32);
REQUIRE(tiff_reader.tile_height() == 32);
REQUIRE(tiff_reader.photometric() == PHOTOMETRIC_RGB);
REQUIRE(tiff_reader.compression() == COMPRESSION_LZW);
mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
REQUIRE( data.is<mapnik::image_rgba8>() == true );
TIFF_ASSERT_SIZE( data,reader );
TIFF_ASSERT_NO_ALPHA_RGB( data );
REQUIRE(data.is<mapnik::image_rgba8>() == true);
TIFF_ASSERT_SIZE(data, reader);
TIFF_ASSERT_NO_ALPHA_RGB(data);
TIFF_READ_ONE_PIXEL
}
SECTION("gray8 striped") {
SECTION("gray8 striped")
{
TIFF_ASSERT("./test/data/tiff/ndvi_256x256_gray8_striped.tif")
REQUIRE( tiff_reader.rows_per_strip() == 32 );
REQUIRE( tiff_reader.bits_per_sample() == 8 );
REQUIRE( tiff_reader.is_tiled() == false );
REQUIRE( tiff_reader.tile_width() == 0 );
REQUIRE( tiff_reader.tile_height() == 0 );
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK );
REQUIRE( tiff_reader.compression() == COMPRESSION_NONE );
REQUIRE(tiff_reader.rows_per_strip() == 32);
REQUIRE(tiff_reader.bits_per_sample() == 8);
REQUIRE(tiff_reader.is_tiled() == false);
REQUIRE(tiff_reader.tile_width() == 0);
REQUIRE(tiff_reader.tile_height() == 0);
REQUIRE(tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK);
REQUIRE(tiff_reader.compression() == COMPRESSION_NONE);
mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
REQUIRE( data.is<mapnik::image_gray8>() == true );
TIFF_ASSERT_SIZE( data,reader );
TIFF_ASSERT_NO_ALPHA_GRAY( data );
REQUIRE(data.is<mapnik::image_gray8>() == true);
TIFF_ASSERT_SIZE(data, reader);
TIFF_ASSERT_NO_ALPHA_GRAY(data);
TIFF_READ_ONE_PIXEL
}
SECTION("gray8 tiled") {
SECTION("gray8 tiled")
{
TIFF_ASSERT("./test/data/tiff/ndvi_256x256_gray8_tiled.tif")
REQUIRE( tiff_reader.rows_per_strip() == 0 );
REQUIRE( tiff_reader.bits_per_sample() == 8 );
REQUIRE( tiff_reader.is_tiled() == true );
REQUIRE( tiff_reader.tile_width() == 256 );
REQUIRE( tiff_reader.tile_height() == 256 );
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK );
REQUIRE( tiff_reader.compression() == COMPRESSION_LZW );
REQUIRE(tiff_reader.rows_per_strip() == 0);
REQUIRE(tiff_reader.bits_per_sample() == 8);
REQUIRE(tiff_reader.is_tiled() == true);
REQUIRE(tiff_reader.tile_width() == 256);
REQUIRE(tiff_reader.tile_height() == 256);
REQUIRE(tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK);
REQUIRE(tiff_reader.compression() == COMPRESSION_LZW);
mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
REQUIRE( data.is<mapnik::image_gray8>() == true );
TIFF_ASSERT_SIZE( data,reader );
TIFF_ASSERT_NO_ALPHA_GRAY( data );
REQUIRE(data.is<mapnik::image_gray8>() == true);
TIFF_ASSERT_SIZE(data, reader);
TIFF_ASSERT_NO_ALPHA_GRAY(data);
TIFF_READ_ONE_PIXEL
}
SECTION("gray16 striped") {
SECTION("gray16 striped")
{
TIFF_ASSERT("./test/data/tiff/ndvi_256x256_gray16_striped.tif")
REQUIRE( tiff_reader.rows_per_strip() == 16 );
REQUIRE( tiff_reader.bits_per_sample() == 16 );
REQUIRE( tiff_reader.is_tiled() == false );
REQUIRE( tiff_reader.tile_width() == 0 );
REQUIRE( tiff_reader.tile_height() == 0 );
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK );
REQUIRE( tiff_reader.compression() == COMPRESSION_NONE );
REQUIRE(tiff_reader.rows_per_strip() == 16);
REQUIRE(tiff_reader.bits_per_sample() == 16);
REQUIRE(tiff_reader.is_tiled() == false);
REQUIRE(tiff_reader.tile_width() == 0);
REQUIRE(tiff_reader.tile_height() == 0);
REQUIRE(tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK);
REQUIRE(tiff_reader.compression() == COMPRESSION_NONE);
mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
REQUIRE( data.is<mapnik::image_gray16>() == true );
TIFF_ASSERT_SIZE( data,reader );
TIFF_ASSERT_NO_ALPHA_GRAY( data );
REQUIRE(data.is<mapnik::image_gray16>() == true);
TIFF_ASSERT_SIZE(data, reader);
TIFF_ASSERT_NO_ALPHA_GRAY(data);
TIFF_READ_ONE_PIXEL
}
SECTION("gray16 tiled") {
SECTION("gray16 tiled")
{
TIFF_ASSERT("./test/data/tiff/ndvi_256x256_gray16_tiled.tif")
REQUIRE( tiff_reader.rows_per_strip() == 0 );
REQUIRE( tiff_reader.bits_per_sample() == 16 );
REQUIRE( tiff_reader.is_tiled() == true );
REQUIRE( tiff_reader.tile_width() == 256 );
REQUIRE( tiff_reader.tile_height() == 256 );
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK );
REQUIRE( tiff_reader.compression() == COMPRESSION_LZW );
REQUIRE(tiff_reader.rows_per_strip() == 0);
REQUIRE(tiff_reader.bits_per_sample() == 16);
REQUIRE(tiff_reader.is_tiled() == true);
REQUIRE(tiff_reader.tile_width() == 256);
REQUIRE(tiff_reader.tile_height() == 256);
REQUIRE(tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK);
REQUIRE(tiff_reader.compression() == COMPRESSION_LZW);
mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
REQUIRE( data.is<mapnik::image_gray16>() == true );
TIFF_ASSERT_SIZE( data,reader );
TIFF_ASSERT_NO_ALPHA_GRAY( data );
REQUIRE(data.is<mapnik::image_gray16>() == true);
TIFF_ASSERT_SIZE(data, reader);
TIFF_ASSERT_NO_ALPHA_GRAY(data);
TIFF_READ_ONE_PIXEL
}
SECTION("gray32f striped") {
SECTION("gray32f striped")
{
TIFF_ASSERT("./test/data/tiff/ndvi_256x256_gray32f_striped.tif")
REQUIRE( tiff_reader.rows_per_strip() == 8 );
REQUIRE( tiff_reader.bits_per_sample() == 32 );
REQUIRE( tiff_reader.is_tiled() == false );
REQUIRE( tiff_reader.tile_width() == 0 );
REQUIRE( tiff_reader.tile_height() == 0 );
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK );
REQUIRE( tiff_reader.compression() == COMPRESSION_NONE );
REQUIRE(tiff_reader.rows_per_strip() == 8);
REQUIRE(tiff_reader.bits_per_sample() == 32);
REQUIRE(tiff_reader.is_tiled() == false);
REQUIRE(tiff_reader.tile_width() == 0);
REQUIRE(tiff_reader.tile_height() == 0);
REQUIRE(tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK);
REQUIRE(tiff_reader.compression() == COMPRESSION_NONE);
mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
REQUIRE( data.is<mapnik::image_gray32f>() == true );
TIFF_ASSERT_SIZE( data,reader );
TIFF_ASSERT_NO_ALPHA_GRAY( data );
REQUIRE(data.is<mapnik::image_gray32f>() == true);
TIFF_ASSERT_SIZE(data, reader);
TIFF_ASSERT_NO_ALPHA_GRAY(data);
TIFF_READ_ONE_PIXEL
}
SECTION("gray32f tiled") {
SECTION("gray32f tiled")
{
TIFF_ASSERT("./test/data/tiff/ndvi_256x256_gray32f_tiled.tif")
REQUIRE( tiff_reader.rows_per_strip() == 0 );
REQUIRE( tiff_reader.bits_per_sample() == 32 );
REQUIRE( tiff_reader.is_tiled() == true );
REQUIRE( tiff_reader.tile_width() == 256 );
REQUIRE( tiff_reader.tile_height() == 256 );
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK );
REQUIRE( tiff_reader.compression() == COMPRESSION_LZW );
REQUIRE(tiff_reader.rows_per_strip() == 0);
REQUIRE(tiff_reader.bits_per_sample() == 32);
REQUIRE(tiff_reader.is_tiled() == true);
REQUIRE(tiff_reader.tile_width() == 256);
REQUIRE(tiff_reader.tile_height() == 256);
REQUIRE(tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK);
REQUIRE(tiff_reader.compression() == COMPRESSION_LZW);
mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
REQUIRE( data.is<mapnik::image_gray32f>() == true );
TIFF_ASSERT_SIZE( data,reader );
TIFF_ASSERT_NO_ALPHA_GRAY( data );
REQUIRE(data.is<mapnik::image_gray32f>() == true);
TIFF_ASSERT_SIZE(data, reader);
TIFF_ASSERT_NO_ALPHA_GRAY(data);
TIFF_READ_ONE_PIXEL
}
}
#endif

View file

@ -8,20 +8,20 @@
#include <mapnik/image_view.hpp>
#include <mapnik/webp_io.hpp>
TEST_CASE("webp io") {
SECTION("does not crash accessing view") {
std::stringstream s;
mapnik::image_rgba8 im(1024,1024);
mapnik::image_view_rgba8 view(512,512,1024,1024,im);
WebPConfig config;
if (!WebPConfigInit(&config))
TEST_CASE("webp io")
{
SECTION("does not crash accessing view")
{
throw std::runtime_error("version mismatch");
std::stringstream s;
mapnik::image_rgba8 im(1024, 1024);
mapnik::image_view_rgba8 view(512, 512, 1024, 1024, im);
WebPConfig config;
if (!WebPConfigInit(&config))
{
throw std::runtime_error("version mismatch");
}
save_as_webp(s, view, config, true);
}
save_as_webp(s,view,config,true);
}
}
#endif

View file

@ -30,57 +30,56 @@
#include <mapnik/cairo/cairo_image_util.hpp>
#endif
TEST_CASE("map") {
SECTION("set background - agg") {
mapnik::Map map(256, 256);
mapnik::image_rgba8 image(map.width(), map.height());
const mapnik::color c1(255, 0, 0);
mapnik::fill(image, c1);
CHECK(image(0, 0) == c1.rgba());
// Fully transparent black should replace red color
const mapnik::color c2(0, 0, 0, 0);
map.set_background(c2);
mapnik::agg_renderer<mapnik::image_rgba8> ren(map, image);
ren.apply();
CHECK(image(0, 0) == c2.rgba());
}
#if defined(HAVE_CAIRO)
SECTION("set background - cairo") {
mapnik::Map map(256, 256);
mapnik::cairo_surface_ptr image_surface(
cairo_image_surface_create(CAIRO_FORMAT_ARGB32, map.width(), map.height()),
mapnik::cairo_surface_closer());
mapnik::cairo_ptr image_context(mapnik::create_context(image_surface));
cairo_set_source_rgba(image_context.get(), 1.0, 0.0, 0.0, 1.0);
cairo_paint(image_context.get());
TEST_CASE("map")
{
SECTION("set background - agg")
{
mapnik::Map map(256, 256);
mapnik::image_rgba8 image(map.width(), map.height());
mapnik::cairo_image_to_rgba8(image, image_surface);
const mapnik::color c1(255, 0, 0);
mapnik::fill(image, c1);
CHECK(image(0, 0) == c1.rgba());
}
// Fully transparent black should replace red color
const mapnik::color c2(0, 0, 0, 0);
map.set_background(c2);
mapnik::cairo_renderer<mapnik::cairo_ptr> ren(map, image_context, 1.0);
ren.apply();
// Fully transparent black should replace red color
const mapnik::color c2(0, 0, 0, 0);
map.set_background(c2);
mapnik::agg_renderer<mapnik::image_rgba8> ren(map, image);
ren.apply();
{
mapnik::image_rgba8 image(map.width(), map.height());
mapnik::cairo_image_to_rgba8(image, image_surface);
CHECK(image(0, 0) == c2.rgba());
}
}
#endif
#if defined(HAVE_CAIRO)
SECTION("set background - cairo")
{
mapnik::Map map(256, 256);
mapnik::cairo_surface_ptr image_surface(
cairo_image_surface_create(CAIRO_FORMAT_ARGB32, map.width(), map.height()),
mapnik::cairo_surface_closer());
mapnik::cairo_ptr image_context(mapnik::create_context(image_surface));
cairo_set_source_rgba(image_context.get(), 1.0, 0.0, 0.0, 1.0);
cairo_paint(image_context.get());
{
mapnik::image_rgba8 image(map.width(), map.height());
mapnik::cairo_image_to_rgba8(image, image_surface);
const mapnik::color c1(255, 0, 0);
CHECK(image(0, 0) == c1.rgba());
}
// Fully transparent black should replace red color
const mapnik::color c2(0, 0, 0, 0);
map.set_background(c2);
mapnik::cairo_renderer<mapnik::cairo_ptr> ren(map, image_context, 1.0);
ren.apply();
{
mapnik::image_rgba8 image(map.width(), map.height());
mapnik::cairo_image_to_rgba8(image, image_surface);
CHECK(image(0, 0) == c2.rgba());
}
}
#endif
}

View file

@ -27,12 +27,13 @@
#include <mapnik/featureset.hpp>
#include <mapnik/load_map.hpp>
namespace {
bool test_query_point(mapnik::Map const& map,
double x, double y,
std::string const& name, std::string const& expected_val)
double x,
double y,
std::string const& name,
std::string const& expected_val)
{
auto featureset = map.query_map_point(0u, x, y);
while (auto feature = featureset->next())
@ -42,19 +43,19 @@ bool test_query_point(mapnik::Map const& map,
}
return false;
}
}
} // namespace
TEST_CASE("Query map point") {
SECTION("Polygons") {
mapnik::Map map(882,780);
mapnik::load_map(map, "./test/data/good_maps/wgs842merc_reprojection.xml");
map.zoom_all();
CHECK(test_query_point(map, 351, 94, "ADMIN", "Greenland"));
CHECK(test_query_point(map, 402, 182,"ADMIN", "Iceland"));
CHECK(test_query_point(map, 339, 687,"ADMIN", "Antarctica"));
CHECK(test_query_point(map, 35, 141, "ADMIN", "Russia"));
CHECK(test_query_point(map, 737, 297,"ADMIN", "Japan"));
}
TEST_CASE("Query map point")
{
SECTION("Polygons")
{
mapnik::Map map(882, 780);
mapnik::load_map(map, "./test/data/good_maps/wgs842merc_reprojection.xml");
map.zoom_all();
CHECK(test_query_point(map, 351, 94, "ADMIN", "Greenland"));
CHECK(test_query_point(map, 402, 182, "ADMIN", "Iceland"));
CHECK(test_query_point(map, 339, 687, "ADMIN", "Antarctica"));
CHECK(test_query_point(map, 35, 141, "ADMIN", "Russia"));
CHECK(test_query_point(map, 737, 297, "ADMIN", "Japan"));
}
}

View file

@ -4,14 +4,13 @@
#include <mapnik/symbolizer_enumerations.hpp>
#include <sstream>
TEST_CASE("enumeration") {
mapnik::line_cap_e e(mapnik::ROUND_CAP);
CHECK( e.as_string() == "round" );
// note: test the << operator, which calls `as_string` internally
// is not used in mapnik, but kept for back compat
std::stringstream s;
s << e;
CHECK( s.str() == "round" );
TEST_CASE("enumeration")
{
mapnik::line_cap_e e(mapnik::ROUND_CAP);
CHECK(e.as_string() == "round");
// note: test the << operator, which calls `as_string` internally
// is not used in mapnik, but kept for back compat
std::stringstream s;
s << e;
CHECK(s.str() == "round");
}

View file

@ -2,59 +2,58 @@
#include "catch.hpp"
#include <mapnik/safe_cast.hpp>
#define CAST_ASSERT(numeric_type) \
using limit = std::numeric_limits<numeric_type>; \
auto min_value = static_cast<std::intmax_t>(limit::min())-1; \
auto max_value = static_cast<std::intmax_t>(limit::max())+1; \
CHECK( limit::min() == mapnik::safe_cast<numeric_type>(min_value) ); \
CHECK( limit::max() == mapnik::safe_cast<numeric_type>(max_value) ); \
#define CAST_ASSERT(numeric_type) \
using limit = std::numeric_limits<numeric_type>; \
auto min_value = static_cast<std::intmax_t>(limit::min()) - 1; \
auto max_value = static_cast<std::intmax_t>(limit::max()) + 1; \
CHECK(limit::min() == mapnik::safe_cast<numeric_type>(min_value)); \
CHECK(limit::max() == mapnik::safe_cast<numeric_type>(max_value));
#define CAST_ASSERT2(numeric_type) \
using limit = std::numeric_limits<numeric_type>; \
auto min_value = static_cast<std::intmax_t>(limit::min()); \
auto max_value = static_cast<std::intmax_t>(limit::max()); \
CHECK( limit::min() == mapnik::safe_cast<numeric_type>(min_value) ); \
CHECK( limit::max() == mapnik::safe_cast<numeric_type>(max_value) ); \
#define CAST_ASSERT2(numeric_type) \
using limit = std::numeric_limits<numeric_type>; \
auto min_value = static_cast<std::intmax_t>(limit::min()); \
auto max_value = static_cast<std::intmax_t>(limit::max()); \
CHECK(limit::min() == mapnik::safe_cast<numeric_type>(min_value)); \
CHECK(limit::max() == mapnik::safe_cast<numeric_type>(max_value));
#define CAST_ASSERT3(numeric_type) \
using limit = std::numeric_limits<numeric_type>; \
auto min_value = static_cast<std::intmax_t>(limit::min())-1; \
auto max_value = static_cast<std::uintmax_t>(limit::max()); \
CHECK( limit::min() == mapnik::safe_cast<numeric_type>(min_value) ); \
CHECK( limit::max() == mapnik::safe_cast<numeric_type>(max_value) ); \
#define CAST_ASSERT3(numeric_type) \
using limit = std::numeric_limits<numeric_type>; \
auto min_value = static_cast<std::intmax_t>(limit::min()) - 1; \
auto max_value = static_cast<std::uintmax_t>(limit::max()); \
CHECK(limit::min() == mapnik::safe_cast<numeric_type>(min_value)); \
CHECK(limit::max() == mapnik::safe_cast<numeric_type>(max_value));
#define CAST_ASSERT4(numeric_type) \
using limit = std::numeric_limits<numeric_type>; \
auto min_value = static_cast<double>(-limit::max())-1; \
auto max_value = static_cast<double>(limit::max()); \
CHECK( -limit::max() == mapnik::safe_cast<numeric_type>(min_value) ); \
CHECK( limit::max() == mapnik::safe_cast<numeric_type>(max_value) ); \
#define CAST_ASSERT4(numeric_type) \
using limit = std::numeric_limits<numeric_type>; \
auto min_value = static_cast<double>(-limit::max()) - 1; \
auto max_value = static_cast<double>(limit::max()); \
CHECK(-limit::max() == mapnik::safe_cast<numeric_type>(min_value)); \
CHECK(limit::max() == mapnik::safe_cast<numeric_type>(max_value));
TEST_CASE("saturated cast") {
TEST_CASE("saturated cast")
{
SECTION("int8") { CAST_ASSERT(std::int8_t); }
SECTION("int16") { CAST_ASSERT(std::int16_t); }
SECTION("int32") { CAST_ASSERT(std::int32_t); }
SECTION("int8") { CAST_ASSERT(std::int8_t); }
SECTION("int16") { CAST_ASSERT(std::int16_t); }
SECTION("int32") { CAST_ASSERT(std::int32_t); }
SECTION("int64") { CAST_ASSERT2(std::int64_t); }
SECTION("int64") { CAST_ASSERT2(std::int64_t); }
SECTION("intmax") { CAST_ASSERT2(std::intmax_t); }
SECTION("intptr") { CAST_ASSERT2(std::intptr_t); }
SECTION("uint8") { CAST_ASSERT(std::uint8_t); }
SECTION("uint16") { CAST_ASSERT(std::uint16_t); }
SECTION("uint32") { CAST_ASSERT(std::uint32_t); }
SECTION("uint8") { CAST_ASSERT(std::uint8_t); }
SECTION("uint16") { CAST_ASSERT(std::uint16_t); }
SECTION("uint32") { CAST_ASSERT(std::uint32_t); }
SECTION("uint64") { CAST_ASSERT3(std::uint64_t); }
SECTION("uint64") { CAST_ASSERT3(std::uint64_t); }
SECTION("uintmax") { CAST_ASSERT3(std::uintmax_t); }
SECTION("uintptr") { CAST_ASSERT3(std::uintptr_t); }
SECTION("float") { CAST_ASSERT4(float); }
SECTION("freeform") {
CHECK( static_cast<std::size_t>(0) == mapnik::safe_cast<std::size_t>(-1) );
CHECK( static_cast<std::uint64_t>(0) == mapnik::safe_cast<std::uint64_t>(-1) );
CHECK( static_cast<unsigned long long>(0) == mapnik::safe_cast<unsigned long long>(-1) );
SECTION("freeform")
{
CHECK(static_cast<std::size_t>(0) == mapnik::safe_cast<std::size_t>(-1));
CHECK(static_cast<std::uint64_t>(0) == mapnik::safe_cast<std::uint64_t>(-1));
CHECK(static_cast<unsigned long long>(0) == mapnik::safe_cast<unsigned long long>(-1));
}
}

View file

@ -21,7 +21,7 @@ std::string to_string(color const& c)
}
template<typename blender>
color blend(color const& source, color const& dest, unsigned cover=255)
color blend(color const& source, color const& dest, unsigned cover = 255)
{
unsigned stride = 4;
unsigned size = 1;
@ -31,27 +31,24 @@ color blend(color const& source, color const& dest, unsigned cover=255)
color dest_pre = dest;
dest_pre.premultiply();
unsigned char* buffer = new unsigned char[size*size*stride];
std::memset(buffer, 0, size*size*stride);
unsigned char* buffer = new unsigned char[size * size * stride];
std::memset(buffer, 0, size * size * stride);
buffer[0] = dest_pre.r;
buffer[1] = dest_pre.g;
buffer[2] = dest_pre.b;
buffer[3] = dest_pre.a;
// http://www.antigrain.com/doc/basic_renderers/basic_renderers.agdoc.html
agg::rendering_buffer rbuf(buffer,
size,
size,
size * stride);
color::value_type* psource = (color::value_type*)rbuf.row_ptr(0,0,1);
blender::blend_pix(psource,source_pre.r,source_pre.g,source_pre.b,source_pre.a,cover);
color color_result(psource[0],psource[1],psource[2],psource[3]);
agg::rendering_buffer rbuf(buffer, size, size, size * stride);
color::value_type* psource = (color::value_type*)rbuf.row_ptr(0, 0, 1);
blender::blend_pix(psource, source_pre.r, source_pre.g, source_pre.b, source_pre.a, cover);
color color_result(psource[0], psource[1], psource[2], psource[3]);
color_result.demultiply();
delete [] buffer;
delete[] buffer;
return color_result;
}
// agg::pixfmt_alpha_blend_rgba
color normal_blend(color const& source, color const& dest, unsigned cover=255)
color normal_blend(color const& source, color const& dest, unsigned cover = 255)
{
using renderer_type = agg::renderer_base<agg::pixfmt_rgba32_pre>;
unsigned stride = 4;
@ -61,60 +58,53 @@ color normal_blend(color const& source, color const& dest, unsigned cover=255)
color dest_pre = dest;
dest_pre.premultiply();
// source buffer
unsigned char* source_buffer = new unsigned char[size*size*stride];
std::memset(source_buffer, 0, size*size*stride);
unsigned char* source_buffer = new unsigned char[size * size * stride];
std::memset(source_buffer, 0, size * size * stride);
source_buffer[0] = source_pre.r;
source_buffer[1] = source_pre.g;
source_buffer[2] = source_pre.b;
source_buffer[3] = source_pre.a;
agg::rendering_buffer source_rbuffer(source_buffer,size,size,size * 4);
agg::rendering_buffer source_rbuffer(source_buffer, size, size, size * 4);
agg::pixfmt_rgba32_pre pixf_source(source_rbuffer);
// destination buffer
unsigned char* dest_buffer = new unsigned char[size*size*stride];
std::memset(dest_buffer, 0, size*size*stride);
unsigned char* dest_buffer = new unsigned char[size * size * stride];
std::memset(dest_buffer, 0, size * size * stride);
dest_buffer[0] = dest_pre.r;
dest_buffer[1] = dest_pre.g;
dest_buffer[2] = dest_pre.b;
dest_buffer[3] = dest_pre.a;
agg::rendering_buffer dest_rbuffer(dest_buffer,size,size,size * 4);
agg::rendering_buffer dest_rbuffer(dest_buffer, size, size, size * 4);
agg::pixfmt_rgba32_pre pixf_dest(dest_rbuffer);
// renderer: blends source into destination
renderer_type ren(pixf_dest);
ren.blend_from(pixf_source,0,0,0,cover);
color color_result(dest_buffer[0],dest_buffer[1],dest_buffer[2],dest_buffer[3]);
ren.blend_from(pixf_source, 0, 0, 0, cover);
color color_result(dest_buffer[0], dest_buffer[1], dest_buffer[2], dest_buffer[3]);
color_result.demultiply();
delete [] source_buffer;
delete [] dest_buffer;
delete[] source_buffer;
delete[] dest_buffer;
return color_result;
}
namespace agg {
// the original agg template code for src_over
// before we changed A as per https://github.com/mapnik/mapnik/issues/1452
template<class ColorT, class Order> struct comp_op_rgba_src_over2
template<class ColorT, class Order>
struct comp_op_rgba_src_over2
{
using color_type = ColorT;
using order_type = Order;
using value_type = typename color_type::value_type;
using calc_type = typename color_type::calc_type;
enum base_scale_e
{
base_shift = color_type::base_shift,
base_mask = color_type::base_mask
};
enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask };
// Dca' = Sca + Dca.(1 - Sa)
// Da' = Sa + Da - Sa.Da
static void blend_pix(value_type* p,
unsigned sr, unsigned sg, unsigned sb,
unsigned sa, unsigned cover)
static void blend_pix(value_type* p, unsigned sr, unsigned sg, unsigned sb, unsigned sa, unsigned cover)
{
if(cover < 255)
if (cover < 255)
{
sr = (sr * cover + 255) >> 8;
sg = (sg * cover + 255) >> 8;
@ -129,79 +119,78 @@ template<class ColorT, class Order> struct comp_op_rgba_src_over2
}
};
}
} // namespace agg
TEST_CASE("blending") {
SECTION("src over") {
using source_over_old_agg = agg::comp_op_rgba_src_over2<color, agg::order_rgba>;
using source_over = agg::comp_op_rgba_src_over<color, agg::order_rgba>;
try
TEST_CASE("blending")
{
SECTION("src over")
{
color white(255,255,255,255);
color black(0,0,0,255);
REQUIRE( to_string(blend<source_over>(white,white)) == to_string(white) );
REQUIRE( to_string(blend<source_over>(white,black)) == to_string(white) );
REQUIRE( to_string(blend<source_over>(black,white)) == to_string(black) );
color near_white(254,254,254,254); // Source
color near_trans(1,1,1,1); // Dest
color expected_color(253,253,253,255); // expected result
REQUIRE( to_string(blend<source_over_old_agg>(near_white,near_trans)) == to_string(color(253,253,253,254)) );
REQUIRE( to_string(blend<source_over>(near_white,near_trans)) == to_string(expected_color) );
REQUIRE( to_string(normal_blend(near_white,near_trans)) == to_string(expected_color) );
// using normal_blend as expected, compare a variety of other colors
using source_over_old_agg = agg::comp_op_rgba_src_over2<color, agg::order_rgba>;
using source_over = agg::comp_op_rgba_src_over<color, agg::order_rgba>;
try
{
color source(128,128,128,255);
color dest(128,128,128,255);
unsigned cover = 128;
std::string expected_str = to_string(normal_blend(source,dest,cover));
REQUIRE( to_string(blend<source_over>(source,dest,cover)) == expected_str );
REQUIRE( to_string(blend<source_over_old_agg>(source,dest,cover)) == expected_str );
}
color white(255, 255, 255, 255);
color black(0, 0, 0, 255);
REQUIRE(to_string(blend<source_over>(white, white)) == to_string(white));
REQUIRE(to_string(blend<source_over>(white, black)) == to_string(white));
REQUIRE(to_string(blend<source_over>(black, white)) == to_string(black));
color near_white(254, 254, 254, 254); // Source
color near_trans(1, 1, 1, 1); // Dest
color expected_color(253, 253, 253, 255); // expected result
REQUIRE(to_string(blend<source_over_old_agg>(near_white, near_trans)) ==
to_string(color(253, 253, 253, 254)));
REQUIRE(to_string(blend<source_over>(near_white, near_trans)) == to_string(expected_color));
REQUIRE(to_string(normal_blend(near_white, near_trans)) == to_string(expected_color));
// using normal_blend as expected, compare a variety of other colors
{
color source(128, 128, 128, 255);
color dest(128, 128, 128, 255);
unsigned cover = 128;
std::string expected_str = to_string(normal_blend(source, dest, cover));
REQUIRE(to_string(blend<source_over>(source, dest, cover)) == expected_str);
REQUIRE(to_string(blend<source_over_old_agg>(source, dest, cover)) == expected_str);
}
{
color source(128, 128, 128, 255);
color dest(128, 128, 128, 255);
unsigned cover = 245;
std::string expected_str = to_string(normal_blend(source, dest, cover));
REQUIRE(to_string(blend<source_over>(source, dest, cover)) == expected_str);
REQUIRE(to_string(blend<source_over_old_agg>(source, dest, cover)) == expected_str);
}
// commenting until I study these failures more (dane)
/*
{
// fails, why?
color source(127,127,127,127);
color dest(127,127,127,127);
unsigned cover = 255;
std::string expected_str = to_string(normal_blend(source,dest,cover));
REQUIRE( to_string(blend<source_over>(source,dest,cover)) == expected_str );
REQUIRE( to_string(blend<source_over_old_agg>(source,dest,cover)) == expected_str );
}
{
// fails, why?
color source(128,128,128,128);
color dest(128,128,128,128);
unsigned cover = 128;
std::string expected_str = to_string(normal_blend(source,dest,cover));
REQUIRE( to_string(blend<source_over>(source,dest,cover)) == expected_str );
REQUIRE( to_string(blend<source_over_old_agg>(source,dest,cover)) == expected_str );
}
*/
} catch (std::exception const& ex)
{
color source(128,128,128,255);
color dest(128,128,128,255);
unsigned cover = 245;
std::string expected_str = to_string(normal_blend(source,dest,cover));
REQUIRE( to_string(blend<source_over>(source,dest,cover)) == expected_str );
REQUIRE( to_string(blend<source_over_old_agg>(source,dest,cover)) == expected_str );
std::clog << ex.what() << "\n";
REQUIRE(false);
}
// commenting until I study these failures more (dane)
/*
{
// fails, why?
color source(127,127,127,127);
color dest(127,127,127,127);
unsigned cover = 255;
std::string expected_str = to_string(normal_blend(source,dest,cover));
REQUIRE( to_string(blend<source_over>(source,dest,cover)) == expected_str );
REQUIRE( to_string(blend<source_over_old_agg>(source,dest,cover)) == expected_str );
}
{
// fails, why?
color source(128,128,128,128);
color dest(128,128,128,128);
unsigned cover = 128;
std::string expected_str = to_string(normal_blend(source,dest,cover));
REQUIRE( to_string(blend<source_over>(source,dest,cover)) == expected_str );
REQUIRE( to_string(blend<source_over_old_agg>(source,dest,cover)) == expected_str );
}
*/
}
catch (std::exception const & ex)
{
std::clog << ex.what() << "\n";
REQUIRE(false);
}
}
}

View file

@ -9,82 +9,106 @@
std::string get_file_contents(std::string const& filename)
{
std::ifstream in(filename.c_str(), std::ios::in | std::ios::binary);
if (in)
{
std::ostringstream contents;
contents << in.rdbuf();
in.close();
return(contents.str());
}
throw(errno);
std::ifstream in(filename.c_str(), std::ios::in | std::ios::binary);
if (in)
{
std::ostringstream contents;
contents << in.rdbuf();
in.close();
return (contents.str());
}
throw(errno);
}
TEST_CASE("palette")
{
SECTION("rgb")
{
mapnik::rgb a(1, 2, 3);
mapnik::rgba b_(1, 2, 3, 4);
mapnik::rgb b(b_);
mapnik::rgb c(3, 4, 5);
CHECK(a == b);
CHECK_FALSE(a == c);
SECTION("rgb")
{
mapnik::rgb a(1,2,3);
mapnik::rgba b_(1,2,3,4);
mapnik::rgb b(b_);
mapnik::rgb c(3,4,5);
CHECK(a == b);
CHECK_FALSE(a == c);
} // END SECTION
} // END SECTION
SECTION("rgba")
{
mapnik::rgba a(1, 2, 3, 4);
mapnik::rgba a_copy(1, 2, 3, 4);
mapnik::rgba b(255, 255, 255, 255);
mapnik::rgba c(4, 3, 2, 1);
mapnik::rgb d_(1, 2, 3);
mapnik::rgba d(d_);
mapnik::rgba e(16909060);
SECTION("rgba")
{
mapnik::rgba a(1,2,3,4);
mapnik::rgba a_copy(1,2,3,4);
mapnik::rgba b(255,255,255,255);
mapnik::rgba c(4,3,2,1);
mapnik::rgb d_(1,2,3);
mapnik::rgba d(d_);
CHECK(e.r == 4);
CHECK(e.g == 3);
CHECK(e.b == 2);
CHECK(e.a == 1);
mapnik::rgba e(16909060);
CHECK(a == a_copy);
CHECK_FALSE(a == c);
CHECK(c == e);
CHECK(e.r == 4);
CHECK(e.g == 3);
CHECK(e.b == 2);
CHECK(e.a == 1);
mapnik::rgba::mean_sort_cmp msc;
CHECK(a == a_copy);
CHECK_FALSE(a == c);
CHECK(c == e);
CHECK_FALSE(msc(a, a_copy));
CHECK(msc(a, b));
CHECK_FALSE(msc(a, c));
CHECK(msc(a, d));
mapnik::rgba::mean_sort_cmp msc;
} // END SECTION
CHECK_FALSE(msc(a,a_copy));
CHECK(msc(a,b));
CHECK_FALSE(msc(a,c));
CHECK(msc(a,d));
SECTION("rgba palette - exceptions and bad palettes")
{
REQUIRE_THROWS(mapnik::rgba_palette("foo"));
REQUIRE_THROWS(mapnik::rgba_palette("fooo", mapnik::rgba_palette::PALETTE_RGB));
REQUIRE_THROWS(mapnik::rgba_palette("foo", mapnik::rgba_palette::PALETTE_ACT));
} // END SECTION
} // END SECTION
SECTION("rgba palette - act pal_64")
{
std::string pal_64 = get_file_contents("./test/data/palettes/palette64.act");
mapnik::rgba_palette rgba_pal(pal_64, mapnik::rgba_palette::PALETTE_ACT);
CHECK(rgba_pal.to_string() ==
"[Palette 64 colors #494746 #c37631 #89827c #d1955c #7397b9 #fc9237 #a09f9c #fbc147 #9bb3ce #b7c9a1 "
"#b5d29c #c4b9aa #cdc4a5 #d5c8a3 #c1d7aa #ccc4b6 #dbd19c #b2c4d5 #eae487 #c9c8c6 #e4db99 #c9dcb5 #dfd3ac "
"#cbd2c2 #d6cdbc #dbd2b6 #c0ceda #ece597 #f7ef86 #d7d3c3 #dfcbc3 #d1d0cd #d1e2bf #d3dec1 #dbd3c4 #e6d8b6 "
"#f4ef91 #d3d3cf #cad5de #ded7c9 #dfdbce #fcf993 #ffff8a #dbd9d7 #dbe7cd #d4dce2 #e4ded3 #ebe3c9 #e0e2e2 "
"#f4edc3 #fdfcae #e9e5dc #f4edda #eeebe4 #fefdc5 #e7edf2 #edf4e5 #f2efe9 #f6ede7 #fefedd #f6f4f0 #f1f5f8 "
"#fbfaf8 #ffffff]");
SECTION("rgba palette - exceptions and bad palettes")
{
REQUIRE_THROWS(mapnik::rgba_palette("foo"));
REQUIRE_THROWS(mapnik::rgba_palette("fooo", mapnik::rgba_palette::PALETTE_RGB));
REQUIRE_THROWS(mapnik::rgba_palette("foo", mapnik::rgba_palette::PALETTE_ACT));
} // END SECTION
} // END SECTION
SECTION("rgba palette - act pal_64")
{
std::string pal_64 = get_file_contents("./test/data/palettes/palette64.act");
mapnik::rgba_palette rgba_pal(pal_64, mapnik::rgba_palette::PALETTE_ACT);
CHECK(rgba_pal.to_string() == "[Palette 64 colors #494746 #c37631 #89827c #d1955c #7397b9 #fc9237 #a09f9c #fbc147 #9bb3ce #b7c9a1 #b5d29c #c4b9aa #cdc4a5 #d5c8a3 #c1d7aa #ccc4b6 #dbd19c #b2c4d5 #eae487 #c9c8c6 #e4db99 #c9dcb5 #dfd3ac #cbd2c2 #d6cdbc #dbd2b6 #c0ceda #ece597 #f7ef86 #d7d3c3 #dfcbc3 #d1d0cd #d1e2bf #d3dec1 #dbd3c4 #e6d8b6 #f4ef91 #d3d3cf #cad5de #ded7c9 #dfdbce #fcf993 #ffff8a #dbd9d7 #dbe7cd #d4dce2 #e4ded3 #ebe3c9 #e0e2e2 #f4edc3 #fdfcae #e9e5dc #f4edda #eeebe4 #fefdc5 #e7edf2 #edf4e5 #f2efe9 #f6ede7 #fefedd #f6f4f0 #f1f5f8 #fbfaf8 #ffffff]");
SECTION("rgba palette - act pal_256")
{
std::string pal_ = get_file_contents("./test/data/palettes/palette256.act");
mapnik::rgba_palette rgba_pal(pal_, mapnik::rgba_palette::PALETTE_ACT);
CHECK(rgba_pal.to_string() ==
"[Palette 256 colors #272727 #3c3c3c #484847 #564b41 #605243 #6a523e #555555 #785941 #5d5d5d #746856 "
"#676767 #956740 #ba712e #787777 #cb752a #c27c3d #b68049 #dc8030 #df9e10 #878685 #e1a214 #928b82 #a88a70 "
"#ea8834 #e7a81d #cb8d55 #909090 #94938c #e18f48 #f68d36 #6f94b7 #e1ab2e #8e959b #c79666 #999897 #ff9238 "
"#ef9447 #a99a88 #f1b32c #919ca6 #a1a09f #f0b04b #8aa4bf #f8bc39 #b3ac8f #d1a67a #e3b857 #a8a8a7 #ffc345 "
"#a2adb9 #afaeab #f9ab69 #afbba4 #c4c48a #b4b2af #dec177 #9ab2cf #a3bebb #d7b491 #b6cd9e #b5d29c #b9c8a2 "
"#f1c969 #c5c79e #bbbab9 #cabdaa #a6bcd1 #cec4a7 #e7cc89 #dad98a #d5c9a3 #fabd8a #c1d7aa #cec5b4 #d1d1a5 "
"#d9cf9f #c5c4c3 #d3c7b5 #ddd59d #b4c6d6 #d1cbb4 #d1c7ba #d7d1aa #e1c6ab #cbc7c2 #dbd0a9 #e8e58a #fee178 "
"#d3cbba #dfd7a3 #d2cfb9 #c9ddb5 #d2cbbe #c3cbce #d7cbba #dcceb2 #dfd3aa #e5dd9a #dbd3b1 #ceccc6 #d7cbbe "
"#d7cfba #dfc3be #dfd3ae #cbcbcb #cbd3c3 #d3cfc0 #e0d8aa #d7cfbe #dbd3b8 #ebe596 #dfd8b0 #c0ceda #f1ee89 "
"#decfbc #d7cfc4 #d7d3c3 #d1d0cd #d2dfc0 #dbd3c3 #e7c7c3 #e7d7b3 #f2ed92 #d1e2bf #dad7c3 #fef383 #d3d3cf "
"#dbd3c7 #e0d3c2 #dfd7c0 #ebe4a8 #dbd7c7 #dfd3c7 #f7f38f #c9d4de #dcdcc5 #dfd7c7 #e7d5c2 #d6d5d4 #faf78e "
"#d7dfca #fbfb8a #fffb86 #dfd7cb #e5ddc0 #dad7d2 #ecd6c1 #cfd7de #e8d0cc #fbfb8e #fffb8a #eae3b8 #e3d7cd "
"#dfdbce #fffb8e #ffff8a #f5efa6 #dae6cc #e3dbcf #edddc3 #dddbd6 #d5dbdf #ffff91 #e3dbd3 #fefc99 #e7dbd2 "
"#eaddcd #e3dfd3 #ebd7d3 #dddddd #d4dee6 #e2dfd7 #fcdcc0 #e7dbd7 #e7dfd3 #ebe4cb #f4eeb8 #e3dfdb #e7dfd7 "
"#ebded5 #e7e3d7 #fefea6 #e1ecd6 #ece5d3 #e7e3db #dee3e5 #ebe3db #efdfdb #efe3d8 #f4efc9 #e6ecdb #ebe3df "
"#ebe7db #f0ecd3 #e5e6e5 #efe7da #ebe7df #efe3df #fefeb8 #dfe7ef #ebe7e3 #edebde #efe7e0 #e8efe0 #e7f3df "
"#ebebe3 #e7ebe8 #f5edd9 #efebe3 #e3ebf1 #e9efe7 #ebebea #efebe7 #f0efe2 #ecf3e5 #fefdc9 #efefe7 #f3efe7 "
"#f5f3e1 #f2efe9 #e9eef4 #ffeddf #efefef #f3efeb #f3f3eb #f0f7eb #fbf7e1 #fefed8 #f3f3ef #f7f3eb #eef3f7 "
"#f7f7ea #f3f3f3 #f3f7ef #f7f3ef #f3f3f7 #f7f3f3 #f7f7ef #fffee3 #f3f7f7 #f7f7f3 #fcf7ee #f7f7f7 #f7fbf4 "
"#f5f7fb #fbf7f6 #fffeef #f7fbfb #fbfbf7 #fbfbfb #fbfbff #fbfffb #fffbfb #fbffff #fffffb #ffffff]");
} // END SECTION
SECTION("rgba palette - act pal_256")
{
std::string pal_ = get_file_contents("./test/data/palettes/palette256.act");
mapnik::rgba_palette rgba_pal(pal_, mapnik::rgba_palette::PALETTE_ACT);
CHECK(rgba_pal.to_string() == "[Palette 256 colors #272727 #3c3c3c #484847 #564b41 #605243 #6a523e #555555 #785941 #5d5d5d #746856 #676767 #956740 #ba712e #787777 #cb752a #c27c3d #b68049 #dc8030 #df9e10 #878685 #e1a214 #928b82 #a88a70 #ea8834 #e7a81d #cb8d55 #909090 #94938c #e18f48 #f68d36 #6f94b7 #e1ab2e #8e959b #c79666 #999897 #ff9238 #ef9447 #a99a88 #f1b32c #919ca6 #a1a09f #f0b04b #8aa4bf #f8bc39 #b3ac8f #d1a67a #e3b857 #a8a8a7 #ffc345 #a2adb9 #afaeab #f9ab69 #afbba4 #c4c48a #b4b2af #dec177 #9ab2cf #a3bebb #d7b491 #b6cd9e #b5d29c #b9c8a2 #f1c969 #c5c79e #bbbab9 #cabdaa #a6bcd1 #cec4a7 #e7cc89 #dad98a #d5c9a3 #fabd8a #c1d7aa #cec5b4 #d1d1a5 #d9cf9f #c5c4c3 #d3c7b5 #ddd59d #b4c6d6 #d1cbb4 #d1c7ba #d7d1aa #e1c6ab #cbc7c2 #dbd0a9 #e8e58a #fee178 #d3cbba #dfd7a3 #d2cfb9 #c9ddb5 #d2cbbe #c3cbce #d7cbba #dcceb2 #dfd3aa #e5dd9a #dbd3b1 #ceccc6 #d7cbbe #d7cfba #dfc3be #dfd3ae #cbcbcb #cbd3c3 #d3cfc0 #e0d8aa #d7cfbe #dbd3b8 #ebe596 #dfd8b0 #c0ceda #f1ee89 #decfbc #d7cfc4 #d7d3c3 #d1d0cd #d2dfc0 #dbd3c3 #e7c7c3 #e7d7b3 #f2ed92 #d1e2bf #dad7c3 #fef383 #d3d3cf #dbd3c7 #e0d3c2 #dfd7c0 #ebe4a8 #dbd7c7 #dfd3c7 #f7f38f #c9d4de #dcdcc5 #dfd7c7 #e7d5c2 #d6d5d4 #faf78e #d7dfca #fbfb8a #fffb86 #dfd7cb #e5ddc0 #dad7d2 #ecd6c1 #cfd7de #e8d0cc #fbfb8e #fffb8a #eae3b8 #e3d7cd #dfdbce #fffb8e #ffff8a #f5efa6 #dae6cc #e3dbcf #edddc3 #dddbd6 #d5dbdf #ffff91 #e3dbd3 #fefc99 #e7dbd2 #eaddcd #e3dfd3 #ebd7d3 #dddddd #d4dee6 #e2dfd7 #fcdcc0 #e7dbd7 #e7dfd3 #ebe4cb #f4eeb8 #e3dfdb #e7dfd7 #ebded5 #e7e3d7 #fefea6 #e1ecd6 #ece5d3 #e7e3db #dee3e5 #ebe3db #efdfdb #efe3d8 #f4efc9 #e6ecdb #ebe3df #ebe7db #f0ecd3 #e5e6e5 #efe7da #ebe7df #efe3df #fefeb8 #dfe7ef #ebe7e3 #edebde #efe7e0 #e8efe0 #e7f3df #ebebe3 #e7ebe8 #f5edd9 #efebe3 #e3ebf1 #e9efe7 #ebebea #efebe7 #f0efe2 #ecf3e5 #fefdc9 #efefe7 #f3efe7 #f5f3e1 #f2efe9 #e9eef4 #ffeddf #efefef #f3efeb #f3f3eb #f0f7eb #fbf7e1 #fefed8 #f3f3ef #f7f3eb #eef3f7 #f7f7ea #f3f3f3 #f3f7ef #f7f3ef #f3f3f7 #f7f3f3 #f7f7ef #fffee3 #f3f7f7 #f7f7f3 #fcf7ee #f7f7f7 #f7fbf4 #f5f7fb #fbf7f6 #fffeef #f7fbfb #fbfbf7 #fbfbfb #fbfbff #fbfffb #fffbfb #fbffff #fffffb #ffffff]");
} // END SECTION
} // END SECTION
} // END TEST CASE

View file

@ -8,276 +8,265 @@
TEST_CASE("projection transform")
{
SECTION("Test bounding box transforms - 4326 to 3857")
{
mapnik::projection proj_4326("epsg:4326");
mapnik::projection proj_3857("epsg:3857");
CHECK(proj_4326.is_geographic());
CHECK(!proj_3857.is_geographic());
mapnik::proj_transform prj_trans(proj_4326, proj_3857);
double minx = -45.0;
double miny = 55.0;
double maxx = -40.0;
double maxy = 75.0;
mapnik::box2d<double> bbox(minx, miny, maxx, maxy);
INFO(bbox.to_string());
CHECKED_IF(prj_trans.forward(bbox))
SECTION("Test bounding box transforms - 4326 to 3857")
{
CHECK(bbox.minx() == Approx(-5009377.085697311));
CHECK(bbox.miny() == Approx(7361866.1130511891));
CHECK(bbox.maxx() == Approx(-4452779.631730943));
CHECK(bbox.maxy() == Approx(12932243.1119920239));
}
mapnik::projection proj_4326("epsg:4326");
mapnik::projection proj_3857("epsg:3857");
CHECKED_IF(prj_trans.backward(bbox))
{
CHECK(bbox.minx() == Approx(minx));
CHECK(bbox.miny() == Approx(miny));
CHECK(bbox.maxx() == Approx(maxx));
CHECK(bbox.maxy() == Approx(maxy));
}
}
CHECK(proj_4326.is_geographic());
CHECK(!proj_3857.is_geographic());
mapnik::proj_transform prj_trans(proj_4326, proj_3857);
double minx = -45.0;
double miny = 55.0;
double maxx = -40.0;
double maxy = 75.0;
mapnik::box2d<double> bbox(minx, miny, maxx, maxy);
INFO(bbox.to_string());
CHECKED_IF(prj_trans.forward(bbox))
{
CHECK(bbox.minx() == Approx(-5009377.085697311));
CHECK(bbox.miny() == Approx(7361866.1130511891));
CHECK(bbox.maxx() == Approx(-4452779.631730943));
CHECK(bbox.maxy() == Approx(12932243.1119920239));
}
CHECKED_IF(prj_trans.backward(bbox))
{
CHECK(bbox.minx() == Approx(minx));
CHECK(bbox.miny() == Approx(miny));
CHECK(bbox.maxx() == Approx(maxx));
CHECK(bbox.maxy() == Approx(maxy));
}
}
#if defined(MAPNIK_USE_PROJ)
SECTION("test proj_transform failure behavior")
{
mapnik::projection proj_4269("epsg:4269");
mapnik::projection proj_3857("epsg:3857");
mapnik::proj_transform prj_trans(proj_4269, proj_3857);
mapnik::proj_transform prj_trans2(proj_3857, proj_4269);
// test valid coordinate
double x0 = -180.0;
double y0 = -60.0;
CHECK( prj_trans.forward(&x0,&y0,nullptr,1,1) );
CHECK( x0 == Approx(-20037508.3427892439) );
CHECK( y0 == Approx(-8399737.8896366451) );
double x1 = -180.0;
double y1 = -60.0;
CHECK( prj_trans2.backward(&x1,&y1,nullptr,1,1) );
CHECK( x1 == Approx(-20037508.3427892439) );
CHECK( y1 == Approx(-8399737.8896366451) );
// now test invalid coordinate
double x2 = -181.0;
double y2 = -91.0;
prj_trans.forward(&x2,&y2,nullptr,1,1);
CHECK( std::isinf(x2) );
CHECK( std::isinf(y2) );
double x3 = -181.0;
double y3 = -91.0;
prj_trans2.backward(&x3,&y3,nullptr,1,1);
CHECK( std::isinf(x3) );
CHECK( std::isinf(y3) );
}
SECTION("test forward/backward transformations")
{
//WGS 84 - World Geodetic System 1984, used in GPS
mapnik::projection proj_4236("epsg:4236");
//OSGB 1936 / British National Grid -- United Kingdom Ordnance Survey
mapnik::projection proj_27700("epsg:27700");
//WGS 84 / Equal Earth Greenwich
mapnik::projection proj_8857("epsg:8857");
//European Terrestrial Reference System 1989 (ETRS89)
mapnik::projection proj_4937("epsg:4937");
//"Webmercator" WGS 84 / Pseudo-Mercator -- Spherical Mercator, Google Maps, OpenStreetMap, Bing, ArcGIS, ESRI
mapnik::projection proj_3857("epsg:3857");
mapnik::proj_transform tr1(proj_4236, proj_27700);
mapnik::proj_transform tr2(proj_4236, proj_8857);
mapnik::proj_transform tr3(proj_4236, proj_4236);
mapnik::proj_transform tr4(proj_4236, proj_4937);
mapnik::proj_transform tr5(proj_4236, proj_3857);
std::initializer_list<std::reference_wrapper<mapnik::proj_transform>> transforms = {
tr1, tr2, tr3, tr4, tr5
};
std::initializer_list<std::tuple<double, double>> coords = {
{-4.0278869, 57.8796955}, // Dórnach, Highland
{-4.2488787, 55.8609825}, // Glaschú, Alba
{-1.4823897, 51.8726941}, // Charlbury, England
{-3.9732612, 51.7077400} // Felindre, Cymru
};
for (auto const& c : coords)
SECTION("test proj_transform failure behavior")
{
double x0, y0;
std::tie(x0, y0) = c;
for (mapnik::proj_transform const& tr : transforms)
{
double x1 = x0;
double y1 = y0;
tr.forward (&x1, &y1, nullptr, 1, 1);
tr.backward(&x1, &y1, nullptr, 1, 1);
CHECK (x0 == Approx(x1));
CHECK (y0 == Approx(y1));
}
mapnik::projection proj_4269("epsg:4269");
mapnik::projection proj_3857("epsg:3857");
mapnik::proj_transform prj_trans(proj_4269, proj_3857);
mapnik::proj_transform prj_trans2(proj_3857, proj_4269);
// test valid coordinate
double x0 = -180.0;
double y0 = -60.0;
CHECK(prj_trans.forward(&x0, &y0, nullptr, 1, 1));
CHECK(x0 == Approx(-20037508.3427892439));
CHECK(y0 == Approx(-8399737.8896366451));
double x1 = -180.0;
double y1 = -60.0;
CHECK(prj_trans2.backward(&x1, &y1, nullptr, 1, 1));
CHECK(x1 == Approx(-20037508.3427892439));
CHECK(y1 == Approx(-8399737.8896366451));
// now test invalid coordinate
double x2 = -181.0;
double y2 = -91.0;
prj_trans.forward(&x2, &y2, nullptr, 1, 1);
CHECK(std::isinf(x2));
CHECK(std::isinf(y2));
double x3 = -181.0;
double y3 = -91.0;
prj_trans2.backward(&x3, &y3, nullptr, 1, 1);
CHECK(std::isinf(x3));
CHECK(std::isinf(y3));
}
}
// Github Issue https://github.com/mapnik/mapnik/issues/2648
SECTION("Test proj antimeridian bbox")
{
mapnik::projection prj_geog("epsg:4326");
mapnik::projection prj_proj("epsg:2193");
mapnik::proj_transform prj_trans_fwd(prj_proj, prj_geog);
mapnik::proj_transform prj_trans_rev(prj_geog, prj_proj);
// reference values taken from proj4 command line tool:
// (non-corner points assume PROJ_ENVELOPE_POINTS == 20)
//
// cs2cs -Ef %.10f epsg:2193 +to epsg:4326 <<END
// 2105800 3087000 # left-most
// 1495200 3087000 # bottom-most
// 2105800 7173000 # right-most
// 3327000 7173000 # top-most
// END
//
// wrong = mapnik.Box2d(-177.3145325044, -62.3337481525,
// 178.0277836332, -24.5845974912)
const mapnik::box2d<double> better(-180.0, -62.3337481525,
180.0, -24.5845974912);
SECTION("test forward/backward transformations")
{
mapnik::box2d<double> ext(274000, 3087000, 3327000, 7173000);
CHECKED_IF(prj_trans_fwd.forward(ext, PROJ_ENVELOPE_POINTS))
// WGS 84 - World Geodetic System 1984, used in GPS
mapnik::projection proj_4236("epsg:4236");
// OSGB 1936 / British National Grid -- United Kingdom Ordnance Survey
mapnik::projection proj_27700("epsg:27700");
// WGS 84 / Equal Earth Greenwich
mapnik::projection proj_8857("epsg:8857");
// European Terrestrial Reference System 1989 (ETRS89)
mapnik::projection proj_4937("epsg:4937");
//"Webmercator" WGS 84 / Pseudo-Mercator -- Spherical Mercator, Google Maps, OpenStreetMap, Bing, ArcGIS, ESRI
mapnik::projection proj_3857("epsg:3857");
mapnik::proj_transform tr1(proj_4236, proj_27700);
mapnik::proj_transform tr2(proj_4236, proj_8857);
mapnik::proj_transform tr3(proj_4236, proj_4236);
mapnik::proj_transform tr4(proj_4236, proj_4937);
mapnik::proj_transform tr5(proj_4236, proj_3857);
std::initializer_list<std::reference_wrapper<mapnik::proj_transform>> transforms = {tr1, tr2, tr3, tr4, tr5};
std::initializer_list<std::tuple<double, double>> coords = {
{-4.0278869, 57.8796955}, // Dórnach, Highland
{-4.2488787, 55.8609825}, // Glaschú, Alba
{-1.4823897, 51.8726941}, // Charlbury, England
{-3.9732612, 51.7077400} // Felindre, Cymru
};
for (auto const& c : coords)
{
CHECK(ext.minx() == Approx(better.minx()));
CHECK(ext.miny() == Approx(better.miny()));
CHECK(ext.maxx() == Approx(better.maxx()));
CHECK(ext.maxy() == Approx(better.maxy()));
double x0, y0;
std::tie(x0, y0) = c;
for (mapnik::proj_transform const& tr : transforms)
{
double x1 = x0;
double y1 = y0;
tr.forward(&x1, &y1, nullptr, 1, 1);
tr.backward(&x1, &y1, nullptr, 1, 1);
CHECK(x0 == Approx(x1));
CHECK(y0 == Approx(y1));
}
}
}
// Github Issue https://github.com/mapnik/mapnik/issues/2648
SECTION("Test proj antimeridian bbox")
{
// check the same logic works for .backward()
mapnik::box2d<double> ext(274000, 3087000, 3327000, 7173000);
CHECKED_IF(prj_trans_rev.backward(ext, PROJ_ENVELOPE_POINTS))
mapnik::projection prj_geog("epsg:4326");
mapnik::projection prj_proj("epsg:2193");
mapnik::proj_transform prj_trans_fwd(prj_proj, prj_geog);
mapnik::proj_transform prj_trans_rev(prj_geog, prj_proj);
// reference values taken from proj4 command line tool:
// (non-corner points assume PROJ_ENVELOPE_POINTS == 20)
//
// cs2cs -Ef %.10f epsg:2193 +to epsg:4326 <<END
// 2105800 3087000 # left-most
// 1495200 3087000 # bottom-most
// 2105800 7173000 # right-most
// 3327000 7173000 # top-most
// END
//
// wrong = mapnik.Box2d(-177.3145325044, -62.3337481525,
// 178.0277836332, -24.5845974912)
const mapnik::box2d<double> better(-180.0, -62.3337481525, 180.0, -24.5845974912);
{
CHECK(ext.minx() == Approx(better.minx()));
CHECK(ext.miny() == Approx(better.miny()));
CHECK(ext.maxx() == Approx(better.maxx()));
CHECK(ext.maxy() == Approx(better.maxy()));
mapnik::box2d<double> ext(274000, 3087000, 3327000, 7173000);
CHECKED_IF(prj_trans_fwd.forward(ext, PROJ_ENVELOPE_POINTS))
{
CHECK(ext.minx() == Approx(better.minx()));
CHECK(ext.miny() == Approx(better.miny()));
CHECK(ext.maxx() == Approx(better.maxx()));
CHECK(ext.maxy() == Approx(better.maxy()));
}
}
{
// check the same logic works for .backward()
mapnik::box2d<double> ext(274000, 3087000, 3327000, 7173000);
CHECKED_IF(prj_trans_rev.backward(ext, PROJ_ENVELOPE_POINTS))
{
CHECK(ext.minx() == Approx(better.minx()));
CHECK(ext.miny() == Approx(better.miny()));
CHECK(ext.maxx() == Approx(better.maxx()));
CHECK(ext.maxy() == Approx(better.maxy()));
}
}
// reference values taken from proj4 command line tool:
//
// cs2cs -Ef %.10f epsg:2193 +to epsg:4326 <<END
// 274000 3087000 # left-most
// 276000 3087000 # bottom-most
// 276000 7173000 # right-most
// 274000 7173000 # top-most
// END
//
const mapnik::box2d<double> normal(148.7639922894, -60.1222810241, 159.9548489296, -24.9771195155);
{
// checks for not being snapped (ie. not antimeridian)
mapnik::box2d<double> ext(274000, 3087000, 276000, 7173000);
CHECKED_IF(prj_trans_fwd.forward(ext, PROJ_ENVELOPE_POINTS))
{
CHECK(ext.minx() == Approx(normal.minx()));
CHECK(ext.miny() == Approx(normal.miny()));
CHECK(ext.maxx() == Approx(normal.maxx()));
CHECK(ext.maxy() == Approx(normal.maxy()));
}
}
{
// check the same logic works for .backward()
mapnik::box2d<double> ext(274000, 3087000, 276000, 7173000);
CHECKED_IF(prj_trans_rev.backward(ext, PROJ_ENVELOPE_POINTS))
{
CHECK(ext.minx() == Approx(normal.minx()));
CHECK(ext.miny() == Approx(normal.miny()));
CHECK(ext.maxx() == Approx(normal.maxx()));
CHECK(ext.maxy() == Approx(normal.maxy()));
}
}
}
// reference values taken from proj4 command line tool:
//
// cs2cs -Ef %.10f epsg:2193 +to epsg:4326 <<END
// 274000 3087000 # left-most
// 276000 3087000 # bottom-most
// 276000 7173000 # right-most
// 274000 7173000 # top-most
// END
//
const mapnik::box2d<double> normal(148.7639922894, -60.1222810241,
159.9548489296, -24.9771195155);
{
// checks for not being snapped (ie. not antimeridian)
mapnik::box2d<double> ext(274000, 3087000, 276000, 7173000);
CHECKED_IF(prj_trans_fwd.forward(ext, PROJ_ENVELOPE_POINTS))
{
CHECK(ext.minx() == Approx(normal.minx()));
CHECK(ext.miny() == Approx(normal.miny()));
CHECK(ext.maxx() == Approx(normal.maxx()));
CHECK(ext.maxy() == Approx(normal.maxy()));
}
}
{
// check the same logic works for .backward()
mapnik::box2d<double> ext(274000, 3087000, 276000, 7173000);
CHECKED_IF(prj_trans_rev.backward(ext, PROJ_ENVELOPE_POINTS))
{
CHECK(ext.minx() == Approx(normal.minx()));
CHECK(ext.miny() == Approx(normal.miny()));
CHECK(ext.maxx() == Approx(normal.maxx()));
CHECK(ext.maxy() == Approx(normal.maxy()));
}
}
}
#endif
SECTION("proj_transform of coordinate arrays with stride > 1")
{
mapnik::projection const proj_4326("epsg:4326");
mapnik::projection const proj_3857("epsg:3857");
mapnik::projection const proj_2193("epsg:2193");
SECTION("lonlat <-> Web Mercator")
SECTION("proj_transform of coordinate arrays with stride > 1")
{
// cs2cs -Ef %.10f epsg:4326 +to epsg:3857 <<END
// 170.142139 -43.595056
// 175.566667 -39.283333
// END
//
// 170.142139 -43.595056 18940136.2759583741 -5402988.5324898539
// 175.566667 -39.283333 19543991.9707122259 -4762338.2380718365
//
mapnik::geometry::point<double> points[] = {{ 170.142139, -43.595056 },
{ 175.566667, -39.283333 }};
// this transform is calculated by Mapnik (well_known_srs.cpp)
mapnik::proj_transform lonlat_to_webmerc(proj_4326, proj_3857);
CHECKED_IF(lonlat_to_webmerc.forward(&points[0].x, &points[0].y, nullptr, 2, 2))
mapnik::projection const proj_4326("epsg:4326");
mapnik::projection const proj_3857("epsg:3857");
mapnik::projection const proj_2193("epsg:2193");
SECTION("lonlat <-> Web Mercator")
{
CHECK(points[0].x == Approx(18940136.2759583741));
CHECK(points[0].y == Approx(-5402988.5324898539));
CHECK(points[1].x == Approx(19543991.9707122259));
CHECK(points[1].y == Approx(-4762338.2380718365));
// cs2cs -Ef %.10f epsg:4326 +to epsg:3857 <<END
// 170.142139 -43.595056
// 175.566667 -39.283333
// END
//
// 170.142139 -43.595056 18940136.2759583741 -5402988.5324898539
// 175.566667 -39.283333 19543991.9707122259 -4762338.2380718365
//
mapnik::geometry::point<double> points[] = {{170.142139, -43.595056}, {175.566667, -39.283333}};
// this transform is calculated by Mapnik (well_known_srs.cpp)
mapnik::proj_transform lonlat_to_webmerc(proj_4326, proj_3857);
CHECKED_IF(lonlat_to_webmerc.forward(&points[0].x, &points[0].y, nullptr, 2, 2))
{
CHECK(points[0].x == Approx(18940136.2759583741));
CHECK(points[0].y == Approx(-5402988.5324898539));
CHECK(points[1].x == Approx(19543991.9707122259));
CHECK(points[1].y == Approx(-4762338.2380718365));
}
CHECKED_IF(lonlat_to_webmerc.backward(&points[0].x, &points[0].y, nullptr, 2, 2))
{
CHECK(points[0].x == Approx(170.142139));
CHECK(points[0].y == Approx(-43.595056));
CHECK(points[1].x == Approx(175.566667));
CHECK(points[1].y == Approx(-39.283333));
}
}
CHECKED_IF(lonlat_to_webmerc.backward(&points[0].x, &points[0].y, nullptr, 2, 2))
{
CHECK(points[0].x == Approx(170.142139));
CHECK(points[0].y == Approx(-43.595056));
CHECK(points[1].x == Approx(175.566667));
CHECK(points[1].y == Approx(-39.283333));
}
}
#ifdef MAPNIK_USE_PROJ
SECTION("lonlat <-> New Zealand Transverse Mercator 2000")
{
mapnik::projection const proj_2193("epsg:2193");
// cs2cs -Ef %.10f epsg:4326 +to epsg:2193 <<END
// 170.142139 -43.595056
// 175.566667 -39.283333
// END
//
// 170.142139 -43.595056 1369316.0970041484 5169132.9750701785
// 175.566667 -39.283333 1821377.9170061364 5648640.2106032455
//
mapnik::geometry::point<double> points[] = {{ 170.142139, -43.595056 },
{ 175.566667, -39.283333 }};
// this transform is not calculated by Mapnik (needs Proj4)
mapnik::proj_transform lonlat_to_nztm(proj_4326, proj_2193);
CHECKED_IF(lonlat_to_nztm.forward(&points[0].x, &points[0].y, nullptr, 2, 2))
SECTION("lonlat <-> New Zealand Transverse Mercator 2000")
{
CHECK(points[0].x == Approx(1369316.0970041484));
CHECK(points[0].y == Approx(5169132.9750701785));
CHECK(points[1].x == Approx(1821377.9170061364));
CHECK(points[1].y == Approx(5648640.2106032455));
mapnik::projection const proj_2193("epsg:2193");
// cs2cs -Ef %.10f epsg:4326 +to epsg:2193 <<END
// 170.142139 -43.595056
// 175.566667 -39.283333
// END
//
// 170.142139 -43.595056 1369316.0970041484 5169132.9750701785
// 175.566667 -39.283333 1821377.9170061364 5648640.2106032455
//
mapnik::geometry::point<double> points[] = {{170.142139, -43.595056}, {175.566667, -39.283333}};
// this transform is not calculated by Mapnik (needs Proj4)
mapnik::proj_transform lonlat_to_nztm(proj_4326, proj_2193);
CHECKED_IF(lonlat_to_nztm.forward(&points[0].x, &points[0].y, nullptr, 2, 2))
{
CHECK(points[0].x == Approx(1369316.0970041484));
CHECK(points[0].y == Approx(5169132.9750701785));
CHECK(points[1].x == Approx(1821377.9170061364));
CHECK(points[1].y == Approx(5648640.2106032455));
}
CHECKED_IF(lonlat_to_nztm.backward(&points[0].x, &points[0].y, nullptr, 2, 2))
{
CHECK(points[0].x == Approx(170.142139));
CHECK(points[0].y == Approx(-43.595056));
CHECK(points[1].x == Approx(175.566667));
CHECK(points[1].y == Approx(-39.283333));
}
}
CHECKED_IF(lonlat_to_nztm.backward(&points[0].x, &points[0].y, nullptr, 2, 2))
{
CHECK(points[0].x == Approx(170.142139));
CHECK(points[0].y == Approx(-43.595056));
CHECK(points[1].x == Approx(175.566667));
CHECK(points[1].y == Approx(-39.283333));
}
}
#endif // MAPNIK_USE_PROJ
}
}
}

View file

@ -14,12 +14,11 @@
class test_datasource : public mapnik::memory_datasource
{
public:
public:
test_datasource(mapnik::box2d<double> const& expected_query_bbox)
: mapnik::memory_datasource(prepare_params()),
expected_query_bbox_(expected_query_bbox)
{
}
: mapnik::memory_datasource(prepare_params())
, expected_query_bbox_(expected_query_bbox)
{}
virtual mapnik::featureset_ptr features(mapnik::query const& q) const
{
@ -31,7 +30,7 @@ public:
return mapnik::memory_datasource::features(q);
}
private:
private:
mapnik::parameters prepare_params() const
{
mapnik::parameters params;
@ -42,58 +41,55 @@ private:
mapnik::box2d<double> expected_query_bbox_;
};
TEST_CASE("feature_style_processor: buffer-size with scale-factor") {
SECTION("query extent with buffer-size should not be affected by scale-factor") {
const mapnik::box2d<double> expected_query_bbox(-0.5, -0.5, 1.5, 1.5);
using datasource_ptr = std::shared_ptr<test_datasource>;
datasource_ptr datasource = std::make_shared<test_datasource>(
expected_query_bbox);
mapnik::context_ptr ctx = std::make_shared<mapnik::context_type>();
TEST_CASE("feature_style_processor: buffer-size with scale-factor")
{
SECTION("query extent with buffer-size should not be affected by scale-factor")
{
mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx, 2));
mapnik::geometry::line_string<double> path;
path.emplace_back(-10, -10);
path.emplace_back(10, 10);
feature->set_geometry(std::move(path));
datasource->push(feature);
}
const mapnik::box2d<double> expected_query_bbox(-0.5, -0.5, 1.5, 1.5);
mapnik::Map map(256, 256);
map.set_buffer_size(128);
using datasource_ptr = std::shared_ptr<test_datasource>;
datasource_ptr datasource = std::make_shared<test_datasource>(expected_query_bbox);
mapnik::context_ptr ctx = std::make_shared<mapnik::context_type>();
{
mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx, 2));
mapnik::geometry::line_string<double> path;
path.emplace_back(-10, -10);
path.emplace_back(10, 10);
feature->set_geometry(std::move(path));
datasource->push(feature);
}
mapnik::feature_type_style lines_style;
mapnik::rule rule;
mapnik::line_symbolizer line_sym;
rule.append(std::move(line_sym));
lines_style.add_rule(std::move(rule));
map.insert_style("lines", std::move(lines_style));
mapnik::Map map(256, 256);
map.set_buffer_size(128);
mapnik::layer lyr("layer");
lyr.set_datasource(datasource);
lyr.add_style("lines");
map.add_layer(lyr);
mapnik::feature_type_style lines_style;
mapnik::rule rule;
mapnik::line_symbolizer line_sym;
rule.append(std::move(line_sym));
lines_style.add_rule(std::move(rule));
map.insert_style("lines", std::move(lines_style));
const mapnik::box2d<double> map_extent(0, 0, 1, 1);
map.zoom_to_box(map_extent);
mapnik::layer lyr("layer");
lyr.set_datasource(datasource);
lyr.add_style("lines");
map.add_layer(lyr);
{
mapnik::image_rgba8 image(map.width(), map.height());
mapnik::agg_renderer<mapnik::image_rgba8> ren(map, image);
ren.apply();
}
const mapnik::box2d<double> map_extent(0, 0, 1, 1);
map.zoom_to_box(map_extent);
{
// Rendering with scale-factor 2.0 should query data
// with the same extent as with scale-factor 1.0.
map.resize(map.width() * 2, map.height() * 2);
mapnik::image_rgba8 image(map.width(), map.height());
mapnik::agg_renderer<mapnik::image_rgba8> ren(map, image, 2.0);
ren.apply();
{
mapnik::image_rgba8 image(map.width(), map.height());
mapnik::agg_renderer<mapnik::image_rgba8> ren(map, image);
ren.apply();
}
{
// Rendering with scale-factor 2.0 should query data
// with the same extent as with scale-factor 1.0.
map.resize(map.width() * 2, map.height() * 2);
mapnik::image_rgba8 image(map.width(), map.height());
mapnik::agg_renderer<mapnik::image_rgba8> ren(map, image, 2.0);
ren.apply();
}
}
}
}

View file

@ -12,24 +12,24 @@ MAPNIK_DISABLE_WARNING_POP
#include <fstream>
#if defined(HAVE_CAIRO)
TEST_CASE("cairo_io") {
TEST_CASE("cairo_io")
{
SECTION("save_to_cairo_file - SVG")
{
std::string directory_name("/tmp/mapnik-tests/");
boost::filesystem::create_directories(directory_name);
REQUIRE(mapnik::util::exists(directory_name));
SECTION("save_to_cairo_file - SVG") {
std::string directory_name("/tmp/mapnik-tests/");
boost::filesystem::create_directories(directory_name);
REQUIRE(mapnik::util::exists(directory_name));
std::string output_file(directory_name + "test_save_to_cairo_file.svg");
std::string output_file(directory_name + "test_save_to_cairo_file.svg");
mapnik::Map map(256, 256);
mapnik::save_to_cairo_file(map, output_file);
mapnik::Map map(256, 256);
mapnik::save_to_cairo_file(map, output_file);
std::ifstream stream(output_file, std::ios_base::in | std::ios_base::binary);
std::string actual_output(std::istreambuf_iterator<char>(stream.rdbuf()), std::istreambuf_iterator<char>());
// Check the Cairo SVG surface is using SVG 1.2
CHECK(actual_output.find("version=\"1.2\"") != std::string::npos);
}
std::ifstream stream(output_file, std::ios_base::in | std::ios_base::binary);
std::string actual_output(std::istreambuf_iterator<char>(stream.rdbuf()), std::istreambuf_iterator<char>());
// Check the Cairo SVG surface is using SVG 1.2
CHECK(actual_output.find("version=\"1.2\"") != std::string::npos);
}
}
#endif

View file

@ -29,85 +29,57 @@ struct rendering_result
class test_renderer : public mapnik::feature_style_processor<test_renderer>
{
public:
public:
using processor_impl_type = test_renderer;
test_renderer(mapnik::Map const& map, rendering_result & result)
: mapnik::feature_style_processor<test_renderer>(map),
result_(result),
painted_(false),
vars_()
{
}
test_renderer(mapnik::Map const& map, rendering_result& result)
: mapnik::feature_style_processor<test_renderer>(map)
, result_(result)
, painted_(false)
, vars_()
{}
void start_map_processing(mapnik::Map const& map)
{
result_.start_map_processing++;
}
void start_map_processing(mapnik::Map const& map) { result_.start_map_processing++; }
void end_map_processing(mapnik::Map const& map)
{
result_.end_map_processing++;
}
void end_map_processing(mapnik::Map const& map) { result_.end_map_processing++; }
void start_layer_processing(mapnik::layer const& lay, mapnik::box2d<double> const& query_extent)
{
result_.layer_query_extents.push_back(query_extent);
}
void end_layer_processing(mapnik::layer const& lay)
{
result_.end_layer_processing++;
}
void end_layer_processing(mapnik::layer const& lay) { result_.end_layer_processing++; }
void start_style_processing(mapnik::feature_type_style const& st)
{
result_.start_style_processing++;
}
void start_style_processing(mapnik::feature_type_style const& st) { result_.start_style_processing++; }
void end_style_processing(mapnik::feature_type_style const& st)
{
result_.end_style_processing++;
}
void end_style_processing(mapnik::feature_type_style const& st) { result_.end_style_processing++; }
template <typename Symbolizer>
void process(Symbolizer const& sym, mapnik::feature_impl & feature, mapnik::proj_transform const& prj_trans)
template<typename Symbolizer>
void process(Symbolizer const& sym, mapnik::feature_impl& feature, mapnik::proj_transform const& prj_trans)
{
result_.geometries.push_back(feature.get_geometry());
}
bool process(mapnik::rule::symbolizers const&, mapnik::feature_impl&, mapnik::proj_transform const& )
bool process(mapnik::rule::symbolizers const&, mapnik::feature_impl&, mapnik::proj_transform const&)
{
return false;
}
double scale_factor() const
{
return 1;
}
double scale_factor() const { return 1; }
mapnik::attributes const& variables() const
{
return vars_;
}
mapnik::attributes const& variables() const { return vars_; }
mapnik::eAttributeCollectionPolicy attribute_collection_policy() const
{
return mapnik::eAttributeCollectionPolicy::DEFAULT;
}
bool painted() const
{
return painted_;
}
bool painted() const { return painted_; }
void painted(bool painted)
{
painted_ = painted;
}
void painted(bool painted) { painted_ = painted; }
private:
rendering_result & result_;
private:
rendering_result& result_;
bool painted_;
mapnik::attributes vars_;
};
@ -162,92 +134,91 @@ mapnik::Map prepare_map()
return map;
}
TEST_CASE("feature_style_processor") {
TEST_CASE("feature_style_processor")
{
SECTION("test_renderer")
{
mapnik::Map map(prepare_map());
rendering_result result;
test_renderer renderer(map, result);
renderer.apply();
SECTION("test_renderer") {
REQUIRE(renderer.painted());
mapnik::Map map(prepare_map());
rendering_result result;
test_renderer renderer(map, result);
renderer.apply();
REQUIRE(result.start_map_processing == 1);
REQUIRE(result.end_map_processing == 1);
REQUIRE(result.end_layer_processing == 1);
REQUIRE(result.start_style_processing == 1);
REQUIRE(result.end_style_processing == 1);
REQUIRE(renderer.painted());
REQUIRE(result.layer_query_extents.size() == 1);
const mapnik::box2d<double> reference_query_extent(-10, 0, 15, 20);
REQUIRE(result.layer_query_extents.front() == reference_query_extent);
REQUIRE(result.start_map_processing == 1);
REQUIRE(result.end_map_processing == 1);
REQUIRE(result.end_layer_processing == 1);
REQUIRE(result.start_style_processing == 1);
REQUIRE(result.end_style_processing == 1);
REQUIRE(result.geometries.size() == 2);
REQUIRE(mapnik::geometry::geometry_type(result.geometries[0]) == mapnik::geometry::geometry_types::Point);
REQUIRE(mapnik::geometry::geometry_type(result.geometries[1]) == mapnik::geometry::geometry_types::LineString);
}
REQUIRE(result.layer_query_extents.size() == 1);
const mapnik::box2d<double> reference_query_extent(-10, 0, 15, 20);
REQUIRE(result.layer_query_extents.front() == reference_query_extent);
REQUIRE(result.geometries.size() == 2);
REQUIRE(mapnik::geometry::geometry_type(result.geometries[0]) == mapnik::geometry::geometry_types::Point);
REQUIRE(mapnik::geometry::geometry_type(result.geometries[1]) == mapnik::geometry::geometry_types::LineString);
}
SECTION("test_renderer - apply() with single layer") {
mapnik::Map map(prepare_map());
rendering_result result;
test_renderer renderer(map, result);
std::set<std::string> attributes;
mapnik::layer const& layer = map.get_layer(0);
renderer.apply(layer, attributes);
REQUIRE(renderer.painted());
REQUIRE(result.start_map_processing == 1);
REQUIRE(result.end_map_processing == 1);
REQUIRE(result.end_layer_processing == 1);
REQUIRE(result.start_style_processing == 1);
REQUIRE(result.end_style_processing == 1);
REQUIRE(result.layer_query_extents.size() == 1);
const mapnik::box2d<double> reference_query_extent(-10, 0, 15, 20);
REQUIRE(result.layer_query_extents.front() == reference_query_extent);
REQUIRE(result.geometries.size() == 2);
REQUIRE(mapnik::geometry::geometry_type(result.geometries[0]) == mapnik::geometry::geometry_types::Point);
REQUIRE(mapnik::geometry::geometry_type(result.geometries[1]) == mapnik::geometry::geometry_types::LineString);
}
SECTION("test_renderer - apply_to_layer") {
mapnik::Map map(prepare_map());
rendering_result result;
test_renderer renderer(map, result);
std::set<std::string> attributes;
mapnik::projection map_proj(map.srs(), true);
mapnik::layer const& layer = map.get_layer(0);
renderer.apply_to_layer(layer,
renderer,
map_proj,
map.scale(),
map.scale_denominator(),
map.width(),
map.height(),
map.get_current_extent(),
0,
attributes);
REQUIRE(renderer.painted());
REQUIRE(result.start_map_processing == 0);
REQUIRE(result.end_map_processing == 0);
REQUIRE(result.end_layer_processing == 1);
REQUIRE(result.start_style_processing == 1);
REQUIRE(result.end_style_processing == 1);
REQUIRE(result.layer_query_extents.size() == 1);
const mapnik::box2d<double> reference_query_extent(-10, 0, 15, 20);
REQUIRE(result.layer_query_extents.front() == reference_query_extent);
REQUIRE(result.geometries.size() == 2);
REQUIRE(mapnik::geometry::geometry_type(result.geometries[0]) == mapnik::geometry::geometry_types::Point);
REQUIRE(mapnik::geometry::geometry_type(result.geometries[1]) == mapnik::geometry::geometry_types::LineString);
}
SECTION("test_renderer - apply() with single layer")
{
mapnik::Map map(prepare_map());
rendering_result result;
test_renderer renderer(map, result);
std::set<std::string> attributes;
mapnik::layer const& layer = map.get_layer(0);
renderer.apply(layer, attributes);
REQUIRE(renderer.painted());
REQUIRE(result.start_map_processing == 1);
REQUIRE(result.end_map_processing == 1);
REQUIRE(result.end_layer_processing == 1);
REQUIRE(result.start_style_processing == 1);
REQUIRE(result.end_style_processing == 1);
REQUIRE(result.layer_query_extents.size() == 1);
const mapnik::box2d<double> reference_query_extent(-10, 0, 15, 20);
REQUIRE(result.layer_query_extents.front() == reference_query_extent);
REQUIRE(result.geometries.size() == 2);
REQUIRE(mapnik::geometry::geometry_type(result.geometries[0]) == mapnik::geometry::geometry_types::Point);
REQUIRE(mapnik::geometry::geometry_type(result.geometries[1]) == mapnik::geometry::geometry_types::LineString);
}
SECTION("test_renderer - apply_to_layer")
{
mapnik::Map map(prepare_map());
rendering_result result;
test_renderer renderer(map, result);
std::set<std::string> attributes;
mapnik::projection map_proj(map.srs(), true);
mapnik::layer const& layer = map.get_layer(0);
renderer.apply_to_layer(layer,
renderer,
map_proj,
map.scale(),
map.scale_denominator(),
map.width(),
map.height(),
map.get_current_extent(),
0,
attributes);
REQUIRE(renderer.painted());
REQUIRE(result.start_map_processing == 0);
REQUIRE(result.end_map_processing == 0);
REQUIRE(result.end_layer_processing == 1);
REQUIRE(result.start_style_processing == 1);
REQUIRE(result.end_style_processing == 1);
REQUIRE(result.layer_query_extents.size() == 1);
const mapnik::box2d<double> reference_query_extent(-10, 0, 15, 20);
REQUIRE(result.layer_query_extents.front() == reference_query_extent);
REQUIRE(result.geometries.size() == 2);
REQUIRE(mapnik::geometry::geometry_type(result.geometries[0]) == mapnik::geometry::geometry_types::Point);
REQUIRE(mapnik::geometry::geometry_type(result.geometries[1]) == mapnik::geometry::geometry_types::LineString);
}
}

View file

@ -8,20 +8,14 @@
#include "cleanup.hpp" // run_cleanup()
int main (int argc, char** argv)
int main(int argc, char** argv)
{
Catch::Session session;
std::string plugin_path;
std::string working_dir;
auto cli = session.cli()
|
Catch::clara::Opt(plugin_path, "plugins")
["-p"]["--plugins"] ("path to mapnik plugins")
|
Catch::clara::Opt(working_dir, "working directory")
["-C"]["--working-directory"] ("change working directory")
;
auto cli =
session.cli() | Catch::clara::Opt(plugin_path, "plugins")["-p"]["--plugins"]("path to mapnik plugins") |
Catch::clara::Opt(working_dir, "working directory")["-C"]["--working-directory"]("change working directory");
session.cli(cli);
int result = session.applyCommandLine(argc, argv);
@ -58,5 +52,4 @@ int main (int argc, char** argv)
testing::run_cleanup();
return result;
}

View file

@ -29,19 +29,20 @@ MAPNIK_DISABLE_WARNING_PUSH
#include <boost/spirit/home/x3.hpp>
MAPNIK_DISABLE_WARNING_POP
namespace mapnik { namespace util {
namespace mapnik {
namespace util {
template <typename Out>
bool parse_hex(std::string const& input, Out & output)
template<typename Out>
bool parse_hex(std::string const& input, Out& output)
{
using boost::spirit::x3::lit;
auto itr = input.begin();
auto end = input.end();
using hex2 = boost::spirit::x3::uint_parser< unsigned, 16, 2, 2 >;
using hex2 = boost::spirit::x3::uint_parser<unsigned, 16, 2, 2>;
return boost::spirit::x3::parse(itr, end, -(lit("\\x") | lit("0x")) > *hex2(), output);
}
}}
} // namespace util
} // namespace mapnik
#endif // MAPNIK_PARSE_HEX_HPP

View file

@ -7,109 +7,117 @@
#include <mapnik/geometry/correct.hpp>
#include <boost/version.hpp>
TEST_CASE("geometry formats") {
SECTION("wkb") {
unsigned char sp_valid_blob[] = {
0x0, 0x1, 0xBC, 0xB, 0x0, 0x0, 0x1F, 0x12, 0xDB, 0xCF, 0xC3, 0xA2, 0x41, 0x41, 0x9D, 0x74, 0xB0, 0x31, 0xE6, 0x34, 0x53, 0x41, 0xDB,
0x1B, 0xB6, 0x7C, 0xD9, 0xA2, 0x41, 0x41, 0x67, 0xA7, 0xB6, 0xF, 0xF6, 0x34, 0x53, 0x41, 0x7C, 0x6, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0,
0x0, 0x69, 0x3, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x12, 0x0, 0x0, 0x0, 0xBB, 0x4B, 0x9C, 0x59, 0xD2, 0xA2, 0x41, 0x41, 0x3A, 0xAA,
0x3F, 0xAE, 0xEB, 0x34, 0x53, 0x41, 0xA2, 0xC2, 0xE4, 0xC6, 0xD1, 0xA2, 0x41, 0x41, 0x4C, 0xFE, 0x6, 0x2B, 0xEC, 0x34, 0x53, 0x41,
0xEC, 0x65, 0x5F, 0x6, 0xCE, 0xA2, 0x41, 0x41, 0xDD, 0x33, 0x7F, 0x24, 0xEF, 0x34, 0x53, 0x41, 0x2D, 0x35, 0x2D, 0x30, 0xCB, 0xA2,
0x41, 0x41, 0x4E, 0xA7, 0x88, 0x9, 0xF1, 0x34, 0x53, 0x41, 0x58, 0x2F, 0x12, 0x96, 0xCA, 0xA2, 0x41, 0x41, 0x52, 0xD1, 0xBD, 0xDC,
0xF0, 0x34, 0x53, 0x41, 0x1F, 0x12, 0xDB, 0xCF, 0xC3, 0xA2, 0x41, 0x41, 0xB9, 0x31, 0xA4, 0xE1, 0xF5, 0x34, 0x53, 0x41, 0x21, 0xBB,
0x20, 0x6D, 0xC4, 0xA2, 0x41, 0x41, 0x67, 0xA7, 0xB6, 0xF, 0xF6, 0x34, 0x53, 0x41, 0x5A, 0x82, 0x4A, 0xD3, 0xCA, 0xA2, 0x41, 0x41,
0xA7, 0x85, 0x3D, 0x58, 0xF1, 0x34, 0x53, 0x41, 0x22, 0xB8, 0x3A, 0x7D, 0xCB, 0xA2, 0x41, 0x41, 0x7D, 0x89, 0xA1, 0x8E, 0xF1, 0x34,
0x53, 0x41, 0xD0, 0x77, 0x3F, 0x80, 0xCF, 0xA2, 0x41, 0x41, 0x57, 0x69, 0x83, 0xC4, 0xEE, 0x34, 0x53, 0x41, 0xA7, 0xF5, 0x8E, 0xF9,
0xD1, 0xA2, 0x41, 0x41, 0x9A, 0xA2, 0x31, 0xEE, 0xEC, 0x34, 0x53, 0x41, 0x2A, 0xCD, 0xDE, 0x4C, 0xD4, 0xA2, 0x41, 0x41, 0x11, 0x43,
0xE1, 0xF7, 0xEA, 0x34, 0x53, 0x41, 0xF, 0x89, 0xB1, 0x66, 0xD5, 0xA2, 0x41, 0x41, 0xC8, 0x5D, 0x86, 0xF1, 0xE9, 0x34, 0x53, 0x41,
0x19, 0xF4, 0x73, 0x63, 0xD7, 0xA2, 0x41, 0x41, 0x7, 0xB1, 0x14, 0x36, 0xE8, 0x34, 0x53, 0x41, 0xDB, 0x1B, 0xB6, 0x7C, 0xD9, 0xA2,
0x41, 0x41, 0x98, 0xB5, 0xE0, 0x74, 0xE6, 0x34, 0x53, 0x41, 0xC0, 0x3F, 0xC6, 0xAC, 0xD8, 0xA2, 0x41, 0x41, 0x9D, 0x74, 0xB0, 0x31,
0xE6, 0x34, 0x53, 0x41, 0xF0, 0xB5, 0xB1, 0x53, 0xD5, 0xA2, 0x41, 0x41, 0x97, 0x47, 0xAD, 0x36, 0xE9, 0x34, 0x53, 0x41, 0xBB, 0x4B,
0x9C, 0x59, 0xD2, 0xA2, 0x41, 0x41, 0x3A, 0xAA, 0x3F, 0xAE, 0xEB, 0x34, 0x53, 0x41, 0xFE };
unsigned char sp_invalid_blob[] = {
0x0, 0x1, 0xBC, 0xB, 0x0, 0x0, 0x1F, 0x12, 0xDB, 0xCF, 0xC3, 0xA2, 0x41, 0x41, 0x9D, 0x74, 0xB0, 0x31, 0xE6, 0x34, 0x53, 0x41, 0xDB,
0x1B, 0xB6, 0x7C, 0xD9, 0xA2, 0x41, 0x41, 0x67, 0xA7, 0xB6, 0xF, 0xF6, 0x34, 0x53, 0x41, 0x7C, 0x6, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0,
0x0, 0x69, 0x3, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x12, 0x0, 0x0, 0x0, 0xBB, 0x4B, 0x9C, 0x59, 0xD2, 0xA2, 0x41, 0x41, 0x3A, 0xAA,
0x3F, 0xAE, 0xEB, 0x34, 0x53, 0x41, 0xA2, 0xC2, 0xE4, 0xC6, 0xD1, 0xA2, 0x41, 0x41, 0x4C, 0xFE, 0x6, 0x2B, 0xEC, 0x34, 0x53, 0x41,
0xEC, 0x65, 0x5F, 0x6, 0xCE, 0xA2, 0x41, 0x41, 0xDD, 0x33, 0x7F, 0x24, 0xEF, 0x34, 0x53, 0x41, 0x2D, 0x35, 0x2D, 0x30, 0xCB, 0xA2,
0x41, 0x41, 0x4E, 0xA7, 0x88, 0x9, 0xF1, 0x34, 0x53, 0x41, 0x58, 0x2F, 0x12, 0x96, 0xCA, 0xA2, 0x41, 0x41, 0x52, 0xD1, 0xBD, 0xDC,
0xF0, 0x34, 0x53, 0x41, 0x1F, 0x12, 0xDB, 0xCF, 0xC3, 0xA2, 0x41, 0x41, 0xB9, 0x31, 0xA4, 0xE1, 0xF5, 0x34, 0x53, 0x41, 0x21, 0xBB,
0x20, 0x6D, 0xC4, 0xA2, 0x41, 0x41, 0x67, 0xA7, 0xB6, 0xF, 0xF6, 0x34, 0x53, 0x41, 0x5A, 0x82, 0x4A, 0xD3, 0xCA, 0xA2, 0x41, 0x41,
0xA7, 0x85, 0x3D, 0x58, 0xF1, 0x34, 0x53, 0x41, 0x22, 0xB8, 0x3A, 0x7D, 0xCB, 0xA2, 0x41, 0x41, 0x7D, 0x89, 0xA1, 0x8E, 0xF1, 0x34,
0x53, 0x41, 0xD0, 0x77, 0x3F, 0x80, 0xCF, 0xA2, 0x41, 0x41, 0x57, 0x69, 0x83, 0xC4, 0xEE, 0x34, 0x53, 0x41, 0xA7, 0xF5, 0x8E, 0xF9,
0xD1, 0xA2, 0x41, 0x41, 0x9A, 0xA2, 0x31, 0xEE, 0xEC, 0x34, 0x53, 0x41, 0x2A, 0xCD, 0xDE, 0x4C, 0xD4, 0xA2, 0x41, 0x41, 0x11, 0x43,
0xE1, 0xF7, 0xEA, 0x34, 0x53, 0x41, 0xF, 0x89, 0xB1, 0x66, 0xD5, 0xA2, 0x41, 0x41, 0xC8, 0x5D, 0x86, 0xF1, 0xE9, 0x34, 0x53, 0x41,
0x19, 0xF4, 0x73, 0x63, 0xD7, 0xA2, 0x41, 0x41, 0x7, 0xB1, 0x14, 0x36, 0xE8, 0x34, 0x53, 0x41, 0xDB, 0x1B, 0xB6, 0x7C, 0xD9, 0xA2,
0x41, 0x41, 0x98, 0xB5, 0xE0, 0x74, 0xE6, 0x34, 0x53, 0x41, 0xC0, 0x3F, 0xC6, 0xAC, 0xD8, 0xA2, 0x41, 0x41, 0x9D, 0x74, 0xB0, 0x31,
0xE6, 0x34, 0x53, 0x41, 0xF0, 0xB5, 0xB1, 0x53, 0xD5, 0xA2, 0x41, 0x41, 0x97, 0x47, 0xAD, 0x36, 0xE9, 0x34, 0x53, 0x41, 0xBB, 0x4B,
0x9C, 0x59, 0xD2, 0xA2, 0x41, 0x41, 0x3A, 0xAA, 0x3F, 0xAE, 0xEB, 0x34, 0x53, 0x41 };
unsigned char sq_valid_blob[] = {
0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x40 };
unsigned char sq_invalid_blob[] = {
0x23, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x40, 0x23 };
// test of parsing wkb geometries
try {
// spatialite blob
mapnik::geometry::geometry<double> geom = mapnik::geometry_utils::from_wkb((const char*)sp_valid_blob,
sizeof(sp_valid_blob) / sizeof(sp_valid_blob[0]),
mapnik::wkbSpatiaLite);
// winding order is not correct per OGC so we'll fix it
mapnik::geometry::correct(geom);
#if BOOST_VERSION >= 105800
REQUIRE(mapnik::geometry::is_valid(geom));
REQUIRE(mapnik::geometry::is_simple(geom));
#endif
geom = mapnik::geometry_utils::from_wkb((const char*)sp_valid_blob,
sizeof(sp_valid_blob) / sizeof(sp_valid_blob[0]),
mapnik::wkbAuto);
mapnik::geometry::correct(geom);
#if BOOST_VERSION >= 105800
REQUIRE(mapnik::geometry::is_valid(geom));
REQUIRE(mapnik::geometry::is_simple(geom));
#endif
geom = mapnik::geometry_utils::from_wkb((const char*)sp_invalid_blob,
sizeof(sp_invalid_blob) / sizeof(sp_invalid_blob[0]),
mapnik::wkbAuto);
REQUIRE(geom.is<mapnik::geometry::geometry_empty>()); // returns geometry_empty
// sqlite generic wkb blob
geom = mapnik::geometry_utils::from_wkb((const char*)sq_valid_blob,
sizeof(sq_valid_blob) / sizeof(sq_valid_blob[0]),
mapnik::wkbGeneric);
#if BOOST_VERSION >= 105800
REQUIRE(mapnik::geometry::is_valid(geom));
REQUIRE(mapnik::geometry::is_simple(geom));
#endif
geom = mapnik::geometry_utils::from_wkb( (const char*)sq_valid_blob,
sizeof(sq_valid_blob) / sizeof(sq_valid_blob[0]),
mapnik::wkbAuto);
#if BOOST_VERSION >= 105800
REQUIRE(mapnik::geometry::is_valid(geom));
REQUIRE(mapnik::geometry::is_simple(geom));
#endif
geom = mapnik::geometry_utils::from_wkb((const char*)sq_invalid_blob,
sizeof(sq_invalid_blob) / sizeof(sq_invalid_blob[0]),
mapnik::wkbGeneric);
REQUIRE(geom.is<mapnik::geometry::geometry_empty>()); // returns geometry_empty
}
catch (std::exception const& ex)
TEST_CASE("geometry formats")
{
SECTION("wkb")
{
REQUIRE(false);
std::clog << "threw: " << ex.what() << "\n";
unsigned char sp_valid_blob[] = {
0x0, 0x1, 0xBC, 0xB, 0x0, 0x0, 0x1F, 0x12, 0xDB, 0xCF, 0xC3, 0xA2, 0x41, 0x41, 0x9D, 0x74, 0xB0, 0x31,
0xE6, 0x34, 0x53, 0x41, 0xDB, 0x1B, 0xB6, 0x7C, 0xD9, 0xA2, 0x41, 0x41, 0x67, 0xA7, 0xB6, 0xF, 0xF6, 0x34,
0x53, 0x41, 0x7C, 0x6, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x69, 0x3, 0x0, 0x0, 0x0, 0x1, 0x0,
0x0, 0x0, 0x12, 0x0, 0x0, 0x0, 0xBB, 0x4B, 0x9C, 0x59, 0xD2, 0xA2, 0x41, 0x41, 0x3A, 0xAA, 0x3F, 0xAE,
0xEB, 0x34, 0x53, 0x41, 0xA2, 0xC2, 0xE4, 0xC6, 0xD1, 0xA2, 0x41, 0x41, 0x4C, 0xFE, 0x6, 0x2B, 0xEC, 0x34,
0x53, 0x41, 0xEC, 0x65, 0x5F, 0x6, 0xCE, 0xA2, 0x41, 0x41, 0xDD, 0x33, 0x7F, 0x24, 0xEF, 0x34, 0x53, 0x41,
0x2D, 0x35, 0x2D, 0x30, 0xCB, 0xA2, 0x41, 0x41, 0x4E, 0xA7, 0x88, 0x9, 0xF1, 0x34, 0x53, 0x41, 0x58, 0x2F,
0x12, 0x96, 0xCA, 0xA2, 0x41, 0x41, 0x52, 0xD1, 0xBD, 0xDC, 0xF0, 0x34, 0x53, 0x41, 0x1F, 0x12, 0xDB, 0xCF,
0xC3, 0xA2, 0x41, 0x41, 0xB9, 0x31, 0xA4, 0xE1, 0xF5, 0x34, 0x53, 0x41, 0x21, 0xBB, 0x20, 0x6D, 0xC4, 0xA2,
0x41, 0x41, 0x67, 0xA7, 0xB6, 0xF, 0xF6, 0x34, 0x53, 0x41, 0x5A, 0x82, 0x4A, 0xD3, 0xCA, 0xA2, 0x41, 0x41,
0xA7, 0x85, 0x3D, 0x58, 0xF1, 0x34, 0x53, 0x41, 0x22, 0xB8, 0x3A, 0x7D, 0xCB, 0xA2, 0x41, 0x41, 0x7D, 0x89,
0xA1, 0x8E, 0xF1, 0x34, 0x53, 0x41, 0xD0, 0x77, 0x3F, 0x80, 0xCF, 0xA2, 0x41, 0x41, 0x57, 0x69, 0x83, 0xC4,
0xEE, 0x34, 0x53, 0x41, 0xA7, 0xF5, 0x8E, 0xF9, 0xD1, 0xA2, 0x41, 0x41, 0x9A, 0xA2, 0x31, 0xEE, 0xEC, 0x34,
0x53, 0x41, 0x2A, 0xCD, 0xDE, 0x4C, 0xD4, 0xA2, 0x41, 0x41, 0x11, 0x43, 0xE1, 0xF7, 0xEA, 0x34, 0x53, 0x41,
0xF, 0x89, 0xB1, 0x66, 0xD5, 0xA2, 0x41, 0x41, 0xC8, 0x5D, 0x86, 0xF1, 0xE9, 0x34, 0x53, 0x41, 0x19, 0xF4,
0x73, 0x63, 0xD7, 0xA2, 0x41, 0x41, 0x7, 0xB1, 0x14, 0x36, 0xE8, 0x34, 0x53, 0x41, 0xDB, 0x1B, 0xB6, 0x7C,
0xD9, 0xA2, 0x41, 0x41, 0x98, 0xB5, 0xE0, 0x74, 0xE6, 0x34, 0x53, 0x41, 0xC0, 0x3F, 0xC6, 0xAC, 0xD8, 0xA2,
0x41, 0x41, 0x9D, 0x74, 0xB0, 0x31, 0xE6, 0x34, 0x53, 0x41, 0xF0, 0xB5, 0xB1, 0x53, 0xD5, 0xA2, 0x41, 0x41,
0x97, 0x47, 0xAD, 0x36, 0xE9, 0x34, 0x53, 0x41, 0xBB, 0x4B, 0x9C, 0x59, 0xD2, 0xA2, 0x41, 0x41, 0x3A, 0xAA,
0x3F, 0xAE, 0xEB, 0x34, 0x53, 0x41, 0xFE};
unsigned char sp_invalid_blob[] = {
0x0, 0x1, 0xBC, 0xB, 0x0, 0x0, 0x1F, 0x12, 0xDB, 0xCF, 0xC3, 0xA2, 0x41, 0x41, 0x9D, 0x74, 0xB0, 0x31,
0xE6, 0x34, 0x53, 0x41, 0xDB, 0x1B, 0xB6, 0x7C, 0xD9, 0xA2, 0x41, 0x41, 0x67, 0xA7, 0xB6, 0xF, 0xF6, 0x34,
0x53, 0x41, 0x7C, 0x6, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x69, 0x3, 0x0, 0x0, 0x0, 0x1, 0x0,
0x0, 0x0, 0x12, 0x0, 0x0, 0x0, 0xBB, 0x4B, 0x9C, 0x59, 0xD2, 0xA2, 0x41, 0x41, 0x3A, 0xAA, 0x3F, 0xAE,
0xEB, 0x34, 0x53, 0x41, 0xA2, 0xC2, 0xE4, 0xC6, 0xD1, 0xA2, 0x41, 0x41, 0x4C, 0xFE, 0x6, 0x2B, 0xEC, 0x34,
0x53, 0x41, 0xEC, 0x65, 0x5F, 0x6, 0xCE, 0xA2, 0x41, 0x41, 0xDD, 0x33, 0x7F, 0x24, 0xEF, 0x34, 0x53, 0x41,
0x2D, 0x35, 0x2D, 0x30, 0xCB, 0xA2, 0x41, 0x41, 0x4E, 0xA7, 0x88, 0x9, 0xF1, 0x34, 0x53, 0x41, 0x58, 0x2F,
0x12, 0x96, 0xCA, 0xA2, 0x41, 0x41, 0x52, 0xD1, 0xBD, 0xDC, 0xF0, 0x34, 0x53, 0x41, 0x1F, 0x12, 0xDB, 0xCF,
0xC3, 0xA2, 0x41, 0x41, 0xB9, 0x31, 0xA4, 0xE1, 0xF5, 0x34, 0x53, 0x41, 0x21, 0xBB, 0x20, 0x6D, 0xC4, 0xA2,
0x41, 0x41, 0x67, 0xA7, 0xB6, 0xF, 0xF6, 0x34, 0x53, 0x41, 0x5A, 0x82, 0x4A, 0xD3, 0xCA, 0xA2, 0x41, 0x41,
0xA7, 0x85, 0x3D, 0x58, 0xF1, 0x34, 0x53, 0x41, 0x22, 0xB8, 0x3A, 0x7D, 0xCB, 0xA2, 0x41, 0x41, 0x7D, 0x89,
0xA1, 0x8E, 0xF1, 0x34, 0x53, 0x41, 0xD0, 0x77, 0x3F, 0x80, 0xCF, 0xA2, 0x41, 0x41, 0x57, 0x69, 0x83, 0xC4,
0xEE, 0x34, 0x53, 0x41, 0xA7, 0xF5, 0x8E, 0xF9, 0xD1, 0xA2, 0x41, 0x41, 0x9A, 0xA2, 0x31, 0xEE, 0xEC, 0x34,
0x53, 0x41, 0x2A, 0xCD, 0xDE, 0x4C, 0xD4, 0xA2, 0x41, 0x41, 0x11, 0x43, 0xE1, 0xF7, 0xEA, 0x34, 0x53, 0x41,
0xF, 0x89, 0xB1, 0x66, 0xD5, 0xA2, 0x41, 0x41, 0xC8, 0x5D, 0x86, 0xF1, 0xE9, 0x34, 0x53, 0x41, 0x19, 0xF4,
0x73, 0x63, 0xD7, 0xA2, 0x41, 0x41, 0x7, 0xB1, 0x14, 0x36, 0xE8, 0x34, 0x53, 0x41, 0xDB, 0x1B, 0xB6, 0x7C,
0xD9, 0xA2, 0x41, 0x41, 0x98, 0xB5, 0xE0, 0x74, 0xE6, 0x34, 0x53, 0x41, 0xC0, 0x3F, 0xC6, 0xAC, 0xD8, 0xA2,
0x41, 0x41, 0x9D, 0x74, 0xB0, 0x31, 0xE6, 0x34, 0x53, 0x41, 0xF0, 0xB5, 0xB1, 0x53, 0xD5, 0xA2, 0x41, 0x41,
0x97, 0x47, 0xAD, 0x36, 0xE9, 0x34, 0x53, 0x41, 0xBB, 0x4B, 0x9C, 0x59, 0xD2, 0xA2, 0x41, 0x41, 0x3A, 0xAA,
0x3F, 0xAE, 0xEB, 0x34, 0x53, 0x41};
unsigned char sq_valid_blob[] = {0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x40};
unsigned char sq_invalid_blob[] = {0x23, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x40, 0x23};
// test of parsing wkb geometries
try
{
// spatialite blob
mapnik::geometry::geometry<double> geom =
mapnik::geometry_utils::from_wkb((const char*)sp_valid_blob,
sizeof(sp_valid_blob) / sizeof(sp_valid_blob[0]),
mapnik::wkbSpatiaLite);
// winding order is not correct per OGC so we'll fix it
mapnik::geometry::correct(geom);
#if BOOST_VERSION >= 105800
REQUIRE(mapnik::geometry::is_valid(geom));
REQUIRE(mapnik::geometry::is_simple(geom));
#endif
geom = mapnik::geometry_utils::from_wkb((const char*)sp_valid_blob,
sizeof(sp_valid_blob) / sizeof(sp_valid_blob[0]),
mapnik::wkbAuto);
mapnik::geometry::correct(geom);
#if BOOST_VERSION >= 105800
REQUIRE(mapnik::geometry::is_valid(geom));
REQUIRE(mapnik::geometry::is_simple(geom));
#endif
geom = mapnik::geometry_utils::from_wkb((const char*)sp_invalid_blob,
sizeof(sp_invalid_blob) / sizeof(sp_invalid_blob[0]),
mapnik::wkbAuto);
REQUIRE(geom.is<mapnik::geometry::geometry_empty>()); // returns geometry_empty
// sqlite generic wkb blob
geom = mapnik::geometry_utils::from_wkb((const char*)sq_valid_blob,
sizeof(sq_valid_blob) / sizeof(sq_valid_blob[0]),
mapnik::wkbGeneric);
#if BOOST_VERSION >= 105800
REQUIRE(mapnik::geometry::is_valid(geom));
REQUIRE(mapnik::geometry::is_simple(geom));
#endif
geom = mapnik::geometry_utils::from_wkb((const char*)sq_valid_blob,
sizeof(sq_valid_blob) / sizeof(sq_valid_blob[0]),
mapnik::wkbAuto);
#if BOOST_VERSION >= 105800
REQUIRE(mapnik::geometry::is_valid(geom));
REQUIRE(mapnik::geometry::is_simple(geom));
#endif
geom = mapnik::geometry_utils::from_wkb((const char*)sq_invalid_blob,
sizeof(sq_invalid_blob) / sizeof(sq_invalid_blob[0]),
mapnik::wkbGeneric);
REQUIRE(geom.is<mapnik::geometry::geometry_empty>()); // returns geometry_empty
} catch (std::exception const& ex)
{
REQUIRE(false);
std::clog << "threw: " << ex.what() << "\n";
}
}
}
}

View file

@ -16,25 +16,23 @@
#include <vector>
#include <fstream>
#if BOOST_VERSION >= 105800
namespace {
namespace {
struct spatially_equal_visitor
{
using result_type = bool;
result_type operator() (mapnik::geometry::geometry_empty, mapnik::geometry::geometry_empty) const
{
return true;
}
result_type operator()(mapnik::geometry::geometry_empty, mapnik::geometry::geometry_empty) const { return true; }
result_type operator() (mapnik::geometry::geometry_collection<double> const& lhs, mapnik::geometry::geometry_collection<double> const& rhs) const
result_type operator()(mapnik::geometry::geometry_collection<double> const& lhs,
mapnik::geometry::geometry_collection<double> const& rhs) const
{
std::size_t size0 = lhs.size();
std::size_t size1 = rhs.size();
if (size0 != size1) return false;
for (std::size_t index = 0; index < size0 ; ++index)
if (size0 != size1)
return false;
for (std::size_t index = 0; index < size0; ++index)
{
if (!mapnik::util::apply_visitor(*this, lhs[index], rhs[index]))
return false;
@ -42,45 +40,47 @@ struct spatially_equal_visitor
return true;
}
result_type operator() (mapnik::geometry::multi_point<double> const& lhs, mapnik::geometry::multi_point<double> const& rhs) const
result_type operator()(mapnik::geometry::multi_point<double> const& lhs,
mapnik::geometry::multi_point<double> const& rhs) const
{
std::size_t size0 = lhs.size();
std::size_t size1 = rhs.size();
if (size0 != size1) return false;
if (size0 != size1)
return false;
auto tmp0 = lhs;
auto tmp1 = rhs;
std::sort(tmp0.begin(), tmp0.end(), boost::geometry::less<mapnik::geometry::point<double>>());
std::sort(tmp1.begin(), tmp1.end(), boost::geometry::less<mapnik::geometry::point<double>>());
for (std::size_t index = 0; index < size0 ; ++index)
for (std::size_t index = 0; index < size0; ++index)
{
if (!boost::geometry::equals(tmp0[index], tmp1[index])) return false;
if (!boost::geometry::equals(tmp0[index], tmp1[index]))
return false;
}
return true;
}
template <typename T>
result_type operator() (T const& lhs, T const& rhs) const
template<typename T>
result_type operator()(T const& lhs, T const& rhs) const
{
if (mapnik::geometry::is_empty(lhs) && mapnik::geometry::is_empty(rhs))
return true; //Empty geometries of the same type are considered to be spatially equal
return true; // Empty geometries of the same type are considered to be spatially equal
return boost::geometry::equals(lhs, rhs);
}
template <typename T0, typename T1>
result_type operator() (T0 const& lhs, T1 const& rhs) const
template<typename T0, typename T1>
result_type operator()(T0 const& lhs, T1 const& rhs) const
{
return false;
}
};
template <typename T>
template<typename T>
bool spatially_equal(mapnik::geometry::geometry<T> const& g0, mapnik::geometry::geometry<T> const& g1)
{
return mapnik::util::apply_visitor(spatially_equal_visitor(), g0, g1);
}
}
} // namespace
#endif
TEST_CASE("Well-known-geometries")
@ -88,10 +88,11 @@ TEST_CASE("Well-known-geometries")
SECTION("wkb+wkt")
{
std::string filename("test/unit/data/well-known-geometries.test");
std::ifstream is(filename.c_str(),std::ios_base::in | std::ios_base::binary);
if (!is) throw std::runtime_error("could not open: '" + filename + "'");
std::ifstream is(filename.c_str(), std::ios_base::in | std::ios_base::binary);
if (!is)
throw std::runtime_error("could not open: '" + filename + "'");
for (std::string line; std::getline(is, line,'\n');)
for (std::string line; std::getline(is, line, '\n');)
{
std::vector<std::string> columns;
boost::split(columns, line, boost::is_any_of(";"));
@ -99,13 +100,14 @@ TEST_CASE("Well-known-geometries")
std::vector<char> wkb, twkb;
REQUIRE(mapnik::util::parse_hex(columns[1], wkb));
REQUIRE(mapnik::util::parse_hex(columns[2], twkb));
mapnik::geometry::geometry<double> geom_0 = mapnik::geometry_utils::from_wkb(wkb.data(), wkb.size(), mapnik::wkbAuto);
mapnik::geometry::geometry<double> geom_0 =
mapnik::geometry_utils::from_wkb(wkb.data(), wkb.size(), mapnik::wkbAuto);
mapnik::geometry::geometry<double> geom_1 = mapnik::geometry_utils::from_twkb(twkb.data(), twkb.size());
// compare WKTs as doubles
std::string wkt, wkt0, wkt1;
wkt = columns[0];
//wkt.erase(std::remove(wkt.begin(), wkt.end(), ' '), wkt.end());
// ^ we can't use this approach because spaces are part of format e.g POINT(100 200)
// wkt.erase(std::remove(wkt.begin(), wkt.end(), ' '), wkt.end());
// ^ we can't use this approach because spaces are part of format e.g POINT(100 200)
REQUIRE(mapnik::util::to_wkt(wkt0, geom_0));
REQUIRE(mapnik::util::to_wkt(wkt1, geom_1));
if (!mapnik::geometry::is_empty(geom_0) && !mapnik::geometry::is_empty(geom_1))
@ -122,13 +124,13 @@ TEST_CASE("Well-known-geometries")
// note: mapnik::util::to_wkt<std::int64_t> used in mapnik-vt
std::string wkt2, wkt3;
mapnik::geometry::line_string<std::int64_t> geom_2;
geom_2.emplace_back(0,0);
geom_2.emplace_back(1,1);
geom_2.emplace_back(2,2);
geom_2.emplace_back(0, 0);
geom_2.emplace_back(1, 1);
geom_2.emplace_back(2, 2);
mapnik::geometry::line_string<std::int64_t> geom_3;
geom_3.emplace_back(0,0);
geom_3.emplace_back(1,1);
geom_3.emplace_back(2,2);
geom_3.emplace_back(0, 0);
geom_3.emplace_back(1, 1);
geom_3.emplace_back(2, 2);
REQUIRE(mapnik::util::to_wkt(wkt0, mapnik::geometry::geometry<std::int64_t>(geom_2)));
REQUIRE(mapnik::util::to_wkt(wkt1, mapnik::geometry::geometry<std::int64_t>(geom_3)));
if (!mapnik::geometry::is_empty(geom_2) && !mapnik::geometry::is_empty(geom_3))

View file

@ -5,40 +5,39 @@
#include <mapnik/xml_loader.hpp>
#include <mapnik/attribute.hpp> // needed due to fwd declare in value_types.hpp
TEST_CASE("xml parser") {
TEST_CASE("xml parser")
{
SECTION("trims whitespace")
{
// simple and non-valid mapnik XML reduced from the empty_parameter2.xml
// test case. this is to check that the xml parsing routine is trimming
// whitespace from text nodes as part of the parsing operation.
const std::string xml("<Map>"
" <Layer>"
" <Datasource>"
" <Parameter name=\"empty\"><![CDATA[ ]]></Parameter>"
" </Datasource>"
" </Layer>"
"</Map>");
SECTION("trims whitespace") {
mapnik::xml_tree tree;
tree.set_filename("xml_datasource_parameter_trim.cpp");
REQUIRE_NOTHROW(read_xml_string(xml, tree.root(), ""));
// simple and non-valid mapnik XML reduced from the empty_parameter2.xml
// test case. this is to check that the xml parsing routine is trimming
// whitespace from text nodes as part of the parsing operation.
const std::string xml("<Map>"
" <Layer>"
" <Datasource>"
" <Parameter name=\"empty\"><![CDATA[ ]]></Parameter>"
" </Datasource>"
" </Layer>"
"</Map>");
REQUIRE(tree.root().has_child("Map"));
mapnik::xml_node const& map = tree.root().get_child("Map");
mapnik::xml_tree tree;
tree.set_filename("xml_datasource_parameter_trim.cpp");
REQUIRE_NOTHROW(read_xml_string(xml, tree.root(), ""));
REQUIRE(map.has_child("Layer"));
mapnik::xml_node const& layer = map.get_child("Layer");
REQUIRE(tree.root().has_child("Map"));
mapnik::xml_node const &map = tree.root().get_child("Map");
REQUIRE(layer.has_child("Datasource"));
mapnik::xml_node const& datasource = layer.get_child("Datasource");
REQUIRE(map.has_child("Layer"));
mapnik::xml_node const &layer = map.get_child("Layer");
REQUIRE(datasource.has_child("Parameter"));
mapnik::xml_node const& parameter = datasource.get_child("Parameter");
REQUIRE(layer.has_child("Datasource"));
mapnik::xml_node const &datasource = layer.get_child("Datasource");
REQUIRE(datasource.has_child("Parameter"));
mapnik::xml_node const &parameter = datasource.get_child("Parameter");
// parser should call mapnik::util::trim on the text content and
// this should result in an empty text string in the parameter.
REQUIRE(parameter.get_text() == "");
}
// parser should call mapnik::util::trim on the text content and
// this should result in an empty text string in the parameter.
REQUIRE(parameter.get_text() == "");
}
}

View file

@ -3,31 +3,35 @@
#include <mapnik/sql_utils.hpp>
TEST_CASE("sql parse") {
TEST_CASE("sql parse")
{
SECTION("table")
{
std::string subquery("table");
REQUIRE(subquery == mapnik::sql_utils::table_from_sql(subquery));
}
SECTION("table") {
std::string subquery("table");
REQUIRE( subquery == mapnik::sql_utils::table_from_sql(subquery) );
}
SECTION("complex sql 1")
{
std::string subquery("(select * FROM table1, table2) AS data");
REQUIRE("table1" == mapnik::sql_utils::table_from_sql(subquery));
}
SECTION("complex sql 1") {
std::string subquery("(select * FROM table1, table2) AS data");
REQUIRE( "table1" == mapnik::sql_utils::table_from_sql(subquery) );
}
SECTION("complex sql 2")
{
std::string subquery("(select * FROM table1 , table2) AS data");
REQUIRE("table1" == mapnik::sql_utils::table_from_sql(subquery));
}
SECTION("complex sql 2") {
std::string subquery("(select * FROM table1 , table2) AS data");
REQUIRE( "table1" == mapnik::sql_utils::table_from_sql(subquery) );
}
SECTION("complex sql 3") {
std::string subquery("(select * FROM table1,table2) AS data");
REQUIRE( "table1" == mapnik::sql_utils::table_from_sql(subquery) );
}
SECTION("complex sql 4") {
std::string subquery("(select * FROM table1) AS data");
REQUIRE( "table1" == mapnik::sql_utils::table_from_sql(subquery) );
}
SECTION("complex sql 3")
{
std::string subquery("(select * FROM table1,table2) AS data");
REQUIRE("table1" == mapnik::sql_utils::table_from_sql(subquery));
}
SECTION("complex sql 4")
{
std::string subquery("(select * FROM table1) AS data");
REQUIRE("table1" == mapnik::sql_utils::table_from_sql(subquery));
}
}

View file

@ -36,42 +36,40 @@
namespace // internal
{
struct test_parser
struct test_parser
{
mapnik::svg_storage_type path;
mapnik::svg::vertex_stl_adapter<mapnik::svg::svg_path_storage> stl_storage;
mapnik::svg::svg_path_adapter svg_path;
mapnik::svg::svg_converter_type svg;
mapnik::svg::svg_parser p;
explicit test_parser(bool strict = false)
: stl_storage(path.source())
, svg_path(stl_storage)
, svg(svg_path, path.attributes())
, p(svg, strict)
{}
mapnik::svg::svg_parser* operator->() { return &p; }
};
template<typename C>
std::string join(C const& container)
{
std::string result;
for (auto const& str : container)
{
mapnik::svg_storage_type path;
mapnik::svg::vertex_stl_adapter<mapnik::svg::svg_path_storage> stl_storage;
mapnik::svg::svg_path_adapter svg_path;
mapnik::svg::svg_converter_type svg;
mapnik::svg::svg_parser p;
explicit test_parser(bool strict = false)
: stl_storage(path.source())
, svg_path(stl_storage)
, svg(svg_path, path.attributes())
, p(svg, strict)
{}
mapnik::svg::svg_parser* operator->()
{
return &p;
}
};
template <typename C>
std::string join(C const& container)
{
std::string result;
for (auto const& str : container)
{
if (!result.empty()) result += "\n ";
result += str;
}
return result;
if (!result.empty())
result += "\n ";
result += str;
}
return result;
}
} // namespace
TEST_CASE("SVG parser") {
TEST_CASE("SVG parser")
{
SECTION("SVG i/o")
{
mapnik::logger::instance().set_severity(mapnik::logger::none);
@ -85,17 +83,13 @@ TEST_CASE("SVG parser") {
SECTION("SVG::parse i/o")
{
std::string svg_name("FAIL");
char const* expected_errors[] =
{
"SVG error: unable to open \"FAIL\""
};
char const* expected_errors[] = {"SVG error: unable to open \"FAIL\""};
test_parser p;
try
{
p->parse(svg_name);
}
catch (std::exception const& ex)
} catch (std::exception const& ex)
{
REQUIRE(ex.what() == join(expected_errors));
}
@ -104,21 +98,18 @@ TEST_CASE("SVG parser") {
SECTION("SVG::parse_from_string syntax error")
{
std::string svg_name("./test/data/svg/invalid.svg");
char const* expected_errors[] =
{
"SVG error: unable to parse \"<?xml version=\"1.0\"?>\n<svg width=\"12cm\" height=\"4cm\" viewBox=\"0 0 1200 400\"\nxmlns=\"http://www.w3.org/2000/svg\" version=\"1.2\" baseProfile=\"tiny\">\n\""
};
char const* expected_errors[] = {
"SVG error: unable to parse \"<?xml version=\"1.0\"?>\n<svg width=\"12cm\" height=\"4cm\" viewBox=\"0 0 1200 "
"400\"\nxmlns=\"http://www.w3.org/2000/svg\" version=\"1.2\" baseProfile=\"tiny\">\n\""};
std::ifstream in(svg_name.c_str());
std::string svg_str((std::istreambuf_iterator<char>(in)),
std::istreambuf_iterator<char>());
std::string svg_str((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
test_parser p;
try
{
p->parse_from_string(svg_str);
}
catch (std::exception const& ex)
} catch (std::exception const& ex)
{
REQUIRE(ex.what() == join(expected_errors));
}
@ -127,17 +118,13 @@ TEST_CASE("SVG parser") {
SECTION("SVG::parse_from_string syntax error")
{
std::string svg_name("./test/data/svg/invalid.svg");
char const* expected_errors[] =
{
"SVG error: unable to parse \"./test/data/svg/invalid.svg\""
};
char const* expected_errors[] = {"SVG error: unable to parse \"./test/data/svg/invalid.svg\""};
test_parser p;
try
{
p->parse(svg_name);
}
catch (std::exception const& ex)
} catch (std::exception const& ex)
{
REQUIRE(ex.what() == join(expected_errors));
}
@ -145,18 +132,14 @@ TEST_CASE("SVG parser") {
SECTION("SVG parser color <fail>")
{
std::string svg_name("./test/data/svg/color_fail.svg");
char const* expected_errors[] =
{
"SVG parse error: can't infer valid image dimensions from width:\"100%\" height:\"100%\"",
"SVG parse error: failed to parse <color> with value \"fail\"",
"SVG parse error: failed to parse <number> with value \"fail\""
};
char const* expected_errors[] = {
"SVG parse error: can't infer valid image dimensions from width:\"100%\" height:\"100%\"",
"SVG parse error: failed to parse <color> with value \"fail\"",
"SVG parse error: failed to parse <number> with value \"fail\""};
std::ifstream in(svg_name.c_str());
std::string svg_str((std::istreambuf_iterator<char>(in)),
std::istreambuf_iterator<char>());
std::string svg_str((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
{
test_parser p;
@ -168,8 +151,7 @@ TEST_CASE("SVG parser") {
try
{
p->parse_from_string(svg_str);
}
catch (std::exception const& ex)
} catch (std::exception const& ex)
{
REQUIRE(ex.what() == std::string(expected_errors[0]));
}
@ -179,27 +161,24 @@ TEST_CASE("SVG parser") {
SECTION("SVG - cope with erroneous geometries")
{
std::string svg_name("./test/data/svg/errors.svg");
char const* expected_errors[] =
{
"SVG parse error: can't infer valid image dimensions from width:\"100%\" height:\"100%\"",
"SVG validation error: invalid <rect> width \"-100\"",
"SVG parse error: failed to parse <number> with value \"FAIL\"",
"SVG validation error: invalid <rect> height \"-100\"",
"SVG validation error: invalid <rect> rx \"-1000\"",
"SVG validation error: invalid <rect> ry \"-1000\"",
"SVG parse error: failed to parse <number> with value \"100invalidunit\"",
"SVG parse error: failed to parse <path>",
"SVG parse error: failed to parse <path> with <id> \"fail-path\"",
"SVG validation error: invalid <circle> radius \"-50\"",
"SVG parse error: failed to parse <polygon> points",
"SVG parse error: failed to parse <polyline> points",
"SVG validation error: invalid <ellipse> rx \"-10\"",
"SVG validation error: invalid <ellipse> ry \"-10\""
};
char const* expected_errors[] = {
"SVG parse error: can't infer valid image dimensions from width:\"100%\" height:\"100%\"",
"SVG validation error: invalid <rect> width \"-100\"",
"SVG parse error: failed to parse <number> with value \"FAIL\"",
"SVG validation error: invalid <rect> height \"-100\"",
"SVG validation error: invalid <rect> rx \"-1000\"",
"SVG validation error: invalid <rect> ry \"-1000\"",
"SVG parse error: failed to parse <number> with value \"100invalidunit\"",
"SVG parse error: failed to parse <path>",
"SVG parse error: failed to parse <path> with <id> \"fail-path\"",
"SVG validation error: invalid <circle> radius \"-50\"",
"SVG parse error: failed to parse <polygon> points",
"SVG parse error: failed to parse <polyline> points",
"SVG validation error: invalid <ellipse> rx \"-10\"",
"SVG validation error: invalid <ellipse> ry \"-10\""};
std::ifstream in(svg_name.c_str());
std::string svg_str((std::istreambuf_iterator<char>(in)),
std::istreambuf_iterator<char>());
std::string svg_str((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
{
test_parser p;
@ -213,8 +192,7 @@ TEST_CASE("SVG parser") {
try
{
p->parse_from_string(svg_str);
}
catch (std::exception const& ex)
} catch (std::exception const& ex)
{
REQUIRE(ex.what() == std::string(expected_errors[0]));
}
@ -223,16 +201,11 @@ TEST_CASE("SVG parser") {
SECTION("SVG parser double % <fail>")
{
std::string svg_name("./test/data/svg/gradient-radial-error.svg");
char const* expected_errors[] =
{
"SVG parse error: failed to parse <number> with value \"FAIL\""
};
char const* expected_errors[] = {"SVG parse error: failed to parse <number> with value \"FAIL\""};
std::ifstream in(svg_name.c_str());
std::string svg_str((std::istreambuf_iterator<char>(in)),
std::istreambuf_iterator<char>());
std::string svg_str((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
{
test_parser p;
@ -244,8 +217,7 @@ TEST_CASE("SVG parser") {
try
{
p->parse_from_string(svg_str);
}
catch (std::exception const& ex)
} catch (std::exception const& ex)
{
REQUIRE(ex.what() == std::string(expected_errors[0]));
}
@ -254,7 +226,6 @@ TEST_CASE("SVG parser") {
SECTION("SVG parser display=none")
{
std::string svg_name("./test/data/svg/invisible.svg");
std::shared_ptr<mapnik::marker const> marker = mapnik::marker_cache::instance().find(svg_name, false);
REQUIRE(marker);
@ -266,13 +237,12 @@ TEST_CASE("SVG parser") {
REQUIRE(storage);
mapnik::svg::vertex_stl_adapter<mapnik::svg::svg_path_storage> stl_storage(storage->source());
mapnik::svg::svg_path_adapter path(stl_storage);
double x,y;
REQUIRE(path.vertex(&x,&y) == mapnik::SEG_END);
double x, y;
REQUIRE(path.vertex(&x, &y) == mapnik::SEG_END);
}
SECTION("SVG parser stroke-linecap=square")
{
std::string svg_name("./test/data/svg/stroke-linecap-square.svg");
std::shared_ptr<mapnik::marker const> marker = mapnik::marker_cache::instance().find(svg_name, false);
REQUIRE(marker);
@ -287,19 +257,19 @@ TEST_CASE("SVG parser") {
auto const& attrs = storage->attributes();
agg::line_cap_e expected_cap(agg::square_cap);
REQUIRE(attrs.size() == 1 );
REQUIRE(attrs.size() == 1);
REQUIRE(attrs[0].line_cap == expected_cap);
double x,y;
double x, y;
unsigned cmd;
std::vector<std::tuple<double,double,unsigned>> vec;
while ((cmd = path.vertex(&x,&y)) != mapnik::SEG_END)
std::vector<std::tuple<double, double, unsigned>> vec;
while ((cmd = path.vertex(&x, &y)) != mapnik::SEG_END)
{
vec.emplace_back(x, y, cmd);
}
std::vector<std::tuple<double,double,unsigned>> expected = { std::make_tuple(5, 60, 1),
std::make_tuple(220, 60, 2) };
REQUIRE(std::equal(expected.begin(),expected.end(), vec.begin()));
std::vector<std::tuple<double, double, unsigned>> expected = {std::make_tuple(5, 60, 1),
std::make_tuple(220, 60, 2)};
REQUIRE(std::equal(expected.begin(), expected.end(), vec.begin()));
}
SECTION("SVG <rect>")
@ -316,20 +286,20 @@ TEST_CASE("SVG parser") {
REQUIRE(storage);
mapnik::svg::vertex_stl_adapter<mapnik::svg::svg_path_storage> stl_storage(storage->source());
mapnik::svg::svg_path_adapter path(stl_storage);
double x,y;
double x, y;
unsigned cmd;
std::vector<std::tuple<double,double,unsigned>> vec;
while ((cmd = path.vertex(&x,&y)) != mapnik::SEG_END)
std::vector<std::tuple<double, double, unsigned>> vec;
while ((cmd = path.vertex(&x, &y)) != mapnik::SEG_END)
{
vec.emplace_back(x, y, cmd);
//std::cerr << x << "," << y << " cmd=" << cmd << std::endl;
// std::cerr << x << "," << y << " cmd=" << cmd << std::endl;
}
std::vector<std::tuple<double,double,unsigned>> expected = { std::make_tuple(0, 0, 1),
std::make_tuple(20, 0, 2),
std::make_tuple(20, 15, 2),
std::make_tuple(0, 15, 2),
std::make_tuple(0, 0, 79) };
REQUIRE(std::equal(expected.begin(),expected.end(), vec.begin()));
std::vector<std::tuple<double, double, unsigned>> expected = {std::make_tuple(0, 0, 1),
std::make_tuple(20, 0, 2),
std::make_tuple(20, 15, 2),
std::make_tuple(0, 15, 2),
std::make_tuple(0, 0, 79)};
REQUIRE(std::equal(expected.begin(), expected.end(), vec.begin()));
}
SECTION("SVG rounded <rect>")
{
@ -345,46 +315,45 @@ TEST_CASE("SVG parser") {
REQUIRE(storage);
mapnik::svg::vertex_stl_adapter<mapnik::svg::svg_path_storage> stl_storage(storage->source());
mapnik::svg::svg_path_adapter path(stl_storage);
double x,y;
double x, y;
unsigned cmd;
std::vector<std::tuple<double,double,unsigned>> vec;
std::vector<std::tuple<double, double, unsigned>> vec;
while ((cmd = path.vertex(&x,&y)) != mapnik::SEG_END)
while ((cmd = path.vertex(&x, &y)) != mapnik::SEG_END)
{
vec.emplace_back(x, y, cmd);
}
std::vector<std::tuple<double,double,unsigned>> expected = {std::make_tuple(0, 5,1),
std::make_tuple(0.481856, 2.85842,2),
std::make_tuple(1.83455, 1.12961,2),
std::make_tuple(3.79736, 0.146789,2),
std::make_tuple(5, 0,2),
std::make_tuple(15, 0,2),
std::make_tuple(17.1416, 0.481856,2),
std::make_tuple(18.8704, 1.83455,2),
std::make_tuple(19.8532, 3.79736,2),
std::make_tuple(20, 5,2),
std::make_tuple(20, 10,2),
std::make_tuple(19.5181, 12.1416,2),
std::make_tuple(18.1654, 13.8704,2),
std::make_tuple(16.2026, 14.8532,2),
std::make_tuple(15, 15,2),
std::make_tuple(5, 15,2),
std::make_tuple(2.85842, 14.5181,2),
std::make_tuple(1.12961, 13.1654,2),
std::make_tuple(0.146789, 11.2026,2),
std::make_tuple(0, 10,2),
std::make_tuple(0, 10,95)};
std::vector<std::tuple<double, double, unsigned>> expected = {std::make_tuple(0, 5, 1),
std::make_tuple(0.481856, 2.85842, 2),
std::make_tuple(1.83455, 1.12961, 2),
std::make_tuple(3.79736, 0.146789, 2),
std::make_tuple(5, 0, 2),
std::make_tuple(15, 0, 2),
std::make_tuple(17.1416, 0.481856, 2),
std::make_tuple(18.8704, 1.83455, 2),
std::make_tuple(19.8532, 3.79736, 2),
std::make_tuple(20, 5, 2),
std::make_tuple(20, 10, 2),
std::make_tuple(19.5181, 12.1416, 2),
std::make_tuple(18.1654, 13.8704, 2),
std::make_tuple(16.2026, 14.8532, 2),
std::make_tuple(15, 15, 2),
std::make_tuple(5, 15, 2),
std::make_tuple(2.85842, 14.5181, 2),
std::make_tuple(1.12961, 13.1654, 2),
std::make_tuple(0.146789, 11.2026, 2),
std::make_tuple(0, 10, 2),
std::make_tuple(0, 10, 95)};
REQUIRE(std::equal(expected.begin(),expected.end(), vec.begin(),vertex_equal<3>()));
REQUIRE(std::equal(expected.begin(), expected.end(), vec.begin(), vertex_equal<3>()));
}
SECTION("SVG viewbox fallback")
{
std::string svg_name("./test/data/svg/viewbox-missing-width-and-height.svg");
std::ifstream in(svg_name.c_str());
std::string svg_str((std::istreambuf_iterator<char>(in)),
std::istreambuf_iterator<char>());
std::string svg_str((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
test_parser p;
p->parse_from_string(svg_str);
auto width = p.svg.width();
@ -406,37 +375,37 @@ TEST_CASE("SVG parser") {
REQUIRE(storage);
mapnik::svg::vertex_stl_adapter<mapnik::svg::svg_path_storage> stl_storage(storage->source());
mapnik::svg::svg_path_adapter path(stl_storage);
double x,y;
double x, y;
unsigned cmd;
std::vector<std::tuple<double,double,unsigned>> vec;
std::vector<std::tuple<double, double, unsigned>> vec;
while ((cmd = path.vertex(&x,&y)) != mapnik::SEG_END)
while ((cmd = path.vertex(&x, &y)) != mapnik::SEG_END)
{
vec.emplace_back(x, y, cmd);
}
std::vector<std::tuple<double,double,unsigned>> expected = {std::make_tuple(0, 5,1),
std::make_tuple(0.481856, 2.85842,2),
std::make_tuple(1.83455, 1.12961,2),
std::make_tuple(3.79736, 0.146789,2),
std::make_tuple(5, 0,2),
std::make_tuple(15, 0,2),
std::make_tuple(17.1416, 0.481856,2),
std::make_tuple(18.8704, 1.83455,2),
std::make_tuple(19.8532, 3.79736,2),
std::make_tuple(20, 5,2),
std::make_tuple(20, 10,2),
std::make_tuple(19.5181, 12.1416,2),
std::make_tuple(18.1654, 13.8704,2),
std::make_tuple(16.2026, 14.8532,2),
std::make_tuple(15, 15,2),
std::make_tuple(5, 15,2),
std::make_tuple(2.85842, 14.5181,2),
std::make_tuple(1.12961, 13.1654,2),
std::make_tuple(0.146789, 11.2026,2),
std::make_tuple(0, 10,2),
std::make_tuple(0, 10,95)};
std::vector<std::tuple<double, double, unsigned>> expected = {std::make_tuple(0, 5, 1),
std::make_tuple(0.481856, 2.85842, 2),
std::make_tuple(1.83455, 1.12961, 2),
std::make_tuple(3.79736, 0.146789, 2),
std::make_tuple(5, 0, 2),
std::make_tuple(15, 0, 2),
std::make_tuple(17.1416, 0.481856, 2),
std::make_tuple(18.8704, 1.83455, 2),
std::make_tuple(19.8532, 3.79736, 2),
std::make_tuple(20, 5, 2),
std::make_tuple(20, 10, 2),
std::make_tuple(19.5181, 12.1416, 2),
std::make_tuple(18.1654, 13.8704, 2),
std::make_tuple(16.2026, 14.8532, 2),
std::make_tuple(15, 15, 2),
std::make_tuple(5, 15, 2),
std::make_tuple(2.85842, 14.5181, 2),
std::make_tuple(1.12961, 13.1654, 2),
std::make_tuple(0.146789, 11.2026, 2),
std::make_tuple(0, 10, 2),
std::make_tuple(0, 10, 95)};
REQUIRE(std::equal(expected.begin(),expected.end(), vec.begin(),vertex_equal<3>()));
REQUIRE(std::equal(expected.begin(), expected.end(), vec.begin(), vertex_equal<3>()));
}
SECTION("SVG beveled <rect>")
@ -454,7 +423,7 @@ TEST_CASE("SVG parser") {
auto const& attrs = storage->attributes();
agg::line_join_e expected_join(agg::bevel_join);
REQUIRE(attrs.size() == 1 );
REQUIRE(attrs.size() == 1);
REQUIRE(attrs[0].line_join == expected_join);
}
@ -467,43 +436,31 @@ TEST_CASE("SVG parser") {
REQUIRE(marker->is<mapnik::marker_svg>());
mapnik::marker_svg const& svg = mapnik::util::get<mapnik::marker_svg>(*marker);
auto bbox = svg.bounding_box();
//REQUIRE(bbox == mapnik::box2d<double>(0.3543307086614174,0.3543307086614174,
// 424.8425196850394059,141.3779527559055396));
// REQUIRE(bbox == mapnik::box2d<double>(0.3543307086614174,0.3543307086614174,
// 424.8425196850394059,141.3779527559055396));
auto storage = svg.get_data();
REQUIRE(storage);
mapnik::svg::vertex_stl_adapter<mapnik::svg::svg_path_storage> stl_storage(storage->source());
mapnik::svg::svg_path_adapter path(stl_storage);
double x,y;
double x, y;
unsigned cmd;
std::vector<std::tuple<double,double,unsigned>> vec;
std::vector<std::tuple<double, double, unsigned>> vec;
std::size_t num_vertices = path.total_vertices();
for (std::size_t i = 0; i < num_vertices; ++i)
{
cmd = path.vertex(&x,&y);
cmd = path.vertex(&x, &y);
vec.emplace_back(x, y, cmd);
}
std::vector<std::tuple<double,double,unsigned>> expected = {std::make_tuple(1, 1, 1),
std::make_tuple(1199, 1, 2),
std::make_tuple(1199, 399, 2),
std::make_tuple(1, 399, 2),
std::make_tuple(1, 1, 79),
std::make_tuple(0, 0, 0),
std::make_tuple(100, 300, 1),
std::make_tuple(300, 100, 2),
std::make_tuple(0, 0, 0),
std::make_tuple(300, 300, 1),
std::make_tuple(500, 100, 2),
std::make_tuple(0, 0, 0),
std::make_tuple(500, 300, 1),
std::make_tuple(700, 100, 2),
std::make_tuple(0, 0, 0),
std::make_tuple(700, 300, 1),
std::make_tuple(900, 100, 2),
std::make_tuple(0, 0, 0),
std::make_tuple(900, 300, 1),
std::make_tuple(1100, 100, 2)};
std::vector<std::tuple<double, double, unsigned>> expected = {
std::make_tuple(1, 1, 1), std::make_tuple(1199, 1, 2), std::make_tuple(1199, 399, 2),
std::make_tuple(1, 399, 2), std::make_tuple(1, 1, 79), std::make_tuple(0, 0, 0),
std::make_tuple(100, 300, 1), std::make_tuple(300, 100, 2), std::make_tuple(0, 0, 0),
std::make_tuple(300, 300, 1), std::make_tuple(500, 100, 2), std::make_tuple(0, 0, 0),
std::make_tuple(500, 300, 1), std::make_tuple(700, 100, 2), std::make_tuple(0, 0, 0),
std::make_tuple(700, 300, 1), std::make_tuple(900, 100, 2), std::make_tuple(0, 0, 0),
std::make_tuple(900, 300, 1), std::make_tuple(1100, 100, 2)};
REQUIRE(std::equal(expected.begin(),expected.end(), vec.begin()));
REQUIRE(std::equal(expected.begin(), expected.end(), vec.begin()));
}
SECTION("SVG <polyline>")
@ -515,51 +472,34 @@ TEST_CASE("SVG parser") {
REQUIRE(marker->is<mapnik::marker_svg>());
mapnik::marker_svg const& svg = mapnik::util::get<mapnik::marker_svg>(*marker);
auto bbox = svg.bounding_box();
//REQUIRE(bbox == mapnik::box2d<double>(1.0,1.0,1199.0,399.0));
// REQUIRE(bbox == mapnik::box2d<double>(1.0,1.0,1199.0,399.0));
auto storage = svg.get_data();
REQUIRE(storage);
mapnik::svg::vertex_stl_adapter<mapnik::svg::svg_path_storage> stl_storage(storage->source());
mapnik::svg::svg_path_adapter path(stl_storage);
double x,y;
double x, y;
unsigned cmd;
std::vector<std::tuple<double,double,unsigned>> vec;
std::vector<std::tuple<double, double, unsigned>> vec;
std::size_t num_vertices = path.total_vertices();
for (std::size_t i = 0; i < num_vertices; ++i)
{
cmd = path.vertex(&x,&y);
cmd = path.vertex(&x, &y);
vec.emplace_back(x, y, cmd);
}
std::vector<std::tuple<double,double,unsigned>> expected = {std::make_tuple(1, 1, 1),
std::make_tuple(1199, 1, 2),
std::make_tuple(1199, 399, 2),
std::make_tuple(1, 399, 2),
std::make_tuple(1, 1, 79),
std::make_tuple(0, 0, 0),
std::make_tuple(50, 375, 1),
std::make_tuple(150, 375, 2),
std::make_tuple(150, 325, 2),
std::make_tuple(250, 325, 2),
std::make_tuple(250, 375, 2),
std::make_tuple(350, 375, 2),
std::make_tuple(350, 250, 2),
std::make_tuple(450, 250, 2),
std::make_tuple(450, 375, 2),
std::make_tuple(550, 375, 2),
std::make_tuple(550, 175, 2),
std::make_tuple(650, 175, 2),
std::make_tuple(650, 375, 2),
std::make_tuple(750, 375, 2),
std::make_tuple(750, 100, 2),
std::make_tuple(850, 100, 2),
std::make_tuple(850, 375, 2),
std::make_tuple(950, 375, 2),
std::make_tuple(950, 25, 2),
std::make_tuple(1050, 25, 2),
std::make_tuple(1050, 375, 2),
std::make_tuple(1150, 375, 2)};
std::vector<std::tuple<double, double, unsigned>> expected = {
std::make_tuple(1, 1, 1), std::make_tuple(1199, 1, 2), std::make_tuple(1199, 399, 2),
std::make_tuple(1, 399, 2), std::make_tuple(1, 1, 79), std::make_tuple(0, 0, 0),
std::make_tuple(50, 375, 1), std::make_tuple(150, 375, 2), std::make_tuple(150, 325, 2),
std::make_tuple(250, 325, 2), std::make_tuple(250, 375, 2), std::make_tuple(350, 375, 2),
std::make_tuple(350, 250, 2), std::make_tuple(450, 250, 2), std::make_tuple(450, 375, 2),
std::make_tuple(550, 375, 2), std::make_tuple(550, 175, 2), std::make_tuple(650, 175, 2),
std::make_tuple(650, 375, 2), std::make_tuple(750, 375, 2), std::make_tuple(750, 100, 2),
std::make_tuple(850, 100, 2), std::make_tuple(850, 375, 2), std::make_tuple(950, 375, 2),
std::make_tuple(950, 25, 2), std::make_tuple(1050, 25, 2), std::make_tuple(1050, 375, 2),
std::make_tuple(1150, 375, 2)};
REQUIRE(std::equal(expected.begin(),expected.end(), vec.begin()));
REQUIRE(std::equal(expected.begin(), expected.end(), vec.begin()));
}
SECTION("SVG <polygon>")
@ -571,48 +511,33 @@ TEST_CASE("SVG parser") {
REQUIRE(marker->is<mapnik::marker_svg>());
mapnik::marker_svg const& svg = mapnik::util::get<mapnik::marker_svg>(*marker);
auto bbox = svg.bounding_box();
//REQUIRE(bbox == mapnik::box2d<double>(1.0,1.0,1199.0,399.0));
// REQUIRE(bbox == mapnik::box2d<double>(1.0,1.0,1199.0,399.0));
auto storage = svg.get_data();
REQUIRE(storage);
mapnik::svg::vertex_stl_adapter<mapnik::svg::svg_path_storage> stl_storage(storage->source());
mapnik::svg::svg_path_adapter path(stl_storage);
double x,y;
double x, y;
unsigned cmd;
std::vector<std::tuple<double,double,unsigned>> vec;
std::vector<std::tuple<double, double, unsigned>> vec;
std::size_t num_vertices = path.total_vertices();
for (std::size_t i = 0; i < num_vertices; ++i)
{
cmd = path.vertex(&x,&y);
cmd = path.vertex(&x, &y);
vec.emplace_back(x, y, cmd);
}
std::vector<std::tuple<double,double,unsigned>> expected = {std::make_tuple(1, 1, 1),
std::make_tuple(1199, 1, 2),
std::make_tuple(1199, 399, 2),
std::make_tuple(1, 399, 2),
std::make_tuple(1, 1, 79),
std::make_tuple(0, 0, 0),
std::make_tuple(350, 75, 1),
std::make_tuple(379, 161, 2),
std::make_tuple(469, 161, 2),
std::make_tuple(397, 215, 2),
std::make_tuple(423, 301, 2),
std::make_tuple(350, 250, 2),
std::make_tuple(277, 301, 2),
std::make_tuple(303, 215, 2),
std::make_tuple(231, 161, 2),
std::make_tuple(321, 161, 2),
std::make_tuple(350, 75, 79),
std::make_tuple(0, 0, 0),
std::make_tuple(850, 75, 1),
std::make_tuple(958, 137.5, 2),
std::make_tuple(958, 262.5, 2),
std::make_tuple(850, 325, 2),
std::make_tuple(742, 262.6, 2),
std::make_tuple(742, 137.5, 2),
std::make_tuple(850, 75, 79)};
std::vector<std::tuple<double, double, unsigned>> expected = {
std::make_tuple(1, 1, 1), std::make_tuple(1199, 1, 2), std::make_tuple(1199, 399, 2),
std::make_tuple(1, 399, 2), std::make_tuple(1, 1, 79), std::make_tuple(0, 0, 0),
std::make_tuple(350, 75, 1), std::make_tuple(379, 161, 2), std::make_tuple(469, 161, 2),
std::make_tuple(397, 215, 2), std::make_tuple(423, 301, 2), std::make_tuple(350, 250, 2),
std::make_tuple(277, 301, 2), std::make_tuple(303, 215, 2), std::make_tuple(231, 161, 2),
std::make_tuple(321, 161, 2), std::make_tuple(350, 75, 79), std::make_tuple(0, 0, 0),
std::make_tuple(850, 75, 1), std::make_tuple(958, 137.5, 2), std::make_tuple(958, 262.5, 2),
std::make_tuple(850, 325, 2), std::make_tuple(742, 262.6, 2), std::make_tuple(742, 137.5, 2),
std::make_tuple(850, 75, 79)};
REQUIRE(std::equal(expected.begin(),expected.end(), vec.begin()));
REQUIRE(std::equal(expected.begin(), expected.end(), vec.begin()));
}
SECTION("SVG <gradient>")
@ -624,51 +549,48 @@ TEST_CASE("SVG parser") {
REQUIRE(marker->is<mapnik::marker_svg>());
mapnik::marker_svg const& svg = mapnik::util::get<mapnik::marker_svg>(*marker);
auto bbox = svg.bounding_box();
//REQUIRE(bbox == mapnik::box2d<double>(1.0,1.0,799.0,599.0));
// REQUIRE(bbox == mapnik::box2d<double>(1.0,1.0,799.0,599.0));
auto storage = svg.get_data();
REQUIRE(storage);
mapnik::svg::vertex_stl_adapter<mapnik::svg::svg_path_storage> stl_storage(storage->source());
mapnik::svg::svg_path_adapter path(stl_storage);
double x,y;
double x, y;
unsigned cmd;
std::vector<std::tuple<double,double,unsigned>> vec;
std::vector<std::tuple<double, double, unsigned>> vec;
std::size_t num_vertices = path.total_vertices();
for (std::size_t i = 0; i < num_vertices; ++i)
{
cmd = path.vertex(&x,&y);
cmd = path.vertex(&x, &y);
vec.emplace_back(x, y, cmd);
}
std::vector<std::tuple<double,double,unsigned>> expected = {std::make_tuple(1, 1, 1),
std::make_tuple(799, 1, 2),
std::make_tuple(799, 599, 2),
std::make_tuple(1, 599, 2),
std::make_tuple(1, 1, 79),
std::make_tuple(0, 0, 0),
std::make_tuple(100, 100, 1),
std::make_tuple(700, 100, 2),
std::make_tuple(700, 300, 2),
std::make_tuple(100, 300, 2),
std::make_tuple(100, 100, 79),
std::make_tuple(0, 0, 0),
std::make_tuple(100, 320, 1),
std::make_tuple(700, 320, 2),
std::make_tuple(700, 520, 2),
std::make_tuple(100, 520, 2),
std::make_tuple(100, 320, 79)};
std::vector<std::tuple<double, double, unsigned>> expected = {std::make_tuple(1, 1, 1),
std::make_tuple(799, 1, 2),
std::make_tuple(799, 599, 2),
std::make_tuple(1, 599, 2),
std::make_tuple(1, 1, 79),
std::make_tuple(0, 0, 0),
std::make_tuple(100, 100, 1),
std::make_tuple(700, 100, 2),
std::make_tuple(700, 300, 2),
std::make_tuple(100, 300, 2),
std::make_tuple(100, 100, 79),
std::make_tuple(0, 0, 0),
std::make_tuple(100, 320, 1),
std::make_tuple(700, 320, 2),
std::make_tuple(700, 520, 2),
std::make_tuple(100, 520, 2),
std::make_tuple(100, 320, 79)};
REQUIRE(std::equal(expected.begin(),expected.end(), vec.begin()));
REQUIRE(std::equal(expected.begin(), expected.end(), vec.begin()));
}
SECTION("SVG missing <gradient> def")
{
std::string svg_name("./test/data/svg/gradient-nodef.svg");
char const* expected_errors[] =
{
"SVG parse error: failed to locate fill with <id> \"MyGradient\"",
"SVG parse error: failed to locate stroke with <id> \"MyGradient\""
};
char const* expected_errors[] = {"SVG parse error: failed to locate fill with <id> \"MyGradient\"",
"SVG parse error: failed to locate stroke with <id> \"MyGradient\""};
{
test_parser p;
p->parse(svg_name);
@ -679,8 +601,7 @@ TEST_CASE("SVG parser") {
try
{
p->parse(svg_name);
}
catch (std::exception const& ex)
} catch (std::exception const& ex)
{
REQUIRE(ex.what() == std::string(expected_errors[0]));
}
@ -690,15 +611,11 @@ TEST_CASE("SVG parser") {
SECTION("SVG missing <gradient> id")
{
std::string svg_name("./test/data/svg/gradient-no-id.svg");
char const* expected_errors[] =
{
"SVG parse error: failed to locate fill with <id> \"MyGradient\"",
"SVG parse error: failed to locate stroke with <id> \"MyGradient\""
};
char const* expected_errors[] = {"SVG parse error: failed to locate fill with <id> \"MyGradient\"",
"SVG parse error: failed to locate stroke with <id> \"MyGradient\""};
std::ifstream in(svg_name.c_str());
std::string svg_str((std::istreambuf_iterator<char>(in)),
std::istreambuf_iterator<char>());
std::string svg_str((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
{
test_parser p;
@ -710,8 +627,7 @@ TEST_CASE("SVG parser") {
try
{
p->parse_from_string(svg_str);
}
catch (std::exception const& ex)
} catch (std::exception const& ex)
{
REQUIRE(ex.what() == std::string(expected_errors[0]));
}
@ -727,45 +643,45 @@ TEST_CASE("SVG parser") {
REQUIRE(marker->is<mapnik::marker_svg>());
mapnik::marker_svg const& svg = mapnik::util::get<mapnik::marker_svg>(*marker);
auto bbox = svg.bounding_box();
//REQUIRE(bbox == mapnik::box2d<double>(1.0,1.0,699.0,199.0));
// REQUIRE(bbox == mapnik::box2d<double>(1.0,1.0,699.0,199.0));
auto storage = svg.get_data();
REQUIRE(storage);
mapnik::svg::vertex_stl_adapter<mapnik::svg::svg_path_storage> stl_storage(storage->source());
auto const& attrs = storage->attributes();
REQUIRE(attrs.size() == 3 );
REQUIRE(attrs.size() == 3);
REQUIRE(attrs[1].fill_gradient == attrs[2].fill_gradient);
mapnik::svg::svg_path_adapter path(stl_storage);
double x,y;
double x, y;
unsigned cmd;
std::vector<std::tuple<double,double,unsigned>> vec;
std::vector<std::tuple<double, double, unsigned>> vec;
std::size_t num_vertices = path.total_vertices();
for (std::size_t i = 0; i < num_vertices; ++i)
{
cmd = path.vertex(&x,&y);
cmd = path.vertex(&x, &y);
vec.emplace_back(x, y, cmd);
}
std::vector<std::tuple<double,double,unsigned>> expected = {std::make_tuple(1, 1, 1),
std::make_tuple(699, 1, 2),
std::make_tuple(699, 199, 2),
std::make_tuple(1, 199, 2),
std::make_tuple(1, 1, 79),
std::make_tuple(0, 0, 0),
std::make_tuple(100, 50, 1),
std::make_tuple(300, 50, 2),
std::make_tuple(300, 150, 2),
std::make_tuple(100, 150, 2),
std::make_tuple(100, 50, 79),
std::make_tuple(0, 0, 0),
std::make_tuple(400, 50, 1),
std::make_tuple(600, 50, 2),
std::make_tuple(600, 150, 2),
std::make_tuple(400, 150, 2),
std::make_tuple(400, 50, 79)};
std::vector<std::tuple<double, double, unsigned>> expected = {std::make_tuple(1, 1, 1),
std::make_tuple(699, 1, 2),
std::make_tuple(699, 199, 2),
std::make_tuple(1, 199, 2),
std::make_tuple(1, 1, 79),
std::make_tuple(0, 0, 0),
std::make_tuple(100, 50, 1),
std::make_tuple(300, 50, 2),
std::make_tuple(300, 150, 2),
std::make_tuple(100, 150, 2),
std::make_tuple(100, 50, 79),
std::make_tuple(0, 0, 0),
std::make_tuple(400, 50, 1),
std::make_tuple(600, 50, 2),
std::make_tuple(600, 150, 2),
std::make_tuple(400, 150, 2),
std::make_tuple(400, 50, 79)};
REQUIRE(std::equal(expected.begin(),expected.end(), vec.begin()));
REQUIRE(std::equal(expected.begin(), expected.end(), vec.begin()));
}
SECTION("SVG <gradient> with transformations")
@ -777,16 +693,16 @@ TEST_CASE("SVG parser") {
REQUIRE(marker->is<mapnik::marker_svg>());
mapnik::marker_svg const& svg = mapnik::util::get<mapnik::marker_svg>(*marker);
auto bbox = svg.bounding_box();
//REQUIRE(bbox == mapnik::box2d<double>(1.0,1.0,799.0,599.0));
// REQUIRE(bbox == mapnik::box2d<double>(1.0,1.0,799.0,599.0));
auto storage = svg.get_data();
REQUIRE(storage);
auto const& attrs = storage->attributes();
REQUIRE(attrs.size() == 3 );
REQUIRE(attrs.size() == 3);
REQUIRE(attrs[1].fill_gradient == attrs[2].fill_gradient);
REQUIRE(attrs[1].fill_gradient.get_gradient_type() == mapnik::RADIAL);
agg::trans_affine transform;
transform *= agg::trans_affine_translation(240,155);
transform *= agg::trans_affine_translation(240, 155);
REQUIRE(attrs[1].fill_gradient.get_transform() == transform);
}
@ -798,12 +714,12 @@ TEST_CASE("SVG parser") {
REQUIRE(marker->is<mapnik::marker_svg>());
mapnik::marker_svg const& svg = mapnik::util::get<mapnik::marker_svg>(*marker);
auto bbox = svg.bounding_box();
//REQUIRE(bbox == mapnik::box2d<double>(20,20,460,230));
// REQUIRE(bbox == mapnik::box2d<double>(20,20,460,230));
auto storage = svg.get_data();
REQUIRE(storage);
auto const& attrs = storage->attributes();
REQUIRE(attrs.size() == 2 );
REQUIRE(attrs.size() == 2);
REQUIRE(attrs[0].fill_gradient.get_gradient_type() == mapnik::LINEAR);
REQUIRE(attrs[1].fill_gradient.get_gradient_type() == mapnik::LINEAR);
REQUIRE(attrs[1].fill_gradient.has_stop());
@ -817,13 +733,13 @@ TEST_CASE("SVG parser") {
REQUIRE(marker->is<mapnik::marker_svg>());
mapnik::marker_svg const& svg = mapnik::util::get<mapnik::marker_svg>(*marker);
auto bbox = svg.bounding_box();
//REQUIRE(bbox == mapnik::box2d<double>(0,0,200,200));
// REQUIRE(bbox == mapnik::box2d<double>(0,0,200,200));
auto storage = svg.get_data();
REQUIRE(storage);
double x1, x2, y1, y2, r;
auto const& attrs = storage->attributes();
REQUIRE(attrs.size() == 1 );
REQUIRE(attrs.size() == 1);
REQUIRE(attrs[0].fill_gradient.get_gradient_type() == mapnik::RADIAL);
REQUIRE(attrs[0].fill_gradient.has_stop());
attrs[0].fill_gradient.get_control_points(x1, y1, x2, y2, r);

View file

@ -31,7 +31,7 @@
namespace {
template <typename Expected>
template<typename Expected>
void test_path_parser(std::string const& str, Expected const& expected)
{
using namespace mapnik::svg;
@ -41,31 +41,30 @@ void test_path_parser(std::string const& str, Expected const& expected)
svg_converter_type svg(svg_path, marker_path->attributes());
CHECK(mapnik::svg::parse_path(str.c_str(), svg));
double x,y;
double x, y;
unsigned cmd;
auto & p = svg.storage();
std::vector<std::tuple<double,double,unsigned>> vec;
while ((cmd = p.vertex(&x,&y)) != mapnik::SEG_END)
auto& p = svg.storage();
std::vector<std::tuple<double, double, unsigned>> vec;
while ((cmd = p.vertex(&x, &y)) != mapnik::SEG_END)
{
vec.emplace_back(x, y, cmd);
//std::cerr << "std::make_tuple(" << x << ", " << y << ", " << cmd << ")," << std::endl;
// std::cerr << "std::make_tuple(" << x << ", " << y << ", " << cmd << ")," << std::endl;
}
REQUIRE(std::equal(expected.begin(),expected.end(), vec.begin(), vertex_equal<3>()));
REQUIRE(std::equal(expected.begin(), expected.end(), vec.begin(), vertex_equal<3>()));
}
} // anonymous ns
TEST_CASE("SVG path parser") {
} // namespace
TEST_CASE("SVG path parser")
{
SECTION("MoveTo/LineTo")
{
std::string str = "M 100 100 L 300 100 L 200 300 z";
std::string str2 = "M100,100L300,100L200,300z";
std::string str3 = "M100,100l200 0L200,300z";
std::vector<std::tuple<double,double,unsigned>> expected = {
std::make_tuple(100, 100, 1),
std::make_tuple(300, 100, 2),
std::make_tuple(200, 300, 2),
std::make_tuple(100, 100, 79) };
std::vector<std::tuple<double, double, unsigned>> expected = {std::make_tuple(100, 100, 1),
std::make_tuple(300, 100, 2),
std::make_tuple(200, 300, 2),
std::make_tuple(100, 100, 79)};
test_path_parser(str, expected);
test_path_parser(str2, expected);
test_path_parser(str3, expected);
@ -75,12 +74,10 @@ TEST_CASE("SVG path parser") {
{
std::string str = "M100 100H300V200z";
std::string str2 = "M100,100h200v100z";
std::vector<std::tuple<double,double,unsigned>> expected = {
std::make_tuple(100, 100, 1),
std::make_tuple(300, 100, 2),
std::make_tuple(300, 200, 2),
std::make_tuple(100, 100, 79)
};
std::vector<std::tuple<double, double, unsigned>> expected = {std::make_tuple(100, 100, 1),
std::make_tuple(300, 100, 2),
std::make_tuple(300, 200, 2),
std::make_tuple(100, 100, 79)};
test_path_parser(str, expected);
test_path_parser(str2, expected);
}
@ -89,76 +86,58 @@ TEST_CASE("SVG path parser") {
{
std::string str = "M300,200 h-150 a150,150 0 1,0 150,-150 z";
std::vector<std::tuple<double,double,unsigned>> expected = {
std::make_tuple(300, 200, 1),
std::make_tuple(150, 200, 2),
std::make_tuple(150, 282.843, 4),
std::make_tuple(217.157, 350, 4),
std::make_tuple(300, 350, 4),
std::make_tuple(382.843, 350, 4),
std::make_tuple(450, 282.843, 4),
std::make_tuple(450, 200, 4),
std::make_tuple(450, 117.157, 4),
std::make_tuple(382.843, 50, 4),
std::make_tuple(300, 50, 4),
std::make_tuple(300, 200, 79)};
std::vector<std::tuple<double, double, unsigned>> expected = {std::make_tuple(300, 200, 1),
std::make_tuple(150, 200, 2),
std::make_tuple(150, 282.843, 4),
std::make_tuple(217.157, 350, 4),
std::make_tuple(300, 350, 4),
std::make_tuple(382.843, 350, 4),
std::make_tuple(450, 282.843, 4),
std::make_tuple(450, 200, 4),
std::make_tuple(450, 117.157, 4),
std::make_tuple(382.843, 50, 4),
std::make_tuple(300, 50, 4),
std::make_tuple(300, 200, 79)};
test_path_parser(str, expected);
}
SECTION("Arcs 2")
{
std::string str = "M275,175 v-150 a150,150 0 0,0 -150,150 z";
std::vector<std::tuple<double,double,unsigned>> expected = {
std::make_tuple(275, 175, 1),
std::make_tuple(275, 25, 2),
std::make_tuple(192.157, 25, 4),
std::make_tuple(125, 92.1573, 4),
std::make_tuple(125, 175, 4),
std::make_tuple(275, 175, 79)};
std::vector<std::tuple<double, double, unsigned>> expected = {std::make_tuple(275, 175, 1),
std::make_tuple(275, 25, 2),
std::make_tuple(192.157, 25, 4),
std::make_tuple(125, 92.1573, 4),
std::make_tuple(125, 175, 4),
std::make_tuple(275, 175, 79)};
test_path_parser(str, expected);
}
SECTION("Arcs 3")
{
std::string str = "M600,350 l 50,-25"
"a25,25 -30 0,1 50,-25 l 50,-25"
"a25,50 -30 01 50,-25 l 50,-25"
"a25,75 -30 0150,-25 l 50,-25"
"a25,100-30 0150-25l50-25";
"a25,25 -30 0,1 50,-25 l 50,-25"
"a25,50 -30 01 50,-25 l 50,-25"
"a25,75 -30 0150,-25 l 50,-25"
"a25,100-30 0150-25l50-25";
std::vector<std::tuple<double,double,unsigned>> expected = {
std::make_tuple(600, 350, 1),
std::make_tuple(650, 325, 2),
std::make_tuple(643.096, 311.193, 4),
std::make_tuple(648.693, 294.404, 4),
std::make_tuple(662.5, 287.5, 4),
std::make_tuple(676.307, 280.596, 4),
std::make_tuple(693.096, 286.193, 4),
std::make_tuple(700, 300, 4),
std::make_tuple(750, 275, 2),
std::make_tuple(734.991, 248.079, 4),
std::make_tuple(734.017, 220.66, 4),
std::make_tuple(747.825, 213.756, 4),
std::make_tuple(761.632, 206.852, 4),
std::make_tuple(784.991, 223.079, 4),
std::make_tuple(800, 250, 4),
std::make_tuple(850, 225, 2),
std::make_tuple(827.153, 184.812, 4),
std::make_tuple(819.825, 146.636, 4),
std::make_tuple(833.632, 139.733, 4),
std::make_tuple(847.44, 132.829, 4),
std::make_tuple(877.153, 159.812, 4),
std::make_tuple(900, 200, 4),
std::make_tuple(950, 175, 2),
std::make_tuple(919.382, 121.506, 4),
std::make_tuple(905.754, 72.5436, 4),
std::make_tuple(919.561, 65.64, 4),
std::make_tuple(933.368, 58.7365, 4),
std::make_tuple(969.382, 96.5057, 4),
std::make_tuple(1000, 150, 4),
std::make_tuple(1050, 125, 2)};
std::vector<std::tuple<double, double, unsigned>> expected = {
std::make_tuple(600, 350, 1), std::make_tuple(650, 325, 2),
std::make_tuple(643.096, 311.193, 4), std::make_tuple(648.693, 294.404, 4),
std::make_tuple(662.5, 287.5, 4), std::make_tuple(676.307, 280.596, 4),
std::make_tuple(693.096, 286.193, 4), std::make_tuple(700, 300, 4),
std::make_tuple(750, 275, 2), std::make_tuple(734.991, 248.079, 4),
std::make_tuple(734.017, 220.66, 4), std::make_tuple(747.825, 213.756, 4),
std::make_tuple(761.632, 206.852, 4), std::make_tuple(784.991, 223.079, 4),
std::make_tuple(800, 250, 4), std::make_tuple(850, 225, 2),
std::make_tuple(827.153, 184.812, 4), std::make_tuple(819.825, 146.636, 4),
std::make_tuple(833.632, 139.733, 4), std::make_tuple(847.44, 132.829, 4),
std::make_tuple(877.153, 159.812, 4), std::make_tuple(900, 200, 4),
std::make_tuple(950, 175, 2), std::make_tuple(919.382, 121.506, 4),
std::make_tuple(905.754, 72.5436, 4), std::make_tuple(919.561, 65.64, 4),
std::make_tuple(933.368, 58.7365, 4), std::make_tuple(969.382, 96.5057, 4),
std::make_tuple(1000, 150, 4), std::make_tuple(1050, 125, 2)};
test_path_parser(str, expected);
}
@ -166,12 +145,11 @@ TEST_CASE("SVG path parser") {
{
std::string str = "M200,300 Q400,50 600,300 T1000,300";
std::vector<std::tuple<double,double,unsigned>> expected = {
std::make_tuple(200, 300, 1),
std::make_tuple(400, 50, 3),
std::make_tuple(600, 300, 3),
std::make_tuple(800, 550, 3),
std::make_tuple(1000, 300, 3)};
std::vector<std::tuple<double, double, unsigned>> expected = {std::make_tuple(200, 300, 1),
std::make_tuple(400, 50, 3),
std::make_tuple(600, 300, 3),
std::make_tuple(800, 550, 3),
std::make_tuple(1000, 300, 3)};
test_path_parser(str, expected);
}
@ -179,14 +157,13 @@ TEST_CASE("SVG path parser") {
{
std::string str = "M100,200 C100,100 250,100 250,200S400,300 400,200";
std::vector<std::tuple<double,double,unsigned>> expected = {
std::make_tuple(100, 200, 1),
std::make_tuple(100, 100, 4),
std::make_tuple(250, 100, 4),
std::make_tuple(250, 200, 4),
std::make_tuple(250, 300, 4),
std::make_tuple(400, 300, 4),
std::make_tuple(400, 200, 4)};
std::vector<std::tuple<double, double, unsigned>> expected = {std::make_tuple(100, 200, 1),
std::make_tuple(100, 100, 4),
std::make_tuple(250, 100, 4),
std::make_tuple(250, 200, 4),
std::make_tuple(250, 300, 4),
std::make_tuple(400, 300, 4),
std::make_tuple(400, 200, 4)};
test_path_parser(str, expected);
}

View file

@ -44,43 +44,40 @@ MAPNIK_DISABLE_WARNING_PUSH
#include "agg_scanline_u.h"
MAPNIK_DISABLE_WARNING_POP
namespace
{
namespace {
mapnik::image_rgba8 render_svg(std::string const& filename, double scale_factor)
{
using pixfmt = agg::pixfmt_rgba32_pre;
using renderer_base = agg::renderer_base<pixfmt>;
using renderer_solid = agg::renderer_scanline_aa_solid<renderer_base>;
using pixfmt = agg::pixfmt_rgba32_pre;
using renderer_base = agg::renderer_base<pixfmt>;
using renderer_solid = agg::renderer_scanline_aa_solid<renderer_base>;
agg::rasterizer_scanline_aa<> ras_ptr;
agg::scanline_u8 sl;
std::shared_ptr<mapnik::marker const> marker = mapnik::marker_cache::instance().find(filename, false);
mapnik::marker_svg const& svg = mapnik::util::get<mapnik::marker_svg>(*marker);
double svg_width, svg_height ;
std::tie(svg_width, svg_height) = svg.dimensions();
int image_width = static_cast<int>(std::round(svg_width));
int image_height = static_cast<int>(std::round(svg_height));
agg::rasterizer_scanline_aa<> ras_ptr;
agg::scanline_u8 sl;
std::shared_ptr<mapnik::marker const> marker = mapnik::marker_cache::instance().find(filename, false);
mapnik::marker_svg const& svg = mapnik::util::get<mapnik::marker_svg>(*marker);
double svg_width, svg_height;
std::tie(svg_width, svg_height) = svg.dimensions();
int image_width = static_cast<int>(std::round(svg_width));
int image_height = static_cast<int>(std::round(svg_height));
mapnik::image_rgba8 im(image_width, image_height, true, true);
agg::rendering_buffer buf(im.bytes(), im.width(), im.height(), im.row_size());
pixfmt pixf(buf);
renderer_base renb(pixf);
mapnik::image_rgba8 im(image_width, image_height, true, true);
agg::rendering_buffer buf(im.bytes(), im.width(), im.height(), im.row_size());
pixfmt pixf(buf);
renderer_base renb(pixf);
agg::trans_affine mtx = agg::trans_affine_translation(-0.5 * svg_width, -0.5 * svg_height);
mtx.scale(scale_factor);
mtx.translate(0.5 * svg_width, 0.5 * svg_height);
agg::trans_affine mtx = agg::trans_affine_translation(-0.5 * svg_width, -0.5 * svg_height);
mtx.scale(scale_factor);
mtx.translate(0.5 * svg_width, 0.5 * svg_height);
mapnik::svg::vertex_stl_adapter<mapnik::svg::svg_path_storage> stl_storage(svg.get_data()->source());
mapnik::svg::svg_path_adapter svg_path(stl_storage);
mapnik::svg::renderer_agg<mapnik::svg_path_adapter,
mapnik::svg_attribute_type,
renderer_solid,
agg::pixfmt_rgba32_pre > renderer(svg_path,
svg.get_data()->attributes());
double opacity = 1.0;
renderer.render(ras_ptr, sl, renb, mtx, opacity, {0, 0, svg_width, svg_height});
return im;
mapnik::svg::vertex_stl_adapter<mapnik::svg::svg_path_storage> stl_storage(svg.get_data()->source());
mapnik::svg::svg_path_adapter svg_path(stl_storage);
mapnik::svg::
renderer_agg<mapnik::svg_path_adapter, mapnik::svg_attribute_type, renderer_solid, agg::pixfmt_rgba32_pre>
renderer(svg_path, svg.get_data()->attributes());
double opacity = 1.0;
renderer.render(ras_ptr, sl, renb, mtx, opacity, {0, 0, svg_width, svg_height});
return im;
}
bool equal(mapnik::image_rgba8 const& im1, mapnik::image_rgba8 const& im2)
@ -88,16 +85,17 @@ bool equal(mapnik::image_rgba8 const& im1, mapnik::image_rgba8 const& im2)
if (im1.width() != im2.width() || im1.height() != im2.height())
return false;
for(auto tup : boost::combine(im1, im2))
for (auto tup : boost::combine(im1, im2))
{
if (boost::get<0>(tup) != boost::get<1>(tup)) return false;
if (boost::get<0>(tup) != boost::get<1>(tup))
return false;
}
return true;
}
}
TEST_CASE("SVG renderer") {
} // namespace
TEST_CASE("SVG renderer")
{
SECTION("SVG octocat inline/css")
{
double scale_factor = 1.0;

View file

@ -27,18 +27,17 @@
namespace {
template <int N = 6>
template<int N = 6>
struct vertex_equal
{
template <typename T>
bool operator() (T const& lhs, T const& rhs) const
template<typename T>
bool operator()(T const& lhs, T const& rhs) const
{
static const double eps = 1.0 / std::pow(10,N);
return (std::fabs(std::get<0>(lhs) - std::get<0>(rhs)) < eps)
&& (std::fabs(std::get<1>(lhs) - std::get<1>(rhs)) < eps)
&& std::get<2>(lhs) == std::get<2>(rhs);
static const double eps = 1.0 / std::pow(10, N);
return (std::fabs(std::get<0>(lhs) - std::get<0>(rhs)) < eps) &&
(std::fabs(std::get<1>(lhs) - std::get<1>(rhs)) < eps) && std::get<2>(lhs) == std::get<2>(rhs);
}
};
}
} // namespace
#endif // TEST_UNIT_SVG_UTIL_HPP

View file

@ -7,120 +7,139 @@
using namespace mapnik;
TEST_CASE("marker placement vertex last") {
TEST_CASE("marker placement vertex last")
{
SECTION("empty geometry")
{
mapnik::geometry::line_string<double> g;
using va_type = mapnik::geometry::line_string_vertex_adapter<double>;
va_type va(g);
SECTION("empty geometry") {
using detector_type = mapnik::label_collision_detector4;
detector_type detector(mapnik::box2d<double>(0, 0, 100, 100));
mapnik::geometry::line_string<double> g;
using va_type = mapnik::geometry::line_string_vertex_adapter<double>;
va_type va(g);
using placement_type = mapnik::markers_vertex_last_placement<va_type, detector_type>;
using detector_type = mapnik::label_collision_detector4;
detector_type detector(mapnik::box2d<double>(0, 0, 100, 100));
mapnik::markers_placement_params params{mapnik::box2d<double>(0, 0, 10, 10),
agg::trans_affine(),
0,
NAN,
0,
false,
false,
DIRECTION_AUTO,
1.0};
using placement_type = mapnik::markers_vertex_last_placement<va_type, detector_type>;
placement_type placement(va, detector, params);
mapnik::markers_placement_params params {
mapnik::box2d<double>(0, 0, 10, 10),
agg::trans_affine(),
0, NAN, 0, false, false, DIRECTION_AUTO, 1.0 };
double x, y, angle;
CHECK(!placement.get_point(x, y, angle, true));
}
placement_type placement(va, detector, params);
double x, y, angle;
CHECK( !placement.get_point(x, y, angle, true) );
}
SECTION("point") {
mapnik::geometry::point<double> g(2.0, 3.0);
using va_type = mapnik::geometry::point_vertex_adapter<double>;
va_type va(g);
using detector_type = mapnik::label_collision_detector4;
detector_type detector(mapnik::box2d<double>(0, 0, 100, 100));
using placement_type = mapnik::markers_vertex_last_placement<va_type, detector_type>;
mapnik::markers_placement_params params {
mapnik::box2d<double>(0, 0, 10, 10),
agg::trans_affine(),
0, NAN, 0, false, false, DIRECTION_AUTO, 1.0 };
placement_type placement(va, detector, params);
double x, y, angle;
CHECK( placement.get_point(x, y, angle, true) );
CHECK( x == Approx(2.0) );
CHECK( y == Approx(3.0) );
CHECK( angle == Approx(0.0) );
CHECK( !placement.get_point(x, y, angle, true) );
}
SECTION("line string") {
mapnik::geometry::line_string<double> g;
g.emplace_back(1.0, 1.0);
g.emplace_back(2.0, 3.0);
using va_type = mapnik::geometry::line_string_vertex_adapter<double>;
va_type va(g);
using detector_type = mapnik::label_collision_detector4;
detector_type detector(mapnik::box2d<double>(0, 0, 100, 100));
using placement_type = mapnik::markers_vertex_last_placement<va_type, detector_type>;
mapnik::markers_placement_params params {
mapnik::box2d<double>(0, 0, 10, 10),
agg::trans_affine(),
0, NAN, 0, false, false, DIRECTION_AUTO, 1.0 };
placement_type placement(va, detector, params);
double x, y, angle;
CHECK( placement.get_point(x, y, angle, true) );
CHECK( x == Approx(2.0) );
CHECK( y == Approx(3.0) );
CHECK( angle == Approx(1.1071487178) );
CHECK( !placement.get_point(x, y, angle, true) );
}
SECTION("polygon") {
mapnik::geometry::polygon<double> g;
g.emplace_back();
auto & exterior = g.back();
exterior.emplace_back(2.0, 3.0);
exterior.emplace_back(1.0, 1.0);
exterior.emplace_back(0.0, 2.0);
exterior.emplace_back(2.0, 3.0);
using va_type = mapnik::geometry::polygon_vertex_adapter<double>;
va_type va(g);
using detector_type = mapnik::label_collision_detector4;
detector_type detector(mapnik::box2d<double>(0, 0, 100, 100));
using placement_type = mapnik::markers_vertex_last_placement<va_type, detector_type>;
mapnik::markers_placement_params params {
mapnik::box2d<double>(0, 0, 10, 10),
agg::trans_affine(),
0, NAN, 0, false, false, DIRECTION_AUTO, 1.0 };
placement_type placement(va, detector, params);
double x, y, angle;
CHECK( placement.get_point(x, y, angle, true) );
CHECK( x == Approx(2.0) );
CHECK( y == Approx(3.0) );
CHECK( angle == Approx(0.463647609) );
CHECK( !placement.get_point(x, y, angle, true) );
}
SECTION("point")
{
mapnik::geometry::point<double> g(2.0, 3.0);
using va_type = mapnik::geometry::point_vertex_adapter<double>;
va_type va(g);
using detector_type = mapnik::label_collision_detector4;
detector_type detector(mapnik::box2d<double>(0, 0, 100, 100));
using placement_type = mapnik::markers_vertex_last_placement<va_type, detector_type>;
mapnik::markers_placement_params params{mapnik::box2d<double>(0, 0, 10, 10),
agg::trans_affine(),
0,
NAN,
0,
false,
false,
DIRECTION_AUTO,
1.0};
placement_type placement(va, detector, params);
double x, y, angle;
CHECK(placement.get_point(x, y, angle, true));
CHECK(x == Approx(2.0));
CHECK(y == Approx(3.0));
CHECK(angle == Approx(0.0));
CHECK(!placement.get_point(x, y, angle, true));
}
SECTION("line string")
{
mapnik::geometry::line_string<double> g;
g.emplace_back(1.0, 1.0);
g.emplace_back(2.0, 3.0);
using va_type = mapnik::geometry::line_string_vertex_adapter<double>;
va_type va(g);
using detector_type = mapnik::label_collision_detector4;
detector_type detector(mapnik::box2d<double>(0, 0, 100, 100));
using placement_type = mapnik::markers_vertex_last_placement<va_type, detector_type>;
mapnik::markers_placement_params params{mapnik::box2d<double>(0, 0, 10, 10),
agg::trans_affine(),
0,
NAN,
0,
false,
false,
DIRECTION_AUTO,
1.0};
placement_type placement(va, detector, params);
double x, y, angle;
CHECK(placement.get_point(x, y, angle, true));
CHECK(x == Approx(2.0));
CHECK(y == Approx(3.0));
CHECK(angle == Approx(1.1071487178));
CHECK(!placement.get_point(x, y, angle, true));
}
SECTION("polygon")
{
mapnik::geometry::polygon<double> g;
g.emplace_back();
auto& exterior = g.back();
exterior.emplace_back(2.0, 3.0);
exterior.emplace_back(1.0, 1.0);
exterior.emplace_back(0.0, 2.0);
exterior.emplace_back(2.0, 3.0);
using va_type = mapnik::geometry::polygon_vertex_adapter<double>;
va_type va(g);
using detector_type = mapnik::label_collision_detector4;
detector_type detector(mapnik::box2d<double>(0, 0, 100, 100));
using placement_type = mapnik::markers_vertex_last_placement<va_type, detector_type>;
mapnik::markers_placement_params params{mapnik::box2d<double>(0, 0, 10, 10),
agg::trans_affine(),
0,
NAN,
0,
false,
false,
DIRECTION_AUTO,
1.0};
placement_type placement(va, detector, params);
double x, y, angle;
CHECK(placement.get_point(x, y, angle, true));
CHECK(x == Approx(2.0));
CHECK(y == Approx(3.0));
CHECK(angle == Approx(0.463647609));
CHECK(!placement.get_point(x, y, angle, true));
}
}

View file

@ -7,116 +7,135 @@
using namespace mapnik;
TEST_CASE("marker placement point") {
TEST_CASE("marker placement point")
{
SECTION("empty geometry")
{
mapnik::geometry::line_string<double> g;
using va_type = mapnik::geometry::line_string_vertex_adapter<double>;
va_type va(g);
SECTION("empty geometry") {
using detector_type = mapnik::label_collision_detector4;
detector_type detector(mapnik::box2d<double>(0, 0, 100, 100));
mapnik::geometry::line_string<double> g;
using va_type = mapnik::geometry::line_string_vertex_adapter<double>;
va_type va(g);
using placement_type = mapnik::markers_point_placement<va_type, detector_type>;
using detector_type = mapnik::label_collision_detector4;
detector_type detector(mapnik::box2d<double>(0, 0, 100, 100));
mapnik::markers_placement_params params{mapnik::box2d<double>(0, 0, 10, 10),
agg::trans_affine(),
0,
NAN,
0,
false,
false,
DIRECTION_AUTO,
1.0};
using placement_type = mapnik::markers_point_placement<va_type, detector_type>;
placement_type placement(va, detector, params);
mapnik::markers_placement_params params {
mapnik::box2d<double>(0, 0, 10, 10),
agg::trans_affine(),
0, NAN, 0, false, false, DIRECTION_AUTO, 1.0 };
double x, y, angle;
CHECK(!placement.get_point(x, y, angle, true));
}
placement_type placement(va, detector, params);
double x, y, angle;
CHECK( !placement.get_point(x, y, angle, true) );
}
SECTION("point") {
mapnik::geometry::point<double> g(2.0, 3.0);
using va_type = mapnik::geometry::point_vertex_adapter<double>;
va_type va(g);
using detector_type = mapnik::label_collision_detector4;
detector_type detector(mapnik::box2d<double>(0, 0, 100, 100));
using placement_type = mapnik::markers_point_placement<va_type, detector_type>;
mapnik::markers_placement_params params {
mapnik::box2d<double>(0, 0, 10, 10),
agg::trans_affine(),
0, NAN, 0, false, false, DIRECTION_AUTO, 1.0 };
placement_type placement(va, detector, params);
double x, y, angle;
CHECK( placement.get_point(x, y, angle, true) );
CHECK( x == Approx(2.0) );
CHECK( y == Approx(3.0) );
CHECK( angle == Approx(0.0) );
CHECK( !placement.get_point(x, y, angle, true) );
}
SECTION("line string") {
mapnik::geometry::line_string<double> g;
g.emplace_back(1.0, 1.0);
g.emplace_back(2.0, 2.0);
using va_type = mapnik::geometry::line_string_vertex_adapter<double>;
va_type va(g);
using detector_type = mapnik::label_collision_detector4;
detector_type detector(mapnik::box2d<double>(0, 0, 100, 100));
using placement_type = mapnik::markers_point_placement<va_type, detector_type>;
mapnik::markers_placement_params params {
mapnik::box2d<double>(0, 0, 10, 10),
agg::trans_affine(),
0, NAN, 0, false, false, DIRECTION_AUTO, 1.0 };
placement_type placement(va, detector, params);
double x, y, angle;
CHECK( placement.get_point(x, y, angle, true) );
CHECK( x == Approx(1.5) );
CHECK( y == Approx(1.5) );
CHECK( angle == Approx(0) );
CHECK( !placement.get_point(x, y, angle, true) );
}
SECTION("line string zero length") {
mapnik::geometry::line_string<double> g;
g.emplace_back(1.0, 1.0);
g.emplace_back(1.0, 1.0);
using va_type = mapnik::geometry::line_string_vertex_adapter<double>;
va_type va(g);
using detector_type = mapnik::label_collision_detector4;
detector_type detector(mapnik::box2d<double>(0, 0, 100, 100));
using placement_type = mapnik::markers_point_placement<va_type, detector_type>;
mapnik::markers_placement_params params {
mapnik::box2d<double>(0, 0, 10, 10),
agg::trans_affine(),
0, NAN, 0, false, false, DIRECTION_AUTO, 1.0 };
placement_type placement(va, detector, params);
double x, y, angle;
CHECK( placement.get_point(x, y, angle, true) );
CHECK( x == Approx(1.0) );
CHECK( y == Approx(1.0) );
CHECK( angle == Approx(0) );
CHECK( !placement.get_point(x, y, angle, true) );
}
SECTION("point")
{
mapnik::geometry::point<double> g(2.0, 3.0);
using va_type = mapnik::geometry::point_vertex_adapter<double>;
va_type va(g);
using detector_type = mapnik::label_collision_detector4;
detector_type detector(mapnik::box2d<double>(0, 0, 100, 100));
using placement_type = mapnik::markers_point_placement<va_type, detector_type>;
mapnik::markers_placement_params params{mapnik::box2d<double>(0, 0, 10, 10),
agg::trans_affine(),
0,
NAN,
0,
false,
false,
DIRECTION_AUTO,
1.0};
placement_type placement(va, detector, params);
double x, y, angle;
CHECK(placement.get_point(x, y, angle, true));
CHECK(x == Approx(2.0));
CHECK(y == Approx(3.0));
CHECK(angle == Approx(0.0));
CHECK(!placement.get_point(x, y, angle, true));
}
SECTION("line string")
{
mapnik::geometry::line_string<double> g;
g.emplace_back(1.0, 1.0);
g.emplace_back(2.0, 2.0);
using va_type = mapnik::geometry::line_string_vertex_adapter<double>;
va_type va(g);
using detector_type = mapnik::label_collision_detector4;
detector_type detector(mapnik::box2d<double>(0, 0, 100, 100));
using placement_type = mapnik::markers_point_placement<va_type, detector_type>;
mapnik::markers_placement_params params{mapnik::box2d<double>(0, 0, 10, 10),
agg::trans_affine(),
0,
NAN,
0,
false,
false,
DIRECTION_AUTO,
1.0};
placement_type placement(va, detector, params);
double x, y, angle;
CHECK(placement.get_point(x, y, angle, true));
CHECK(x == Approx(1.5));
CHECK(y == Approx(1.5));
CHECK(angle == Approx(0));
CHECK(!placement.get_point(x, y, angle, true));
}
SECTION("line string zero length")
{
mapnik::geometry::line_string<double> g;
g.emplace_back(1.0, 1.0);
g.emplace_back(1.0, 1.0);
using va_type = mapnik::geometry::line_string_vertex_adapter<double>;
va_type va(g);
using detector_type = mapnik::label_collision_detector4;
detector_type detector(mapnik::box2d<double>(0, 0, 100, 100));
using placement_type = mapnik::markers_point_placement<va_type, detector_type>;
mapnik::markers_placement_params params{mapnik::box2d<double>(0, 0, 10, 10),
agg::trans_affine(),
0,
NAN,
0,
false,
false,
DIRECTION_AUTO,
1.0};
placement_type placement(va, detector, params);
double x, y, angle;
CHECK(placement.get_point(x, y, angle, true));
CHECK(x == Approx(1.0));
CHECK(y == Approx(1.0));
CHECK(angle == Approx(0));
CHECK(!placement.get_point(x, y, angle, true));
}
}

View file

@ -6,24 +6,23 @@
using namespace mapnik;
TEST_CASE("symbolizer") {
SECTION("enums") {
try {
marker_multi_policy_enum policy_in = MARKER_WHOLE_MULTI;
REQUIRE(policy_in == MARKER_WHOLE_MULTI);
markers_symbolizer sym;
put(sym, keys::markers_multipolicy, policy_in);
REQUIRE(sym.properties.count(keys::markers_multipolicy) == static_cast<unsigned long>(1));
marker_multi_policy_enum policy_out = get<mapnik::marker_multi_policy_enum>(sym, keys::markers_multipolicy);
REQUIRE(policy_out == MARKER_WHOLE_MULTI);
}
catch (std::exception const & ex)
TEST_CASE("symbolizer")
{
SECTION("enums")
{
std::clog << ex.what() << std::endl;
REQUIRE(false);
try
{
marker_multi_policy_enum policy_in = MARKER_WHOLE_MULTI;
REQUIRE(policy_in == MARKER_WHOLE_MULTI);
markers_symbolizer sym;
put(sym, keys::markers_multipolicy, policy_in);
REQUIRE(sym.properties.count(keys::markers_multipolicy) == static_cast<unsigned long>(1));
marker_multi_policy_enum policy_out = get<mapnik::marker_multi_policy_enum>(sym, keys::markers_multipolicy);
REQUIRE(policy_out == MARKER_WHOLE_MULTI);
} catch (std::exception const& ex)
{
std::clog << ex.what() << std::endl;
REQUIRE(false);
}
}
}
}

View file

@ -5,14 +5,16 @@
TEST_CASE("nested script runs")
{
mapnik::value_unicode_string text("Nested text runs(первый(second(третий)))"); //mixed scripts
mapnik::value_unicode_string text("Nested text runs(первый(second(третий)))"); // mixed scripts
ScriptRun runs(text.getBuffer(), text.length());
std::size_t count = 0;
std::size_t size = 0;
while (runs.next())
{
if (count & 1) CHECK(runs.getScriptCode() == USCRIPT_CYRILLIC);
else CHECK(runs.getScriptCode() == USCRIPT_LATIN);
if (count & 1)
CHECK(runs.getScriptCode() == USCRIPT_CYRILLIC);
else
CHECK(runs.getScriptCode() == USCRIPT_LATIN);
size += runs.getScriptEnd() - runs.getScriptStart();
++count;
}

View file

@ -9,11 +9,14 @@ namespace {
using mapnik::util::from_u8string;
void test_shaping( mapnik::font_set const& fontset, mapnik::face_manager& fm,
std::vector<std::pair<unsigned, unsigned>> const& expected, char const* str, bool debug = false)
void test_shaping(mapnik::font_set const& fontset,
mapnik::face_manager& fm,
std::vector<std::pair<unsigned, unsigned>> const& expected,
char const* str,
bool debug = false)
{
mapnik::transcoder tr("utf8");
std::map<unsigned,double> width_map;
std::map<unsigned, double> width_map;
mapnik::text_itemizer itemizer;
auto props = std::make_unique<mapnik::detail::evaluated_format_properties>();
props->fontset = fontset;
@ -25,20 +28,19 @@ void test_shaping( mapnik::font_set const& fontset, mapnik::face_manager& fm,
itemizer.add_text(ustr, props);
mapnik::text_line line(0, length);
mapnik::harfbuzz_shaper::shape_text(line, itemizer,
width_map,
fm,
scale_factor);
mapnik::harfbuzz_shaper::shape_text(line, itemizer, width_map, fm, scale_factor);
std::size_t index = 0;
for (auto const& g : line)
{
if (debug)
{
if (index++ > 0) std::cerr << ",";
std::cerr << "{" << g.glyph_index << ", " << g.char_index
//<< ", " << g.face->family_name() << ":" << g.face->style_name()
<< "}";
if (index++ > 0)
std::cerr << ",";
std::cerr << "{" << g.glyph_index << ", "
<< g.char_index
//<< ", " << g.face->family_name() << ":" << g.face->style_name()
<< "}";
}
else
{
@ -50,7 +52,7 @@ void test_shaping( mapnik::font_set const& fontset, mapnik::face_manager& fm,
}
}
}
}
} // namespace
TEST_CASE("shaping")
{
@ -69,36 +71,34 @@ TEST_CASE("shaping")
{
std::vector<std::pair<unsigned, unsigned>> expected =
{{977, 0}, {1094, 3}, {1038, 4}, {1168, 4}, {9, 7}, {3, 8}, {11, 9}, {68, 10}, {69, 11}, {70, 12}, {12, 13}};
{{977, 0}, {1094, 3}, {1038, 4}, {1168, 4}, {9, 7}, {3, 8}, {11, 9}, {68, 10}, {69, 11}, {70, 12}, {12, 13}};
test_shaping(fontset, fm, expected, from_u8string(u8"སྤུ་ཧྲེང (abc)").c_str());
}
{
std::vector<std::pair<unsigned, unsigned>> expected =
{{977, 0}, {1094, 3}, {1038, 4}, {1168, 4}, {9, 7}, {3, 8}, {11, 9}, {0, 10}, {0, 11}, {0, 12}, {12, 13}};
{{977, 0}, {1094, 3}, {1038, 4}, {1168, 4}, {9, 7}, {3, 8}, {11, 9}, {0, 10}, {0, 11}, {0, 12}, {12, 13}};
test_shaping(fontset, fm, expected, from_u8string(u8"སྤུ་ཧྲེང (普兰镇)").c_str());
}
{
std::vector<std::pair<unsigned, unsigned>> expected =
{{68, 0}, {69, 1}, {70, 2}, {3, 3}, {11, 4}, {0, 5}, {0, 6}, {0, 7}, {12, 8}};
{{68, 0}, {69, 1}, {70, 2}, {3, 3}, {11, 4}, {0, 5}, {0, 6}, {0, 7}, {12, 8}};
test_shaping(fontset, fm, expected, from_u8string(u8"abc (普兰镇)").c_str());
}
{
std::vector<std::pair<unsigned, unsigned>> expected =
{{68, 0}, {69, 1}, {70, 2}, {3, 3}, {11, 4}, {68, 5}, {69, 6}, {70, 7}, {12, 8}};
{{68, 0}, {69, 1}, {70, 2}, {3, 3}, {11, 4}, {68, 5}, {69, 6}, {70, 7}, {12, 8}};
test_shaping(fontset, fm, expected, "abc (abc)");
}
{
// "ⵃⴰⵢ ⵚⵉⵏⴰⵄⵉ الحي الصناعي"
std::vector<std::pair<unsigned, unsigned>> expected =
{{0, 0}, {0, 1}, {0, 2}, {3, 3}, {0, 4}, {0, 5}, {0, 6}, {0, 7},
{0, 8}, {0, 9}, {3, 10}, {509, 22}, {481, 21}, {438, 20}, {503, 19},
{470, 18}, {496, 17}, {43, 16}, {3, 15}, {509, 14}, {454, 13}, {496, 12}, {43, 11}};
std::vector<std::pair<unsigned, unsigned>> expected = {
{0, 0}, {0, 1}, {0, 2}, {3, 3}, {0, 4}, {0, 5}, {0, 6}, {0, 7},
{0, 8}, {0, 9}, {3, 10}, {509, 22}, {481, 21}, {438, 20}, {503, 19}, {470, 18},
{496, 17}, {43, 16}, {3, 15}, {509, 14}, {454, 13}, {496, 12}, {43, 11}};
test_shaping(fontset, fm, expected, from_u8string(u8"ⵃⴰⵢ ⵚⵉⵏⴰⵄⵉ الحي الصناعي").c_str());
}
}

View file

@ -11,13 +11,13 @@ TEST_CASE("text_placements_list")
list.defaults.set_format_tree(std::make_shared<mapnik::formatting::text_node>("\"Default text\""));
{
mapnik::text_symbolizer_properties & properties = list.add();
mapnik::text_symbolizer_properties& properties = list.add();
properties.format_defaults.text_size = 10.0;
properties.set_format_tree(std::make_shared<mapnik::formatting::text_node>("\"Alternative text 1\""));
}
{
mapnik::text_symbolizer_properties & properties = list.add();
mapnik::text_symbolizer_properties& properties = list.add();
properties.format_defaults.text_size = 8.0;
properties.set_format_tree(std::make_shared<mapnik::formatting::text_node>("\"Alternative text 2\""));
}

View file

@ -3,17 +3,17 @@
#include <mapnik/util/char_array_buffer.hpp>
#include <istream>
TEST_CASE("char_array_buffer") {
TEST_CASE("char_array_buffer")
{
SECTION("std::istream seekg, tellg")
{
const std::size_t buffer_size = 66;
char buffer[buffer_size];
mapnik::util::char_array_buffer array_buff(buffer, buffer_size);
std::istream stream(&array_buff);
SECTION("std::istream seekg, tellg") {
const std::size_t buffer_size = 66;
char buffer[buffer_size];
mapnik::util::char_array_buffer array_buff(buffer, buffer_size);
std::istream stream(&array_buff);
CHECK(stream.seekg(0).tellg() == 0);
CHECK(stream.seekg(buffer_size).tellg() == buffer_size);
CHECK(stream.seekg(70).tellg() == buffer_size);
}
CHECK(stream.seekg(0).tellg() == 0);
CHECK(stream.seekg(buffer_size).tellg() == buffer_size);
CHECK(stream.seekg(70).tellg() == buffer_size);
}
}

View file

@ -22,8 +22,8 @@ MAPNIK_DISABLE_WARNING_POP
// agg
#include "agg_conv_clip_polyline.h"
template <typename T>
std::string dump_path(T & path)
template<typename T>
std::string dump_path(T& path)
{
unsigned cmd = 1;
double x = 0;
@ -33,25 +33,25 @@ std::string dump_path(T & path)
path.rewind(0);
while ((cmd = path.vertex(&x, &y)) != mapnik::SEG_END)
{
if (idx > 0) s << ",";
if (idx > 0)
s << ",";
s << x << " " << y << " " << cmd;
idx++;
}
return s.str();
}
std::string clip_line(mapnik::box2d<double> const& bbox,
mapnik::path_type const& path)
std::string clip_line(mapnik::box2d<double> const& bbox, mapnik::path_type const& path)
{
using line_clipper = agg::conv_clip_polyline<mapnik::vertex_adapter>;
mapnik::vertex_adapter va(path);
line_clipper clipped(va);
clipped.clip_box(bbox.minx(),bbox.miny(),bbox.maxx(),bbox.maxy());
clipped.clip_box(bbox.minx(), bbox.miny(), bbox.maxx(), bbox.maxy());
return dump_path(clipped);
}
void parse_geom(mapnik::path_type & path,
std::string const& geom_string) {
void parse_geom(mapnik::path_type& path, std::string const& geom_string)
{
std::vector<std::string> vertices;
boost::split(vertices, geom_string, boost::is_any_of(","));
for (std::string const& vert : vertices)
@ -65,11 +65,10 @@ void parse_geom(mapnik::path_type & path,
double x = 0;
double y = 0;
int c = 0;
if (mapnik::util::string2double(commands[0],x)
&& mapnik::util::string2double(commands[1],y)
&& mapnik::util::string2int(commands[2],c))
if (mapnik::util::string2double(commands[0], x) && mapnik::util::string2double(commands[1], y) &&
mapnik::util::string2int(commands[2], c))
{
path.push_vertex(x,y,(mapnik::CommandType)c);
path.push_vertex(x, y, (mapnik::CommandType)c);
}
else
{
@ -78,42 +77,41 @@ void parse_geom(mapnik::path_type & path,
}
}
TEST_CASE("clipping") {
SECTION("lines") {
try {
std::string filename("test/unit/data/cases.txt");
std::ifstream stream(filename.c_str(),std::ios_base::in | std::ios_base::binary);
if (!stream.is_open())
throw std::runtime_error("could not open: '" + filename + "'");
std::string csv_line;
while(std::getline(stream,csv_line,'\n'))
{
if (csv_line.empty() || csv_line[0] == '#') continue;
std::vector<std::string> parts;
boost::split(parts, csv_line, boost::is_any_of(";"));
// first part is clipping box
mapnik::box2d<double> bbox;
if (!bbox.from_string(parts[0])) {
throw std::runtime_error(std::string("could not parse bbox '") + parts[0] + "'");
}
// second part is input geometry
mapnik::path_type path;
parse_geom(path, parts[1]);
//std::clog << dump_path(path) << "\n";
// third part is expected, clipped geometry
REQUIRE(clip_line(bbox, path) == mapnik::util::trim_copy(parts[2]));
}
stream.close();
}
catch (std::exception const& ex)
TEST_CASE("clipping")
{
SECTION("lines")
{
std::cerr << ex.what() << "\n";
try
{
std::string filename("test/unit/data/cases.txt");
std::ifstream stream(filename.c_str(), std::ios_base::in | std::ios_base::binary);
if (!stream.is_open())
throw std::runtime_error("could not open: '" + filename + "'");
std::string csv_line;
while (std::getline(stream, csv_line, '\n'))
{
if (csv_line.empty() || csv_line[0] == '#')
continue;
std::vector<std::string> parts;
boost::split(parts, csv_line, boost::is_any_of(";"));
// first part is clipping box
mapnik::box2d<double> bbox;
if (!bbox.from_string(parts[0]))
{
throw std::runtime_error(std::string("could not parse bbox '") + parts[0] + "'");
}
// second part is input geometry
mapnik::path_type path;
parse_geom(path, parts[1]);
// std::clog << dump_path(path) << "\n";
// third part is expected, clipped geometry
REQUIRE(clip_line(bbox, path) == mapnik::util::trim_copy(parts[2]));
}
stream.close();
} catch (std::exception const& ex)
{
std::cerr << ex.what() << "\n";
}
}
}
}

View file

@ -9,120 +9,119 @@
namespace offset_test {
TEST_CASE("extend converter") {
SECTION("empty") {
try
TEST_CASE("extend converter")
{
SECTION("empty")
{
fake_path path = {};
mapnik::extend_converter<fake_path> c(path, 1000);
double x, y;
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_END);
try
{
fake_path path = {};
mapnik::extend_converter<fake_path> c(path, 1000);
double x, y;
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_END);
} catch (std::exception const& ex)
{
std::cerr << ex.what() << "\n";
REQUIRE(false);
}
}
catch (std::exception const& ex)
SECTION("one point")
{
std::cerr << ex.what() << "\n";
REQUIRE(false);
try
{
fake_path path = {0, 0};
mapnik::extend_converter<fake_path> c(path, 1000);
double x, y;
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_MOVETO);
REQUIRE(x == 0);
REQUIRE(y == 0);
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_END);
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_END);
} catch (std::exception const& ex)
{
std::cerr << ex.what() << "\n";
REQUIRE(false);
}
}
SECTION("two points")
{
try
{
fake_path path = {0, 0, 1, 0};
mapnik::extend_converter<fake_path> c(path, 1000);
double x, y;
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_MOVETO);
REQUIRE(x == -1000);
REQUIRE(y == 0);
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_LINETO);
REQUIRE(x == 1001);
REQUIRE(y == 0);
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_END);
} catch (std::exception const& ex)
{
std::cerr << ex.what() << "\n";
REQUIRE(false);
}
}
SECTION("three points")
{
try
{
fake_path path = {0, 0, 1, 0, 2, 0};
mapnik::extend_converter<fake_path> c(path, 1000);
double x, y;
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_MOVETO);
REQUIRE(x == -1000);
REQUIRE(y == 0);
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_LINETO);
REQUIRE(x == 1);
REQUIRE(y == 0);
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_LINETO);
REQUIRE(x == 1002);
REQUIRE(y == 0);
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_END);
} catch (std::exception const& ex)
{
std::cerr << ex.what() << "\n";
REQUIRE(false);
}
}
SECTION("more points")
{
try
{
fake_path path = {0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0};
mapnik::extend_converter<fake_path> c(path, 1000);
double x, y;
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_MOVETO);
REQUIRE(x == -1000);
REQUIRE(y == 0);
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_LINETO);
REQUIRE(x == 1);
REQUIRE(y == 0);
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_LINETO);
REQUIRE(x == 2);
REQUIRE(y == 0);
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_LINETO);
REQUIRE(x == 3);
REQUIRE(y == 0);
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_LINETO);
REQUIRE(x == 4);
REQUIRE(y == 0);
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_LINETO);
REQUIRE(x == 1005);
REQUIRE(y == 0);
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_END);
} catch (std::exception const& ex)
{
std::cerr << ex.what() << "\n";
REQUIRE(false);
}
}
}
SECTION("one point") {
try
{
fake_path path = { 0, 0 };
mapnik::extend_converter<fake_path> c(path, 1000);
double x, y;
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_MOVETO);
REQUIRE(x == 0);
REQUIRE(y == 0);
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_END);
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_END);
}
catch (std::exception const& ex)
{
std::cerr << ex.what() << "\n";
REQUIRE(false);
}
}
SECTION("two points") {
try
{
fake_path path = { 0, 0 , 1, 0};
mapnik::extend_converter<fake_path> c(path, 1000);
double x, y;
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_MOVETO);
REQUIRE(x == -1000);
REQUIRE(y == 0);
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_LINETO);
REQUIRE(x == 1001);
REQUIRE(y == 0);
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_END);
}
catch (std::exception const& ex)
{
std::cerr << ex.what() << "\n";
REQUIRE(false);
}
}
SECTION("three points") {
try
{
fake_path path = { 0, 0, 1, 0, 2, 0 };
mapnik::extend_converter<fake_path> c(path, 1000);
double x, y;
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_MOVETO);
REQUIRE(x == -1000);
REQUIRE(y == 0);
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_LINETO);
REQUIRE(x == 1);
REQUIRE(y == 0);
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_LINETO);
REQUIRE(x == 1002);
REQUIRE(y == 0);
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_END);
}
catch (std::exception const& ex)
{
std::cerr << ex.what() << "\n";
REQUIRE(false);
}
}
SECTION("more points") {
try
{
fake_path path = { 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0 };
mapnik::extend_converter<fake_path> c(path, 1000);
double x, y;
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_MOVETO);
REQUIRE(x == -1000);
REQUIRE(y == 0);
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_LINETO);
REQUIRE(x == 1);
REQUIRE(y == 0);
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_LINETO);
REQUIRE(x == 2);
REQUIRE(y == 0);
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_LINETO);
REQUIRE(x == 3);
REQUIRE(y == 0);
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_LINETO);
REQUIRE(x == 4);
REQUIRE(y == 0);
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_LINETO);
REQUIRE(x == 1005);
REQUIRE(y == 0);
REQUIRE(c.vertex(&x, &y) == mapnik::SEG_END);
}
catch (std::exception const& ex)
{
std::cerr << ex.what() << "\n";
REQUIRE(false);
}
}
}
}
} // namespace offset_test

View file

@ -27,10 +27,9 @@
#include <vector>
#include <tuple>
namespace detail
{
namespace detail {
template <typename T>
template<typename T>
struct fake_path
{
using coord_type = std::tuple<T, T, unsigned>;
@ -40,22 +39,20 @@ struct fake_path
fake_path(std::initializer_list<T> l)
: fake_path(l.begin(), l.size())
{
}
{}
fake_path(std::vector<T> const &v, bool make_invalid = false)
fake_path(std::vector<T> const& v, bool make_invalid = false)
: fake_path(v.begin(), v.size(), make_invalid)
{
}
{}
template <typename Itr>
template<typename Itr>
fake_path(Itr itr, size_t sz, bool make_invalid = false)
{
size_t num_coords = sz >> 1;
vertices_.reserve(num_coords + (make_invalid ? 1 : 0));
if (make_invalid)
{
vertices_.push_back(std::make_tuple(0,0,mapnik::SEG_END));
vertices_.push_back(std::make_tuple(0, 0, mapnik::SEG_END));
}
for (size_t i = 0; i < num_coords; ++i)
@ -68,7 +65,7 @@ struct fake_path
itr_ = vertices_.begin();
}
unsigned vertex(T *x, T *y)
unsigned vertex(T* x, T* y)
{
if (itr_ == vertices_.end())
{
@ -81,13 +78,9 @@ struct fake_path
return cmd;
}
void rewind(unsigned)
{
itr_ = vertices_.begin();
}
void rewind(unsigned) { itr_ = vertices_.begin(); }
};
}
} // namespace detail
using fake_path = detail::fake_path<double>;

View file

@ -9,64 +9,76 @@
// stl
#include <iostream>
double dist(mapnik::pixel_position const &a,
mapnik::pixel_position const &b)
double dist(mapnik::pixel_position const& a, mapnik::pixel_position const& b)
{
mapnik::pixel_position d = a - b;
return std::sqrt(d.x*d.x + d.y*d.y);
return std::sqrt(d.x * d.x + d.y * d.y);
}
void test_simple_segment(double const &offset)
void test_simple_segment(double const& offset)
{
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);
vc.reset(); vc.next_subpath();
off_vc.reset(); off_vc.next_subpath();
vc.reset();
vc.next_subpath();
off_vc.reset();
off_vc.next_subpath();
while (vc.move(dx)) {
while (vc.move(dx))
{
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);
}
}
void test_straight_line(double const &offset) {
void test_straight_line(double const& offset)
{
const double dx = 0.01;
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};
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};
mapnik::vertex_cache vc(path), off_vc(off_path);
vc.reset(); vc.next_subpath();
off_vc.reset(); off_vc.next_subpath();
vc.reset();
vc.next_subpath();
off_vc.reset();
off_vc.next_subpath();
while (vc.move(dx)) {
while (vc.move(dx))
{
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);
}
}
void test_offset_curve(double const &offset) {
void test_offset_curve(double const& offset)
{
const double dx = 0.01;
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) {
for (size_t i = 0; i <= max_i; ++i)
{
double x = mapnik::util::pi * double(i) / max_i;
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));
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::vertex_cache vc(path), off_vc(off_path);
vc.reset(); vc.next_subpath();
off_vc.reset(); off_vc.next_subpath();
vc.reset();
vc.next_subpath();
off_vc.reset();
off_vc.next_subpath();
while (vc.move(dx)) {
while (vc.move(dx))
{
double mpos = vc.linear_position();
double moff_pos = off_vc.position_closest_to(vc.current_position());
{
@ -80,31 +92,41 @@ void test_offset_curve(double const &offset) {
}
}
void test_s_shaped_curve(double const &offset) {
void test_s_shaped_curve(double const& offset)
{
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;
for (size_t i = 0; i <= max_i; ++i) {
for (size_t i = 0; i <= max_i; ++i)
{
double x = mapnik::util::pi * double(i) / max_i;
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));
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) {
for (size_t i = 0; i <= max_i; ++i)
{
double x = mapnik::util::pi * double(i) / max_i;
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));
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::vertex_cache vc(path), off_vc(off_path);
vc.reset(); vc.next_subpath();
off_vc.reset(); off_vc.next_subpath();
vc.reset();
vc.next_subpath();
off_vc.reset();
off_vc.next_subpath();
while (vc.move(dx)) {
while (vc.move(dx))
{
double moff_pos = off_vc.position_closest_to(vc.current_position());
{
mapnik::vertex_cache::scoped_state s(off_vc);
@ -114,34 +136,35 @@ void test_s_shaped_curve(double const &offset) {
}
}
TEST_CASE("offsets") {
TEST_CASE("offsets")
{
SECTION("line")
{
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);
SECTION("line") {
try {
// test straight line consisting of more than one segment.
test_straight_line(offset);
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 an offset outer curve
test_offset_curve(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);
// 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);
}
}
catch (std::exception const& ex)
{
std::cerr << ex.what() << "\n";
REQUIRE(false);
}
}
}

View file

@ -17,10 +17,10 @@ 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);
return std::sqrt(dx * dx + dy * dy);
}
void test_null_segment(double const &offset)
void test_null_segment(double const& offset)
{
fake_path path = {};
mapnik::offset_converter<fake_path> off_path_new(path);
@ -32,7 +32,7 @@ void test_null_segment(double const &offset)
REQUIRE(off_path_new.vertex(&x0, &y0) == mapnik::SEG_END);
}
void test_invalid_segment(double const &offset)
void test_invalid_segment(double const& offset)
{
std::vector<double> v_path = {1, 1, 1, 2};
fake_path path(v_path, true);
@ -45,8 +45,7 @@ void test_invalid_segment(double const &offset)
REQUIRE(off_path_new.vertex(&x0, &y0) == mapnik::SEG_END);
}
void test_simple_segment(double const &offset)
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);
@ -54,12 +53,13 @@ void test_simple_segment(double const &offset)
double x0, y0, x1, y1;
unsigned cmd0 = off_path_new.vertex(&x0, &y0);
unsigned cmd1 = off_path.vertex(&x1,&y1);
unsigned cmd1 = off_path.vertex(&x1, &y1);
double d = dist(x0, y0, x1, y1);
while (true) {
while (true)
{
if (d > (std::abs(offset) + DELTA_BUFF))
{
cmd0 = off_path_new.vertex(&x0,&y0);
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));
@ -67,41 +67,43 @@ void test_simple_segment(double const &offset)
else
{
REQUIRE(d <= (std::abs(offset) + DELTA_BUFF));
}
cmd1 = off_path.vertex(&x1,&y1);
if (cmd1 == mapnik::SEG_END) break;
cmd1 = off_path.vertex(&x1, &y1);
if (cmd1 == mapnik::SEG_END)
break;
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);
cmd0 = off_path_new.vertex(&x0, &y0);
if (cmd0 == mapnik::SEG_END)
{
done = true;
break;
}
}
if (done) 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};
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);
off_path_new.set_offset(offset);
double x0, y0, x1, y1;
unsigned cmd0 = off_path_new.vertex(&x0, &y0);
unsigned cmd1 = off_path.vertex(&x1,&y1);
unsigned cmd1 = off_path.vertex(&x1, &y1);
double d = dist(x0, y0, x1, y1);
while (true) {
while (true)
{
if (d > (std::abs(offset) + DELTA_BUFF))
{
cmd0 = off_path_new.vertex(&x0,&y0);
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));
@ -109,35 +111,39 @@ void test_straight_line(double const &offset) {
else
{
REQUIRE(d <= (std::abs(offset) + DELTA_BUFF));
}
cmd1 = off_path.vertex(&x1,&y1);
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);
cmd0 = off_path_new.vertex(&x0, &y0);
if (cmd0 == mapnik::SEG_END)
{
done = true;
break;
}
}
if (done) break;
if (done)
break;
}
}
void test_offset_curve(double const &offset) {
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) {
for (size_t i = 0; i <= max_i; ++i)
{
double x = mapnik::util::pi * double(i) / max_i;
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));
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);
@ -146,12 +152,13 @@ void test_offset_curve(double const &offset) {
double x0, y0, x1, y1;
unsigned cmd0 = off_path_new.vertex(&x0, &y0);
unsigned cmd1 = off_path.vertex(&x1,&y1);
unsigned cmd1 = off_path.vertex(&x1, &y1);
double d = dist(x0, y0, x1, y1);
while (true) {
while (true)
{
if (d > (std::abs(offset) + DELTA_BUFF))
{
cmd0 = off_path_new.vertex(&x0,&y0);
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));
@ -159,41 +166,48 @@ void test_offset_curve(double const &offset) {
else
{
REQUIRE(d <= (std::abs(offset) + DELTA_BUFF));
}
cmd1 = off_path.vertex(&x1,&y1);
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);
cmd0 = off_path_new.vertex(&x0, &y0);
if (cmd0 == mapnik::SEG_END)
{
done = true;
break;
}
}
if (done) break;
if (done)
break;
}
}
void test_s_shaped_curve(double const &offset) {
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) {
for (size_t i = 0; i <= max_i; ++i)
{
double x = mapnik::util::pi * double(i) / max_i;
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));
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) {
for (size_t i = 0; i <= max_i; ++i)
{
double x = mapnik::util::pi * double(i) / max_i;
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));
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);
@ -202,12 +216,13 @@ void test_s_shaped_curve(double const &offset) {
double x0, y0, x1, y1;
unsigned cmd0 = off_path_new.vertex(&x0, &y0);
unsigned cmd1 = off_path.vertex(&x1,&y1);
unsigned cmd1 = off_path.vertex(&x1, &y1);
double d = dist(x0, y0, x1, y1);
while (true) {
while (true)
{
if (d > (std::abs(offset) + DELTA_BUFF))
{
cmd0 = off_path_new.vertex(&x0,&y0);
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));
@ -215,171 +230,175 @@ void test_s_shaped_curve(double const &offset) {
else
{
REQUIRE(d <= (std::abs(offset) + DELTA_BUFF));
}
cmd1 = off_path.vertex(&x1,&y1);
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);
cmd0 = off_path_new.vertex(&x0, &y0);
if (cmd0 == mapnik::SEG_END)
{
done = true;
break;
}
}
if (done) break;
if (done)
break;
}
}
} // END NS
} // namespace offset_test
TEST_CASE("offset converter") {
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)
TEST_CASE("offset converter")
{
SECTION("null segment")
{
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);
}
}
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);
}
}
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)
try
{
case mapnik::SEG_MOVETO:
move_to_count++;
break;
case mapnik::SEG_CLOSE:
close_count++;
break;
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);
}
}
CHECK(move_to_count == 2);
CHECK(close_count == 2);
}
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);
}
}
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);
}
}
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);
}
}

View file

@ -41,37 +41,44 @@ void simplify(std::string const& wkt_in, double tolerance, std::string const& me
#endif
}
TEST_CASE("converters") {
TEST_CASE("converters")
{
SECTION("simplify")
{
simplify(std::string("LineString(0 0,2 2,3 5,4 1,5 0,6 7,7 0)"),
4,
"douglas-peucker",
std::string("LineString(0 0,6 7,7 0)"));
SECTION("simplify") {
simplify(std::string("LineString(0 0,2 2,3 5,4 1,5 0,6 7,7 0)"),
2,
"douglas-peucker",
std::string("LineString(0 0,3 5,5 0,6 7,7 0)"));
simplify( std::string("LineString(0 0,2 2,3 5,4 1,5 0,6 7,7 0)"),
4, "douglas-peucker",
std::string("LineString(0 0,6 7,7 0)"));
simplify(
std::string("LineString(10 0,9 -4,7 -7,4 -9,0 -10,-4 -9,-7 -7,-9 -4,-10 0,-9 4,-7 7,-4 9,0 10,4 9,7 7,9 4)"),
4,
"douglas-peucker",
std::string("LineString(10 0,0 -10,-10 0,0 10,9 4)"));
simplify( std::string("LineString(0 0,2 2,3 5,4 1,5 0,6 7,7 0)"),
2, "douglas-peucker",
std::string("LineString(0 0,3 5,5 0,6 7,7 0)"));
simplify(std::string("LineString(0 0,1 1,2 2,0 10,0 0)"),
10,
"douglas-peucker",
std::string("LineString(0 0,0 0)"));
simplify( std::string("LineString(10 0,9 -4,7 -7,4 -9,0 -10,-4 -9,-7 -7,-9 -4,-10 0,-9 4,-7 7,-4 9,0 10,4 9,7 7,9 4)"),
4, "douglas-peucker",
std::string("LineString(10 0,0 -10,-10 0,0 10,9 4)"));
simplify(std::string("LineString(0 0,1 1,2 2,0 10,0 0)"),
8,
"douglas-peucker",
std::string("LineString(0 0,0 10,0 0)"));
simplify( std::string("LineString(0 0,1 1,2 2,0 10,0 0)"),
10, "douglas-peucker",
std::string("LineString(0 0,0 0)"));
simplify( std::string("LineString(0 0,1 1,2 2,0 10,0 0)"),
8, "douglas-peucker",
std::string("LineString(0 0,0 10,0 0)"));
simplify( std::string("LineString(0 0,1 1,2 2,0 10,0 0)"),
1, "douglas-peucker",
std::string("LineString(0 0,2 2,0 10,0 0)"));
simplify( std::string("LineString(0 0, 1 -1, 2 2, 0 -10, 0 0, -5 7, 4 6)"),
3, "douglas-peucker",
std::string("LineString(0 0,0 -10,-5 7,4 6)"));
simplify(std::string("LineString(0 0,1 1,2 2,0 10,0 0)"),
1,
"douglas-peucker",
std::string("LineString(0 0,2 2,0 10,0 0)"));
}
simplify(std::string("LineString(0 0, 1 -1, 2 2, 0 -10, 0 0, -5 7, 4 6)"),
3,
"douglas-peucker",
std::string("LineString(0 0,0 -10,-5 7,4 6)"));
}
}

View file

@ -8,113 +8,114 @@
#include <mapnik/proj_transform.hpp>
#include <mapnik/projection.hpp>
TEST_CASE("transform_path_adapter") {
TEST_CASE("transform_path_adapter")
{
#ifdef MAPNIK_USE_PROJ
SECTION("polygon closing - epsg 2330") {
mapnik::geometry::polygon<double> g;
g.emplace_back();
auto & exterior = g.back();
SECTION("polygon closing - epsg 2330")
{
mapnik::geometry::polygon<double> g;
g.emplace_back();
auto& exterior = g.back();
exterior.emplace_back(88.1844308217992, 69.3553916041731);
exterior.emplace_back(88.1846166524913, 69.3552821191223);
exterior.emplace_back(88.1845090893871, 69.3553454342903);
exterior.emplace_back(88.1844308217992, 69.3553916041731);
exterior.emplace_back(88.1844308217992, 69.3553916041731);
exterior.emplace_back(88.1846166524913, 69.3552821191223);
exterior.emplace_back(88.1845090893871, 69.3553454342903);
exterior.emplace_back(88.1844308217992, 69.3553916041731);
using va_type = mapnik::geometry::polygon_vertex_adapter<double>;
using path_type = mapnik::transform_path_adapter<mapnik::view_transform, va_type>;
using va_type = mapnik::geometry::polygon_vertex_adapter<double>;
using path_type = mapnik::transform_path_adapter<mapnik::view_transform, va_type>;
va_type va(g);
mapnik::box2d<double> extent(16310607, 7704513, 16310621, 7704527);
mapnik::view_transform tr(512, 512, extent);
mapnik::projection proj1("epsg:2330");
mapnik::projection proj2("epsg:4326");
mapnik::proj_transform prj_trans(proj1, proj2);
path_type path(tr, va, prj_trans);
va_type va(g);
mapnik::box2d<double> extent(16310607, 7704513, 16310621, 7704527);
mapnik::view_transform tr(512, 512, extent);
mapnik::projection proj1("epsg:2330");
mapnik::projection proj2("epsg:4326");
mapnik::proj_transform prj_trans(proj1, proj2);
path_type path(tr, va, prj_trans);
double x,y;
unsigned cmd;
double x, y;
unsigned cmd;
cmd = path.vertex(&x, &y);
CHECK( cmd == mapnik::SEG_MOVETO );
CHECK( x == Approx(110.4328050613) );
CHECK( y == Approx(20.2204537392) );
cmd = path.vertex(&x, &y);
CHECK(cmd == mapnik::SEG_MOVETO);
CHECK(x == Approx(110.4328050613));
CHECK(y == Approx(20.2204537392));
cmd = path.vertex(&x, &y);
CHECK( cmd == mapnik::SEG_LINETO );
CHECK( x == Approx(342.1220560074) );
CHECK( y == Approx(486.732225963) );
cmd = path.vertex(&x, &y);
CHECK(cmd == mapnik::SEG_LINETO);
CHECK(x == Approx(342.1220560074));
CHECK(y == Approx(486.732225963));
cmd = path.vertex(&x, &y);
CHECK( cmd == mapnik::SEG_LINETO );
CHECK( x == Approx(207.9962329183) );
CHECK( y == Approx(216.9376912798) );
cmd = path.vertex(&x, &y);
CHECK(cmd == mapnik::SEG_LINETO);
CHECK(x == Approx(207.9962329183));
CHECK(y == Approx(216.9376912798));
// close
cmd = path.vertex(&x, &y);
CHECK( cmd == mapnik::SEG_CLOSE );
CHECK( x == 0 );
CHECK( y == 0 );
// close
cmd = path.vertex(&x, &y);
CHECK(cmd == mapnik::SEG_CLOSE);
CHECK(x == 0);
CHECK(y == 0);
// end
cmd = path.vertex(&x, &y);
CHECK( cmd == mapnik::SEG_END );
CHECK( x == 0 );
CHECK( y == 0 );
}
SECTION("polygon closing - epsg 32633") {
mapnik::geometry::polygon<double> g;
g.emplace_back();
auto & exterior = g.back();
exterior.emplace_back(13, 13);
exterior.emplace_back(14, 13);
exterior.emplace_back(14, 14);
exterior.emplace_back(14, 14);
using va_type = mapnik::geometry::polygon_vertex_adapter<double>;
using path_type = mapnik::transform_path_adapter<mapnik::view_transform, va_type>;
va_type va(g);
mapnik::box2d<double> extent(166022, 0, 833978, 9329005);
mapnik::view_transform tr(512, 512, extent);
mapnik::projection proj1("epsg:32633");
mapnik::projection proj2("epsg:4326");
mapnik::proj_transform prj_trans(proj1, proj2);
path_type path(tr, va, prj_trans);
double x,y;
unsigned cmd;
cmd = path.vertex(&x, &y);
CHECK( cmd == mapnik::SEG_MOVETO );
CHECK( x == Approx(89.7250280748) );
CHECK( y == Approx(433.0795069885) );
cmd = path.vertex(&x, &y);
CHECK( cmd == mapnik::SEG_LINETO );
CHECK( x == Approx(172.873973465) );
CHECK( y == Approx(433.1145779929) );
cmd = path.vertex(&x, &y);
CHECK( cmd == mapnik::SEG_LINETO );
CHECK( x == Approx(173.2194366775) );
CHECK( y == Approx(427.0442504759) );
// close
cmd = path.vertex(&x, &y);
CHECK( cmd == mapnik::SEG_CLOSE );
CHECK( x == 0 );
CHECK( y == 0 );
// end
cmd = path.vertex(&x, &y);
CHECK( cmd == mapnik::SEG_END );
CHECK( x == 0 );
CHECK( y == 0 );
}
#endif //MAPNIK_USE_PROJ
// end
cmd = path.vertex(&x, &y);
CHECK(cmd == mapnik::SEG_END);
CHECK(x == 0);
CHECK(y == 0);
}
SECTION("polygon closing - epsg 32633")
{
mapnik::geometry::polygon<double> g;
g.emplace_back();
auto& exterior = g.back();
exterior.emplace_back(13, 13);
exterior.emplace_back(14, 13);
exterior.emplace_back(14, 14);
exterior.emplace_back(14, 14);
using va_type = mapnik::geometry::polygon_vertex_adapter<double>;
using path_type = mapnik::transform_path_adapter<mapnik::view_transform, va_type>;
va_type va(g);
mapnik::box2d<double> extent(166022, 0, 833978, 9329005);
mapnik::view_transform tr(512, 512, extent);
mapnik::projection proj1("epsg:32633");
mapnik::projection proj2("epsg:4326");
mapnik::proj_transform prj_trans(proj1, proj2);
path_type path(tr, va, prj_trans);
double x, y;
unsigned cmd;
cmd = path.vertex(&x, &y);
CHECK(cmd == mapnik::SEG_MOVETO);
CHECK(x == Approx(89.7250280748));
CHECK(y == Approx(433.0795069885));
cmd = path.vertex(&x, &y);
CHECK(cmd == mapnik::SEG_LINETO);
CHECK(x == Approx(172.873973465));
CHECK(y == Approx(433.1145779929));
cmd = path.vertex(&x, &y);
CHECK(cmd == mapnik::SEG_LINETO);
CHECK(x == Approx(173.2194366775));
CHECK(y == Approx(427.0442504759));
// close
cmd = path.vertex(&x, &y);
CHECK(cmd == mapnik::SEG_CLOSE);
CHECK(x == 0);
CHECK(y == 0);
// end
cmd = path.vertex(&x, &y);
CHECK(cmd == mapnik::SEG_END);
CHECK(x == 0);
CHECK(y == 0);
}
#endif // MAPNIK_USE_PROJ
}

View file

@ -3,335 +3,338 @@
#include <mapnik/vertex_adapters.hpp>
#include <mapnik/geometry/correct.hpp>
TEST_CASE("vertex_adapters") {
TEST_CASE("vertex_adapters")
{
SECTION("polygon")
{
mapnik::geometry::polygon<double> g;
g.emplace_back();
g.back().emplace_back(1, 1);
g.back().emplace_back(2, 2);
g.back().emplace_back(100, 100);
g.back().emplace_back(1, 1);
SECTION("polygon") {
mapnik::geometry::polygon<double> g;
g.emplace_back();
g.back().emplace_back(1,1);
g.back().emplace_back(2,2);
g.back().emplace_back(100,100);
g.back().emplace_back(1,1);
mapnik::geometry::polygon_vertex_adapter<double> va(g);
double x, y;
unsigned cmd;
mapnik::geometry::polygon_vertex_adapter<double> va(g);
double x,y;
unsigned cmd;
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_MOVETO);
REQUIRE(x == 1);
REQUIRE(y == 1);
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_MOVETO );
REQUIRE( x == 1 );
REQUIRE( y == 1 );
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_LINETO);
REQUIRE(x == 2);
REQUIRE(y == 2);
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_LINETO );
REQUIRE( x == 2 );
REQUIRE( y == 2 );
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_LINETO);
REQUIRE(x == 100);
REQUIRE(y == 100);
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_LINETO );
REQUIRE( x == 100 );
REQUIRE( y == 100 );
// close
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_CLOSE);
REQUIRE(x == 0);
REQUIRE(y == 0);
// close
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_CLOSE );
REQUIRE( x == 0 );
REQUIRE( y == 0 );
// end
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_END );
REQUIRE( x == 0 );
REQUIRE( y == 0 );
}
SECTION("polygon with hole") {
mapnik::geometry::polygon<double> g;
g.emplace_back();
g.back().emplace_back(0,0);
g.back().emplace_back(-10,0);
g.back().emplace_back(-10,10);
g.back().emplace_back(0,10);
g.back().emplace_back(0,0);
std::vector<mapnik::geometry::linear_ring<double> > interior_rings;
mapnik::geometry::linear_ring<double> hole;
hole.emplace_back(-7,7);
hole.emplace_back(-7,3);
hole.emplace_back(-3,3);
hole.emplace_back(-3,7);
hole.emplace_back(-7,7);
g.push_back(std::move(hole));
mapnik::geometry::linear_ring<double> hole_in_hole;
hole_in_hole.emplace_back(-6,4);
hole_in_hole.emplace_back(-6,6);
hole_in_hole.emplace_back(-4,6);
hole_in_hole.emplace_back(-4,4);
hole_in_hole.emplace_back(-6,4);
g.push_back(std::move(hole_in_hole));
mapnik::geometry::polygon_vertex_adapter<double> va(g);
double x,y;
unsigned cmd;
// exterior ring
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_MOVETO );
REQUIRE( x == 0 );
REQUIRE( y == 0 );
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_LINETO );
REQUIRE( x == -10 );
REQUIRE( y == 0 );
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_LINETO );
REQUIRE( x == -10 );
REQUIRE( y == 10 );
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_LINETO );
REQUIRE( x == 0 );
REQUIRE( y == 10 );
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_CLOSE );
REQUIRE( x == 0 );
REQUIRE( y == 0 );
// exterior ring via ring_vertex_adapter
mapnik::geometry::ring_vertex_adapter<double> va2(g.front());
cmd = va2.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_MOVETO );
REQUIRE( x == 0 );
REQUIRE( y == 0 );
cmd = va2.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_LINETO );
REQUIRE( x == -10 );
REQUIRE( y == 0 );
cmd = va2.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_LINETO );
REQUIRE( x == -10 );
REQUIRE( y == 10 );
cmd = va2.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_LINETO );
REQUIRE( x == 0 );
REQUIRE( y == 10 );
cmd = va2.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_CLOSE );
REQUIRE( x == 0 );
REQUIRE( y == 0 );
// since ring adapter is only for exterior, next should be END
cmd = va2.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_END );
REQUIRE( x == 0 );
REQUIRE( y == 0 );
// first hole for polygon_adapter
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_MOVETO );
REQUIRE( x == -7 );
REQUIRE( y == 7 );
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_LINETO );
REQUIRE( x == -7 );
REQUIRE( y == 3 );
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_LINETO );
REQUIRE( x == -3 );
REQUIRE( y == 3 );
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_LINETO );
REQUIRE( x == -3 );
REQUIRE( y == 7 );
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_CLOSE );
REQUIRE( x == 0 );
REQUIRE( y == 0 );
// second hole
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_MOVETO );
REQUIRE( x == -6 );
REQUIRE( y == 4 );
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_LINETO );
REQUIRE( x == -6 );
REQUIRE( y == 6 );
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_LINETO );
REQUIRE( x == -4 );
REQUIRE( y == 6 );
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_LINETO );
REQUIRE( x == -4 );
REQUIRE( y == 4 );
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_CLOSE );
REQUIRE( x == 0 );
REQUIRE( y == 0 );
mapnik::geometry::correct(g);
va.rewind(0);
// exterior ring: flipped winding order from correct
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_MOVETO );
REQUIRE( x == 0 );
REQUIRE( y == 0 );
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_LINETO );
REQUIRE( x == 0 );
REQUIRE( y == 10 );
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_LINETO );
REQUIRE( x == -10 );
REQUIRE( y == 10 );
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_LINETO );
REQUIRE( x == -10 );
REQUIRE( y == 0 );
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_CLOSE );
REQUIRE( x == 0 );
REQUIRE( y == 0 );
// first hole: flipped winding order from correct
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_MOVETO );
REQUIRE( x == -7 );
REQUIRE( y == 7 );
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_LINETO );
REQUIRE( x == -3 );
REQUIRE( y == 7 );
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_LINETO );
REQUIRE( x == -3 );
REQUIRE( y == 3 );
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_LINETO );
REQUIRE( x == -7 );
REQUIRE( y == 3 );
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_CLOSE );
REQUIRE( x == 0 );
REQUIRE( y == 0 );
// second hole: correct appears not to have changed winding order
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_MOVETO );
REQUIRE( x == -6 );
REQUIRE( y == 4 );
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_LINETO );
REQUIRE( x == -6 );
REQUIRE( y == 6 );
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_LINETO );
REQUIRE( x == -4 );
REQUIRE( y == 6 );
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_LINETO );
REQUIRE( x == -4 );
REQUIRE( y == 4 );
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_CLOSE );
REQUIRE( x == 0 );
REQUIRE( y == 0 );
}
SECTION("polygon with empty exterior ring") {
mapnik::geometry::polygon<double> g;
g.emplace_back();
mapnik::geometry::polygon_vertex_adapter<double> va(g);
double x = 0, y = 0;
unsigned cmd;
cmd = va.vertex(&x,&y);
CHECK( cmd == mapnik::SEG_END );
CHECK( x == Approx(0) );
CHECK( y == Approx(0) );
}
SECTION("polygon with empty interior ring") {
mapnik::geometry::polygon<double> g;
g.emplace_back();
g.back().emplace_back(-1, -1);
g.back().emplace_back( 1, -1);
g.back().emplace_back( 1, 1);
g.back().emplace_back(-1, 1);
g.back().emplace_back(-1, -1);
// Emplace empty interior ring
g.emplace_back();
mapnik::geometry::polygon_vertex_adapter<double> va(g);
double x,y;
unsigned cmd;
cmd = va.vertex(&x,&y);
CHECK( cmd == mapnik::SEG_MOVETO );
CHECK( x == Approx(-1) );
CHECK( y == Approx(-1) );
cmd = va.vertex(&x,&y);
CHECK( cmd == mapnik::SEG_LINETO );
CHECK( x == Approx(1) );
CHECK( y == Approx(-1) );
cmd = va.vertex(&x,&y);
CHECK( cmd == mapnik::SEG_LINETO );
CHECK( x == Approx(1) );
CHECK( y == Approx(1) );
cmd = va.vertex(&x,&y);
CHECK( cmd == mapnik::SEG_LINETO );
CHECK( x == Approx(-1) );
CHECK( y == Approx(1) );
cmd = va.vertex(&x,&y);
CHECK( cmd == mapnik::SEG_CLOSE );
CHECK( x == Approx(0) );
CHECK( y == Approx(0) );
cmd = va.vertex(&x,&y);
CHECK( cmd == mapnik::SEG_CLOSE );
CHECK( x == Approx(0) );
CHECK( y == Approx(0) );
cmd = va.vertex(&x,&y);
REQUIRE( cmd == mapnik::SEG_END );
REQUIRE( x == Approx(0) );
REQUIRE( y == Approx(0) );
}
// end
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_END);
REQUIRE(x == 0);
REQUIRE(y == 0);
}
SECTION("polygon with hole")
{
mapnik::geometry::polygon<double> g;
g.emplace_back();
g.back().emplace_back(0, 0);
g.back().emplace_back(-10, 0);
g.back().emplace_back(-10, 10);
g.back().emplace_back(0, 10);
g.back().emplace_back(0, 0);
std::vector<mapnik::geometry::linear_ring<double>> interior_rings;
mapnik::geometry::linear_ring<double> hole;
hole.emplace_back(-7, 7);
hole.emplace_back(-7, 3);
hole.emplace_back(-3, 3);
hole.emplace_back(-3, 7);
hole.emplace_back(-7, 7);
g.push_back(std::move(hole));
mapnik::geometry::linear_ring<double> hole_in_hole;
hole_in_hole.emplace_back(-6, 4);
hole_in_hole.emplace_back(-6, 6);
hole_in_hole.emplace_back(-4, 6);
hole_in_hole.emplace_back(-4, 4);
hole_in_hole.emplace_back(-6, 4);
g.push_back(std::move(hole_in_hole));
mapnik::geometry::polygon_vertex_adapter<double> va(g);
double x, y;
unsigned cmd;
// exterior ring
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_MOVETO);
REQUIRE(x == 0);
REQUIRE(y == 0);
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_LINETO);
REQUIRE(x == -10);
REQUIRE(y == 0);
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_LINETO);
REQUIRE(x == -10);
REQUIRE(y == 10);
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_LINETO);
REQUIRE(x == 0);
REQUIRE(y == 10);
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_CLOSE);
REQUIRE(x == 0);
REQUIRE(y == 0);
// exterior ring via ring_vertex_adapter
mapnik::geometry::ring_vertex_adapter<double> va2(g.front());
cmd = va2.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_MOVETO);
REQUIRE(x == 0);
REQUIRE(y == 0);
cmd = va2.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_LINETO);
REQUIRE(x == -10);
REQUIRE(y == 0);
cmd = va2.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_LINETO);
REQUIRE(x == -10);
REQUIRE(y == 10);
cmd = va2.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_LINETO);
REQUIRE(x == 0);
REQUIRE(y == 10);
cmd = va2.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_CLOSE);
REQUIRE(x == 0);
REQUIRE(y == 0);
// since ring adapter is only for exterior, next should be END
cmd = va2.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_END);
REQUIRE(x == 0);
REQUIRE(y == 0);
// first hole for polygon_adapter
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_MOVETO);
REQUIRE(x == -7);
REQUIRE(y == 7);
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_LINETO);
REQUIRE(x == -7);
REQUIRE(y == 3);
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_LINETO);
REQUIRE(x == -3);
REQUIRE(y == 3);
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_LINETO);
REQUIRE(x == -3);
REQUIRE(y == 7);
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_CLOSE);
REQUIRE(x == 0);
REQUIRE(y == 0);
// second hole
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_MOVETO);
REQUIRE(x == -6);
REQUIRE(y == 4);
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_LINETO);
REQUIRE(x == -6);
REQUIRE(y == 6);
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_LINETO);
REQUIRE(x == -4);
REQUIRE(y == 6);
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_LINETO);
REQUIRE(x == -4);
REQUIRE(y == 4);
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_CLOSE);
REQUIRE(x == 0);
REQUIRE(y == 0);
mapnik::geometry::correct(g);
va.rewind(0);
// exterior ring: flipped winding order from correct
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_MOVETO);
REQUIRE(x == 0);
REQUIRE(y == 0);
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_LINETO);
REQUIRE(x == 0);
REQUIRE(y == 10);
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_LINETO);
REQUIRE(x == -10);
REQUIRE(y == 10);
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_LINETO);
REQUIRE(x == -10);
REQUIRE(y == 0);
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_CLOSE);
REQUIRE(x == 0);
REQUIRE(y == 0);
// first hole: flipped winding order from correct
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_MOVETO);
REQUIRE(x == -7);
REQUIRE(y == 7);
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_LINETO);
REQUIRE(x == -3);
REQUIRE(y == 7);
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_LINETO);
REQUIRE(x == -3);
REQUIRE(y == 3);
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_LINETO);
REQUIRE(x == -7);
REQUIRE(y == 3);
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_CLOSE);
REQUIRE(x == 0);
REQUIRE(y == 0);
// second hole: correct appears not to have changed winding order
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_MOVETO);
REQUIRE(x == -6);
REQUIRE(y == 4);
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_LINETO);
REQUIRE(x == -6);
REQUIRE(y == 6);
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_LINETO);
REQUIRE(x == -4);
REQUIRE(y == 6);
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_LINETO);
REQUIRE(x == -4);
REQUIRE(y == 4);
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_CLOSE);
REQUIRE(x == 0);
REQUIRE(y == 0);
}
SECTION("polygon with empty exterior ring")
{
mapnik::geometry::polygon<double> g;
g.emplace_back();
mapnik::geometry::polygon_vertex_adapter<double> va(g);
double x = 0, y = 0;
unsigned cmd;
cmd = va.vertex(&x, &y);
CHECK(cmd == mapnik::SEG_END);
CHECK(x == Approx(0));
CHECK(y == Approx(0));
}
SECTION("polygon with empty interior ring")
{
mapnik::geometry::polygon<double> g;
g.emplace_back();
g.back().emplace_back(-1, -1);
g.back().emplace_back(1, -1);
g.back().emplace_back(1, 1);
g.back().emplace_back(-1, 1);
g.back().emplace_back(-1, -1);
// Emplace empty interior ring
g.emplace_back();
mapnik::geometry::polygon_vertex_adapter<double> va(g);
double x, y;
unsigned cmd;
cmd = va.vertex(&x, &y);
CHECK(cmd == mapnik::SEG_MOVETO);
CHECK(x == Approx(-1));
CHECK(y == Approx(-1));
cmd = va.vertex(&x, &y);
CHECK(cmd == mapnik::SEG_LINETO);
CHECK(x == Approx(1));
CHECK(y == Approx(-1));
cmd = va.vertex(&x, &y);
CHECK(cmd == mapnik::SEG_LINETO);
CHECK(x == Approx(1));
CHECK(y == Approx(1));
cmd = va.vertex(&x, &y);
CHECK(cmd == mapnik::SEG_LINETO);
CHECK(x == Approx(-1));
CHECK(y == Approx(1));
cmd = va.vertex(&x, &y);
CHECK(cmd == mapnik::SEG_CLOSE);
CHECK(x == Approx(0));
CHECK(y == Approx(0));
cmd = va.vertex(&x, &y);
CHECK(cmd == mapnik::SEG_CLOSE);
CHECK(x == Approx(0));
CHECK(y == Approx(0));
cmd = va.vertex(&x, &y);
REQUIRE(cmd == mapnik::SEG_END);
REQUIRE(x == Approx(0));
REQUIRE(y == Approx(0));
}
}

View file

@ -34,25 +34,29 @@
#include <mapnik/geometry/box2d.hpp>
namespace visual_tests
{
namespace visual_tests {
struct map_size
{
map_size(std::size_t _width, std::size_t _height) : width(_width), height(_height) { }
map_size() { }
map_size(std::size_t _width, std::size_t _height)
: width(_width)
, height(_height)
{}
map_size() {}
std::size_t width = 0;
std::size_t height = 0;
};
struct config
{
config() : status(true),
scales({ 1.0, 2.0 }),
sizes({ { 500, 100 } }),
tiles({ { 1, 1 } }),
bbox(),
ignored_renderers() { }
config()
: status(true)
, scales({1.0, 2.0})
, sizes({{500, 100}})
, tiles({{1, 1}})
, bbox()
, ignored_renderers()
{}
bool status;
std::vector<double> scales;
@ -62,13 +66,7 @@ struct config
std::set<std::string> ignored_renderers;
};
enum result_state : std::uint8_t
{
STATE_OK,
STATE_FAIL,
STATE_ERROR,
STATE_OVERWRITE
};
enum result_state : std::uint8_t { STATE_OK, STATE_FAIL, STATE_ERROR, STATE_OVERWRITE };
struct result
{
@ -87,6 +85,6 @@ struct result
using result_list = std::vector<result>;
}
} // namespace visual_tests
#endif

View file

@ -29,21 +29,16 @@ MAPNIK_DISABLE_WARNING_PUSH
#include <boost/fusion/include/adapt_struct.hpp>
MAPNIK_DISABLE_WARNING_POP
BOOST_FUSION_ADAPT_STRUCT (
visual_tests::map_size,
(std::size_t, width)
(std::size_t, height)
)
BOOST_FUSION_ADAPT_STRUCT(visual_tests::map_size, (std::size_t, width)(std::size_t, height))
namespace visual_tests {
namespace x3 = boost::spirit::x3;
using x3::ulong_;
auto const map_size_rule = x3::rule<class map_size_rule, map_size> {} = ulong_ >> ',' >> ulong_;
auto const map_sizes_grammar = x3::rule<class map_sizes_grammar_type, std::vector<map_size> > {} =
map_size_rule % ';' ;
auto const map_size_rule = x3::rule<class map_size_rule, map_size>{} = ulong_ >> ',' >> ulong_;
auto const map_sizes_grammar = x3::rule<class map_sizes_grammar_type, std::vector<map_size>>{} = map_size_rule % ';';
void parse_map_sizes(std::string const & str, std::vector<map_size> & sizes)
void parse_map_sizes(std::string const& str, std::vector<map_size>& sizes)
{
boost::spirit::x3::ascii::space_type space;
std::string::const_iterator iter = str.begin();
@ -54,4 +49,4 @@ void parse_map_sizes(std::string const & str, std::vector<map_size> & sizes)
}
}
}
} // namespace visual_tests

View file

@ -29,8 +29,8 @@
namespace visual_tests {
void parse_map_sizes(std::string const & str, std::vector<map_size> & sizes);
void parse_map_sizes(std::string const& str, std::vector<map_size>& sizes);
}
#endif //VISUAL_TESTS_PARSE_MAP_SIZES_HPP
#endif // VISUAL_TESTS_PARSE_MAP_SIZES_HPP

View file

@ -60,18 +60,17 @@
// boost
#include <boost/filesystem.hpp>
namespace visual_tests
{
namespace visual_tests {
template <typename ImageType>
template<typename ImageType>
struct raster_renderer_base
{
using image_type = ImageType;
static constexpr const char * ext = ".png";
static constexpr const char* ext = ".png";
static constexpr const bool support_tiles = true;
unsigned compare(image_type const & actual, boost::filesystem::path const& reference) const
unsigned compare(image_type const& actual, boost::filesystem::path const& reference) const
{
std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(reference.string(), "png"));
if (!reader.get())
@ -80,12 +79,12 @@ struct raster_renderer_base
}
mapnik::image_any ref_image_any = reader->read(0, 0, reader->width(), reader->height());
ImageType const & reference_image = mapnik::util::get<ImageType>(ref_image_any);
ImageType const& reference_image = mapnik::util::get<ImageType>(ref_image_any);
return mapnik::compare(actual, reference_image, 0, true);
}
void save(image_type const & image, boost::filesystem::path const& path) const
void save(image_type const& image, boost::filesystem::path const& path) const
{
mapnik::save_to_file(image, path.string(), "png32");
}
@ -97,7 +96,7 @@ struct vector_renderer_base
static constexpr const bool support_tiles = false;
unsigned compare(image_type const & actual, boost::filesystem::path const& reference) const
unsigned compare(image_type const& actual, boost::filesystem::path const& reference) const
{
std::ifstream stream(reference.string().c_str(), std::ios_base::in | std::ios_base::binary);
if (!stream)
@ -108,7 +107,7 @@ struct vector_renderer_base
return std::max(actual.size(), expected.size()) - std::min(actual.size(), expected.size());
}
void save(image_type const & image, boost::filesystem::path const& path) const
void save(image_type const& image, boost::filesystem::path const& path) const
{
std::ofstream file(path.string().c_str(), std::ios::out | std::ios::trunc | std::ios::binary);
if (!file)
@ -121,9 +120,9 @@ struct vector_renderer_base
struct agg_renderer : raster_renderer_base<mapnik::image_rgba8>
{
static constexpr const char * name = "agg";
static constexpr const char* name = "agg";
image_type render(mapnik::Map const & map, double scale_factor) const
image_type render(mapnik::Map const& map, double scale_factor) const
{
image_type image(map.width(), map.height());
mapnik::agg_renderer<image_type> ren(map, image, scale_factor);
@ -135,13 +134,13 @@ struct agg_renderer : raster_renderer_base<mapnik::image_rgba8>
#if defined(HAVE_CAIRO)
struct cairo_renderer : raster_renderer_base<mapnik::image_rgba8>
{
static constexpr const char * name = "cairo";
static constexpr const char* name = "cairo";
image_type render(mapnik::Map const & map, double scale_factor) const
image_type render(mapnik::Map const& map, double scale_factor) const
{
mapnik::cairo_surface_ptr image_surface(
cairo_image_surface_create(CAIRO_FORMAT_ARGB32, map.width(), map.height()),
mapnik::cairo_surface_closer());
cairo_image_surface_create(CAIRO_FORMAT_ARGB32, map.width(), map.height()),
mapnik::cairo_surface_closer());
mapnik::cairo_ptr image_context(mapnik::create_context(image_surface));
mapnik::cairo_renderer<mapnik::cairo_ptr> ren(map, image_context, scale_factor);
ren.apply();
@ -151,26 +150,23 @@ struct cairo_renderer : raster_renderer_base<mapnik::image_rgba8>
}
};
using surface_create_type = cairo_surface_t *(&)(cairo_write_func_t, void *, double, double);
using surface_create_type = cairo_surface_t* (&)(cairo_write_func_t, void*, double, double);
template <surface_create_type SurfaceCreateFunction>
template<surface_create_type SurfaceCreateFunction>
struct cairo_vector_renderer : vector_renderer_base
{
static cairo_status_t write(void *closure,
const unsigned char *data,
unsigned int length)
static cairo_status_t write(void* closure, const unsigned char* data, unsigned int length)
{
std::ostringstream & ss = *reinterpret_cast<std::ostringstream*>(closure);
ss.write(reinterpret_cast<char const *>(data), length);
std::ostringstream& ss = *reinterpret_cast<std::ostringstream*>(closure);
ss.write(reinterpret_cast<char const*>(data), length);
return ss ? CAIRO_STATUS_SUCCESS : CAIRO_STATUS_WRITE_ERROR;
}
image_type render(mapnik::Map const & map, double scale_factor) const
image_type render(mapnik::Map const& map, double scale_factor) const
{
std::ostringstream ss(std::stringstream::binary);
mapnik::cairo_surface_ptr image_surface(
SurfaceCreateFunction(write, &ss, map.width(), map.height()),
mapnik::cairo_surface_closer());
mapnik::cairo_surface_ptr image_surface(SurfaceCreateFunction(write, &ss, map.width(), map.height()),
mapnik::cairo_surface_closer());
mapnik::cairo_ptr image_context(mapnik::create_context(image_surface));
mapnik::cairo_renderer<mapnik::cairo_ptr> ren(map, image_context, scale_factor);
ren.apply();
@ -180,36 +176,33 @@ struct cairo_vector_renderer : vector_renderer_base
};
#ifdef CAIRO_HAS_SVG_SURFACE
inline cairo_surface_t *create_svg_1_2(cairo_write_func_t write_func,
void *closure,
double width,
double height)
inline cairo_surface_t* create_svg_1_2(cairo_write_func_t write_func, void* closure, double width, double height)
{
cairo_surface_t * surface = cairo_svg_surface_create_for_stream(write_func, closure, width, height);
cairo_surface_t* surface = cairo_svg_surface_create_for_stream(write_func, closure, width, height);
cairo_svg_surface_restrict_to_version(surface, CAIRO_SVG_VERSION_1_2);
return surface;
}
struct cairo_svg_renderer : cairo_vector_renderer<create_svg_1_2>
{
static constexpr const char * name = "cairo-svg";
static constexpr const char * ext = ".svg";
static constexpr const char* name = "cairo-svg";
static constexpr const char* ext = ".svg";
};
#endif
#ifdef CAIRO_HAS_PS_SURFACE
struct cairo_ps_renderer : cairo_vector_renderer<cairo_ps_surface_create_for_stream>
{
static constexpr const char * name = "cairo-ps";
static constexpr const char * ext = ".ps";
static constexpr const char* name = "cairo-ps";
static constexpr const char* ext = ".ps";
};
#endif
#ifdef CAIRO_HAS_PDF_SURFACE
struct cairo_pdf_renderer : cairo_vector_renderer<cairo_pdf_surface_create_for_stream>
{
static constexpr const char * name = "cairo-pdf";
static constexpr const char * ext = ".pdf";
static constexpr const char* name = "cairo-pdf";
static constexpr const char* ext = ".pdf";
};
#endif
#endif
@ -217,10 +210,10 @@ struct cairo_pdf_renderer : cairo_vector_renderer<cairo_pdf_surface_create_for_s
#if defined(SVG_RENDERER)
struct svg_renderer : vector_renderer_base
{
static constexpr const char * name = "svg";
static constexpr const char * ext = ".svg";
static constexpr const char* name = "svg";
static constexpr const char* ext = ".svg";
image_type render(mapnik::Map const & map, double scale_factor) const
image_type render(mapnik::Map const& map, double scale_factor) const
{
std::stringstream ss;
std::ostream_iterator<char> output_stream_iterator(ss);
@ -234,14 +227,14 @@ struct svg_renderer : vector_renderer_base
#if defined(GRID_RENDERER)
struct grid_renderer : raster_renderer_base<mapnik::image_rgba8>
{
static constexpr const char * name = "grid";
static constexpr const char* name = "grid";
void convert(mapnik::grid::data_type const & grid, image_type & image) const
void convert(mapnik::grid::data_type const& grid, image_type& image) const
{
for (std::size_t y = 0; y < grid.height(); ++y)
{
mapnik::grid::value_type const * grid_row = grid.get_row(y);
image_type::pixel_type * image_row = image.get_row(y);
mapnik::grid::value_type const* grid_row = grid.get_row(y);
image_type::pixel_type* image_row = image.get_row(y);
for (std::size_t x = 0; x < grid.width(); ++x)
{
mapnik::grid::value_type val = grid_row[x];
@ -268,7 +261,7 @@ struct grid_renderer : raster_renderer_base<mapnik::image_rgba8>
}
}
image_type render(mapnik::Map const & map, double scale_factor) const
image_type render(mapnik::Map const& map, double scale_factor) const
{
mapnik::grid grid(map.width(), map.height(), "__id__");
mapnik::grid_renderer<mapnik::grid> ren(map, grid, scale_factor);
@ -280,8 +273,8 @@ struct grid_renderer : raster_renderer_base<mapnik::image_rgba8>
};
#endif
template <typename T>
void set_rectangle(T const & src, T & dst, std::size_t x, std::size_t y)
template<typename T>
void set_rectangle(T const& src, T& dst, std::size_t x, std::size_t y)
{
mapnik::box2d<int> ext0(0, 0, dst.width(), dst.height());
mapnik::box2d<int> ext1(x, y, x + src.width(), y + src.height());
@ -291,8 +284,8 @@ void set_rectangle(T const & src, T & dst, std::size_t x, std::size_t y)
mapnik::box2d<int> box = ext0.intersect(ext1);
for (std::size_t pix_y = box.miny(); pix_y < static_cast<std::size_t>(box.maxy()); ++pix_y)
{
typename T::pixel_type * row_to = dst.get_row(pix_y);
typename T::pixel_type const * row_from = src.get_row(pix_y - y);
typename T::pixel_type* row_to = dst.get_row(pix_y);
typename T::pixel_type const* row_from = src.get_row(pix_y - y);
for (std::size_t pix_x = box.minx(); pix_x < static_cast<std::size_t>(box.maxx()); ++pix_x)
{
@ -302,24 +295,23 @@ void set_rectangle(T const & src, T & dst, std::size_t x, std::size_t y)
}
}
template <typename Renderer>
template<typename Renderer>
class renderer
{
public:
public:
using renderer_type = Renderer;
using image_type = typename Renderer::image_type;
renderer(boost::filesystem::path const & _output_dir, boost::filesystem::path const & _reference_dir, bool _overwrite)
: ren(), output_dir(_output_dir), reference_dir(_reference_dir), overwrite(_overwrite)
{
}
renderer(boost::filesystem::path const& _output_dir, boost::filesystem::path const& _reference_dir, bool _overwrite)
: ren()
, output_dir(_output_dir)
, reference_dir(_reference_dir)
, overwrite(_overwrite)
{}
image_type render(mapnik::Map const & map, double scale_factor) const
{
return ren.render(map, scale_factor);
}
image_type render(mapnik::Map const& map, double scale_factor) const { return ren.render(map, scale_factor); }
image_type render(mapnik::Map & map, double scale_factor, map_size const & tiles) const
image_type render(mapnik::Map& map, double scale_factor, map_size const& tiles) const
{
mapnik::box2d<double> box = map.get_current_extent();
image_type image(map.width(), map.height());
@ -330,11 +322,10 @@ public:
{
for (std::size_t tile_x = 0; tile_x < tiles.width; tile_x++)
{
mapnik::box2d<double> tile_box(
box.minx() + tile_x * tile_box_width,
box.miny() + tile_y * tile_box_height,
box.minx() + (tile_x + 1) * tile_box_width,
box.miny() + (tile_y + 1) * tile_box_height);
mapnik::box2d<double> tile_box(box.minx() + tile_x * tile_box_width,
box.miny() + tile_y * tile_box_height,
box.minx() + (tile_x + 1) * tile_box_width,
box.miny() + (tile_y + 1) * tile_box_height);
map.zoom_to_box(tile_box);
image_type tile(ren.render(map, scale_factor));
set_rectangle(tile, image, tile_x * tile.width(), (tiles.height - 1 - tile_y) * tile.height());
@ -343,10 +334,10 @@ public:
return image;
}
result report(image_type const & image,
std::string const & name,
map_size const & size,
map_size const & tiles,
result report(image_type const& image,
std::string const& name,
map_size const& size,
map_size const& tiles,
double scale_factor) const
{
boost::filesystem::path reference = reference_dir / image_file_name(name, size, tiles, scale_factor, true);
@ -380,10 +371,10 @@ public:
return res;
}
private:
std::string image_file_name(std::string const & test_name,
map_size const & size,
map_size const & tiles,
private:
std::string image_file_name(std::string const& test_name,
map_size const& size,
map_size const& tiles,
double scale_factor,
bool reference) const
{
@ -410,25 +401,31 @@ private:
using renderer_type = mapnik::util::variant<renderer<agg_renderer>
#if defined(HAVE_CAIRO)
,renderer<cairo_renderer>
,
renderer<cairo_renderer>
#ifdef CAIRO_HAS_SVG_SURFACE
,renderer<cairo_svg_renderer>
,
renderer<cairo_svg_renderer>
#endif
#ifdef CAIRO_HAS_PS_SURFACE
,renderer<cairo_ps_renderer>
,
renderer<cairo_ps_renderer>
#endif
#ifdef CAIRO_HAS_PDF_SURFACE
,renderer<cairo_pdf_renderer>
,
renderer<cairo_pdf_renderer>
#endif
#endif
#if defined(SVG_RENDERER)
,renderer<svg_renderer>
,
renderer<svg_renderer>
#endif
#if defined(GRID_RENDERER)
,renderer<grid_renderer>
,
renderer<grid_renderer>
#endif
>;
}
} // namespace visual_tests
#endif

View file

@ -28,10 +28,9 @@
#include "report.hpp"
namespace visual_tests
{
namespace visual_tests {
void console_report::report(result const & r)
void console_report::report(result const& r)
{
s << '"' << r.name << '-' << r.size.width << '-' << r.size.height;
if (r.tiles.width > 1 || r.tiles.height > 1)
@ -49,7 +48,7 @@ void console_report::report(result const & r)
s << std::endl;
}
unsigned console_report::summary(result_list const & results)
unsigned console_report::summary(result_list const& results)
{
unsigned ok = 0;
unsigned error = 0;
@ -60,14 +59,22 @@ unsigned console_report::summary(result_list const & results)
using duration_map_type = std::map<std::string, high_resolution_clock::duration>;
duration_map_type durations;
for (auto const & r : results)
for (auto const& r : results)
{
switch (r.state)
{
case STATE_OK: ok++; break;
case STATE_FAIL: fail++; break;
case STATE_ERROR: error++; break;
case STATE_OVERWRITE: overwrite++; break;
case STATE_OK:
ok++;
break;
case STATE_FAIL:
fail++;
break;
case STATE_ERROR:
error++;
break;
case STATE_OVERWRITE:
overwrite++;
break;
}
if (show_duration)
@ -85,16 +92,16 @@ unsigned console_report::summary(result_list const & results)
}
s << std::endl;
s << "Visual rendering: " << fail << " failed / " << ok << " passed / "
<< overwrite << " overwritten / " << error << " errors" << std::endl;
s << "Visual rendering: " << fail << " failed / " << ok << " passed / " << overwrite << " overwritten / " << error
<< " errors" << std::endl;
if (show_duration)
{
high_resolution_clock::duration total(0);
for (auto const & duration : durations)
for (auto const& duration : durations)
{
s << duration.first << ": \t" << duration_cast<milliseconds>(duration.second).count()
<< " milliseconds" << std::endl;
s << duration.first << ": \t" << duration_cast<milliseconds>(duration.second).count() << " milliseconds"
<< std::endl;
total += duration.second;
}
s << "total: \t" << duration_cast<milliseconds>(total).count() << " milliseconds" << std::endl;
@ -107,7 +114,7 @@ unsigned console_report::summary(result_list const & results)
return fail + error;
}
void console_report::report_state(result const & r)
void console_report::report_state(result const& r)
{
switch (r.state)
{
@ -126,9 +133,9 @@ void console_report::report_state(result const & r)
}
}
void console_report::report_failures(result_list const & results)
void console_report::report_failures(result_list const& results)
{
for (auto const & r : results)
for (auto const& r : results)
{
if (r.state == STATE_OK)
{
@ -146,7 +153,7 @@ void console_report::report_failures(result_list const & results)
}
}
void console_short_report::report(result const & r)
void console_short_report::report(result const& r)
{
switch (r.state)
{
@ -165,31 +172,31 @@ void console_short_report::report(result const & r)
}
}
void html_report::report(result const & r, boost::filesystem::path const & output_dir)
void html_report::report(result const& r, boost::filesystem::path const& output_dir)
{
if (r.state == STATE_ERROR)
{
s << "<div class=\"text\">Failed to render: " << r.name << "<br><em>" << r.error_message << "</em></div>\n";
s << "<div class=\"text\">Failed to render: " << r.name << "<br><em>" << r.error_message << "</em></div>\n";
}
else if (r.state == STATE_FAIL)
{
using namespace boost::filesystem;
using namespace boost::filesystem;
path reference = output_dir / r.reference_image_path.filename();
path actual = output_dir / r.actual_image_path.filename();
path reference = output_dir / r.reference_image_path.filename();
path actual = output_dir / r.actual_image_path.filename();
if (exists(reference))
{
remove(reference);
}
if (exists(actual))
{
remove(actual);
}
copy_file(r.reference_image_path, reference);
copy_file(r.actual_image_path, actual);
s << "<p>" << r.diff << "</p>\n"
if (exists(reference))
{
remove(reference);
}
if (exists(actual))
{
remove(actual);
}
copy_file(r.reference_image_path, reference);
copy_file(r.actual_image_path, actual);
// clang-format off
s << "<p>" << r.diff << "</p>\n"
"<div class=\"r\">"
" <div class=\"i\">"
" <a href=" << reference.filename() << ">\n"
@ -202,10 +209,11 @@ void html_report::report(result const & r, boost::filesystem::path const & outpu
" </a>\n"
" </div>\n"
"</div>\n";
// clang-format on
}
}
constexpr const char * html_header = R"template(<!DOCTYPE html>
constexpr const char* html_header = R"template(<!DOCTYPE html>
<html>
<head>
<style>
@ -226,15 +234,15 @@ constexpr const char * html_header = R"template(<!DOCTYPE html>
<body>
)template";
constexpr const char * html_footer = R"template(</div>
constexpr const char* html_footer = R"template(</div>
</body>
</html>)template";
void html_report::summary(result_list const & results, boost::filesystem::path const & output_dir)
void html_report::summary(result_list const& results, boost::filesystem::path const& output_dir)
{
s << html_header;
for (auto const & r : results)
for (auto const& r : results)
{
if (r.state != STATE_OK)
{
@ -245,7 +253,7 @@ void html_report::summary(result_list const & results, boost::filesystem::path c
s << html_footer;
}
void html_summary(result_list const & results, boost::filesystem::path output_dir)
void html_summary(result_list const& results, boost::filesystem::path output_dir)
{
boost::filesystem::path html_root = output_dir / "visual-test-results";
boost::filesystem::create_directories(html_root);
@ -256,4 +264,4 @@ void html_summary(result_list const & results, boost::filesystem::path output_di
report.summary(results, html_root);
}
}
} // namespace visual_tests

View file

@ -30,99 +30,97 @@
#include "config.hpp"
namespace visual_tests
{
namespace visual_tests {
class console_report
{
public:
console_report(bool _show_duration) : s(std::clog), show_duration(_show_duration)
{
}
public:
console_report(bool _show_duration)
: s(std::clog)
, show_duration(_show_duration)
{}
console_report(std::ostream & _s) : s(_s)
{
}
console_report(std::ostream& _s)
: s(_s)
{}
void report(result const & r);
unsigned summary(result_list const & results);
void report(result const& r);
unsigned summary(result_list const& results);
protected:
void report_state(result const & r);
void report_failures(result_list const & results);
protected:
void report_state(result const& r);
void report_failures(result_list const& results);
std::ostream & s;
std::ostream& s;
bool show_duration;
};
class console_short_report : public console_report
{
public:
console_short_report(bool _show_duration) : console_report(_show_duration)
{
}
public:
console_short_report(bool _show_duration)
: console_report(_show_duration)
{}
console_short_report(std::ostream & _s) : console_report(_s)
{
}
console_short_report(std::ostream& _s)
: console_report(_s)
{}
void report(result const & r);
void report(result const& r);
};
class html_report
{
public:
html_report(std::ostream & _s) : s(_s)
{
}
public:
html_report(std::ostream& _s)
: s(_s)
{}
void report(result const & r, boost::filesystem::path const & output_dir);
void summary(result_list const & results, boost::filesystem::path const & output_dir);
void report(result const& r, boost::filesystem::path const& output_dir);
void summary(result_list const& results, boost::filesystem::path const& output_dir);
protected:
std::ostream & s;
protected:
std::ostream& s;
};
using report_type = mapnik::util::variant<console_report, console_short_report>;
class report_visitor
{
public:
report_visitor(result const & r)
public:
report_visitor(result const& r)
: result_(r)
{
}
{}
template <typename T>
void operator()(T & report) const
template<typename T>
void operator()(T& report) const
{
return report.report(result_);
}
private:
result const & result_;
private:
result const& result_;
};
class summary_visitor
{
public:
summary_visitor(result_list const & r)
public:
summary_visitor(result_list const& r)
: result_(r)
{
}
{}
template <typename T>
unsigned operator()(T & report) const
template<typename T>
unsigned operator()(T& report) const
{
return report.summary(result_);
}
private:
result_list const & result_;
private:
result_list const& result_;
};
void html_summary(result_list const & results, boost::filesystem::path output_dir);
void html_summary(result_list const& results, boost::filesystem::path output_dir);
}
} // namespace visual_tests
#endif

View file

@ -34,21 +34,17 @@
#ifdef MAPNIK_LOG
using log_levels_map = std::map<std::string, mapnik::logger::severity_type>;
log_levels_map log_levels
{
{ "debug", mapnik::logger::severity_type::debug },
{ "warn", mapnik::logger::severity_type::warn },
{ "error", mapnik::logger::severity_type::error },
{ "none", mapnik::logger::severity_type::none }
};
log_levels_map log_levels{{"debug", mapnik::logger::severity_type::debug},
{"warn", mapnik::logger::severity_type::warn},
{"error", mapnik::logger::severity_type::error},
{"none", mapnik::logger::severity_type::none}};
#endif
using namespace visual_tests;
namespace po = boost::program_options;
runner::renderer_container create_renderers(po::variables_map const & args,
boost::filesystem::path const & output_dir,
bool force_append = false)
runner::renderer_container
create_renderers(po::variables_map const& args, boost::filesystem::path const& output_dir, bool force_append = false)
{
boost::filesystem::path reference_dir(args["images-dir"].as<std::string>());
bool overwrite = args.count("overwrite");
@ -106,6 +102,7 @@ runner::renderer_container create_renderers(po::variables_map const & args,
int main(int argc, char** argv)
{
po::options_description desc("visual test runner");
// clang-format off
desc.add_options()
("help,h", "produce usage message")
("verbose,v", "verbose output")
@ -147,7 +144,7 @@ int main(int argc, char** argv)
(grid_renderer::name, "render with Grid renderer")
#endif
;
// clang-format on
po::positional_options_description p;
p.add("styles", -1);
po::variables_map vm;
@ -194,7 +191,8 @@ int main(int argc, char** argv)
vm["jobs"].as<std::size_t>(),
create_renderers(vm, output_dir));
bool show_duration = vm.count("duration");
report_type report(vm.count("verbose") ? report_type((console_report(show_duration))) : report_type((console_short_report(show_duration))));
report_type report(vm.count("verbose") ? report_type((console_report(show_duration)))
: report_type((console_short_report(show_duration))));
result_list results;
try
@ -207,8 +205,7 @@ int main(int argc, char** argv)
{
results = run.test_all(report);
}
}
catch (std::exception & e)
} catch (std::exception& e)
{
std::cerr << "Error running tests: " << e.what() << std::endl;
return 1;

View file

@ -25,18 +25,16 @@
#include <future>
#include <atomic>
#include <mapnik/load_map.hpp>
#include "runner.hpp"
#include "parse_map_sizes.hpp"
namespace visual_tests
{
namespace visual_tests {
struct renderer_name_visitor
{
template <typename Renderer>
template<typename Renderer>
std::string operator()(Renderer const&) const
{
return Renderer::renderer_type::name;
@ -45,36 +43,35 @@ struct renderer_name_visitor
class renderer_visitor
{
public:
renderer_visitor(std::string const & name,
mapnik::Map & map,
map_size const & tiles,
public:
renderer_visitor(std::string const& name,
mapnik::Map& map,
map_size const& tiles,
double scale_factor,
result_list & results,
report_type & report,
result_list& results,
report_type& report,
std::size_t iterations,
bool is_fail_limit,
std::atomic<std::size_t> & fail_count)
: name_(name),
map_(map),
tiles_(tiles),
scale_factor_(scale_factor),
results_(results),
report_(report),
iterations_(iterations),
is_fail_limit_(is_fail_limit),
fail_count_(fail_count)
{
}
std::atomic<std::size_t>& fail_count)
: name_(name)
, map_(map)
, tiles_(tiles)
, scale_factor_(scale_factor)
, results_(results)
, report_(report)
, iterations_(iterations)
, is_fail_limit_(is_fail_limit)
, fail_count_(fail_count)
{}
template <typename T, typename std::enable_if<T::renderer_type::support_tiles>::type* = nullptr>
template<typename T, typename std::enable_if<T::renderer_type::support_tiles>::type* = nullptr>
void operator()(T const& renderer) const
{
test(renderer);
}
template <typename T, typename std::enable_if<!T::renderer_type::support_tiles>::type* = nullptr>
void operator()(T const & renderer) const
template<typename T, typename std::enable_if<!T::renderer_type::support_tiles>::type* = nullptr>
void operator()(T const& renderer) const
{
if (tiles_.width == 1 && tiles_.height == 1)
{
@ -82,13 +79,13 @@ public:
}
}
private:
template <typename T>
void test(T const & renderer) const
private:
template<typename T>
void test(T const& renderer) const
{
map_size size { map_.width(), map_.height() };
map_size size{map_.width(), map_.height()};
std::chrono::high_resolution_clock::time_point start(std::chrono::high_resolution_clock::now());
for (std::size_t i = iterations_ ; i > 0; i--)
for (std::size_t i = iterations_; i > 0; i--)
{
typename T::image_type image(render(renderer));
if (i == 1)
@ -106,7 +103,7 @@ private:
}
}
template <typename T, typename std::enable_if<T::renderer_type::support_tiles>::type* = nullptr>
template<typename T, typename std::enable_if<T::renderer_type::support_tiles>::type* = nullptr>
typename T::image_type render(T const& renderer) const
{
if (tiles_.width == 1 && tiles_.height == 1)
@ -119,39 +116,38 @@ private:
}
}
template <typename T, typename std::enable_if<!T::renderer_type::support_tiles>::type* = nullptr>
typename T::image_type render(T const & renderer) const
template<typename T, typename std::enable_if<!T::renderer_type::support_tiles>::type* = nullptr>
typename T::image_type render(T const& renderer) const
{
return renderer.render(map_, scale_factor_);
}
std::string const & name_;
mapnik::Map & map_;
map_size const & tiles_;
std::string const& name_;
mapnik::Map& map_;
map_size const& tiles_;
double scale_factor_;
result_list & results_;
report_type & report_;
result_list& results_;
report_type& report_;
std::size_t iterations_;
bool is_fail_limit_;
std::atomic<std::size_t> & fail_count_;
std::atomic<std::size_t>& fail_count_;
};
runner::runner(runner::path_type const & styles_dir,
config const & defaults,
runner::runner(runner::path_type const& styles_dir,
config const& defaults,
std::size_t iterations,
std::size_t fail_limit,
std::size_t jobs,
runner::renderer_container const & renderers)
: styles_dir_(styles_dir),
defaults_(defaults),
jobs_(jobs),
iterations_(iterations),
fail_limit_(fail_limit),
renderers_(renderers)
{
}
runner::renderer_container const& renderers)
: styles_dir_(styles_dir)
, defaults_(defaults)
, jobs_(jobs)
, iterations_(iterations)
, fail_limit_(fail_limit)
, renderers_(renderers)
{}
result_list runner::test_all(report_type & report) const
result_list runner::test_all(report_type& report) const
{
boost::filesystem::directory_iterator begin(styles_dir_);
boost::filesystem::directory_iterator end;
@ -159,19 +155,21 @@ result_list runner::test_all(report_type & report) const
return test_parallel(files, report, jobs_);
}
result_list runner::test(std::vector<std::string> const & style_names, report_type & report) const
result_list runner::test(std::vector<std::string> const& style_names, report_type& report) const
{
std::vector<runner::path_type> files;
files.reserve(style_names.size());
std::transform(style_names.begin(), style_names.end(), std::back_inserter(files),
[&](runner::path_type const & name)
{
return (name.extension() == ".xml") ? name : (styles_dir_ / (name.string() + ".xml"));
});
std::transform(style_names.begin(),
style_names.end(),
std::back_inserter(files),
[&](runner::path_type const& name) {
return (name.extension() == ".xml") ? name : (styles_dir_ / (name.string() + ".xml"));
});
return test_parallel(files, report, jobs_);
}
result_list runner::test_parallel(std::vector<runner::path_type> const & files, report_type & report, std::size_t jobs) const
result_list
runner::test_parallel(std::vector<runner::path_type> const& files, report_type& report, std::size_t jobs) const
{
result_list results;
@ -211,7 +209,7 @@ result_list runner::test_parallel(std::vector<runner::path_type> const & files,
futures[i] = std::async(launch, &runner::test_range, this, begin, end, std::ref(report), std::ref(fail_count));
}
for (auto & f : futures)
for (auto& f : futures)
{
result_list r = f.get();
std::move(r.begin(), r.end(), std::back_inserter(results));
@ -229,15 +227,14 @@ result_list runner::test_range(files_iterator begin,
for (runner::files_iterator i = begin; i != end; i++)
{
runner::path_type const & file = *i;
runner::path_type const& file = *i;
if (file.extension() == ".xml")
{
try
{
result_list r = test_one(file, report, fail_count.get());
std::move(r.begin(), r.end(), std::back_inserter(results));
}
catch (std::exception const& ex)
} catch (std::exception const& ex)
{
result r;
r.state = STATE_ERROR;
@ -258,7 +255,7 @@ result_list runner::test_range(files_iterator begin,
return results;
}
void runner::parse_params(mapnik::parameters const & params, config & cfg) const
void runner::parse_params(mapnik::parameters const& params, config& cfg) const
{
cfg.status = *params.get<mapnik::value_bool>("status", cfg.status);
@ -285,7 +282,7 @@ void runner::parse_params(mapnik::parameters const & params, config & cfg) const
cfg.bbox.from_string(*bbox_string);
}
for (auto const & renderer : renderers_)
for (auto const& renderer : renderers_)
{
std::string renderer_name = mapnik::util::apply_visitor(renderer_name_visitor(), renderer);
boost::optional<mapnik::value_bool> enabled = params.get<mapnik::value_bool>(renderer_name);
@ -296,9 +293,8 @@ void runner::parse_params(mapnik::parameters const & params, config & cfg) const
}
}
result_list runner::test_one(runner::path_type const& style_path,
report_type & report,
std::atomic<std::size_t> & fail_count) const
result_list
runner::test_one(runner::path_type const& style_path, report_type& report, std::atomic<std::size_t>& fail_count) const
{
config cfg(defaults_);
mapnik::Map map(cfg.sizes.front().width, cfg.sizes.front().height);
@ -307,8 +303,7 @@ result_list runner::test_one(runner::path_type const& style_path,
try
{
mapnik::load_map(map, style_path.string(), true);
}
catch (std::exception const& ex)
} catch (std::exception const& ex)
{
std::string what = ex.what();
if (what.find("Could not create datasource") != std::string::npos ||
@ -328,11 +323,11 @@ result_list runner::test_one(runner::path_type const& style_path,
std::string name(style_path.stem().string());
for (auto const & size : cfg.sizes)
for (auto const& size : cfg.sizes)
{
for (auto const & scale_factor : cfg.scales)
for (auto const& scale_factor : cfg.scales)
{
for (auto const & tiles_count : cfg.tiles)
for (auto const& tiles_count : cfg.tiles)
{
if (!tiles_count.width || !tiles_count.height)
{
@ -343,7 +338,7 @@ result_list runner::test_one(runner::path_type const& style_path,
throw std::runtime_error("Tile size is not an integer.");
}
for (auto const & ren : renderers_)
for (auto const& ren : renderers_)
{
std::string renderer_name = mapnik::util::apply_visitor(renderer_name_visitor(), ren);
if (cfg.ignored_renderers.count(renderer_name))
@ -368,7 +363,8 @@ result_list runner::test_one(runner::path_type const& style_path,
report,
iterations_,
fail_limit_,
fail_count), ren);
fail_count),
ren);
if (fail_limit_ && fail_count >= fail_limit_)
{
return results;
@ -380,4 +376,4 @@ result_list runner::test_one(runner::path_type const& style_path,
return results;
}
}
} // namespace visual_tests

Some files were not shown because too many files have changed in this diff Show more