Merge pull request #437 from awulkiew/feature/complexify

Add new algorithm - densify()
This commit is contained in:
Adam Wulkiewicz 2018-01-16 14:45:06 +01:00 committed by GitHub
commit dbf56a8210
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 1334 additions and 23 deletions

View File

@ -2,6 +2,10 @@
// //
// Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2018.
// Modifications copyright (c) 2018, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License, // Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
@ -26,6 +30,7 @@
\defgroup covered_by covered_by: detect if a geometry is inside or on the border of another geometry, a.o. point-in-polygon (border included) \defgroup covered_by covered_by: detect if a geometry is inside or on the border of another geometry, a.o. point-in-polygon (border included)
\defgroup crosses crosses: detect if two geometries crosses each other \defgroup crosses crosses: detect if two geometries crosses each other
\defgroup cs coordinate systems \defgroup cs coordinate systems
\defgroup densify densify: add points to geometry, keeping shape
\defgroup difference difference: difference of two geometries \defgroup difference difference: difference of two geometries
\defgroup disjoint disjoint: detect if geometries are not spatially related \defgroup disjoint disjoint: detect if geometries are not spatially related
\defgroup distance distance: calculate distance between two geometries \defgroup distance distance: calculate distance between two geometries

View File

@ -5,6 +5,9 @@
Copyright (c) 2009-2012 Mateusz Loskot, London, UK. Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
Copyright (c) 2009-2012 Bruno Lalande, Paris, France. Copyright (c) 2009-2012 Bruno Lalande, Paris, France.
Copyright (c) 2018, Oracle and/or its affiliates.
Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
Use, modification and distribution is subject to the Boost Software License, Use, modification and distribution is subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt) http://www.boost.org/LICENSE_1_0.txt)
@ -27,6 +30,8 @@
[import src/examples/algorithms/convert.cpp] [import src/examples/algorithms/convert.cpp]
[import src/examples/algorithms/convex_hull.cpp] [import src/examples/algorithms/convex_hull.cpp]
[import src/examples/algorithms/correct.cpp] [import src/examples/algorithms/correct.cpp]
[import src/examples/algorithms/densify.cpp]
[import src/examples/algorithms/densify_strategy.cpp]
[import src/examples/algorithms/distance.cpp] [import src/examples/algorithms/distance.cpp]
[import src/examples/algorithms/difference.cpp] [import src/examples/algorithms/difference.cpp]
[import src/examples/algorithms/envelope.cpp] [import src/examples/algorithms/envelope.cpp]

View File

@ -6,6 +6,9 @@
# Copyright (c) 2009-2012 Mateusz Loskot (mateusz@loskot.net), London, UK # Copyright (c) 2009-2012 Mateusz Loskot (mateusz@loskot.net), London, UK
# Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland # Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland
# #
# Copyright (c) 2018, Oracle and/or its affiliates.
# Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
#
# Use, modification and distribution is subject to the Boost Software License, # Use, modification and distribution is subject to the Boost Software License,
# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at # Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt) # http://www.boost.org/LICENSE_1_0.txt)
@ -91,7 +94,7 @@ call_doxygen()
algorithms = ["append", "assign", "make", "clear" algorithms = ["append", "assign", "make", "clear"
, "area", "buffer", "centroid", "convert", "correct", "covered_by" , "area", "buffer", "centroid", "convert", "correct", "covered_by"
, "convex_hull", "crosses", "difference", "disjoint", "distance" , "convex_hull", "crosses", "densify", "difference", "disjoint", "distance"
, "envelope", "equals", "expand", "for_each", "is_empty" , "envelope", "equals", "expand", "for_each", "is_empty"
, "is_simple", "is_valid", "intersection", "intersects", "length" , "is_simple", "is_valid", "intersection", "intersects", "length"
, "num_geometries", "num_interior_rings", "num_points" , "num_geometries", "num_interior_rings", "num_points"
@ -120,7 +123,8 @@ models = ["point", "linestring", "box"
, "multi_linestring", "multi_point", "multi_polygon", "referring_segment"] , "multi_linestring", "multi_point", "multi_polygon", "referring_segment"]
strategies = ["distance::pythagoras", "distance::pythagoras_box_box" strategies = ["densify::cartesian", "densify::geographic", "densify::spherical"
, "distance::pythagoras", "distance::pythagoras_box_box"
, "distance::pythagoras_point_box", "distance::haversine" , "distance::pythagoras_point_box", "distance::haversine"
, "distance::cross_track", "distance::cross_track_point_box" , "distance::cross_track", "distance::cross_track_point_box"
, "distance::projected_point" , "distance::projected_point"

View File

@ -10,8 +10,8 @@
Copyright (c) 2009-2015 Bruno Lalande, Paris, France. Copyright (c) 2009-2015 Bruno Lalande, Paris, France.
Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland. Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
This file was modified by Oracle on 2014, 2015, 2017. This file was modified by Oracle on 2014, 2015, 2017, 2018.
Modifications copyright (c) 2014-2017, Oracle and/or its affiliates. Modifications copyright (c) 2014-2018, Oracle and/or its affiliates.
Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@ -389,6 +389,10 @@
</row> </row>
<row> <row>
<entry valign="top"> <entry valign="top">
<bridgehead renderas="sect3">Densify</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="geometry.reference.algorithms.densify">densify</link></member>
</simplelist>
<bridgehead renderas="sect3">Distance</bridgehead> <bridgehead renderas="sect3">Distance</bridgehead>
<simplelist type="vert" columns="1"> <simplelist type="vert" columns="1">
<member><link linkend="geometry.reference.algorithms.distance">distance</link></member> <member><link linkend="geometry.reference.algorithms.distance">distance</link></member>
@ -410,17 +414,16 @@
<simplelist type="vert" columns="1"> <simplelist type="vert" columns="1">
<member><link linkend="geometry.reference.algorithms.for_each">for each (point, segment)</link></member> <member><link linkend="geometry.reference.algorithms.for_each">for each (point, segment)</link></member>
</simplelist> </simplelist>
</entry>
<entry valign="top">
<bridgehead renderas="sect3">Intersection</bridgehead> <bridgehead renderas="sect3">Intersection</bridgehead>
<simplelist type="vert" columns="1"> <simplelist type="vert" columns="1">
<member><link linkend="geometry.reference.algorithms.intersection">intersection</link></member> <member><link linkend="geometry.reference.algorithms.intersection">intersection</link></member>
</simplelist> </simplelist>
</entry>
<entry valign="top">
<bridgehead renderas="sect3">Length</bridgehead> <bridgehead renderas="sect3">Length</bridgehead>
<simplelist type="vert" columns="1"> <simplelist type="vert" columns="1">
<member><link linkend="geometry.reference.algorithms.length">length</link></member> <member><link linkend="geometry.reference.algorithms.length">length</link></member>
</simplelist> </simplelist>
<bridgehead renderas="sect3">Num_ (counting)</bridgehead> <bridgehead renderas="sect3">Num_ (counting)</bridgehead>
<simplelist type="vert" columns="1"> <simplelist type="vert" columns="1">
<member><link linkend="geometry.reference.algorithms.num_interior_rings">num_interior_rings</link></member> <member><link linkend="geometry.reference.algorithms.num_interior_rings">num_interior_rings</link></member>
@ -428,8 +431,6 @@
<member><link linkend="geometry.reference.algorithms.num_points">num_points</link></member> <member><link linkend="geometry.reference.algorithms.num_points">num_points</link></member>
<member><link linkend="geometry.reference.algorithms.num_segments">num_segments</link></member> <member><link linkend="geometry.reference.algorithms.num_segments">num_segments</link></member>
</simplelist> </simplelist>
<bridgehead renderas="sect3">Perimeter</bridgehead> <bridgehead renderas="sect3">Perimeter</bridgehead>
<simplelist type="vert" columns="1"> <simplelist type="vert" columns="1">
<member><link linkend="geometry.reference.algorithms.perimeter">perimeter</link></member> <member><link linkend="geometry.reference.algorithms.perimeter">perimeter</link></member>
@ -439,12 +440,12 @@
<member><link linkend="geometry.reference.algorithms.relate">relate</link></member> <member><link linkend="geometry.reference.algorithms.relate">relate</link></member>
<member><link linkend="geometry.reference.algorithms.relation">relation</link></member> <member><link linkend="geometry.reference.algorithms.relation">relation</link></member>
</simplelist> </simplelist>
</entry>
<entry valign="top">
<bridgehead renderas="sect3">Reverse</bridgehead> <bridgehead renderas="sect3">Reverse</bridgehead>
<simplelist type="vert" columns="1"> <simplelist type="vert" columns="1">
<member><link linkend="geometry.reference.algorithms.reverse">reverse</link></member> <member><link linkend="geometry.reference.algorithms.reverse">reverse</link></member>
</simplelist> </simplelist>
</entry>
<entry valign="top">
<bridgehead renderas="sect3">Simplify</bridgehead> <bridgehead renderas="sect3">Simplify</bridgehead>
<simplelist type="vert" columns="1"> <simplelist type="vert" columns="1">
<member><link linkend="geometry.reference.algorithms.simplify">simplify</link></member> <member><link linkend="geometry.reference.algorithms.simplify">simplify</link></member>
@ -554,6 +555,14 @@
<member><link linkend="geometry.reference.strategies.strategy_convex_hull_graham_andrew">strategy::convex_hull::graham_andrew</link></member> <member><link linkend="geometry.reference.strategies.strategy_convex_hull_graham_andrew">strategy::convex_hull::graham_andrew</link></member>
</simplelist> </simplelist>
</entry> </entry>
<entry valign="top">
<bridgehead renderas="sect3">Densify</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="geometry.reference.strategies.strategy_densify_cartesian">strategy::densify::cartesian</link></member>
<member><link linkend="geometry.reference.strategies.strategy_densify_geographic">strategy::densify::geographic</link></member>
<member><link linkend="geometry.reference.strategies.strategy_densify_spherical">strategy::densify::spherical</link></member>
</simplelist>
</entry>
<entry valign="top"> <entry valign="top">
<bridgehead renderas="sect3">Distance</bridgehead> <bridgehead renderas="sect3">Distance</bridgehead>
<simplelist type="vert" columns="1"> <simplelist type="vert" columns="1">
@ -566,6 +575,8 @@
<member><link linkend="geometry.reference.strategies.strategy_distance_haversine">strategy::distance::haversine</link></member> <member><link linkend="geometry.reference.strategies.strategy_distance_haversine">strategy::distance::haversine</link></member>
</simplelist> </simplelist>
</entry> </entry>
</row>
<row>
<entry valign="top"> <entry valign="top">
<bridgehead renderas="sect3">Side</bridgehead> <bridgehead renderas="sect3">Side</bridgehead>
<simplelist type="vert" columns="1"> <simplelist type="vert" columns="1">
@ -574,8 +585,6 @@
<member><link linkend="geometry.reference.strategies.strategy_side_spherical_side_formula">strategy::side::spherical_side_formula</link></member> <member><link linkend="geometry.reference.strategies.strategy_side_spherical_side_formula">strategy::side::spherical_side_formula</link></member>
</simplelist> </simplelist>
</entry> </entry>
</row>
<row>
<entry valign="top"> <entry valign="top">
<bridgehead renderas="sect3">Simplify</bridgehead> <bridgehead renderas="sect3">Simplify</bridgehead>
<simplelist type="vert" columns="1"> <simplelist type="vert" columns="1">
@ -593,7 +602,9 @@
<member><link linkend="geometry.reference.strategies.strategy_transform_rotate_transformer">strategy::transform::rotate_transformer</link></member> <member><link linkend="geometry.reference.strategies.strategy_transform_rotate_transformer">strategy::transform::rotate_transformer</link></member>
</simplelist> </simplelist>
</entry> </entry>
<entry valign="top"> </row>
<row>
<entry valign="top" namest="a" nameend="c">
<bridgehead renderas="sect3">Within</bridgehead> <bridgehead renderas="sect3">Within</bridgehead>
<simplelist type="vert" columns="1"> <simplelist type="vert" columns="1">
<member><link linkend="geometry.reference.strategies.strategy_within_winding">strategy::winding</link></member> <member><link linkend="geometry.reference.strategies.strategy_within_winding">strategy::winding</link></member>

View File

@ -6,8 +6,8 @@
Copyright (c) 2009-2017 Bruno Lalande, Paris, France. Copyright (c) 2009-2017 Bruno Lalande, Paris, France.
Copyright (c) 2013-2017 Adam Wulkiewicz, Lodz, Poland. Copyright (c) 2013-2017 Adam Wulkiewicz, Lodz, Poland.
This file was modified by Oracle on 2014, 2017. This file was modified by Oracle on 2014, 2017, 2018.
Modifications copyright (c) 2014-2017, Oracle and/or its affiliates. Modifications copyright (c) 2014-2018, Oracle and/or its affiliates.
Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@ -102,6 +102,10 @@
[include generated/crosses.qbk] [include generated/crosses.qbk]
[endsect] [endsect]
[section:densify densify]
[include generated/densify.qbk]
[endsect]
[section:difference difference] [section:difference difference]
[include generated/difference.qbk] [include generated/difference.qbk]
[endsect] [endsect]
@ -332,6 +336,9 @@
[section:strategies Strategies] [section:strategies Strategies]
[include generated/densify_cartesian.qbk]
[include generated/densify_geographic.qbk]
[include generated/densify_spherical.qbk]
[include generated/distance_pythagoras.qbk] [include generated/distance_pythagoras.qbk]
[include generated/distance_pythagoras_box_box.qbk] [include generated/distance_pythagoras_box_box.qbk]
[include generated/distance_pythagoras_point_box.qbk] [include generated/distance_pythagoras_point_box.qbk]

View File

@ -0,0 +1,25 @@
[/============================================================================
Boost.Geometry
Copyright (c) 2018, Oracle and/or its affiliates.
Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
Use, modification and distribution is subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
=============================================================================/]
[def __this_function__ densify]
[heading_conformance_no_ogc __this_function__]
[note PostGIS contains an algorithm ST_Segmentize with the same functionality.
See the [@http://www.postgis.org/docs/ST_Segmentize.html PostGIS documentation].
]
[heading Behavior]
The algorithm divides segments of a geometry if they are longer than passed
distance into smaller segments.
[note The units of the distance depends on strategy. In order to change the
default behavior a user has to create a strategy and pass it explicitly into
the algorithm.]

View File

@ -4,10 +4,11 @@
# Copyright (c) 2008-2015 Bruno Lalande, Paris, France. # Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
# Copyright (c) 2009-2015 Mateusz Loskot, London, UK. # Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
# This file was modified by Oracle on 2014, 2015. # This file was modified by Oracle on 2014, 2015, 2018.
# Modifications copyright (c) 2014-2015, Oracle and/or its affiliates. # Modifications copyright (c) 2014-2018, Oracle and/or its affiliates.
# Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle # Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
# Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
# Use, modification and distribution is subject to the Boost Software License, # Use, modification and distribution is subject to the Boost Software License,
# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at # Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@ -40,6 +41,8 @@ exe convert : convert.cpp ;
exe convex_hull : convex_hull.cpp ; exe convex_hull : convex_hull.cpp ;
exe correct : correct.cpp ; exe correct : correct.cpp ;
exe densify : densify.cpp ;
exe densify_strategy : densify_strategy.cpp ;
exe difference : difference.cpp ; exe difference : difference.cpp ;
exe distance : distance.cpp ; exe distance : distance.cpp ;

View File

@ -0,0 +1,47 @@
// Boost.Geometry
// QuickBook Example
// Copyright (c) 2018, Oracle and/or its affiliates
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//[densify
//` Shows how to densify a polygon
#include <iostream>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>
int main()
{
typedef boost::geometry::model::d2::point_xy<double> point_type;
typedef boost::geometry::model::polygon<point_type> polygon_type;
polygon_type poly;
boost::geometry::read_wkt(
"POLYGON((0 0,0 10,10 10,10 0,0 0),(1 1,4 1,4 4,1 4,1 1))", poly);
polygon_type res;
boost::geometry::densify(poly, res, 6.0);
std::cout << "densified: " << boost::geometry::wkt(res) << std::endl;
return 0;
}
//]
//[densify_output
/*`
Output:
[pre
densified: POLYGON((0 0,0 5,0 10,5 10,10 10,10 5,10 0,5 0,0 0),(1 1,4 1,4 4,1 4,1 1))
]
*/
//]

View File

@ -0,0 +1,50 @@
// Boost.Geometry
// QuickBook Example
// Copyright (c) 2018, Oracle and/or its affiliates
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//[densify_strategy
//` Shows how to densify a linestring in geographic coordinate system
#include <iostream>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/linestring.hpp>
int main()
{
namespace bg = boost::geometry;
typedef bg::model::point<double, 2, bg::cs::geographic<bg::degree> > point_type;
typedef bg::model::linestring<point_type> linestring_type;
linestring_type ls;
bg::read_wkt("LINESTRING(0 0,1 1)", ls);
linestring_type res;
bg::srs::spheroid<double> spheroid(6378137.0, 6356752.3142451793);
bg::strategy::densify::geographic<> strategy(spheroid);
boost::geometry::densify(ls, res, 50000.0, strategy);
std::cout << "densified: " << boost::geometry::wkt(res) << std::endl;
return 0;
}
//]
//[densify_strategy_output
/*`
Output:
[pre
densified: LINESTRING(0 0,0.249972 0.250011,0.499954 0.500017,0.749954 0.750013,1 1)
]
*/
//]

View File

@ -0,0 +1,425 @@
// Boost.Geometry
// Copyright (c) 2017-2018, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ALGORITHMS_DENSIFY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DENSIFY_HPP
#include <boost/geometry/algorithms/clear.hpp>
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/exception.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/densify.hpp>
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/range/size.hpp>
#include <boost/range/value_type.hpp>
#include <boost/throw_exception.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace densify
{
template <typename Range>
struct push_back_policy
{
typedef typename boost::range_value<Range>::type point_type;
inline explicit push_back_policy(Range & rng)
: m_rng(rng)
{}
inline void apply(point_type const& p)
{
range::push_back(m_rng, p);
}
private:
Range & m_rng;
};
template <typename Range, typename Point>
inline void convert_and_push_back(Range & range, Point const& p)
{
typename boost::range_value<Range>::type p2;
geometry::detail::conversion::convert_point_to_point(p, p2);
range::push_back(range, p2);
}
template <bool AppendLastPoint = true>
struct densify_range
{
template <typename FwdRng, typename MutRng, typename T, typename Strategy>
static inline void apply(FwdRng const& rng, MutRng & rng_out,
T const& len, Strategy const& strategy)
{
typedef typename boost::range_iterator<FwdRng const>::type iterator_t;
typedef typename boost::range_value<FwdRng>::type point_t;
iterator_t it = boost::begin(rng);
iterator_t end = boost::end(rng);
if (it == end) // empty(rng)
{
return;
}
push_back_policy<MutRng> policy(rng_out);
iterator_t prev = it;
for ( ++it ; it != end ; prev = it++)
{
point_t const& p0 = *prev;
point_t const& p1 = *it;
convert_and_push_back(rng_out, p0);
strategy.apply(p0, p1, policy, len);
}
if (BOOST_GEOMETRY_CONDITION(AppendLastPoint))
{
convert_and_push_back(rng_out, *prev); // back(rng)
}
}
};
template <bool IsClosed1, bool IsClosed2> // false, X
struct densify_ring
{
template <typename Geometry, typename GeometryOut, typename T, typename Strategy>
static inline void apply(Geometry const& ring, GeometryOut & ring_out,
T const& len, Strategy const& strategy)
{
geometry::detail::densify::densify_range<true>
::apply(ring, ring_out, len, strategy);
if (boost::size(ring) <= 1)
return;
typedef typename point_type<Geometry>::type point_t;
point_t const& p0 = range::back(ring);
point_t const& p1 = range::front(ring);
push_back_policy<GeometryOut> policy(ring_out);
strategy.apply(p0, p1, policy, len);
if (BOOST_GEOMETRY_CONDITION(IsClosed2))
{
convert_and_push_back(ring_out, p1);
}
}
};
template <>
struct densify_ring<true, true>
: densify_range<true>
{};
template <>
struct densify_ring<true, false>
: densify_range<false>
{};
}} // namespace detail::densify
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template
<
typename Geometry,
typename GeometryOut,
typename Tag1 = typename tag<Geometry>::type,
typename Tag2 = typename tag<GeometryOut>::type
>
struct densify
: not_implemented<Tag1, Tag2>
{};
template <typename Geometry, typename GeometryOut>
struct densify<Geometry, GeometryOut, linestring_tag, linestring_tag>
: geometry::detail::densify::densify_range<>
{};
template <typename Geometry, typename GeometryOut>
struct densify<Geometry, GeometryOut, multi_linestring_tag, multi_linestring_tag>
{
template <typename T, typename Strategy>
static void apply(Geometry const& mls, GeometryOut & mls_out,
T const& len, Strategy const& strategy)
{
std::size_t count = boost::size(mls);
range::resize(mls_out, count);
for (std::size_t i = 0 ; i < count ; ++i)
{
geometry::detail::densify::densify_range<>
::apply(range::at(mls, i), range::at(mls_out, i),
len, strategy);
}
}
};
template <typename Geometry, typename GeometryOut>
struct densify<Geometry, GeometryOut, ring_tag, ring_tag>
: geometry::detail::densify::densify_ring
<
geometry::closure<Geometry>::value != geometry::open,
geometry::closure<GeometryOut>::value != geometry::open
>
{};
template <typename Geometry, typename GeometryOut>
struct densify<Geometry, GeometryOut, polygon_tag, polygon_tag>
{
template <typename T, typename Strategy>
static void apply(Geometry const& poly, GeometryOut & poly_out,
T const& len, Strategy const& strategy)
{
apply_ring(exterior_ring(poly), exterior_ring(poly_out),
len, strategy);
std::size_t count = boost::size(interior_rings(poly));
range::resize(interior_rings(poly_out), count);
for (std::size_t i = 0 ; i < count ; ++i)
{
apply_ring(range::at(interior_rings(poly), i),
range::at(interior_rings(poly_out), i),
len, strategy);
}
}
template <typename Ring, typename RingOut, typename T, typename Strategy>
static void apply_ring(Ring const& ring, RingOut & ring_out,
T const& len, Strategy const& strategy)
{
densify<Ring, RingOut, ring_tag, ring_tag>
::apply(ring, ring_out, len, strategy);
}
};
template <typename Geometry, typename GeometryOut>
struct densify<Geometry, GeometryOut, multi_polygon_tag, multi_polygon_tag>
{
template <typename T, typename Strategy>
static void apply(Geometry const& mpoly, GeometryOut & mpoly_out,
T const& len, Strategy const& strategy)
{
std::size_t count = boost::size(mpoly);
range::resize(mpoly_out, count);
for (std::size_t i = 0 ; i < count ; ++i)
{
apply_poly(range::at(mpoly, i),
range::at(mpoly_out, i),
len, strategy);
}
}
template <typename Poly, typename PolyOut, typename T, typename Strategy>
static void apply_poly(Poly const& poly, PolyOut & poly_out,
T const& len, Strategy const& strategy)
{
densify<Poly, PolyOut, polygon_tag, polygon_tag>::
apply(poly, poly_out, len, strategy);
}
};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
namespace resolve_strategy
{
struct densify
{
template <typename Geometry, typename Distance, typename Strategy>
static inline void apply(Geometry const& geometry,
Geometry& out,
Distance const& max_distance,
Strategy const& strategy)
{
dispatch::densify<Geometry, Geometry>
::apply(geometry, out, max_distance, strategy);
}
template <typename Geometry, typename Distance>
static inline void apply(Geometry const& geometry,
Geometry& out,
Distance const& max_distance,
default_strategy)
{
typedef typename strategy::densify::services::default_strategy
<
typename cs_tag<Geometry>::type
>::type strategy_type;
/*BOOST_CONCEPT_ASSERT(
(concepts::DensifyStrategy<strategy_type>)
);*/
apply(geometry, out, max_distance, strategy_type());
}
};
} // namespace resolve_strategy
namespace resolve_variant {
template <typename Geometry>
struct densify
{
template <typename Distance, typename Strategy>
static inline void apply(Geometry const& geometry,
Geometry& out,
Distance const& max_distance,
Strategy const& strategy)
{
resolve_strategy::densify::apply(geometry, out, max_distance, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct densify<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
template <typename Distance, typename Strategy>
struct visitor: boost::static_visitor<void>
{
Distance const& m_max_distance;
Strategy const& m_strategy;
visitor(Distance const& max_distance, Strategy const& strategy)
: m_max_distance(max_distance)
, m_strategy(strategy)
{}
template <typename Geometry>
void operator()(Geometry const& geometry, Geometry& out) const
{
densify<Geometry>::apply(geometry, out, m_max_distance, m_strategy);
}
};
template <typename Distance, typename Strategy>
static inline void
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& out,
Distance const& max_distance,
Strategy const& strategy)
{
boost::apply_visitor(
visitor<Distance, Strategy>(max_distance, strategy),
geometry,
out
);
}
};
} // namespace resolve_variant
/*!
\brief Densify a geometry using a specified strategy
\ingroup densify
\tparam Geometry \tparam_geometry
\tparam Distance A numerical distance measure
\tparam Strategy A type fulfilling a DensifyStrategy concept
\param geometry Input geometry, to be densified
\param out Output geometry, densified version of the input geometry
\param max_distance Distance threshold (in units depending on strategy)
\param strategy Densify strategy to be used for densification
\qbk{distinguish,with strategy}
\qbk{[include reference/algorithms/densify.qbk]}
\qbk{
[heading Available Strategies]
\* [link geometry.reference.strategies.strategy_densify_cartesian Cartesian]
\* [link geometry.reference.strategies.strategy_densify_spherical Spherical]
\* [link geometry.reference.strategies.strategy_densify_geographic Geographic]
[heading Example]
[densify_strategy]
[densify_strategy_output]
}
*/
template <typename Geometry, typename Distance, typename Strategy>
inline void densify(Geometry const& geometry,
Geometry& out,
Distance const& max_distance,
Strategy const& strategy)
{
concepts::check<Geometry>();
if (max_distance <= Distance(0))
{
BOOST_THROW_EXCEPTION(geometry::invalid_input_exception());
}
geometry::clear(out);
resolve_variant::densify
<
Geometry
>::apply(geometry, out, max_distance, strategy);
}
/*!
\brief Densify a geometry
\ingroup densify
\tparam Geometry \tparam_geometry
\tparam Distance A numerical distance measure
\param geometry Input geometry, to be densified
\param out Output geometry, densified version of the input geometry
\param max_distance Distance threshold (in units depending on coordinate system)
\qbk{[include reference/algorithms/densify.qbk]}
\qbk{
[heading Example]
[densify]
[densify_output]
}
*/
template <typename Geometry, typename Distance>
inline void densify(Geometry const& geometry,
Geometry& out,
Distance const& max_distance)
{
densify(geometry, out, max_distance, default_strategy());
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DENSIFY_HPP

View File

@ -4,8 +4,8 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. // Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014, 2015, 2016. // This file was modified by Oracle on 2014-2018.
// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates. // Modifications copyright (c) 2014-2018 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@ -61,6 +61,7 @@
#include <boost/geometry/algorithms/correct.hpp> #include <boost/geometry/algorithms/correct.hpp>
#include <boost/geometry/algorithms/covered_by.hpp> #include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/algorithms/crosses.hpp> #include <boost/geometry/algorithms/crosses.hpp>
#include <boost/geometry/algorithms/densify.hpp>
#include <boost/geometry/algorithms/difference.hpp> #include <boost/geometry/algorithms/difference.hpp>
#include <boost/geometry/algorithms/disjoint.hpp> #include <boost/geometry/algorithms/disjoint.hpp>
#include <boost/geometry/algorithms/distance.hpp> #include <boost/geometry/algorithms/distance.hpp>

View File

@ -0,0 +1,133 @@
// Boost.Geometry
// Copyright (c) 2017-2018, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DENSIFY_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DENSIFY_HPP
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/algorithms/detail/signed_size_type.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/arithmetic/dot_product.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/strategies/densify.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace densify
{
/*!
\brief Densification of cartesian segment.
\ingroup strategies
\tparam CalculationType \tparam_calculation
\qbk{
[heading See also]
[link geometry.reference.algorithms.densify.densify_4_with_strategy densify (with strategy)]
}
*/
template
<
typename CalculationType = void
>
class cartesian
{
public:
template <typename Point, typename AssignPolicy, typename T>
static inline void apply(Point const& p0, Point const& p1, AssignPolicy & policy, T const& length_threshold)
{
typedef typename AssignPolicy::point_type out_point_t;
typedef typename select_most_precise
<
typename coordinate_type<Point>::type,
typename coordinate_type<out_point_t>::type,
CalculationType
>::type calc_t;
typedef model::point<calc_t, geometry::dimension<Point>::value, cs::cartesian> calc_point_t;
calc_point_t cp0, cp1;
geometry::detail::conversion::convert_point_to_point(p0, cp0);
geometry::detail::conversion::convert_point_to_point(p1, cp1);
// dir01 = xy1 - xy0
calc_point_t dir01 = cp1;
geometry::subtract_point(dir01, cp0);
calc_t const dot01 = geometry::dot_product(dir01, dir01);
calc_t const len = math::sqrt(dot01);
BOOST_GEOMETRY_ASSERT(length_threshold > T(0));
signed_size_type n = signed_size_type(len / length_threshold);
if (n <= 0)
{
return;
}
// NOTE: Normalization will not work for integral coordinates
// normalize
//geometry::divide_value(dir01, len);
calc_t step = len / (n + 1);
calc_t d = step;
for (signed_size_type i = 0 ; i < n ; ++i, d += step)
{
// pd = xy0 + d * dir01
calc_point_t pd = dir01;
// without normalization
geometry::multiply_value(pd, calc_t(i + 1));
geometry::divide_value(pd, calc_t(n + 1));
// with normalization
//geometry::multiply_value(pd, d);
geometry::add_point(pd, cp0);
// NOTE: Only needed if types calc_point_t and out_point_t are different
// otherwise pd could simply be passed into policy
out_point_t p;
assert_dimension_equal<calc_point_t, out_point_t>();
geometry::detail::conversion::convert_point_to_point(pd, p);
policy.apply(p);
}
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <>
struct default_strategy<cartesian_tag>
{
typedef strategy::densify::cartesian<> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::densify
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DENSIFY_HPP

View File

@ -0,0 +1,42 @@
// Boost.Geometry
// Copyright (c) 2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_STRATEGIES_DENSIFY_HPP
#define BOOST_GEOMETRY_STRATEGIES_DENSIFY_HPP
#include <boost/mpl/assert.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace densify
{
namespace services
{
template <typename CSTag>
struct default_strategy
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_IMPLEMENTED_FOR_THIS_CS
, (types<CSTag>)
);
};
} // namespace services
}} // namespace strategy::densify
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_DENSIFY_HPP

View File

@ -0,0 +1,135 @@
// Boost.Geometry
// Copyright (c) 2017-2018, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DENSIFY_HPP
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DENSIFY_HPP
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/algorithms/detail/signed_size_type.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/core/srs.hpp>
#include <boost/geometry/strategies/densify.hpp>
#include <boost/geometry/strategies/geographic/parameters.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace densify
{
/*!
\brief Densification of geographic segment.
\ingroup strategies
\tparam FormulaPolicy The geodesic formulas used internally.
\tparam Spheroid The spheroid model.
\tparam CalculationType \tparam_calculation
\qbk{
[heading See also]
[link geometry.reference.algorithms.densify.densify_4_with_strategy densify (with strategy)]
}
*/
template
<
typename FormulaPolicy = strategy::andoyer,
typename Spheroid = srs::spheroid<double>,
typename CalculationType = void
>
class geographic
{
public:
geographic()
: m_spheroid()
{}
explicit geographic(Spheroid const& spheroid)
: m_spheroid(spheroid)
{}
template <typename Point, typename AssignPolicy, typename T>
inline void apply(Point const& p0, Point const& p1, AssignPolicy & policy, T const& length_threshold) const
{
typedef typename AssignPolicy::point_type out_point_t;
typedef typename select_most_precise
<
typename coordinate_type<Point>::type,
typename coordinate_type<out_point_t>::type,
CalculationType
>::type calc_t;
typedef typename FormulaPolicy::template direct<calc_t, true, false, false, false> direct_t;
typedef typename FormulaPolicy::template inverse<calc_t, true, true, false, false, false> inverse_t;
typename inverse_t::result_type
inv_r = inverse_t::apply(get_as_radian<0>(p0), get_as_radian<1>(p0),
get_as_radian<0>(p1), get_as_radian<1>(p1),
m_spheroid);
BOOST_GEOMETRY_ASSERT(length_threshold > T(0));
signed_size_type n = signed_size_type(inv_r.distance / length_threshold);
if (n <= 0)
return;
calc_t step = inv_r.distance / (n + 1);
calc_t current = step;
for (signed_size_type i = 0 ; i < n ; ++i, current += step)
{
typename direct_t::result_type
dir_r = direct_t::apply(get_as_radian<0>(p0), get_as_radian<1>(p0),
current, inv_r.azimuth,
m_spheroid);
out_point_t p;
set_from_radian<0>(p, dir_r.lon2);
set_from_radian<1>(p, dir_r.lat2);
geometry::detail::conversion::point_to_point
<
Point, out_point_t,
2, dimension<out_point_t>::value
>::apply(p0, p);
policy.apply(p);
}
}
private:
Spheroid m_spheroid;
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <>
struct default_strategy<geographic_tag>
{
typedef strategy::densify::geographic<> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::densify
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DENSIFY_HPP

View File

@ -0,0 +1,186 @@
// Boost.Geometry
// Copyright (c) 2017-2018, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DENSIFY_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DENSIFY_HPP
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/algorithms/detail/signed_size_type.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/arithmetic/cross_product.hpp>
#include <boost/geometry/arithmetic/dot_product.hpp>
#include <boost/geometry/arithmetic/normalize.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/formulas/spherical.hpp>
#include <boost/geometry/strategies/densify.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace densify
{
/*!
\brief Densification of spherical segment.
\ingroup strategies
\tparam Sphere The sphere model.
\tparam CalculationType \tparam_calculation
\qbk{
[heading See also]
[link geometry.reference.algorithms.densify.densify_4_with_strategy densify (with strategy)]
}
*/
template
<
typename Sphere = srs::sphere<double>,
typename CalculationType = void
>
class spherical
{
public:
// For consistency with area strategy the radius is set to 1
spherical()
: m_radius(1.0)
{}
explicit spherical(Sphere const& sphere)
: m_radius(geometry::get_radius<0>(sphere))
{}
// TODO: use enable_if/disable_if to distinguish between Sphere and Radius?
template <typename OtherSphere>
explicit spherical(OtherSphere const& sphere)
: m_radius(geometry::get_radius<0>(sphere))
{}
template <typename Point, typename AssignPolicy, typename T>
inline void apply(Point const& p0, Point const& p1, AssignPolicy & policy, T const& length_threshold) const
{
typedef typename AssignPolicy::point_type out_point_t;
typedef typename select_most_precise
<
typename coordinate_type<Point>::type,
typename coordinate_type<out_point_t>::type,
CalculationType
>::type calc_t;
calc_t const c0 = 0;
calc_t const c1 = 1;
calc_t const pi = math::pi<calc_t>();
typedef model::point<calc_t, 3, cs::cartesian> point3d_t;
point3d_t const xyz0 = formula::sph_to_cart3d<point3d_t>(p0);
point3d_t const xyz1 = formula::sph_to_cart3d<point3d_t>(p1);
calc_t const dot01 = geometry::dot_product(xyz0, xyz1);
calc_t const angle01 = acos(dot01);
BOOST_GEOMETRY_ASSERT(length_threshold > T(0));
signed_size_type n = signed_size_type(angle01 * m_radius / length_threshold);
if (n <= 0)
return;
point3d_t axis;
if (! math::equals(angle01, pi))
{
axis = geometry::cross_product(xyz0, xyz1);
geometry::detail::vec_normalize(axis);
}
else // antipodal
{
calc_t const half_pi = math::half_pi<calc_t>();
calc_t const lat = geometry::get_as_radian<1>(p0);
if (math::equals(lat, half_pi))
{
// pointing east, segment lies on prime meridian, going south
axis = point3d_t(c0, c1, c0);
}
else if (math::equals(lat, -half_pi))
{
// pointing west, segment lies on prime meridian, going north
axis = point3d_t(c0, -c1, c0);
}
else
{
// lon rotated west by pi/2 at equator
calc_t const lon = geometry::get_as_radian<0>(p0);
axis = point3d_t(sin(lon), -cos(lon), c0);
}
}
calc_t step = angle01 / (n + 1);
calc_t a = step;
for (signed_size_type i = 0 ; i < n ; ++i, a += step)
{
// Axis-Angle rotation
// see: https://en.wikipedia.org/wiki/Axis-angle_representation
calc_t const cos_a = cos(a);
calc_t const sin_a = sin(a);
// cos_a * v
point3d_t s1 = xyz0;
geometry::multiply_value(s1, cos_a);
// sin_a * (n x v)
point3d_t s2 = geometry::cross_product(axis, xyz0);
geometry::multiply_value(s2, sin_a);
// (1 - cos_a)(n.v) * n
point3d_t s3 = axis;
geometry::multiply_value(s3, (c1 - cos_a) * geometry::dot_product(axis, xyz0));
// v_rot = cos_a * v + sin_a * (n x v) + (1 - cos_a)(n.v) * e
point3d_t v_rot = s1;
geometry::add_point(v_rot, s2);
geometry::add_point(v_rot, s3);
out_point_t p = formula::cart3d_to_sph<out_point_t>(v_rot);
geometry::detail::conversion::point_to_point
<
Point, out_point_t,
2, dimension<out_point_t>::value
>::apply(p0, p);
policy.apply(p);
}
}
private:
typename geometry::radius_type<Sphere>::type m_radius;
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <>
struct default_strategy<spherical_equatorial_tag>
{
typedef strategy::densify::spherical<> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::densify
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DENSIFY_HPP

View File

@ -4,8 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014-2017. // This file was modified by Oracle on 2014-2018.
// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates. // Modifications copyright (c) 2014-2018 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@ -30,6 +30,7 @@
#include <boost/geometry/strategies/compare.hpp> #include <boost/geometry/strategies/compare.hpp>
#include <boost/geometry/strategies/convex_hull.hpp> #include <boost/geometry/strategies/convex_hull.hpp>
#include <boost/geometry/strategies/covered_by.hpp> #include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/densify.hpp>
#include <boost/geometry/strategies/disjoint.hpp> #include <boost/geometry/strategies/disjoint.hpp>
#include <boost/geometry/strategies/distance.hpp> #include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/envelope.hpp> #include <boost/geometry/strategies/envelope.hpp>
@ -54,6 +55,7 @@
#include <boost/geometry/strategies/cartesian/centroid_average.hpp> #include <boost/geometry/strategies/cartesian/centroid_average.hpp>
#include <boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp> #include <boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp>
#include <boost/geometry/strategies/cartesian/centroid_weighted_length.hpp> #include <boost/geometry/strategies/cartesian/centroid_weighted_length.hpp>
#include <boost/geometry/strategies/cartesian/densify.hpp>
#include <boost/geometry/strategies/cartesian/disjoint_segment_box.hpp> #include <boost/geometry/strategies/cartesian/disjoint_segment_box.hpp>
#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp> #include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
#include <boost/geometry/strategies/cartesian/distance_pythagoras_point_box.hpp> #include <boost/geometry/strategies/cartesian/distance_pythagoras_point_box.hpp>
@ -70,6 +72,7 @@
#include <boost/geometry/strategies/spherical/area.hpp> #include <boost/geometry/strategies/spherical/area.hpp>
#include <boost/geometry/strategies/spherical/azimuth.hpp> #include <boost/geometry/strategies/spherical/azimuth.hpp>
#include <boost/geometry/strategies/spherical/densify.hpp>
#include <boost/geometry/strategies/spherical/disjoint_segment_box.hpp> #include <boost/geometry/strategies/spherical/disjoint_segment_box.hpp>
#include <boost/geometry/strategies/spherical/distance_haversine.hpp> #include <boost/geometry/strategies/spherical/distance_haversine.hpp>
#include <boost/geometry/strategies/spherical/distance_cross_track.hpp> #include <boost/geometry/strategies/spherical/distance_cross_track.hpp>
@ -82,6 +85,7 @@
#include <boost/geometry/strategies/geographic/area.hpp> #include <boost/geometry/strategies/geographic/area.hpp>
#include <boost/geometry/strategies/geographic/azimuth.hpp> #include <boost/geometry/strategies/geographic/azimuth.hpp>
#include <boost/geometry/strategies/geographic/densify.hpp>
#include <boost/geometry/strategies/geographic/disjoint_segment_box.hpp> #include <boost/geometry/strategies/geographic/disjoint_segment_box.hpp>
#include <boost/geometry/strategies/geographic/distance.hpp> #include <boost/geometry/strategies/geographic/distance.hpp>
#include <boost/geometry/strategies/geographic/distance_andoyer.hpp> #include <boost/geometry/strategies/geographic/distance_andoyer.hpp>

View File

@ -29,6 +29,7 @@ test-suite boost-geometry-algorithms
[ run correct.cpp : : : : algorithms_correct ] [ run correct.cpp : : : : algorithms_correct ]
[ run correct_multi.cpp : : : : algorithms_correct_multi ] [ run correct_multi.cpp : : : : algorithms_correct_multi ]
[ run correct_closure.cpp : : : : algorithms_correct_closure ] [ run correct_closure.cpp : : : : algorithms_correct_closure ]
[ run densify.cpp : : : : algorithms_densify ]
[ run for_each.cpp : : : : algorithms_for_each ] [ run for_each.cpp : : : : algorithms_for_each ]
[ run for_each_multi.cpp : : : : algorithms_for_each_multi ] [ run for_each_multi.cpp : : : : algorithms_for_each_multi ]
[ run is_convex.cpp : : : : algorithms_is_convex ] [ run is_convex.cpp : : : : algorithms_is_convex ]

227
test/algorithms/densify.cpp Normal file
View File

@ -0,0 +1,227 @@
// Boost.Geometry
// Unit Test
// Copyright (c) 2017-2018, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#include <geometry_test_common.hpp>
#include <boost/geometry/geometries/geometries.hpp>
#include <boost/geometry/algorithms/densify.hpp>
#include <boost/geometry/algorithms/length.hpp>
#include <boost/geometry/algorithms/num_points.hpp>
#include <boost/geometry/algorithms/perimeter.hpp>
#include <boost/geometry/iterators/segment_iterator.hpp>
#include <boost/geometry/strategies/cartesian/densify.hpp>
#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
#include <boost/geometry/strategies/geographic/densify.hpp>
#include <boost/geometry/strategies/geographic/distance.hpp>
#include <boost/geometry/strategies/spherical/densify.hpp>
#include <boost/geometry/strategies/spherical/distance_haversine.hpp>
#include <boost/geometry/io/wkt/wkt.hpp>
struct check_lengths
{
template <typename G, typename S>
void operator()(G const& g, G const& o, S const& s) const
{
double d1 = bg::length(g, s);
double d2 = bg::length(o, s);
BOOST_CHECK_CLOSE(d1, d2, 0.0001);
}
};
struct check_perimeters
{
template <typename G, typename S>
void operator()(G const& g, G const& o, S const& s) const
{
double d1 = bg::perimeter(g, s);
double d2 = bg::perimeter(o, s);
BOOST_CHECK_CLOSE(d1, d2, 0.0001);
}
};
template <typename G, typename DistS>
double inline shortest_length(G const& g, DistS const& dist_s)
{
double min_len = (std::numeric_limits<double>::max)();
for (bg::segment_iterator<G const> it = bg::segments_begin(g);
it != bg::segments_end(g); ++it)
{
double len = bg::length(*it, dist_s);
min_len = (std::min)(min_len, len);
}
return min_len;
}
template <typename G, typename DistS>
double inline greatest_length(G const& o, DistS const& dist_s)
{
double max_len = 0.0;
for (bg::segment_iterator<G const> it = bg::segments_begin(o);
it != bg::segments_end(o); ++it)
{
double len = bg::length(*it, dist_s);
max_len = (std::max)(max_len, len);
}
return max_len;
}
template <typename G, typename CSTag = typename bg::cs_tag<G>::type>
struct cs_data
{};
template <typename G>
struct cs_data<G, bg::cartesian_tag>
{
bg::strategy::densify::cartesian<> compl_s;
bg::strategy::distance::pythagoras<> dist_s;
};
template <typename G>
struct cs_data<G, bg::spherical_equatorial_tag>
{
cs_data()
: model(6378137.0)
, compl_s(model)
, dist_s(6378137.0)
{}
bg::srs::sphere<double> model;
bg::strategy::densify::spherical<> compl_s;
bg::strategy::distance::haversine<double> dist_s;
};
template <typename G>
struct cs_data<G, bg::geographic_tag>
{
cs_data()
: model(6378137.0, 6356752.3142451793)
, compl_s(model)
, dist_s(model)
{}
bg::srs::spheroid<double> model;
bg::strategy::densify::geographic<> compl_s;
bg::strategy::distance::geographic<> dist_s;
};
template <typename G, typename DistS, typename Check>
inline void check_result(G const& g, G const& o, double max_distance,
DistS const& dist_s, Check const& check)
{
// geometry was indeed densified
std::size_t g_count = bg::num_points(g);
std::size_t o_count = bg::num_points(o);
BOOST_CHECK(g_count < o_count);
// all segments have lengths smaller or equal to max_distance
double gr_len = greatest_length(o, dist_s);
// NOTE: Currently geographic strategies can generate segments that have
// lengths slightly greater than max_distance. In order to change
// this the generation of new points should e.g. be recursive with
// stop condition comparing the current distance calculated by
// inverse strategy.
// NOTE: Closeness value tweaked for Andoyer
bool is_close = (gr_len - max_distance) / (std::max)(gr_len, max_distance) < 0.0001;
BOOST_CHECK(gr_len <= max_distance || is_close);
// the overall length or perimeter didn't change
check(g, o, dist_s);
}
template <typename G, typename Check>
inline void test_geometry(std::string const& wkt, Check const& check)
{
cs_data<G> d;
G g;
bg::read_wkt(wkt, g);
{
bg::default_strategy def_s;
double max_distance = shortest_length(g, def_s) / 3.0;
G o;
bg::densify(g, o, max_distance);
check_result(g, o, max_distance, def_s, check);
}
{
double max_distance = shortest_length(g, d.dist_s) / 3.0;
G o;
bg::densify(g, o, max_distance, d.compl_s);
check_result(g, o, max_distance, d.dist_s, check);
}
}
template <typename G>
inline void test_linear(std::string const& wkt)
{
test_geometry<G>(wkt, check_lengths());
}
template <typename G>
inline void test_areal(std::string const& wkt)
{
test_geometry<G>(wkt, check_perimeters());
}
template <typename P>
void test_all()
{
typedef bg::model::linestring<P> ls_t;
typedef bg::model::multi_linestring<ls_t> mls_t;
typedef bg::model::ring<P> ring_t;
typedef bg::model::polygon<P> poly_t;
typedef bg::model::multi_polygon<poly_t> mpoly_t;
typedef bg::model::ring<P, true, false> oring_t;
typedef bg::model::polygon<P, true, false> opoly_t;
typedef bg::model::multi_polygon<opoly_t> ompoly_t;
test_linear<ls_t>("LINESTRING(4 -4, 4 -1)");
test_linear<ls_t>("LINESTRING(4 4, 4 1)");
test_linear<ls_t>("LINESTRING(0 0, 180 0)");
test_linear<ls_t>("LINESTRING(1 1, -179 -1)");
test_linear<ls_t>("LINESTRING(1 1, 2 2, 4 2)");
test_linear<mls_t>("MULTILINESTRING((1 1, 2 2),(2 2, 4 2))");
test_areal<ring_t>("POLYGON((1 1, 1 2, 2 2, 1 1))");
test_areal<poly_t>("POLYGON((1 1, 1 4, 4 4, 4 1, 1 1),(1 1, 2 2, 2 3, 1 1))");
test_areal<mpoly_t>("MULTIPOLYGON(((1 1, 1 4, 4 4, 4 1, 1 1),(1 1, 2 2, 2 3, 1 1)),((4 4, 5 5, 5 4, 4 4)))");
test_areal<oring_t>("POLYGON((1 1, 1 2, 2 2))");
test_areal<opoly_t>("POLYGON((1 1, 1 4, 4 4, 4 1),(1 1, 2 2, 2 3))");
test_areal<ompoly_t>("MULTIPOLYGON(((1 1, 1 4, 4 4, 4 1),(1 1, 2 2, 2 3)),((4 4, 5 5, 5 4)))");
test_areal<ring_t>("POLYGON((0 0,0 40,40 40,40 0,0 0))");
test_areal<oring_t>("POLYGON((0 0,0 40,40 40,40 0))");
}
int test_main(int, char* [])
{
test_all< bg::model::point<double, 2, bg::cs::cartesian> >();
test_all< bg::model::point<double, 2, bg::cs::spherical_equatorial<bg::degree> > >();
test_all< bg::model::point<double, 2, bg::cs::geographic<bg::degree> > >();
return 0;
}