geopoint.h 4.28 KB
Newer Older
1 2 3 4 5
#pragma once

#include <string>

#include "ros_bridge/include/message_traits.h"
6 7 8

#include <QJsonObject>
#include <QJsonValue>
9 10 11 12

namespace ros_bridge {
//! @brief Namespace containing classes and methodes ros message generation.
namespace messages {
13 14
//! @brief Namespace containing classes and methodes for geometry_msgs
//! generation.
15
namespace geographic_msgs {
16 17
//! @brief Namespace containing methodes for geometry_msgs/GeoPoint message
//! generation.
18 19
namespace geo_point {

20
std::string messageType();
21

22 23 24 25 26 27 28
namespace {
const char *lonKey = "longitude";
const char *latKey = "latitude";
const char *altKey = "altitude";

} // namespace

29
//! @brief C++ representation of geographic_msgs/GeoPoint.
30 31
template <class FloatType = _Float64, class OStream = std::ostream>
class GenericGeoPoint {
32
public:
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
  GenericGeoPoint() : _latitude(0), _longitude(0), _altitude(0) {}
  GenericGeoPoint(const GenericGeoPoint &other)
      : _latitude(other.latitude()), _longitude(other.longitude()),
        _altitude(other.altitude()) {}
  GenericGeoPoint(FloatType latitude, FloatType longitude, FloatType altitude)
      : _latitude(latitude), _longitude(longitude), _altitude(altitude) {}

  FloatType latitude() const { return _latitude; }
  FloatType longitude() const { return _longitude; }
  FloatType altitude() const { return _altitude; }

  void setLatitude(FloatType latitude) { _latitude = latitude; }
  void setLongitude(FloatType longitude) { _longitude = longitude; }
  void setAltitude(FloatType altitude) { _altitude = altitude; }

  bool operator==(const GenericGeoPoint &p1) {
    return (p1._latitude == this->_latitude &&
            p1._longitude == this->_longitude &&
            p1._altitude == this->_altitude);
  }

  bool operator!=(const GenericGeoPoint &p1) { return !this->operator==(p1); }

  friend OStream &operator<<(OStream &os, const GenericGeoPoint &p) {
    os << "lat: " << p._latitude << " lon: " << p._longitude
       << " alt: " << p._altitude;
    return os;
  }
61 62

private:
63 64 65
  FloatType _latitude;
  FloatType _longitude;
  FloatType _altitude;
66 67 68 69 70
};
typedef GenericGeoPoint<> GeoPoint;

namespace detail {

71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
template <class T>
auto getAltitude(const T &p, traits::Type2Type<traits::Has3Components>) {
  return p.altitude();
}

template <class T>
auto getAltitude(const T &p, traits::Type2Type<traits::Has2Components>) {
  (void)p;
  return 0.0;
}

template <class T>
void setAltitude(const QJsonValue &o, T &p,
                 traits::Type2Type<traits::Has3Components>) {
  p.setAltitude(o.toDouble());
}
87 88

template <class T>
89 90 91 92
void setAltitude(const QJsonValue &o, T &p,
                 traits::Type2Type<traits::Has2Components>) {
  (void)o;
  (void)p;
93
}
94 95 96 97 98
} // namespace detail

template <class T> bool toJson(const T &p, QJsonObject &value) {
  value[latKey] = p.latitude();
  value[lonKey] = p.longitude();
99

100 101 102 103 104 105 106
  typedef typename traits::Select<traits::HasMemberAltitude<T>::value,
                                  traits::Has3Components,
                                  traits::Has2Components>::Result
      Components; // Check if PointType has 2 or 3 dimensions.
  auto altitude = detail::getAltitude(
      p, traits::Type2Type<Components>()); // If T has no member altitude()
                                           // replace it by 0.0;
107

108 109 110
  value[altKey] = altitude;
  return true;
}
111 112

template <class PointType>
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
bool fromJson(const QJsonObject &value, PointType &p) {
  if (!value.contains("latitude") || !value["latitude"].isDouble()) {
    return false;
  }
  if (!value.contains("longitude") || !value["longitude"].isDouble()) {
    return false;
  }
  if (!value.contains("altitude") || !value["altitude"].isDouble()) {
    return false;
  }

  p.setLatitude(value["latitude"].toDouble());
  p.setLongitude(value["longitude"].toDouble());
  typedef
      typename traits::Select<traits::HasMemberSetAltitude<PointType>::value,
                              traits::Has3Components,
                              traits::Has2Components>::Result
          Components; // Check if PointType has 2 or 3 dimensions.
  detail::setAltitude(
      value["altitude"], p,
      traits::Type2Type<Components>()); // If T has no member altitude() discard
                                        // doc["altitude"];

  return true;
137 138
} // namespace detail

139 140
} // namespace geo_point
} // namespace geographic_msgs
141 142
} // namespace messages
} // namespace ros_bridge