#ifndef AIRMAP_GEOMETRY_H_ #define AIRMAP_GEOMETRY_H_ #include #include namespace airmap { /// Geometry bundles up different types of geometries. class Geometry { public: /// Type enumerates all known geometry types. enum class Type { invalid, ///< Marks an invalid geometry. point, ///< Geometry contains a Point. multi_point, ///< Geometry contains a MultiPoint. line_string, ///< Geometry contains a LineString. multi_line_string, ///< Geometry contains a MultiLineString. polygon, ///< Geometry contains a Polygon. multi_polygon, ///< Geometry contains a MultiPolygon. geometry_collection ///< Geometry is a GemetryCollection. }; /// Coordinate marks a point in 3-dimensional space. struct Coordinate { double latitude; /// The latitude component of this coordinate in [°]. double longitude; /// The longitude component of this coordinate in [°]. Optional altitude; /// The altitude component of this coordinate in [m]. Optional elevation; }; /// CoordinateVector is a collection of points in 3-dimensional space. template struct CoordinateVector { std::vector coordinates; ///< The individual coordinates. }; using Point = Coordinate; using MultiPoint = CoordinateVector; using LineString = CoordinateVector; using MultiLineString = std::vector; /// Polygon follows the GeoJSON standard, citing from https://tools.ietf.org/html/rfc7946: /// * For type "Polygon", the "coordinates" member MUST be an array of /// linear ring coordinate arrays. /// * For Polygons with more than one of these rings, the first MUST be /// the exterior ring, and any others MUST be interior rings. The /// exterior ring bounds the surface, and the interior rings (if /// present) bound holes within the surface. struct Polygon { CoordinateVector outer_ring; std::vector> inner_rings; }; using MultiPolygon = std::vector; using GeometryCollection = std::vector; /// point returns a Geometry instance with Type::point at the given coordinate (lat, lon). static Geometry point(double lat, double lon); /// polygon returns a Geometry instance with Type::polygon with the given 'coordinates'. static Geometry polygon(const std::vector& coordinates); /// Initializes a new instance with Type::invalid. Geometry(); /// Geometry initializes a new instance with the given Point. explicit Geometry(const Point& other); /// Geometry initializes a new instance with the given MultiPoint. explicit Geometry(const MultiPoint& other); /// Geometry initializes a new instance with the given LineString. explicit Geometry(const LineString& other); /// Geometry initializes a new instance with the given MultiLineString. explicit Geometry(const MultiLineString& other); /// Geometry initializes a new instance with the given Polyon. explicit Geometry(const Polygon& other); /// Geometry initializes a new instance with the given MultiPolygon. explicit Geometry(const MultiPolygon& other); /// Geometry initializes a new instance with the given GeometryCollection. explicit Geometry(const GeometryCollection& other); /// @cond Geometry(const Geometry& other); ~Geometry(); Geometry& operator=(const Geometry& rhs); bool operator==(const Geometry& rhs) const; /// @endcond /// type returns the Type of the geometry. Type type() const; /// details_for_point returns an immutable instance to the contained Point instance. const Point& details_for_point() const; /// details_for_multi_point returns an immutable instance to the contained MultiPoint instance. const MultiPoint& details_for_multi_point() const; /// details_for_line_string returns an immutable instance to the contained LineString instance. const LineString& details_for_line_string() const; /// details_for_multi_line_string returns an immutable instance to the contained MultiLineString instance. const MultiLineString& details_for_multi_line_string() const; /// details_for_polygon returns an immutable instance to the contained Polygon instance. const Polygon& details_for_polygon() const; /// details_for_multi_polygon returns an immutable instance to the contained MultiPolygon instance. const MultiPolygon& details_for_multi_polygon() const; /// details_for_geometry_collection returns an immutable instance to the contained GeometryCollection instance. const GeometryCollection details_for_geometry_collection() const; private: struct Invalid {}; union Data { Data(); ~Data(); Invalid invalid; Point point; MultiPoint multi_point; LineString line_string; MultiLineString multi_line_string; Polygon polygon; MultiPolygon multi_polygon; GeometryCollection geometry_collection; }; Geometry& reset(); void set_point(const Point& point); void set_multi_point(const MultiPoint& multi_point); void set_line_string(const LineString& line_string); void set_multi_line_string(const MultiLineString& multi_line_string); void set_polygon(const Polygon& polygon); void set_multi_polygon(const MultiPolygon& multi_polygon); void set_geometry_collection(const GeometryCollection& geometry_collection); Geometry& set_geometry(const Geometry& other); Type type_; Data data_; }; /// @cond bool operator==(const Geometry::Coordinate& lhs, const Geometry::Coordinate& rhs); bool operator==(const Geometry::Polygon& lhs, const Geometry::Polygon& rhs); template bool operator==(const Geometry::CoordinateVector& lhs, const Geometry::CoordinateVector& rhs) { return lhs.coordinates == rhs.coordinates; } /// @endcond } // namespace airmap #endif // AIRMAP_GEOMETRY_H_