Newer
Older
#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>
namespace bg = boost::geometry;
namespace bu = boost::units;
#include <GeographicLib/Geocentric.hpp>
#include <GeographicLib/LocalCartesian.hpp>
using namespace std;
namespace snake {
//=========================================================================
// Geometry stuff.
//=========================================================================
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 {
37
38
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
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}); }
size_t _elements;
size_t _m;
size_t _n;
bool _isInitialized;
std::vector<T> _matrix;
struct BoundingBox {
BoundingBox();
double width;
double height;
double angle;
BoostPolygon corners;
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);
proj.Forward(in.latitude(), in.longitude(), in.altitude(), x, y, z);
out.set<0>(x);
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);
proj.Reverse(in.get<0>(), in.get<1>(), 0.0, lat, lon, alt);
out.setLatitude(lat);
out.setLongitude(lon);
out.setAltitude(alt);
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);
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);
}
void polygonCenter(const BoostPolygon &polygon, BoostPoint ¢er);
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);
void toDistanceMatrix(Matrix<double> &graph);
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);
typedef bu::quantity<bu::si::length> Length;
typedef bu::quantity<bu::si::area> Area;
typedef bu::quantity<bu::si::plane_angle> Angle;
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);
using Transects = vector<BoostLineString>;
using Progress = vector<int>;
using Route = BoostLineString;
bool transectsFromScenario(Length distance, Length minLength, Angle angle,
const BoostPolygon &mArea,
const std::vector<BoostPolygon> &tiles,
const Progress &p, Transects &t,
string &errorString);
bool route(const BoostPolygon &area, const Transects &transects,
Transects &transectsRouted, Route &route, string &errorString);
1; // meter, polygon offset to compenstate for numerical inaccurracies.
} // 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);
} // namespace model
} // namespace geometry
} // namespace boost