add create_feature
helper method (geojson_value -> mapnik::feature_impl)
This commit is contained in:
parent
21a121df18
commit
493b662f16
1 changed files with 237 additions and 0 deletions
237
include/mapnik/json/create_feature.hpp
Normal file
237
include/mapnik/json/create_feature.hpp
Normal file
|
@ -0,0 +1,237 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* This file is part of Mapnik (c++ mapping toolkit)
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 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 MAPNIK_JSON_CREATE_FEATURE_HPP
|
||||||
|
#define MAPNIK_JSON_CREATE_FEATURE_HPP
|
||||||
|
|
||||||
|
#include <mapnik/json/json_grammar_config.hpp>
|
||||||
|
#include <mapnik/json/geojson_grammar_x3.hpp>
|
||||||
|
#include <mapnik/json/create_geometry.hpp>
|
||||||
|
#include <mapnik/util/conversions.hpp>
|
||||||
|
|
||||||
|
#include <mapnik/value.hpp>
|
||||||
|
#include <mapnik/unicode.hpp>
|
||||||
|
#include <mapnik/feature.hpp>
|
||||||
|
|
||||||
|
namespace mapnik { namespace json {
|
||||||
|
|
||||||
|
struct stringifier
|
||||||
|
{
|
||||||
|
std::string operator()(std::string const& val) const
|
||||||
|
{
|
||||||
|
return "\"" + val + "\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string operator()(value_null) const
|
||||||
|
{
|
||||||
|
return "null";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string operator()(value_bool val) const
|
||||||
|
{
|
||||||
|
return val ? "true" : "false";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string operator()(value_integer val) const
|
||||||
|
{
|
||||||
|
std::string str;
|
||||||
|
util::to_string(str, val);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string operator()(value_double val) const
|
||||||
|
{
|
||||||
|
std::string str;
|
||||||
|
util::to_string(str, val);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string operator()(mapnik::json::geojson_array const& array) const
|
||||||
|
{
|
||||||
|
std::string str = "[";
|
||||||
|
bool first = true;
|
||||||
|
for (auto const& val : array)
|
||||||
|
{
|
||||||
|
if (first) first = false;
|
||||||
|
else str += ",";
|
||||||
|
str += mapnik::util::apply_visitor(*this, val);
|
||||||
|
}
|
||||||
|
str += "]";
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string operator()(mapnik::json::geojson_object const& object, keys_map const& keys) const
|
||||||
|
{
|
||||||
|
std::string str = "{";
|
||||||
|
bool first = true;
|
||||||
|
for (auto const& kv : object)
|
||||||
|
{
|
||||||
|
auto itr = keys.right.find(std::get<0>(kv));
|
||||||
|
if (itr != keys.right.end())
|
||||||
|
{
|
||||||
|
if (first) first = false;
|
||||||
|
else str += ",";
|
||||||
|
str += "\"" + itr->second + "\"";
|
||||||
|
str += ":";
|
||||||
|
str += mapnik::util::apply_visitor(*this, kv.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
str += "}";
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
std::string operator()(T const&) const
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct attribute_value_visitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
attribute_value_visitor(mapnik::transcoder const& tr, keys_map const& keys)
|
||||||
|
: tr_(tr),
|
||||||
|
keys_(keys) {}
|
||||||
|
|
||||||
|
mapnik::value operator()(std::string const& val) const
|
||||||
|
{
|
||||||
|
return mapnik::value(tr_.transcode(val.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
mapnik::value operator()(mapnik::json::geojson_array const& array) const
|
||||||
|
{
|
||||||
|
std::string str = stringifier()(array);
|
||||||
|
return mapnik::value(tr_.transcode(str.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
mapnik::value operator()(mapnik::json::geojson_object const& object) const
|
||||||
|
{
|
||||||
|
std::string str = stringifier()(object, keys_);
|
||||||
|
return mapnik::value(tr_.transcode(str.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
mapnik::value operator() (mapnik::value_bool val) const
|
||||||
|
{
|
||||||
|
return mapnik::value(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
mapnik::value operator() (mapnik::value_integer val) const
|
||||||
|
{
|
||||||
|
return mapnik::value(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
mapnik::value operator() (mapnik::value_double val) const
|
||||||
|
{
|
||||||
|
return mapnik::value(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
mapnik::value operator()(T const& val) const
|
||||||
|
{
|
||||||
|
return mapnik::value_null{};
|
||||||
|
}
|
||||||
|
|
||||||
|
mapnik::transcoder const& tr_;
|
||||||
|
mapnik::json::keys_map const& keys_;
|
||||||
|
};
|
||||||
|
|
||||||
|
void create_feature(feature_impl & feature,
|
||||||
|
mapnik::json::geojson_value const& value,
|
||||||
|
mapnik::json::keys_map const& keys,
|
||||||
|
mapnik::transcoder const& tr)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!value.is<mapnik::json::geojson_object>())
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Expecting an GeoJSON object");
|
||||||
|
}
|
||||||
|
mapnik::json::geojson_object const& feature_value = mapnik::util::get<mapnik::json::geojson_object>(value);
|
||||||
|
for (auto const& elem : feature_value)
|
||||||
|
{
|
||||||
|
auto const key = std::get<0>(elem);
|
||||||
|
if (key == mapnik::json::well_known_names::geometry)
|
||||||
|
{
|
||||||
|
auto const& geom_value = std::get<1>(elem);
|
||||||
|
if (!geom_value.is<mapnik::json::geojson_object>())
|
||||||
|
{
|
||||||
|
throw std::runtime_error("\"geometry\": xxx <-- expecting an JSON object here");
|
||||||
|
}
|
||||||
|
auto const& geometry = mapnik::util::get<mapnik::json::geojson_object>(geom_value);
|
||||||
|
mapnik::geometry::geometry_types geom_type;
|
||||||
|
mapnik::json::positions const* coordinates = nullptr;
|
||||||
|
for (auto & elem2 : geometry)
|
||||||
|
{
|
||||||
|
auto const key2 = std::get<0>(elem2);
|
||||||
|
if (key2 == mapnik::json::well_known_names::type)
|
||||||
|
{
|
||||||
|
auto const& geom_type_value = std::get<1>(elem2);
|
||||||
|
if (!geom_type_value.is<mapnik::geometry::geometry_types>())
|
||||||
|
{
|
||||||
|
throw std::runtime_error("\"type\": xxx <-- expecting an GeoJSON geometry type here");
|
||||||
|
}
|
||||||
|
geom_type = mapnik::util::get<mapnik::geometry::geometry_types>(geom_type_value);
|
||||||
|
if (geom_type == mapnik::geometry::geometry_types::GeometryCollection)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("GeometryCollections are not allowed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (key2 == mapnik::json::well_known_names::coordinates)
|
||||||
|
{
|
||||||
|
auto const& coordinates_value = std::get<1>(elem2);
|
||||||
|
if (!coordinates_value.is<mapnik::json::positions>())
|
||||||
|
{
|
||||||
|
throw std::runtime_error("\"coordinates\": xxx <-- expecting an GeoJSON positions here");
|
||||||
|
}
|
||||||
|
coordinates = &mapnik::util::get<mapnik::json::positions>(coordinates_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mapnik::geometry::geometry<double> geom;
|
||||||
|
mapnik::json::create_geometry(geom, geom_type, *coordinates);
|
||||||
|
feature.set_geometry(std::move(geom));
|
||||||
|
}
|
||||||
|
else if (key == mapnik::json::well_known_names::properties)
|
||||||
|
{
|
||||||
|
auto const& prop_value = std::get<1>(elem);
|
||||||
|
if (!prop_value.is<mapnik::json::geojson_object>())
|
||||||
|
{
|
||||||
|
throw std::runtime_error("\"properties\": xxx <-- expecting an JSON object here");
|
||||||
|
}
|
||||||
|
auto const& properties = mapnik::util::get<mapnik::json::geojson_object>(prop_value);
|
||||||
|
auto end = keys.right.end();
|
||||||
|
for (auto const& kv : properties)
|
||||||
|
{
|
||||||
|
auto itr = keys.right.find(std::get<0>(kv));
|
||||||
|
if (itr != end)
|
||||||
|
{
|
||||||
|
feature.put_new(itr->second,
|
||||||
|
mapnik::util::apply_visitor(mapnik::json::attribute_value_visitor(tr, keys),
|
||||||
|
std::get<1>(kv)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}}
|
||||||
|
|
||||||
|
#endif //MAPNIK_JSON_CREATE_FEATURE_HPP
|
Loading…
Add table
Reference in a new issue