1. added boost::optional<T> to/form Python converter
2. make background color optional (Map object) 3. exposed 'blend' method for Image object
This commit is contained in:
parent
d78ccbaed0
commit
d959701d5a
13 changed files with 288 additions and 114 deletions
|
@ -38,17 +38,25 @@ PyObject* rawdata( Image32 const& im)
|
|||
}
|
||||
|
||||
void (*save_to_file2)(std::string const&,std::string const&, mapnik::Image32 const&) = mapnik::save_to_file;
|
||||
|
||||
void blend (Image32 & im, unsigned x, unsigned y, Image32 const& im2, float opacity)
|
||||
{
|
||||
im.set_rectangle_alpha2(im2.data(),x,y,opacity);
|
||||
}
|
||||
|
||||
void export_image()
|
||||
{
|
||||
using namespace boost::python;
|
||||
class_<Image32>("Image","This class represents a 32 bit image.",init<int,int>())
|
||||
.def("width",&Image32::width)
|
||||
.def("height",&Image32::height)
|
||||
.def("view",&Image32::get_view)
|
||||
.add_property("background",make_function
|
||||
(&Image32::getBackground,return_value_policy<copy_const_reference>()),
|
||||
&Image32::setBackground, "The background color of the image.")
|
||||
;
|
||||
.def("width",&Image32::width)
|
||||
.def("height",&Image32::height)
|
||||
.def("view",&Image32::get_view)
|
||||
.add_property("background",make_function
|
||||
(&Image32::getBackground,return_value_policy<copy_const_reference>()),
|
||||
&Image32::setBackground, "The background color of the image.")
|
||||
.def("set_alpha",&Image32::set_alpha)
|
||||
.def("blend",&blend)
|
||||
;
|
||||
def("rawdata",&rawdata); // FIXME : I dont think we need this one
|
||||
def("save_to_file", save_to_file2);
|
||||
}
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
#include <mapnik/layer.hpp>
|
||||
#include <mapnik/map.hpp>
|
||||
|
||||
#include "python_optional.hpp"
|
||||
|
||||
using mapnik::Color;
|
||||
using mapnik::coord;
|
||||
using mapnik::Envelope;
|
||||
|
@ -51,7 +53,7 @@ struct map_pickle_suite : boost::python::pickle_suite
|
|||
{
|
||||
l.append(m.getLayer(i));
|
||||
}
|
||||
return boost::python::make_tuple(m.getCurrentExtent(),m.getBackground(),l);
|
||||
return boost::python::make_tuple(m.getCurrentExtent(),m.background(),l);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -69,7 +71,7 @@ struct map_pickle_suite : boost::python::pickle_suite
|
|||
Envelope<double> ext = extract<Envelope<double> >(state[0]);
|
||||
Color bg = extract<Color>(state[1]);
|
||||
m.zoomToBox(ext);
|
||||
m.setBackground(bg);
|
||||
m.set_background(bg);
|
||||
boost::python::list l=extract<boost::python::list>(state[2]);
|
||||
for (int i=0;i<len(l);++i)
|
||||
{
|
||||
|
@ -83,39 +85,40 @@ std::vector<Layer> const& (Map::*layers_const)() const = &Map::layers;
|
|||
|
||||
void export_map()
|
||||
{
|
||||
using namespace boost::python;
|
||||
class_<std::vector<Layer> >("Layers")
|
||||
using namespace boost::python;
|
||||
python_optional<mapnik::Color> ();
|
||||
class_<std::vector<Layer> >("Layers")
|
||||
.def(vector_indexing_suite<std::vector<Layer> >())
|
||||
;
|
||||
|
||||
class_<Map>("Map","The map object.",init<int,int,optional<std::string const&> >())
|
||||
.add_property("width",&Map::getWidth, &Map::setWidth, "The width of the map.")
|
||||
.add_property("height",&Map::getHeight, &Map::setHeight, "The height of the map.")
|
||||
.add_property("srs",make_function(&Map::srs,return_value_policy<copy_const_reference>()),
|
||||
&Map::set_srs,"Spatial reference in proj4 format e.g. \"+proj=latlong +datum=WGS84\"")
|
||||
.add_property("background",make_function
|
||||
(&Map::getBackground,return_value_policy<copy_const_reference>()),
|
||||
&Map::setBackground, "The background color of the map.")
|
||||
.def("envelope",make_function(&Map::getCurrentExtent,
|
||||
return_value_policy<copy_const_reference>()),
|
||||
"The current extent of the map")
|
||||
.def("scale", &Map::scale)
|
||||
.def("zoom_all",&Map::zoom_all,
|
||||
"Set the geographical extent of the map "
|
||||
"to the combined extents of all active layers")
|
||||
.def("zoom_to_box",&Map::zoomToBox, "Set the geographical extent of the map.")
|
||||
.def("pan",&Map::pan)
|
||||
.def("zoom",&Map::zoom)
|
||||
.def("zoom_all",&Map::zoom_all)
|
||||
.def("pan_and_zoom",&Map::pan_and_zoom)
|
||||
.def("append_style",&Map::insert_style)
|
||||
.def("remove_style",&Map::remove_style)
|
||||
.def("query_point",&Map::query_point)
|
||||
.def("query_map_point",&Map::query_map_point)
|
||||
.add_property("layers",make_function
|
||||
(layers_nonconst,return_value_policy<reference_existing_object>()),
|
||||
"Get the list of layers in this map.")
|
||||
.def("find_style",&Map::find_style,return_value_policy<copy_const_reference>())
|
||||
.def_pickle(map_pickle_suite())
|
||||
;
|
||||
;
|
||||
|
||||
class_<Map>("Map","The map object.",init<int,int,optional<std::string const&> >())
|
||||
.add_property("width",&Map::getWidth, &Map::setWidth, "The width of the map.")
|
||||
.add_property("height",&Map::getHeight, &Map::setHeight, "The height of the map.")
|
||||
.add_property("srs",make_function(&Map::srs,return_value_policy<copy_const_reference>()),
|
||||
&Map::set_srs,"Spatial reference in proj4 format e.g. \"+proj=latlong +datum=WGS84\"")
|
||||
.add_property("background",make_function
|
||||
(&Map::background,return_value_policy<copy_const_reference>()),
|
||||
&Map::set_background, "The background color of the map.")
|
||||
.def("envelope",make_function(&Map::getCurrentExtent,
|
||||
return_value_policy<copy_const_reference>()),
|
||||
"The current extent of the map")
|
||||
.def("scale", &Map::scale)
|
||||
.def("zoom_all",&Map::zoom_all,
|
||||
"Set the geographical extent of the map "
|
||||
"to the combined extents of all active layers")
|
||||
.def("zoom_to_box",&Map::zoomToBox, "Set the geographical extent of the map.")
|
||||
.def("pan",&Map::pan)
|
||||
.def("zoom",&Map::zoom)
|
||||
.def("zoom_all",&Map::zoom_all)
|
||||
.def("pan_and_zoom",&Map::pan_and_zoom)
|
||||
.def("append_style",&Map::insert_style)
|
||||
.def("remove_style",&Map::remove_style)
|
||||
.def("query_point",&Map::query_point)
|
||||
.def("query_map_point",&Map::query_map_point)
|
||||
.add_property("layers",make_function
|
||||
(layers_nonconst,return_value_policy<reference_existing_object>()),
|
||||
"Get the list of layers in this map.")
|
||||
.def("find_style",&Map::find_style,return_value_policy<copy_const_reference>())
|
||||
.def_pickle(map_pickle_suite())
|
||||
;
|
||||
}
|
||||
|
|
|
@ -140,5 +140,9 @@ BOOST_PYTHON_MODULE(_mapnik)
|
|||
def("load_map",&load_map,"load Map object from XML");
|
||||
def("save_map",&load_map,"sace Map object to XML");
|
||||
|
||||
using mapnik::symbolizer;
|
||||
class_<symbolizer>("Symbolizer",no_init)
|
||||
;
|
||||
|
||||
register_ptr_to_python<mapnik::filter_ptr>();
|
||||
}
|
||||
|
|
102
bindings/python/python_optional.hpp
Normal file
102
bindings/python/python_optional.hpp
Normal file
|
@ -0,0 +1,102 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2007 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
|
||||
*
|
||||
*****************************************************************************/
|
||||
//$Id$
|
||||
|
||||
#include <boost/optional/optional.hpp>
|
||||
#include <boost/python.hpp>
|
||||
|
||||
// boost::optional<T> to/from converter from John Wiegley
|
||||
|
||||
template <typename T, typename TfromPy>
|
||||
struct object_from_python
|
||||
{
|
||||
object_from_python() {
|
||||
boost::python::converter::registry::push_back
|
||||
(&TfromPy::convertible, &TfromPy::construct,
|
||||
boost::python::type_id<T>());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename TtoPy, typename TfromPy>
|
||||
struct register_python_conversion
|
||||
{
|
||||
register_python_conversion() {
|
||||
boost::python::to_python_converter<T, TtoPy>();
|
||||
object_from_python<T, TfromPy>();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct python_optional : public boost::noncopyable
|
||||
{
|
||||
struct optional_to_python
|
||||
{
|
||||
static PyObject * convert(const boost::optional<T>& value)
|
||||
{
|
||||
return (value ? boost::python::to_python_value<T>()(*value) :
|
||||
boost::python::detail::none());
|
||||
}
|
||||
};
|
||||
|
||||
struct optional_from_python
|
||||
{
|
||||
static void * convertible(PyObject * source)
|
||||
{
|
||||
using namespace boost::python::converter;
|
||||
|
||||
if (source == Py_None)
|
||||
return source;
|
||||
|
||||
const registration& converters(registered<T>::converters);
|
||||
|
||||
if (implicit_rvalue_convertible_from_python(source,
|
||||
converters)) {
|
||||
rvalue_from_python_stage1_data data =
|
||||
rvalue_from_python_stage1(source, converters);
|
||||
return rvalue_from_python_stage2(source, data, converters);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void construct(PyObject * source,
|
||||
boost::python::converter::rvalue_from_python_stage1_data * data)
|
||||
{
|
||||
using namespace boost::python::converter;
|
||||
|
||||
void * const storage = ((rvalue_from_python_storage<T> *)
|
||||
data)->storage.bytes;
|
||||
|
||||
if (data->convertible == source) // == None
|
||||
new (storage) boost::optional<T>(); // A Boost uninitialized value
|
||||
else
|
||||
new (storage) boost::optional<T>(*static_cast<T *>(data->convertible));
|
||||
|
||||
data->convertible = storage;
|
||||
}
|
||||
};
|
||||
|
||||
explicit python_optional() {
|
||||
register_python_conversion<boost::optional<T>,
|
||||
optional_to_python, optional_from_python>();
|
||||
}
|
||||
};
|
||||
|
|
@ -46,10 +46,10 @@ namespace mapnik {
|
|||
private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
typedef T1 geometry_type;
|
||||
typedef T2 raster_type;
|
||||
typedef std::map<std::string,value>::value_type value_type;
|
||||
typedef std::map<std::string,value>::size_type size_type;
|
||||
typedef T1 geometry_type;
|
||||
typedef T2 raster_type;
|
||||
typedef std::map<std::string,value>::value_type value_type;
|
||||
typedef std::map<std::string,value>::size_type size_type;
|
||||
|
||||
private:
|
||||
int id_;
|
||||
|
|
|
@ -34,12 +34,12 @@ namespace mapnik
|
|||
template <typename FeatureT>
|
||||
class MAPNIK_DECL filter
|
||||
{
|
||||
public:
|
||||
virtual bool pass(const FeatureT& feature) const=0;
|
||||
virtual filter<FeatureT>* clone() const=0;
|
||||
virtual void accept(filter_visitor<FeatureT>& v) = 0;
|
||||
virtual std::string to_string() const=0;
|
||||
virtual ~filter() {}
|
||||
public:
|
||||
virtual bool pass(const FeatureT& feature) const=0;
|
||||
virtual filter<FeatureT>* clone() const=0;
|
||||
virtual void accept(filter_visitor<FeatureT>& v) = 0;
|
||||
virtual std::string to_string() const=0;
|
||||
virtual ~filter() {}
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<filter<Feature> > filter_ptr;
|
||||
|
@ -47,43 +47,43 @@ namespace mapnik
|
|||
template <typename FeatureT>
|
||||
class all_filter : public filter<FeatureT>
|
||||
{
|
||||
public:
|
||||
bool pass (const FeatureT&) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
filter<FeatureT>* clone() const
|
||||
{
|
||||
return new all_filter<FeatureT>;
|
||||
}
|
||||
std::string to_string() const
|
||||
{
|
||||
return "true";
|
||||
}
|
||||
void accept(filter_visitor<FeatureT>&) {}
|
||||
virtual ~all_filter() {}
|
||||
public:
|
||||
bool pass (const FeatureT&) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
filter<FeatureT>* clone() const
|
||||
{
|
||||
return new all_filter<FeatureT>;
|
||||
}
|
||||
std::string to_string() const
|
||||
{
|
||||
return "true";
|
||||
}
|
||||
void accept(filter_visitor<FeatureT>&) {}
|
||||
virtual ~all_filter() {}
|
||||
};
|
||||
|
||||
template <typename FeatureT>
|
||||
class none_filter : public filter<FeatureT>
|
||||
{
|
||||
public:
|
||||
bool pass (const FeatureT&) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
filter<FeatureT>* clone() const
|
||||
{
|
||||
return new none_filter<FeatureT>;
|
||||
}
|
||||
std::string to_string() const
|
||||
{
|
||||
return "false";
|
||||
}
|
||||
void accept(filter_visitor<FeatureT>&) {}
|
||||
virtual ~none_filter() {}
|
||||
|
||||
template <typename FeatureT>
|
||||
class none_filter : public filter<FeatureT>
|
||||
{
|
||||
public:
|
||||
bool pass (const FeatureT&) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
filter<FeatureT>* clone() const
|
||||
{
|
||||
return new none_filter<FeatureT>;
|
||||
}
|
||||
std::string to_string() const
|
||||
{
|
||||
return "false";
|
||||
}
|
||||
void accept(filter_visitor<FeatureT>&) {}
|
||||
virtual ~none_filter() {}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -146,7 +146,26 @@ namespace mapnik
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline void set_alpha(float alpha) // 0...1
|
||||
{
|
||||
unsigned w = data_.width();
|
||||
unsigned h = data_.height();
|
||||
unsigned a = int(0xff * alpha) & 0xff;
|
||||
|
||||
for (unsigned y = 0; y < h ; ++y)
|
||||
{
|
||||
for (unsigned x = 0; x < w ; ++x)
|
||||
{
|
||||
unsigned rgba = data_(x,y);
|
||||
if (rgba > 0)
|
||||
{
|
||||
data_(x,y) = (rgba & 0x00ffffff) | (a << 24);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void set_rectangle_alpha(int x0,int y0,const ImageData32& data)
|
||||
{
|
||||
Envelope<int> ext0(0,0,width_,height_);
|
||||
|
@ -185,6 +204,44 @@ namespace mapnik
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void set_rectangle_alpha2(ImageData32 const& data, unsigned x0, unsigned y0, float opacity)
|
||||
{
|
||||
Envelope<int> ext0(0,0,width_,height_);
|
||||
Envelope<int> ext1(x0,y0,x0 + data.width(),y0 + data.height());
|
||||
unsigned a1 = int(opacity * 255);
|
||||
|
||||
if (ext0.intersects(ext1))
|
||||
{
|
||||
Envelope<int> box = ext0.intersect(ext1);
|
||||
for (int y = box.miny(); y < box.maxy(); ++y)
|
||||
{
|
||||
for (int x = box.minx(); x < box.maxx(); ++x)
|
||||
{
|
||||
unsigned rgba0 = data_(x,y);
|
||||
unsigned rgba1 = data(x-x0,y-y0);
|
||||
|
||||
if (((rgba1 >> 24) & 255)== 0) continue;
|
||||
unsigned r1 = rgba1 & 0xff;
|
||||
unsigned g1 = (rgba1 >> 8 ) & 0xff;
|
||||
unsigned b1 = (rgba1 >> 16) & 0xff;
|
||||
|
||||
unsigned a0 = (rgba0 >> 24) & 0xff;
|
||||
unsigned r0 = rgba0 & 0xff ;
|
||||
unsigned g0 = (rgba0 >> 8 ) & 0xff;
|
||||
unsigned b0 = (rgba0 >> 16) & 0xff;
|
||||
|
||||
unsigned a = (a1 * 255 + (255 - a1) * a0 + 127)/255;
|
||||
|
||||
r0 = (r1*a1 + (((255 - a1) * a0 + 127)/255) * r0 + 127)/a;
|
||||
g0 = (g1*a1 + (((255 - a1) * a0 + 127)/255) * g0 + 127)/a;
|
||||
b0 = (b1*a1 + (((255 - a1) * a0 + 127)/255) * b0 + 127)/a;
|
||||
|
||||
data_(x,y)= (a << 24)| (b0 << 16) | (g0 << 8) | (r0) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
#endif //GRAPHICS_HPP
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace mapnik
|
|||
height_(height),
|
||||
pData_((width!=0 && height!=0)? static_cast<T*>(::operator new(sizeof(T)*width*height)):0)
|
||||
{
|
||||
if (pData_) memset(pData_,0,sizeof(T)*width_*height_);
|
||||
//if (pData_) memset(pData_,0,sizeof(T)*width_*height_);
|
||||
}
|
||||
|
||||
ImageData(const ImageData<T>& rhs)
|
||||
|
@ -77,6 +77,7 @@ namespace mapnik
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline const T* getData() const
|
||||
{
|
||||
return pData_;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <mapnik/feature_type_style.hpp>
|
||||
#include <mapnik/datasource.hpp>
|
||||
#include <mapnik/layer.hpp>
|
||||
#include <boost/optional/optional.hpp>
|
||||
|
||||
namespace mapnik
|
||||
{
|
||||
|
@ -37,11 +38,10 @@ namespace mapnik
|
|||
unsigned width_;
|
||||
unsigned height_;
|
||||
std::string srs_;
|
||||
Color background_;
|
||||
boost::optional<Color> background_;
|
||||
std::map<std::string,feature_type_style> styles_;
|
||||
std::vector<Layer> layers_;
|
||||
Envelope<double> currentExtent_;
|
||||
|
||||
Envelope<double> currentExtent_;
|
||||
public:
|
||||
typedef std::map<std::string,feature_type_style>::const_iterator const_style_iterator;
|
||||
typedef std::map<std::string,feature_type_style>::iterator style_iterator;
|
||||
|
@ -72,8 +72,8 @@ namespace mapnik
|
|||
void resize(unsigned width,unsigned height);
|
||||
std::string const& srs() const;
|
||||
void set_srs(std::string const& srs);
|
||||
void setBackground(const Color& c);
|
||||
const Color& getBackground() const;
|
||||
void set_background(const Color& c);
|
||||
boost::optional<Color> const& background() const;
|
||||
void zoom(double zoom);
|
||||
void zoomToBox(const Envelope<double>& box);
|
||||
void zoom_all();
|
||||
|
|
|
@ -100,7 +100,7 @@ feature_ptr postgis_featureset::next()
|
|||
#ifdef MAPNIK_DEBUG
|
||||
std::clog << "uknown OID = " << oid << " FIXME \n";
|
||||
#endif
|
||||
//boost::put(*feature,name,0);
|
||||
//boost::put(*feature,name,0);
|
||||
}
|
||||
}
|
||||
++count_;
|
||||
|
|
|
@ -97,8 +97,8 @@ namespace mapnik
|
|||
detector_(Envelope<double>(-64 ,-64, m.getWidth() + 64 ,m.getHeight() + 64)),
|
||||
finder_(detector_,Envelope<double>(0 ,0, m.getWidth(), m.getHeight()))
|
||||
{
|
||||
Color const& bg = m.getBackground();
|
||||
pixmap_.setBackground(bg);
|
||||
boost::optional<Color> bg = m.background();
|
||||
if (bg) pixmap_.setBackground(*bg);
|
||||
#ifdef MAPNIK_DEBUG
|
||||
std::clog << "scale=" << m.scale() << "\n";
|
||||
#endif
|
||||
|
|
|
@ -56,7 +56,7 @@ namespace mapnik
|
|||
if (bgcolor)
|
||||
{
|
||||
Color bg = color_factory::from_string(bgcolor->c_str());
|
||||
map.setBackground(bg);
|
||||
map.set_background(bg);
|
||||
}
|
||||
|
||||
std::string srs = pt.get<std::string>("Map.<xmlattr>.srs",
|
||||
|
|
27
src/map.cpp
27
src/map.cpp
|
@ -39,9 +39,8 @@ namespace mapnik
|
|||
Map::Map(int width,int height, std::string const& srs)
|
||||
: width_(width),
|
||||
height_(height),
|
||||
srs_(srs),
|
||||
background_(Color(255,255,255)) {}
|
||||
|
||||
srs_(srs) {}
|
||||
|
||||
Map::Map(const Map& rhs)
|
||||
: width_(rhs.width_),
|
||||
height_(rhs.height_),
|
||||
|
@ -190,17 +189,17 @@ namespace mapnik
|
|||
{
|
||||
srs_ = srs;
|
||||
}
|
||||
|
||||
void Map::setBackground(const Color& c)
|
||||
{
|
||||
background_=c;
|
||||
}
|
||||
|
||||
const Color& Map::getBackground() const
|
||||
{
|
||||
return background_;
|
||||
}
|
||||
|
||||
|
||||
boost::optional<Color> const& Map::background() const
|
||||
{
|
||||
return background_;
|
||||
}
|
||||
|
||||
void Map::set_background(const Color& c)
|
||||
{
|
||||
background_ = c;
|
||||
}
|
||||
|
||||
void Map::zoom(double factor)
|
||||
{
|
||||
coord2d center = currentExtent_.center();
|
||||
|
|
Loading…
Reference in a new issue