Merge branch 'master' into svg-parser-errors

This commit is contained in:
artemp 2015-07-21 09:46:38 +02:00
commit 52007b8019
45 changed files with 396 additions and 4224 deletions

View file

@ -110,14 +110,7 @@ PLUGINS = { # plugins with external dependencies
'pgraster': {'default':True,'path':None,'inc':'libpq-fe.h','lib':'pq','lang':'C'},
'gdal': {'default':True,'path':None,'inc':'gdal_priv.h','lib':'gdal','lang':'C++'},
'ogr': {'default':True,'path':None,'inc':'ogrsf_frmts.h','lib':'gdal','lang':'C++'},
# configured with custom paths, hence 'path': PREFIX/INCLUDES/LIBS
'occi': {'default':False,'path':'OCCI','inc':'occi.h','lib':'clntsh','lang':'C++'},
'sqlite': {'default':True,'path':'SQLITE','inc':'sqlite3.h','lib':'sqlite3','lang':'C'},
'rasterlite': {'default':False,'path':'RASTERLITE','inc':['sqlite3.h','rasterlite.h'],'lib':'rasterlite','lang':'C'},
# todo: osm plugin does also depend on libxml2 (but there is a separate check for that)
'osm': {'default':False,'path':None,'inc':None,'lib':None,'lang':'C'},
# plugins without external dependencies requiring CheckLibWithHeader...
'shape': {'default':True,'path':None,'inc':None,'lib':None,'lang':'C++'},
'csv': {'default':True,'path':None,'inc':None,'lib':None,'lang':'C++'},

View file

@ -44,6 +44,20 @@ We host our code on github.com/mapnik and encourage anyone interested to fork th
If you just have a question about the code, or a feature you want to discuss then feel free to create a new issue at github.com/mapnik-support.
## Plugins
Mapnik has a plugin interface for reading various geodata formats. Plugins are both viable inside of Mapnik core and also able to be used outside of Mapnik.
Plugins should be developed outside of core except in rare cases when most of the following are met:
- The plugin has no external dependencies or dependencies are easily installed
- The plugin has excellent unit tests
- The plugin has a maintainer willing to support the plugin over time
- Setup and testing of the plugin is easy on travis.ci (see .travis.yml)
Therefore plugins that depend on proprietary, unmaintained, or difficult to test third-party dependencies are not viable for Mapnik core. However they are still likely very valuable for the Mapnik community, so get in touch via https://github.com/mapnik/mapnik-support if we can help you develop your plugin outside of core.
## Code Philosophy

View file

@ -63,10 +63,9 @@ extract_bounding_box_grammar<Iterator, ErrorHandler>::extract_bounding_box_gramm
start = features(_r1)
;
features = iter_pos[_a = _1] >> -(lit('{') >> -lit("\"type\"")
>> lit(':') >> lit("\"FeatureCollection\"")
>> *(lit(',') >> (json.key_value - lit("\"features\"")))
>> lit(',') >> lit("\"features\"")
features = iter_pos[_a = _1] >> -(lit('{')
>> *((json.key_value - lit("\"features\"")) >> lit(','))
>> lit("\"features\"")
>> lit(':'))
>> lit('[') >> (feature(_r1,_a) % lit(',')) >> lit(']')
;

View file

@ -56,6 +56,7 @@ private:
datasource::datasource_t type_;
bool bbox_check_;
mutable box2d<double> extent_;
mutable bool dirty_extent_ = true;
};
}

View file

@ -45,7 +45,7 @@ using namespace agg;
template<class VertexContainer> class path_adapter : util::noncopyable
{
public:
using container_type = VertexContainer ;
using container_type = VertexContainer;
using self_type = path_adapter<VertexContainer>;
//--------------------------------------------------------------------

View file

@ -1,12 +0,0 @@
#
# To regenerate C++ class declarations & implementations for the Spatial
# object types of your database you should execute OTT in your server !
#
echo "TYPE MDSYS.SDO_POINT_TYPE AS SDOPointType" > spatial_types.typ
echo "TYPE MDSYS.SDO_GEOMETRY AS SDOGeometry" >> spatial_types.typ
ott userid=scott/tiger attraccess=private intype=spatial_types.typ code=cpp \
cppfile=spatial_classeso.cpp hfile=spatial_classesh.h mapfile=spatial_classesm.cpp \
mapfunc=RegisterClasses

View file

@ -1,74 +0,0 @@
#
# This file is part of Mapnik (c++ mapping toolkit)
#
# Copyright (C) 2015 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 ('plugin_base')
Import ('env')
PLUGIN_NAME = 'occi'
plugin_env = plugin_base.Clone()
plugin_sources = Split(
"""
%(PLUGIN_NAME)s_types.cpp
%(PLUGIN_NAME)s_datasource.cpp
%(PLUGIN_NAME)s_featureset.cpp
spatial_classesm.cpp
spatial_classeso.cpp
""" % locals()
)
libraries = [ 'clntsh', 'occi' ]
libraries.append('boost_system%s' % env['BOOST_APPEND'])
libraries.append(env['ICU_LIB_NAME'])
if env['PLUGIN_LINKING'] == 'shared':
libraries.append(env['MAPNIK_NAME'])
# libocci.dylib, at least for 11.2 links to libstdc++
# so we defer symbol resolution to runtime in order to
# dodge linking errors like
# Undefined symbols for architecture x86_64:
# "std::string::_Rep::_M_destroy(std::allocator<char> const&)", referenced from:
# RegisterClasses(oracle::occi::Environment*) in spatial_classesm.os
if env['PLATFORM'] == 'Darwin':
plugin_env.Append(LINKFLAGS='-undefined dynamic_lookup')
TARGET = plugin_env.SharedLibrary('../%s' % PLUGIN_NAME,
SHLIBPREFIX='',
SHLIBSUFFIX='.input',
source=plugin_sources,
LIBS=libraries)
# 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')

View file

@ -1,641 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2015 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 "occi_datasource.hpp"
#include "occi_featureset.hpp"
// mapnik
#include <mapnik/debug.hpp>
#include <mapnik/boolean.hpp>
#include <mapnik/sql_utils.hpp>
#include <mapnik/timer.hpp>
#include <mapnik/value_types.hpp>
// boost
#include <boost/algorithm/string.hpp>
#include <boost/tokenizer.hpp>
// stl
#include <string>
#include <algorithm>
#include <set>
#include <sstream>
#include <iomanip>
using mapnik::datasource;
using mapnik::parameters;
using mapnik::query;
using mapnik::featureset_ptr;
using mapnik::layer_descriptor;
using mapnik::attribute_descriptor;
using mapnik::datasource_exception;
using mapnik::box2d;
using mapnik::coord2d;
using oracle::occi::Environment;
using oracle::occi::Connection;
using oracle::occi::Statement;
using oracle::occi::ResultSet;
using oracle::occi::MetaData;
using oracle::occi::SQLException;
using oracle::occi::Type;
using oracle::occi::StatelessConnectionPool;
const double occi_datasource::FMAX = std::numeric_limits<double>::max();
const std::string occi_datasource::METADATA_TABLE = "USER_SDO_GEOM_METADATA";
DATASOURCE_PLUGIN(occi_datasource)
occi_datasource::occi_datasource(parameters const& params)
: datasource (params),
type_(datasource::Vector),
fields_(*params.get<std::string>("fields", "*")),
geometry_field_(*params.get<std::string>("geometry_field", "")),
srid_initialized_(false),
extent_initialized_(false),
bbox_token_("!bbox!"),
scale_denom_token_("!scale_denominator!"),
pixel_width_token_("!pixel_width!"),
pixel_height_token_("!pixel_height!"),
desc_(occi_datasource::name(), *params.get<std::string>("encoding", "utf-8")),
use_wkb_(*params.get<mapnik::boolean_type>("use_wkb", false)),
row_limit_(*params.get<mapnik::value_integer>("row_limit", 0)),
row_prefetch_(*params.get<mapnik::value_integer>("row_prefetch", 100)),
pool_(0),
conn_(0)
{
#ifdef MAPNIK_STATS
mapnik::progress_timer __stats__(std::clog, "occi_datasource::init");
#endif
if (! params.get<std::string>("user")) throw datasource_exception("OCCI Plugin: no <user> specified");
if (! params.get<std::string>("password")) throw datasource_exception("OCCI Plugin: no <password> specified");
if (! params.get<std::string>("host")) throw datasource_exception("OCCI Plugin: no <host> string specified");
boost::optional<std::string> table = params.get<std::string>("table");
if (! table)
{
throw datasource_exception("OCCI Plugin: no <table> parameter specified");
}
else
{
table_ = *table;
}
estimate_extent_ = *params.get<mapnik::boolean_type>("estimate_extent",false);
use_spatial_index_ = *params.get<mapnik::boolean_type>("use_spatial_index",true);
use_connection_pool_ = *params.get<mapnik::boolean_type>("use_connection_pool",true);
boost::optional<std::string> ext = params.get<std::string>("extent");
if (ext) extent_initialized_ = extent_.from_string(*ext);
boost::optional<mapnik::value_integer> srid = params.get<mapnik::value_integer>("srid");
if (srid)
{
srid_ = *srid;
srid_initialized_ = true;
}
// connect to environment
if (use_connection_pool_)
{
try
{
pool_ = occi_environment::instance().create_pool(
*params.get<std::string>("user"),
*params.get<std::string>("password"),
*params.get<std::string>("host"),
*params.get<mapnik::value_integer>("max_size", 5),
*params.get<mapnik::value_integer>("initial_size", 1),
1);
}
catch (SQLException& ex)
{
throw datasource_exception("OCCI Plugin: " + ex.getMessage());
}
}
else
{
try
{
conn_ = occi_environment::instance().create_connection(
*params.get<std::string>("user"),
*params.get<std::string>("password"),
*params.get<std::string>("host"));
}
catch (SQLException& ex)
{
throw datasource_exception("OCCI Plugin: " + ex.getMessage());
}
}
// extract real table name
table_name_ = mapnik::sql_utils::table_from_sql(table_);
// get SRID and/or GEOMETRY_FIELD from metadata table only if we need to
if (! srid_initialized_ || geometry_field_ == "")
{
#ifdef MAPNIK_STATS
mapnik::progress_timer __stats__(std::clog, "occi_datasource::get_srid_and_geometry_field");
#endif
std::ostringstream s;
s << "SELECT srid, column_name FROM " << METADATA_TABLE << " WHERE";
s << " LOWER(table_name) = LOWER('" << table_name_ << "')";
if (geometry_field_ != "")
{
s << " AND LOWER(column_name) = LOWER('" << geometry_field_ << "')";
}
MAPNIK_LOG_DEBUG(occi) << "occi_datasource: " << s.str();
try
{
occi_connection_ptr conn;
if (use_connection_pool_) conn.set_pool(pool_);
else conn.set_connection(conn_, false);
ResultSet* rs = conn.execute_query(s.str());
if (rs && rs->next ())
{
if (! srid_initialized_)
{
srid_ = rs->getInt(1);
srid_initialized_ = true;
}
if (geometry_field_ == "")
{
geometry_field_ = rs->getString(2);
}
}
}
catch (SQLException& ex)
{
throw datasource_exception("OCCI Plugin: " + ex.getMessage());
}
}
// get columns description
{
#ifdef MAPNIK_STATS
mapnik::progress_timer __stats__(std::clog, "occi_datasource::get_column_description");
#endif
std::ostringstream s;
s << "SELECT " << fields_ << " FROM (" << table_name_ << ") WHERE ROWNUM < 1";
MAPNIK_LOG_DEBUG(occi) << "occi_datasource: " << s.str();
try
{
occi_connection_ptr conn;
if (use_connection_pool_) conn.set_pool(pool_);
else conn.set_connection(conn_, false);
ResultSet* rs = conn.execute_query(s.str());
if (rs)
{
std::vector<MetaData> listOfColumns = rs->getColumnListMetaData();
for (unsigned int i = 0; i < listOfColumns.size(); ++i)
{
MetaData columnObj = listOfColumns[i];
std::string fld_name = columnObj.getString(MetaData::ATTR_NAME);
int type_oid = columnObj.getInt(MetaData::ATTR_DATA_TYPE);
/*
int type_code = columnObj.getInt(MetaData::ATTR_TYPECODE);
if (type_code == OCCI_TYPECODE_OBJECT)
{
desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Object));
continue;
}
*/
switch (type_oid)
{
case oracle::occi::OCCIBOOL:
desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Boolean));
break;
case oracle::occi::OCCIINT:
case oracle::occi::OCCIUNSIGNED_INT:
desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Integer));
break;
case oracle::occi::OCCIFLOAT:
case oracle::occi::OCCIBFLOAT:
case oracle::occi::OCCIDOUBLE:
case oracle::occi::OCCIBDOUBLE:
case oracle::occi::OCCINUMBER:
case oracle::occi::OCCI_SQLT_NUM:
desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Double));
break;
case oracle::occi::OCCICHAR:
case oracle::occi::OCCISTRING:
case oracle::occi::OCCI_SQLT_AFC:
case oracle::occi::OCCI_SQLT_AVC:
case oracle::occi::OCCI_SQLT_CHR:
case oracle::occi::OCCI_SQLT_LNG:
case oracle::occi::OCCI_SQLT_LVC:
case oracle::occi::OCCI_SQLT_STR:
case oracle::occi::OCCI_SQLT_VCS:
case oracle::occi::OCCI_SQLT_VNU:
case oracle::occi::OCCI_SQLT_VBI:
case oracle::occi::OCCI_SQLT_VST:
case oracle::occi::OCCIROWID:
case oracle::occi::OCCI_SQLT_RDD:
case oracle::occi::OCCI_SQLT_RID:
case oracle::occi::OCCIDATE:
case oracle::occi::OCCI_SQLT_DAT:
case oracle::occi::OCCI_SQLT_DATE:
case oracle::occi::OCCI_SQLT_TIME:
case oracle::occi::OCCI_SQLT_TIME_TZ:
case oracle::occi::OCCITIMESTAMP:
case oracle::occi::OCCI_SQLT_TIMESTAMP:
case oracle::occi::OCCI_SQLT_TIMESTAMP_LTZ:
case oracle::occi::OCCI_SQLT_TIMESTAMP_TZ:
desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::String));
break;
case oracle::occi::OCCIINTERVALDS:
case oracle::occi::OCCIINTERVALYM:
case oracle::occi::OCCI_SQLT_INTERVAL_YM:
case oracle::occi::OCCI_SQLT_INTERVAL_DS:
case oracle::occi::OCCIANYDATA:
case oracle::occi::OCCIBLOB:
case oracle::occi::OCCIBFILE:
case oracle::occi::OCCIBYTES:
case oracle::occi::OCCICLOB:
case oracle::occi::OCCIVECTOR:
case oracle::occi::OCCIMETADATA:
case oracle::occi::OCCIPOBJECT:
case oracle::occi::OCCIREF:
case oracle::occi::OCCIREFANY:
case oracle::occi::OCCISTREAM:
case oracle::occi::OCCICURSOR:
case oracle::occi::OCCI_SQLT_FILE:
case oracle::occi::OCCI_SQLT_CFILE:
case oracle::occi::OCCI_SQLT_REF:
case oracle::occi::OCCI_SQLT_CLOB:
case oracle::occi::OCCI_SQLT_BLOB:
case oracle::occi::OCCI_SQLT_RSET:
MAPNIK_LOG_WARN(occi) << "occi_datasource: Unsupported datatype "
<< occi_enums::resolve_datatype(type_oid)
<< " (type_oid=" << type_oid << ")";
break;
default:
MAPNIK_LOG_WARN(occi) << "occi_datasource: Unknown datatype "
<< "(type_oid=" << type_oid << ")";
break;
}
}
}
}
catch (SQLException& ex)
{
throw datasource_exception(ex.getMessage());
}
}
}
occi_datasource::~occi_datasource()
{
if (use_connection_pool_)
{
if (pool_ != 0)
{
occi_environment::instance().destroy_pool(pool_);
}
}
else
{
if (conn_ != 0)
{
occi_environment::instance().destroy_connection(conn_);
}
}
}
const char * occi_datasource::name()
{
return "occi";
}
mapnik::datasource::datasource_t occi_datasource::type() const
{
return type_;
}
box2d<double> occi_datasource::envelope() const
{
if (extent_initialized_) return extent_;
double lox = 0.0, loy = 0.0, hix = 0.0, hiy = 0.0;
if (estimate_extent_)
{
#ifdef MAPNIK_STATS
mapnik::progress_timer __stats__(std::clog, "occi_datasource::envelope(estimate_extent)");
#endif
std::ostringstream s;
s << "SELECT MIN(c.x), MIN(c.y), MAX(c.x), MAX(c.y) FROM ";
s << " (SELECT SDO_AGGR_MBR(" << geometry_field_ << ") shape FROM " << table_ << ") a, ";
s << " TABLE(SDO_UTIL.GETVERTICES(a.shape)) c";
MAPNIK_LOG_DEBUG(occi) << "occi_datasource: " << s.str();
try
{
occi_connection_ptr conn;
if (use_connection_pool_) conn.set_pool(pool_);
else conn.set_connection(conn_, false);
ResultSet* rs = conn.execute_query(s.str());
if (rs && rs->next())
{
lox = rs->getDouble(1);
loy = rs->getDouble(2);
hix = rs->getDouble(3);
hiy = rs->getDouble(4);
extent_.init(lox, loy, hix, hiy);
extent_initialized_ = true;
}
}
catch (SQLException& ex)
{
throw datasource_exception("OCCI Plugin: " + ex.getMessage());
}
}
else if (use_spatial_index_)
{
#ifdef MAPNIK_STATS
mapnik::progress_timer __stats__(std::clog, "occi_datasource::envelope(use_spatial_index)");
#endif
std::ostringstream s;
s << "SELECT dim.sdo_lb, dim.sdo_ub FROM ";
s << METADATA_TABLE << " m, TABLE(m.diminfo) dim ";
s << " WHERE LOWER(m.table_name) = LOWER('" << table_name_ << "') AND dim.sdo_dimname = 'X'";
s << " UNION ";
s << "SELECT dim.sdo_lb, dim.sdo_ub FROM ";
s << METADATA_TABLE << " m, TABLE(m.diminfo) dim ";
s << " WHERE LOWER(m.table_name) = LOWER('" << table_name_ << "') AND dim.sdo_dimname = 'Y'";
MAPNIK_LOG_DEBUG(occi) << "occi_datasource: " << s.str();
try
{
occi_connection_ptr conn;
if (use_connection_pool_) conn.set_pool(pool_);
else conn.set_connection(conn_, false);
ResultSet* rs = conn.execute_query(s.str());
if (rs)
{
if (rs->next())
{
lox = rs->getDouble(1);
hix = rs->getDouble(2);
}
if (rs->next())
{
loy = rs->getDouble(1);
hiy = rs->getDouble(2);
}
extent_.init(lox, loy, hix, hiy);
extent_initialized_ = true;
}
}
catch (SQLException& ex)
{
throw datasource_exception("OCCI Plugin: " + ex.getMessage());
}
}
if (! extent_initialized_)
{
throw datasource_exception("OCCI Plugin: unable to determine the extent of a <occi> table");
}
return extent_;
}
boost::optional<mapnik::datasource_geometry_t> occi_datasource::get_geometry_type() const
{
return boost::optional<mapnik::datasource_geometry_t>();
}
layer_descriptor occi_datasource::get_descriptor() const
{
return desc_;
}
std::string occi_datasource::sql_bbox(box2d<double> const& env) const
{
std::ostringstream b;
b << std::setprecision(16);
b << "MDSYS.SDO_GEOMETRY(" << SDO_GTYPE_2DPOLYGON << "," << srid_ << ",NULL,";
b << " MDSYS.SDO_ELEM_INFO_ARRAY(1," << SDO_ETYPE_POLYGON << "," << SDO_INTERPRETATION_RECTANGLE << "),";
b << " MDSYS.SDO_ORDINATE_ARRAY(";
b << env.minx() << "," << env.miny() << ", ";
b << env.maxx() << "," << env.maxy() << "))";
return b.str();
}
std::string occi_datasource::populate_tokens(std::string const& sql, double scale_denom, box2d<double> const& env, double pixel_width, double pixel_height) const
{
std::string populated_sql = sql;
if (boost::algorithm::icontains(populated_sql, scale_denom_token_))
{
std::ostringstream ss;
ss << scale_denom;
boost::algorithm::replace_all(populated_sql, scale_denom_token_, ss.str());
}
if (boost::algorithm::icontains(sql, pixel_width_token_))
{
std::ostringstream ss;
ss << pixel_width;
boost::algorithm::replace_all(populated_sql, pixel_width_token_, ss.str());
}
if (boost::algorithm::icontains(sql, pixel_height_token_))
{
std::ostringstream ss;
ss << pixel_height;
boost::algorithm::replace_all(populated_sql, pixel_height_token_, ss.str());
}
if (boost::algorithm::icontains(populated_sql, bbox_token_))
{
boost::algorithm::replace_all(populated_sql, bbox_token_, sql_bbox(env));
}
return populated_sql;
}
featureset_ptr occi_datasource::features(query const& q) const
{
#ifdef MAPNIK_STATS
mapnik::progress_timer __stats__(std::clog, "occi_datasource::features");
#endif
box2d<double> const& box = q.get_bbox();
const double px_gw = 1.0 / std::get<0>(q.resolution());
const double px_gh = 1.0 / std::get<1>(q.resolution());
const double scale_denom = q.scale_denominator();
std::ostringstream s;
s << "SELECT ";
if (use_wkb_)
{
s << "SDO_UTIL.TO_WKBGEOMETRY(" << geometry_field_ << ")";
}
else
{
s << geometry_field_;
}
std::set<std::string> const& props = q.property_names();
std::set<std::string>::const_iterator pos = props.begin();
std::set<std::string>::const_iterator end = props.end();
mapnik::context_ptr ctx = std::make_shared<mapnik::context_type>();
for (; pos != end; ++pos)
{
s << ", " << *pos;
ctx->push(*pos);
}
std::string query = populate_tokens(table_, scale_denom, box, px_gw, px_gh);
if (use_spatial_index_)
{
std::ostringstream spatial_sql;
spatial_sql << " WHERE SDO_FILTER(";
spatial_sql << geometry_field_ << "," << sql_bbox(box);
spatial_sql << ", 'querytype = WINDOW') = 'TRUE'";
if (boost::algorithm::ifind_first(query, "WHERE"))
{
boost::algorithm::ireplace_first(query, "WHERE", spatial_sql.str() + " AND ");
}
else if (boost::algorithm::ifind_first(query, table_name_))
{
boost::algorithm::ireplace_first(query, table_name_, table_name_ + " " + spatial_sql.str());
}
else
{
MAPNIK_LOG_WARN(occi) << "occi_datasource: cannot determine where to add the spatial filter declaration";
}
}
s << " FROM " << query;
if (row_limit_ > 0)
{
s << " WHERE ROWNUM < " << row_limit_;
}
MAPNIK_LOG_DEBUG(occi) << "occi_datasource: " << s.str();
return std::make_shared<occi_featureset>(pool_,
conn_,
ctx,
s.str(),
desc_.get_encoding(),
use_connection_pool_,
use_wkb_,
row_prefetch_);
}
featureset_ptr occi_datasource::features_at_point(coord2d const& pt, double tol) const
{
#ifdef MAPNIK_STATS
mapnik::progress_timer __stats__(std::clog, "occi_datasource::features_at_point");
#endif
std::ostringstream s;
s << "SELECT ";
if (use_wkb_)
{
s << "SDO_UTIL.TO_WKBGEOMETRY(" << geometry_field_ << ")";
}
else
{
s << geometry_field_;
}
std::vector<attribute_descriptor>::const_iterator itr = desc_.get_descriptors().begin();
std::vector<attribute_descriptor>::const_iterator end = desc_.get_descriptors().end();
mapnik::context_ptr ctx = std::make_shared<mapnik::context_type>();
while (itr != end)
{
s << ", " << itr->get_name();
ctx->push(itr->get_name());
++itr;
}
box2d<double> box(pt.x - tol, pt.y - tol, pt.x + tol, pt.y + tol);
std::string query = populate_tokens(table_, FMAX, box, 0, 0);
if (use_spatial_index_)
{
std::ostringstream spatial_sql;
spatial_sql << " WHERE SDO_FILTER(";
spatial_sql << geometry_field_ << "," << sql_bbox(box);
spatial_sql << ", 'querytype = WINDOW') = 'TRUE'";
if (boost::algorithm::ifind_first(query, "WHERE"))
{
boost::algorithm::ireplace_first(query, "WHERE", spatial_sql.str() + " AND ");
}
else if (boost::algorithm::ifind_first(query, table_name_))
{
boost::algorithm::ireplace_first(query, table_name_, table_name_ + " " + spatial_sql.str());
}
else
{
MAPNIK_LOG_WARN(occi) << "occi_datasource: Cannot determine where to add the spatial filter declaration";
}
}
s << " FROM " << query;
if (row_limit_ > 0)
{
s << " WHERE ROWNUM < " << row_limit_;
}
MAPNIK_LOG_DEBUG(occi) << "occi_datasource: " << s.str();
return std::make_shared<occi_featureset>(pool_,
conn_,
ctx,
s.str(),
desc_.get_encoding(),
use_connection_pool_,
use_wkb_,
row_prefetch_);
}

