mapnik-index - refactor to use box2d<float> and reduce memory requirement during index creations

This commit is contained in:
artemp 2016-03-24 17:12:16 +00:00
parent 450533ebc6
commit 7cd5301cbe
8 changed files with 45 additions and 34 deletions

View file

@ -238,8 +238,12 @@ void csv_file_parser::add_feature(mapnik::value_integer, mapnik::csv_line const
// no-op by default
}
void csv_file_parser::parse_csv_and_boxes(std::istream & csv_file, boxes_type & boxes)
template <typename T>
void csv_file_parser::parse_csv_and_boxes(std::istream & csv_file, T & boxes)
{
using boxes_type = T;
using box_type = typename boxes_type::value_type::first_type;
auto file_length = detail::file_length(csv_file);
// set back to start
csv_file.seekg(0, std::ios::beg);
@ -412,7 +416,7 @@ void csv_file_parser::parse_csv_and_boxes(std::istream & csv_file, boxes_type &
else
extent_ = box;
}
boxes.emplace_back(box, make_pair(record_offset, record_size));
boxes.emplace_back(box_type(box), make_pair(record_offset, record_size));
add_feature(++feature_count, values);
}
else
@ -496,4 +500,8 @@ mapnik::geometry::geometry<double> extract_geometry(std::vector<std::string> con
return geom;
}
template void csv_file_parser::parse_csv_and_boxes(std::istream & csv_file, std::vector<std::pair<mapnik::box2d<double>, std::pair<std::size_t, std::size_t>>> & boxes);
template void csv_file_parser::parse_csv_and_boxes(std::istream & csv_file, std::vector<std::pair<mapnik::box2d<float>, std::pair<std::size_t, std::size_t>>> & boxes);
} // namespace csv_utils

View file

