25 #ifndef INCLUDED_JSONEigen_h_GUID_A8A98FBE_0A98_4C83_9A13_D022330FE13E
26 #define INCLUDED_JSONEigen_h_GUID_A8A98FBE_0A98_4C83_9A13_D022330FE13E
32 #include <json/value.h>
33 #include <boost/lexical_cast.hpp>
34 #include <boost/algorithm/string.hpp>
35 #include <boost/range/algorithm/count_if.hpp>
36 #include <boost/assert.hpp>
46 template <
typename Derived>
47 inline Json::Value
toJson(Eigen::QuaternionBase<Derived>
const &quat) {
48 Json::Value ret(Json::objectValue);
57 template <
typename Derived>
58 inline Json::Value
toJson(Eigen::MatrixBase<Derived>
const &vec) {
59 static_assert(Derived::ColsAtCompileTime == 1,
60 "This function is only for converting vectors to JSON");
61 Json::Value ret(Json::arrayValue);
62 for (
size_t i = 0; i < Derived::RowsAtCompileTime; ++i) {
69 static const char AXIS_NAMES[] =
"XYZ";
70 static const char MINUS[] =
"-";
71 template <
typename VecType>
72 inline VecType stringToVector(std::string
const &s) {
76 VecType ret = VecType::Zero();
78 throw std::runtime_error(
79 "Can't parse a vector from an empty string!");
83 std::string upperS(boost::to_upper_copy(s));
86 using boost::is_any_of;
87 using boost::algorithm::is_space;
88 using boost::count_if;
89 if ((!boost::algorithm::all(upperS, is_any_of(AXIS_NAMES) ||
92 count_if(upperS, is_any_of(AXIS_NAMES)) != 1 ||
93 count_if(upperS, is_any_of(MINUS)) > 1) {
94 throw std::runtime_error(
95 "Cannot turn the specified string into a vector: " + s);
99 (upperS.find(MINUS[0]) == std::string::npos) ? 1.0 : -1.0;
100 for (
const char c : upperS) {
101 auto axisPtr = std::strchr(AXIS_NAMES, c);
102 if (
nullptr != axisPtr) {
103 auto index = axisPtr - AXIS_NAMES;
104 if (index >= VecType::RowsAtCompileTime) {
105 throw std::runtime_error(
106 "A vector of this size cannot be initialized to " +
114 BOOST_ASSERT_MSG(
false,
"Should never reach here!");
118 #define OSVR_EXTRACT_JSON_MEMBER(_DATATYPENAME, _LOWER, _UPPER) \
119 if (json.isMember(#_LOWER)) { \
120 ret._LOWER() = json[#_LOWER].asDouble(); \
121 } else if (json.isMember(#_UPPER)) { \
122 ret._LOWER() = json[#_UPPER].asDouble(); \
124 throw std::runtime_error("In parsing " _DATATYPENAME \
125 " from JSON, no " #_LOWER " element found!"); \
128 Eigen::Quaterniond quatFromJson(Json::Value
const &json) {
129 Eigen::Quaterniond ret;
130 if (json.isObject()) {
131 OSVR_EXTRACT_JSON_MEMBER(
"quaternion", w, W);
132 OSVR_EXTRACT_JSON_MEMBER(
"quaternion", x, X);
133 OSVR_EXTRACT_JSON_MEMBER(
"quaternion", y, Y);
134 OSVR_EXTRACT_JSON_MEMBER(
"quaternion", z, Z);
135 }
else if (json.isArray()) {
137 ret = Eigen::Quaterniond(json[0].asDouble(), json[1].asDouble(),
138 json[2].asDouble(), json[3].asDouble());
140 throw std::runtime_error(
"Could not parse quaternion from JSON - "
141 "neither an object nor an array");
146 inline Eigen::Vector3d vec3FromJson(Json::Value
const &json) {
147 typedef Eigen::Vector3d type;
148 #define OSVR_PARSE_NAME "Vector3d"
150 if (json.isString()) {
152 if ((json ==
"x") || (json ==
"X")) {
154 }
else if ((json ==
"y") || (json ==
"Y")) {
156 }
else if ((json ==
"z") || (json ==
"Z")) {
159 throw std::runtime_error(
160 "Could not parse a " OSVR_PARSE_NAME
161 " from JSON string: looking for an axis name, got " +
164 }
else if (json.isNumeric()) {
168 throw std::runtime_error(
169 "Could not parse a " OSVR_PARSE_NAME
170 " from the scalar value " +
171 boost::lexical_cast<std::string>(json.asDouble()));
173 }
else if (json.isArray()) {
174 if (json.size() != type::RowsAtCompileTime) {
175 throw std::runtime_error(
176 "Could not parse a " OSVR_PARSE_NAME
177 " from an array with " +
178 boost::lexical_cast<std::string>(json.size()) +
181 ret = type(json[0].asDouble(), json[1].asDouble(),
183 }
else if (json.isObject()) {
184 OSVR_EXTRACT_JSON_MEMBER(OSVR_PARSE_NAME, x, X);
185 OSVR_EXTRACT_JSON_MEMBER(OSVR_PARSE_NAME, y, Y);
186 OSVR_EXTRACT_JSON_MEMBER(OSVR_PARSE_NAME, z, Z);
188 throw std::runtime_error(
189 "Could not parse " OSVR_PARSE_NAME
" from JSON - "
190 "not a component name, 0, an array, nor an object");
193 #undef OSVR_PARSE_NAME
196 #undef OSVR_EXTRACT_JSON_MEMBER
200 #endif // INCLUDED_JSONEigen_h_GUID_A8A98FBE_0A98_4C83_9A13_D022330FE13E
Header wrapping include of and for warning quieting.
Json::Value toJson(Eigen::QuaternionBase< Derived > const &quat)
Converts quaternions to JSON objects.
double Scalar
Common scalar type.