View file

@ -1,95 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2015 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 OCCI_DATASOURCE_HPP
#define OCCI_DATASOURCE_HPP
// mapnik
#include <mapnik/datasource.hpp>
#include <mapnik/params.hpp>
#include <mapnik/query.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/box2d.hpp>
#include <mapnik/coord.hpp>
#include <mapnik/feature_layer_desc.hpp>
#include <mapnik/value_types.hpp>
// boost
#include <boost/optional.hpp>
#include <memory>
// stl
#include <vector>
#include <string>
// oci
#include "occi_types.hpp"
class occi_datasource : public mapnik::datasource
{
public:
occi_datasource(mapnik::parameters const& params);
virtual ~occi_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<double> envelope() const;
boost::optional<mapnik::datasource_geometry_t> get_geometry_type() const;
mapnik::layer_descriptor get_descriptor() const;
private:
std::string sql_bbox(mapnik::box2d<double> const& env) const;
std::string populate_tokens(std::string const& sql,
double scale_denom,
mapnik::box2d<double> const& env,
double pixel_width,
double pixel_height) const;
static const std::string METADATA_TABLE;
static const double FMAX;
mapnik::datasource::datasource_t type_;
std::string table_;
std::string table_name_;
std::string fields_;
std::string geometry_field_;
int srid_;
bool srid_initialized_;
mutable bool extent_initialized_;
mutable mapnik::box2d<double> extent_;
const std::string bbox_token_;
const std::string scale_denom_token_;
const std::string pixel_width_token_;
const std::string pixel_height_token_;
mapnik::layer_descriptor desc_;
bool use_wkb_;
mapnik::value_integer row_limit_;
int row_prefetch_;
oracle::occi::StatelessConnectionPool* pool_;
oracle::occi::Connection* conn_;
bool use_connection_pool_;
bool use_spatial_index_;
bool estimate_extent_;
};
#endif // OCCI_DATASOURCE_HPP

View file

@ -1,516 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2015 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 <mapnik/global.hpp>
#include <mapnik/debug.hpp>
#include <mapnik/box2d.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/feature_layer_desc.hpp>
#include <mapnik/wkb.hpp>
#include <mapnik/unicode.hpp>
#include <mapnik/value_types.hpp>
#include <mapnik/feature_factory.hpp>
#include <mapnik/make_unique.hpp>
// ogr
#include "occi_featureset.hpp"
using mapnik::query;
using mapnik::box2d;
using mapnik::feature_ptr;
using mapnik::geometry_type;
using mapnik::geometry_utils;
using mapnik::transcoder;
using mapnik::datasource_exception;
using mapnik::feature_factory;
using oracle::occi::Connection;
using oracle::occi::Statement;
using oracle::occi::ResultSet;
using oracle::occi::StatelessConnectionPool;
using oracle::occi::MetaData;
using oracle::occi::SQLException;
using oracle::occi::Type;
using oracle::occi::Number;
using oracle::occi::Blob;
occi_featureset::occi_featureset(StatelessConnectionPool* pool,
Connection* conn,
mapnik::context_ptr const& ctx,
std::string const& sqlstring,
std::string const& encoding,
bool use_connection_pool,
bool use_wkb,
unsigned prefetch_rows)
: rs_(nullptr),
tr_(new transcoder(encoding)),
feature_id_(1),
ctx_(ctx),
use_wkb_(use_wkb)
{
if (use_connection_pool)
{
conn_.set_pool(pool);
}
else
{
conn_.set_connection(conn, false);
}
try
{
rs_ = conn_.execute_query(sqlstring, prefetch_rows);
}
catch (SQLException &ex)
{
MAPNIK_LOG_ERROR(occi) << "OCCI Plugin: error processing " << sqlstring << " : " << ex.getMessage();
rs_ = nullptr;
}
}
occi_featureset::~occi_featureset()
{
}
feature_ptr occi_featureset::next()
{
while (rs_ != nullptr && rs_->next() == oracle::occi::ResultSet::DATA_AVAILABLE)
{
feature_ptr feature(feature_factory::create(ctx_, feature_id_));
if (use_wkb_)
{
Blob blob = rs_->getBlob(1);
blob.open(oracle::occi::OCCI_LOB_READONLY);
unsigned int size = blob.length();
if (buffer_.size() < size)
{
buffer_.resize(size);
}
oracle::occi::Stream* instream = blob.getStream(1, 0);
instream->readBuffer(buffer_.data(), size);
blob.closeStream(instream);
blob.close();
if (! geometry_utils::from_wkb(feature->paths(), buffer_.data(), size))
{
continue;
}
}
else
{
const std::unique_ptr<SDOGeometry> geom(dynamic_cast<SDOGeometry*>(rs_->getObject(1)));
if (geom.get())
{
convert_geometry(geom.get(), feature);
}
else
{
continue;
}
}
std::vector<MetaData> listOfColumns = rs_->getColumnListMetaData();
for (unsigned int i = 1; i < listOfColumns.size(); ++i)
{
MetaData columnObj = listOfColumns[i];
std::string fld_name = columnObj.getString(MetaData::ATTR_NAME);
int type_oid = columnObj.getInt(MetaData::ATTR_DATA_TYPE);
/*
int type_code = columnObj.getInt(MetaData::ATTR_TYPECODE);
if (type_code == OCCI_TYPECODE_OBJECT)
{
continue;
}
*/
switch (type_oid)
{
case oracle::occi::OCCIBOOL:
feature->put(fld_name, (rs_->getInt(i + 1) != 0));
break;
case oracle::occi::OCCIINT:
case oracle::occi::OCCIUNSIGNED_INT:
feature->put(fld_name, static_cast<mapnik::value_integer>(rs_->getInt(i + 1)));
break;
case oracle::occi::OCCIFLOAT:
case oracle::occi::OCCIBFLOAT:
feature->put(fld_name, (double)rs_->getFloat(i + 1));
break;
case oracle::occi::OCCIDOUBLE:
case oracle::occi::OCCIBDOUBLE:
case oracle::occi::OCCINUMBER:
case oracle::occi::OCCI_SQLT_NUM:
feature->put(fld_name, rs_->getDouble(i + 1));
break;
case oracle::occi::OCCICHAR:
case oracle::occi::OCCISTRING:
case oracle::occi::OCCI_SQLT_AFC:
case oracle::occi::OCCI_SQLT_AVC:
case oracle::occi::OCCI_SQLT_CHR:
case oracle::occi::OCCI_SQLT_LNG:
case oracle::occi::OCCI_SQLT_LVC:
case oracle::occi::OCCI_SQLT_STR:
case oracle::occi::OCCI_SQLT_VCS:
case oracle::occi::OCCI_SQLT_VNU:
case oracle::occi::OCCI_SQLT_VBI:
case oracle::occi::OCCI_SQLT_VST:
case oracle::occi::OCCIROWID:
case oracle::occi::OCCI_SQLT_RDD:
case oracle::occi::OCCI_SQLT_RID:
case oracle::occi::OCCIDATE:
case oracle::occi::OCCI_SQLT_DAT:
case oracle::occi::OCCI_SQLT_DATE:
case oracle::occi::OCCI_SQLT_TIME:
case oracle::occi::OCCI_SQLT_TIME_TZ:
case oracle::occi::OCCITIMESTAMP:
case oracle::occi::OCCI_SQLT_TIMESTAMP:
case oracle::occi::OCCI_SQLT_TIMESTAMP_LTZ:
case oracle::occi::OCCI_SQLT_TIMESTAMP_TZ:
feature->put(fld_name, static_cast<mapnik::value_unicode_string>(tr_->transcode(rs_->getString(i + 1).c_str())));
break;
case oracle::occi::OCCIINTERVALDS:
case oracle::occi::OCCIINTERVALYM:
case oracle::occi::OCCI_SQLT_INTERVAL_YM:
case oracle::occi::OCCI_SQLT_INTERVAL_DS:
case oracle::occi::OCCIANYDATA:
case oracle::occi::OCCIBLOB:
case oracle::occi::OCCIBFILE:
case oracle::occi::OCCIBYTES:
case oracle::occi::OCCICLOB:
case oracle::occi::OCCIVECTOR:
case oracle::occi::OCCIMETADATA:
case oracle::occi::OCCIPOBJECT:
case oracle::occi::OCCIREF:
case oracle::occi::OCCIREFANY:
case oracle::occi::OCCISTREAM:
case oracle::occi::OCCICURSOR:
case oracle::occi::OCCI_SQLT_FILE:
case oracle::occi::OCCI_SQLT_CFILE:
case oracle::occi::OCCI_SQLT_REF:
case oracle::occi::OCCI_SQLT_CLOB:
case oracle::occi::OCCI_SQLT_BLOB:
case oracle::occi::OCCI_SQLT_RSET:
{
MAPNIK_LOG_WARN(occi) << "occi_featureset: Unsupported datatype "
<< occi_enums::resolve_datatype(type_oid)
<< " (type_oid=" << type_oid << ")";
break;
}
default: // shouldn't get here
{
MAPNIK_LOG_WARN(occi) << "occi_featureset: Unknown datatype "
<< "(type_oid=" << type_oid << ")";
break;
}
}
}
++feature_id_;
return feature;
}
return feature_ptr();
}
void occi_featureset::convert_geometry(SDOGeometry* geom, feature_ptr feature)
{
int gtype = (int)geom->getSdo_gtype();
int dimensions = gtype / 1000;
int lrsvalue = (gtype - dimensions * 1000) / 100;
int geomtype = (gtype - dimensions * 1000 - lrsvalue * 100);
const std::vector<Number>& elem_info = geom->getSdo_elem_info();
const std::vector<Number>& ordinates = geom->getSdo_ordinates();
const int ordinates_size = (int)ordinates.size();
switch (geomtype)
{
case SDO_GTYPE_POINT:
{
SDOPointType* sdopoint = geom->getSdo_point();
if (sdopoint && ! sdopoint->isNull())
{
std::unique_ptr<geometry_type> point = std::make_unique<geometry_type>(mapnik::geometry::geometry_types::Point);
point->move_to(sdopoint->getX(), sdopoint->getY());
feature->add_geometry(point.release());
}
}
break;
case SDO_GTYPE_LINE:
{
if (ordinates_size >= dimensions)
{
const bool is_single_geom = true;
const bool is_point_type = false;
convert_ordinates(feature,
mapnik::geometry::geometry_types::LineString,
elem_info,
ordinates,
dimensions,
is_single_geom,
is_point_type);
}
}
break;
case SDO_GTYPE_POLYGON:
{
if (ordinates_size >= dimensions)
{
const bool is_single_geom = true;
const bool is_point_type = false;
convert_ordinates(feature,
mapnik::geometry::geometry_types::Polygon,
elem_info,
ordinates,
dimensions,
is_single_geom,
is_point_type);
}
}
break;
case SDO_GTYPE_MULTIPOINT:
{
if (ordinates_size >= dimensions)
{
const bool is_single_geom = false;
const bool is_point_type = true;
convert_ordinates(feature,
mapnik::geometry::geometry_types::Point,
elem_info,
ordinates,
dimensions,
is_single_geom,
is_point_type);
}
}
break;
case SDO_GTYPE_MULTILINE:
{
if (ordinates_size >= dimensions)
{
const bool is_single_geom = false;
const bool is_point_type = false;
convert_ordinates(feature,
mapnik::geometry::geometry_types::LineString,
elem_info,
ordinates,
dimensions,
is_single_geom,
is_point_type);
}
}
break;
case SDO_GTYPE_MULTIPOLYGON:
{
if (ordinates_size >= dimensions)
{
const bool is_single_geom = false;
const bool is_point_type = false;
convert_ordinates(feature,
mapnik::geometry::geometry_types::Polygon,
elem_info,
ordinates,
dimensions,
is_single_geom,
is_point_type);
}
}
break;
case SDO_GTYPE_COLLECTION:
{
if (ordinates_size >= dimensions)
{
const bool is_single_geom = false;
const bool is_point_type = false;
convert_ordinates(feature,
mapnik::geometry::geometry_types::Polygon,
elem_info,
ordinates,
dimensions,
is_single_geom,
is_point_type);
}
}
break;
case SDO_GTYPE_UNKNOWN:
default:
{
MAPNIK_LOG_WARN(occi) << "occi_featureset: Unknown oracle enum "
<< occi_enums::resolve_gtype(geomtype)
<< "(gtype=" << gtype << ")";
}
break;
}
}
void occi_featureset::convert_ordinates(mapnik::feature_ptr feature,
const mapnik::geometry_type::types& geom_type,
const std::vector<Number>& elem_info,
const std::vector<Number>& ordinates,
const int dimensions,
const bool is_single_geom,
const bool is_point_geom)
{
const int elem_size = elem_info.size();
const int ord_size = ordinates.size();
if (elem_size >= 0)
{
int offset = elem_info[0];
int etype = elem_info[1];
int interp = elem_info[2];
if (! is_single_geom && elem_size > SDO_ELEM_INFO_SIZE)
{
geometry_type* geom = new geometry_type(geom_type);
for (int i = SDO_ELEM_INFO_SIZE; i < elem_size; i+=3)
{
int next_offset = elem_info[i];
int next_etype = elem_info[i + 1];
int next_interp = elem_info[i + 2];
bool is_linear_element = true;
bool is_unknown_etype = false;
mapnik::geometry_type::types gtype = mapnik::geometry::geometry_types::Point;
switch (etype)
{
case SDO_ETYPE_POINT:
if (interp == SDO_INTERPRETATION_POINT) {}
if (interp > SDO_INTERPRETATION_POINT) {}
gtype = mapnik::geometry::geometry_types::Point;
break;
case SDO_ETYPE_LINESTRING:
if (interp == SDO_INTERPRETATION_STRAIGHT) {}
if (interp == SDO_INTERPRETATION_CIRCULAR) {}
gtype = mapnik::geometry::geometry_types::LineString;
break;
case SDO_ETYPE_POLYGON:
case SDO_ETYPE_POLYGON_INTERIOR:
if (interp == SDO_INTERPRETATION_STRAIGHT) {}
if (interp == SDO_INTERPRETATION_CIRCULAR) {}
if (interp == SDO_INTERPRETATION_RECTANGLE) {}
if (interp == SDO_INTERPRETATION_CIRCLE) {}
gtype = mapnik::geometry::geometry_types::Polygon;
break;
case SDO_ETYPE_COMPOUND_LINESTRING:
case SDO_ETYPE_COMPOUND_POLYGON:
case SDO_ETYPE_COMPOUND_POLYGON_INTERIOR:
// interp = next ETYPE to consider
is_linear_element = false;
gtype = mapnik::geometry::geometry_types::Polygon;
break;
case SDO_ETYPE_UNKNOWN: // unknown
default:
is_unknown_etype = true;
break;
}
if (is_unknown_etype)
{
break;
}
if (is_linear_element)
{
if (geom)
{
feature->add_geometry(geom);
}
geom = new geometry_type(gtype);
fill_geometry_type(geom,
offset - 1,
next_offset - 1,
ordinates,
dimensions,
is_point_geom);
}
offset = next_offset;
etype = next_etype;
interp = next_interp;
}
if (geom)
{
feature->add_geometry(geom);
geom = 0;
}
}
else
{
geometry_type * geom = new geometry_type(geom_type);
fill_geometry_type(geom,
offset - 1,
ord_size,
ordinates,
dimensions,
is_point_geom);
feature->add_geometry(geom);
}
}
}
void occi_featureset::fill_geometry_type(geometry_type* geom,
const int real_offset,
const int next_offset,
const std::vector<Number>& ordinates,
const int dimensions,
const bool is_point_geom)
{
geom->move_to((double) ordinates[real_offset], (double) ordinates[real_offset + 1]);
if (is_point_geom)
{
for (int p = real_offset + dimensions; p < next_offset; p += dimensions)
{
geom->move_to((double) ordinates[p], (double) ordinates[p + 1]);
}
}
else
{
for (int p = real_offset + dimensions; p < next_offset; p += dimensions)
{
geom->line_to((double) ordinates[p], (double) ordinates[p + 1]);
}
}
}

View file

@ -1,77 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2015 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 OCCI_FEATURESET_HPP
#define OCCI_FEATURESET_HPP
// mapnik
#include <mapnik/feature.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/unicode.hpp>
// stl
#include <memory>
// oci
#include "occi_types.hpp"
#include <vector>
class occi_featureset : public mapnik::Featureset
{
public:
occi_featureset(oracle::occi::StatelessConnectionPool* pool,
oracle::occi::Connection* conn,
mapnik::context_ptr const& ctx,
std::string const& sqlstring,
std::string const& encoding,
bool use_connection_pool,
bool use_wkb,
unsigned prefetch_rows);
virtual ~occi_featureset();
mapnik::feature_ptr next();
private:
void convert_geometry (SDOGeometry* geom, mapnik::feature_ptr feature);
void convert_ordinates (mapnik::feature_ptr feature,
const mapnik::geometry_type::types& geom_type,
const std::vector<oracle::occi::Number>& elem_info,
const std::vector<oracle::occi::Number>& ordinates,
const int dimensions,
const bool is_single_geom,
const bool is_point_geom);
void fill_geometry_type (mapnik::geometry_type* geom,
const int real_offset,
const int next_offset,
const std::vector<oracle::occi::Number>& ordinates,
const int dimensions,
const bool is_point_geom);
occi_connection_ptr conn_;
oracle::occi::ResultSet* rs_;
const std::unique_ptr<mapnik::transcoder> tr_;
mapnik::value_integer feature_id_;
mapnik::context_ptr ctx_;
bool use_wkb_;
std::vector<char> buffer_;
};
#endif // OCCI_FEATURESET_HPP

View file

@ -1,91 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2015 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 "occi_types.hpp"
std::string occi_enums::resolve_gtype(int gtype)
{
switch (gtype)
{
case SDO_GTYPE_UNKNOWN: return "SDO_GTYPE_UNKNOWN";
case SDO_GTYPE_POINT: return "SDO_GTYPE_POINT";
case SDO_GTYPE_LINE: return "SDO_GTYPE_LINE";
case SDO_GTYPE_POLYGON: return "SDO_GTYPE_POLYGON";
case SDO_GTYPE_MULTIPOINT: return "SDO_GTYPE_MULTIPOINT";
case SDO_GTYPE_MULTILINE: return "SDO_GTYPE_MULTILINE";
case SDO_GTYPE_MULTIPOLYGON: return "SDO_GTYPE_MULTIPOLYGON";
case SDO_GTYPE_COLLECTION: return "SDO_GTYPE_COLLECTION";
default: return "<unknown SDO_GTYPE>";
}
}
std::string occi_enums::resolve_etype(int etype)
{
switch (etype)
{
case SDO_ETYPE_UNKNOWN: return "SDO_ETYPE_UNKNOWN";
case SDO_ETYPE_POINT: return "SDO_ETYPE_POINT";
case SDO_ETYPE_LINESTRING: return "SDO_ETYPE_LINESTRING";
case SDO_ETYPE_POLYGON: return "SDO_ETYPE_POLYGON";
case SDO_ETYPE_POLYGON_INTERIOR: return "SDO_ETYPE_POLYGON_INTERIOR";
case SDO_ETYPE_COMPOUND_LINESTRING: return "SDO_ETYPE_COMPOUND_LINESTRING";
case SDO_ETYPE_COMPOUND_POLYGON: return "SDO_ETYPE_COMPOUND_POLYGON";
case SDO_ETYPE_COMPOUND_POLYGON_INTERIOR: return "SDO_ETYPE_COMPOUND_POLYGON_INTERIOR";
default: return "<unknown SDO_ETYPE>";
}
}
std::string occi_enums::resolve_datatype(int type_id)
{
switch (type_id)
{
case oracle::occi::OCCIINT: return "OCCIINT";
case oracle::occi::OCCIUNSIGNED_INT: return "OCCIUNSIGNED_INT";
case oracle::occi::OCCIFLOAT: return "OCCIFLOAT";
case oracle::occi::OCCIBFLOAT: return "OCCIBFLOAT";
case oracle::occi::OCCIDOUBLE: return "OCCIDOUBLE";
case oracle::occi::OCCIBDOUBLE: return "OCCIBDOUBLE";
case oracle::occi::OCCINUMBER: return "OCCINUMBER";
case oracle::occi::OCCI_SQLT_NUM: return "OCCI_SQLT_NUM";
case oracle::occi::OCCICHAR: return "OCCICHAR";
case oracle::occi::OCCISTRING: return "OCCISTRING";
case oracle::occi::OCCI_SQLT_AFC: return "OCCI_SQLT_AFC";
case oracle::occi::OCCI_SQLT_AVC: return "OCCI_SQLT_AVC";
case oracle::occi::OCCI_SQLT_CHR: return "OCCI_SQLT_CHR";
case oracle::occi::OCCI_SQLT_LVC: return "OCCI_SQLT_LVC";
case oracle::occi::OCCI_SQLT_LNG: return "OCCI_SQLT_LNG";
case oracle::occi::OCCI_SQLT_STR: return "OCCI_SQLT_STR";
case oracle::occi::OCCI_SQLT_VCS: return "OCCI_SQLT_VCS";
case oracle::occi::OCCI_SQLT_VNU: return "OCCI_SQLT_VNU";
case oracle::occi::OCCI_SQLT_VBI: return "OCCI_SQLT_VBI";
case oracle::occi::OCCI_SQLT_VST: return "OCCI_SQLT_VST";
case oracle::occi::OCCI_SQLT_RDD: return "OCCI_SQLT_RDD";
case oracle::occi::OCCIDATE: return "OCCIDATE";
case oracle::occi::OCCITIMESTAMP: return "OCCITIMESTAMP";
case oracle::occi::OCCI_SQLT_DAT: return "OCCI_SQLT_DAT";
case oracle::occi::OCCI_SQLT_TIMESTAMP: return "OCCI_SQLT_TIMESTAMP";
case oracle::occi::OCCI_SQLT_TIMESTAMP_LTZ: return "OCCI_SQLT_TIMESTAMP_LTZ";
case oracle::occi::OCCI_SQLT_TIMESTAMP_TZ: return "OCCI_SQLT_TIMESTAMP_TZ";
case oracle::occi::OCCIPOBJECT: return "OCCIPOBJECT";
default: return "<unknown ATTR_DATA_TYPE>";
}
}

View file

