Merge branch 'master' of github.com:mapnik/mapnik
This commit is contained in:
commit
f556aa14a6
55 changed files with 1167 additions and 616 deletions
|
@ -9,6 +9,12 @@ For a complete change history, see the SVN log.
|
||||||
|
|
||||||
## Mapnik 2.1.0
|
## Mapnik 2.1.0
|
||||||
|
|
||||||
|
- PostGIS: Added 'simplify_geometries' option - will trigger ST_Simplify on geometries before returning to Mapnik (#1179)
|
||||||
|
|
||||||
|
- Improved error feedback for invalid values passed to map.query_point
|
||||||
|
|
||||||
|
- Fixed rendering of thin svg lines (#1129)
|
||||||
|
|
||||||
- Improved logging/debugging system with release logs and file redirection (#937 and partially #986, #467)
|
- Improved logging/debugging system with release logs and file redirection (#937 and partially #986, #467)
|
||||||
|
|
||||||
- GDAL: allow setting nodata value on the fly (will override value if nodata is set in data) (#1161)
|
- GDAL: allow setting nodata value on the fly (will override value if nodata is set in data) (#1161)
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -18,7 +18,7 @@ uninstall:
|
||||||
python scons/scons.py uninstall
|
python scons/scons.py uninstall
|
||||||
|
|
||||||
test:
|
test:
|
||||||
@echo "*** Running visual tests…"
|
@echo "*** Running visual tests..."
|
||||||
@python tests/visual_tests/test.py -q
|
@python tests/visual_tests/test.py -q
|
||||||
@echo "*** Running C++ tests..."
|
@echo "*** Running C++ tests..."
|
||||||
@for FILE in tests/cpp_tests/*-bin; do \
|
@for FILE in tests/cpp_tests/*-bin; do \
|
||||||
|
|
|
@ -96,7 +96,7 @@ PLUGINS = { # plugins with external dependencies
|
||||||
'rasterlite': {'default':False,'path':'RASTERLITE','inc':['sqlite3.h','rasterlite.h'],'lib':'rasterlite','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)
|
# todo: osm plugin does also depend on libxml2 (but there is a separate check for that)
|
||||||
'osm': {'default':False,'path':None,'inc':'curl/curl.h','lib':'curl','lang':'C'},
|
'osm': {'default':True,'path':None,'inc':'curl/curl.h','lib':'curl','lang':'C'},
|
||||||
|
|
||||||
# plugins without external dependencies requiring CheckLibWithHeader...
|
# plugins without external dependencies requiring CheckLibWithHeader...
|
||||||
'shape': {'default':True,'path':None,'inc':None,'lib':None,'lang':'C++'},
|
'shape': {'default':True,'path':None,'inc':None,'lib':None,'lang':'C++'},
|
||||||
|
@ -242,7 +242,6 @@ else:
|
||||||
LIBDIR_SCHEMA='lib'
|
LIBDIR_SCHEMA='lib'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def pretty_dep(dep):
|
def pretty_dep(dep):
|
||||||
pretty = pretty_dep_names.get(dep)
|
pretty = pretty_dep_names.get(dep)
|
||||||
if pretty:
|
if pretty:
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include <boost/python.hpp>
|
#include <boost/python.hpp>
|
||||||
#include <mapnik/debug.hpp>
|
#include <mapnik/debug.hpp>
|
||||||
#include <mapnik/utils.hpp>
|
#include <mapnik/utils.hpp>
|
||||||
|
#include "mapnik_enumeration.hpp"
|
||||||
|
|
||||||
void export_logger()
|
void export_logger()
|
||||||
{
|
{
|
||||||
|
@ -37,6 +38,15 @@ void export_logger()
|
||||||
.staticmethod("instance")
|
.staticmethod("instance")
|
||||||
;
|
;
|
||||||
|
|
||||||
|
enum_<mapnik::logger::severity_type>("severity_type")
|
||||||
|
.value("Info", logger::info)
|
||||||
|
.value("Debug", logger::debug)
|
||||||
|
.value("Warn", logger::warn)
|
||||||
|
.value("Error", logger::error)
|
||||||
|
.value("Fatal", logger::fatal)
|
||||||
|
.value("None", logger::none)
|
||||||
|
;
|
||||||
|
|
||||||
class_<logger,bases<singleton<logger,CreateStatic> >,
|
class_<logger,bases<singleton<logger,CreateStatic> >,
|
||||||
boost::noncopyable>("logger",no_init)
|
boost::noncopyable>("logger",no_init)
|
||||||
.def_readonly("Info", logger::info)
|
.def_readonly("Info", logger::info)
|
||||||
|
|
|
@ -124,5 +124,15 @@ void export_markers_symbolizer()
|
||||||
&markers_symbolizer::get_height,
|
&markers_symbolizer::get_height,
|
||||||
&markers_symbolizer::set_height,
|
&markers_symbolizer::set_height,
|
||||||
"Set/get the marker height")
|
"Set/get the marker height")
|
||||||
|
.add_property("fill",
|
||||||
|
make_function(&markers_symbolizer::get_fill,
|
||||||
|
return_value_policy<copy_const_reference>()),
|
||||||
|
&markers_symbolizer::set_fill,
|
||||||
|
"Set/get the marker fill color")
|
||||||
|
.add_property("stroke",
|
||||||
|
make_function(&markers_symbolizer::get_stroke,
|
||||||
|
return_value_policy<copy_const_reference>()),
|
||||||
|
&markers_symbolizer::set_stroke,
|
||||||
|
"Set/get the marker stroke (outline)")
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,7 +102,7 @@ void export_style()
|
||||||
.add_property("filter_mode",
|
.add_property("filter_mode",
|
||||||
&feature_type_style::get_filter_mode,
|
&feature_type_style::get_filter_mode,
|
||||||
&feature_type_style::set_filter_mode,
|
&feature_type_style::set_filter_mode,
|
||||||
"Set/get the placement of the label")
|
"Set/get the filter mode of the style")
|
||||||
;
|
;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,10 @@
|
||||||
|
|
||||||
namespace mapnik {
|
namespace mapnik {
|
||||||
|
|
||||||
|
/*
|
||||||
|
Global logger class that holds the configuration of severity, format
|
||||||
|
and file/console redirection.
|
||||||
|
*/
|
||||||
class MAPNIK_DECL logger :
|
class MAPNIK_DECL logger :
|
||||||
public singleton<logger,CreateStatic>,
|
public singleton<logger,CreateStatic>,
|
||||||
private boost::noncopyable
|
private boost::noncopyable
|
||||||
|
@ -153,6 +157,9 @@ namespace mapnik {
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
|
/*
|
||||||
|
Default sink, it regulates access to clog
|
||||||
|
*/
|
||||||
template<class Ch, class Tr, class A>
|
template<class Ch, class Tr, class A>
|
||||||
class clog_sink
|
class clog_sink
|
||||||
{
|
{
|
||||||
|
@ -170,6 +177,12 @@ namespace mapnik {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Base log class, should not log anything when no MAPNIK_LOG is defined
|
||||||
|
|
||||||
|
This is used for info/debug/warn reporting that should not output
|
||||||
|
anything when not compiling for speed.
|
||||||
|
*/
|
||||||
template<template <class Ch, class Tr, class A> class OutputPolicy,
|
template<template <class Ch, class Tr, class A> class OutputPolicy,
|
||||||
logger::severity_type Severity,
|
logger::severity_type Severity,
|
||||||
class Ch = char,
|
class Ch = char,
|
||||||
|
@ -223,14 +236,67 @@ namespace mapnik {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Base log class that always log, regardless of MAPNIK_LOG.
|
||||||
|
|
||||||
|
This is used for error/fatal reporting that should always log something
|
||||||
|
*/
|
||||||
|
template<template <class Ch, class Tr, class A> class OutputPolicy,
|
||||||
|
logger::severity_type Severity,
|
||||||
|
class Ch = char,
|
||||||
|
class Tr = std::char_traits<Ch>,
|
||||||
|
class A = std::allocator<Ch> >
|
||||||
|
class base_log_always : public boost::noncopyable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef OutputPolicy<Ch, Tr, A> output_policy;
|
||||||
|
|
||||||
|
base_log_always() {}
|
||||||
|
|
||||||
|
base_log_always(const char* object_name)
|
||||||
|
{
|
||||||
|
if (object_name != NULL)
|
||||||
|
{
|
||||||
|
object_name_ = object_name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~base_log_always()
|
||||||
|
{
|
||||||
|
if (check_severity())
|
||||||
|
{
|
||||||
|
output_policy()(Severity, streambuf_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
base_log_always &operator<<(const T &x)
|
||||||
|
{
|
||||||
|
streambuf_ << x;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline bool check_severity()
|
||||||
|
{
|
||||||
|
return Severity >= logger::get_object_severity(object_name_);
|
||||||
|
}
|
||||||
|
|
||||||
|
typename output_policy::stream_buffer streambuf_;
|
||||||
|
std::string object_name_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
typedef base_log<clog_sink, logger::info> base_log_info;
|
typedef base_log<clog_sink, logger::info> base_log_info;
|
||||||
typedef base_log<clog_sink, logger::debug> base_log_debug;
|
typedef base_log<clog_sink, logger::debug> base_log_debug;
|
||||||
typedef base_log<clog_sink, logger::warn> base_log_warn;
|
typedef base_log<clog_sink, logger::warn> base_log_warn;
|
||||||
typedef base_log<clog_sink, logger::error> base_log_error;
|
typedef base_log_always<clog_sink, logger::error> base_log_error;
|
||||||
typedef base_log<clog_sink, logger::fatal> base_log_fatal;
|
typedef base_log_always<clog_sink, logger::fatal> base_log_fatal;
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
|
|
||||||
// real interfaces
|
// real interfaces
|
||||||
class MAPNIK_DECL info : public detail::base_log_info {
|
class MAPNIK_DECL info : public detail::base_log_info {
|
||||||
public:
|
public:
|
||||||
|
@ -262,6 +328,7 @@ namespace mapnik {
|
||||||
fatal(const char* object_name) : detail::base_log_fatal(object_name) {}
|
fatal(const char* object_name) : detail::base_log_fatal(object_name) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// logging helpers
|
// logging helpers
|
||||||
#define MAPNIK_LOG_INFO(s) mapnik::info(#s)
|
#define MAPNIK_LOG_INFO(s) mapnik::info(#s)
|
||||||
#define MAPNIK_LOG_DEBUG(s) mapnik::debug(#s)
|
#define MAPNIK_LOG_DEBUG(s) mapnik::debug(#s)
|
||||||
|
|
|
@ -141,9 +141,8 @@ struct expression_grammar : qi::grammar<Iterator, expr_node(), space_type>
|
||||||
using qi::_r1;
|
using qi::_r1;
|
||||||
#if BOOST_VERSION > 104200
|
#if BOOST_VERSION > 104200
|
||||||
using qi::no_skip;
|
using qi::no_skip;
|
||||||
#else
|
|
||||||
using qi::lexeme;
|
|
||||||
#endif
|
#endif
|
||||||
|
using qi::lexeme;
|
||||||
using qi::_val;
|
using qi::_val;
|
||||||
using qi::lit;
|
using qi::lit;
|
||||||
using qi::int_;
|
using qi::int_;
|
||||||
|
|
|
@ -39,7 +39,8 @@ class layer_descriptor
|
||||||
public:
|
public:
|
||||||
layer_descriptor(std::string const& name, std::string const& encoding)
|
layer_descriptor(std::string const& name, std::string const& encoding)
|
||||||
: name_(name),
|
: name_(name),
|
||||||
encoding_(encoding) {}
|
encoding_(encoding),
|
||||||
|
desc_ar_() {}
|
||||||
|
|
||||||
layer_descriptor(layer_descriptor const& other)
|
layer_descriptor(layer_descriptor const& other)
|
||||||
: name_(other.name_),
|
: name_(other.name_),
|
||||||
|
|
|
@ -266,7 +266,8 @@ class MAPNIK_DECL face_manager : private boost::noncopyable
|
||||||
public:
|
public:
|
||||||
face_manager(T & engine)
|
face_manager(T & engine)
|
||||||
: engine_(engine),
|
: engine_(engine),
|
||||||
stroker_(engine_.create_stroker()) {}
|
stroker_(engine_.create_stroker()),
|
||||||
|
face_ptr_cache_() {}
|
||||||
|
|
||||||
face_ptr get_face(std::string const& name)
|
face_ptr get_face(std::string const& name)
|
||||||
{
|
{
|
||||||
|
@ -303,16 +304,19 @@ public:
|
||||||
face_set_ptr face_set = boost::make_shared<font_face_set>();
|
face_set_ptr face_set = boost::make_shared<font_face_set>();
|
||||||
for (std::vector<std::string>::const_iterator name = names.begin(); name != names.end(); ++name)
|
for (std::vector<std::string>::const_iterator name = names.begin(); name != names.end(); ++name)
|
||||||
{
|
{
|
||||||
if (face_ptr face = get_face(*name))
|
face_ptr face = get_face(*name);
|
||||||
|
if (face)
|
||||||
{
|
{
|
||||||
face_set->add(face);
|
face_set->add(face);
|
||||||
}
|
}
|
||||||
|
#ifdef MAPNIK_LOG
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MAPNIK_LOG_ERROR(font_engine_freetype)
|
MAPNIK_LOG_DEBUG(font_engine_freetype)
|
||||||
<< "Failed to find face '" << *name
|
<< "Failed to find face '" << *name
|
||||||
<< "' in font set '" << fset.get_name() << "'\n";
|
<< "' in font set '" << fset.get_name() << "'\n";
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return face_set;
|
return face_set;
|
||||||
}
|
}
|
||||||
|
@ -335,9 +339,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
face_ptr_cache_type face_ptr_cache_;
|
|
||||||
font_engine_type & engine_;
|
font_engine_type & engine_;
|
||||||
stroker_ptr stroker_;
|
stroker_ptr stroker_;
|
||||||
|
face_ptr_cache_type face_ptr_cache_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|
|
@ -63,13 +63,13 @@ private:
|
||||||
unsigned width_;
|
unsigned width_;
|
||||||
unsigned height_;
|
unsigned height_;
|
||||||
std::string key_;
|
std::string key_;
|
||||||
feature_key_type f_keys_;
|
|
||||||
feature_type features_;
|
|
||||||
data_type data_;
|
data_type data_;
|
||||||
std::set<std::string> names_;
|
|
||||||
unsigned int resolution_;
|
unsigned int resolution_;
|
||||||
std::string id_name_;
|
std::string id_name_;
|
||||||
bool painted_;
|
bool painted_;
|
||||||
|
std::set<std::string> names_;
|
||||||
|
feature_key_type f_keys_;
|
||||||
|
feature_type features_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -80,7 +80,10 @@ public:
|
||||||
data_(width,height),
|
data_(width,height),
|
||||||
resolution_(resolution),
|
resolution_(resolution),
|
||||||
id_name_("__id__"),
|
id_name_("__id__"),
|
||||||
painted_(false)
|
painted_(false),
|
||||||
|
names_(),
|
||||||
|
f_keys_(),
|
||||||
|
features_()
|
||||||
{
|
{
|
||||||
// this only works if each datasource's
|
// this only works if each datasource's
|
||||||
// feature count starts at 1
|
// feature count starts at 1
|
||||||
|
@ -94,7 +97,10 @@ public:
|
||||||
data_(rhs.data_),
|
data_(rhs.data_),
|
||||||
resolution_(rhs.resolution_),
|
resolution_(rhs.resolution_),
|
||||||
id_name_("__id__"),
|
id_name_("__id__"),
|
||||||
painted_(rhs.painted_)
|
painted_(rhs.painted_),
|
||||||
|
names_(rhs.names_),
|
||||||
|
f_keys_(rhs.f_keys_),
|
||||||
|
features_(rhs.features_)
|
||||||
{
|
{
|
||||||
f_keys_[0] = "";
|
f_keys_[0] = "";
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,12 @@
|
||||||
#ifndef MAPNIK_IMAGE_COMPOSITING_HPP
|
#ifndef MAPNIK_IMAGE_COMPOSITING_HPP
|
||||||
#define MAPNIK_IMAGE_COMPOSITING_HPP
|
#define MAPNIK_IMAGE_COMPOSITING_HPP
|
||||||
|
|
||||||
|
#include <mapnik/config.hpp>
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#include <mapnik/image_data.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
// agg
|
// agg
|
||||||
|
|
||||||
namespace mapnik
|
namespace mapnik
|
||||||
|
@ -64,7 +70,11 @@ enum composite_mode_e
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T1, typename T2>
|
template <typename T1, typename T2>
|
||||||
void composite(T1 & im, T2 & im2, composite_mode_e mode);
|
MAPNIK_DECL void composite(T1 & im, T2 & im2, composite_mode_e mode);
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
template MAPNIK_DECL void composite<mapnik::image_data_32,mapnik::image_data_32>(mapnik::image_data_32 & im, mapnik::image_data_32 & im2, composite_mode_e mode);
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif // MAPNIK_IMAGE_COMPOSITING_HPP
|
#endif // MAPNIK_IMAGE_COMPOSITING_HPP
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#ifndef MAPNIK_GEOJSON_GENERATOR_HPP
|
#ifndef MAPNIK_GEOJSON_GENERATOR_HPP
|
||||||
#define MAPNIK_GEOJSON_GENERATOR_HPP
|
#define MAPNIK_GEOJSON_GENERATOR_HPP
|
||||||
|
|
||||||
|
#include <mapnik/config.hpp>
|
||||||
#include <mapnik/feature.hpp>
|
#include <mapnik/feature.hpp>
|
||||||
#include <boost/scoped_ptr.hpp>
|
#include <boost/scoped_ptr.hpp>
|
||||||
#include <boost/utility.hpp>
|
#include <boost/utility.hpp>
|
||||||
|
@ -35,7 +36,7 @@ namespace mapnik { namespace json {
|
||||||
template <typename OutputIterator> struct feature_generator_grammar;
|
template <typename OutputIterator> struct feature_generator_grammar;
|
||||||
template <typename OutputIterator> struct multi_geometry_generator_grammar;
|
template <typename OutputIterator> struct multi_geometry_generator_grammar;
|
||||||
|
|
||||||
class feature_generator : private boost::noncopyable
|
class MAPNIK_DECL feature_generator : private boost::noncopyable
|
||||||
{
|
{
|
||||||
typedef std::back_insert_iterator<std::string> sink_type;
|
typedef std::back_insert_iterator<std::string> sink_type;
|
||||||
public:
|
public:
|
||||||
|
@ -46,7 +47,7 @@ private:
|
||||||
boost::scoped_ptr<feature_generator_grammar<sink_type> > grammar_;
|
boost::scoped_ptr<feature_generator_grammar<sink_type> > grammar_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class geometry_generator : private boost::noncopyable
|
class MAPNIK_DECL geometry_generator : private boost::noncopyable
|
||||||
{
|
{
|
||||||
typedef std::back_insert_iterator<std::string> sink_type;
|
typedef std::back_insert_iterator<std::string> sink_type;
|
||||||
public:
|
public:
|
||||||
|
@ -59,7 +60,7 @@ private:
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
class feature_generator : private boost::noncopyable
|
class MAPNIK_DECL feature_generator : private boost::noncopyable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
feature_generator() {}
|
feature_generator() {}
|
||||||
|
@ -67,7 +68,7 @@ public:
|
||||||
bool generate(std::string & geojson, mapnik::Feature const& f);
|
bool generate(std::string & geojson, mapnik::Feature const& f);
|
||||||
};
|
};
|
||||||
|
|
||||||
class geometry_generator : private boost::noncopyable
|
class MAPNIK_DECL geometry_generator : private boost::noncopyable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
geometry_generator() {}
|
geometry_generator() {}
|
||||||
|
|
|
@ -140,7 +140,7 @@ class label_collision_detector4 : boost::noncopyable
|
||||||
public:
|
public:
|
||||||
struct label
|
struct label
|
||||||
{
|
{
|
||||||
label(box2d<double> const& b) : box(b) {}
|
label(box2d<double> const& b) : box(b), text() {}
|
||||||
label(box2d<double> const& b, UnicodeString const& t) : box(b), text(t) {}
|
label(box2d<double> const& b, UnicodeString const& t) : box(b), text(t) {}
|
||||||
|
|
||||||
box2d<double> box;
|
box2d<double> box;
|
||||||
|
|
|
@ -50,13 +50,18 @@ public:
|
||||||
typedef std::map<std::string, UnicodeString> property_map;
|
typedef std::map<std::string, UnicodeString> property_map;
|
||||||
typedef property_map::const_iterator const_iterator;
|
typedef property_map::const_iterator const_iterator;
|
||||||
|
|
||||||
metawriter_property_map() {}
|
metawriter_property_map() :
|
||||||
|
m_(),
|
||||||
|
not_found_() {}
|
||||||
|
|
||||||
UnicodeString const& operator[](std::string const& key) const;
|
UnicodeString const& operator[](std::string const& key) const;
|
||||||
UnicodeString& operator[](std::string const& key) {return m_[key];}
|
UnicodeString& operator[](std::string const& key) {return m_[key];}
|
||||||
|
|
||||||
std::map<std::string, UnicodeString>::const_iterator find(std::string const& key) const
|
std::map<std::string, UnicodeString>::const_iterator find(std::string const& key) const
|
||||||
{
|
{
|
||||||
return m_.find(key);
|
return m_.find(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<std::string, UnicodeString>::const_iterator end() const
|
std::map<std::string, UnicodeString>::const_iterator end() const
|
||||||
{
|
{
|
||||||
return m_.end();
|
return m_.end();
|
||||||
|
@ -66,6 +71,7 @@ public:
|
||||||
{
|
{
|
||||||
return (*this)[key];
|
return (*this)[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
property_map m_;
|
property_map m_;
|
||||||
UnicodeString not_found_;
|
UnicodeString not_found_;
|
||||||
|
|
|
@ -80,17 +80,22 @@ struct rgba
|
||||||
byte a;
|
byte a;
|
||||||
|
|
||||||
inline rgba(byte r_, byte g_, byte b_, byte a_)
|
inline rgba(byte r_, byte g_, byte b_, byte a_)
|
||||||
: r(r_), g(g_), b(b_), a(a_) {}
|
: r(r_),
|
||||||
|
g(g_),
|
||||||
|
b(b_),
|
||||||
|
a(a_) {}
|
||||||
|
|
||||||
inline rgba(rgb const& c)
|
inline rgba(rgb const& c)
|
||||||
: r(c.r), g(c.g), b(c.b), a(0xFF) {}
|
: r(c.r),
|
||||||
|
g(c.g),
|
||||||
|
b(c.b),
|
||||||
|
a(0xFF) {}
|
||||||
|
|
||||||
inline rgba(unsigned const& c) {
|
inline rgba(unsigned const& c)
|
||||||
r = U2RED(c);
|
: r(U2RED(c)),
|
||||||
g = U2GREEN(c);
|
g(U2GREEN(c)),
|
||||||
b = U2BLUE(c);
|
b(U2BLUE(c)),
|
||||||
a = U2ALPHA(c);
|
a(U2ALPHA(c)) {}
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator==(const rgba& y) const
|
inline bool operator==(const rgba& y) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -47,8 +47,8 @@ template <typename Iterator> struct path_expression_grammar;
|
||||||
|
|
||||||
MAPNIK_DECL path_expression_ptr parse_path(std::string const & str);
|
MAPNIK_DECL path_expression_ptr parse_path(std::string const & str);
|
||||||
MAPNIK_DECL bool parse_path_from_string(path_expression_ptr const& path,
|
MAPNIK_DECL bool parse_path_from_string(path_expression_ptr const& path,
|
||||||
std::string const & str,
|
std::string const & str,
|
||||||
path_expression_grammar<std::string::const_iterator> const& g);
|
path_expression_grammar<std::string::const_iterator> const& g);
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|
|
@ -86,23 +86,20 @@ class quad_tree : boost::noncopyable
|
||||||
typedef typename node::cont_t cont_t;
|
typedef typename node::cont_t cont_t;
|
||||||
typedef typename cont_t::iterator node_data_iterator;
|
typedef typename cont_t::iterator node_data_iterator;
|
||||||
|
|
||||||
nodes_t nodes_;
|
|
||||||
node * root_;
|
|
||||||
const unsigned int max_depth_;
|
|
||||||
const double ratio_;
|
|
||||||
public:
|
public:
|
||||||
typedef typename nodes_t::iterator iterator;
|
typedef typename nodes_t::iterator iterator;
|
||||||
typedef typename nodes_t::const_iterator const_iterator;
|
typedef typename nodes_t::const_iterator const_iterator;
|
||||||
typedef typename boost::ptr_vector<T,boost::view_clone_allocator> result_t;
|
typedef typename boost::ptr_vector<T,boost::view_clone_allocator> result_t;
|
||||||
typedef typename result_t::iterator query_iterator;
|
typedef typename result_t::iterator query_iterator;
|
||||||
|
|
||||||
result_t query_result_;
|
|
||||||
|
|
||||||
explicit quad_tree(box2d<double> const& ext,
|
explicit quad_tree(box2d<double> const& ext,
|
||||||
unsigned int max_depth = 8,
|
unsigned int max_depth = 8,
|
||||||
double ratio = 0.55)
|
double ratio = 0.55)
|
||||||
: max_depth_(max_depth),
|
: max_depth_(max_depth),
|
||||||
ratio_(ratio)
|
ratio_(ratio),
|
||||||
|
query_result_(),
|
||||||
|
nodes_()
|
||||||
{
|
{
|
||||||
nodes_.push_back(new node(ext));
|
nodes_.push_back(new node(ext));
|
||||||
root_ = &nodes_[0];
|
root_ = &nodes_[0];
|
||||||
|
@ -219,6 +216,13 @@ private:
|
||||||
ext[2]=box2d<double>(lox,hiy - height*ratio_,lox + width * ratio_,hiy);
|
ext[2]=box2d<double>(lox,hiy - height*ratio_,lox + width * ratio_,hiy);
|
||||||
ext[3]=box2d<double>(hix - width * ratio_,hiy - height*ratio_,hix,hiy);
|
ext[3]=box2d<double>(hix - width * ratio_,hiy - height*ratio_,hix,hiy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const unsigned int max_depth_;
|
||||||
|
const double ratio_;
|
||||||
|
result_t query_result_;
|
||||||
|
nodes_t nodes_;
|
||||||
|
node * root_;
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,14 +40,6 @@ class query
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef boost::tuple<double,double> resolution_type;
|
typedef boost::tuple<double,double> resolution_type;
|
||||||
private:
|
|
||||||
box2d<double> bbox_;
|
|
||||||
resolution_type resolution_;
|
|
||||||
double scale_denominator_;
|
|
||||||
double filter_factor_;
|
|
||||||
box2d<double> unbuffered_bbox_;
|
|
||||||
std::set<std::string> names_;
|
|
||||||
public:
|
|
||||||
|
|
||||||
query(box2d<double> const& bbox,
|
query(box2d<double> const& bbox,
|
||||||
resolution_type const& resolution,
|
resolution_type const& resolution,
|
||||||
|
@ -57,7 +49,8 @@ public:
|
||||||
resolution_(resolution),
|
resolution_(resolution),
|
||||||
scale_denominator_(scale_denominator),
|
scale_denominator_(scale_denominator),
|
||||||
filter_factor_(1.0),
|
filter_factor_(1.0),
|
||||||
unbuffered_bbox_(unbuffered_bbox)
|
unbuffered_bbox_(unbuffered_bbox),
|
||||||
|
names_()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
query(box2d<double> const& bbox,
|
query(box2d<double> const& bbox,
|
||||||
|
@ -67,7 +60,8 @@ public:
|
||||||
resolution_(resolution),
|
resolution_(resolution),
|
||||||
scale_denominator_(scale_denominator),
|
scale_denominator_(scale_denominator),
|
||||||
filter_factor_(1.0),
|
filter_factor_(1.0),
|
||||||
unbuffered_bbox_(bbox)
|
unbuffered_bbox_(bbox),
|
||||||
|
names_()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
query(box2d<double> const& bbox)
|
query(box2d<double> const& bbox)
|
||||||
|
@ -75,7 +69,8 @@ public:
|
||||||
resolution_(resolution_type(1.0,1.0)),
|
resolution_(resolution_type(1.0,1.0)),
|
||||||
scale_denominator_(1.0),
|
scale_denominator_(1.0),
|
||||||
filter_factor_(1.0),
|
filter_factor_(1.0),
|
||||||
unbuffered_bbox_(bbox)
|
unbuffered_bbox_(bbox),
|
||||||
|
names_()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
query(query const& other)
|
query(query const& other)
|
||||||
|
@ -94,8 +89,8 @@ public:
|
||||||
resolution_=other.resolution_;
|
resolution_=other.resolution_;
|
||||||
scale_denominator_=other.scale_denominator_;
|
scale_denominator_=other.scale_denominator_;
|
||||||
filter_factor_=other.filter_factor_;
|
filter_factor_=other.filter_factor_;
|
||||||
names_=other.names_;
|
|
||||||
unbuffered_bbox_=other.unbuffered_bbox_;
|
unbuffered_bbox_=other.unbuffered_bbox_;
|
||||||
|
names_=other.names_;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,12 +114,12 @@ public:
|
||||||
return unbuffered_bbox_;
|
return unbuffered_bbox_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_unbuffered_bbox(const box2d<double>& bbox)
|
void set_unbuffered_bbox(box2d<double> const& bbox)
|
||||||
{
|
{
|
||||||
unbuffered_bbox_ = bbox;
|
unbuffered_bbox_ = bbox;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_bbox(const box2d<double>& bbox)
|
void set_bbox(box2d<double> const& bbox)
|
||||||
{
|
{
|
||||||
bbox_ = bbox;
|
bbox_ = bbox;
|
||||||
}
|
}
|
||||||
|
@ -148,6 +143,14 @@ public:
|
||||||
{
|
{
|
||||||
return names_;
|
return names_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
box2d<double> bbox_;
|
||||||
|
resolution_type resolution_;
|
||||||
|
double scale_denominator_;
|
||||||
|
double filter_factor_;
|
||||||
|
box2d<double> unbuffered_bbox_;
|
||||||
|
std::set<std::string> names_;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -279,7 +279,8 @@ public:
|
||||||
{
|
{
|
||||||
ras.reset();
|
ras.reset();
|
||||||
|
|
||||||
if(fabs(curved_trans_contour.width()) < 0.0001)
|
// https://github.com/mapnik/mapnik/issues/1129
|
||||||
|
if(fabs(curved_trans_contour.width()) <= 1)
|
||||||
{
|
{
|
||||||
ras.add_path(curved_trans, attr.index);
|
ras.add_path(curved_trans, attr.index);
|
||||||
}
|
}
|
||||||
|
@ -384,7 +385,7 @@ public:
|
||||||
{
|
{
|
||||||
ras.reset();
|
ras.reset();
|
||||||
|
|
||||||
if(fabs(curved_trans_contour.width()) < 0.0001)
|
if(fabs(curved_trans_contour.width()) <= 1)
|
||||||
{
|
{
|
||||||
ras.add_path(curved_trans, attr.index);
|
ras.add_path(curved_trans, attr.index);
|
||||||
}
|
}
|
||||||
|
|
|
@ -157,6 +157,6 @@ private:
|
||||||
std::string base_message_;
|
std::string base_message_;
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
}
|
||||||
|
|
||||||
#endif // MAPNIK_TIMER_HPP
|
#endif // MAPNIK_TIMER_HPP
|
||||||
|
|
|
@ -29,16 +29,73 @@
|
||||||
// stl
|
// stl
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
// boost
|
||||||
|
#include <boost/version.hpp>
|
||||||
|
|
||||||
|
#if BOOST_VERSION >= 104500
|
||||||
|
#include <boost/config/warning_disable.hpp>
|
||||||
|
#include <boost/spirit/include/karma.hpp>
|
||||||
|
#else
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace mapnik { namespace util {
|
namespace mapnik { namespace util {
|
||||||
|
|
||||||
MAPNIK_DECL bool string2int(std::string const& value, int & result);
|
MAPNIK_DECL bool string2int(const char * value, int & result);
|
||||||
MAPNIK_DECL bool string2int(const char * value, int & result);
|
MAPNIK_DECL bool string2int(std::string const& value, int & result);
|
||||||
|
|
||||||
MAPNIK_DECL bool string2double(std::string const& value, double & result);
|
MAPNIK_DECL bool string2double(std::string const& value, double & result);
|
||||||
MAPNIK_DECL bool string2double(const char * value, double & result);
|
MAPNIK_DECL bool string2double(const char * value, double & result);
|
||||||
|
|
||||||
MAPNIK_DECL bool string2float(std::string const& value, float & result);
|
MAPNIK_DECL bool string2float(std::string const& value, float & result);
|
||||||
MAPNIK_DECL bool string2float(const char * value, float & result);
|
MAPNIK_DECL bool string2float(const char * value, float & result);
|
||||||
|
|
||||||
|
#if BOOST_VERSION >= 104500
|
||||||
|
// generic
|
||||||
|
template <typename T>
|
||||||
|
bool to_string(std::string & str, T value)
|
||||||
|
{
|
||||||
|
namespace karma = boost::spirit::karma;
|
||||||
|
std::back_insert_iterator<std::string> sink(str);
|
||||||
|
return karma::generate(sink, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct double_policy : boost::spirit::karma::real_policies<T>
|
||||||
|
{
|
||||||
|
typedef boost::spirit::karma::real_policies<T> base_type;
|
||||||
|
static int floatfield(T n) { return base_type::fmtflags::fixed; }
|
||||||
|
static unsigned precision(T n) { return 16 ;}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// specialisation for double
|
||||||
|
template <>
|
||||||
|
inline bool to_string(std::string & str, double value)
|
||||||
|
{
|
||||||
|
namespace karma = boost::spirit::karma;
|
||||||
|
typedef boost::spirit::karma::real_generator<double, double_policy<double> > double_type;
|
||||||
|
std::back_insert_iterator<std::string> sink(str);
|
||||||
|
return karma::generate(sink, double_type(), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool to_string(std::string & str, T value)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
str = boost::lexical_cast<T>(value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (std::exception const& ex)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,9 @@ namespace mapnik { namespace util {
|
||||||
typedef vertex_vector<T> container_type;
|
typedef vertex_vector<T> container_type;
|
||||||
|
|
||||||
vertex_iterator()
|
vertex_iterator()
|
||||||
: v_(SEG_END,0,0)
|
: v_(SEG_END,0,0),
|
||||||
|
vertices_(),
|
||||||
|
pos_(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
explicit vertex_iterator(container_type const& vertices)
|
explicit vertex_iterator(container_type const& vertices)
|
||||||
|
@ -74,8 +76,8 @@ namespace mapnik { namespace util {
|
||||||
return v_;
|
return v_;
|
||||||
}
|
}
|
||||||
|
|
||||||
container_type const *vertices_;
|
|
||||||
value_type v_;
|
value_type v_;
|
||||||
|
container_type const *vertices_;
|
||||||
unsigned pos_;
|
unsigned pos_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -36,8 +36,6 @@
|
||||||
// stl
|
// stl
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
|
||||||
#include <iomanip>
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
// uci
|
// uci
|
||||||
|
@ -338,20 +336,34 @@ struct add : public boost::static_visitor<V>
|
||||||
return lhs + rhs;
|
return lhs + rhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
value_type operator() (UnicodeString const& lhs, value_null rhs) const
|
||||||
|
{
|
||||||
|
boost::ignore_unused_variable_warning(rhs);
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
value_type operator() (value_null lhs, UnicodeString const& rhs) const
|
||||||
|
{
|
||||||
|
boost::ignore_unused_variable_warning(lhs);
|
||||||
|
return rhs;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename R>
|
template <typename R>
|
||||||
value_type operator() (UnicodeString const& lhs, R const& rhs) const
|
value_type operator() (UnicodeString const& lhs, R const& rhs) const
|
||||||
{
|
{
|
||||||
std::basic_ostringstream<char> out;
|
std::string val;
|
||||||
out << rhs;
|
if (util::to_string(val,rhs))
|
||||||
return lhs + UnicodeString(out.str().c_str());
|
return lhs + UnicodeString(val.c_str());
|
||||||
|
return lhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename L>
|
template <typename L>
|
||||||
value_type operator() (L const& lhs , UnicodeString const& rhs) const
|
value_type operator() (L const& lhs , UnicodeString const& rhs) const
|
||||||
{
|
{
|
||||||
std::basic_ostringstream<char> out;
|
std::string val;
|
||||||
out << lhs;
|
if (util::to_string(val,lhs))
|
||||||
return UnicodeString(out.str().c_str()) + rhs;
|
return UnicodeString(val.c_str()) + rhs;
|
||||||
|
return rhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T1, typename T2>
|
template <typename T1, typename T2>
|
||||||
|
@ -540,14 +552,14 @@ struct to_bool : public boost::static_visitor<bool>
|
||||||
|
|
||||||
struct to_string : public boost::static_visitor<std::string>
|
struct to_string : public boost::static_visitor<std::string>
|
||||||
{
|
{
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::string operator() (T val) const
|
std::string operator() (T val) const
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::string str;
|
||||||
ss << val;
|
util::to_string(str, val);
|
||||||
return ss.str();
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
// specializations
|
// specializations
|
||||||
std::string operator() (UnicodeString const& val) const
|
std::string operator() (UnicodeString const& val) const
|
||||||
{
|
{
|
||||||
|
@ -558,9 +570,9 @@ struct to_string : public boost::static_visitor<std::string>
|
||||||
|
|
||||||
std::string operator() (double val) const
|
std::string operator() (double val) const
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::string str;
|
||||||
ss << std::setprecision(16) << val;
|
util::to_string(str, val); // TODO set precision(16)
|
||||||
return ss.str();
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string operator() (value_null const& val) const
|
std::string operator() (value_null const& val) const
|
||||||
|
@ -576,9 +588,9 @@ struct to_unicode : public boost::static_visitor<UnicodeString>
|
||||||
template <typename T>
|
template <typename T>
|
||||||
UnicodeString operator() (T val) const
|
UnicodeString operator() (T val) const
|
||||||
{
|
{
|
||||||
std::basic_ostringstream<char> out;
|
std::string str;
|
||||||
out << val;
|
util::to_string(str,val);
|
||||||
return UnicodeString(out.str().c_str());
|
return UnicodeString(str.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// specializations
|
// specializations
|
||||||
|
@ -589,9 +601,9 @@ struct to_unicode : public boost::static_visitor<UnicodeString>
|
||||||
|
|
||||||
UnicodeString operator() (double val) const
|
UnicodeString operator() (double val) const
|
||||||
{
|
{
|
||||||
std::basic_ostringstream<char> out;
|
std::string str;
|
||||||
out << std::setprecision(16) << val;
|
util::to_string(str,val);
|
||||||
return UnicodeString(out.str().c_str());
|
return UnicodeString(str.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
UnicodeString operator() (value_null const& val) const
|
UnicodeString operator() (value_null const& val) const
|
||||||
|
@ -612,9 +624,9 @@ struct to_expression_string : public boost::static_visitor<std::string>
|
||||||
|
|
||||||
std::string operator() (double val) const
|
std::string operator() (double val) const
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::string output;
|
||||||
ss << std::setprecision(16) << val;
|
util::to_string(output,val); // TODO precision(16)
|
||||||
return ss.str();
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string operator() (bool val) const
|
std::string operator() (bool val) const
|
||||||
|
@ -651,17 +663,17 @@ struct to_double : public boost::static_visitor<double>
|
||||||
|
|
||||||
double operator() (std::string const& val) const
|
double operator() (std::string const& val) const
|
||||||
{
|
{
|
||||||
double ret(0);
|
double result;
|
||||||
mapnik::util::string2double(val,ret);
|
if (util::string2double(val,result))
|
||||||
return ret;
|
return result;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
double operator() (UnicodeString const& val) const
|
double operator() (UnicodeString const& val) const
|
||||||
{
|
{
|
||||||
std::string utf8;
|
std::string utf8;
|
||||||
to_utf8(val,utf8);
|
to_utf8(val,utf8);
|
||||||
double ret(0);
|
return operator()(utf8);
|
||||||
mapnik::util::string2double(utf8,ret);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double operator() (value_null const& val) const
|
double operator() (value_null const& val) const
|
||||||
|
@ -685,17 +697,17 @@ struct to_int : public boost::static_visitor<double>
|
||||||
|
|
||||||
int operator() (std::string const& val) const
|
int operator() (std::string const& val) const
|
||||||
{
|
{
|
||||||
int ret(0);
|
int result;
|
||||||
mapnik::util::string2int(val,ret);
|
if (util::string2int(val,result))
|
||||||
return ret;
|
return result;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int operator() (UnicodeString const& val) const
|
int operator() (UnicodeString const& val) const
|
||||||
{
|
{
|
||||||
std::string utf8;
|
std::string utf8;
|
||||||
to_utf8(val,utf8);
|
to_utf8(val,utf8);
|
||||||
int ret(0);
|
return operator()(utf8);
|
||||||
mapnik::util::string2int(utf8,ret);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int operator() (value_null const& val) const
|
int operator() (value_null const& val) const
|
||||||
|
|
|
@ -31,12 +31,14 @@ namespace mapnik {
|
||||||
class value_error : public std::exception
|
class value_error : public std::exception
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
value_error() {}
|
value_error() :
|
||||||
|
what_() {}
|
||||||
|
|
||||||
value_error( std::string const& what ) :
|
value_error( std::string const& what ) :
|
||||||
what_( what )
|
what_( what )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~value_error() throw() {};
|
virtual ~value_error() throw() {};
|
||||||
|
|
||||||
virtual const char * what() const throw()
|
virtual const char * what() const throw()
|
||||||
|
|
|
@ -386,6 +386,9 @@ boost::optional<mapnik::datasource::geometry_t> ogr_datasource::get_geometry_typ
|
||||||
if (dataset_ && layer_.is_valid())
|
if (dataset_ && layer_.is_valid())
|
||||||
{
|
{
|
||||||
OGRLayer* layer = layer_.layer();
|
OGRLayer* layer = layer_.layer();
|
||||||
|
// only new either reset of setNext
|
||||||
|
//layer->ResetReading();
|
||||||
|
layer->SetNextByIndex(0);
|
||||||
ogr_feature_ptr feat(layer->GetNextFeature());
|
ogr_feature_ptr feat(layer->GetNextFeature());
|
||||||
if ((*feat) != NULL)
|
if ((*feat) != NULL)
|
||||||
{
|
{
|
||||||
|
|
|
@ -67,6 +67,7 @@ postgis_datasource::postgis_datasource(parameters const& params, bool bind)
|
||||||
type_(datasource::Vector),
|
type_(datasource::Vector),
|
||||||
srid_(*params_.get<int>("srid", 0)),
|
srid_(*params_.get<int>("srid", 0)),
|
||||||
extent_initialized_(false),
|
extent_initialized_(false),
|
||||||
|
simplify_geometries_(false),
|
||||||
desc_(*params_.get<std::string>("type"), "utf-8"),
|
desc_(*params_.get<std::string>("type"), "utf-8"),
|
||||||
creator_(params.get<std::string>("host"),
|
creator_(params.get<std::string>("host"),
|
||||||
params.get<std::string>("port"),
|
params.get<std::string>("port"),
|
||||||
|
@ -76,6 +77,8 @@ postgis_datasource::postgis_datasource(parameters const& params, bool bind)
|
||||||
params.get<std::string>("connect_timeout", "4")),
|
params.get<std::string>("connect_timeout", "4")),
|
||||||
bbox_token_("!bbox!"),
|
bbox_token_("!bbox!"),
|
||||||
scale_denom_token_("!scale_denominator!"),
|
scale_denom_token_("!scale_denominator!"),
|
||||||
|
pixel_width_token_("!pixel_width!"),
|
||||||
|
pixel_height_token_("!pixel_height!"),
|
||||||
persist_connection_(*params_.get<mapnik::boolean>("persist_connection", true)),
|
persist_connection_(*params_.get<mapnik::boolean>("persist_connection", true)),
|
||||||
extent_from_subquery_(*params_.get<mapnik::boolean>("extent_from_subquery", false)),
|
extent_from_subquery_(*params_.get<mapnik::boolean>("extent_from_subquery", false)),
|
||||||
// params below are for testing purposes only (will likely be removed at any time)
|
// params below are for testing purposes only (will likely be removed at any time)
|
||||||
|
@ -114,6 +117,9 @@ void postgis_datasource::bind() const
|
||||||
boost::optional<int> max_size = params_.get<int>("max_size", 10);
|
boost::optional<int> max_size = params_.get<int>("max_size", 10);
|
||||||
boost::optional<mapnik::boolean> autodetect_key_field = params_.get<mapnik::boolean>("autodetect_key_field", false);
|
boost::optional<mapnik::boolean> autodetect_key_field = params_.get<mapnik::boolean>("autodetect_key_field", false);
|
||||||
|
|
||||||
|
boost::optional<mapnik::boolean> simplify_opt = params_.get<mapnik::boolean>("simplify_geometries", false);
|
||||||
|
simplify_geometries_ = simplify_opt && *simplify_opt;
|
||||||
|
|
||||||
ConnectionManager* mgr = ConnectionManager::instance();
|
ConnectionManager* mgr = ConnectionManager::instance();
|
||||||
mgr->registerPool(creator_, *initial_size, *max_size);
|
mgr->registerPool(creator_, *initial_size, *max_size);
|
||||||
|
|
||||||
|
@ -233,23 +239,23 @@ void postgis_datasource::bind() const
|
||||||
|
|
||||||
std::ostringstream s;
|
std::ostringstream s;
|
||||||
s << "SELECT a.attname, a.attnum, t.typname, t.typname in ('int2','int4','int8') "
|
s << "SELECT a.attname, a.attnum, t.typname, t.typname in ('int2','int4','int8') "
|
||||||
"AS is_int FROM pg_class c, pg_attribute a, pg_type t, pg_namespace n, pg_index i "
|
"AS is_int FROM pg_class c, pg_attribute a, pg_type t, pg_namespace n, pg_index i "
|
||||||
"WHERE a.attnum > 0 AND a.attrelid = c.oid "
|
"WHERE a.attnum > 0 AND a.attrelid = c.oid "
|
||||||
"AND a.atttypid = t.oid AND c.relnamespace = n.oid "
|
"AND a.atttypid = t.oid AND c.relnamespace = n.oid "
|
||||||
"AND c.oid = i.indrelid AND i.indisprimary = 't' "
|
"AND c.oid = i.indrelid AND i.indisprimary = 't' "
|
||||||
"AND t.typname !~ '^geom' AND c.relname ="
|
"AND t.typname !~ '^geom' AND c.relname ="
|
||||||
<< " '" << mapnik::sql_utils::unquote_double(geometry_table_) << "' "
|
<< " '" << mapnik::sql_utils::unquote_double(geometry_table_) << "' "
|
||||||
//"AND a.attnum = ANY (i.indkey) " // postgres >= 8.1
|
//"AND a.attnum = ANY (i.indkey) " // postgres >= 8.1
|
||||||
<< "AND (i.indkey[0]=a.attnum OR i.indkey[1]=a.attnum OR i.indkey[2]=a.attnum "
|
<< "AND (i.indkey[0]=a.attnum OR i.indkey[1]=a.attnum OR i.indkey[2]=a.attnum "
|
||||||
"OR i.indkey[3]=a.attnum OR i.indkey[4]=a.attnum OR i.indkey[5]=a.attnum "
|
"OR i.indkey[3]=a.attnum OR i.indkey[4]=a.attnum OR i.indkey[5]=a.attnum "
|
||||||
"OR i.indkey[6]=a.attnum OR i.indkey[7]=a.attnum OR i.indkey[8]=a.attnum "
|
"OR i.indkey[6]=a.attnum OR i.indkey[7]=a.attnum OR i.indkey[8]=a.attnum "
|
||||||
"OR i.indkey[9]=a.attnum) ";
|
"OR i.indkey[9]=a.attnum) ";
|
||||||
if (! schema_.empty())
|
if (! schema_.empty())
|
||||||
{
|
{
|
||||||
s << "AND n.nspname='"
|
s << "AND n.nspname='"
|
||||||
<< mapnik::sql_utils::unquote_double(schema_)
|
<< mapnik::sql_utils::unquote_double(schema_)
|
||||||
<< "' ";
|
<< "' ";
|
||||||
}
|
}
|
||||||
s << "ORDER BY a.attnum";
|
s << "ORDER BY a.attnum";
|
||||||
|
|
||||||
shared_ptr<ResultSet> rs_key = conn->executeQuery(s.str());
|
shared_ptr<ResultSet> rs_key = conn->executeQuery(s.str());
|
||||||
|
@ -299,8 +305,8 @@ void postgis_datasource::bind() const
|
||||||
if (*autodetect_key_field && key_field_.empty())
|
if (*autodetect_key_field && key_field_.empty())
|
||||||
{
|
{
|
||||||
throw mapnik::datasource_exception(std::string("PostGIS Plugin: Error: primary key required")
|
throw mapnik::datasource_exception(std::string("PostGIS Plugin: Error: primary key required")
|
||||||
+ " but could not be detected for table '" +
|
+ " but could not be detected for table '" +
|
||||||
geometry_table_ + "', please supply 'key_field' option to specify field to use for primary key");
|
geometry_table_ + "', please supply 'key_field' option to specify field to use for primary key");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (srid_ == 0)
|
if (srid_ == 0)
|
||||||
|
@ -493,10 +499,24 @@ std::string postgis_datasource::populate_tokens(const std::string& sql) const
|
||||||
boost::algorithm::replace_all(populated_sql, scale_denom_token_, ss.str());
|
boost::algorithm::replace_all(populated_sql, scale_denom_token_, ss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (boost::algorithm::icontains(sql, pixel_width_token_))
|
||||||
|
{
|
||||||
|
std::ostringstream ss;
|
||||||
|
ss << 0;
|
||||||
|
boost::algorithm::replace_all(populated_sql, pixel_width_token_, ss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (boost::algorithm::icontains(sql, pixel_height_token_))
|
||||||
|
{
|
||||||
|
std::ostringstream ss;
|
||||||
|
ss << 0;
|
||||||
|
boost::algorithm::replace_all(populated_sql, pixel_height_token_, ss.str());
|
||||||
|
}
|
||||||
|
|
||||||
return populated_sql;
|
return populated_sql;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string postgis_datasource::populate_tokens(const std::string& sql, double scale_denom, box2d<double> const& env) const
|
std::string postgis_datasource::populate_tokens(const std::string& sql, double scale_denom, box2d<double> const& env, double pixel_width, double pixel_height) const
|
||||||
{
|
{
|
||||||
std::string populated_sql = sql;
|
std::string populated_sql = sql;
|
||||||
std::string box = sql_bbox(env);
|
std::string box = sql_bbox(env);
|
||||||
|
@ -508,6 +528,20 @@ std::string postgis_datasource::populate_tokens(const std::string& sql, double s
|
||||||
boost::algorithm::replace_all(populated_sql, scale_denom_token_, ss.str());
|
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_))
|
if (boost::algorithm::icontains(populated_sql, bbox_token_))
|
||||||
{
|
{
|
||||||
boost::algorithm::replace_all(populated_sql, bbox_token_, box);
|
boost::algorithm::replace_all(populated_sql, bbox_token_, box);
|
||||||
|
@ -607,7 +641,24 @@ featureset_ptr postgis_datasource::features(const query& q) const
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostringstream s;
|
std::ostringstream s;
|
||||||
s << "SELECT ST_AsBinary(\"" << geometryColumn_ << "\") AS geom";
|
|
||||||
|
const double px_gw = 1.0 / boost::get<0>(q.resolution());
|
||||||
|
const double px_gh = 1.0 / boost::get<1>(q.resolution());
|
||||||
|
|
||||||
|
s << "SELECT ST_AsBinary(";
|
||||||
|
|
||||||
|
if (simplify_geometries_) {
|
||||||
|
s << "ST_Simplify(";
|
||||||
|
}
|
||||||
|
|
||||||
|
s << "\"" << geometryColumn_ << "\"";
|
||||||
|
|
||||||
|
if (simplify_geometries_) {
|
||||||
|
const double tolerance = std::min(px_gw, px_gh) / 2.0;
|
||||||
|
s << ", " << tolerance << ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
s << ") AS geom";
|
||||||
|
|
||||||
mapnik::context_ptr ctx = boost::make_shared<mapnik::context_type>();
|
mapnik::context_ptr ctx = boost::make_shared<mapnik::context_type>();
|
||||||
std::set<std::string> const& props = q.property_names();
|
std::set<std::string> const& props = q.property_names();
|
||||||
|
@ -637,7 +688,7 @@ featureset_ptr postgis_datasource::features(const query& q) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string table_with_bbox = populate_tokens(table_, scale_denom, box);
|
std::string table_with_bbox = populate_tokens(table_, scale_denom, box, px_gw, px_gh);
|
||||||
|
|
||||||
s << " FROM " << table_with_bbox;
|
s << " FROM " << table_with_bbox;
|
||||||
|
|
||||||
|
@ -730,7 +781,7 @@ featureset_ptr postgis_datasource::features_at_point(coord2d const& pt) const
|
||||||
}
|
}
|
||||||
|
|
||||||
box2d<double> box(pt.x, pt.y, pt.x, pt.y);
|
box2d<double> box(pt.x, pt.y, pt.x, pt.y);
|
||||||
std::string table_with_bbox = populate_tokens(table_, FMAX, box);
|
std::string table_with_bbox = populate_tokens(table_, FMAX, box, 0, 0);
|
||||||
|
|
||||||
s << " FROM " << table_with_bbox;
|
s << " FROM " << table_with_bbox;
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string sql_bbox(box2d<double> const& env) const;
|
std::string sql_bbox(box2d<double> const& env) const;
|
||||||
std::string populate_tokens(const std::string& sql, double scale_denom, box2d<double> const& env) const;
|
std::string populate_tokens(const std::string& sql, double scale_denom, box2d<double> const& env, double pixel_width, double pixel_height) const;
|
||||||
std::string populate_tokens(const std::string& sql) const;
|
std::string populate_tokens(const std::string& sql) const;
|
||||||
static std::string unquote(const std::string& sql);
|
static std::string unquote(const std::string& sql);
|
||||||
boost::shared_ptr<IResultSet> get_resultset(boost::shared_ptr<Connection> const &conn, std::string const& sql) const;
|
boost::shared_ptr<IResultSet> get_resultset(boost::shared_ptr<Connection> const &conn, std::string const& sql) const;
|
||||||
|
@ -85,10 +85,13 @@ private:
|
||||||
mutable int srid_;
|
mutable int srid_;
|
||||||
mutable bool extent_initialized_;
|
mutable bool extent_initialized_;
|
||||||
mutable mapnik::box2d<double> extent_;
|
mutable mapnik::box2d<double> extent_;
|
||||||
|
mutable bool simplify_geometries_;
|
||||||
mutable layer_descriptor desc_;
|
mutable layer_descriptor desc_;
|
||||||
ConnectionCreator<Connection> creator_;
|
ConnectionCreator<Connection> creator_;
|
||||||
const std::string bbox_token_;
|
const std::string bbox_token_;
|
||||||
const std::string scale_denom_token_;
|
const std::string scale_denom_token_;
|
||||||
|
const std::string pixel_width_token_;
|
||||||
|
const std::string pixel_height_token_;
|
||||||
bool persist_connection_;
|
bool persist_connection_;
|
||||||
bool extent_from_subquery_;
|
bool extent_from_subquery_;
|
||||||
// params below are for testing purposes only (will likely be removed at any time)
|
// params below are for testing purposes only (will likely be removed at any time)
|
||||||
|
|
|
@ -53,7 +53,7 @@ shape_index_featureset<filterT>::shape_index_featureset(filterT const& filter,
|
||||||
{
|
{
|
||||||
shape_.shp().skip(100);
|
shape_.shp().skip(100);
|
||||||
setup_attributes(ctx_, attribute_names, shape_name, shape_,attr_ids_);
|
setup_attributes(ctx_, attribute_names, shape_name, shape_,attr_ids_);
|
||||||
|
|
||||||
boost::shared_ptr<shape_file> index = shape_.index();
|
boost::shared_ptr<shape_file> index = shape_.index();
|
||||||
if (index)
|
if (index)
|
||||||
{
|
{
|
||||||
|
|
77
src/build.py
77
src/build.py
|
@ -80,13 +80,8 @@ else:
|
||||||
else:
|
else:
|
||||||
lib_env['LIBS'].append([lib for lib in env['LIBS'] if lib.startswith('agg')])
|
lib_env['LIBS'].append([lib for lib in env['LIBS'] if lib.startswith('agg')])
|
||||||
|
|
||||||
|
|
||||||
if env['PLATFORM'] == 'Darwin':
|
|
||||||
mapnik_libname = 'libmapnik.dylib'
|
|
||||||
else:
|
|
||||||
mapnik_libname = 'libmapnik.so.' + ("%d.%d" % (int(ABI_VERSION[0]),int(ABI_VERSION[1])))
|
|
||||||
|
|
||||||
if env['PLATFORM'] == 'Darwin':
|
if env['PLATFORM'] == 'Darwin':
|
||||||
|
mapnik_libname = env.subst(env['MAPNIK_LIB_NAME'])
|
||||||
if env['FULL_LIB_PATH']:
|
if env['FULL_LIB_PATH']:
|
||||||
lib_path = '%s/%s' % (env['MAPNIK_LIB_BASE'],mapnik_libname)
|
lib_path = '%s/%s' % (env['MAPNIK_LIB_BASE'],mapnik_libname)
|
||||||
else:
|
else:
|
||||||
|
@ -94,13 +89,15 @@ if env['PLATFORM'] == 'Darwin':
|
||||||
mapnik_lib_link_flag += ' -Wl,-install_name,%s' % lib_path
|
mapnik_lib_link_flag += ' -Wl,-install_name,%s' % lib_path
|
||||||
_d = {'version':env['MAPNIK_VERSION_STRING'].replace('-pre','')}
|
_d = {'version':env['MAPNIK_VERSION_STRING'].replace('-pre','')}
|
||||||
mapnik_lib_link_flag += ' -current_version %(version)s -compatibility_version %(version)s' % _d
|
mapnik_lib_link_flag += ' -current_version %(version)s -compatibility_version %(version)s' % _d
|
||||||
elif env['PLATFORM'] == 'SunOS':
|
else: # unix, non-macos
|
||||||
if env['CXX'].startswith('CC'):
|
mapnik_libname = env.subst(env['MAPNIK_LIB_NAME']) + (".%d.%d" % (int(ABI_VERSION[0]),int(ABI_VERSION[1])))
|
||||||
mapnik_lib_link_flag += ' -R. -h %s' % mapnik_libname
|
if env['PLATFORM'] == 'SunOS':
|
||||||
else:
|
if env['CXX'].startswith('CC'):
|
||||||
mapnik_lib_link_flag += ' -Wl,-h,%s' % mapnik_libname
|
mapnik_lib_link_flag += ' -R. -h %s' % mapnik_libname
|
||||||
else: # Linux and others
|
else:
|
||||||
mapnik_lib_link_flag += ' -Wl,-rpath-link,. -Wl,-soname,%s' % mapnik_libname
|
mapnik_lib_link_flag += ' -Wl,-h,%s' % mapnik_libname
|
||||||
|
else: # Linux and others
|
||||||
|
mapnik_lib_link_flag += ' -Wl,-rpath-link,. -Wl,-soname,%s' % mapnik_libname
|
||||||
|
|
||||||
source = Split(
|
source = Split(
|
||||||
"""
|
"""
|
||||||
|
@ -324,16 +321,22 @@ if env['CUSTOM_LDFLAGS']:
|
||||||
else:
|
else:
|
||||||
linkflags = mapnik_lib_link_flag
|
linkflags = mapnik_lib_link_flag
|
||||||
|
|
||||||
if env['LINKING'] == 'static':
|
|
||||||
mapnik = lib_env.StaticLibrary('mapnik', source, LINKFLAGS=linkflags)
|
|
||||||
else:
|
|
||||||
mapnik = lib_env.SharedLibrary('mapnik', source, LINKFLAGS=linkflags)
|
|
||||||
|
|
||||||
# cache library values for other builds to use
|
# cache library values for other builds to use
|
||||||
env['LIBMAPNIK_LIBS'] = copy(lib_env['LIBS'])
|
env['LIBMAPNIK_LIBS'] = copy(lib_env['LIBS'])
|
||||||
env['LIBMAPNIK_CXXFLAGS'] = libmapnik_cxxflags
|
env['LIBMAPNIK_CXXFLAGS'] = libmapnik_cxxflags
|
||||||
|
|
||||||
if env['PLATFORM'] != 'Darwin':
|
if env['PLATFORM'] == 'Darwin':
|
||||||
|
target_path = env['MAPNIK_LIB_BASE_DEST']
|
||||||
|
if 'uninstall' not in COMMAND_LINE_TARGETS:
|
||||||
|
if env['LINKING'] == 'static':
|
||||||
|
mapnik = lib_env.StaticLibrary('mapnik', source, LINKFLAGS=linkflags)
|
||||||
|
else:
|
||||||
|
mapnik = lib_env.SharedLibrary('mapnik', source, LINKFLAGS=linkflags)
|
||||||
|
result = env.Install(target_path, mapnik)
|
||||||
|
env.Alias(target='install', source=result)
|
||||||
|
|
||||||
|
env['create_uninstall_target'](env, os.path.join(target_path,env.subst(env['MAPNIK_LIB_NAME'])))
|
||||||
|
else:
|
||||||
# Symlink command, only works if both files are in same directory
|
# Symlink command, only works if both files are in same directory
|
||||||
def symlink(env, target, source):
|
def symlink(env, target, source):
|
||||||
trgt = str(target[0])
|
trgt = str(target[0])
|
||||||
|
@ -345,38 +348,34 @@ if env['PLATFORM'] != 'Darwin':
|
||||||
|
|
||||||
major, minor, micro = ABI_VERSION
|
major, minor, micro = ABI_VERSION
|
||||||
|
|
||||||
soFile = "%s.%d.%d.%d" % (os.path.basename(str(mapnik[0])), int(major), int(minor), int(micro))
|
soFile = "%s.%d.%d.%d" % (os.path.basename(env.subst(env['MAPNIK_LIB_NAME'])), int(major), int(minor), int(micro))
|
||||||
target = os.path.join(env['MAPNIK_LIB_BASE_DEST'], soFile)
|
target = os.path.join(env['MAPNIK_LIB_BASE_DEST'], soFile)
|
||||||
|
|
||||||
if 'uninstall' not in COMMAND_LINE_TARGETS:
|
if 'uninstall' not in COMMAND_LINE_TARGETS:
|
||||||
result = env.InstallAs(target=target, source=mapnik)
|
if env['LINKING'] == 'static':
|
||||||
env.Alias(target='install', source=result)
|
mapnik = lib_env.StaticLibrary('mapnik', source, LINKFLAGS=linkflags)
|
||||||
if result:
|
else:
|
||||||
env.AddPostAction(result, ldconfig)
|
mapnik = lib_env.SharedLibrary('mapnik', source, LINKFLAGS=linkflags)
|
||||||
|
result = env.InstallAs(target=target, source=mapnik)
|
||||||
|
env.Alias(target='install', source=result)
|
||||||
|
if result:
|
||||||
|
env.AddPostAction(result, ldconfig)
|
||||||
|
|
||||||
|
|
||||||
# Install symlinks
|
# Install symlinks
|
||||||
target1 = os.path.join(env['MAPNIK_LIB_BASE_DEST'], "%s.%d.%d" % (os.path.basename(str(mapnik[0])),int(major), int(minor)))
|
target1 = os.path.join(env['MAPNIK_LIB_BASE_DEST'], "%s.%d.%d" % \
|
||||||
target2 = os.path.join(env['MAPNIK_LIB_BASE_DEST'], os.path.basename(str(mapnik[0])))
|
(os.path.basename(env.subst(env['MAPNIK_LIB_NAME'])),int(major), int(minor)))
|
||||||
|
target2 = os.path.join(env['MAPNIK_LIB_BASE_DEST'], os.path.basename(env.subst(env['MAPNIK_LIB_NAME'])))
|
||||||
if 'uninstall' not in COMMAND_LINE_TARGETS:
|
if 'uninstall' not in COMMAND_LINE_TARGETS:
|
||||||
if 'install' in COMMAND_LINE_TARGETS:
|
link1 = env.Command(target1, target, symlink)
|
||||||
link1 = env.Command(target1, target, symlink)
|
env.Alias(target='install', source=link1)
|
||||||
env.Alias(target='install', source=link1)
|
link2 = env.Command(target2, target1, symlink)
|
||||||
link2 = env.Command(target2, target1, symlink)
|
env.Alias(target='install', source=link2)
|
||||||
env.Alias(target='install', source=link2)
|
|
||||||
# delete in reverse order..
|
# delete in reverse order..
|
||||||
env['create_uninstall_target'](env, target2)
|
env['create_uninstall_target'](env, target2)
|
||||||
env['create_uninstall_target'](env, target1)
|
env['create_uninstall_target'](env, target1)
|
||||||
env['create_uninstall_target'](env, target)
|
env['create_uninstall_target'](env, target)
|
||||||
|
|
||||||
else:
|
|
||||||
target_path = env['MAPNIK_LIB_BASE_DEST']
|
|
||||||
if 'uninstall' not in COMMAND_LINE_TARGETS:
|
|
||||||
result = env.Install(target_path, mapnik)
|
|
||||||
env.Alias(target='install', source=result)
|
|
||||||
|
|
||||||
env['create_uninstall_target'](env, os.path.join(target_path,mapnik_libname))
|
|
||||||
|
|
||||||
includes = glob.glob('../include/mapnik/*.hpp')
|
includes = glob.glob('../include/mapnik/*.hpp')
|
||||||
svg_includes = glob.glob('../include/mapnik/svg/*.hpp')
|
svg_includes = glob.glob('../include/mapnik/svg/*.hpp')
|
||||||
wkt_includes = glob.glob('../include/mapnik/wkt/*.hpp')
|
wkt_includes = glob.glob('../include/mapnik/wkt/*.hpp')
|
||||||
|
|
|
@ -102,9 +102,13 @@ bool freetype_engine::register_font(std::string const& file_name)
|
||||||
// http://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_FaceRec
|
// http://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_FaceRec
|
||||||
if (face->family_name && face->style_name)
|
if (face->family_name && face->style_name)
|
||||||
{
|
{
|
||||||
success = true;
|
|
||||||
std::string name = std::string(face->family_name) + " " + std::string(face->style_name);
|
std::string name = std::string(face->family_name) + " " + std::string(face->style_name);
|
||||||
name2file_.insert(std::make_pair(name, std::make_pair(i,file_name)));
|
// skip fonts with leading . in name
|
||||||
|
if (!boost::algorithm::starts_with(name,"."))
|
||||||
|
{
|
||||||
|
success = true;
|
||||||
|
name2file_.insert(std::make_pair(name, std::make_pair(i,file_name)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -142,17 +146,27 @@ bool freetype_engine::register_fonts(std::string const& dir, bool recurse)
|
||||||
for (boost::filesystem::directory_iterator itr(dir); itr != end_itr; ++itr)
|
for (boost::filesystem::directory_iterator itr(dir); itr != end_itr; ++itr)
|
||||||
{
|
{
|
||||||
#if (BOOST_FILESYSTEM_VERSION == 3)
|
#if (BOOST_FILESYSTEM_VERSION == 3)
|
||||||
std::string const& file_name = itr->path().string();
|
std::string file_name = itr->path().string();
|
||||||
#else // v2
|
#else // v2
|
||||||
std::string const& file_name = itr->string();
|
std::string file_name = itr->string();
|
||||||
#endif
|
#endif
|
||||||
if (boost::filesystem::is_directory(*itr) && recurse)
|
if (boost::filesystem::is_directory(*itr) && recurse)
|
||||||
{
|
{
|
||||||
success = register_fonts(file_name, true);
|
success = register_fonts(file_name, true);
|
||||||
}
|
}
|
||||||
else if (boost::filesystem::is_regular_file(file_name) && is_font_file(file_name))
|
else
|
||||||
{
|
{
|
||||||
success = mapnik::freetype_engine::register_font(file_name);
|
#if (BOOST_FILESYSTEM_VERSION == 3)
|
||||||
|
std::string base_name = itr->path().filename().string();
|
||||||
|
#else // v2
|
||||||
|
std::string base_name = itr->filename();
|
||||||
|
#endif
|
||||||
|
if (!boost::algorithm::starts_with(base_name,".") &&
|
||||||
|
boost::filesystem::is_regular_file(file_name) &&
|
||||||
|
is_font_file(file_name))
|
||||||
|
{
|
||||||
|
success = mapnik::freetype_engine::register_font(file_name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return success;
|
return success;
|
||||||
|
|
|
@ -135,11 +135,15 @@ public:
|
||||||
xmlError * error = xmlCtxtGetLastError( ctx_ );
|
xmlError * error = xmlCtxtGetLastError( ctx_ );
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
os << "XML document not well formed";
|
os << "XML document not well formed";
|
||||||
|
int line=0;
|
||||||
|
std::string file;
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
os << ": " << std::endl << error->message;
|
os << ": " << std::endl << error->message;
|
||||||
|
line = error->line;
|
||||||
|
file = error->file;
|
||||||
}
|
}
|
||||||
throw config_error(os.str(), error->line, error->file);
|
throw config_error(os.str(), line, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
int iXIncludeReturn = xmlXIncludeProcessFlags(doc, options_);
|
int iXIncludeReturn = xmlXIncludeProcessFlags(doc, options_);
|
||||||
|
|
|
@ -98,7 +98,7 @@ private:
|
||||||
void parse_metawriter_in_symbolizer(symbolizer_base &sym, xml_node const& pt);
|
void parse_metawriter_in_symbolizer(symbolizer_base &sym, xml_node const& pt);
|
||||||
|
|
||||||
void parse_fontset(Map & map, xml_node const & fset);
|
void parse_fontset(Map & map, xml_node const & fset);
|
||||||
void parse_font(font_set & fset, xml_node const& f);
|
bool parse_font(font_set & fset, xml_node const& f);
|
||||||
|
|
||||||
void parse_rule(feature_type_style & style, xml_node const & r);
|
void parse_rule(feature_type_style & style, xml_node const & r);
|
||||||
|
|
||||||
|
@ -455,44 +455,62 @@ void map_parser::parse_fontset(Map & map, xml_node const& fset)
|
||||||
{
|
{
|
||||||
name = fset.get_attr<std::string>("name");
|
name = fset.get_attr<std::string>("name");
|
||||||
font_set fontset(name);
|
font_set fontset(name);
|
||||||
|
|
||||||
xml_node::const_iterator itr = fset.begin();
|
xml_node::const_iterator itr = fset.begin();
|
||||||
xml_node::const_iterator end = fset.end();
|
xml_node::const_iterator end = fset.end();
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
for (; itr != end; ++itr)
|
for (; itr != end; ++itr)
|
||||||
{
|
{
|
||||||
if (itr->is("Font"))
|
if (itr->is("Font"))
|
||||||
{
|
{
|
||||||
parse_font(fontset, *itr);
|
if (parse_font(fontset, *itr))
|
||||||
|
{
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if not at least one face-name is valid
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
throw mapnik::config_error("no valid fonts could be loaded");
|
||||||
|
}
|
||||||
|
|
||||||
map.insert_fontset(name, fontset);
|
map.insert_fontset(name, fontset);
|
||||||
|
|
||||||
// XXX Hack because map object isn't accessible by text_symbolizer
|
// XXX Hack because map object isn't accessible by text_symbolizer
|
||||||
// when it's parsed
|
// when it's parsed
|
||||||
fontsets_.insert(pair<std::string, font_set>(name, fontset));
|
fontsets_.insert(pair<std::string, font_set>(name, fontset));
|
||||||
} catch (const config_error & ex) {
|
}
|
||||||
|
catch (const config_error & ex)
|
||||||
|
{
|
||||||
ex.append_context(std::string("in FontSet '") + name + "'", fset);
|
ex.append_context(std::string("in FontSet '") + name + "'", fset);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void map_parser::parse_font(font_set &fset, xml_node const& f)
|
bool map_parser::parse_font(font_set &fset, xml_node const& f)
|
||||||
{
|
{
|
||||||
optional<std::string> face_name = f.get_opt_attr<std::string>("face-name");
|
optional<std::string> face_name = f.get_opt_attr<std::string>("face-name");
|
||||||
if (face_name)
|
if (face_name)
|
||||||
{
|
{
|
||||||
if (strict_)
|
face_ptr face = font_manager_.get_face(*face_name);
|
||||||
|
if (face)
|
||||||
{
|
{
|
||||||
ensure_font_face(*face_name);
|
fset.add_face_name(*face_name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (strict_)
|
||||||
|
{
|
||||||
|
throw config_error("Failed to find font face '" +
|
||||||
|
*face_name + "'");
|
||||||
}
|
}
|
||||||
fset.add_face_name(*face_name);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw config_error("Must have 'face-name' set", f);
|
throw config_error("Must have 'face-name' set", f);
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void map_parser::parse_layer(Map & map, xml_node const& lay)
|
void map_parser::parse_layer(Map & map, xml_node const& lay)
|
||||||
|
|
107
src/map.cpp
107
src/map.cpp
|
@ -564,85 +564,66 @@ CoordTransform Map::view_transform() const
|
||||||
|
|
||||||
featureset_ptr Map::query_point(unsigned index, double x, double y) const
|
featureset_ptr Map::query_point(unsigned index, double x, double y) const
|
||||||
{
|
{
|
||||||
if ( index< layers_.size())
|
if (!current_extent_.valid())
|
||||||
|
{
|
||||||
|
throw std::runtime_error("query_point: map extent is not intialized, you need to set a valid extent before querying");
|
||||||
|
}
|
||||||
|
if (!current_extent_.intersects(x,y))
|
||||||
|
{
|
||||||
|
throw std::runtime_error("query_point: x,y coords do not intersect map extent");
|
||||||
|
}
|
||||||
|
if (index < layers_.size())
|
||||||
{
|
{
|
||||||
mapnik::layer const& layer = layers_[index];
|
mapnik::layer const& layer = layers_[index];
|
||||||
try
|
mapnik::datasource_ptr ds = layer.datasource();
|
||||||
|
if (ds)
|
||||||
{
|
{
|
||||||
double z = 0;
|
|
||||||
mapnik::projection dest(srs_);
|
mapnik::projection dest(srs_);
|
||||||
mapnik::projection source(layer.srs());
|
mapnik::projection source(layer.srs());
|
||||||
proj_transform prj_trans(source,dest);
|
proj_transform prj_trans(source,dest);
|
||||||
prj_trans.backward(x,y,z);
|
double z = 0;
|
||||||
|
if (!prj_trans.equal() && !prj_trans.backward(x,y,z))
|
||||||
double minx = current_extent_.minx();
|
|
||||||
double miny = current_extent_.miny();
|
|
||||||
double maxx = current_extent_.maxx();
|
|
||||||
double maxy = current_extent_.maxy();
|
|
||||||
|
|
||||||
prj_trans.backward(minx,miny,z);
|
|
||||||
prj_trans.backward(maxx,maxy,z);
|
|
||||||
double tol = (maxx - minx) / width_ * 3;
|
|
||||||
mapnik::datasource_ptr ds = layer.datasource();
|
|
||||||
if (ds)
|
|
||||||
{
|
{
|
||||||
|
throw std::runtime_error("query_point: could not project x,y into layer srs");
|
||||||
|
}
|
||||||
|
// TODO - pass tolerance to features_at_point as well
|
||||||
|
featureset_ptr fs = ds->features_at_point(mapnik::coord2d(x,y));
|
||||||
|
if (fs)
|
||||||
|
{
|
||||||
|
mapnik::box2d<double> map_ex = current_extent_;
|
||||||
|
if (maximum_extent_) {
|
||||||
|
map_ex.clip(*maximum_extent_);
|
||||||
|
}
|
||||||
|
if (!prj_trans.backward(map_ex,PROJ_ENVELOPE_POINTS))
|
||||||
|
{
|
||||||
|
std::ostringstream s;
|
||||||
|
s << "query_point: could not project map extent '" << map_ex
|
||||||
|
<< "' into layer srs for tolerance calculation";
|
||||||
|
throw std::runtime_error(s.str());
|
||||||
|
}
|
||||||
|
double tol = (map_ex.maxx() - map_ex.minx()) / width_ * 3;
|
||||||
MAPNIK_LOG_DEBUG(map) << "map: Query at point tol=" << tol << "(" << x << "," << y << ")";
|
MAPNIK_LOG_DEBUG(map) << "map: Query at point tol=" << tol << "(" << x << "," << y << ")";
|
||||||
|
return boost::make_shared<filter_featureset<hit_test_filter> >(fs,
|
||||||
featureset_ptr fs = ds->features_at_point(mapnik::coord2d(x,y));
|
hit_test_filter(x,y,tol));
|
||||||
if (fs)
|
|
||||||
return boost::make_shared<filter_featureset<hit_test_filter> >(fs,
|
|
||||||
hit_test_filter(x,y,tol));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (...)
|
}
|
||||||
{
|
else
|
||||||
MAPNIK_LOG_ERROR(map) << "Exception caught in \"query_point\"";
|
{
|
||||||
}
|
std::ostringstream s;
|
||||||
|
s << "Invalid layer index passed to query_point: '" << index << "'";
|
||||||
|
if (layers_.size() > 0) s << " for map with " << layers_.size() << " layers(s)";
|
||||||
|
else s << " (map has no layers)";
|
||||||
|
throw std::out_of_range(s.str());
|
||||||
}
|
}
|
||||||
return featureset_ptr();
|
return featureset_ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
featureset_ptr Map::query_map_point(unsigned index, double x, double y) const
|
featureset_ptr Map::query_map_point(unsigned index, double x, double y) const
|
||||||
{
|
{
|
||||||
if ( index< layers_.size())
|
CoordTransform tr = view_transform();
|
||||||
{
|
tr.backward(&x,&y);
|
||||||
mapnik::layer const& layer = layers_[index];
|
return query_point(index,x,y);
|
||||||
CoordTransform tr = view_transform();
|
|
||||||
tr.backward(&x,&y);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
mapnik::projection dest(srs_);
|
|
||||||
mapnik::projection source(layer.srs());
|
|
||||||
proj_transform prj_trans(source,dest);
|
|
||||||
double z = 0;
|
|
||||||
prj_trans.backward(x,y,z);
|
|
||||||
|
|
||||||
double minx = current_extent_.minx();
|
|
||||||
double miny = current_extent_.miny();
|
|
||||||
double maxx = current_extent_.maxx();
|
|
||||||
double maxy = current_extent_.maxy();
|
|
||||||
|
|
||||||
prj_trans.backward(minx,miny,z);
|
|
||||||
prj_trans.backward(maxx,maxy,z);
|
|
||||||
double tol = (maxx - minx) / width_ * 3;
|
|
||||||
mapnik::datasource_ptr ds = layer.datasource();
|
|
||||||
if (ds)
|
|
||||||
{
|
|
||||||
MAPNIK_LOG_DEBUG(map) << "map: Query at point tol=" << tol << "(" << x << "," << y << ")";
|
|
||||||
|
|
||||||
featureset_ptr fs = ds->features_at_point(mapnik::coord2d(x,y));
|
|
||||||
if (fs)
|
|
||||||
return boost::make_shared<filter_featureset<hit_test_filter> >(fs,
|
|
||||||
hit_test_filter(x,y,tol));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
MAPNIK_LOG_ERROR(map) << "Exception caught in \"query_map_point\"";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return featureset_ptr();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Map::~Map() {}
|
Map::~Map() {}
|
||||||
|
|
|
@ -73,43 +73,37 @@ boost::optional<marker_ptr> marker_cache::find(std::string const& uri, bool upda
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// we can't find marker in cache, lets try to load it from filesystem
|
try
|
||||||
boost::filesystem::path path(uri);
|
|
||||||
if (exists(path))
|
|
||||||
{
|
{
|
||||||
if (is_svg(uri))
|
// we can't find marker in cache, lets try to load it from filesystem
|
||||||
|
boost::filesystem::path path(uri);
|
||||||
|
if (!exists(path))
|
||||||
{
|
{
|
||||||
using namespace mapnik::svg;
|
MAPNIK_LOG_ERROR(marker_cache) << "Marker does not exist: " << uri;
|
||||||
try
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (is_svg(uri))
|
||||||
{
|
{
|
||||||
|
using namespace mapnik::svg;
|
||||||
path_ptr marker_path(boost::make_shared<svg_storage_type>());
|
path_ptr marker_path(boost::make_shared<svg_storage_type>());
|
||||||
vertex_stl_adapter<svg_path_storage> stl_storage(marker_path->source());
|
vertex_stl_adapter<svg_path_storage> stl_storage(marker_path->source());
|
||||||
svg_path_adapter svg_path(stl_storage);
|
svg_path_adapter svg_path(stl_storage);
|
||||||
svg_converter_type svg(svg_path, marker_path->attributes());
|
svg_converter_type svg(svg_path, marker_path->attributes());
|
||||||
|
|
||||||
svg_parser p(svg);
|
svg_parser p(svg);
|
||||||
p.parse(uri);
|
p.parse(uri);
|
||||||
//svg.arrange_orientations();
|
//svg.arrange_orientations();
|
||||||
double lox,loy,hix,hiy;
|
double lox,loy,hix,hiy;
|
||||||
svg.bounding_rect(&lox, &loy, &hix, &hiy);
|
svg.bounding_rect(&lox, &loy, &hix, &hiy);
|
||||||
marker_path->set_bounding_box(lox,loy,hix,hiy);
|
marker_path->set_bounding_box(lox,loy,hix,hiy);
|
||||||
|
|
||||||
marker_ptr mark(boost::make_shared<marker>(marker_path));
|
marker_ptr mark(boost::make_shared<marker>(marker_path));
|
||||||
result.reset(mark);
|
result.reset(mark);
|
||||||
if (update_cache)
|
if (update_cache)
|
||||||
{
|
{
|
||||||
cache_.insert(std::make_pair(uri,*result));
|
cache_.insert(std::make_pair(uri,*result));
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
catch (...)
|
else
|
||||||
{
|
|
||||||
MAPNIK_LOG_ERROR(marker_cache) << "Exception caught while loading SVG: " << uri;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
std::auto_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(uri));
|
std::auto_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(uri));
|
||||||
if (reader.get())
|
if (reader.get())
|
||||||
|
@ -126,17 +120,20 @@ boost::optional<marker_ptr> marker_cache::find(std::string const& uri, bool upda
|
||||||
cache_.insert(std::make_pair(uri,*result));
|
cache_.insert(std::make_pair(uri,*result));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
catch (...)
|
MAPNIK_LOG_ERROR(marker_cache) << "could not intialize reader for: '" << uri << "'";
|
||||||
{
|
}
|
||||||
MAPNIK_LOG_ERROR(marker_cache) << "Exception caught while loading image: " << uri;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
catch (std::exception const& ex)
|
||||||
{
|
{
|
||||||
MAPNIK_LOG_WARN(marker_cache) << "Marker does not exist: " << uri;
|
MAPNIK_LOG_ERROR(marker_cache) << "Exception caught while loading: '" << uri << "' (" << ex.what() << ")";
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
MAPNIK_LOG_ERROR(marker_cache) << "Exception caught while loading: '" << uri << "'";
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,19 +33,20 @@
|
||||||
namespace mapnik {
|
namespace mapnik {
|
||||||
|
|
||||||
#if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 480
|
#if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 480
|
||||||
|
#warning mapnik is building against < proj 4.8, reprojection will be faster if you use >= 4.8
|
||||||
boost::mutex projection::mutex_;
|
boost::mutex projection::mutex_;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
projection::projection(std::string const& params)
|
projection::projection(std::string const& params)
|
||||||
: params_(params)
|
: params_(params)
|
||||||
{
|
{
|
||||||
init(); //
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
projection::projection(projection const& rhs)
|
projection::projection(projection const& rhs)
|
||||||
: params_(rhs.params_)
|
: params_(rhs.params_)
|
||||||
{
|
{
|
||||||
init(); //
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
projection& projection::operator=(projection const& rhs)
|
projection& projection::operator=(projection const& rhs)
|
||||||
|
@ -158,9 +159,9 @@ std::string projection::expanded() const
|
||||||
return std::string("");
|
return std::string("");
|
||||||
}
|
}
|
||||||
|
|
||||||
void projection::swap (projection& rhs)
|
void projection::swap(projection& rhs)
|
||||||
{
|
{
|
||||||
std::swap(params_,rhs.params_);
|
std::swap(params_,rhs.params_);
|
||||||
init ();
|
init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -428,11 +428,21 @@ void svg_parser::parse_path(xmlTextReaderPtr reader)
|
||||||
if (value)
|
if (value)
|
||||||
{
|
{
|
||||||
path_.begin_path();
|
path_.begin_path();
|
||||||
|
|
||||||
if (!mapnik::svg::parse_path((const char*) value, path_))
|
if (!mapnik::svg::parse_path((const char*) value, path_))
|
||||||
{
|
{
|
||||||
xmlFree(value);
|
xmlFree(value);
|
||||||
throw std::runtime_error("can't parse PATH\n");
|
xmlChar *id_value;
|
||||||
|
id_value = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
|
||||||
|
if (id_value)
|
||||||
|
{
|
||||||
|
std::string id_string((const char *) id_value);
|
||||||
|
xmlFree(id_value);
|
||||||
|
throw std::runtime_error(std::string("unable to parse invalid svg <path> with id '") + id_string + "'");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw std::runtime_error("unable to parse invalid svg <path>");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
path_.end_path();
|
path_.end_path();
|
||||||
xmlFree(value);
|
xmlFree(value);
|
||||||
|
@ -450,7 +460,7 @@ void svg_parser::parse_polygon(xmlTextReaderPtr reader)
|
||||||
if (!mapnik::svg::parse_points((const char*) value, path_))
|
if (!mapnik::svg::parse_points((const char*) value, path_))
|
||||||
{
|
{
|
||||||
xmlFree(value);
|
xmlFree(value);
|
||||||
throw std::runtime_error("Failed to parse <polygon>\n");
|
throw std::runtime_error("Failed to parse <polygon>");
|
||||||
}
|
}
|
||||||
path_.close_subpath();
|
path_.close_subpath();
|
||||||
path_.end_path();
|
path_.end_path();
|
||||||
|
@ -469,7 +479,7 @@ void svg_parser::parse_polyline(xmlTextReaderPtr reader)
|
||||||
if (!mapnik::svg::parse_points((const char*) value, path_))
|
if (!mapnik::svg::parse_points((const char*) value, path_))
|
||||||
{
|
{
|
||||||
xmlFree(value);
|
xmlFree(value);
|
||||||
throw std::runtime_error("Failed to parse <polygon>\n");
|
throw std::runtime_error("Failed to parse <polygon>");
|
||||||
}
|
}
|
||||||
|
|
||||||
path_.end_path();
|
path_.end_path();
|
||||||
|
|
|
@ -113,8 +113,9 @@ public:
|
||||||
{
|
{
|
||||||
int type = read_integer();
|
int type = read_integer();
|
||||||
|
|
||||||
|
#ifdef MAPNIK_LOG
|
||||||
MAPNIK_LOG_DEBUG(wkb_reader) << "wkb_reader: Read=" << wkb_geometry_type_string(type) << "," << type;
|
MAPNIK_LOG_DEBUG(wkb_reader) << "wkb_reader: Read=" << wkb_geometry_type_string(type) << "," << type;
|
||||||
|
#endif
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case wkbPoint:
|
case wkbPoint:
|
||||||
|
@ -401,6 +402,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPNIK_LOG
|
||||||
std::string wkb_geometry_type_string(int type)
|
std::string wkb_geometry_type_string(int type)
|
||||||
{
|
{
|
||||||
std::stringstream s;
|
std::stringstream s;
|
||||||
|
@ -426,6 +428,7 @@ private:
|
||||||
|
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
void geometry_utils::from_wkb (boost::ptr_vector<geometry_type>& paths,
|
void geometry_utils::from_wkb (boost::ptr_vector<geometry_type>& paths,
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
//#include <boost/config/warning_disable.hpp>
|
|
||||||
|
|
||||||
#include <boost/filesystem/convenience.hpp>
|
#include <boost/filesystem/convenience.hpp>
|
||||||
namespace fs = boost::filesystem;
|
namespace fs = boost::filesystem;
|
||||||
using fs::path;
|
using fs::path;
|
||||||
|
@ -9,79 +7,72 @@ namespace sys = boost::system;
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <mapnik/font_engine_freetype.hpp>
|
#include <mapnik/font_engine_freetype.hpp>
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------//
|
|
||||||
|
|
||||||
int main( int, char*[] )
|
int main( int, char*[] )
|
||||||
{
|
{
|
||||||
|
std::string fontdir("fonts/");
|
||||||
|
|
||||||
|
BOOST_TEST( fs::exists( fontdir ) );
|
||||||
|
BOOST_TEST( fs::is_directory( fontdir ) );
|
||||||
|
|
||||||
// font registration() tests ----------------------------------------------//
|
std::vector<std::string> face_names;
|
||||||
|
|
||||||
std::string fontdir("fonts/");
|
std::string foo("foo");
|
||||||
|
|
||||||
BOOST_TEST( fs::exists( fontdir ) );
|
|
||||||
BOOST_TEST( fs::is_directory( fontdir ) );
|
|
||||||
|
|
||||||
std::vector<std::string> face_names;
|
// fake directories
|
||||||
|
BOOST_TEST( !mapnik::freetype_engine::register_fonts(foo , true ) );
|
||||||
|
face_names = mapnik::freetype_engine::face_names();
|
||||||
|
BOOST_TEST( face_names.size() == 0 );
|
||||||
|
BOOST_TEST( !mapnik::freetype_engine::register_fonts(foo) );
|
||||||
|
face_names = mapnik::freetype_engine::face_names();
|
||||||
|
BOOST_TEST( face_names.size() == 0 );
|
||||||
|
|
||||||
std::string foo("foo");
|
// directories without fonts
|
||||||
|
std::string src("src");
|
||||||
|
// an empty directory will not return true
|
||||||
|
// we need to register at least one font and not fail on any
|
||||||
|
// to return true
|
||||||
|
BOOST_TEST( mapnik::freetype_engine::register_font(src) == false );
|
||||||
|
BOOST_TEST( mapnik::freetype_engine::register_fonts(src, true) == false );
|
||||||
|
BOOST_TEST( mapnik::freetype_engine::face_names().size() == 0 );
|
||||||
|
|
||||||
// fake directories
|
// bogus, emtpy file that looks like font
|
||||||
BOOST_TEST( !mapnik::freetype_engine::register_fonts(foo , true ) );
|
BOOST_TEST( mapnik::freetype_engine::register_font("tests/data/fonts/fake.ttf") == false );
|
||||||
face_names = mapnik::freetype_engine::face_names();
|
BOOST_TEST( mapnik::freetype_engine::register_fonts("tests/data/fonts/fake.ttf") == false );
|
||||||
BOOST_TEST( face_names.size() == 0 );
|
BOOST_TEST( mapnik::freetype_engine::face_names().size() == 0 );
|
||||||
BOOST_TEST( !mapnik::freetype_engine::register_fonts(foo) );
|
|
||||||
face_names = mapnik::freetype_engine::face_names();
|
|
||||||
BOOST_TEST( face_names.size() == 0 );
|
|
||||||
|
|
||||||
// directories without fonts
|
BOOST_TEST( mapnik::freetype_engine::register_font("tests/data/fonts/intentionally-broken.ttf") == false );
|
||||||
std::string src("src");
|
BOOST_TEST( mapnik::freetype_engine::register_fonts("tests/data/fonts/intentionally-broken.ttf") == false );
|
||||||
// an empty directory will not return true
|
BOOST_TEST( mapnik::freetype_engine::face_names().size() == 0 );
|
||||||
// we need to register at least one font and not fail on any
|
|
||||||
// to return true
|
|
||||||
BOOST_TEST( mapnik::freetype_engine::register_font(src) == false );
|
|
||||||
BOOST_TEST( mapnik::freetype_engine::register_fonts(src, true) == false );
|
|
||||||
BOOST_TEST( mapnik::freetype_engine::face_names().size() == 0 );
|
|
||||||
|
|
||||||
// bogus, emtpy file that looks like font
|
// register unifont, since we know it sits in the root fonts/ dir
|
||||||
BOOST_TEST( mapnik::freetype_engine::register_font("tests/data/fonts/fake.ttf") == false );
|
BOOST_TEST( mapnik::freetype_engine::register_fonts(fontdir) );
|
||||||
BOOST_TEST( mapnik::freetype_engine::register_fonts("tests/data/fonts/fake.ttf") == false );
|
face_names = mapnik::freetype_engine::face_names();
|
||||||
BOOST_TEST( mapnik::freetype_engine::face_names().size() == 0 );
|
//std::clog << "number of registered fonts: " << face_names.size() << std::endl;
|
||||||
|
BOOST_TEST( face_names.size() > 0 );
|
||||||
|
BOOST_TEST( face_names.size() == 1 );
|
||||||
|
|
||||||
//BOOST_TEST( mapnik::freetype_engine::register_font("tests/data/fonts/intentionally-broken.ttf") == false );
|
// re-register unifont, should not have any affect
|
||||||
//BOOST_TEST( mapnik::freetype_engine::register_fonts("tests/data/fonts/intentionally-broken.ttf") == false );
|
BOOST_TEST( mapnik::freetype_engine::register_fonts(fontdir, false) );
|
||||||
//BOOST_TEST( mapnik::freetype_engine::face_names().size() == 0 );
|
face_names = mapnik::freetype_engine::face_names();
|
||||||
|
//std::clog << "number of registered fonts: " << face_names.size() << std::endl;
|
||||||
|
BOOST_TEST( face_names.size() == 1 );
|
||||||
|
|
||||||
// register unifont, since we know it sits in the root fonts/ dir
|
// register a single dejavu font
|
||||||
BOOST_TEST( mapnik::freetype_engine::register_fonts(fontdir) );
|
std::string dejavu_bold_oblique("tests/data/fonts/DejaVuSansMono-BoldOblique.ttf");
|
||||||
face_names = mapnik::freetype_engine::face_names();
|
BOOST_TEST( mapnik::freetype_engine::register_font(dejavu_bold_oblique) );
|
||||||
//std::clog << "number of registered fonts: " << face_names.size() << std::endl;
|
face_names = mapnik::freetype_engine::face_names();
|
||||||
BOOST_TEST( face_names.size() > 0 );
|
//std::clog << "number of registered fonts: " << face_names.size() << std::endl;
|
||||||
BOOST_TEST( face_names.size() == 1 );
|
BOOST_TEST( face_names.size() == 2 );
|
||||||
|
|
||||||
// re-register unifont, should not have any affect
|
// recurse to find all dejavu fonts
|
||||||
BOOST_TEST( mapnik::freetype_engine::register_fonts(fontdir, false) );
|
BOOST_TEST( mapnik::freetype_engine::register_fonts(fontdir, true) );
|
||||||
face_names = mapnik::freetype_engine::face_names();
|
face_names = mapnik::freetype_engine::face_names();
|
||||||
//std::clog << "number of registered fonts: " << face_names.size() << std::endl;
|
//std::clog << "number of registered fonts: " << face_names.size() << std::endl;
|
||||||
BOOST_TEST( face_names.size() == 1 );
|
BOOST_TEST( face_names.size() == 22 );
|
||||||
|
|
||||||
// register a single dejavu font
|
if (!::boost::detail::test_errors()) {
|
||||||
std::string dejavu_bold_oblique("tests/data/fonts/DejaVuSansMono-BoldOblique.ttf");
|
std::clog << "C++ fonts registration: \x1b[1;32m✓ \x1b[0m\n";
|
||||||
BOOST_TEST( mapnik::freetype_engine::register_font(dejavu_bold_oblique) );
|
} else {
|
||||||
face_names = mapnik::freetype_engine::face_names();
|
return ::boost::report_errors();
|
||||||
//std::clog << "number of registered fonts: " << face_names.size() << std::endl;
|
}
|
||||||
BOOST_TEST( face_names.size() == 2 );
|
|
||||||
|
|
||||||
// recurse to find all dejavu fonts
|
|
||||||
BOOST_TEST( mapnik::freetype_engine::register_fonts(fontdir, true) );
|
|
||||||
face_names = mapnik::freetype_engine::face_names();
|
|
||||||
//std::clog << "number of registered fonts: " << face_names.size() << std::endl;
|
|
||||||
BOOST_TEST( face_names.size() == 22 );
|
|
||||||
|
|
||||||
if (!::boost::detail::test_errors()) {
|
|
||||||
std::clog << "C++ fonts registration: \x1b[1;32m✓ \x1b[0m\n";
|
|
||||||
} else {
|
|
||||||
return ::boost::report_errors();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,71 +7,71 @@
|
||||||
int main( int, char*[] )
|
int main( int, char*[] )
|
||||||
{
|
{
|
||||||
|
|
||||||
mapnik::parameters params;
|
mapnik::parameters params;
|
||||||
|
|
||||||
// true
|
|
||||||
params["bool"] = true;
|
|
||||||
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));
|
|
||||||
|
|
||||||
params["bool"] = "true";
|
// true
|
||||||
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));
|
params["bool"] = true;
|
||||||
|
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));
|
||||||
|
|
||||||
params["bool"] = 1;
|
params["bool"] = "true";
|
||||||
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));
|
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));
|
||||||
|
|
||||||
params["bool"] = "1";
|
params["bool"] = 1;
|
||||||
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));
|
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));
|
||||||
|
|
||||||
params["bool"] = "True";
|
params["bool"] = "1";
|
||||||
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));
|
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));
|
||||||
|
|
||||||
params["bool"] = "on";
|
params["bool"] = "True";
|
||||||
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));
|
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));
|
||||||
|
|
||||||
params["bool"] = "yes";
|
params["bool"] = "on";
|
||||||
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));
|
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));
|
||||||
|
|
||||||
// false
|
params["bool"] = "yes";
|
||||||
params["bool"] = false;
|
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));
|
||||||
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false) );
|
|
||||||
|
|
||||||
params["bool"] = "false";
|
// false
|
||||||
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false) );
|
params["bool"] = false;
|
||||||
|
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false) );
|
||||||
|
|
||||||
params["bool"] = 0;
|
params["bool"] = "false";
|
||||||
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false));
|
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false) );
|
||||||
|
|
||||||
params["bool"] = "0";
|
params["bool"] = 0;
|
||||||
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false));
|
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false));
|
||||||
|
|
||||||
params["bool"] = "False";
|
params["bool"] = "0";
|
||||||
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false));
|
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false));
|
||||||
|
|
||||||
params["bool"] = "off";
|
params["bool"] = "False";
|
||||||
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false));
|
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false));
|
||||||
|
|
||||||
params["bool"] = "no";
|
params["bool"] = "off";
|
||||||
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false));
|
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false));
|
||||||
|
|
||||||
// strings
|
params["bool"] = "no";
|
||||||
params["string"] = "hello";
|
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false));
|
||||||
BOOST_TEST( (params.get<std::string>("string") && *params.get<std::string>("string") == "hello") );
|
|
||||||
|
|
||||||
// int
|
// strings
|
||||||
params["int"] = 1;
|
params["string"] = "hello";
|
||||||
BOOST_TEST( (params.get<int>("int") && *params.get<int>("int") == 1) );
|
BOOST_TEST( (params.get<std::string>("string") && *params.get<std::string>("string") == "hello") );
|
||||||
|
|
||||||
// double
|
// int
|
||||||
params["double"] = 1.5;
|
params["int"] = 1;
|
||||||
BOOST_TEST( (params.get<double>("double") && *params.get<double>("double") == 1.5) );
|
BOOST_TEST( (params.get<int>("int") && *params.get<int>("int") == 1) );
|
||||||
|
|
||||||
// value_null
|
// double
|
||||||
params["null"] = mapnik::value_null();
|
params["double"] = 1.5;
|
||||||
//BOOST_TEST( (params.get<mapnik::value_null>("null")/* && *params.get<mapnik::value_null>("null") == mapnik::value_null()*/) );
|
BOOST_TEST( (params.get<double>("double") && *params.get<double>("double") == 1.5) );
|
||||||
|
|
||||||
if (!::boost::detail::test_errors()) {
|
// value_null
|
||||||
std::clog << "C++ parameters: \x1b[1;32m✓ \x1b[0m\n";
|
params["null"] = mapnik::value_null();
|
||||||
} else {
|
//BOOST_TEST( (params.get<mapnik::value_null>("null")/* && *params.get<mapnik::value_null>("null") == mapnik::value_null()*/) );
|
||||||
return ::boost::report_errors();
|
|
||||||
}
|
if (!::boost::detail::test_errors()) {
|
||||||
|
std::clog << "C++ parameters: \x1b[1;32m✓ \x1b[0m\n";
|
||||||
|
} else {
|
||||||
|
return ::boost::report_errors();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#define BOOST_TEST_MODULE background_color_test
|
#define BOOST_TEST_MODULE background_color_test
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This test module contains several generators for
|
* This test module contains several generators for
|
||||||
* the implementation of a background color in SVG
|
* the implementation of a background color in SVG
|
||||||
* using a rectangle.
|
* using a rectangle.
|
||||||
*/
|
*/
|
||||||
|
@ -25,16 +25,16 @@ namespace repository = boost::spirit::repository;
|
||||||
namespace fusion = boost::fusion;
|
namespace fusion = boost::fusion;
|
||||||
using namespace karma;
|
using namespace karma;
|
||||||
|
|
||||||
struct F
|
struct F
|
||||||
{
|
{
|
||||||
F() :
|
F() :
|
||||||
x(0),
|
x(0),
|
||||||
y(0),
|
y(0),
|
||||||
width(100),
|
width(100),
|
||||||
height(100),
|
height(100),
|
||||||
bgcolor("#ffffff"),
|
bgcolor("#ffffff"),
|
||||||
expected_output("<rect x=\"0\" y=\"0\" width=\"100px\" height=\"100px\" style=\"fill: #ffffff\"/>") {}
|
expected_output("<rect x=\"0\" y=\"0\" width=\"100px\" height=\"100px\" style=\"fill: #ffffff\"/>") {}
|
||||||
|
|
||||||
~F() {}
|
~F() {}
|
||||||
|
|
||||||
const int x;
|
const int x;
|
||||||
|
@ -61,14 +61,14 @@ struct F
|
||||||
BOOST_FIXTURE_TEST_CASE(bgcolor_stream_test_case, F)
|
BOOST_FIXTURE_TEST_CASE(bgcolor_stream_test_case, F)
|
||||||
{
|
{
|
||||||
actual_output
|
actual_output
|
||||||
<< format(
|
<< format(
|
||||||
"<rect x=\"" << int_ << "\" "
|
"<rect x=\"" << int_ << "\" "
|
||||||
<< "y=\"" << int_ << "\" "
|
<< "y=\"" << int_ << "\" "
|
||||||
<< "width=\"" << int_ << string << "\" "
|
<< "width=\"" << int_ << string << "\" "
|
||||||
<< "height=\"" << int_ << string << "\" "
|
<< "height=\"" << int_ << string << "\" "
|
||||||
<< "style=\"fill: " << string << "\""
|
<< "style=\"fill: " << string << "\""
|
||||||
<< "/>",
|
<< "/>",
|
||||||
x, y, width, "px", height, "px", bgcolor);
|
x, y, width, "px", height, "px", bgcolor);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(actual_output.str(), expected_output);
|
BOOST_CHECK_EQUAL(actual_output.str(), expected_output);
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ BOOST_FIXTURE_TEST_CASE(bgcolor_stream_test_case, F)
|
||||||
*
|
*
|
||||||
* Notice that the generators' attribute list contains also tuples.
|
* Notice that the generators' attribute list contains also tuples.
|
||||||
* Tuples are needed to specify each confix's attributes that contain
|
* Tuples are needed to specify each confix's attributes that contain
|
||||||
* more than one generator, like confix()[int_ << string] (this
|
* more than one generator, like confix()[int_ << string] (this
|
||||||
* generator needs a tuple: tuple<int, string>).
|
* generator needs a tuple: tuple<int, string>).
|
||||||
*
|
*
|
||||||
* The difference between this generator and the one in test case
|
* The difference between this generator and the one in test case
|
||||||
|
@ -92,15 +92,15 @@ BOOST_FIXTURE_TEST_CASE(bgcolor_stream_confix_test_case, F)
|
||||||
using fusion::tuple;
|
using fusion::tuple;
|
||||||
|
|
||||||
actual_output
|
actual_output
|
||||||
<< format(
|
<< format(
|
||||||
"<rect x=" << confix('"', '"')[int_]
|
"<rect x=" << confix('"', '"')[int_]
|
||||||
<< " y=" << confix('"', '"')[int_]
|
<< " y=" << confix('"', '"')[int_]
|
||||||
<< " width=" << confix('"', '"')[int_ << string]
|
<< " width=" << confix('"', '"')[int_ << string]
|
||||||
<< " height=" << confix('"', '"')[int_ << string]
|
<< " height=" << confix('"', '"')[int_ << string]
|
||||||
<< " style=" << confix('"', '"')["fill: " << string]
|
<< " style=" << confix('"', '"')["fill: " << string]
|
||||||
<< "/>",
|
<< "/>",
|
||||||
x, y, tuple<int, std::string>(width, "px"), tuple<int, std::string>(height, "px"), bgcolor);
|
x, y, tuple<int, std::string>(width, "px"), tuple<int, std::string>(height, "px"), bgcolor);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(actual_output.str(), expected_output);
|
BOOST_CHECK_EQUAL(actual_output.str(), expected_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,11 +109,11 @@ BOOST_FIXTURE_TEST_CASE(bgcolor_stream_confix_test_case, F)
|
||||||
* using confix. notice that a confix generator can be part of another
|
* using confix. notice that a confix generator can be part of another
|
||||||
* confix generator's expression.
|
* confix generator's expression.
|
||||||
*
|
*
|
||||||
* Notice also that the attribute list is the same as in
|
* Notice also that the attribute list is the same as in
|
||||||
* 'bgcolor_stream_confix_test_case'. From this one can see that each
|
* 'bgcolor_stream_confix_test_case'. From this one can see that each
|
||||||
* generator is meant to have a list of attributes if it has more than one.
|
* generator is meant to have a list of attributes if it has more than one.
|
||||||
*
|
*
|
||||||
* If the generator is nested inside another generator, the former's attribute
|
* If the generator is nested inside another generator, the former's attribute
|
||||||
* list will be another list (a tuple, for example) inside the latter's.
|
* list will be another list (a tuple, for example) inside the latter's.
|
||||||
*/
|
*/
|
||||||
BOOST_FIXTURE_TEST_CASE(bgcolor_stream_confix_complete_test_case, F)
|
BOOST_FIXTURE_TEST_CASE(bgcolor_stream_confix_complete_test_case, F)
|
||||||
|
@ -122,15 +122,15 @@ BOOST_FIXTURE_TEST_CASE(bgcolor_stream_confix_complete_test_case, F)
|
||||||
using fusion::tuple;
|
using fusion::tuple;
|
||||||
|
|
||||||
actual_output
|
actual_output
|
||||||
<< format(
|
<< format(
|
||||||
confix('<', "/>")[
|
confix('<', "/>")[
|
||||||
"rect x=" << confix('"', '"')[int_]
|
"rect x=" << confix('"', '"')[int_]
|
||||||
<< " y=" << confix('"', '"')[int_]
|
<< " y=" << confix('"', '"')[int_]
|
||||||
<< " width=" << confix('"', '"')[int_ << string]
|
<< " width=" << confix('"', '"')[int_ << string]
|
||||||
<< " height=" << confix('"', '"')[int_ << string]
|
<< " height=" << confix('"', '"')[int_ << string]
|
||||||
<< " style=" << confix('"', '"')["fill: " << string]],
|
<< " style=" << confix('"', '"')["fill: " << string]],
|
||||||
x, y, tuple<int, std::string>(width, "px"), tuple<int, std::string>(height, "px"), bgcolor);
|
x, y, tuple<int, std::string>(width, "px"), tuple<int, std::string>(height, "px"), bgcolor);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(actual_output.str(), expected_output);
|
BOOST_CHECK_EQUAL(actual_output.str(), expected_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,14 +152,14 @@ BOOST_FIXTURE_TEST_CASE(bgcolor_stream_iterator_test_case, F)
|
||||||
std::ostream_iterator<char> actual_output_iterator(actual_output);
|
std::ostream_iterator<char> actual_output_iterator(actual_output);
|
||||||
|
|
||||||
generate(
|
generate(
|
||||||
actual_output_iterator,
|
actual_output_iterator,
|
||||||
confix("<", "/>")[
|
confix("<", "/>")[
|
||||||
"rect x=" << confix('"', '"')[int_]
|
"rect x=" << confix('"', '"')[int_]
|
||||||
<< " y=" << confix('"', '"')[int_]
|
<< " y=" << confix('"', '"')[int_]
|
||||||
<< " width=" << confix('"', '"')[int_ << string]
|
<< " width=" << confix('"', '"')[int_ << string]
|
||||||
<< " height=" << confix('"', '"')[int_ << string]
|
<< " height=" << confix('"', '"')[int_ << string]
|
||||||
<< " style=" << confix('"', '"')["fill: " << string]],
|
<< " style=" << confix('"', '"')["fill: " << string]],
|
||||||
x, y, tuple<int, std::string>(width, "px"), tuple<int, std::string>(height, "px"), bgcolor);
|
x, y, tuple<int, std::string>(width, "px"), tuple<int, std::string>(height, "px"), bgcolor);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(actual_output.str(), expected_output);
|
BOOST_CHECK_EQUAL(actual_output.str(), expected_output);
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,21 +37,21 @@ BOOST_AUTO_TEST_CASE(combined_test_case)
|
||||||
svg_ren renderer(map, output_stream_iterator);
|
svg_ren renderer(map, output_stream_iterator);
|
||||||
renderer.apply();
|
renderer.apply();
|
||||||
|
|
||||||
/*std::string expected_output =
|
/*std::string expected_output =
|
||||||
svg_ren::XML_DECLARATION
|
svg_ren::XML_DECLARATION
|
||||||
+ "\n"
|
+ "\n"
|
||||||
+ svg_ren::SVG_DTD
|
+ svg_ren::SVG_DTD
|
||||||
+ "\n"
|
+ "\n"
|
||||||
+ "<svg width=\"800px\" height=\"600px\" version=\"1.1\" xmlns=\""
|
+ "<svg width=\"800px\" height=\"600px\" version=\"1.1\" xmlns=\""
|
||||||
+ svg_ren::SVG_NAMESPACE_URL
|
+ svg_ren::SVG_NAMESPACE_URL
|
||||||
+ "\">"
|
+ "\">"
|
||||||
+"\n"
|
+"\n"
|
||||||
+"<rect x=\"0\" y=\"0\" width=\"800px\" height=\"600px\" style=\"fill: #ffffff\"/>"
|
+"<rect x=\"0\" y=\"0\" width=\"800px\" height=\"600px\" style=\"fill: #ffffff\"/>"
|
||||||
+"\n"
|
+"\n"
|
||||||
+"</svg>";
|
+"</svg>";
|
||||||
|
|
||||||
std::string actual_output = output_stream.str();
|
std::string actual_output = output_stream.str();
|
||||||
BOOST_CHECK_EQUAL(actual_output, expected_output);
|
BOOST_CHECK_EQUAL(actual_output, expected_output);
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,15 +51,15 @@ BOOST_AUTO_TEST_CASE(file_output_test_case)
|
||||||
if(output_stream)
|
if(output_stream)
|
||||||
{
|
{
|
||||||
std::ostream_iterator<char> output_stream_iterator(output_stream);
|
std::ostream_iterator<char> output_stream_iterator(output_stream);
|
||||||
|
|
||||||
svg_ren renderer(map, output_stream_iterator);
|
svg_ren renderer(map, output_stream_iterator);
|
||||||
renderer.apply();
|
renderer.apply();
|
||||||
|
|
||||||
output_stream.close();
|
output_stream.close();
|
||||||
|
|
||||||
filesystem::path output_filename_path =
|
filesystem::path output_filename_path =
|
||||||
filesystem::system_complete(filesystem::path(".")) / filesystem::path(output_filename);
|
filesystem::system_complete(filesystem::path(".")) / filesystem::path(output_filename);
|
||||||
|
|
||||||
BOOST_CHECK_MESSAGE(filesystem::exists(output_filename_path), "File '"+output_filename_path.string()+"' was created.");
|
BOOST_CHECK_MESSAGE(filesystem::exists(output_filename_path), "File '"+output_filename_path.string()+"' was created.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -25,54 +25,54 @@ namespace filesystem = boost::filesystem;
|
||||||
using namespace mapnik;
|
using namespace mapnik;
|
||||||
|
|
||||||
void prepare_map(Map& m)
|
void prepare_map(Map& m)
|
||||||
{
|
{
|
||||||
const std::string mapnik_dir("/usr/local/lib/mapnik/");
|
const std::string mapnik_dir("/usr/local/lib/mapnik/");
|
||||||
std::cout << " looking for 'shape.input' plugin in... " << mapnik_dir << "input/" << "\n";
|
std::cout << " looking for 'shape.input' plugin in... " << mapnik_dir << "input/" << "\n";
|
||||||
datasource_cache::instance()->register_datasources(mapnik_dir + "input/");
|
datasource_cache::instance()->register_datasources(mapnik_dir + "input/");
|
||||||
|
|
||||||
// create styles
|
// create styles
|
||||||
|
|
||||||
// Provinces (polygon)
|
// Provinces (polygon)
|
||||||
feature_type_style provpoly_style;
|
feature_type_style provpoly_style;
|
||||||
|
|
||||||
rule provpoly_rule_on;
|
rule provpoly_rule_on;
|
||||||
provpoly_rule_on.set_filter(parse_expression("[NAME_EN] = 'Ontario'"));
|
provpoly_rule_on.set_filter(parse_expression("[NAME_EN] = 'Ontario'"));
|
||||||
provpoly_rule_on.append(polygon_symbolizer(color(250, 190, 183)));
|
provpoly_rule_on.append(polygon_symbolizer(color(250, 190, 183)));
|
||||||
provpoly_style.add_rule(provpoly_rule_on);
|
provpoly_style.add_rule(provpoly_rule_on);
|
||||||
|
|
||||||
rule provpoly_rule_qc;
|
rule provpoly_rule_qc;
|
||||||
provpoly_rule_qc.set_filter(parse_expression("[NOM_FR] = 'Québec'"));
|
provpoly_rule_qc.set_filter(parse_expression("[NOM_FR] = 'Québec'"));
|
||||||
provpoly_rule_qc.append(polygon_symbolizer(color(217, 235, 203)));
|
provpoly_rule_qc.append(polygon_symbolizer(color(217, 235, 203)));
|
||||||
provpoly_style.add_rule(provpoly_rule_qc);
|
provpoly_style.add_rule(provpoly_rule_qc);
|
||||||
|
|
||||||
m.insert_style("provinces",provpoly_style);
|
m.insert_style("provinces",provpoly_style);
|
||||||
|
|
||||||
// Provinces (polyline)
|
// Provinces (polyline)
|
||||||
feature_type_style provlines_style;
|
feature_type_style provlines_style;
|
||||||
|
|
||||||
stroke provlines_stk (color(0,0,0),1.0);
|
stroke provlines_stk (color(0,0,0),1.0);
|
||||||
provlines_stk.add_dash(8, 4);
|
provlines_stk.add_dash(8, 4);
|
||||||
provlines_stk.add_dash(2, 2);
|
provlines_stk.add_dash(2, 2);
|
||||||
provlines_stk.add_dash(2, 2);
|
provlines_stk.add_dash(2, 2);
|
||||||
|
|
||||||
rule provlines_rule;
|
rule provlines_rule;
|
||||||
provlines_rule.append(line_symbolizer(provlines_stk));
|
provlines_rule.append(line_symbolizer(provlines_stk));
|
||||||
provlines_style.add_rule(provlines_rule);
|
provlines_style.add_rule(provlines_rule);
|
||||||
|
|
||||||
m.insert_style("provlines",provlines_style);
|
m.insert_style("provlines",provlines_style);
|
||||||
|
|
||||||
// Drainage
|
// Drainage
|
||||||
feature_type_style qcdrain_style;
|
feature_type_style qcdrain_style;
|
||||||
|
|
||||||
rule qcdrain_rule;
|
rule qcdrain_rule;
|
||||||
qcdrain_rule.set_filter(parse_expression("[HYC] = 8"));
|
qcdrain_rule.set_filter(parse_expression("[HYC] = 8"));
|
||||||
qcdrain_rule.append(polygon_symbolizer(color(153, 204, 255)));
|
qcdrain_rule.append(polygon_symbolizer(color(153, 204, 255)));
|
||||||
qcdrain_style.add_rule(qcdrain_rule);
|
qcdrain_style.add_rule(qcdrain_rule);
|
||||||
|
|
||||||
m.insert_style("drainage",qcdrain_style);
|
m.insert_style("drainage",qcdrain_style);
|
||||||
|
|
||||||
// Roads 3 and 4 (The "grey" roads)
|
// Roads 3 and 4 (The "grey" roads)
|
||||||
feature_type_style roads34_style;
|
feature_type_style roads34_style;
|
||||||
rule roads34_rule;
|
rule roads34_rule;
|
||||||
roads34_rule.set_filter(parse_expression("[CLASS] = 3 or [CLASS] = 4"));
|
roads34_rule.set_filter(parse_expression("[CLASS] = 3 or [CLASS] = 4"));
|
||||||
stroke roads34_rule_stk(color(171,158,137),2.0);
|
stroke roads34_rule_stk(color(171,158,137),2.0);
|
||||||
|
@ -80,9 +80,9 @@ void prepare_map(Map& m)
|
||||||
roads34_rule_stk.set_line_join(ROUND_JOIN);
|
roads34_rule_stk.set_line_join(ROUND_JOIN);
|
||||||
roads34_rule.append(line_symbolizer(roads34_rule_stk));
|
roads34_rule.append(line_symbolizer(roads34_rule_stk));
|
||||||
roads34_style.add_rule(roads34_rule);
|
roads34_style.add_rule(roads34_rule);
|
||||||
|
|
||||||
m.insert_style("smallroads",roads34_style);
|
m.insert_style("smallroads",roads34_style);
|
||||||
|
|
||||||
// Roads 2 (The thin yellow ones)
|
// Roads 2 (The thin yellow ones)
|
||||||
feature_type_style roads2_style_1;
|
feature_type_style roads2_style_1;
|
||||||
rule roads2_rule_1;
|
rule roads2_rule_1;
|
||||||
|
@ -92,9 +92,9 @@ void prepare_map(Map& m)
|
||||||
roads2_rule_stk_1.set_line_join(ROUND_JOIN);
|
roads2_rule_stk_1.set_line_join(ROUND_JOIN);
|
||||||
roads2_rule_1.append(line_symbolizer(roads2_rule_stk_1));
|
roads2_rule_1.append(line_symbolizer(roads2_rule_stk_1));
|
||||||
roads2_style_1.add_rule(roads2_rule_1);
|
roads2_style_1.add_rule(roads2_rule_1);
|
||||||
|
|
||||||
m.insert_style("road-border", roads2_style_1);
|
m.insert_style("road-border", roads2_style_1);
|
||||||
|
|
||||||
feature_type_style roads2_style_2;
|
feature_type_style roads2_style_2;
|
||||||
rule roads2_rule_2;
|
rule roads2_rule_2;
|
||||||
roads2_rule_2.set_filter(parse_expression("[CLASS] = 2"));
|
roads2_rule_2.set_filter(parse_expression("[CLASS] = 2"));
|
||||||
|
@ -103,9 +103,9 @@ void prepare_map(Map& m)
|
||||||
roads2_rule_stk_2.set_line_join(ROUND_JOIN);
|
roads2_rule_stk_2.set_line_join(ROUND_JOIN);
|
||||||
roads2_rule_2.append(line_symbolizer(roads2_rule_stk_2));
|
roads2_rule_2.append(line_symbolizer(roads2_rule_stk_2));
|
||||||
roads2_style_2.add_rule(roads2_rule_2);
|
roads2_style_2.add_rule(roads2_rule_2);
|
||||||
|
|
||||||
m.insert_style("road-fill", roads2_style_2);
|
m.insert_style("road-fill", roads2_style_2);
|
||||||
|
|
||||||
// Roads 1 (The big orange ones, the highways)
|
// Roads 1 (The big orange ones, the highways)
|
||||||
feature_type_style roads1_style_1;
|
feature_type_style roads1_style_1;
|
||||||
rule roads1_rule_1;
|
rule roads1_rule_1;
|
||||||
|
@ -116,7 +116,7 @@ void prepare_map(Map& m)
|
||||||
roads1_rule_1.append(line_symbolizer(roads1_rule_stk_1));
|
roads1_rule_1.append(line_symbolizer(roads1_rule_stk_1));
|
||||||
roads1_style_1.add_rule(roads1_rule_1);
|
roads1_style_1.add_rule(roads1_rule_1);
|
||||||
m.insert_style("highway-border", roads1_style_1);
|
m.insert_style("highway-border", roads1_style_1);
|
||||||
|
|
||||||
feature_type_style roads1_style_2;
|
feature_type_style roads1_style_2;
|
||||||
rule roads1_rule_2;
|
rule roads1_rule_2;
|
||||||
roads1_rule_2.set_filter(parse_expression("[CLASS] = 1"));
|
roads1_rule_2.set_filter(parse_expression("[CLASS] = 1"));
|
||||||
|
@ -125,21 +125,21 @@ void prepare_map(Map& m)
|
||||||
roads1_rule_stk_2.set_line_join(ROUND_JOIN);
|
roads1_rule_stk_2.set_line_join(ROUND_JOIN);
|
||||||
roads1_rule_2.append(line_symbolizer(roads1_rule_stk_2));
|
roads1_rule_2.append(line_symbolizer(roads1_rule_stk_2));
|
||||||
roads1_style_2.add_rule(roads1_rule_2);
|
roads1_style_2.add_rule(roads1_rule_2);
|
||||||
m.insert_style("highway-fill", roads1_style_2);
|
m.insert_style("highway-fill", roads1_style_2);
|
||||||
|
|
||||||
// layers
|
// layers
|
||||||
// Provincial polygons
|
// Provincial polygons
|
||||||
{
|
{
|
||||||
parameters p;
|
parameters p;
|
||||||
p["type"]="shape";
|
p["type"]="shape";
|
||||||
p["file"]="../../../demo/data/boundaries";
|
p["file"]="../../../demo/data/boundaries";
|
||||||
|
|
||||||
layer lyr("Provinces");
|
layer lyr("Provinces");
|
||||||
lyr.set_datasource(datasource_cache::instance()->create(p));
|
lyr.set_datasource(datasource_cache::instance()->create(p));
|
||||||
lyr.add_style("provinces");
|
lyr.add_style("provinces");
|
||||||
m.addLayer(lyr);
|
m.addLayer(lyr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drainage
|
// Drainage
|
||||||
{
|
{
|
||||||
parameters p;
|
parameters p;
|
||||||
|
@ -147,46 +147,46 @@ void prepare_map(Map& m)
|
||||||
p["file"]="../../../demo/data/qcdrainage";
|
p["file"]="../../../demo/data/qcdrainage";
|
||||||
layer lyr("Quebec Hydrography");
|
layer lyr("Quebec Hydrography");
|
||||||
lyr.set_datasource(datasource_cache::instance()->create(p));
|
lyr.set_datasource(datasource_cache::instance()->create(p));
|
||||||
lyr.add_style("drainage");
|
lyr.add_style("drainage");
|
||||||
m.addLayer(lyr);
|
m.addLayer(lyr);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
parameters p;
|
parameters p;
|
||||||
p["type"]="shape";
|
p["type"]="shape";
|
||||||
p["file"]="../../../demo/data/ontdrainage";
|
p["file"]="../../../demo/data/ontdrainage";
|
||||||
|
|
||||||
layer lyr("Ontario Hydrography");
|
layer lyr("Ontario Hydrography");
|
||||||
lyr.set_datasource(datasource_cache::instance()->create(p));
|
lyr.set_datasource(datasource_cache::instance()->create(p));
|
||||||
lyr.add_style("drainage");
|
lyr.add_style("drainage");
|
||||||
m.addLayer(lyr);
|
m.addLayer(lyr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provincial boundaries
|
// Provincial boundaries
|
||||||
{
|
{
|
||||||
parameters p;
|
parameters p;
|
||||||
p["type"]="shape";
|
p["type"]="shape";
|
||||||
p["file"]="../../../demo/data/boundaries_l";
|
p["file"]="../../../demo/data/boundaries_l";
|
||||||
layer lyr("Provincial borders");
|
layer lyr("Provincial borders");
|
||||||
lyr.set_datasource(datasource_cache::instance()->create(p));
|
lyr.set_datasource(datasource_cache::instance()->create(p));
|
||||||
lyr.add_style("provlines");
|
lyr.add_style("provlines");
|
||||||
m.addLayer(lyr);
|
m.addLayer(lyr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Roads
|
// Roads
|
||||||
{
|
{
|
||||||
parameters p;
|
parameters p;
|
||||||
p["type"]="shape";
|
p["type"]="shape";
|
||||||
p["file"]="../../../demo/data/roads";
|
p["file"]="../../../demo/data/roads";
|
||||||
layer lyr("Roads");
|
layer lyr("Roads");
|
||||||
lyr.set_datasource(datasource_cache::instance()->create(p));
|
lyr.set_datasource(datasource_cache::instance()->create(p));
|
||||||
lyr.add_style("smallroads");
|
lyr.add_style("smallroads");
|
||||||
lyr.add_style("road-border");
|
lyr.add_style("road-border");
|
||||||
lyr.add_style("road-fill");
|
lyr.add_style("road-fill");
|
||||||
lyr.add_style("highway-border");
|
lyr.add_style("highway-border");
|
||||||
lyr.add_style("highway-fill");
|
lyr.add_style("highway-fill");
|
||||||
|
|
||||||
m.addLayer(lyr);
|
m.addLayer(lyr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,19 +197,19 @@ void render_to_file(Map const& m, const std::string output_filename)
|
||||||
if(output_stream)
|
if(output_stream)
|
||||||
{
|
{
|
||||||
typedef svg_renderer<std::ostream_iterator<char> > svg_ren;
|
typedef svg_renderer<std::ostream_iterator<char> > svg_ren;
|
||||||
|
|
||||||
std::ostream_iterator<char> output_stream_iterator(output_stream);
|
std::ostream_iterator<char> output_stream_iterator(output_stream);
|
||||||
|
|
||||||
svg_ren renderer(m, output_stream_iterator);
|
svg_ren renderer(m, output_stream_iterator);
|
||||||
renderer.apply();
|
renderer.apply();
|
||||||
|
|
||||||
output_stream.close();
|
output_stream.close();
|
||||||
|
|
||||||
filesystem::path output_filename_path =
|
filesystem::path output_filename_path =
|
||||||
filesystem::system_complete(filesystem::path(".")) / filesystem::path(output_filename);
|
filesystem::system_complete(filesystem::path(".")) / filesystem::path(output_filename);
|
||||||
|
|
||||||
BOOST_CHECK_MESSAGE(filesystem::exists(output_filename_path),
|
BOOST_CHECK_MESSAGE(filesystem::exists(output_filename_path),
|
||||||
"File '"+output_filename_path.string()+"' was created.");
|
"File '"+output_filename_path.string()+"' was created.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -220,12 +220,12 @@ void render_to_file(Map const& m, const std::string output_filename)
|
||||||
BOOST_AUTO_TEST_CASE(path_element_test_case_1)
|
BOOST_AUTO_TEST_CASE(path_element_test_case_1)
|
||||||
{
|
{
|
||||||
Map m(800,600);
|
Map m(800,600);
|
||||||
m.set_background(color_factory::from_string("steelblue"));
|
m.set_background(color_factory::from_string("steelblue"));
|
||||||
|
|
||||||
prepare_map(m);
|
prepare_map(m);
|
||||||
|
|
||||||
//m.zoom_to_box(box2d<double>(1405120.04127408, -247003.813399447,
|
//m.zoom_to_box(box2d<double>(1405120.04127408, -247003.813399447,
|
||||||
//1706357.31328276, -25098.593149577));
|
//1706357.31328276, -25098.593149577));
|
||||||
m.zoom_all();
|
m.zoom_all();
|
||||||
render_to_file(m, "path_element_test_case_1.svg");
|
render_to_file(m, "path_element_test_case_1.svg");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#define BOOST_TEST_MODULE root_element_test
|
#define BOOST_TEST_MODULE root_element_test
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This test module contains several generators for
|
* This test module contains several generators for
|
||||||
* the SVG root element.
|
* the SVG root element.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -24,14 +24,14 @@ namespace repository = boost::spirit::repository;
|
||||||
namespace fusion = boost::fusion;
|
namespace fusion = boost::fusion;
|
||||||
using namespace karma;
|
using namespace karma;
|
||||||
|
|
||||||
struct F
|
struct F
|
||||||
{
|
{
|
||||||
F() :
|
F() :
|
||||||
width(100),
|
width(100),
|
||||||
height(100),
|
height(100),
|
||||||
version(1.1),
|
version(1.1),
|
||||||
xmlns("http://www.w3.org/2000/svg"),
|
xmlns("http://www.w3.org/2000/svg"),
|
||||||
expected_output("<svg width=\"100px\" height=\"100px\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">") {}
|
expected_output("<svg width=\"100px\" height=\"100px\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">") {}
|
||||||
|
|
||||||
~F() {}
|
~F() {}
|
||||||
|
|
||||||
|
@ -58,13 +58,13 @@ struct F
|
||||||
BOOST_FIXTURE_TEST_CASE(bgcolor_stream_test_case, F)
|
BOOST_FIXTURE_TEST_CASE(bgcolor_stream_test_case, F)
|
||||||
{
|
{
|
||||||
actual_output
|
actual_output
|
||||||
<< format(
|
<< format(
|
||||||
"<svg width=\"" << int_ << string << "\" "
|
"<svg width=\"" << int_ << string << "\" "
|
||||||
<< "height=\"" << int_ << string << "\" "
|
<< "height=\"" << int_ << string << "\" "
|
||||||
<< "version=\"" << float_ << "\" "
|
<< "version=\"" << float_ << "\" "
|
||||||
<< "xmlns=\"" << string << "\""
|
<< "xmlns=\"" << string << "\""
|
||||||
<< ">",
|
<< ">",
|
||||||
width, "px", height, "px", version, xmlns);
|
width, "px", height, "px", version, xmlns);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(actual_output.str(), expected_output);
|
BOOST_CHECK_EQUAL(actual_output.str(), expected_output);
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ BOOST_FIXTURE_TEST_CASE(bgcolor_stream_test_case, F)
|
||||||
*
|
*
|
||||||
* Notice that the generators' attribute list contains also tuples.
|
* Notice that the generators' attribute list contains also tuples.
|
||||||
* Tuples are needed to specify each confix's attributes that contain
|
* Tuples are needed to specify each confix's attributes that contain
|
||||||
* more than one generator, like confix()[int_ << string] (this
|
* more than one generator, like confix()[int_ << string] (this
|
||||||
* generator needs a tuple: tuple<int, string>).
|
* generator needs a tuple: tuple<int, string>).
|
||||||
*
|
*
|
||||||
* The difference between this generator and the one in test case
|
* The difference between this generator and the one in test case
|
||||||
|
@ -88,14 +88,14 @@ BOOST_FIXTURE_TEST_CASE(bgcolor_stream_confix_test_case, F)
|
||||||
using fusion::tuple;
|
using fusion::tuple;
|
||||||
|
|
||||||
actual_output
|
actual_output
|
||||||
<< format(
|
<< format(
|
||||||
"<svg width=" << confix('"', '"')[int_ << string]
|
"<svg width=" << confix('"', '"')[int_ << string]
|
||||||
<< " height=" << confix('"', '"')[int_ << string]
|
<< " height=" << confix('"', '"')[int_ << string]
|
||||||
<< " version=" << confix('"', '"')[float_]
|
<< " version=" << confix('"', '"')[float_]
|
||||||
<< " xmlns=" << confix('"', '"')[string]
|
<< " xmlns=" << confix('"', '"')[string]
|
||||||
<< ">",
|
<< ">",
|
||||||
tuple<int, std::string>(width, "px"), tuple<int, std::string>(height, "px"), version, xmlns);
|
tuple<int, std::string>(width, "px"), tuple<int, std::string>(height, "px"), version, xmlns);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(actual_output.str(), expected_output);
|
BOOST_CHECK_EQUAL(actual_output.str(), expected_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,11 +104,11 @@ BOOST_FIXTURE_TEST_CASE(bgcolor_stream_confix_test_case, F)
|
||||||
* using confix. notice that a confix generator can be part of another
|
* using confix. notice that a confix generator can be part of another
|
||||||
* confix generator's expression.
|
* confix generator's expression.
|
||||||
*
|
*
|
||||||
* Notice also that the attribute list is the same as in
|
* Notice also that the attribute list is the same as in
|
||||||
* 'bgcolor_stream_confix_test_case'. From this one can see that each
|
* 'bgcolor_stream_confix_test_case'. From this one can see that each
|
||||||
* generator is meant to have a list of attributes if it has more than one.
|
* generator is meant to have a list of attributes if it has more than one.
|
||||||
*
|
*
|
||||||
* If the generator is nested inside another generator, the former's attribute
|
* If the generator is nested inside another generator, the former's attribute
|
||||||
* list will be another list (a tuple, for example) inside the latter's.
|
* list will be another list (a tuple, for example) inside the latter's.
|
||||||
*/
|
*/
|
||||||
BOOST_FIXTURE_TEST_CASE(bgcolor_stream_confix_complete_test_case, F)
|
BOOST_FIXTURE_TEST_CASE(bgcolor_stream_confix_complete_test_case, F)
|
||||||
|
@ -117,14 +117,14 @@ BOOST_FIXTURE_TEST_CASE(bgcolor_stream_confix_complete_test_case, F)
|
||||||
using fusion::tuple;
|
using fusion::tuple;
|
||||||
|
|
||||||
actual_output
|
actual_output
|
||||||
<< format(
|
<< format(
|
||||||
confix('<', ">")[
|
confix('<', ">")[
|
||||||
"svg width=" << confix('"', '"')[int_ << string]
|
"svg width=" << confix('"', '"')[int_ << string]
|
||||||
<< " height=" << confix('"', '"')[int_ << string]
|
<< " height=" << confix('"', '"')[int_ << string]
|
||||||
<< " version=" << confix('"', '"')[float_]
|
<< " version=" << confix('"', '"')[float_]
|
||||||
<< " xmlns=" << confix('"', '"')[string]],
|
<< " xmlns=" << confix('"', '"')[string]],
|
||||||
tuple<int, std::string>(width, "px"), tuple<int, std::string>(height, "px"), version, xmlns);
|
tuple<int, std::string>(width, "px"), tuple<int, std::string>(height, "px"), version, xmlns);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(actual_output.str(), expected_output);
|
BOOST_CHECK_EQUAL(actual_output.str(), expected_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,13 +146,13 @@ BOOST_FIXTURE_TEST_CASE(bgcolor_stream_iterator_test_case, F)
|
||||||
std::ostream_iterator<char> actual_output_iterator(actual_output);
|
std::ostream_iterator<char> actual_output_iterator(actual_output);
|
||||||
|
|
||||||
generate(
|
generate(
|
||||||
actual_output_iterator,
|
actual_output_iterator,
|
||||||
confix("<", ">")[
|
confix("<", ">")[
|
||||||
"svg width=" << confix('"', '"')[int_ << string]
|
"svg width=" << confix('"', '"')[int_ << string]
|
||||||
<< " height=" << confix('"', '"')[int_ << string]
|
<< " height=" << confix('"', '"')[int_ << string]
|
||||||
<< " version=" << confix('"', '"')[float_]
|
<< " version=" << confix('"', '"')[float_]
|
||||||
<< " xmlns=" << confix('"', '"')[string]],
|
<< " xmlns=" << confix('"', '"')[string]],
|
||||||
tuple<int, std::string>(width, "px"), tuple<int, std::string>(height, "px"), version, xmlns);
|
tuple<int, std::string>(width, "px"), tuple<int, std::string>(height, "px"), version, xmlns);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(actual_output.str(), expected_output);
|
BOOST_CHECK_EQUAL(actual_output.str(), expected_output);
|
||||||
}
|
}
|
||||||
|
|
107
tests/python_tests/map_query_test.py
Normal file
107
tests/python_tests/map_query_test.py
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
from nose.tools import *
|
||||||
|
from utilities import execution_path
|
||||||
|
from copy import deepcopy
|
||||||
|
|
||||||
|
import os, mapnik
|
||||||
|
|
||||||
|
def setup():
|
||||||
|
# All of the paths used are relative, if we run the tests
|
||||||
|
# from another directory we need to chdir()
|
||||||
|
os.chdir(execution_path('.'))
|
||||||
|
|
||||||
|
# map has no layers
|
||||||
|
@raises(IndexError)
|
||||||
|
def test_map_query_throw1():
|
||||||
|
m = mapnik.Map(256,256)
|
||||||
|
m.zoom_to_box(mapnik.Box2d(-1,-1,0,0))
|
||||||
|
m.query_point(0,0,0)
|
||||||
|
|
||||||
|
# only positive indexes
|
||||||
|
@raises(IndexError)
|
||||||
|
def test_map_query_throw2():
|
||||||
|
m = mapnik.Map(256,256)
|
||||||
|
m.query_point(-1,0,0)
|
||||||
|
|
||||||
|
# map has never been zoomed (nodata)
|
||||||
|
@raises(RuntimeError)
|
||||||
|
def test_map_query_throw3():
|
||||||
|
m = mapnik.Map(256,256)
|
||||||
|
m.query_point(0,0,0)
|
||||||
|
|
||||||
|
# map has never been zoomed (even with data)
|
||||||
|
@raises(RuntimeError)
|
||||||
|
def test_map_query_throw4():
|
||||||
|
m = mapnik.Map(256,256)
|
||||||
|
mapnik.load_map(m,'../data/good_maps/agg_poly_gamma_map.xml')
|
||||||
|
m.query_point(0,0,0)
|
||||||
|
|
||||||
|
# invalid coords in general (do not intersect)
|
||||||
|
@raises(RuntimeError)
|
||||||
|
def test_map_query_throw5():
|
||||||
|
m = mapnik.Map(256,256)
|
||||||
|
mapnik.load_map(m,'../data/good_maps/agg_poly_gamma_map.xml')
|
||||||
|
m.zoom_all()
|
||||||
|
m.query_point(0,9999999999999999,9999999999999999)
|
||||||
|
|
||||||
|
# invalid coords for back projecting
|
||||||
|
@raises(RuntimeError)
|
||||||
|
def test_map_query_throw6():
|
||||||
|
m = mapnik.Map(256,256)
|
||||||
|
mapnik.load_map(m,'../data/good_maps/merc2wgs84_reprojection.xml')
|
||||||
|
wgs84_bounds = mapnik.Box2d(-180,-90,180,90)
|
||||||
|
m.maximum_extent = wgs84_bounds
|
||||||
|
m.zoom_all()
|
||||||
|
m.query_point(0,-180,-90)
|
||||||
|
|
||||||
|
def test_map_query_works1():
|
||||||
|
m = mapnik.Map(256,256)
|
||||||
|
mapnik.load_map(m,'../data/good_maps/wgs842merc_reprojection.xml')
|
||||||
|
merc_bounds = mapnik.Box2d(-20037508.34,-20037508.34,20037508.34,20037508.34)
|
||||||
|
m.maximum_extent = merc_bounds
|
||||||
|
m.zoom_all()
|
||||||
|
fs = m.query_point(0,-11012435.5376, 4599674.6134) # somewhere in kansas
|
||||||
|
feat = fs.next()
|
||||||
|
eq_(feat.attributes['NAME_FORMA'],u'United States of America')
|
||||||
|
|
||||||
|
def test_map_query_works2():
|
||||||
|
m = mapnik.Map(256,256)
|
||||||
|
mapnik.load_map(m,'../data/good_maps/merc2wgs84_reprojection.xml')
|
||||||
|
wgs84_bounds = mapnik.Box2d(-179.999999975,-85.0511287776,179.999999975,85.0511287776)
|
||||||
|
m.maximum_extent = wgs84_bounds
|
||||||
|
# caution - will go square due to evil aspect_fix_mode backhandedness
|
||||||
|
m.zoom_all()
|
||||||
|
#mapnik.render_to_file(m,'works2.png')
|
||||||
|
# valid that aspec_fix_mode modified the bbox
|
||||||
|
eq_(m.envelope(),mapnik.Box2d(-179.999999975,-179.999999975,179.999999975,179.999999975))
|
||||||
|
fs = m.query_point(0,-98.9264, 38.1432) # somewhere in kansas
|
||||||
|
feat = fs.next()
|
||||||
|
eq_(feat.attributes['NAME'],u'United States')
|
||||||
|
|
||||||
|
def test_map_query_in_pixels_works1():
|
||||||
|
m = mapnik.Map(256,256)
|
||||||
|
mapnik.load_map(m,'../data/good_maps/wgs842merc_reprojection.xml')
|
||||||
|
merc_bounds = mapnik.Box2d(-20037508.34,-20037508.34,20037508.34,20037508.34)
|
||||||
|
m.maximum_extent = merc_bounds
|
||||||
|
m.zoom_all()
|
||||||
|
fs = m.query_map_point(0,55,100) # somewhere in middle of us
|
||||||
|
feat = fs.next()
|
||||||
|
eq_(feat.attributes['NAME_FORMA'],u'United States of America')
|
||||||
|
|
||||||
|
def test_map_query_in_pixels_works2():
|
||||||
|
m = mapnik.Map(256,256)
|
||||||
|
mapnik.load_map(m,'../data/good_maps/merc2wgs84_reprojection.xml')
|
||||||
|
wgs84_bounds = mapnik.Box2d(-179.999999975,-85.0511287776,179.999999975,85.0511287776)
|
||||||
|
m.maximum_extent = wgs84_bounds
|
||||||
|
# caution - will go square due to evil aspect_fix_mode backhandedness
|
||||||
|
m.zoom_all()
|
||||||
|
# valid that aspec_fix_mode modified the bbox
|
||||||
|
eq_(m.envelope(),mapnik.Box2d(-179.999999975,-179.999999975,179.999999975,179.999999975))
|
||||||
|
fs = m.query_map_point(0,55,100) # somewhere in middle of us
|
||||||
|
feat = fs.next()
|
||||||
|
eq_(feat.attributes['NAME'],u'United States')
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
setup()
|
||||||
|
[eval(run)() for run in dir() if 'test_' in run]
|
|
@ -113,6 +113,27 @@ def test_pointsymbolizer_init():
|
||||||
eq_(p.ignore_placement,True)
|
eq_(p.ignore_placement,True)
|
||||||
eq_(p.placement, mapnik.point_placement.INTERIOR)
|
eq_(p.placement, mapnik.point_placement.INTERIOR)
|
||||||
|
|
||||||
|
|
||||||
|
# PointSymbolizer initialization
|
||||||
|
def test_markersymbolizer_init():
|
||||||
|
p = mapnik.MarkersSymbolizer()
|
||||||
|
eq_(p.allow_overlap, False)
|
||||||
|
eq_(p.opacity,1)
|
||||||
|
eq_(p.filename,'')
|
||||||
|
|
||||||
|
stroke = mapnik.Stroke()
|
||||||
|
stroke.color = mapnik.Color('black')
|
||||||
|
stroke.width = 1.0
|
||||||
|
|
||||||
|
p.stroke = stroke
|
||||||
|
p.fill = mapnik.Color('white')
|
||||||
|
p.allow_overlap = True
|
||||||
|
p.opacity = 0.5
|
||||||
|
|
||||||
|
eq_(p.allow_overlap, True)
|
||||||
|
eq_(p.opacity, 0.5)
|
||||||
|
|
||||||
|
|
||||||
# PointSymbolizer missing image file
|
# PointSymbolizer missing image file
|
||||||
# images paths are now PathExpressions are evaluated at runtime
|
# images paths are now PathExpressions are evaluated at runtime
|
||||||
# so it does not make sense to throw...
|
# so it does not make sense to throw...
|
||||||
|
|
|
@ -69,17 +69,20 @@ def test_dataraster_query_point():
|
||||||
_map = mapnik.Map(256,256, srs)
|
_map = mapnik.Map(256,256, srs)
|
||||||
_map.layers.append(lyr)
|
_map.layers.append(lyr)
|
||||||
|
|
||||||
# point inside raster extent with valid data
|
x, y = 556113.0,4381428.0 # center of extent of raster
|
||||||
x, y = 427417, 4477517
|
_map.zoom_all()
|
||||||
features = _map.query_point(0,x,y).features
|
features = _map.query_point(0,x,y).features
|
||||||
assert len(features) == 1
|
assert len(features) == 1
|
||||||
feat = features[0]
|
feat = features[0]
|
||||||
center = feat.envelope().center()
|
center = feat.envelope().center()
|
||||||
assert center.x==x and center.y==y, center
|
assert center.x==x and center.y==y, center
|
||||||
value = feat['value']
|
value = feat['value']
|
||||||
assert value == 21.0, value
|
assert value == 18.0, value
|
||||||
|
|
||||||
# point outside raster extent
|
# point inside map extent but outside raster extent
|
||||||
|
current_box = _map.envelope()
|
||||||
|
current_box.expand_to_include(-427417,4477517)
|
||||||
|
_map.zoom_to_box(current_box)
|
||||||
features = _map.query_point(0,-427417,4477517).features
|
features = _map.query_point(0,-427417,4477517).features
|
||||||
assert len(features) == 0
|
assert len(features) == 0
|
||||||
|
|
||||||
|
|
|
@ -71,6 +71,88 @@ if 'sqlite' in mapnik.DatasourceCache.instance().plugin_names():
|
||||||
eq_(os.path.exists(index),True)
|
eq_(os.path.exists(index),True)
|
||||||
os.unlink(index)
|
os.unlink(index)
|
||||||
|
|
||||||
|
def test_geometry_round_trip():
|
||||||
|
test_db = '/tmp/mapnik-sqlite-point.db'
|
||||||
|
ogr_metadata = True
|
||||||
|
|
||||||
|
# create test db
|
||||||
|
conn = sqlite3.connect(test_db)
|
||||||
|
cur = conn.cursor()
|
||||||
|
cur.execute('''
|
||||||
|
CREATE TABLE IF NOT EXISTS point_table
|
||||||
|
(id INTEGER PRIMARY KEY AUTOINCREMENT, geometry BLOB, name varchar)
|
||||||
|
''')
|
||||||
|
# optional: but nice if we want to read with ogr
|
||||||
|
if ogr_metadata:
|
||||||
|
cur.execute('''CREATE TABLE IF NOT EXISTS geometry_columns (
|
||||||
|
f_table_name VARCHAR,
|
||||||
|
f_geometry_column VARCHAR,
|
||||||
|
geometry_type INTEGER,
|
||||||
|
coord_dimension INTEGER,
|
||||||
|
srid INTEGER,
|
||||||
|
geometry_format VARCHAR )''')
|
||||||
|
cur.execute('''INSERT INTO geometry_columns
|
||||||
|
(f_table_name, f_geometry_column, geometry_format,
|
||||||
|
geometry_type, coord_dimension, srid) VALUES
|
||||||
|
('point_table','geometry','WKB', 1, 1, 4326)''')
|
||||||
|
conn.commit()
|
||||||
|
cur.close()
|
||||||
|
|
||||||
|
# add a point as wkb (using mapnik) to match how an ogr created db looks
|
||||||
|
x = -122 # longitude
|
||||||
|
y = 48 # latitude
|
||||||
|
wkt = 'POINT(%s %s)' % (x,y)
|
||||||
|
# little endian wkb (mapnik will auto-detect and ready either little or big endian (XDR))
|
||||||
|
wkb = mapnik.Path.from_wkt(wkt).to_wkb(mapnik.wkbByteOrder.NDR)
|
||||||
|
values = (None,sqlite3.Binary(wkb),"test point")
|
||||||
|
cur = conn.cursor()
|
||||||
|
cur.execute('''INSERT into "point_table" (id,geometry,name) values (?,?,?)''',values)
|
||||||
|
conn.commit()
|
||||||
|
cur.close()
|
||||||
|
|
||||||
|
def make_wkb_point(x,y):
|
||||||
|
import struct
|
||||||
|
byteorder = 1; # little endian
|
||||||
|
endianess = ''
|
||||||
|
if byteorder == 1:
|
||||||
|
endianess = '<'
|
||||||
|
else:
|
||||||
|
endianess = '>'
|
||||||
|
geom_type = 1; # for a point
|
||||||
|
return struct.pack('%sbldd' % endianess, byteorder, geom_type, x, y)
|
||||||
|
|
||||||
|
# confirm the wkb matches a manually formed wkb
|
||||||
|
wkb2 = make_wkb_point(x,y)
|
||||||
|
eq_(wkb,wkb2)
|
||||||
|
|
||||||
|
# ensure we can read this data back out properly with mapnik
|
||||||
|
ds = mapnik.Datasource(**{'type':'sqlite','file':test_db, 'table':'point_table'})
|
||||||
|
fs = ds.featureset()
|
||||||
|
feat = fs.next()
|
||||||
|
eq_(feat.id(),1)
|
||||||
|
eq_(feat['name'],'test point')
|
||||||
|
geoms = feat.geometries()
|
||||||
|
eq_(len(geoms),1)
|
||||||
|
eq_(geoms.to_wkt(),'Point(-122.0 48.0)')
|
||||||
|
|
||||||
|
# ensure it matches data read with just sqlite
|
||||||
|
cur = conn.cursor()
|
||||||
|
cur.execute('''SELECT * from point_table''')
|
||||||
|
conn.commit()
|
||||||
|
result = cur.fetchone()
|
||||||
|
cur.close()
|
||||||
|
feat_id = result[0]
|
||||||
|
eq_(feat_id,1)
|
||||||
|
name = result[2]
|
||||||
|
eq_(name,'test point')
|
||||||
|
geom_wkb_blob = result[1]
|
||||||
|
eq_(str(geom_wkb_blob),geoms.to_wkb(mapnik.wkbByteOrder.NDR))
|
||||||
|
new_geom = mapnik.Path.from_wkb(str(geom_wkb_blob))
|
||||||
|
eq_(new_geom.to_wkt(),geoms.to_wkt())
|
||||||
|
|
||||||
|
# cleanup
|
||||||
|
os.unlink(test_db)
|
||||||
|
os.unlink(test_db + '.index')
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
setup()
|
setup()
|
||||||
|
|
|
@ -27,13 +27,13 @@ def compare(fn1, fn2):
|
||||||
try:
|
try:
|
||||||
im2 = Image.open(fn2)
|
im2 = Image.open(fn2)
|
||||||
except IOError:
|
except IOError:
|
||||||
errors.append((fn1, None))
|
errors.append((fn1, None, fn2))
|
||||||
return -1
|
return -1
|
||||||
diff = 0
|
diff = 0
|
||||||
pixels = im1.size[0] * im1.size[1]
|
pixels = im1.size[0] * im1.size[1]
|
||||||
delta_pixels = im2.size[0] * im2.size[1] - pixels
|
delta_pixels = im2.size[0] * im2.size[1] - pixels
|
||||||
if delta_pixels != 0:
|
if delta_pixels != 0:
|
||||||
errors.append((fn1, delta_pixels))
|
errors.append((fn1, delta_pixels, fn2))
|
||||||
return delta_pixels
|
return delta_pixels
|
||||||
im1 = im1.getdata()
|
im1 = im1.getdata()
|
||||||
im2 = im2.getdata()
|
im2 = im2.getdata()
|
||||||
|
@ -41,7 +41,7 @@ def compare(fn1, fn2):
|
||||||
if(compare_pixels(im1[i], im2[i])):
|
if(compare_pixels(im1[i], im2[i])):
|
||||||
diff = diff + 1
|
diff = diff + 1
|
||||||
if diff != 0:
|
if diff != 0:
|
||||||
errors.append((fn1, diff))
|
errors.append((fn1, diff, fn2))
|
||||||
passed += 1
|
passed += 1
|
||||||
return diff
|
return diff
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ def summary():
|
||||||
if (error[1] is None):
|
if (error[1] is None):
|
||||||
print "Could not verify %s: No reference image found!" % error[0]
|
print "Could not verify %s: No reference image found!" % error[0]
|
||||||
else:
|
else:
|
||||||
print "%s failed: %d different pixels" % error
|
print "%s failed: %d different pixels \n\t%s (expected)" % error
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
else:
|
else:
|
||||||
print 'All %s tests passed: \x1b[1;32m✓ \x1b[0m' % passed
|
print 'All %s tests passed: \x1b[1;32m✓ \x1b[0m' % passed
|
||||||
|
|
|
@ -57,9 +57,12 @@ def render(filename, width, height, bbox, quiet=False):
|
||||||
m.zoom_to_box(bbox)
|
m.zoom_to_box(bbox)
|
||||||
else:
|
else:
|
||||||
m.zoom_all()
|
m.zoom_all()
|
||||||
basefn = os.path.join(dirname, "images", '%s-%d' % (filename, width))
|
expected = os.path.join(dirname, "images", '%s-%d-reference.png' % (filename, width))
|
||||||
mapnik.render_to_file(m, basefn+'-agg.png')
|
if not os.path.exists('/tmp/mapnik-visual-images'):
|
||||||
diff = compare(basefn + '-agg.png', basefn + '-reference.png')
|
os.makedirs('/tmp/mapnik-visual-images')
|
||||||
|
actual = os.path.join("/tmp/mapnik-visual-images", '%s-%d-agg.png' % (filename, width))
|
||||||
|
mapnik.render_to_file(m, actual)
|
||||||
|
diff = compare(actual, expected)
|
||||||
if diff > 0:
|
if diff > 0:
|
||||||
print "-"*80
|
print "-"*80
|
||||||
print '\x1b[33mError:\x1b[0m %u different pixels' % diff
|
print '\x1b[33mError:\x1b[0m %u different pixels' % diff
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
# batch format *.{hpp,cpp} files
|
# batch format *.{hpp,cpp} files
|
||||||
|
|
||||||
MAPNIK_DIR=`pwd`
|
MAPNIK_DIR=`pwd`
|
||||||
DIRS="$MAPNIK_DIR/plugins $MAPNIK_DIR/demo/c++ $MAPNIK_DIR/src $MAPNIK_DIR/include $MAPNIK_DIR/bindings $MAPNIK_DIR/utils"
|
DIRS="$MAPNIK_DIR/plugins $MAPNIK_DIR/demo/c++ $MAPNIK_DIR/src $MAPNIK_DIR/include $MAPNIK_DIR/bindings $MAPNIK_DIR/utils $MAPNIK_DIR/tests"
|
||||||
EMACS="emacs"
|
EMACS="emacs"
|
||||||
|
|
||||||
for file in $(find $DIRS -name '*.cpp' -o -name '*.hpp')
|
for file in $(find $DIRS -name '*.cpp' -o -name '*.hpp')
|
||||||
|
|
|
@ -35,8 +35,13 @@ source = Split(
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
headers = ['#plugins/input/postgis'] + env['CPPPATH']
|
program_env['CXXFLAGS'] = copy(env['LIBMAPNIK_CXXFLAGS'])
|
||||||
|
|
||||||
|
if env['HAS_CAIRO']:
|
||||||
|
program_env.PrependUnique(CPPPATH=env['CAIROMM_CPPPATHS'])
|
||||||
|
program_env.Append(CXXFLAGS = '-DHAVE_CAIRO')
|
||||||
|
|
||||||
|
program_env.PrependUnique(CPPPATH=['#plugins/input/postgis'])
|
||||||
|
|
||||||
libraries = []
|
libraries = []
|
||||||
boost_program_options = 'boost_program_options%s' % env['BOOST_APPEND']
|
boost_program_options = 'boost_program_options%s' % env['BOOST_APPEND']
|
||||||
|
@ -49,7 +54,7 @@ if env['SQLITE_LINKFLAGS']:
|
||||||
if env['RUNTIME_LINK'] == 'static':
|
if env['RUNTIME_LINK'] == 'static':
|
||||||
libraries.extend(['ldap','pam','ssl','crypto','krb5'])
|
libraries.extend(['ldap','pam','ssl','crypto','krb5'])
|
||||||
|
|
||||||
pgsql2sqlite = program_env.Program('pgsql2sqlite', source, CPPPATH=headers, LIBS=libraries, LINKFLAGS=linkflags)
|
pgsql2sqlite = program_env.Program('pgsql2sqlite', source, LIBS=libraries, LINKFLAGS=linkflags)
|
||||||
Depends(pgsql2sqlite, env.subst('../../src/%s' % env['MAPNIK_LIB_NAME']))
|
Depends(pgsql2sqlite, env.subst('../../src/%s' % env['MAPNIK_LIB_NAME']))
|
||||||
|
|
||||||
if 'uninstall' not in COMMAND_LINE_TARGETS:
|
if 'uninstall' not in COMMAND_LINE_TARGETS:
|
||||||
|
|
|
@ -33,13 +33,17 @@ source = Split(
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
headers = env['CPPPATH']
|
program_env['CXXFLAGS'] = copy(env['LIBMAPNIK_CXXFLAGS'])
|
||||||
|
|
||||||
|
if env['HAS_CAIRO']:
|
||||||
|
program_env.PrependUnique(CPPPATH=env['CAIROMM_CPPPATHS'])
|
||||||
|
program_env.Append(CXXFLAGS = '-DHAVE_CAIRO')
|
||||||
|
|
||||||
libraries = copy(env['LIBMAPNIK_LIBS'])
|
libraries = copy(env['LIBMAPNIK_LIBS'])
|
||||||
boost_program_options = 'boost_program_options%s' % env['BOOST_APPEND']
|
boost_program_options = 'boost_program_options%s' % env['BOOST_APPEND']
|
||||||
libraries.extend([boost_program_options,'mapnik'])
|
libraries.extend([boost_program_options,'mapnik'])
|
||||||
|
|
||||||
svg2png = program_env.Program('svg2png', source, CPPPATH=headers, LIBS=libraries, LINKFLAGS=env['CUSTOM_LDFLAGS'])
|
svg2png = program_env.Program('svg2png', source, LIBS=libraries, LINKFLAGS=env['CUSTOM_LDFLAGS'])
|
||||||
|
|
||||||
Depends(svg2png, env.subst('../../src/%s' % env['MAPNIK_LIB_NAME']))
|
Depends(svg2png, env.subst('../../src/%s' % env['MAPNIK_LIB_NAME']))
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,10 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
//#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include <mapnik/version.hpp>
|
||||||
|
#include <mapnik/debug.hpp>
|
||||||
#include <mapnik/marker.hpp>
|
#include <mapnik/marker.hpp>
|
||||||
#include <mapnik/marker_cache.hpp>
|
#include <mapnik/marker_cache.hpp>
|
||||||
#include <mapnik/image_util.hpp>
|
#include <mapnik/image_util.hpp>
|
||||||
|
@ -44,13 +46,19 @@
|
||||||
#include "agg_pixfmt_rgba.h"
|
#include "agg_pixfmt_rgba.h"
|
||||||
#include "agg_scanline_u.h"
|
#include "agg_scanline_u.h"
|
||||||
|
|
||||||
|
#include <libxml/parser.h> // for xmlInitParser(), xmlCleanupParser()
|
||||||
|
|
||||||
|
|
||||||
int main (int argc,char** argv)
|
int main (int argc,char** argv)
|
||||||
{
|
{
|
||||||
namespace po = boost::program_options;
|
namespace po = boost::program_options;
|
||||||
|
|
||||||
bool verbose=false;
|
bool verbose = false;
|
||||||
|
bool auto_open = false;
|
||||||
|
bool error = false;
|
||||||
std::vector<std::string> svg_files;
|
std::vector<std::string> svg_files;
|
||||||
|
mapnik::logger logger;
|
||||||
|
logger.set_severity(mapnik::logger::error);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -59,6 +67,7 @@ int main (int argc,char** argv)
|
||||||
("help,h", "produce usage message")
|
("help,h", "produce usage message")
|
||||||
("version,V","print version string")
|
("version,V","print version string")
|
||||||
("verbose,v","verbose output")
|
("verbose,v","verbose output")
|
||||||
|
("open","automatically open the file after rendering (os x only)")
|
||||||
("svg",po::value<std::vector<std::string> >(),"svg file to read")
|
("svg",po::value<std::vector<std::string> >(),"svg file to read")
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -70,7 +79,7 @@ int main (int argc,char** argv)
|
||||||
|
|
||||||
if (vm.count("version"))
|
if (vm.count("version"))
|
||||||
{
|
{
|
||||||
std::clog<<"version 0.3.0" << std::endl;
|
std::clog <<"version " << MAPNIK_VERSION_STRING << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,11 +88,17 @@ int main (int argc,char** argv)
|
||||||
std::clog << desc << std::endl;
|
std::clog << desc << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vm.count("verbose"))
|
if (vm.count("verbose"))
|
||||||
{
|
{
|
||||||
verbose = true;
|
verbose = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vm.count("open"))
|
||||||
|
{
|
||||||
|
auto_open = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (vm.count("svg"))
|
if (vm.count("svg"))
|
||||||
{
|
{
|
||||||
svg_files=vm["svg"].as< std::vector<std::string> >();
|
svg_files=vm["svg"].as< std::vector<std::string> >();
|
||||||
|
@ -100,66 +115,97 @@ int main (int argc,char** argv)
|
||||||
std::clog << "no svg files to render" << std::endl;
|
std::clog << "no svg files to render" << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xmlInitParser();
|
||||||
|
|
||||||
while (itr != svg_files.end())
|
while (itr != svg_files.end())
|
||||||
{
|
{
|
||||||
|
|
||||||
std::string svg_name (*itr++);
|
std::string svg_name (*itr++);
|
||||||
|
if (verbose)
|
||||||
boost::optional<mapnik::marker_ptr> marker_ptr = mapnik::marker_cache::instance()->find(svg_name, false);
|
{
|
||||||
if (marker_ptr) {
|
std::clog << "found: " << svg_name << "\n";
|
||||||
|
|
||||||
mapnik::marker marker = **marker_ptr;
|
|
||||||
if (marker.is_vector()) {
|
|
||||||
|
|
||||||
typedef agg::pixfmt_rgba32_plain pixfmt;
|
|
||||||
typedef agg::renderer_base<pixfmt> renderer_base;
|
|
||||||
typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_solid;
|
|
||||||
agg::rasterizer_scanline_aa<> ras_ptr;
|
|
||||||
agg::scanline_u8 sl;
|
|
||||||
|
|
||||||
double opacity = 1;
|
|
||||||
double scale_factor_ = .95;
|
|
||||||
int w = marker.width();
|
|
||||||
int h = marker.height();
|
|
||||||
mapnik::image_32 im(w,h);
|
|
||||||
agg::rendering_buffer buf(im.raw_data(), w, h, w * 4);
|
|
||||||
pixfmt pixf(buf);
|
|
||||||
renderer_base renb(pixf);
|
|
||||||
|
|
||||||
mapnik::box2d<double> const& bbox = (*marker.get_vector_data())->bounding_box();
|
|
||||||
mapnik::coord<double,2> c = bbox.center();
|
|
||||||
// center the svg marker on '0,0'
|
|
||||||
agg::trans_affine mtx = agg::trans_affine_translation(-c.x,-c.y);
|
|
||||||
// apply symbol transformation to get to map space
|
|
||||||
mtx *= agg::trans_affine_scaling(scale_factor_);
|
|
||||||
// render the marker at the center of the marker box
|
|
||||||
mtx.translate(0.5 * w, 0.5 * h);
|
|
||||||
|
|
||||||
mapnik::svg::vertex_stl_adapter<mapnik::svg::svg_path_storage> stl_storage((*marker.get_vector_data())->source());
|
|
||||||
mapnik::svg::svg_path_adapter svg_path(stl_storage);
|
|
||||||
mapnik::svg::svg_renderer<mapnik::svg::svg_path_adapter,
|
|
||||||
agg::pod_bvector<mapnik::svg::path_attributes>,
|
|
||||||
renderer_solid,
|
|
||||||
agg::pixfmt_rgba32_plain > svg_renderer_this(svg_path,
|
|
||||||
(*marker.get_vector_data())->attributes());
|
|
||||||
|
|
||||||
svg_renderer_this.render(ras_ptr, sl, renb, mtx, opacity, bbox);
|
|
||||||
|
|
||||||
boost::algorithm::ireplace_last(svg_name,".svg",".png");
|
|
||||||
mapnik::save_to_file<mapnik::image_data_32>(im.data(),svg_name,"png");
|
|
||||||
std::ostringstream s;
|
|
||||||
s << "open " << svg_name;
|
|
||||||
return system(s.str().c_str());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boost::optional<mapnik::marker_ptr> marker_ptr =
|
||||||
|
mapnik::marker_cache::instance()->find(svg_name, false);
|
||||||
|
if (!marker_ptr)
|
||||||
|
{
|
||||||
|
std::clog << "svg2png error: could not open: '" << svg_name << "'\n";
|
||||||
|
error = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
mapnik::marker marker = **marker_ptr;
|
||||||
|
if (!marker.is_vector())
|
||||||
|
{
|
||||||
|
std::clog << "svg2png error: '" << svg_name << "' is not a valid vector!\n";
|
||||||
|
error = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef agg::pixfmt_rgba32_plain pixfmt;
|
||||||
|
typedef agg::renderer_base<pixfmt> renderer_base;
|
||||||
|
typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_solid;
|
||||||
|
agg::rasterizer_scanline_aa<> ras_ptr;
|
||||||
|
agg::scanline_u8 sl;
|
||||||
|
|
||||||
|
double opacity = 1;
|
||||||
|
double scale_factor_ = .95;
|
||||||
|
int w = marker.width();
|
||||||
|
int h = marker.height();
|
||||||
|
if (verbose)
|
||||||
|
{
|
||||||
|
std::clog << "found width of '" << w << "' and height of '" << h << "'\n";
|
||||||
|
}
|
||||||
|
mapnik::image_32 im(w,h);
|
||||||
|
agg::rendering_buffer buf(im.raw_data(), w, h, w * 4);
|
||||||
|
pixfmt pixf(buf);
|
||||||
|
renderer_base renb(pixf);
|
||||||
|
|
||||||
|
mapnik::box2d<double> const& bbox = (*marker.get_vector_data())->bounding_box();
|
||||||
|
mapnik::coord<double,2> c = bbox.center();
|
||||||
|
// center the svg marker on '0,0'
|
||||||
|
agg::trans_affine mtx = agg::trans_affine_translation(-c.x,-c.y);
|
||||||
|
// apply symbol transformation to get to map space
|
||||||
|
mtx *= agg::trans_affine_scaling(scale_factor_);
|
||||||
|
// render the marker at the center of the marker box
|
||||||
|
mtx.translate(0.5 * w, 0.5 * h);
|
||||||
|
|
||||||
|
mapnik::svg::vertex_stl_adapter<mapnik::svg::svg_path_storage> stl_storage((*marker.get_vector_data())->source());
|
||||||
|
mapnik::svg::svg_path_adapter svg_path(stl_storage);
|
||||||
|
mapnik::svg::svg_renderer<mapnik::svg::svg_path_adapter,
|
||||||
|
agg::pod_bvector<mapnik::svg::path_attributes>,
|
||||||
|
renderer_solid,
|
||||||
|
agg::pixfmt_rgba32_plain > svg_renderer_this(svg_path,
|
||||||
|
(*marker.get_vector_data())->attributes());
|
||||||
|
|
||||||
|
svg_renderer_this.render(ras_ptr, sl, renb, mtx, opacity, bbox);
|
||||||
|
|
||||||
|
boost::algorithm::ireplace_last(svg_name,".svg",".png");
|
||||||
|
mapnik::save_to_file<mapnik::image_data_32>(im.data(),svg_name,"png");
|
||||||
|
#ifdef DARWIN
|
||||||
|
if (auto_open)
|
||||||
|
{
|
||||||
|
std::ostringstream s;
|
||||||
|
s << "open " << svg_name;
|
||||||
|
system(s.str().c_str());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
std::clog << "rendered to: " << svg_name << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
std::clog << "Exception of unknown type!" << std::endl;
|
std::clog << "Exception of unknown type!" << std::endl;
|
||||||
|
xmlCleanupParser();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// only call this once, on exit
|
||||||
|
// to make sure valgrind output is clean
|
||||||
|
// http://xmlsoft.org/xmlmem.html
|
||||||
|
xmlCleanupParser();
|
||||||
|
if (error)
|
||||||
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue