Boost logo

Geometry :

Subject: [geometry] backward compatibility breakage in boost::geometry::partition apply function
From: vish (vrang4_at_[hidden])
Date: 2017-05-10 23:39:31


A change in boost 1_64_0 has broken backward compatibility of the apply()
function in boost::geometry::partition. I have used this apply() function in
multiple versions of boost geometry for 6 years up through version 1_62_0.
The sample code is provided below. It's a minor modification of a sample
Barend gave in a post on labeling intersections in polygons. The codepad
links in that post don't work anymore.

Items pasted below are in the following order:
1. Sample code (test.cpp).
2. Compiler command (using VS 2015).
3. Errors with boost_1_64_0.
4. Warnings when compiled with boost_1_62_0 (no errors result).

1. Sample code (test.cpp).

// Boost.Geometry (aka GGL, Generic Geometry Library)
//
// Copyright (c) 2011 Barend Gehrels, Amsterdam, the Netherlands.
// 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)

#include <fstream>
#include <boost/geometry.hpp>
#include <boost/foreach.hpp>
#include <boost/geometry/io/wkt/read.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <iostream>

typedef boost::geometry::model::d2::point_xy<double> Point2D;

class polygon_with_id : public boost::geometry::model::polygon<Point2D>
{
    public :
        int id;

        polygon_with_id(std::string const& wkt, int the_id = 0)
            : id(the_id)
        {
            boost::geometry::read_wkt(wkt, *this);
        }

        polygon_with_id()
            : id(0)
        {}

};

namespace boost { namespace geometry { namespace traits {

typedef ring_type<model::polygon&lt;model::d2::point_xy&lt;double> > >::type
ring_of_polygon_with_id;

template<> struct tag<polygon_with_id> { typedef polygon_tag type; };
template<> struct ring_const_type<polygon_with_id> { typedef
ring_of_polygon_with_id const& type; };
template<> struct ring_mutable_type<polygon_with_id> { typedef
ring_of_polygon_with_id& type; };

template<> struct interior_const_type<polygon_with_id>
{
    typedef std::vector<ring_of_polygon_with_id> const& type;
};

template<> struct interior_mutable_type<polygon_with_id>
{
    typedef std::vector<ring_of_polygon_with_id>& type;
};

template<> struct exterior_ring<polygon_with_id>
{
    static ring_of_polygon_with_id& get(polygon_with_id& p)
    {
        return p.outer();
    }

    static ring_of_polygon_with_id const& get(polygon_with_id const& p)
    {
        return p.outer();
    }
};

template<> struct interior_rings<polygon_with_id>
{
    typedef std::vector<ring_of_polygon_with_id> holes_type;

    static holes_type& get(polygon_with_id& p)
    {
        return p.inners();
    }

    static holes_type const& get(polygon_with_id const& p)
    {
        return p.inners();
    }
};

}}}

struct do_expand
{
    template <typename Box, typename Geometry>
    static inline void apply(Box& total, Geometry const& geometry)
    {
        boost::geometry::expand(total,
boost::geometry::return_envelope<Box>(geometry));
    }
};

struct has_overlap
{
    template <typename Box, typename Geometry>
    static inline bool apply(Box const& box, Geometry const& geometry)
    {
        // We're return true if the BOXES are not disjoint (box and polygon
might be)
        // (this results just in a few more intersection trials in the
visitor, but
        // there is no performance penalty: hardly any difference if we
intersect them
        // here or or there).
        return ! boost::geometry::disjoint(box,
boost::geometry::return_envelope<Box>(geometry));
    }
};

struct intersection_visitor
{

    intersection_visitor()
    {}

    template <typename Item>
    inline void apply(Item const& owner, Item const& mr)
    {
        boost::geometry::intersection(owner, mr, output);
    }
    
    // A member to save the intersection results
    boost::geometry::model::multi_polygon<polygon_with_id> output;
};