@ -1,265 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2015 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 OCCI_TYPES_HPP
#define OCCI_TYPES_HPP
// mapnik
#include <mapnik/debug.hpp>
#include <mapnik/util/singleton.hpp>
// occi
#include <occi.h>
// ott generated SDOGeometry classes
#include "spatial_classesh.h"
#include "spatial_classesm.h"
// check for oracle support
#if OCCI_MAJOR_VERSION >= 10 && OCCI_MINOR_VERSION >= 1
// We have at least ORACLE 10g >= 10.2.0.X
#else
#error Only ORACLE 10g >= 10.2.0.X is supported !
#endif
// geometry types definitions
enum
{
SDO_GTYPE_UNKNOWN = 0,
SDO_GTYPE_POINT = 1,
SDO_GTYPE_LINE = 2,
SDO_GTYPE_POLYGON = 3,
SDO_GTYPE_COLLECTION = 4,
SDO_GTYPE_MULTIPOINT = 5,
SDO_GTYPE_MULTILINE = 6,
SDO_GTYPE_MULTIPOLYGON = 7,
SDO_GTYPE_2DPOINT = 2001,
SDO_GTYPE_2DLINE = 2002,
SDO_GTYPE_2DPOLYGON = 2003,
SDO_GTYPE_2DMULTIPOINT = 2005,
SDO_GTYPE_2DMULTILINE = 2006,
SDO_GTYPE_2DMULTIPOLYGON = 2007,
SDO_ELEM_INFO_SIZE = 3,
SDO_ETYPE_UNKNOWN = 0,
SDO_ETYPE_POINT = 1,
SDO_ETYPE_LINESTRING = 2,
SDO_ETYPE_POLYGON = 1003,
SDO_ETYPE_POLYGON_INTERIOR = 2003,
SDO_ETYPE_COMPOUND_LINESTRING = 4,
SDO_ETYPE_COMPOUND_POLYGON = 1005,
SDO_ETYPE_COMPOUND_POLYGON_INTERIOR = 2005,
SDO_INTERPRETATION_POINT = 1,
SDO_INTERPRETATION_RECTANGLE = 3,
SDO_INTERPRETATION_CIRCLE = 4,
SDO_INTERPRETATION_STRAIGHT = 1,
SDO_INTERPRETATION_CIRCULAR = 2
};
class occi_environment : public mapnik::singleton<occi_environment, mapnik::CreateStatic>
{
friend class mapnik::CreateStatic<occi_environment>;
public:
oracle::occi::Environment* get_environment()
{
return env_;
}
oracle::occi::Connection* create_connection(
const std::string& user,
const std::string& password,
const std::string& host)
{
MAPNIK_LOG_DEBUG(occi) << "occi_environment: create_connection";
return env_->createConnection(user, password, host);
}
void destroy_connection(oracle::occi::Connection* conn)
{
env_->terminateConnection(conn);
}
oracle::occi::StatelessConnectionPool* create_pool(
const std::string& user,
const std::string& password,
const std::string& host,
int max_size,
int initial_size,
int incr_size)
{
MAPNIK_LOG_DEBUG(occi) << "occi_environment: create_pool";
return env_->createStatelessConnectionPool(
user,
password,
host,
max_size,
initial_size,
incr_size,
oracle::occi::StatelessConnectionPool::HOMOGENEOUS);
}
void destroy_pool(oracle::occi::StatelessConnectionPool* pool)
{
env_->terminateStatelessConnectionPool(
pool,
oracle::occi::StatelessConnectionPool::SPD_FORCE);
}
private:
occi_environment()
: env_(0)
{
MAPNIK_LOG_DEBUG(occi) << "occi_environment: constructor";
env_ = oracle::occi::Environment::createEnvironment(
(oracle::occi::Environment::Mode)(oracle::occi::Environment::OBJECT
| oracle::occi::Environment::THREADED_MUTEXED));
RegisterClasses(env_);
}
~occi_environment()
{
MAPNIK_LOG_DEBUG(occi) << "occi_environment: destructor";
oracle::occi::Environment::terminateEnvironment(env_);
env_ = 0;
}
oracle::occi::Environment* env_;
};
class occi_connection_ptr
{
public:
explicit occi_connection_ptr()
: pool_(0),
conn_(0),
stmt_(0),
rs_(0),
owns_connection_(false)
{
}
~occi_connection_ptr()
{
close_query(true);
}
void set_pool(oracle::occi::StatelessConnectionPool* pool)
{
close_query(true);
pool_ = pool;
conn_ = pool_->getConnection();
owns_connection_ = true;
}
void set_connection(oracle::occi::Connection* conn, bool owns_connection)
{
close_query(true);
pool_ = 0;
conn_ = conn;
owns_connection_ = owns_connection;
}
oracle::occi::ResultSet* execute_query(std::string const& s, const unsigned prefetch = 0)
{
close_query(false);
MAPNIK_LOG_DEBUG(occi) << "occi_connection_ptr: " << s;
stmt_ = conn_->createStatement(s);
if (prefetch > 0)
{
stmt_->setPrefetchMemorySize(0);
stmt_->setPrefetchRowCount(prefetch);
}
rs_ = stmt_->executeQuery();
return rs_;
}
private:
void close_query(const bool release_connection)
{
if (conn_)
{
if (stmt_)
{
if (rs_)
{
stmt_->closeResultSet(rs_);
rs_ = 0;
}
conn_->terminateStatement(stmt_);
stmt_ = 0;
}
if (release_connection)
{
if (pool_)
{
pool_->releaseConnection(conn_);
}
else
{
if (owns_connection_)
{
occi_environment::instance().destroy_connection(conn_);
}
}
conn_ = 0;
}
}
}
oracle::occi::StatelessConnectionPool* pool_;
oracle::occi::Connection* conn_;
oracle::occi::Statement* stmt_;
oracle::occi::ResultSet* rs_;
bool owns_connection_;
};
class occi_enums
{
public:
static std::string resolve_gtype(int gtype);
static std::string resolve_etype(int etype);
static std::string resolve_datatype(int type_id);
};
#endif // OCCI_TYPES_HPP

View file

@ -1,147 +0,0 @@
#ifndef SPATIAL_CLASSESH_ORACLE
# define SPATIAL_CLASSESH_ORACLE
#ifndef OCCI_ORACLE
# include <occi.h>
#endif
class SDOPointType;
class SDOGeometry;
/************************************************************/
// generated declarations for the SDO_POINT_TYPE object type.
/************************************************************/
class SDOPointType : public oracle::occi::PObject {
private:
oracle::occi::Number X;
oracle::occi::Number Y;
oracle::occi::Number Z;
public:
oracle::occi::Number getX() const;
void setX(const oracle::occi::Number &value);
oracle::occi::Number getY() const;
void setY(const oracle::occi::Number &value);
oracle::occi::Number getZ() const;
void setZ(const oracle::occi::Number &value);
void *operator new(size_t size);
void *operator new(size_t size, const oracle::occi::Connection * sess,
const OCCI_STD_NAMESPACE::string& table);
void *operator new(size_t, void *ctxOCCI_);
void *operator new(size_t size, const oracle::occi::Connection *sess,
const OCCI_STD_NAMESPACE::string &tableName,
const OCCI_STD_NAMESPACE::string &typeName,
const OCCI_STD_NAMESPACE::string &tableSchema,
const OCCI_STD_NAMESPACE::string &typeSchema);
OCCI_STD_NAMESPACE::string getSQLTypeName() const;
void getSQLTypeName(oracle::occi::Environment *env, void **schemaName,
unsigned int &schemaNameLen, void **typeName,
unsigned int &typeNameLen) const;
SDOPointType();
SDOPointType(void *ctxOCCI_) : oracle::occi::PObject (ctxOCCI_) { }
static void *readSQL(void *ctxOCCI_);
virtual void readSQL(oracle::occi::AnyData& streamOCCI_);
static void writeSQL(void *objOCCI_, void *ctxOCCI_);
virtual void writeSQL(oracle::occi::AnyData& streamOCCI_);
~SDOPointType();
};
/************************************************************/
// generated declarations for the SDO_GEOMETRY object type.
/************************************************************/
class SDOGeometry : public oracle::occi::PObject {
private:
oracle::occi::Number SDO_GTYPE;
oracle::occi::Number SDO_SRID;
SDOPointType * SDO_POINT;
OCCI_STD_NAMESPACE::vector< oracle::occi::Number > SDO_ELEM_INFO;
OCCI_STD_NAMESPACE::vector< oracle::occi::Number > SDO_ORDINATES;
public:
oracle::occi::Number getSdo_gtype() const;
void setSdo_gtype(const oracle::occi::Number &value);
oracle::occi::Number getSdo_srid() const;
void setSdo_srid(const oracle::occi::Number &value);
SDOPointType * getSdo_point() const;
void setSdo_point(SDOPointType * value);
OCCI_STD_NAMESPACE::vector< oracle::occi::Number >& getSdo_elem_info();
const OCCI_STD_NAMESPACE::vector< oracle::occi::Number >& getSdo_elem_info() const;
void setSdo_elem_info(const OCCI_STD_NAMESPACE::vector< oracle::occi::Number > &value);
OCCI_STD_NAMESPACE::vector< oracle::occi::Number >& getSdo_ordinates();
const OCCI_STD_NAMESPACE::vector< oracle::occi::Number >& getSdo_ordinates() const;
void setSdo_ordinates(const OCCI_STD_NAMESPACE::vector< oracle::occi::Number > &value);
void *operator new(size_t size);
void *operator new(size_t size, const oracle::occi::Connection * sess,
const OCCI_STD_NAMESPACE::string& table);
void *operator new(size_t, void *ctxOCCI_);
void *operator new(size_t size, const oracle::occi::Connection *sess,
const OCCI_STD_NAMESPACE::string &tableName,
const OCCI_STD_NAMESPACE::string &typeName,
const OCCI_STD_NAMESPACE::string &tableSchema,
const OCCI_STD_NAMESPACE::string &typeSchema);
OCCI_STD_NAMESPACE::string getSQLTypeName() const;
void getSQLTypeName(oracle::occi::Environment *env, void **schemaName,
unsigned int &schemaNameLen, void **typeName,
unsigned int &typeNameLen) const;
SDOGeometry();
SDOGeometry(void *ctxOCCI_) : oracle::occi::PObject (ctxOCCI_) { }
static void *readSQL(void *ctxOCCI_);
virtual void readSQL(oracle::occi::AnyData& streamOCCI_);
static void writeSQL(void *objOCCI_, void *ctxOCCI_);
virtual void writeSQL(oracle::occi::AnyData& streamOCCI_);
~SDOGeometry();
};
#endif

View file

@ -1,11 +0,0 @@
#ifndef SPATIAL_CLASSESM_ORACLE
# include "spatial_classesm.h"
#endif
void RegisterClasses(oracle::occi::Environment* envOCCI_)
{
oracle::occi::Map *mapOCCI_ = envOCCI_->getMap();
mapOCCI_->put("MDSYS.SDO_POINT_TYPE", &SDOPointType::readSQL, &SDOPointType::writeSQL);
mapOCCI_->put("MDSYS.SDO_GEOMETRY", &SDOGeometry::readSQL, &SDOGeometry::writeSQL);
}

View file

@ -1,14 +0,0 @@
#ifndef SPATIAL_CLASSESM_ORACLE
# define SPATIAL_CLASSESM_ORACLE
#ifndef OCCI_ORACLE
# include <occi.h>
#endif
#ifndef SPATIAL_CLASSESH_ORACLE
# include "spatial_classesh.h"
#endif
void RegisterClasses(oracle::occi::Environment* envOCCI_);
#endif

View file

@ -1,312 +0,0 @@
#ifndef SPATIAL_CLASSESH_ORACLE
# include "spatial_classesh.h"
#endif
/*****************************************************************/
// generated method implementations for the SDO_POINT_TYPE object type.
/*****************************************************************/
oracle::occi::Number SDOPointType::getX() const
{
return X;
}
void SDOPointType::setX(const oracle::occi::Number &value)
{
X = value;
}
oracle::occi::Number SDOPointType::getY() const
{
return Y;
}
void SDOPointType::setY(const oracle::occi::Number &value)
{
Y = value;
}
oracle::occi::Number SDOPointType::getZ() const
{
return Z;
}
void SDOPointType::setZ(const oracle::occi::Number &value)
{
Z = value;
}
void *SDOPointType::operator new(size_t size)
{
return oracle::occi::PObject::operator new(size);
}
void *SDOPointType::operator new(size_t size, const oracle::occi::Connection * sess,
const OCCI_STD_NAMESPACE::string& table)
{
return oracle::occi::PObject::operator new(size, sess, table,
(char *) "MDSYS.SDO_POINT_TYPE");
}
void *SDOPointType::operator new(size_t size, void *ctxOCCI_)
{
return oracle::occi::PObject::operator new(size, ctxOCCI_);
}
void *SDOPointType::operator new(size_t size,
const oracle::occi::Connection *sess,
const OCCI_STD_NAMESPACE::string &tableName,
const OCCI_STD_NAMESPACE::string &typeName,
const OCCI_STD_NAMESPACE::string &tableSchema,
const OCCI_STD_NAMESPACE::string &typeSchema)
{
return oracle::occi::PObject::operator new(size, sess, tableName,
typeName, tableSchema, typeSchema);
}
OCCI_STD_NAMESPACE::string SDOPointType::getSQLTypeName() const
{
return OCCI_STD_NAMESPACE::string("MDSYS.SDO_POINT_TYPE");
}
void SDOPointType::getSQLTypeName(oracle::occi::Environment *env, void **schemaName,
unsigned int &schemaNameLen, void **typeName, unsigned int &typeNameLen) const
{
PObject::getSQLTypeName(env, &SDOPointType::readSQL, schemaName,
schemaNameLen, typeName, typeNameLen);
}
SDOPointType::SDOPointType()
{
}
void *SDOPointType::readSQL(void *ctxOCCI_)
{
SDOPointType *objOCCI_ = new(ctxOCCI_) SDOPointType(ctxOCCI_);
oracle::occi::AnyData streamOCCI_(ctxOCCI_);
try
{
if (streamOCCI_.isNull())
objOCCI_->setNull();
else
objOCCI_->readSQL(streamOCCI_);
}
catch (oracle::occi::SQLException& excep)
{
delete objOCCI_;
excep.setErrorCtx(ctxOCCI_);
return (void *)nullptr;
}
return (void *)objOCCI_;
}
void SDOPointType::readSQL(oracle::occi::AnyData& streamOCCI_)
{
X = streamOCCI_.getNumber();
Y = streamOCCI_.getNumber();
Z = streamOCCI_.getNumber();
}
void SDOPointType::writeSQL(void *objectOCCI_, void *ctxOCCI_)
{
SDOPointType *objOCCI_ = (SDOPointType *) objectOCCI_;
oracle::occi::AnyData streamOCCI_(ctxOCCI_);
try
{
if (objOCCI_->isNull())
streamOCCI_.setNull();
else
objOCCI_->writeSQL(streamOCCI_);
}
catch (oracle::occi::SQLException& excep)
{
excep.setErrorCtx(ctxOCCI_);
}
return;
}
void SDOPointType::writeSQL(oracle::occi::AnyData& streamOCCI_)
{
streamOCCI_.setNumber(X);
streamOCCI_.setNumber(Y);
streamOCCI_.setNumber(Z);
}
SDOPointType::~SDOPointType()
{
}
/*****************************************************************/
// generated method implementations for the SDO_GEOMETRY object type.
/*****************************************************************/
oracle::occi::Number SDOGeometry::getSdo_gtype() const
{
return SDO_GTYPE;
}
void SDOGeometry::setSdo_gtype(const oracle::occi::Number &value)
{
SDO_GTYPE = value;
}
oracle::occi::Number SDOGeometry::getSdo_srid() const
{
return SDO_SRID;
}
void SDOGeometry::setSdo_srid(const oracle::occi::Number &value)
{
SDO_SRID = value;
}
SDOPointType * SDOGeometry::getSdo_point() const
{
return SDO_POINT;
}
void SDOGeometry::setSdo_point(SDOPointType * value)
{
SDO_POINT = value;
}
OCCI_STD_NAMESPACE::vector< oracle::occi::Number >& SDOGeometry::getSdo_elem_info()
{
return SDO_ELEM_INFO;
}
const OCCI_STD_NAMESPACE::vector< oracle::occi::Number >& SDOGeometry::getSdo_elem_info() const
{
return SDO_ELEM_INFO;
}
void SDOGeometry::setSdo_elem_info(const OCCI_STD_NAMESPACE::vector< oracle::occi::Number > &value)
{
SDO_ELEM_INFO = value;
}
OCCI_STD_NAMESPACE::vector< oracle::occi::Number >& SDOGeometry::getSdo_ordinates()
{
return SDO_ORDINATES;
}
const OCCI_STD_NAMESPACE::vector< oracle::occi::Number >& SDOGeometry::getSdo_ordinates() const
{
return SDO_ORDINATES;
}
void SDOGeometry::setSdo_ordinates(const OCCI_STD_NAMESPACE::vector< oracle::occi::Number > &value)
{
SDO_ORDINATES = value;
}
void *SDOGeometry::operator new(size_t size)
{
return oracle::occi::PObject::operator new(size);
}
void *SDOGeometry::operator new(size_t size, const oracle::occi::Connection * sess,
const OCCI_STD_NAMESPACE::string& table)
{
return oracle::occi::PObject::operator new(size, sess, table,
(char *) "MDSYS.SDO_GEOMETRY");
}
void *SDOGeometry::operator new(size_t size, void *ctxOCCI_)
{
return oracle::occi::PObject::operator new(size, ctxOCCI_);
}
void *SDOGeometry::operator new(size_t size,
const oracle::occi::Connection *sess,
const OCCI_STD_NAMESPACE::string &tableName,
const OCCI_STD_NAMESPACE::string &typeName,
const OCCI_STD_NAMESPACE::string &tableSchema,
const OCCI_STD_NAMESPACE::string &typeSchema)
{
return oracle::occi::PObject::operator new(size, sess, tableName,
typeName, tableSchema, typeSchema);
}
OCCI_STD_NAMESPACE::string SDOGeometry::getSQLTypeName() const
{
return OCCI_STD_NAMESPACE::string("MDSYS.SDO_GEOMETRY");
}
void SDOGeometry::getSQLTypeName(oracle::occi::Environment *env, void **schemaName,
unsigned int &schemaNameLen, void **typeName, unsigned int &typeNameLen) const
{
PObject::getSQLTypeName(env, &SDOGeometry::readSQL, schemaName,
schemaNameLen, typeName, typeNameLen);
}
SDOGeometry::SDOGeometry()
{
SDO_POINT = (SDOPointType *) 0;
}
void *SDOGeometry::readSQL(void *ctxOCCI_)
{
SDOGeometry *objOCCI_ = new(ctxOCCI_) SDOGeometry(ctxOCCI_);
oracle::occi::AnyData streamOCCI_(ctxOCCI_);
try
{
if (streamOCCI_.isNull())
objOCCI_->setNull();
else
objOCCI_->readSQL(streamOCCI_);
}
catch (oracle::occi::SQLException& excep)
{
delete objOCCI_;
excep.setErrorCtx(ctxOCCI_);
return (void *)nullptr;
}
return (void *)objOCCI_;
}
void SDOGeometry::readSQL(oracle::occi::AnyData& streamOCCI_)
{
SDO_GTYPE = streamOCCI_.getNumber();
SDO_SRID = streamOCCI_.getNumber();
SDO_POINT = (SDOPointType *) streamOCCI_.getObject(&SDOPointType::readSQL);
oracle::occi::getVector(streamOCCI_, SDO_ELEM_INFO);
oracle::occi::getVector(streamOCCI_, SDO_ORDINATES);
}
void SDOGeometry::writeSQL(void *objectOCCI_, void *ctxOCCI_)
{
SDOGeometry *objOCCI_ = (SDOGeometry *) objectOCCI_;
oracle::occi::AnyData streamOCCI_(ctxOCCI_);
try
{
if (objOCCI_->isNull())
streamOCCI_.setNull();
else
objOCCI_->writeSQL(streamOCCI_);
}
catch (oracle::occi::SQLException& excep)
{
excep.setErrorCtx(ctxOCCI_);
}
return;
}
void SDOGeometry::writeSQL(oracle::occi::AnyData& streamOCCI_)
{
streamOCCI_.setNumber(SDO_GTYPE);
streamOCCI_.setNumber(SDO_SRID);
streamOCCI_.setObject(SDO_POINT);
oracle::occi::setVector(streamOCCI_, SDO_ELEM_INFO);
oracle::occi::setVector(streamOCCI_, SDO_ORDINATES);
}
SDOGeometry::~SDOGeometry()
{
delete SDO_POINT;
}

View file

@ -1,4 +0,0 @@
TYPE MDSYS.SDO_POINT_TYPE AS SDOPointType
TYPE MDSYS.SDO_GEOMETRY AS SDOGeometry

View file

@ -1,75 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2015 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 "basiccurl.h"
#include <iostream>
#include <cstring>
CURL_LOAD_DATA* grab_http_response(const char* url)
{
CURL_LOAD_DATA* data;
CURL* curl = curl_easy_init();
if(curl)
{
data = do_grab(curl, url);
curl_easy_cleanup(curl);
return data;
}
return nullptr;
}
CURL_LOAD_DATA* do_grab(CURL* curl,const char* url)
{
CURL_LOAD_DATA* data = (CURL_LOAD_DATA*)malloc(sizeof(CURL_LOAD_DATA));
data->data = nullptr;
data->nbytes = 0;
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, response_callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, data);
CURLcode res = curl_easy_perform(curl);
if (res !=0) {
std::clog << "error grabbing data\n";
}
return data;
}
size_t response_callback(void* ptr, size_t size, size_t nmemb, void* d)
{
size_t rsize = size * nmemb;
CURL_LOAD_DATA* data = (CURL_LOAD_DATA*)d;
// fprintf(stderr,"rsize is %d\n", rsize);
data->data = (char*)realloc(data->data, (data->nbytes + rsize) * sizeof(char));
std::memcpy(&(data->data[data->nbytes]), ptr, rsize);
data->nbytes += rsize;
// fprintf(stderr,"data->nbytes is %d\n", data->nbytes);
return rsize;
}

View file

@ -1,40 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 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 BASICCURL_H
#define BASICCURL_H
#include <curl/curl.h>
#include <cstdlib>
#include <cstring>
typedef struct
{
char *data;
int nbytes;
} CURL_LOAD_DATA;
CURL_LOAD_DATA *grab_http_response(const char *url);
CURL_LOAD_DATA *do_grab(CURL *curl, const char *url);
size_t response_callback(void *ptr ,size_t size, size_t nmemb, void *data);
#endif // BASICCURL_H

View file

@ -1,69 +0,0 @@
#
# This file is part of Mapnik (c++ mapping toolkit)
#
# Copyright (C) 2015 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 ('plugin_base')
Import ('env')
from copy import copy
PLUGIN_NAME = 'osm'
plugin_env = plugin_base.Clone()
plugin_sources = Split(
"""
%(PLUGIN_NAME)s.cpp
%(PLUGIN_NAME)s_datasource.cpp
%(PLUGIN_NAME)s_featureset.cpp
osmparser.cpp
dataset_deliverer.cpp
""" % locals()
)
plugin_env['LIBS'] = []
plugin_env.Append(LIBS='xml2')
# Link Library to Dependencies
libraries = copy(plugin_env['LIBS'])
libraries.append(env['ICU_LIB_NAME'])
libraries.append('boost_system%s' % env['BOOST_APPEND'])
if env['PLUGIN_LINKING'] == 'shared':
libraries.append(env['MAPNIK_NAME'])
TARGET = plugin_env.SharedLibrary('../%s' % PLUGIN_NAME,
SHLIBPREFIX='',
SHLIBSUFFIX='.input',
source=plugin_sources,
LIBS=libraries)
# 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')

View file

@ -1,66 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2015 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 <mapnik/debug.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/util/fs.hpp>
// std
#include <sstream>
#include "dataset_deliverer.h"
osm_dataset * dataset_deliverer::dataset = nullptr;
std::string dataset_deliverer::last_bbox = "";
std::string dataset_deliverer::last_filename = "";
osm_dataset* dataset_deliverer::load_from_file(const string& file, const string& parser)
{
// Only actually load from file if we haven't done so already
if (dataset == nullptr)
{
if (!mapnik::util::exists(file))
{
throw mapnik::datasource_exception("OSM Plugin: '" + file + "' does not exist");
}
dataset = new osm_dataset;
if (dataset->load(file.c_str(), parser) == false)
{
return nullptr;
}
atexit(dataset_deliverer::release);
last_filename = file;
}
else if(file != last_filename)
{
dataset = new osm_dataset;
if (dataset->load(file.c_str(), parser) == false)
{
return nullptr;
}
last_filename = file;
}
return dataset;
}

View file

@ -1,47 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 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 DATASET_DELIVERER_H
#define DATASET_DELIVERER_H
#include "osm.h"
#include <string>
using namespace std;
class dataset_deliverer
{
private:
static osm_dataset* dataset;
static std::string last_bbox;
static std::string last_filename;
public:
static osm_dataset *load_from_file(const string&, const string&);
static void release()
{
delete dataset;
}
};
#endif // DATASET_DELIVERER_H

View file

@ -1,230 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2015 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 "osm.h"
#include "osmparser.h"
#include <mapnik/debug.hpp>
#include <libxml/parser.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <cstring>
polygon_types osm_way::ptypes;
bool osm_dataset::load(const char* filename,std::string const& parser)
{
if (parser == "libxml2")
{
return osmparser::parse(this, filename);
}
return false;
}
osm_dataset::~osm_dataset()
{
clear();
}
void osm_dataset::clear()
{
MAPNIK_LOG_DEBUG(osm) << "osm_dataset: Clear";
MAPNIK_LOG_DEBUG(osm) << "osm_dataset: -- Deleting ways";
for (unsigned int count = 0; count < ways.size(); ++count)
{
delete ways[count];
ways[count] = nullptr;
}
ways.clear();
MAPNIK_LOG_DEBUG(osm) << "osm_dataset: -- Deleting nodes";
for (unsigned int count = 0; count < nodes.size(); ++count)
{
delete nodes[count];
nodes[count] = nullptr;
}
nodes.clear();
MAPNIK_LOG_DEBUG(osm) << "osm_dataset: Clear done";
}
std::string osm_dataset::to_string()
{
std::string result;
for (unsigned int count = 0; count < nodes.size(); ++count)
{
result += nodes[count]->to_string();
}
for (unsigned int count = 0; count < ways.size(); ++count)
{
result += ways[count]->to_string();
}
return result;
}
bounds osm_dataset::get_bounds()
{
bounds b (-180, -90, 180, 90);
for (unsigned int count = 0; count < nodes.size(); ++count)
{
if(nodes[count]->lon > b.w) b.w = nodes[count]->lon;
if(nodes[count]->lon < b.e) b.e = nodes[count]->lon;
if(nodes[count]->lat > b.s) b.s = nodes[count]->lat;
if(nodes[count]->lat < b.n) b.n = nodes[count]->lat;
}
return b;
}
osm_node* osm_dataset::next_node()
{
if (node_i != nodes.end())
{
return *(node_i++);
}
return nullptr;
}
osm_way* osm_dataset::next_way()
{
if (way_i != ways.end())
{
return *(way_i++);
}
return nullptr;
}
osm_item* osm_dataset::next_item()
{
osm_item* item = nullptr;
if (next_item_mode == Node)
{
item = next_node();
if (item == nullptr)
{
next_item_mode = Way;
rewind_ways();
item = next_way();
}
}
else
{
item = next_way();
}
return item;
}
std::set<std::string> osm_dataset::get_keys()
{
std::set<std::string> keys;
for (unsigned int count = 0; count < nodes.size(); ++count)
{
for (std::map<std::string, std::string>::iterator i = nodes[count]->keyvals.begin();
i != nodes[count]->keyvals.end(); i++)
{
keys.insert(i->first);
}
}
for (unsigned int count = 0; count < ways.size(); ++count)
{
for (std::map<std::string, std::string>::iterator i = ways[count]->keyvals.begin();
i != ways[count]->keyvals.end(); i++)
{
keys.insert(i->first);
}
}
return keys;
}
std::string osm_item::to_string()
{
std::ostringstream strm;
strm << "id=" << id << std::endl << "Keyvals: " << std::endl;
for (std::map<std::string, std::string>::iterator i = keyvals.begin();
i != keyvals.end(); i++)
{
strm << "Key " << i->first << " Value " << i->second << std::endl;
}
return strm.str();
}
std::string osm_node::to_string()
{
std::ostringstream strm;
strm << "Node: " << osm_item::to_string() << " lat=" << lat <<" lon=" <<lon << std::endl;
return strm.str();
}
std::string osm_way::to_string()
{
std::ostringstream strm;
strm << "Way: " << osm_item::to_string() << "Nodes in way:";
for (unsigned int count = 0; count < nodes.size(); ++count)
{
if (nodes[count] != nullptr)
{
strm << nodes[count]->id << " ";
}
}
strm << std::endl;
return strm.str();
}
bounds osm_way::get_bounds()
{
bounds b (-180, -90, 180, 90);
for (unsigned int count = 0; count < nodes.size(); ++count)
{
if(nodes[count]->lon > b.w) b.w = nodes[count]->lon;
if(nodes[count]->lon < b.e) b.e = nodes[count]->lon;
if(nodes[count]->lat > b.s) b.s = nodes[count]->lat;
if(nodes[count]->lat < b.n) b.n = nodes[count]->lat;
}
return b;
}
bool osm_way::is_polygon()
{
for (unsigned int count = 0; count < ptypes.ptypes.size(); ++count)
{
if (keyvals.find(ptypes.ptypes[count].first) != keyvals.end() &&
(ptypes.ptypes[count].second.empty() || keyvals[ptypes.ptypes[count].first] == ptypes.ptypes[count].second))
{
return true;
}
}
return false;
}

View file

@ -1,136 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 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 OSM_H
#define OSM_H
#include <mapnik/value_types.hpp>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <utility>
struct bounds
{
double w, s, e, n;
bounds() { w = -180; s = -90; e = 180; n = 90; }
bounds(double w_, double s_, double e_, double n_)
{
this->w = w_;
this->s = s_;
this->e = e_;
this->n = n_;
}
};
class polygon_types
{
public:
std::vector<std::pair<std::string, std::string> > ptypes;
polygon_types()
{
ptypes.push_back(std::pair<std::string, std::string>("water", ""));
ptypes.push_back(std::pair<std::string, std::string>("aeroway", ""));
ptypes.push_back(std::pair<std::string, std::string>("building", ""));
ptypes.push_back(std::pair<std::string, std::string>("natural", "wood"));
ptypes.push_back(std::pair<std::string, std::string>("natural", "water"));
ptypes.push_back(std::pair<std::string, std::string>("natural", "heath"));
ptypes.push_back(std::pair<std::string, std::string>("natural", "marsh"));
ptypes.push_back(std::pair<std::string, std::string>("military", "danger_area"));
ptypes.push_back(std::pair<std::string, std::string>("landuse", "forest"));
ptypes.push_back(std::pair<std::string, std::string>("landuse", "industrial"));
ptypes.push_back(std::pair<std::string, std::string>("leisure", "park"));
ptypes.push_back(std::pair<std::string, std::string>("area", "yes"));
}
};
struct osm_item
{
mapnik::value_integer id;
std::map<std::string, std::string> keyvals;
virtual std::string to_string();
virtual ~osm_item() {}
};
struct osm_node : public osm_item
{
double lat, lon;
std::string to_string();
};
struct osm_way : public osm_item
{
std::vector<osm_node*> nodes;
std::string to_string();
bounds get_bounds();
bool is_polygon();
static polygon_types ptypes;
};
class osm_dataset
{
public:
osm_dataset()
{
node_i = nodes.begin();
way_i = ways.begin();
next_item_mode = Node;
}
osm_dataset(const char* name)
{
node_i = nodes.begin();
way_i = ways.begin();
next_item_mode = Node;
load(name);
}
~osm_dataset();
bool load(const char* name, std::string const& parser = "libxml2");
void clear();
void add_node(osm_node* n) { nodes.push_back(n); }
void add_way(osm_way* w) { ways.push_back(w); }
std::string to_string();
bounds get_bounds();
std::set<std::string> get_keys();
void rewind_nodes() { node_i = nodes.begin(); }
void rewind_ways() { way_i = ways.begin(); }
void rewind() { rewind_nodes(); rewind_ways(); next_item_mode = Node; }
osm_node * next_node();
osm_way * next_way();
osm_item * next_item();
bool current_item_is_node() { return next_item_mode == Node; }
bool current_item_is_way() { return next_item_mode == Way; }
private:
int next_item_mode;
enum { Node, Way };
std::vector<osm_node*>::iterator node_i;
std::vector<osm_way*>::iterator way_i;
std::vector<osm_node*> nodes;
std::vector<osm_way*> ways;
};
#endif // OSM_H

View file

@ -1,159 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2015 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
*
*****************************************************************************/
// stl
#include <stdexcept>
#include <set>
// mapnik
#include <mapnik/debug.hpp>
#include <mapnik/geom_util.hpp>
#include <mapnik/query.hpp>
#include <mapnik/boolean.hpp>
// boost
#include "osm_datasource.hpp"
#include "osm_featureset.hpp"
#include "dataset_deliverer.h"
#include "osmtagtypes.h"
#include "osmparser.h"
using mapnik::String;
using mapnik::Double;
using mapnik::Integer;
using mapnik::datasource_exception;
using mapnik::filter_in_box;
using mapnik::filter_at_point;
using mapnik::attribute_descriptor;
DATASOURCE_PLUGIN(osm_datasource)
osm_datasource::osm_datasource(const parameters& params)
: datasource (params),
extent_(),
type_(datasource::Vector),
desc_(osm_datasource::name(), *params.get<std::string>("encoding", "utf-8"))
{
osm_data_ = nullptr;
std::string osm_filename = *params.get<std::string>("file", "");
std::string parser = *params.get<std::string>("parser", "libxml2");
std::string url = *params.get<std::string>("url", "");
std::string bbox = *params.get<std::string>("bbox", "");
// load the data
if (url != "" && bbox != "")
{
throw datasource_exception("Error loading from URL is no longer supported (removed in >= Mapnik 2.3.x");
}
else if (osm_filename != "")
{
// if we supplied a filename, load from file
if ((osm_data_ = dataset_deliverer::load_from_file(osm_filename, parser)) == nullptr)
{
std::string s("OSM Plugin: Error loading from file '");
s += osm_filename + "'";
throw datasource_exception(s);
}
}
else
{
throw datasource_exception("OSM Plugin: Neither 'file' nor 'url' and 'bbox' specified");
}
osm_tag_types tagtypes;
tagtypes.add_type("maxspeed", mapnik::Integer);
tagtypes.add_type("z_order", mapnik::Integer);
osm_data_->rewind();
// Need code to get the attributes of all the data
std::set<std::string> keys = osm_data_->get_keys();
// Add the attributes to the datasource descriptor - assume they are
// all of type String
for (auto const& key : keys)
{
desc_.add_descriptor(attribute_descriptor(key, tagtypes.get_type(key)));
}
// Get the bounds of the data and set extent_ accordingly
bounds b = osm_data_->get_bounds();
extent_ = box2d<double>(b.w,b.s,b.e,b.n);
}
osm_datasource::~osm_datasource()
{
// Do not do as is now static variable and cleaned up at exit
//delete osm_data_;
}
const char * osm_datasource::name()
{
return "osm";
}
mapnik::datasource::datasource_t osm_datasource::type() const
{
return type_;
}
layer_descriptor osm_datasource::get_descriptor() const
{
return desc_;
}
featureset_ptr osm_datasource::features(const query& q) const
{
filter_in_box filter(q.get_bbox());
// so we need to filter osm features by bbox here...
return std::make_shared<osm_featureset<filter_in_box> >(filter,
osm_data_,
q.property_names(),
desc_.get_encoding());
}
featureset_ptr osm_datasource::features_at_point(coord2d const& pt, double tol) const
{
filter_at_point filter(pt);
// collect all attribute names
std::set<std::string> names;
for (auto const& elem : desc_.get_descriptors())
{
names.insert(elem.get_name());
}
return std::make_shared<osm_featureset<filter_at_point> >(filter,
osm_data_,
names,
desc_.get_encoding());
}
box2d<double> osm_datasource::envelope() const
{
return extent_;
}
boost::optional<mapnik::datasource_geometry_t> osm_datasource::get_geometry_type() const
{
return boost::optional<mapnik::datasource_geometry_t>(mapnik::datasource_geometry_t::Collection);
}

View file

@ -1,73 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2015 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 OSM_DATASOURCE_HPP
#define OSM_DATASOURCE_HPP
// mapnik
#include <mapnik/datasource.hpp>
#include <mapnik/params.hpp>
#include <mapnik/query.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/box2d.hpp>
#include <mapnik/coord.hpp>
#include <mapnik/feature_layer_desc.hpp>
// boost
#include <boost/optional.hpp>
#include <memory>
// stl
#include <vector>
#include <string>
#include "osm.h"
using mapnik::datasource;
using mapnik::parameters;
using mapnik::query;
using mapnik::featureset_ptr;
using mapnik::layer_descriptor;
using mapnik::coord2d;
using mapnik::box2d;
class osm_datasource : public datasource
{
public:
osm_datasource(const parameters& params);
virtual ~osm_datasource();
mapnik::datasource::datasource_t type() const;
static const char * name();
featureset_ptr features(const query& q) const;
featureset_ptr features_at_point(coord2d const& pt, double tol = 0) const;
box2d<double> envelope() const;
boost::optional<mapnik::datasource_geometry_t> get_geometry_type() const;
layer_descriptor get_descriptor() const;
private:
box2d<double> extent_;
osm_dataset* osm_data_;
mapnik::datasource::datasource_t type_;
layer_descriptor desc_;
};
#endif // OSM_DATASOURCE_HPP

View file

@ -1,132 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2015 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 <mapnik/make_unique.hpp>
#include <mapnik/geometry.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/feature_factory.hpp>
#include <mapnik/debug.hpp>
#include <mapnik/unicode.hpp>
#include <mapnik/geometry_correct.hpp>
#include "osm_featureset.hpp"
using mapnik::feature_ptr;
using mapnik::feature_factory;
template <typename filterT>
osm_featureset<filterT>::osm_featureset(const filterT& filter,
osm_dataset* dataset,
const std::set<std::string>&
attribute_names,
std::string const& encoding)
: filter_(filter),
query_ext_(),
tr_(new transcoder(encoding)),
dataset_ (dataset),
attribute_names_ (attribute_names),
ctx_(std::make_shared<mapnik::context_type>())
{
dataset_->rewind();
}
template <typename filterT>
feature_ptr osm_featureset<filterT>::next()
{
feature_ptr feature;
osm_item* cur_item = dataset_->next_item();
if (!cur_item) return feature_ptr();
if (dataset_->current_item_is_node())
{
feature = feature_factory::create(ctx_, cur_item->id);
double lat = static_cast<osm_node*>(cur_item)->lat;
double lon = static_cast<osm_node*>(cur_item)->lon;
feature->set_geometry(mapnik::geometry::point<double>(lon,lat));
}
else if (dataset_->current_item_is_way())
{
// Loop until we find a feature which passes the filter
while (cur_item)
{
bounds b = static_cast<osm_way*>(cur_item)->get_bounds();
if (filter_.pass(box2d<double>(b.w, b.s, b.e, b.n))
&&
static_cast<osm_way*>(cur_item)->nodes.size()) break;
cur_item = dataset_->next_item();
}
if (!cur_item) return feature_ptr();
feature = feature_factory::create(ctx_, cur_item->id);
if (static_cast<osm_way*>(cur_item)->is_polygon())
{
mapnik::geometry::linear_ring<double> ring;
for (unsigned int count = 0;
count < static_cast<osm_way*>(cur_item)->nodes.size();
count++)
{
ring.add_coord(static_cast<osm_way*>(cur_item)->nodes[count]->lon,
static_cast<osm_way*>(cur_item)->nodes[count]->lat);
}
mapnik::geometry::polygon<double> geom;
geom.set_exterior_ring(std::move(ring));
mapnik::geometry::correct(geom);
feature->set_geometry(std::move(geom));
}
else
{
mapnik::geometry::line_string<double> geom;
for (unsigned int count = 0;
count < static_cast<osm_way*>(cur_item)->nodes.size();
count++)
{
geom.add_coord(static_cast<osm_way*>(cur_item)->nodes[count]->lon,
static_cast<osm_way*>(cur_item)->nodes[count]->lat);
}
feature->set_geometry(std::move(geom));
}
}
else
{
MAPNIK_LOG_ERROR(osm_featureset) << "Current item is neither node nor way.\n";
}
std::set<std::string>::const_iterator itr = attribute_names_.begin();
std::set<std::string>::const_iterator end = attribute_names_.end();
std::map<std::string,std::string>::iterator end_keyvals = cur_item->keyvals.end();
for (; itr != end; itr++)
{
std::map<std::string,std::string>::iterator i = cur_item->keyvals.find(*itr);
if (i != end_keyvals)
{
feature->put_new(i->first, tr_->transcode(i->second.c_str()));
}
}
return feature;
}
template <typename filterT>
osm_featureset<filterT>::~osm_featureset() {}
template class osm_featureset<mapnik::filter_in_box>;
template class osm_featureset<mapnik::filter_at_point>;

View file

@ -1,72 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2015 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 OSM_FS_HH
#define OSM_FS_HH
// stl
#include <set>
// boost
// mapnik
#include <mapnik/geom_util.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/query.hpp>
#include <mapnik/unicode.hpp>
#include <mapnik/datasource.hpp>
#include "osm.h"
using mapnik::Featureset;
using mapnik::box2d;
using mapnik::feature_ptr;
using mapnik::transcoder;
template <typename filterT>
class osm_featureset : public Featureset
{
public:
osm_featureset(const filterT& filter,
osm_dataset* dataset,
const std::set<std::string>& attribute_names,
std::string const& encoding);
virtual ~osm_featureset();
feature_ptr next();
private:
filterT filter_;
box2d<double> query_ext_;
const std::unique_ptr<transcoder> tr_;
std::vector<int> attr_ids_;
mutable box2d<double> feature_ext_;
mutable int total_geom_size;
osm_dataset *dataset_;
std::set<std::string> attribute_names_;
mapnik::context_ptr ctx_;
osm_featureset(const osm_featureset&);
const osm_featureset& operator=(const osm_featureset&);
};
#endif // OSM_FS_HH

View file

@ -1,150 +0,0 @@
// much of this is based on osm2pgsql
#include "osmparser.h"
#include "osm.h"
#include <string>
#include <cassert>
#include <mapnik/util/conversions.hpp>
osm_item* osmparser::cur_item=nullptr;
mapnik::value_integer osmparser::curID=0;
bool osmparser::in_node=false, osmparser::in_way=false;
osm_dataset* osmparser::components=nullptr;
std::string osmparser::error="";
std::map<mapnik::value_integer,osm_node*> osmparser::tmp_node_store=std::map<mapnik::value_integer,osm_node*>();
void osmparser::processNode(xmlTextReaderPtr reader)
{
xmlChar *name = xmlTextReaderName(reader);
if(name==nullptr)
name=xmlStrdup(BAD_CAST "--");
switch(xmlTextReaderNodeType(reader))
{
case XML_READER_TYPE_ELEMENT:
startElement(reader,name);
break;
case XML_READER_TYPE_END_ELEMENT:
endElement(name);
}
xmlFree(name);
}
void osmparser::startElement(xmlTextReaderPtr reader, const xmlChar *name)
{
std::string tags;
xmlChar *xid, *xlat, *xlon, *xk, *xv;
if(xmlStrEqual(name,BAD_CAST "node"))
{
curID = 0;
in_node = true;
osm_node *node=new osm_node;
xlat=xmlTextReaderGetAttribute(reader,BAD_CAST "lat");
xlon=xmlTextReaderGetAttribute(reader,BAD_CAST "lon");
xid=xmlTextReaderGetAttribute(reader,BAD_CAST "id");
assert(xlat);
assert(xlon);
assert(xid);
node->lat=atof((char*)xlat);
node->lon=atof((char*)xlon);
mapnik::util::string2int((char *)xid, node->id);
cur_item = node;
tmp_node_store[node->id] = node;
xmlFree(xid);
xmlFree(xlon);
xmlFree(xlat);
}
else if (xmlStrEqual(name,BAD_CAST "way"))
{
curID=0;
in_way = true;
osm_way *way=new osm_way;
xid=xmlTextReaderGetAttribute(reader,BAD_CAST "id");
assert(xid);
mapnik::util::string2int((char *)xid, way->id);
cur_item = way;
xmlFree(xid);
}
else if (xmlStrEqual(name,BAD_CAST "nd"))
{
xid=xmlTextReaderGetAttribute(reader,BAD_CAST "ref");
assert(xid);
mapnik::value_integer ndid;
mapnik::util::string2int((char *)xid, ndid);
if(tmp_node_store.find(ndid)!=tmp_node_store.end())
{
(static_cast<osm_way*>(cur_item))->nodes.push_back
(tmp_node_store[ndid]);
}
xmlFree(xid);
}
else if (xmlStrEqual(name,BAD_CAST "tag"))
{
std::string key="", value="";
xk = xmlTextReaderGetAttribute(reader,BAD_CAST "k");
xv = xmlTextReaderGetAttribute(reader,BAD_CAST "v");
assert(xk);
assert(xv);
cur_item->keyvals[(char*)xk] = (char*)xv;
xmlFree(xk);
xmlFree(xv);
}
if (xmlTextReaderIsEmptyElement(reader))
{
// Fake endElement for empty nodes
endElement(name);
}
}
void osmparser::endElement(const xmlChar* name)
{
if(xmlStrEqual(name,BAD_CAST "node"))
{
in_node = false;
components->add_node(static_cast<osm_node*>(cur_item));
}
else if(xmlStrEqual(name,BAD_CAST "way"))
{
in_way = false;
components->add_way(static_cast<osm_way*>(cur_item));
}
}
bool osmparser::parse(osm_dataset *ds, const char* filename)
{
components=ds;
xmlTextReaderPtr reader = xmlNewTextReaderFilename(filename);
int ret=do_parse(reader);
xmlFreeTextReader(reader);
return (ret==0) ? true:false;
}
bool osmparser::parse(osm_dataset *ds,char* data, int nbytes)
{
// from cocoasamurai.blogspot.com/2008/10/getting-some-xml-love-with-
// libxml2.html, converted from Objective-C to straight C
components=ds;
xmlTextReaderPtr reader = xmlReaderForMemory(data,nbytes,nullptr,nullptr,0);
int ret=do_parse(reader);
xmlFreeTextReader(reader);
return (ret==0) ? true:false;
}
int osmparser::do_parse(xmlTextReaderPtr reader)
{
int ret=-1;
if(reader!=nullptr)
{
ret = xmlTextReaderRead(reader);
while(ret==1)
{
processNode(reader);
ret=xmlTextReaderRead(reader);
}
}
return ret;
}

View file

@ -1,54 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 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 OSMPARSER_H
#define OSMPARSER_H
#include <mapnik/value_types.hpp>
#include <libxml/xmlreader.h>
#include <cstdio>
#include <cstdlib>
#include <string>
#include "osm.h"
#include <map>
class osmparser
{
public:
static void processNode(xmlTextReaderPtr reader);
static void startElement(xmlTextReaderPtr reader, const xmlChar* name);
static void endElement(const xmlChar* name);
static bool parse(osm_dataset* ds, const char* filename);
static bool parse(osm_dataset* ds, char* data, int nbytes);
private:
static osm_item *cur_item;
static mapnik::value_integer curID;
static bool in_node, in_way;
static osm_dataset* components;
static std::string error;
static std::map<mapnik::value_integer, osm_node*> tmp_node_store;
static int do_parse(xmlTextReaderPtr);
};
#endif // OSMPARSER_H

View file

@ -1,50 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 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 OSMTAGTYPES_H
#define OSMTAGTYPES_H
// osmtagtypes.h
// for finding the types of particular tags
// mapnik
#include <mapnik/feature_layer_desc.hpp>
class osm_tag_types
{
public:
void add_type(std::string tag, mapnik::eAttributeType type)
{
types[tag] = type;
}
mapnik::eAttributeType get_type(std::string tag)
{
std::map<std::string, mapnik::eAttributeType>::iterator i = types.find(tag);
return (i == types.end()) ? mapnik::String : i->second;
}
private:
std::map<std::string, mapnik::eAttributeType> types;
};
#endif // OSMTAGTYPES_H

