Merge pull request #1311 from mapnik/stock-markers
Stock markers support
This commit is contained in:
commit
5f2c60261c
5 changed files with 135 additions and 25 deletions
|
@ -97,7 +97,7 @@ void export_markers_symbolizer()
|
|||
;
|
||||
|
||||
class_<markers_symbolizer>("MarkersSymbolizer",
|
||||
init<>("Default Markers Symbolizer - blue arrow"))
|
||||
init<>("Default Markers Symbolizer - circle"))
|
||||
.def (init<mapnik::path_expression_ptr>("<path expression ptr>"))
|
||||
//.def_pickle(markers_symbolizer_pickle_suite())
|
||||
.add_property("filename",
|
||||
|
|
|
@ -41,14 +41,21 @@ class marker;
|
|||
typedef boost::shared_ptr<marker> marker_ptr;
|
||||
|
||||
|
||||
struct MAPNIK_DECL marker_cache :
|
||||
public singleton <marker_cache, CreateStatic>,
|
||||
class MAPNIK_DECL marker_cache :
|
||||
public singleton <marker_cache, CreateUsingNew>,
|
||||
private boost::noncopyable
|
||||
{
|
||||
|
||||
friend class CreateStatic<marker_cache>;
|
||||
static boost::unordered_map<std::string,marker_ptr> cache_;
|
||||
static bool insert(std::string const& key, marker_ptr);
|
||||
friend class CreateUsingNew<marker_cache>;
|
||||
private:
|
||||
marker_cache();
|
||||
~marker_cache();
|
||||
static bool insert_marker(std::string const& key, marker_ptr path);
|
||||
static boost::unordered_map<std::string,marker_ptr> marker_cache_;
|
||||
static bool insert_svg(std::string const& name, std::string const& svg_string);
|
||||
static boost::unordered_map<std::string,std::string> svg_cache_;
|
||||
public:
|
||||
static std::string known_svg_prefix_;
|
||||
static bool is_uri(std::string const& path);
|
||||
static boost::optional<marker_ptr> find(std::string const& key, bool update_cache = false);
|
||||
static void clear();
|
||||
};
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#include <mapnik/config_error.hpp>
|
||||
#include <mapnik/util/dasharray_parser.hpp>
|
||||
#include <mapnik/util/conversions.hpp>
|
||||
#include <mapnik/marker_cache.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/optional.hpp>
|
||||
|
@ -987,15 +988,35 @@ void map_parser::parse_markers_symbolizer(rule & rule, xml_node const& node)
|
|||
}
|
||||
}
|
||||
|
||||
path_expression_ptr expr(boost::make_shared<path_expression>());
|
||||
optional<std::string> marker_type = node.get_opt_attr<std::string>("marker-type");
|
||||
if (marker_type)
|
||||
{
|
||||
MAPNIK_LOG_ERROR(markers_symbolizer) << "'marker-type' is deprecated and will be removed in Mapnik 3.x, use file='shape://<type>' to specify known svg shapes";
|
||||
// back compatibility with Mapnik 2.0.0
|
||||
if (!marker_type->empty() && filename.empty())
|
||||
{
|
||||
if (*marker_type == "ellipse")
|
||||
{
|
||||
filename = marker_cache::known_svg_prefix_ + "ellipse";
|
||||
}
|
||||
else if (*marker_type == "arrow")
|
||||
{
|
||||
filename = marker_cache::known_svg_prefix_ + "arrow";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
markers_symbolizer sym;
|
||||
|
||||
if (!filename.empty())
|
||||
{
|
||||
path_expression_ptr expr(boost::make_shared<path_expression>());
|
||||
if (!parse_path_from_string(expr, filename, node.get_tree().path_expr_grammar))
|
||||
{
|
||||
throw mapnik::config_error("Failed to parse path_expression '" + filename + "'");
|
||||
}
|
||||
sym.set_filename(expr);
|
||||
}
|
||||
markers_symbolizer sym(expr);
|
||||
|
||||
optional<float> opacity = node.get_opt_attr<float>("opacity");
|
||||
if (opacity) sym.set_opacity(*opacity);
|
||||
|
@ -1610,6 +1631,9 @@ void map_parser::ensure_font_face(std::string const& face_name)
|
|||
|
||||
std::string map_parser::ensure_relative_to_xml(boost::optional<std::string> opt_path)
|
||||
{
|
||||
if (marker_cache::is_uri(*opt_path))
|
||||
return *opt_path;
|
||||
|
||||
if (relative_to_xml_)
|
||||
{
|
||||
boost::filesystem::path xml_path = filename_;
|
||||
|
|
|
@ -45,25 +45,73 @@
|
|||
namespace mapnik
|
||||
{
|
||||
|
||||
boost::unordered_map<std::string, marker_ptr> marker_cache::cache_;
|
||||
boost::unordered_map<std::string, marker_ptr> marker_cache::marker_cache_;
|
||||
boost::unordered_map<std::string, std::string> marker_cache::svg_cache_;
|
||||
std::string marker_cache::known_svg_prefix_ = "shape://";
|
||||
|
||||
marker_cache::marker_cache()
|
||||
{
|
||||
insert_svg("ellipse",
|
||||
"<?xml version='1.0' standalone='no'?>"
|
||||
"<svg width='100%' height='100%' version='1.1' xmlns='http://www.w3.org/2000/svg'>"
|
||||
"<circle r='10' fill='#93a7ac' fill-opacity='.5' stroke='none'/>"
|
||||
"</svg>");
|
||||
insert_svg("arrow",
|
||||
"<?xml version='1.0' standalone='no'?>"
|
||||
"<svg width='100%' height='100%' version='1.1' xmlns='http://www.w3.org/2000/svg'>"
|
||||
"<path fill='#93a7ac' fill-opacity='.5' d='m 31.698405,7.5302648 -8.910967,-6.0263712 0.594993,4.8210971 -18.9822542,0 0,2.4105482 18.9822542,0 -0.594993,4.8210971 z'/>"
|
||||
"</svg>");
|
||||
}
|
||||
|
||||
marker_cache::~marker_cache() {}
|
||||
|
||||
void marker_cache::clear()
|
||||
{
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
#endif
|
||||
return cache_.clear();
|
||||
typedef boost::unordered_map<std::string, marker_ptr>::const_iterator iterator_type;
|
||||
iterator_type itr = marker_cache_.begin();
|
||||
while(itr != marker_cache_.end())
|
||||
{
|
||||
if (!is_uri(itr->first))
|
||||
{
|
||||
marker_cache_.erase(itr++);
|
||||
}
|
||||
else
|
||||
{
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool marker_cache::insert(std::string const& uri, marker_ptr path)
|
||||
bool marker_cache::is_uri(std::string const& path)
|
||||
{
|
||||
return boost::algorithm::starts_with(path,known_svg_prefix_);
|
||||
}
|
||||
|
||||
bool marker_cache::insert_svg(std::string const& name, std::string const& svg_string)
|
||||
{
|
||||
std::string key = known_svg_prefix_ + name;
|
||||
typedef boost::unordered_map<std::string, std::string>::const_iterator iterator_type;
|
||||
iterator_type itr = svg_cache_.find(key);
|
||||
if (itr == svg_cache_.end())
|
||||
{
|
||||
return svg_cache_.insert(std::make_pair(key,svg_string)).second;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool marker_cache::insert_marker(std::string const& uri, marker_ptr path)
|
||||
{
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
#endif
|
||||
return cache_.insert(std::make_pair(uri,path)).second;
|
||||
return marker_cache_.insert(std::make_pair(uri,path)).second;
|
||||
}
|
||||
|
||||
boost::optional<marker_ptr> marker_cache::find(std::string const& uri, bool update_cache)
|
||||
boost::optional<marker_ptr> marker_cache::find(std::string const& uri,
|
||||
bool update_cache)
|
||||
{
|
||||
|
||||
boost::optional<marker_ptr> result;
|
||||
|
@ -71,12 +119,13 @@ boost::optional<marker_ptr> marker_cache::find(std::string const& uri, bool upda
|
|||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef MAPNIK_THREADSAFE
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
#endif
|
||||
typedef boost::unordered_map<std::string, marker_ptr>::const_iterator iterator_type;
|
||||
iterator_type itr = cache_.find(uri);
|
||||
if (itr != cache_.end())
|
||||
iterator_type itr = marker_cache_.find(uri);
|
||||
if (itr != marker_cache_.end())
|
||||
{
|
||||
result.reset(itr->second);
|
||||
return result;
|
||||
|
@ -84,14 +133,43 @@ boost::optional<marker_ptr> marker_cache::find(std::string const& uri, bool upda
|
|||
|
||||
try
|
||||
{
|
||||
// we can't find marker in cache, lets try to load it from filesystem
|
||||
// if uri references a built-in marker
|
||||
if (is_uri(uri))
|
||||
{
|
||||
boost::unordered_map<std::string, std::string>::const_iterator mark_itr = svg_cache_.find(uri);
|
||||
if (mark_itr == svg_cache_.end())
|
||||
{
|
||||
MAPNIK_LOG_ERROR(marker_cache) << "Marker does not exist: " << uri;
|
||||
return result;
|
||||
}
|
||||
std::string known_svg_string = mark_itr->second;
|
||||
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_from_string(known_svg_string);
|
||||
//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)
|
||||
{
|
||||
marker_cache_.insert(std::make_pair(uri,*result));
|
||||
}
|
||||
}
|
||||
// otherwise assume file-based
|
||||
else
|
||||
{
|
||||
boost::filesystem::path path(uri);
|
||||
if (!exists(path))
|
||||
{
|
||||
MAPNIK_LOG_ERROR(marker_cache) << "Marker does not exist: " << uri;
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_svg(uri))
|
||||
{
|
||||
using namespace mapnik::svg;
|
||||
|
@ -109,11 +187,12 @@ boost::optional<marker_ptr> marker_cache::find(std::string const& uri, bool upda
|
|||
result.reset(mark);
|
||||
if (update_cache)
|
||||
{
|
||||
cache_.insert(std::make_pair(uri,*result));
|
||||
marker_cache_.insert(std::make_pair(uri,*result));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO - support reading images from string
|
||||
std::auto_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(uri));
|
||||
if (reader.get())
|
||||
{
|
||||
|
@ -131,7 +210,7 @@ boost::optional<marker_ptr> marker_cache::find(std::string const& uri, bool upda
|
|||
result.reset(mark);
|
||||
if (update_cache)
|
||||
{
|
||||
cache_.insert(std::make_pair(uri,*result));
|
||||
marker_cache_.insert(std::make_pair(uri,*result));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -37,7 +37,7 @@ static const char * marker_placement_strings[] = {
|
|||
IMPLEMENT_ENUM( marker_placement_e, marker_placement_strings )
|
||||
|
||||
markers_symbolizer::markers_symbolizer()
|
||||
: symbolizer_with_image(path_expression_ptr(new path_expression)),
|
||||
: symbolizer_with_image(parse_path("shape://ellipse")),
|
||||
symbolizer_base(),
|
||||
width_(),
|
||||
height_(),
|
||||
|
@ -45,7 +45,7 @@ markers_symbolizer::markers_symbolizer()
|
|||
allow_overlap_(false),
|
||||
spacing_(100.0),
|
||||
max_error_(0.2),
|
||||
marker_p_(MARKER_LINE_PLACEMENT) {}
|
||||
marker_p_(MARKER_POINT_PLACEMENT) {}
|
||||
|
||||
markers_symbolizer::markers_symbolizer(path_expression_ptr const& filename)
|
||||
: symbolizer_with_image(filename),
|
||||
|
@ -56,7 +56,7 @@ markers_symbolizer::markers_symbolizer(path_expression_ptr const& filename)
|
|||
allow_overlap_(false),
|
||||
spacing_(100.0),
|
||||
max_error_(0.2),
|
||||
marker_p_(MARKER_LINE_PLACEMENT) {}
|
||||
marker_p_(MARKER_POINT_PLACEMENT) {}
|
||||
|
||||
markers_symbolizer::markers_symbolizer(markers_symbolizer const& rhs)
|
||||
: symbolizer_with_image(rhs),
|
||||
|
|
Loading…
Reference in a new issue