snake.h 6.76 KB
Newer Older
1 2 3
#pragma once

#include <array>
4 5
#include <atomic>
#include <functional>
Valentin Platzgummer's avatar
Valentin Platzgummer committed
6
#include <memory>
7 8 9 10 11 12 13 14 15
#include <string>
#include <vector>

#include <boost/geometry.hpp>
#include <boost/units/systems/angle/degrees.hpp>
#include <boost/units/systems/si.hpp>
#include <boost/units/systems/si/io.hpp>
#include <boost/units/systems/si/plane_angle.hpp>
#include <boost/units/systems/si/prefixes.hpp>
16

17 18
namespace bg = boost::geometry;
namespace bu = boost::units;
19

Valentin Platzgummer's avatar
Valentin Platzgummer committed
20 21 22
#include <GeographicLib/Geocentric.hpp>
#include <GeographicLib/LocalCartesian.hpp>

23 24 25
using namespace std;

namespace snake {
Valentin Platzgummer's avatar
Valentin Platzgummer committed
26 27 28
//=========================================================================
// Geometry stuff.
//=========================================================================
29 30 31 32 33 34 35 36 37

typedef bg::model::point<double, 2, bg::cs::cartesian> BoostPoint;
// typedef std::vector<BoostPoint>                        BoostPointList;
typedef bg::model::polygon<BoostPoint> BoostPolygon;
typedef bg::model::linestring<BoostPoint> BoostLineString;
typedef std::vector<std::vector<int64_t>> Int64Matrix;
typedef bg::model::box<BoostPoint> BoostBox;

template <class T> class Matrix {
Valentin Platzgummer's avatar
Valentin Platzgummer committed
38
public:
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
  Matrix() : _elements(0), _m(0), _n(0), _isInitialized(false) {}
  Matrix(size_t m, size_t n) : Matrix(m, n, T{0}) {}
  Matrix(size_t m, size_t n, T value)
      : _elements(m * n), _m(m), _n(n), _isInitialized(true) {
    assert((m > 0) || (n > 0));
    _matrix.resize(_elements, value);
  }

  double get(size_t i, size_t j) const {
    assert(_isInitialized);
    assert(i < _m);
    assert(j < _n);
    return _matrix[i * _m + j];
  }

  size_t getM() const { return _m; }
  size_t getN() const { return _n; }

  void set(size_t i, size_t j, const T &value) {
    assert(_isInitialized);
    assert(i < _m);
    assert(j < _n);
    _matrix[i * _m + j] = value;
  }

  void setDimension(size_t m, size_t n, const T &value) {
    assert((m > 0) || (n > 0));
    assert(!_isInitialized);
    _m = m;
    _n = n;
    _elements = n * m;
    _matrix.resize(_elements, value);
    _isInitialized = true;
  }

  void setDimension(size_t m, size_t n) { setDimension(m, n, T{0}); }
Valentin Platzgummer's avatar
Valentin Platzgummer committed
75 76

private:
77 78 79 80 81
  size_t _elements;
  size_t _m;
  size_t _n;
  bool _isInitialized;
  std::vector<T> _matrix;
Valentin Platzgummer's avatar
Valentin Platzgummer committed
82 83
};

84 85
struct BoundingBox {
  BoundingBox();
Valentin Platzgummer's avatar
Valentin Platzgummer committed
86

87
  void clear();
Valentin Platzgummer's avatar
Valentin Platzgummer committed
88

89 90 91 92
  double width;
  double height;
  double angle;
  BoostPolygon corners;
Valentin Platzgummer's avatar
Valentin Platzgummer committed
93
};
Valentin Platzgummer's avatar
Valentin Platzgummer committed
94

95 96 97 98 99 100 101
template <class GeoPoint>
void toENU(const GeoPoint &origin, const GeoPoint &in, BoostPoint &out) {
  GeographicLib::Geocentric earth(GeographicLib::Constants::WGS84_a(),
                                  GeographicLib::Constants::WGS84_f());
  GeographicLib::LocalCartesian proj(origin.latitude(), origin.longitude(),
                                     origin.altitude(), earth);

Valentin Platzgummer's avatar
Valentin Platzgummer committed
102
  double x = 0, y = 0, z = 0;
Valentin Platzgummer's avatar
Valentin Platzgummer committed
103 104 105
  auto alt = in.altitude();
  alt = std::isnan(alt) ? 0 : alt;
  proj.Forward(in.latitude(), in.longitude(), alt, x, y, z);
106
  out.set<0>(x);
Valentin Platzgummer's avatar
Valentin Platzgummer committed
107
  out.set<1>(y);
108
  (void)z;
Valentin Platzgummer's avatar
Valentin Platzgummer committed
109
}
Valentin Platzgummer's avatar
Valentin Platzgummer committed
110

111 112 113 114 115 116 117
template <class GeoPoint>
void fromENU(const GeoPoint &origin, const BoostPoint &in, GeoPoint &out) {
  GeographicLib::Geocentric earth(GeographicLib::Constants::WGS84_a(),
                                  GeographicLib::Constants::WGS84_f());
  GeographicLib::LocalCartesian proj(origin.latitude(), origin.longitude(),
                                     origin.altitude(), earth);

Valentin Platzgummer's avatar
Valentin Platzgummer committed
118
  double lat = 0, lon = 0, alt = 0;
119 120 121 122
  proj.Reverse(in.get<0>(), in.get<1>(), 0.0, lat, lon, alt);
  out.setLatitude(lat);
  out.setLongitude(lon);
  out.setAltitude(alt);
Valentin Platzgummer's avatar
Valentin Platzgummer committed
123 124
}

125 126 127 128 129 130 131 132 133
template <class GeoPoint, template <class, class...> class Container>
void areaToEnu(const GeoPoint &origin, const Container<GeoPoint> &in,
               BoostPolygon &out) {
  for (auto vertex : in) {
    BoostPoint p;
    toENU(origin, vertex, p);
    out.outer().push_back(p);
  }
  bg::correct(out);
Valentin Platzgummer's avatar
Valentin Platzgummer committed
134 135
}

136 137 138 139 140 141 142 143
template <class GeoPoint, template <class, class...> class Container>
void areaFromEnu(const GeoPoint &origin, BoostPolygon &in,
                 const Container<GeoPoint> &out) {
  for (auto vertex : in.outer()) {
    GeoPoint p;
    fromENU(origin, vertex, p);
    out.push_back(p);
  }
Valentin Platzgummer's avatar
Valentin Platzgummer committed
144
}
145

Valentin Platzgummer's avatar
Valentin Platzgummer committed
146 147 148 149 150 151
void polygonCenter(const BoostPolygon &polygon, BoostPoint &center);
bool minimalBoundingBox(const BoostPolygon &polygon, BoundingBox &minBBox);
void offsetPolygon(const BoostPolygon &polygon, BoostPolygon &polygonOffset,
                   double offset);
void graphFromPolygon(const BoostPolygon &polygon,
                      const BoostLineString &vertices, Matrix<double> &graph);
152
bool toDistanceMatrix(Matrix<double> &graph);
Valentin Platzgummer's avatar
Valentin Platzgummer committed
153 154 155 156 157 158
bool dijkstraAlgorithm(
    const size_t numElements, size_t startIndex, size_t endIndex,
    std::vector<size_t> &elementPath,
    std::function<double(const size_t, const size_t)> distanceDij);
void shortestPathFromGraph(const Matrix<double> &graph, size_t startIndex,
                           size_t endIndex, std::vector<size_t> &pathIdx);
Valentin Platzgummer's avatar
Valentin Platzgummer committed
159

Valentin Platzgummer's avatar
Valentin Platzgummer committed
160 161 162
typedef bu::quantity<bu::si::length> Length;
typedef bu::quantity<bu::si::area> Area;
typedef bu::quantity<bu::si::plane_angle> Angle;
Valentin Platzgummer's avatar
Valentin Platzgummer committed
163 164
typedef bu::quantity<bu::si::plane_angle> Radian;
typedef bu::quantity<bu::degree::plane_angle> Degree;
Valentin Platzgummer's avatar
Valentin Platzgummer committed
165

Valentin Platzgummer's avatar
Valentin Platzgummer committed
166 167 168 169 170 171 172
bool joinedArea(const std::vector<BoostPolygon *> &areas, BoostPolygon &jArea);
bool joinedArea(const BoostPolygon &mArea, const BoostPolygon &sArea,
                const BoostPolygon &corridor, BoostPolygon &jArea,
                std::string &errorString);
bool tiles(const BoostPolygon &area, Length tileHeight, Length tileWidth,
           Area minTileArea, std::vector<BoostPolygon> &tiles,
           BoundingBox &bbox, std::string &errorString);
173 174 175

using Transects = vector<BoostLineString>;
using Progress = vector<int>;
176
using Route = BoostLineString;
177 178

bool transectsFromScenario(Length distance, Length minLength, Angle angle,
Valentin Platzgummer's avatar
Valentin Platzgummer committed
179 180 181 182
                           const BoostPolygon &mArea,
                           const std::vector<BoostPolygon> &tiles,
                           const Progress &p, Transects &t,
                           string &errorString);
Valentin Platzgummer's avatar
Valentin Platzgummer committed
183 184 185 186 187 188

struct TransectInfo {
  TransectInfo(size_t n, bool r) : index(n), reversed(r) {}
  size_t index;
  bool reversed;
};
189
bool route(const BoostPolygon &area, const Transects &transects,
190
           std::vector<TransectInfo> &transectInfo, Route &r,
Valentin Platzgummer's avatar
Valentin Platzgummer committed
191
           string &errorString);
192 193 194
bool route(const BoostPolygon &area, const Transects &transects,
           std::vector<TransectInfo> &transectInfo, Route &r,
           std::function<bool(void)> stop, string &errorString);
Valentin Platzgummer's avatar
Valentin Platzgummer committed
195 196

namespace detail {
197
const double offsetConstant =
Valentin Platzgummer's avatar
Valentin Platzgummer committed
198
    0.1; // meter, polygon offset to compenstate for numerical inaccurracies.
Valentin Platzgummer's avatar
Valentin Platzgummer committed
199
} // namespace detail
200 201 202 203 204 205 206 207 208
} // namespace snake

// operator== and operator!= for boost point
namespace boost {
namespace geometry {
namespace model {

bool operator==(snake::BoostPoint p1, snake::BoostPoint p2);
bool operator!=(snake::BoostPoint p1, snake::BoostPoint p2);
209

210 211 212
} // namespace model
} // namespace geometry
} // namespace boost