View file

@ -271,18 +271,30 @@ mapnik::raster_ptr read_grayscale_band(mapnik::box2d<double> const& bbox,
int val;
int nodataval;
uint8_t * data = image.bytes();
int ps = 4; // sizeof(image::pixel_type)
int off;
val = reader(); // nodata value, need to read anyway
nodataval = reader(); // nodata value, need to read anyway
for (int y=0; y<height; ++y) {
for (int x=0; x<width; ++x) {
val = reader();
// Apply harsh type clipping rules ala GDAL
if ( val < 0 ) val = 0;
if ( val > 255 ) val = 255;
// Calculate pixel offset
off = y * width * ps + x * ps;
// Pixel space is RGBA
// Pixel space is RGBA, fill all w/ same value for Grey
data[off+0] = val;
data[off+1] = val;
data[off+2] = val;
// Set the alpha channel for transparent nodata values
// Nodata handling is *manual* at the driver level
if ( hasnodata && val == nodataval ) {
data[off+3] = 0x00; // transparent
} else {
data[off+3] = 0xFF; // opaque
}
}
}
mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(bbox, image, 1.0);

View file

@ -1,71 +0,0 @@
#
# This file is part of Mapnik (c++ mapping toolkit)
#
# Copyright (C) 2015 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 ('plugin_base')
Import ('env')
PLUGIN_NAME = 'rasterlite'
plugin_env = plugin_base.Clone()
plugin_sources = Split(
"""
%(PLUGIN_NAME)s_datasource.cpp
%(PLUGIN_NAME)s_featureset.cpp
""" % locals()
)
# Link Library to Dependencies
libraries = [env['PLUGINS']['rasterlite']['lib']]
libraries.append(env['ICU_LIB_NAME'])
libraries.append('boost_system%s' % env['BOOST_APPEND'])
if env['RUNTIME_LINK'] == 'static':
libraries.append('geotiff')
libraries.append('spatialite')
libraries.append('sqlite3')
libraries.append('geos_c')
libraries.append('geos')
libraries.append('proj')
libraries.append('z')
if env['PLUGIN_LINKING'] == 'shared':
libraries.append(env['MAPNIK_NAME'])
TARGET = plugin_env.SharedLibrary('../%s' % PLUGIN_NAME,
SHLIBPREFIX='',
SHLIBSUFFIX='.input',
source=plugin_sources,
LIBS=libraries)
# 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')

View file

@ -1,191 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2015 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 "rasterlite_datasource.hpp"
#include "rasterlite_featureset.hpp"
// boost
// mapnik
#include <mapnik/util/fs.hpp>
#include <mapnik/debug.hpp>
#include <mapnik/boolean.hpp>
#include <mapnik/geom_util.hpp>
using mapnik::datasource;
using mapnik::parameters;
DATASOURCE_PLUGIN(rasterlite_datasource)
using mapnik::box2d;
using mapnik::coord2d;
using mapnik::query;
using mapnik::featureset_ptr;
using mapnik::layer_descriptor;
using mapnik::datasource_exception;
/*
* Opens a GDALDataset and returns a pointer to it.
* Caller is responsible for calling GDALClose on it
*/
inline void* rasterlite_datasource::open_dataset() const
{
void* dataset = rasterliteOpen (dataset_name_.c_str(), table_name_.c_str());
if (! dataset)
{
throw datasource_exception("Rasterlite Plugin: Error opening dataset");
}
if (rasterliteIsError (dataset))
{
std::string error (rasterliteGetLastError(dataset));
rasterliteClose (dataset);
throw datasource_exception(error);
}
return dataset;
}
rasterlite_datasource::rasterlite_datasource(parameters const& params)
: datasource(params),
desc_(rasterlite_datasource::name(),"utf-8")
{
MAPNIK_LOG_DEBUG(rasterlite) << "rasterlite_datasource: Initializing...";
boost::optional<std::string> file = params.get<std::string>("file");
if (!file) throw datasource_exception("missing <file> parameter");
boost::optional<std::string> table = params.get<std::string>("table");
if (!table) throw datasource_exception("missing <table> parameter");
table_name_ = *table;
boost::optional<std::string> base = params.get<std::string>("base");
if (base)
dataset_name_ = *base + "/" + *file;
else
dataset_name_ = *file;
if (!mapnik::util::exists(dataset_name_)) throw datasource_exception(dataset_name_ + " does not exist");
void *dataset = open_dataset();
double x0, y0, x1, y1;
if (rasterliteGetExtent (dataset, &x0, &y0, &x1, &y1) != RASTERLITE_OK)
{
std::string error (rasterliteGetLastError(dataset));
rasterliteClose (dataset);
throw datasource_exception(error);
}
extent_.init(x0,y0,x1,y1);
#ifdef MAPNIK_LOG
int srid, auth_srid;
const char *auth_name;
const char *ref_sys_name;
const char *proj4text;
int tile_count;
double pixel_x_size, pixel_y_size;
int levels = rasterliteGetLevels (dataset);
if (rasterliteGetSrid(dataset, &srid, &auth_name, &auth_srid, &ref_sys_name, &proj4text) != RASTERLITE_OK)
{
std::string error (rasterliteGetLastError(dataset));
rasterliteClose (dataset);
throw datasource_exception(error);
}
MAPNIK_LOG_DEBUG(rasterlite) << "rasterlite_datasource: Data Source=" << rasterliteGetTablePrefix(dataset);
MAPNIK_LOG_DEBUG(rasterlite) << "rasterlite_datasource: SRID=" << srid;
MAPNIK_LOG_DEBUG(rasterlite) << "rasterlite_datasource: Authority=" << auth_name;
MAPNIK_LOG_DEBUG(rasterlite) << "rasterlite_datasource: AuthSRID=" << auth_srid;
MAPNIK_LOG_DEBUG(rasterlite) << "rasterlite_datasource: RefSys Name=" << ref_sys_name;
MAPNIK_LOG_DEBUG(rasterlite) << "rasterlite_datasource: Proj4Text=" << proj4text;
MAPNIK_LOG_DEBUG(rasterlite) << "rasterlite_datasource: Extent=" << x0 << "," << y0 << " " << x1 << "," << y1 << ")";
MAPNIK_LOG_DEBUG(rasterlite) << "rasterlite_datasource: Levels=" << levels;
for (int i = 0; i < levels; i++)
{
if (rasterliteGetResolution(dataset, i, &pixel_x_size, &pixel_y_size, &tile_count) == RASTERLITE_OK)
{
MAPNIK_LOG_DEBUG(rasterlite) << "rasterlite_datasource: Level=" << i
<< " x=" << pixel_x_size
<< " y=" << pixel_y_size
<< " tiles=" << tile_count;
}
}
#endif
rasterliteClose(dataset);
}
rasterlite_datasource::~rasterlite_datasource()
{
}
const char * rasterlite_datasource::name()
{
return "rasterlite";
}
mapnik::datasource::datasource_t rasterlite_datasource::type() const
{
return datasource::Raster;
}
box2d<double> rasterlite_datasource::envelope() const
{
return extent_;
}
boost::optional<mapnik::datasource_geometry_t> rasterlite_datasource::get_geometry_type() const
{
return boost::optional<mapnik::datasource_geometry_t>();
}
layer_descriptor rasterlite_datasource::get_descriptor() const
{
return desc_;
}
featureset_ptr rasterlite_datasource::features(query const& q) const
{
rasterlite_query gq = q;
return std::make_shared<rasterlite_featureset>(open_dataset(), gq);
}
featureset_ptr rasterlite_datasource::features_at_point(coord2d const& pt, double tol) const
{
rasterlite_query gq = pt;
return std::make_shared<rasterlite_featureset>(open_dataset(), gq);
}

View file

@ -1,66 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2015 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 RASTERLITE_DATASOURCE_HPP
#define RASTERLITE_DATASOURCE_HPP
// mapnik
#include <mapnik/datasource.hpp>
#include <mapnik/params.hpp>
#include <mapnik/query.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/box2d.hpp>
#include <mapnik/coord.hpp>
#include <mapnik/feature_layer_desc.hpp>
// boost
#include <boost/optional.hpp>
#include <memory>
// stl
#include <vector>
#include <string>
#include "rasterlite_include.hpp"
class rasterlite_datasource : public mapnik::datasource
{
public:
rasterlite_datasource(mapnik::parameters const& params);
virtual ~rasterlite_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<double> envelope() const;
boost::optional<mapnik::datasource_geometry_t> get_geometry_type() const;
mapnik::layer_descriptor get_descriptor() const;
private:
void* open_dataset() const;
mapnik::box2d<double> extent_;
std::string dataset_name_;
std::string table_name_;
mapnik::layer_descriptor desc_;
};
#endif // RASTERLITE_DATASOURCE_HPP

View file

@ -1,136 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2015 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 "rasterlite_featureset.hpp"
// mapnik
#include <mapnik/debug.hpp>
#include <mapnik/image.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/query.hpp>
#include <mapnik/raster.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/feature_factory.hpp>
#include <cstring>
using mapnik::coord2d;
using mapnik::box2d;
using mapnik::feature_ptr;
using mapnik::query;
using mapnik::feature_factory;
rasterlite_featureset::rasterlite_featureset(void* dataset,
rasterlite_query q)
: dataset_(dataset),
gquery_(q),
first_(true),
ctx_(std::make_shared<mapnik::context_type>())
{
rasterliteSetBackgroundColor(dataset_, 255, 0, 255);
rasterliteSetTransparentColor(dataset_, 255, 0, 255);
}
rasterlite_featureset::~rasterlite_featureset()
{
MAPNIK_LOG_DEBUG(rasterlite) << "rasterlite_featureset: Closing";
rasterliteClose(dataset_);
}
feature_ptr rasterlite_featureset::next()
{
if (first_)
{
first_ = false;
MAPNIK_LOG_DEBUG(gdal) << "rasterlite_featureset: Next feature in Dataset=" << &dataset_;
return mapnik::util::apply_visitor(query_dispatch(*this), gquery_);
}
return feature_ptr();
}
feature_ptr rasterlite_featureset::get_feature(mapnik::query const& q)
{
MAPNIK_LOG_DEBUG(rasterlite) << "rasterlite_featureset: Running get_feature";
feature_ptr feature(feature_factory::create(ctx_,1));
double x0, y0, x1, y1;
rasterliteGetExtent (dataset_, &x0, &y0, &x1, &y1);
box2d<double> raster_extent(x0, y0, x1, y1);
box2d<double> intersect = raster_extent.intersect(q.get_bbox());
const int width = static_cast<int>(std::get<0>(q.resolution()) * intersect.width() + 0.5);
const int height = static_cast<int>(std::get<0>(q.resolution()) * intersect.height() + 0.5);
const double pixel_size = (intersect.width() >= intersect.height()) ?
(intersect.width() / (double) width) : (intersect.height() / (double) height);
MAPNIK_LOG_DEBUG(rasterlite) << "rasterlite_featureset: Raster extent=" << raster_extent;
MAPNIK_LOG_DEBUG(rasterlite) << "rasterlite_featureset: View extent=" << q.get_bbox();
MAPNIK_LOG_DEBUG(rasterlite) << "rasterlite_featureset: Intersect extent=" << intersect;
MAPNIK_LOG_DEBUG(rasterlite) << "rasterlite_featureset: Query resolution=" << std::get<0>(q.resolution()) << "," << std::get<1>(q.resolution());
MAPNIK_LOG_DEBUG(rasterlite) << "rasterlite_featureset: Size=" << width << " " << height;
MAPNIK_LOG_DEBUG(rasterlite) << "rasterlite_featureset: Pixel Size=" << pixel_size;
if (width > 0 && height > 0)
{
int size = 0;
void* raster = 0;
if (rasterliteGetRawImageByRect(dataset_,
intersect.minx(),
intersect.miny(),
intersect.maxx(),
intersect.maxy(),
pixel_size,
width,
height,
GAIA_RGBA_ARRAY,
&raster,
&size) == RASTERLITE_OK)
{
if (size > 0)
{
mapnik::image_rgba8 image(width,height);
unsigned char* raster_data = static_cast<unsigned char*>(raster);
std::memcpy(image.bytes(), raster_data, size);
feature->set_raster(std::make_shared<mapnik::raster>(intersect, std::move(image), 1.0));
MAPNIK_LOG_DEBUG(rasterlite) << "rasterlite_featureset: Done";
}
else
{
MAPNIK_LOG_ERROR(rasterlite) << "Rasterlite Plugin: Error " << rasterliteGetLastError (dataset_);
}
}
return feature;
}
return feature_ptr();
}
feature_ptr rasterlite_featureset::get_feature_at_point(mapnik::coord2d const& pt)
{
return feature_ptr();
}

View file

@ -1,71 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2015 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 RASTERLITE_FEATURESET_HPP
#define RASTERLITE_FEATURESET_HPP
// mapnik
#include <mapnik/feature.hpp>
#include <mapnik/query.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/util/variant.hpp>
#include "rasterlite_include.hpp"
using rasterlite_query = mapnik::util::variant<mapnik::query,mapnik::coord2d>;
class rasterlite_featureset : public mapnik::Featureset
{
struct query_dispatch
{
query_dispatch( rasterlite_featureset & featureset)
: featureset_(featureset) {}
mapnik::feature_ptr operator() (mapnik::query const& q) const
{
return featureset_.get_feature(q);
}
mapnik::feature_ptr operator() (mapnik::coord2d const& p) const
{
return featureset_.get_feature_at_point(p);
}
rasterlite_featureset & featureset_;
};
public:
rasterlite_featureset(void* dataset,
rasterlite_query q);
virtual ~rasterlite_featureset();
mapnik::feature_ptr next();
private:
mapnik::feature_ptr get_feature(mapnik::query const& q);
mapnik::feature_ptr get_feature_at_point(mapnik::coord2d const& p);
void* dataset_;
rasterlite_query gquery_;
bool first_;
mapnik::context_ptr ctx_;
};
#endif // RASTERLITE_FEATURESET_HPP

View file

@ -1,31 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2015 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 RASTERLITE_INCLUDE_HPP
#define RASTERLITE_INCLUDE_HPP
extern "C" {
#include <sqlite3.h>
#include <rasterlite.h>
}
#endif // RASTERLITE_INCLUDE_HPP

View file

@ -82,6 +82,7 @@ void memory_datasource::push(feature_ptr feature)
// TODO - collect attribute descriptors?
//desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Integer));
features_.push_back(feature);
dirty_extent_ = true;
}
datasource::datasource_t memory_datasource::type() const
@ -110,10 +111,11 @@ void memory_datasource::set_envelope(box2d<double> const& box)
box2d<double> memory_datasource::envelope() const
{
if (!extent_.valid())
if (!extent_.valid() || dirty_extent_)
{
accumulate_extent func(extent_);
std::for_each(features_.begin(),features_.end(),func);
dirty_extent_ = false;
}
return extent_;
}

View file

@ -136,17 +136,8 @@ double parse_double_optional_percent(const char* str, bool &percent)
qi::char_type char_;
double val = 0.0;
char unit='\0';
parse(str, str + std::strlen(str),double_[ref(val)=_1] >> *char_('%')[ref(unit)=_1]);
if (unit =='%')
{
percent = true;
val/=100.0;
}
else
{
percent = false;
}
parse(str, str + std::strlen(str),double_[ref(val)=_1, ref(percent) = false]
>> -char_('%')[ref(val)/100.0, ref(percent) = true]);
return val;
}

@ -1 +1 @@
Subproject commit bc51f1d9890b4dc5887864b00b1217c3ab904b4a
Subproject commit 07e9a9c7c3e9365d6b0d9023d77dfe897887af1c

View file

