C++ 删除重复项:如何为boost::geometry::box编写排序谓词?

C++ 删除重复项:如何为boost::geometry::box编写排序谓词?,c++,boost,boost-geometry,C++,Boost,Boost Geometry,我在这样的类中使用boost::geometry::model::box: struct Feature { typedef boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian> point; typedef boost::geometry::model::box<point> box; box bounds; //... other member

我在这样的类中使用
boost::geometry::model::box

struct Feature {
    typedef boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian> point;
    typedef boost::geometry::model::box<point> box;

    box bounds;
    //... other members ...
};

std::list<Feature> v;
我能够使用
boost::geometry::equals
(如中所述)编写
操作符==
,因此
std::unique
可以工作。是否有类似的函数可用于将谓词写入
排序
,还是需要从头开始编写


或者,在
boost::geometry
中是否有更好的方法来删除重复项?

我认为您不能重复使用
boost::geometry::index
中的任何内容,因为(遗憾的是)即使是
nearest()
查询的结果也没有顺序

所以,给你我的。。。最简单的做法是:

#include <boost/geometry.hpp>
#include <boost/geometry/io/io.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
// #include <boost/range/adaptors.hpp>
#include <tuple>
#include <iostream>
#include <iomanip>

namespace bg  = boost::geometry;
namespace bgm = bg::model;

typedef bgm::point<double, 2, bg::cs::cartesian> point;
typedef bgm::box<point> box;

namespace std {
    // less
    template <> struct less<point> {
        bool operator()(point const& a, point const& b) const { return std::tie(a.get<0>(), a.get<1>()) < std::tie(b.get<0>(), b.get<1>()); }
    };
    template <> struct less<box> {
        bool operator()(box const& a, box const& b) const { return 
                std::tie(a.min_corner().get<0>(), a.min_corner().get<1>(), a.max_corner().get<0>(), a.max_corner().get<1>())
              < std::tie(b.min_corner().get<0>(), b.min_corner().get<1>(), b.max_corner().get<0>(), b.max_corner().get<1>()); }
    };
    // equal_to
    template <> struct equal_to<point> {
        bool operator()(point const& a, point const& b) const { return std::tie(a.get<0>(), a.get<1>()) == std::tie(b.get<0>(), b.get<1>()); }
    };
    template <> struct equal_to<box> {
        bool operator()(box const& a, box const& b) const { return 
                std::tie(a.min_corner().get<0>(), a.min_corner().get<1>(), a.max_corner().get<0>(), a.max_corner().get<1>())
             == std::tie(b.min_corner().get<0>(), b.min_corner().get<1>(), b.max_corner().get<0>(), b.max_corner().get<1>()); }
    };
}

struct Feature {
    box bounds;
    //... other members ...
    std::string other;

    friend std::ostream& operator<<(std::ostream& os, Feature const& f) {
        return os << "{" << bg::wkt(f.bounds) << ", " << std::quoted(f.other) << "}";
    }

    struct less_by_box : std::less<box> {
        bool operator()(Feature const& a, Feature const& b) const { return std::less<box>::operator()(a.bounds, b.bounds); }
    };
    struct by_box : std::equal_to<box> {
        bool operator()(Feature const& a, Feature const& b) const { return std::equal_to<box>::operator()(a.bounds, b.bounds); }
    };
};

int main() {
    std::vector<Feature> v {
        { box { {2,3}, {4,5} }, "three" },
        { box { {1,2}, {3,4} }, "two" },
        { box { {2,3}, {4,5} }, "one" },
    };

    auto dump = [&] {
        std::cout << "Size: " << v.size() << "\n";
        for (Feature const& f : v) { std::cout << f << "\n"; }
    };

    dump();

    std::cout << " -- Sort, Unique, Erase:\n";
    std::stable_sort(v.begin(), v.end(), Feature::less_by_box{});
    v.erase(std::unique(v.begin(), v.end(), Feature::by_box{}), v.end());

    dump();
}

这和我最终做的很相似,只是我还没有读过std::tie,所以我的更详细。。。
#include <boost/geometry.hpp>
#include <boost/geometry/io/io.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
// #include <boost/range/adaptors.hpp>
#include <tuple>
#include <iostream>
#include <iomanip>

namespace bg  = boost::geometry;
namespace bgm = bg::model;

typedef bgm::point<double, 2, bg::cs::cartesian> point;
typedef bgm::box<point> box;

namespace std {
    // less
    template <> struct less<point> {
        bool operator()(point const& a, point const& b) const { return std::tie(a.get<0>(), a.get<1>()) < std::tie(b.get<0>(), b.get<1>()); }
    };
    template <> struct less<box> {
        bool operator()(box const& a, box const& b) const { return 
                std::tie(a.min_corner().get<0>(), a.min_corner().get<1>(), a.max_corner().get<0>(), a.max_corner().get<1>())
              < std::tie(b.min_corner().get<0>(), b.min_corner().get<1>(), b.max_corner().get<0>(), b.max_corner().get<1>()); }
    };
    // equal_to
    template <> struct equal_to<point> {
        bool operator()(point const& a, point const& b) const { return std::tie(a.get<0>(), a.get<1>()) == std::tie(b.get<0>(), b.get<1>()); }
    };
    template <> struct equal_to<box> {
        bool operator()(box const& a, box const& b) const { return 
                std::tie(a.min_corner().get<0>(), a.min_corner().get<1>(), a.max_corner().get<0>(), a.max_corner().get<1>())
             == std::tie(b.min_corner().get<0>(), b.min_corner().get<1>(), b.max_corner().get<0>(), b.max_corner().get<1>()); }
    };
}

struct Feature {
    box bounds;
    //... other members ...
    std::string other;

    friend std::ostream& operator<<(std::ostream& os, Feature const& f) {
        return os << "{" << bg::wkt(f.bounds) << ", " << std::quoted(f.other) << "}";
    }

    struct less_by_box : std::less<box> {
        bool operator()(Feature const& a, Feature const& b) const { return std::less<box>::operator()(a.bounds, b.bounds); }
    };
    struct by_box : std::equal_to<box> {
        bool operator()(Feature const& a, Feature const& b) const { return std::equal_to<box>::operator()(a.bounds, b.bounds); }
    };
};

int main() {
    std::vector<Feature> v {
        { box { {2,3}, {4,5} }, "three" },
        { box { {1,2}, {3,4} }, "two" },
        { box { {2,3}, {4,5} }, "one" },
    };

    auto dump = [&] {
        std::cout << "Size: " << v.size() << "\n";
        for (Feature const& f : v) { std::cout << f << "\n"; }
    };

    dump();

    std::cout << " -- Sort, Unique, Erase:\n";
    std::stable_sort(v.begin(), v.end(), Feature::less_by_box{});
    v.erase(std::unique(v.begin(), v.end(), Feature::by_box{}), v.end());

    dump();
}
Size: 3
{POLYGON((2 3,2 5,4 5,4 3,2 3)), "three"}
{POLYGON((1 2,1 4,3 4,3 2,1 2)), "two"}
{POLYGON((2 3,2 5,4 5,4 3,2 3)), "one"}
 -- Sort, Unique, Erase:
Size: 2
{POLYGON((1 2,1 4,3 4,3 2,1 2)), "two"}
{POLYGON((2 3,2 5,4 5,4 3,2 3)), "three"}