Search code examples
c++booststdconvex-hullboost-geometry

Boost::convex_hull of scattered 2-D points in STL container


I have a vector of 2-D points. Lets assume they are of the form std::pair<int,int>. I want to use boost to calculate the convex hull. That's the question. How do I do that?

The only documentation I have found is like a graduate text for a course in rationale and trivia.

Fill in the BLANKS:

#include <iostream>
#include <vector>
#include <utility>

// BLANK boost include-files
// #include <boost/geometry.hpp>
// #include <boost/geometry/geometries/polygon.hpp> // Noop.
// #include <boost/geometry/geometries/adapted/boost_tuple.hpp>
// BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian)

int main() {
    // Serving suggestion
    std::vector<std::pair<int, int>> A{ { 0,3 },{ 1,4 },{ 2,2 },{ 1,0 }, \
    {0,0},{ 2,0 },{ 0,1 },{ 0,2 },{ 3,1 },{ 3,3 },{ 4,4 },{ 4,3 },{ 4,2 } };

    std::vector<std::pair<int, int>> the_hull; // Fill this, please.

 // BLANK - Boost magic goes here.

    // Print convex hull of A
    for (auto h: the_hull) {
        std::cout << h.first << "," << h.second << "\n";
    }
    std::cout<< std::endl;
    return 0;
}

Note to VC++ users. I had a metric tonne of trouble getting the answers below to compile, using VC++ 2017. I finally got it working. I re-installed boost, using the windows binaries for boost 1.66. Next I had to add the following two lines to the project properties

_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS;_SCL_SECURE_NO_WARNINGS

The IDE treats those "warnings" as fatal. It is not sufficient to disable all warnings. Furthermore, some of the "deprecation warnings" appear to be finger-wagging from Microsoft, not officially deprecated C++ things.


Solution

  • There is a way to do this without copying data from a container to a multi_point and vice versa. You have to register the vector container and the pair as a multi_point and point entity.

    #include <boost/geometry.hpp>
    #include <boost/geometry/geometries/register/point.hpp>
    #include <boost/geometry/multi/geometries/register/multi_point.hpp> 
    
    #include<iostream>
    
    BOOST_GEOMETRY_REGISTER_POINT_2D(decltype(std::pair<int, int>{}), int, cs::cartesian, first, second)
    BOOST_GEOMETRY_REGISTER_MULTI_POINT(decltype(std::vector<std::pair<int, int>>{}))
    
    int main(){
        std::vector<std::pair<int, int>> A{
            { 0,3 },{ 1,4 },{ 2,2 },{ 1,0 }, { 0,0 }, { 2,0 }, { 0,1 }, { 0,2 },
            { 3,1 },{ 3,3 },{ 4,4 },{ 4,3 }, { 4,2 } 
        };
        std::cout << "A: " << boost::geometry::wkt(A) << std::endl;
        std::vector<std::pair<int, int>> B;
        boost::geometry::convex_hull(A, B);
        std::cout << "B: " << boost::geometry::wkt(B) << std::endl;
    }
    

    Output:

    A: MULTIPOINT((0 3),(1 4),(2 2),(1 0),(0 0),(2 0),(0 1),(0 2),(3 1),(3 3),(4 4),(4 3),(4 2))
    B: MULTIPOINT((0 0),(0 3),(1 4),(4 4),(4 2),(2 0),(0 0)
    

    This works in Fedora 27, gcc 7.2.1, clang++ 4.0.1, Boost 1.64


    For Visual C++ 2017, Boost 1.66, it is necessary to add these to properties/C C++/Preprocessor/Preprocessor Definitions

     _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS;_SCL_SECURE_NO_WARNINGS
    

    The Visual Studio IDE treats those "warnings" as fatal. It is not sufficient to disable all warnings. Furthermore, some of the "deprecation warnings" appear to be Microsoft specific, not officially deprecated C++ things.