Permalink
Browse files

implement built in support for ellipse and arrow markers, make marker…

…s_symbolizer default to POINT placement and ellipse drawing, add back compatibility for deprecated marker-type property - refs #1285 and #1304
  • Loading branch information...
1 parent cd66495 commit 3e895ac6b7205d4490501ce66f83c2ae178fbca3 Dane Springmeyer committed Jul 11, 2012
@@ -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();
};
View
@@ -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
@@ -45,53 +45,131 @@
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;
if (uri.empty())
{
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;
}
try
{
- // we can't find marker in cache, lets try to load it from filesystem
- boost::filesystem::path path(uri);
- if (!exists(path))
+ // if uri references a built-in marker
+ if (is_uri(uri))
{
- MAPNIK_LOG_ERROR(marker_cache) << "Marker does not exist: " << 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;
+ }
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,15 +37,15 @@ 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_(),
ignore_placement_(false),
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),

0 comments on commit 3e895ac

Please sign in to comment.