Merge branch 'master' into python-textplacement

This commit is contained in:
Hermann Kraus 2012-02-16 00:18:44 +01:00
commit ceda45249f
48 changed files with 748 additions and 633 deletions

View file

@ -134,7 +134,7 @@ mapnik::value_holder get_params_by_key2(mapnik::parameters const& p, std::string
mapnik::parameter get_params_by_index(mapnik::parameters const& p, int index)
{
if (index < 0 || index > p.size())
if (index < 0 || static_cast<unsigned>(index) > p.size())
{
PyErr_SetString(PyExc_IndexError, "Index is out of range");
throw boost::python::error_already_set();
@ -143,7 +143,7 @@ mapnik::parameter get_params_by_index(mapnik::parameters const& p, int index)
parameters::const_iterator itr = p.begin();
parameters::const_iterator end = p.end();
unsigned idx = 0;
int idx = 0;
while (itr != end)
{
if (idx == index)

View file

@ -60,13 +60,18 @@ public:
attribute_descriptor& operator=(attribute_descriptor const& other)
{
if (this == &other)
{
return *this;
name_=other.name_;
type_=other.type_;
primary_key_=other.primary_key_;
size_=other.size_;
precision_=other.precision_;
return *this;
}
else
{
name_=other.name_;
type_=other.type_;
primary_key_=other.primary_key_;
size_=other.size_;
precision_=other.precision_;
return *this;
}
}
std::string const& get_name() const

View file

@ -229,16 +229,17 @@ struct expression_grammar : qi::grammar<Iterator, expr_node(), space_type>
("\\r", '\r')("\\t", '\t')("\\v", '\v')("\\\\", '\\')
("\\\'", '\'')("\\\"", '\"')
;
#if BOOST_VERSION > 104500
quote_char %= char_('\'') | char_('"');
ustring %= omit[quote_char[_a = _1]]
>> *(unesc_char | "\\x" >> hex | (char_ - lit(_a)))
>> lit(_a);
quote_char %= char_('\'') | char_('"');
#if BOOST_VERSION > 104200
attr %= '[' >> no_skip[+~char_(']')] >> ']';
#else
ustring %= lit('\'')
>> *(unesc_char | "\\x" >> hex | (char_ - lit('\'')))
>> lit('\'');
attr %= '[' >> lexeme[+(char_ - ']')] >> ']';
#endif

View file

@ -32,7 +32,7 @@
namespace mapnik
{
MAPNIK_DECL std::string to_expression_string(expr_node const& );
MAPNIK_DECL std::string to_expression_string(expr_node const& node);
}
#endif // MAPNIK_EXPRESSION_STRING_HPP

View file

@ -128,7 +128,9 @@ public:
data_[itr->second] = val;
}
else
throw std::out_of_range("Key doesn't exist");
{
throw std::out_of_range(std::string("Key does not exist: '") + key + "'");
}
}
@ -162,7 +164,10 @@ public:
{
return data_[itr->second];
}
throw std::out_of_range("Key doesn't exist");
else
{
throw std::out_of_range(std::string("Key does not exist: '") + key + "'");
}
}
value_type const& get(std::size_t index) const

View file

@ -1,35 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#ifndef MAPNIK_FILL_HPP
#define MAPNIK_FILL_HPP
namespace mapnik
{
class fill
{
};
}
#endif // MAPNIK_FILL_HPP

View file

@ -0,0 +1,2 @@
#warning "filter_factory.hpp" is now called "expression.hpp"
#include <mapnik/expression.hpp>

View file

@ -0,0 +1,58 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2012 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#ifndef FORMATTING_EXPRESSION_HPP
#define FORMATTING_EXPRESSION_HPP
#include <mapnik/formatting/base.hpp>
#include <mapnik/expression.hpp>
namespace mapnik {
namespace formatting {
class expression_format: public node {
public:
void to_xml(boost::property_tree::ptree &xml) const;
static node_ptr from_xml(boost::property_tree::ptree const& xml);
virtual void apply(char_properties const& p, Feature const& feature, processed_text &output) const;
virtual void add_expressions(expression_set &output) const;
void set_child(node_ptr child);
node_ptr get_child() const;
expression_ptr face_name;
expression_ptr text_size;
expression_ptr character_spacing;
expression_ptr line_spacing;
expression_ptr text_opacity;
expression_ptr wrap_before;
expression_ptr wrap_char;
expression_ptr fill;
expression_ptr halo_fill;
expression_ptr halo_radius;
private:
node_ptr child_;
static expression_ptr get_expression(boost::property_tree::ptree const& xml, std::string name);
};
} //ns formatting
} //ns mapnik
#endif // FORMATTING_EXPRESSION_HPP

View file

@ -1,51 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#ifndef MAPNIK_GAMMA_HPP
#define MAPNIK_GAMMA_HPP
#include <cmath>
namespace mapnik
{
struct MAPNIK_DECL gamma
{
unsigned char g2l[256];
unsigned char l2g[256];
gamma(double gamma=2.0)
{
int result;
for (int i=0;i< 256;i++)
{
result=(int)(std::pow(i/255.0,gamma) * 255.0 + 0.5);
g2l[i]=(unsigned char)result;
}
for (int i = 0; i < 256; i++)
{
result = (int)(std::pow(i/255.0, 1/gamma) * 255.0 + 0.5);
l2g[i] = (unsigned char)result;
}
}
};
}
#endif // MAPNIK_GAMMA_HPP

View file

@ -48,6 +48,7 @@ public:
typedef T coord_type;
typedef Container<coord_type> container_type;
typedef typename container_type::value_type value_type;
typedef typename container_type::size_type size_type;
private:
container_type cont_;
eGeomType type_;
@ -389,11 +390,7 @@ public:
}
return false;
}
void set_capacity(size_t size)
{
cont_.set_capacity(size);
}
};
typedef geometry<double,vertex_vector> geometry_type;

View file

@ -25,7 +25,6 @@
// mapnik
#include <mapnik/color.hpp>
#include <mapnik/gamma.hpp>
#include <mapnik/image_data.hpp>
#include <mapnik/box2d.hpp>
#include <mapnik/image_view.hpp>

View file

