mirror of
https://github.com/boostorg/geometry.git
synced 2026-01-31 20:22:09 +00:00
Merge branch 'develop' into feature/disjoint_geo_new
This commit is contained in:
@@ -211,6 +211,7 @@ INPUT = . .. ../../../../boost/geometry/core \
|
||||
../../../../boost/geometry/strategies/agnostic \
|
||||
../../../../boost/geometry/strategies/cartesian \
|
||||
../../../../boost/geometry/strategies/spherical \
|
||||
../../../../boost/geometry/strategies/geographic \
|
||||
../../../../boost/geometry/strategies/transform \
|
||||
../../../../boost/geometry/util \
|
||||
../../../../boost/geometry/views \
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
[/============================================================================
|
||||
Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
Copyright (c) 2009-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
Copyright (c) 2009-2015 Bruno Lalande, Paris, France.
|
||||
Copyright (c) 2009-2017 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
Copyright (c) 2009-2017 Mateusz Loskot, London, UK.
|
||||
Copyright (c) 2009-2017 Bruno Lalande, Paris, France.
|
||||
Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
Use, modification and distribution is subject to the Boost Software License,
|
||||
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -12,8 +13,8 @@
|
||||
|
||||
[library Geometry
|
||||
[quickbook 1.5]
|
||||
[authors [Gehrels, Barend], [Lalande, Bruno], [Loskot, Mateusz], [Wulkiewicz, Adam], [Karavelas, Menelaos]]
|
||||
[copyright 2009-2015 Barend Gehrels, Bruno Lalande, Mateusz Loskot, Adam Wulkiewicz, Oracle and/or its affiliates]
|
||||
[authors [Gehrels, Barend], [Lalande, Bruno], [Loskot, Mateusz], [Wulkiewicz, Adam], [Karavelas, Menelaos], [Fisikopoulos, Vissarion]]
|
||||
[copyright 2009-2017 Barend Gehrels, Bruno Lalande, Mateusz Loskot, Adam Wulkiewicz, Oracle and/or its affiliates]
|
||||
[purpose Documentation of Boost.Geometry library]
|
||||
[license
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
|
||||
@@ -37,8 +37,12 @@
|
||||
<div><div class="author"><h3 class="author">
|
||||
<span class="firstname">Menelaos</span> <span class="surname">Karavelas</span>
|
||||
</h3></div></div>
|
||||
<div><p class="copyright">Copyright © 2009-2014 Barend Gehrels, Bruno Lalande, Mateusz Loskot, Adam
|
||||
Wulkiewicz, Oracle and/or its affiliates</p></div>
|
||||
<div><div class="author"><h3 class="author">
|
||||
<span class="firstname">Vissarion</span> <span class="surname">Fisikopoulos</span>
|
||||
</h3></div></div>
|
||||
<div><p class="copyright">Copyright © 2009-2017 Barend
|
||||
Gehrels, Bruno Lalande, Mateusz Loskot, Adam Wulkiewicz, Oracle and/or its
|
||||
affiliates</p></div>
|
||||
<div><div class="legalnotice">
|
||||
<a name="geometry.legal"></a><p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
@@ -72,6 +76,7 @@
|
||||
<dt><span class="section"><a href="geometry/reference/constants.html">Constants</a></span></dt>
|
||||
<dt><span class="section"><a href="geometry/reference/cs.html">Coordinate Systems</a></span></dt>
|
||||
<dt><span class="section"><a href="geometry/reference/core.html">Core Metafunctions</a></span></dt>
|
||||
<dt><span class="section"><a href="geometry/reference/de9im.html">DE-9IM</a></span></dt>
|
||||
<dt><span class="section"><a href="geometry/reference/enumerations.html">Enumerations</a></span></dt>
|
||||
<dt><span class="section"><a href="geometry/reference/exceptions.html">Exceptions</a></span></dt>
|
||||
<dt><span class="section"><a href="geometry/reference/io.html">IO (input/output)</a></span></dt>
|
||||
@@ -81,11 +86,9 @@
|
||||
<dt><span class="section"><a href="geometry/reference/strategies.html">Strategies</a></span></dt>
|
||||
<dt><span class="section"><a href="geometry/reference/views.html">Views</a></span></dt>
|
||||
</dl></dd>
|
||||
<dt><span class="section"><a href="geometry/indexes.html">Indexes</a></span></dt>
|
||||
<dd><dl>
|
||||
<dt><span class="section"><a href="geometry/indexes/matrix.html">Reference Matrix</a></span></dt>
|
||||
<dt><span class="section"><a href="geometry/indexes/alphabetical_index.html">Alphabetical Index</a></span></dt>
|
||||
</dl></dd>
|
||||
<dt><span class="section"><a href="geometry/matrix.html">Reference Matrix</a></span></dt>
|
||||
<dt><span class="section"><a href="geometry/reference_alphabetical_index.html">Reference Alphabetical
|
||||
Index</a></span></dt>
|
||||
<dt><span class="section"><a href="geometry/examples.html">Examples</a></span></dt>
|
||||
<dd><dl>
|
||||
<dt><span class="section"><a href="geometry/examples/example__adapting_a_legacy_geometry_object_model.html">Example:
|
||||
@@ -124,6 +127,9 @@
|
||||
<li class="listitem">
|
||||
Mats Taraldsvik (documentation: adapting a legacy model)
|
||||
</li>
|
||||
<li class="listitem">
|
||||
Matt Amos (fixes for point_on_surface)
|
||||
</li>
|
||||
<li class="listitem">
|
||||
Samuel Debionne (variant support for distance, assign, crosses, intersection,
|
||||
...)
|
||||
@@ -131,7 +137,7 @@
|
||||
</ul></div>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"><p><small>Last revised: July 17, 2014 at 20:45:09 GMT</small></p></td>
|
||||
<td align="left"><p><small>Last revised: February 26, 2017 at 00:30:21 GMT</small></p></td>
|
||||
<td align="right"><div class="copyright-footer"></div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[/============================================================================
|
||||
Boost.Geometry Index
|
||||
|
||||
Copyright (c) 2011-2013 Adam Wulkiewicz.
|
||||
Copyright (c) 2011-2017 Adam Wulkiewicz.
|
||||
|
||||
Use, modification and distribution is subject to the Boost Software License,
|
||||
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -57,7 +57,7 @@ Query iterators returned by free functions
|
||||
__box__ box_region(...);
|
||||
std::copy(bgi::qbegin(rt, bgi::intersects(box_region)), bgi::qend(rt), std::back_inserter(returned_values));
|
||||
|
||||
[h4 Spatial predicates]
|
||||
[h4 Spatial queries]
|
||||
|
||||
Queries using spatial predicates returns `__value__`s which are related somehow to some Geometry - box, polygon, etc.
|
||||
Names of spatial predicates correspond to names of __boost_geometry__ algorithms (boolean operations).
|
||||
@@ -129,6 +129,9 @@ The same way different query Geometries can be used:
|
||||
Segment seg(/*...*/);
|
||||
rt.query(bgi::nearest(seg, k), std::back_inserter(returned_values));
|
||||
|
||||
[note In case of k-NN queries performed with `query()` function it's not guaranteed that the returned values will be sorted according to the distance.
|
||||
It's different in case of k-NN queries performed with query iterator returned by `qbegin()` function which guarantees the iteration over the closest `__value__`s first. ]
|
||||
|
||||
[h4 User-defined unary predicate]
|
||||
|
||||
The user may pass a `UnaryPredicate` - function, function object or lambda expression taking const reference to Value and returning bool.
|
||||
@@ -175,7 +178,7 @@ may use `index::satisfies()` function like on the example below:
|
||||
rt.query(index::intersects(box) && !index::satisfies(is_not_red),
|
||||
std::back_inserter(result));
|
||||
|
||||
[h4 Passing a set of predicates]
|
||||
[h4 Passing set of predicates]
|
||||
|
||||
It's possible to use some number of predicates in one query by connecting them with `operator&&` e.g. `Pred1 && Pred2 && Pred3 && ...`.
|
||||
|
||||
@@ -190,7 +193,7 @@ left-to-right so placing most restrictive predicates first should accelerate the
|
||||
rt.query(index::intersects(box1) && !index::within(box2) && index::overlaps(box3),
|
||||
std::back_inserter(result));
|
||||
|
||||
Of course it's possible to connect different types of predicates together.
|
||||
It's possible to connect different types of predicates together.
|
||||
|
||||
index::query(rt, index::nearest(pt, k) && index::within(b), std::back_inserter(returned_values));
|
||||
|
||||
@@ -211,13 +214,11 @@ or may be stopped at some point, when all interesting values were gathered. The
|
||||
break;
|
||||
}
|
||||
|
||||
[note In the case of iterative k-NN queries it's guaranteed to iterate over the closest `__value__`s first. ]
|
||||
|
||||
[warning The modification of the `rtree`, e.g. insertion or removal of `__value__`s may invalidate the iterators. ]
|
||||
|
||||
[h4 Inserting query results into the other R-tree]
|
||||
[h4 Inserting query results into another R-tree]
|
||||
|
||||
There are several ways of inserting Values returned by a query to the other R-tree container.
|
||||
There are several ways of inserting Values returned by a query into another R-tree container.
|
||||
The most basic way is creating a temporary container for Values and insert them later.
|
||||
|
||||
namespace bgi = boost::geometry::index;
|
||||
@@ -231,14 +232,13 @@ The most basic way is creating a temporary container for Values and insert them
|
||||
rt1.query(bgi::intersects(Box(/*...*/)), std::back_inserter(result));
|
||||
RTree rt2(result.begin(), result.end());
|
||||
|
||||
However there are better ways. One of these methods is mentioned in the "Creation and modification" section.
|
||||
However there are other ways. One of these methods is mentioned in the "Creation and modification" section.
|
||||
The insert iterator may be passed directly into the query.
|
||||
|
||||
RTree rt3;
|
||||
rt1.query(bgi::intersects(Box(/*...*/))), bgi::inserter(rt3));
|
||||
|
||||
If you're a user of Boost.Range you'll appreciate the third option. You may pass the result Range directly into the
|
||||
constructor or `insert()` member function.
|
||||
You may also pass the resulting Range directly into the constructor or `insert()` member function using Boost.Range adaptor syntax.
|
||||
|
||||
RTree rt4(rt1 | bgi::adaptors::queried(bgi::intersects(Box(/*...*/)))));
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
# Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
# 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
|
||||
#
|
||||
# Use, modification and distribution is subject to the Boost Software License,
|
||||
# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -123,7 +124,8 @@ strategies = ["distance::pythagoras", "distance::pythagoras_box_box"
|
||||
, "distance::cross_track", "distance::cross_track_point_box"
|
||||
, "distance::projected_point"
|
||||
, "within::winding", "within::franklin", "within::crossings_multiply"
|
||||
, "area::surveyor", "area::huiller"
|
||||
, "area::surveyor", "area::spherical"
|
||||
#, "area::geographic"
|
||||
, "buffer::point_circle", "buffer::point_square"
|
||||
, "buffer::join_round", "buffer::join_miter"
|
||||
, "buffer::end_round", "buffer::end_flat"
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
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.
|
||||
Modifications copyright (c) 2014-2015, Oracle and/or its affiliates.
|
||||
|
||||
This file was modified by Oracle on 2014, 2015, 2017.
|
||||
Modifications copyright (c) 2014-2017, 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
|
||||
@@ -521,7 +521,8 @@
|
||||
<bridgehead renderas="sect3">Area</bridgehead>
|
||||
<simplelist type="vert" columns="1">
|
||||
<member><link linkend="geometry.reference.strategies.strategy_area_surveyor">strategy::area::surveyor</link></member>
|
||||
<member><link linkend="geometry.reference.strategies.strategy_area_huiller">strategy::area::huiller</link></member>
|
||||
<member><link linkend="geometry.reference.strategies.strategy_area_spherical">strategy::area::spherical</link></member>
|
||||
<!--member><link linkend="geometry.reference.strategies.strategy_area_geographic">strategy::area::geographic</link></member-->
|
||||
</simplelist>
|
||||
</entry>
|
||||
<entry valign="top">
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
[/============================================================================
|
||||
Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
Copyright (c) 2009-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
Copyright (c) 2009-2014 Bruno Lalande, Paris, France.
|
||||
Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
Copyright (c) 2009-2017 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
Copyright (c) 2009-2017 Mateusz Loskot, London, UK.
|
||||
Copyright (c) 2009-2017 Bruno Lalande, Paris, France.
|
||||
Copyright (c) 2013-2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
This file was modified by Oracle on 2014.
|
||||
Modifications copyright (c) 2014, Oracle and/or its affiliates.
|
||||
This file was modified by Oracle on 2014, 2017.
|
||||
Modifications copyright (c) 2014-2017, 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
|
||||
@@ -94,10 +95,17 @@
|
||||
[include generated/covered_by.qbk]
|
||||
[endsect]
|
||||
|
||||
[section:crosses crosses]
|
||||
[include generated/crosses.qbk]
|
||||
[endsect]
|
||||
|
||||
[section:difference difference]
|
||||
[include generated/difference.qbk]
|
||||
[endsect]
|
||||
|
||||
[section:disjoint disjoint]
|
||||
[include generated/disjoint.qbk]
|
||||
[endsect]
|
||||
|
||||
[section:distance distance]
|
||||
[include generated/distance.qbk]
|
||||
@@ -107,16 +115,21 @@
|
||||
[include generated/envelope.qbk]
|
||||
[endsect]
|
||||
|
||||
[section:equals equals]
|
||||
[include generated/equals.qbk]
|
||||
[endsect]
|
||||
|
||||
[section:expand expand]
|
||||
[include generated/expand.qbk]
|
||||
[endsect]
|
||||
|
||||
[section:for_each for_each]
|
||||
[include generated/for_each.qbk]
|
||||
[endsect]
|
||||
|
||||
[/section:intersection intersection]
|
||||
[section:intersection intersection]
|
||||
[include generated/intersection.qbk]
|
||||
[/endsect]
|
||||
[endsect]
|
||||
|
||||
[section:intersects intersects]
|
||||
[include generated/intersects.qbk]
|
||||
@@ -124,7 +137,9 @@
|
||||
|
||||
[include generated/is_empty.qbk]
|
||||
|
||||
[section:is_simple is_simple]
|
||||
[include generated/is_simple.qbk]
|
||||
[endsect]
|
||||
|
||||
[section:is_valid is_valid]
|
||||
[include generated/is_valid.qbk]
|
||||
@@ -143,16 +158,21 @@
|
||||
[include generated/num_points.qbk]
|
||||
[include generated/num_segments.qbk]
|
||||
|
||||
|
||||
[section:overlaps overlaps]
|
||||
[include generated/overlaps.qbk]
|
||||
[endsect]
|
||||
|
||||
[section:perimeter perimeter]
|
||||
[include generated/perimeter.qbk]
|
||||
[endsect]
|
||||
|
||||
[section:relate relate]
|
||||
[include generated/relate.qbk]
|
||||
[endsect]
|
||||
|
||||
[section:relation relation]
|
||||
[include generated/relation.qbk]
|
||||
[endsect]
|
||||
|
||||
[include generated/reverse.qbk]
|
||||
|
||||
@@ -160,9 +180,9 @@
|
||||
[include generated/simplify.qbk]
|
||||
[endsect]
|
||||
|
||||
[/section:sym_difference sym_difference]
|
||||
[section:sym_difference sym_difference]
|
||||
[include generated/sym_difference.qbk]
|
||||
[/endsect]
|
||||
[endsect]
|
||||
|
||||
[section:touches touches]
|
||||
[include generated/touches.qbk]
|
||||
@@ -172,9 +192,9 @@
|
||||
[include generated/transform.qbk]
|
||||
[endsect]
|
||||
|
||||
[/section:union union]
|
||||
[section:union_ union_]
|
||||
[include generated/union.qbk]
|
||||
[/endsect]
|
||||
[endsect]
|
||||
|
||||
[include generated/unique.qbk]
|
||||
|
||||
@@ -317,7 +337,8 @@
|
||||
[include generated/distance_cross_track.qbk]
|
||||
[include generated/distance_cross_track_point_box.qbk]
|
||||
[include generated/area_surveyor.qbk]
|
||||
[include generated/area_huiller.qbk]
|
||||
[include generated/area_spherical.qbk]
|
||||
[/include generated/area_geographic.qbk]
|
||||
[include generated/buffer_join_round.qbk]
|
||||
[include generated/buffer_join_miter.qbk]
|
||||
[include generated/buffer_end_round.qbk]
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
[/============================================================================
|
||||
Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
Copyright (c) 2009-2016 Barend Gehrels, Geodan, Amsterdam, the Netherlands.
|
||||
Copyright (c) 2009-2016 Bruno Lalande, Paris, France.
|
||||
Copyright (c) 2009-2016 Mateusz Loskot <mateusz@loskot.net>, London, UK.
|
||||
Copyright (c) 2011-2016 Adam Wulkiewicz, Lodz, Poland.
|
||||
Copyright (c) 2009-2017 Barend Gehrels, Geodan, Amsterdam, the Netherlands.
|
||||
Copyright (c) 2009-2017 Bruno Lalande, Paris, France.
|
||||
Copyright (c) 2009-2017 Mateusz Loskot <mateusz@loskot.net>, London, UK.
|
||||
Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
This file was modified by Oracle on 2015, 2016.
|
||||
Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
|
||||
This file was modified by Oracle on 2015, 2017.
|
||||
Modifications copyright (c) 2015-2017, 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
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
[*Breaking changes]
|
||||
|
||||
* ublas_transformer is renamed to matrix_transformer
|
||||
* explicit modifier is added to constructors of rtree index::dynamic_* parameters
|
||||
* strategy::area::huiller replaced by strategy::area::spherical
|
||||
|
||||
[*Solved issues]
|
||||
|
||||
@@ -38,6 +40,7 @@
|
||||
[*Solved tickets]
|
||||
|
||||
* [@https://svn.boost.org/trac/boost/ticket/12566 12566] Ambiguous template instantiation in equal_to<> when pair value contains raw pointer
|
||||
* [@https://svn.boost.org/trac/boost/ticket/12861 12566] Segmentation fault in stdlibc++ (gcc 4.8.2) affecting rtree
|
||||
|
||||
[/=================]
|
||||
[heading Boost 1.63]
|
||||
|
||||
@@ -12,12 +12,12 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/assign.hpp>
|
||||
|
||||
#include <boost/geometry.hpp>
|
||||
#include <boost/geometry/geometries/polygon.hpp>
|
||||
#include <boost/geometry/geometries/adapted/boost_tuple.hpp>
|
||||
|
||||
#include <boost/assign.hpp> /*< At the end to avoid conflicts with Boost.QVM >*/
|
||||
|
||||
BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian)
|
||||
|
||||
int main()
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/assign.hpp>
|
||||
|
||||
#include <boost/geometry.hpp>
|
||||
#include <boost/geometry/geometries/polygon.hpp>
|
||||
#include <boost/geometry/geometries/multi_polygon.hpp>
|
||||
#include <boost/geometry/geometries/adapted/boost_tuple.hpp>
|
||||
|
||||
#include <boost/assign.hpp> /*< At the end to avoid conflicts with Boost.QVM >*/
|
||||
|
||||
BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian)
|
||||
|
||||
template <typename Tag> struct dispatch {};
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/assign.hpp>
|
||||
|
||||
#include <boost/geometry.hpp>
|
||||
#include <boost/geometry/geometries/linestring.hpp>
|
||||
#include <boost/geometry/geometries/point_xy.hpp>
|
||||
#include <boost/geometry/geometries/adapted/boost_range/sliced.hpp>
|
||||
|
||||
#include <boost/assign.hpp> /*< At the end to avoid conflicts with Boost.QVM >*/
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/assign.hpp>
|
||||
|
||||
#include <boost/geometry.hpp>
|
||||
#include <boost/geometry/geometries/point_xy.hpp>
|
||||
#include <boost/geometry/geometries/ring.hpp>
|
||||
#include <boost/geometry/geometries/adapted/boost_range/strided.hpp>
|
||||
|
||||
#include <boost/assign.hpp> /*< At the end to avoid conflicts with Boost.QVM >*/
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
//#pragma warning( disable : 4244 )
|
||||
#endif // defined(_MSC_VER)
|
||||
|
||||
#include <iostream>
|
||||
|
||||
//[quickstart_include
|
||||
|
||||
#include <boost/geometry.hpp>
|
||||
|
||||
@@ -27,6 +27,12 @@
|
||||
#include <boost/geometry/io/wkt/write.hpp>
|
||||
#include <boost/assign/list_of.hpp>
|
||||
|
||||
#include <boost/geometry/multi/algorithms/equals.hpp>
|
||||
#include <boost/geometry/multi/geometries/multi_geometries.hpp>
|
||||
#include <boost/geometry/multi/io/wkt/wkt.hpp>
|
||||
|
||||
#include <boost/geometry/extensions/multi/gis/io/wkb/read_wkb.hpp>
|
||||
|
||||
namespace bg = boost::geometry;
|
||||
|
||||
namespace { // anonymous
|
||||
@@ -42,6 +48,15 @@ void test_geometry_wrong_wkb(std::string const& wkbhex, std::string const& wkt)
|
||||
BOOST_MESSAGE("read_wkb: " << bg::read_wkb(wkb.begin(), wkb.end(), g_wkb));
|
||||
}
|
||||
|
||||
template <typename Geometry>
|
||||
void test_geometry_parse_failure(std::string const& wkbhex, std::string const& wkt)
|
||||
{
|
||||
byte_vector wkb;
|
||||
BOOST_CHECK( bg::hex2wkb(wkbhex, std::back_inserter(wkb)) );
|
||||
Geometry g_wkb;
|
||||
BOOST_CHECK( bg::read_wkb(wkb.begin(), wkb.end(), g_wkb) == false );
|
||||
}
|
||||
|
||||
template <typename Geometry, bool IsEqual>
|
||||
void test_geometry_equals_old(std::string const& wkbhex, std::string const& wkt)
|
||||
{
|
||||
@@ -130,16 +145,17 @@ int test_main(int, char* [])
|
||||
// "POINT (1.234 5.678)");
|
||||
|
||||
}
|
||||
|
||||
typedef bg::model::point<double, 2, bg::cs::cartesian> point_type;
|
||||
typedef bg::model::point<double, 3, bg::cs::cartesian> point3d_type;
|
||||
|
||||
typedef bg::model::linestring<point_type> linestring_type;
|
||||
//typedef bg::model::linestring<point3d_type> linestring3d_type;
|
||||
|
||||
typedef bg::model::polygon<point_type> polygon_type;
|
||||
//typedef bg::model::polygon<point3d_type> polygon3d_type;
|
||||
|
||||
{
|
||||
typedef bg::model::point<double, 2, bg::cs::cartesian> point_type;
|
||||
typedef bg::model::point<double, 3, bg::cs::cartesian> point3d_type;
|
||||
|
||||
typedef bg::model::linestring<point_type> linestring_type;
|
||||
//typedef bg::model::linestring<point3d_type> linestring3d_type;
|
||||
|
||||
typedef bg::model::polygon<point_type> polygon_type;
|
||||
//typedef bg::model::polygon<point3d_type> polygon3d_type;
|
||||
|
||||
//
|
||||
// POINT
|
||||
@@ -165,6 +181,16 @@ int test_main(int, char* [])
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
point3d_type point(1.234, 5.678, 99.0);
|
||||
|
||||
test_geometry_equals<point3d_type, true>
|
||||
(
|
||||
point,
|
||||
"01e90300005839b4c876bef33f83c0caa145b616400000000000c05840"
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// LINESTRING
|
||||
//
|
||||
@@ -185,6 +211,30 @@ int test_main(int, char* [])
|
||||
"010200000003000000000000000000F03F00000000000000400000000000000040000000000000084000000000000010400000000000001440"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
linestring_type linestring;
|
||||
|
||||
bg::append(linestring,
|
||||
boost::assign::list_of
|
||||
(point_type(1.234, 5.678))
|
||||
(point_type(9.1011, 10.1112))
|
||||
(point_type(13.1415, 16.1718))
|
||||
);
|
||||
|
||||
test_geometry_equals<linestring_type, true>
|
||||
(
|
||||
linestring,
|
||||
"0102000000030000005839B4C876BEF33F83C0CAA145B616404F401361C333224062A1D634EF3824409CC420B072482A40EB73B515FB2B3040"
|
||||
);
|
||||
|
||||
test_geometry_equals<linestring_type, false>
|
||||
(
|
||||
linestring,
|
||||
"0102000080030000005839B4C876BEF33F83C0CAA145B616400000000000C058404F401361C333224062A1D634EF3824400000000000C058409CC420B072482A40EB73B515FB2B30400000000000C05840"
|
||||
);
|
||||
}
|
||||
|
||||
// {
|
||||
// linestring3d_type linestring;
|
||||
@@ -225,7 +275,26 @@ int test_main(int, char* [])
|
||||
"010300000001000000050000000000000000004940000000000000494000000000000049400000000000005940000000000000594000000000000059400000000000005940000000000000494000000000000049400000000000004940"
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
polygon_type polygon;
|
||||
|
||||
bg::append(polygon,
|
||||
boost::assign::list_of
|
||||
(point_type(100.0, 200.0))
|
||||
(point_type(200.0, 200.0))
|
||||
(point_type(200.0, 400.0))
|
||||
(point_type(100.0, 400.0))
|
||||
(point_type(100.0, 200.0))
|
||||
);
|
||||
|
||||
test_geometry_equals<polygon_type, true>
|
||||
(
|
||||
polygon,
|
||||
"010300000001000000050000000000000000005940000000000000694000000000000069400000000000006940000000000000694000000000000079400000000000005940000000000000794000000000000059400000000000006940"
|
||||
);
|
||||
}
|
||||
|
||||
// {
|
||||
// polygon3d_type polygon;
|
||||
//
|
||||
@@ -251,7 +320,7 @@ int test_main(int, char* [])
|
||||
);
|
||||
|
||||
// Create an interior ring (append does not do this automatically)
|
||||
boost::geometry::interior_rings(polygon).resize(1);
|
||||
polygon.inners().resize(1);
|
||||
|
||||
bg::append(polygon,
|
||||
boost::assign::list_of
|
||||
@@ -269,6 +338,158 @@ int test_main(int, char* [])
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Multi Geometries
|
||||
//
|
||||
|
||||
typedef bg::model::multi_point<point_type> multipoint_type;
|
||||
typedef bg::model::multi_linestring<linestring_type> multilinestring_type;
|
||||
typedef bg::model::multi_polygon<polygon_type> multipolygon_type;
|
||||
|
||||
//
|
||||
// MultiPoint
|
||||
//
|
||||
|
||||
{
|
||||
multipoint_type multipoint;
|
||||
|
||||
bg::append(multipoint,
|
||||
boost::assign::list_of
|
||||
(point_type(1.234, 5.678))
|
||||
);
|
||||
|
||||
test_geometry_equals<multipoint_type, true>
|
||||
(
|
||||
multipoint,
|
||||
"01040000000100000001010000005839b4c876bef33f83c0caa145b61640"
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
multipoint_type multipoint;
|
||||
|
||||
bg::append(multipoint,
|
||||
boost::assign::list_of
|
||||
(point_type(1.234, 5.678))
|
||||
(point_type(10.1112, 13.1415))
|
||||
);
|
||||
|
||||
test_geometry_equals<multipoint_type, true>
|
||||
(
|
||||
multipoint,
|
||||
"01040000000200000001010000005839b4c876bef33f83c0caa145b61640010100000062a1d634ef3824409cc420b072482a40"
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// MultiLineString
|
||||
//
|
||||
|
||||
{
|
||||
multilinestring_type multilinestring;
|
||||
|
||||
// Create linestrings (append does not do this automatically)
|
||||
multilinestring.resize(1);
|
||||
|
||||
bg::append(multilinestring[0],
|
||||
boost::assign::list_of
|
||||
(point_type(1.234, 5.678))
|
||||
(point_type(9.1011, 10.1112))
|
||||
(point_type(13.1415, 16.1718))
|
||||
);
|
||||
|
||||
test_geometry_equals<multilinestring_type, true>
|
||||
(
|
||||
multilinestring,
|
||||
"0105000000010000000102000000030000005839b4c876bef33f83c0caa145b616404f401361c333224062a1d634ef3824409cc420b072482a40eb73b515fb2b3040"
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
multilinestring_type multilinestring;
|
||||
|
||||
// Create linestrings (append does not do this automatically)
|
||||
multilinestring.resize(2);
|
||||
|
||||
bg::append(multilinestring[0],
|
||||
boost::assign::list_of
|
||||
(point_type(1.234, 5.678))
|
||||
(point_type(9.1011, 10.1112))
|
||||
(point_type(13.1415, 16.1718))
|
||||
);
|
||||
|
||||
bg::append(multilinestring[1],
|
||||
boost::assign::list_of
|
||||
(point_type(19.2, 21.22))
|
||||
(point_type(23.24, 25.26))
|
||||
);
|
||||
|
||||
test_geometry_equals<multilinestring_type, true>
|
||||
(
|
||||
multilinestring,
|
||||
"0105000000020000000102000000030000005839b4c876bef33f83c0caa145b616404f401361c333224062a1d634ef3824409cc420b072482a40eb73b515fb2b30400102000000020000003333333333333340b81e85eb513835403d0ad7a3703d3740c3f5285c8f423940"
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// MultiPolygon
|
||||
//
|
||||
|
||||
{
|
||||
multipolygon_type multipolygon;
|
||||
|
||||
// Create polygons (append does not do this automatically)
|
||||
multipolygon.resize(1);
|
||||
|
||||
bg::append(multipolygon[0],
|
||||
boost::assign::list_of
|
||||
(point_type(100, 200))
|
||||
(point_type(200, 200))
|
||||
(point_type(200, 400))
|
||||
(point_type(100, 400))
|
||||
(point_type(100, 200))
|
||||
);
|
||||
|
||||
test_geometry_equals<multipolygon_type, true>
|
||||
(
|
||||
multipolygon,
|
||||
"010600000001000000010300000001000000050000000000000000005940000000000000694000000000000069400000000000006940000000000000694000000000000079400000000000005940000000000000794000000000000059400000000000006940"
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
multipolygon_type multipolygon;
|
||||
|
||||
// Create polygons (append does not do this automatically)
|
||||
multipolygon.resize(1);
|
||||
// Create an interior ring (append does not do this automatically)
|
||||
multipolygon[0].inners().resize(1);
|
||||
|
||||
bg::append(multipolygon[0],
|
||||
boost::assign::list_of
|
||||
(point_type(35, 10))
|
||||
(point_type(10, 20))
|
||||
(point_type(15, 40))
|
||||
(point_type(45, 45))
|
||||
(point_type(35, 10))
|
||||
);
|
||||
|
||||
bg::append(multipolygon[0],
|
||||
boost::assign::list_of
|
||||
(point_type(20, 30))
|
||||
(point_type(35, 35))
|
||||
(point_type(30, 20))
|
||||
(point_type(20, 30)),
|
||||
0
|
||||
);
|
||||
|
||||
test_geometry_equals<multipolygon_type, true>
|
||||
(
|
||||
multipolygon,
|
||||
"0106000000010000000103000000020000000500000000000000008041400000000000002440000000000000244000000000000034400000000000002e40000000000000444000000000008046400000000000804640000000000080414000000000000024400400000000000000000034400000000000003e40000000000080414000000000008041400000000000003e40000000000000344000000000000034400000000000003e40"
|
||||
);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -27,9 +27,17 @@
|
||||
|
||||
#include <boost/geometry/io/wkt/wkt.hpp>
|
||||
|
||||
#include <boost/geometry/multi/algorithms/equals.hpp>
|
||||
#include <boost/geometry/multi/geometries/multi_geometries.hpp>
|
||||
#include <boost/geometry/multi/io/wkt/wkt.hpp>
|
||||
|
||||
#include <boost/geometry/extensions/multi/gis/io/wkb/write_wkb.hpp>
|
||||
|
||||
#include <boost/range/algorithm_ext/push_back.hpp>
|
||||
#include <boost/assign/list_of.hpp>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
namespace bg = boost::geometry;
|
||||
|
||||
namespace { // anonymous
|
||||
@@ -42,10 +50,11 @@ void test_geometry_equals(Geometry const& geometry, std::string const& wkbhex)
|
||||
|
||||
std::string hex_out;
|
||||
BOOST_CHECK( bg::wkb2hex(wkb_out.begin(), wkb_out.end(), hex_out) );
|
||||
|
||||
|
||||
boost::algorithm::to_lower(hex_out);
|
||||
|
||||
BOOST_CHECK_EQUAL( wkbhex, hex_out);
|
||||
}
|
||||
|
||||
} // namespace anonymous
|
||||
|
||||
int test_main(int, char* [])
|
||||
@@ -67,7 +76,7 @@ int test_main(int, char* [])
|
||||
test_geometry_equals<point_type, true>
|
||||
(
|
||||
point,
|
||||
"0101000000000000000000F03F0000000000000040"
|
||||
"0101000000000000000000f03f0000000000000040"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -77,7 +86,7 @@ int test_main(int, char* [])
|
||||
test_geometry_equals<point3d_type, true>
|
||||
(
|
||||
point,
|
||||
"01E9030000000000000000F03F00000000000000400000000000000840"
|
||||
"01e9030000000000000000f03f00000000000000400000000000000840"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -98,7 +107,7 @@ int test_main(int, char* [])
|
||||
test_geometry_equals<linestring_type, true>
|
||||
(
|
||||
linestring,
|
||||
"010200000003000000000000000000F03F00000000000000400000000000000040000000000000084000000000000010400000000000001440"
|
||||
"010200000003000000000000000000f03f00000000000000400000000000000040000000000000084000000000000010400000000000001440"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -115,7 +124,7 @@ int test_main(int, char* [])
|
||||
test_geometry_equals<linestring3d_type, true>
|
||||
(
|
||||
linestring,
|
||||
"01EA03000003000000000000000000F03F00000000000000400000000000000840000000000000004000000000000008400000000000001040000000000000104000000000000014400000000000001840"
|
||||
"01ea03000003000000000000000000f03f00000000000000400000000000000840000000000000004000000000000008400000000000001040000000000000104000000000000014400000000000001840"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -157,7 +166,7 @@ int test_main(int, char* [])
|
||||
test_geometry_equals<polygon3d_type, true>
|
||||
(
|
||||
polygon,
|
||||
"01EB0300000100000005000000000000000000494000000000000049400000000000001440000000000000494000000000000059400000000000002440000000000000594000000000000059400000000000001440000000000000594000000000000049400000000000002440000000000000494000000000000049400000000000001440"
|
||||
"01eb0300000100000005000000000000000000494000000000000049400000000000001440000000000000494000000000000059400000000000002440000000000000594000000000000059400000000000001440000000000000594000000000000049400000000000002440000000000000494000000000000049400000000000001440"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -187,9 +196,161 @@ int test_main(int, char* [])
|
||||
test_geometry_equals<polygon_type, true>
|
||||
(
|
||||
polygon,
|
||||
"0103000000020000000500000000000000008041400000000000002440000000000080464000000000008046400000000000002E40000000000000444000000000000024400000000000003440000000000080414000000000000024400400000000000000000034400000000000003E40000000000080414000000000008041400000000000003E40000000000000344000000000000034400000000000003E40"
|
||||
"0103000000020000000500000000000000008041400000000000002440000000000080464000000000008046400000000000002e40000000000000444000000000000024400000000000003440000000000080414000000000000024400400000000000000000034400000000000003e40000000000080414000000000008041400000000000003e40000000000000344000000000000034400000000000003e40"
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// Multi Geometries
|
||||
//
|
||||
|
||||
typedef bg::model::multi_point<point_type> multipoint_type;
|
||||
typedef bg::model::multi_linestring<linestring_type> multilinestring_type;
|
||||
typedef bg::model::multi_polygon<polygon_type> multipolygon_type;
|
||||
|
||||
//
|
||||
// MultiPoint
|
||||
//
|
||||
|
||||
{
|
||||
multipoint_type multipoint;
|
||||
|
||||
bg::append(multipoint,
|
||||
boost::assign::list_of
|
||||
(point_type(1.234, 5.678))
|
||||
);
|
||||
|
||||
test_geometry_equals<multipoint_type, true>
|
||||
(
|
||||
multipoint,
|
||||
"01040000000100000001010000005839b4c876bef33f83c0caa145b61640"
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
multipoint_type multipoint;
|
||||
|
||||
bg::append(multipoint,
|
||||
boost::assign::list_of
|
||||
(point_type(1.234, 5.678))
|
||||
(point_type(10.1112, 13.1415))
|
||||
);
|
||||
|
||||
test_geometry_equals<multipoint_type, true>
|
||||
(
|
||||
multipoint,
|
||||
"01040000000200000001010000005839b4c876bef33f83c0caa145b61640010100000062a1d634ef3824409cc420b072482a40"
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// MultiLineString
|
||||
//
|
||||
|
||||
{
|
||||
multilinestring_type multilinestring;
|
||||
|
||||
// Create linestrings (append does not do this automatically)
|
||||
multilinestring.resize(1);
|
||||
|
||||
bg::append(multilinestring[0],
|
||||
boost::assign::list_of
|
||||
(point_type(1.234, 5.678))
|
||||
(point_type(9.1011, 10.1112))
|
||||
(point_type(13.1415, 16.1718))
|
||||
);
|
||||
|
||||
test_geometry_equals<multilinestring_type, true>
|
||||
(
|
||||
multilinestring,
|
||||
"0105000000010000000102000000030000005839b4c876bef33f83c0caa145b616404f401361c333224062a1d634ef3824409cc420b072482a40eb73b515fb2b3040"
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
multilinestring_type multilinestring;
|
||||
|
||||
// Create linestrings (append does not do this automatically)
|
||||
multilinestring.resize(2);
|
||||
|
||||
bg::append(multilinestring[0],
|
||||
boost::assign::list_of
|
||||
(point_type(1.234, 5.678))
|
||||
(point_type(9.1011, 10.1112))
|
||||
(point_type(13.1415, 16.1718))
|
||||
);
|
||||
|
||||
bg::append(multilinestring[1],
|
||||
boost::assign::list_of
|
||||
(point_type(19.2, 21.22))
|
||||
(point_type(23.24, 25.26))
|
||||
);
|
||||
|
||||
test_geometry_equals<multilinestring_type, true>
|
||||
(
|
||||
multilinestring,
|
||||
"0105000000020000000102000000030000005839b4c876bef33f83c0caa145b616404f401361c333224062a1d634ef3824409cc420b072482a40eb73b515fb2b30400102000000020000003333333333333340b81e85eb513835403d0ad7a3703d3740c3f5285c8f423940"
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// MultiPolygon
|
||||
//
|
||||
|
||||
{
|
||||
multipolygon_type multipolygon;
|
||||
|
||||
// Create polygons (append does not do this automatically)
|
||||
multipolygon.resize(1);
|
||||
|
||||
bg::append(multipolygon[0],
|
||||
boost::assign::list_of
|
||||
(point_type(100, 200))
|
||||
(point_type(200, 200))
|
||||
(point_type(200, 400))
|
||||
(point_type(100, 400))
|
||||
(point_type(100, 200))
|
||||
);
|
||||
|
||||
test_geometry_equals<multipolygon_type, true>
|
||||
(
|
||||
multipolygon,
|
||||
"010600000001000000010300000001000000050000000000000000005940000000000000694000000000000069400000000000006940000000000000694000000000000079400000000000005940000000000000794000000000000059400000000000006940"
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
multipolygon_type multipolygon;
|
||||
|
||||
// Create polygons (append does not do this automatically)
|
||||
multipolygon.resize(1);
|
||||
// Create an interior ring (append does not do this automatically)
|
||||
multipolygon[0].inners().resize(1);
|
||||
|
||||
bg::append(multipolygon[0],
|
||||
boost::assign::list_of
|
||||
(point_type(35, 10))
|
||||
(point_type(10, 20))
|
||||
(point_type(15, 40))
|
||||
(point_type(45, 45))
|
||||
(point_type(35, 10))
|
||||
);
|
||||
|
||||
bg::append(multipolygon[0],
|
||||
boost::assign::list_of
|
||||
(point_type(20, 30))
|
||||
(point_type(35, 35))
|
||||
(point_type(30, 20))
|
||||
(point_type(20, 30)),
|
||||
0
|
||||
);
|
||||
|
||||
test_geometry_equals<multipolygon_type, true>
|
||||
(
|
||||
multipolygon,
|
||||
"0106000000010000000103000000020000000500000000000000008041400000000000002440000000000000244000000000000034400000000000002e40000000000000444000000000008046400000000000804640000000000080414000000000000024400400000000000000000034400000000000003e40000000000080414000000000008041400000000000003e40000000000000344000000000000034400000000000003e40"
|
||||
);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2017.
|
||||
// Modifications copyright (c) 2017 Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
@@ -303,7 +307,8 @@ inline typename default_area_result<Geometry>::type area(Geometry const& geometr
|
||||
|
||||
[heading Available Strategies]
|
||||
\* [link geometry.reference.strategies.strategy_area_surveyor Surveyor (cartesian)]
|
||||
\* [link geometry.reference.strategies.strategy_area_huiller Huiller (spherical)]
|
||||
\* [link geometry.reference.strategies.strategy_area_spherical Spherical]
|
||||
[/link geometry.reference.strategies.strategy_area_geographic Geographic]
|
||||
}
|
||||
*/
|
||||
template <typename Geometry, typename Strategy>
|
||||
|
||||
@@ -228,6 +228,7 @@ namespace resolve_variant
|
||||
\param strategy \param_strategy{crosses}
|
||||
\return \return_check2{crosses}
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/crosses.qbk]}
|
||||
*/
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
|
||||
@@ -203,6 +203,7 @@ struct disjoint
|
||||
\param strategy \param_strategy{disjoint}
|
||||
\return \return_check2{are disjoint}
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/disjoint.qbk]}
|
||||
*/
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
|
||||
@@ -135,6 +135,7 @@ struct envelope<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
\param mbr \param_box \param_set{envelope}
|
||||
\param strategy \param_strategy{envelope}
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/envelope.qbk]}
|
||||
\qbk{
|
||||
[heading Example]
|
||||
@@ -142,7 +143,7 @@ struct envelope<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
}
|
||||
*/
|
||||
template<typename Geometry, typename Box, typename Strategy>
|
||||
inline void envelope(Geometry const& geometry, Box& mbr, Strategy& strategy)
|
||||
inline void envelope(Geometry const& geometry, Box& mbr, Strategy const& strategy)
|
||||
{
|
||||
resolve_variant::envelope<Geometry>::apply(geometry, mbr, strategy);
|
||||
}
|
||||
@@ -169,6 +170,32 @@ inline void envelope(Geometry const& geometry, Box& mbr)
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_calc{envelope}
|
||||
\ingroup envelope
|
||||
\details \details_calc{return_envelope,\det_envelope}. \details_return{envelope}
|
||||
\tparam Box \tparam_box
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Strategy \tparam_strategy{Envelope}
|
||||
\param geometry \param_geometry
|
||||
\param strategy \param_strategy{envelope}
|
||||
\return \return_calc{envelope}
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/envelope.qbk]}
|
||||
\qbk{
|
||||
[heading Example]
|
||||
[return_envelope] [return_envelope_output]
|
||||
}
|
||||
*/
|
||||
template<typename Box, typename Geometry, typename Strategy>
|
||||
inline Box return_envelope(Geometry const& geometry, Strategy const& strategy)
|
||||
{
|
||||
Box mbr;
|
||||
resolve_variant::envelope<Geometry>::apply(geometry, mbr, strategy);
|
||||
return mbr;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief \brief_calc{envelope}
|
||||
\ingroup envelope
|
||||
|
||||
@@ -160,10 +160,13 @@ inline void expand(Box& box, Geometry const& geometry,
|
||||
\ingroup expand
|
||||
\tparam Box type of the box
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Strategy \tparam_strategy{expand}
|
||||
\param box box to be expanded using another geometry, mutable
|
||||
\param geometry \param_geometry geometry which envelope (bounding box)
|
||||
\param strategy \param_strategy{expand}
|
||||
will be added to the box
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/expand.qbk]}
|
||||
*/
|
||||
template <typename Box, typename Geometry, typename Strategy>
|
||||
|
||||
@@ -15,12 +15,14 @@
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_INTERFACE_HPP
|
||||
|
||||
|
||||
// TODO: those headers probably may be removed
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/algorithms/intersects.hpp>
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/overlay/intersection_insert.hpp>
|
||||
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
|
||||
#include <boost/geometry/strategies/default_strategy.hpp>
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -98,33 +100,46 @@ struct intersection
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
namespace resolve_variant
|
||||
{
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
|
||||
namespace resolve_strategy {
|
||||
|
||||
struct intersection
|
||||
{
|
||||
template <typename GeometryOut>
|
||||
static inline bool
|
||||
apply(
|
||||
const Geometry1& geometry1,
|
||||
const Geometry2& geometry2,
|
||||
GeometryOut& geometry_out)
|
||||
template
|
||||
<
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename RobustPolicy,
|
||||
typename GeometryOut,
|
||||
typename Strategy
|
||||
>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
RobustPolicy const& robust_policy,
|
||||
GeometryOut & geometry_out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
concepts::check<Geometry1 const>();
|
||||
concepts::check<Geometry2 const>();
|
||||
|
||||
typedef typename geometry::rescale_overlay_policy_type
|
||||
return dispatch::intersection
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::type rescale_policy_type;
|
||||
|
||||
rescale_policy_type robust_policy
|
||||
= geometry::get_rescale_policy<rescale_policy_type>(geometry1,
|
||||
geometry2);
|
||||
|
||||
>::apply(geometry1, geometry2, robust_policy, geometry_out,
|
||||
strategy);
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename RobustPolicy,
|
||||
typename GeometryOut
|
||||
>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
RobustPolicy const& robust_policy,
|
||||
GeometryOut & geometry_out,
|
||||
default_strategy)
|
||||
{
|
||||
typedef typename strategy::relate::services::default_strategy
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
@@ -139,44 +154,83 @@ struct intersection
|
||||
}
|
||||
};
|
||||
|
||||
} // resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_variant
|
||||
{
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct intersection
|
||||
{
|
||||
template <typename GeometryOut, typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
GeometryOut& geometry_out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
concepts::check<Geometry1 const>();
|
||||
concepts::check<Geometry2 const>();
|
||||
|
||||
typedef typename geometry::rescale_overlay_policy_type
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::type rescale_policy_type;
|
||||
|
||||
rescale_policy_type robust_policy
|
||||
= geometry::get_rescale_policy<rescale_policy_type>(geometry1,
|
||||
geometry2);
|
||||
|
||||
return resolve_strategy::intersection::apply(geometry1,
|
||||
geometry2,
|
||||
robust_policy,
|
||||
geometry_out,
|
||||
strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
|
||||
struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
|
||||
{
|
||||
template <typename GeometryOut>
|
||||
template <typename GeometryOut, typename Strategy>
|
||||
struct visitor: static_visitor<bool>
|
||||
{
|
||||
Geometry2 const& m_geometry2;
|
||||
GeometryOut& m_geometry_out;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Geometry2 const& geometry2,
|
||||
GeometryOut& geometry_out)
|
||||
GeometryOut& geometry_out,
|
||||
Strategy const& strategy)
|
||||
: m_geometry2(geometry2)
|
||||
, m_geometry_out(geometry_out)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry1>
|
||||
result_type operator()(Geometry1 const& geometry1) const
|
||||
bool operator()(Geometry1 const& geometry1) const
|
||||
{
|
||||
return intersection
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::template apply
|
||||
<
|
||||
GeometryOut
|
||||
>
|
||||
(geometry1, m_geometry2, m_geometry_out);
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(geometry1, m_geometry2, m_geometry_out, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename GeometryOut>
|
||||
template <typename GeometryOut, typename Strategy>
|
||||
static inline bool
|
||||
apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
GeometryOut& geometry_out)
|
||||
GeometryOut& geometry_out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return boost::apply_visitor(visitor<GeometryOut>(geometry2, geometry_out), geometry1);
|
||||
return boost::apply_visitor(visitor<GeometryOut, Strategy>(geometry2,
|
||||
geometry_out,
|
||||
strategy),
|
||||
geometry1);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -184,40 +238,43 @@ struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
|
||||
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct intersection<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
{
|
||||
template <typename GeometryOut>
|
||||
template <typename GeometryOut, typename Strategy>
|
||||
struct visitor: static_visitor<bool>
|
||||
{
|
||||
Geometry1 const& m_geometry1;
|
||||
GeometryOut& m_geometry_out;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Geometry1 const& geometry1,
|
||||
GeometryOut& geometry_out)
|
||||
GeometryOut& geometry_out,
|
||||
Strategy const& strategy)
|
||||
: m_geometry1(geometry1)
|
||||
, m_geometry_out(geometry_out)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry2>
|
||||
result_type operator()(Geometry2 const& geometry2) const
|
||||
bool operator()(Geometry2 const& geometry2) const
|
||||
{
|
||||
return intersection
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::template apply
|
||||
<
|
||||
GeometryOut
|
||||
>
|
||||
(m_geometry1, geometry2, m_geometry_out);
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(m_geometry1, geometry2, m_geometry_out, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename GeometryOut>
|
||||
template <typename GeometryOut, typename Strategy>
|
||||
static inline bool
|
||||
apply(Geometry1 const& geometry1,
|
||||
const variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry2,
|
||||
GeometryOut& geometry_out)
|
||||
variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
|
||||
GeometryOut& geometry_out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return boost::apply_visitor(visitor<GeometryOut>(geometry1, geometry_out), geometry2);
|
||||
return boost::apply_visitor(visitor<GeometryOut, Strategy>(geometry1,
|
||||
geometry_out,
|
||||
strategy),
|
||||
geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -225,44 +282,83 @@ struct intersection<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
|
||||
struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
|
||||
{
|
||||
template <typename GeometryOut>
|
||||
template <typename GeometryOut, typename Strategy>
|
||||
struct visitor: static_visitor<bool>
|
||||
{
|
||||
GeometryOut& m_geometry_out;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(GeometryOut& geometry_out)
|
||||
visitor(GeometryOut& geometry_out, Strategy const& strategy)
|
||||
: m_geometry_out(geometry_out)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
result_type operator()(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2) const
|
||||
bool operator()(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2) const
|
||||
{
|
||||
return intersection
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::template apply
|
||||
<
|
||||
GeometryOut
|
||||
>
|
||||
(geometry1, geometry2, m_geometry_out);
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(geometry1, geometry2, m_geometry_out, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename GeometryOut>
|
||||
template <typename GeometryOut, typename Strategy>
|
||||
static inline bool
|
||||
apply(const variant<BOOST_VARIANT_ENUM_PARAMS(T1)>& geometry1,
|
||||
const variant<BOOST_VARIANT_ENUM_PARAMS(T2)>& geometry2,
|
||||
GeometryOut& geometry_out)
|
||||
apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
|
||||
variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
|
||||
GeometryOut& geometry_out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return boost::apply_visitor(visitor<GeometryOut>(geometry_out), geometry1, geometry2);
|
||||
return boost::apply_visitor(visitor<GeometryOut, Strategy>(geometry_out,
|
||||
strategy),
|
||||
geometry1, geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_calc2{intersection}
|
||||
\ingroup intersection
|
||||
\details \details_calc2{intersection, spatial set theoretic intersection}.
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\tparam GeometryOut Collection of geometries (e.g. std::vector, std::deque, boost::geometry::multi*) of which
|
||||
the value_type fulfills a \p_l_or_c concept, or it is the output geometry (e.g. for a box)
|
||||
\tparam Strategy \tparam_strategy{Intersection}
|
||||
\param geometry1 \param_geometry
|
||||
\param geometry2 \param_geometry
|
||||
\param geometry_out The output geometry, either a multi_point, multi_polygon,
|
||||
multi_linestring, or a box (for intersection of two boxes)
|
||||
\param strategy \param_strategy{intersection}
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/intersection.qbk]}
|
||||
*/
|
||||
template
|
||||
<
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename GeometryOut,
|
||||
typename Strategy
|
||||
>
|
||||
inline bool intersection(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
GeometryOut& geometry_out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return resolve_variant::intersection
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(geometry1, geometry2, geometry_out, strategy);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_calc2{intersection}
|
||||
\ingroup intersection
|
||||
@@ -285,18 +381,14 @@ template
|
||||
typename GeometryOut
|
||||
>
|
||||
inline bool intersection(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
GeometryOut& geometry_out)
|
||||
Geometry2 const& geometry2,
|
||||
GeometryOut& geometry_out)
|
||||
{
|
||||
return resolve_variant::intersection
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::template apply
|
||||
<
|
||||
GeometryOut
|
||||
>
|
||||
(geometry1, geometry2, geometry_out);
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(geometry1, geometry2, geometry_out, default_strategy());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2014-2017, 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
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
@@ -27,7 +28,8 @@ namespace detail { namespace is_simple
|
||||
template <typename Geometry>
|
||||
struct always_simple
|
||||
{
|
||||
static inline bool apply(Geometry const&)
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Geometry const&, Strategy const&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014-2015, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2014-2017, 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
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
@@ -37,6 +38,12 @@ namespace detail { namespace is_simple
|
||||
template <typename Ring>
|
||||
struct is_simple_ring
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Ring const& ring, Strategy const&)
|
||||
{
|
||||
return apply(ring);
|
||||
}
|
||||
|
||||
static inline bool apply(Ring const& ring)
|
||||
{
|
||||
simplicity_failure_policy policy;
|
||||
@@ -69,6 +76,12 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Polygon const& polygon, Strategy const&)
|
||||
{
|
||||
return apply(polygon);
|
||||
}
|
||||
|
||||
static inline bool apply(Polygon const& polygon)
|
||||
{
|
||||
return
|
||||
@@ -119,7 +132,8 @@ struct is_simple<Polygon, polygon_tag>
|
||||
template <typename MultiPolygon>
|
||||
struct is_simple<MultiPolygon, multi_polygon_tag>
|
||||
{
|
||||
static inline bool apply(MultiPolygon const& multipolygon)
|
||||
template <typename Strategy>
|
||||
static inline bool apply(MultiPolygon const& multipolygon, Strategy const&)
|
||||
{
|
||||
return
|
||||
detail::check_iterator_range
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2014-2017, 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
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
@@ -17,46 +18,106 @@
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/is_simple.hpp>
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/strategies/default_strategy.hpp>
|
||||
#include <boost/geometry/strategies/intersection.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
namespace resolve_strategy
|
||||
{
|
||||
|
||||
namespace resolve_variant {
|
||||
struct is_simple
|
||||
{
|
||||
template <typename Geometry, typename Strategy>
|
||||
static inline bool apply(Geometry const& geometry,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return dispatch::is_simple<Geometry>::apply(geometry, strategy);
|
||||
}
|
||||
|
||||
template <typename Geometry>
|
||||
static inline bool apply(Geometry const& geometry,
|
||||
default_strategy)
|
||||
{
|
||||
// NOTE: Currently the strategy is only used for Linear geometries
|
||||
typedef typename strategy::intersection::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Geometry>::type
|
||||
>::type strategy_type;
|
||||
|
||||
return dispatch::is_simple<Geometry>::apply(geometry, strategy_type());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_strategy
|
||||
|
||||
namespace resolve_variant
|
||||
{
|
||||
|
||||
template <typename Geometry>
|
||||
struct is_simple
|
||||
{
|
||||
static inline bool apply(Geometry const& geometry)
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Geometry const& geometry, Strategy const& strategy)
|
||||
{
|
||||
concepts::check<Geometry const>();
|
||||
return dispatch::is_simple<Geometry>::apply(geometry);
|
||||
|
||||
return resolve_strategy::is_simple::apply(geometry, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct is_simple<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
{
|
||||
template <typename Strategy>
|
||||
struct visitor : boost::static_visitor<bool>
|
||||
{
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Strategy const& strategy)
|
||||
: m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry>
|
||||
bool operator()(Geometry const& geometry) const
|
||||
{
|
||||
return is_simple<Geometry>::apply(geometry);
|
||||
return is_simple<Geometry>::apply(geometry, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
static inline bool
|
||||
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry)
|
||||
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return boost::apply_visitor(visitor(), geometry);
|
||||
return boost::apply_visitor(visitor<Strategy>(strategy), geometry);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_check{is simple}
|
||||
\ingroup is_simple
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Strategy \tparam_strategy{Is_simple}
|
||||
\param geometry \param_geometry
|
||||
\param strategy \param_strategy{is_simple}
|
||||
\return \return_check{is simple}
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/is_simple.qbk]}
|
||||
*/
|
||||
template <typename Geometry, typename Strategy>
|
||||
inline bool is_simple(Geometry const& geometry, Strategy const& strategy)
|
||||
{
|
||||
return resolve_variant::is_simple<Geometry>::apply(geometry, strategy);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_check{is simple}
|
||||
@@ -70,7 +131,7 @@ struct is_simple<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
template <typename Geometry>
|
||||
inline bool is_simple(Geometry const& geometry)
|
||||
{
|
||||
return resolve_variant::is_simple<Geometry>::apply(geometry);
|
||||
return resolve_variant::is_simple<Geometry>::apply(geometry, default_strategy());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -189,8 +189,8 @@ private:
|
||||
};
|
||||
|
||||
|
||||
template <typename Linear>
|
||||
inline bool has_self_intersections(Linear const& linear)
|
||||
template <typename Linear, typename Strategy>
|
||||
inline bool has_self_intersections(Linear const& linear, Strategy const& strategy)
|
||||
{
|
||||
typedef typename point_type<Linear>::type point_type;
|
||||
|
||||
@@ -217,16 +217,11 @@ inline bool has_self_intersections(Linear const& linear)
|
||||
is_acceptable_turn<Linear>
|
||||
> interrupt_policy(predicate);
|
||||
|
||||
typedef typename strategy::intersection::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Linear>::type
|
||||
>::type strategy_type;
|
||||
|
||||
detail::self_get_turn_points::get_turns
|
||||
<
|
||||
turn_policy
|
||||
>::apply(linear,
|
||||
strategy_type(),
|
||||
strategy,
|
||||
detail::no_rescale_policy(),
|
||||
turns,
|
||||
interrupt_policy);
|
||||
@@ -252,8 +247,19 @@ struct is_simple_linestring
|
||||
&& ! detail::is_valid::has_spikes
|
||||
<
|
||||
Linestring, closed
|
||||
>::apply(linestring, policy)
|
||||
&& ! (CheckSelfIntersections && has_self_intersections(linestring));
|
||||
>::apply(linestring, policy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Linestring>
|
||||
struct is_simple_linestring<Linestring, true>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Linestring const& linestring,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return is_simple_linestring<Linestring, false>::apply(linestring)
|
||||
&& ! has_self_intersections(linestring, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -261,7 +267,9 @@ struct is_simple_linestring
|
||||
template <typename MultiLinestring>
|
||||
struct is_simple_multilinestring
|
||||
{
|
||||
static inline bool apply(MultiLinestring const& multilinestring)
|
||||
template <typename Strategy>
|
||||
static inline bool apply(MultiLinestring const& multilinestring,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
// check each of the linestrings for simplicity
|
||||
// but do not compute self-intersections yet; these will be
|
||||
@@ -281,7 +289,7 @@ struct is_simple_multilinestring
|
||||
return false;
|
||||
}
|
||||
|
||||
return ! has_self_intersections(multilinestring);
|
||||
return ! has_self_intersections(multilinestring, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014-2015, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2014-2017, 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
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
@@ -38,7 +39,8 @@ namespace detail { namespace is_simple
|
||||
template <typename MultiPoint>
|
||||
struct is_simple_multipoint
|
||||
{
|
||||
static inline bool apply(MultiPoint const& multipoint)
|
||||
template <typename Strategy>
|
||||
static inline bool apply(MultiPoint const& multipoint, Strategy const&)
|
||||
{
|
||||
if (boost::empty(multipoint))
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014-2015, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2014-2017, 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
|
||||
@@ -71,8 +71,8 @@ struct has_valid_corners<Box, 0>
|
||||
template <typename Box>
|
||||
struct is_valid_box
|
||||
{
|
||||
template <typename VisitPolicy>
|
||||
static inline bool apply(Box const& box, VisitPolicy& visitor)
|
||||
template <typename VisitPolicy, typename Strategy>
|
||||
static inline bool apply(Box const& box, VisitPolicy& visitor, Strategy const&)
|
||||
{
|
||||
return
|
||||
! has_invalid_coordinate<Box>::apply(box, visitor)
|
||||
|
||||
@@ -48,11 +48,6 @@ class has_valid_self_turns
|
||||
private:
|
||||
typedef typename point_type<Geometry>::type point_type;
|
||||
|
||||
typedef typename strategy::intersection::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Geometry>::type
|
||||
>::type intersection_strategy_type;
|
||||
|
||||
typedef typename geometry::rescale_policy_type
|
||||
<
|
||||
point_type
|
||||
@@ -75,15 +70,14 @@ public:
|
||||
> turn_type;
|
||||
|
||||
// returns true if all turns are valid
|
||||
template <typename Turns, typename VisitPolicy>
|
||||
template <typename Turns, typename VisitPolicy, typename Strategy>
|
||||
static inline bool apply(Geometry const& geometry,
|
||||
Turns& turns,
|
||||
VisitPolicy& visitor)
|
||||
VisitPolicy& visitor,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
boost::ignore_unused(visitor);
|
||||
|
||||
intersection_strategy_type intersection_strategy;
|
||||
|
||||
rescale_policy_type robust_policy
|
||||
= geometry::get_rescale_policy<rescale_policy_type>(geometry);
|
||||
|
||||
@@ -93,7 +87,7 @@ public:
|
||||
> interrupt_policy;
|
||||
|
||||
geometry::self_turns<turn_policy>(geometry,
|
||||
intersection_strategy,
|
||||
strategy,
|
||||
robust_policy,
|
||||
turns,
|
||||
interrupt_policy);
|
||||
@@ -110,11 +104,11 @@ public:
|
||||
}
|
||||
|
||||
// returns true if all turns are valid
|
||||
template <typename VisitPolicy>
|
||||
static inline bool apply(Geometry const& geometry, VisitPolicy& visitor)
|
||||
template <typename VisitPolicy, typename Strategy>
|
||||
static inline bool apply(Geometry const& geometry, VisitPolicy& visitor, Strategy const& strategy)
|
||||
{
|
||||
std::vector<turn_type> turns;
|
||||
return apply(geometry, turns, visitor);
|
||||
return apply(geometry, turns, visitor, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014-2015, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2014-2017, 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
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
@@ -23,48 +24,88 @@
|
||||
#include <boost/geometry/policies/is_valid/default_policy.hpp>
|
||||
#include <boost/geometry/policies/is_valid/failing_reason_policy.hpp>
|
||||
#include <boost/geometry/policies/is_valid/failure_type_policy.hpp>
|
||||
#include <boost/geometry/strategies/default_strategy.hpp>
|
||||
#include <boost/geometry/strategies/intersection.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
namespace resolve_strategy
|
||||
{
|
||||
|
||||
struct is_valid
|
||||
{
|
||||
template <typename Geometry, typename VisitPolicy, typename Strategy>
|
||||
static inline bool apply(Geometry const& geometry,
|
||||
VisitPolicy& visitor,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return dispatch::is_valid<Geometry>::apply(geometry, visitor, strategy);
|
||||
}
|
||||
|
||||
namespace resolve_variant {
|
||||
template <typename Geometry, typename VisitPolicy>
|
||||
static inline bool apply(Geometry const& geometry,
|
||||
VisitPolicy& visitor,
|
||||
default_strategy)
|
||||
{
|
||||
// NOTE: Currently the strategy is only used for Areal geometries
|
||||
typedef typename strategy::intersection::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Geometry>::type
|
||||
>::type strategy_type;
|
||||
|
||||
return dispatch::is_valid<Geometry>::apply(geometry, visitor, strategy_type());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_strategy
|
||||
|
||||
namespace resolve_variant
|
||||
{
|
||||
|
||||
template <typename Geometry>
|
||||
struct is_valid
|
||||
{
|
||||
template <typename VisitPolicy>
|
||||
static inline bool apply(Geometry const& geometry, VisitPolicy& visitor)
|
||||
template <typename VisitPolicy, typename Strategy>
|
||||
static inline bool apply(Geometry const& geometry,
|
||||
VisitPolicy& visitor,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
concepts::check<Geometry const>();
|
||||
return dispatch::is_valid<Geometry>::apply(geometry, visitor);
|
||||
|
||||
return resolve_strategy::is_valid::apply(geometry, visitor, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct is_valid<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
{
|
||||
template <typename VisitPolicy>
|
||||
template <typename VisitPolicy, typename Strategy>
|
||||
struct visitor : boost::static_visitor<bool>
|
||||
{
|
||||
visitor(VisitPolicy& policy) : m_policy(policy) {}
|
||||
visitor(VisitPolicy& policy, Strategy const& strategy)
|
||||
: m_policy(policy)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry>
|
||||
bool operator()(Geometry const& geometry) const
|
||||
{
|
||||
return is_valid<Geometry>::apply(geometry, m_policy);
|
||||
return is_valid<Geometry>::apply(geometry, m_policy, m_strategy);
|
||||
}
|
||||
|
||||
VisitPolicy& m_policy;
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
|
||||
template <typename VisitPolicy>
|
||||
template <typename VisitPolicy, typename Strategy>
|
||||
static inline bool
|
||||
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
|
||||
VisitPolicy& policy_visitor)
|
||||
VisitPolicy& policy_visitor,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return boost::apply_visitor(visitor<VisitPolicy>(policy_visitor),
|
||||
return boost::apply_visitor(visitor<VisitPolicy, Strategy>(policy_visitor, strategy),
|
||||
geometry);
|
||||
}
|
||||
};
|
||||
@@ -73,13 +114,38 @@ struct is_valid<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
|
||||
|
||||
// Undocumented for now
|
||||
template <typename Geometry, typename VisitPolicy>
|
||||
inline bool is_valid(Geometry const& geometry, VisitPolicy& visitor)
|
||||
template <typename Geometry, typename VisitPolicy, typename Strategy>
|
||||
inline bool is_valid(Geometry const& geometry,
|
||||
VisitPolicy& visitor,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return resolve_variant::is_valid<Geometry>::apply(geometry, visitor);
|
||||
return resolve_variant::is_valid<Geometry>::apply(geometry, visitor, strategy);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_check{is valid (in the OGC sense)}
|
||||
\ingroup is_valid
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Strategy \tparam_strategy{Is_valid}
|
||||
\param geometry \param_geometry
|
||||
\param strategy \param_strategy{is_valid}
|
||||
\return \return_check{is valid (in the OGC sense);
|
||||
furthermore, the following geometries are considered valid:
|
||||
multi-geometries with no elements,
|
||||
linear geometries containing spikes,
|
||||
areal geometries with duplicate (consecutive) points}
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/is_valid.qbk]}
|
||||
*/
|
||||
template <typename Geometry, typename Strategy>
|
||||
inline bool is_valid(Geometry const& geometry, Strategy const& strategy)
|
||||
{
|
||||
is_valid_default_policy<> visitor;
|
||||
return resolve_variant::is_valid<Geometry>::apply(geometry, visitor, strategy);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief \brief_check{is valid (in the OGC sense)}
|
||||
\ingroup is_valid
|
||||
@@ -96,11 +162,37 @@ inline bool is_valid(Geometry const& geometry, VisitPolicy& visitor)
|
||||
template <typename Geometry>
|
||||
inline bool is_valid(Geometry const& geometry)
|
||||
{
|
||||
is_valid_default_policy<> policy_visitor;
|
||||
return geometry::is_valid(geometry, policy_visitor);
|
||||
return is_valid(geometry, default_strategy());
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_check{is valid (in the OGC sense)}
|
||||
\ingroup is_valid
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Strategy \tparam_strategy{Is_valid}
|
||||
\param geometry \param_geometry
|
||||
\param failure An enumeration value indicating that the geometry is
|
||||
valid or not, and if not valid indicating the reason why
|
||||
\param strategy \param_strategy{is_valid}
|
||||
\return \return_check{is valid (in the OGC sense);
|
||||
furthermore, the following geometries are considered valid:
|
||||
multi-geometries with no elements,
|
||||
linear geometries containing spikes,
|
||||
areal geometries with duplicate (consecutive) points}
|
||||
|
||||
\qbk{distinguish,with failure value and strategy}
|
||||
\qbk{[include reference/algorithms/is_valid_with_failure.qbk]}
|
||||
*/
|
||||
template <typename Geometry, typename Strategy>
|
||||
inline bool is_valid(Geometry const& geometry, validity_failure_type& failure, Strategy const& strategy)
|
||||
{
|
||||
failure_type_policy<> visitor;
|
||||
bool result = resolve_variant::is_valid<Geometry>::apply(geometry, visitor, strategy);
|
||||
failure = visitor.failure();
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief \brief_check{is valid (in the OGC sense)}
|
||||
\ingroup is_valid
|
||||
@@ -120,13 +212,38 @@ inline bool is_valid(Geometry const& geometry)
|
||||
template <typename Geometry>
|
||||
inline bool is_valid(Geometry const& geometry, validity_failure_type& failure)
|
||||
{
|
||||
failure_type_policy<> policy_visitor;
|
||||
bool result = geometry::is_valid(geometry, policy_visitor);
|
||||
failure = policy_visitor.failure();
|
||||
return result;
|
||||
return is_valid(geometry, failure, default_strategy());
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_check{is valid (in the OGC sense)}
|
||||
\ingroup is_valid
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Strategy \tparam_strategy{Is_valid}
|
||||
\param geometry \param_geometry
|
||||
\param message A string containing a message stating if the geometry
|
||||
is valid or not, and if not valid a reason why
|
||||
\param strategy \param_strategy{is_valid}
|
||||
\return \return_check{is valid (in the OGC sense);
|
||||
furthermore, the following geometries are considered valid:
|
||||
multi-geometries with no elements,
|
||||
linear geometries containing spikes,
|
||||
areal geometries with duplicate (consecutive) points}
|
||||
|
||||
\qbk{distinguish,with message and strategy}
|
||||
\qbk{[include reference/algorithms/is_valid_with_message.qbk]}
|
||||
*/
|
||||
template <typename Geometry, typename Strategy>
|
||||
inline bool is_valid(Geometry const& geometry, std::string& message, Strategy const& strategy)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
failing_reason_policy<> visitor(stream);
|
||||
bool result = resolve_variant::is_valid<Geometry>::apply(geometry, visitor, strategy);
|
||||
message = stream.str();
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief \brief_check{is valid (in the OGC sense)}
|
||||
\ingroup is_valid
|
||||
@@ -146,11 +263,7 @@ inline bool is_valid(Geometry const& geometry, validity_failure_type& failure)
|
||||
template <typename Geometry>
|
||||
inline bool is_valid(Geometry const& geometry, std::string& message)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
failing_reason_policy<> policy_visitor(stream);
|
||||
bool result = geometry::is_valid(geometry, policy_visitor);
|
||||
message = stream.str();
|
||||
return result;
|
||||
return is_valid(geometry, message, default_strategy());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014-2015, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2014-2017, 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
|
||||
@@ -77,6 +77,14 @@ struct is_valid_linestring
|
||||
}
|
||||
return ! has_spikes<Linestring, closed>::apply(linestring, visitor);
|
||||
}
|
||||
|
||||
template <typename VisitPolicy, typename Strategy>
|
||||
static inline bool apply(Linestring const& linestring,
|
||||
VisitPolicy& visitor,
|
||||
Strategy const&)
|
||||
{
|
||||
return apply(linestring, visitor);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -142,9 +150,10 @@ private:
|
||||
};
|
||||
|
||||
public:
|
||||
template <typename VisitPolicy>
|
||||
template <typename VisitPolicy, typename Strategy>
|
||||
static inline bool apply(MultiLinestring const& multilinestring,
|
||||
VisitPolicy& visitor)
|
||||
VisitPolicy& visitor,
|
||||
Strategy const&)
|
||||
{
|
||||
if (BOOST_GEOMETRY_CONDITION(
|
||||
AllowEmptyMultiGeometries && boost::empty(multilinestring)))
|
||||
|
||||
@@ -237,23 +237,28 @@ private:
|
||||
}
|
||||
|
||||
|
||||
template <typename VisitPolicy>
|
||||
template <typename VisitPolicy, typename Strategy>
|
||||
struct per_polygon
|
||||
{
|
||||
per_polygon(VisitPolicy& policy) : m_policy(policy) {}
|
||||
per_polygon(VisitPolicy& policy, Strategy const& strategy)
|
||||
: m_policy(policy)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Polygon>
|
||||
inline bool apply(Polygon const& polygon) const
|
||||
{
|
||||
return base::apply(polygon, m_policy);
|
||||
return base::apply(polygon, m_policy, m_strategy);
|
||||
}
|
||||
|
||||
VisitPolicy& m_policy;
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
public:
|
||||
template <typename VisitPolicy>
|
||||
template <typename VisitPolicy, typename Strategy>
|
||||
static inline bool apply(MultiPolygon const& multipolygon,
|
||||
VisitPolicy& visitor)
|
||||
VisitPolicy& visitor,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef debug_validity_phase<MultiPolygon> debug_phase;
|
||||
|
||||
@@ -268,11 +273,11 @@ public:
|
||||
|
||||
if (! detail::check_iterator_range
|
||||
<
|
||||
per_polygon<VisitPolicy>,
|
||||
per_polygon<VisitPolicy, Strategy>,
|
||||
false // do not check for empty multipolygon (done above)
|
||||
>::apply(boost::begin(multipolygon),
|
||||
boost::end(multipolygon),
|
||||
per_polygon<VisitPolicy>(visitor)))
|
||||
per_polygon<VisitPolicy, Strategy>(visitor, strategy)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -285,7 +290,7 @@ public:
|
||||
|
||||
std::deque<typename has_valid_turns::turn_type> turns;
|
||||
bool has_invalid_turns =
|
||||
! has_valid_turns::apply(multipolygon, turns, visitor);
|
||||
! has_valid_turns::apply(multipolygon, turns, visitor, strategy);
|
||||
debug_print_turns(turns.begin(), turns.end());
|
||||
|
||||
if (has_invalid_turns)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014-2015, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2014-2017, 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
|
||||
@@ -36,8 +36,8 @@ namespace dispatch
|
||||
template <typename Point>
|
||||
struct is_valid<Point, point_tag>
|
||||
{
|
||||
template <typename VisitPolicy>
|
||||
static inline bool apply(Point const& point, VisitPolicy& visitor)
|
||||
template <typename VisitPolicy, typename Strategy>
|
||||
static inline bool apply(Point const& point, VisitPolicy& visitor, Strategy const&)
|
||||
{
|
||||
boost::ignore_unused(visitor);
|
||||
return ! detail::is_valid::has_invalid_coordinate
|
||||
@@ -56,9 +56,10 @@ struct is_valid<Point, point_tag>
|
||||
template <typename MultiPoint, bool AllowEmptyMultiGeometries>
|
||||
struct is_valid<MultiPoint, multi_point_tag, AllowEmptyMultiGeometries>
|
||||
{
|
||||
template <typename VisitPolicy>
|
||||
template <typename VisitPolicy, typename Strategy>
|
||||
static inline bool apply(MultiPoint const& multipoint,
|
||||
VisitPolicy& visitor)
|
||||
VisitPolicy& visitor,
|
||||
Strategy const&)
|
||||
{
|
||||
boost::ignore_unused(multipoint, visitor);
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014-2015, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2014-2017, 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
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
@@ -74,10 +75,13 @@ class is_valid_polygon
|
||||
protected:
|
||||
typedef debug_validity_phase<Polygon> debug_phase;
|
||||
|
||||
template <typename VisitPolicy>
|
||||
template <typename VisitPolicy, typename Strategy>
|
||||
struct per_ring
|
||||
{
|
||||
per_ring(VisitPolicy& policy) : m_policy(policy) {}
|
||||
per_ring(VisitPolicy& policy, Strategy const& strategy)
|
||||
: m_policy(policy)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Ring>
|
||||
inline bool apply(Ring const& ring) const
|
||||
@@ -85,30 +89,34 @@ protected:
|
||||
return detail::is_valid::is_valid_ring
|
||||
<
|
||||
Ring, false, true
|
||||
>::apply(ring, m_policy);
|
||||
>::apply(ring, m_policy, m_strategy);
|
||||
}
|
||||
|
||||
VisitPolicy& m_policy;
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
|
||||
template <typename InteriorRings, typename VisitPolicy>
|
||||
template <typename InteriorRings, typename VisitPolicy, typename Strategy>
|
||||
static bool has_valid_interior_rings(InteriorRings const& interior_rings,
|
||||
VisitPolicy& visitor)
|
||||
VisitPolicy& visitor,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return
|
||||
detail::check_iterator_range
|
||||
<
|
||||
per_ring<VisitPolicy>,
|
||||
per_ring<VisitPolicy, Strategy>,
|
||||
true // allow for empty interior ring range
|
||||
>::apply(boost::begin(interior_rings),
|
||||
boost::end(interior_rings),
|
||||
per_ring<VisitPolicy>(visitor));
|
||||
per_ring<VisitPolicy, Strategy>(visitor, strategy));
|
||||
}
|
||||
|
||||
struct has_valid_rings
|
||||
{
|
||||
template <typename VisitPolicy>
|
||||
static inline bool apply(Polygon const& polygon, VisitPolicy& visitor)
|
||||
template <typename VisitPolicy, typename Strategy>
|
||||
static inline bool apply(Polygon const& polygon,
|
||||
VisitPolicy& visitor,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename ring_type<Polygon>::type ring_type;
|
||||
|
||||
@@ -119,7 +127,7 @@ protected:
|
||||
<
|
||||
ring_type,
|
||||
false // do not check self intersections
|
||||
>::apply(exterior_ring(polygon), visitor))
|
||||
>::apply(exterior_ring(polygon), visitor, strategy))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -128,7 +136,8 @@ protected:
|
||||
debug_phase::apply(2);
|
||||
|
||||
return has_valid_interior_rings(geometry::interior_rings(polygon),
|
||||
visitor);
|
||||
visitor,
|
||||
strategy);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -344,10 +353,12 @@ protected:
|
||||
};
|
||||
|
||||
public:
|
||||
template <typename VisitPolicy>
|
||||
static inline bool apply(Polygon const& polygon, VisitPolicy& visitor)
|
||||
template <typename VisitPolicy, typename Strategy>
|
||||
static inline bool apply(Polygon const& polygon,
|
||||
VisitPolicy& visitor,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
if (! has_valid_rings::apply(polygon, visitor))
|
||||
if (! has_valid_rings::apply(polygon, visitor, strategy))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -364,7 +375,7 @@ public:
|
||||
|
||||
std::deque<typename has_valid_turns::turn_type> turns;
|
||||
bool has_invalid_turns
|
||||
= ! has_valid_turns::apply(polygon, turns, visitor);
|
||||
= ! has_valid_turns::apply(polygon, turns, visitor, strategy);
|
||||
debug_print_turns(turns.begin(), turns.end());
|
||||
|
||||
if (has_invalid_turns)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014-2015, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2014-2017, 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
|
||||
@@ -101,35 +101,33 @@ struct ring_area_predicate<ResultType, true>
|
||||
template <typename Ring, bool IsInteriorRing>
|
||||
struct is_properly_oriented
|
||||
{
|
||||
typedef typename point_type<Ring>::type point_type;
|
||||
|
||||
typedef typename strategy::area::services::default_strategy
|
||||
<
|
||||
typename cs_tag<point_type>::type,
|
||||
point_type
|
||||
>::type strategy_type;
|
||||
|
||||
typedef detail::area::ring_area
|
||||
<
|
||||
order_as_direction<geometry::point_order<Ring>::value>::value,
|
||||
geometry::closure<Ring>::value
|
||||
> ring_area_type;
|
||||
|
||||
typedef typename default_area_result<Ring>::type area_result_type;
|
||||
|
||||
template <typename VisitPolicy>
|
||||
static inline bool apply(Ring const& ring, VisitPolicy& visitor)
|
||||
template <typename VisitPolicy, typename Strategy>
|
||||
static inline bool apply(Ring const& ring, VisitPolicy& visitor,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
boost::ignore_unused(visitor);
|
||||
|
||||
typedef typename point_type<Ring>::type point_type;
|
||||
|
||||
typedef detail::area::ring_area
|
||||
<
|
||||
order_as_direction<geometry::point_order<Ring>::value>::value,
|
||||
geometry::closure<Ring>::value
|
||||
> ring_area_type;
|
||||
|
||||
typedef typename default_area_result<Ring>::type area_result_type;
|
||||
|
||||
typename ring_area_predicate
|
||||
<
|
||||
area_result_type, IsInteriorRing
|
||||
>::type predicate;
|
||||
|
||||
// Check area
|
||||
area_result_type const zero = area_result_type();
|
||||
if (predicate(ring_area_type::apply(ring, strategy_type()), zero))
|
||||
area_result_type const zero = 0;
|
||||
area_result_type const area
|
||||
= ring_area_type::apply(ring,
|
||||
strategy.template get_area_strategy<point_type>());
|
||||
if (predicate(area, zero))
|
||||
{
|
||||
return visitor.template apply<no_failure>();
|
||||
}
|
||||
@@ -150,8 +148,9 @@ template
|
||||
>
|
||||
struct is_valid_ring
|
||||
{
|
||||
template <typename VisitPolicy>
|
||||
static inline bool apply(Ring const& ring, VisitPolicy& visitor)
|
||||
template <typename VisitPolicy, typename Strategy>
|
||||
static inline bool apply(Ring const& ring, VisitPolicy& visitor,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
// return invalid if any of the following condition holds:
|
||||
// (a) the ring's point coordinates are not invalid (e.g., NaN)
|
||||
@@ -198,8 +197,8 @@ struct is_valid_ring
|
||||
&& ! has_duplicates<Ring, closure>::apply(ring, visitor)
|
||||
&& ! has_spikes<Ring, closure>::apply(ring, visitor)
|
||||
&& (! CheckSelfIntersections
|
||||
|| has_valid_self_turns<Ring>::apply(ring, visitor))
|
||||
&& is_properly_oriented<Ring, IsInteriorRing>::apply(ring, visitor);
|
||||
|| has_valid_self_turns<Ring>::apply(ring, visitor, strategy))
|
||||
&& is_properly_oriented<Ring, IsInteriorRing>::apply(ring, visitor, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014-2015, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2014-2017, 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
|
||||
@@ -44,8 +44,8 @@ namespace dispatch
|
||||
template <typename Segment>
|
||||
struct is_valid<Segment, segment_tag>
|
||||
{
|
||||
template <typename VisitPolicy>
|
||||
static inline bool apply(Segment const& segment, VisitPolicy& visitor)
|
||||
template <typename VisitPolicy, typename Strategy>
|
||||
static inline bool apply(Segment const& segment, VisitPolicy& visitor, Strategy const&)
|
||||
{
|
||||
boost::ignore_unused(visitor);
|
||||
|
||||
|
||||
@@ -272,6 +272,7 @@ struct self_get_turn_points
|
||||
\tparam Turns type of intersection container
|
||||
(e.g. vector of "intersection/turn point"'s)
|
||||
\param geometry geometry
|
||||
\param strategy strategy to be used
|
||||
\param robust_policy policy to handle robustness issues
|
||||
\param turns container which will contain intersection points
|
||||
\param interrupt_policy policy determining if process is stopped
|
||||
|
||||
@@ -375,6 +375,7 @@ struct relate<
|
||||
\param strategy \param_strategy{relate}
|
||||
\return true if the relation is compatible with the mask, false otherwise.
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/relate.qbk]}
|
||||
*/
|
||||
template <typename Geometry1, typename Geometry2, typename Mask, typename Strategy>
|
||||
|
||||
@@ -175,6 +175,7 @@ struct relation
|
||||
\param strategy \param_strategy{relation}
|
||||
\return The DE-9IM matrix expressing the relation between geometries.
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/relation.qbk]}
|
||||
*/
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
// This file was modified by Oracle on 2017.
|
||||
// Modifications copyright (c) 2017, 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,
|
||||
@@ -13,10 +14,16 @@
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DIFFERENCE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DIFFERENCE_HPP
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/overlay/intersection_insert.hpp>
|
||||
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
|
||||
#include <boost/geometry/strategies/default_strategy.hpp>
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -101,18 +108,14 @@ inline OutputIterator difference_insert(Geometry1 const& geometry1,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator out)
|
||||
{
|
||||
concepts::check<Geometry1 const>();
|
||||
concepts::check<Geometry2 const>();
|
||||
concepts::check<GeometryOut>();
|
||||
|
||||
typename strategy::relate::services::default_strategy
|
||||
typedef typename strategy::relate::services::default_strategy
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::type strategy;
|
||||
>::type strategy_type;
|
||||
|
||||
return difference_insert<GeometryOut>(geometry1, geometry2,
|
||||
robust_policy, out, strategy);
|
||||
robust_policy, out, strategy_type());
|
||||
}
|
||||
|
||||
|
||||
@@ -120,6 +123,251 @@ inline OutputIterator difference_insert(Geometry1 const& geometry1,
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
namespace resolve_strategy {
|
||||
|
||||
struct difference
|
||||
{
|
||||
template
|
||||
<
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename RobustPolicy,
|
||||
typename Collection,
|
||||
typename Strategy
|
||||
>
|
||||
static inline void apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
RobustPolicy const& robust_policy,
|
||||
Collection & output_collection,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename boost::range_value<Collection>::type geometry_out;
|
||||
|
||||
detail::difference::difference_insert<geometry_out>(
|
||||
geometry1, geometry2, robust_policy,
|
||||
range::back_inserter(output_collection),
|
||||
strategy);
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename RobustPolicy,
|
||||
typename Collection
|
||||
>
|
||||
static inline void apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
RobustPolicy const& robust_policy,
|
||||
Collection & output_collection,
|
||||
default_strategy)
|
||||
{
|
||||
typedef typename boost::range_value<Collection>::type geometry_out;
|
||||
|
||||
detail::difference::difference_insert<geometry_out>(
|
||||
geometry1, geometry2, robust_policy,
|
||||
range::back_inserter(output_collection));
|
||||
}
|
||||
};
|
||||
|
||||
} // resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_variant
|
||||
{
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct difference
|
||||
{
|
||||
template <typename Collection, typename Strategy>
|
||||
static inline void apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Collection& output_collection,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename geometry::rescale_overlay_policy_type
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::type rescale_policy_type;
|
||||
|
||||
rescale_policy_type robust_policy
|
||||
= geometry::get_rescale_policy<rescale_policy_type>(geometry1,
|
||||
geometry2);
|
||||
|
||||
resolve_strategy::difference::apply(geometry1, geometry2,
|
||||
robust_policy,
|
||||
output_collection,
|
||||
strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
|
||||
struct difference<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
|
||||
{
|
||||
template <typename Collection, typename Strategy>
|
||||
struct visitor: static_visitor<>
|
||||
{
|
||||
Geometry2 const& m_geometry2;
|
||||
Collection& m_output_collection;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Geometry2 const& geometry2,
|
||||
Collection& output_collection,
|
||||
Strategy const& strategy)
|
||||
: m_geometry2(geometry2)
|
||||
, m_output_collection(output_collection)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry1>
|
||||
void operator()(Geometry1 const& geometry1) const
|
||||
{
|
||||
difference
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(geometry1, m_geometry2, m_output_collection, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Collection, typename Strategy>
|
||||
static inline void
|
||||
apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Collection& output_collection,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
boost::apply_visitor(visitor<Collection, Strategy>(geometry2,
|
||||
output_collection,
|
||||
strategy),
|
||||
geometry1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct difference<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
{
|
||||
template <typename Collection, typename Strategy>
|
||||
struct visitor: static_visitor<>
|
||||
{
|
||||
Geometry1 const& m_geometry1;
|
||||
Collection& m_output_collection;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Geometry1 const& geometry1,
|
||||
Collection& output_collection,
|
||||
Strategy const& strategy)
|
||||
: m_geometry1(geometry1)
|
||||
, m_output_collection(output_collection)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry2>
|
||||
void operator()(Geometry2 const& geometry2) const
|
||||
{
|
||||
difference
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(m_geometry1, geometry2, m_output_collection, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Collection, typename Strategy>
|
||||
static inline void
|
||||
apply(Geometry1 const& geometry1,
|
||||
variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
|
||||
Collection& output_collection,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
boost::apply_visitor(visitor<Collection, Strategy>(geometry1,
|
||||
output_collection,
|
||||
strategy),
|
||||
geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
|
||||
struct difference<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
|
||||
{
|
||||
template <typename Collection, typename Strategy>
|
||||
struct visitor: static_visitor<>
|
||||
{
|
||||
Collection& m_output_collection;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Collection& output_collection, Strategy const& strategy)
|
||||
: m_output_collection(output_collection)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
void operator()(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2) const
|
||||
{
|
||||
difference
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(geometry1, geometry2, m_output_collection, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Collection, typename Strategy>
|
||||
static inline void
|
||||
apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
|
||||
variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
|
||||
Collection& output_collection,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
boost::apply_visitor(visitor<Collection, Strategy>(output_collection,
|
||||
strategy),
|
||||
geometry1, geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
|
||||
|
||||
/*!
|
||||
\brief_calc2{difference}
|
||||
\ingroup difference
|
||||
\details \details_calc2{difference, spatial set theoretic difference}.
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\tparam Collection \tparam_output_collection
|
||||
\tparam Strategy \tparam_strategy{Difference}
|
||||
\param geometry1 \param_geometry
|
||||
\param geometry2 \param_geometry
|
||||
\param output_collection the output collection
|
||||
\param strategy \param_strategy{difference}
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/difference.qbk]}
|
||||
*/
|
||||
template
|
||||
<
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename Collection,
|
||||
typename Strategy
|
||||
>
|
||||
inline void difference(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Collection& output_collection,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
resolve_variant::difference
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(geometry1, geometry2, output_collection, strategy);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief_calc2{difference}
|
||||
@@ -144,25 +392,11 @@ inline void difference(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Collection& output_collection)
|
||||
{
|
||||
concepts::check<Geometry1 const>();
|
||||
concepts::check<Geometry2 const>();
|
||||
|
||||
typedef typename boost::range_value<Collection>::type geometry_out;
|
||||
concepts::check<geometry_out>();
|
||||
|
||||
typedef typename geometry::rescale_overlay_policy_type
|
||||
resolve_variant::difference
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::type rescale_policy_type;
|
||||
|
||||
rescale_policy_type robust_policy
|
||||
= geometry::get_rescale_policy<rescale_policy_type>(geometry1,
|
||||
geometry2);
|
||||
|
||||
detail::difference::difference_insert<geometry_out>(
|
||||
geometry1, geometry2, robust_policy,
|
||||
range::back_inserter(output_collection));
|
||||
>::apply(geometry1, geometry2, output_collection, default_strategy());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -138,24 +138,32 @@ struct segment_segment
|
||||
|
||||
struct area_check
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return geometry::math::equals(
|
||||
geometry::area(geometry1),
|
||||
geometry::area(geometry2));
|
||||
geometry::area(geometry1,
|
||||
strategy.template get_area_strategy<Geometry1>()),
|
||||
geometry::area(geometry2,
|
||||
strategy.template get_area_strategy<Geometry2>()));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct length_check
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return geometry::math::equals(
|
||||
geometry::length(geometry1),
|
||||
geometry::length(geometry2));
|
||||
geometry::length(geometry1,
|
||||
strategy.template get_distance_strategy<Geometry1>()),
|
||||
geometry::length(geometry2,
|
||||
strategy.template get_distance_strategy<Geometry2>()));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -184,9 +192,11 @@ template <typename TrivialCheck>
|
||||
struct equals_by_collection
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const&)
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
if (! TrivialCheck::apply(geometry1, geometry2))
|
||||
if (! TrivialCheck::apply(geometry1, geometry2, strategy))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -321,6 +331,20 @@ struct equals<P1, P2, point_tag, point_tag, DimensionCount, Reverse>
|
||||
: detail::equals::point_point<0, DimensionCount>
|
||||
{};
|
||||
|
||||
template <typename MultiPoint1, typename MultiPoint2, std::size_t DimensionCount, bool Reverse>
|
||||
struct equals<MultiPoint1, MultiPoint2, multi_point_tag, multi_point_tag, DimensionCount, Reverse>
|
||||
: detail::equals::equals_by_relate<MultiPoint1, MultiPoint2>
|
||||
{};
|
||||
|
||||
template <typename MultiPoint, typename Point, std::size_t DimensionCount, bool Reverse>
|
||||
struct equals<MultiPoint, Point, multi_point_tag, point_tag, DimensionCount, Reverse>
|
||||
: detail::equals::equals_by_relate<MultiPoint, Point>
|
||||
{};
|
||||
|
||||
template <typename MultiPoint, typename Point, std::size_t DimensionCount, bool Reverse>
|
||||
struct equals<Point, MultiPoint, point_tag, multi_point_tag, DimensionCount, Reverse>
|
||||
: detail::equals::equals_by_relate<Point, MultiPoint>
|
||||
{};
|
||||
|
||||
template <typename Box1, typename Box2, std::size_t DimensionCount, bool Reverse>
|
||||
struct equals<Box1, Box2, box_tag, box_tag, DimensionCount, Reverse>
|
||||
@@ -601,8 +625,8 @@ struct equals<
|
||||
\param strategy \param_strategy{equals}
|
||||
\return \return_check2{are spatially equal}
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/equals.qbk]}
|
||||
|
||||
*/
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
inline bool equals(Geometry1 const& geometry1,
|
||||
@@ -631,7 +655,6 @@ inline bool equals(Geometry1 const& geometry1,
|
||||
\return \return_check2{are spatially equal}
|
||||
|
||||
\qbk{[include reference/algorithms/equals.qbk]}
|
||||
|
||||
*/
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
inline bool equals(Geometry1 const& geometry1, Geometry2 const& geometry2)
|
||||
|
||||
@@ -97,7 +97,7 @@ inline bool intersects(Geometry const& geometry)
|
||||
\param strategy \param_strategy{intersects}
|
||||
\return \return_check2{intersect each other}
|
||||
|
||||
\qbk{distinguish,two geometries}
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/intersects.qbk]}
|
||||
*/
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
|
||||
@@ -180,6 +180,7 @@ struct overlaps<Box1, Box2, box_tag, box_tag>
|
||||
\param strategy \param_strategy{overlaps}
|
||||
\return \return_check2{overlap}
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/overlaps.qbk]}
|
||||
*/
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
|
||||
@@ -15,13 +15,21 @@
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_SYM_DIFFERENCE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_SYM_DIFFERENCE_HPP
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/intersection.hpp>
|
||||
#include <boost/geometry/algorithms/union.hpp>
|
||||
#include <boost/geometry/geometries/multi_polygon.hpp>
|
||||
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
|
||||
#include <boost/geometry/strategies/default_strategy.hpp>
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -289,6 +297,253 @@ inline OutputIterator sym_difference_insert(Geometry1 const& geometry1,
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
namespace resolve_strategy {
|
||||
|
||||
struct sym_difference
|
||||
{
|
||||
template
|
||||
<
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename RobustPolicy,
|
||||
typename Collection,
|
||||
typename Strategy
|
||||
>
|
||||
static inline void apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
RobustPolicy const& robust_policy,
|
||||
Collection & output_collection,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename boost::range_value<Collection>::type geometry_out;
|
||||
|
||||
detail::sym_difference::sym_difference_insert<geometry_out>(
|
||||
geometry1, geometry2, robust_policy,
|
||||
range::back_inserter(output_collection),
|
||||
strategy);
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename RobustPolicy,
|
||||
typename Collection
|
||||
>
|
||||
static inline void apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
RobustPolicy const& robust_policy,
|
||||
Collection & output_collection,
|
||||
default_strategy)
|
||||
{
|
||||
typedef typename boost::range_value<Collection>::type geometry_out;
|
||||
|
||||
detail::sym_difference::sym_difference_insert<geometry_out>(
|
||||
geometry1, geometry2, robust_policy,
|
||||
range::back_inserter(output_collection));
|
||||
}
|
||||
};
|
||||
|
||||
} // resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_variant
|
||||
{
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct sym_difference
|
||||
{
|
||||
template <typename Collection, typename Strategy>
|
||||
static inline void apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Collection& output_collection,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename geometry::rescale_overlay_policy_type
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::type rescale_policy_type;
|
||||
|
||||
rescale_policy_type robust_policy
|
||||
= geometry::get_rescale_policy<rescale_policy_type>(geometry1,
|
||||
geometry2);
|
||||
|
||||
resolve_strategy::sym_difference::apply(geometry1, geometry2,
|
||||
robust_policy,
|
||||
output_collection,
|
||||
strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
|
||||
struct sym_difference<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
|
||||
{
|
||||
template <typename Collection, typename Strategy>
|
||||
struct visitor: static_visitor<>
|
||||
{
|
||||
Geometry2 const& m_geometry2;
|
||||
Collection& m_output_collection;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Geometry2 const& geometry2,
|
||||
Collection& output_collection,
|
||||
Strategy const& strategy)
|
||||
: m_geometry2(geometry2)
|
||||
, m_output_collection(output_collection)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry1>
|
||||
void operator()(Geometry1 const& geometry1) const
|
||||
{
|
||||
sym_difference
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(geometry1, m_geometry2, m_output_collection, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Collection, typename Strategy>
|
||||
static inline void
|
||||
apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Collection& output_collection,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
boost::apply_visitor(visitor<Collection, Strategy>(geometry2,
|
||||
output_collection,
|
||||
strategy),
|
||||
geometry1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct sym_difference<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
{
|
||||
template <typename Collection, typename Strategy>
|
||||
struct visitor: static_visitor<>
|
||||
{
|
||||
Geometry1 const& m_geometry1;
|
||||
Collection& m_output_collection;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Geometry1 const& geometry1,
|
||||
Collection& output_collection,
|
||||
Strategy const& strategy)
|
||||
: m_geometry1(geometry1)
|
||||
, m_output_collection(output_collection)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry2>
|
||||
void operator()(Geometry2 const& geometry2) const
|
||||
{
|
||||
sym_difference
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(m_geometry1, geometry2, m_output_collection, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Collection, typename Strategy>
|
||||
static inline void
|
||||
apply(Geometry1 const& geometry1,
|
||||
variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
|
||||
Collection& output_collection,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
boost::apply_visitor(visitor<Collection, Strategy>(geometry1,
|
||||
output_collection,
|
||||
strategy),
|
||||
geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
|
||||
struct sym_difference<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
|
||||
{
|
||||
template <typename Collection, typename Strategy>
|
||||
struct visitor: static_visitor<>
|
||||
{
|
||||
Collection& m_output_collection;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Collection& output_collection, Strategy const& strategy)
|
||||
: m_output_collection(output_collection)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
void operator()(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2) const
|
||||
{
|
||||
sym_difference
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(geometry1, geometry2, m_output_collection, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Collection, typename Strategy>
|
||||
static inline void
|
||||
apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
|
||||
variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
|
||||
Collection& output_collection,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
boost::apply_visitor(visitor<Collection, Strategy>(output_collection,
|
||||
strategy),
|
||||
geometry1, geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_calc2{symmetric difference}
|
||||
\ingroup sym_difference
|
||||
\details \details_calc2{symmetric difference, spatial set theoretic symmetric difference (XOR)}.
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\tparam Collection output collection, either a multi-geometry,
|
||||
or a std::vector<Geometry> / std::deque<Geometry> etc
|
||||
\tparam Strategy \tparam_strategy{Sym_difference}
|
||||
\param geometry1 \param_geometry
|
||||
\param geometry2 \param_geometry
|
||||
\param output_collection the output collection
|
||||
\param strategy \param_strategy{sym_difference}
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/sym_difference.qbk]}
|
||||
*/
|
||||
template
|
||||
<
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename Collection,
|
||||
typename Strategy
|
||||
>
|
||||
inline void sym_difference(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Collection& output_collection,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
resolve_variant::sym_difference
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(geometry1, geometry2, output_collection, strategy);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_calc2{symmetric difference}
|
||||
\ingroup sym_difference
|
||||
@@ -310,26 +565,14 @@ template
|
||||
typename Collection
|
||||
>
|
||||
inline void sym_difference(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2, Collection& output_collection)
|
||||
Geometry2 const& geometry2,
|
||||
Collection& output_collection)
|
||||
{
|
||||
concepts::check<Geometry1 const>();
|
||||
concepts::check<Geometry2 const>();
|
||||
|
||||
typedef typename boost::range_value<Collection>::type geometry_out;
|
||||
concepts::check<geometry_out>();
|
||||
|
||||
typedef typename geometry::rescale_overlay_policy_type
|
||||
resolve_variant::sym_difference
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::type rescale_policy_type;
|
||||
|
||||
rescale_policy_type robust_policy
|
||||
= geometry::get_rescale_policy<rescale_policy_type>(geometry1, geometry2);
|
||||
|
||||
detail::sym_difference::sym_difference_insert<geometry_out>(
|
||||
geometry1, geometry2, robust_policy,
|
||||
range::back_inserter(output_collection));
|
||||
>::apply(geometry1, geometry2, output_collection, default_strategy());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -687,7 +687,7 @@ inline bool touches(Geometry1 const& geometry1, Geometry2 const& geometry2)
|
||||
\param strategy \param_strategy{touches}
|
||||
\return \return_check2{touch each other}
|
||||
|
||||
\qbk{distinguish,two geometries}
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/touches.qbk]}
|
||||
*/
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/overlay.hpp>
|
||||
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
|
||||
#include <boost/geometry/strategies/default_strategy.hpp>
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/overlay/linear_linear.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp>
|
||||
@@ -234,6 +236,266 @@ inline OutputIterator union_insert(Geometry1 const& geometry1,
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
namespace resolve_strategy {
|
||||
|
||||
struct union_
|
||||
{
|
||||
template
|
||||
<
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename RobustPolicy,
|
||||
typename Collection,
|
||||
typename Strategy
|
||||
>
|
||||
static inline void apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
RobustPolicy const& robust_policy,
|
||||
Collection & output_collection,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename boost::range_value<Collection>::type geometry_out;
|
||||
|
||||
dispatch::union_insert
|
||||
<
|
||||
Geometry1, Geometry2, geometry_out
|
||||
>::apply(geometry1, geometry2, robust_policy,
|
||||
range::back_inserter(output_collection),
|
||||
strategy);
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename RobustPolicy,
|
||||
typename Collection
|
||||
>
|
||||
static inline void apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
RobustPolicy const& robust_policy,
|
||||
Collection & output_collection,
|
||||
default_strategy)
|
||||
{
|
||||
typedef typename boost::range_value<Collection>::type geometry_out;
|
||||
|
||||
typedef typename strategy::intersection::services::default_strategy
|
||||
<
|
||||
typename cs_tag<geometry_out>::type
|
||||
>::type strategy_type;
|
||||
|
||||
dispatch::union_insert
|
||||
<
|
||||
Geometry1, Geometry2, geometry_out
|
||||
>::apply(geometry1, geometry2, robust_policy,
|
||||
range::back_inserter(output_collection),
|
||||
strategy_type());
|
||||
}
|
||||
};
|
||||
|
||||
} // resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_variant
|
||||
{
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct union_
|
||||
{
|
||||
template <typename Collection, typename Strategy>
|
||||
static inline void apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Collection& output_collection,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
concepts::check<Geometry1 const>();
|
||||
concepts::check<Geometry2 const>();
|
||||
concepts::check<typename boost::range_value<Collection>::type>();
|
||||
|
||||
typedef typename geometry::rescale_overlay_policy_type
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::type rescale_policy_type;
|
||||
|
||||
rescale_policy_type robust_policy
|
||||
= geometry::get_rescale_policy<rescale_policy_type>(geometry1,
|
||||
geometry2);
|
||||
|
||||
resolve_strategy::union_::apply(geometry1, geometry2,
|
||||
robust_policy,
|
||||
output_collection,
|
||||
strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
|
||||
struct union_<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
|
||||
{
|
||||
template <typename Collection, typename Strategy>
|
||||
struct visitor: static_visitor<>
|
||||
{
|
||||
Geometry2 const& m_geometry2;
|
||||
Collection& m_output_collection;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Geometry2 const& geometry2,
|
||||
Collection& output_collection,
|
||||
Strategy const& strategy)
|
||||
: m_geometry2(geometry2)
|
||||
, m_output_collection(output_collection)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry1>
|
||||
void operator()(Geometry1 const& geometry1) const
|
||||
{
|
||||
union_
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(geometry1, m_geometry2, m_output_collection, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Collection, typename Strategy>
|
||||
static inline void
|
||||
apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Collection& output_collection,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
boost::apply_visitor(visitor<Collection, Strategy>(geometry2,
|
||||
output_collection,
|
||||
strategy),
|
||||
geometry1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct union_<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
{
|
||||
template <typename Collection, typename Strategy>
|
||||
struct visitor: static_visitor<>
|
||||
{
|
||||
Geometry1 const& m_geometry1;
|
||||
Collection& m_output_collection;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Geometry1 const& geometry1,
|
||||
Collection& output_collection,
|
||||
Strategy const& strategy)
|
||||
: m_geometry1(geometry1)
|
||||
, m_output_collection(output_collection)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry2>
|
||||
void operator()(Geometry2 const& geometry2) const
|
||||
{
|
||||
union_
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(m_geometry1, geometry2, m_output_collection, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Collection, typename Strategy>
|
||||
static inline void
|
||||
apply(Geometry1 const& geometry1,
|
||||
variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
|
||||
Collection& output_collection,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
boost::apply_visitor(visitor<Collection, Strategy>(geometry1,
|
||||
output_collection,
|
||||
strategy),
|
||||
geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
|
||||
struct union_<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
|
||||
{
|
||||
template <typename Collection, typename Strategy>
|
||||
struct visitor: static_visitor<>
|
||||
{
|
||||
Collection& m_output_collection;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Collection& output_collection, Strategy const& strategy)
|
||||
: m_output_collection(output_collection)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
void operator()(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2) const
|
||||
{
|
||||
union_
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(geometry1, geometry2, m_output_collection, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Collection, typename Strategy>
|
||||
static inline void
|
||||
apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
|
||||
variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
|
||||
Collection& output_collection,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
boost::apply_visitor(visitor<Collection, Strategy>(output_collection,
|
||||
strategy),
|
||||
geometry1, geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
|
||||
|
||||
/*!
|
||||
\brief Combines two geometries which each other
|
||||
\ingroup union
|
||||
\details \details_calc2{union, spatial set theoretic union}.
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\tparam Collection output collection, either a multi-geometry,
|
||||
or a std::vector<Geometry> / std::deque<Geometry> etc
|
||||
\tparam Strategy \tparam_strategy{Union_}
|
||||
\param geometry1 \param_geometry
|
||||
\param geometry2 \param_geometry
|
||||
\param output_collection the output collection
|
||||
\param strategy \param_strategy{union_}
|
||||
\note Called union_ because union is a reserved word.
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/union.qbk]}
|
||||
*/
|
||||
template
|
||||
<
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename Collection,
|
||||
typename Strategy
|
||||
>
|
||||
inline void union_(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Collection& output_collection,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
resolve_variant::union_
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(geometry1, geometry2, output_collection, strategy);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
@@ -258,17 +520,14 @@ template
|
||||
typename Collection
|
||||
>
|
||||
inline void union_(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Collection& output_collection)
|
||||
Geometry2 const& geometry2,
|
||||
Collection& output_collection)
|
||||
{
|
||||
concepts::check<Geometry1 const>();
|
||||
concepts::check<Geometry2 const>();
|
||||
|
||||
typedef typename boost::range_value<Collection>::type geometry_out;
|
||||
concepts::check<geometry_out>();
|
||||
|
||||
detail::union_::union_insert<geometry_out>(geometry1, geometry2,
|
||||
range::back_inserter(output_collection));
|
||||
resolve_variant::union_
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(geometry1, geometry2, output_collection, default_strategy());
|
||||
}
|
||||
|
||||
|
||||
|
||||
71
include/boost/geometry/arithmetic/normalize.hpp
Normal file
71
include/boost/geometry/arithmetic/normalize.hpp
Normal file
@@ -0,0 +1,71 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2016, 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)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ARITHMETIC_NORMALIZE_HPP
|
||||
#define BOOST_GEOMETRY_ARITHMETIC_NORMALIZE_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
|
||||
#include <boost/geometry/arithmetic/arithmetic.hpp>
|
||||
#include <boost/geometry/arithmetic/dot_product.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename Point>
|
||||
inline typename coordinate_type<Point>::type vec_length_sqr(Point const& pt)
|
||||
{
|
||||
return dot_product(pt, pt);
|
||||
}
|
||||
|
||||
template <typename Point>
|
||||
inline typename coordinate_type<Point>::type vec_length(Point const& pt)
|
||||
{
|
||||
// NOTE: hypot() could be used instead of sqrt()
|
||||
return math::sqrt(dot_product(pt, pt));
|
||||
}
|
||||
|
||||
template <typename Point>
|
||||
inline bool vec_normalize(Point & pt, typename coordinate_type<Point>::type & len)
|
||||
{
|
||||
typedef typename coordinate_type<Point>::type coord_t;
|
||||
|
||||
coord_t const c0 = 0;
|
||||
len = vec_length(pt);
|
||||
|
||||
if (math::equals(len, c0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
divide_value(pt, len);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Point>
|
||||
inline bool vec_normalize(Point & pt)
|
||||
{
|
||||
typedef typename coordinate_type<Point>::type coord_t;
|
||||
coord_t len;
|
||||
return vec_normalize(pt, len);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ARITHMETIC_NORMALIZE_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.
|
||||
// Modifications copyright (c) 2014 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2014, 2016.
|
||||
// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@@ -51,7 +51,7 @@ public:
|
||||
|
||||
spheroid()
|
||||
: m_a(RadiusType(6378137.0))
|
||||
, m_b(RadiusType(6356752.314245))
|
||||
, m_b(RadiusType(6356752.3142451793))
|
||||
{}
|
||||
|
||||
template <std::size_t I>
|
||||
|
||||
@@ -68,12 +68,10 @@ struct geometry_type_ogc
|
||||
{
|
||||
point = 1,
|
||||
linestring = 2,
|
||||
polygon = 3
|
||||
|
||||
// TODO: Not implemented
|
||||
//multipoint = 4,
|
||||
//multilinestring = 5,
|
||||
//multipolygon = 6,
|
||||
polygon = 3,
|
||||
multipoint = 4,
|
||||
multilinestring = 5,
|
||||
multipolygon = 6,
|
||||
//collection = 7
|
||||
};
|
||||
};
|
||||
@@ -169,6 +167,21 @@ struct geometry_type<Geometry, CheckPolicy, polygon_tag>
|
||||
: geometry_type_impl<Geometry, geometry_type_ogc::polygon>
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename CheckPolicy>
|
||||
struct geometry_type<Geometry, CheckPolicy, multi_point_tag>
|
||||
: geometry_type_impl<Geometry, geometry_type_ogc::multipoint>
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename CheckPolicy>
|
||||
struct geometry_type<Geometry, CheckPolicy, multi_linestring_tag>
|
||||
: geometry_type_impl<Geometry, geometry_type_ogc::multilinestring>
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename CheckPolicy>
|
||||
struct geometry_type<Geometry, CheckPolicy, multi_polygon_tag>
|
||||
: geometry_type_impl<Geometry, geometry_type_ogc::multipolygon>
|
||||
{};
|
||||
|
||||
}} // namespace detail::wkb
|
||||
#endif // DOXYGEN_NO_IMPL
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
|
||||
#include <boost/geometry/core/exception.hpp>
|
||||
|
||||
#include <boost/concept_check.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/type_traits/is_integral.hpp>
|
||||
@@ -33,6 +35,23 @@
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
/*!
|
||||
\brief Read WKB Exception
|
||||
\ingroup core
|
||||
\details The read_wkb_exception is thrown when there is an error in wkb parsing
|
||||
*/
|
||||
class read_wkb_exception : public geometry::exception
|
||||
{
|
||||
public:
|
||||
|
||||
inline read_wkb_exception() {}
|
||||
|
||||
virtual char const* what() const throw()
|
||||
{
|
||||
return "Boost.Geometry Read WKB exception";
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace wkb
|
||||
{
|
||||
@@ -191,9 +210,12 @@ struct point_container_parser
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
typedef typename std::iterator_traits<Iterator>::difference_type size_type;
|
||||
BOOST_GEOMETRY_ASSERT(num_points <= boost::uint32_t( (std::numeric_limits<size_type>::max)() ) );
|
||||
if(num_points > (std::numeric_limits<boost::uint32_t>::max)() )
|
||||
{
|
||||
throw boost::geometry::read_wkb_exception();
|
||||
}
|
||||
|
||||
size_type const container_size = static_cast<size_type>(num_points);
|
||||
size_type const point_size = dimension<point_type>::value * sizeof(double);
|
||||
@@ -237,7 +259,11 @@ struct linestring_parser
|
||||
return false;
|
||||
}
|
||||
|
||||
BOOST_GEOMETRY_ASSERT(it != end);
|
||||
if(it == end)
|
||||
{
|
||||
throw boost::geometry::read_wkb_exception();
|
||||
}
|
||||
|
||||
return point_container_parser<L>::parse(it, end, linestring, order);
|
||||
}
|
||||
};
|
||||
@@ -259,15 +285,15 @@ struct polygon_parser
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
typedef typename ring_type<Polygon>::type ring_type;
|
||||
|
||||
typedef typename boost::geometry::ring_return_type<Polygon>::type ring_type;
|
||||
|
||||
std::size_t rings_parsed = 0;
|
||||
while (rings_parsed < num_rings && it != end)
|
||||
{
|
||||
if (0 == rings_parsed)
|
||||
{
|
||||
ring_type& ring0 = exterior_ring(polygon);
|
||||
ring_type ring0 = exterior_ring(polygon);
|
||||
if (!point_container_parser<ring_type>::parse(it, end, ring0, order))
|
||||
{
|
||||
return false;
|
||||
@@ -275,19 +301,16 @@ struct polygon_parser
|
||||
}
|
||||
else
|
||||
{
|
||||
interior_rings(polygon).resize(rings_parsed);
|
||||
ring_type& ringN = interior_rings(polygon).back();
|
||||
boost::geometry::range::resize(interior_rings(polygon), rings_parsed);
|
||||
ring_type ringN = boost::geometry::range::back(interior_rings(polygon));
|
||||
|
||||
if (!point_container_parser<ring_type>::parse(it, end, ringN, order))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
++rings_parsed;
|
||||
}
|
||||
|
||||
if (num_rings != rings_parsed)
|
||||
{
|
||||
return false;
|
||||
++rings_parsed;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -27,38 +27,38 @@ namespace dispatch
|
||||
template <typename Tag, typename G>
|
||||
struct read_wkb {};
|
||||
|
||||
template <typename G>
|
||||
struct read_wkb<point_tag, G>
|
||||
template <typename Geometry>
|
||||
struct read_wkb<point_tag, Geometry>
|
||||
{
|
||||
template <typename Iterator>
|
||||
static inline bool parse(Iterator& it, Iterator end, G& geometry,
|
||||
static inline bool parse(Iterator& it, Iterator end, Geometry& geometry,
|
||||
detail::wkb::byte_order_type::enum_t order)
|
||||
{
|
||||
return detail::wkb::point_parser<G>::parse(it, end, geometry, order);
|
||||
return detail::wkb::point_parser<Geometry>::parse(it, end, geometry, order);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename G>
|
||||
struct read_wkb<linestring_tag, G>
|
||||
template <typename Geometry>
|
||||
struct read_wkb<linestring_tag, Geometry>
|
||||
{
|
||||
template <typename Iterator>
|
||||
static inline bool parse(Iterator& it, Iterator end, G& geometry,
|
||||
static inline bool parse(Iterator& it, Iterator end, Geometry& geometry,
|
||||
detail::wkb::byte_order_type::enum_t order)
|
||||
{
|
||||
geometry::clear(geometry);
|
||||
return detail::wkb::linestring_parser<G>::parse(it, end, geometry, order);
|
||||
return detail::wkb::linestring_parser<Geometry>::parse(it, end, geometry, order);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename G>
|
||||
struct read_wkb<polygon_tag, G>
|
||||
template <typename Geometry>
|
||||
struct read_wkb<polygon_tag, Geometry>
|
||||
{
|
||||
template <typename Iterator>
|
||||
static inline bool parse(Iterator& it, Iterator end, G& geometry,
|
||||
static inline bool parse(Iterator& it, Iterator end, Geometry& geometry,
|
||||
detail::wkb::byte_order_type::enum_t order)
|
||||
{
|
||||
geometry::clear(geometry);
|
||||
return detail::wkb::polygon_parser<G>::parse(it, end, geometry, order);
|
||||
return detail::wkb::polygon_parser<Geometry>::parse(it, end, geometry, order);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -66,8 +66,8 @@ struct read_wkb<polygon_tag, G>
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
template <typename Iterator, typename G>
|
||||
inline bool read_wkb(Iterator begin, Iterator end, G& geometry)
|
||||
template <typename Iterator, typename Geometry>
|
||||
inline bool read_wkb(Iterator begin, Iterator end, Geometry& geometry)
|
||||
{
|
||||
// Stream of bytes can only be parsed using random access iterator.
|
||||
BOOST_STATIC_ASSERT((
|
||||
@@ -82,16 +82,16 @@ inline bool read_wkb(Iterator begin, Iterator end, G& geometry)
|
||||
{
|
||||
return dispatch::read_wkb
|
||||
<
|
||||
typename tag<G>::type,
|
||||
G
|
||||
typename tag<Geometry>::type,
|
||||
Geometry
|
||||
>::parse(begin, end, geometry, byte_order);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename ByteType, typename G>
|
||||
inline bool read_wkb(ByteType const* bytes, std::size_t length, G& geometry)
|
||||
template <typename ByteType, typename Geometry>
|
||||
inline bool read_wkb(ByteType const* bytes, std::size_t length, Geometry& geometry)
|
||||
{
|
||||
BOOST_STATIC_ASSERT((boost::is_integral<ByteType>::value));
|
||||
BOOST_STATIC_ASSERT((sizeof(boost::uint8_t) == sizeof(ByteType)));
|
||||
|
||||
@@ -0,0 +1,248 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_MULTI_IO_WKB_DETAIL_PARSER_HPP
|
||||
#define BOOST_GEOMETRY_MULTI_IO_WKB_DETAIL_PARSER_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
|
||||
#include <boost/geometry/core/exception.hpp>
|
||||
|
||||
#include <boost/geometry/extensions/gis/io/wkb/detail/endian.hpp>
|
||||
#include <boost/geometry/extensions/gis/io/wkb/detail/parser.hpp>
|
||||
#include <boost/geometry/extensions/gis/io/wkb/detail/ogc.hpp>
|
||||
|
||||
|
||||
#include <boost/geometry/multi/core/point_type.hpp>
|
||||
#include <boost/geometry/multi/core/ring_type.hpp>
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
|
||||
#include <boost/geometry/multi/core/interior_rings.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace wkb
|
||||
{
|
||||
|
||||
template <typename MultiPoint>
|
||||
struct multipoint_parser
|
||||
{
|
||||
template <typename Iterator>
|
||||
static bool parse(Iterator& it, Iterator end, MultiPoint& multipoint, byte_order_type::enum_t order)
|
||||
{
|
||||
if (!geometry_type_parser<MultiPoint>::parse(it, end, order))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
boost::uint32_t num_points(0);
|
||||
if (!value_parser<boost::uint32_t>::parse(it, end, num_points, order))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that the number of double values in the stream is equal
|
||||
// or greater than the number of expected values in the multipoint
|
||||
|
||||
typedef typename std::iterator_traits<Iterator>::difference_type size_type;
|
||||
|
||||
typedef typename point_type<MultiPoint>::type point_type;
|
||||
|
||||
size_type const container_byte_size = dimension<point_type>::value * num_points * sizeof(double)
|
||||
+ num_points * sizeof(boost::uint8_t)
|
||||
+ num_points * sizeof(boost::uint32_t);
|
||||
|
||||
size_type const stream_byte_size = std::distance(it,end);
|
||||
|
||||
if(stream_byte_size < container_byte_size)
|
||||
{
|
||||
throw boost::geometry::read_wkb_exception();
|
||||
}
|
||||
|
||||
point_type point_buffer;
|
||||
std::back_insert_iterator<MultiPoint> output(std::back_inserter(multipoint));
|
||||
|
||||
typedef typename std::iterator_traits<Iterator>::difference_type size_type;
|
||||
if(num_points > (std::numeric_limits<boost::uint32_t>::max)() )
|
||||
{
|
||||
throw boost::geometry::read_wkb_exception();
|
||||
}
|
||||
|
||||
size_type points_parsed = 0;
|
||||
while (points_parsed < num_points && it != end)
|
||||
{
|
||||
detail::wkb::byte_order_type::enum_t point_byte_order;
|
||||
if (!detail::wkb::byte_order_parser::parse(it, end, point_byte_order))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!geometry_type_parser<point_type>::parse(it, end, point_byte_order))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
parsing_assigner<point_type, 0, dimension<point_type>::value>::run(it, end, point_buffer, point_byte_order);
|
||||
|
||||
output = point_buffer;
|
||||
|
||||
++output;
|
||||
++points_parsed;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename MultiLinestring>
|
||||
struct multilinestring_parser
|
||||
{
|
||||
template <typename Iterator>
|
||||
static bool parse(Iterator& it, Iterator end, MultiLinestring& multilinestring, byte_order_type::enum_t order)
|
||||
{
|
||||
typedef typename MultiLinestring::value_type linestring_type;
|
||||
typedef typename point_type<MultiLinestring>::type point_type;
|
||||
|
||||
if (!geometry_type_parser<MultiLinestring>::parse(it, end, order))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
boost::uint32_t num_linestrings(0);
|
||||
if (!value_parser<boost::uint32_t>::parse(it, end, num_linestrings, order))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::back_insert_iterator<MultiLinestring> output(std::back_inserter(multilinestring));
|
||||
|
||||
typedef typename std::iterator_traits<Iterator>::difference_type size_type;
|
||||
if(num_linestrings > (std::numeric_limits<boost::uint32_t>::max)() )
|
||||
{
|
||||
throw boost::geometry::read_wkb_exception();
|
||||
}
|
||||
|
||||
size_type linestrings_parsed = 0;
|
||||
while (linestrings_parsed < num_linestrings && it != end)
|
||||
{
|
||||
linestring_type linestring_buffer;
|
||||
|
||||
detail::wkb::byte_order_type::enum_t linestring_byte_order;
|
||||
if (!detail::wkb::byte_order_parser::parse(it, end, linestring_byte_order))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!geometry_type_parser<linestring_type>::parse(it, end, order))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!point_container_parser<linestring_type>::parse(it, end, linestring_buffer, linestring_byte_order))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
output = linestring_buffer;
|
||||
|
||||
++output;
|
||||
++linestrings_parsed;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename MultiPolygon>
|
||||
struct multipolygon_parser
|
||||
{
|
||||
template <typename Iterator>
|
||||
static bool parse(Iterator& it, Iterator end, MultiPolygon& multipolygon, byte_order_type::enum_t order)
|
||||
{
|
||||
typedef typename boost::range_value<MultiPolygon>::type polygon_type;
|
||||
|
||||
if (!geometry_type_parser<MultiPolygon>::parse(it, end, order))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
boost::uint32_t num_polygons(0);
|
||||
if (!value_parser<boost::uint32_t>::parse(it, end, num_polygons, order))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::back_insert_iterator<MultiPolygon> output(std::back_inserter(multipolygon));
|
||||
|
||||
std::size_t polygons_parsed = 0;
|
||||
while(polygons_parsed < num_polygons && it != end)
|
||||
{
|
||||
polygon_type polygon_buffer;
|
||||
|
||||
detail::wkb::byte_order_type::enum_t polygon_byte_order;
|
||||
if (!detail::wkb::byte_order_parser::parse(it, end, polygon_byte_order))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!geometry_type_parser<polygon_type>::parse(it, end, order))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
boost::uint32_t num_rings(0);
|
||||
if (!value_parser<boost::uint32_t>::parse(it, end, num_rings, polygon_byte_order))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::size_t rings_parsed = 0;
|
||||
|
||||
while (rings_parsed < num_rings && it != end)
|
||||
{
|
||||
typedef typename boost::geometry::ring_return_type<polygon_type>::type ring_type;
|
||||
|
||||
if (0 == rings_parsed)
|
||||
{
|
||||
ring_type ring0 = exterior_ring(polygon_buffer);
|
||||
|
||||
if (!point_container_parser<ring_type>::parse(it, end, ring0, polygon_byte_order))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
boost::geometry::range::resize(interior_rings(polygon_buffer), rings_parsed);
|
||||
ring_type ringN = boost::geometry::range::back(interior_rings(polygon_buffer));
|
||||
|
||||
if (!point_container_parser<ring_type>::parse(it, end, ringN, polygon_byte_order))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
++rings_parsed;
|
||||
}
|
||||
|
||||
output = polygon_buffer;
|
||||
++output;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail::wkb
|
||||
#endif // DOXYGEN_NO_IMPL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_MULTI_IO_WKB_DETAIL_PARSER_HPP
|
||||
@@ -0,0 +1,145 @@
|
||||
// Boost.Geometry
|
||||
//
|
||||
// Copyright (c) 2015 Mats Taraldsvik.
|
||||
//
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_MULTI_IO_WKB_DETAIL_WRITER_HPP
|
||||
#define BOOST_GEOMETRY_MULTI_IO_WKB_DETAIL_WRITER_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
|
||||
#include <boost/concept_check.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_traits/is_integral.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
#include <boost/geometry/extensions/gis/io/wkb/detail/writer.hpp>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
#include <boost/geometry/core/interior_rings.hpp>
|
||||
#include <boost/geometry/extensions/gis/io/wkb/detail/endian.hpp>
|
||||
#include <boost/geometry/extensions/gis/io/wkb/detail/ogc.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace wkb
|
||||
{
|
||||
template <typename MultiPoint>
|
||||
struct multipoint_writer
|
||||
{
|
||||
template <typename OutputIterator>
|
||||
static bool write(MultiPoint const& multipoint,
|
||||
OutputIterator& iter,
|
||||
byte_order_type::enum_t byte_order)
|
||||
{
|
||||
// write endian type
|
||||
value_writer<uint8_t>::write(byte_order, iter, byte_order);
|
||||
|
||||
// write geometry type
|
||||
uint32_t type = geometry_type<MultiPoint>::get();
|
||||
value_writer<uint32_t>::write(type, iter, byte_order);
|
||||
|
||||
// write num points
|
||||
uint32_t num_points = boost::size(multipoint);
|
||||
value_writer<uint32_t>::write(num_points, iter, byte_order);
|
||||
|
||||
typedef typename point_type<MultiPoint>::type point_type;
|
||||
|
||||
for(typename boost::range_iterator<MultiPoint const>::type
|
||||
point_iter = boost::begin(multipoint);
|
||||
point_iter != boost::end(multipoint);
|
||||
++point_iter)
|
||||
{
|
||||
detail::wkb::point_writer<point_type>::write(*point_iter, iter, byte_order);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename MultiLinestring>
|
||||
struct multilinestring_writer
|
||||
{
|
||||
template <typename OutputIterator>
|
||||
static bool write(MultiLinestring const& multilinestring,
|
||||
OutputIterator& iter,
|
||||
byte_order_type::enum_t byte_order)
|
||||
{
|
||||
// write endian type
|
||||
value_writer<uint8_t>::write(byte_order, iter, byte_order);
|
||||
|
||||
// write geometry type
|
||||
uint32_t type = geometry_type<MultiLinestring>::get();
|
||||
value_writer<uint32_t>::write(type, iter, byte_order);
|
||||
|
||||
// write num linestrings
|
||||
uint32_t num_linestrings = boost::size(multilinestring);
|
||||
value_writer<uint32_t>::write(num_linestrings, iter, byte_order);
|
||||
|
||||
typedef typename boost::range_value<MultiLinestring>::type linestring_type;
|
||||
|
||||
for(typename boost::range_iterator<MultiLinestring const>::type
|
||||
linestring_iter = boost::begin(multilinestring);
|
||||
linestring_iter != boost::end(multilinestring);
|
||||
++linestring_iter)
|
||||
{
|
||||
detail::wkb::linestring_writer<linestring_type>::write(*linestring_iter, iter, byte_order);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename MultiPolygon>
|
||||
struct multipolygon_writer
|
||||
{
|
||||
template <typename OutputIterator>
|
||||
static bool write(MultiPolygon const& multipolygon,
|
||||
OutputIterator& iter,
|
||||
byte_order_type::enum_t byte_order)
|
||||
{
|
||||
// write endian type
|
||||
value_writer<uint8_t>::write(byte_order, iter, byte_order);
|
||||
|
||||
// write geometry type
|
||||
uint32_t type = geometry_type<MultiPolygon>::get();
|
||||
value_writer<uint32_t>::write(type, iter, byte_order);
|
||||
|
||||
// write num polygons
|
||||
uint32_t num_polygons = boost::size(multipolygon);
|
||||
value_writer<uint32_t>::write(num_polygons, iter, byte_order);
|
||||
|
||||
typedef typename boost::range_value<MultiPolygon>::type polygon_type;
|
||||
|
||||
for(typename boost::range_iterator<MultiPolygon const>::type
|
||||
polygon_iter = boost::begin(multipolygon);
|
||||
polygon_iter != boost::end(multipolygon);
|
||||
++polygon_iter)
|
||||
{
|
||||
detail::wkb::polygon_writer<polygon_type>::write(*polygon_iter, iter, byte_order);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail::wkb
|
||||
#endif // DOXYGEN_NO_IMPL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
#endif // BOOST_GEOMETRY_MULTI_IO_WKB_DETAIL_WRITER_HPP
|
||||
@@ -0,0 +1,62 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2015 Mats Taraldsvik
|
||||
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_MULTI_IO_WKB_READ_WKB_HPP
|
||||
#define BOOST_GEOMETRY_MULTI_IO_WKB_READ_WKB_HPP
|
||||
|
||||
#include <iterator>
|
||||
|
||||
#include <boost/geometry/extensions/multi/gis/io/wkb/detail/parser.hpp>
|
||||
#include <boost/geometry/extensions/gis/io/wkb/read_wkb.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template <typename Geometry>
|
||||
struct read_wkb<multi_point_tag, Geometry>
|
||||
{
|
||||
template <typename Iterator>
|
||||
static inline bool parse(Iterator& it, Iterator end, Geometry& geometry,
|
||||
detail::wkb::byte_order_type::enum_t order)
|
||||
{
|
||||
return detail::wkb::multipoint_parser<Geometry>::parse(it, end, geometry, order);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
struct read_wkb<multi_linestring_tag, Geometry>
|
||||
{
|
||||
template <typename Iterator>
|
||||
static inline bool parse(Iterator& it, Iterator end, Geometry& geometry,
|
||||
detail::wkb::byte_order_type::enum_t order)
|
||||
{
|
||||
return detail::wkb::multilinestring_parser<Geometry>::parse(it, end, geometry, order);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
struct read_wkb<multi_polygon_tag, Geometry>
|
||||
{
|
||||
template <typename Iterator>
|
||||
static inline bool parse(Iterator& it, Iterator end, Geometry& geometry,
|
||||
detail::wkb::byte_order_type::enum_t order)
|
||||
{
|
||||
return detail::wkb::multipolygon_parser<Geometry>::parse(it, end, geometry, order);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_MULTI_IO_WKB_READ_WKB_HPP
|
||||
@@ -0,0 +1,66 @@
|
||||
// Boost.Geometry
|
||||
//
|
||||
// Copyright (c) 2015 Mats Taraldsvik.
|
||||
//
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_MULTI_IO_WKB_WRITE_WKB_HPP
|
||||
#define BOOST_GEOMETRY_MULTI_IO_WKB_WRITE_WKB_HPP
|
||||
|
||||
#include <iterator>
|
||||
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/extensions/multi/gis/io/wkb/detail/writer.hpp>
|
||||
#include <boost/geometry/extensions/gis/io/wkb/write_wkb.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template <typename Geometry>
|
||||
struct write_wkb<multi_point_tag, Geometry>
|
||||
{
|
||||
template <typename OutputIterator>
|
||||
static inline bool write(const Geometry& geometry, OutputIterator iter,
|
||||
detail::wkb::byte_order_type::enum_t byte_order)
|
||||
{
|
||||
return detail::wkb::multipoint_writer<Geometry>::write(geometry, iter, byte_order);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
struct write_wkb<multi_linestring_tag, Geometry>
|
||||
{
|
||||
template <typename OutputIterator>
|
||||
static inline bool write(const Geometry& geometry, OutputIterator iter,
|
||||
detail::wkb::byte_order_type::enum_t byte_order)
|
||||
{
|
||||
return detail::wkb::multilinestring_writer<Geometry>::write(geometry, iter, byte_order);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
struct write_wkb<multi_polygon_tag, Geometry>
|
||||
{
|
||||
template <typename OutputIterator>
|
||||
static inline bool write(const Geometry& geometry, OutputIterator iter,
|
||||
detail::wkb::byte_order_type::enum_t byte_order)
|
||||
{
|
||||
return detail::wkb::multipolygon_writer<Geometry>::write(geometry, iter, byte_order);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
}} // namespace boost::geometry
|
||||
#endif // BOOST_GEOMETRY_MULTI_IO_WKB_WRITE_WKB_HPP
|
||||
@@ -1,6 +1,6 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2015-2016 Oracle and/or its affiliates.
|
||||
// Copyright (c) 2015-2017 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@@ -20,9 +20,8 @@
|
||||
#include <boost/geometry/util/condition.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/flattening.hpp>
|
||||
|
||||
#include <boost/geometry/formulas/differential_quantities.hpp>
|
||||
#include <boost/geometry/formulas/flattening.hpp>
|
||||
#include <boost/geometry/formulas/result_inverse.hpp>
|
||||
|
||||
|
||||
@@ -75,7 +74,7 @@ public:
|
||||
CT const c0 = CT(0);
|
||||
CT const c1 = CT(1);
|
||||
CT const pi = math::pi<CT>();
|
||||
CT const f = detail::flattening<CT>(spheroid);
|
||||
CT const f = formula::flattening<CT>(spheroid);
|
||||
|
||||
CT const dlon = lon2 - lon1;
|
||||
CT const sin_dlon = sin(dlon);
|
||||
@@ -138,7 +137,14 @@ public:
|
||||
|
||||
CT A = c0;
|
||||
CT U = c0;
|
||||
if ( ! math::equals(cos_lat2, c0) )
|
||||
if (math::equals(cos_lat2, c0))
|
||||
{
|
||||
if (sin_lat2 < c0)
|
||||
{
|
||||
A = pi;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CT const tan_lat2 = sin_lat2/cos_lat2;
|
||||
CT const M = cos_lat1*tan_lat2-sin_lat1*cos_dlon;
|
||||
@@ -149,7 +155,14 @@ public:
|
||||
|
||||
CT B = c0;
|
||||
CT V = c0;
|
||||
if ( ! math::equals(cos_lat1, c0) )
|
||||
if (math::equals(cos_lat1, c0))
|
||||
{
|
||||
if (sin_lat1 < c0)
|
||||
{
|
||||
B = pi;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CT const tan_lat1 = sin_lat1/cos_lat1;
|
||||
CT const N = cos_lat2*tan_lat1-sin_lat2*cos_dlon;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#ifndef BOOST_GEOMETRY_FORMULAS_AREA_FORMULAS_HPP
|
||||
#define BOOST_GEOMETRY_FORMULAS_AREA_FORMULAS_HPP
|
||||
|
||||
#include <boost/geometry/algorithms/detail/flattening.hpp>
|
||||
#include <boost/geometry/formulas/flattening.hpp>
|
||||
#include <boost/math/special_functions/hypot.hpp>
|
||||
|
||||
namespace boost { namespace geometry { namespace formula
|
||||
@@ -429,7 +429,7 @@ public:
|
||||
// Constants
|
||||
|
||||
CT const ep = spheroid_const.m_ep;
|
||||
CT const f = geometry::detail::flattening<CT>(spheroid_const.m_spheroid);
|
||||
CT const f = formula::flattening<CT>(spheroid_const.m_spheroid);
|
||||
CT const one_minus_f = CT(1) - f;
|
||||
std::size_t const series_order_plus_one = SeriesOrder + 1;
|
||||
std::size_t const series_order_plus_two = SeriesOrder + 2;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2016 Oracle and/or its affiliates.
|
||||
// Copyright (c) 2016-2017 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@@ -64,8 +64,8 @@ public:
|
||||
CT const c1 = 1;
|
||||
CT const one_minus_f = c1 - f;
|
||||
|
||||
CT const sin_bet1 = one_minus_f * sin_lat1;
|
||||
CT const sin_bet2 = one_minus_f * sin_lat2;
|
||||
CT sin_bet1 = one_minus_f * sin_lat1;
|
||||
CT sin_bet2 = one_minus_f * sin_lat2;
|
||||
|
||||
// equator
|
||||
if (math::equals(sin_bet1, c0) && math::equals(sin_bet2, c0))
|
||||
@@ -89,14 +89,17 @@ public:
|
||||
CT const e2 = f * (c2 - f);
|
||||
CT const ep2 = e2 / math::sqr(one_minus_f);
|
||||
|
||||
CT const cos_bet1 = cos_lat1;
|
||||
CT const cos_bet2 = cos_lat2;
|
||||
|
||||
CT const sin_alp1 = sin(azimuth);
|
||||
CT const cos_alp1 = cos(azimuth);
|
||||
//CT const sin_alp2 = sin(reverse_azimuth);
|
||||
CT const cos_alp2 = cos(reverse_azimuth);
|
||||
|
||||
CT cos_bet1 = cos_lat1;
|
||||
CT cos_bet2 = cos_lat2;
|
||||
|
||||
normalize(sin_bet1, cos_bet1);
|
||||
normalize(sin_bet2, cos_bet2);
|
||||
|
||||
CT sin_sig1 = sin_bet1;
|
||||
CT cos_sig1 = cos_alp1 * cos_bet1;
|
||||
CT sin_sig2 = sin_bet2;
|
||||
@@ -112,8 +115,8 @@ public:
|
||||
J12_f(sin_sig1, cos_sig1, sin_sig2, cos_sig2, cos_alp0_sqr, f) :
|
||||
J12_ep_sqr(sin_sig1, cos_sig1, sin_sig2, cos_sig2, cos_alp0_sqr, ep2) ;
|
||||
|
||||
CT const dn1 = math::sqrt(c1 + e2 * math::sqr(sin_lat1));
|
||||
CT const dn2 = math::sqrt(c1 + e2 * math::sqr(sin_lat2));
|
||||
CT const dn1 = math::sqrt(c1 + ep2 * math::sqr(sin_bet1));
|
||||
CT const dn2 = math::sqrt(c1 + ep2 * math::sqr(sin_bet2));
|
||||
|
||||
if (BOOST_GEOMETRY_CONDITION(EnableReducedLength))
|
||||
{
|
||||
|
||||
70
include/boost/geometry/formulas/eccentricity_sqr.hpp
Normal file
70
include/boost/geometry/formulas/eccentricity_sqr.hpp
Normal file
@@ -0,0 +1,70 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2016 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)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_FORMULAS_ECCENCRICITY_SQR_HPP
|
||||
#define BOOST_GEOMETRY_FORMULAS_ECCENCRICITY_SQR_HPP
|
||||
|
||||
#include <boost/geometry/core/radius.hpp>
|
||||
#include <boost/geometry/core/tag.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace formula_dispatch
|
||||
{
|
||||
|
||||
template <typename ResultType, typename Geometry, typename Tag = typename tag<Geometry>::type>
|
||||
struct eccentricity_sqr
|
||||
: not_implemented<Tag>
|
||||
{};
|
||||
|
||||
template <typename ResultType, typename Geometry>
|
||||
struct eccentricity_sqr<ResultType, Geometry, srs_sphere_tag>
|
||||
{
|
||||
static inline ResultType apply(Geometry const& /*geometry*/)
|
||||
{
|
||||
return ResultType(0);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ResultType, typename Geometry>
|
||||
struct eccentricity_sqr<ResultType, Geometry, srs_spheroid_tag>
|
||||
{
|
||||
static inline ResultType apply(Geometry const& geometry)
|
||||
{
|
||||
// 1 - (b / a)^2
|
||||
return ResultType(1) - math::sqr(ResultType(get_radius<2>(geometry))
|
||||
/ ResultType(get_radius<0>(geometry)));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace formula_dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace formula
|
||||
{
|
||||
|
||||
template <typename ResultType, typename Geometry>
|
||||
ResultType eccentricity_sqr(Geometry const& geometry)
|
||||
{
|
||||
return formula_dispatch::eccentricity_sqr<ResultType, Geometry>::apply(geometry);
|
||||
}
|
||||
|
||||
} // namespace formula
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_FORMULAS_ECCENCRICITY_SQR_HPP
|
||||
@@ -1,6 +1,6 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2014 Oracle and/or its affiliates.
|
||||
// Copyright (c) 2014-2016 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_FLATTENING_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_FLATTENING_HPP
|
||||
#ifndef BOOST_GEOMETRY_FORMULAS_FLATTENING_HPP
|
||||
#define BOOST_GEOMETRY_FORMULAS_FLATTENING_HPP
|
||||
|
||||
#include <boost/geometry/core/radius.hpp>
|
||||
#include <boost/geometry/core/tag.hpp>
|
||||
@@ -21,7 +21,7 @@ namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace detail_dispatch
|
||||
namespace formula_dispatch
|
||||
{
|
||||
|
||||
template <typename ResultType, typename Geometry, typename Tag = typename tag<Geometry>::type>
|
||||
@@ -43,27 +43,28 @@ struct flattening<ResultType, Geometry, srs_spheroid_tag>
|
||||
{
|
||||
static inline ResultType apply(Geometry const& geometry)
|
||||
{
|
||||
// (a - b) / a
|
||||
return ResultType(get_radius<0>(geometry) - get_radius<2>(geometry))
|
||||
/ ResultType(get_radius<0>(geometry));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail_dispatch
|
||||
} // namespace formula_dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
namespace formula
|
||||
{
|
||||
|
||||
template <typename ResultType, typename Geometry>
|
||||
ResultType flattening(Geometry const& geometry)
|
||||
{
|
||||
return detail_dispatch::flattening<ResultType, Geometry>::apply(geometry);
|
||||
return formula_dispatch::flattening<ResultType, Geometry>::apply(geometry);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace formula
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_FLATTENING_HPP
|
||||
#endif // BOOST_GEOMETRY_FORMULAS_FLATTENING_HPP
|
||||
457
include/boost/geometry/formulas/geographic.hpp
Normal file
457
include/boost/geometry/formulas/geographic.hpp
Normal file
@@ -0,0 +1,457 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2016, 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)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_FORMULAS_GEOGRAPHIC_HPP
|
||||
#define BOOST_GEOMETRY_FORMULAS_GEOGRAPHIC_HPP
|
||||
|
||||
#include <boost/geometry/core/coordinate_system.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/radian_access.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/formulas/eccentricity_sqr.hpp>
|
||||
#include <boost/geometry/formulas/flattening.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
|
||||
#include <boost/geometry/util/select_coordinate_type.hpp>
|
||||
|
||||
namespace boost { namespace geometry {
|
||||
|
||||
namespace formula {
|
||||
|
||||
template <typename Point3d, typename PointGeo, typename Spheroid>
|
||||
inline Point3d geo_to_cart3d(PointGeo const& point_geo, Spheroid const& spheroid)
|
||||
{
|
||||
typedef typename coordinate_type<Point3d>::type calc_t;
|
||||
|
||||
calc_t const c1 = 1;
|
||||
calc_t const e_sqr = eccentricity_sqr<calc_t>(spheroid);
|
||||
|
||||
calc_t const lon = get_as_radian<0>(point_geo);
|
||||
calc_t const lat = get_as_radian<1>(point_geo);
|
||||
|
||||
Point3d res;
|
||||
|
||||
calc_t const sin_lat = sin(lat);
|
||||
|
||||
// "unit" spheroid, a = 1
|
||||
calc_t const N = c1 / math::sqrt(c1 - e_sqr * math::sqr(sin_lat));
|
||||
calc_t const N_cos_lat = N * cos(lat);
|
||||
|
||||
set<0>(res, N_cos_lat * cos(lon));
|
||||
set<1>(res, N_cos_lat * sin(lon));
|
||||
set<2>(res, N * (c1 - e_sqr) * sin_lat);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename PointGeo, typename Spheroid, typename Point3d>
|
||||
inline void geo_to_cart3d(PointGeo const& point_geo, Point3d & result, Point3d & north, Point3d & east, Spheroid const& spheroid)
|
||||
{
|
||||
typedef typename coordinate_type<Point3d>::type calc_t;
|
||||
|
||||
calc_t const c1 = 1;
|
||||
calc_t const e_sqr = eccentricity_sqr<calc_t>(spheroid);
|
||||
|
||||
calc_t const lon = get_as_radian<0>(point_geo);
|
||||
calc_t const lat = get_as_radian<1>(point_geo);
|
||||
|
||||
calc_t const sin_lon = sin(lon);
|
||||
calc_t const cos_lon = cos(lon);
|
||||
calc_t const sin_lat = sin(lat);
|
||||
calc_t const cos_lat = cos(lat);
|
||||
|
||||
// "unit" spheroid, a = 1
|
||||
calc_t const N = c1 / math::sqrt(c1 - e_sqr * math::sqr(sin_lat));
|
||||
calc_t const N_cos_lat = N * cos_lat;
|
||||
|
||||
set<0>(result, N_cos_lat * cos_lon);
|
||||
set<1>(result, N_cos_lat * sin_lon);
|
||||
set<2>(result, N * (c1 - e_sqr) * sin_lat);
|
||||
|
||||
set<0>(east, -sin_lon);
|
||||
set<1>(east, cos_lon);
|
||||
set<2>(east, 0);
|
||||
|
||||
set<0>(north, -sin_lat * cos_lon);
|
||||
set<1>(north, -sin_lat * sin_lon);
|
||||
set<2>(north, cos_lat);
|
||||
}
|
||||
|
||||
template <typename PointGeo, typename Point3d, typename Spheroid>
|
||||
inline PointGeo cart3d_to_geo(Point3d const& point_3d, Spheroid const& spheroid)
|
||||
{
|
||||
typedef typename coordinate_type<PointGeo>::type coord_t;
|
||||
typedef typename coordinate_type<Point3d>::type calc_t;
|
||||
|
||||
calc_t const c1 = 1;
|
||||
//calc_t const c2 = 2;
|
||||
calc_t const e_sqr = eccentricity_sqr<calc_t>(spheroid);
|
||||
|
||||
calc_t const x = get<0>(point_3d);
|
||||
calc_t const y = get<1>(point_3d);
|
||||
calc_t const z = get<2>(point_3d);
|
||||
calc_t const xy_l = math::sqrt(math::sqr(x) + math::sqr(y));
|
||||
|
||||
calc_t const lonr = atan2(y, x);
|
||||
|
||||
// NOTE: Alternative version
|
||||
// http://www.iag-aig.org/attach/989c8e501d9c5b5e2736955baf2632f5/V60N2_5FT.pdf
|
||||
// calc_t const lonr = c2 * atan2(y, x + xy_l);
|
||||
|
||||
calc_t const latr = atan2(z, (c1 - e_sqr) * xy_l);
|
||||
|
||||
// NOTE: If h is equal to 0 then there is no need to improve value of latitude
|
||||
// because then N_i / (N_i + h_i) = 1
|
||||
// http://www.navipedia.net/index.php/Ellipsoidal_and_Cartesian_Coordinates_Conversion
|
||||
|
||||
PointGeo res;
|
||||
|
||||
set_from_radian<0>(res, lonr);
|
||||
set_from_radian<1>(res, latr);
|
||||
|
||||
coord_t lon = get<0>(res);
|
||||
coord_t lat = get<1>(res);
|
||||
|
||||
math::normalize_spheroidal_coordinates
|
||||
<
|
||||
typename coordinate_system<PointGeo>::type::units,
|
||||
coord_t
|
||||
>(lon, lat);
|
||||
|
||||
set<0>(res, lon);
|
||||
set<1>(res, lat);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename Point3d, typename Spheroid>
|
||||
inline Point3d projected_to_xy(Point3d const& point_3d, Spheroid const& spheroid)
|
||||
{
|
||||
typedef typename coordinate_type<Point3d>::type coord_t;
|
||||
|
||||
// len_xy = sqrt(x^2 + y^2)
|
||||
// r = len_xy - |z / tan(lat)|
|
||||
// assuming h = 0
|
||||
// lat = atan2(z, (1 - e^2) * len_xy);
|
||||
// |z / tan(lat)| = (1 - e^2) * len_xy
|
||||
// r = e^2 * len_xy
|
||||
// x_res = r * cos(lon) = e^2 * len_xy * x / len_xy = e^2 * x
|
||||
// y_res = r * sin(lon) = e^2 * len_xy * y / len_xy = e^2 * y
|
||||
|
||||
coord_t const c0 = 0;
|
||||
coord_t const e_sqr = formula::eccentricity_sqr<coord_t>(spheroid);
|
||||
|
||||
Point3d res;
|
||||
|
||||
set<0>(res, e_sqr * get<0>(point_3d));
|
||||
set<1>(res, e_sqr * get<1>(point_3d));
|
||||
set<2>(res, c0);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename Point3d, typename Spheroid>
|
||||
inline Point3d projected_to_surface(Point3d const& direction, Spheroid const& spheroid)
|
||||
{
|
||||
typedef typename coordinate_type<Point3d>::type coord_t;
|
||||
|
||||
//coord_t const c0 = 0;
|
||||
coord_t const c2 = 2;
|
||||
coord_t const c4 = 4;
|
||||
|
||||
// calculate the point of intersection of a ray and spheroid's surface
|
||||
// the origin is the origin of the coordinate system
|
||||
//(x*x+y*y)/(a*a) + z*z/(b*b) = 1
|
||||
// x = d.x * t
|
||||
// y = d.y * t
|
||||
// z = d.z * t
|
||||
coord_t const dx = get<0>(direction);
|
||||
coord_t const dy = get<1>(direction);
|
||||
coord_t const dz = get<2>(direction);
|
||||
|
||||
//coord_t const a_sqr = math::sqr(get_radius<0>(spheroid));
|
||||
//coord_t const b_sqr = math::sqr(get_radius<2>(spheroid));
|
||||
// "unit" spheroid, a = 1
|
||||
coord_t const a_sqr = 1;
|
||||
coord_t const b_sqr = math::sqr(get_radius<2>(spheroid) / get_radius<0>(spheroid));
|
||||
|
||||
coord_t const param_a = (dx*dx + dy*dy) / a_sqr + dz*dz / b_sqr;
|
||||
coord_t const delta = c4 * param_a;
|
||||
// delta >= 0
|
||||
coord_t const t = math::sqrt(delta) / (c2 * param_a);
|
||||
|
||||
// result = direction * t
|
||||
Point3d result = direction;
|
||||
multiply_value(result, t);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Point3d, typename Spheroid>
|
||||
inline bool projected_to_surface(Point3d const& origin, Point3d const& direction, Point3d & result1, Point3d & result2, Spheroid const& spheroid)
|
||||
{
|
||||
typedef typename coordinate_type<Point3d>::type coord_t;
|
||||
|
||||
coord_t const c0 = 0;
|
||||
coord_t const c1 = 1;
|
||||
coord_t const c2 = 2;
|
||||
coord_t const c4 = 4;
|
||||
|
||||
// calculate the point of intersection of a ray and spheroid's surface
|
||||
//(x*x+y*y)/(a*a) + z*z/(b*b) = 1
|
||||
// x = o.x + d.x * t
|
||||
// y = o.y + d.y * t
|
||||
// z = o.z + d.z * t
|
||||
coord_t const ox = get<0>(origin);
|
||||
coord_t const oy = get<1>(origin);
|
||||
coord_t const oz = get<2>(origin);
|
||||
coord_t const dx = get<0>(direction);
|
||||
coord_t const dy = get<1>(direction);
|
||||
coord_t const dz = get<2>(direction);
|
||||
|
||||
//coord_t const a_sqr = math::sqr(get_radius<0>(spheroid));
|
||||
//coord_t const b_sqr = math::sqr(get_radius<2>(spheroid));
|
||||
// "unit" spheroid, a = 1
|
||||
coord_t const a_sqr = 1;
|
||||
coord_t const b_sqr = math::sqr(get_radius<2>(spheroid) / get_radius<0>(spheroid));
|
||||
|
||||
coord_t const param_a = (dx*dx + dy*dy) / a_sqr + dz*dz / b_sqr;
|
||||
coord_t const param_b = c2 * ((ox*dx + oy*dy) / a_sqr + oz*dz / b_sqr);
|
||||
coord_t const param_c = (ox*ox + oy*oy) / a_sqr + oz*oz / b_sqr - c1;
|
||||
|
||||
coord_t const delta = math::sqr(param_b) - c4 * param_a*param_c;
|
||||
|
||||
// equals() ?
|
||||
if (delta < c0 || param_a == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// result = origin + direction * t
|
||||
|
||||
coord_t const sqrt_delta = math::sqrt(delta);
|
||||
coord_t const two_a = c2 * param_a;
|
||||
|
||||
coord_t const t1 = (-param_b + sqrt_delta) / two_a;
|
||||
result1 = direction;
|
||||
multiply_value(result1, t1);
|
||||
add_point(result1, origin);
|
||||
|
||||
coord_t const t2 = (-param_b - sqrt_delta) / two_a;
|
||||
result2 = direction;
|
||||
multiply_value(result2, t2);
|
||||
add_point(result2, origin);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Point3d, typename Spheroid>
|
||||
inline bool great_elliptic_intersection(Point3d const& a1, Point3d const& a2,
|
||||
Point3d const& b1, Point3d const& b2,
|
||||
Point3d & result,
|
||||
Spheroid const& spheroid)
|
||||
{
|
||||
typedef typename coordinate_type<Point3d>::type coord_t;
|
||||
|
||||
coord_t c0 = 0;
|
||||
coord_t c1 = 1;
|
||||
|
||||
Point3d n1 = cross_product(a1, a2);
|
||||
Point3d n2 = cross_product(b1, b2);
|
||||
|
||||
// intersection direction
|
||||
Point3d id = cross_product(n1, n2);
|
||||
coord_t id_len_sqr = dot_product(id, id);
|
||||
|
||||
if (math::equals(id_len_sqr, c0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// no need to normalize a1 and a2 because the intersection point on
|
||||
// the opposite side of the globe is at the same distance from the origin
|
||||
coord_t cos_a1i = dot_product(a1, id);
|
||||
coord_t cos_a2i = dot_product(a2, id);
|
||||
coord_t gri = math::detail::greatest(cos_a1i, cos_a2i);
|
||||
Point3d neg_id = id;
|
||||
multiply_value(neg_id, -c1);
|
||||
coord_t cos_a1ni = dot_product(a1, neg_id);
|
||||
coord_t cos_a2ni = dot_product(a2, neg_id);
|
||||
coord_t grni = math::detail::greatest(cos_a1ni, cos_a2ni);
|
||||
|
||||
if (gri >= grni)
|
||||
{
|
||||
result = projected_to_surface(id, spheroid);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = projected_to_surface(neg_id, spheroid);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Point3d1, typename Point3d2>
|
||||
static inline int elliptic_side_value(Point3d1 const& origin, Point3d1 const& norm, Point3d2 const& pt)
|
||||
{
|
||||
typedef typename coordinate_type<Point3d1>::type calc_t;
|
||||
calc_t c0 = 0;
|
||||
|
||||
// vector oposite to pt - origin
|
||||
// only for the purpose of assigning origin
|
||||
Point3d1 vec = origin;
|
||||
subtract_point(vec, pt);
|
||||
|
||||
calc_t d = dot_product(norm, vec);
|
||||
|
||||
// since the vector is opposite the signs are opposite
|
||||
return math::equals(d, c0) ? 0
|
||||
: d < c0 ? 1
|
||||
: -1; // d > 0
|
||||
}
|
||||
|
||||
template <typename Point3d, typename Spheroid>
|
||||
inline bool planes_spheroid_intersection(Point3d const& o1, Point3d const& n1,
|
||||
Point3d const& o2, Point3d const& n2,
|
||||
Point3d & ip1, Point3d & ip2,
|
||||
Spheroid const& spheroid)
|
||||
{
|
||||
typedef typename coordinate_type<Point3d>::type coord_t;
|
||||
|
||||
coord_t c0 = 0;
|
||||
coord_t c1 = 1;
|
||||
|
||||
// Below
|
||||
// n . (p - o) = 0
|
||||
// n . p - n . o = 0
|
||||
// n . p + d = 0
|
||||
// n . p = h
|
||||
|
||||
// intersection direction
|
||||
Point3d id = cross_product(n1, n2);
|
||||
|
||||
if (math::equals(dot_product(id, id), c0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
coord_t dot_n1_n2 = dot_product(n1, n2);
|
||||
coord_t dot_n1_n2_sqr = math::sqr(dot_n1_n2);
|
||||
|
||||
coord_t h1 = dot_product(n1, o1);
|
||||
coord_t h2 = dot_product(n2, o2);
|
||||
|
||||
coord_t denom = c1 - dot_n1_n2_sqr;
|
||||
coord_t C1 = (h1 - h2 * dot_n1_n2) / denom;
|
||||
coord_t C2 = (h2 - h1 * dot_n1_n2) / denom;
|
||||
|
||||
// C1 * n1 + C2 * n2
|
||||
Point3d C1_n1 = n1;
|
||||
multiply_value(C1_n1, C1);
|
||||
Point3d C2_n2 = n2;
|
||||
multiply_value(C2_n2, C2);
|
||||
Point3d io = C1_n1;
|
||||
add_point(io, C2_n2);
|
||||
|
||||
if (! projected_to_surface(io, id, ip1, ip2, spheroid))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template <typename Point3d, typename Spheroid>
|
||||
inline void experimental_elliptic_plane(Point3d const& p1, Point3d const& p2,
|
||||
Point3d & v1, Point3d & v2,
|
||||
Point3d & origin, Point3d & normal,
|
||||
Spheroid const& spheroid)
|
||||
{
|
||||
typedef typename coordinate_type<Point3d>::type coord_t;
|
||||
|
||||
Point3d xy1 = projected_to_xy(p1, spheroid);
|
||||
Point3d xy2 = projected_to_xy(p2, spheroid);
|
||||
|
||||
// origin = (xy1 + xy2) / 2
|
||||
origin = xy1;
|
||||
add_point(origin, xy2);
|
||||
multiply_value(origin, coord_t(0.5));
|
||||
|
||||
// v1 = p1 - origin
|
||||
v1 = p1;
|
||||
subtract_point(v1, origin);
|
||||
// v2 = p2 - origin
|
||||
v2 = p2;
|
||||
subtract_point(v2, origin);
|
||||
|
||||
normal = cross_product(v1, v2);
|
||||
}
|
||||
|
||||
template <typename Point3d, typename Spheroid>
|
||||
inline void experimental_elliptic_plane(Point3d const& p1, Point3d const& p2,
|
||||
Point3d & origin, Point3d & normal,
|
||||
Spheroid const& spheroid)
|
||||
{
|
||||
Point3d v1, v2;
|
||||
experimental_elliptic_plane(p1, p2, v1, v2, origin, normal, spheroid);
|
||||
}
|
||||
|
||||
template <typename Point3d, typename Spheroid>
|
||||
inline bool experimental_elliptic_intersection(Point3d const& a1, Point3d const& a2,
|
||||
Point3d const& b1, Point3d const& b2,
|
||||
Point3d & result,
|
||||
Spheroid const& spheroid)
|
||||
{
|
||||
typedef typename coordinate_type<Point3d>::type coord_t;
|
||||
|
||||
coord_t c0 = 0;
|
||||
coord_t c1 = 1;
|
||||
|
||||
Point3d a1v, a2v, o1, n1;
|
||||
experimental_elliptic_plane(a1, a2, a1v, a2v, o1, n1, spheroid);
|
||||
Point3d b1v, b2v, o2, n2;
|
||||
experimental_elliptic_plane(b1, b2, b1v, b2v, o2, n2, spheroid);
|
||||
|
||||
if (! detail::vec_normalize(n1) || ! detail::vec_normalize(n2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Point3d ip1_s, ip2_s;
|
||||
if (! planes_spheroid_intersection(o1, n1, o2, n2, ip1_s, ip2_s, spheroid))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// NOTE: simplified test, may not work in all cases
|
||||
coord_t dot_a1i1 = dot_product(a1, ip1_s);
|
||||
coord_t dot_a2i1 = dot_product(a2, ip1_s);
|
||||
coord_t gri1 = math::detail::greatest(dot_a1i1, dot_a2i1);
|
||||
coord_t dot_a1i2 = dot_product(a1, ip2_s);
|
||||
coord_t dot_a2i2 = dot_product(a2, ip2_s);
|
||||
coord_t gri2 = math::detail::greatest(dot_a1i2, dot_a2i2);
|
||||
|
||||
result = gri1 >= gri2 ? ip1_s : ip2_s;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace formula
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_FORMULAS_GEOGRAPHIC_HPP
|
||||
@@ -14,12 +14,11 @@
|
||||
|
||||
#include <boost/geometry/core/radius.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/flattening.hpp>
|
||||
|
||||
#include <boost/geometry/util/condition.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
#include <boost/geometry/formulas/andoyer_inverse.hpp>
|
||||
#include <boost/geometry/formulas/flattening.hpp>
|
||||
#include <boost/geometry/formulas/thomas_inverse.hpp>
|
||||
#include <boost/geometry/formulas/vincenty_direct.hpp>
|
||||
#include <boost/geometry/formulas/vincenty_inverse.hpp>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -40,38 +40,55 @@ struct result_spherical
|
||||
T reverse_azimuth;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
static inline void sph_to_cart3d(T const& lon, T const& lat, T & x, T & y, T & z)
|
||||
{
|
||||
T const cos_lat = cos(lat);
|
||||
x = cos_lat * cos(lon);
|
||||
y = cos_lat * sin(lon);
|
||||
z = sin(lat);
|
||||
}
|
||||
|
||||
template <typename Point3d, typename PointSph>
|
||||
static inline Point3d sph_to_cart3d(PointSph const& point_sph)
|
||||
{
|
||||
typedef typename coordinate_type<Point3d>::type calc_t;
|
||||
|
||||
calc_t const lon = get_as_radian<0>(point_sph);
|
||||
calc_t const lat = get_as_radian<1>(point_sph);
|
||||
calc_t x, y, z;
|
||||
sph_to_cart3d(lon, lat, x, y, z);
|
||||
|
||||
Point3d res;
|
||||
|
||||
calc_t lon = get_as_radian<0>(point_sph);
|
||||
calc_t lat = get_as_radian<1>(point_sph);
|
||||
|
||||
calc_t const cos_lat = cos(lat);
|
||||
set<0>(res, cos_lat * cos(lon));
|
||||
set<1>(res, cos_lat * sin(lon));
|
||||
set<2>(res, sin(lat));
|
||||
set<0>(res, x);
|
||||
set<1>(res, y);
|
||||
set<2>(res, z);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline void cart3d_to_sph(T const& x, T const& y, T const& z, T & lon, T & lat)
|
||||
{
|
||||
lon = atan2(y, x);
|
||||
lat = asin(z);
|
||||
}
|
||||
|
||||
template <typename PointSph, typename Point3d>
|
||||
static inline PointSph cart3d_to_sph(Point3d const& point_3d)
|
||||
{
|
||||
typedef typename coordinate_type<PointSph>::type coord_t;
|
||||
typedef typename coordinate_type<Point3d>::type calc_t;
|
||||
|
||||
PointSph res;
|
||||
|
||||
calc_t const x = get<0>(point_3d);
|
||||
calc_t const y = get<1>(point_3d);
|
||||
calc_t const z = get<2>(point_3d);
|
||||
calc_t lonr, latr;
|
||||
cart3d_to_sph(x, y, z, lonr, latr);
|
||||
|
||||
set_from_radian<0>(res, atan2(y, x));
|
||||
set_from_radian<1>(res, asin(z));
|
||||
PointSph res;
|
||||
set_from_radian<0>(res, lonr);
|
||||
set_from_radian<1>(res, latr);
|
||||
|
||||
coord_t lon = get<0>(res);
|
||||
coord_t lat = get<1>(res);
|
||||
@@ -104,9 +121,9 @@ static inline int sph_side_value(Point3d1 const& norm, Point3d2 const& pt)
|
||||
|
||||
template <typename CT, bool ReverseAzimuth, typename T1, typename T2>
|
||||
static inline result_spherical<CT> spherical_azimuth(T1 const& lon1,
|
||||
T1 const& lat1,
|
||||
T2 const& lon2,
|
||||
T2 const& lat2)
|
||||
T1 const& lat1,
|
||||
T2 const& lon2,
|
||||
T2 const& lat2)
|
||||
{
|
||||
typedef result_spherical<CT> result_type;
|
||||
result_type result;
|
||||
@@ -114,12 +131,6 @@ static inline result_spherical<CT> spherical_azimuth(T1 const& lon1,
|
||||
// http://williams.best.vwh.net/avform.htm#Crs
|
||||
// https://en.wikipedia.org/wiki/Great-circle_navigation
|
||||
CT dlon = lon2 - lon1;
|
||||
CT cos_dlon = cos(dlon);
|
||||
CT sin_dlon = sin(dlon);
|
||||
CT cos_lat1 = cos(lat1);
|
||||
CT cos_lat2 = cos(lat2);
|
||||
CT sin_lat1 = sin(lat1);
|
||||
CT sin_lat2 = sin(lat2);
|
||||
|
||||
// An optimization which should kick in often for Boxes
|
||||
//if ( math::equals(dlon, ReturnType(0)) )
|
||||
@@ -128,21 +139,84 @@ static inline result_spherical<CT> spherical_azimuth(T1 const& lon1,
|
||||
// return - sin(get_as_radian<1>(p1)) * cos_p2lat);
|
||||
//}
|
||||
|
||||
// "An alternative formula, not requiring the pre-computation of d"
|
||||
// In the formula below dlon is used as "d"
|
||||
result.azimuth = atan2(sin_dlon * cos_lat2,
|
||||
cos_lat1 * sin_lat2 - sin_lat1 * cos_lat2 * cos_dlon);
|
||||
CT const cos_dlon = cos(dlon);
|
||||
CT const sin_dlon = sin(dlon);
|
||||
CT const cos_lat1 = cos(lat1);
|
||||
CT const cos_lat2 = cos(lat2);
|
||||
CT const sin_lat1 = sin(lat1);
|
||||
CT const sin_lat2 = sin(lat2);
|
||||
|
||||
{
|
||||
// "An alternative formula, not requiring the pre-computation of d"
|
||||
// In the formula below dlon is used as "d"
|
||||
CT const y = sin_dlon * cos_lat2;
|
||||
CT const x = cos_lat1 * sin_lat2 - sin_lat1 * cos_lat2 * cos_dlon;
|
||||
result.azimuth = atan2(y, x);
|
||||
}
|
||||
|
||||
if (ReverseAzimuth)
|
||||
{
|
||||
result.reverse_azimuth =
|
||||
atan2(sin_dlon * cos_lat1,
|
||||
sin_lat2 * cos_lat1 * cos_dlon - cos_lat2 * sin_lat1);
|
||||
CT const y = sin_dlon * cos_lat1;
|
||||
CT const x = sin_lat2 * cos_lat1 * cos_dlon - cos_lat2 * sin_lat1;
|
||||
result.reverse_azimuth = atan2(y, x);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename ReturnType, typename T1, typename T2>
|
||||
inline ReturnType spherical_azimuth(T1 const& lon1, T1 const& lat1,
|
||||
T2 const& lon2, T2 const& lat2)
|
||||
{
|
||||
return spherical_azimuth<ReturnType, false>(lon1, lat1, lon2, lat2).azimuth;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T spherical_azimuth(T const& lon1, T const& lat1, T const& lon2, T const& lat2)
|
||||
{
|
||||
return spherical_azimuth<T, false>(lon1, lat1, lon2, lat2).azimuth;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline int azimuth_side_value(T const& azi_a1_p, T const& azi_a1_a2)
|
||||
{
|
||||
T const pi = math::pi<T>();
|
||||
T const two_pi = math::two_pi<T>();
|
||||
|
||||
// instead of the formula from XTD
|
||||
//calc_t a_diff = asin(sin(azi_a1_p - azi_a1_a2));
|
||||
|
||||
T a_diff = azi_a1_p - azi_a1_a2;
|
||||
// normalize, angle in [-pi, pi]
|
||||
while (a_diff > pi)
|
||||
a_diff -= two_pi;
|
||||
while (a_diff < -pi)
|
||||
a_diff += two_pi;
|
||||
|
||||
// NOTE: in general it shouldn't be required to support the pi/-pi case
|
||||
// because in non-cartesian systems it makes sense to check the side
|
||||
// only "between" the endpoints.
|
||||
// However currently the winding strategy calls the side strategy
|
||||
// for vertical segments to check if the point is "between the endpoints.
|
||||
// This could be avoided since the side strategy is not required for that
|
||||
// because meridian is the shortest path. So a difference of
|
||||
// longitudes would be sufficient (of course normalized to [-pi, pi]).
|
||||
|
||||
// NOTE: with the above said, the pi/-pi check is temporary
|
||||
// however in case if this was required
|
||||
// the geodesics on ellipsoid aren't "symmetrical"
|
||||
// therefore instead of comparing a_diff to pi and -pi
|
||||
// one should probably use inverse azimuths and compare
|
||||
// the difference to 0 as well
|
||||
|
||||
// positive azimuth is on the right side
|
||||
return math::equals(a_diff, 0)
|
||||
|| math::equals(a_diff, pi)
|
||||
|| math::equals(a_diff, -pi) ? 0
|
||||
: a_diff > 0 ? -1 // right
|
||||
: 1; // left
|
||||
}
|
||||
|
||||
} // namespace formula
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
@@ -20,9 +20,8 @@
|
||||
#include <boost/geometry/util/condition.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/flattening.hpp>
|
||||
|
||||
#include <boost/geometry/formulas/differential_quantities.hpp>
|
||||
#include <boost/geometry/formulas/flattening.hpp>
|
||||
#include <boost/geometry/formulas/result_direct.hpp>
|
||||
|
||||
|
||||
@@ -82,7 +81,7 @@ public:
|
||||
|
||||
CT const a = CT(get_radius<0>(spheroid));
|
||||
CT const b = CT(get_radius<2>(spheroid));
|
||||
CT const f = detail::flattening<CT>(spheroid);
|
||||
CT const f = formula::flattening<CT>(spheroid);
|
||||
CT const one_minus_f = c1 - f;
|
||||
|
||||
CT const pi = math::pi<CT>();
|
||||
|
||||
@@ -20,9 +20,8 @@
|
||||
#include <boost/geometry/util/condition.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/flattening.hpp>
|
||||
|
||||
#include <boost/geometry/formulas/differential_quantities.hpp>
|
||||
#include <boost/geometry/formulas/flattening.hpp>
|
||||
#include <boost/geometry/formulas/result_inverse.hpp>
|
||||
|
||||
|
||||
@@ -78,7 +77,7 @@ public:
|
||||
CT const c4 = 4;
|
||||
|
||||
CT const pi_half = math::pi<CT>() / c2;
|
||||
CT const f = detail::flattening<CT>(spheroid);
|
||||
CT const f = formula::flattening<CT>(spheroid);
|
||||
CT const one_minus_f = c1 - f;
|
||||
|
||||
// CT const tan_theta1 = one_minus_f * tan(lat1);
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
#ifndef BOOST_GEOMETRY_FORMULAS_MAXIMUM_LATITUDE_HPP
|
||||
#define BOOST_GEOMETRY_FORMULAS_MAXIMUM_LATITUDE_HPP
|
||||
|
||||
#include <boost/geometry/formulas/spherical.hpp>
|
||||
#include <boost/geometry/algorithms/detail/flattening.hpp>
|
||||
#include <boost/geometry/core/srs.hpp>
|
||||
#include <boost/geometry/formulas/flattening.hpp>
|
||||
#include <boost/geometry/formulas/spherical.hpp>
|
||||
#include <boost/mpl/assert.hpp>
|
||||
|
||||
namespace boost { namespace geometry { namespace formula
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
T2 const& alp1,
|
||||
Spheroid const& spheroid)
|
||||
{
|
||||
CT const f = detail::flattening<CT>(spheroid);
|
||||
CT const f = formula::flattening<CT>(spheroid);
|
||||
|
||||
CT const e2 = f * (CT(2) - f);
|
||||
CT const sin_alp1 = sin(alp1);
|
||||
@@ -76,7 +76,7 @@ public:
|
||||
T2 const& alp1,
|
||||
Spheroid const& spheroid)
|
||||
{
|
||||
CT const f = detail::flattening<CT>(spheroid);
|
||||
CT const f = formula::flattening<CT>(spheroid);
|
||||
|
||||
CT const one_minus_f = (CT(1) - f);
|
||||
|
||||
|
||||
@@ -23,9 +23,8 @@
|
||||
#include <boost/geometry/util/condition.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/flattening.hpp>
|
||||
|
||||
#include <boost/geometry/formulas/differential_quantities.hpp>
|
||||
#include <boost/geometry/formulas/flattening.hpp>
|
||||
#include <boost/geometry/formulas/result_direct.hpp>
|
||||
|
||||
|
||||
@@ -85,7 +84,7 @@ public:
|
||||
|
||||
CT const radius_a = CT(get_radius<0>(spheroid));
|
||||
CT const radius_b = CT(get_radius<2>(spheroid));
|
||||
CT const flattening = geometry::detail::flattening<CT>(spheroid);
|
||||
CT const flattening = formula::flattening<CT>(spheroid);
|
||||
|
||||
CT const sin_azimuth12 = sin(azimuth12);
|
||||
CT const cos_azimuth12 = cos(azimuth12);
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2014, 2016.
|
||||
// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2014, 2016, 2017.
|
||||
// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@@ -23,9 +23,8 @@
|
||||
#include <boost/geometry/util/condition.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/flattening.hpp>
|
||||
|
||||
#include <boost/geometry/formulas/differential_quantities.hpp>
|
||||
#include <boost/geometry/formulas/flattening.hpp>
|
||||
#include <boost/geometry/formulas/result_inverse.hpp>
|
||||
|
||||
|
||||
@@ -41,7 +40,7 @@ namespace boost { namespace geometry { namespace formula
|
||||
\brief The solution of the inverse problem of geodesics on latlong coordinates, after Vincenty, 1975
|
||||
\author See
|
||||
- http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf
|
||||
- http://www.icsm.gov.au/gda/gdav2.3.pdf
|
||||
- http://www.icsm.gov.au/gda/gda-v_2.4.pdf
|
||||
\author Adapted from various implementations to get it close to the original document
|
||||
- http://www.movable-type.co.uk/scripts/LatLongVincenty.html
|
||||
- http://exogen.case.edu/projects/geopy/source/geopy.distance.html
|
||||
@@ -99,10 +98,10 @@ public:
|
||||
|
||||
CT const radius_a = CT(get_radius<0>(spheroid));
|
||||
CT const radius_b = CT(get_radius<2>(spheroid));
|
||||
CT const flattening = geometry::detail::flattening<CT>(spheroid);
|
||||
CT const f = formula::flattening<CT>(spheroid);
|
||||
|
||||
// U: reduced latitude, defined by tan U = (1-f) tan phi
|
||||
CT const one_min_f = c1 - flattening;
|
||||
CT const one_min_f = c1 - f;
|
||||
CT const tan_U1 = one_min_f * tan(lat1); // above (1)
|
||||
CT const tan_U2 = one_min_f * tan(lat2); // above (1)
|
||||
|
||||
@@ -113,8 +112,9 @@ public:
|
||||
CT const cos_U1 = c1 / temp_den_U1;
|
||||
CT const cos_U2 = c1 / temp_den_U2;
|
||||
// sin = tan / sqrt(1 + tan^2)
|
||||
CT const sin_U1 = tan_U1 / temp_den_U1;
|
||||
CT const sin_U2 = tan_U2 / temp_den_U2;
|
||||
// sin = tan * cos
|
||||
CT const sin_U1 = tan_U1 * cos_U1;
|
||||
CT const sin_U2 = tan_U2 * cos_U2;
|
||||
|
||||
// calculate sin U and cos U directly
|
||||
//CT const U1 = atan(tan_U1);
|
||||
@@ -130,7 +130,8 @@ public:
|
||||
CT sin_sigma;
|
||||
CT sin_alpha;
|
||||
CT cos2_alpha;
|
||||
CT cos2_sigma_m;
|
||||
CT cos_2sigma_m;
|
||||
CT cos2_2sigma_m;
|
||||
CT sigma;
|
||||
|
||||
int counter = 0; // robustness
|
||||
@@ -144,12 +145,13 @@ public:
|
||||
CT cos_sigma = sin_U1 * sin_U2 + cos_U1 * cos_U2 * cos_lambda; // (15)
|
||||
sin_alpha = cos_U1 * cos_U2 * sin_lambda / sin_sigma; // (17)
|
||||
cos2_alpha = c1 - math::sqr(sin_alpha);
|
||||
cos2_sigma_m = math::equals(cos2_alpha, 0) ? 0 : cos_sigma - c2 * sin_U1 * sin_U2 / cos2_alpha; // (18)
|
||||
cos_2sigma_m = math::equals(cos2_alpha, 0) ? 0 : cos_sigma - c2 * sin_U1 * sin_U2 / cos2_alpha; // (18)
|
||||
cos2_2sigma_m = math::sqr(cos_2sigma_m);
|
||||
|
||||
CT C = flattening/c16 * cos2_alpha * (c4 + flattening * (c4 - c3 * cos2_alpha)); // (10)
|
||||
CT C = f/c16 * cos2_alpha * (c4 + f * (c4 - c3 * cos2_alpha)); // (10)
|
||||
sigma = atan2(sin_sigma, cos_sigma); // (16)
|
||||
lambda = L + (c1 - C) * flattening * sin_alpha *
|
||||
(sigma + C * sin_sigma * ( cos2_sigma_m + C * cos_sigma * (-c1 + c2 * math::sqr(cos2_sigma_m)))); // (11)
|
||||
lambda = L + (c1 - C) * f * sin_alpha *
|
||||
(sigma + C * sin_sigma * (cos_2sigma_m + C * cos_sigma * (-c1 + c2 * cos2_2sigma_m))); // (11)
|
||||
|
||||
++counter; // robustness
|
||||
|
||||
@@ -182,8 +184,10 @@ public:
|
||||
|
||||
CT A = c1 + sqr_u/c16384 * (c4096 + sqr_u * (-c768 + sqr_u * (c320 - c175 * sqr_u))); // (3)
|
||||
CT B = sqr_u/c1024 * (c256 + sqr_u * ( -c128 + sqr_u * (c74 - c47 * sqr_u))); // (4)
|
||||
CT delta_sigma = B * sin_sigma * ( cos2_sigma_m + (B/c4) * (cos(sigma)* (-c1 + c2 * cos2_sigma_m)
|
||||
- (B/c6) * cos2_sigma_m * (-c3 + c4 * math::sqr(sin_sigma)) * (-c3 + c4 * cos2_sigma_m))); // (6)
|
||||
CT const cos_sigma = cos(sigma);
|
||||
CT const sin2_sigma = math::sqr(sin_sigma);
|
||||
CT delta_sigma = B * sin_sigma * (cos_2sigma_m + (B/c4) * (cos_sigma* (-c1 + c2 * cos2_2sigma_m)
|
||||
- (B/c6) * cos_2sigma_m * (-c3 + c4 * sin2_sigma) * (-c3 + c4 * cos2_2sigma_m))); // (6)
|
||||
|
||||
result.distance = radius_b * A * (sigma - delta_sigma); // (19)
|
||||
}
|
||||
@@ -206,7 +210,7 @@ public:
|
||||
typedef differential_quantities<CT, EnableReducedLength, EnableGeodesicScale, 2> quantities;
|
||||
quantities::apply(lon1, lat1, lon2, lat2,
|
||||
result.azimuth, result.reverse_azimuth,
|
||||
radius_b, flattening,
|
||||
radius_b, f,
|
||||
result.reduced_length, result.geodesic_scale);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
// Boost.Geometry Index
|
||||
//
|
||||
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_NTH_ELEMENT_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_NTH_ELEMENT_HPP
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace boost { namespace geometry { namespace index { namespace detail {
|
||||
|
||||
// See https://svn.boost.org/trac/boost/ticket/12861
|
||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58800
|
||||
// https://gcc.gnu.org/develop.html#timeline
|
||||
// 20120920 4.7.2 - no bug
|
||||
// 20130322 4.8.0 - no bug
|
||||
// 20130411 4.7.3 - no bug
|
||||
// 20130531 4.8.1 - no bug
|
||||
// 20131016 4.8.2 - bug
|
||||
// 20140422 4.9.0 - fixed
|
||||
// 20140522 4.8.3 - fixed
|
||||
// 20140612 4.7.4 - fixed
|
||||
// 20140716 4.9.1 - fixed
|
||||
#if defined(__GLIBCXX__) && (__GLIBCXX__ == 20131016)
|
||||
|
||||
#warning "std::nth_element replaced with std::sort, libstdc++ bug workaround.";
|
||||
|
||||
template <typename RandomIt>
|
||||
void nth_element(RandomIt first, RandomIt , RandomIt last)
|
||||
{
|
||||
std::sort(first, last);
|
||||
}
|
||||
|
||||
template <typename RandomIt, typename Compare>
|
||||
void nth_element(RandomIt first, RandomIt , RandomIt last, Compare comp)
|
||||
{
|
||||
std::sort(first, last, comp);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template <typename RandomIt>
|
||||
void nth_element(RandomIt first, RandomIt nth, RandomIt last)
|
||||
{
|
||||
std::nth_element(first, nth, last);
|
||||
}
|
||||
|
||||
template <typename RandomIt, typename Compare>
|
||||
void nth_element(RandomIt first, RandomIt nth, RandomIt last, Compare comp)
|
||||
{
|
||||
std::nth_element(first, nth, last, comp);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}}}} // namespace boost::geometry::index::detail
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_NTH_ELEMENT_HPP
|
||||
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// R-tree initial packing
|
||||
//
|
||||
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include <boost/geometry/algorithms/expand.hpp>
|
||||
#include <boost/geometry/index/detail/algorithms/bounds.hpp>
|
||||
#include <boost/geometry/index/detail/algorithms/nth_element.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
|
||||
|
||||
@@ -67,7 +68,7 @@ struct nth_element_and_half_boxes
|
||||
{
|
||||
if ( I == dim_index )
|
||||
{
|
||||
std::nth_element(first, median, last, point_entries_comparer<I>());
|
||||
index::detail::nth_element(first, median, last, point_entries_comparer<I>());
|
||||
|
||||
geometry::convert(box, left);
|
||||
geometry::convert(box, right);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// R-tree R*-tree next node choosing algorithm implementation
|
||||
//
|
||||
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include <boost/geometry/index/detail/algorithms/content.hpp>
|
||||
#include <boost/geometry/index/detail/algorithms/intersection_content.hpp>
|
||||
#include <boost/geometry/index/detail/algorithms/nth_element.hpp>
|
||||
#include <boost/geometry/index/detail/algorithms/union_content.hpp>
|
||||
|
||||
#include <boost/geometry/index/detail/rtree/node/node.hpp>
|
||||
@@ -112,7 +113,7 @@ private:
|
||||
first_n_children_count = overlap_cost_threshold;
|
||||
// rearrange by content_diff
|
||||
// in order to calculate nearly minimum overlap cost
|
||||
std::nth_element(children_contents.begin(), children_contents.begin() + first_n_children_count, children_contents.end(), content_diff_less);
|
||||
index::detail::nth_element(children_contents.begin(), children_contents.begin() + first_n_children_count, children_contents.end(), content_diff_less);
|
||||
}
|
||||
|
||||
// calculate minimum or nearly minimum overlap cost
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// R-tree R*-tree split algorithm implementation
|
||||
//
|
||||
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -12,8 +12,9 @@
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_REDISTRIBUTE_ELEMENTS_HPP
|
||||
|
||||
#include <boost/geometry/index/detail/algorithms/intersection_content.hpp>
|
||||
#include <boost/geometry/index/detail/algorithms/union_content.hpp>
|
||||
#include <boost/geometry/index/detail/algorithms/margin.hpp>
|
||||
#include <boost/geometry/index/detail/algorithms/nth_element.hpp>
|
||||
#include <boost/geometry/index/detail/algorithms/union_content.hpp>
|
||||
|
||||
#include <boost/geometry/index/detail/bounded_view.hpp>
|
||||
|
||||
@@ -122,8 +123,9 @@ struct choose_split_axis_and_index_for_corner
|
||||
// {
|
||||
// typename Elements::iterator f = elements_copy.begin() + index_first;
|
||||
// typename Elements::iterator l = elements_copy.begin() + index_last;
|
||||
// std::nth_element(elements_copy.begin(), f, elements_copy.end(), elements_less); // MAY THROW, BASIC (copy)
|
||||
// std::nth_element(f, l, elements_copy.end(), elements_less); // MAY THROW, BASIC (copy)
|
||||
// // NOTE: for stdlibc++ shipped with gcc 4.8.2 std::nth_element is replaced with std::sort anyway
|
||||
// index::detail::nth_element(elements_copy.begin(), f, elements_copy.end(), elements_less); // MAY THROW, BASIC (copy)
|
||||
// index::detail::nth_element(f, l, elements_copy.end(), elements_less); // MAY THROW, BASIC (copy)
|
||||
// std::sort(f, l, elements_less); // MAY THROW, BASIC (copy)
|
||||
// }
|
||||
|
||||
@@ -349,7 +351,7 @@ struct nth_element
|
||||
typedef typename tag<indexable_type>::type indexable_tag;
|
||||
|
||||
element_axis_corner_less<element_type, Translator, indexable_tag, Corner, I> less(tr);
|
||||
std::nth_element(elements.begin(), elements.begin() + index, elements.end(), less); // MAY THROW, BASIC (copy)
|
||||
index::detail::nth_element(elements.begin(), elements.begin() + index, elements.end(), less); // MAY THROW, BASIC (copy)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// R-tree algorithms parameters
|
||||
//
|
||||
// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
|
||||
// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -162,8 +162,8 @@ public:
|
||||
\param max_elements Maximum number of elements in nodes.
|
||||
\param min_elements Minimum number of elements in nodes. Default: 0.3*Max.
|
||||
*/
|
||||
dynamic_linear(size_t max_elements,
|
||||
size_t min_elements = detail::default_min_elements_d())
|
||||
explicit dynamic_linear(size_t max_elements,
|
||||
size_t min_elements = detail::default_min_elements_d())
|
||||
: m_max_elements(max_elements)
|
||||
, m_min_elements(detail::default_min_elements_d_calc(max_elements, min_elements))
|
||||
{
|
||||
@@ -191,8 +191,8 @@ public:
|
||||
\param max_elements Maximum number of elements in nodes.
|
||||
\param min_elements Minimum number of elements in nodes. Default: 0.3*Max.
|
||||
*/
|
||||
dynamic_quadratic(size_t max_elements,
|
||||
size_t min_elements = detail::default_min_elements_d())
|
||||
explicit dynamic_quadratic(size_t max_elements,
|
||||
size_t min_elements = detail::default_min_elements_d())
|
||||
: m_max_elements(max_elements)
|
||||
, m_min_elements(detail::default_min_elements_d_calc(max_elements, min_elements))
|
||||
{
|
||||
@@ -228,10 +228,10 @@ public:
|
||||
nearly minimum overlap cost, otherwise all leafs are analyzed
|
||||
and true minimum overlap cost is calculated. Default: 32.
|
||||
*/
|
||||
dynamic_rstar(size_t max_elements,
|
||||
size_t min_elements = detail::default_min_elements_d(),
|
||||
size_t reinserted_elements = detail::default_rstar_reinserted_elements_d(),
|
||||
size_t overlap_cost_threshold = 32)
|
||||
explicit dynamic_rstar(size_t max_elements,
|
||||
size_t min_elements = detail::default_min_elements_d(),
|
||||
size_t reinserted_elements = detail::default_rstar_reinserted_elements_d(),
|
||||
size_t overlap_cost_threshold = 32)
|
||||
: m_max_elements(max_elements)
|
||||
, m_min_elements(detail::default_min_elements_d_calc(max_elements, min_elements))
|
||||
, m_reinserted_elements(detail::default_rstar_reinserted_elements_d_calc(max_elements, reinserted_elements))
|
||||
|
||||
@@ -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 2016.
|
||||
// Modifications copyright (c) 2016, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2016, 2017.
|
||||
// Modifications copyright (c) 2016-2017, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
//#include <boost/geometry/arithmetic/determinant.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/strategies/area.hpp>
|
||||
#include <boost/geometry/util/select_most_precise.hpp>
|
||||
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
#include <boost/geometry/util/select_calculation_type.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/area_surveyor.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
|
||||
#include <boost/geometry/strategies/covered_by.hpp>
|
||||
#include <boost/geometry/strategies/intersection.hpp>
|
||||
@@ -95,6 +97,39 @@ struct relate_cartesian_segments
|
||||
return strategy_type();
|
||||
}
|
||||
|
||||
template <typename Geometry>
|
||||
struct area_strategy
|
||||
{
|
||||
typedef area::surveyor
|
||||
<
|
||||
typename point_type<Geometry>::type,
|
||||
CalculationType
|
||||
> type;
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
static inline typename area_strategy<Geometry>::type get_area_strategy()
|
||||
{
|
||||
typedef typename area_strategy<Geometry>::type strategy_type;
|
||||
return strategy_type();
|
||||
}
|
||||
|
||||
template <typename Geometry>
|
||||
struct distance_strategy
|
||||
{
|
||||
typedef distance::pythagoras
|
||||
<
|
||||
CalculationType
|
||||
> type;
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
static inline typename distance_strategy<Geometry>::type get_distance_strategy()
|
||||
{
|
||||
typedef typename distance_strategy<Geometry>::type strategy_type;
|
||||
return strategy_type();
|
||||
}
|
||||
|
||||
template <typename CoordinateType, typename SegmentRatio>
|
||||
struct segment_intersection_info
|
||||
{
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2016 Oracle and/or its affiliates.
|
||||
// Copyright (c) 2016-2017 Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Vissarion Fisikopoulos, 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
|
||||
@@ -11,6 +12,7 @@
|
||||
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_AREA_HPP
|
||||
|
||||
#include <boost/geometry/formulas/area_formulas.hpp>
|
||||
#include <boost/geometry/formulas/flattening.hpp>
|
||||
#include <boost/geometry/formulas/thomas_inverse.hpp>
|
||||
#include <boost/math/special_functions/atanh.hpp>
|
||||
|
||||
@@ -21,12 +23,26 @@ namespace strategy { namespace area
|
||||
{
|
||||
|
||||
/*!
|
||||
\brief Geographic area calculation by trapezoidal rule plus integral
|
||||
approximation that gives the ellipsoidal correction
|
||||
|
||||
\brief Geographic area calculation
|
||||
\ingroup strategies
|
||||
\details Geographic area calculation by trapezoidal rule plus integral
|
||||
approximation that gives the ellipsoidal correction
|
||||
\tparam PointOfSegment \tparam_segment_point
|
||||
\tparam Inverse Formula used to calculate azimuths
|
||||
\tparam SeriesOrder The order of approximation of the geodesic integral
|
||||
\tparam ExpandEpsN Switch between two kinds of approximation (series in eps and n v.s. series in k^2 and e'^2)
|
||||
\tparam LongSegment Enables special handling of long segments
|
||||
\tparam Spheroid The spheroid model
|
||||
\tparam CalculationType \tparam_calculation
|
||||
\author See
|
||||
- Danielsen JS, The area under the geodesic. Surv Rev 30(232): 61–66, 1989
|
||||
- Charles F.F Karney, Algorithms for geodesics, 2011 https://arxiv.org/pdf/1109.4448.pdf
|
||||
|
||||
\qbk{
|
||||
[heading See also]
|
||||
[link geometry.reference.algorithms.area.area_2_with_strategy area (with strategy)]
|
||||
}
|
||||
*/
|
||||
|
||||
template
|
||||
<
|
||||
typename PointOfSegment,
|
||||
@@ -87,8 +103,8 @@ protected :
|
||||
inline spheroid_constants(SpheroidType spheroid)
|
||||
: m_spheroid(spheroid)
|
||||
, m_a2(math::sqr(get_radius<0>(spheroid)))
|
||||
, m_e2(detail::flattening<CT>(spheroid)
|
||||
* (CT(2.0) - CT(detail::flattening<CT>(spheroid))))
|
||||
, m_e2(formula::flattening<CT>(spheroid)
|
||||
* (CT(2.0) - CT(formula::flattening<CT>(spheroid))))
|
||||
, m_ep2(m_e2 / (CT(1.0) - m_e2))
|
||||
, m_ep(math::sqrt(m_ep2))
|
||||
, m_c2((m_a2 / CT(2.0)) +
|
||||
|
||||
194
include/boost/geometry/strategies/geographic/distance.hpp
Normal file
194
include/boost/geometry/strategies/geographic/distance.hpp
Normal file
@@ -0,0 +1,194 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2016 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2014-2017.
|
||||
// Modifications copyright (c) 2014-2017 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)
|
||||
|
||||
|
||||
#ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_HPP
|
||||
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/core/radian_access.hpp>
|
||||
#include <boost/geometry/core/radius.hpp>
|
||||
#include <boost/geometry/core/srs.hpp>
|
||||
|
||||
#include <boost/geometry/formulas/andoyer_inverse.hpp>
|
||||
#include <boost/geometry/formulas/flattening.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/promote_floating_point.hpp>
|
||||
#include <boost/geometry/util/select_calculation_type.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
namespace strategy { namespace distance
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
template<typename, bool, bool, bool, bool, bool> class InverseFormula = formula::andoyer_inverse,
|
||||
typename Spheroid = srs::spheroid<double>,
|
||||
typename CalculationType = void
|
||||
>
|
||||
class geographic
|
||||
{
|
||||
public :
|
||||
template <typename Point1, typename Point2>
|
||||
struct calculation_type
|
||||
: promote_floating_point
|
||||
<
|
||||
typename select_calculation_type
|
||||
<
|
||||
Point1,
|
||||
Point2,
|
||||
CalculationType
|
||||
>::type
|
||||
>
|
||||
{};
|
||||
|
||||
typedef Spheroid model_type;
|
||||
|
||||
inline geographic()
|
||||
: m_spheroid()
|
||||
{}
|
||||
|
||||
explicit inline geographic(Spheroid const& spheroid)
|
||||
: m_spheroid(spheroid)
|
||||
{}
|
||||
|
||||
template <typename Point1, typename Point2>
|
||||
inline typename calculation_type<Point1, Point2>::type
|
||||
apply(Point1 const& point1, Point2 const& point2) const
|
||||
{
|
||||
return InverseFormula
|
||||
<
|
||||
typename calculation_type<Point1, Point2>::type,
|
||||
true, false, false, false, false
|
||||
>::apply(get_as_radian<0>(point1), get_as_radian<1>(point1),
|
||||
get_as_radian<0>(point2), get_as_radian<1>(point2),
|
||||
m_spheroid).distance;
|
||||
}
|
||||
|
||||
inline Spheroid const& model() const
|
||||
{
|
||||
return m_spheroid;
|
||||
}
|
||||
|
||||
private :
|
||||
Spheroid m_spheroid;
|
||||
};
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
namespace services
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
template<typename, bool, bool, bool, bool, bool> class Formula,
|
||||
typename Spheroid,
|
||||
typename CalculationType
|
||||
>
|
||||
struct tag<geographic<Formula, Spheroid, CalculationType> >
|
||||
{
|
||||
typedef strategy_tag_distance_point_point type;
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
template<typename, bool, bool, bool, bool, bool> class Formula,
|
||||
typename Spheroid,
|
||||
typename CalculationType,
|
||||
typename P1,
|
||||
typename P2
|
||||
>
|
||||
struct return_type<geographic<Formula, Spheroid, CalculationType>, P1, P2>
|
||||
: geographic<Formula, Spheroid, CalculationType>::template calculation_type<P1, P2>
|
||||
{};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
template<typename, bool, bool, bool, bool, bool> class Formula,
|
||||
typename Spheroid,
|
||||
typename CalculationType
|
||||
>
|
||||
struct comparable_type<geographic<Formula, Spheroid, CalculationType> >
|
||||
{
|
||||
typedef geographic<Formula, Spheroid, CalculationType> type;
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
template<typename, bool, bool, bool, bool, bool> class Formula,
|
||||
typename Spheroid,
|
||||
typename CalculationType
|
||||
>
|
||||
struct get_comparable<geographic<Formula, Spheroid, CalculationType> >
|
||||
{
|
||||
static inline geographic<Formula, Spheroid, CalculationType>
|
||||
apply(geographic<Formula, Spheroid, CalculationType> const& input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
template<typename, bool, bool, bool, bool, bool> class Formula,
|
||||
typename Spheroid,
|
||||
typename CalculationType,
|
||||
typename P1,
|
||||
typename P2
|
||||
>
|
||||
struct result_from_distance<geographic<Formula, Spheroid, CalculationType>, P1, P2>
|
||||
{
|
||||
template <typename T>
|
||||
static inline typename return_type<geographic<Formula, Spheroid, CalculationType>, P1, P2>::type
|
||||
apply(geographic<Formula, Spheroid, CalculationType> const& , T const& value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Point1, typename Point2>
|
||||
struct default_strategy<point_tag, point_tag, Point1, Point2, geographic_tag, geographic_tag>
|
||||
{
|
||||
typedef strategy::distance::geographic
|
||||
<
|
||||
formula::andoyer_inverse,
|
||||
srs::spheroid
|
||||
<
|
||||
typename select_coordinate_type<Point1, Point2>::type
|
||||
>
|
||||
> type;
|
||||
};
|
||||
|
||||
|
||||
} // namespace services
|
||||
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
|
||||
|
||||
}} // namespace strategy::distance
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_HPP
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
// Copyright (c) 2007-2016 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2014, 2016.
|
||||
// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2014, 2017.
|
||||
// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@@ -11,24 +11,13 @@
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_ANDOYER_HPP
|
||||
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_ANDOYER_HPP
|
||||
#ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_DETAIL_HPP
|
||||
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_DETAIL_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/core/radian_access.hpp>
|
||||
#include <boost/geometry/core/radius.hpp>
|
||||
#include <boost/geometry/core/srs.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/flattening.hpp>
|
||||
|
||||
#include <boost/geometry/formulas/andoyer_inverse.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/promote_floating_point.hpp>
|
||||
#include <boost/geometry/util/select_calculation_type.hpp>
|
||||
#include <boost/geometry/strategies/geographic/distance.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -61,51 +50,24 @@ template
|
||||
typename CalculationType = void
|
||||
>
|
||||
class andoyer
|
||||
: public strategy::distance::geographic
|
||||
<
|
||||
formula::andoyer_inverse, Spheroid, CalculationType
|
||||
>
|
||||
{
|
||||
typedef strategy::distance::geographic
|
||||
<
|
||||
formula::andoyer_inverse, Spheroid, CalculationType
|
||||
> base_type;
|
||||
|
||||
public :
|
||||
template <typename Point1, typename Point2>
|
||||
struct calculation_type
|
||||
: promote_floating_point
|
||||
<
|
||||
typename select_calculation_type
|
||||
<
|
||||
Point1,
|
||||
Point2,
|
||||
CalculationType
|
||||
>::type
|
||||
>
|
||||
{};
|
||||
|
||||
typedef Spheroid model_type;
|
||||
|
||||
inline andoyer()
|
||||
: m_spheroid()
|
||||
: base_type()
|
||||
{}
|
||||
|
||||
explicit inline andoyer(Spheroid const& spheroid)
|
||||
: m_spheroid(spheroid)
|
||||
: base_type(spheroid)
|
||||
{}
|
||||
|
||||
template <typename Point1, typename Point2>
|
||||
inline typename calculation_type<Point1, Point2>::type
|
||||
apply(Point1 const& point1, Point2 const& point2) const
|
||||
{
|
||||
return geometry::formula::andoyer_inverse
|
||||
<
|
||||
typename calculation_type<Point1, Point2>::type,
|
||||
true, false
|
||||
>::apply(get_as_radian<0>(point1), get_as_radian<1>(point1),
|
||||
get_as_radian<0>(point2), get_as_radian<1>(point2),
|
||||
m_spheroid).distance;
|
||||
}
|
||||
|
||||
inline Spheroid const& model() const
|
||||
{
|
||||
return m_spheroid;
|
||||
}
|
||||
|
||||
private :
|
||||
Spheroid m_spheroid;
|
||||
};
|
||||
|
||||
|
||||
@@ -154,19 +116,6 @@ struct result_from_distance<andoyer<Spheroid, CalculationType>, P1, P2>
|
||||
};
|
||||
|
||||
|
||||
template <typename Point1, typename Point2>
|
||||
struct default_strategy<point_tag, point_tag, Point1, Point2, geographic_tag, geographic_tag>
|
||||
{
|
||||
typedef strategy::distance::andoyer
|
||||
<
|
||||
srs::spheroid
|
||||
<
|
||||
typename select_coordinate_type<Point1, Point2>::type
|
||||
>
|
||||
> type;
|
||||
};
|
||||
|
||||
|
||||
} // namespace services
|
||||
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
|
||||
@@ -177,4 +126,4 @@ struct default_strategy<point_tag, point_tag, Point1, Point2, geographic_tag, ge
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_ANDOYER_HPP
|
||||
#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_DETAIL_HPP
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2016.
|
||||
// Modifications copyright (c) 2015-2016 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2015-2017.
|
||||
// Modifications copyright (c) 2015-2017 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@@ -15,16 +15,11 @@
|
||||
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_THOMAS_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/core/radian_access.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
|
||||
#include <boost/geometry/util/promote_floating_point.hpp>
|
||||
#include <boost/geometry/util/select_calculation_type.hpp>
|
||||
|
||||
#include <boost/geometry/formulas/thomas_inverse.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/geographic/distance.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
@@ -49,53 +44,24 @@ template
|
||||
typename CalculationType = void
|
||||
>
|
||||
class thomas
|
||||
: public strategy::distance::geographic
|
||||
<
|
||||
formula::thomas_inverse, Spheroid, CalculationType
|
||||
>
|
||||
{
|
||||
typedef strategy::distance::geographic
|
||||
<
|
||||
formula::thomas_inverse, Spheroid, CalculationType
|
||||
> base_type;
|
||||
|
||||
public :
|
||||
template <typename Point1, typename Point2>
|
||||
struct calculation_type
|
||||
: promote_floating_point
|
||||
<
|
||||
typename select_calculation_type
|
||||
<
|
||||
Point1,
|
||||
Point2,
|
||||
CalculationType
|
||||
>::type
|
||||
>
|
||||
{};
|
||||
|
||||
typedef Spheroid model_type;
|
||||
|
||||
inline thomas()
|
||||
: m_spheroid()
|
||||
: base_type()
|
||||
{}
|
||||
|
||||
explicit inline thomas(Spheroid const& spheroid)
|
||||
: m_spheroid(spheroid)
|
||||
: base_type(spheroid)
|
||||
{}
|
||||
|
||||
template <typename Point1, typename Point2>
|
||||
inline typename calculation_type<Point1, Point2>::type
|
||||
apply(Point1 const& point1, Point2 const& point2) const
|
||||
{
|
||||
return geometry::formula::thomas_inverse
|
||||
<
|
||||
typename calculation_type<Point1, Point2>::type,
|
||||
true, false
|
||||
>::apply(get_as_radian<0>(point1),
|
||||
get_as_radian<1>(point1),
|
||||
get_as_radian<0>(point2),
|
||||
get_as_radian<1>(point2),
|
||||
m_spheroid).distance;
|
||||
}
|
||||
|
||||
inline Spheroid const& model() const
|
||||
{
|
||||
return m_spheroid;
|
||||
}
|
||||
|
||||
private :
|
||||
Spheroid m_spheroid;
|
||||
};
|
||||
|
||||
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2014, 2016.
|
||||
// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2014-2017.
|
||||
// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@@ -15,16 +15,11 @@
|
||||
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_VINCENTY_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/core/radian_access.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
|
||||
#include <boost/geometry/util/promote_floating_point.hpp>
|
||||
#include <boost/geometry/util/select_calculation_type.hpp>
|
||||
|
||||
#include <boost/geometry/formulas/vincenty_inverse.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/geographic/distance.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
@@ -51,53 +46,24 @@ template
|
||||
typename CalculationType = void
|
||||
>
|
||||
class vincenty
|
||||
: public strategy::distance::geographic
|
||||
<
|
||||
formula::vincenty_inverse, Spheroid, CalculationType
|
||||
>
|
||||
{
|
||||
public :
|
||||
template <typename Point1, typename Point2>
|
||||
struct calculation_type
|
||||
: promote_floating_point
|
||||
<
|
||||
typename select_calculation_type
|
||||
<
|
||||
Point1,
|
||||
Point2,
|
||||
CalculationType
|
||||
>::type
|
||||
>
|
||||
{};
|
||||
|
||||
typedef Spheroid model_type;
|
||||
typedef strategy::distance::geographic
|
||||
<
|
||||
formula::vincenty_inverse, Spheroid, CalculationType
|
||||
> base_type;
|
||||
|
||||
public:
|
||||
inline vincenty()
|
||||
: m_spheroid()
|
||||
: base_type()
|
||||
{}
|
||||
|
||||
explicit inline vincenty(Spheroid const& spheroid)
|
||||
: m_spheroid(spheroid)
|
||||
: base_type(spheroid)
|
||||
{}
|
||||
|
||||
template <typename Point1, typename Point2>
|
||||
inline typename calculation_type<Point1, Point2>::type
|
||||
apply(Point1 const& point1, Point2 const& point2) const
|
||||
{
|
||||
return geometry::formula::vincenty_inverse
|
||||
<
|
||||
typename calculation_type<Point1, Point2>::type,
|
||||
true, false
|
||||
>::apply(get_as_radian<0>(point1),
|
||||
get_as_radian<1>(point1),
|
||||
get_as_radian<0>(point2),
|
||||
get_as_radian<1>(point2),
|
||||
m_spheroid).distance;
|
||||
}
|
||||
|
||||
inline Spheroid const& model() const
|
||||
{
|
||||
return m_spheroid;
|
||||
}
|
||||
|
||||
private :
|
||||
Spheroid m_spheroid;
|
||||
};
|
||||
|
||||
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
|
||||
@@ -0,0 +1,893 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2016-2017, 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)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_GEODESIC_INTERSECTION_HPP
|
||||
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_GEODESIC_INTERSECTION_HPP
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/radian_access.hpp>
|
||||
#include <boost/geometry/core/srs.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/assign_values.hpp>
|
||||
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/recalculate.hpp>
|
||||
|
||||
#include <boost/geometry/formulas/andoyer_inverse.hpp>
|
||||
#include <boost/geometry/formulas/sjoberg_intersection.hpp>
|
||||
#include <boost/geometry/formulas/spherical.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/concepts/point_concept.hpp>
|
||||
#include <boost/geometry/geometries/concepts/segment_concept.hpp>
|
||||
|
||||
#include <boost/geometry/policies/robustness/segment_ratio.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/geographic/area_geographic.hpp>
|
||||
#include <boost/geometry/strategies/geographic/distance.hpp>
|
||||
#include <boost/geometry/strategies/geographic/side.hpp>
|
||||
#include <boost/geometry/strategies/intersection.hpp>
|
||||
#include <boost/geometry/strategies/intersection_result.hpp>
|
||||
#include <boost/geometry/strategies/side_info.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/select_calculation_type.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
namespace strategy { namespace intersection
|
||||
{
|
||||
|
||||
// CONSIDER: Improvement of the robustness/accuracy/repeatability by
|
||||
// moving all segments to 0 longitude
|
||||
// picking latitudes closer to 0
|
||||
// etc.
|
||||
|
||||
template
|
||||
<
|
||||
typename Spheroid = srs::spheroid<double>,
|
||||
template <typename, bool, bool, bool, bool, bool> class Inverse = formula::andoyer_inverse,
|
||||
unsigned int Order = 2,
|
||||
typename CalculationType = void
|
||||
>
|
||||
struct relate_geodesic_segments
|
||||
{
|
||||
typedef side::geographic
|
||||
<
|
||||
Inverse, Spheroid, CalculationType
|
||||
> side_strategy_type;
|
||||
|
||||
inline side_strategy_type get_side_strategy()
|
||||
{
|
||||
return side_strategy_type(m_spheroid);
|
||||
}
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct point_in_geometry_strategy
|
||||
{
|
||||
typedef strategy::within::winding
|
||||
<
|
||||
typename point_type<Geometry1>::type,
|
||||
typename point_type<Geometry2>::type,
|
||||
side_strategy_type,
|
||||
CalculationType
|
||||
> type;
|
||||
};
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
inline typename point_in_geometry_strategy<Geometry1, Geometry2>::type
|
||||
get_point_in_geometry_strategy()
|
||||
{
|
||||
typedef typename point_in_geometry_strategy
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::type strategy_type;
|
||||
return strategy_type(get_side_strategy());
|
||||
}
|
||||
|
||||
template <typename Geometry>
|
||||
struct area_strategy
|
||||
{
|
||||
typedef area::geographic
|
||||
<
|
||||
typename point_type<Geometry>::type,
|
||||
Inverse,
|
||||
Order,
|
||||
true,
|
||||
false,
|
||||
Spheroid,
|
||||
CalculationType
|
||||
> type;
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
inline typename area_strategy<Geometry>::type get_area_strategy()
|
||||
{
|
||||
typedef typename area_strategy<Geometry>::type strategy_type;
|
||||
return strategy_type(m_spheroid);
|
||||
}
|
||||
|
||||
template <typename Geometry>
|
||||
struct distance_strategy
|
||||
{
|
||||
typedef distance::geographic<Inverse, Spheroid, CalculationType> type;
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
inline typename distance_strategy<Geometry>::type get_distance_strategy()
|
||||
{
|
||||
typedef typename distance_strategy<Geometry>::type strategy_type;
|
||||
return strategy_type(m_spheroid);
|
||||
}
|
||||
|
||||
enum intersection_point_flag { ipi_inters = 0, ipi_at_a1, ipi_at_a2, ipi_at_b1, ipi_at_b2 };
|
||||
|
||||
template <typename CoordinateType, typename SegmentRatio>
|
||||
struct segment_intersection_info
|
||||
{
|
||||
typedef typename select_most_precise
|
||||
<
|
||||
CoordinateType, double
|
||||
>::type promoted_type;
|
||||
|
||||
promoted_type comparable_length_a() const
|
||||
{
|
||||
return robust_ra.denominator();
|
||||
}
|
||||
|
||||
promoted_type comparable_length_b() const
|
||||
{
|
||||
return robust_rb.denominator();
|
||||
}
|
||||
|
||||
template <typename Point, typename Segment1, typename Segment2>
|
||||
void assign_a(Point& point, Segment1 const& a, Segment2 const& b) const
|
||||
{
|
||||
assign(point, a, b);
|
||||
}
|
||||
template <typename Point, typename Segment1, typename Segment2>
|
||||
void assign_b(Point& point, Segment1 const& a, Segment2 const& b) const
|
||||
{
|
||||
assign(point, a, b);
|
||||
}
|
||||
|
||||
template <typename Point, typename Segment1, typename Segment2>
|
||||
void assign(Point& point, Segment1 const& a, Segment2 const& b) const
|
||||
{
|
||||
if (ip_flag == ipi_inters)
|
||||
{
|
||||
// TODO: assign the rest of coordinates
|
||||
set_from_radian<0>(point, lon);
|
||||
set_from_radian<1>(point, lat);
|
||||
}
|
||||
else if (ip_flag == ipi_at_a1)
|
||||
{
|
||||
detail::assign_point_from_index<0>(a, point);
|
||||
}
|
||||
else if (ip_flag == ipi_at_a2)
|
||||
{
|
||||
detail::assign_point_from_index<1>(a, point);
|
||||
}
|
||||
else if (ip_flag == ipi_at_b1)
|
||||
{
|
||||
detail::assign_point_from_index<0>(b, point);
|
||||
}
|
||||
else // ip_flag == ipi_at_b2
|
||||
{
|
||||
detail::assign_point_from_index<1>(b, point);
|
||||
}
|
||||
}
|
||||
|
||||
CoordinateType lon;
|
||||
CoordinateType lat;
|
||||
SegmentRatio robust_ra;
|
||||
SegmentRatio robust_rb;
|
||||
intersection_point_flag ip_flag;
|
||||
};
|
||||
|
||||
relate_geodesic_segments(Spheroid const& spheroid = Spheroid())
|
||||
: m_spheroid(spheroid)
|
||||
{}
|
||||
|
||||
// Relate segments a and b
|
||||
template
|
||||
<
|
||||
typename Segment1,
|
||||
typename Segment2,
|
||||
typename Policy,
|
||||
typename RobustPolicy
|
||||
>
|
||||
inline typename Policy::return_type apply(Segment1 const& a, Segment2 const& b,
|
||||
Policy const& policy,
|
||||
RobustPolicy const& robust_policy) const
|
||||
{
|
||||
typedef typename point_type<Segment1>::type point1_t;
|
||||
typedef typename point_type<Segment2>::type point2_t;
|
||||
point1_t a1, a2;
|
||||
point2_t b1, b2;
|
||||
|
||||
detail::assign_point_from_index<0>(a, a1);
|
||||
detail::assign_point_from_index<1>(a, a2);
|
||||
detail::assign_point_from_index<0>(b, b1);
|
||||
detail::assign_point_from_index<1>(b, b2);
|
||||
|
||||
return apply(a, b, policy, robust_policy, a1, a2, b1, b2);
|
||||
}
|
||||
|
||||
// Relate segments a and b
|
||||
template
|
||||
<
|
||||
typename Segment1,
|
||||
typename Segment2,
|
||||
typename Policy,
|
||||
typename RobustPolicy,
|
||||
typename Point1,
|
||||
typename Point2
|
||||
>
|
||||
inline typename Policy::return_type apply(Segment1 const& a, Segment2 const& b,
|
||||
Policy const&, RobustPolicy const&,
|
||||
Point1 a1, Point1 a2, Point2 b1, Point2 b2) const
|
||||
{
|
||||
bool is_a_reversed = get<1>(a1) > get<1>(a2);
|
||||
bool is_b_reversed = get<1>(b1) > get<1>(b2);
|
||||
|
||||
if (is_a_reversed)
|
||||
{
|
||||
std::swap(a1, a2);
|
||||
}
|
||||
|
||||
if (is_b_reversed)
|
||||
{
|
||||
std::swap(b1, b2);
|
||||
}
|
||||
|
||||
return apply<Policy>(a, b, a1, a2, b1, b2, is_a_reversed, is_b_reversed);
|
||||
}
|
||||
|
||||
private:
|
||||
// Relate segments a and b
|
||||
template
|
||||
<
|
||||
typename Policy,
|
||||
typename Segment1,
|
||||
typename Segment2,
|
||||
typename Point1,
|
||||
typename Point2
|
||||
>
|
||||
inline typename Policy::return_type apply(Segment1 const& a, Segment2 const& b,
|
||||
Point1 const& a1, Point1 const& a2,
|
||||
Point2 const& b1, Point2 const& b2,
|
||||
bool is_a_reversed, bool is_b_reversed) const
|
||||
{
|
||||
BOOST_CONCEPT_ASSERT( (concepts::ConstSegment<Segment1>) );
|
||||
BOOST_CONCEPT_ASSERT( (concepts::ConstSegment<Segment2>) );
|
||||
|
||||
typedef typename select_calculation_type
|
||||
<Segment1, Segment2, CalculationType>::type calc_t;
|
||||
|
||||
// normalized spheroid
|
||||
srs::spheroid<calc_t> spheroid = normalized_spheroid<calc_t>(m_spheroid);
|
||||
|
||||
// TODO: check only 2 first coordinates here?
|
||||
using geometry::detail::equals::equals_point_point;
|
||||
bool a_is_point = equals_point_point(a1, a2);
|
||||
bool b_is_point = equals_point_point(b1, b2);
|
||||
|
||||
if(a_is_point && b_is_point)
|
||||
{
|
||||
return equals_point_point(a1, b2)
|
||||
? Policy::degenerate(a, true)
|
||||
: Policy::disjoint()
|
||||
;
|
||||
}
|
||||
|
||||
calc_t const a1_lon = get_as_radian<0>(a1);
|
||||
calc_t const a1_lat = get_as_radian<1>(a1);
|
||||
calc_t const a2_lon = get_as_radian<0>(a2);
|
||||
calc_t const a2_lat = get_as_radian<1>(a2);
|
||||
calc_t const b1_lon = get_as_radian<0>(b1);
|
||||
calc_t const b1_lat = get_as_radian<1>(b1);
|
||||
calc_t const b2_lon = get_as_radian<0>(b2);
|
||||
calc_t const b2_lat = get_as_radian<1>(b2);
|
||||
|
||||
side_info sides;
|
||||
|
||||
// NOTE: potential optimization, don't calculate distance at this point
|
||||
// this would require to reimplement inverse strategy to allow
|
||||
// calculation of distance if needed, probably also storing intermediate
|
||||
// results somehow inside an object.
|
||||
typedef Inverse<calc_t, true, true, false, false, false> inverse_dist_azi;
|
||||
typedef typename inverse_dist_azi::result_type inverse_result;
|
||||
|
||||
// TODO: no need to call inverse formula if we know that the points are equal
|
||||
// distance can be set to 0 in this case and azimuth may be not calculated
|
||||
bool const is_equal_a1_b1 = equals_point_point(a1, b1);
|
||||
bool const is_equal_a2_b1 = equals_point_point(a2, b1);
|
||||
|
||||
inverse_result res_b1_b2 = inverse_dist_azi::apply(b1_lon, b1_lat, b2_lon, b2_lat, spheroid);
|
||||
inverse_result res_b1_a1 = inverse_dist_azi::apply(b1_lon, b1_lat, a1_lon, a1_lat, spheroid);
|
||||
inverse_result res_b1_a2 = inverse_dist_azi::apply(b1_lon, b1_lat, a2_lon, a2_lat, spheroid);
|
||||
sides.set<0>(is_equal_a1_b1 ? 0 : formula::azimuth_side_value(res_b1_a1.azimuth, res_b1_b2.azimuth),
|
||||
is_equal_a2_b1 ? 0 : formula::azimuth_side_value(res_b1_a2.azimuth, res_b1_b2.azimuth));
|
||||
if (sides.same<0>())
|
||||
{
|
||||
// Both points are at the same side of other segment, we can leave
|
||||
return Policy::disjoint();
|
||||
}
|
||||
|
||||
bool const is_equal_a1_b2 = equals_point_point(a1, b2);
|
||||
|
||||
inverse_result res_a1_a2 = inverse_dist_azi::apply(a1_lon, a1_lat, a2_lon, a2_lat, spheroid);
|
||||
inverse_result res_a1_b1 = inverse_dist_azi::apply(a1_lon, a1_lat, b1_lon, b1_lat, spheroid);
|
||||
inverse_result res_a1_b2 = inverse_dist_azi::apply(a1_lon, a1_lat, b2_lon, b2_lat, spheroid);
|
||||
sides.set<1>(is_equal_a1_b1 ? 0 : formula::azimuth_side_value(res_a1_b1.azimuth, res_a1_a2.azimuth),
|
||||
is_equal_a1_b2 ? 0 : formula::azimuth_side_value(res_a1_b2.azimuth, res_a1_a2.azimuth));
|
||||
if (sides.same<1>())
|
||||
{
|
||||
// Both points are at the same side of other segment, we can leave
|
||||
return Policy::disjoint();
|
||||
}
|
||||
|
||||
// NOTE: at this point the segments may still be disjoint
|
||||
// NOTE: at this point one of the segments may be degenerated
|
||||
|
||||
bool collinear = sides.collinear();
|
||||
|
||||
if (! collinear)
|
||||
{
|
||||
// WARNING: the side strategy doesn't have the info about the other
|
||||
// segment so it may return results inconsistent with this intersection
|
||||
// strategy, as it checks both segments for consistency
|
||||
|
||||
if (sides.get<0, 0>() == 0 && sides.get<0, 1>() == 0)
|
||||
{
|
||||
collinear = true;
|
||||
sides.set<1>(0, 0);
|
||||
}
|
||||
else if (sides.get<1, 0>() == 0 && sides.get<1, 1>() == 0)
|
||||
{
|
||||
collinear = true;
|
||||
sides.set<0>(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (collinear)
|
||||
{
|
||||
if (a_is_point)
|
||||
{
|
||||
return collinear_one_degenerated<Policy, calc_t>(a, true, b1, b2, a1, a2, res_b1_b2, res_b1_a1, is_b_reversed);
|
||||
}
|
||||
else if (b_is_point)
|
||||
{
|
||||
return collinear_one_degenerated<Policy, calc_t>(b, false, a1, a2, b1, b2, res_a1_a2, res_a1_b1, is_a_reversed);
|
||||
}
|
||||
else
|
||||
{
|
||||
calc_t dist_a1_a2, dist_a1_b1, dist_a1_b2;
|
||||
calc_t dist_b1_b2, dist_b1_a1, dist_b1_a2;
|
||||
// use shorter segment
|
||||
if (res_a1_a2.distance <= res_b1_b2.distance)
|
||||
{
|
||||
calculate_collinear_data(a1, a2, b1, b2, res_a1_a2, res_a1_b1, dist_a1_a2, dist_a1_b1);
|
||||
calculate_collinear_data(a1, a2, b1, b2, res_a1_a2, res_a1_b2, dist_a1_a2, dist_a1_b2);
|
||||
dist_b1_b2 = dist_a1_b2 - dist_a1_b1;
|
||||
dist_b1_a1 = -dist_a1_b1;
|
||||
dist_b1_a2 = dist_a1_a2 - dist_a1_b1;
|
||||
}
|
||||
else
|
||||
{
|
||||
calculate_collinear_data(b1, b2, a1, a2, res_b1_b2, res_b1_a1, dist_b1_b2, dist_b1_a1);
|
||||
calculate_collinear_data(b1, b2, a1, a2, res_b1_b2, res_b1_a2, dist_b1_b2, dist_b1_a2);
|
||||
dist_a1_a2 = dist_b1_a2 - dist_b1_a1;
|
||||
dist_a1_b1 = -dist_b1_a1;
|
||||
dist_a1_b2 = dist_b1_b2 - dist_b1_a1;
|
||||
}
|
||||
|
||||
// NOTE: this is probably not needed
|
||||
calc_t const c0 = 0;
|
||||
int a1_on_b = position_value(c0, dist_a1_b1, dist_a1_b2);
|
||||
int a2_on_b = position_value(dist_a1_a2, dist_a1_b1, dist_a1_b2);
|
||||
int b1_on_a = position_value(c0, dist_b1_a1, dist_b1_a2);
|
||||
int b2_on_a = position_value(dist_b1_b2, dist_b1_a1, dist_b1_a2);
|
||||
|
||||
if ((a1_on_b < 1 && a2_on_b < 1) || (a1_on_b > 3 && a2_on_b > 3))
|
||||
{
|
||||
return Policy::disjoint();
|
||||
}
|
||||
|
||||
if (a1_on_b == 1)
|
||||
{
|
||||
dist_b1_a1 = 0;
|
||||
dist_a1_b1 = 0;
|
||||
}
|
||||
else if (a1_on_b == 3)
|
||||
{
|
||||
dist_b1_a1 = dist_b1_b2;
|
||||
dist_a1_b2 = 0;
|
||||
}
|
||||
|
||||
if (a2_on_b == 1)
|
||||
{
|
||||
dist_b1_a2 = 0;
|
||||
dist_a1_b1 = dist_a1_a2;
|
||||
}
|
||||
else if (a2_on_b == 3)
|
||||
{
|
||||
dist_b1_a2 = dist_b1_b2;
|
||||
dist_a1_b2 = dist_a1_a2;
|
||||
}
|
||||
|
||||
bool opposite = ! same_direction(res_a1_a2.azimuth, res_b1_b2.azimuth);
|
||||
|
||||
// NOTE: If segment was reversed opposite, positions and segment ratios has to be altered
|
||||
if (is_a_reversed)
|
||||
{
|
||||
// opposite
|
||||
opposite = ! opposite;
|
||||
// positions
|
||||
std::swap(a1_on_b, a2_on_b);
|
||||
b1_on_a = 4 - b1_on_a;
|
||||
b2_on_a = 4 - b2_on_a;
|
||||
// distances for ratios
|
||||
std::swap(dist_b1_a1, dist_b1_a2);
|
||||
dist_a1_b1 = dist_a1_a2 - dist_a1_b1;
|
||||
dist_a1_b2 = dist_a1_a2 - dist_a1_b2;
|
||||
}
|
||||
if (is_b_reversed)
|
||||
{
|
||||
// opposite
|
||||
opposite = ! opposite;
|
||||
// positions
|
||||
a1_on_b = 4 - a1_on_b;
|
||||
a2_on_b = 4 - a2_on_b;
|
||||
std::swap(b1_on_a, b2_on_a);
|
||||
// distances for ratios
|
||||
dist_b1_a1 = dist_b1_b2 - dist_b1_a1;
|
||||
dist_b1_a2 = dist_b1_b2 - dist_b1_a2;
|
||||
std::swap(dist_a1_b1, dist_a1_b2);
|
||||
}
|
||||
|
||||
segment_ratio<calc_t> ra_from(dist_b1_a1, dist_b1_b2);
|
||||
segment_ratio<calc_t> ra_to(dist_b1_a2, dist_b1_b2);
|
||||
segment_ratio<calc_t> rb_from(dist_a1_b1, dist_a1_a2);
|
||||
segment_ratio<calc_t> rb_to(dist_a1_b2, dist_a1_a2);
|
||||
|
||||
return Policy::segments_collinear(a, b, opposite,
|
||||
a1_on_b, a2_on_b, b1_on_a, b2_on_a,
|
||||
ra_from, ra_to, rb_from, rb_to);
|
||||
}
|
||||
}
|
||||
else // crossing or touching
|
||||
{
|
||||
if (a_is_point || b_is_point)
|
||||
{
|
||||
return Policy::disjoint();
|
||||
}
|
||||
|
||||
calc_t lon = 0, lat = 0;
|
||||
intersection_point_flag ip_flag;
|
||||
calc_t dist_a1_a2, dist_a1_i1, dist_b1_b2, dist_b1_i1;
|
||||
if (calculate_ip_data(a1, a2, b1, b2,
|
||||
a1_lon, a1_lat, a2_lon, a2_lat,
|
||||
b1_lon, b1_lat, b2_lon, b2_lat,
|
||||
res_a1_a2, res_a1_b1, res_a1_b2,
|
||||
res_b1_b2, res_b1_a1, res_b1_a2,
|
||||
sides, spheroid,
|
||||
lon, lat,
|
||||
dist_a1_a2, dist_a1_i1, dist_b1_b2, dist_b1_i1,
|
||||
ip_flag))
|
||||
{
|
||||
// NOTE: If segment was reversed sides and segment ratios has to be altered
|
||||
if (is_a_reversed)
|
||||
{
|
||||
// sides
|
||||
sides_reverse_segment<0>(sides);
|
||||
// distance for ratio
|
||||
dist_a1_i1 = dist_a1_a2 - dist_a1_i1;
|
||||
// ip flag
|
||||
ip_flag_reverse_segment(ip_flag, ipi_at_a1, ipi_at_a2);
|
||||
}
|
||||
if (is_b_reversed)
|
||||
{
|
||||
// sides
|
||||
sides_reverse_segment<1>(sides);
|
||||
// distance for ratio
|
||||
dist_b1_i1 = dist_b1_b2 - dist_b1_i1;
|
||||
// ip flag
|
||||
ip_flag_reverse_segment(ip_flag, ipi_at_b1, ipi_at_b2);
|
||||
}
|
||||
|
||||
// intersects
|
||||
segment_intersection_info
|
||||
<
|
||||
calc_t,
|
||||
segment_ratio<calc_t>
|
||||
> sinfo;
|
||||
|
||||
sinfo.lon = lon;
|
||||
sinfo.lat = lat;
|
||||
sinfo.robust_ra.assign(dist_a1_i1, dist_a1_a2);
|
||||
sinfo.robust_rb.assign(dist_b1_i1, dist_b1_b2);
|
||||
sinfo.ip_flag = ip_flag;
|
||||
|
||||
return Policy::segments_crosses(sides, sinfo, a, b);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Policy::disjoint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Policy, typename CalcT, typename Segment, typename Point1, typename Point2, typename ResultInverse>
|
||||
static inline typename Policy::return_type
|
||||
collinear_one_degenerated(Segment const& segment, bool degenerated_a,
|
||||
Point1 const& a1, Point1 const& a2,
|
||||
Point2 const& b1, Point2 const& b2,
|
||||
ResultInverse const& res_a1_a2,
|
||||
ResultInverse const& res_a1_bi,
|
||||
bool is_other_reversed)
|
||||
{
|
||||
CalcT dist_1_2, dist_1_o;
|
||||
if (! calculate_collinear_data(a1, a2, b1, b2, res_a1_a2, res_a1_bi, dist_1_2, dist_1_o))
|
||||
{
|
||||
return Policy::disjoint();
|
||||
}
|
||||
|
||||
// NOTE: If segment was reversed segment ratio has to be altered
|
||||
if (is_other_reversed)
|
||||
{
|
||||
// distance for ratio
|
||||
dist_1_o = dist_1_2 - dist_1_o;
|
||||
}
|
||||
|
||||
return Policy::one_degenerate(segment, segment_ratio<CalcT>(dist_1_o, dist_1_2), degenerated_a);
|
||||
}
|
||||
|
||||
// TODO: instead of checks below test bi against a1 and a2 here?
|
||||
// in order to make this independent from is_near()
|
||||
template <typename Point1, typename Point2, typename ResultInverse, typename CalcT>
|
||||
static inline bool calculate_collinear_data(Point1 const& a1, Point1 const& a2, // in
|
||||
Point2 const& b1, Point2 const& b2, // in
|
||||
ResultInverse const& res_a1_a2, // in
|
||||
ResultInverse const& res_a1_bi, // in
|
||||
CalcT& dist_a1_a2, CalcT& dist_a1_bi) // out
|
||||
{
|
||||
dist_a1_a2 = res_a1_a2.distance;
|
||||
|
||||
dist_a1_bi = res_a1_bi.distance;
|
||||
if (! same_direction(res_a1_bi.azimuth, res_a1_a2.azimuth))
|
||||
{
|
||||
dist_a1_bi = -dist_a1_bi;
|
||||
}
|
||||
|
||||
// if i1 is close to a1 and b1 or b2 is equal to a1
|
||||
if (is_endpoint_equal(dist_a1_bi, a1, b1, b2))
|
||||
{
|
||||
dist_a1_bi = 0;
|
||||
return true;
|
||||
}
|
||||
// or i1 is close to a2 and b1 or b2 is equal to a2
|
||||
else if (is_endpoint_equal(dist_a1_a2 - dist_a1_bi, a2, b1, b2))
|
||||
{
|
||||
dist_a1_bi = dist_a1_a2;
|
||||
return true;
|
||||
}
|
||||
|
||||
// or i1 is on b
|
||||
return segment_ratio<CalcT>(dist_a1_bi, dist_a1_a2).on_segment();
|
||||
}
|
||||
|
||||
template <typename Point1, typename Point2, typename CalcT, typename ResultInverse, typename Spheroid_>
|
||||
static inline bool calculate_ip_data(Point1 const& a1, Point1 const& a2, // in
|
||||
Point2 const& b1, Point2 const& b2, // in
|
||||
CalcT const& a1_lon, CalcT const& a1_lat, // in
|
||||
CalcT const& a2_lon, CalcT const& a2_lat, // in
|
||||
CalcT const& b1_lon, CalcT const& b1_lat, // in
|
||||
CalcT const& b2_lon, CalcT const& b2_lat, // in
|
||||
ResultInverse const& res_a1_a2, // in
|
||||
ResultInverse const& res_a1_b1, // in
|
||||
ResultInverse const& res_a1_b2, // in
|
||||
ResultInverse const& res_b1_b2, // in
|
||||
ResultInverse const& res_b1_a1, // in
|
||||
ResultInverse const& res_b1_a2, // in
|
||||
side_info const& sides, // in
|
||||
Spheroid_ const& spheroid, // in
|
||||
CalcT & lon, CalcT & lat, // out
|
||||
CalcT& dist_a1_a2, CalcT& dist_a1_ip, // out
|
||||
CalcT& dist_b1_b2, CalcT& dist_b1_ip, // out
|
||||
intersection_point_flag& ip_flag) // out
|
||||
{
|
||||
dist_a1_a2 = res_a1_a2.distance;
|
||||
dist_b1_b2 = res_b1_b2.distance;
|
||||
|
||||
// assign the IP if some endpoints overlap
|
||||
using geometry::detail::equals::equals_point_point;
|
||||
if (equals_point_point(a1, b1))
|
||||
{
|
||||
lon = a1_lon;
|
||||
lat = a1_lat;
|
||||
dist_a1_ip = 0;
|
||||
dist_b1_ip = 0;
|
||||
ip_flag = ipi_at_a1;
|
||||
return true;
|
||||
}
|
||||
else if (equals_point_point(a1, b2))
|
||||
{
|
||||
lon = a1_lon;
|
||||
lat = a1_lat;
|
||||
dist_a1_ip = 0;
|
||||
dist_b1_ip = dist_b1_b2;
|
||||
ip_flag = ipi_at_a1;
|
||||
return true;
|
||||
}
|
||||
else if (equals_point_point(a2, b1))
|
||||
{
|
||||
lon = a2_lon;
|
||||
lat = a2_lat;
|
||||
dist_a1_ip = dist_a1_a2;
|
||||
dist_b1_ip = 0;
|
||||
ip_flag = ipi_at_a2;
|
||||
return true;
|
||||
}
|
||||
else if (equals_point_point(a2, b2))
|
||||
{
|
||||
lon = a2_lon;
|
||||
lat = a2_lat;
|
||||
dist_a1_ip = dist_a1_a2;
|
||||
dist_b1_ip = dist_b1_b2;
|
||||
ip_flag = ipi_at_a2;
|
||||
return true;
|
||||
}
|
||||
|
||||
// at this point we know that the endpoints doesn't overlap
|
||||
// check cases when an endpoint lies on the other geodesic
|
||||
if (sides.template get<0, 0>() == 0) // a1 wrt b
|
||||
{
|
||||
if (res_b1_a1.distance <= res_b1_b2.distance
|
||||
&& same_direction(res_b1_a1.azimuth, res_b1_b2.azimuth))
|
||||
{
|
||||
lon = a1_lon;
|
||||
lat = a1_lat;
|
||||
dist_a1_ip = 0;
|
||||
dist_b1_ip = res_b1_a1.distance;
|
||||
ip_flag = ipi_at_a1;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (sides.template get<0, 1>() == 0) // a2 wrt b
|
||||
{
|
||||
if (res_b1_a2.distance <= res_b1_b2.distance
|
||||
&& same_direction(res_b1_a2.azimuth, res_b1_b2.azimuth))
|
||||
{
|
||||
lon = a2_lon;
|
||||
lat = a2_lat;
|
||||
dist_a1_ip = res_a1_a2.distance;
|
||||
dist_b1_ip = res_b1_a2.distance;
|
||||
ip_flag = ipi_at_a2;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (sides.template get<1, 0>() == 0) // b1 wrt a
|
||||
{
|
||||
if (res_a1_b1.distance <= res_a1_a2.distance
|
||||
&& same_direction(res_a1_b1.azimuth, res_a1_a2.azimuth))
|
||||
{
|
||||
lon = b1_lon;
|
||||
lat = b1_lat;
|
||||
dist_a1_ip = res_a1_b1.distance;
|
||||
dist_b1_ip = 0;
|
||||
ip_flag = ipi_at_b1;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (sides.template get<1, 1>() == 0) // b2 wrt a
|
||||
{
|
||||
if (res_a1_b2.distance <= res_a1_a2.distance
|
||||
&& same_direction(res_a1_b2.azimuth, res_a1_a2.azimuth))
|
||||
{
|
||||
lon = b2_lon;
|
||||
lat = b2_lat;
|
||||
dist_a1_ip = res_a1_b2.distance;
|
||||
dist_b1_ip = res_b1_b2.distance;
|
||||
ip_flag = ipi_at_b2;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// At this point neither the endpoints overlaps
|
||||
// nor any andpoint lies on the other geodesic
|
||||
// So the endpoints should lie on the opposite sides of both geodesics
|
||||
|
||||
bool const ok = formula::sjoberg_intersection<CalcT, Inverse, Order>::apply(
|
||||
a1_lon, a1_lat, a2_lon, a2_lat, res_a1_a2.azimuth,
|
||||
b1_lon, b1_lat, b2_lon, b2_lat, res_b1_b2.azimuth,
|
||||
lon, lat, spheroid);
|
||||
|
||||
if (! ok)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
typedef Inverse<CalcT, true, true, false, false, false> inverse_dist_azi;
|
||||
typedef typename inverse_dist_azi::result_type inverse_result;
|
||||
|
||||
inverse_result const res_a1_ip = inverse_dist_azi::apply(a1_lon, a1_lat, lon, lat, spheroid);
|
||||
dist_a1_ip = res_a1_ip.distance;
|
||||
if (! same_direction(res_a1_ip.azimuth, res_a1_a2.azimuth))
|
||||
{
|
||||
dist_a1_ip = -dist_a1_ip;
|
||||
}
|
||||
|
||||
bool is_on_a = segment_ratio<CalcT>(dist_a1_ip, dist_a1_a2).on_segment();
|
||||
// NOTE: not fully consistent with equals_point_point() since radians are always used.
|
||||
bool is_on_a1 = math::equals(lon, a1_lon) && math::equals(lat, a1_lat);
|
||||
bool is_on_a2 = math::equals(lon, a2_lon) && math::equals(lat, a2_lat);
|
||||
|
||||
if (! (is_on_a || is_on_a1 || is_on_a2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
inverse_result const res_b1_ip = inverse_dist_azi::apply(b1_lon, b1_lat, lon, lat, spheroid);
|
||||
dist_b1_ip = res_b1_ip.distance;
|
||||
if (! same_direction(res_b1_ip.azimuth, res_b1_b2.azimuth))
|
||||
{
|
||||
dist_b1_ip = -dist_b1_ip;
|
||||
}
|
||||
|
||||
bool is_on_b = segment_ratio<CalcT>(dist_b1_ip, dist_b1_b2).on_segment();
|
||||
// NOTE: not fully consistent with equals_point_point() since radians are always used.
|
||||
bool is_on_b1 = math::equals(lon, b1_lon) && math::equals(lat, b1_lat);
|
||||
bool is_on_b2 = math::equals(lon, b2_lon) && math::equals(lat, b2_lat);
|
||||
|
||||
if (! (is_on_b || is_on_b1 || is_on_b2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ip_flag = ipi_inters;
|
||||
|
||||
if (is_on_b1)
|
||||
{
|
||||
lon = b1_lon;
|
||||
lat = b1_lat;
|
||||
dist_b1_ip = 0;
|
||||
ip_flag = ipi_at_b1;
|
||||
}
|
||||
else if (is_on_b2)
|
||||
{
|
||||
lon = b2_lon;
|
||||
lat = b2_lat;
|
||||
dist_b1_ip = res_b1_b2.distance;
|
||||
ip_flag = ipi_at_b2;
|
||||
}
|
||||
|
||||
if (is_on_a1)
|
||||
{
|
||||
lon = a1_lon;
|
||||
lat = a1_lat;
|
||||
dist_a1_ip = 0;
|
||||
ip_flag = ipi_at_a1;
|
||||
}
|
||||
else if (is_on_a2)
|
||||
{
|
||||
lon = a2_lon;
|
||||
lat = a2_lat;
|
||||
dist_a1_ip = res_a1_a2.distance;
|
||||
ip_flag = ipi_at_a2;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename CalcT, typename P1, typename P2>
|
||||
static inline bool is_endpoint_equal(CalcT const& dist,
|
||||
P1 const& ai, P2 const& b1, P2 const& b2)
|
||||
{
|
||||
using geometry::detail::equals::equals_point_point;
|
||||
return is_near(dist) && (equals_point_point(ai, b1) || equals_point_point(ai, b2));
|
||||
}
|
||||
|
||||
template <typename CalcT>
|
||||
static inline bool is_near(CalcT const& dist)
|
||||
{
|
||||
// NOTE: This strongly depends on the Inverse method
|
||||
CalcT const small_number = CalcT(boost::is_same<CalcT, float>::value ? 0.0001 : 0.00000001);
|
||||
return math::abs(dist) <= small_number;
|
||||
}
|
||||
|
||||
template <typename ProjCoord1, typename ProjCoord2>
|
||||
static inline int position_value(ProjCoord1 const& ca1,
|
||||
ProjCoord2 const& cb1,
|
||||
ProjCoord2 const& cb2)
|
||||
{
|
||||
// S1x 0 1 2 3 4
|
||||
// S2 |---------->
|
||||
return math::equals(ca1, cb1) ? 1
|
||||
: math::equals(ca1, cb2) ? 3
|
||||
: cb1 < cb2 ?
|
||||
( ca1 < cb1 ? 0
|
||||
: ca1 > cb2 ? 4
|
||||
: 2 )
|
||||
: ( ca1 > cb1 ? 0
|
||||
: ca1 < cb2 ? 4
|
||||
: 2 );
|
||||
}
|
||||
|
||||
template <typename CalcT>
|
||||
static inline bool same_direction(CalcT const& azimuth1, CalcT const& azimuth2)
|
||||
{
|
||||
// distance between two angles normalized to (-180, 180]
|
||||
CalcT const angle_diff = math::longitude_distance_signed<radian>(azimuth1, azimuth2);
|
||||
return math::abs(angle_diff) <= math::half_pi<CalcT>();
|
||||
}
|
||||
|
||||
template <int Which>
|
||||
static inline void sides_reverse_segment(side_info & sides)
|
||||
{
|
||||
// names assuming segment A is reversed (Which == 0)
|
||||
int a1_wrt_b = sides.template get<Which, 0>();
|
||||
int a2_wrt_b = sides.template get<Which, 1>();
|
||||
std::swap(a1_wrt_b, a2_wrt_b);
|
||||
sides.template set<Which>(a1_wrt_b, a2_wrt_b);
|
||||
int b1_wrt_a = sides.template get<1 - Which, 0>();
|
||||
int b2_wrt_a = sides.template get<1 - Which, 1>();
|
||||
sides.template set<1 - Which>(-b1_wrt_a, -b2_wrt_a);
|
||||
}
|
||||
|
||||
static inline void ip_flag_reverse_segment(intersection_point_flag & ip_flag,
|
||||
intersection_point_flag const& ipi_at_p1,
|
||||
intersection_point_flag const& ipi_at_p2)
|
||||
{
|
||||
ip_flag = ip_flag == ipi_at_p1 ? ipi_at_p2 :
|
||||
ip_flag == ipi_at_p2 ? ipi_at_p1 :
|
||||
ip_flag;
|
||||
}
|
||||
|
||||
template <typename CalcT, typename SpheroidT>
|
||||
static inline srs::spheroid<CalcT> normalized_spheroid(SpheroidT const& spheroid)
|
||||
{
|
||||
return srs::spheroid<CalcT>(CalcT(1),
|
||||
CalcT(get_radius<2>(spheroid)) // b/a
|
||||
/ CalcT(get_radius<0>(spheroid)));
|
||||
}
|
||||
|
||||
private:
|
||||
Spheroid m_spheroid;
|
||||
};
|
||||
|
||||
|
||||
}} // namespace strategy::intersection
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_GEODESIC_INTERSECTION_HPP
|
||||
235
include/boost/geometry/strategies/geographic/intersection.hpp
Normal file
235
include/boost/geometry/strategies/geographic/intersection.hpp
Normal file
@@ -0,0 +1,235 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2016-2017, 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)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_INTERSECTION_HPP
|
||||
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_INTERSECTION_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/core/srs.hpp>
|
||||
|
||||
#include <boost/geometry/formulas/geographic.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/spherical/intersection.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
namespace strategy { namespace intersection
|
||||
{
|
||||
|
||||
template <typename Spheroid>
|
||||
struct relate_great_elliptic_segments_calc_policy
|
||||
: relate_spherical_segments_calc_policy
|
||||
{
|
||||
explicit relate_great_elliptic_segments_calc_policy(Spheroid const& spheroid = Spheroid())
|
||||
: m_spheroid(spheroid)
|
||||
{}
|
||||
|
||||
template <typename Point, typename Point3d>
|
||||
Point from_cart3d(Point3d const& point_3d) const
|
||||
{
|
||||
return formula::cart3d_to_geo<Point>(point_3d, m_spheroid);
|
||||
}
|
||||
|
||||
template <typename Point3d, typename Point>
|
||||
Point3d to_cart3d(Point const& point) const
|
||||
{
|
||||
return formula::geo_to_cart3d<Point3d>(point, m_spheroid);
|
||||
}
|
||||
|
||||
// relate_xxx_calc_policy must live londer than plane because it contains
|
||||
// Spheroid object and plane keeps the reference to that object.
|
||||
template <typename Point3d>
|
||||
struct plane
|
||||
{
|
||||
typedef typename coordinate_type<Point3d>::type coord_t;
|
||||
|
||||
// not normalized
|
||||
plane(Point3d const& p1, Point3d const& p2)
|
||||
: normal(cross_product(p1, p2))
|
||||
{}
|
||||
|
||||
int side_value(Point3d const& pt) const
|
||||
{
|
||||
return formula::sph_side_value(normal, pt);
|
||||
}
|
||||
|
||||
coord_t cos_angle_between(Point3d const& p1, Point3d const& p2) const
|
||||
{
|
||||
Point3d v1 = p1;
|
||||
detail::vec_normalize(v1);
|
||||
Point3d v2 = p2;
|
||||
detail::vec_normalize(v2);
|
||||
|
||||
return dot_product(v1, v2);
|
||||
}
|
||||
|
||||
coord_t cos_angle_between(Point3d const& p1, Point3d const& p2, bool & is_forward) const
|
||||
{
|
||||
coord_t const c0 = 0;
|
||||
|
||||
Point3d v1 = p1;
|
||||
detail::vec_normalize(v1);
|
||||
Point3d v2 = p2;
|
||||
detail::vec_normalize(v2);
|
||||
|
||||
is_forward = dot_product(normal, cross_product(v1, v2)) >= c0;
|
||||
return dot_product(v1, v2);
|
||||
}
|
||||
|
||||
Point3d normal;
|
||||
};
|
||||
|
||||
template <typename Point3d>
|
||||
plane<Point3d> get_plane(Point3d const& p1, Point3d const& p2) const
|
||||
{
|
||||
return plane<Point3d>(p1, p2);
|
||||
}
|
||||
|
||||
template <typename Point3d>
|
||||
bool intersection_points(plane<Point3d> const& plane1,
|
||||
plane<Point3d> const& plane2,
|
||||
Point3d & ip1, Point3d & ip2) const
|
||||
{
|
||||
typedef typename coordinate_type<Point3d>::type coord_t;
|
||||
|
||||
Point3d id = cross_product(plane1.normal, plane2.normal);
|
||||
// NOTE: the length should be greater than 0 at this point
|
||||
// NOTE: no need to normalize in this case
|
||||
|
||||
ip1 = formula::projected_to_surface(id, m_spheroid);
|
||||
|
||||
ip2 = ip1;
|
||||
multiply_value(ip2, coord_t(-1));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
Spheroid m_spheroid;
|
||||
};
|
||||
|
||||
template <typename Spheroid>
|
||||
struct relate_experimental_elliptic_segments_calc_policy
|
||||
{
|
||||
explicit relate_experimental_elliptic_segments_calc_policy(Spheroid const& spheroid = Spheroid())
|
||||
: m_spheroid(spheroid)
|
||||
{}
|
||||
|
||||
template <typename Point, typename Point3d>
|
||||
Point from_cart3d(Point3d const& point_3d) const
|
||||
{
|
||||
return formula::cart3d_to_geo<Point>(point_3d, m_spheroid);
|
||||
}
|
||||
|
||||
template <typename Point3d, typename Point>
|
||||
Point3d to_cart3d(Point const& point) const
|
||||
{
|
||||
return formula::geo_to_cart3d<Point3d>(point, m_spheroid);
|
||||
}
|
||||
|
||||
// relate_xxx_calc_policy must live londer than plane because it contains
|
||||
// Spheroid object and plane keeps the reference to that object.
|
||||
template <typename Point3d>
|
||||
struct plane
|
||||
{
|
||||
typedef typename coordinate_type<Point3d>::type coord_t;
|
||||
|
||||
// not normalized
|
||||
plane(Point3d const& p1, Point3d const& p2, Spheroid const& spheroid)
|
||||
: m_spheroid(spheroid)
|
||||
{
|
||||
formula::experimental_elliptic_plane(p1, p2, origin, normal, m_spheroid);
|
||||
}
|
||||
|
||||
int side_value(Point3d const& pt) const
|
||||
{
|
||||
return formula::elliptic_side_value(origin, normal, pt);
|
||||
}
|
||||
|
||||
coord_t cos_angle_between(Point3d const& p1, Point3d const& p2) const
|
||||
{
|
||||
Point3d const v1 = normalized_vec(p1);
|
||||
Point3d const v2 = normalized_vec(p2);
|
||||
return dot_product(v1, v2);
|
||||
}
|
||||
|
||||
coord_t cos_angle_between(Point3d const& p1, Point3d const& p2, bool & is_forward) const
|
||||
{
|
||||
coord_t const c0 = 0;
|
||||
|
||||
Point3d const v1 = normalized_vec(p1);
|
||||
Point3d const v2 = normalized_vec(p2);
|
||||
|
||||
is_forward = dot_product(normal, cross_product(v1, v2)) >= c0;
|
||||
return dot_product(v1, v2);
|
||||
}
|
||||
|
||||
Point3d origin;
|
||||
Point3d normal;
|
||||
|
||||
private:
|
||||
Point3d normalized_vec(Point3d const& p) const
|
||||
{
|
||||
Point3d v = p;
|
||||
subtract_point(v, origin);
|
||||
detail::vec_normalize(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
Spheroid const& m_spheroid;
|
||||
};
|
||||
|
||||
template <typename Point3d>
|
||||
plane<Point3d> get_plane(Point3d const& p1, Point3d const& p2) const
|
||||
{
|
||||
return plane<Point3d>(p1, p2, m_spheroid);
|
||||
}
|
||||
|
||||
template <typename Point3d>
|
||||
bool intersection_points(plane<Point3d> const& plane1,
|
||||
plane<Point3d> const& plane2,
|
||||
Point3d & ip1, Point3d & ip2) const
|
||||
{
|
||||
return formula::planes_spheroid_intersection(plane1.origin, plane1.normal,
|
||||
plane2.origin, plane2.normal,
|
||||
ip1, ip2, m_spheroid);
|
||||
}
|
||||
|
||||
private:
|
||||
Spheroid m_spheroid;
|
||||
};
|
||||
|
||||
|
||||
template <typename Spheroid = srs::spheroid<double>, typename CalculationType = void>
|
||||
struct relate_great_elliptic_segments
|
||||
: relate_ecef_segments
|
||||
<
|
||||
relate_great_elliptic_segments_calc_policy<Spheroid>,
|
||||
CalculationType
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename Spheroid = srs::spheroid<double>, typename CalculationType = void>
|
||||
struct relate_experimental_elliptic_segments
|
||||
: relate_ecef_segments
|
||||
<
|
||||
relate_experimental_elliptic_segments_calc_policy<Spheroid>,
|
||||
CalculationType
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
}} // namespace strategy::intersection
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_INTERSECTION_HPP
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// 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-2017.
|
||||
// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@@ -11,14 +11,16 @@
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_DETAIL_HPP
|
||||
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_DETAIL_HPP
|
||||
#ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_HPP
|
||||
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_HPP
|
||||
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/radian_access.hpp>
|
||||
#include <boost/geometry/core/radius.hpp>
|
||||
|
||||
#include <boost/geometry/formulas/spherical.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/promote_floating_point.hpp>
|
||||
#include <boost/geometry/util/select_calculation_type.hpp>
|
||||
@@ -34,9 +36,6 @@ namespace boost { namespace geometry
|
||||
namespace strategy { namespace side
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
{
|
||||
|
||||
/*!
|
||||
\brief Check at which side of a segment a point lies
|
||||
@@ -49,10 +48,13 @@ namespace detail
|
||||
template <template<typename, bool, bool, bool, bool, bool> class InverseFormula,
|
||||
typename Model,
|
||||
typename CalculationType = void>
|
||||
class by_azimuth
|
||||
class geographic
|
||||
{
|
||||
public:
|
||||
by_azimuth(Model const& model = Model())
|
||||
geographic()
|
||||
{}
|
||||
|
||||
explicit geographic(Model const& model)
|
||||
: m_model(model)
|
||||
{}
|
||||
|
||||
@@ -73,40 +75,7 @@ public:
|
||||
calc_t a1p = azimuth<calc_t, inverse_formula>(p1, p, m_model);
|
||||
calc_t a12 = azimuth<calc_t, inverse_formula>(p1, p2, m_model);
|
||||
|
||||
calc_t const pi = math::pi<calc_t>();
|
||||
|
||||
// instead of the formula from XTD
|
||||
//calc_t a_diff = asin(sin(a1p - a12));
|
||||
|
||||
calc_t a_diff = a1p - a12;
|
||||
// normalize, angle in [-pi, pi]
|
||||
while ( a_diff > pi )
|
||||
a_diff -= calc_t(2) * pi;
|
||||
while ( a_diff < -pi )
|
||||
a_diff += calc_t(2) * pi;
|
||||
|
||||
// NOTE: in general it shouldn't be required to support the pi/-pi case
|
||||
// because in non-cartesian systems it makes sense to check the side
|
||||
// only "between" the endpoints.
|
||||
// However currently the winding strategy calls the side strategy
|
||||
// for vertical segments to check if the point is "between the endpoints.
|
||||
// This could be avoided since the side strategy is not required for that
|
||||
// because meridian is the shortest path. So a difference of
|
||||
// longitudes would be sufficient (of course normalized to [-pi, pi]).
|
||||
|
||||
// NOTE: with the above said, the pi/-pi check is temporary
|
||||
// however in case if this was required
|
||||
// the geodesics on ellipsoid aren't "symmetrical"
|
||||
// therefore instead of comparing a_diff to pi and -pi
|
||||
// one should probably use inverse azimuths and compare
|
||||
// the difference to 0 as well
|
||||
|
||||
// positive azimuth is on the right side
|
||||
return math::equals(a_diff, 0)
|
||||
|| math::equals(a_diff, pi)
|
||||
|| math::equals(a_diff, -pi) ? 0
|
||||
: a_diff > 0 ? -1 // right
|
||||
: 1; // left
|
||||
return formula::azimuth_side_value(a1p, a12);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -127,8 +96,6 @@ private:
|
||||
Model m_model;
|
||||
};
|
||||
|
||||
} // detail
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace strategy::side
|
||||
|
||||
@@ -136,4 +103,4 @@ private:
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_DETAIL_HPP
|
||||
#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_HPP
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// 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-2017.
|
||||
// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
#include <boost/geometry/formulas/andoyer_inverse.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/geographic/side_detail.hpp>
|
||||
#include <boost/geometry/strategies/geographic/side.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -36,12 +36,15 @@ namespace strategy { namespace side
|
||||
*/
|
||||
template <typename Model, typename CalculationType = void>
|
||||
class andoyer
|
||||
: public detail::by_azimuth<geometry::formula::andoyer_inverse, Model, CalculationType>
|
||||
: public side::geographic<formula::andoyer_inverse, Model, CalculationType>
|
||||
{
|
||||
typedef detail::by_azimuth<geometry::formula::andoyer_inverse, Model, CalculationType> base_t;
|
||||
typedef side::geographic<formula::andoyer_inverse, Model, CalculationType> base_t;
|
||||
|
||||
public:
|
||||
andoyer(Model const& model = Model())
|
||||
andoyer()
|
||||
{}
|
||||
|
||||
explicit andoyer(Model const& model)
|
||||
: base_t(model)
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// 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-2017.
|
||||
// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
#include <boost/geometry/formulas/thomas_inverse.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/geographic/side_detail.hpp>
|
||||
#include <boost/geometry/strategies/geographic/side.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -36,12 +36,15 @@ namespace strategy { namespace side
|
||||
*/
|
||||
template <typename Model, typename CalculationType = void>
|
||||
class thomas
|
||||
: public detail::by_azimuth<geometry::formula::thomas_inverse, Model, CalculationType>
|
||||
: public side::geographic<formula::thomas_inverse, Model, CalculationType>
|
||||
{
|
||||
typedef detail::by_azimuth<geometry::formula::thomas_inverse, Model, CalculationType> base_t;
|
||||
typedef side::geographic<formula::thomas_inverse, Model, CalculationType> base_t;
|
||||
|
||||
public:
|
||||
thomas(Model const& model = Model())
|
||||
thomas()
|
||||
{}
|
||||
|
||||
explicit thomas(Model const& model)
|
||||
: base_t(model)
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// 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-2017.
|
||||
// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
#include <boost/geometry/formulas/vincenty_inverse.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/geographic/side_detail.hpp>
|
||||
#include <boost/geometry/strategies/geographic/side.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -36,12 +36,15 @@ namespace strategy { namespace side
|
||||
*/
|
||||
template <typename Model, typename CalculationType = void>
|
||||
class vincenty
|
||||
: public detail::by_azimuth<geometry::formula::vincenty_inverse, Model, CalculationType>
|
||||
: public side::geographic<formula::vincenty_inverse, Model, CalculationType>
|
||||
{
|
||||
typedef detail::by_azimuth<geometry::formula::vincenty_inverse, Model, CalculationType> base_t;
|
||||
typedef side::geographic<formula::vincenty_inverse, Model, CalculationType> base_t;
|
||||
|
||||
public:
|
||||
vincenty(Model const& model = Model())
|
||||
vincenty()
|
||||
{}
|
||||
|
||||
explicit vincenty(Model const& model)
|
||||
: base_t(model)
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2016 Oracle and/or its affiliates.
|
||||
// Copyright (c) 2016-2017 Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Vissarion Fisikopoulos, 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
|
||||
@@ -10,9 +11,12 @@
|
||||
#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_AREA_SPHERICAL_HPP
|
||||
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_AREA_SPHERICAL_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/formulas/area_formulas.hpp>
|
||||
#include <boost/geometry/core/radius.hpp>
|
||||
#include <boost/geometry/core/srs.hpp>
|
||||
#include <boost/geometry/strategies/area.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -21,10 +25,17 @@ namespace strategy { namespace area
|
||||
{
|
||||
|
||||
/*!
|
||||
\brief Spherical area calculation by trapezoidal rule
|
||||
\brief Spherical area calculation
|
||||
\ingroup strategies
|
||||
\details Calculates area on the surface of a sphere using the trapezoidal rule
|
||||
\tparam PointOfSegment \tparam_segment_point
|
||||
\tparam LongSegment Enables special handling of long segments
|
||||
\tparam CalculationType \tparam_calculation
|
||||
|
||||
\qbk{
|
||||
[heading See also]
|
||||
[link geometry.reference.algorithms.area.area_2_with_strategy area (with strategy)]
|
||||
}
|
||||
|
||||
*/
|
||||
template
|
||||
<
|
||||
@@ -102,7 +113,7 @@ public :
|
||||
inline spherical(CT radius) //backward compatibility
|
||||
: m_sphere()
|
||||
{
|
||||
m_sphere.set_radius<0>(radius);
|
||||
geometry::set_radius<0>(m_sphere, radius);
|
||||
}
|
||||
|
||||
inline void apply(PointOfSegment const& p1,
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#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/formulas/spherical.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/concepts/point_concept.hpp>
|
||||
@@ -38,6 +39,8 @@
|
||||
#include <boost/geometry/strategies/intersection_result.hpp>
|
||||
#include <boost/geometry/strategies/side.hpp>
|
||||
#include <boost/geometry/strategies/side_info.hpp>
|
||||
#include <boost/geometry/strategies/spherical/area_spherical.hpp>
|
||||
#include <boost/geometry/strategies/spherical/distance_haversine.hpp>
|
||||
#include <boost/geometry/strategies/spherical/ssf.hpp>
|
||||
#include <boost/geometry/strategies/within.hpp>
|
||||
|
||||
@@ -73,8 +76,8 @@ namespace strategy { namespace intersection
|
||||
// For now, intersection points near the endpoints are checked explicitly if needed (if the IP is near the endpoint)
|
||||
// to generate precise result for them. Only the crossing (i) case may suffer from lower precision.
|
||||
|
||||
template <typename CalculationType = void>
|
||||
struct relate_spherical_segments
|
||||
template <typename CalcPolicy, typename CalculationType = void>
|
||||
struct relate_ecef_segments
|
||||
{
|
||||
typedef side::spherical_side_formula<CalculationType> side_strategy_type;
|
||||
|
||||
@@ -106,8 +109,44 @@ struct relate_spherical_segments
|
||||
return strategy_type();
|
||||
}
|
||||
|
||||
template <typename Geometry>
|
||||
struct area_strategy
|
||||
{
|
||||
typedef area::spherical
|
||||
<
|
||||
typename point_type<Geometry>::type,
|
||||
false,
|
||||
CalculationType
|
||||
> type;
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
static inline typename area_strategy<Geometry>::type get_area_strategy()
|
||||
{
|
||||
typedef typename area_strategy<Geometry>::type strategy_type;
|
||||
return strategy_type();
|
||||
}
|
||||
|
||||
template <typename Geometry>
|
||||
struct distance_strategy
|
||||
{
|
||||
typedef distance::haversine
|
||||
<
|
||||
typename coordinate_type<Geometry>::type,
|
||||
CalculationType
|
||||
> type;
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
static inline typename distance_strategy<Geometry>::type get_distance_strategy()
|
||||
{
|
||||
typedef typename distance_strategy<Geometry>::type strategy_type;
|
||||
return strategy_type();
|
||||
}
|
||||
|
||||
enum intersection_point_flag { ipi_inters = 0, ipi_at_a1, ipi_at_a2, ipi_at_b1, ipi_at_b2 };
|
||||
|
||||
// segment_intersection_info cannot outlive relate_ecef_segments
|
||||
template <typename CoordinateType, typename SegmentRatio, typename Vector3d>
|
||||
struct segment_intersection_info
|
||||
{
|
||||
@@ -116,6 +155,10 @@ struct relate_spherical_segments
|
||||
CoordinateType, double
|
||||
>::type promoted_type;
|
||||
|
||||
segment_intersection_info(CalcPolicy const& calc)
|
||||
: calc_policy(calc)
|
||||
{}
|
||||
|
||||
promoted_type comparable_length_a() const
|
||||
{
|
||||
return robust_ra.denominator();
|
||||
@@ -143,7 +186,7 @@ struct relate_spherical_segments
|
||||
if (ip_flag == ipi_inters)
|
||||
{
|
||||
// TODO: assign the rest of coordinates
|
||||
point = formula::cart3d_to_sph<Point>(intersection_point);
|
||||
point = calc_policy.template from_cart3d<Point>(intersection_point);
|
||||
}
|
||||
else if (ip_flag == ipi_at_a1)
|
||||
{
|
||||
@@ -167,6 +210,8 @@ struct relate_spherical_segments
|
||||
SegmentRatio robust_ra;
|
||||
SegmentRatio robust_rb;
|
||||
intersection_point_flag ip_flag;
|
||||
|
||||
CalcPolicy const& calc_policy;
|
||||
};
|
||||
|
||||
// Relate segments a and b
|
||||
@@ -210,6 +255,12 @@ struct relate_spherical_segments
|
||||
Policy const&, RobustPolicy const&,
|
||||
Point1 const& a1, Point1 const& a2, Point2 const& b1, Point2 const& b2)
|
||||
{
|
||||
// For now create it using default constructor. In the future it could
|
||||
// be stored in strategy. However then apply() wouldn't be static and
|
||||
// all relops and setops would have to take the strategy or model.
|
||||
// Initialize explicitly to prevent compiler errors in case of PoD type
|
||||
CalcPolicy const calc_policy = CalcPolicy();
|
||||
|
||||
BOOST_CONCEPT_ASSERT( (concepts::ConstSegment<Segment1>) );
|
||||
BOOST_CONCEPT_ASSERT( (concepts::ConstSegment<Segment2>) );
|
||||
|
||||
@@ -234,25 +285,29 @@ struct relate_spherical_segments
|
||||
|
||||
typedef model::point<calc_t, 3, cs::cartesian> vec3d_t;
|
||||
|
||||
using namespace formula;
|
||||
vec3d_t const a1v = sph_to_cart3d<vec3d_t>(a1);
|
||||
vec3d_t const a2v = sph_to_cart3d<vec3d_t>(a2);
|
||||
vec3d_t const b1v = sph_to_cart3d<vec3d_t>(b1);
|
||||
vec3d_t const b2v = sph_to_cart3d<vec3d_t>(b2);
|
||||
vec3d_t const a1v = calc_policy.template to_cart3d<vec3d_t>(a1);
|
||||
vec3d_t const a2v = calc_policy.template to_cart3d<vec3d_t>(a2);
|
||||
vec3d_t const b1v = calc_policy.template to_cart3d<vec3d_t>(b1);
|
||||
vec3d_t const b2v = calc_policy.template to_cart3d<vec3d_t>(b2);
|
||||
|
||||
vec3d_t norm1 = cross_product(a1v, a2v);
|
||||
vec3d_t norm2 = cross_product(b1v, b2v);
|
||||
|
||||
side_info sides;
|
||||
// not normalized normals, the same as in SSF
|
||||
sides.set<0>(sph_side_value(norm2, a1v), sph_side_value(norm2, a2v));
|
||||
|
||||
typename CalcPolicy::template plane<vec3d_t>
|
||||
plane2 = calc_policy.get_plane(b1v, b2v);
|
||||
|
||||
// not normalized normals, the same as in side strategy
|
||||
sides.set<0>(plane2.side_value(a1v), plane2.side_value(a2v));
|
||||
if (sides.same<0>())
|
||||
{
|
||||
// Both points are at same side of other segment, we can leave
|
||||
return Policy::disjoint();
|
||||
}
|
||||
// not normalized normals, the same as in SSF
|
||||
sides.set<1>(sph_side_value(norm1, b1v), sph_side_value(norm1, b2v));
|
||||
|
||||
typename CalcPolicy::template plane<vec3d_t>
|
||||
plane1 = calc_policy.get_plane(a1v, a2v);
|
||||
|
||||
// not normalized normals, the same as in side strategy
|
||||
sides.set<1>(plane1.side_value(b1v), plane1.side_value(b2v));
|
||||
if (sides.same<1>())
|
||||
{
|
||||
// Both points are at same side of other segment, we can leave
|
||||
@@ -261,13 +316,10 @@ struct relate_spherical_segments
|
||||
|
||||
// NOTE: at this point the segments may still be disjoint
|
||||
|
||||
bool collinear = sides.collinear();
|
||||
calc_t len1, len2;
|
||||
|
||||
calc_t const len1 = math::sqrt(dot_product(norm1, norm1));
|
||||
calc_t const len2 = math::sqrt(dot_product(norm2, norm2));
|
||||
|
||||
// point or opposite sides of a sphere, assume point
|
||||
if (math::equals(len1, c0))
|
||||
// point or opposite sides of a sphere/spheroid, assume point
|
||||
if (! detail::vec_normalize(plane1.normal, len1))
|
||||
{
|
||||
a_is_point = true;
|
||||
if (sides.get<0, 0>() == 0 || sides.get<0, 1>() == 0)
|
||||
@@ -275,13 +327,8 @@ struct relate_spherical_segments
|
||||
sides.set<0>(0, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// normalize
|
||||
divide_value(norm1, len1);
|
||||
}
|
||||
|
||||
if (math::equals(len2, c0))
|
||||
if (! detail::vec_normalize(plane2.normal, len2))
|
||||
{
|
||||
b_is_point = true;
|
||||
if (sides.get<1, 0>() == 0 || sides.get<1, 1>() == 0)
|
||||
@@ -289,11 +336,6 @@ struct relate_spherical_segments
|
||||
sides.set<1>(0, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// normalize
|
||||
divide_value(norm2, len2);
|
||||
}
|
||||
|
||||
// check both degenerated once more
|
||||
if (a_is_point && b_is_point)
|
||||
@@ -304,16 +346,42 @@ struct relate_spherical_segments
|
||||
;
|
||||
}
|
||||
|
||||
// NOTE: at this point the segments may still be disjoint
|
||||
// NOTE: at this point one of the segments may be degenerated
|
||||
// and the segments may still be disjoint
|
||||
|
||||
calc_t dot_n1n2 = dot_product(norm1, norm2);
|
||||
bool collinear = sides.collinear();
|
||||
|
||||
if (! collinear)
|
||||
{
|
||||
// NOTE: for some approximations it's possible that both points may lie
|
||||
// on the same geodesic but still some of the sides may be != 0.
|
||||
// This is e.g. true for long segments represented as elliptic arcs
|
||||
// with origin different than the center of the coordinate system.
|
||||
// So make the sides consistent
|
||||
|
||||
// WARNING: the side strategy doesn't have the info about the other
|
||||
// segment so it may return results inconsistent with this intersection
|
||||
// strategy, as it checks both segments for consistency
|
||||
|
||||
if (sides.get<0, 0>() == 0 && sides.get<0, 1>() == 0)
|
||||
{
|
||||
collinear = true;
|
||||
sides.set<1>(0, 0);
|
||||
}
|
||||
else if (sides.get<1, 0>() == 0 && sides.get<1, 1>() == 0)
|
||||
{
|
||||
collinear = true;
|
||||
sides.set<0>(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
calc_t dot_n1n2 = dot_product(plane1.normal, plane2.normal);
|
||||
|
||||
// NOTE: this is technically not needed since theoretically above sides
|
||||
// are calculated, but just in case check the normals.
|
||||
// Have in mind that SSF side strategy doesn't check this.
|
||||
// collinear if normals are equal or opposite: cos(a) in {-1, 1}
|
||||
if (!collinear && math::equals(math::abs(dot_n1n2), c1))
|
||||
if (! collinear && math::equals(math::abs(dot_n1n2), c1))
|
||||
{
|
||||
collinear = true;
|
||||
sides.set<0>(0, 0);
|
||||
@@ -324,12 +392,12 @@ struct relate_spherical_segments
|
||||
{
|
||||
if (a_is_point)
|
||||
{
|
||||
return collinear_one_degenerted<Policy, calc_t>(a, true, b1, b2, a1, a2, b1v, b2v, norm2, a1v);
|
||||
return collinear_one_degenerated<Policy, calc_t>(a, true, b1, b2, a1, a2, b1v, b2v, plane2, a1v);
|
||||
}
|
||||
else if (b_is_point)
|
||||
{
|
||||
// b2 used to be consistent with (degenerated) checks above (is it needed?)
|
||||
return collinear_one_degenerted<Policy, calc_t>(b, false, a1, a2, b1, b2, a1v, a2v, norm1, b1v);
|
||||
return collinear_one_degenerated<Policy, calc_t>(b, false, a1, a2, b1, b2, a1v, a2v, plane1, b1v);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -338,16 +406,16 @@ struct relate_spherical_segments
|
||||
// use shorter segment
|
||||
if (len1 <= len2)
|
||||
{
|
||||
calculate_collinear_data(a1, a2, b1, b2, a1v, a2v, norm1, b1v, dist_a1_a2, dist_a1_b1);
|
||||
calculate_collinear_data(a1, a2, b1, b2, a1v, a2v, norm1, b2v, dist_a1_a2, dist_a1_b2);
|
||||
calculate_collinear_data(a1, a2, b1, b2, a1v, a2v, plane1, b1v, dist_a1_a2, dist_a1_b1);
|
||||
calculate_collinear_data(a1, a2, b1, b2, a1v, a2v, plane1, b2v, dist_a1_a2, dist_a1_b2);
|
||||
dist_b1_b2 = dist_a1_b2 - dist_a1_b1;
|
||||
dist_b1_a1 = -dist_a1_b1;
|
||||
dist_b1_a2 = dist_a1_a2 - dist_a1_b1;
|
||||
}
|
||||
else
|
||||
{
|
||||
calculate_collinear_data(b1, b2, a1, a2, b1v, b2v, norm2, a1v, dist_b1_b2, dist_b1_a1);
|
||||
calculate_collinear_data(b1, b2, a1, a2, b1v, b2v, norm2, a2v, dist_b1_b2, dist_b1_a2);
|
||||
calculate_collinear_data(b1, b2, a1, a2, b1v, b2v, plane2, a1v, dist_b1_b2, dist_b1_a1);
|
||||
calculate_collinear_data(b1, b2, a1, a2, b1v, b2v, plane2, a2v, dist_b1_b2, dist_b1_a2);
|
||||
dist_a1_a2 = dist_b1_a2 - dist_b1_a1;
|
||||
dist_a1_b1 = -dist_b1_a1;
|
||||
dist_a1_b2 = dist_b1_b2 - dist_b1_a1;
|
||||
@@ -408,7 +476,8 @@ struct relate_spherical_segments
|
||||
vec3d_t i1;
|
||||
intersection_point_flag ip_flag;
|
||||
calc_t dist_a1_a2, dist_a1_i1, dist_b1_b2, dist_b1_i1;
|
||||
if (calculate_ip_data(a1, a2, b1, b2, a1v, a2v, b1v, b2v, norm1, norm2, sides,
|
||||
if (calculate_ip_data(a1, a2, b1, b2, a1v, a2v, b1v, b2v,
|
||||
plane1, plane2, calc_policy, sides,
|
||||
i1, dist_a1_a2, dist_a1_i1, dist_b1_b2, dist_b1_i1, ip_flag))
|
||||
{
|
||||
// intersects
|
||||
@@ -417,7 +486,7 @@ struct relate_spherical_segments
|
||||
calc_t,
|
||||
segment_ratio<calc_t>,
|
||||
vec3d_t
|
||||
> sinfo;
|
||||
> sinfo(calc_policy);
|
||||
|
||||
sinfo.robust_ra.assign(dist_a1_i1, dist_a1_a2);
|
||||
sinfo.robust_rb.assign(dist_b1_i1, dist_b1_b2);
|
||||
@@ -434,31 +503,32 @@ struct relate_spherical_segments
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Policy, typename CalcT, typename Segment, typename Point1, typename Point2, typename Vec3d>
|
||||
template <typename Policy, typename CalcT, typename Segment, typename Point1, typename Point2, typename Vec3d, typename Plane>
|
||||
static inline typename Policy::return_type
|
||||
collinear_one_degenerted(Segment const& segment, bool degenerated_a,
|
||||
Point1 const& a1, Point1 const& a2,
|
||||
Point2 const& b1, Point2 const& b2,
|
||||
Vec3d const& v1, Vec3d const& v2, Vec3d const& norm,
|
||||
Vec3d const& vother)
|
||||
collinear_one_degenerated(Segment const& segment, bool degenerated_a,
|
||||
Point1 const& a1, Point1 const& a2,
|
||||
Point2 const& b1, Point2 const& b2,
|
||||
Vec3d const& v1, Vec3d const& v2,
|
||||
Plane const& plane,
|
||||
Vec3d const& vother)
|
||||
{
|
||||
CalcT dist_1_2, dist_1_o;
|
||||
return ! calculate_collinear_data(a1, a2, b1, b2, v1, v2, norm, vother, dist_1_2, dist_1_o)
|
||||
return ! calculate_collinear_data(a1, a2, b1, b2, v1, v2, plane, vother, dist_1_2, dist_1_o)
|
||||
? Policy::disjoint()
|
||||
: Policy::one_degenerate(segment, segment_ratio<CalcT>(dist_1_o, dist_1_2), degenerated_a);
|
||||
}
|
||||
|
||||
template <typename Point1, typename Point2, typename Vec3d, typename CalcT>
|
||||
static inline bool calculate_collinear_data(Point1 const& a1, Point1 const& a2,
|
||||
Point2 const& b1, Point2 const& b2,
|
||||
Vec3d const& a1v, // in
|
||||
Vec3d const& a2v, // in
|
||||
Vec3d const& norm1, // in
|
||||
Vec3d const& b1v_or_b2v, // in
|
||||
template <typename Point1, typename Point2, typename Vec3d, typename Plane, typename CalcT>
|
||||
static inline bool calculate_collinear_data(Point1 const& a1, Point1 const& a2, // in
|
||||
Point2 const& b1, Point2 const& b2, // in
|
||||
Vec3d const& a1v, // in
|
||||
Vec3d const& a2v, // in
|
||||
Plane const& plane1, // in
|
||||
Vec3d const& b1v_or_b2v, // in
|
||||
CalcT& dist_a1_a2, CalcT& dist_a1_i1) // out
|
||||
{
|
||||
// calculate dist_a1_a2 and dist_a1_i1
|
||||
calculate_dists(a1v, a2v, norm1, b1v_or_b2v, dist_a1_a2, dist_a1_i1);
|
||||
calculate_dists(a1v, a2v, plane1, b1v_or_b2v, dist_a1_a2, dist_a1_i1);
|
||||
|
||||
// if i1 is close to a1 and b1 or b2 is equal to a1
|
||||
if (is_endpoint_equal(dist_a1_i1, a1, b1, b2))
|
||||
@@ -477,54 +547,53 @@ private:
|
||||
return segment_ratio<CalcT>(dist_a1_i1, dist_a1_a2).on_segment();
|
||||
}
|
||||
|
||||
template <typename Point1, typename Point2, typename Vec3d, typename CalcT>
|
||||
template <typename Point1, typename Point2, typename Vec3d, typename Plane, typename CalcT>
|
||||
static inline bool calculate_ip_data(Point1 const& a1, Point1 const& a2, // in
|
||||
Point2 const& b1, Point2 const& b2, // in
|
||||
Vec3d const& a1v, Vec3d const& a2v, // in
|
||||
Vec3d const& b1v, Vec3d const& b2v, // in
|
||||
Vec3d const& norm1, Vec3d const& norm2, // in
|
||||
side_info const& sides, // in
|
||||
Vec3d & i1, // in-out
|
||||
CalcT& dist_a1_a2, CalcT& dist_a1_i1, // out
|
||||
CalcT& dist_b1_b2, CalcT& dist_b1_i1, // out
|
||||
Plane const& plane1, // in
|
||||
Plane const& plane2, // in
|
||||
CalcPolicy const& calc_policy, // in
|
||||
side_info const& sides, // in
|
||||
Vec3d & ip, // out
|
||||
CalcT& dist_a1_a2, CalcT& dist_a1_ip, // out
|
||||
CalcT& dist_b1_b2, CalcT& dist_b1_ip, // out
|
||||
intersection_point_flag& ip_flag) // out
|
||||
{
|
||||
// great circles intersections
|
||||
i1 = cross_product(norm1, norm2);
|
||||
// NOTE: the length should be greater than 0 at this point
|
||||
// if the normals were not normalized and their dot product
|
||||
// not checked before this function is called the length
|
||||
// should be checked here (math::equals(len, c0))
|
||||
CalcT const len = math::sqrt(dot_product(i1, i1));
|
||||
divide_value(i1, len); // normalize i1
|
||||
|
||||
calculate_dists(a1v, a2v, norm1, i1, dist_a1_a2, dist_a1_i1);
|
||||
Vec3d ip1, ip2;
|
||||
calc_policy.intersection_points(plane1, plane2, ip1, ip2);
|
||||
|
||||
calculate_dists(a1v, a2v, plane1, ip1, dist_a1_a2, dist_a1_ip);
|
||||
ip = ip1;
|
||||
|
||||
// choose the opposite side of the globe if the distance is shorter
|
||||
{
|
||||
CalcT const d = abs_distance(dist_a1_a2, dist_a1_i1);
|
||||
CalcT const d = abs_distance(dist_a1_a2, dist_a1_ip);
|
||||
if (d > CalcT(0))
|
||||
{
|
||||
CalcT const dist_a1_i2 = dist_of_i2(dist_a1_i1);
|
||||
// TODO: this should be ok not only for sphere
|
||||
// but requires more investigation
|
||||
CalcT const dist_a1_i2 = dist_of_i2(dist_a1_ip);
|
||||
CalcT const d2 = abs_distance(dist_a1_a2, dist_a1_i2);
|
||||
if (d2 < d)
|
||||
{
|
||||
dist_a1_i1 = dist_a1_i2;
|
||||
multiply_value(i1, CalcT(-1)); // the opposite intersection
|
||||
dist_a1_ip = dist_a1_i2;
|
||||
ip = ip2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool is_on_a = false, is_near_a1 = false, is_near_a2 = false;
|
||||
if (! is_potentially_crossing(dist_a1_a2, dist_a1_i1, is_on_a, is_near_a1, is_near_a2))
|
||||
if (! is_potentially_crossing(dist_a1_a2, dist_a1_ip, is_on_a, is_near_a1, is_near_a2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
calculate_dists(b1v, b2v, norm2, i1, dist_b1_b2, dist_b1_i1);
|
||||
calculate_dists(b1v, b2v, plane2, ip, dist_b1_b2, dist_b1_ip);
|
||||
|
||||
bool is_on_b = false, is_near_b1 = false, is_near_b2 = false;
|
||||
if (! is_potentially_crossing(dist_b1_b2, dist_b1_i1, is_on_b, is_near_b1, is_near_b2))
|
||||
if (! is_potentially_crossing(dist_b1_b2, dist_b1_ip, is_on_b, is_near_b1, is_near_b2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -535,8 +604,8 @@ private:
|
||||
{
|
||||
if (is_near_b1 && equals_point_point(a1, b1))
|
||||
{
|
||||
dist_a1_i1 = 0;
|
||||
dist_b1_i1 = 0;
|
||||
dist_a1_ip = 0;
|
||||
dist_b1_ip = 0;
|
||||
//i1 = a1v;
|
||||
ip_flag = ipi_at_a1;
|
||||
return true;
|
||||
@@ -544,8 +613,8 @@ private:
|
||||
|
||||
if (is_near_b2 && equals_point_point(a1, b2))
|
||||
{
|
||||
dist_a1_i1 = 0;
|
||||
dist_b1_i1 = dist_b1_b2;
|
||||
dist_a1_ip = 0;
|
||||
dist_b1_ip = dist_b1_b2;
|
||||
//i1 = a1v;
|
||||
ip_flag = ipi_at_a1;
|
||||
return true;
|
||||
@@ -556,8 +625,8 @@ private:
|
||||
{
|
||||
if (is_near_b1 && equals_point_point(a2, b1))
|
||||
{
|
||||
dist_a1_i1 = dist_a1_a2;
|
||||
dist_b1_i1 = 0;
|
||||
dist_a1_ip = dist_a1_a2;
|
||||
dist_b1_ip = 0;
|
||||
//i1 = a2v;
|
||||
ip_flag = ipi_at_a2;
|
||||
return true;
|
||||
@@ -565,8 +634,8 @@ private:
|
||||
|
||||
if (is_near_b2 && equals_point_point(a2, b2))
|
||||
{
|
||||
dist_a1_i1 = dist_a1_a2;
|
||||
dist_b1_i1 = dist_b1_b2;
|
||||
dist_a1_ip = dist_a1_a2;
|
||||
dist_b1_ip = dist_b1_b2;
|
||||
//i1 = a2v;
|
||||
ip_flag = ipi_at_a2;
|
||||
return true;
|
||||
@@ -580,7 +649,7 @@ private:
|
||||
{
|
||||
if (is_near_b1 && sides.template get<1, 0>() == 0) // b1 wrt a
|
||||
{
|
||||
dist_b1_i1 = 0;
|
||||
dist_b1_ip = 0;
|
||||
//i1 = b1v;
|
||||
ip_flag = ipi_at_b1;
|
||||
return true;
|
||||
@@ -588,7 +657,7 @@ private:
|
||||
|
||||
if (is_near_b2 && sides.template get<1, 1>() == 0) // b2 wrt a
|
||||
{
|
||||
dist_b1_i1 = dist_b1_b2;
|
||||
dist_b1_ip = dist_b1_b2;
|
||||
//i1 = b2v;
|
||||
ip_flag = ipi_at_b2;
|
||||
return true;
|
||||
@@ -599,7 +668,7 @@ private:
|
||||
{
|
||||
if (is_near_a1 && sides.template get<0, 0>() == 0) // a1 wrt b
|
||||
{
|
||||
dist_a1_i1 = 0;
|
||||
dist_a1_ip = 0;
|
||||
//i1 = a1v;
|
||||
ip_flag = ipi_at_a1;
|
||||
return true;
|
||||
@@ -607,7 +676,7 @@ private:
|
||||
|
||||
if (is_near_a2 && sides.template get<0, 1>() == 0) // a2 wrt b
|
||||
{
|
||||
dist_a1_i1 = dist_a1_a2;
|
||||
dist_a1_ip = dist_a1_a2;
|
||||
//i1 = a2v;
|
||||
ip_flag = ipi_at_a2;
|
||||
return true;
|
||||
@@ -619,24 +688,26 @@ private:
|
||||
return is_on_a && is_on_b;
|
||||
}
|
||||
|
||||
template <typename Vec3d, typename CalcT>
|
||||
static inline void calculate_dists(Vec3d const& a1v, // in
|
||||
Vec3d const& a2v, // in
|
||||
Vec3d const& norm1, // in
|
||||
Vec3d const& i1, // in
|
||||
CalcT& dist_a1_a2, CalcT& dist_a1_i1) // out
|
||||
template <typename Vec3d, typename Plane, typename CalcT>
|
||||
static inline void calculate_dists(Vec3d const& a1v, // in
|
||||
Vec3d const& a2v, // in
|
||||
Plane const& plane1, // in
|
||||
Vec3d const& i1, // in
|
||||
CalcT& dist_a1_a2, // out
|
||||
CalcT& dist_a1_i1) // out
|
||||
{
|
||||
CalcT const c0 = 0;
|
||||
//CalcT const c0 = 0;
|
||||
CalcT const c1 = 1;
|
||||
CalcT const c2 = 2;
|
||||
CalcT const c4 = 4;
|
||||
|
||||
CalcT cos_a1_a2 = dot_product(a1v, a2v);
|
||||
CalcT cos_a1_a2 = plane1.cos_angle_between(a1v, a2v);
|
||||
dist_a1_a2 = -cos_a1_a2 + c1; // [1, -1] -> [0, 2] representing [0, pi]
|
||||
|
||||
CalcT cos_a1_i1 = dot_product(a1v, i1);
|
||||
bool is_forward = true;
|
||||
CalcT cos_a1_i1 = plane1.cos_angle_between(a1v, i1, is_forward);
|
||||
dist_a1_i1 = -cos_a1_i1 + c1; // [0, 2] representing [0, pi]
|
||||
if (dot_product(norm1, cross_product(a1v, i1)) < c0) // left or right of a1 on a
|
||||
if (! is_forward) // left or right of a1 on a
|
||||
{
|
||||
dist_a1_i1 = -dist_a1_i1; // [0, 2] -> [0, -2] representing [0, -pi]
|
||||
}
|
||||
@@ -716,6 +787,88 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
struct relate_spherical_segments_calc_policy
|
||||
{
|
||||
template <typename Point, typename Point3d>
|
||||
static Point from_cart3d(Point3d const& point_3d)
|
||||
{
|
||||
return formula::cart3d_to_sph<Point>(point_3d);
|
||||
}
|
||||
|
||||
template <typename Point3d, typename Point>
|
||||
static Point3d to_cart3d(Point const& point)
|
||||
{
|
||||
return formula::sph_to_cart3d<Point3d>(point);
|
||||
}
|
||||
|
||||
template <typename Point3d>
|
||||
struct plane
|
||||
{
|
||||
typedef typename coordinate_type<Point3d>::type coord_t;
|
||||
|
||||
// not normalized
|
||||
plane(Point3d const& p1, Point3d const& p2)
|
||||
: normal(cross_product(p1, p2))
|
||||
{}
|
||||
|
||||
int side_value(Point3d const& pt) const
|
||||
{
|
||||
return formula::sph_side_value(normal, pt);
|
||||
}
|
||||
|
||||
static coord_t cos_angle_between(Point3d const& p1, Point3d const& p2)
|
||||
{
|
||||
return dot_product(p1, p2);
|
||||
}
|
||||
|
||||
coord_t cos_angle_between(Point3d const& p1, Point3d const& p2, bool & is_forward) const
|
||||
{
|
||||
coord_t const c0 = 0;
|
||||
is_forward = dot_product(normal, cross_product(p1, p2)) >= c0;
|
||||
return dot_product(p1, p2);
|
||||
}
|
||||
|
||||
Point3d normal;
|
||||
};
|
||||
|
||||
template <typename Point3d>
|
||||
static plane<Point3d> get_plane(Point3d const& p1, Point3d const& p2)
|
||||
{
|
||||
return plane<Point3d>(p1, p2);
|
||||
}
|
||||
|
||||
template <typename Point3d>
|
||||
static bool intersection_points(plane<Point3d> const& plane1,
|
||||
plane<Point3d> const& plane2,
|
||||
Point3d & ip1, Point3d & ip2)
|
||||
{
|
||||
typedef typename coordinate_type<Point3d>::type coord_t;
|
||||
|
||||
ip1 = cross_product(plane1.normal, plane2.normal);
|
||||
// NOTE: the length should be greater than 0 at this point
|
||||
// if the normals were not normalized and their dot product
|
||||
// not checked before this function is called the length
|
||||
// should be checked here (math::equals(len, c0))
|
||||
coord_t const len = math::sqrt(dot_product(ip1, ip1));
|
||||
divide_value(ip1, len); // normalize i1
|
||||
|
||||
ip2 = ip1;
|
||||
multiply_value(ip2, coord_t(-1));
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename CalculationType = void>
|
||||
struct relate_spherical_segments
|
||||
: relate_ecef_segments
|
||||
<
|
||||
relate_spherical_segments_calc_policy,
|
||||
CalculationType
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
namespace services
|
||||
@@ -736,6 +889,11 @@ struct default_strategy<spherical_equatorial_tag, CalculationType>
|
||||
template <typename CalculationType>
|
||||
struct default_strategy<geographic_tag, CalculationType>
|
||||
{
|
||||
// NOTE: Spherical strategy returns the same result as the geographic one
|
||||
// representing segments as great elliptic arcs. If the elliptic arcs are
|
||||
// not great elliptic arcs (the origin not in the center of the coordinate
|
||||
// system) then there may be problems with consistency of the side and
|
||||
// intersection strategies.
|
||||
typedef relate_spherical_segments<CalculationType> type;
|
||||
};
|
||||
|
||||
|
||||
@@ -80,10 +80,14 @@
|
||||
#include <boost/geometry/strategies/geographic/area_geographic.hpp>
|
||||
#include <boost/geometry/strategies/geographic/azimuth_geographic.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>
|
||||
#include <boost/geometry/strategies/geographic/distance_thomas.hpp>
|
||||
#include <boost/geometry/strategies/geographic/distance_vincenty.hpp>
|
||||
#include <boost/geometry/strategies/geographic/envelope_segment.hpp>
|
||||
//#include <boost/geometry/strategies/geographic/geodesic_intersection.hpp>
|
||||
//#include <boost/geometry/strategies/geographic/intersection.hpp>
|
||||
//#include <boost/geometry/strategies/geographic/side.hpp>
|
||||
//#include <boost/geometry/strategies/geographic/side_andoyer.hpp>
|
||||
//#include <boost/geometry/strategies/geographic/side_thomas.hpp>
|
||||
//#include <boost/geometry/strategies/geographic/side_vincenty.hpp>
|
||||
|
||||
@@ -71,6 +71,19 @@ inline T const& greatest(T const& v1, T const& v2, T const& v3, T const& v4, T c
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
inline T bounded(T const& v, T const& lower, T const& upper)
|
||||
{
|
||||
return (std::min)((std::max)(v, lower), upper);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T bounded(T const& v, T const& lower)
|
||||
{
|
||||
return (std::max)(v, lower);
|
||||
}
|
||||
|
||||
|
||||
template <typename T,
|
||||
bool IsFloatingPoint = boost::is_floating_point<T>::value>
|
||||
struct abs
|
||||
|
||||
@@ -282,6 +282,40 @@ inline CoordinateType longitude_distance_unsigned(CoordinateType const& longitud
|
||||
return diff;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief The abs difference between longitudes in range [0, 180].
|
||||
\tparam Units The units of the coordindate system in the spheroid
|
||||
\tparam CoordinateType The type of the coordinates
|
||||
\param longitude1 Longitude 1
|
||||
\param longitude2 Longitude 2
|
||||
\ingroup utility
|
||||
*/
|
||||
template <typename Units, typename CoordinateType>
|
||||
inline CoordinateType longitude_difference(CoordinateType const& longitude1,
|
||||
CoordinateType const& longitude2)
|
||||
{
|
||||
return math::abs(math::longitude_distance_signed<Units>(longitude1, longitude2));
|
||||
}
|
||||
|
||||
template <typename Units, typename CoordinateType>
|
||||
inline CoordinateType longitude_interval_distance_signed(CoordinateType const& longitude_a1,
|
||||
CoordinateType const& longitude_a2,
|
||||
CoordinateType const& longitude_b)
|
||||
{
|
||||
CoordinateType const c0 = 0;
|
||||
CoordinateType dist_a12 = longitude_distance_signed<Units>(longitude_a1, longitude_a2);
|
||||
CoordinateType dist_a1b = longitude_distance_signed<Units>(longitude_a1, longitude_b);
|
||||
if (dist_a12 < c0)
|
||||
{
|
||||
dist_a12 = -dist_a12;
|
||||
dist_a1b = -dist_a1b;
|
||||
}
|
||||
|
||||
return dist_a1b < c0 ? dist_a1b
|
||||
: dist_a1b > dist_a12 ? dist_a1b - dist_a12
|
||||
: c0;
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
|
||||
#include "test_envelope_expand_on_spheroid.hpp"
|
||||
|
||||
|
||||
template <
|
||||
template <typename, bool, bool, bool, bool, bool> class Inverse,
|
||||
typename CS_Tag
|
||||
@@ -152,11 +153,54 @@ private:
|
||||
BOOST_CHECK_MESSAGE(same_boxes, stream.str());
|
||||
}
|
||||
|
||||
template <typename Box, typename Geometry>
|
||||
template
|
||||
<
|
||||
typename Geometry, typename Box,
|
||||
typename T1, typename T2, typename T3, typename T4
|
||||
>
|
||||
static inline void check_message(bool same_boxes,
|
||||
std::string const& case_id,
|
||||
std::string const& units_str,
|
||||
Geometry const& geometry,
|
||||
T1 const& lon_min, T2 const& lat_min, double height_min,
|
||||
T3 const& lon_max, T4 const& lat_max, double height_max,
|
||||
Box const& detected)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
stream << "case ID: " << case_id << ", "
|
||||
<< "MBR units: " << units_str << "; "
|
||||
<< "geometry: ";
|
||||
|
||||
write_geometry<Geometry>::apply(stream, geometry);
|
||||
|
||||
stream << std::setprecision(17);
|
||||
|
||||
stream << "; " << "expected: ";
|
||||
|
||||
if (BOOST_GEOMETRY_CONDITION(bg::dimension<Box>::value == 2))
|
||||
{
|
||||
stream << "(" << lon_min << " " << lat_min
|
||||
<< ", " << lon_max << " " << lat_max << ")";
|
||||
}
|
||||
else
|
||||
{
|
||||
stream << "(" << lon_min << " " << lat_min << " " << height_min
|
||||
<< ", " << lon_max << " " << lat_max << " " << height_max << ")";
|
||||
}
|
||||
stream << ", " << "detected: " << bg::dsv(detected);
|
||||
|
||||
BOOST_CHECK_MESSAGE(same_boxes, stream.str());
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename Box, typename Geometry,
|
||||
typename T1, typename T2, typename T3, typename T4
|
||||
>
|
||||
static inline void base_test(std::string const& case_id,
|
||||
Geometry const& geometry,
|
||||
double lon_min, double lat_min, double height_min,
|
||||
double lon_max, double lat_max, double height_max,
|
||||
T1 const& lon_min, T2 const& lat_min, double height_min,
|
||||
T3 const& lon_max, T4 const& lat_max, double height_max,
|
||||
double tolerance)
|
||||
{
|
||||
typedef typename bg::coordinate_system<Box>::type::units box_units_type;
|
||||
@@ -168,27 +212,40 @@ private:
|
||||
typename bg::cs_tag<Geometry>::type
|
||||
>::apply(geometry, detected);
|
||||
|
||||
Box expected;
|
||||
initialize_box<Box>::apply(expected,
|
||||
lon_min, lat_min, height_min,
|
||||
lon_max, lat_max, height_max);
|
||||
|
||||
#ifdef BOOST_GEOMETRY_TEST_DEBUG
|
||||
std::cout << "geometry: ";
|
||||
write_geometry<Geometry>::apply(std::cout, geometry);
|
||||
|
||||
std::cout << std::endl
|
||||
<< "MBR units: " << units_str
|
||||
<< std::endl
|
||||
<< "expected: " << bg::dsv(expected)
|
||||
<< std::endl
|
||||
<< std::endl;
|
||||
std::cout << "expected: ";
|
||||
if (BOOST_GEOMETRY_CONDITION(bg::dimension<Box>::value == 2))
|
||||
{
|
||||
std::cout << "(" << lon_min << " " << lat_min
|
||||
<< ", " << lon_max << " " << lat_max << ")";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "(" << lon_min << " " << lat_min << " " << height_min
|
||||
<< ", " << lon_max << " " << lat_max << " " << height_max << ")";
|
||||
}
|
||||
std::cout << std::endl
|
||||
<< "detected: " << bg::dsv(detected)
|
||||
<< std::endl << std::endl;
|
||||
#endif
|
||||
|
||||
check_message(box_equals<Box>::apply(detected, expected, tolerance),
|
||||
bool check = box_check_equals<Box>::apply(detected,
|
||||
lon_min, lat_min, height_min,
|
||||
lon_max, lat_max, height_max,
|
||||
tolerance);
|
||||
|
||||
check_message(check,
|
||||
case_id, units_str,
|
||||
geometry, expected, detected);
|
||||
geometry,
|
||||
lon_min, lat_min, height_min,
|
||||
lon_max, lat_max, height_max,
|
||||
detected);
|
||||
|
||||
// if valid box is expected, check the validity
|
||||
if (lon_min <= lon_max && lat_min <= lat_max && height_min <= height_max)
|
||||
@@ -201,11 +258,15 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename Geometry>
|
||||
template
|
||||
<
|
||||
typename Geometry,
|
||||
typename T1, typename T2, typename T3, typename T4
|
||||
>
|
||||
static inline void apply(std::string const& case_id,
|
||||
Geometry const& geometry,
|
||||
double lon_min, double lat_min, double height_min,
|
||||
double lon_max, double lat_max, double height_max,
|
||||
T1 const& lon_min, T2 const& lat_min, double height_min,
|
||||
T3 const& lon_max, T4 const& lat_max, double height_max,
|
||||
double tolerance)
|
||||
{
|
||||
typedef other_system_info
|
||||
@@ -291,12 +352,14 @@ template
|
||||
>
|
||||
struct test_envelope_on_sphere_or_spheroid
|
||||
{
|
||||
template <typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6, typename T7, typename T8>
|
||||
static inline void apply(std::string const& case_id,
|
||||
Geometry const& geometry,
|
||||
double lon_min1, double lat_min1, double height_min1,
|
||||
double lon_max1, double lat_max1, double height_max1,
|
||||
double lon_min2, double lat_min2, double height_min2,
|
||||
double lon_max2, double lat_max2, double height_max2,
|
||||
T1 const& lon_min1, T2 const& lat_min1, double height_min1,
|
||||
T3 const& lon_max1, T4 const& lat_max1, double height_max1,
|
||||
T5 const& lon_min2, T6 const& lat_min2, double height_min2,
|
||||
T7 const& lon_max2, T8 const& lat_max2, double height_max2,
|
||||
double tolerance = std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
envelope_on_spheroid_basic_tester
|
||||
@@ -328,12 +391,14 @@ struct test_envelope_on_sphere_or_spheroid
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6, typename T7, typename T8>
|
||||
static inline void apply(std::string const& case_id,
|
||||
Geometry const& geometry,
|
||||
double lon_min1, double lat_min1,
|
||||
double lon_max1, double lat_max1,
|
||||
double lon_min2, double lat_min2,
|
||||
double lon_max2, double lat_max2,
|
||||
T1 const& lon_min1, T2 const& lat_min1,
|
||||
T3 const& lon_max1, T4 const& lat_max1,
|
||||
T5 const& lon_min2, T6 const& lat_min2,
|
||||
T7 const& lon_max2, T8 const& lat_max2,
|
||||
double tolerance = std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
apply(case_id, geometry,
|
||||
@@ -342,10 +407,11 @@ struct test_envelope_on_sphere_or_spheroid
|
||||
tolerance);
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4>
|
||||
static inline void apply(std::string const& case_id,
|
||||
Geometry const& geometry,
|
||||
double lon_min, double lat_min, double height_min,
|
||||
double lon_max, double lat_max, double height_max,
|
||||
T1 const& lon_min, T2 const& lat_min, double height_min,
|
||||
T3 const& lon_max, T4 const& lat_max, double height_max,
|
||||
double tolerance = std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
apply(case_id, geometry,
|
||||
@@ -356,10 +422,11 @@ struct test_envelope_on_sphere_or_spheroid
|
||||
tolerance);
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4>
|
||||
static inline void apply(std::string const& case_id,
|
||||
Geometry const& geometry,
|
||||
double lon_min, double lat_min,
|
||||
double lon_max, double lat_max,
|
||||
T1 const& lon_min, T2 const& lat_min,
|
||||
T3 const& lon_max, T4 const& lat_max,
|
||||
double tolerance = std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
apply(case_id, geometry,
|
||||
@@ -373,13 +440,15 @@ struct test_envelope_on_sphere_or_spheroid
|
||||
template <typename Geometry, typename MBR, bool TestReverse>
|
||||
struct test_envelope_on_sphere_or_spheroid<Geometry, MBR, bg::ring_tag, TestReverse>
|
||||
{
|
||||
template <typename T1, typename T2, typename T3, typename T4,
|
||||
typename T5, typename T6, typename T7, typename T8>
|
||||
static inline void apply(std::string const& case_id,
|
||||
Geometry const& geometry,
|
||||
double lon_min1, double lat_min1,
|
||||
double lon_max1, double lat_max1,
|
||||
double lon_min2, double lat_min2,
|
||||
double lon_max2, double lat_max2,
|
||||
double tolerance = std::numeric_limits<double>::epsilon())
|
||||
T1 const& lon_min1, T2 const& lat_min1,
|
||||
T3 const& lon_max1, T4 const& lat_max1,
|
||||
T5 const& lon_min2, T6 const& lat_min2,
|
||||
T7 const& lon_max2, T8 const& lat_max2,
|
||||
double const& tolerance = std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
envelope_on_spheroid_basic_tester
|
||||
<
|
||||
@@ -409,10 +478,11 @@ struct test_envelope_on_sphere_or_spheroid<Geometry, MBR, bg::ring_tag, TestReve
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4>
|
||||
static inline void apply(std::string const& case_id,
|
||||
Geometry const& geometry,
|
||||
double lon_min, double lat_min,
|
||||
double lon_max, double lat_max,
|
||||
T1 const& lon_min, T2 const& lat_min,
|
||||
T3 const& lon_max, T4 const& lat_max,
|
||||
double tolerance = std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
apply(case_id, geometry,
|
||||
@@ -822,26 +892,24 @@ BOOST_AUTO_TEST_CASE( envelope_segment_spheroid )
|
||||
|
||||
tester::apply("s09",
|
||||
from_wkt<G>("SEGMENT(1 -45,179 30)"),
|
||||
1, -85.392785243526134, 179, 30,
|
||||
3 * eps);
|
||||
1, rng(-85.392785243526134, -85.392785243525253), 179, 30);
|
||||
|
||||
tester::apply("s09a",
|
||||
from_wkt<G>("SEGMENT(2 -45,181 30)"),
|
||||
2, -87.689300911353811, 181, 30);
|
||||
2, rng(-87.689300911353811, -87.689300911353371), 181, 30);
|
||||
|
||||
// very long segment
|
||||
tester::apply("s10",
|
||||
from_wkt<G>("SEGMENT(0 -45,181 30)"),
|
||||
-179, -87.689300911353797, 0, 30,
|
||||
2.0 * eps);
|
||||
-179, rng(-87.689300911353797, -87.689300911353385), 0, 30);
|
||||
|
||||
tester::apply("s11",
|
||||
from_wkt<G>("SEGMENT(260 30,20 45)"),
|
||||
-100, 30, 20, 57.990810958016965);
|
||||
-100, 30, 20, rng(57.990810958016482, 57.990810958016965));
|
||||
|
||||
tester::apply("s11a",
|
||||
from_wkt<G>("SEGMENT(260 45,20 30)"),
|
||||
-100, 30, 20, 57.990810958016965);
|
||||
-100, 30, 20, rng(57.990810958016453, 57.990810958016965));
|
||||
|
||||
// segment degenerating to the north pole
|
||||
tester::apply("s12",
|
||||
@@ -859,7 +927,7 @@ BOOST_AUTO_TEST_CASE( envelope_segment_spheroid )
|
||||
|
||||
tester::apply("s15",
|
||||
from_wkt<G>("SEGMENT(50 45,185 45)"),
|
||||
50, 45, 185, 69.098479073903178);
|
||||
50, 45, 185, rng(69.098479073902851, 69.098479073903178));
|
||||
|
||||
// segment that lies on the equator
|
||||
tester::apply("s16",
|
||||
@@ -924,7 +992,7 @@ BOOST_AUTO_TEST_CASE( envelope_segment_spheroid )
|
||||
1-heps, 1, 1, 1);
|
||||
tester::apply("s104",
|
||||
G(P(2, 1), P(1, 1-heps)),
|
||||
1, 1-heps, 2, 1.0000383271569036);
|
||||
1, 1-heps, 2, rng(1.0000383271568751, 1.0000383271569036));
|
||||
tester::apply("s105",
|
||||
G(P(1, 2), P(1-heps, 1)),
|
||||
1-heps, 1, 1, 2);
|
||||
@@ -940,13 +1008,11 @@ BOOST_AUTO_TEST_CASE( envelope_segment_spheroid_with_strategy_thomas )
|
||||
typedef test_envelope_on_sphere_or_spheroid
|
||||
<
|
||||
G, B,
|
||||
typename bg::tag<G>::type,
|
||||
bg::tag<G>::type,
|
||||
test_reverse_geometry<G>::value,
|
||||
bg::formula::thomas_inverse
|
||||
> tester;
|
||||
|
||||
double const eps = std::numeric_limits<double>::epsilon();
|
||||
|
||||
tester::apply("s01",
|
||||
from_wkt<G>("SEGMENT(10 10,40 40)"),
|
||||
10, 10, 40, 40);
|
||||
@@ -1011,26 +1077,24 @@ BOOST_AUTO_TEST_CASE( envelope_segment_spheroid_with_strategy_thomas )
|
||||
|
||||
tester::apply("s09",
|
||||
from_wkt<G>("SEGMENT(1 -45,179 30)"),
|
||||
1, -85.392785243526134, 179, 30,
|
||||
3 * eps);
|
||||
1, rng(-85.392785243526134, -85.392785243525253), 179, 30);
|
||||
|
||||
tester::apply("s09a",
|
||||
from_wkt<G>("SEGMENT(2 -45,181 30)"),
|
||||
2, -87.689300911353811, 181, 30);
|
||||
2, rng(-87.689300911353811, -87.689300911353371), 181, 30);
|
||||
|
||||
// very long segment
|
||||
tester::apply("s10",
|
||||
from_wkt<G>("SEGMENT(0 -45,181 30)"),
|
||||
-179, -87.689300911353797, 0, 30,
|
||||
2.0 * eps);
|
||||
-179, rng(-87.689300911353797, -87.689300911353385), 0, 30);
|
||||
|
||||
tester::apply("s11",
|
||||
from_wkt<G>("SEGMENT(260 30,20 45)"),
|
||||
-100, 30, 20, 57.990810958016965);
|
||||
-100, 30, 20, rng(57.990810958016482, 57.990810958016965));
|
||||
|
||||
tester::apply("s11a",
|
||||
from_wkt<G>("SEGMENT(260 45,20 30)"),
|
||||
-100, 30, 20, 57.990810958016965);
|
||||
-100, 30, 20, rng(57.990810958016453, 57.990810958016965));
|
||||
|
||||
// segment degenerating to the north pole
|
||||
tester::apply("s12",
|
||||
@@ -1048,7 +1112,7 @@ BOOST_AUTO_TEST_CASE( envelope_segment_spheroid_with_strategy_thomas )
|
||||
|
||||
tester::apply("s15",
|
||||
from_wkt<G>("SEGMENT(50 45,185 45)"),
|
||||
50, 45, 185, 69.098479073903178);
|
||||
50, 45, 185, rng(69.098479073902851, 69.098479073903178));
|
||||
|
||||
// segment that lies on the equator
|
||||
tester::apply("s16",
|
||||
@@ -1098,13 +1162,11 @@ BOOST_AUTO_TEST_CASE( envelope_segment_spheroid_with_strategy_andoyer )
|
||||
typedef test_envelope_on_sphere_or_spheroid
|
||||
<
|
||||
G, B,
|
||||
typename bg::tag<G>::type,
|
||||
bg::tag<G>::type,
|
||||
test_reverse_geometry<G>::value,
|
||||
bg::formula::andoyer_inverse
|
||||
> tester;
|
||||
|
||||
double const eps = std::numeric_limits<double>::epsilon();
|
||||
|
||||
tester::apply("s01",
|
||||
from_wkt<G>("SEGMENT(10 10,40 40)"),
|
||||
10, 10, 40, 40);
|
||||
@@ -1169,26 +1231,24 @@ BOOST_AUTO_TEST_CASE( envelope_segment_spheroid_with_strategy_andoyer )
|
||||
|
||||
tester::apply("s09",
|
||||
from_wkt<G>("SEGMENT(1 -45,179 30)"),
|
||||
1, -85.394745211091248, 179, 30,
|
||||
3 * eps);
|
||||
1, rng(-85.394745211091248, -85.394745211090353), 179, 30);
|
||||
|
||||
tester::apply("s09a",
|
||||
from_wkt<G>("SEGMENT(2 -45,181 30)"),
|
||||
2, -87.690317839849726, 181, 30);
|
||||
2, rng(-87.690317839849726, -87.690317839849271), 181, 30);
|
||||
|
||||
// very long segment
|
||||
tester::apply("s10",
|
||||
from_wkt<G>("SEGMENT(0 -45,181 30)"),
|
||||
-179, -87.69031783984974, 0, 30,
|
||||
2.0 * eps);
|
||||
-179, rng(-87.69031783984974, -87.690317839849271), 0, 30);
|
||||
|
||||
tester::apply("s11",
|
||||
from_wkt<G>("SEGMENT(260 30,20 45)"),
|
||||
-100, 30, 20, 57.990742552280153);
|
||||
-100, 30, 20, rng(57.990742552279649, 57.990742552280153));
|
||||
|
||||
tester::apply("s11a",
|
||||
from_wkt<G>("SEGMENT(260 45,20 30)"),
|
||||
-100, 30, 20, 57.990742552280118);
|
||||
-100, 30, 20, rng(57.99074255227962, 57.990742552280118));
|
||||
|
||||
// segment degenerating to the north pole
|
||||
tester::apply("s12",
|
||||
@@ -1206,7 +1266,7 @@ BOOST_AUTO_TEST_CASE( envelope_segment_spheroid_with_strategy_andoyer )
|
||||
|
||||
tester::apply("s15",
|
||||
from_wkt<G>("SEGMENT(50 45,185 45)"),
|
||||
50, 45, 185, 69.09844689340845);
|
||||
50, 45, 185, rng(69.098446893408124, 69.09844689340845));
|
||||
|
||||
// segment that lies on the equator
|
||||
tester::apply("s16",
|
||||
@@ -1256,36 +1316,34 @@ BOOST_AUTO_TEST_CASE( envelope_segment_spheroid_with_strategy_vincenty )
|
||||
typedef test_envelope_on_sphere_or_spheroid
|
||||
<
|
||||
G, B,
|
||||
typename bg::tag<G>::type,
|
||||
bg::tag<G>::type,
|
||||
test_reverse_geometry<G>::value,
|
||||
bg::formula::vincenty_inverse
|
||||
> tester;
|
||||
|
||||
double const eps = std::numeric_limits<double>::epsilon();
|
||||
|
||||
tester::apply("s01",
|
||||
from_wkt<G>("SEGMENT(10 10,40 40)"),
|
||||
10, 10, 40, 40);
|
||||
|
||||
tester::apply("s02",
|
||||
from_wkt<G>("SEGMENT(10 10,40 10)"),
|
||||
10, 10, 40, 10.347587628821941);
|
||||
10, 10, 40, rng(10.347587628821937, 10.347587628821941));
|
||||
|
||||
tester::apply("s02a",
|
||||
from_wkt<G>("SEGMENT(40 10,10 10)"),
|
||||
10, 10, 40, 10.347587628821941);
|
||||
10, 10, 40, rng(10.347587628821937, 10.347587628821941));
|
||||
|
||||
tester::apply("s03",
|
||||
from_wkt<G>("SEGMENT(160 10,-170 10)"),
|
||||
160, 10, 190, 10.347587628821941);
|
||||
160, 10, 190, rng(10.347587628821937, 10.347587628821941));
|
||||
|
||||
tester::apply("s03a",
|
||||
from_wkt<G>("SEGMENT(-170 10,160 10)"),
|
||||
160, 10, 190, 10.347587628821941);
|
||||
160, 10, 190, rng(10.347587628821937, 10.347587628821941));
|
||||
|
||||
tester::apply("s03b",
|
||||
from_wkt<G>("SEGMENT(-170 -10,160 -10)"),
|
||||
160, -10.347587628821941, 190, -10);
|
||||
160, rng(-10.347587628821941, -10.347587628821937), 190, -10);
|
||||
|
||||
tester::apply("s04",
|
||||
from_wkt<G>("SEGMENT(-40 45,140 60)"),
|
||||
@@ -1327,26 +1385,24 @@ BOOST_AUTO_TEST_CASE( envelope_segment_spheroid_with_strategy_vincenty )
|
||||
|
||||
tester::apply("s09",
|
||||
from_wkt<G>("SEGMENT(1 -45,179 30)"),
|
||||
1, -85.392840929577218, 179, 30,
|
||||
3 * eps);
|
||||
1, rng(-85.392840929577218, -85.392840929576352), 179, 30);
|
||||
|
||||
tester::apply("s09a",
|
||||
from_wkt<G>("SEGMENT(2 -45,181 30)"),
|
||||
2, -87.689330275867817, 181, 30);
|
||||
2, rng(-87.689330275867817, -87.689330275867405), 181, 30);
|
||||
|
||||
// very long segment
|
||||
tester::apply("s10",
|
||||
from_wkt<G>("SEGMENT(0 -45,181 30)"),
|
||||
-179, -87.689330275867832, 0, 30,
|
||||
2.0 * eps);
|
||||
-179, rng(-87.689330275867832, -87.689330275867405), 0, 30);
|
||||
|
||||
tester::apply("s11",
|
||||
from_wkt<G>("SEGMENT(260 30,20 45)"),
|
||||
-100, 30, 20, 57.990810647057032);
|
||||
-100, 30, 20, rng(57.990810647056549, 57.990810647057032));
|
||||
|
||||
tester::apply("s11a",
|
||||
from_wkt<G>("SEGMENT(260 45,20 30)"),
|
||||
-100, 30, 20, 57.990810647057032);
|
||||
-100, 30, 20, rng(57.990810647056541, 57.990810647057032));
|
||||
|
||||
// segment degenerating to the north pole
|
||||
tester::apply("s12",
|
||||
@@ -1364,7 +1420,7 @@ BOOST_AUTO_TEST_CASE( envelope_segment_spheroid_with_strategy_vincenty )
|
||||
|
||||
tester::apply("s15",
|
||||
from_wkt<G>("SEGMENT(50 45,185 45)"),
|
||||
50, 45, 185, 69.098479136978497);
|
||||
50, 45, 185, rng(69.098479136978156, 69.098479136978497));
|
||||
|
||||
// segment that lies on the equator
|
||||
tester::apply("s16",
|
||||
@@ -2012,8 +2068,7 @@ BOOST_AUTO_TEST_CASE( envelope_spheroid_linestring )
|
||||
// linestring that circles the entire globe
|
||||
tester::apply("l03",
|
||||
from_wkt<G>("LINESTRING(-185 0,-170 25,-50 10,10 10,20 20,100 5,180 15)"),
|
||||
-180, 0, 180, 33.702476580413318,
|
||||
4.0 * std::numeric_limits<double>::epsilon());
|
||||
-180, 0, 180, rng(33.702476580412359, 33.702476580413318));
|
||||
|
||||
// linestring that crosses the antimeridian but staying close to it
|
||||
tester::apply("l04",
|
||||
@@ -2261,19 +2316,19 @@ BOOST_AUTO_TEST_CASE( envelope_spheroid_multilinestring )
|
||||
|
||||
tester::apply("ml04",
|
||||
from_wkt<G>("MULTILINESTRING((-150 40,-100 80),(10 35,100 80))"),
|
||||
-150, 35, 100, 80.082544902477267);
|
||||
-150, 35, 100, rng(80.07385383411011, 80.082544902477267));
|
||||
|
||||
tester::apply("ml04a",
|
||||
from_wkt<G>("MULTILINESTRING((-150 40,-100 80),(10 35,100 80),(170 25,-160 80))"),
|
||||
10, 25, 260, 80.082544902477267);
|
||||
10, 25, 260, rng(80.07385383411011, 80.082544902477267));
|
||||
|
||||
tester::apply("ml05",
|
||||
from_wkt<G>("MULTILINESTRING((-140 40,-100 80),(10 35,100 80))"),
|
||||
-140, 35, 100, 80.082544902477267);
|
||||
-140, 35, 100, rng(80.07385383411011, 80.082544902477267));
|
||||
|
||||
tester::apply("ml05a",
|
||||
from_wkt<G>("MULTILINESTRING((-140 40,-100 80),(10 35,100 80),(170 25,-160 80))"),
|
||||
10, 25, 260, 80.082544902477267);
|
||||
10, 25, 260, rng(80.07385383411011, 80.082544902477267));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -11,9 +11,11 @@
|
||||
#ifndef BOOST_GEOMETRY_TEST_ENVELOPE_EXPAND_ON_SPHEROID_HPP
|
||||
#define BOOST_GEOMETRY_TEST_ENVELOPE_EXPAND_ON_SPHEROID_HPP
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
@@ -29,6 +31,37 @@
|
||||
#include <boost/geometry/algorithms/assign.hpp>
|
||||
|
||||
|
||||
struct rng
|
||||
{
|
||||
typedef double type;
|
||||
|
||||
rng(double l, double h)
|
||||
: lo(l), hi(h)
|
||||
{
|
||||
BOOST_GEOMETRY_ASSERT(lo <= hi);
|
||||
}
|
||||
|
||||
friend rng operator*(rng const& l, double v) { return rng(l.lo * v, l.hi * v); }
|
||||
|
||||
friend bool operator<=(rng const& l, rng const& r) { return l.lo <= r.hi; }
|
||||
friend bool operator<=(double l, rng const& r) { return l <= r.hi; }
|
||||
friend bool operator<=(rng const& l, double r) { return l.lo <= r; }
|
||||
|
||||
friend bool operator<(rng const& l, rng const& r) { return !operator<=(r, l); }
|
||||
friend bool operator<(double l, rng const& r) { return !operator<=(r, l); }
|
||||
friend bool operator<(rng const& l, double r) { return !operator<=(r, l); }
|
||||
|
||||
friend bool operator==(double l, rng const& r) { return r.lo <= l && l <= r.hi; }
|
||||
|
||||
friend std::ostream & operator<<(std::ostream & os, rng const& v)
|
||||
{
|
||||
return (os << "[" << v.lo << ", " << v.hi << "]");
|
||||
}
|
||||
|
||||
double lo, hi;
|
||||
};
|
||||
|
||||
|
||||
template <typename Units>
|
||||
char const* units2string()
|
||||
{
|
||||
@@ -49,10 +82,14 @@ struct other_system_info<bg::cs::spherical_equatorial<bg::radian> >
|
||||
typedef bg::degree units;
|
||||
typedef bg::cs::spherical_equatorial<units> type;
|
||||
|
||||
template <typename T>
|
||||
static inline T convert(T const& value)
|
||||
static inline double convert(double value)
|
||||
{
|
||||
return value * bg::math::r2d<T>();
|
||||
return value * bg::math::r2d<double>();
|
||||
}
|
||||
|
||||
static inline rng convert(rng const& value)
|
||||
{
|
||||
return value * bg::math::r2d<double>();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -62,10 +99,14 @@ struct other_system_info<bg::cs::spherical_equatorial<bg::degree> >
|
||||
typedef bg::radian units;
|
||||
typedef bg::cs::spherical_equatorial<units> type;
|
||||
|
||||
template <typename T>
|
||||
static inline T convert(T const& value)
|
||||
static inline double convert(double value)
|
||||
{
|
||||
return value * bg::math::d2r<T>();
|
||||
return value * bg::math::d2r<double>();
|
||||
}
|
||||
|
||||
static inline rng convert(rng const& value)
|
||||
{
|
||||
return value * bg::math::d2r<double>();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -75,10 +116,14 @@ struct other_system_info<bg::cs::geographic<bg::radian> >
|
||||
typedef bg::degree units;
|
||||
typedef bg::cs::geographic<units> type;
|
||||
|
||||
template <typename T>
|
||||
static inline T convert(T const& value)
|
||||
static inline double convert(double value)
|
||||
{
|
||||
return value * bg::math::r2d<T>();
|
||||
return value * bg::math::r2d<double>();
|
||||
}
|
||||
|
||||
static inline rng convert(rng const& value)
|
||||
{
|
||||
return value * bg::math::r2d<double>();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -88,15 +133,18 @@ struct other_system_info<bg::cs::geographic<bg::degree> >
|
||||
typedef bg::radian units;
|
||||
typedef bg::cs::geographic<units> type;
|
||||
|
||||
template <typename T>
|
||||
static inline T convert(T const& value)
|
||||
static inline double convert(double value)
|
||||
{
|
||||
return value * bg::math::d2r<T>();
|
||||
return value * bg::math::d2r<double>();
|
||||
}
|
||||
|
||||
static inline rng convert(rng const& value)
|
||||
{
|
||||
return value * bg::math::d2r<double>();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
class equals_with_tolerance
|
||||
{
|
||||
private:
|
||||
@@ -118,11 +166,99 @@ private:
|
||||
public:
|
||||
equals_with_tolerance(double tolerence) : m_tolerence(tolerence) {}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator()(T const& value1, T const& value2) const
|
||||
inline bool operator()(double value1, double value2) const
|
||||
{
|
||||
return check_close(value1, value2, m_tolerence);
|
||||
}
|
||||
|
||||
inline bool operator()(double l, rng const& r) const
|
||||
{
|
||||
return (r.lo < l && l < r.hi)
|
||||
|| check_close(l, r.lo, m_tolerence)
|
||||
|| check_close(l, r.hi, m_tolerence);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
bool equals_with_eps(double l, double r)
|
||||
{
|
||||
return bg::math::equals(l, r);
|
||||
}
|
||||
|
||||
bool equals_with_eps(double l, rng r)
|
||||
{
|
||||
return (r.lo < l && l < r.hi)
|
||||
|| bg::math::equals(l, r.lo)
|
||||
|| bg::math::equals(l, r.hi);
|
||||
}
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Box,
|
||||
std::size_t DimensionCount = bg::dimension<Box>::value
|
||||
>
|
||||
struct box_check_equals
|
||||
{
|
||||
template <typename T1, typename T2, typename T3, typename T4>
|
||||
static inline bool apply(Box const& box,
|
||||
T1 const& lon_min, T2 const& lat_min, double,
|
||||
T3 const& lon_max, T4 const& lat_max, double,
|
||||
double tol)
|
||||
{
|
||||
equals_with_tolerance equals(tol);
|
||||
|
||||
#ifndef BOOST_GEOMETRY_TEST_ENABLE_FAILING
|
||||
// check latitude with tolerance when necessary
|
||||
return equals_with_eps(bg::get<0, 0>(box), lon_min)
|
||||
&& (bg::get<0, 1>(box) < 0
|
||||
? equals(bg::get<0, 1>(box), lat_min)
|
||||
: equals_with_eps(bg::get<0, 1>(box), lat_min))
|
||||
&& equals_with_eps(bg::get<1, 0>(box), lon_max)
|
||||
&& (bg::get<1, 1>(box) > 0
|
||||
? equals(bg::get<1, 1>(box), lat_max)
|
||||
: equals_with_eps(bg::get<1, 1>(box), lat_max));
|
||||
#else
|
||||
// check latitude with tolerance when necessary
|
||||
return bg::get<0, 0>(box) == lon_min
|
||||
&& (bg::get<0, 1>(box) < 0
|
||||
? equals(bg::get<0, 1>(box), lat_min)
|
||||
: bg::get<0, 1>(box) == lat_min)
|
||||
&& bg::get<1, 0>(box) == lon_max
|
||||
&& (bg::get<1, 1>(box) > 0
|
||||
? equals(bg::get<1, 1>(box), lat_max)
|
||||
: bg::get<1, 1>(box) == lat_max);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Box>
|
||||
struct box_check_equals<Box, 3>
|
||||
{
|
||||
template <typename T1, typename T2, typename T3, typename T4>
|
||||
static inline bool apply(Box const& box,
|
||||
T1 const& lon_min, T2 const& lat_min, double height_min,
|
||||
T3 const& lon_max, T4 const& lat_max, double height_max,
|
||||
double tol)
|
||||
{
|
||||
#ifndef BOOST_GEOMETRY_TEST_ENABLE_FAILING
|
||||
equals_with_tolerance equals(tol);
|
||||
|
||||
return box_check_equals<Box, 2>::apply(box,
|
||||
lon_min, lat_min, height_min,
|
||||
lon_max, lat_max, height_max,
|
||||
tol)
|
||||
&& equals(bg::get<0, 2>(box), height_min)
|
||||
&& equals(bg::get<1, 2>(box), height_max);
|
||||
#else
|
||||
return box_equals<Box, 2>::apply(box,
|
||||
lon_min, lat_min, height_min,
|
||||
lon_max, lat_max, height_max,
|
||||
tol)
|
||||
&& bg::get<0, 2>(box) == height_min
|
||||
&& bg::get<1, 2>(box) == height_max;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -136,48 +272,22 @@ struct box_equals
|
||||
{
|
||||
static inline bool apply(Box1 const& box1, Box2 const& box2, double tol)
|
||||
{
|
||||
equals_with_tolerance equals(tol);
|
||||
|
||||
#ifndef BOOST_GEOMETRY_TEST_ENABLE_FAILING
|
||||
// check latitude with tolerance when necessary
|
||||
return bg::math::equals(bg::get<0, 0>(box1), bg::get<0, 0>(box2))
|
||||
&& (bg::get<0, 1>(box1) < 0
|
||||
? equals(bg::get<0, 1>(box1), bg::get<0, 1>(box2))
|
||||
: bg::math::equals(bg::get<0, 1>(box1), bg::get<0, 1>(box2)))
|
||||
&& bg::math::equals(bg::get<1, 0>(box1), bg::get<1, 0>(box2))
|
||||
&& (bg::get<1, 1>(box1) > 0
|
||||
? equals(bg::get<1, 1>(box1), bg::get<1, 1>(box2))
|
||||
: bg::math::equals(bg::get<1, 1>(box1), bg::get<1, 1>(box2)));
|
||||
#else
|
||||
// check latitude with tolerance when necessary
|
||||
return bg::get<0, 0>(box1) == bg::get<0, 0>(box2)
|
||||
&& (bg::get<0, 1>(box1) < 0
|
||||
? equals(bg::get<0, 1>(box1), bg::get<0, 1>(box2))
|
||||
: bg::get<0, 1>(box1) == bg::get<0, 1>(box2))
|
||||
&& bg::get<1, 0>(box1) == bg::get<1, 0>(box2)
|
||||
&& (bg::get<1, 1>(box1) > 0
|
||||
? equals(bg::get<1, 1>(box1), bg::get<1, 1>(box2))
|
||||
: bg::get<1, 1>(box1) == bg::get<1, 1>(box2));
|
||||
#endif
|
||||
return box_check_equals<Box1>::apply(box1,
|
||||
bg::get<0, 0>(box2), bg::get<0, 1>(box2), 0.0,
|
||||
bg::get<1, 0>(box2), bg::get<1, 1>(box2), 0.0,
|
||||
tol);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Box1, typename Box2>
|
||||
template<typename Box1, typename Box2>
|
||||
struct box_equals<Box1, Box2, 3>
|
||||
{
|
||||
static inline bool apply(Box1 const& box1, Box2 const& box2, double tol)
|
||||
{
|
||||
#ifndef BOOST_GEOMETRY_TEST_ENABLE_FAILING
|
||||
equals_with_tolerance equals(tol);
|
||||
|
||||
return box_equals<Box1, Box2, 2>::apply(box1, box2, tol)
|
||||
&& equals(bg::get<0, 2>(box1), bg::get<0, 2>(box2))
|
||||
&& equals(bg::get<1, 2>(box1), bg::get<1, 2>(box2));
|
||||
#else
|
||||
return box_equals<Box1, Box2, 2>::apply(box1, box2, tol)
|
||||
&& bg::get<0, 2>(box1) == bg::get<0, 2>(box2)
|
||||
&& bg::get<1, 2>(box1) == bg::get<1, 2>(box2);
|
||||
#endif
|
||||
return box_check_equals<Box1>::apply(box1,
|
||||
bg::get<0, 0>(box2), bg::get<0, 1>(box2), bg::get<0, 2>(box2),
|
||||
bg::get<1, 0>(box2), bg::get<1, 1>(box2), bg::get<1, 2>(box2),
|
||||
tol);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
// Unit Test
|
||||
|
||||
// Copyright (c) 2014-2015, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2014-2017, 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
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
@@ -63,7 +64,7 @@ typedef bg::model::box<point_type> box_type;
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
template <typename Geometry>
|
||||
template <typename CSTag, typename Geometry>
|
||||
void test_simple(Geometry const& geometry, bool expected_result,
|
||||
bool check_validity = true)
|
||||
{
|
||||
@@ -72,12 +73,22 @@ void test_simple(Geometry const& geometry, bool expected_result,
|
||||
#endif
|
||||
|
||||
bool simple = bg::is_simple(geometry);
|
||||
|
||||
BOOST_ASSERT( ! check_validity || bg::is_valid(geometry) );
|
||||
BOOST_CHECK_MESSAGE( simple == expected_result,
|
||||
"Expected: " << expected_result
|
||||
<< " detected: " << simple
|
||||
<< " wkt: " << bg::wkt(geometry) );
|
||||
|
||||
typedef typename bg::strategy::intersection::services::default_strategy
|
||||
<
|
||||
CSTag
|
||||
>::type strategy_type;
|
||||
|
||||
bool simple_s = bg::is_simple(geometry, strategy_type());
|
||||
|
||||
BOOST_CHECK_EQUAL(simple, simple_s);
|
||||
|
||||
#ifdef BOOST_GEOMETRY_TEST_DEBUG
|
||||
std::cout << "Geometry: ";
|
||||
pretty_print_geometry<Geometry>::apply(std::cout, geometry);
|
||||
@@ -92,6 +103,26 @@ void test_simple(Geometry const& geometry, bool expected_result,
|
||||
}
|
||||
|
||||
|
||||
template <typename Geometry>
|
||||
void test_simple(Geometry const& geometry,
|
||||
bool expected_result,
|
||||
bool check_validity = true)
|
||||
{
|
||||
typedef typename bg::cs_tag<Geometry>::type cs_tag;
|
||||
test_simple<cs_tag>(geometry, expected_result, check_validity);
|
||||
}
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
void test_simple(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& variant_geometry,
|
||||
bool expected_result,
|
||||
bool check_validity = true)
|
||||
{
|
||||
typedef typename bg::cs_tag<T0>::type cs_tag;
|
||||
test_simple<cs_tag>(variant_geometry, expected_result, check_validity);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ template <typename P>
|
||||
void test_vincenty()
|
||||
{
|
||||
typename geo_strategies<P>::vincenty_type vincenty;
|
||||
test_with_strategy<P>(1116828.8624 + 1116161.625, vincenty);
|
||||
test_with_strategy<P>(1116825.857 + 1116159.144, vincenty);
|
||||
}
|
||||
|
||||
template <typename P>
|
||||
|
||||
@@ -83,7 +83,7 @@ template <typename P>
|
||||
void test_vincenty()
|
||||
{
|
||||
typename geo_strategies<P>::vincenty_type vincenty;
|
||||
test_with_strategy<P>(1116828.8624 + 1116161.625, vincenty);
|
||||
test_with_strategy<P>(1116825.857 + 1116159.144, vincenty);
|
||||
}
|
||||
|
||||
template <typename P>
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2016.
|
||||
// Modifications copyright (c) 2016, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2016, 2017.
|
||||
// Modifications copyright (c) 2016-2017, 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,
|
||||
@@ -131,20 +131,28 @@ std::string test_difference(std::string const& caseid, G1 const& g1, G2 const& g
|
||||
typedef typename bg::coordinate_type<G1>::type coordinate_type;
|
||||
boost::ignore_unused<coordinate_type>();
|
||||
|
||||
bg::model::multi_polygon<OutputType> result;
|
||||
bg::model::multi_polygon<OutputType> result, result_s;
|
||||
|
||||
typedef typename bg::strategy::relate::services::default_strategy
|
||||
<
|
||||
G1, G2
|
||||
>::type strategy_type;
|
||||
|
||||
if (sym)
|
||||
{
|
||||
bg::sym_difference(g1, g2, result);
|
||||
bg::sym_difference(g1, g2, result_s, strategy_type());
|
||||
}
|
||||
else
|
||||
{
|
||||
bg::difference(g1, g2, result);
|
||||
bg::difference(g1, g2, result_s, strategy_type());
|
||||
}
|
||||
|
||||
if (settings.remove_spikes)
|
||||
{
|
||||
bg::remove_spikes(result);
|
||||
bg::remove_spikes(result_s);
|
||||
}
|
||||
|
||||
std::ostringstream return_string;
|
||||
@@ -233,6 +241,8 @@ std::string test_difference(std::string const& caseid, G1 const& g1, G2 const& g
|
||||
}
|
||||
|
||||
BOOST_CHECK_CLOSE(area, expected_area, settings.percentage);
|
||||
|
||||
BOOST_CHECK_EQUAL(bg::num_points(result), bg::num_points(result_s));
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014-2015, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2014-2017, 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
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
#ifndef BOOST_GEOMETRY_TEST_DIFFERENCE_LINEAR_LINEAR_HPP
|
||||
#define BOOST_GEOMETRY_TEST_DIFFERENCE_LINEAR_LINEAR_HPP
|
||||
@@ -25,6 +26,23 @@
|
||||
//==================================================================
|
||||
//==================================================================
|
||||
|
||||
template <typename Geometry1, typename Geometry2, typename MultiLineString>
|
||||
inline void check_result(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
MultiLineString const& mls_output,
|
||||
MultiLineString const& mls_diff,
|
||||
std::string const& case_id,
|
||||
double tolerance)
|
||||
{
|
||||
BOOST_CHECK_MESSAGE( equals::apply(mls_diff, mls_output, tolerance),
|
||||
"case id: " << case_id
|
||||
<< ", difference L/L: " << bg::wkt(geometry1)
|
||||
<< " " << bg::wkt(geometry2)
|
||||
<< " -> Expected: " << bg::wkt(mls_diff)
|
||||
<< std::setprecision(20)
|
||||
<< " computed: " << bg::wkt(mls_output) );
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry1, typename Geometry2,
|
||||
@@ -52,6 +70,22 @@ private:
|
||||
linestring_vector ls_vector_output;
|
||||
linestring_deque ls_deque_output;
|
||||
|
||||
// Check strategy passed explicitly
|
||||
typedef typename bg::strategy::relate::services::default_strategy
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::type strategy_type;
|
||||
bg::difference(geometry1, geometry2, mls_output, strategy_type());
|
||||
|
||||
if (reverse_output_for_checking)
|
||||
{
|
||||
bg::reverse(mls_output);
|
||||
}
|
||||
|
||||
check_result(geometry1, geometry2, mls_output, mls_diff, case_id, tolerance);
|
||||
|
||||
// Check normal behaviour
|
||||
bg::clear(mls_output);
|
||||
bg::difference(geometry1, geometry2, mls_output);
|
||||
|
||||
if ( reverse_output_for_checking )
|
||||
@@ -59,14 +93,8 @@ private:
|
||||
bg::reverse(mls_output);
|
||||
}
|
||||
|
||||
BOOST_CHECK_MESSAGE( equals::apply(mls_diff, mls_output, tolerance),
|
||||
"case id: " << case_id
|
||||
<< ", difference L/L: " << bg::wkt(geometry1)
|
||||
<< " " << bg::wkt(geometry2)
|
||||
<< " -> Expected: " << bg::wkt(mls_diff)
|
||||
<< std::setprecision(20)
|
||||
<< " computed: " << bg::wkt(mls_output) );
|
||||
|
||||
check_result(geometry1, geometry2, mls_output, mls_diff, case_id, tolerance);
|
||||
|
||||
set_operation_output("difference", case_id,
|
||||
geometry1, geometry2, mls_output);
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2016.
|
||||
// Modifications copyright (c) 2016, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2016, 2017.
|
||||
// Modifications copyright (c) 2016-2017, 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,
|
||||
@@ -189,6 +189,18 @@ typename bg::default_area_result<G1>::type test_intersection(std::string const&
|
||||
result_type intersection_output;
|
||||
bg::intersection(g1, g2, intersection_output);
|
||||
|
||||
check_result<G1, G2>(intersection_output, caseid, expected_count,
|
||||
expected_holes_count, expected_point_count, expected_length_or_area,
|
||||
settings);
|
||||
|
||||
// Check strategy passed explicitly
|
||||
typedef typename bg::strategy::relate::services::default_strategy
|
||||
<
|
||||
G1, G2
|
||||
>::type strategy_type;
|
||||
intersection_output.clear();
|
||||
bg::intersection(g1, g2, intersection_output, strategy_type());
|
||||
|
||||
check_result<G1, G2>(intersection_output, caseid, expected_count,
|
||||
expected_holes_count, expected_point_count, expected_length_or_area,
|
||||
settings);
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014-2015, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2014-2017, 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
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
#ifndef BOOST_GEOMETRY_TEST_INTERSECTION_LINEAR_LINEAR_HPP
|
||||
#define BOOST_GEOMETRY_TEST_INTERSECTION_LINEAR_LINEAR_HPP
|
||||
@@ -26,6 +27,25 @@
|
||||
//==================================================================
|
||||
//==================================================================
|
||||
|
||||
template <typename Geometry1, typename Geometry2, typename MultiLineString>
|
||||
inline void check_result(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
MultiLineString const& mls_output,
|
||||
MultiLineString const& mls_int1,
|
||||
MultiLineString const& mls_int2,
|
||||
std::string const& case_id,
|
||||
double tolerance)
|
||||
{
|
||||
BOOST_CHECK_MESSAGE( equals::apply(mls_int1, mls_output, tolerance)
|
||||
|| equals::apply(mls_int2, mls_output, tolerance),
|
||||
"case id: " << case_id
|
||||
<< ", intersection L/L: " << bg::wkt(geometry1)
|
||||
<< " " << bg::wkt(geometry2)
|
||||
<< " -> Expected: " << bg::wkt(mls_int1)
|
||||
<< " or: " << bg::wkt(mls_int2)
|
||||
<< " computed: " << bg::wkt(mls_output) );
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry1, typename Geometry2,
|
||||
@@ -53,16 +73,20 @@ private:
|
||||
linestring_vector ls_vector_output;
|
||||
linestring_deque ls_deque_output;
|
||||
|
||||
// Check normal behaviour
|
||||
bg::intersection(geometry1, geometry2, mls_output);
|
||||
|
||||
BOOST_CHECK_MESSAGE( equals::apply(mls_int1, mls_output, tolerance)
|
||||
|| equals::apply(mls_int2, mls_output, tolerance),
|
||||
"case id: " << case_id
|
||||
<< ", intersection L/L: " << bg::wkt(geometry1)
|
||||
<< " " << bg::wkt(geometry2)
|
||||
<< " -> Expected: " << bg::wkt(mls_int1)
|
||||
<< " or: " << bg::wkt(mls_int2)
|
||||
<< " computed: " << bg::wkt(mls_output) );
|
||||
check_result(geometry1, geometry2, mls_output, mls_int1, mls_int2, case_id, tolerance);
|
||||
|
||||
// Check strategy passed explicitly
|
||||
typedef typename bg::strategy::relate::services::default_strategy
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::type strategy_type;
|
||||
bg::clear(mls_output);
|
||||
bg::intersection(geometry1, geometry2, mls_output, strategy_type());
|
||||
|
||||
check_result(geometry1, geometry2, mls_output, mls_int1, mls_int2, case_id, tolerance);
|
||||
|
||||
set_operation_output("intersection", case_id,
|
||||
geometry1, geometry2, mls_output);
|
||||
@@ -109,14 +133,7 @@ private:
|
||||
bg::clear(mls_output);
|
||||
bg::intersection(geometry2, geometry1, mls_output);
|
||||
|
||||
BOOST_CHECK_MESSAGE( equals::apply(mls_int1, mls_output, tolerance)
|
||||
|| equals::apply(mls_int2, mls_output, tolerance),
|
||||
"case id: " << case_id
|
||||
<< ", intersection L/L: " << bg::wkt(geometry1)
|
||||
<< " " << bg::wkt(geometry2)
|
||||
<< " -> Expected: " << bg::wkt(mls_int1)
|
||||
<< " or: " << bg::wkt(mls_int2)
|
||||
<< " computed: " << bg::wkt(mls_output) );
|
||||
check_result(geometry1, geometry2, mls_output, mls_int1, mls_int2, case_id, tolerance);
|
||||
|
||||
#ifdef BOOST_GEOMETRY_TEST_DEBUG
|
||||
std::cout << "Geometry #1: " << bg::wkt(geometry2) << std::endl;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user