1

I have extents of 2 boxes (values are in the same projection/CRS). How can i convert them to polygons using boost? Boost polygon needs some kind of WKT and i just have extents as below for each box specifying its bounding box co-ordinates (extent of each box look like below)

minX = 394702.91392588202
minY = 6432746.6604581000
maxX = 403253.65448691702
maxY = 6439166.2975105597

I believe the boost polygon needs some kind of wkt

#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>

int main()
{

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

 polygon a;
 boost::geometry::read_wkt("POLYGON((123.345 6205.885, 5873.9832 6205.885, 395873.998 674.0062, 30.30683 614.300, 910.3083 6435.40))", a);
   
return 0;
}

My intention is to convert my extents to polygon using boost. Any pointers how to achieve this?

sehe
  • 374,641
  • 47
  • 450
  • 633
  • An important point of confusion is that [Boost Polygon](https://www.boost.org/doc/libs/1_76_0/libs/polygon/doc/) is an entirely different library from [Boost Geometry](https://www.boost.org/doc/libs/1_76_0/libs/geometry/doc/html/index.html), and your code isn't using it. – sehe Jul 30 '21 at 14:27

1 Answers1

0

There are some fine points of confusion I spotted from your question, but lets shine a flash light onto a (path to) solution:

Boost Geometry has a Box concept, and you can use it directly:

double minX = 394702.91392588202, minY = 6432746.6604581000,
       maxX = 403253.65448691702, maxY = 6439166.297510559;

box b{{minX, minY}, {maxX, maxY}};
std::cout << bg::wkt(b) << "\n";

Which prints

POLYGON((394703 6.43275e+06,394703 6.43917e+06,403254 6.43917e+06,403254 6.43
275e+06,394703 6.43275e+06))

Note that the polygon has the starting point as the closing point to satisfy the concept requirements. Also note that the outer ring is in specific orientation. If your box's corner points are mixed up, you can use bg::correct to sort the rings correctly.

Now if you must have it as a polygon, you can do that in various ways. Obviously reading from WKT is most flexible but not efficient.

Assign

I'd recommend this, as it is relatively efficient and less error prone than juggling the coordinates manually. If b is still the box from above:

polygon a;
bg::assign(a, b);
std::cout << bg::wkt(a) << "\n";

This prints the same as for the box.

Construct

polygon a{{
    {minX, minY},
    {minX, maxY},
    {maxX, maxY},
    {maxX, minY},
    {minX, minY}, // closed
}};
std::cout << bg::wkt(a) << "\n";

Again, prints the same. Also, again, take care to order the points and close the polygon!

Assign Points

Using library primitives:

polygon a;
bg::assign_points(a,
                  std::vector{
                      point{minX, minY},
                      {minX, maxY},
                      {maxX, maxY},
                      {maxX, minY},
                      {minX, minY}, // closed
                  });

Using direct model implementation:

polygon a;
a.outer() = {
    {minX, minY}, {minX, maxY}, {maxX, maxY},
    {maxX, minY}, {minX, minY}, // closed
};

Note in the latter case it's up to you to maintain model invariants/consistency (like e.g. dealing with any existing inner rings).

Convert

When the point types don't match, use bg::convert(from, to) instead of bg::assign(to, from). Note that this does technical conversion, not coordinate system projections or anything like those.

Live Demo

A listing combining the above information:

Live On Coliru

#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <iostream>

namespace bg  = boost::geometry;
namespace bgm = bg::model;
using point   = bgm::d2::point_xy<double>;
using polygon = bgm::polygon<point>;
using box     = bgm::box<point>;

int main()
{
    double minX = 394702.91392588202, minY = 6432746.6604581000,
           maxX = 403253.65448691702, maxY = 6439166.297510559;

    box b{{minX, minY}, {maxX, maxY}};
    std::cout << bg::wkt(b) << "\n";

    polygon a;
    bg::assign_points(a,
                      std::vector{
                          point{minX, minY},
                          {minX, maxY},
                          {maxX, maxY},
                          {maxX, minY},
                          {minX, minY}, // closed
                      });
    a.outer() = {
        {minX, minY}, {minX, maxY}, {maxX, maxY},
        {maxX, minY}, {minX, minY}, // closed
    };
    bg::assign(a, b);
    bg::convert(b, a);

    std::cout << bg::wkt(a) << "\n";

    std::string validity_reason;
    bool valid = bg::is_valid(a, validity_reason);
    std::cout << "Assigned points: " << validity_reason << "\n";
    if (!valid) 
    {
        bg::correct(a);
        std::cout << "Corrected: " << bg::wkt(a) << "\n";
    }
}

Prints

POLYGON((394703 6.43275e+06,394703 6.43917e+06,403254 6.43917e+06,403254 6.43275e+06,394703 6.43275e+06))
POLYGON((394703 6.43275e+06,394703 6.43917e+06,403254 6.43917e+06,403254 6.43275e+06,394703 6.43275e+06))
Assigned points: Geometry is valid
sehe
  • 374,641
  • 47
  • 450
  • 633