@ -73,5 +73,49 @@ TEST_CASE("geojson") {
REQUIRE(feature != nullptr);
}
mapnik::datasource_cache::instance().register_datasources("plugins/input/geojson.input");
SECTION("json extra properties cache-feature=\"true\"")
{
// Create datasource
mapnik::parameters params;
params["type"] = "geojson";
params["file"] = "./test/data/json/feature_collection_extra_properties.json";
params["cache-features"] = true;
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(bool(ds));
auto fields = ds->get_descriptor().get_descriptors();
mapnik::query query(ds->envelope());
for (auto const &field : fields)
{
query.add_property_name(field.get_name());
}
auto features = ds->features(query);
auto feature = features->next();
REQUIRE(feature != nullptr);
REQUIRE(feature->envelope() == mapnik::box2d<double>(123,456,123,456));
}
mapnik::datasource_cache::instance().register_datasources("plugins/input/geojson.input");
SECTION("json extra properties cache-feature=\"false\"")
{
// Create datasource
mapnik::parameters params;
params["type"] = "geojson";
params["file"] = "./test/data/json/feature_collection_extra_properties.json";
params["cache-features"] = false;
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(bool(ds));
auto fields = ds->get_descriptor().get_descriptors();
mapnik::query query(ds->envelope());
for (auto const &field : fields)
{
query.add_property_name(field.get_name());
}
auto features = ds->features(query);
auto feature = features->next();
REQUIRE(feature != nullptr);
REQUIRE(feature->envelope() == mapnik::box2d<double>(123,456,123,456));
}
}
}

View file

@ -0,0 +1,295 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2015 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 "catch.hpp"
#include <mapnik/version.hpp>
#include <mapnik/debug.hpp>
#include <mapnik/marker.hpp>
#include <mapnik/marker_cache.hpp>
#include <mapnik/vertex.hpp>
#include <mapnik/svg/svg_path_adapter.hpp>
#include <mapnik/svg/svg_renderer_agg.hpp>
#include <mapnik/svg/svg_path_attributes.hpp>
#include <libxml/parser.h> // for xmlInitParser(), xmlCleanupParser()
#include <cmath>
namespace detail {
template <int N = 6>
struct vertex_equal
{
template <typename T>
bool operator() (T const& lhs, T const& rhs) const
{
static const double eps = 1.0 / std::pow(10,N);
return (std::fabs(std::get<0>(lhs) - std::get<0>(rhs)) < eps)
&& (std::fabs(std::get<1>(lhs) - std::get<1>(rhs)) < eps)
&& std::get<2>(lhs) == std::get<2>(rhs);
}
};
}
TEST_CASE("SVG parser") {
xmlInitParser();
SECTION("SVG <rect>")
{
//<rect width="20" height="15" style="fill:rgb(0,0,255);stroke-width:1;stroke:rgb(0,0,0)" />
std::string svg_name("./test/data/svg/rect.svg");
std::shared_ptr<mapnik::marker const> marker = mapnik::marker_cache::instance().find(svg_name, false);
REQUIRE(marker);
REQUIRE(marker->is<mapnik::marker_svg>());
mapnik::marker_svg const& svg = mapnik::util::get<mapnik::marker_svg>(*marker);
auto bbox = svg.bounding_box();
REQUIRE(bbox == mapnik::box2d<double>(0, 0, 20, 15));
auto storage = svg.get_data();
REQUIRE(storage);
mapnik::svg::vertex_stl_adapter<mapnik::svg::svg_path_storage> stl_storage(storage->source());
mapnik::svg::svg_path_adapter path(stl_storage);
double x,y;
unsigned cmd;
std::vector<std::tuple<double,double,unsigned>> vec;
while ((cmd = path.vertex(&x,&y)) != mapnik::SEG_END)
{
vec.emplace_back(x, y, cmd);
//std::cerr << x << "," << y << " cmd=" << cmd << std::endl;
}
std::vector<std::tuple<double,double,unsigned>> expected = { std::make_tuple(0, 0, 1),
std::make_tuple(20, 0, 2),
std::make_tuple(20, 15, 2),
std::make_tuple(0, 15, 2),
std::make_tuple(0, 0, 79) };
REQUIRE(std::equal(expected.begin(),expected.end(), vec.begin()));
}
SECTION("SVG rounded <rect>")
{
//<rect width="20" height="15" rx="5" ry="10" style="fill:rgb(0,0,255);stroke-width:1;stroke:rgb(0,0,0)" />
std::string svg_name("./test/data/svg/rounded_rect.svg");
std::shared_ptr<mapnik::marker const> marker = mapnik::marker_cache::instance().find(svg_name, false);
REQUIRE(marker);
REQUIRE(marker->is<mapnik::marker_svg>());
mapnik::marker_svg const& svg = mapnik::util::get<mapnik::marker_svg>(*marker);
auto bbox = svg.bounding_box();
REQUIRE(bbox == mapnik::box2d<double>(0, 0, 20, 15));
auto storage = svg.get_data();
REQUIRE(storage);
mapnik::svg::vertex_stl_adapter<mapnik::svg::svg_path_storage> stl_storage(storage->source());
mapnik::svg::svg_path_adapter path(stl_storage);
double x,y;
unsigned cmd;
std::vector<std::tuple<double,double,unsigned>> vec;
while ((cmd = path.vertex(&x,&y)) != mapnik::SEG_END)
{
vec.emplace_back(x, y, cmd);
}
std::vector<std::tuple<double,double,unsigned>> expected = {std::make_tuple(0, 5,1),
std::make_tuple(0.481856, 2.85842,2),
std::make_tuple(1.83455, 1.12961,2),
std::make_tuple(3.79736, 0.146789,2),
std::make_tuple(5, 0,2),
std::make_tuple(15, 0,2),
std::make_tuple(17.1416, 0.481856,2),
std::make_tuple(18.8704, 1.83455,2),
std::make_tuple(19.8532, 3.79736,2),
std::make_tuple(20, 5,2),
std::make_tuple(20, 10,2),
std::make_tuple(19.5181, 12.1416,2),
std::make_tuple(18.1654, 13.8704,2),
std::make_tuple(16.2026, 14.8532,2),
std::make_tuple(15, 15,2),
std::make_tuple(5, 15,2),
std::make_tuple(2.85842, 14.5181,2),
std::make_tuple(1.12961, 13.1654,2),
std::make_tuple(0.146789, 11.2026,2),
std::make_tuple(0, 10,2),
std::make_tuple(0, 10,95)};
REQUIRE(std::equal(expected.begin(),expected.end(), vec.begin(),detail::vertex_equal<3>()));
}
SECTION("SVG <line>")
{
//
std::string svg_name("./test/data/svg/line.svg");
std::shared_ptr<mapnik::marker const> marker = mapnik::marker_cache::instance().find(svg_name, false);
REQUIRE(marker);
REQUIRE(marker->is<mapnik::marker_svg>());
mapnik::marker_svg const& svg = mapnik::util::get<mapnik::marker_svg>(*marker);
auto bbox = svg.bounding_box();
REQUIRE(bbox == mapnik::box2d<double>(1.0,1.0,1199.0,399.0));
auto storage = svg.get_data();
REQUIRE(storage);
mapnik::svg::vertex_stl_adapter<mapnik::svg::svg_path_storage> stl_storage(storage->source());
mapnik::svg::svg_path_adapter path(stl_storage);
double x,y;
unsigned cmd;
std::vector<std::tuple<double,double,unsigned>> vec;
std::size_t num_vertices = path.total_vertices();
//std::cerr << "Num vertices = " << num_vertices << std::endl;
//std::cerr << "{";
for (std::size_t i = 0; i < num_vertices; ++i)
{
cmd = path.vertex(&x,&y);
vec.emplace_back(x, y, cmd);
//if (vec.size() > 1) std::cerr << ",";
//std::cerr << std::setprecision(6) << "std::make_tuple(" << x << ", " << y << ", " << cmd << ")";
}
//std::cerr << "}" << std::endl;
std::vector<std::tuple<double,double,unsigned>> expected = {std::make_tuple(1, 1, 1),
std::make_tuple(1199, 1, 2),
std::make_tuple(1199, 399, 2),
std::make_tuple(1, 399, 2),
std::make_tuple(1, 1, 79),
std::make_tuple(0, 0, 0),
std::make_tuple(100, 300, 1),
std::make_tuple(300, 100, 2),
std::make_tuple(0, 0, 0),
std::make_tuple(300, 300, 1),
std::make_tuple(500, 100, 2),
std::make_tuple(0, 0, 0),
std::make_tuple(500, 300, 1),
std::make_tuple(700, 100, 2),
std::make_tuple(0, 0, 0),
std::make_tuple(700, 300, 1),
std::make_tuple(900, 100, 2),
std::make_tuple(0, 0, 0),
std::make_tuple(900, 300, 1),
std::make_tuple(1100, 100, 2)};
REQUIRE(std::equal(expected.begin(),expected.end(), vec.begin()));
}
SECTION("SVG <polyline>")
{
//
std::string svg_name("./test/data/svg/polyline.svg");
std::shared_ptr<mapnik::marker const> marker = mapnik::marker_cache::instance().find(svg_name, false);
REQUIRE(marker);
REQUIRE(marker->is<mapnik::marker_svg>());
mapnik::marker_svg const& svg = mapnik::util::get<mapnik::marker_svg>(*marker);
auto bbox = svg.bounding_box();
REQUIRE(bbox == mapnik::box2d<double>(1.0,1.0,1199.0,399.0));
auto storage = svg.get_data();
REQUIRE(storage);
mapnik::svg::vertex_stl_adapter<mapnik::svg::svg_path_storage> stl_storage(storage->source());
mapnik::svg::svg_path_adapter path(stl_storage);
double x,y;
unsigned cmd;
std::vector<std::tuple<double,double,unsigned>> vec;
std::size_t num_vertices = path.total_vertices();
for (std::size_t i = 0; i < num_vertices; ++i)
{
cmd = path.vertex(&x,&y);
vec.emplace_back(x, y, cmd);
}
std::vector<std::tuple<double,double,unsigned>> expected = {std::make_tuple(1, 1, 1),
std::make_tuple(1199, 1, 2),
std::make_tuple(1199, 399, 2),
std::make_tuple(1, 399, 2),
std::make_tuple(1, 1, 79),
std::make_tuple(0, 0, 0),
std::make_tuple(50, 375, 1),
std::make_tuple(150, 375, 2),
std::make_tuple(150, 325, 2),
std::make_tuple(250, 325, 2),
std::make_tuple(250, 375, 2),
std::make_tuple(350, 375, 2),
std::make_tuple(350, 250, 2),
std::make_tuple(450, 250, 2),
std::make_tuple(450, 375, 2),
std::make_tuple(550, 375, 2),
std::make_tuple(550, 175, 2),
std::make_tuple(650, 175, 2),
std::make_tuple(650, 375, 2),
std::make_tuple(750, 375, 2),
std::make_tuple(750, 100, 2),
std::make_tuple(850, 100, 2),
std::make_tuple(850, 375, 2),
std::make_tuple(950, 375, 2),
std::make_tuple(950, 25, 2),
std::make_tuple(1050, 25, 2),
std::make_tuple(1050, 375, 2),
std::make_tuple(1150, 375, 2)};
REQUIRE(std::equal(expected.begin(),expected.end(), vec.begin()));
}
SECTION("SVG <polygon>")
{
//
std::string svg_name("./test/data/svg/polygon.svg");
std::shared_ptr<mapnik::marker const> marker = mapnik::marker_cache::instance().find(svg_name, false);
REQUIRE(marker);
REQUIRE(marker->is<mapnik::marker_svg>());
mapnik::marker_svg const& svg = mapnik::util::get<mapnik::marker_svg>(*marker);
auto bbox = svg.bounding_box();
REQUIRE(bbox == mapnik::box2d<double>(1.0,1.0,1199.0,399.0));
auto storage = svg.get_data();
REQUIRE(storage);
mapnik::svg::vertex_stl_adapter<mapnik::svg::svg_path_storage> stl_storage(storage->source());
mapnik::svg::svg_path_adapter path(stl_storage);
double x,y;
unsigned cmd;
std::vector<std::tuple<double,double,unsigned>> vec;
std::size_t num_vertices = path.total_vertices();
for (std::size_t i = 0; i < num_vertices; ++i)
{
cmd = path.vertex(&x,&y);
vec.emplace_back(x, y, cmd);
}
std::vector<std::tuple<double,double,unsigned>> expected = {std::make_tuple(1, 1, 1),
std::make_tuple(1199, 1, 2),
std::make_tuple(1199, 399, 2),
std::make_tuple(1, 399, 2),
std::make_tuple(1, 1, 79),
std::make_tuple(0, 0, 0),
std::make_tuple(350, 75, 1),
std::make_tuple(379, 161, 2),
std::make_tuple(469, 161, 2),
std::make_tuple(397, 215, 2),
std::make_tuple(423, 301, 2),
std::make_tuple(350, 250, 2),
std::make_tuple(277, 301, 2),
std::make_tuple(303, 215, 2),
std::make_tuple(231, 161, 2),
std::make_tuple(321, 161, 2),
std::make_tuple(350, 75, 79),
std::make_tuple(0, 0, 0),
std::make_tuple(850, 75, 1),
std::make_tuple(958, 137.5, 2),
std::make_tuple(958, 262.5, 2),
std::make_tuple(850, 325, 2),
std::make_tuple(742, 262.6, 2),
std::make_tuple(742, 137.5, 2),
std::make_tuple(850, 75, 79)};
REQUIRE(std::equal(expected.begin(),expected.end(), vec.begin()));
}
xmlCleanupParser();
}

View file

@ -52,16 +52,14 @@
struct main_marker_visitor
{
main_marker_visitor(std::string & svg_name,
int & return_value,
main_marker_visitor(std::string const& svg_name,
bool verbose,
bool auto_open)
: svg_name_(svg_name),
return_value_(return_value),
verbose_(verbose),
auto_open_(auto_open) {}
void operator() (mapnik::marker_svg const& marker)
int operator() (mapnik::marker_svg const& marker)
{
using pixfmt = agg::pixfmt_rgba32_pre;
using renderer_base = agg::renderer_base<pixfmt>;
@ -99,36 +97,37 @@ struct main_marker_visitor
svg_renderer_this.render(ras_ptr, sl, renb, mtx, opacity, bbox);
boost::algorithm::ireplace_last(svg_name_,".svg",".png");
std::string png_name(svg_name_);
boost::algorithm::ireplace_last(png_name,".svg",".png");
demultiply_alpha(im);
mapnik::save_to_file<mapnik::image_rgba8>(im,svg_name_,"png");
mapnik::save_to_file<mapnik::image_rgba8>(im,png_name,"png");
int status = 0;
if (auto_open_)
{
std::ostringstream s;
#ifdef DARWIN
s << "open " << svg_name_;
s << "open " << png_name;
#else
s << "xdg-open " << svg_name_;
s << "xdg-open " << png_name;
#endif
int ret = system(s.str().c_str());
if (ret != 0)
return_value_ = ret;
status = ret;
}
std::clog << "rendered to: " << svg_name_ << "\n";
std::clog << "rendered to: " << png_name << "\n";
return status;
}
// default
template <typename T>
void operator() (T const&)
int operator() (T const&)
{
std::clog << "svg2png error: '" << svg_name_ << "' is not a valid vector!\n";
return_value_ = -1;
return -1;
}
private:
std::string & svg_name_;
int & return_value_;
std::string const& svg_name_;
bool verbose_;
bool auto_open_;
};
@ -139,7 +138,7 @@ int main (int argc,char** argv)
bool verbose = false;
bool auto_open = false;
int return_value = 0;
int status = 0;
std::vector<std::string> svg_files;
mapnik::logger::instance().set_severity(mapnik::logger::error);
@ -210,8 +209,8 @@ int main (int argc,char** argv)
}
std::shared_ptr<mapnik::marker const> marker = mapnik::marker_cache::instance().find(svg_name, false);
main_marker_visitor visitor(svg_name, return_value, verbose, auto_open);
mapnik::util::apply_visitor(visitor, *marker);
main_marker_visitor visitor(svg_name, verbose, auto_open);
status = mapnik::util::apply_visitor(visitor, *marker);
}
}
catch (...)
@ -225,5 +224,5 @@ int main (int argc,char** argv)
// to make sure valgrind output is clean
// http://xmlsoft.org/xmlmem.html
xmlCleanupParser();
return return_value;
return status;
}