Merge pull request #160 from awulkiew/fix/read_wkt

Fix/read wkt
This commit is contained in:
Adam Wulkiewicz 2014-11-19 17:57:48 +01:00
commit 11d627808a
6 changed files with 181 additions and 39 deletions

View File

@ -4,6 +4,11 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@ -29,6 +34,7 @@
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/append.hpp>
#include <boost/geometry/algorithms/clear.hpp>
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
@ -38,6 +44,7 @@
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/mutable_range.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
@ -98,7 +105,9 @@ namespace detail { namespace wkt
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
template <typename Point, std::size_t Dimension, std::size_t DimensionCount>
template <typename Point,
std::size_t Dimension = 0,
std::size_t DimensionCount = geometry::dimension<Point>::value>
struct parsing_assigner
{
static inline void apply(tokenizer::iterator& it, tokenizer::iterator end,
@ -208,12 +217,7 @@ struct container_inserter
while (it != end && *it != ")")
{
parsing_assigner
<
Point,
0,
dimension<Point>::value
>::apply(it, end, point, wkt);
parsing_assigner<Point>::apply(it, end, point, wkt);
out = point;
++out;
if (it != end && *it == ",")
@ -227,35 +231,92 @@ struct container_inserter
};
template <typename Geometry,
closure_selector Closure = closure<Geometry>::value>
struct stateful_range_appender
{
typedef typename geometry::point_type<Geometry>::type point_type;
inline void append(Geometry & geom, point_type const& point, bool)
{
geometry::append(geom, point);
}
};
template <typename Geometry>
struct stateful_range_appender<Geometry, open>
{
typedef typename geometry::point_type<Geometry>::type point_type;
typedef typename boost::range_size
<
typename util::bare_type<Geometry>::type
>::type size_type;
BOOST_STATIC_ASSERT(( boost::is_same
<
typename tag<Geometry>::type,
ring_tag
>::value ));
inline stateful_range_appender()
: pt_index(0)
{}
inline void append(Geometry & geom, point_type const& point, bool is_next_expected)
{
bool should_append = true;
if ( pt_index == 0 )
{
first_point = point;
//should_append = true;
}
else
{
// NOTE: if there is not enough Points, they're always appended
should_append
= is_next_expected
|| pt_index < core_detail::closure::minimum_ring_size<open>::value
|| !detail::equals::equals_point_point(point, first_point);
}
++pt_index;
if ( should_append )
{
geometry::append(geom, point);
}
}
private:
size_type pt_index;
point_type first_point;
};
// Geometry is a value-type or reference-type
template <typename Geometry>
struct container_appender
{
typedef typename geometry::point_type
<
typename boost::remove_reference<Geometry>::type
>::type point_type;
typedef typename geometry::point_type<Geometry>::type point_type;
static inline void apply(tokenizer::iterator& it, tokenizer::iterator end,
std::string const& wkt, Geometry out)
std::string const& wkt, Geometry out)
{
handle_open_parenthesis(it, end, wkt);
point_type point;
stateful_range_appender<Geometry> appender;
// Parse points until closing parenthesis
while (it != end && *it != ")")
{
parsing_assigner
<
point_type,
0,
dimension<point_type>::value
>::apply(it, end, point, wkt);
point_type point;
geometry::append(out, point);
if (it != end && *it == ",")
parsing_assigner<point_type>::apply(it, end, point, wkt);
bool const is_next_expected = it != end && *it == ",";
appender.append(out, point, is_next_expected);
if ( is_next_expected )
{
++it;
}
@ -276,7 +337,7 @@ struct point_parser
std::string const& wkt, P& point)
{
handle_open_parenthesis(it, end, wkt);
parsing_assigner<P, 0, dimension<P>::value>::apply(it, end, point, wkt);
parsing_assigner<P>::apply(it, end, point, wkt);
handle_close_parenthesis(it, end, wkt);
}
};
@ -512,7 +573,7 @@ struct noparenthesis_point_parser
static inline void apply(tokenizer::iterator& it, tokenizer::iterator end,
std::string const& wkt, P& point)
{
parsing_assigner<P, 0, dimension<P>::value>::apply(it, end, point, wkt);
parsing_assigner<P>::apply(it, end, point, wkt);
}
};

View File

@ -280,7 +280,7 @@ void test_open_rings()
test::apply(from_wkt<OG>("POLYGON((0 0,0 0,0 0))"), false);
test::apply(from_wkt<OG>("POLYGON((0 0,1 0,1 0))"), false);
test::apply(from_wkt<OG>("POLYGON((0 0,1 0,0 0))"), false);
test::apply(from_wkt<OG>("POLYGON((0 0,1 0,1 1,0 0))"),
test::apply(from_wkt<OG>("POLYGON((0 0,1 0,1 1,0 0,0 0))"),
AllowDuplicates);
test::apply(from_wkt<OG>("POLYGON((0 0,1 0,1 0,1 1))"),
AllowDuplicates);
@ -426,7 +426,7 @@ void test_open_polygons()
test::apply(from_wkt<OG>("POLYGON((0 0,0 0,0 0))"), false);
test::apply(from_wkt<OG>("POLYGON((0 0,1 0,1 0))"), false);
test::apply(from_wkt<OG>("POLYGON((0 0,1 0,0 0))"), false);
test::apply(from_wkt<OG>("POLYGON((0 0,1 0,1 1,0 0))"), AllowDuplicates);
test::apply(from_wkt<OG>("POLYGON((0 0,1 0,1 1,0 0,0 0))"), AllowDuplicates);
test::apply(from_wkt<OG>("POLYGON((0 0,1 0,1 0,1 1))"), AllowDuplicates);
test::apply(from_wkt<OG>("POLYGON((0 0,1 0,1 0,1 1,0 0))"),
AllowDuplicates);
@ -438,7 +438,7 @@ void test_open_polygons()
false);
test::apply(from_wkt<OG>("POLYGON((0 0,10 0,10 10,0 10),(1 1,2 1,1 1))"),
false);
test::apply(from_wkt<OG>("POLYGON((0 0,10 0,10 10,0 10),(1 1,2 2,2 1,1 1))"),
test::apply(from_wkt<OG>("POLYGON((0 0,10 0,10 10,0 10),(1 1,2 2,2 1,1 1,1 1))"),
AllowDuplicates);
test::apply(from_wkt<OG>("POLYGON((0 0,10 0,10 10,0 10),(1 1,2 2,2 2,2 1))"),
AllowDuplicates);

View File

@ -86,11 +86,11 @@ int test_main(int, char* [])
// test open geometries
test_num_points<open_ring>("POLYGON((0 0,1 1,0 1))", 3u, 4u);
test_num_points<open_ring>("POLYGON((0 0,1 1,0 1,0 0))", 4u, 5u);
test_num_points<open_ring>("POLYGON((0 0,1 1,0 1,0 0))", 3u, 4u);
test_num_points<open_polygon>("POLYGON((0 0,10 10,0 10))", 3u, 4u);
test_num_points<open_polygon>("POLYGON((0 0,10 10,0 10,0 0))", 4u, 5u);
test_num_points<open_polygon>("POLYGON((0 0,10 10,0 10,0 0))", 3u, 4u);
test_num_points<open_multi_polygon>("MULTIPOLYGON(((0 0,0 10,10 10,10 0)),((0 10,1 10,1 9)))", 7u, 9u);
test_num_points<open_multi_polygon>("MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)),((0 10,1 10,1 9,0 10)))", 9u, 11u);
test_num_points<open_multi_polygon>("MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)),((0 10,1 10,1 9,0 10)))", 7u, 9u);
return 0;
}

View File

@ -88,10 +88,6 @@ void test_ordered_ring(std::string const& wkt_point,
{
std::reverse(boost::begin(ring), boost::end(ring));
}
if (! Closed)
{
ring.resize(ring.size() - 1);
}
bg::read_wkt(wkt_point, point);

View File

@ -5,6 +5,11 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@ -45,6 +50,33 @@ void test_all();
#define GEOMETRY_TEST_MULTI
#include "io/wkt/wkt.cpp"
template <typename T>
void test_order_closure()
{
using namespace boost::geometry;
typedef bg::model::point<T, 2, bg::cs::cartesian> Pt;
typedef bg::model::polygon<Pt, true, true> PCWC;
typedef bg::model::polygon<Pt, true, false> PCWO;
typedef bg::model::polygon<Pt, false, true> PCCWC;
typedef bg::model::polygon<Pt, false, false> PCCWO;
typedef bg::model::multi_polygon<PCWC> MPCWC;
typedef bg::model::multi_polygon<PCWO> MPCWO;
typedef bg::model::multi_polygon<PCCWC> MPCCWC;
typedef bg::model::multi_polygon<PCCWO> MPCCWO;
std::string wkt_cwc = "MULTIPOLYGON(((0 0,0 2,2 2,2 0,0 0)),((0 0,0 -3,-3 -3,-3 0,0 0),(-1 -1,-2 -1,-2 -2,-1 -2,-1 -1)))";
std::string wkt_cwo = "MULTIPOLYGON(((0 0,0 2,2 2,2 0)),((0 0,0 -3,-3 -3,-3 0),(-1 -1,-2 -1,-2 -2,-1 -2)))";
std::string wkt_ccwc = "MULTIPOLYGON(((0 0,2 0,2 2,0 2,0 0)),((0 0,-3 0,-3 -3,0 -3,0 0),(-1 -1,-1 -2,-2 -2,-2 -1,-1 -1)))";
std::string wkt_ccwo = "MULTIPOLYGON(((0 0,2 0,2 2,0 2)),((0 0,-3 0,-3 -3,0 -3),(-1 -1,-1 -2,-2 -2,-2 -1)))";
test_wkt<MPCWC>(wkt_cwc, wkt_cwc, 15, 0, 12, 24);
test_wkt<MPCWO>(wkt_cwc, wkt_cwc, 12, 0, 12, 24);
test_wkt<MPCWO>(wkt_cwo, wkt_cwc, 12, 0, 12, 24);
test_wkt<MPCCWC>(wkt_ccwc, wkt_ccwc, 15, 0, 12, 24);
test_wkt<MPCCWO>(wkt_ccwc, wkt_ccwc, 12, 0, 12, 24);
test_wkt<MPCCWO>(wkt_ccwo, wkt_ccwc, 12, 0, 12, 24);
}
template <typename T>
void test_all()
{
@ -79,6 +111,8 @@ void test_all()
test_wrong_wkt<bg::model::multi_point<P> >(
"MULTIPOINT(16 17), (18 19)",
"too much tokens at ',' in 'multipoint(16 17), (18 19)'");
test_order_closure<T>();
}
/*

View File

@ -5,6 +5,11 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@ -42,8 +47,8 @@ void check_wkt(G const& geometry, std::string const& expected)
}
template <typename G>
void test_wkt(std::string const& wkt, std::size_t n, double len = 0,
double ar = 0, double peri = 0)
void test_wkt(std::string const& wkt, std::string const& expected,
std::size_t n, double len = 0, double ar = 0, double peri = 0)
{
G geometry;
@ -67,8 +72,15 @@ void test_wkt(std::string const& wkt, std::size_t n, double len = 0,
BOOST_CHECK_CLOSE(double(bg::perimeter(geometry)), peri, 0.0001);
}
check_wkt(geometry, wkt);
check_wkt(boost::variant<G>(geometry), wkt);
check_wkt(geometry, expected);
check_wkt(boost::variant<G>(geometry), expected);
}
template <typename G>
void test_wkt(std::string const& wkt,
std::size_t n, double len = 0, double ar = 0, double peri = 0)
{
test_wkt<G>(wkt, wkt, n, len, ar, peri);
}
template <typename G>
@ -135,6 +147,44 @@ void test_wkt_output_iterator(std::string const& wkt)
#ifndef GEOMETRY_TEST_MULTI
template <typename T>
void test_order_closure()
{
using namespace boost::geometry;
typedef bg::model::point<T, 2, bg::cs::cartesian> Pt;
typedef bg::model::polygon<Pt, true, true> PCWC;
typedef bg::model::polygon<Pt, true, false> PCWO;
typedef bg::model::polygon<Pt, false, true> PCCWC;
typedef bg::model::polygon<Pt, false, false> PCCWO;
{
std::string wkt_cwc = "POLYGON((0 0,0 2,2 2,2 0,0 0))";
std::string wkt_cwo = "POLYGON((0 0,0 2,2 2,2 0))";
std::string wkt_ccwc = "POLYGON((0 0,2 0,2 2,0 2,0 0))";
std::string wkt_ccwo = "POLYGON((0 0,2 0,2 2,0 2))";
test_wkt<PCWC>(wkt_cwc, 5, 0, 4, 8);
test_wkt<PCWO>(wkt_cwc, 4, 0, 4, 8);
test_wkt<PCWO>(wkt_cwo, wkt_cwc, 4, 0, 4, 8);
test_wkt<PCCWC>(wkt_ccwc, 5, 0, 4, 8);
test_wkt<PCCWO>(wkt_ccwc, 4, 0, 4, 8);
test_wkt<PCCWO>(wkt_ccwo, wkt_ccwc, 4, 0, 4, 8);
}
{
std::string wkt_cwc = "POLYGON((0 0,0 3,3 3,3 0,0 0),(1 1,2 1,2 2,1 2,1 1))";
std::string wkt_cwo = "POLYGON((0 0,0 3,3 3,3 0),(1 1,2 1,2 2,1 2))";
std::string wkt_ccwc = "POLYGON((0 0,3 0,3 3,0 3,0 0),(1 1,1 2,2 2,2 1,1 1))";
std::string wkt_ccwo = "POLYGON((0 0,3 0,3 3,0 3),(1 1,1 2,2 2,2 1,1 1))";
test_wkt<PCWC>(wkt_cwc, 10, 0, 8, 16);
test_wkt<PCWO>(wkt_cwc, 8, 0, 8, 16);
test_wkt<PCWO>(wkt_cwo, wkt_cwc, 8, 0, 8, 16);
test_wkt<PCCWC>(wkt_ccwc, 10, 0, 8, 16);
test_wkt<PCCWO>(wkt_ccwc, 8, 0, 8, 16);
test_wkt<PCCWO>(wkt_ccwo, wkt_ccwc, 8, 0, 8, 16);
}
}
template <typename T>
void test_all()
{
@ -201,10 +251,11 @@ void test_all()
// Deprecated:
// test_wkt_output_iterator<bg::model::linestring<P> >("LINESTRING(1 1,2 2,3 3)");
// test_wkt_output_iterator<bg::model::ring<P> >("POLYGON((1 1,2 2,3 3))");
test_order_closure<T>();
}
#endif
int test_main(int, char* [])
{
test_all<double>();