Merge branch 'master' into twkb-direct

This commit is contained in:
artemp 2016-03-29 10:47:05 +01:00
commit ce52c91156
12 changed files with 126 additions and 92 deletions

View file

@ -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);

View file

@ -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;
};
}}

View file

@ -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)
;

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

@ -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;

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);
}}