int main()
{

    std::vector<polygon_with_id> owners;
    std::vector<polygon_with_id> mineral_rights;

    owners.push_back(polygon_with_id("POLYGON((0 0.5,0 1,0.5 1,0.5 0.5,0
0.5))"));
    owners.push_back(polygon_with_id("POLYGON((0.5 0.5,0.5 1,1 1,1 0.5,0.5
0.5))"));
    owners.push_back(polygon_with_id("POLYGON((0 0,0 0.5,0.5 0.5,0.5 0,0
0))"));
    owners.push_back(polygon_with_id("POLYGON((0.5 0,0.5 0.5,1 0.5,1 0,0.5
0))"));

    mineral_rights.push_back(polygon_with_id("POLYGON((0.25 0.75,0.25
1.25,0.75 1.25,0.75 0.75,0.25 0.75))"));
    mineral_rights.push_back(polygon_with_id("POLYGON((0.75 0.75,0.75
1.25,1.25 1.25,1.25 0.75,0.75 0.75))"));
    mineral_rights.push_back(polygon_with_id("POLYGON((0.25 0.25,0.25
0.75,0.75 0.75,0.75 0.25,0.25 0.25))"));
    mineral_rights.push_back(polygon_with_id("POLYGON((0.75 0.25,0.75
0.75,1.25 0.75,1.25 0.25,0.75 0.25))"));
    
    std::cout << "n-log-n solution" << std::endl;

    intersection_visitor visitor;

    boost::geometry::partition
        <
            boost::geometry::model::box<Point2D>, do_expand, has_overlap
>::apply(owners, mineral_rights, visitor, 1);

    return 0;
}

2. Compiler command (using VS 2015).

cl -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE
-D_SCL_SECURE_NO_DEPRECATE -D_USE_MATH_DEFINES -DNOMINMAX
-DWIN32_LEAN_AND_MEAN -Dstrcasecmp=_stricmp -Dstrncasecmp=_strnicmp -we4311
-we4473 -we4474 -we4477 -MDd -Zi -Od -nologo -W4 -wd4100 -wd4127 -wd4345
-wd4351 -wd4510 -wd4512 -wd4610 -wd4706 -wd4714 -wd6326 -wd6993 -EHsc
-Id:\boost_1_64_0 -DBOOST_ALL_NO_LIB /c test.cpp

3. Errors with boost_1_64_0.

test.cpp
d:\boost_1_64_0\boost/geometry/algorithms/detail/partition.hpp(649): error
C2039: 'apply': is not a member of
'std::vector<Polygon,std::allocator&lt;Polygon>>'
        with
        [
            Polygon=polygon_with_id
        ]
d:\boost_1_64_0\boost/geometry/geometries/multi_polygon.hpp(55): note: see
declaration of 'std::vector<Polygon,std::allocator&lt;Polygon>>'
        with
        [
            Polygon=polygon_with_id
        ]
d:\boost_1_64_0\boost/geometry/algorithms/detail/partition.hpp(586): note:
see reference to function template instantiation 'void
boost::geometry::partition<boost::geometry::model::box&lt;Point2D>,do_expand,has_overlap>::apply<ForwardRange,VisitPolicy,ExpandPolicy,OverlapsPolicy,boost::geometry::detail::partition::visit_no_policy>(const
ForwardRange &,VisitPolicy &,const ExpandPolicy &,const OverlapsPolicy
&,std::size_t,VisitBoxPolicy)' being compiled
        with
        [
           
ForwardRange=std::vector<polygon_with_id,std::allocator&lt;polygon_with_id>>,
           
VisitPolicy=std::vector<polygon_with_id,std::allocator&lt;polygon_with_id>>,
            ExpandPolicy=intersection_visitor,
            OverlapsPolicy=int,
           
VisitBoxPolicy=boost::geometry::detail::partition::visit_no_policy
        ]
