Merge branch 'master' into twkb-direct
This commit is contained in:
commit
ce52c91156
12 changed files with 126 additions and 92 deletions
|
@ -50,7 +50,8 @@ template <typename T> class MAPNIK_DECL box2d
|
|||
boost::multipliable2<box2d<T>, T > > > >
|
||||
{
|
||||
public:
|
||||
using box2d_type = box2d<T>;
|
||||
using value_type = T;
|
||||
using box2d_type = box2d<value_type>;
|
||||
private:
|
||||
T minx_;
|
||||
T miny_;
|
||||
|
@ -65,12 +66,22 @@ private:
|
|||
swap(lhs.maxy_, rhs.maxy_);
|
||||
}
|
||||
public:
|
||||
|
||||
box2d();
|
||||
box2d(T minx,T miny,T maxx,T maxy);
|
||||
box2d(coord<T,2> const& c0, coord<T,2> const& c1);
|
||||
box2d(box2d_type const& rhs);
|
||||
box2d(box2d_type const& rhs, agg::trans_affine const& tr);
|
||||
// move
|
||||
box2d(box2d_type&& rhs);
|
||||
// converting ctor
|
||||
template <typename T1>
|
||||
explicit box2d(box2d<T1> other)
|
||||
: minx_(static_cast<value_type>(other.minx())),
|
||||
miny_(static_cast<value_type>(other.miny())),
|
||||
maxx_(static_cast<value_type>(other.maxx())),
|
||||
maxy_(static_cast<value_type>(other.maxy()))
|
||||
{}
|
||||
box2d_type& operator=(box2d_type other);
|
||||
T minx() const;
|
||||
T miny() const;
|
||||
|
@ -99,6 +110,7 @@ public:
|
|||
void re_center(T cx,T cy);
|
||||
void re_center(coord<T,2> const& c);
|
||||
void init(T x0,T y0,T x1,T y1);
|
||||
void init(T x, T y);
|
||||
void clip(box2d_type const& other);
|
||||
void pad(T padding);
|
||||
bool from_string(std::string const& str);
|
||||
|
|
|
@ -32,53 +32,19 @@
|
|||
#pragma GCC diagnostic push
|
||||
#include <mapnik/warning_ignore.hpp>
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include <boost/spirit/include/phoenix_function.hpp>
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
namespace mapnik { namespace json {
|
||||
|
||||
using position_type = mapnik::geometry::point<double>;
|
||||
using box_type = box2d<double>;
|
||||
using boxes_type = std::vector<std::pair<box_type, std::pair<std::size_t, std::size_t>>>;
|
||||
|
||||
namespace qi = boost::spirit::qi;
|
||||
|
||||
struct calculate_bounding_box_impl
|
||||
{
|
||||
using result_type = void;
|
||||
template <typename T0, typename T1>
|
||||
result_type operator() (T0 & bbox, T1 const& pos) const
|
||||
{
|
||||
if (pos)
|
||||
{
|
||||
double x = pos->x;
|
||||
double y = pos->y;
|
||||
if (!bbox.valid())
|
||||
{
|
||||
bbox.init(x, y, x, y); //TODO: add init(x,y) convinience method
|
||||
}
|
||||
else
|
||||
{
|
||||
bbox.expand_to_include(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct push_box_impl
|
||||
{
|
||||
using result_type = void;
|
||||
template <typename T0, typename T1, typename T2, typename T3>
|
||||
void operator() (T0 & boxes, T1 const& begin, T2 const& box, T3 const& range) const
|
||||
{
|
||||
if (box.valid()) boxes.emplace_back(box, std::make_pair(std::distance(begin, range.begin()), std::distance(range.begin(), range.end())));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Iterator, typename Boxes = boxes_type, typename ErrorHandler = error_handler<Iterator> >
|
||||
template <typename Iterator, typename Boxes, typename ErrorHandler = error_handler<Iterator> >
|
||||
struct extract_bounding_box_grammar :
|
||||
qi::grammar<Iterator, void(Boxes&), space_type>
|
||||
{
|
||||
using position_type = mapnik::geometry::point<double>;
|
||||
using boxes_type = Boxes;
|
||||
using box_type = typename Boxes::value_type::first_type;
|
||||
extract_bounding_box_grammar();
|
||||
// rules
|
||||
qi::rule<Iterator, void(boxes_type&), space_type> start;
|
||||
|
@ -91,11 +57,6 @@ struct extract_bounding_box_grammar :
|
|||
qi::rule<Iterator, void(box_type&), space_type> rings_array;
|
||||
// generic JSON support
|
||||
json::generic_json<Iterator> json;
|
||||
// phoenix functions
|
||||
boost::phoenix::function<push_box_impl> push_box;
|
||||
boost::phoenix::function<calculate_bounding_box_impl> calculate_bounding_box;
|
||||
// error handler
|
||||
boost::phoenix::function<ErrorHandler> const error_handler;
|
||||
};
|
||||
|
||||
}}
|
||||
|
|
|
@ -29,12 +29,48 @@
|
|||
#include <boost/spirit/include/phoenix_stl.hpp>
|
||||
#include <boost/spirit/include/phoenix_operator.hpp>
|
||||
#include <boost/spirit/repository/include/qi_iter_pos.hpp>
|
||||
#include <boost/spirit/include/phoenix_function.hpp>
|
||||
// stl
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
namespace mapnik { namespace json {
|
||||
|
||||
struct calculate_bounding_box_impl
|
||||
{
|
||||
using result_type = void;
|
||||
template <typename T0, typename T1>
|
||||
result_type operator() (T0 & bbox, T1 const& pos) const
|
||||
{
|
||||
if (pos)
|
||||
{
|
||||
typename T0::value_type x = pos->x;
|
||||
typename T0::value_type y = pos->y;
|
||||
if (!bbox.valid())
|
||||
{
|
||||
bbox.init(x, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
bbox.expand_to_include(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct push_box_impl
|
||||
{
|
||||
using result_type = void;
|
||||
template <typename T0, typename T1, typename T2, typename T3>
|
||||
void operator() (T0 & boxes, T1 const& begin, T2 const& box, T3 const& range) const
|
||||
{
|
||||
if (box.valid()) boxes.emplace_back(box,
|
||||
std::make_pair(std::distance(begin,
|
||||
range.begin()),
|
||||
std::distance(range.begin(), range.end())));
|
||||
}
|
||||
};
|
||||
|
||||
namespace repo = boost::spirit::repository;
|
||||
|
||||
template <typename Iterator, typename Boxes, typename ErrorHandler>
|
||||
|
@ -61,6 +97,12 @@ extract_bounding_box_grammar<Iterator, Boxes, ErrorHandler>::extract_bounding_bo
|
|||
using qi::fail;
|
||||
using qi::on_error;
|
||||
|
||||
// phoenix functions
|
||||
boost::phoenix::function<push_box_impl> push_box;
|
||||
boost::phoenix::function<calculate_bounding_box_impl> calculate_bounding_box;
|
||||
// error handler
|
||||
boost::phoenix::function<ErrorHandler> const error_handler;
|
||||
|
||||
start = features(_r1)
|
||||
;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -299,33 +299,43 @@ void box2d<T>::re_center(coord<T,2> const& c)
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
void box2d<T>::init(T x0,T y0,T x1,T y1)
|
||||
void box2d<T>::init(T x0, T y0, T x1, T y1)
|
||||
{
|
||||
if (x0<x1)
|
||||
if (x0 < x1)
|
||||
{
|
||||
minx_=x0;maxx_=x1;
|
||||
minx_ = x0;
|
||||
maxx_ = x1;
|
||||
}
|
||||
else
|
||||
{
|
||||
minx_=x1;maxx_=x0;
|
||||
minx_ = x1;
|
||||
maxx_ = x0;
|
||||
}
|
||||
if (y0<y1)
|
||||
if (y0 < y1)
|
||||
{
|
||||
miny_=y0;maxy_=y1;
|
||||
miny_ = y0;
|
||||
maxy_ = y1;
|
||||
}
|
||||
else
|
||||
{
|
||||
miny_=y1;maxy_=y0;
|
||||
miny_ = y1;
|
||||
maxy_ = y0;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void box2d<T>::init(T x, T y)
|
||||
{
|
||||
init(x, y, x, y);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void box2d<T>::clip(box2d_type const& other)
|
||||
{
|
||||
minx_ = std::max(minx_,other.minx());
|
||||
miny_ = std::max(miny_,other.miny());
|
||||
maxx_ = std::min(maxx_,other.maxx());
|
||||
maxy_ = std::min(maxy_,other.maxy());
|
||||
minx_ = std::max(minx_, other.minx());
|
||||
miny_ = std::max(miny_, other.miny());
|
||||
maxx_ = std::min(maxx_, other.maxx());
|
||||
maxy_ = std::min(maxy_, other.maxy());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -337,7 +347,6 @@ void box2d<T>::pad(T padding)
|
|||
maxy_ += padding;
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
bool box2d<T>::from_string(std::string const& str)
|
||||
{
|
||||
|
@ -346,8 +355,7 @@ bool box2d<T>::from_string(std::string const& str)
|
|||
boost::spirit::ascii::space_type space;
|
||||
bool r = boost::spirit::qi::phrase_parse(str.begin(),
|
||||
str.end(),
|
||||
double_ >> -lit(',') >> double_ >> -lit(',')
|
||||
>> double_ >> -lit(',') >> double_,
|
||||
double_ >> -lit(',') >> double_ >> -lit(',') >> double_ >> -lit(',') >> double_,
|
||||
space,
|
||||
*this);
|
||||
return r;
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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);
|
||||
|
||||
}}
|
||||
|
|
|
@ -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);
|
||||
|
||||
}}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
}}
|
||||
|
|
|
@ -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);
|
||||
|
||||
}}
|
||||
|
||||
|
|
Loading…
Reference in a new issue