@ -40,7 +40,8 @@ namespace mapnik { namespace json {
namespace qi = boost::spirit::qi;
namespace phoenix = boost::phoenix;
namespace ascii = boost::spirit::ascii;
namespace standard_wide = boost::spirit::standard_wide;
using standard_wide::space_type;
struct generate_id
{
@ -58,7 +59,7 @@ struct generate_id
template <typename Iterator, typename FeatureType>
struct feature_collection_grammar :
qi::grammar<Iterator, std::vector<feature_ptr>(), ascii::space_type>
qi::grammar<Iterator, std::vector<feature_ptr>(), space_type>
{
feature_collection_grammar(context_ptr const& ctx, mapnik::transcoder const& tr)
: feature_collection_grammar::base_type(feature_collection,"feature-collection"),
@ -113,10 +114,10 @@ struct feature_collection_grammar :
}
context_ptr ctx_;
qi::rule<Iterator, std::vector<feature_ptr>(), ascii::space_type> feature_collection; // START
qi::rule<Iterator, ascii::space_type> type;
qi::rule<Iterator, std::vector<feature_ptr>(), ascii::space_type> features;
qi::rule<Iterator, qi::locals<feature_ptr,int>, void(std::vector<feature_ptr>&), ascii::space_type> feature;
qi::rule<Iterator, std::vector<feature_ptr>(), space_type> feature_collection; // START
qi::rule<Iterator, space_type> type;
qi::rule<Iterator, std::vector<feature_ptr>(), space_type> features;
qi::rule<Iterator, qi::locals<feature_ptr,int>, void(std::vector<feature_ptr>&), space_type> feature;
feature_grammar<Iterator,FeatureType> feature_g;
boost::phoenix::function<generate_id> generate_id_;
};

View file

@ -41,7 +41,8 @@ namespace mapnik { namespace json {
namespace qi = boost::spirit::qi;
namespace phoenix = boost::phoenix;
namespace fusion = boost::fusion;
namespace ascii = boost::spirit::ascii;
namespace standard_wide = boost::spirit::standard_wide;
using standard_wide::space_type;
class attribute_value_visitor
: public boost::static_visitor<mapnik::value>
@ -132,7 +133,7 @@ struct cleanup
template <typename Iterator, typename FeatureType>
struct feature_grammar :
qi::grammar<Iterator, void(FeatureType&),
ascii::space_type>
space_type>
{
feature_grammar(mapnik::transcoder const& tr)
: feature_grammar::base_type(feature,"feature"),
@ -146,7 +147,7 @@ struct feature_grammar :
#else
using qi::lexeme;
#endif
using ascii::char_;
using standard_wide::char_;
using qi::_val;
using qi::_1;
using qi::_2;
@ -328,49 +329,49 @@ struct feature_grammar :
// start
// generic JSON
qi::rule<Iterator,ascii::space_type> value;
qi::rule<Iterator,space_type> value;
qi::symbols<char const, char const> unesc_char;
qi::uint_parser< unsigned, 16, 4, 4 > hex4 ;
qi::rule<Iterator,std::string(), ascii::space_type> string_;
qi::rule<Iterator,ascii::space_type> key_value;
qi::rule<Iterator,boost::variant<value_null,bool,int,double>(),ascii::space_type> number;
qi::rule<Iterator,ascii::space_type> object;
qi::rule<Iterator,ascii::space_type> array;
qi::rule<Iterator,ascii::space_type> pairs;
qi::rule<Iterator,std::string(), space_type> string_;
qi::rule<Iterator,space_type> key_value;
qi::rule<Iterator,boost::variant<value_null,bool,int,double>(),space_type> number;
qi::rule<Iterator,space_type> object;
qi::rule<Iterator,space_type> array;
qi::rule<Iterator,space_type> pairs;
qi::real_parser<double, qi::strict_real_policies<double> > strict_double;
// geoJSON
qi::rule<Iterator,void(FeatureType&),ascii::space_type> feature; // START
qi::rule<Iterator,ascii::space_type> feature_type;
qi::rule<Iterator,void(FeatureType&),space_type> feature; // START
qi::rule<Iterator,space_type> feature_type;
// Nabialek trick //////////////////////////////////////
//typedef typename qi::rule<Iterator,void(FeatureType &), ascii::space_type> dispatch_rule;
//qi::rule<Iterator,qi::locals<dispatch_rule*>, void(FeatureType&),ascii::space_type> geometry;
//typedef typename qi::rule<Iterator,void(FeatureType &), space_type> dispatch_rule;
//qi::rule<Iterator,qi::locals<dispatch_rule*>, void(FeatureType&),space_type> geometry;
//qi::symbols<char, dispatch_rule*> geometry_dispatch;
////////////////////////////////////////////////////////
qi::rule<Iterator,qi::locals<int>, void(FeatureType&),ascii::space_type> geometry;
qi::rule<Iterator,qi::locals<int>, void(FeatureType&),space_type> geometry;
qi::symbols<char, int> geometry_dispatch;
qi::rule<Iterator,void(CommandType,geometry_type*),ascii::space_type> point;
qi::rule<Iterator,qi::locals<CommandType>,void(geometry_type*),ascii::space_type> points;
qi::rule<Iterator,void(FeatureType &,int),ascii::space_type> coordinates;
qi::rule<Iterator,void(CommandType,geometry_type*),space_type> point;
qi::rule<Iterator,qi::locals<CommandType>,void(geometry_type*),space_type> points;
qi::rule<Iterator,void(FeatureType &,int),space_type> coordinates;
//
qi::rule<Iterator,qi::locals<geometry_type*>,
void(boost::ptr_vector<mapnik::geometry_type>& ),ascii::space_type> point_coordinates;
void(boost::ptr_vector<mapnik::geometry_type>& ),space_type> point_coordinates;
qi::rule<Iterator,qi::locals<geometry_type*>,
void(boost::ptr_vector<mapnik::geometry_type>& ),ascii::space_type> linestring_coordinates;
void(boost::ptr_vector<mapnik::geometry_type>& ),space_type> linestring_coordinates;
qi::rule<Iterator,qi::locals<geometry_type*>,
void(boost::ptr_vector<mapnik::geometry_type>& ),ascii::space_type> polygon_coordinates;
void(boost::ptr_vector<mapnik::geometry_type>& ),space_type> polygon_coordinates;
qi::rule<Iterator,void(boost::ptr_vector<mapnik::geometry_type>& ),ascii::space_type> multipoint_coordinates;
qi::rule<Iterator,void(boost::ptr_vector<mapnik::geometry_type>& ),ascii::space_type> multilinestring_coordinates;
qi::rule<Iterator,void(boost::ptr_vector<mapnik::geometry_type>& ),ascii::space_type> multipolygon_coordinates;
qi::rule<Iterator,void(FeatureType&),ascii::space_type> geometry_collection;
qi::rule<Iterator,void(boost::ptr_vector<mapnik::geometry_type>& ),space_type> multipoint_coordinates;
qi::rule<Iterator,void(boost::ptr_vector<mapnik::geometry_type>& ),space_type> multilinestring_coordinates;
qi::rule<Iterator,void(boost::ptr_vector<mapnik::geometry_type>& ),space_type> multipolygon_coordinates;
qi::rule<Iterator,void(FeatureType&),space_type> geometry_collection;
qi::rule<Iterator,void(FeatureType &),ascii::space_type> properties;
qi::rule<Iterator,qi::locals<std::string>, void(FeatureType &),ascii::space_type> attributes;
qi::rule<Iterator,boost::variant<value_null,bool,int,double,std::string>(), ascii::space_type> attribute_value;
qi::rule<Iterator,void(FeatureType &),space_type> properties;
qi::rule<Iterator,qi::locals<std::string>, void(FeatureType &),space_type> attributes;
qi::rule<Iterator,boost::variant<value_null,bool,int,double,std::string>(), space_type> attribute_value;
phoenix::function<put_property> put_property_;
phoenix::function<extract_geometry> extract_geometry_;

View file

@ -23,232 +23,66 @@
#ifndef MAPNIK_MARKERS_PLACEMENT_HPP
#define MAPNIK_MARKERS_PLACEMENT_HPP
// agg
#include "agg_basics.h"
// mapnik
#include <mapnik/box2d.hpp>
// boost
#include <boost/utility.hpp>
// stl
#include <cmath>
namespace mapnik {
template <typename Locator, typename Detector>
class markers_placement : boost::noncopyable
{
public:
/** Constructor for markers_placement object.
* \param locator Path along which markers are placed (type: vertex source)
* \param size Size of the marker
* \param detector Collision detection
* \param spacing Distance between markers. If the value is negative it is
* converted to a positive value with similar magnitude, but
* choosen to optimize marker placement. 0 = no markers
*/
markers_placement(Locator &locator, box2d<double> size, Detector &detector, double spacing, double max_error, bool allow_overlap);
/** Start again at first marker.
* \note Returns the same list of markers only works when they were NOT added
* to the detector.
*/
void rewind();
/** Get a point where the marker should be placed.
* Each time this function is called a new point is returned.
* \param x Return value for x position
* \param y Return value for x position
* \param angle Return value for rotation angle
* \param add_to_detector Add selected position to detector
* \return True if a place is found, false if none is found.
*/
bool get_point(double *x, double *y, double *angle, bool add_to_detector = true);
private:
Locator &locator_;
box2d<double> size_;
Detector &detector_;
double spacing_;
double max_error_;
bool allow_overlap_;
bool done_;
double last_x, last_y;
double next_x, next_y;
/** If a marker could not be placed at the exact point where it should
* go the next markers distance will be a bit lower. */
* go the next marker's distance will be a bit lower. */
double error_;
double max_error_;
double spacing_left_;
unsigned marker_nr_;
bool allow_overlap_;
/** Rotates the size_ box and translates the position. */
box2d<double> perform_transform(double angle, double dx, double dy);
/** Automatically chooses spacing. */
double find_optimal_spacing(double s);
/** Set spacing_left_, adjusts error_ and performs sanity checks. */
void set_spacing_left(double sl, bool allow_negative=false);
};
/** Constructor for markers_placement object.
* \param locator Path along which markers are placed (type: vertex source)
* \param size Size of the marker
* \param detector Collision detection
* \param spacing Distance between markers. If the value is negative it is
* converted to a positive value with similar magnitude, but
* choosen to optimize marker placement. 0 = no markers
*/
template <typename Locator, typename Detector> markers_placement<Locator, Detector>::markers_placement(
Locator &locator, box2d<double> size, Detector &detector, double spacing, double max_error, bool allow_overlap)
: locator_(locator), size_(size), detector_(detector), max_error_(max_error), allow_overlap_(allow_overlap)
{
if (spacing >= 0)
{
spacing_ = spacing;
} else if (spacing < 0)
{
spacing_ = find_optimal_spacing(-spacing);
}
rewind();
}
/** Autmatically chooses spacing. */
template <typename Locator, typename Detector> double markers_placement<Locator, Detector>::find_optimal_spacing(double s)
{
rewind();
//Calculate total path length
unsigned cmd = agg::path_cmd_move_to;
double length = 0;
while (!agg::is_stop(cmd))
{
double dx = next_x - last_x;
double dy = next_y - last_y;
length += std::sqrt(dx * dx + dy * dy);
last_x = next_x;
last_y = next_y;
while (agg::is_move_to(cmd = locator_.vertex(&next_x, &next_y)))
{
//Skip over "move" commands
last_x = next_x;
last_y = next_y;
}
}
unsigned points = round(length / s);
if (points == 0) return 0.0; //Path to short
return length / points;
}
/** Start again at first marker.
* \note Returning the same list of markers only works when they were NOT added
* to the detector.
*/
template <typename Locator, typename Detector> void markers_placement<Locator, Detector>::rewind()
{
locator_.rewind(0);
//Get first point
done_ = agg::is_stop(locator_.vertex(&next_x, &next_y)) || spacing_ < size_.width();
last_x = next_x;
last_y = next_y; // Force request of new segment
error_ = 0;
marker_nr_ = 0;
}
/** Get a point where the marker should be placed.
* Each time this function is called a new point is returned.
* \param x Return value for x position
* \param y Return value for x position
* \param angle Return value for rotation angle
* \param add_to_detector Add selected position to detector
* \return True if a place is found, false if none is found.
*/
template <typename Locator, typename Detector> bool markers_placement<Locator, Detector>::get_point(
double *x, double *y, double *angle, bool add_to_detector)
{
if (done_) return false;
unsigned cmd;
double spacing_left;
if (marker_nr_++ == 0)
{
spacing_left = spacing_ / 2;
} else
{
spacing_left = spacing_;
}
spacing_left -= error_;
error_ = 0;
while (true)
{
//Loop exits when a position is found or when no more segments are available
if (spacing_left < size_.width()/2)
{
//Do not place markers to close to the beginning of a segment
error_ += size_.width()/2 - spacing_left;
spacing_left = size_.width()/2;
}
if (abs(error_) > max_error_ * spacing_)
{
spacing_left += spacing_ - error_;
error_ = 0;
}
double dx = next_x - last_x;
double dy = next_y - last_y;
double d = std::sqrt(dx * dx + dy * dy);
if (d <= spacing_left)
{
//Segment is to short to place marker. Find next segment
spacing_left -= d;
last_x = next_x;
last_y = next_y;
while (agg::is_move_to(cmd = locator_.vertex(&next_x, &next_y)))
{
//Skip over "move" commands
last_x = next_x;
last_y = next_y;
}
if (agg::is_stop(cmd))
{
done_ = true;
return false;
}
continue; //Try again
}
//Check if marker really fits in this segment
if (d < size_.width())
{
//Segment to short => Skip this segment
error_ += d + size_.width()/2 - spacing_left;
spacing_left = d + size_.width()/2;
continue;
} else if (d - spacing_left < size_.width()/2)
{
//Segment is long enough, but we are to close to the end
//Note: This function moves backwards. This could lead to an infinite
// loop when another function adds a positive offset. Therefore we
// only move backwards when there is no offset
if (error_ == 0)
{
error_ += d - size_.width()/2 - spacing_left;
spacing_left = d - size_.width()/2;
} else
{
//Skip this segment
error_ += d + size_.width()/2 - spacing_left;
spacing_left = d + size_.width()/2;
}
continue; //Force checking of max_error constraint
}
*angle = atan2(dy, dx);
*x = last_x + dx * (spacing_left / d);
*y = last_y + dy * (spacing_left / d);
box2d<double> box = perform_transform(*angle, *x, *y);
if (!allow_overlap_ && !detector_.has_placement(box))
{
//10.0 is choosen arbitrarily
error_ += spacing_ * max_error_ / 10.0;
spacing_left += spacing_ * max_error_ / 10.0;
continue;
}
if (add_to_detector) detector_.insert(box);
last_x = *x;
last_y = *y;
return true;
}
}
/** Rotates the size_ box and translates the position. */
template <typename Locator, typename Detector> box2d<double> markers_placement<Locator, Detector>::perform_transform(double angle, double dx, double dy)
{
double c = cos(angle), s = sin(angle);
double x1 = size_.minx();
double x2 = size_.maxx();
double y1 = size_.miny();
double y2 = size_.maxy();
double x1_ = dx + x1 * c - y1 * s;
double y1_ = dy + x1 * s + y1 * c;
double x2_ = dx + x2 * c - y2 * s;
double y2_ = dy + x2 * s + y2 * c;
return box2d<double>(x1_, y1_, x2_, y2_);
}
}
#endif // MAPNIK_MARKERS_PLACEMENT_HPP

View file

@ -31,7 +31,7 @@
namespace mapnik {
class memory_featureset : public Featureset, private boost::noncopyable
class memory_featureset : public Featureset
{
public:
memory_featureset(box2d<double> const& bbox, memory_datasource const& ds)

View file

@ -1,36 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#ifndef MAPNIK_STYLE_FACTORY_HPP
#define MAPNIK_STYLE_FACTORY_HPP
//#include <mapnik/style.hpp>
namespace mapnik {
class style_factory
{
};
}
#endif // MAPNIK_STYLE_FACTORY_HPP

View file

@ -129,7 +129,7 @@ public:
virtual ~text_placements() {}
/** List of all properties used as the default for the subclasses. */
text_symbolizer_properties properties;
text_symbolizer_properties defaults;
};
/** Pointer to object of class text_placements */

View file

@ -162,7 +162,7 @@ struct text_symbolizer_properties
unsigned text_ratio;
unsigned wrap_width;
/** Default values for char_properties. */
char_properties default_format;
char_properties format;
private:
/** A tree of formatting::nodes which contain text and formatting information. */
formatting::node_ptr tree_;

View file

@ -36,35 +36,35 @@
namespace boost { namespace spirit { namespace traits {
template <>
struct is_container<mapnik::geometry_type const> : mpl::true_ {} ;
template <>
struct is_container<mapnik::geometry_type const> : mpl::true_ {} ;
template <>
struct container_iterator<mapnik::geometry_type const>
{
typedef mapnik::util::vertex_iterator<double> type;
};
template <>
struct container_iterator<mapnik::geometry_type const>
{
typedef mapnik::util::vertex_iterator<double> type;
};
template <>
struct begin_container<mapnik::geometry_type const>
{
static mapnik::util::vertex_iterator<double>
call (mapnik::geometry_type const& g)
{
return mapnik::util::vertex_iterator<double>(g.data());
}
};
template <>
struct begin_container<mapnik::geometry_type const>
{
static mapnik::util::vertex_iterator<double>
call (mapnik::geometry_type const& g)
{
return mapnik::util::vertex_iterator<double>(g.data());
}
};
template <>
struct end_container<mapnik::geometry_type const>
{
static mapnik::util::vertex_iterator<double>
call (mapnik::geometry_type const& g)
{
return mapnik::util::vertex_iterator<double>();
}
};
template <>
struct end_container<mapnik::geometry_type const>
{
static mapnik::util::vertex_iterator<double>
call (mapnik::geometry_type const& g)
{
return mapnik::util::vertex_iterator<double>();
}
};
}}}
}}}
#endif // CONTAINER_ADAPTER_HPP

View file

@ -46,12 +46,12 @@
namespace boost { namespace spirit { namespace traits {
// make gcc and darwin toolsets happy.
template <>
struct is_container<mapnik::geometry_container>
: mpl::false_
{};
template <>
struct is_container<mapnik::geometry_container>
: mpl::false_
{};
}}}
}}}
namespace mapnik { namespace util {

View file

@ -1,92 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#ifndef MAPNIK_VERTEX_TRANSFORM_HPP
#define MAPNIK_VERTEX_TRANSFORM_HPP
// mapnik
#include <mapnik/box2d.hpp>
#include <mapnik/vertex.hpp>
namespace mapnik
{
template <typename T0 ,typename T1,int shift=8>
struct Shift
{
typedef T0 value_type;
typedef T1 return_type;
static return_type apply(value_type val)
{
return static_cast<return_type>(val*(1<<shift));
}
};
template <typename T0,typename T1>
struct Shift<T0,T1,0>
{
typedef T0 value_type;
typedef T1 return_type;
static return_type apply(value_type val)
{
return static_cast<return_type>(val);
}
};
template <typename T>
struct Shift<T,T,0>
{
typedef T value_type;
typedef T return_type;
static T& apply(T& val)
{
return val;
}
};
typedef Shift<double,double,0> NO_SHIFT;
typedef Shift<double,int,0> SHIFT0;
typedef Shift<double,int,8> SHIFT8;
template <typename T0,typename T1,typename Trans>
struct view_transform;
template <typename Trans>
struct view_transform <vertex2d,vertex2d,Trans>
{
};
template <typename Trans>
struct view_transform <vertex2d,vertex2i,Trans>
{
};
template <typename Trans>
struct view_transform<box2d<double>,box2d<double>,Trans>
{
};
}
#endif // MAPNIK_VERTEX_TRANSFORM_HPP

View file

@ -51,18 +51,20 @@ class vertex_vector : private boost::noncopyable
block_mask = block_size - 1,
grow_by = 256
};
public:
// required for iterators support
typedef boost::tuple<unsigned,coord_type,coord_type> value_type;
typedef std::size_t size_type;
private:
unsigned num_blocks_;
unsigned max_blocks_;
coord_type** vertices_;
unsigned char** commands_;
unsigned pos_;
size_type pos_;
public:
// required for iterators support
typedef typename boost::tuple<unsigned,coord_type,coord_type> value_type;
vertex_vector()
: num_blocks_(0),
max_blocks_(0),
@ -83,7 +85,7 @@ public:
::operator delete(vertices_);
}
}
unsigned size() const
size_type size() const
{
return pos_;
}
@ -112,12 +114,7 @@ public:
*y = (*vertex);
return commands_[block] [pos & block_mask];
}
void set_capacity(size_t)
{
//do nothing
}
private:
void allocate_block(unsigned block)
{

View file

@ -30,6 +30,8 @@
#include <boost/utility.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/version.hpp>
// stl
#include <string>

View file

@ -857,7 +857,7 @@ boost::optional<mapnik::datasource::geometry_t> csv_datasource::get_geometry_typ
boost::optional<mapnik::datasource::geometry_t> result;
int multi_type = 0;
unsigned num_features = features_.size();
for (int i = 0; i < num_features && i < 5; ++i)
for (unsigned i = 0; i < num_features && i < 5; ++i)
{
mapnik::util::to_ds_type(features_[i]->paths(),result);
if (result)

View file

@ -373,8 +373,7 @@ void occi_featureset::convert_ordinates(mapnik::feature_ptr feature,
if (! is_single_geom && elem_size > SDO_ELEM_INFO_SIZE)
{
geometry_type* geom = new geometry_type(geom_type);
if (geom) geom->set_capacity(ord_size);
for (int i = SDO_ELEM_INFO_SIZE; i < elem_size; i+=3)
{
int next_offset = elem_info[i];
@ -434,8 +433,6 @@ void occi_featureset::convert_ordinates(mapnik::feature_ptr feature,
}
geom = new geometry_type(gtype);
geom->set_capacity((next_offset - 1) - (offset - 1 - dimensions));
fill_geometry_type(geom,
offset - 1,
next_offset - 1,
@ -458,8 +455,6 @@ void occi_featureset::convert_ordinates(mapnik::feature_ptr feature,
else
{
geometry_type * geom = new geometry_type(geom_type);
geom->set_capacity(ord_size);
fill_geometry_type(geom,
offset - 1,
ord_size,

View file

@ -137,7 +137,6 @@ void SDOPointType::writeSQL(oracle::occi::AnyData& streamOCCI_)
SDOPointType::~SDOPointType()
{
int i;
}
/*****************************************************************/
@ -309,6 +308,5 @@ void SDOGeometry::writeSQL(oracle::occi::AnyData& streamOCCI_)
SDOGeometry::~SDOGeometry()
{
int i;
delete SDO_POINT;
}

View file

@ -49,6 +49,13 @@ if env['RUNTIME_LINK'] == 'static':
plugin_env.ParseConfig(cmd)
plugin_env['LIBS'].append('proj')
if env.get('BOOST_LIB_VERSION_FROM_HEADER'):
boost_version_from_header = int(env['BOOST_LIB_VERSION_FROM_HEADER'].split('_')[1])
if boost_version_from_header < 46:
# avoid ubuntu issue with boost interprocess:
# https://github.com/mapnik/mapnik/issues/1082
plugin_env.Append(CXXFLAGS = '-fpermissive')
input_plugin = plugin_env.SharedLibrary('../ogr', source=ogr_src, SHLIBPREFIX='', SHLIBSUFFIX='.input', LINKFLAGS=env['CUSTOM_LDFLAGS'])
# if the plugin links to libmapnik ensure it is built first

View file

@ -87,7 +87,6 @@ void ogr_converter::convert_linestring(OGRLineString* geom, feature_ptr feature)
{
int num_points = geom->getNumPoints();
geometry_type* line = new geometry_type(mapnik::LineString);
line->set_capacity(num_points);
line->move_to(geom->getX(0), geom->getY(0));
for (int i = 1; i < num_points; ++i)
{
@ -108,7 +107,6 @@ void ogr_converter::convert_polygon(OGRPolygon* geom, feature_ptr feature)
capacity += interior->getNumPoints();
}
geometry_type* poly = new geometry_type(mapnik::Polygon);
poly->set_capacity(num_points + capacity);
poly->move_to(exterior->getX(0), exterior->getY(0));
for (int i = 1; i < num_points; ++i)
{

View file

@ -103,7 +103,6 @@ feature_ptr osm_featureset<filterT>::next()
geom = new geometry_type(mapnik::LineString);
}
geom->set_capacity(static_cast<osm_way*>(cur_item)->nodes.size());
geom->move_to(static_cast<osm_way*>(cur_item)->nodes[0]->lon,
static_cast<osm_way*>(cur_item)->nodes[0]->lat);

View file

@ -362,7 +362,7 @@ std::string postgis_datasource::sql_bbox(box2d<double> const& env) const
{
std::ostringstream b;
if (srid_ > 0)
b << "SetSRID(";
b << "ST_SetSRID(";
b << "'BOX3D(";
b << std::setprecision(16);
b << env.minx() << " " << env.miny() << ",";
@ -502,15 +502,18 @@ featureset_ptr postgis_datasource::features(const query& q) const
std::ostringstream s;
s << "SELECT ST_AsBinary(\"" << geometryColumn_ << "\") AS geom";
mapnik::context_ptr ctx = boost::make_shared<mapnik::context_type>();
if (!key_field_.empty())
{
mapnik::sql_utils::quote_attr(s,key_field_);
ctx->push(key_field_);
}
std::set<std::string> const& props=q.property_names();
std::set<std::string>::const_iterator pos=props.begin();
std::set<std::string>::const_iterator end=props.end();
mapnik::context_ptr ctx = boost::make_shared<mapnik::context_type>();
for ( ;pos != end;++pos)
{
mapnik::sql_utils::quote_attr(s,*pos);
@ -526,9 +529,6 @@ featureset_ptr postgis_datasource::features(const query& q) const
}
boost::shared_ptr<IResultSet> rs = get_resultset(conn, s.str());
unsigned num_attr = props.size();
if (!key_field_.empty())
++num_attr;
return boost::make_shared<postgis_featureset>(rs, ctx, desc_.get_encoding(), !key_field_.empty());
}
else
@ -574,11 +574,14 @@ featureset_ptr postgis_datasource::features_at_point(coord2d const& pt) const
std::ostringstream s;
s << "SELECT ST_AsBinary(\"" << geometryColumn_ << "\") AS geom";
if (!key_field_.empty())
mapnik::sql_utils::quote_attr(s,key_field_);
mapnik::context_ptr ctx = boost::make_shared<mapnik::context_type>();
if (!key_field_.empty())
{
mapnik::sql_utils::quote_attr(s,key_field_);
ctx->push(key_field_);
}
std::vector<attribute_descriptor>::const_iterator itr = desc_.get_descriptors().begin();
std::vector<attribute_descriptor>::const_iterator end = desc_.get_descriptors().end();

View file

@ -49,6 +49,13 @@ libraries.append('boost_filesystem%s' % env['BOOST_APPEND'])
if env['SHAPE_MEMORY_MAPPED_FILE']:
plugin_env.Append(CXXFLAGS = '-DSHAPE_MEMORY_MAPPED_FILE')
if env.get('BOOST_LIB_VERSION_FROM_HEADER'):
boost_version_from_header = int(env['BOOST_LIB_VERSION_FROM_HEADER'].split('_')[1])
if boost_version_from_header < 46:
# avoid ubuntu issue with boost interprocess:
# https://github.com/mapnik/mapnik/issues/1082
plugin_env.Append(CXXFLAGS = '-fpermissive')
input_plugin = plugin_env.SharedLibrary('../shape', SHLIBSUFFIX='.input', source=shape_src, SHLIBPREFIX='', LIBS = libraries, LINKFLAGS=env['CUSTOM_LDFLAGS'])
# if the plugin links to libmapnik ensure it is built first

View file

@ -60,8 +60,9 @@ void agg_renderer<T>::process(polygon_symbolizer const& sym,
unsigned g=fill_.green();
unsigned b=fill_.blue();
unsigned a=fill_.alpha();
renb.clip_box(0,0,width_,height_);
renderer ren(renb);
ras_ptr->reset();
switch (sym.get_gamma_method())
{

View file

@ -164,6 +164,8 @@ source = Split(
svg_transform_parser.cpp
warp.cpp
json/feature_collection_parser.cpp
markers_placement.cpp
formatting/expression.cpp
"""
)
@ -358,6 +360,8 @@ wkt_includes = glob.glob('../include/mapnik/wkt/*.hpp')
grid_includes = glob.glob('../include/mapnik/grid/*.hpp')
json_includes = glob.glob('../include/mapnik/json/*.hpp')
util_includes = glob.glob('../include/mapnik/util/*.hpp')
text_placements_includes = glob.glob('../include/mapnik/text_placements/*.hpp')
formatting_includes = glob.glob('../include/mapnik/formatting/*.hpp')
inc_target = os.path.normpath(env['INSTALL_PREFIX']+'/include/mapnik')
svg_inc_target = os.path.normpath(env['INSTALL_PREFIX']+'/include/mapnik/svg')
@ -365,6 +369,8 @@ wkt_inc_target = os.path.normpath(env['INSTALL_PREFIX']+'/include/mapnik/wkt')
grid_inc_target = os.path.normpath(env['INSTALL_PREFIX']+'/include/mapnik/grid')
json_inc_target = os.path.normpath(env['INSTALL_PREFIX']+'/include/mapnik/json')
util_inc_target = os.path.normpath(env['INSTALL_PREFIX']+'/include/mapnik/util')
text_placements_inc_target = os.path.normpath(env['INSTALL_PREFIX']+'/include/mapnik/text_placements')
formatting_inc_target = os.path.normpath(env['INSTALL_PREFIX']+'/include/mapnik/formatting')
if 'uninstall' not in COMMAND_LINE_TARGETS:
env.Alias(target='install', source=env.Install(inc_target, includes))
@ -373,6 +379,8 @@ if 'uninstall' not in COMMAND_LINE_TARGETS:
env.Alias(target='install', source=env.Install(grid_inc_target, grid_includes))
env.Alias(target='install', source=env.Install(json_inc_target, json_includes))
env.Alias(target='install', source=env.Install(util_inc_target, util_includes))
env.Alias(target='install', source=env.Install(text_placements_inc_target, text_placements_includes))
env.Alias(target='install', source=env.Install(formatting_inc_target, formatting_includes))
env['create_uninstall_target'](env, inc_target)
env['create_uninstall_target'](env, svg_inc_target)
@ -380,3 +388,5 @@ env['create_uninstall_target'](env, wkt_inc_target)
env['create_uninstall_target'](env, grid_inc_target)
env['create_uninstall_target'](env, json_inc_target)
env['create_uninstall_target'](env, util_inc_target)
env['create_uninstall_target'](env, text_placements_inc_target)
env['create_uninstall_target'](env, formatting_inc_target)

View file

@ -0,0 +1,144 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2012 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
// mapnik
#include <mapnik/formatting/expression.hpp>
#include <mapnik/ptree_helpers.hpp>
#include <mapnik/expression_string.hpp>
#include <mapnik/expression_evaluator.hpp>
#include <mapnik/text_properties.hpp>
#include <mapnik/feature.hpp>
// boost
namespace mapnik
{
namespace formatting
{
using boost::property_tree::ptree;
void expression_format::to_xml(boost::property_tree::ptree &xml) const
{
ptree &new_node = xml.push_back(ptree::value_type("Format", ptree()))->second;
if (face_name) set_attr(new_node, "face-name", to_expression_string(*face_name));
if (text_size) set_attr(new_node, "size", to_expression_string(*text_size));
if (character_spacing) set_attr(new_node, "character-spacing", to_expression_string*character_spacing);
if (line_spacing) set_attr(new_node, "line-spacing", to_expression_string(*line_spacing));
if (text_opacity) set_attr(new_node, "opacity", to_expression_string(*text_opacity));
if (wrap_before) set_attr(new_node, "wrap-before", to_expression_string(*wrap_before));
if (wrap_char) set_attr(new_node, "wrap-character", to_expression_string(*wrap_char));
if (fill) set_attr(new_node, "fill", to_expression_string(*fill));
if (halo_fill) set_attr(new_node, "halo-fill", to_expression_string(*halo_fill));
if (halo_radius) set_attr(new_node, "halo-radius", to_expression_string(*halo_radius));
if (child_) child_->to_xml(new_node);
}
node_ptr expression_format::from_xml(ptree const& xml)
{
expression_format *n = new expression_format();
node_ptr np(n);
node_ptr child = node::from_xml(xml);
n->set_child(child);
n->face_name = get_expression(xml, "face-name");
n->text_size = get_expression(xml, "size");
n->character_spacing = get_expression(xml, "character-spacing");
n->line_spacing = get_expression(xml, "line-spacing");
n->text_opacity = get_expression(xml, "opactity");
n->wrap_before = get_expression(xml, "wrap-before");
n->wrap_char = get_expression(xml, "wrap-character");
n->fill = get_expression(xml, "fill");
n->halo_fill = get_expression(xml, "halo-fill");
n->halo_radius = get_expression(xml, "halo-radius");
return np;
}
expression_ptr expression_format::get_expression(ptree const& xml, std::string name)
{
boost::optional<std::string> tmp = get_opt_attr<std::string>(xml, name);
if (tmp) return parse_expression(*tmp);
return expression_ptr();
}
void expression_format::apply(char_properties const& p, const Feature &feature, processed_text &output) const
{
char_properties new_properties = p;
if (face_name) new_properties.face_name =
boost::apply_visitor(evaluate<Feature,value_type>(feature), *face_name).to_string();
if (text_size) new_properties.text_size =
boost::apply_visitor(evaluate<Feature,value_type>(feature), *text_size).to_double();
if (character_spacing) new_properties.character_spacing =
boost::apply_visitor(evaluate<Feature,value_type>(feature), *character_spacing).to_double();
if (line_spacing) new_properties.line_spacing =
boost::apply_visitor(evaluate<Feature,value_type>(feature), *line_spacing).to_double();
if (text_opacity) new_properties.text_opacity =
boost::apply_visitor(evaluate<Feature,value_type>(feature), *text_opacity).to_double();
if (wrap_before) new_properties.wrap_before =
boost::apply_visitor(evaluate<Feature,value_type>(feature), *wrap_before).to_bool();
if (wrap_char) new_properties.wrap_char =
boost::apply_visitor(evaluate<Feature,value_type>(feature), *character_spacing).to_unicode()[0];
// if (fill) new_properties.fill =
// boost::apply_visitor(evaluate<Feature,value_type>(feature), *fill).to_color();
// if (halo_fill) new_properties.halo_fill =
// boost::apply_visitor(evaluate<Feature,value_type>(feature), *halo_fill).to_color();
if (halo_radius) new_properties.halo_radius =
boost::apply_visitor(evaluate<Feature,value_type>(feature), *halo_radius).to_double();
if (child_) {
child_->apply(new_properties, feature, output);
} else {
#ifdef MAPNIK_DEBUG
std::cerr << "Warning: Useless format: No text to format\n";
#endif
}
}
void expression_format::set_child(node_ptr child)
{
child_ = child;
}
node_ptr expression_format::get_child() const
{
return child_;
}
void expression_format::add_expressions(expression_set &output) const
{
if (child_) child_->add_expressions(output);
output.insert(face_name);
output.insert(text_size);
output.insert(character_spacing);
output.insert(line_spacing);
output.insert(text_opacity);
output.insert(wrap_before);
output.insert(wrap_char);
output.insert(fill);
output.insert(halo_fill);
output.insert(halo_radius);
}
} //ns formatting
} //ns mapnik

View file

@ -43,7 +43,7 @@ bool feature_collection_parser::parse(std::string const& json, std::vector<mapni
using namespace boost::spirit;
iterator_type first = json.begin();
iterator_type last = json.end();
return qi::phrase_parse(first, last, *grammar_, ascii::space, features);
return qi::phrase_parse(first, last, *grammar_, standard_wide::space, features);
#else
std::ostringstream s;
s << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000 << "." << BOOST_VERSION % 100;

View file

@ -1281,10 +1281,10 @@ void map_parser::parse_text_symbolizer( rule & rule, ptree const & sym )
placement_finder = text_placements_ptr(new text_placements_dummy());
}
placement_finder->properties.from_xml(sym, fontsets_);
placement_finder->defaults.from_xml(sym, fontsets_);
if (strict_ &&
!placement_finder->properties.default_format.fontset.size())
ensure_font_face(placement_finder->properties.default_format.face_name);
!placement_finder->defaults.format.fontset.size())
ensure_font_face(placement_finder->defaults.format.face_name);
if (list) {
ptree::const_iterator symIter = sym.begin();
ptree::const_iterator endSym = sym.end();
@ -1299,8 +1299,8 @@ void map_parser::parse_text_symbolizer( rule & rule, ptree const & sym )
text_symbolizer_properties & p = list->add();
p.from_xml(symIter->second, fontsets_);
if (strict_ &&
!p.default_format.fontset.size())
ensure_font_face(p.default_format.face_name);
!p.format.fontset.size())
ensure_font_face(p.format.face_name);
}
}
@ -1354,10 +1354,10 @@ void map_parser::parse_shield_symbolizer( rule & rule, ptree const & sym )
placement_finder = text_placements_ptr(new text_placements_dummy());
}
placement_finder->properties.from_xml(sym, fontsets_);
placement_finder->defaults.from_xml(sym, fontsets_);
if (strict_ &&
!placement_finder->properties.default_format.fontset.size())
ensure_font_face(placement_finder->properties.default_format.face_name);
!placement_finder->defaults.format.fontset.size())
ensure_font_face(placement_finder->defaults.format.face_name);
if (list) {
ptree::const_iterator symIter = sym.begin();
ptree::const_iterator endSym = sym.end();
@ -1372,8 +1372,8 @@ void map_parser::parse_shield_symbolizer( rule & rule, ptree const & sym )
text_symbolizer_properties & p = list->add();
p.from_xml(symIter->second, fontsets_);
if (strict_&&
!placement_finder->properties.default_format.fontset.size())
ensure_font_face(p.default_format.face_name);
!p.format.fontset.size())
ensure_font_face(p.format.face_name);
}
}

232
src/markers_placement.cpp Normal file
View file

@ -0,0 +1,232 @@
// mapnik
#include <mapnik/markers_placement.hpp>
#include <mapnik/geometry.hpp>
#include <mapnik/ctrans.hpp>
#include <mapnik/label_collision_detector.hpp>
// agg
#include "agg_basics.h"
// stl
#include <cmath>
namespace mapnik
{
template <typename Locator, typename Detector>
markers_placement<Locator, Detector>::markers_placement(
Locator &locator, box2d<double> size, Detector &detector, double spacing, double max_error, bool allow_overlap)
: locator_(locator), size_(size), detector_(detector), max_error_(max_error), allow_overlap_(allow_overlap)
{
if (spacing >= 0)
{
spacing_ = spacing;
} else if (spacing < 0)
{
spacing_ = find_optimal_spacing(-spacing);
}
rewind();
}
template <typename Locator, typename Detector>
double markers_placement<Locator, Detector>::find_optimal_spacing(double s)
{
rewind();
//Calculate total path length
unsigned cmd = agg::path_cmd_move_to;
double length = 0;
while (!agg::is_stop(cmd))
{
double dx = next_x - last_x;
double dy = next_y - last_y;
length += std::sqrt(dx * dx + dy * dy);
last_x = next_x;
last_y = next_y;
while (agg::is_move_to(cmd = locator_.vertex(&next_x, &next_y)))
{
//Skip over "move" commands
last_x = next_x;
last_y = next_y;
}
}
unsigned points = round(length / s);
if (points == 0) return 0.0; //Path to short
return length / points;
}
template <typename Locator, typename Detector>
void markers_placement<Locator, Detector>::rewind()
{
locator_.rewind(0);
//Get first point
done_ = agg::is_stop(locator_.vertex(&next_x, &next_y)) || spacing_ < size_.width();
last_x = next_x;
last_y = next_y; // Force request of new segment
error_ = 0;
marker_nr_ = 0;
}
template <typename Locator, typename Detector>
bool markers_placement<Locator, Detector>::get_point(
double *x, double *y, double *angle, bool add_to_detector)
{
if (done_) return false;
unsigned cmd;
/* This functions starts at the position of the previous marker,
walks along the path, counting how far it has to go in spacing_left.
If one marker can't be placed at the position it should go to it is
moved a bit. The error is compensated for in the next call to this
function.
error > 0: Marker too near to the end of the path.
error = 0: Perfect position.
error < 0: Marker too near to the beginning of the path.
*/
if (marker_nr_++ == 0)
{
//First marker
spacing_left_ = spacing_ / 2;
} else
{
spacing_left_ = spacing_;
}
spacing_left_ -= error_;
error_ = 0;
//Loop exits when a position is found or when no more segments are available
while (true)
{
//Do not place markers too close to the beginning of a segment
if (spacing_left_ < size_.width()/2)
{
set_spacing_left(size_.width()/2); //Only moves forward
}
//Error for this marker is too large. Skip to the next position.
if (abs(error_) > max_error_ * spacing_)
{
if (error_ > spacing_) {
error_ = 0; //Avoid moving backwards
#ifdef MAPNIK_DEBUG
std::cerr << "WARNING: Extremely large error in markers_placement. Please file a bug report.\n";
#endif
}
spacing_left_ += spacing_ - error_;
error_ = 0;
}
double dx = next_x - last_x;
double dy = next_y - last_y;
double segment_length = std::sqrt(dx * dx + dy * dy);
if (segment_length <= spacing_left_)
{
//Segment is to short to place marker. Find next segment
spacing_left_ -= segment_length;
last_x = next_x;
last_y = next_y;
while (agg::is_move_to(cmd = locator_.vertex(&next_x, &next_y)))
{
//Skip over "move" commands
last_x = next_x;
last_y = next_y;
}
if (agg::is_stop(cmd))
{
done_ = true;
return false;
}
continue; //Try again
}
/* At this point we know the following things:
- segment_length > spacing_left
- error is small enough
- at least half a marker fits into this segment
*/
//Check if marker really fits in this segment
if (segment_length < size_.width())
{
//Segment to short => Skip this segment
set_spacing_left(segment_length + size_.width()/2); //Only moves forward
continue;
} else if (segment_length - spacing_left_ < size_.width()/2)
{
//Segment is long enough, but we are to close to the end
//Note: This function moves backwards. This could lead to an infinite
// loop when another function adds a positive offset. Therefore we
// only move backwards when there is no offset
if (error_ == 0)
{
set_spacing_left(segment_length - size_.width()/2, true);
} else
{
//Skip this segment
set_spacing_left(segment_length + size_.width()/2); //Only moves forward
}
continue; //Force checking of max_error constraint
}
*angle = atan2(dy, dx);
*x = last_x + dx * (spacing_left_ / segment_length);
*y = last_y + dy * (spacing_left_ / segment_length);
box2d<double> box = perform_transform(*angle, *x, *y);
if (!allow_overlap_ && !detector_.has_placement(box))
{
//10.0 is the approxmiate number of positions tried and choosen arbitrarily
set_spacing_left(spacing_left_ + spacing_ * max_error_ / 10.0); //Only moves forward
continue;
}
if (add_to_detector) detector_.insert(box);
last_x = *x;
last_y = *y;
return true;
}
}
template <typename Locator, typename Detector>
box2d<double> markers_placement<Locator, Detector>::perform_transform(double angle, double dx, double dy)
{
double c = cos(angle), s = sin(angle);
double x1 = size_.minx();
double x2 = size_.maxx();
double y1 = size_.miny();
double y2 = size_.maxy();
double x1_ = dx + x1 * c - y1 * s;
double y1_ = dy + x1 * s + y1 * c;
double x2_ = dx + x2 * c - y2 * s;
double y2_ = dy + x2 * s + y2 * c;
return box2d<double>(x1_, y1_, x2_, y2_);
}
template <typename Locator, typename Detector>
void markers_placement<Locator, Detector>::set_spacing_left(double sl, bool allow_negative)
{
double delta_error = sl - spacing_left_;
if (!allow_negative && delta_error < 0)
{
#ifdef MAPNIK_DEBUG
std::cerr << "WARNING: Unexpected negative error in markers_placement. Please file a bug report.\n";
#endif
return;
}
#ifdef MAPNIK_DEBUG
if (delta_error == 0.0)
{
std::cerr << "WARNING: Not moving at all in set_spacing_left()! Please file a bug report.\n";
}
#endif
error_ += delta_error;
spacing_left_ = sl;
}
typedef coord_transform2<CoordTransform,geometry_type> path_type;
template class markers_placement<path_type, label_collision_detector4>;
} //ns mapnik

View file

@ -357,7 +357,7 @@ private:
void add_font_attributes(ptree & node, const text_symbolizer & sym)
{
text_placements_ptr p = sym.get_placement_options();
p->properties.to_xml(node, explicit_defaults_);
p->defaults.to_xml(node, explicit_defaults_);
/* Known types:
- text_placements_dummy: no handling required
- text_placements_simple: positions string
@ -366,13 +366,14 @@ private:
text_placements_simple *simple = dynamic_cast<text_placements_simple *>(p.get());
text_placements_list *list = dynamic_cast<text_placements_list *>(p.get());
if (simple) {
set_attr(node, "placment-type", "simple");
set_attr(node, "placement-type", "simple");
set_attr(node, "placements", simple->get_positions());
}
if (list) {
set_attr(node, "placment-type", "list");
set_attr(node, "placement-type", "list");
unsigned i;
text_symbolizer_properties *dfl = &(list->properties);
//dfl = last properties passed as default so only attributes that change are actually written
text_symbolizer_properties *dfl = &(list->defaults);
for (i=0; i < list->size(); i++) {
ptree &placement_node = node.push_back(ptree::value_type("Placement", ptree()))->second;
list->get(i).to_xml(placement_node, explicit_defaults_, *dfl);

View file

@ -68,7 +68,7 @@ void text_symbolizer_properties::process(processed_text &output, Feature const&
{
output.clear();
if (tree_) {
tree_->apply(default_format, feature, output);
tree_->apply(format, feature, output);
} else {
#ifdef MAPNIK_DEBUG
std::cerr << "Warning: text_symbolizer_properties can't produce text: No formatting tree!\n";
@ -130,7 +130,7 @@ void text_symbolizer_properties::from_xml(boost::property_tree::ptree const &sym
set_old_style_expression(parse_expression(*name_, "utf8"));
}
default_format.from_xml(sym, fontsets);
format.from_xml(sym, fontsets);
formatting::node_ptr n(formatting::node::from_xml(sym));
if (n) set_format_tree(n);
}
@ -213,7 +213,7 @@ void text_symbolizer_properties::to_xml(boost::property_tree::ptree &node, bool
{
set_attr(node, "vertical-alignment", valign);
}
default_format.to_xml(node, explicit_defaults, dfl.default_format);
format.to_xml(node, explicit_defaults, dfl.format);
if (tree_) tree_->to_xml(node);
}
@ -352,13 +352,13 @@ void char_properties::to_xml(boost::property_tree::ptree &node, bool explicit_de
/************************************************************************/
text_placements::text_placements() : properties()
text_placements::text_placements() : defaults()
{
}
void text_placements::add_expressions(expression_set &output)
{
properties.add_expressions(output);
defaults.add_expressions(output);
}
@ -366,7 +366,7 @@ void text_placements::add_expressions(expression_set &output)
text_placement_info::text_placement_info(text_placements const* parent,
double scale_factor_, dimension_type dim, bool has_dimensions_)
: properties(parent->properties),
: properties(parent->defaults),
scale_factor(scale_factor_),
has_dimensions(has_dimensions_),
dimensions(dim),
@ -397,7 +397,7 @@ bool text_placement_info_simple::next()
if (state > 0)
{
if (state > parent_->text_sizes_.size()) return false;
properties.default_format.text_size = parent_->text_sizes_[state-1];
properties.format.text_size = parent_->text_sizes_[state-1];
}
if (!next_position_only()) {
state++;
@ -411,7 +411,7 @@ bool text_placement_info_simple::next()
bool text_placement_info_simple::next_position_only()
{
const position &pdisp = parent_->properties.displacement;
const position &pdisp = parent_->defaults.displacement;
position &displacement = properties.displacement;
if (position_state >= parent_->direction_.size()) return false;
directions_t dir = parent_->direction_[position_state];
@ -523,7 +523,7 @@ std::string text_placements_simple::get_positions()
bool text_placement_info_list::next()
{
if (state == 0) {
properties = parent_->properties;
properties = parent_->defaults;
} else {
if (state-1 >= parent_->list_.size()) return false;
properties = parent_->list_[state-1];
@ -538,7 +538,7 @@ text_symbolizer_properties & text_placements_list::add()
text_symbolizer_properties &last = list_.back();
list_.push_back(last); //Preinitialize with old values
} else {
list_.push_back(properties);
list_.push_back(defaults);
}
return list_.back();
}
@ -564,7 +564,7 @@ text_placements_list::text_placements_list() : text_placements(), list_(0)
void text_placements_list::add_expressions(expression_set &output)
{
properties.add_expressions(output);
defaults.add_expressions(output);
std::vector<text_symbolizer_properties>::const_iterator it;
for (it=list_.begin(); it != list_.end(); it++)

View file

@ -22,6 +22,7 @@
#include <mapnik/formatting/text.hpp>
#include <mapnik/formatting/list.hpp>
#include <mapnik/formatting/format.hpp>
#include <mapnik/formatting/expression.hpp>
#include <mapnik/processed_text.hpp>
#include <mapnik/color.hpp>
#include <mapnik/feature.hpp>
@ -62,6 +63,8 @@ node_ptr node::from_xml(boost::property_tree::ptree const& xml)
n = text_node::from_xml(itr->second);
} else if (itr->first == "Format") {
n = format_node::from_xml(itr->second);
} else if (itr->first == "ExpressionFormat") {
n = expression_format::from_xml(itr->second);
} else if (itr->first != "<xmlcomment>" && itr->first != "<xmlattr>" && itr->first != "Placement") {
throw config_error("Unknown item " + itr->first);
}

View file

@ -138,312 +138,312 @@ expression_ptr text_symbolizer::get_name() const
void text_symbolizer::set_name(expression_ptr name)
{
placement_options_->properties.set_old_style_expression(name);
placement_options_->defaults.set_old_style_expression(name);
}
expression_ptr text_symbolizer::get_orientation() const
{
return placement_options_->properties.orientation;
return placement_options_->defaults.orientation;
}
void text_symbolizer::set_orientation(expression_ptr orientation)
{
placement_options_->properties.orientation = orientation;
placement_options_->defaults.orientation = orientation;
}
std::string const& text_symbolizer::get_face_name() const
{
return placement_options_->properties.default_format.face_name;
return placement_options_->defaults.format.face_name;
}
void text_symbolizer::set_face_name(std::string face_name)
{
placement_options_->properties.default_format.face_name = face_name;
placement_options_->defaults.format.face_name = face_name;
}
void text_symbolizer::set_fontset(font_set const& fontset)
{
placement_options_->properties.default_format.fontset = fontset;
placement_options_->defaults.format.fontset = fontset;
}
font_set const& text_symbolizer::get_fontset() const
{
return placement_options_->properties.default_format.fontset;
return placement_options_->defaults.format.fontset;
}
unsigned text_symbolizer::get_text_ratio() const
{
return placement_options_->properties.text_ratio;
return placement_options_->defaults.text_ratio;
}
void text_symbolizer::set_text_ratio(unsigned ratio)
{
placement_options_->properties.text_ratio = ratio;
placement_options_->defaults.text_ratio = ratio;
}
unsigned text_symbolizer::get_wrap_width() const
{
return placement_options_->properties.wrap_width;
return placement_options_->defaults.wrap_width;
}
void text_symbolizer::set_wrap_width(unsigned width)
{
placement_options_->properties.wrap_width = width;
placement_options_->defaults.wrap_width = width;
}
bool text_symbolizer::get_wrap_before() const
{
return placement_options_->properties.default_format.wrap_before;
return placement_options_->defaults.format.wrap_before;
}
void text_symbolizer::set_wrap_before(bool wrap_before)
{
placement_options_->properties.default_format.wrap_before = wrap_before;
placement_options_->defaults.format.wrap_before = wrap_before;
}
unsigned char text_symbolizer::get_wrap_char() const
{
return placement_options_->properties.default_format.wrap_char;
return placement_options_->defaults.format.wrap_char;
}
std::string text_symbolizer::get_wrap_char_string() const
{
return std::string(1, placement_options_->properties.default_format.wrap_char);
return std::string(1, placement_options_->defaults.format.wrap_char);
}
void text_symbolizer::set_wrap_char(unsigned char character)
{
placement_options_->properties.default_format.wrap_char = character;
placement_options_->defaults.format.wrap_char = character;
}
void text_symbolizer::set_wrap_char_from_string(std::string const& character)
{
placement_options_->properties.default_format.wrap_char = (character)[0];
placement_options_->defaults.format.wrap_char = (character)[0];
}
text_transform_e text_symbolizer::get_text_transform() const
{
return placement_options_->properties.default_format.text_transform;
return placement_options_->defaults.format.text_transform;
}
void text_symbolizer::set_text_transform(text_transform_e convert)
{
placement_options_->properties.default_format.text_transform = convert;
placement_options_->defaults.format.text_transform = convert;
}
unsigned text_symbolizer::get_line_spacing() const
{
return placement_options_->properties.default_format.line_spacing;
return placement_options_->defaults.format.line_spacing;
}
void text_symbolizer::set_line_spacing(unsigned spacing)
{
placement_options_->properties.default_format.line_spacing = spacing;
placement_options_->defaults.format.line_spacing = spacing;
}
unsigned text_symbolizer::get_character_spacing() const
{
return placement_options_->properties.default_format.character_spacing;
return placement_options_->defaults.format.character_spacing;
}
void text_symbolizer::set_character_spacing(unsigned spacing)
{
placement_options_->properties.default_format.character_spacing = spacing;
placement_options_->defaults.format.character_spacing = spacing;
}
unsigned text_symbolizer::get_label_spacing() const
{
return placement_options_->properties.label_spacing;
return placement_options_->defaults.label_spacing;
}
void text_symbolizer::set_label_spacing(unsigned spacing)
{
placement_options_->properties.label_spacing = spacing;
placement_options_->defaults.label_spacing = spacing;
}
unsigned text_symbolizer::get_label_position_tolerance() const
{
return placement_options_->properties.label_position_tolerance;
return placement_options_->defaults.label_position_tolerance;
}
void text_symbolizer::set_label_position_tolerance(unsigned tolerance)
{
placement_options_->properties.label_position_tolerance = tolerance;
placement_options_->defaults.label_position_tolerance = tolerance;
}
bool text_symbolizer::get_force_odd_labels() const
{
return placement_options_->properties.force_odd_labels;
return placement_options_->defaults.force_odd_labels;
}
void text_symbolizer::set_force_odd_labels(bool force)
{
placement_options_->properties.force_odd_labels = force;
placement_options_->defaults.force_odd_labels = force;
}
double text_symbolizer::get_max_char_angle_delta() const
{
return placement_options_->properties.max_char_angle_delta;
return placement_options_->defaults.max_char_angle_delta;
}
void text_symbolizer::set_max_char_angle_delta(double angle)
{
placement_options_->properties.max_char_angle_delta = angle;
placement_options_->defaults.max_char_angle_delta = angle;
}
void text_symbolizer::set_text_size(float size)
{
placement_options_->properties.default_format.text_size = size;
placement_options_->defaults.format.text_size = size;
}
float text_symbolizer::get_text_size() const
{
return placement_options_->properties.default_format.text_size;
return placement_options_->defaults.format.text_size;
}
void text_symbolizer::set_fill(color const& fill)
{
placement_options_->properties.default_format.fill = fill;
placement_options_->defaults.format.fill = fill;
}
color const& text_symbolizer::get_fill() const
{
return placement_options_->properties.default_format.fill;
return placement_options_->defaults.format.fill;
}
void text_symbolizer::set_halo_fill(color const& fill)
{
placement_options_->properties.default_format.halo_fill = fill;
placement_options_->defaults.format.halo_fill = fill;
}
color const& text_symbolizer::get_halo_fill() const
{
return placement_options_->properties.default_format.halo_fill;
return placement_options_->defaults.format.halo_fill;
}
void text_symbolizer::set_halo_radius(double radius)
{
placement_options_->properties.default_format.halo_radius = radius;
placement_options_->defaults.format.halo_radius = radius;
}
double text_symbolizer::get_halo_radius() const
{
return placement_options_->properties.default_format.halo_radius;
return placement_options_->defaults.format.halo_radius;
}
void text_symbolizer::set_label_placement(label_placement_e label_p)
{
placement_options_->properties.label_placement = label_p;
placement_options_->defaults.label_placement = label_p;
}
label_placement_e text_symbolizer::get_label_placement() const
{
return placement_options_->properties.label_placement;
return placement_options_->defaults.label_placement;
}
void text_symbolizer::set_displacement(double x, double y)
{
placement_options_->properties.displacement = std::make_pair(x,y);
placement_options_->defaults.displacement = std::make_pair(x,y);
}
void text_symbolizer::set_displacement(position const& p)
{
placement_options_->properties.displacement = p;
placement_options_->defaults.displacement = p;
}
position const& text_symbolizer::get_displacement() const
{
return placement_options_->properties.displacement;
return placement_options_->defaults.displacement;
}
bool text_symbolizer::get_avoid_edges() const
{
return placement_options_->properties.avoid_edges;
return placement_options_->defaults.avoid_edges;
}
void text_symbolizer::set_avoid_edges(bool avoid)
{
placement_options_->properties.avoid_edges = avoid;
placement_options_->defaults.avoid_edges = avoid;
}
double text_symbolizer::get_minimum_distance() const
{
return placement_options_->properties.minimum_distance;
return placement_options_->defaults.minimum_distance;
}
void text_symbolizer::set_minimum_distance(double distance)
{
placement_options_->properties.minimum_distance = distance;
placement_options_->defaults.minimum_distance = distance;
}
double text_symbolizer::get_minimum_padding() const
{
return placement_options_->properties.minimum_padding;
return placement_options_->defaults.minimum_padding;
}
void text_symbolizer::set_minimum_padding(double distance)
{
placement_options_->properties.minimum_padding = distance;
placement_options_->defaults.minimum_padding = distance;
}
double text_symbolizer::get_minimum_path_length() const
{
return placement_options_->properties.minimum_path_length;
return placement_options_->defaults.minimum_path_length;
}
void text_symbolizer::set_minimum_path_length(double size)
{
placement_options_->properties.minimum_path_length = size;
placement_options_->defaults.minimum_path_length = size;
}
void text_symbolizer::set_allow_overlap(bool overlap)
{
placement_options_->properties.allow_overlap = overlap;
placement_options_->defaults.allow_overlap = overlap;
}
bool text_symbolizer::get_allow_overlap() const
{
return placement_options_->properties.allow_overlap;
return placement_options_->defaults.allow_overlap;
}
void text_symbolizer::set_text_opacity(double text_opacity)
{
placement_options_->properties.default_format.text_opacity = text_opacity;
placement_options_->defaults.format.text_opacity = text_opacity;
}
double text_symbolizer::get_text_opacity() const
{
return placement_options_->properties.default_format.text_opacity;
return placement_options_->defaults.format.text_opacity;
}
void text_symbolizer::set_vertical_alignment(vertical_alignment_e valign)
{
placement_options_->properties.valign = valign;
placement_options_->defaults.valign = valign;
}
vertical_alignment_e text_symbolizer::get_vertical_alignment() const
{
return placement_options_->properties.valign;
return placement_options_->defaults.valign;
}
void text_symbolizer::set_horizontal_alignment(horizontal_alignment_e halign)
{
placement_options_->properties.halign = halign;
placement_options_->defaults.halign = halign;
}
horizontal_alignment_e text_symbolizer::get_horizontal_alignment() const
{
return placement_options_->properties.halign;
return placement_options_->defaults.halign;
}
void text_symbolizer::set_justify_alignment(justify_alignment_e jalign)
{
placement_options_->properties.jalign = jalign;
placement_options_->defaults.jalign = jalign;
}
justify_alignment_e text_symbolizer::get_justify_alignment() const
{
return placement_options_->properties.jalign;
return placement_options_->defaults.jalign;
}
text_placements_ptr text_symbolizer::get_placement_options() const

View file

@ -296,7 +296,6 @@ private:
int num_points = read_integer();
CoordinateArray ar(num_points);
read_coords(ar);
line->set_capacity(num_points);
line->move_to(ar[0].x, ar[0].y);
for (int i = 1; i < num_points; ++i)
{
@ -321,7 +320,6 @@ private:
int num_points = read_integer();
CoordinateArray ar(num_points);
read_coords_xyz(ar);
line->set_capacity(num_points);
line->move_to(ar[0].x, ar[0].y);
for (int i = 1; i < num_points; ++i)
{
@ -352,7 +350,6 @@ private:
capacity += num_points;
CoordinateArray ar(num_points);
read_coords(ar);
poly->set_capacity(capacity);
poly->move_to(ar[0].x, ar[0].y);
for (int j = 1; j < num_points; ++j)
{
@ -383,7 +380,6 @@ private:
capacity += num_points;
CoordinateArray ar(num_points);
read_coords_xyz(ar);
poly->set_capacity(capacity);
poly->move_to(ar[0].x, ar[0].y);
for (int j = 1; j < num_points; ++j)
{

View file

@ -67,8 +67,11 @@ def test_feature_expression_evaluation_missing_attr():
f['name'] = u'a'
eq_(f['name'],u'a')
expr = mapnik.Expression("[fielddoesnotexist]='a'")
evaluated = expr.evaluate(f)
eq_(evaluated,False)
eq_(f.has_key('fielddoesnotexist'),False)
try:
evaluated = expr.evaluate(f)
except Exception, e:
eq_("Key does not exist" in str(e),True)
num_attributes = len(f)
eq_(num_attributes,1)
eq_(f.id(),1)

View file

@ -16,17 +16,18 @@ def test_add_feature():
featureset = md.features_at_point(mapnik.Coord(2,3))
retrieved = []
feat = featureset.next()
while featureset.next():
while feat:
retrieved.append(feat)
feat = featureset.next()
eq_(len(retrieved), 1)
f = retrieved[0]
eq_(f['foo'], 'bar')
featureset = md.features_at_point(Coord(20,30)).features
featureset = md.features_at_point(mapnik.Coord(20,30))
retrieved = []
feat = featureset.next()
while featureset.next():
while feat:
retrieved.append(feat)
eq_(len(retrieved), 0)

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Map>
<Map background-color="white" srs="+proj=latlong +datum=WGS84">
<Layer name="layer" srs="+proj=latlong +datum=WGS84">
<StyleName>My Style</StyleName>
<Datasource>
<Parameter name="type">shape</Parameter>
<Parameter name="file">points.shp</Parameter>
</Datasource>
</Layer>
<Style name="My Style">
<Rule>
<PointSymbolizer/>
<TextSymbolizer face-name="DejaVu Sans Book" placement="point" dx="0" dy="5">
<ExpressionFormat size="[nr]">[name]</ExpressionFormat>
</TextSymbolizer>
</Rule>
</Style>
</Map>

View file

@ -13,7 +13,7 @@ filenames = ["list", "simple"]
filenames_one_width = ["simple-E", "simple-NE", "simple-NW", "simple-N",
"simple-SE", "simple-SW", "simple-S", "simple-W",
"formating-1", "formating-2", "formating-3", "formating-4",
"shieldsymbolizer-1"]
"shieldsymbolizer-1", "expressionformat"]
def render(filename, width):
print "Rendering style \"%s\" with width %d" % (filename, width)

View file

@ -41,6 +41,13 @@ boost_filesystem = 'boost_filesystem%s' % env['BOOST_APPEND']
boost_system = 'boost_system%s' % env['BOOST_APPEND']
libraries = [boost_program_options, boost_filesystem, boost_system]
if env.get('BOOST_LIB_VERSION_FROM_HEADER'):
boost_version_from_header = int(env['BOOST_LIB_VERSION_FROM_HEADER'].split('_')[1])
if boost_version_from_header < 46:
# avoid ubuntu issue with boost interprocess:
# https://github.com/mapnik/mapnik/issues/1082
program_env.Append(CXXFLAGS = '-fpermissive')
shapeindex = program_env.Program('shapeindex', source, CPPPATH=headers, LIBS=libraries, LINKFLAGS=env['CUSTOM_LDFLAGS'])
Depends(shapeindex, env.subst('../../src/%s' % env['MAPNIK_LIB_NAME']))