@ -130,11 +130,8 @@ void process_properties(Feature & feature, Headers const& headers, Values const&
struct csv_file_parser
{
using box_type = mapnik::box2d<double>;
using item_type = std::pair<box_type, std::pair<std::size_t, std::size_t>>;
using boxes_type = std::vector<item_type>;
void parse_csv_and_boxes(std::istream & csv_file, boxes_type & boxes);
template <typename T>
void parse_csv_and_boxes(std::istream & csv_file, T & boxes);
virtual void add_feature(mapnik::value_integer index, mapnik::csv_line const & values);

View file

@ -192,12 +192,14 @@ geojson_datasource::geojson_datasource(parameters const& params)
}
namespace {
using box_type = box2d<double>;
using boxes_type = std::vector<std::pair<box_type, std::pair<std::size_t, std::size_t>>>;
using base_iterator_type = char const*;
const mapnik::transcoder geojson_datasource_static_tr("utf8");
const mapnik::json::feature_collection_grammar<base_iterator_type,mapnik::feature_impl> geojson_datasource_static_fc_grammar(geojson_datasource_static_tr);
const mapnik::json::feature_grammar_callback<base_iterator_type,mapnik::feature_impl> geojson_datasource_static_feature_callback_grammar(geojson_datasource_static_tr);
const mapnik::json::feature_grammar<base_iterator_type, mapnik::feature_impl> geojson_datasource_static_feature_grammar(geojson_datasource_static_tr);
const mapnik::json::extract_bounding_box_grammar<base_iterator_type> geojson_datasource_static_bbox_grammar;
const mapnik::json::extract_bounding_box_grammar<base_iterator_type, boxes_type> geojson_datasource_static_bbox_grammar;
}
void geojson_datasource::initialise_descriptor(mapnik::feature_ptr const& feature)
@ -257,7 +259,7 @@ void geojson_datasource::initialise_disk_index(std::string const& filename)
template <typename Iterator>
void geojson_datasource::initialise_index(Iterator start, Iterator end)
{
mapnik::json::boxes_type boxes;
boxes_type boxes;
boost::spirit::standard::space_type space;
Iterator itr = start;
if (!boost::spirit::qi::phrase_parse(itr, end, (geojson_datasource_static_bbox_grammar)(boost::phoenix::ref(boxes)) , space))

View file

@ -163,7 +163,7 @@ int main (int argc, char** argv)
std::clog << "max tree depth:" << depth << std::endl;
std::clog << "split ratio:" << ratio << std::endl;
using box_type = mapnik::box2d<double>;
using box_type = mapnik::box2d<float>;
using item_type = std::pair<box_type, std::pair<std::size_t, std::size_t>>;
for (auto const& filename : files_to_process)
@ -175,7 +175,7 @@ int main (int argc, char** argv)
}
std::vector<item_type> boxes;
mapnik::box2d<double> extent;
box_type extent;
if (mapnik::detail::is_csv(filename))
{
std::clog << "processing '" << filename << "' as CSV\n";
@ -198,10 +198,12 @@ int main (int argc, char** argv)
if (extent.valid())
{
std::clog << extent << std::endl;
mapnik::quad_tree<std::pair<std::size_t, std::size_t>> tree(extent, depth, ratio);
mapnik::box2d<double> extent_d(extent.minx(), extent.miny(), extent.maxx(), extent.maxy());
mapnik::quad_tree<std::pair<std::size_t, std::size_t>> tree(extent_d, depth, ratio);
for (auto const& item : boxes)
{
tree.insert(std::get<1>(item), std::get<0>(item));
auto ext_f = std::get<0>(item);
tree.insert(std::get<1>(item), mapnik::box2d<double>(ext_f.minx(), ext_f.miny(), ext_f.maxx(), ext_f.maxy()));
}
std::fstream file((filename + ".index").c_str(),

View file

@ -44,7 +44,7 @@
namespace mapnik { namespace detail {
template <typename T>
std::pair<bool,box2d<double>> 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)
{
csv_utils::csv_file_parser p;
p.manual_headers_ = manual_headers;
@ -65,7 +65,7 @@ std::pair<bool,box2d<double>> process_csv_file(T & boxes, std::string const& fil
else
{
std::clog << "Error : cannot mmap " << filename << std::endl;
return std::make_pair(false, p.extent_);
return std::make_pair(false, box2d<float>(p.extent_));
}
#else
#if defined(_WINDOWS)
@ -76,24 +76,24 @@ std::pair<bool,box2d<double>> process_csv_file(T & boxes, std::string const& fil
if (!csv_file.is_open())
{
std::clog << "Error : cannot open " << filename << std::endl;
return std::make_pair(false, p.extent_);
return std::make_pair(false, box2d<float>(p.extent_));
}
#endif
try
{
p.parse_csv_and_boxes(csv_file, boxes);
return std::make_pair(true, p.extent_);
return std::make_pair(true, box2d<float>(p.extent_));
}
catch (std::exception const& ex)
{
std::clog << ex.what() << std::endl;
return std::make_pair(false, p.extent_);
return std::make_pair(false, box2d<float>(p.extent_));
}
}
using box_type = mapnik::box2d<double>;
using box_type = mapnik::box2d<float>;
using item_type = std::pair<box_type, std::pair<std::size_t, std::size_t>>;
using boxes_type = std::vector<item_type>;
template std::pair<bool,box2d<double>> 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);
}}

View file

@ -29,7 +29,7 @@
namespace mapnik { namespace detail {
template <typename T>
std::pair<bool, box2d<double>> 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);
}}

View file

@ -38,33 +38,38 @@
#include <mapnik/json/feature_collection_grammar_impl.hpp>
namespace {
template <typename T>
struct feature_validate_callback
{
feature_validate_callback(mapnik::box2d<double> const& box)
feature_validate_callback(mapnik::box2d<T> const& box)
: box_(box) {}
void operator() (mapnik::feature_ptr const& f) const
{
if (box_ != f->envelope())
if (box_ != box_)
{
throw std::runtime_error("Bounding boxes mismatch validation feature");
}
}
mapnik::box2d<double> const& box_;
mapnik::box2d<T> const& box_;
};
using box_type = mapnik::box2d<float>;
using boxes_type = std::vector<std::pair<box_type, std::pair<std::size_t, std::size_t>>>;
using base_iterator_type = char const*;
const mapnik::json::extract_bounding_box_grammar<base_iterator_type> geojson_datasource_static_bbox_grammar;
const mapnik::json::extract_bounding_box_grammar<base_iterator_type, boxes_type> geojson_datasource_static_bbox_grammar;
const mapnik::transcoder tr("utf8");
const mapnik::json::feature_grammar_callback<base_iterator_type, mapnik::feature_impl, feature_validate_callback> fc_grammar(tr);
const mapnik::json::feature_grammar_callback<base_iterator_type, mapnik::feature_impl, feature_validate_callback<float>> fc_grammar(tr);
}
namespace mapnik { namespace detail {
template <typename T>
std::pair<bool,box2d<double>> process_geojson_file(T & boxes, std::string const& filename, bool validate_features, bool verbose)
std::pair<bool,typename T::value_type::first_type> process_geojson_file(T & boxes, std::string const& filename, bool validate_features, bool verbose)
{
mapnik::box2d<double> extent;
using box_type = typename T::value_type::first_type;
box_type extent;
#if defined(MAPNIK_MEMORY_MAPPED_FILE)
mapnik::mapped_region_ptr mapped_region;
boost::optional<mapnik::mapped_region_ptr> memory =
@ -121,7 +126,7 @@ std::pair<bool,box2d<double>> process_geojson_file(T & boxes, std::string const&
{
base_iterator_type feat_itr = start + item.second.first;
base_iterator_type feat_end = feat_itr + item.second.second;
feature_validate_callback callback(item.first);
feature_validate_callback<float> callback(item.first);
bool result = boost::spirit::qi::phrase_parse(feat_itr, feat_end, (fc_grammar)
(boost::phoenix::ref(ctx), boost::phoenix::ref(start_id), boost::phoenix::ref(callback)),
space);
@ -136,9 +141,6 @@ std::pair<bool,box2d<double>> process_geojson_file(T & boxes, std::string const&
return std::make_pair(true, extent);
}
using box_type = mapnik::box2d<double>;
using item_type = std::pair<box_type, std::pair<std::size_t, std::size_t>>;
using boxes_type = std::vector<item_type>;
template std::pair<bool,box2d<double>> process_geojson_file(boxes_type&, std::string const&, bool, bool);
template std::pair<bool,box_type> process_geojson_file(boxes_type&, std::string const&, bool, bool);
}}

View file

@ -29,7 +29,7 @@
namespace mapnik { namespace detail {
template <typename T>
std::pair<bool, box2d<double>> process_geojson_file(T & boxes, std::string const& filename, bool validate_features, bool verbose);
std::pair<bool, typename T::value_type::first_type> process_geojson_file(T & boxes, std::string const& filename, bool validate_features, bool verbose);
}}