Skip to content

Commit

Permalink
Merge pull request boostorg#650 from awulkiew/feature/setops_output
Browse files Browse the repository at this point in the history
Missing input combinations in intersection() and introduction of tupled-output.
  • Loading branch information
awulkiew authored Mar 26, 2020
2 parents 99901e3 + 2b74e42 commit 2015302
Show file tree
Hide file tree
Showing 33 changed files with 3,501 additions and 739 deletions.
348 changes: 348 additions & 0 deletions include/boost/geometry/algorithms/detail/intersection/areal_areal.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,348 @@
// Boost.Geometry

// Copyright (c) 2020, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle

// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html

#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_AREAL_AREAL_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_AREAL_AREAL_HPP


#include <boost/core/ignore_unused.hpp>

#include <boost/geometry/algorithms/detail/intersection/interface.hpp>


namespace boost { namespace geometry
{

#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace intersection
{


template
<
typename GeometryOut,
typename OutTag = typename detail::intersection::tag
<
typename geometry::detail::output_geometry_value
<
GeometryOut
>::type
>::type
>
struct intersection_areal_areal_
{
template
<
typename Areal1,
typename Areal2,
typename RobustPolicy,
typename Strategy
>
static inline void apply(Areal1 const& areal1,
Areal2 const& areal2,
RobustPolicy const& robust_policy,
GeometryOut& geometry_out,
Strategy const& strategy)
{
geometry::dispatch::intersection_insert
<
Areal1, Areal2,
typename boost::range_value<GeometryOut>::type,
overlay_intersection
>::apply(areal1, areal2, robust_policy,
geometry::range::back_inserter(geometry_out),
strategy);
}
};

// TODO: Ideally this should be done in one call of intersection_insert
// just like it's done for all other combinations
template <typename TupledOut>
struct intersection_areal_areal_<TupledOut, tupled_output_tag>
{
template
<
typename Areal1,
typename Areal2,
typename RobustPolicy,
typename Strategy
>
static inline void apply(Areal1 const& areal1,
Areal2 const& areal2,
RobustPolicy const& robust_policy,
TupledOut& geometry_out,
Strategy const& strategy)
{
typedef typename geometry::detail::output_geometry_value
<
TupledOut
>::type single_out;

boost::ignore_unused
<
detail::intersection::expect_output_pla
<
Areal1, Areal2, single_out
>
>();

typedef geometry::detail::output_geometry_access
<
single_out, polygon_tag, polygon_tag
> areal;
typedef geometry::detail::output_geometry_access
<
single_out, linestring_tag, linestring_tag
> linear;
typedef geometry::detail::output_geometry_access
<
single_out, point_tag, point_tag
> pointlike;

typedef typename geometry::tuples::element
<
areal::index, TupledOut
>::type areal_out_type;
typedef typename geometry::tuples::element
<
pointlike::index, TupledOut
>::type pointlike_out_type;

// NOTE: The same robust_policy is used in each call of
// intersection_insert. Is that correct?

// A * A -> A
call_intersection(areal1, areal2, robust_policy,
areal::get(geometry_out),
strategy);

bool const is_areal_empty = boost::empty(areal::get(geometry_out));
TupledOut temp_out;

// L * L -> (L, P)
call_intersection(geometry::detail::boundary_view<Areal1 const>(areal1),
geometry::detail::boundary_view<Areal2 const>(areal2),
robust_policy,
! is_areal_empty
? temp_out
: geometry_out,
strategy);

if (! is_areal_empty)
{
// NOTE: the original areal geometry could be used instead of boundary here
// however this results in static assert failure related to rescale policy
typedef geometry::detail::boundary_view
<
areal_out_type const
> areal_out_boundary_type;

areal_out_boundary_type areal_out_boundary(areal::get(geometry_out));

// L - L -> L
call_difference(linear::get(temp_out),
areal_out_boundary,
robust_policy,
linear::get(geometry_out),
strategy);

// P - L -> P
call_difference(pointlike::get(temp_out),
areal_out_boundary,
robust_policy,
pointlike::get(geometry_out),
strategy.template get_point_in_geometry_strategy
<
pointlike_out_type,
areal_out_boundary_type
>());
}

return;
}

private:
template
<
typename Geometry1,
typename Geometry2,
typename RobustPolicy,
typename GeometryOut,
typename Strategy
>
static inline void call_intersection(Geometry1 const& geometry1,
Geometry2 const& geometry2,
RobustPolicy const& robust_policy,
GeometryOut& geometry_out,
Strategy const& strategy)
{
geometry::dispatch::intersection_insert
<
Geometry1,
Geometry2,
typename geometry::detail::output_geometry_value
<
GeometryOut
>::type,
overlay_intersection
>::apply(geometry1,
geometry2,
robust_policy,
geometry::detail::output_geometry_back_inserter(geometry_out),
strategy);
}

template
<
typename Geometry1,
typename Geometry2,
typename RobustPolicy,
typename GeometryOut,
typename Strategy
>
static inline void call_difference(Geometry1 const& geometry1,
Geometry2 const& geometry2,
RobustPolicy const& robust_policy,
GeometryOut& geometry_out,
Strategy const& strategy)
{
geometry::dispatch::intersection_insert
<
Geometry1,
Geometry2,
typename boost::range_value<GeometryOut>::type,
overlay_difference
>::apply(geometry1,
geometry2,
robust_policy,
geometry::range::back_inserter(geometry_out),
strategy);
}
};


struct intersection_areal_areal
{
template
<
typename Areal1,
typename Areal2,
typename RobustPolicy,
typename GeometryOut,
typename Strategy
>
static inline bool apply(Areal1 const& areal1,
Areal2 const& areal2,
RobustPolicy const& robust_policy,
GeometryOut& geometry_out,
Strategy const& strategy)
{
intersection_areal_areal_
<
GeometryOut
>::apply(areal1, areal2, robust_policy, geometry_out, strategy);

return true;
}
};


}} // namespace detail::intersection
#endif // DOXYGEN_NO_DETAIL


#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{


template
<
typename Polygon1, typename Polygon2
>
struct intersection
<
Polygon1, Polygon2,
polygon_tag, polygon_tag,
false
>
: detail::intersection::intersection_areal_areal
{};

template
<
typename Polygon, typename Ring
>
struct intersection
<
Polygon, Ring,
polygon_tag, ring_tag,
false
>
: detail::intersection::intersection_areal_areal
{};

template
<
typename Ring1, typename Ring2
>
struct intersection
<
Ring1, Ring2,
ring_tag, ring_tag,
false
>
: detail::intersection::intersection_areal_areal
{};

template
<
typename Polygon, typename MultiPolygon
>
struct intersection
<
Polygon, MultiPolygon,
polygon_tag, multi_polygon_tag,
false
>
: detail::intersection::intersection_areal_areal
{};

template
<
typename MultiPolygon, typename Ring
>
struct intersection
<
MultiPolygon, Ring,
multi_polygon_tag, ring_tag,
false
>
: detail::intersection::intersection_areal_areal
{};

template
<
typename MultiPolygon1, typename MultiPolygon2
>
struct intersection
<
MultiPolygon1, MultiPolygon2,
multi_polygon_tag, multi_polygon_tag,
false
>
: detail::intersection::intersection_areal_areal
{};


} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH

}} // namespace boost::geometry

#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_AREAL_AREAL_HPP
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_IMPLEMENTATION_HPP


#include <boost/geometry/algorithms/detail/intersection/areal_areal.hpp>
#include <boost/geometry/algorithms/detail/intersection/box_box.hpp>
#include <boost/geometry/algorithms/detail/intersection/multi.hpp>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <boost/variant/variant_fwd.hpp>

#include <boost/geometry/algorithms/detail/overlay/intersection_insert.hpp>
#include <boost/geometry/algorithms/detail/tupled_output.hpp>
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/util/range.hpp>
Expand Down Expand Up @@ -50,14 +51,18 @@ struct intersection
GeometryOut& geometry_out,
Strategy const& strategy)
{
typedef typename boost::range_value<GeometryOut>::type OneOut;
typedef typename geometry::detail::output_geometry_value
<
GeometryOut
>::type SingleOut;

intersection_insert
<
Geometry1, Geometry2, OneOut,
Geometry1, Geometry2, SingleOut,
overlay_intersection
>::apply(geometry1, geometry2, robust_policy,
range::back_inserter(geometry_out), strategy);
geometry::detail::output_geometry_back_inserter(geometry_out),
strategy);

return true;
}
Expand Down
Loading

0 comments on commit 2015302

Please sign in to comment.