format utils

This commit is contained in:
Mathis Logemann 2022-01-26 20:41:37 +01:00
parent e7c3d04309
commit d5a873e81c
14 changed files with 630 additions and 595 deletions

View file

@ -20,7 +20,6 @@
* *
*****************************************************************************/ *****************************************************************************/
#include <iostream> #include <iostream>
#include <string> #include <string>
@ -31,11 +30,9 @@
#include <mapnik/datasource_cache.hpp> #include <mapnik/datasource_cache.hpp>
#include <mapnik/util/geometry_to_wkb.hpp> #include <mapnik/util/geometry_to_wkb.hpp>
int main(int argc, char** argv)
int main (int argc, char ** argv )
{ {
if (argc != 2)
if ( argc !=2)
{ {
std::cerr << "Usage: " << argv[0] << " <path-to-shapefile>\n"; std::cerr << "Usage: " << argv[0] << " <path-to-shapefile>\n";
return EXIT_SUCCESS; return EXIT_SUCCESS;
@ -57,8 +54,7 @@ int main (int argc, char ** argv )
try try
{ {
ds = mapnik::datasource_cache::instance().create(p); ds = mapnik::datasource_cache::instance().create(p);
} } catch (...)
catch ( ... )
{ {
std::cerr << "Can't create datasource!\n"; std::cerr << "Can't create datasource!\n";
return EXIT_FAILURE; return EXIT_FAILURE;
@ -78,25 +74,23 @@ int main (int argc, char ** argv )
mapnik::featureset_ptr fs = ds->features(q); mapnik::featureset_ptr fs = ds->features(q);
mapnik::feature_ptr f = fs->next(); mapnik::feature_ptr f = fs->next();
while(f) while (f)
{ {
std::cerr << *f << std::endl; std::cerr << *f << std::endl;
mapnik::geometry::geometry<double> const& geom = f->get_geometry(); mapnik::geometry::geometry<double> const& geom = f->get_geometry();
// NDR // NDR
{ {
mapnik::util::wkb_buffer_ptr wkb = mapnik::util::to_wkb(geom,mapnik::wkbNDR); mapnik::util::wkb_buffer_ptr wkb = mapnik::util::to_wkb(geom, mapnik::wkbNDR);
std::cerr << mapnik::util::detail::to_hex(wkb->buffer(),wkb->size()) << std::endl; std::cerr << mapnik::util::detail::to_hex(wkb->buffer(), wkb->size()) << std::endl;
} }
// XDR // XDR
{ {
mapnik::util::wkb_buffer_ptr wkb = mapnik::util::to_wkb(geom,mapnik::wkbXDR); mapnik::util::wkb_buffer_ptr wkb = mapnik::util::to_wkb(geom, mapnik::wkbXDR);
std::cerr << mapnik::util::detail::to_hex(wkb->buffer(),wkb->size()) << std::endl; std::cerr << mapnik::util::detail::to_hex(wkb->buffer(), wkb->size()) << std::endl;
} }
f = fs->next(); f = fs->next();
} }
} }
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View file

@ -42,25 +42,25 @@ MAPNIK_DISABLE_WARNING_POP
const int DEFAULT_DEPTH = 8; const int DEFAULT_DEPTH = 8;
const double DEFAULT_RATIO = 0.55; const double DEFAULT_RATIO = 0.55;
namespace mapnik { namespace detail { namespace mapnik {
namespace detail {
bool is_csv(std::string const& filename) bool is_csv(std::string const& filename)
{ {
return boost::iends_with(filename,".csv") return boost::iends_with(filename, ".csv") || boost::iends_with(filename, ".tsv");
|| boost::iends_with(filename,".tsv");
} }
bool is_geojson(std::string const& filename) bool is_geojson(std::string const& filename)
{ {
return boost::iends_with(filename,".geojson") return boost::iends_with(filename, ".geojson") || boost::iends_with(filename, ".json");
|| boost::iends_with(filename,".json");
} }
}} } // namespace detail
} // namespace mapnik
int main (int argc, char** argv) int main(int argc, char** argv)
{ {
//using namespace mapnik; // using namespace mapnik;
namespace po = boost::program_options; namespace po = boost::program_options;
bool verbose = false; bool verbose = false;
bool validate_features = false; bool validate_features = false;
@ -76,6 +76,7 @@ int main (int argc, char** argv)
try try
{ {
po::options_description desc("Mapnik CSV/GeoJSON index utility"); po::options_description desc("Mapnik CSV/GeoJSON index utility");
// clang-format off
desc.add_options() desc.add_options()
("help,h", "Produce usage message") ("help,h", "Produce usage message")
("version,V","Print version string") ("version,V","Print version string")
@ -89,14 +90,15 @@ int main (int argc, char** argv)
("validate-features", "Validate GeoJSON features") ("validate-features", "Validate GeoJSON features")
("bbox,b", po::value<std::string>(), "Only index features within bounding box: --bbox=minx,miny,maxx,maxy") ("bbox,b", po::value<std::string>(), "Only index features within bounding box: --bbox=minx,miny,maxx,maxy")
; ;
// clang-format on
po::positional_options_description p; po::positional_options_description p;
p.add("files",-1); p.add("files", -1);
po::store(po::command_line_parser(argc, argv) po::store(po::command_line_parser(argc, argv)
.options(desc) .options(desc)
.style(po::command_line_style::unix_style | po::command_line_style::allow_long_disguise) .style(po::command_line_style::unix_style | po::command_line_style::allow_long_disguise)
.positional(p) .positional(p)
.run(), vm); .run(),
vm);
po::notify(vm); po::notify(vm);
if (vm.count("version")) if (vm.count("version"))
@ -139,14 +141,13 @@ int main (int argc, char** argv)
} }
if (vm.count("files")) if (vm.count("files"))
{ {
files=vm["files"].as<std::vector<std::string> >(); files = vm["files"].as<std::vector<std::string>>();
} }
if (vm.count("bbox") && bbox.from_string(vm["bbox"].as<std::string>())) if (vm.count("bbox") && bbox.from_string(vm["bbox"].as<std::string>()))
{ {
use_bbox = true; use_bbox = true;
} }
} } catch (std::exception const& ex)
catch (std::exception const& ex)
{ {
std::clog << "Error: " << ex.what() << std::endl; std::clog << "Error: " << ex.what() << std::endl;
return EXIT_FAILURE; return EXIT_FAILURE;
@ -203,7 +204,7 @@ int main (int argc, char** argv)
else if (mapnik::detail::is_geojson(filename)) else if (mapnik::detail::is_geojson(filename))
{ {
std::clog << "processing '" << filename << "' as GeoJSON\n"; std::clog << "processing '" << filename << "' as GeoJSON\n";
std::pair<bool,mapnik::box2d<float>> result; std::pair<bool, mapnik::box2d<float>> result;
result = mapnik::detail::process_geojson_file_x3(boxes, filename, validate_features, verbose); result = mapnik::detail::process_geojson_file_x3(boxes, filename, validate_features, verbose);
if (!result.first) if (!result.first)
{ {
@ -221,9 +222,9 @@ int main (int argc, char** argv)
for (auto const& item : boxes) for (auto const& item : boxes)
{ {
auto ext_f = std::get<0>(item); auto ext_f = std::get<0>(item);
if (use_bbox && !bbox.intersects(ext_f)) continue; if (use_bbox && !bbox.intersects(ext_f))
mapnik::util::index_record rec = continue;
{std::get<1>(item).first, std::get<1>(item).second, ext_f}; mapnik::util::index_record rec = {std::get<1>(item).first, std::get<1>(item).second, ext_f};
tree.insert(rec, ext_f); tree.insert(rec, ext_f);
} }
@ -231,8 +232,7 @@ int main (int argc, char** argv)
std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary); std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary);
if (!file) if (!file)
{ {
std::clog << "cannot open index file for writing file \"" std::clog << "cannot open index file for writing file \"" << (filename + ".index") << "\"" << std::endl;
<< (filename + ".index") << "\"" << std::endl;
} }
else else
{ {

View file

@ -36,10 +36,12 @@
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
namespace mapnik { namespace detail { namespace mapnik {
namespace detail {
template <typename T> template<typename T>
std::pair<bool,typename T::value_type::first_type> process_csv_file(T & boxes, std::string const& filename, std::string const& manual_headers, char separator, char quote) std::pair<bool, typename T::value_type::first_type>
process_csv_file(T& boxes, std::string const& filename, std::string const& manual_headers, char separator, char quote)
{ {
using box_type = typename T::value_type::first_type; using box_type = typename T::value_type::first_type;
csv_utils::csv_file_parser p; csv_utils::csv_file_parser p;
@ -47,14 +49,12 @@ std::pair<bool,typename T::value_type::first_type> process_csv_file(T & boxes, s
p.separator_ = separator; p.separator_ = separator;
p.quote_ = quote; p.quote_ = quote;
util::mapped_memory_file csv_file{filename}; util::mapped_memory_file csv_file{filename};
try try
{ {
p.parse_csv_and_boxes(csv_file.file(), boxes); p.parse_csv_and_boxes(csv_file.file(), boxes);
return std::make_pair(true, box_type(p.extent_)); return std::make_pair(true, box_type(p.extent_));
} } catch (std::exception const& ex)
catch (std::exception const& ex)
{ {
std::clog << ex.what() << std::endl; std::clog << ex.what() << std::endl;
return std::make_pair(false, box_type(p.extent_)); return std::make_pair(false, box_type(p.extent_));
@ -64,6 +64,7 @@ std::pair<bool,typename T::value_type::first_type> process_csv_file(T & boxes, s
using box_type = mapnik::box2d<float>; using box_type = mapnik::box2d<float>;
using item_type = std::pair<box_type, std::pair<std::uint64_t, std::uint64_t>>; using item_type = std::pair<box_type, std::pair<std::uint64_t, std::uint64_t>>;
using boxes_type = std::vector<item_type>; using boxes_type = std::vector<item_type>;
template std::pair<bool,box_type> process_csv_file(boxes_type&, std::string const&, std::string const&, char, char); template std::pair<bool, box_type> process_csv_file(boxes_type&, std::string const&, std::string const&, char, char);
}} } // namespace detail
} // namespace mapnik

View file

@ -26,11 +26,17 @@
#include <utility> #include <utility>
#include <mapnik/geometry/box2d.hpp> #include <mapnik/geometry/box2d.hpp>
namespace mapnik { namespace detail { namespace mapnik {
namespace detail {
template <typename T> template<typename T>
std::pair<bool, typename T::value_type::first_type> process_csv_file(T & boxes, std::string const& filename, std::string const& manual_headers, char separator, char quote); std::pair<bool, typename T::value_type::first_type> process_csv_file(T& boxes,
std::string const& filename,
std::string const& manual_headers,
char separator,
char quote);
}} }
} // namespace mapnik
#endif // MAPNIK_UTILS_PROCESS_CSV_FILE_HPP #endif // MAPNIK_UTILS_PROCESS_CSV_FILE_HPP

View file

@ -43,35 +43,34 @@ MAPNIK_DISABLE_WARNING_POP
namespace { namespace {
constexpr mapnik::json::well_known_names feature_properties[] = { constexpr mapnik::json::well_known_names feature_properties[] = {mapnik::json::well_known_names::type,
mapnik::json::well_known_names::type, mapnik::json::well_known_names::geometry,
mapnik::json::well_known_names::geometry, mapnik::json::well_known_names::properties}; // sorted
mapnik::json::well_known_names::properties}; // sorted
constexpr mapnik::json::well_known_names geometry_properties[] = { constexpr mapnik::json::well_known_names geometry_properties[] = {
mapnik::json::well_known_names::type, mapnik::json::well_known_names::type,
mapnik::json::well_known_names::coordinates}; // sorted mapnik::json::well_known_names::coordinates}; // sorted
constexpr mapnik::json::well_known_names geometry_collection_properties[] = { constexpr mapnik::json::well_known_names geometry_collection_properties[] = {
mapnik::json::well_known_names::type, mapnik::json::well_known_names::type,
mapnik::json::well_known_names::geometries}; // sorted mapnik::json::well_known_names::geometries}; // sorted
template<typename Keys>
template <typename Keys>
std::string join(Keys const& keys) std::string join(Keys const& keys)
{ {
std::string result; std::string result;
bool first = true; bool first = true;
for (auto const& key : keys) for (auto const& key : keys)
{ {
if (!first) result += ","; if (!first)
result += ",";
result += "\"" + std::string(mapnik::json::wkn_to_string(key)) + "\""; result += "\"" + std::string(mapnik::json::wkn_to_string(key)) + "\"";
first = false; first = false;
} }
return result; return result;
} }
template <typename Iterator, typename Keys> template<typename Iterator, typename Keys>
bool has_keys(Iterator first1, Iterator last1, Keys const& keys) bool has_keys(Iterator first1, Iterator last1, Keys const& keys)
{ {
auto first2 = std::begin(keys); auto first2 = std::begin(keys);
@ -86,55 +85,57 @@ bool has_keys(Iterator first1, Iterator last1, Keys const& keys)
return true; return true;
} }
template <typename Keys> template<typename Keys>
bool validate_geojson_feature(mapnik::json::geojson_value & value, Keys const& keys, bool verbose) bool validate_geojson_feature(mapnik::json::geojson_value& value, Keys const& keys, bool verbose)
{ {
if (!value.is<mapnik::json::geojson_object>()) if (!value.is<mapnik::json::geojson_object>())
{ {
if (verbose) std::clog << "Expecting an GeoJSON object" << std::endl; if (verbose)
std::clog << "Expecting an GeoJSON object" << std::endl;
return false; return false;
} }
mapnik::json::geojson_object & feature = mapnik::util::get<mapnik::json::geojson_object>(value); mapnik::json::geojson_object& feature = mapnik::util::get<mapnik::json::geojson_object>(value);
std::sort(feature.begin(), feature.end(), [](auto const& e0, auto const& e1) std::sort(feature.begin(), feature.end(), [](auto const& e0, auto const& e1) {
{ return std::get<0>(e0) < std::get<0>(e1);
return std::get<0>(e0) < std::get<0>(e1); });
});
if (!has_keys(feature.begin(), feature.end(), feature_properties)) if (!has_keys(feature.begin(), feature.end(), feature_properties))
{ {
if (verbose) std::clog << "Expecting one of " << join(feature_properties) << std::endl; if (verbose)
std::clog << "Expecting one of " << join(feature_properties) << std::endl;
return false; return false;
} }
for (auto & elem : feature) for (auto& elem : feature)
{ {
auto const key = std::get<0>(elem); auto const key = std::get<0>(elem);
if (key == mapnik::json::well_known_names::geometry) if (key == mapnik::json::well_known_names::geometry)
{ {
auto & geom_value = std::get<1>(elem); auto& geom_value = std::get<1>(elem);
if (!geom_value.is<mapnik::json::geojson_object>()) if (!geom_value.is<mapnik::json::geojson_object>())
{ {
if (verbose) std::clog << "\"geometry\": xxx <-- expecting an JSON object here" << std::endl; if (verbose)
std::clog << "\"geometry\": xxx <-- expecting an JSON object here" << std::endl;
return false; return false;
} }
auto & geometry = mapnik::util::get<mapnik::json::geojson_object>(geom_value); auto& geometry = mapnik::util::get<mapnik::json::geojson_object>(geom_value);
// sort by property name // sort by property name
std::sort(geometry.begin(), geometry.end(), [](auto const& e0, auto const& e1) std::sort(geometry.begin(), geometry.end(), [](auto const& e0, auto const& e1) {
{ return std::get<0>(e0) < std::get<0>(e1);
return std::get<0>(e0) < std::get<0>(e1); });
});
if (!has_keys(geometry.begin(), geometry.end(), geometry_properties) if (!has_keys(geometry.begin(), geometry.end(), geometry_properties) &&
&& !has_keys(geometry.begin(), geometry.end(), geometry_collection_properties)) !has_keys(geometry.begin(), geometry.end(), geometry_collection_properties))
{ {
if (verbose) std::clog << "\"geometry\": xxx <-- expecting one of " << join(geometry_properties) if (verbose)
<< " or " << join(geometry_collection_properties) << std::endl; std::clog << "\"geometry\": xxx <-- expecting one of " << join(geometry_properties) << " or "
<< join(geometry_collection_properties) << std::endl;
return false; return false;
} }
mapnik::geometry::geometry_types geom_type; mapnik::geometry::geometry_types geom_type;
mapnik::json::positions const* coordinates = nullptr; mapnik::json::positions const* coordinates = nullptr;
for (auto & elem2 : geometry) for (auto& elem2 : geometry)
{ {
auto const key2 = std::get<0>(elem2); auto const key2 = std::get<0>(elem2);
if (key2 == mapnik::json::well_known_names::type) if (key2 == mapnik::json::well_known_names::type)
@ -142,13 +143,16 @@ bool validate_geojson_feature(mapnik::json::geojson_value & value, Keys const& k
auto const& geom_type_value = std::get<1>(elem2); auto const& geom_type_value = std::get<1>(elem2);
if (!geom_type_value.is<mapnik::geometry::geometry_types>()) if (!geom_type_value.is<mapnik::geometry::geometry_types>())
{ {
if (verbose) std::clog << "\"type\": xxx <-- expecting an GeoJSON geometry type here" << std::endl; if (verbose)
std::clog << "\"type\": xxx <-- expecting an GeoJSON geometry type here" << std::endl;
return false; return false;
} }
geom_type = mapnik::util::get<mapnik::geometry::geometry_types>(geom_type_value); geom_type = mapnik::util::get<mapnik::geometry::geometry_types>(geom_type_value);
if (geom_type == mapnik::geometry::geometry_types::GeometryCollection) if (geom_type == mapnik::geometry::geometry_types::GeometryCollection)
{ {
if (verbose) std::clog << "GeometryCollections are not allowed" << std::endl;; if (verbose)
std::clog << "GeometryCollections are not allowed" << std::endl;
;
return false; return false;
} }
} }
@ -157,7 +161,8 @@ bool validate_geojson_feature(mapnik::json::geojson_value & value, Keys const& k
auto const& coordinates_value = std::get<1>(elem2); auto const& coordinates_value = std::get<1>(elem2);
if (!coordinates_value.is<mapnik::json::positions>()) if (!coordinates_value.is<mapnik::json::positions>())
{ {
if (verbose) std::clog << "\"coordinates\": xxx <-- expecting an GeoJSON positions here" << std::endl; if (verbose)
std::clog << "\"coordinates\": xxx <-- expecting an GeoJSON positions here" << std::endl;
return false; return false;
} }
coordinates = &mapnik::util::get<mapnik::json::positions>(coordinates_value); coordinates = &mapnik::util::get<mapnik::json::positions>(coordinates_value);
@ -168,7 +173,8 @@ bool validate_geojson_feature(mapnik::json::geojson_value & value, Keys const& k
// expecting single position // expecting single position
if (!coordinates->is<mapnik::json::point>()) if (!coordinates->is<mapnik::json::point>())
{ {
if (verbose) std::clog << "Expecting single position in Point" << std::endl; if (verbose)
std::clog << "Expecting single position in Point" << std::endl;
return false; return false;
} }
} }
@ -177,7 +183,8 @@ bool validate_geojson_feature(mapnik::json::geojson_value & value, Keys const& k
// expecting // expecting
if (!coordinates->is<mapnik::json::ring>()) if (!coordinates->is<mapnik::json::ring>())
{ {
if (verbose) std::clog << "Expecting sequence of positions (ring) in LineString" << std::endl; if (verbose)
std::clog << "Expecting sequence of positions (ring) in LineString" << std::endl;
return false; return false;
} }
else else
@ -185,7 +192,8 @@ bool validate_geojson_feature(mapnik::json::geojson_value & value, Keys const& k
auto const& ring = mapnik::util::get<mapnik::json::ring>(*coordinates); auto const& ring = mapnik::util::get<mapnik::json::ring>(*coordinates);
if (ring.size() < 2) if (ring.size() < 2)
{ {
if (verbose) std::clog << "Expecting at least two coordinates in LineString" << std::endl; if (verbose)
std::clog << "Expecting at least two coordinates in LineString" << std::endl;
return false; return false;
} }
} }
@ -195,7 +203,8 @@ bool validate_geojson_feature(mapnik::json::geojson_value & value, Keys const& k
// expecting // expecting
if (!coordinates->is<mapnik::json::rings>()) if (!coordinates->is<mapnik::json::rings>())
{ {
if (verbose) std::clog << "Expecting an array of rings in Polygon" << std::endl; if (verbose)
std::clog << "Expecting an array of rings in Polygon" << std::endl;
return false; return false;
} }
else else
@ -203,14 +212,16 @@ bool validate_geojson_feature(mapnik::json::geojson_value & value, Keys const& k
auto const& rings = mapnik::util::get<mapnik::json::rings>(*coordinates); auto const& rings = mapnik::util::get<mapnik::json::rings>(*coordinates);
if (rings.size() < 1) if (rings.size() < 1)
{ {
if (verbose) std::clog << "Expecting at least one ring in Polygon" << std::endl; if (verbose)
std::clog << "Expecting at least one ring in Polygon" << std::endl;
return false; return false;
} }
for (auto const& ring : rings) for (auto const& ring : rings)
{ {
if (ring.size() < 4) if (ring.size() < 4)
{ {
if (verbose) std::clog << "Expecting at least four coordinates in Polygon ring" << std::endl; if (verbose)
std::clog << "Expecting at least four coordinates in Polygon ring" << std::endl;
return false; return false;
} }
} }
@ -227,20 +238,20 @@ using base_iterator_type = char const*;
auto const& geojson_value = mapnik::json::grammar::geojson_value; auto const& geojson_value = mapnik::json::grammar::geojson_value;
} } // namespace
namespace mapnik { namespace detail { namespace mapnik {
namespace detail {
template<typename T>
template <typename T> std::pair<bool, typename T::value_type::first_type>
std::pair<bool,typename T::value_type::first_type> process_geojson_file_x3(T & boxes, std::string const& filename, bool validate_features, bool verbose) process_geojson_file_x3(T& boxes, std::string const& filename, bool validate_features, bool verbose)
{ {
using box_type = typename T::value_type::first_type; using box_type = typename T::value_type::first_type;
box_type extent; box_type extent;
#if defined(MAPNIK_MEMORY_MAPPED_FILE) #if defined(MAPNIK_MEMORY_MAPPED_FILE)
mapnik::mapped_region_ptr mapped_region; mapnik::mapped_region_ptr mapped_region;
boost::optional<mapnik::mapped_region_ptr> memory = boost::optional<mapnik::mapped_region_ptr> memory = mapnik::mapped_memory_cache::instance().find(filename, true);
mapnik::mapped_memory_cache::instance().find(filename, true);
if (!memory) if (!memory)
{ {
std::clog << "Error : cannot memory map " << filename << std::endl; std::clog << "Error : cannot memory map " << filename << std::endl;
@ -269,17 +280,16 @@ std::pair<bool,typename T::value_type::first_type> process_geojson_file_x3(T & b
try try
{ {
mapnik::json::extract_bounding_boxes(itr, end, boxes); mapnik::json::extract_bounding_boxes(itr, end, boxes);
} } catch (boost::spirit::x3::expectation_failure<base_iterator_type> const& ex)
catch (boost::spirit::x3::expectation_failure<base_iterator_type> const& ex)
{ {
std::clog << ex.what() << std::endl; std::clog << ex.what() << std::endl;
std::clog << "Expected: " << ex.which(); std::clog << "Expected: " << ex.which();
std::clog << " Got: \"" << std::string(ex.where(), ex.where() + 200) << '"' << std::endl; std::clog << " Got: \"" << std::string(ex.where(), ex.where() + 200) << '"' << std::endl;
return std::make_pair(false, extent); return std::make_pair(false, extent);
} } catch (std::exception const& ex)
catch (std::exception const& ex)
{ {
std::clog << "mapnik-index (GeoJSON) : could not extract bounding boxes from : '" << filename << "'" << std::endl; std::clog << "mapnik-index (GeoJSON) : could not extract bounding boxes from : '" << filename << "'"
<< std::endl;
return std::make_pair(false, extent); return std::make_pair(false, extent);
} }
@ -287,18 +297,18 @@ std::pair<bool,typename T::value_type::first_type> process_geojson_file_x3(T & b
using space_type = mapnik::json::grammar::space_type; using space_type = mapnik::json::grammar::space_type;
auto keys = mapnik::json::get_keys(); auto keys = mapnik::json::get_keys();
#if BOOST_VERSION >= 106700 #if BOOST_VERSION >= 106700
auto feature_grammar = x3::with<mapnik::json::grammar::keys_tag>(keys) auto feature_grammar = x3::with<mapnik::json::grammar::keys_tag>(keys)[geojson_value];
[ geojson_value ];
#else #else
auto feature_grammar = x3::with<mapnik::json::grammar::keys_tag>(std::ref(keys)) auto feature_grammar = x3::with<mapnik::json::grammar::keys_tag>(std::ref(keys))[geojson_value];
[ geojson_value ];
#endif #endif
for (auto const& item : boxes) for (auto const& item : boxes)
{ {
if (item.first.valid()) if (item.first.valid())
{ {
if (!extent.valid()) extent = item.first; if (!extent.valid())
else extent.expand_to_include(item.first); extent = item.first;
else
extent.expand_to_include(item.first);
if (validate_features) if (validate_features)
{ {
base_iterator_type feat_itr = start + item.second.first; base_iterator_type feat_itr = start + item.second.first;
@ -309,36 +319,43 @@ std::pair<bool,typename T::value_type::first_type> process_geojson_file_x3(T & b
bool result = x3::phrase_parse(feat_itr, feat_end, feature_grammar, space_type(), feature_value); bool result = x3::phrase_parse(feat_itr, feat_end, feature_grammar, space_type(), feature_value);
if (!result || feat_itr != feat_end) if (!result || feat_itr != feat_end)
{ {
if (verbose) std::clog << "Failed to parse: offset=" << item.second.first << " size=" << item.second.second << std::endl; if (verbose)
std::clog << "Failed to parse: offset=" << item.second.first
<< " size=" << item.second.second << std::endl;
return std::make_pair(false, extent); return std::make_pair(false, extent);
} }
} } catch (x3::expectation_failure<std::string::const_iterator> const& ex)
catch (x3::expectation_failure<std::string::const_iterator> const& ex)
{ {
if (verbose) std::clog << ex.what() << std::endl; if (verbose)
std::clog << ex.what() << std::endl;
return std::make_pair(false, extent); return std::make_pair(false, extent);
} } catch (...)
catch (...)
{ {
if (verbose) std::clog << "Failed to parse: offset=" << item.second.first << " size=" << item.second.second << std::endl; if (verbose)
std::clog << "Failed to parse: offset=" << item.second.first << " size=" << item.second.second
<< std::endl;
return std::make_pair(false, extent); return std::make_pair(false, extent);
} }
if (!validate_geojson_feature(feature_value, keys, verbose)) if (!validate_geojson_feature(feature_value, keys, verbose))
{ {
if (verbose) std::clog << "Failed to validate: [" << std::string(start + item.second.first, feat_end ) << "]" << std::endl; if (verbose)
std::clog << "Failed to validate: [" << std::string(start + item.second.first, feat_end) << "]"
<< std::endl;
return std::make_pair(false, extent); return std::make_pair(false, extent);
} }
} }
} }
else if (validate_features) else if (validate_features)
{ {
if (verbose) std::clog << "Invalid bbox encountered " << item.first << std::endl; if (verbose)
std::clog << "Invalid bbox encountered " << item.first << std::endl;
return std::make_pair(false, extent); return std::make_pair(false, extent);
} }
} }
return std::make_pair(true, extent); return std::make_pair(true, extent);
} }
template std::pair<bool,box_type> process_geojson_file_x3(boxes_type&, std::string const&, bool, bool); template std::pair<bool, box_type> process_geojson_file_x3(boxes_type&, std::string const&, bool, bool);
}} } // namespace detail
} // namespace mapnik

View file

@ -26,11 +26,14 @@
#include <utility> #include <utility>
#include <string> #include <string>
namespace mapnik { namespace detail { namespace mapnik {
namespace detail {
template <typename T> template<typename T>
std::pair<bool, typename T::value_type::first_type> process_geojson_file_x3(T & boxes, std::string const& filename, bool validate_features, bool verbose); std::pair<bool, typename T::value_type::first_type>
process_geojson_file_x3(T& boxes, std::string const& filename, bool validate_features, bool verbose);
}} }
} // namespace mapnik
#endif // MAPNIK_UTILS_PROCESS_GEOJSON_FILE_X3_HPP #endif // MAPNIK_UTILS_PROCESS_GEOJSON_FILE_X3_HPP

View file

@ -17,7 +17,7 @@ MAPNIK_DISABLE_WARNING_POP
#include <string> #include <string>
int main (int argc,char** argv) int main(int argc, char** argv)
{ {
namespace po = boost::program_options; namespace po = boost::program_options;
@ -36,6 +36,7 @@ int main (int argc,char** argv)
try try
{ {
po::options_description desc("mapnik-render utility"); po::options_description desc("mapnik-render utility");
// clang-format off
desc.add_options() desc.add_options()
("help,h", "produce usage message") ("help,h", "produce usage message")
("version,V","print version string") ("version,V","print version string")
@ -48,17 +49,17 @@ int main (int argc,char** argv)
("map-height",po::value<int>(),"map height in pixels") ("map-height",po::value<int>(),"map height in pixels")
("variables","make map parameters available as render-time variables") ("variables","make map parameters available as render-time variables")
; ;
// clang-format on
po::positional_options_description p; po::positional_options_description p;
p.add("xml",1); p.add("xml", 1);
p.add("img",1); p.add("img", 1);
po::variables_map vm; po::variables_map vm;
po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm); po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
po::notify(vm); po::notify(vm);
if (vm.count("version")) if (vm.count("version"))
{ {
std::clog <<"version " << MAPNIK_VERSION_STRING << std::endl; std::clog << "version " << MAPNIK_VERSION_STRING << std::endl;
return 1; return 1;
} }
@ -80,7 +81,7 @@ int main (int argc,char** argv)
if (vm.count("xml")) if (vm.count("xml"))
{ {
xml_file=vm["xml"].as<std::string>(); xml_file = vm["xml"].as<std::string>();
} }
else else
{ {
@ -90,7 +91,7 @@ int main (int argc,char** argv)
if (vm.count("img")) if (vm.count("img"))
{ {
img_file=vm["img"].as<std::string>(); img_file = vm["img"].as<std::string>();
} }
else else
{ {
@ -100,7 +101,7 @@ int main (int argc,char** argv)
if (vm.count("scale-factor")) if (vm.count("scale-factor"))
{ {
scale_factor=vm["scale-factor"].as<double>(); scale_factor = vm["scale-factor"].as<double>();
} }
if (vm.count("variables")) if (vm.count("variables"))
@ -108,21 +109,23 @@ int main (int argc,char** argv)
params_as_variables = true; params_as_variables = true;
} }
if (vm.count("map-width")) { if (vm.count("map-width"))
map_width = vm["map-width"].as<int>(); {
map_width = vm["map-width"].as<int>();
} }
if (vm.count("map-height")) { if (vm.count("map-height"))
map_height = vm["map-height"].as<int>(); {
map_height = vm["map-height"].as<int>();
} }
mapnik::datasource_cache::instance().register_datasources("./plugins/input/"); mapnik::datasource_cache::instance().register_datasources("./plugins/input/");
mapnik::freetype_engine::register_fonts("./fonts",true); mapnik::freetype_engine::register_fonts("./fonts", true);
mapnik::Map map(map_width,map_height); mapnik::Map map(map_width, map_height);
mapnik::load_map(map,xml_file,true); mapnik::load_map(map, xml_file, true);
map.zoom_all(); map.zoom_all();
mapnik::image_rgba8 im(map.width(),map.height()); mapnik::image_rgba8 im(map.width(), map.height());
mapnik::request req(map.width(),map.height(),map.get_current_extent()); mapnik::request req(map.width(), map.height(), map.get_current_extent());
req.set_buffer_size(map.buffer_size()); req.set_buffer_size(map.buffer_size());
mapnik::attributes vars; mapnik::attributes vars;
if (params_as_variables) if (params_as_variables)
@ -148,9 +151,9 @@ int main (int argc,char** argv)
} }
} }
} }
mapnik::agg_renderer<mapnik::image_rgba8> ren(map,req,vars,im,scale_factor,0,0); mapnik::agg_renderer<mapnik::image_rgba8> ren(map, req, vars, im, scale_factor, 0, 0);
ren.apply(); ren.apply();
mapnik::save_to_file(im,img_file); mapnik::save_to_file(im, img_file);
if (auto_open) if (auto_open)
{ {
std::ostringstream s; std::ostringstream s;
@ -170,8 +173,7 @@ int main (int argc,char** argv)
{ {
std::clog << "rendered to: " << img_file << "\n"; std::clog << "rendered to: " << img_file << "\n";
} }
} } catch (std::exception const& ex)
catch (std::exception const& ex)
{ {
std::clog << "Error " << ex.what() << std::endl; std::clog << "Error " << ex.what() << std::endl;
return -1; return -1;

View file

@ -20,7 +20,6 @@
* *
*****************************************************************************/ *****************************************************************************/
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <string> #include <string>
@ -45,25 +44,26 @@ using mapnik::datasource_exception;
const int MAXDEPTH = 64; const int MAXDEPTH = 64;
const int DEFAULT_DEPTH = 8; const int DEFAULT_DEPTH = 8;
const double MINRATIO=0.5; const double MINRATIO = 0.5;
const double MAXRATIO=0.8; const double MAXRATIO = 0.8;
const double DEFAULT_RATIO=0.55; const double DEFAULT_RATIO = 0.55;
int main (int argc,char** argv) int main(int argc, char** argv)
{ {
using namespace mapnik; using namespace mapnik;
namespace po = boost::program_options; namespace po = boost::program_options;
using std::string; using std::string;
using std::vector; using std::vector;
bool verbose=false; bool verbose = false;
unsigned int depth=DEFAULT_DEPTH; unsigned int depth = DEFAULT_DEPTH;
double ratio=DEFAULT_RATIO; double ratio = DEFAULT_RATIO;
vector<string> ogr_files; vector<string> ogr_files;
try try
{ {
po::options_description desc("ogrindex utility"); po::options_description desc("ogrindex utility");
// clang-format off
desc.add_options() desc.add_options()
("help,h", "produce usage message") ("help,h", "produce usage message")
("version,V", "print version string") ("version,V", "print version string")
@ -72,16 +72,16 @@ int main (int argc,char** argv)
("ratio,r", po::value<double>(), "split ratio (default 0.55)") ("ratio,r", po::value<double>(), "split ratio (default 0.55)")
("ogr_files", po::value<vector<string> >(), "ogr supported files to index: file1 file2 ...fileN") ("ogr_files", po::value<vector<string> >(), "ogr supported files to index: file1 file2 ...fileN")
; ;
// clang-format on
po::positional_options_description p; po::positional_options_description p;
p.add("ogr_files",-1); p.add("ogr_files", -1);
po::variables_map vm; po::variables_map vm;
po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm); po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
po::notify(vm); po::notify(vm);
if (vm.count("version")) if (vm.count("version"))
{ {
std::clog<<"version 0.1.0" <<std::endl; std::clog << "version 0.1.0" << std::endl;
return 1; return 1;
} }
if (vm.count("help")) if (vm.count("help"))
@ -99,10 +99,9 @@ int main (int argc,char** argv)
} }
if (vm.count("ogr_files")) if (vm.count("ogr_files"))
{ {
ogr_files=vm["ogr_files"].as< vector<string> >(); ogr_files = vm["ogr_files"].as<vector<string>>();
} }
} } catch (...)
catch (...)
{ {
std::clog << "Exception of unknown type!" << std::endl; std::clog << "Exception of unknown type!" << std::endl;
return -1; return -1;
@ -121,9 +120,9 @@ int main (int argc,char** argv)
{ {
std::clog << "processing " << *itr << std::endl; std::clog << "processing " << *itr << std::endl;
std::string ogrname (*itr++); std::string ogrname(*itr++);
if (! mapnik::util::exists (ogrname)) if (!mapnik::util::exists(ogrname))
{ {
std::clog << "error : file " << ogrname << " doesn't exists" << std::endl; std::clog << "error : file " << ogrname << " doesn't exists" << std::endl;
continue; continue;
@ -131,11 +130,12 @@ int main (int argc,char** argv)
// TODO - layer names don't match dataset name, so this will break for // TODO - layer names don't match dataset name, so this will break for
// any layer types of ogr than shapefiles, etc // any layer types of ogr than shapefiles, etc
size_t breakpoint = ogrname.find_last_of ("."); size_t breakpoint = ogrname.find_last_of(".");
if (breakpoint == string::npos) breakpoint = ogrname.length(); if (breakpoint == string::npos)
std::string ogrlayername (ogrname.substr(0, breakpoint)); breakpoint = ogrname.length();
std::string ogrlayername(ogrname.substr(0, breakpoint));
if (mapnik::util::exists (ogrlayername + ".ogrindex")) if (mapnik::util::exists(ogrlayername + ".ogrindex"))
{ {
std::clog << "error : " << ogrlayername << ".ogrindex file already exists for " << ogrname << std::endl; std::clog << "error : " << ogrlayername << ".ogrindex file already exists for " << ogrname << std::endl;
continue; continue;
@ -144,24 +144,23 @@ int main (int argc,char** argv)
mapnik::parameters params; mapnik::parameters params;
params["type"] = "ogr"; params["type"] = "ogr";
params["file"] = ogrname; params["file"] = ogrname;
//unsigned first = 0; // unsigned first = 0;
params["layer_by_index"] = 0;//ogrlayername; params["layer_by_index"] = 0; // ogrlayername;
try try
{ {
ogr_datasource ogr (params); ogr_datasource ogr(params);
box2d<double> extent = ogr.envelope(); box2d<double> extent = ogr.envelope();
quadtree<int> tree (extent, depth, ratio); quadtree<int> tree(extent, depth, ratio);
int count=0; int count = 0;
std::clog << "file:" << ogrname << std::endl; std::clog << "file:" << ogrname << std::endl;
std::clog << "layer:" << ogrlayername << std::endl; std::clog << "layer:" << ogrlayername << std::endl;
std::clog << "extent:" << extent << std::endl; std::clog << "extent:" << extent << std::endl;
mapnik::query q (extent, 1.0); mapnik::query q(extent, 1.0);
mapnik::featureset_ptr itr = ogr.features (q); mapnik::featureset_ptr itr = ogr.features(q);
while (true) while (true)
{ {
@ -173,8 +172,9 @@ int main (int argc,char** argv)
box2d<double> item_ext = fp->envelope(); box2d<double> item_ext = fp->envelope();
tree.insert (count, item_ext); tree.insert(count, item_ext);
if (verbose) { if (verbose)
{
std::clog << "record number " << (count + 1) << " box=" << item_ext << std::endl; std::clog << "record number " << (count + 1) << " box=" << item_ext << std::endl;
} }
@ -183,14 +183,17 @@ int main (int argc,char** argv)
std::clog << " number shapes=" << count << std::endl; std::clog << " number shapes=" << count << std::endl;
std::fstream file((ogrlayername+".ogrindex").c_str(), std::fstream file((ogrlayername + ".ogrindex").c_str(),
std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary); std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary);
if (!file) { if (!file)
std::clog << "cannot open ogrindex file for writing file \"" {
<< (ogrlayername+".ogrindex") << "\"" << std::endl; std::clog << "cannot open ogrindex file for writing file \"" << (ogrlayername + ".ogrindex") << "\""
} else { << std::endl;
}
else
{
tree.trim(); tree.trim();
std::clog<<" number nodes="<<tree.count()<<std::endl; std::clog << " number nodes=" << tree.count() << std::endl;
file.exceptions(std::ios::failbit | std::ios::badbit); file.exceptions(std::ios::failbit | std::ios::badbit);
tree.write(file); tree.write(file);
file.flush(); file.flush();
@ -198,7 +201,7 @@ int main (int argc,char** argv)
} }
} }
// catch problem at the datasource creation // catch problem at the datasource creation
catch (const mapnik::datasource_exception & ex ) catch (const mapnik::datasource_exception& ex)
{ {
std::clog << ex.what() << "\n"; std::clog << ex.what() << "\n";
return -1; return -1;
@ -206,10 +209,10 @@ int main (int argc,char** argv)
catch (...) catch (...)
{ {
std::clog << "unknown exception..." << "\n"; std::clog << "unknown exception..."
<< "\n";
return -1; return -1;
} }
} }
std::clog << "done!" << std::endl; std::clog << "done!" << std::endl;

View file

@ -35,20 +35,20 @@ MAPNIK_DISABLE_WARNING_POP
#include <memory> #include <memory>
//stl // stl
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <exception> #include <exception>
int main ( int argc, char** argv) int main(int argc, char** argv)
{ {
namespace po = boost::program_options; namespace po = boost::program_options;
po::options_description desc("Postgresql/PostGIS to SQLite3 converter\n Options"); po::options_description desc("Postgresql/PostGIS to SQLite3 converter\n Options");
std::string usage = "usage: pgsql2sqlite --dbname db --table planet_osm_line --file osm.sqlite --query \"select * from planet_osm_line\""; std::string usage = "usage: pgsql2sqlite --dbname db --table planet_osm_line --file osm.sqlite --query \"select * "
"from planet_osm_line\"";
try try
{ {
// clang-format off
desc.add_options() desc.add_options()
("help,?","Display this help screen.") ("help,?","Display this help screen.")
("host,h",po::value<std::string>(),"Allows you to specify connection to a database on a machine other than the default.") ("host,h",po::value<std::string>(),"Allows you to specify connection to a database on a machine other than the default.")
@ -61,13 +61,13 @@ int main ( int argc, char** argv)
("file,f",po::value<std::string>(),"Use this option to specify the name of the file to create.") ("file,f",po::value<std::string>(),"Use this option to specify the name of the file to create.")
; ;
// clang-format on
//po::positional_options_description p; // po::positional_options_description p;
//p.add("table",1); // p.add("table",1);
po::variables_map vm; po::variables_map vm;
//positional(p) // positional(p)
po::store(po::command_line_parser(argc,argv).options(desc).run(),vm); po::store(po::command_line_parser(argc, argv).options(desc).run(), vm);
po::notify(vm); po::notify(vm);
if (vm.count("help")) if (vm.count("help"))
@ -76,7 +76,7 @@ int main ( int argc, char** argv)
std::cout << usage << "\n"; std::cout << usage << "\n";
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
else if ( !vm.count("dbname") || !vm.count("file") || !vm.count("query") ) else if (!vm.count("dbname") || !vm.count("file") || !vm.count("query"))
{ {
std::cout << desc << "\n"; std::cout << desc << "\n";
std::cout << usage << "\n"; std::cout << usage << "\n";
@ -98,20 +98,20 @@ int main ( int argc, char** argv)
std::shared_ptr<Connection> conn(creator()); std::shared_ptr<Connection> conn(creator());
std::string query = vm["query"].as<std::string>(); std::string query = vm["query"].as<std::string>();
std::string output_table_name = vm.count("table") ? vm["table"].as<std::string>() : mapnik::sql_utils::table_from_sql(query); std::string output_table_name =
vm.count("table") ? vm["table"].as<std::string>() : mapnik::sql_utils::table_from_sql(query);
std::string output_file = vm["file"].as<std::string>(); std::string output_file = vm["file"].as<std::string>();
std::cout << "output_table : " << output_table_name << "\n"; std::cout << "output_table : " << output_table_name << "\n";
mapnik::pgsql2sqlite(conn,query,output_table_name,output_file); mapnik::pgsql2sqlite(conn, query, output_table_name, output_file);
} } catch (mapnik::datasource_exception& ex)
catch (mapnik::datasource_exception & ex)
{ {
std::cerr << ex.what() << "\n"; std::cerr << ex.what() << "\n";
return EXIT_FAILURE; return EXIT_FAILURE;
} }
} } catch (std::exception& e)
catch(std::exception& e) { {
std::cerr << desc << "\n"; std::cerr << desc << "\n";
std::cout << usage << "\n"; std::cout << usage << "\n";
std::cerr << e.what() << "\n"; std::cerr << e.what() << "\n";

View file

@ -41,7 +41,7 @@ MAPNIK_DISABLE_WARNING_PUSH
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
MAPNIK_DISABLE_WARNING_POP MAPNIK_DISABLE_WARNING_POP
//st // st
#include <cstdint> #include <cstdint>
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
@ -50,21 +50,22 @@ MAPNIK_DISABLE_WARNING_POP
static std::string numeric2string(const char* buf) static std::string numeric2string(const char* buf)
{ {
std::int16_t ndigits = int2net(buf); std::int16_t ndigits = int2net(buf);
std::int16_t weight = int2net(buf+2); std::int16_t weight = int2net(buf + 2);
std::int16_t sign = int2net(buf+4); std::int16_t sign = int2net(buf + 4);
std::int16_t dscale = int2net(buf+6); std::int16_t dscale = int2net(buf + 6);
const std::unique_ptr<std::int16_t[]> digits(new std::int16_t[ndigits]); const std::unique_ptr<std::int16_t[]> digits(new std::int16_t[ndigits]);
for (int n=0; n < ndigits ;++n) for (int n = 0; n < ndigits; ++n)
{ {
digits[n] = int2net(buf+8+n*2); digits[n] = int2net(buf + 8 + n * 2);
} }
std::ostringstream ss; std::ostringstream ss;
if (sign == 0x4000) ss << "-"; if (sign == 0x4000)
ss << "-";
int i = std::max(weight,std::int16_t(0)); int i = std::max(weight, std::int16_t(0));
int d = 0; int d = 0;
// Each numeric "digit" is actually a value between 0000 and 9999 stored in a 16 bit field. // Each numeric "digit" is actually a value between 0000 and 9999 stored in a 16 bit field.
@ -72,7 +73,7 @@ static std::string numeric2string(const char* buf)
// Note that the last two digits show that the leading 0's are lost when the number is split. // Note that the last two digits show that the leading 0's are lost when the number is split.
// We must be careful to re-insert these 0's when building the string. // We must be careful to re-insert these 0's when building the string.
while ( i >= 0) while (i >= 0)
{ {
if (i <= weight && d < ndigits) if (i <= weight && d < ndigits)
{ {
@ -87,24 +88,24 @@ static std::string numeric2string(const char* buf)
} }
else if (dig < 100) else if (dig < 100)
{ {
ss << "00"; // 0010 - 0099 ss << "00"; // 0010 - 0099
} }
else else
{ {
ss << "0"; // 0100 - 0999; ss << "0"; // 0100 - 0999;
} }
#else #else
switch(digits[d]) switch (digits[d])
{ {
case 0 ... 9: case 0 ... 9:
ss << "000"; // 0000 - 0009 ss << "000"; // 0000 - 0009
break; break;
case 10 ... 99: case 10 ... 99:
ss << "00"; // 0010 - 0099 ss << "00"; // 0010 - 0099
break; break;
case 100 ... 999: case 100 ... 999:
ss << "0"; // 0100 - 0999 ss << "0"; // 0100 - 0999
break; break;
} }
#endif #endif
} }
@ -113,9 +114,9 @@ static std::string numeric2string(const char* buf)
else else
{ {
if (d == 0) if (d == 0)
ss << "0"; ss << "0";
else else
ss << "0000"; ss << "0000";
} }
i--; i--;
@ -133,22 +134,26 @@ static std::string numeric2string(const char* buf)
value = 0; value = 0;
// Output up to 4 decimal digits for this value // Output up to 4 decimal digits for this value
if (dscale > 0) { if (dscale > 0)
{
ss << (value / 1000); ss << (value / 1000);
value %= 1000; value %= 1000;
dscale--; dscale--;
} }
if (dscale > 0) { if (dscale > 0)
{
ss << (value / 100); ss << (value / 100);
value %= 100; value %= 100;
dscale--; dscale--;
} }
if (dscale > 0) { if (dscale > 0)
{
ss << (value / 10); ss << (value / 10);
value %= 10; value %= 10;
dscale--; dscale--;
} }
if (dscale > 0) { if (dscale > 0)
{
ss << value; ss << value;
dscale--; dscale--;
} }
@ -159,10 +164,9 @@ static std::string numeric2string(const char* buf)
return ss.str(); return ss.str();
} }
namespace mapnik { namespace mapnik {
template <typename Connection> template<typename Connection>
void pgsql2sqlite(Connection conn, void pgsql2sqlite(Connection conn,
std::string const& query, std::string const& query,
std::string const& output_table_name, std::string const& output_table_name,
@ -178,26 +182,27 @@ void pgsql2sqlite(Connection conn,
select_sql << "select "; select_sql << "select ";
for (int i=0; i<count; ++i) for (int i = 0; i < count; ++i)
{ {
if (i!=0) select_sql << ","; if (i != 0)
select_sql << "\"" << rs->getFieldName(i) << "\""; select_sql << ",";
select_sql << "\"" << rs->getFieldName(i) << "\"";
} }
select_sql << " from (" << query << ") as query"; select_sql << " from (" << query << ") as query";
std::string table_name = mapnik::sql_utils::table_from_sql(query); std::string table_name = mapnik::sql_utils::table_from_sql(query);
std::string schema_name=""; std::string schema_name = "";
std::string::size_type idx=table_name.find_last_of('.'); std::string::size_type idx = table_name.find_last_of('.');
if (idx!=std::string::npos) if (idx != std::string::npos)
{ {
schema_name=table_name.substr(0,idx); schema_name = table_name.substr(0, idx);
table_name=table_name.substr(idx+1); table_name = table_name.substr(idx + 1);
} }
else else
{ {
table_name=table_name.substr(0); table_name = table_name.substr(0);
} }
std::ostringstream geom_col_sql; std::ostringstream geom_col_sql;
@ -205,7 +210,7 @@ void pgsql2sqlite(Connection conn,
geom_col_sql << "where f_table_name='" << table_name << "'"; geom_col_sql << "where f_table_name='" << table_name << "'";
if (schema_name.length() > 0) if (schema_name.length() > 0)
{ {
geom_col_sql <<" and f_table_schema='"<< schema_name <<"'"; geom_col_sql << " and f_table_schema='" << schema_name << "'";
} }
rs = conn->executeQuery(geom_col_sql.str()); rs = conn->executeQuery(geom_col_sql.str());
@ -214,9 +219,9 @@ void pgsql2sqlite(Connection conn,
std::string geom_col = "UNKNOWN"; std::string geom_col = "UNKNOWN";
std::string geom_type = "UNKNOWN"; std::string geom_type = "UNKNOWN";
if ( rs->next()) if (rs->next())
{ {
if (!mapnik::util::string2int(rs->getValue("srid"),srid)) if (!mapnik::util::string2int(rs->getValue("srid"), srid))
{ {
std::clog << "could not convert srid to integer\n"; std::clog << "could not convert srid to integer\n";
} }
@ -226,7 +231,9 @@ void pgsql2sqlite(Connection conn,
// add AsBinary(<geometry_column>) modifier // add AsBinary(<geometry_column>) modifier
std::string select_sql_str = select_sql.str(); std::string select_sql_str = select_sql.str();
boost::algorithm::replace_all(select_sql_str, "\"" + geom_col + "\"","ST_AsBinary(" + geom_col+") as " + geom_col); boost::algorithm::replace_all(select_sql_str,
"\"" + geom_col + "\"",
"ST_AsBinary(" + geom_col + ") as " + geom_col);
#ifdef MAPNIK_DEBUG #ifdef MAPNIK_DEBUG
std::cout << select_sql_str << "\n"; std::cout << select_sql_str << "\n";
@ -235,19 +242,22 @@ void pgsql2sqlite(Connection conn,
std::ostringstream cursor_sql; std::ostringstream cursor_sql;
std::string cursor_name("my_cursor"); std::string cursor_name("my_cursor");
cursor_sql << "DECLARE " << cursor_name << " BINARY INSENSITIVE NO SCROLL CURSOR WITH HOLD FOR " << select_sql_str << " FOR READ ONLY"; cursor_sql << "DECLARE " << cursor_name << " BINARY INSENSITIVE NO SCROLL CURSOR WITH HOLD FOR " << select_sql_str
<< " FOR READ ONLY";
conn->execute(cursor_sql.str()); conn->execute(cursor_sql.str());
std::shared_ptr<CursorResultSet> cursor(new CursorResultSet(conn,cursor_name,10000)); std::shared_ptr<CursorResultSet> cursor(new CursorResultSet(conn, cursor_name, 10000));
unsigned num_fields = cursor->getNumFields(); unsigned num_fields = cursor->getNumFields();
if (num_fields == 0) return; if (num_fields == 0)
return;
std::string feature_id = "fid"; std::string feature_id = "fid";
std::ostringstream create_sql; std::ostringstream create_sql;
create_sql << "create table if not exists " << output_table_name << " (" << feature_id << " INTEGER PRIMARY KEY AUTOINCREMENT,"; create_sql << "create table if not exists " << output_table_name << " (" << feature_id
<< " INTEGER PRIMARY KEY AUTOINCREMENT,";
int geometry_oid = -1; int geometry_oid = -1;
@ -255,7 +265,7 @@ void pgsql2sqlite(Connection conn,
context_ptr ctx = std::make_shared<context_type>(); context_ptr ctx = std::make_shared<context_type>();
for ( unsigned pos = 0; pos < num_fields ; ++pos) for (unsigned pos = 0; pos < num_fields; ++pos)
{ {
const char* field_name = cursor->getFieldName(pos); const char* field_name = cursor->getFieldName(pos);
ctx->push(field_name); ctx->push(field_name);
@ -264,7 +274,7 @@ void pgsql2sqlite(Connection conn,
{ {
create_sql << ","; create_sql << ",";
} }
output_table_insert_sql +=",?"; output_table_insert_sql += ",?";
int oid = cursor->getTypeOID(pos); int oid = cursor->getTypeOID(pos);
if (geom_col == cursor->getFieldName(pos)) if (geom_col == cursor->getFieldName(pos))
{ {
@ -276,54 +286,52 @@ void pgsql2sqlite(Connection conn,
create_sql << "'" << cursor->getFieldName(pos); create_sql << "'" << cursor->getFieldName(pos);
switch (oid) switch (oid)
{ {
case 20: case 20:
case 21: case 21:
case 23: case 23:
create_sql << "' INTEGER"; create_sql << "' INTEGER";
break; break;
case 700: case 700:
case 701: case 701:
create_sql << "' REAL"; create_sql << "' REAL";
break; break;
default: default:
create_sql << "' TEXT"; create_sql << "' TEXT";
break; break;
} }
} }
} }
create_sql << ");"; create_sql << ");";
output_table_insert_sql +=")"; output_table_insert_sql += ")";
std::cout << "client_encoding=" << conn->client_encoding() << "\n"; std::cout << "client_encoding=" << conn->client_encoding() << "\n";
std::cout << "geometry_column=" << geom_col << "(" << geom_type std::cout << "geometry_column=" << geom_col << "(" << geom_type << ") srid=" << srid << " oid=" << geometry_oid
<< ") srid=" << srid << " oid=" << geometry_oid << "\n"; << "\n";
db.execute("begin;"); db.execute("begin;");
// output table sql // output table sql
db.execute(create_sql.str()); db.execute(create_sql.str());
// spatial index sql // spatial index sql
std::string spatial_index_sql = "create virtual table idx_" + output_table_name std::string spatial_index_sql =
+ "_" + geom_col + " using rtree(pkid, xmin, xmax, ymin, ymax)"; "create virtual table idx_" + output_table_name + "_" + geom_col + " using rtree(pkid, xmin, xmax, ymin, ymax)";
db.execute(spatial_index_sql); db.execute(spatial_index_sql);
//blob_to_hex hex; // blob_to_hex hex;
int pkid = 0; int pkid = 0;
std::string spatial_index_insert_sql = "insert into idx_" + output_table_name + "_" std::string spatial_index_insert_sql =
+ geom_col + " values (?,?,?,?,?)" ; "insert into idx_" + output_table_name + "_" + geom_col + " values (?,?,?,?,?)";
sqlite::prepared_statement spatial_index(db,spatial_index_insert_sql); sqlite::prepared_statement spatial_index(db, spatial_index_insert_sql);
#ifdef MAPNIK_DEBUG #ifdef MAPNIK_DEBUG
std::cout << output_table_insert_sql << "\n"; std::cout << output_table_insert_sql << "\n";
#endif #endif
sqlite::prepared_statement output_table(db,output_table_insert_sql); sqlite::prepared_statement output_table(db, output_table_insert_sql);
while (cursor->next()) while (cursor->next())
{ {
@ -332,86 +340,81 @@ void pgsql2sqlite(Connection conn,
sqlite::record_type output_rec; sqlite::record_type output_rec;
output_rec.push_back(sqlite::value_type(pkid)); output_rec.push_back(sqlite::value_type(pkid));
bool empty_geom = true; bool empty_geom = true;
const char * buf = 0; const char* buf = 0;
for (unsigned pos=0 ; pos < num_fields; ++pos) for (unsigned pos = 0; pos < num_fields; ++pos)
{ {
if (! cursor->isNull(pos)) if (!cursor->isNull(pos))
{ {
int size=cursor->getFieldLength(pos); int size = cursor->getFieldLength(pos);
int oid = cursor->getTypeOID(pos); int oid = cursor->getTypeOID(pos);
buf=cursor->getValue(pos); buf = cursor->getValue(pos);
switch (oid) switch (oid)
{ {
case 25: case 25:
case 1042: case 1042:
case 1043: case 1043: {
{ std::string text(buf);
std::string text(buf); boost::algorithm::replace_all(text, "'", "''");
boost::algorithm::replace_all(text,"'","''"); output_rec.push_back(sqlite::value_type(text));
output_rec.push_back(sqlite::value_type(text)); break;
break; }
} case 23:
case 23: output_rec.emplace_back(int4net(buf));
output_rec.emplace_back(int4net(buf)); break;
break; case 21:
case 21: output_rec.emplace_back(int(int2net(buf)));
output_rec.emplace_back(int(int2net(buf))); break;
break; case 700: {
case 700: float val;
{ float4net(val, buf);
float val; output_rec.emplace_back(double(val));
float4net(val,buf); break;
output_rec.emplace_back(double(val)); }
break; case 701: {
} double val;
case 701: float8net(val, buf);
{
double val;
float8net(val,buf);
output_rec.emplace_back(val);
break;
}
case 1700:
{
std::string str = numeric2string(buf);
double val;
if (mapnik::util::string2double(str,val))
{
output_rec.emplace_back(val); output_rec.emplace_back(val);
break;
} }
break; case 1700: {
} std::string str = numeric2string(buf);
double val;
default: if (mapnik::util::string2double(str, val))
{
if (oid == geometry_oid)
{
mapnik::feature_impl feat(ctx,pkid);
mapnik::geometry::geometry<double> geom = geometry_utils::from_wkb(buf, size, wkbGeneric);
if (!mapnik::geometry::is_empty(geom))
{ {
box2d<double> bbox = mapnik::geometry::envelope(geom); output_rec.emplace_back(val);
if (bbox.valid())
{
sqlite::record_type rec;
rec.push_back(sqlite::value_type(pkid));
rec.push_back(sqlite::value_type(bbox.minx()));
rec.push_back(sqlite::value_type(bbox.maxx()));
rec.push_back(sqlite::value_type(bbox.miny()));
rec.push_back(sqlite::value_type(bbox.maxy()));
spatial_index.insert_record(rec);
empty_geom = false;
}
} }
output_rec.push_back(sqlite::blob(buf,size)); break;
} }
else
{ default: {
output_rec.push_back(sqlite::null_type()); if (oid == geometry_oid)
{
mapnik::feature_impl feat(ctx, pkid);
mapnik::geometry::geometry<double> geom = geometry_utils::from_wkb(buf, size, wkbGeneric);
if (!mapnik::geometry::is_empty(geom))
{
box2d<double> bbox = mapnik::geometry::envelope(geom);
if (bbox.valid())
{
sqlite::record_type rec;
rec.push_back(sqlite::value_type(pkid));
rec.push_back(sqlite::value_type(bbox.minx()));
rec.push_back(sqlite::value_type(bbox.maxx()));
rec.push_back(sqlite::value_type(bbox.miny()));
rec.push_back(sqlite::value_type(bbox.maxy()));
spatial_index.insert_record(rec);
empty_geom = false;
}
}
output_rec.push_back(sqlite::blob(buf, size));
}
else
{
output_rec.push_back(sqlite::null_type());
}
break;
} }
break;
}
} }
} }
else else
@ -420,7 +423,8 @@ void pgsql2sqlite(Connection conn,
} }
} }
if (!empty_geom) output_table.insert_record(output_rec); if (!empty_geom)
output_table.insert_record(output_rec);
if (pkid % 1000 == 0) if (pkid % 1000 == 0)
{ {
@ -440,4 +444,4 @@ void pgsql2sqlite(Connection conn,
std::cout << "\r vacumming"; std::cout << "\r vacumming";
std::cout << "\n Done!" << std::endl; std::cout << "\n Done!" << std::endl;
} }
} } // namespace mapnik

View file

@ -22,37 +22,38 @@
#include "sqlite.hpp" #include "sqlite.hpp"
namespace mapnik { namespace sqlite { namespace mapnik {
namespace sqlite {
database::database(std::string const& name) database::database(std::string const& name)
{
sqlite3* db;
int res = sqlite3_open(name.c_str(), &db);
if (res)
{ {
sqlite3 *db; sqlite3_close(db);
int res = sqlite3_open(name.c_str(), &db); throw;
if (res) }
{
sqlite3_close(db);
throw;
}
db_ = sqlite_db(db,database_closer()); db_ = sqlite_db(db, database_closer());
#ifdef MAPNIK_DEBUG #ifdef MAPNIK_DEBUG
std::cerr << "Open database " << name << "\n"; std::cerr << "Open database " << name << "\n";
#endif #endif
}
database::~database() {}
bool database::execute(std::string const& sql)
{
char * err_msg;
int res = sqlite3_exec(db_.get(),sql.c_str(),0,0,&err_msg);
if (res != SQLITE_OK)
{
std::cerr << "SQL"<< sql << " ERR:" << err_msg << "\n";
sqlite3_free(err_msg);
return false;
}
return true;
}
}
} }
database::~database() {}
bool database::execute(std::string const& sql)
{
char* err_msg;
int res = sqlite3_exec(db_.get(), sql.c_str(), 0, 0, &err_msg);
if (res != SQLITE_OK)
{
std::cerr << "SQL" << sql << " ERR:" << err_msg << "\n";
sqlite3_free(err_msg);
return false;
}
return true;
}
} // namespace sqlite
} // namespace mapnik

View file

@ -31,7 +31,7 @@ MAPNIK_DISABLE_WARNING_PUSH
#include <sqlite3.h> #include <sqlite3.h>
MAPNIK_DISABLE_WARNING_POP MAPNIK_DISABLE_WARNING_POP
//stl // stl
#ifdef MAPNIK_DEBUG #ifdef MAPNIK_DEBUG
#include <cassert> #include <cassert>
#endif #endif
@ -40,154 +40,162 @@ MAPNIK_DISABLE_WARNING_POP
#include <string> #include <string>
#include <vector> #include <vector>
namespace mapnik { namespace sqlite { namespace mapnik {
namespace sqlite {
class database : private util::noncopyable class database : private util::noncopyable
{
friend class prepared_statement;
struct database_closer
{ {
friend class prepared_statement; void operator()(sqlite3* db)
struct database_closer
{
void operator () (sqlite3 * db)
{
#ifdef MAPNIK_DEBUG
std::cerr << "close database " << db << "\n";
#endif
sqlite3_close(db);
}
};
using sqlite_db = std::shared_ptr<sqlite3>;
sqlite_db db_;
public:
database(std::string const& name);
~database();
bool execute(std::string const& sql);
};
struct null_type {};
struct blob
{
blob(const char* buf, unsigned size)
: buf_(buf), size_(size) {}
const char * buf_;
unsigned size_;
};
using value_type = mapnik::util::variant<int,double,std::string, blob,null_type>;
using record_type = std::vector<value_type>;
class prepared_statement : util::noncopyable
{
struct binder
{
binder(sqlite3_stmt * stmt, unsigned index)
: stmt_(stmt), index_(index) {}
bool operator() (null_type )
{
if (sqlite3_bind_null(stmt_, index_) != SQLITE_OK)
{
std::cerr << "cannot bind nullptr\n";
return false;
}
return true;
}
bool operator() (int val)
{
if (sqlite3_bind_int(stmt_, index_ , val ) != SQLITE_OK)
{
std::cerr << "cannot bind " << val << "\n";
return false;
}
return true;
}
bool operator() (double val)
{
if (sqlite3_bind_double(stmt_, index_ , val ) != SQLITE_OK)
{
std::cerr << "cannot bind " << val << "\n";
return false;
}
return true;
}
bool operator() (std::string const& val)
{
if (sqlite3_bind_text(stmt_, index_, val.c_str(), val.length(), SQLITE_STATIC) != SQLITE_OK)
{
std::cerr << "cannot bind " << val << "\n";
return false;
}
return true;
}
bool operator() (blob const& val)
{
if (sqlite3_bind_blob(stmt_, index_, val.buf_, val.size_, SQLITE_STATIC) != SQLITE_OK)
{
std::cerr << "cannot bind BLOB\n";
return false;
}
return true;
}
sqlite3_stmt * stmt_;
unsigned index_;
};
public:
prepared_statement(database & db, std::string const& sql)
: db_(db.db_.get()), stmt_(0)
{
const char * tail;
//char * err_msg;
int res = sqlite3_prepare_v2(db_, sql.c_str(),-1, &stmt_,&tail);
if (res != SQLITE_OK)
{
std::cerr << "ERR:"<< res << "\n";
throw;
}
}
~prepared_statement()
{
int res = sqlite3_finalize(stmt_);
if (res != SQLITE_OK)
{
std::cerr << "ERR:" << res << "\n";
}
}
bool insert_record(record_type const& rec) const
{ {
#ifdef MAPNIK_DEBUG #ifdef MAPNIK_DEBUG
assert( unsigned(sqlite3_bind_parameter_count(stmt_)) == rec.size()); std::cerr << "close database " << db << "\n";
#endif #endif
record_type::const_iterator itr = rec.begin(); sqlite3_close(db);
record_type::const_iterator end = rec.end(); }
int count = 1; };
for (; itr!=end;++itr)
using sqlite_db = std::shared_ptr<sqlite3>;
sqlite_db db_;
public:
database(std::string const& name);
~database();
bool execute(std::string const& sql);
};
struct null_type
{};
struct blob
{
blob(const char* buf, unsigned size)
: buf_(buf)
, size_(size)
{}
const char* buf_;
unsigned size_;
};
using value_type = mapnik::util::variant<int, double, std::string, blob, null_type>;
using record_type = std::vector<value_type>;
class prepared_statement : util::noncopyable
{
struct binder
{
binder(sqlite3_stmt* stmt, unsigned index)
: stmt_(stmt)
, index_(index)
{}
bool operator()(null_type)
{
if (sqlite3_bind_null(stmt_, index_) != SQLITE_OK)
{ {
binder op(stmt_,count++); std::cerr << "cannot bind nullptr\n";
if (!util::apply_visitor(op,*itr)) return false;
{
return false;
}
} }
sqlite3_step(stmt_);
sqlite3_reset(stmt_);
return true; return true;
} }
private: bool operator()(int val)
sqlite3 * db_; {
sqlite3_stmt * stmt_; if (sqlite3_bind_int(stmt_, index_, val) != SQLITE_OK)
{
std::cerr << "cannot bind " << val << "\n";
return false;
}
return true;
}
bool operator()(double val)
{
if (sqlite3_bind_double(stmt_, index_, val) != SQLITE_OK)
{
std::cerr << "cannot bind " << val << "\n";
return false;
}
return true;
}
bool operator()(std::string const& val)
{
if (sqlite3_bind_text(stmt_, index_, val.c_str(), val.length(), SQLITE_STATIC) != SQLITE_OK)
{
std::cerr << "cannot bind " << val << "\n";
return false;
}
return true;
}
bool operator()(blob const& val)
{
if (sqlite3_bind_blob(stmt_, index_, val.buf_, val.size_, SQLITE_STATIC) != SQLITE_OK)
{
std::cerr << "cannot bind BLOB\n";
return false;
}
return true;
}
sqlite3_stmt* stmt_;
unsigned index_;
}; };
public:
prepared_statement(database& db, std::string const& sql)
: db_(db.db_.get())
, stmt_(0)
{
const char* tail;
// char * err_msg;
int res = sqlite3_prepare_v2(db_, sql.c_str(), -1, &stmt_, &tail);
if (res != SQLITE_OK)
{
std::cerr << "ERR:" << res << "\n";
throw;
}
} }
}
~prepared_statement()
{
int res = sqlite3_finalize(stmt_);
if (res != SQLITE_OK)
{
std::cerr << "ERR:" << res << "\n";
}
}
bool insert_record(record_type const& rec) const
{
#ifdef MAPNIK_DEBUG
assert(unsigned(sqlite3_bind_parameter_count(stmt_)) == rec.size());
#endif
record_type::const_iterator itr = rec.begin();
record_type::const_iterator end = rec.end();
int count = 1;
for (; itr != end; ++itr)
{
binder op(stmt_, count++);
if (!util::apply_visitor(op, *itr))
{
return false;
}
}
sqlite3_step(stmt_);
sqlite3_reset(stmt_);
return true;
}
private:
sqlite3* db_;
sqlite3_stmt* stmt_;
};
} // namespace sqlite
} // namespace mapnik

View file

@ -44,15 +44,15 @@ const double DEFAULT_RATIO = 0.55;
#ifdef _WIN32 #ifdef _WIN32
#define NOMINMAX #define NOMINMAX
#include <windows.h> #include <windows.h>
int main () int main()
#else #else
int main (int argc,char** argv) int main(int argc, char** argv)
#endif #endif
{ {
using namespace mapnik; using namespace mapnik;
namespace po = boost::program_options; namespace po = boost::program_options;
bool verbose=false; bool verbose = false;
bool index_parts = false; bool index_parts = false;
unsigned int depth = DEFAULT_DEPTH; unsigned int depth = DEFAULT_DEPTH;
double ratio = DEFAULT_RATIO; double ratio = DEFAULT_RATIO;
@ -61,6 +61,7 @@ int main (int argc,char** argv)
try try
{ {
po::options_description desc("shapeindex utility"); po::options_description desc("shapeindex utility");
// clang-format off
desc.add_options() desc.add_options()
("help,h", "produce usage message") ("help,h", "produce usage message")
("version,V","print version string") ("version,V","print version string")
@ -70,14 +71,14 @@ int main (int argc,char** argv)
("ratio,r",po::value<double>(),"split ratio (default 0.55)") ("ratio,r",po::value<double>(),"split ratio (default 0.55)")
("shape_files",po::value<std::vector<std::string> >(),"shape files to index: file1 file2 ...fileN") ("shape_files",po::value<std::vector<std::string> >(),"shape files to index: file1 file2 ...fileN")
; ;
// clang-format on
po::positional_options_description p; po::positional_options_description p;
p.add("shape_files",-1); p.add("shape_files", -1);
po::variables_map vm; po::variables_map vm;
#ifdef _WIN32 #ifdef _WIN32
std::vector<std::string> args; std::vector<std::string> args;
const auto wargs = po::split_winmain(GetCommandLineW()); const auto wargs = po::split_winmain(GetCommandLineW());
for( auto it = wargs.begin() + 1; it != wargs.end(); ++it ) for (auto it = wargs.begin() + 1; it != wargs.end(); ++it)
args.push_back(mapnik::utf16_to_utf8(*it)); args.push_back(mapnik::utf16_to_utf8(*it));
po::store(po::command_line_parser(args).options(desc).positional(p).run(), vm); po::store(po::command_line_parser(args).options(desc).positional(p).run(), vm);
#else #else
@ -115,10 +116,9 @@ int main (int argc,char** argv)
if (vm.count("shape_files")) if (vm.count("shape_files"))
{ {
shape_files=vm["shape_files"].as< std::vector<std::string> >(); shape_files = vm["shape_files"].as<std::vector<std::string>>();
} }
} } catch (std::exception const& ex)
catch (std::exception const& ex)
{ {
std::clog << "Error: " << ex.what() << std::endl; std::clog << "Error: " << ex.what() << std::endl;
return EXIT_FAILURE; return EXIT_FAILURE;
@ -135,46 +135,45 @@ int main (int argc,char** argv)
for (auto const& filename : shape_files) for (auto const& filename : shape_files)
{ {
std::clog << "processing " << filename << std::endl; std::clog << "processing " << filename << std::endl;
std::string shapename (filename); std::string shapename(filename);
boost::algorithm::ireplace_last(shapename,".shp",""); boost::algorithm::ireplace_last(shapename, ".shp", "");
std::string shapename_full (shapename + ".shp"); std::string shapename_full(shapename + ".shp");
std::string shxname(shapename + ".shx"); std::string shxname(shapename + ".shx");
if (! mapnik::util::exists (shapename_full)) if (!mapnik::util::exists(shapename_full))
{ {
std::clog << "Error : file " << shapename_full << " does not exist" << std::endl; std::clog << "Error : file " << shapename_full << " does not exist" << std::endl;
continue; continue;
} }
if (! mapnik::util::exists(shxname)) if (!mapnik::util::exists(shxname))
{ {
std::clog << "Error : shapefile index file (*.shx) " << shxname << " does not exist" << std::endl; std::clog << "Error : shapefile index file (*.shx) " << shxname << " does not exist" << std::endl;
continue; continue;
} }
shape_file shp (shapename_full); shape_file shp(shapename_full);
if (! shp.is_open()) if (!shp.is_open())
{ {
std::clog << "Error : cannot open " << shapename_full << std::endl; std::clog << "Error : cannot open " << shapename_full << std::endl;
continue; continue;
} }
shape_file shx (shxname); shape_file shx(shxname);
if (!shx.is_open()) if (!shx.is_open())
{ {
std::clog << "Error : cannot open " << shxname << std::endl; std::clog << "Error : cannot open " << shxname << std::endl;
continue; continue;
} }
int code = shx.read_xdr_integer(); //file_code == 9994 int code = shx.read_xdr_integer(); // file_code == 9994
std::clog << code << std::endl; std::clog << code << std::endl;
shx.skip(5*4); shx.skip(5 * 4);
int file_length=shx.read_xdr_integer(); int file_length = shx.read_xdr_integer();
int version=shx.read_ndr_integer(); int version = shx.read_ndr_integer();
int shape_type=shx.read_ndr_integer(); int shape_type = shx.read_ndr_integer();
box2d<double> extent; box2d<double> extent;
shx.read_envelope(extent); shx.read_envelope(extent);
std::clog << "length=" << file_length << std::endl; std::clog << "length=" << file_length << std::endl;
std::clog << "version=" << version << std::endl; std::clog << "version=" << version << std::endl;
std::clog << "type=" << shape_type << std::endl; std::clog << "type=" << shape_type << std::endl;
@ -187,12 +186,12 @@ int main (int argc,char** argv)
} }
int pos = 50; int pos = 50;
shx.seek(pos * 2); shx.seek(pos * 2);
mapnik::box2d<float> extent_f { static_cast<float>(extent.minx()), mapnik::box2d<float> extent_f{static_cast<float>(extent.minx()),
static_cast<float>(extent.miny()), static_cast<float>(extent.miny()),
static_cast<float>(extent.maxx()), static_cast<float>(extent.maxx()),
static_cast<float>(extent.maxy())}; static_cast<float>(extent.maxy())};
mapnik::quad_tree<mapnik::detail::node, mapnik::box2d<float> > tree(extent_f, depth, ratio); mapnik::quad_tree<mapnik::detail::node, mapnik::box2d<float>> tree(extent_f, depth, ratio);
int count = 0; int count = 0;
if (shape_type != shape_io::shape_null) if (shape_type != shape_io::shape_null)
@ -216,32 +215,35 @@ int main (int argc,char** argv)
} }
shape_type = shp.read_ndr_integer(); shape_type = shp.read_ndr_integer();
if (shape_type == shape_io::shape_null) continue; if (shape_type == shape_io::shape_null)
continue;
if (shape_type==shape_io::shape_point if (shape_type == shape_io::shape_point || shape_type == shape_io::shape_pointm ||
|| shape_type==shape_io::shape_pointm shape_type == shape_io::shape_pointz)
|| shape_type == shape_io::shape_pointz)
{ {
double x=shp.read_double(); double x = shp.read_double();
double y=shp.read_double(); double y = shp.read_double();
item_ext=box2d<double>(x,y,x,y); item_ext = box2d<double>(x, y, x, y);
} }
else if (index_parts && else if (index_parts &&
(shape_type == shape_io::shape_polygon || shape_type == shape_io::shape_polygonm || shape_type == shape_io::shape_polygonz (shape_type == shape_io::shape_polygon || shape_type == shape_io::shape_polygonm ||
|| shape_type == shape_io::shape_polyline || shape_type == shape_io::shape_polylinem || shape_type == shape_io::shape_polylinez)) shape_type == shape_io::shape_polygonz || shape_type == shape_io::shape_polyline ||
shape_type == shape_io::shape_polylinem || shape_type == shape_io::shape_polylinez))
{ {
shp.read_envelope(item_ext); shp.read_envelope(item_ext);
int num_parts = shp.read_ndr_integer(); int num_parts = shp.read_ndr_integer();
int num_points = shp.read_ndr_integer(); int num_points = shp.read_ndr_integer();
std::vector<int> parts; std::vector<int> parts;
parts.resize(num_parts); parts.resize(num_parts);
std::for_each(parts.begin(), parts.end(), [&](int & part) { part = shp.read_ndr_integer();}); std::for_each(parts.begin(), parts.end(), [&](int& part) { part = shp.read_ndr_integer(); });
for (int k = 0; k < num_parts; ++k) for (int k = 0; k < num_parts; ++k)
{ {
int start = parts[k]; int start = parts[k];
int end; int end;
if (k == num_parts - 1) end = num_points; if (k == num_parts - 1)
else end = parts[k + 1]; end = num_points;
else
end = parts[k + 1];
mapnik::geometry::linear_ring<double> ring; mapnik::geometry::linear_ring<double> ring;
ring.reserve(end - start); ring.reserve(end - start);
@ -258,15 +260,15 @@ int main (int argc,char** argv)
{ {
std::clog << "record number " << record_number << " box=" << item_ext << std::endl; std::clog << "record number " << record_number << " box=" << item_ext << std::endl;
} }
mapnik::box2d<float> ext_f {static_cast<float>(item_ext.minx()), mapnik::box2d<float> ext_f{static_cast<float>(item_ext.minx()),
static_cast<float>(item_ext.miny()), static_cast<float>(item_ext.miny()),
static_cast<float>(item_ext.maxx()), static_cast<float>(item_ext.maxx()),
static_cast<float>(item_ext.maxy())}; static_cast<float>(item_ext.maxy())};
tree.insert(mapnik::detail::node(offset * 2, start, end, std::move(ext_f)), ext_f); tree.insert(mapnik::detail::node(offset * 2, start, end, std::move(ext_f)), ext_f);
++count; ++count;
} }
} }
item_ext = mapnik::box2d<double>(); //invalid item_ext = mapnik::box2d<double>(); // invalid
} }
else else
{ {
@ -279,10 +281,10 @@ int main (int argc,char** argv)
{ {
std::clog << "record number " << record_number << " box=" << item_ext << std::endl; std::clog << "record number " << record_number << " box=" << item_ext << std::endl;
} }
mapnik::box2d<float> ext_f {static_cast<float>(item_ext.minx()), mapnik::box2d<float> ext_f{static_cast<float>(item_ext.minx()),
static_cast<float>(item_ext.miny()), static_cast<float>(item_ext.miny()),
static_cast<float>(item_ext.maxx()), static_cast<float>(item_ext.maxx()),
static_cast<float>(item_ext.maxy())}; static_cast<float>(item_ext.maxy())};
tree.insert(mapnik::detail::node(offset * 2, -1, 0, std::move(ext_f)), ext_f); tree.insert(mapnik::detail::node(offset * 2, -1, 0, std::move(ext_f)), ext_f);
++count; ++count;
@ -294,14 +296,14 @@ int main (int argc,char** argv)
{ {
std::clog << " number shapes=" << count << std::endl; std::clog << " number shapes=" << count << std::endl;
#ifdef _WIN32 #ifdef _WIN32
std::ofstream file(mapnik::utf8_to_utf16(shapename+".index").c_str(), std::ios::trunc | std::ios::binary); std::ofstream file(mapnik::utf8_to_utf16(shapename + ".index").c_str(), std::ios::trunc | std::ios::binary);
#else #else
std::ofstream file((shapename+".index").c_str(), std::ios::trunc | std::ios::binary); std::ofstream file((shapename + ".index").c_str(), std::ios::trunc | std::ios::binary);
#endif #endif
if (!file) if (!file)
{ {
std::clog << "cannot open index file for writing file \"" std::clog << "cannot open index file for writing file \"" << (shapename + ".index") << "\""
<< (shapename+".index") << "\"" << std::endl; << std::endl;
} }
else else
{ {

View file

@ -53,19 +53,16 @@ MAPNIK_DISABLE_WARNING_PUSH
#include "agg_scanline_u.h" #include "agg_scanline_u.h"
MAPNIK_DISABLE_WARNING_POP MAPNIK_DISABLE_WARNING_POP
struct main_marker_visitor struct main_marker_visitor
{ {
main_marker_visitor(std::string const& svg_name, main_marker_visitor(std::string const& svg_name, double scale_factor, bool verbose, bool auto_open)
double scale_factor, : svg_name_(svg_name)
bool verbose, , scale_factor_(scale_factor)
bool auto_open) , verbose_(verbose)
: svg_name_(svg_name), , auto_open_(auto_open)
scale_factor_(scale_factor), {}
verbose_(verbose),
auto_open_(auto_open) {}
int operator() (mapnik::marker_svg const& marker) const int operator()(mapnik::marker_svg const& marker) const
{ {
using pixfmt = agg::pixfmt_rgba32_pre; using pixfmt = agg::pixfmt_rgba32_pre;
using renderer_base = agg::renderer_base<pixfmt>; using renderer_base = agg::renderer_base<pixfmt>;
@ -112,19 +109,16 @@ struct main_marker_visitor
mapnik::svg::vertex_stl_adapter<mapnik::svg::svg_path_storage> stl_storage(marker.get_data()->source()); mapnik::svg::vertex_stl_adapter<mapnik::svg::svg_path_storage> stl_storage(marker.get_data()->source());
mapnik::svg::svg_path_adapter svg_path(stl_storage); mapnik::svg::svg_path_adapter svg_path(stl_storage);
mapnik::svg::renderer_agg< mapnik::svg::
mapnik::svg_path_adapter, renderer_agg<mapnik::svg_path_adapter, mapnik::svg_attribute_type, renderer_solid, agg::pixfmt_rgba32_pre>
mapnik::svg_attribute_type, svg_renderer_this(svg_path, marker.get_data()->attributes());
renderer_solid,
agg::pixfmt_rgba32_pre > svg_renderer_this(svg_path,
marker.get_data()->attributes());
svg_renderer_this.render(ras_ptr, sl, renb, mtx, opacity, bbox); svg_renderer_this.render(ras_ptr, sl, renb, mtx, opacity, bbox);
std::string png_name(svg_name_); std::string png_name(svg_name_);
boost::algorithm::ireplace_last(png_name,".svg",".png"); boost::algorithm::ireplace_last(png_name, ".svg", ".png");
demultiply_alpha(im); demultiply_alpha(im);
mapnik::save_to_file<mapnik::image_rgba8>(im,png_name,"png"); mapnik::save_to_file<mapnik::image_rgba8>(im, png_name, "png");
int status = 0; int status = 0;
if (auto_open_) if (auto_open_)
{ {
@ -143,8 +137,8 @@ struct main_marker_visitor
} }
// default // default
template <typename T> template<typename T>
int operator() (T const&) const int operator()(T const&) const
{ {
std::clog << "svg2png error: failed to process '" << svg_name_ << "'\n"; std::clog << "svg2png error: failed to process '" << svg_name_ << "'\n";
return -1; return -1;
@ -157,7 +151,7 @@ struct main_marker_visitor
bool auto_open_; bool auto_open_;
}; };
int main (int argc,char** argv) int main(int argc, char** argv)
{ {
namespace po = boost::program_options; namespace po = boost::program_options;
@ -172,6 +166,7 @@ int main (int argc,char** argv)
try try
{ {
po::options_description desc("svg2png utility"); po::options_description desc("svg2png utility");
// clang-format off
desc.add_options() desc.add_options()
("help,h", "produce usage message") ("help,h", "produce usage message")
("version,V","print version string") ("version,V","print version string")
@ -181,7 +176,7 @@ int main (int argc,char** argv)
("scale-factor", po::value<double>(), "provide scaling factor (default: 1.0)") ("scale-factor", po::value<double>(), "provide scaling factor (default: 1.0)")
("svg",po::value<std::vector<std::string> >(),"svg file to read") ("svg",po::value<std::vector<std::string> >(),"svg file to read")
; ;
// clang-format on
po::positional_options_description p; po::positional_options_description p;
p.add("svg", -1); p.add("svg", -1);
po::variables_map vm; po::variables_map vm;
@ -221,7 +216,7 @@ int main (int argc,char** argv)
} }
if (vm.count("svg")) if (vm.count("svg"))
{ {
svg_files=vm["svg"].as< std::vector<std::string> >(); svg_files = vm["svg"].as<std::vector<std::string>>();
} }
else else
{ {
@ -237,22 +232,21 @@ int main (int argc,char** argv)
} }
while (itr != svg_files.end()) while (itr != svg_files.end())
{ {
std::string svg_name (*itr++); std::string svg_name(*itr++);
if (verbose) if (verbose)
{ {
std::clog << "found: " << svg_name << "\n"; std::clog << "found: " << svg_name << "\n";
} }
std::shared_ptr<mapnik::marker const> marker = mapnik::marker_cache::instance().find(svg_name, false, strict); std::shared_ptr<mapnik::marker const> marker =
mapnik::marker_cache::instance().find(svg_name, false, strict);
main_marker_visitor visitor(svg_name, scale_factor, verbose, auto_open); main_marker_visitor visitor(svg_name, scale_factor, verbose, auto_open);
status = mapnik::util::apply_visitor(visitor, *marker); status = mapnik::util::apply_visitor(visitor, *marker);
} }
} } catch (std::exception const& ex)
catch (std::exception const& ex)
{ {
std::clog << "Exception caught:" << ex.what() << std::endl; std::clog << "Exception caught:" << ex.what() << std::endl;
return -1; return -1;
} } catch (...)
catch (...)
{ {
std::clog << "Exception of unknown type!" << std::endl; std::clog << "Exception of unknown type!" << std::endl;
return -1; return -1;