From fddec700ad38caa9b49239a87721b961882f0025 Mon Sep 17 00:00:00 2001 From: artemp Date: Mon, 30 Sep 2013 14:14:58 +0100 Subject: [PATCH] TopoJSON input plugin skeleton implementation --- SConstruct | 1 + include/mapnik/json/topojson_grammar.hpp | 2 +- include/mapnik/json/topojson_grammar_impl.hpp | 2 +- plugins/input/topojson/build.py | 76 +++++++++ .../input/topojson/topojson_datasource.cpp | 161 ++++++++++++++++++ .../input/topojson/topojson_datasource.hpp | 81 +++++++++ .../input/topojson/topojson_featureset.cpp | 52 ++++++ .../input/topojson/topojson_featureset.hpp | 48 ++++++ plugins/input/topojson/topojson_grammar.cpp | 35 ++++ 9 files changed, 456 insertions(+), 2 deletions(-) create mode 100644 plugins/input/topojson/build.py create mode 100644 plugins/input/topojson/topojson_datasource.cpp create mode 100644 plugins/input/topojson/topojson_datasource.hpp create mode 100644 plugins/input/topojson/topojson_featureset.cpp create mode 100644 plugins/input/topojson/topojson_featureset.hpp create mode 100644 plugins/input/topojson/topojson_grammar.cpp diff --git a/SConstruct b/SConstruct index 54ad20ad6..64b397a44 100644 --- a/SConstruct +++ b/SConstruct @@ -112,6 +112,7 @@ PLUGINS = { # plugins with external dependencies 'csv': {'default':True,'path':None,'inc':None,'lib':None,'lang':'C++'}, 'raster': {'default':True,'path':None,'inc':None,'lib':None,'lang':'C++'}, 'geojson': {'default':True,'path':None,'inc':None,'lib':None,'lang':'C++'}, + 'topojson':{'default':True,'path':None,'inc':None,'lib':None,'lang':'C++'}, 'python': {'default':False,'path':None,'inc':None,'lib':None,'lang':'C++'}, } diff --git a/include/mapnik/json/topojson_grammar.hpp b/include/mapnik/json/topojson_grammar.hpp index 1cc24e34b..9406c1e34 100644 --- a/include/mapnik/json/topojson_grammar.hpp +++ b/include/mapnik/json/topojson_grammar.hpp @@ -28,7 +28,7 @@ #include // #include -#include +#include // #include diff --git a/include/mapnik/json/topojson_grammar_impl.hpp b/include/mapnik/json/topojson_grammar_impl.hpp index ac02ae556..5d969bf18 100644 --- a/include/mapnik/json/topojson_grammar_impl.hpp +++ b/include/mapnik/json/topojson_grammar_impl.hpp @@ -20,7 +20,7 @@ * *****************************************************************************/ -#include +#include namespace mapnik { namespace topojson { diff --git a/plugins/input/topojson/build.py b/plugins/input/topojson/build.py new file mode 100644 index 000000000..c2b8edea4 --- /dev/null +++ b/plugins/input/topojson/build.py @@ -0,0 +1,76 @@ +# +# This file is part of Mapnik (c++ mapping toolkit) +# +# Copyright (C) 2013 Artem Pavlenko +# +# Mapnik is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# + +Import ('env') + +can_build = True +if env.get('BOOST_LIB_VERSION_FROM_HEADER'): + boost_version_from_header = int(env['BOOST_LIB_VERSION_FROM_HEADER'].split('_')[1]) + if boost_version_from_header < 47: + can_build = False + +if not can_build: + print 'WARNING: skipping building the optional geojson datasource plugin which requires boost >= 1.47' +else: + Import ('plugin_base') + + PLUGIN_NAME = 'topojson' + + plugin_env = plugin_base.Clone() + + plugin_sources = Split( + """ + %(PLUGIN_NAME)s_datasource.cpp + %(PLUGIN_NAME)s_featureset.cpp + %(PLUGIN_NAME)s_grammar.cpp + """ % locals() + ) + + # Link Library to Dependencies + libraries = [] + libraries.append(env['ICU_LIB_NAME']) + libraries.append('boost_system%s' % env['BOOST_APPEND']) + if env['THREADING'] == 'multi': + libraries.append('boost_thread%s' % env['BOOST_APPEND']) + + if env['PLUGIN_LINKING'] == 'shared': + libraries.append('mapnik') + + TARGET = plugin_env.SharedLibrary('../%s' % PLUGIN_NAME, + SHLIBPREFIX='', + SHLIBSUFFIX='.input', + source=plugin_sources, + LIBS=libraries, + LINKFLAGS=env['CUSTOM_LDFLAGS']) + + # if the plugin links to libmapnik ensure it is built first + Depends(TARGET, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + + if 'uninstall' not in COMMAND_LINE_TARGETS: + env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], TARGET) + env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + + plugin_obj = { + 'LIBS': libraries, + 'SOURCES': plugin_sources, + } + + Return('plugin_obj') diff --git a/plugins/input/topojson/topojson_datasource.cpp b/plugins/input/topojson/topojson_datasource.cpp new file mode 100644 index 000000000..35b013f0a --- /dev/null +++ b/plugins/input/topojson/topojson_datasource.cpp @@ -0,0 +1,161 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2012 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#include "topojson_datasource.hpp" +#include "topojson_featureset.hpp" + +#include +#include + +// boost +#include +#include +#include +#include + +#include +#include +#include +#include + +// mapnik +#include +#include +#include +//#include +#include +#include +#include +#include +#include +//#include +#include + +using mapnik::datasource; +using mapnik::parameters; + +DATASOURCE_PLUGIN(topojson_datasource) + +topojson_datasource::topojson_datasource(parameters const& params) +: datasource(params), + type_(datasource::Vector), + desc_(*params.get("type"), + *params.get("encoding","utf-8")), + file_(*params.get("file","")), + extent_(), + tr_(new mapnik::transcoder(*params.get("encoding","utf-8"))), + tree_(16,1) +{ + if (file_.empty()) throw mapnik::datasource_exception("TopoJSON Plugin: missing parameter"); + + boost::optional base = params.get("base"); + if (base) + { + file_ = *base + "/" + file_; + } + + typedef std::istreambuf_iterator base_iterator_type; + +#if defined (_WINDOWS) + std::ifstream is(mapnik::utf8_to_utf16(file_),std::ios_base::in | std::ios_base::binary); +#else + std::ifstream is(file_.c_str(),std::ios_base::in | std::ios_base::binary); +#endif + if (!is.is_open()) + { + throw mapnik::datasource_exception("TopoJSON Plugin: could not open: '" + file_ + "'"); + } + + boost::spirit::multi_pass begin = + boost::spirit::make_default_multi_pass(base_iterator_type(is)); + + boost::spirit::multi_pass end = + boost::spirit::make_default_multi_pass(base_iterator_type()); + + //mapnik::context_ptr ctx = std::make_shared(); + + mapnik::topojson::topojson_grammar > g; + bool result = boost::spirit::qi::phrase_parse(begin, end, g, boost::spirit::standard_wide::space, topo_); + if (!result) + { + throw mapnik::datasource_exception("topojson_datasource: Failed parse TopoJSON file '" + file_ + "'"); + } + + // tree_.insert(box_type(point_type(box.minx(),box.miny()),point_type(box.maxx(),box.maxy())), count++); +} + +topojson_datasource::~topojson_datasource() { } + +const char * topojson_datasource::name() +{ + return "geojson"; +} + +boost::optional topojson_datasource::get_geometry_type() const +{ + boost::optional result; + return result; +} + +mapnik::datasource::datasource_t topojson_datasource::type() const +{ + return type_; +} + +mapnik::box2d topojson_datasource::envelope() const +{ + return extent_; +} + +mapnik::layer_descriptor topojson_datasource::get_descriptor() const +{ + return desc_; +} + +mapnik::featureset_ptr topojson_datasource::features(mapnik::query const& q) const +{ + // if the query box intersects our world extent then query for features + mapnik::box2d const& b = q.get_bbox(); + if (extent_.intersects(b)) + { + box_type box(point_type(b.minx(),b.miny()),point_type(b.maxx(),b.maxy())); + index_array_ = tree_.find(box); + return std::make_shared(topo_, index_array_.begin(), index_array_.end()); + } + // otherwise return an empty featureset pointer + return mapnik::featureset_ptr(); +} + +mapnik::featureset_ptr topojson_datasource::features_at_point(mapnik::coord2d const& pt, double tol) const +{ + mapnik::box2d query_bbox(pt, pt); + query_bbox.pad(tol); + mapnik::query q(query_bbox); + std::vector const& desc = desc_.get_descriptors(); + std::vector::const_iterator itr = desc.begin(); + std::vector::const_iterator end = desc.end(); + for ( ;itr!=end;++itr) + { + q.add_property_name(itr->get_name()); + } + return features(q); +} diff --git a/plugins/input/topojson/topojson_datasource.hpp b/plugins/input/topojson/topojson_datasource.hpp new file mode 100644 index 000000000..69c2c84f6 --- /dev/null +++ b/plugins/input/topojson/topojson_datasource.hpp @@ -0,0 +1,81 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2012 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef TOPOJSON_DATASOURCE_HPP +#define TOPOJSON_DATASOURCE_HPP + +// mapnik +#include +#include +#include +#include +#include +#include +#include +#include +#include +// boost +#include + +#include +#include +#include +#include +#include +// stl +#include +#include +#include +#include +#include + +class topojson_datasource : public mapnik::datasource +{ +public: + typedef boost::geometry::model::d2::point_xy point_type; + typedef boost::geometry::model::box box_type; + typedef boost::geometry::index::rtree spatial_index_type; + + // constructor + topojson_datasource(mapnik::parameters const& params); + virtual ~topojson_datasource (); + mapnik::datasource::datasource_t type() const; + static const char * name(); + mapnik::featureset_ptr features(mapnik::query const& q) const; + mapnik::featureset_ptr features_at_point(mapnik::coord2d const& pt, double tol = 0) const; + mapnik::box2d envelope() const; + mapnik::layer_descriptor get_descriptor() const; + boost::optional get_geometry_type() const; +private: + mapnik::datasource::datasource_t type_; + std::map statistics_; + mapnik::layer_descriptor desc_; + std::string file_; + mapnik::box2d extent_; + std::shared_ptr tr_; + mapnik::topojson::topology topo_; + spatial_index_type tree_; + mutable std::deque index_array_; +}; + + +#endif // FILE_DATASOURCE_HPP diff --git a/plugins/input/topojson/topojson_featureset.cpp b/plugins/input/topojson/topojson_featureset.cpp new file mode 100644 index 000000000..e36702d87 --- /dev/null +++ b/plugins/input/topojson/topojson_featureset.cpp @@ -0,0 +1,52 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2013 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +// mapnik +#include +// stl +#include +#include +#include + +#include "topojson_featureset.hpp" + +topojson_featureset::topojson_featureset(mapnik::topojson::topology const& topo, + std::deque::const_iterator index_itr, + std::deque::const_iterator index_end) + : topo_(topo), + index_itr_(index_itr), + index_end_(index_end) {} + +topojson_featureset::~topojson_featureset() {} + +mapnik::feature_ptr topojson_featureset::next() +{ + if (index_itr_ != index_end_) + { + std::size_t index = *index_itr_++; + if ( index < topo_.geometries.size()) + { + return mapnik::feature_ptr(); // TODO + } + } + return mapnik::feature_ptr(); +} diff --git a/plugins/input/topojson/topojson_featureset.hpp b/plugins/input/topojson/topojson_featureset.hpp new file mode 100644 index 000000000..d6a1c93f9 --- /dev/null +++ b/plugins/input/topojson/topojson_featureset.hpp @@ -0,0 +1,48 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2013 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef TOPOJSON_FEATURESET_HPP +#define TOPOJSON_FEATURESET_HPP + +#include +#include "topojson_datasource.hpp" + +#include +#include + +class topojson_featureset : public mapnik::Featureset +{ +public: + topojson_featureset(mapnik::topojson::topology const& topo, + std::deque::const_iterator index_itr, + std::deque::const_iterator index_end); + virtual ~topojson_featureset(); + mapnik::feature_ptr next(); + +private: + mapnik::box2d box_; + mapnik::topojson::topology const& topo_; + std::deque::const_iterator index_itr_; + std::deque::const_iterator index_end_; +}; + +#endif // TOPOJSON_FEATURESET_HPP diff --git a/plugins/input/topojson/topojson_grammar.cpp b/plugins/input/topojson/topojson_grammar.cpp new file mode 100644 index 000000000..91655b0b9 --- /dev/null +++ b/plugins/input/topojson/topojson_grammar.cpp @@ -0,0 +1,35 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2013 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +// mapnik +#include +// stl +#include +// boost +#include + +namespace mapnik { namespace topojson { + +//template struct topojson_grammar; +template struct topojson_grammar > >; + +}}