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
|
||||
|
||||
- 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)
|
||||
|
||||
- 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
|
||||
|
||||
test:
|
||||
@echo "*** Running visual tests…"
|
||||
@echo "*** Running visual tests..."
|
||||
@python tests/visual_tests/test.py -q
|
||||
@echo "*** Running C++ tests..."
|
||||
@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'},
|
||||
|
||||
# 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...
|
||||
'shape': {'default':True,'path':None,'inc':None,'lib':None,'lang':'C++'},
|
||||
|
@ -242,7 +242,6 @@ else:
|
|||
LIBDIR_SCHEMA='lib'
|
||||
|
||||
|
||||
|
||||
def pretty_dep(dep):
|
||||
pretty = pretty_dep_names.get(dep)
|
||||
if pretty:
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <boost/python.hpp>
|
||||
#include <mapnik/debug.hpp>
|
||||
#include <mapnik/utils.hpp>
|
||||
#include "mapnik_enumeration.hpp"
|
||||
|
||||
void export_logger()
|
||||
{
|
||||
|
@ -37,6 +38,15 @@ void export_logger()
|
|||
.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> >,
|
||||
boost::noncopyable>("logger",no_init)
|
||||
.def_readonly("Info", logger::info)
|
||||
|
|
|
@ -124,5 +124,15 @@ void export_markers_symbolizer()
|
|||
&markers_symbolizer::get_height,
|
||||
&markers_symbolizer::set_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",
|
||||
&feature_type_style::get_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 {
|
||||
|
||||
/*
|
||||
Global logger class that holds the configuration of severity, format
|
||||
and file/console redirection.
|
||||
*/
|
||||
class MAPNIK_DECL logger :
|
||||
public singleton<logger,CreateStatic>,
|
||||
private boost::noncopyable
|
||||
|
@ -153,6 +157,9 @@ namespace mapnik {
|
|||
|
||||
namespace detail {
|
||||
|
||||
/*
|
||||
Default sink, it regulates access to clog
|
||||
*/
|
||||
template<class Ch, class Tr, class A>
|
||||
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,
|
||||
logger::severity_type Severity,
|
||||
class Ch = char,
|
||||
|
@ -223,14 +236,67 @@ namespace mapnik {
|
|||
#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::debug> base_log_debug;
|
||||
typedef base_log<clog_sink, logger::warn> base_log_warn;
|
||||
typedef base_log<clog_sink, logger::error> base_log_error;
|
||||
typedef base_log<clog_sink, logger::fatal> base_log_fatal;
|
||||
typedef base_log_always<clog_sink, logger::error> base_log_error;
|
||||
typedef base_log_always<clog_sink, logger::fatal> base_log_fatal;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
// real interfaces
|
||||
class MAPNIK_DECL info : public detail::base_log_info {
|
||||
public:
|
||||
|
@ -262,6 +328,7 @@ namespace mapnik {
|
|||
fatal(const char* object_name) : detail::base_log_fatal(object_name) {}
|
||||
};
|
||||
|
||||
|
||||
// logging helpers
|
||||
#define MAPNIK_LOG_INFO(s) mapnik::info(#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;
|
||||
#if BOOST_VERSION > 104200
|
||||
using qi::no_skip;
|
||||
#else
|
||||
using qi::lexeme;
|
||||
#endif
|
||||
using qi::lexeme;
|
||||
using qi::_val;
|
||||
using qi::lit;
|
||||
using qi::int_;
|
||||
|
|
|
@ -39,7 +39,8 @@ class layer_descriptor
|
|||
public:
|
||||
layer_descriptor(std::string const& name, std::string const& encoding)
|
||||
: name_(name),
|
||||
encoding_(encoding) {}
|
||||
encoding_(encoding),
|
||||
desc_ar_() {}
|
||||
|
||||
layer_descriptor(layer_descriptor const& other)
|
||||
: name_(other.name_),
|
||||
|
|
|
@ -266,7 +266,8 @@ class MAPNIK_DECL face_manager : private boost::noncopyable
|
|||
public:
|
||||
face_manager(T & engine)
|
||||
: engine_(engine),
|
||||
stroker_(engine_.create_stroker()) {}
|
||||
stroker_(engine_.create_stroker()),
|
||||
face_ptr_cache_() {}
|
||||
|
||||
face_ptr get_face(std::string const& name)
|
||||
{
|
||||
|
@ -303,16 +304,19 @@ public:
|
|||
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)
|
||||
{
|
||||
if (face_ptr face = get_face(*name))
|
||||
face_ptr face = get_face(*name);
|
||||
if (face)
|
||||
{
|
||||
face_set->add(face);
|
||||
}
|
||||
#ifdef MAPNIK_LOG
|
||||
else
|
||||
{
|
||||
MAPNIK_LOG_ERROR(font_engine_freetype)
|
||||
MAPNIK_LOG_DEBUG(font_engine_freetype)
|
||||
<< "Failed to find face '" << *name
|
||||
<< "' in font set '" << fset.get_name() << "'\n";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return face_set;
|
||||
}
|
||||
|
@ -335,9 +339,9 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
face_ptr_cache_type face_ptr_cache_;
|
||||
font_engine_type & engine_;
|
||||
stroker_ptr stroker_;
|
||||
face_ptr_cache_type face_ptr_cache_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
|
|
@ -63,13 +63,13 @@ private:
|
|||
unsigned width_;
|
||||
unsigned height_;
|
||||
std::string key_;
|
||||
feature_key_type f_keys_;
|
||||
feature_type features_;
|
||||
data_type data_;
|
||||
std::set<std::string> names_;
|
||||
unsigned int resolution_;
|
||||
std::string id_name_;
|
||||
bool painted_;
|
||||
std::set<std::string> names_;
|
||||
feature_key_type f_keys_;
|
||||
feature_type features_;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -80,7 +80,10 @@ public:
|
|||
data_(width,height),
|
||||
resolution_(resolution),
|
||||
id_name_("__id__"),
|
||||
painted_(false)
|
||||
painted_(false),
|
||||
names_(),
|
||||
f_keys_(),
|
||||
features_()
|
||||
{
|
||||
// this only works if each datasource's
|
||||
// feature count starts at 1
|
||||
|
@ -94,7 +97,10 @@ public:
|
|||
data_(rhs.data_),
|
||||
resolution_(rhs.resolution_),
|
||||
id_name_("__id__"),
|
||||
painted_(rhs.painted_)
|
||||
painted_(rhs.painted_),
|
||||
names_(rhs.names_),
|
||||
f_keys_(rhs.f_keys_),
|
||||
features_(rhs.features_)
|
||||
{
|
||||
f_keys_[0] = "";
|
||||
}
|
||||
|
|
|
@ -23,6 +23,12 @@
|
|||
#ifndef MAPNIK_IMAGE_COMPOSITING_HPP
|
||||
#define MAPNIK_IMAGE_COMPOSITING_HPP
|
||||
|
||||
#include <mapnik/config.hpp>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <mapnik/image_data.hpp>
|
||||
#endif
|
||||
|
||||
// agg
|
||||
|
||||
namespace mapnik
|
||||
|
@ -64,7 +70,11 @@ enum composite_mode_e
|
|||
};
|
||||
|
||||
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
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#ifndef MAPNIK_GEOJSON_GENERATOR_HPP
|
||||
#define MAPNIK_GEOJSON_GENERATOR_HPP
|
||||
|
||||
#include <mapnik/config.hpp>
|
||||
#include <mapnik/feature.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
|
@ -35,7 +36,7 @@ namespace mapnik { namespace json {
|
|||
template <typename OutputIterator> struct feature_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;
|
||||
public:
|
||||
|
@ -46,7 +47,7 @@ private:
|
|||
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;
|
||||
public:
|
||||
|
@ -59,7 +60,7 @@ private:
|
|||
|
||||
#else
|
||||
|
||||
class feature_generator : private boost::noncopyable
|
||||
class MAPNIK_DECL feature_generator : private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
feature_generator() {}
|
||||
|
@ -67,7 +68,7 @@ public:
|
|||
bool generate(std::string & geojson, mapnik::Feature const& f);
|
||||
};
|
||||
|
||||
class geometry_generator : private boost::noncopyable
|
||||
class MAPNIK_DECL geometry_generator : private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
geometry_generator() {}
|
||||
|
|
|
@ -140,7 +140,7 @@ class label_collision_detector4 : boost::noncopyable
|
|||
public:
|
||||
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) {}
|
||||
|
||||
box2d<double> box;
|
||||
|
|
|
@ -50,13 +50,18 @@ public:
|
|||
typedef std::map<std::string, UnicodeString> property_map;
|
||||
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& operator[](std::string const& key) {return m_[key];}
|
||||
|
||||
std::map<std::string, UnicodeString>::const_iterator find(std::string const& key) const
|
||||
{
|
||||
return m_.find(key);
|
||||
}
|
||||
|
||||
std::map<std::string, UnicodeString>::const_iterator end() const
|
||||
{
|
||||
return m_.end();
|
||||
|
@ -66,6 +71,7 @@ public:
|
|||
{
|
||||
return (*this)[key];
|
||||
}
|
||||
|
||||
private:
|
||||
property_map m_;
|
||||
UnicodeString not_found_;
|
||||
|
|
|
@ -80,17 +80,22 @@ struct rgba
|
|||
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)
|
||||
: 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) {
|
||||
r = U2RED(c);
|
||||
g = U2GREEN(c);
|
||||
b = U2BLUE(c);
|
||||
a = U2ALPHA(c);
|
||||
}
|
||||
inline rgba(unsigned const& c)
|
||||
: r(U2RED(c)),
|
||||
g(U2GREEN(c)),
|
||||
b(U2BLUE(c)),
|
||||
a(U2ALPHA(c)) {}
|
||||
|
||||
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 bool parse_path_from_string(path_expression_ptr const& path,
|
||||
std::string const & str,
|
||||
path_expression_grammar<std::string::const_iterator> const& g);
|
||||
std::string const & str,
|
||||
path_expression_grammar<std::string::const_iterator> const& g);
|
||||
|
||||
|
||||
template <typename T>
|
||||
|
|
|
@ -86,23 +86,20 @@ class quad_tree : boost::noncopyable
|
|||
typedef typename node::cont_t cont_t;
|
||||
typedef typename cont_t::iterator node_data_iterator;
|
||||
|
||||
nodes_t nodes_;
|
||||
node * root_;
|
||||
const unsigned int max_depth_;
|
||||
const double ratio_;
|
||||
public:
|
||||
typedef typename nodes_t::iterator iterator;
|
||||
typedef typename nodes_t::const_iterator const_iterator;
|
||||
typedef typename boost::ptr_vector<T,boost::view_clone_allocator> result_t;
|
||||
typedef typename result_t::iterator query_iterator;
|
||||
|
||||
result_t query_result_;
|
||||
|
||||
explicit quad_tree(box2d<double> const& ext,
|
||||
unsigned int max_depth = 8,
|
||||
double ratio = 0.55)
|
||||
: max_depth_(max_depth),
|
||||
ratio_(ratio)
|
||||
ratio_(ratio),
|
||||
query_result_(),
|
||||
nodes_()
|
||||
{
|
||||
nodes_.push_back(new node(ext));
|
||||
root_ = &nodes_[0];
|
||||
|
@ -219,6 +216,13 @@ private:
|
|||
ext[2]=box2d<double>(lox,hiy - height*ratio_,lox + width * ratio_,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:
|
||||
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,
|
||||
resolution_type const& resolution,
|
||||
|
@ -57,7 +49,8 @@ public:
|
|||
resolution_(resolution),
|
||||
scale_denominator_(scale_denominator),
|
||||
filter_factor_(1.0),
|
||||
unbuffered_bbox_(unbuffered_bbox)
|
||||
unbuffered_bbox_(unbuffered_bbox),
|
||||
names_()
|
||||
{}
|
||||
|
||||
query(box2d<double> const& bbox,
|
||||
|
@ -67,7 +60,8 @@ public:
|
|||
resolution_(resolution),
|
||||
scale_denominator_(scale_denominator),
|
||||
filter_factor_(1.0),
|
||||
unbuffered_bbox_(bbox)
|
||||
unbuffered_bbox_(bbox),
|
||||
names_()
|
||||
{}
|
||||
|
||||
query(box2d<double> const& bbox)
|
||||
|
@ -75,7 +69,8 @@ public:
|
|||
resolution_(resolution_type(1.0,1.0)),
|
||||
scale_denominator_(1.0),
|
||||
filter_factor_(1.0),
|
||||
unbuffered_bbox_(bbox)
|
||||
unbuffered_bbox_(bbox),
|
||||
names_()
|
||||
{}
|
||||
|
||||
query(query const& other)
|
||||
|
@ -94,8 +89,8 @@ public:
|
|||
resolution_=other.resolution_;
|
||||
scale_denominator_=other.scale_denominator_;
|
||||
filter_factor_=other.filter_factor_;
|
||||
names_=other.names_;
|
||||
unbuffered_bbox_=other.unbuffered_bbox_;
|
||||
names_=other.names_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -119,12 +114,12 @@ public:
|
|||
return unbuffered_bbox_;
|
||||
}
|
||||
|
||||
void set_unbuffered_bbox(const box2d<double>& bbox)
|
||||
void set_unbuffered_bbox(box2d<double> const& bbox)
|
||||
{
|
||||
unbuffered_bbox_ = bbox;
|
||||
}
|
||||
|
||||
void set_bbox(const box2d<double>& bbox)
|
||||
void set_bbox(box2d<double> const& bbox)
|
||||
{
|
||||
bbox_ = bbox;
|
||||
}
|
||||
|
@ -148,6 +143,14 @@ public:
|
|||
{
|
||||
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();
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -384,7 +385,7 @@ public:
|
|||
{
|
||||
ras.reset();
|
||||
|
||||
if(fabs(curved_trans_contour.width()) < 0.0001)
|
||||
if(fabs(curved_trans_contour.width()) <= 1)
|
||||
{
|
||||
ras.add_path(curved_trans, attr.index);
|
||||
}
|
||||
|
|
|
@ -157,6 +157,6 @@ private:
|
|||
std::string base_message_;
|
||||
};
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif // MAPNIK_TIMER_HPP
|
||||
|
|
|
@ -29,16 +29,73 @@
|
|||
// stl
|
||||
#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 {
|
||||
|
||||
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(const char * 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 string2float(std::string const& value, float & result);
|
||||
MAPNIK_DECL bool string2float(const char * value, float & result);
|
||||
MAPNIK_DECL bool string2float(std::string const& 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;
|
||||
|
||||
vertex_iterator()
|
||||
: v_(SEG_END,0,0)
|
||||
: v_(SEG_END,0,0),
|
||||
vertices_(),
|
||||
pos_(0)
|
||||
{}
|
||||
|
||||
explicit vertex_iterator(container_type const& vertices)
|
||||
|
@ -74,8 +76,8 @@ namespace mapnik { namespace util {
|
|||
return v_;
|
||||
}
|
||||
|
||||
container_type const *vertices_;
|
||||
value_type v_;
|
||||
container_type const *vertices_;
|
||||
unsigned pos_;
|
||||
};
|
||||
|
||||
|
|
|
@ -36,8 +36,6 @@
|
|||
// stl
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <cmath>
|
||||
|
||||
// uci
|
||||
|
@ -338,20 +336,34 @@ struct add : public boost::static_visitor<V>
|
|||
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>
|
||||
value_type operator() (UnicodeString const& lhs, R const& rhs) const
|
||||
{
|
||||
std::basic_ostringstream<char> out;
|
||||
out << rhs;
|
||||
return lhs + UnicodeString(out.str().c_str());
|
||||
std::string val;
|
||||
if (util::to_string(val,rhs))
|
||||
return lhs + UnicodeString(val.c_str());
|
||||
return lhs;
|
||||
}
|
||||
|
||||
template <typename L>
|
||||
value_type operator() (L const& lhs , UnicodeString const& rhs) const
|
||||
{
|
||||
std::basic_ostringstream<char> out;
|
||||
out << lhs;
|
||||
return UnicodeString(out.str().c_str()) + rhs;
|
||||
std::string val;
|
||||
if (util::to_string(val,lhs))
|
||||
return UnicodeString(val.c_str()) + rhs;
|
||||
return rhs;
|
||||
}
|
||||
|
||||
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>
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
std::string operator() (T val) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << val;
|
||||
return ss.str();
|
||||
std::string str;
|
||||
util::to_string(str, val);
|
||||
return str;
|
||||
}
|
||||
|
||||
// specializations
|
||||
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::stringstream ss;
|
||||
ss << std::setprecision(16) << val;
|
||||
return ss.str();
|
||||
std::string str;
|
||||
util::to_string(str, val); // TODO set precision(16)
|
||||
return str;
|
||||
}
|
||||
|
||||
std::string operator() (value_null const& val) const
|
||||
|
@ -576,9 +588,9 @@ struct to_unicode : public boost::static_visitor<UnicodeString>
|
|||
template <typename T>
|
||||
UnicodeString operator() (T val) const
|
||||
{
|
||||
std::basic_ostringstream<char> out;
|
||||
out << val;
|
||||
return UnicodeString(out.str().c_str());
|
||||
std::string str;
|
||||
util::to_string(str,val);
|
||||
return UnicodeString(str.c_str());
|
||||
}
|
||||
|
||||
// specializations
|
||||
|
@ -589,9 +601,9 @@ struct to_unicode : public boost::static_visitor<UnicodeString>
|
|||
|
||||
UnicodeString operator() (double val) const
|
||||
{
|
||||
std::basic_ostringstream<char> out;
|
||||
out << std::setprecision(16) << val;
|
||||
return UnicodeString(out.str().c_str());
|
||||
std::string str;
|
||||
util::to_string(str,val);
|
||||
return UnicodeString(str.c_str());
|
||||
}
|
||||
|
||||
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::stringstream ss;
|
||||
ss << std::setprecision(16) << val;
|
||||
return ss.str();
|
||||
std::string output;
|
||||
util::to_string(output,val); // TODO precision(16)
|
||||
return output;
|
||||
}
|
||||
|
||||
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 ret(0);
|
||||
mapnik::util::string2double(val,ret);
|
||||
return ret;
|
||||
double result;
|
||||
if (util::string2double(val,result))
|
||||
return result;
|
||||
return 0;
|
||||
}
|
||||
|
||||
double operator() (UnicodeString const& val) const
|
||||
{
|
||||
std::string utf8;
|
||||
to_utf8(val,utf8);
|
||||
double ret(0);
|
||||
mapnik::util::string2double(utf8,ret);
|
||||
return ret;
|
||||
return operator()(utf8);
|
||||
}
|
||||
|
||||
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 ret(0);
|
||||
mapnik::util::string2int(val,ret);
|
||||
return ret;
|
||||
int result;
|
||||
if (util::string2int(val,result))
|
||||
return result;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int operator() (UnicodeString const& val) const
|
||||
{
|
||||
std::string utf8;
|
||||
to_utf8(val,utf8);
|
||||
int ret(0);
|
||||
mapnik::util::string2int(utf8,ret);
|
||||
return ret;
|
||||
return operator()(utf8);
|
||||
}
|
||||
|
||||
int operator() (value_null const& val) const
|
||||
|
|
|
@ -31,12 +31,14 @@ namespace mapnik {
|
|||
class value_error : public std::exception
|
||||
{
|
||||
public:
|
||||
value_error() {}
|
||||
value_error() :
|
||||
what_() {}
|
||||
|
||||
value_error( std::string const& what ) :
|
||||
what_( what )
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~value_error() 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())
|
||||
{
|
||||
OGRLayer* layer = layer_.layer();
|
||||
// only new either reset of setNext
|
||||
//layer->ResetReading();
|
||||
layer->SetNextByIndex(0);
|
||||
ogr_feature_ptr feat(layer->GetNextFeature());
|
||||
if ((*feat) != NULL)
|
||||
{
|
||||
|
|
|
@ -67,6 +67,7 @@ postgis_datasource::postgis_datasource(parameters const& params, bool bind)
|
|||
type_(datasource::Vector),
|
||||
srid_(*params_.get<int>("srid", 0)),
|
||||
extent_initialized_(false),
|
||||
simplify_geometries_(false),
|
||||
desc_(*params_.get<std::string>("type"), "utf-8"),
|
||||
creator_(params.get<std::string>("host"),
|
||||
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")),
|
||||
bbox_token_("!bbox!"),
|
||||
scale_denom_token_("!scale_denominator!"),
|
||||
pixel_width_token_("!pixel_width!"),
|
||||
pixel_height_token_("!pixel_height!"),
|
||||
persist_connection_(*params_.get<mapnik::boolean>("persist_connection", true)),
|
||||
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)
|
||||
|
@ -114,6 +117,9 @@ void postgis_datasource::bind() const
|
|||
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> simplify_opt = params_.get<mapnik::boolean>("simplify_geometries", false);
|
||||
simplify_geometries_ = simplify_opt && *simplify_opt;
|
||||
|
||||
ConnectionManager* mgr = ConnectionManager::instance();
|
||||
mgr->registerPool(creator_, *initial_size, *max_size);
|
||||
|
||||
|
@ -233,23 +239,23 @@ void postgis_datasource::bind() const
|
|||
|
||||
std::ostringstream s;
|
||||
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 "
|
||||
"WHERE a.attnum > 0 AND a.attrelid = c.oid "
|
||||
"AND a.atttypid = t.oid AND c.relnamespace = n.oid "
|
||||
"AND c.oid = i.indrelid AND i.indisprimary = 't' "
|
||||
"AND t.typname !~ '^geom' AND c.relname ="
|
||||
"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 "
|
||||
"AND a.atttypid = t.oid AND c.relnamespace = n.oid "
|
||||
"AND c.oid = i.indrelid AND i.indisprimary = 't' "
|
||||
"AND t.typname !~ '^geom' AND c.relname ="
|
||||
<< " '" << 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 "
|
||||
"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[9]=a.attnum) ";
|
||||
if (! schema_.empty())
|
||||
{
|
||||
s << "AND n.nspname='"
|
||||
<< mapnik::sql_utils::unquote_double(schema_)
|
||||
<< "' ";
|
||||
}
|
||||
"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[9]=a.attnum) ";
|
||||
if (! schema_.empty())
|
||||
{
|
||||
s << "AND n.nspname='"
|
||||
<< mapnik::sql_utils::unquote_double(schema_)
|
||||
<< "' ";
|
||||
}
|
||||
s << "ORDER BY a.attnum";
|
||||
|
||||
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())
|
||||
{
|
||||
throw mapnik::datasource_exception(std::string("PostGIS Plugin: Error: primary key required")
|
||||
+ " but could not be detected for table '" +
|
||||
geometry_table_ + "', please supply 'key_field' option to specify field to use for primary key");
|
||||
+ " but could not be detected for table '" +
|
||||
geometry_table_ + "', please supply 'key_field' option to specify field to use for primary key");
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 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());
|
||||
}
|
||||
|
||||
if (boost::algorithm::icontains(sql, pixel_width_token_))
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << pixel_width;
|
||||
boost::algorithm::replace_all(populated_sql, pixel_width_token_, ss.str());
|
||||
}
|
||||
|
||||
if (boost::algorithm::icontains(sql, pixel_height_token_))
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << pixel_height;
|
||||
boost::algorithm::replace_all(populated_sql, pixel_height_token_, ss.str());
|
||||
}
|
||||
|
||||
if (boost::algorithm::icontains(populated_sql, bbox_token_))
|
||||
{
|
||||
boost::algorithm::replace_all(populated_sql, bbox_token_, box);
|
||||
|
@ -607,7 +641,24 @@ featureset_ptr postgis_datasource::features(const query& q) const
|
|||
}
|
||||
|
||||
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>();
|
||||
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;
|
||||
|
||||
|
@ -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);
|
||||
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;
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ public:
|
|||
|
||||
private:
|
||||
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;
|
||||
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;
|
||||
|
@ -85,10 +85,13 @@ private:
|
|||
mutable int srid_;
|
||||
mutable bool extent_initialized_;
|
||||
mutable mapnik::box2d<double> extent_;
|
||||
mutable bool simplify_geometries_;
|
||||
mutable layer_descriptor desc_;
|
||||
ConnectionCreator<Connection> creator_;
|
||||
const std::string bbox_token_;
|
||||
const std::string scale_denom_token_;
|
||||
const std::string pixel_width_token_;
|
||||
const std::string pixel_height_token_;
|
||||
bool persist_connection_;
|
||||
bool extent_from_subquery_;
|
||||
// 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);
|
||||
setup_attributes(ctx_, attribute_names, shape_name, shape_,attr_ids_);
|
||||
|
||||
|
||||
boost::shared_ptr<shape_file> index = shape_.index();
|
||||
if (index)
|
||||
{
|
||||
|
|
77
src/build.py
77
src/build.py
|
@ -80,13 +80,8 @@ else:
|
|||
else:
|
||||
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':
|
||||
mapnik_libname = env.subst(env['MAPNIK_LIB_NAME'])
|
||||
if env['FULL_LIB_PATH']:
|
||||
lib_path = '%s/%s' % (env['MAPNIK_LIB_BASE'],mapnik_libname)
|
||||
else:
|
||||
|
@ -94,13 +89,15 @@ if env['PLATFORM'] == 'Darwin':
|
|||
mapnik_lib_link_flag += ' -Wl,-install_name,%s' % lib_path
|
||||
_d = {'version':env['MAPNIK_VERSION_STRING'].replace('-pre','')}
|
||||
mapnik_lib_link_flag += ' -current_version %(version)s -compatibility_version %(version)s' % _d
|
||||
elif env['PLATFORM'] == 'SunOS':
|
||||
if env['CXX'].startswith('CC'):
|
||||
mapnik_lib_link_flag += ' -R. -h %s' % mapnik_libname
|
||||
else:
|
||||
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
|
||||
else: # unix, non-macos
|
||||
mapnik_libname = env.subst(env['MAPNIK_LIB_NAME']) + (".%d.%d" % (int(ABI_VERSION[0]),int(ABI_VERSION[1])))
|
||||
if env['PLATFORM'] == 'SunOS':
|
||||
if env['CXX'].startswith('CC'):
|
||||
mapnik_lib_link_flag += ' -R. -h %s' % mapnik_libname
|
||||
else:
|
||||
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(
|
||||
"""
|
||||
|
@ -324,16 +321,22 @@ if env['CUSTOM_LDFLAGS']:
|
|||
else:
|
||||
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
|
||||
env['LIBMAPNIK_LIBS'] = copy(lib_env['LIBS'])
|
||||
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
|
||||
def symlink(env, target, source):
|
||||
trgt = str(target[0])
|
||||
|
@ -345,38 +348,34 @@ if env['PLATFORM'] != 'Darwin':
|
|||
|
||||
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)
|
||||
|
||||
if 'uninstall' not in COMMAND_LINE_TARGETS:
|
||||
result = env.InstallAs(target=target, source=mapnik)
|
||||
env.Alias(target='install', source=result)
|
||||
if result:
|
||||
env.AddPostAction(result, ldconfig)
|
||||
if env['LINKING'] == 'static':
|
||||
mapnik = lib_env.StaticLibrary('mapnik', source, LINKFLAGS=linkflags)
|
||||
else:
|
||||
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
|
||||
target1 = os.path.join(env['MAPNIK_LIB_BASE_DEST'], "%s.%d.%d" % (os.path.basename(str(mapnik[0])),int(major), int(minor)))
|
||||
target2 = os.path.join(env['MAPNIK_LIB_BASE_DEST'], os.path.basename(str(mapnik[0])))
|
||||
target1 = os.path.join(env['MAPNIK_LIB_BASE_DEST'], "%s.%d.%d" % \
|
||||
(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 'install' in COMMAND_LINE_TARGETS:
|
||||
link1 = env.Command(target1, target, symlink)
|
||||
env.Alias(target='install', source=link1)
|
||||
link2 = env.Command(target2, target1, symlink)
|
||||
env.Alias(target='install', source=link2)
|
||||
link1 = env.Command(target1, target, symlink)
|
||||
env.Alias(target='install', source=link1)
|
||||
link2 = env.Command(target2, target1, symlink)
|
||||
env.Alias(target='install', source=link2)
|
||||
# delete in reverse order..
|
||||
env['create_uninstall_target'](env, target2)
|
||||
env['create_uninstall_target'](env, target1)
|
||||
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')
|
||||
svg_includes = glob.glob('../include/mapnik/svg/*.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
|
||||
if (face->family_name && face->style_name)
|
||||
{
|
||||
success = true;
|
||||
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
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
#if (BOOST_FILESYSTEM_VERSION == 3)
|
||||
std::string const& file_name = itr->path().string();
|
||||
std::string file_name = itr->path().string();
|
||||
#else // v2
|
||||
std::string const& file_name = itr->string();
|
||||
std::string file_name = itr->string();
|
||||
#endif
|
||||
if (boost::filesystem::is_directory(*itr) && recurse)
|
||||
{
|
||||
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;
|
||||
|
|
|
@ -135,11 +135,15 @@ public:
|
|||
xmlError * error = xmlCtxtGetLastError( ctx_ );
|
||||
std::ostringstream os;
|
||||
os << "XML document not well formed";
|
||||
int line=0;
|
||||
std::string file;
|
||||
if (error)
|
||||
{
|
||||
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_);
|
||||
|
|
|
@ -98,7 +98,7 @@ private:
|
|||
void parse_metawriter_in_symbolizer(symbolizer_base &sym, xml_node const& pt);
|
||||
|
||||
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);
|
||||
|
||||
|
@ -455,44 +455,62 @@ void map_parser::parse_fontset(Map & map, xml_node const& fset)
|
|||
{
|
||||
name = fset.get_attr<std::string>("name");
|
||||
font_set fontset(name);
|
||||
|
||||
xml_node::const_iterator itr = fset.begin();
|
||||
xml_node::const_iterator end = fset.end();
|
||||
|
||||
bool success = false;
|
||||
for (; itr != end; ++itr)
|
||||
{
|
||||
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);
|
||||
|
||||
// XXX Hack because map object isn't accessible by text_symbolizer
|
||||
// when it's parsed
|
||||
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);
|
||||
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");
|
||||
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
|
||||
{
|
||||
throw config_error("Must have 'face-name' set", f);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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];
|
||||
try
|
||||
mapnik::datasource_ptr ds = layer.datasource();
|
||||
if (ds)
|
||||
{
|
||||
double z = 0;
|
||||
mapnik::projection dest(srs_);
|
||||
mapnik::projection source(layer.srs());
|
||||
proj_transform prj_trans(source,dest);
|
||||
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)
|
||||
double z = 0;
|
||||
if (!prj_trans.equal() && !prj_trans.backward(x,y,z))
|
||||
{
|
||||
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 << ")";
|
||||
|
||||
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));
|
||||
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_point\"";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
featureset_ptr Map::query_map_point(unsigned index, double x, double y) const
|
||||
{
|
||||
if ( index< layers_.size())
|
||||
{
|
||||
mapnik::layer const& layer = layers_[index];
|
||||
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();
|
||||
CoordTransform tr = view_transform();
|
||||
tr.backward(&x,&y);
|
||||
return query_point(index,x,y);
|
||||
}
|
||||
|
||||
Map::~Map() {}
|
||||
|
|
|
@ -73,43 +73,37 @@ boost::optional<marker_ptr> marker_cache::find(std::string const& uri, bool upda
|
|||
return result;
|
||||
}
|
||||
|
||||
// we can't find marker in cache, lets try to load it from filesystem
|
||||
boost::filesystem::path path(uri);
|
||||
if (exists(path))
|
||||
try
|
||||
{
|
||||
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;
|
||||
try
|
||||
MAPNIK_LOG_ERROR(marker_cache) << "Marker does not exist: " << uri;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_svg(uri))
|
||||
{
|
||||
using namespace mapnik::svg;
|
||||
path_ptr marker_path(boost::make_shared<svg_storage_type>());
|
||||
vertex_stl_adapter<svg_path_storage> stl_storage(marker_path->source());
|
||||
svg_path_adapter svg_path(stl_storage);
|
||||
svg_converter_type svg(svg_path, marker_path->attributes());
|
||||
|
||||
svg_parser p(svg);
|
||||
p.parse(uri);
|
||||
//svg.arrange_orientations();
|
||||
double lox,loy,hix,hiy;
|
||||
svg.bounding_rect(&lox, &loy, &hix, &hiy);
|
||||
marker_path->set_bounding_box(lox,loy,hix,hiy);
|
||||
|
||||
marker_ptr mark(boost::make_shared<marker>(marker_path));
|
||||
result.reset(mark);
|
||||
if (update_cache)
|
||||
{
|
||||
cache_.insert(std::make_pair(uri,*result));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
MAPNIK_LOG_ERROR(marker_cache) << "Exception caught while loading SVG: " << uri;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
else
|
||||
{
|
||||
std::auto_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(uri));
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
catch (...)
|
||||
{
|
||||
MAPNIK_LOG_ERROR(marker_cache) << "Exception caught while loading image: " << uri;
|
||||
else
|
||||
{
|
||||
MAPNIK_LOG_ERROR(marker_cache) << "could not intialize reader for: '" << 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;
|
||||
}
|
||||
|
|
|
@ -33,19 +33,20 @@
|
|||
namespace mapnik {
|
||||
|
||||
#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_;
|
||||
#endif
|
||||
|
||||
projection::projection(std::string const& params)
|
||||
: params_(params)
|
||||
{
|
||||
init(); //
|
||||
init();
|
||||
}
|
||||
|
||||
projection::projection(projection const& rhs)
|
||||
: params_(rhs.params_)
|
||||
{
|
||||
init(); //
|
||||
init();
|
||||
}
|
||||
|
||||
projection& projection::operator=(projection const& rhs)
|
||||
|
@ -158,9 +159,9 @@ std::string projection::expanded() const
|
|||
return std::string("");
|
||||
}
|
||||
|
||||
void projection::swap (projection& rhs)
|
||||
void projection::swap(projection& rhs)
|
||||
{
|
||||
std::swap(params_,rhs.params_);
|
||||
init ();
|
||||
init();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -428,11 +428,21 @@ void svg_parser::parse_path(xmlTextReaderPtr reader)
|
|||
if (value)
|
||||
{
|
||||
path_.begin_path();
|
||||
|
||||
if (!mapnik::svg::parse_path((const char*) value, path_))
|
||||
{
|
||||
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();
|
||||
xmlFree(value);
|
||||
|
@ -450,7 +460,7 @@ void svg_parser::parse_polygon(xmlTextReaderPtr reader)
|
|||
if (!mapnik::svg::parse_points((const char*) value, path_))
|
||||
{
|
||||
xmlFree(value);
|
||||
throw std::runtime_error("Failed to parse <polygon>\n");
|
||||
throw std::runtime_error("Failed to parse <polygon>");
|
||||
}
|
||||
path_.close_subpath();
|
||||
path_.end_path();
|
||||
|
@ -469,7 +479,7 @@ void svg_parser::parse_polyline(xmlTextReaderPtr reader)
|
|||
if (!mapnik::svg::parse_points((const char*) value, path_))
|
||||
{
|
||||
xmlFree(value);
|
||||
throw std::runtime_error("Failed to parse <polygon>\n");
|
||||
throw std::runtime_error("Failed to parse <polygon>");
|
||||
}
|
||||
|
||||
path_.end_path();
|
||||
|
|
|
@ -113,8 +113,9 @@ public:
|
|||
{
|
||||
int type = read_integer();
|
||||
|
||||
#ifdef MAPNIK_LOG
|
||||
MAPNIK_LOG_DEBUG(wkb_reader) << "wkb_reader: Read=" << wkb_geometry_type_string(type) << "," << type;
|
||||
|
||||
#endif
|
||||
switch (type)
|
||||
{
|
||||
case wkbPoint:
|
||||
|
@ -401,6 +402,7 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef MAPNIK_LOG
|
||||
std::string wkb_geometry_type_string(int type)
|
||||
{
|
||||
std::stringstream s;
|
||||
|
@ -426,6 +428,7 @@ private:
|
|||
|
||||
return s.str();
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
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>
|
||||
namespace fs = boost::filesystem;
|
||||
using fs::path;
|
||||
|
@ -9,79 +7,72 @@ namespace sys = boost::system;
|
|||
#include <iostream>
|
||||
#include <mapnik/font_engine_freetype.hpp>
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------//
|
||||
|
||||
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/");
|
||||
|
||||
BOOST_TEST( fs::exists( fontdir ) );
|
||||
BOOST_TEST( fs::is_directory( fontdir ) );
|
||||
std::string foo("foo");
|
||||
|
||||
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
|
||||
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 );
|
||||
// bogus, emtpy file that looks like font
|
||||
BOOST_TEST( mapnik::freetype_engine::register_font("tests/data/fonts/fake.ttf") == false );
|
||||
BOOST_TEST( mapnik::freetype_engine::register_fonts("tests/data/fonts/fake.ttf") == false );
|
||||
BOOST_TEST( mapnik::freetype_engine::face_names().size() == 0 );
|
||||
|
||||
// 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 );
|
||||
BOOST_TEST( mapnik::freetype_engine::register_font("tests/data/fonts/intentionally-broken.ttf") == false );
|
||||
BOOST_TEST( mapnik::freetype_engine::register_fonts("tests/data/fonts/intentionally-broken.ttf") == false );
|
||||
BOOST_TEST( mapnik::freetype_engine::face_names().size() == 0 );
|
||||
|
||||
// bogus, emtpy file that looks like font
|
||||
BOOST_TEST( mapnik::freetype_engine::register_font("tests/data/fonts/fake.ttf") == false );
|
||||
BOOST_TEST( mapnik::freetype_engine::register_fonts("tests/data/fonts/fake.ttf") == false );
|
||||
BOOST_TEST( mapnik::freetype_engine::face_names().size() == 0 );
|
||||
// register unifont, since we know it sits in the root fonts/ dir
|
||||
BOOST_TEST( mapnik::freetype_engine::register_fonts(fontdir) );
|
||||
face_names = mapnik::freetype_engine::face_names();
|
||||
//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 );
|
||||
//BOOST_TEST( mapnik::freetype_engine::register_fonts("tests/data/fonts/intentionally-broken.ttf") == false );
|
||||
//BOOST_TEST( mapnik::freetype_engine::face_names().size() == 0 );
|
||||
// re-register unifont, should not have any affect
|
||||
BOOST_TEST( mapnik::freetype_engine::register_fonts(fontdir, false) );
|
||||
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
|
||||
BOOST_TEST( mapnik::freetype_engine::register_fonts(fontdir) );
|
||||
face_names = mapnik::freetype_engine::face_names();
|
||||
//std::clog << "number of registered fonts: " << face_names.size() << std::endl;
|
||||
BOOST_TEST( face_names.size() > 0 );
|
||||
BOOST_TEST( face_names.size() == 1 );
|
||||
// register a single dejavu font
|
||||
std::string dejavu_bold_oblique("tests/data/fonts/DejaVuSansMono-BoldOblique.ttf");
|
||||
BOOST_TEST( mapnik::freetype_engine::register_font(dejavu_bold_oblique) );
|
||||
face_names = mapnik::freetype_engine::face_names();
|
||||
//std::clog << "number of registered fonts: " << face_names.size() << std::endl;
|
||||
BOOST_TEST( face_names.size() == 2 );
|
||||
|
||||
// re-register unifont, should not have any affect
|
||||
BOOST_TEST( mapnik::freetype_engine::register_fonts(fontdir, false) );
|
||||
face_names = mapnik::freetype_engine::face_names();
|
||||
//std::clog << "number of registered fonts: " << face_names.size() << std::endl;
|
||||
BOOST_TEST( face_names.size() == 1 );
|
||||
// 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 );
|
||||
|
||||
// register a single dejavu font
|
||||
std::string dejavu_bold_oblique("tests/data/fonts/DejaVuSansMono-BoldOblique.ttf");
|
||||
BOOST_TEST( mapnik::freetype_engine::register_font(dejavu_bold_oblique) );
|
||||
face_names = mapnik::freetype_engine::face_names();
|
||||
//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();
|
||||
}
|
||||
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*[] )
|
||||
{
|
||||
|
||||
mapnik::parameters params;
|
||||
|
||||
// true
|
||||
params["bool"] = true;
|
||||
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));
|
||||
mapnik::parameters params;
|
||||
|
||||
params["bool"] = "true";
|
||||
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));
|
||||
// true
|
||||
params["bool"] = true;
|
||||
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));
|
||||
|
||||
params["bool"] = 1;
|
||||
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";
|
||||
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));
|
||||
params["bool"] = 1;
|
||||
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";
|
||||
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));
|
||||
|
||||
params["bool"] = "on";
|
||||
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"] = "yes";
|
||||
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));
|
||||
params["bool"] = "on";
|
||||
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));
|
||||
|
||||
// false
|
||||
params["bool"] = false;
|
||||
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false) );
|
||||
params["bool"] = "yes";
|
||||
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == true));
|
||||
|
||||
params["bool"] = "false";
|
||||
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false) );
|
||||
// false
|
||||
params["bool"] = false;
|
||||
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false) );
|
||||
|
||||
params["bool"] = 0;
|
||||
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";
|
||||
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false));
|
||||
params["bool"] = 0;
|
||||
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";
|
||||
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false));
|
||||
|
||||
params["bool"] = "off";
|
||||
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"] = "no";
|
||||
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false));
|
||||
params["bool"] = "off";
|
||||
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false));
|
||||
|
||||
// strings
|
||||
params["string"] = "hello";
|
||||
BOOST_TEST( (params.get<std::string>("string") && *params.get<std::string>("string") == "hello") );
|
||||
params["bool"] = "no";
|
||||
BOOST_TEST( (params.get<mapnik::boolean>("bool") && *params.get<mapnik::boolean>("bool") == false));
|
||||
|
||||
// int
|
||||
params["int"] = 1;
|
||||
BOOST_TEST( (params.get<int>("int") && *params.get<int>("int") == 1) );
|
||||
// strings
|
||||
params["string"] = "hello";
|
||||
BOOST_TEST( (params.get<std::string>("string") && *params.get<std::string>("string") == "hello") );
|
||||
|
||||
// double
|
||||
params["double"] = 1.5;
|
||||
BOOST_TEST( (params.get<double>("double") && *params.get<double>("double") == 1.5) );
|
||||
// int
|
||||
params["int"] = 1;
|
||||
BOOST_TEST( (params.get<int>("int") && *params.get<int>("int") == 1) );
|
||||
|
||||
// value_null
|
||||
params["null"] = mapnik::value_null();
|
||||
//BOOST_TEST( (params.get<mapnik::value_null>("null")/* && *params.get<mapnik::value_null>("null") == mapnik::value_null()*/) );
|
||||
// double
|
||||
params["double"] = 1.5;
|
||||
BOOST_TEST( (params.get<double>("double") && *params.get<double>("double") == 1.5) );
|
||||
|
||||
if (!::boost::detail::test_errors()) {
|
||||
std::clog << "C++ parameters: \x1b[1;32m✓ \x1b[0m\n";
|
||||
} else {
|
||||
return ::boost::report_errors();
|
||||
}
|
||||
// value_null
|
||||
params["null"] = mapnik::value_null();
|
||||
//BOOST_TEST( (params.get<mapnik::value_null>("null")/* && *params.get<mapnik::value_null>("null") == mapnik::value_null()*/) );
|
||||
|
||||
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
|
||||
|
||||
/*
|
||||
* This test module contains several generators for
|
||||
* This test module contains several generators for
|
||||
* the implementation of a background color in SVG
|
||||
* using a rectangle.
|
||||
*/
|
||||
|
@ -25,16 +25,16 @@ namespace repository = boost::spirit::repository;
|
|||
namespace fusion = boost::fusion;
|
||||
using namespace karma;
|
||||
|
||||
struct F
|
||||
struct F
|
||||
{
|
||||
F() :
|
||||
x(0),
|
||||
y(0),
|
||||
width(100),
|
||||
height(100),
|
||||
bgcolor("#ffffff"),
|
||||
expected_output("<rect x=\"0\" y=\"0\" width=\"100px\" height=\"100px\" style=\"fill: #ffffff\"/>") {}
|
||||
|
||||
x(0),
|
||||
y(0),
|
||||
width(100),
|
||||
height(100),
|
||||
bgcolor("#ffffff"),
|
||||
expected_output("<rect x=\"0\" y=\"0\" width=\"100px\" height=\"100px\" style=\"fill: #ffffff\"/>") {}
|
||||
|
||||
~F() {}
|
||||
|
||||
const int x;
|
||||
|
@ -61,14 +61,14 @@ struct F
|
|||
BOOST_FIXTURE_TEST_CASE(bgcolor_stream_test_case, F)
|
||||
{
|
||||
actual_output
|
||||
<< format(
|
||||
"<rect x=\"" << int_ << "\" "
|
||||
<< "y=\"" << int_ << "\" "
|
||||
<< "width=\"" << int_ << string << "\" "
|
||||
<< "height=\"" << int_ << string << "\" "
|
||||
<< "style=\"fill: " << string << "\""
|
||||
<< "/>",
|
||||
x, y, width, "px", height, "px", bgcolor);
|
||||
<< format(
|
||||
"<rect x=\"" << int_ << "\" "
|
||||
<< "y=\"" << int_ << "\" "
|
||||
<< "width=\"" << int_ << string << "\" "
|
||||
<< "height=\"" << int_ << string << "\" "
|
||||
<< "style=\"fill: " << string << "\""
|
||||
<< "/>",
|
||||
x, y, width, "px", height, "px", bgcolor);
|
||||
|
||||
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.
|
||||
* 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>).
|
||||
*
|
||||
* 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;
|
||||
|
||||
actual_output
|
||||
<< format(
|
||||
"<rect x=" << confix('"', '"')[int_]
|
||||
<< " y=" << confix('"', '"')[int_]
|
||||
<< " width=" << confix('"', '"')[int_ << string]
|
||||
<< " height=" << confix('"', '"')[int_ << string]
|
||||
<< " style=" << confix('"', '"')["fill: " << string]
|
||||
<< "/>",
|
||||
x, y, tuple<int, std::string>(width, "px"), tuple<int, std::string>(height, "px"), bgcolor);
|
||||
|
||||
<< format(
|
||||
"<rect x=" << confix('"', '"')[int_]
|
||||
<< " y=" << confix('"', '"')[int_]
|
||||
<< " width=" << confix('"', '"')[int_ << string]
|
||||
<< " height=" << confix('"', '"')[int_ << string]
|
||||
<< " style=" << confix('"', '"')["fill: " << string]
|
||||
<< "/>",
|
||||
x, y, tuple<int, std::string>(width, "px"), tuple<int, std::string>(height, "px"), bgcolor);
|
||||
|
||||
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
|
||||
* confix generator's expression.
|
||||
*
|
||||
* Notice also that the attribute list is the same as in
|
||||
* '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.
|
||||
* Notice also that the attribute list is the same as in
|
||||
* '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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
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;
|
||||
|
||||
actual_output
|
||||
<< format(
|
||||
confix('<', "/>")[
|
||||
"rect x=" << confix('"', '"')[int_]
|
||||
<< " y=" << confix('"', '"')[int_]
|
||||
<< " width=" << confix('"', '"')[int_ << string]
|
||||
<< " height=" << confix('"', '"')[int_ << string]
|
||||
<< " style=" << confix('"', '"')["fill: " << string]],
|
||||
x, y, tuple<int, std::string>(width, "px"), tuple<int, std::string>(height, "px"), bgcolor);
|
||||
|
||||
<< format(
|
||||
confix('<', "/>")[
|
||||
"rect x=" << confix('"', '"')[int_]
|
||||
<< " y=" << confix('"', '"')[int_]
|
||||
<< " width=" << confix('"', '"')[int_ << string]
|
||||
<< " height=" << confix('"', '"')[int_ << string]
|
||||
<< " style=" << confix('"', '"')["fill: " << string]],
|
||||
x, y, tuple<int, std::string>(width, "px"), tuple<int, std::string>(height, "px"), bgcolor);
|
||||
|
||||
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);
|
||||
|
||||
generate(
|
||||
actual_output_iterator,
|
||||
confix("<", "/>")[
|
||||
"rect x=" << confix('"', '"')[int_]
|
||||
<< " y=" << confix('"', '"')[int_]
|
||||
<< " width=" << confix('"', '"')[int_ << string]
|
||||
<< " height=" << confix('"', '"')[int_ << string]
|
||||
<< " style=" << confix('"', '"')["fill: " << string]],
|
||||
x, y, tuple<int, std::string>(width, "px"), tuple<int, std::string>(height, "px"), bgcolor);
|
||||
actual_output_iterator,
|
||||
confix("<", "/>")[
|
||||
"rect x=" << confix('"', '"')[int_]
|
||||
<< " y=" << confix('"', '"')[int_]
|
||||
<< " width=" << confix('"', '"')[int_ << string]
|
||||
<< " height=" << confix('"', '"')[int_ << string]
|
||||
<< " style=" << confix('"', '"')["fill: " << string]],
|
||||
x, y, tuple<int, std::string>(width, "px"), tuple<int, std::string>(height, "px"), bgcolor);
|
||||
|
||||
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);
|
||||
renderer.apply();
|
||||
|
||||
/*std::string expected_output =
|
||||
svg_ren::XML_DECLARATION
|
||||
+ "\n"
|
||||
+ svg_ren::SVG_DTD
|
||||
+ "\n"
|
||||
+ "<svg width=\"800px\" height=\"600px\" version=\"1.1\" xmlns=\""
|
||||
+ svg_ren::SVG_NAMESPACE_URL
|
||||
+ "\">"
|
||||
+"\n"
|
||||
+"<rect x=\"0\" y=\"0\" width=\"800px\" height=\"600px\" style=\"fill: #ffffff\"/>"
|
||||
+"\n"
|
||||
+"</svg>";
|
||||
/*std::string expected_output =
|
||||
svg_ren::XML_DECLARATION
|
||||
+ "\n"
|
||||
+ svg_ren::SVG_DTD
|
||||
+ "\n"
|
||||
+ "<svg width=\"800px\" height=\"600px\" version=\"1.1\" xmlns=\""
|
||||
+ svg_ren::SVG_NAMESPACE_URL
|
||||
+ "\">"
|
||||
+"\n"
|
||||
+"<rect x=\"0\" y=\"0\" width=\"800px\" height=\"600px\" style=\"fill: #ffffff\"/>"
|
||||
+"\n"
|
||||
+"</svg>";
|
||||
|
||||
std::string actual_output = output_stream.str();
|
||||
BOOST_CHECK_EQUAL(actual_output, expected_output);
|
||||
std::string actual_output = output_stream.str();
|
||||
BOOST_CHECK_EQUAL(actual_output, expected_output);
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
|
@ -51,15 +51,15 @@ BOOST_AUTO_TEST_CASE(file_output_test_case)
|
|||
if(output_stream)
|
||||
{
|
||||
std::ostream_iterator<char> output_stream_iterator(output_stream);
|
||||
|
||||
|
||||
svg_ren renderer(map, output_stream_iterator);
|
||||
renderer.apply();
|
||||
|
||||
|
||||
output_stream.close();
|
||||
|
||||
filesystem::path output_filename_path =
|
||||
|
||||
filesystem::path output_filename_path =
|
||||
filesystem::system_complete(filesystem::path(".")) / filesystem::path(output_filename);
|
||||
|
||||
|
||||
BOOST_CHECK_MESSAGE(filesystem::exists(output_filename_path), "File '"+output_filename_path.string()+"' was created.");
|
||||
}
|
||||
else
|
||||
|
|
|
@ -25,54 +25,54 @@ namespace filesystem = boost::filesystem;
|
|||
using namespace mapnik;
|
||||
|
||||
void prepare_map(Map& m)
|
||||
{
|
||||
{
|
||||
const std::string mapnik_dir("/usr/local/lib/mapnik/");
|
||||
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
|
||||
|
||||
// Provinces (polygon)
|
||||
feature_type_style provpoly_style;
|
||||
|
||||
|
||||
rule provpoly_rule_on;
|
||||
provpoly_rule_on.set_filter(parse_expression("[NAME_EN] = 'Ontario'"));
|
||||
provpoly_rule_on.append(polygon_symbolizer(color(250, 190, 183)));
|
||||
provpoly_style.add_rule(provpoly_rule_on);
|
||||
|
||||
|
||||
rule provpoly_rule_qc;
|
||||
provpoly_rule_qc.set_filter(parse_expression("[NOM_FR] = 'Québec'"));
|
||||
provpoly_rule_qc.append(polygon_symbolizer(color(217, 235, 203)));
|
||||
provpoly_style.add_rule(provpoly_rule_qc);
|
||||
|
||||
|
||||
m.insert_style("provinces",provpoly_style);
|
||||
|
||||
// Provinces (polyline)
|
||||
feature_type_style provlines_style;
|
||||
|
||||
|
||||
stroke provlines_stk (color(0,0,0),1.0);
|
||||
provlines_stk.add_dash(8, 4);
|
||||
provlines_stk.add_dash(2, 2);
|
||||
provlines_stk.add_dash(2, 2);
|
||||
|
||||
|
||||
rule provlines_rule;
|
||||
provlines_rule.append(line_symbolizer(provlines_stk));
|
||||
provlines_style.add_rule(provlines_rule);
|
||||
|
||||
|
||||
m.insert_style("provlines",provlines_style);
|
||||
|
||||
// Drainage
|
||||
|
||||
// Drainage
|
||||
feature_type_style qcdrain_style;
|
||||
|
||||
|
||||
rule qcdrain_rule;
|
||||
qcdrain_rule.set_filter(parse_expression("[HYC] = 8"));
|
||||
qcdrain_rule.append(polygon_symbolizer(color(153, 204, 255)));
|
||||
qcdrain_style.add_rule(qcdrain_rule);
|
||||
|
||||
|
||||
m.insert_style("drainage",qcdrain_style);
|
||||
|
||||
|
||||
// Roads 3 and 4 (The "grey" roads)
|
||||
feature_type_style roads34_style;
|
||||
feature_type_style roads34_style;
|
||||
rule roads34_rule;
|
||||
roads34_rule.set_filter(parse_expression("[CLASS] = 3 or [CLASS] = 4"));
|
||||
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.append(line_symbolizer(roads34_rule_stk));
|
||||
roads34_style.add_rule(roads34_rule);
|
||||
|
||||
|
||||
m.insert_style("smallroads",roads34_style);
|
||||
|
||||
|
||||
// Roads 2 (The thin yellow ones)
|
||||
feature_type_style roads2_style_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_1.append(line_symbolizer(roads2_rule_stk_1));
|
||||
roads2_style_1.add_rule(roads2_rule_1);
|
||||
|
||||
|
||||
m.insert_style("road-border", roads2_style_1);
|
||||
|
||||
|
||||
feature_type_style roads2_style_2;
|
||||
rule roads2_rule_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_2.append(line_symbolizer(roads2_rule_stk_2));
|
||||
roads2_style_2.add_rule(roads2_rule_2);
|
||||
|
||||
|
||||
m.insert_style("road-fill", roads2_style_2);
|
||||
|
||||
|
||||
// Roads 1 (The big orange ones, the highways)
|
||||
feature_type_style roads1_style_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_style_1.add_rule(roads1_rule_1);
|
||||
m.insert_style("highway-border", roads1_style_1);
|
||||
|
||||
|
||||
feature_type_style roads1_style_2;
|
||||
rule roads1_rule_2;
|
||||
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_2.append(line_symbolizer(roads1_rule_stk_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
|
||||
// Provincial polygons
|
||||
{
|
||||
parameters p;
|
||||
p["type"]="shape";
|
||||
p["file"]="../../../demo/data/boundaries";
|
||||
|
||||
layer lyr("Provinces");
|
||||
|
||||
layer lyr("Provinces");
|
||||
lyr.set_datasource(datasource_cache::instance()->create(p));
|
||||
lyr.add_style("provinces");
|
||||
lyr.add_style("provinces");
|
||||
m.addLayer(lyr);
|
||||
}
|
||||
|
||||
|
||||
// Drainage
|
||||
{
|
||||
parameters p;
|
||||
|
@ -147,46 +147,46 @@ void prepare_map(Map& m)
|
|||
p["file"]="../../../demo/data/qcdrainage";
|
||||
layer lyr("Quebec Hydrography");
|
||||
lyr.set_datasource(datasource_cache::instance()->create(p));
|
||||
lyr.add_style("drainage");
|
||||
lyr.add_style("drainage");
|
||||
m.addLayer(lyr);
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
parameters p;
|
||||
p["type"]="shape";
|
||||
p["file"]="../../../demo/data/ontdrainage";
|
||||
|
||||
layer lyr("Ontario Hydrography");
|
||||
|
||||
layer lyr("Ontario Hydrography");
|
||||
lyr.set_datasource(datasource_cache::instance()->create(p));
|
||||
lyr.add_style("drainage");
|
||||
lyr.add_style("drainage");
|
||||
m.addLayer(lyr);
|
||||
}
|
||||
|
||||
|
||||
// Provincial boundaries
|
||||
{
|
||||
parameters p;
|
||||
p["type"]="shape";
|
||||
p["file"]="../../../demo/data/boundaries_l";
|
||||
layer lyr("Provincial borders");
|
||||
layer lyr("Provincial borders");
|
||||
lyr.set_datasource(datasource_cache::instance()->create(p));
|
||||
lyr.add_style("provlines");
|
||||
lyr.add_style("provlines");
|
||||
m.addLayer(lyr);
|
||||
}
|
||||
|
||||
|
||||
// Roads
|
||||
{
|
||||
parameters p;
|
||||
p["type"]="shape";
|
||||
p["file"]="../../../demo/data/roads";
|
||||
layer lyr("Roads");
|
||||
p["file"]="../../../demo/data/roads";
|
||||
layer lyr("Roads");
|
||||
lyr.set_datasource(datasource_cache::instance()->create(p));
|
||||
lyr.add_style("smallroads");
|
||||
lyr.add_style("road-border");
|
||||
lyr.add_style("road-fill");
|
||||
lyr.add_style("highway-border");
|
||||
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)
|
||||
{
|
||||
typedef svg_renderer<std::ostream_iterator<char> > svg_ren;
|
||||
|
||||
|
||||
std::ostream_iterator<char> output_stream_iterator(output_stream);
|
||||
|
||||
|
||||
svg_ren renderer(m, output_stream_iterator);
|
||||
renderer.apply();
|
||||
|
||||
|
||||
output_stream.close();
|
||||
|
||||
filesystem::path output_filename_path =
|
||||
|
||||
filesystem::path output_filename_path =
|
||||
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
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
Map m(800,600);
|
||||
m.set_background(color_factory::from_string("steelblue"));
|
||||
m.set_background(color_factory::from_string("steelblue"));
|
||||
|
||||
prepare_map(m);
|
||||
|
||||
|
||||
//m.zoom_to_box(box2d<double>(1405120.04127408, -247003.813399447,
|
||||
//1706357.31328276, -25098.593149577));
|
||||
m.zoom_all();
|
||||
//1706357.31328276, -25098.593149577));
|
||||
m.zoom_all();
|
||||
render_to_file(m, "path_element_test_case_1.svg");
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#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.
|
||||
*/
|
||||
|
||||
|
@ -24,14 +24,14 @@ namespace repository = boost::spirit::repository;
|
|||
namespace fusion = boost::fusion;
|
||||
using namespace karma;
|
||||
|
||||
struct F
|
||||
struct F
|
||||
{
|
||||
F() :
|
||||
width(100),
|
||||
height(100),
|
||||
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\">") {}
|
||||
width(100),
|
||||
height(100),
|
||||
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() {}
|
||||
|
||||
|
@ -58,13 +58,13 @@ struct F
|
|||
BOOST_FIXTURE_TEST_CASE(bgcolor_stream_test_case, F)
|
||||
{
|
||||
actual_output
|
||||
<< format(
|
||||
"<svg width=\"" << int_ << string << "\" "
|
||||
<< "height=\"" << int_ << string << "\" "
|
||||
<< "version=\"" << float_ << "\" "
|
||||
<< "xmlns=\"" << string << "\""
|
||||
<< ">",
|
||||
width, "px", height, "px", version, xmlns);
|
||||
<< format(
|
||||
"<svg width=\"" << int_ << string << "\" "
|
||||
<< "height=\"" << int_ << string << "\" "
|
||||
<< "version=\"" << float_ << "\" "
|
||||
<< "xmlns=\"" << string << "\""
|
||||
<< ">",
|
||||
width, "px", height, "px", version, xmlns);
|
||||
|
||||
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.
|
||||
* 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>).
|
||||
*
|
||||
* 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;
|
||||
|
||||
actual_output
|
||||
<< format(
|
||||
"<svg width=" << confix('"', '"')[int_ << string]
|
||||
<< " height=" << confix('"', '"')[int_ << string]
|
||||
<< " version=" << confix('"', '"')[float_]
|
||||
<< " xmlns=" << confix('"', '"')[string]
|
||||
<< ">",
|
||||
tuple<int, std::string>(width, "px"), tuple<int, std::string>(height, "px"), version, xmlns);
|
||||
|
||||
<< format(
|
||||
"<svg width=" << confix('"', '"')[int_ << string]
|
||||
<< " height=" << confix('"', '"')[int_ << string]
|
||||
<< " version=" << confix('"', '"')[float_]
|
||||
<< " xmlns=" << confix('"', '"')[string]
|
||||
<< ">",
|
||||
tuple<int, std::string>(width, "px"), tuple<int, std::string>(height, "px"), version, xmlns);
|
||||
|
||||
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
|
||||
* confix generator's expression.
|
||||
*
|
||||
* Notice also that the attribute list is the same as in
|
||||
* '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.
|
||||
* Notice also that the attribute list is the same as in
|
||||
* '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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
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;
|
||||
|
||||
actual_output
|
||||
<< format(
|
||||
confix('<', ">")[
|
||||
"svg width=" << confix('"', '"')[int_ << string]
|
||||
<< " height=" << confix('"', '"')[int_ << string]
|
||||
<< " version=" << confix('"', '"')[float_]
|
||||
<< " xmlns=" << confix('"', '"')[string]],
|
||||
tuple<int, std::string>(width, "px"), tuple<int, std::string>(height, "px"), version, xmlns);
|
||||
|
||||
<< format(
|
||||
confix('<', ">")[
|
||||
"svg width=" << confix('"', '"')[int_ << string]
|
||||
<< " height=" << confix('"', '"')[int_ << string]
|
||||
<< " version=" << confix('"', '"')[float_]
|
||||
<< " xmlns=" << confix('"', '"')[string]],
|
||||
tuple<int, std::string>(width, "px"), tuple<int, std::string>(height, "px"), version, xmlns);
|
||||
|
||||
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);
|
||||
|
||||
generate(
|
||||
actual_output_iterator,
|
||||
confix("<", ">")[
|
||||
"svg width=" << confix('"', '"')[int_ << string]
|
||||
<< " height=" << confix('"', '"')[int_ << string]
|
||||
<< " version=" << confix('"', '"')[float_]
|
||||
<< " xmlns=" << confix('"', '"')[string]],
|
||||
tuple<int, std::string>(width, "px"), tuple<int, std::string>(height, "px"), version, xmlns);
|
||||
actual_output_iterator,
|
||||
confix("<", ">")[
|
||||
"svg width=" << confix('"', '"')[int_ << string]
|
||||
<< " height=" << confix('"', '"')[int_ << string]
|
||||
<< " version=" << confix('"', '"')[float_]
|
||||
<< " xmlns=" << confix('"', '"')[string]],
|
||||
tuple<int, std::string>(width, "px"), tuple<int, std::string>(height, "px"), version, xmlns);
|
||||
|
||||
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.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
|
||||
# images paths are now PathExpressions are evaluated at runtime
|
||||
# so it does not make sense to throw...
|
||||
|
|
|
@ -69,17 +69,20 @@ def test_dataraster_query_point():
|
|||
_map = mapnik.Map(256,256, srs)
|
||||
_map.layers.append(lyr)
|
||||
|
||||
# point inside raster extent with valid data
|
||||
x, y = 427417, 4477517
|
||||
x, y = 556113.0,4381428.0 # center of extent of raster
|
||||
_map.zoom_all()
|
||||
features = _map.query_point(0,x,y).features
|
||||
assert len(features) == 1
|
||||
feat = features[0]
|
||||
center = feat.envelope().center()
|
||||
assert center.x==x and center.y==y, center
|
||||
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
|
||||
assert len(features) == 0
|
||||
|
||||
|
|
|
@ -71,6 +71,88 @@ if 'sqlite' in mapnik.DatasourceCache.instance().plugin_names():
|
|||
eq_(os.path.exists(index),True)
|
||||
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__":
|
||||
setup()
|
||||
|
|
|
@ -27,13 +27,13 @@ def compare(fn1, fn2):
|
|||
try:
|
||||
im2 = Image.open(fn2)
|
||||
except IOError:
|
||||
errors.append((fn1, None))
|
||||
errors.append((fn1, None, fn2))
|
||||
return -1
|
||||
diff = 0
|
||||
pixels = im1.size[0] * im1.size[1]
|
||||
delta_pixels = im2.size[0] * im2.size[1] - pixels
|
||||
if delta_pixels != 0:
|
||||
errors.append((fn1, delta_pixels))
|
||||
errors.append((fn1, delta_pixels, fn2))
|
||||
return delta_pixels
|
||||
im1 = im1.getdata()
|
||||
im2 = im2.getdata()
|
||||
|
@ -41,7 +41,7 @@ def compare(fn1, fn2):
|
|||
if(compare_pixels(im1[i], im2[i])):
|
||||
diff = diff + 1
|
||||
if diff != 0:
|
||||
errors.append((fn1, diff))
|
||||
errors.append((fn1, diff, fn2))
|
||||
passed += 1
|
||||
return diff
|
||||
|
||||
|
@ -55,7 +55,7 @@ def summary():
|
|||
if (error[1] is None):
|
||||
print "Could not verify %s: No reference image found!" % error[0]
|
||||
else:
|
||||
print "%s failed: %d different pixels" % error
|
||||
print "%s failed: %d different pixels \n\t%s (expected)" % error
|
||||
sys.exit(1)
|
||||
else:
|
||||
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)
|
||||
else:
|
||||
m.zoom_all()
|
||||
basefn = os.path.join(dirname, "images", '%s-%d' % (filename, width))
|
||||
mapnik.render_to_file(m, basefn+'-agg.png')
|
||||
diff = compare(basefn + '-agg.png', basefn + '-reference.png')
|
||||
expected = os.path.join(dirname, "images", '%s-%d-reference.png' % (filename, width))
|
||||
if not os.path.exists('/tmp/mapnik-visual-images'):
|
||||
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:
|
||||
print "-"*80
|
||||
print '\x1b[33mError:\x1b[0m %u different pixels' % diff
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# batch format *.{hpp,cpp} files
|
||||
|
||||
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"
|
||||
|
||||
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 = []
|
||||
boost_program_options = 'boost_program_options%s' % env['BOOST_APPEND']
|
||||
|
@ -49,7 +54,7 @@ if env['SQLITE_LINKFLAGS']:
|
|||
if env['RUNTIME_LINK'] == 'static':
|
||||
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']))
|
||||
|
||||
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'])
|
||||
boost_program_options = 'boost_program_options%s' % env['BOOST_APPEND']
|
||||
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']))
|
||||
|
||||
|
|
|
@ -23,8 +23,10 @@
|
|||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
//#include <string>
|
||||
#include <string>
|
||||
|
||||
#include <mapnik/version.hpp>
|
||||
#include <mapnik/debug.hpp>
|
||||
#include <mapnik/marker.hpp>
|
||||
#include <mapnik/marker_cache.hpp>
|
||||
#include <mapnik/image_util.hpp>
|
||||
|
@ -44,13 +46,19 @@
|
|||
#include "agg_pixfmt_rgba.h"
|
||||
#include "agg_scanline_u.h"
|
||||
|
||||
#include <libxml/parser.h> // for xmlInitParser(), xmlCleanupParser()
|
||||
|
||||
|
||||
int main (int argc,char** argv)
|
||||
{
|
||||
namespace po = boost::program_options;
|
||||
|
||||
bool verbose=false;
|
||||
bool verbose = false;
|
||||
bool auto_open = false;
|
||||
bool error = false;
|
||||
std::vector<std::string> svg_files;
|
||||
mapnik::logger logger;
|
||||
logger.set_severity(mapnik::logger::error);
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -59,6 +67,7 @@ int main (int argc,char** argv)
|
|||
("help,h", "produce usage message")
|
||||
("version,V","print version string")
|
||||
("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")
|
||||
;
|
||||
|
||||
|
@ -70,7 +79,7 @@ int main (int argc,char** argv)
|
|||
|
||||
if (vm.count("version"))
|
||||
{
|
||||
std::clog<<"version 0.3.0" << std::endl;
|
||||
std::clog <<"version " << MAPNIK_VERSION_STRING << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -79,11 +88,17 @@ int main (int argc,char** argv)
|
|||
std::clog << desc << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (vm.count("verbose"))
|
||||
{
|
||||
verbose = true;
|
||||
}
|
||||
|
||||
if (vm.count("open"))
|
||||
{
|
||||
auto_open = true;
|
||||
}
|
||||
|
||||
if (vm.count("svg"))
|
||||
{
|
||||
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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
xmlInitParser();
|
||||
|
||||
while (itr != svg_files.end())
|
||||
{
|
||||
|
||||
std::string svg_name (*itr++);
|
||||
|
||||
boost::optional<mapnik::marker_ptr> marker_ptr = mapnik::marker_cache::instance()->find(svg_name, false);
|
||||
if (marker_ptr) {
|
||||
|
||||
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());
|
||||
}
|
||||
if (verbose)
|
||||
{
|
||||
std::clog << "found: " << svg_name << "\n";
|
||||
}
|
||||
|
||||
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 (...)
|
||||
{
|
||||
std::clog << "Exception of unknown type!" << std::endl;
|
||||
xmlCleanupParser();
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue