Search code examples
c++boostgeometrypoint-in-polygonboost-geometry

Convert array of point to polygon


I have array of point with latitude and longitude, from this array generating LineString to display way on road by leaflet.

Now i want to improve code function to detect when user point (received from GPS device):

1) Out from waypoint
2) Position on waypoint
3) Direction (begin or back)

After having tried many ways to implement my idea i coming to convert my array of point to Polygon and control by boost::geometry::intersection

I tried realise this function by search near point in array that work perfect in one way road else code can lock point from neighbour way :(

Example of ways:

[start]--------------[end]

But it can be so
[start]
---------one_road---turning_road_and_reverse-]
-------two_road-----------
[end]

Now i want to convert array to one polygon

-----------------------------------------------
one_road
two_road
-----------------------------------------------

i think that i can easily release function to detect location without errors

May be someone know how easily convert linestring to polygon?

example

i have:
LINESTRING(-105.40392744645942 38.49004450086558,-105.40486621961463 38.491262147649266,-105.40443706617225 38.49272329662804,-105.40424394712318 38.49368058506501,-105.4055099497782 38.49443633010962,-105.40690469846595 38.494940155735165,-105.40694761381019 38.49450350706328,-105.40634679899085 38.49324392875914,-105.40510225400794 38.49146368720108,-105.40437269315589 38.490422393448746,-105.40394675757852 38.489957795386)

i want:

POLYGON((-105.40419674129225 38.49056599190572,-105.40475464076735 38.49046522094479,-105.40737247676589 38.494462360981586,-105.40685749263503 38.49520130375959,-105.40647554502357 38.493848529093356,-105.4052739153849 38.49193394396309,-105.4047160159098 38.49237060820819,-105.40473747358192 38.49344546276763,-105.40600347623695 38.49430197601443,-105.40664720640052 38.49480580257953,-105.40585327253211 38.494789008417456,-105.40432977781165 38.49394929532246,-105.40394353971351 38.493059188756156,-105.40465164289344 38.49129573761371,-105.40419674129225 38.49056599190572))

Please help!


Solution

  • Your question is in serious need of a SSCCE. Reading it you might be looking for anything from trivial type conversion to complicated routing algorithms.

    Here's are two simple SSCCE's that show how to do the type conversions you describe.

    NOTE The extra work to check that the polygon is valid (it needs to be closed, and the points need to have the correct orientation for the outer ring)

    Array Of Point To Polygon

    Live On Coliru

    #include <boost/geometry.hpp>
    #include <boost/geometry/geometries/point_xy.hpp>
    #include <boost/geometry/geometries/linestring.hpp>
    #include <boost/geometry/geometries/polygon.hpp>
    
    #include <iostream>
    #include <boost/geometry/io/io.hpp>
    
    namespace bg = boost::geometry;
    namespace bgm = bg::model;
    
    using point      = bgm::d2::point_xy<int>;
    using polygon    = bgm::polygon<point>;
    
    void debug_print(polygon const& p) {
        std::string reason;
        bool valid = bg::is_valid(p, reason);
        std::cout << bg::dsv(p) << " - " << (!valid?"invalid ("+reason+")":"valid") << "\n";
    }
    
    int main() {
    
        point arr[] { {1,3}, {4,5}, {9, 0} };
        for (auto& p : arr)
            std::cout << bg::wkt(p) << " ";
        std::cout << "\n";
    
        polygon p { {std::begin(arr), std::end(arr)} };
        debug_print(p);
    
        bg::correct(p);
        debug_print(p);
    
        std::cout << bg::wkt(p) << "\n";
    }
    

    Prints:

    POINT(1 3) POINT(4 5) POINT(9 0) 
    (((1, 3), (4, 5), (9, 0))) - invalid (Geometry has too few points)
    (((1, 3), (4, 5), (9, 0), (1, 3))) - valid
    POLYGON((1 3,4 5,9 0,1 3))
    

    LineString To Polygon

    Live On Coliru

    #include <boost/geometry.hpp>
    #include <boost/geometry/geometries/point_xy.hpp>
    #include <boost/geometry/geometries/linestring.hpp>
    #include <boost/geometry/geometries/polygon.hpp>
    
    #include <iostream>
    #include <boost/geometry/io/io.hpp>
    
    namespace bg = boost::geometry;
    namespace bgm = bg::model;
    
    using point      = bgm::d2::point_xy<int>;
    using linestring = bgm::linestring<point>;
    using ring       = bgm::ring<point>;
    using polygon    = bgm::polygon<point>;
    
    void debug_print(polygon const& p) {
        std::string reason;
        bool valid = bg::is_valid(p, reason);
        std::cout << bg::dsv(p) << " - " << (!valid?"invalid ("+reason+")":"valid") << "\n";
    }
    
    int main() {
    
        linestring ls { {1,3}, {4,5}, {9, 0} };
        std::cout << bg::wkt(ls) << "\n";
    
        polygon p { ring{ls.begin(), ls.end()} };
        debug_print(p);
    
        bg::correct(p);
        debug_print(p);
    
        std::cout << bg::wkt(p) << "\n";
    }
    

    Prints

    LINESTRING(1 3,4 5,9 0)
    (((1, 3), (4, 5), (9, 0))) - invalid (Geometry has too few points)
    (((1, 3), (4, 5), (9, 0), (1, 3))) - valid
    POLYGON((1 3,4 5,9 0,1 3))