Merge pull request #1311 from mapnik/stock-markers

Stock markers support
This commit is contained in:
Artem Pavlenko 2012-07-11 01:36:09 -07:00
commit 5f2c60261c
5 changed files with 135 additions and 25 deletions

View file

@ -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",

View file

@ -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();
};

View file

@ -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_;

View file

@ -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

View file

@ -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),