d:\boost_1_64_0\boost/geometry/algorithms/detail/partition.hpp(585): note:
see reference to function template instantiation 'void
boost::geometry::partition<boost::geometry::model::box&lt;Point2D>,do_expand,has_overlap>::apply<ForwardRange,VisitPolicy,ExpandPolicy,OverlapsPolicy,boost::geometry::detail::partition::visit_no_policy>(const
ForwardRange &,VisitPolicy &,const ExpandPolicy &,const OverlapsPolicy
&,std::size_t,VisitBoxPolicy)' being compiled
        with
        [
           
ForwardRange=std::vector<polygon_with_id,std::allocator&lt;polygon_with_id>>,
           
VisitPolicy=std::vector<polygon_with_id,std::allocator&lt;polygon_with_id>>,
            ExpandPolicy=intersection_visitor,
            OverlapsPolicy=int,
           
VisitBoxPolicy=boost::geometry::detail::partition::visit_no_policy
        ]
test.cpp(148): note: see reference to function template instantiation 'void
boost::geometry::partition<boost::geometry::model::box&lt;Point2D>,do_expand,has_overlap>::apply<std::vector&lt;Polygon,std::allocator&lt;Polygon>>,std::vector<Polygon,std::allocator&lt;Polygon>>,intersection_visitor,int>(const
ForwardRange &,VisitPolicy &,const ExpandPolicy &,const OverlapsPolicy &)'
being compiled
        with
        [
            Polygon=polygon_with_id,
           
ForwardRange=std::vector<polygon_with_id,std::allocator&lt;polygon_with_id>>,
           
VisitPolicy=std::vector<polygon_with_id,std::allocator&lt;polygon_with_id>>,
            ExpandPolicy=intersection_visitor,
            OverlapsPolicy=int
        ]
test.cpp(148): note: see reference to function template instantiation 'void
boost::geometry::partition<boost::geometry::model::box&lt;Point2D>,do_expand,has_overlap>::apply<std::vector&lt;Polygon,std::allocator&lt;Polygon>>,std::vector<Polygon,std::allocator&lt;Polygon>>,intersection_visitor,int>(const
ForwardRange &,VisitPolicy &,const ExpandPolicy &,const OverlapsPolicy &)'
being compiled
        with
        [
            Polygon=polygon_with_id,
           
ForwardRange=std::vector<polygon_with_id,std::allocator&lt;polygon_with_id>>,
           
VisitPolicy=std::vector<polygon_with_id,std::allocator&lt;polygon_with_id>>,
            ExpandPolicy=intersection_visitor,
            OverlapsPolicy=int
        ]

        
4. Warnings when compiled with boost_1_62_0 (no errors result).

d:\boost_1_62_0\boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp(113):
warning C4244: 'initializing': conversion from 'const __int64' to 'int',
possible loss of data
...
d:\boost_1_62_0\boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp(113):
warning C4244: 'initializing': conversion from 'const __int64' to 'const
int', possible loss of data
d:\boost_1_62_0\boost/geometry/algorithms/detail/overlay/handle_colocations.hpp(314):
warning C4456: declaration of 'it' hides previous local declaration
...
d:\boost_1_62_0\boost/geometry/algorithms/detail/overlay/handle_colocations.hpp(322):
warning C4244: '=': conversion from 'const
boost::geometry::signed_size_type' to 'int', possible loss of data
d:\boost_1_62_0\boost/geometry/algorithms/detail/overlay/traversal.hpp(142):
warning C4457: declaration of 'op' hides function parameter
...
d:\boost_1_62_0\boost/geometry/algorithms/detail/overlay/sort_by_side.hpp(306):
warning C4267: 'initializing': conversion from 'size_t' to 'int', possible
loss of data
...
[and more warnings which are omitted]

--
View this message in context: http://boost-geometry.203548.n3.nabble.com/backward-compatibility-breakage-in-boost-geometry-partition-apply-function-tp4026789.html
Sent from the Boost Geometry mailing list archive at Nabble.com.

Geometry list run by mateusz at loskot.net