mirror of
https://github.com/boostorg/geometry.git
synced 2025-05-11 05:24:02 +00:00
Merge pull request #437 from awulkiew/feature/complexify
Add new algorithm - densify()
This commit is contained in:
commit
dbf56a8210
@ -2,6 +2,10 @@
|
||||
//
|
||||
// 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,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// 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 crosses crosses: detect if two geometries crosses each other
|
||||
\defgroup cs coordinate systems
|
||||
\defgroup densify densify: add points to geometry, keeping shape
|
||||
\defgroup difference difference: difference of two geometries
|
||||
\defgroup disjoint disjoint: detect if geometries are not spatially related
|
||||
\defgroup distance distance: calculate distance between two geometries
|
||||
|
@ -5,6 +5,9 @@
|
||||
Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
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,
|
||||
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
@ -27,6 +30,8 @@
|
||||
[import src/examples/algorithms/convert.cpp]
|
||||
[import src/examples/algorithms/convex_hull.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/difference.cpp]
|
||||
[import src/examples/algorithms/envelope.cpp]
|
||||
|
@ -5,6 +5,9 @@
|
||||
# Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
# Copyright (c) 2009-2012 Mateusz Loskot (mateusz@loskot.net), London, UK
|
||||
# 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,
|
||||
# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -91,7 +94,7 @@ call_doxygen()
|
||||
|
||||
algorithms = ["append", "assign", "make", "clear"
|
||||
, "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"
|
||||
, "is_simple", "is_valid", "intersection", "intersects", "length"
|
||||
, "num_geometries", "num_interior_rings", "num_points"
|
||||
@ -120,7 +123,8 @@ models = ["point", "linestring", "box"
|
||||
, "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::cross_track", "distance::cross_track_point_box"
|
||||
, "distance::projected_point"
|
||||
|
@ -10,8 +10,8 @@
|
||||
Copyright (c) 2009-2015 Bruno Lalande, Paris, France.
|
||||
Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
This file was modified by Oracle on 2014, 2015, 2017.
|
||||
Modifications copyright (c) 2014-2017, Oracle and/or its affiliates.
|
||||
This file was modified by Oracle on 2014, 2015, 2017, 2018.
|
||||
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 Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@ -389,6 +389,10 @@
|
||||
</row>
|
||||
<row>
|
||||
<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>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member><link linkend="geometry.reference.algorithms.distance">distance</link></member>
|
||||
@ -410,17 +414,16 @@
|
||||
<simplelist type="vert" columns="1">
|
||||
<member><link linkend="geometry.reference.algorithms.for_each">for each (point, segment)</link></member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Intersection</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member><link linkend="geometry.reference.algorithms.intersection">intersection</link></member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Length</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member><link linkend="geometry.reference.algorithms.length">length</link></member>
|
||||
</simplelist>
|
||||
|
||||
</simplelist>
|
||||
<bridgehead renderas="sect3">Num_ (counting)</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<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_segments">num_segments</link></member>
|
||||
</simplelist>
|
||||
|
||||
|
||||
<bridgehead renderas="sect3">Perimeter</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<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.relation">relation</link></member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Reverse</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member><link linkend="geometry.reference.algorithms.reverse">reverse</link></member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Simplify</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<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>
|
||||
</simplelist>
|
||||
</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">
|
||||
<bridgehead renderas="sect3">Distance</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
@ -566,6 +575,8 @@
|
||||
<member><link linkend="geometry.reference.strategies.strategy_distance_haversine">strategy::distance::haversine</link></member>
|
||||
</simplelist>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Side</bridgehead>
|
||||
<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>
|
||||
</simplelist>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry valign="top">
|
||||
<bridgehead renderas="sect3">Simplify</bridgehead>
|
||||
<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>
|
||||
</simplelist>
|
||||
</entry>
|
||||
<entry valign="top">
|
||||
</row>
|
||||
<row>
|
||||
<entry valign="top" namest="a" nameend="c">
|
||||
<bridgehead renderas="sect3">Within</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member><link linkend="geometry.reference.strategies.strategy_within_winding">strategy::winding</link></member>
|
||||
|
@ -6,8 +6,8 @@
|
||||
Copyright (c) 2009-2017 Bruno Lalande, Paris, France.
|
||||
Copyright (c) 2013-2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
This file was modified by Oracle on 2014, 2017.
|
||||
Modifications copyright (c) 2014-2017, Oracle and/or its affiliates.
|
||||
This file was modified by Oracle on 2014, 2017, 2018.
|
||||
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 Adam Wulkiewicz, on behalf of Oracle
|
||||
@ -102,6 +102,10 @@
|
||||
[include generated/crosses.qbk]
|
||||
[endsect]
|
||||
|
||||
[section:densify densify]
|
||||
[include generated/densify.qbk]
|
||||
[endsect]
|
||||
|
||||
[section:difference difference]
|
||||
[include generated/difference.qbk]
|
||||
[endsect]
|
||||
@ -332,6 +336,9 @@
|
||||
|
||||
|
||||
[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_box_box.qbk]
|
||||
[include generated/distance_pythagoras_point_box.qbk]
|
||||
|
25
doc/reference/algorithms/densify.qbk
Normal file
25
doc/reference/algorithms/densify.qbk
Normal 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.]
|
@ -4,10 +4,11 @@
|
||||
# Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
# Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
|
||||
# This file was modified by Oracle on 2014, 2015.
|
||||
# Modifications copyright (c) 2014-2015, Oracle and/or its affiliates.
|
||||
# This file was modified by Oracle on 2014, 2015, 2018.
|
||||
# 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 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
|
||||
@ -40,6 +41,8 @@ exe convert : convert.cpp ;
|
||||
exe convex_hull : convex_hull.cpp ;
|
||||
exe correct : correct.cpp ;
|
||||
|
||||
exe densify : densify.cpp ;
|
||||
exe densify_strategy : densify_strategy.cpp ;
|
||||
exe difference : difference.cpp ;
|
||||
exe distance : distance.cpp ;
|
||||
|
||||
|
47
doc/src/examples/algorithms/densify.cpp
Normal file
47
doc/src/examples/algorithms/densify.cpp
Normal 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))
|
||||
]
|
||||
*/
|
||||
//]
|
50
doc/src/examples/algorithms/densify_strategy.cpp
Normal file
50
doc/src/examples/algorithms/densify_strategy.cpp
Normal 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)
|
||||
]
|
||||
*/
|
||||
//]
|
425
include/boost/geometry/algorithms/densify.hpp
Normal file
425
include/boost/geometry/algorithms/densify.hpp
Normal 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
|
@ -4,8 +4,8 @@
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2014, 2015, 2016.
|
||||
// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2014-2018.
|
||||
// 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 Menelaos Karavelas, on behalf of Oracle
|
||||
@ -61,6 +61,7 @@
|
||||
#include <boost/geometry/algorithms/correct.hpp>
|
||||
#include <boost/geometry/algorithms/covered_by.hpp>
|
||||
#include <boost/geometry/algorithms/crosses.hpp>
|
||||
#include <boost/geometry/algorithms/densify.hpp>
|
||||
#include <boost/geometry/algorithms/difference.hpp>
|
||||
#include <boost/geometry/algorithms/disjoint.hpp>
|
||||
#include <boost/geometry/algorithms/distance.hpp>
|
||||
|
133
include/boost/geometry/strategies/cartesian/densify.hpp
Normal file
133
include/boost/geometry/strategies/cartesian/densify.hpp
Normal 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
|
42
include/boost/geometry/strategies/densify.hpp
Normal file
42
include/boost/geometry/strategies/densify.hpp
Normal 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
|
135
include/boost/geometry/strategies/geographic/densify.hpp
Normal file
135
include/boost/geometry/strategies/geographic/densify.hpp
Normal 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
|
186
include/boost/geometry/strategies/spherical/densify.hpp
Normal file
186
include/boost/geometry/strategies/spherical/densify.hpp
Normal 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
|
@ -4,8 +4,8 @@
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2014-2017.
|
||||
// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2014-2018.
|
||||
// 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 Adam Wulkiewicz, on behalf of Oracle
|
||||
@ -30,6 +30,7 @@
|
||||
#include <boost/geometry/strategies/compare.hpp>
|
||||
#include <boost/geometry/strategies/convex_hull.hpp>
|
||||
#include <boost/geometry/strategies/covered_by.hpp>
|
||||
#include <boost/geometry/strategies/densify.hpp>
|
||||
#include <boost/geometry/strategies/disjoint.hpp>
|
||||
#include <boost/geometry/strategies/distance.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_bashein_detmer.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/distance_pythagoras.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/azimuth.hpp>
|
||||
#include <boost/geometry/strategies/spherical/densify.hpp>
|
||||
#include <boost/geometry/strategies/spherical/disjoint_segment_box.hpp>
|
||||
#include <boost/geometry/strategies/spherical/distance_haversine.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/azimuth.hpp>
|
||||
#include <boost/geometry/strategies/geographic/densify.hpp>
|
||||
#include <boost/geometry/strategies/geographic/disjoint_segment_box.hpp>
|
||||
#include <boost/geometry/strategies/geographic/distance.hpp>
|
||||
#include <boost/geometry/strategies/geographic/distance_andoyer.hpp>
|
||||
|
@ -29,6 +29,7 @@ test-suite boost-geometry-algorithms
|
||||
[ run correct.cpp : : : : algorithms_correct ]
|
||||
[ run correct_multi.cpp : : : : algorithms_correct_multi ]
|
||||
[ run correct_closure.cpp : : : : algorithms_correct_closure ]
|
||||
[ run densify.cpp : : : : algorithms_densify ]
|
||||
[ run for_each.cpp : : : : algorithms_for_each ]
|
||||
[ run for_each_multi.cpp : : : : algorithms_for_each_multi ]
|
||||
[ run is_convex.cpp : : : : algorithms_is_convex ]
|
||||
|
227
test/algorithms/densify.cpp
Normal file
227
test/algorithms/densify.cpp
Normal 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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user