python: fixup mapnik.Path interface (closes #901), add to_wkb method (closes #831), and add tests for both
This commit is contained in:
parent
1d408aa485
commit
742fb891e6
2 changed files with 83 additions and 4 deletions
|
@ -31,6 +31,7 @@
|
||||||
#include <mapnik/geometry.hpp>
|
#include <mapnik/geometry.hpp>
|
||||||
#include <mapnik/wkt/wkt_factory.hpp>
|
#include <mapnik/wkt/wkt_factory.hpp>
|
||||||
#include <mapnik/wkb.hpp>
|
#include <mapnik/wkb.hpp>
|
||||||
|
#include <mapnik/util/geometry_to_wkb.hpp>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -47,19 +48,47 @@ geometry_type const& getitem_impl(path_type & p, int key)
|
||||||
throw boost::python::error_already_set();
|
throw boost::python::error_already_set();
|
||||||
}
|
}
|
||||||
|
|
||||||
void from_wkt_impl(path_type& p, std::string const& wkt)
|
void add_wkt_impl(path_type& p, std::string const& wkt)
|
||||||
{
|
{
|
||||||
bool result = mapnik::from_wkt(wkt , p);
|
bool result = mapnik::from_wkt(wkt , p);
|
||||||
if (!result) throw std::runtime_error("Failed to parse WKT");
|
if (!result) throw std::runtime_error("Failed to parse WKT");
|
||||||
}
|
}
|
||||||
|
|
||||||
void from_wkb_impl(path_type& p, std::string const& wkb)
|
void add_wkb_impl(path_type& p, std::string const& wkb)
|
||||||
{
|
{
|
||||||
mapnik::geometry_utils::from_wkb(p, wkb.c_str(), wkb.size(), true);
|
mapnik::geometry_utils::from_wkb(p, wkb.c_str(), wkb.size(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boost::shared_ptr<path_type> from_wkt_impl(std::string const& wkt)
|
||||||
|
{
|
||||||
|
boost::shared_ptr<path_type> paths = boost::make_shared<path_type>();
|
||||||
|
bool result = mapnik::from_wkt(wkt, *paths);
|
||||||
|
if (!result) throw std::runtime_error("Failed to parse WKT");
|
||||||
|
return paths;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boost::shared_ptr<path_type> from_wkb_impl(std::string const& wkb)
|
||||||
|
{
|
||||||
|
boost::shared_ptr<path_type> paths = boost::make_shared<path_type>();
|
||||||
|
mapnik::geometry_utils::from_wkb(*paths, wkb.c_str(), wkb.size(), true);
|
||||||
|
return paths;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject* to_wkb( geometry_type const& geom)
|
||||||
|
{
|
||||||
|
mapnik::util::wkb_buffer_ptr wkb = mapnik::util::to_wkb(geom,mapnik::util::wkbXDR);
|
||||||
|
return
|
||||||
|
#if PY_VERSION_HEX >= 0x03000000
|
||||||
|
::PyBytes_FromStringAndSize
|
||||||
|
#else
|
||||||
|
::PyString_FromStringAndSize
|
||||||
|
#endif
|
||||||
|
((const char*)wkb->buffer(),wkb->size());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void export_geometry()
|
void export_geometry()
|
||||||
{
|
{
|
||||||
using namespace boost::python;
|
using namespace boost::python;
|
||||||
|
@ -78,14 +107,19 @@ void export_geometry()
|
||||||
.def("envelope",&geometry_type::envelope)
|
.def("envelope",&geometry_type::envelope)
|
||||||
// .def("__str__",&geometry_type::to_string)
|
// .def("__str__",&geometry_type::to_string)
|
||||||
.def("type",&geometry_type::type)
|
.def("type",&geometry_type::type)
|
||||||
|
.def("to_wkb",&to_wkb)
|
||||||
// TODO add other geometry_type methods
|
// TODO add other geometry_type methods
|
||||||
;
|
;
|
||||||
|
|
||||||
class_<path_type,boost::noncopyable>("Path")
|
class_<path_type, boost::shared_ptr<path_type>, boost::noncopyable>("Path")
|
||||||
.def("__getitem__", getitem_impl,return_value_policy<reference_existing_object>())
|
.def("__getitem__", getitem_impl,return_value_policy<reference_existing_object>())
|
||||||
.def("__len__", &path_type::size)
|
.def("__len__", &path_type::size)
|
||||||
|
.def("add_wkt",add_wkt_impl)
|
||||||
|
.def("add_wkb",add_wkb_impl)
|
||||||
.def("from_wkt",from_wkt_impl)
|
.def("from_wkt",from_wkt_impl)
|
||||||
.def("from_wkb",from_wkb_impl)
|
.def("from_wkb",from_wkb_impl)
|
||||||
|
.staticmethod("from_wkt")
|
||||||
|
.staticmethod("from_wkb")
|
||||||
;
|
;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
45
tests/python_tests/geometry_wkb_test.py
Normal file
45
tests/python_tests/geometry_wkb_test.py
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#encoding: utf8
|
||||||
|
|
||||||
|
from nose.tools import *
|
||||||
|
import os
|
||||||
|
from utilities import execution_path
|
||||||
|
import mapnik
|
||||||
|
|
||||||
|
wkts = [
|
||||||
|
[1,"POINT (30 10)"],
|
||||||
|
[1,"LINESTRING (30 10, 10 30, 40 40)"],
|
||||||
|
[1,"POLYGON ((30 10, 10 20, 20 40, 40 40, 30 10))"],
|
||||||
|
[1,"POLYGON ((35 10, 10 20, 15 40, 45 45, 35 10),(20 30, 35 35, 30 20, 20 30))"],
|
||||||
|
[4,"MULTIPOINT ((10 40), (40 30), (20 20), (30 10))"],
|
||||||
|
[2,"MULTILINESTRING ((10 10, 20 20, 10 40),(40 40, 30 30, 40 20, 30 10))"],
|
||||||
|
[2,"MULTIPOLYGON (((30 20, 10 40, 45 40, 30 20)),((15 5, 40 10, 10 20, 5 10, 15 5)))"],
|
||||||
|
[2,"MULTIPOLYGON (((40 40, 20 45, 45 30, 40 40)),((20 35, 45 20, 30 5, 10 10, 10 30, 20 35),(30 20, 20 25, 20 15, 30 20)))"]
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def compare_wkb_from_wkt(wkt,num):
|
||||||
|
f = mapnik.Feature(1)
|
||||||
|
f.add_geometries_from_wkt(wkt)
|
||||||
|
eq_(len(f.geometries()),num)
|
||||||
|
|
||||||
|
paths = mapnik.Path.from_wkt(wkt)
|
||||||
|
eq_(len(paths),num)
|
||||||
|
|
||||||
|
eq_(f.geometries()[0].to_wkb(),paths[0].to_wkb())
|
||||||
|
|
||||||
|
paths2 = mapnik.Path()
|
||||||
|
for path in paths:
|
||||||
|
paths2.add_wkb(path.to_wkb())
|
||||||
|
|
||||||
|
eq_(len(paths2),num)
|
||||||
|
eq_(f.geometries()[0].to_wkb(),paths2[0].to_wkb())
|
||||||
|
|
||||||
|
def test_point():
|
||||||
|
for wkt in wkts:
|
||||||
|
try:
|
||||||
|
compare_wkb_from_wkt(wkt[1],wkt[0])
|
||||||
|
except RuntimeError, e:
|
||||||
|
raise RuntimeError('%s %s' % (e, wkt))
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
[eval(run)() for run in dir() if 'test_' in run]
|
Loading…
Reference in a new issue