mapnik-geometry based to_wkb() implementation
This commit is contained in:
parent
58d07338e9
commit
5f073ee299
1 changed files with 136 additions and 127 deletions
|
@ -2,7 +2,7 @@
|
||||||
*
|
*
|
||||||
* This file is part of Mapnik (c++ mapping toolkit)
|
* This file is part of Mapnik (c++ mapping toolkit)
|
||||||
*
|
*
|
||||||
* Copyright (C) 2014 Artem Pavlenko
|
* Copyright (C) 2015 Artem Pavlenko
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
@ -26,9 +26,9 @@
|
||||||
// mapnik
|
// mapnik
|
||||||
#include <mapnik/config.hpp>
|
#include <mapnik/config.hpp>
|
||||||
#include <mapnik/make_unique.hpp>
|
#include <mapnik/make_unique.hpp>
|
||||||
#include <mapnik/geometry.hpp>
|
#include <mapnik/wkb.hpp>
|
||||||
|
#include <mapnik/geometry_impl.hpp>
|
||||||
#include <mapnik/vertex.hpp>
|
#include <mapnik/geometry_type.hpp>
|
||||||
|
|
||||||
// stl
|
// stl
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
@ -38,17 +38,17 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
namespace mapnik { namespace util {
|
namespace mapnik { namespace util { namespace detail {
|
||||||
|
|
||||||
std::string to_hex(const char* blob, unsigned size)
|
std::string to_hex(const char* blob, unsigned size)
|
||||||
{
|
{
|
||||||
std::string buf;
|
std::string buf;
|
||||||
buf.reserve(size*2);
|
buf.reserve(size * 2);
|
||||||
std::ostringstream s(buf);
|
std::ostringstream s(buf);
|
||||||
s.seekp(0);
|
s.seekp(0);
|
||||||
char hex[3];
|
char hex[3];
|
||||||
std::memset(hex,0,3);
|
std::memset(hex, 0, 3);
|
||||||
for ( unsigned pos=0; pos < size; ++pos)
|
for ( unsigned pos = 0; pos < size; ++pos)
|
||||||
{
|
{
|
||||||
std::sprintf (hex, "%02x", int(blob[pos]) & 0xff);
|
std::sprintf (hex, "%02x", int(blob[pos]) & 0xff);
|
||||||
s << hex;
|
s << hex;
|
||||||
|
@ -107,7 +107,7 @@ struct wkb_buffer
|
||||||
{
|
{
|
||||||
wkb_buffer(std::size_t size)
|
wkb_buffer(std::size_t size)
|
||||||
: size_(size),
|
: size_(size),
|
||||||
data_( (size_!=0) ? static_cast<char*>(::operator new (size_)):0)
|
data_( (size_ != 0) ? static_cast<char*>(::operator new (size_)) : 0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
~wkb_buffer()
|
~wkb_buffer()
|
||||||
|
@ -131,96 +131,70 @@ struct wkb_buffer
|
||||||
|
|
||||||
using wkb_buffer_ptr = std::unique_ptr<wkb_buffer>;
|
using wkb_buffer_ptr = std::unique_ptr<wkb_buffer>;
|
||||||
|
|
||||||
template<typename GeometryType>
|
wkb_buffer_ptr point_wkb( new_geometry::point const& pt, wkbByteOrder byte_order)
|
||||||
wkb_buffer_ptr to_point_wkb( GeometryType const& g, wkbByteOrder byte_order)
|
|
||||||
{
|
{
|
||||||
assert(g.size() == 1);
|
std::size_t size = 1 + 4 + 8 * 2 ; // byteOrder + wkbType + Point
|
||||||
std::size_t size = 1 + 4 + 8*2 ; // byteOrder + wkbType + Point
|
|
||||||
wkb_buffer_ptr wkb = std::make_unique<wkb_buffer>(size);
|
wkb_buffer_ptr wkb = std::make_unique<wkb_buffer>(size);
|
||||||
wkb_stream ss(wkb->buffer(), wkb->size());
|
wkb_stream ss(wkb->buffer(), wkb->size());
|
||||||
ss.write(reinterpret_cast<char*>(&byte_order),1);
|
ss.write(reinterpret_cast<char*>(&byte_order),1);
|
||||||
int type = static_cast<int>(mapnik::new_geometry::geometry_types::Point);
|
write(ss, static_cast<int>(new_geometry::geometry_types::Point), 4 , byte_order);
|
||||||
write(ss,type,4,byte_order);
|
write(ss, pt.x, 8, byte_order);
|
||||||
double x = 0;
|
write(ss, pt.y, 8, byte_order);
|
||||||
double y = 0;
|
|
||||||
g.vertex(0,&x,&y);
|
|
||||||
write(ss,x,8,byte_order);
|
|
||||||
write(ss,y,8,byte_order);
|
|
||||||
assert(ss.good());
|
assert(ss.good());
|
||||||
return std::move(wkb);
|
return std::move(wkb);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename GeometryType>
|
wkb_buffer_ptr line_string_wkb(new_geometry::line_string const& line, wkbByteOrder byte_order)
|
||||||
wkb_buffer_ptr to_line_string_wkb( GeometryType const& g, wkbByteOrder byte_order)
|
|
||||||
{
|
{
|
||||||
unsigned num_points = g.size();
|
unsigned num_points = line.size();
|
||||||
assert(num_points > 1);
|
assert(num_points > 1);
|
||||||
std::size_t size = 1 + 4 + 4 + 8*2*num_points ; // byteOrder + wkbType + numPoints + Point*numPoints
|
std::size_t size = 1 + 4 + 4 + 8 * 2 * num_points ; // byteOrder + wkbType + numPoints + Point*numPoints
|
||||||
wkb_buffer_ptr wkb = std::make_unique<wkb_buffer>(size);
|
wkb_buffer_ptr wkb = std::make_unique<wkb_buffer>(size);
|
||||||
wkb_stream ss(wkb->buffer(), wkb->size());
|
wkb_stream ss(wkb->buffer(), wkb->size());
|
||||||
ss.write(reinterpret_cast<char*>(&byte_order),1);
|
ss.write(reinterpret_cast<char*>(&byte_order),1);
|
||||||
int type = static_cast<int>(mapnik::new_geometry::geometry_types::LineString);
|
write(ss, static_cast<int>(mapnik::new_geometry::geometry_types::LineString) , 4, byte_order);
|
||||||
write(ss,type,4,byte_order);
|
write(ss, num_points, 4, byte_order);
|
||||||
write(ss,num_points,4,byte_order);
|
|
||||||
double x = 0;
|
|
||||||
double y = 0;
|
|
||||||
for (unsigned i=0; i< num_points; ++i)
|
for (unsigned i=0; i< num_points; ++i)
|
||||||
{
|
{
|
||||||
g.vertex(i,&x,&y);
|
new_geometry::point const& pt = line[i];
|
||||||
write(ss,x,8,byte_order);
|
write(ss, pt.x, 8, byte_order);
|
||||||
write(ss,y,8,byte_order);
|
write(ss, pt.y, 8, byte_order);
|
||||||
}
|
}
|
||||||
assert(ss.good());
|
assert(ss.good());
|
||||||
return std::move(wkb);
|
return std::move(wkb);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename GeometryType>
|
wkb_buffer_ptr polygon_wkb( new_geometry::polygon const& poly, wkbByteOrder byte_order)
|
||||||
wkb_buffer_ptr to_polygon_wkb( GeometryType const& g, wkbByteOrder byte_order)
|
|
||||||
{
|
{
|
||||||
unsigned num_points = g.size();
|
|
||||||
assert(num_points > 1);
|
|
||||||
|
|
||||||
using point_type = std::pair<double,double>;
|
|
||||||
using linear_ring = std::vector<point_type>;
|
|
||||||
std::vector<linear_ring> rings;
|
|
||||||
|
|
||||||
double x = 0;
|
|
||||||
double y = 0;
|
|
||||||
std::size_t size = 1 + 4 + 4 ; // byteOrder + wkbType + numRings
|
std::size_t size = 1 + 4 + 4 ; // byteOrder + wkbType + numRings
|
||||||
for (unsigned i=0; i< num_points; ++i)
|
size += 4 + 2 * 8 * poly.exterior_ring.size();
|
||||||
|
for ( auto const& ring : poly.interior_rings)
|
||||||
{
|
{
|
||||||
unsigned command = g.vertex(i,&x,&y);
|
|
||||||
if (command == SEG_MOVETO)
|
size += 4 + 2 * 8 * ring.size();
|
||||||
{
|
|
||||||
linear_ring ring;
|
|
||||||
ring.reserve(1);
|
|
||||||
ring.emplace_back(x,y);
|
|
||||||
rings.push_back(std::move(ring)); // start new loop
|
|
||||||
size += 4; // num_points
|
|
||||||
size += 2 * 8; // point
|
|
||||||
}
|
|
||||||
else if (command == SEG_LINETO)
|
|
||||||
{
|
|
||||||
rings.back().emplace_back(x,y);
|
|
||||||
size += 2 * 8; // point
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
unsigned num_rings = rings.size();
|
|
||||||
wkb_buffer_ptr wkb = std::make_unique<wkb_buffer>(size);
|
wkb_buffer_ptr wkb = std::make_unique<wkb_buffer>(size);
|
||||||
wkb_stream ss(wkb->buffer(), wkb->size());
|
wkb_stream ss(wkb->buffer(), wkb->size());
|
||||||
ss.write(reinterpret_cast<char*>(&byte_order),1);
|
ss.write(reinterpret_cast<char*>(&byte_order),1);
|
||||||
int type = static_cast<int>(mapnik::new_geometry::geometry_types::Polygon);
|
write(ss, static_cast<int>(mapnik::new_geometry::geometry_types::Polygon), 4, byte_order);
|
||||||
write(ss,type,4,byte_order);
|
write(ss, poly.num_rings(), 4, byte_order);
|
||||||
write(ss,num_rings,4,byte_order);
|
|
||||||
|
|
||||||
for ( linear_ring const& ring : rings)
|
// exterior
|
||||||
|
write(ss, poly.exterior_ring.size(), 4, byte_order);
|
||||||
|
for (auto const& pt : poly.exterior_ring)
|
||||||
{
|
{
|
||||||
unsigned num_ring_points = ring.size();
|
write(ss, pt.x, 8, byte_order);
|
||||||
write(ss,num_ring_points,4,byte_order);
|
write(ss, pt.y, 8, byte_order);
|
||||||
for ( point_type const& pt : ring)
|
}
|
||||||
|
// interiors
|
||||||
|
for (auto const& ring : poly.interior_rings)
|
||||||
|
{
|
||||||
|
write(ss, ring.size(), 4, byte_order);
|
||||||
|
for ( auto const& pt : ring)
|
||||||
{
|
{
|
||||||
write(ss,pt.first,8,byte_order);
|
write(ss, pt.x, 8, byte_order);
|
||||||
write(ss,pt.second,8,byte_order);
|
write(ss, pt.y, 8, byte_order);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,71 +202,106 @@ wkb_buffer_ptr to_polygon_wkb( GeometryType const& g, wkbByteOrder byte_order)
|
||||||
return std::move(wkb);
|
return std::move(wkb);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename GeometryType>
|
wkb_buffer_ptr multi_point_wkb( new_geometry::multi_point const& multi_pt, wkbByteOrder byte_order)
|
||||||
wkb_buffer_ptr to_wkb(GeometryType const& g, wkbByteOrder byte_order )
|
|
||||||
{
|
{
|
||||||
wkb_buffer_ptr wkb;
|
std::size_t size = 1 + 4 + (1 + 4 + 8 * 2) * multi_pt.size() ; // byteOrder + wkbType + Point.size * num_points
|
||||||
vertex_adapter va(g);
|
wkb_buffer_ptr wkb = std::make_unique<wkb_buffer>(size);
|
||||||
switch (va.type())
|
wkb_stream ss(wkb->buffer(), wkb->size());
|
||||||
|
ss.write(reinterpret_cast<char*>(&byte_order),1);
|
||||||
|
write(ss, static_cast<int>(new_geometry::geometry_types::MultiPoint), 4, byte_order);
|
||||||
|
write(ss, multi_pt.size(), 4 ,byte_order);
|
||||||
|
for (auto const& pt : multi_pt)
|
||||||
{
|
{
|
||||||
case mapnik::new_geometry::geometry_types::Point:
|
|
||||||
wkb = to_point_wkb(va, byte_order);
|
|
||||||
break;
|
|
||||||
case mapnik::new_geometry::geometry_types::LineString:
|
|
||||||
wkb = to_line_string_wkb(va, byte_order);
|
|
||||||
break;
|
|
||||||
case mapnik::new_geometry::geometry_types::Polygon:
|
|
||||||
wkb = to_polygon_wkb(va, byte_order);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return wkb;
|
|
||||||
}
|
|
||||||
|
|
||||||
wkb_buffer_ptr to_wkb(geometry_container const& paths, wkbByteOrder byte_order )
|
|
||||||
{
|
|
||||||
if (paths.size() == 1)
|
|
||||||
{
|
|
||||||
// single geometry
|
|
||||||
return to_wkb(paths.front(), byte_order);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (paths.size() > 1)
|
|
||||||
{
|
|
||||||
// multi geometry or geometry collection
|
|
||||||
std::vector<wkb_buffer_ptr> wkb_cont;
|
|
||||||
bool collection = false;
|
|
||||||
int multi_type = 0;
|
|
||||||
size_t multi_size = 1 + 4 + 4;
|
|
||||||
|
|
||||||
for (auto const& geom : paths)
|
|
||||||
{
|
|
||||||
wkb_buffer_ptr wkb = to_wkb(geom,byte_order);
|
|
||||||
multi_size += wkb->size();
|
|
||||||
int type = static_cast<int>(geom.type());
|
|
||||||
if (multi_type > 0 && multi_type != geom.type())
|
|
||||||
collection = true;
|
|
||||||
multi_type = type;
|
|
||||||
wkb_cont.push_back(std::move(wkb));
|
|
||||||
}
|
|
||||||
|
|
||||||
wkb_buffer_ptr multi_wkb = std::make_unique<wkb_buffer>(multi_size);
|
|
||||||
wkb_stream ss(multi_wkb->buffer(), multi_wkb->size());
|
|
||||||
ss.write(reinterpret_cast<char*>(&byte_order),1);
|
ss.write(reinterpret_cast<char*>(&byte_order),1);
|
||||||
multi_type = collection ? 7 : multi_type + 3;
|
write(ss, static_cast<int>(new_geometry::geometry_types::Point), 4, byte_order);
|
||||||
write(ss,multi_type, 4, byte_order);
|
write(ss, pt.x, 8, byte_order);
|
||||||
write(ss,paths.size(),4,byte_order);
|
write(ss, pt.y, 8, byte_order);
|
||||||
|
}
|
||||||
|
assert(ss.good());
|
||||||
|
return std::move(wkb);
|
||||||
|
}
|
||||||
|
|
||||||
for ( wkb_buffer_ptr const& wkb : wkb_cont)
|
|
||||||
{
|
template <typename MultiGeometry>
|
||||||
ss.write(wkb->buffer(),wkb->size());
|
wkb_buffer_ptr multi_geom_wkb(MultiGeometry const& multi_geom, wkbByteOrder byte_order);
|
||||||
}
|
|
||||||
return std::move(multi_wkb);
|
struct geometry_to_wkb
|
||||||
|
{
|
||||||
|
using result_type = wkb_buffer_ptr;
|
||||||
|
|
||||||
|
geometry_to_wkb(wkbByteOrder byte_order)
|
||||||
|
: byte_order_(byte_order) {}
|
||||||
|
|
||||||
|
result_type operator() (new_geometry::geometry const& geom) const
|
||||||
|
{
|
||||||
|
return util::apply_visitor(*this, geom);
|
||||||
}
|
}
|
||||||
|
|
||||||
return wkb_buffer_ptr();
|
result_type operator() (new_geometry::point const& pt) const
|
||||||
|
{
|
||||||
|
return point_wkb(pt, byte_order_);
|
||||||
|
}
|
||||||
|
|
||||||
|
result_type operator() (new_geometry::line_string const& line) const
|
||||||
|
{
|
||||||
|
return line_string_wkb(line, byte_order_);
|
||||||
|
}
|
||||||
|
|
||||||
|
result_type operator() (new_geometry::polygon const& poly) const
|
||||||
|
{
|
||||||
|
return polygon_wkb(poly, byte_order_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// multi/collection
|
||||||
|
|
||||||
|
//result_type operator() (new_geometry::multi_point const& multi_pt) const
|
||||||
|
//{
|
||||||
|
// return multi_point_wkb(multi_pt, byte_order_);
|
||||||
|
//}
|
||||||
|
|
||||||
|
template <typename Geometry>
|
||||||
|
result_type operator() (Geometry const& geom) const
|
||||||
|
{
|
||||||
|
return multi_geom_wkb(geom, byte_order_);
|
||||||
|
}
|
||||||
|
|
||||||
|
wkbByteOrder byte_order_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename MultiGeometry>
|
||||||
|
wkb_buffer_ptr multi_geom_wkb(MultiGeometry const& multi_geom, wkbByteOrder byte_order)
|
||||||
|
{
|
||||||
|
size_t multi_size = 1 + 4 + 4;
|
||||||
|
std::vector<wkb_buffer_ptr> wkb_cont;
|
||||||
|
for (auto const& geom : multi_geom)
|
||||||
|
{
|
||||||
|
wkb_buffer_ptr wkb = geometry_to_wkb(byte_order)(geom);
|
||||||
|
multi_size += wkb->size();
|
||||||
|
wkb_cont.push_back(std::move(wkb));
|
||||||
|
}
|
||||||
|
wkb_buffer_ptr multi_wkb = std::make_unique<wkb_buffer>(multi_size);
|
||||||
|
wkb_stream ss(multi_wkb->buffer(), multi_wkb->size());
|
||||||
|
ss.write(reinterpret_cast<char*>(&byte_order),1);
|
||||||
|
write(ss, static_cast<int>(new_geometry::detail::geometry_type()(multi_geom)) , 4, byte_order);
|
||||||
|
write(ss, multi_geom.size(), 4 ,byte_order);
|
||||||
|
|
||||||
|
for ( wkb_buffer_ptr const& wkb : wkb_cont)
|
||||||
|
{
|
||||||
|
ss.write(wkb->buffer(), wkb->size());
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::move(multi_wkb);
|
||||||
}
|
}
|
||||||
|
} // ns detail
|
||||||
|
|
||||||
|
using wkb_buffer_ptr = detail::wkb_buffer_ptr;
|
||||||
|
|
||||||
|
template<typename GeometryType>
|
||||||
|
wkb_buffer_ptr to_wkb(GeometryType const& geom, wkbByteOrder byte_order )
|
||||||
|
{
|
||||||
|
return std::move(detail::geometry_to_wkb(byte_order)(geom));
|
||||||
|
}
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|
||||||
#endif // MAPNIK_GEOMETRY_TO_WKB_HPP
|
#endif // MAPNIK_GEOMETRY_TO_WKB_HPP
|
||||||
|
|
Loading…
Reference in a new issue