mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-05-06 11:29:55 -05:00
Use the correct type for the navigation state
Add unit tests to verify parsing of these parameters
This commit is contained in:
@@ -92,10 +92,10 @@ public:
|
||||
std::string anchor;
|
||||
std::string aim;
|
||||
std::string referenceFrame;
|
||||
std::string position; // @TODO (abock, 2020-06-17) change to vec3
|
||||
std::string up;// @TODO (abock, 2020-06-17) change to vec3
|
||||
std::string yaw;
|
||||
std::string pitch;
|
||||
glm::dvec3 position;
|
||||
std::optional<glm::dvec3> up;
|
||||
std::optional<double> yaw;
|
||||
std::optional<double> pitch;
|
||||
};
|
||||
struct CameraGoToGeo {
|
||||
static constexpr const char* Type = "goToGeo";
|
||||
|
||||
+109
-25
@@ -289,10 +289,80 @@ namespace {
|
||||
camera.anchor = fields[1];
|
||||
camera.aim = fields[2];
|
||||
camera.referenceFrame = fields[3];
|
||||
camera.position = fields[4];
|
||||
camera.up = fields[5];
|
||||
camera.yaw = fields[6];
|
||||
camera.pitch = fields[7];
|
||||
|
||||
std::vector<std::string> position = ghoul::tokenizeString(fields[4], ' ');
|
||||
if (position.size() != 3) {
|
||||
throw ProfileParsingError(
|
||||
lineNumber,
|
||||
fmt::format(
|
||||
"Expected 3 fields for the camera's position, got {}",
|
||||
position.size()
|
||||
)
|
||||
);
|
||||
}
|
||||
try {
|
||||
camera.position = glm::dvec3(
|
||||
std::stod(position[0]),
|
||||
std::stod(position[1]),
|
||||
std::stod(position[2])
|
||||
);
|
||||
}
|
||||
catch (const std::invalid_argument&) {
|
||||
throw ProfileParsingError(
|
||||
lineNumber,
|
||||
"Camera's position components must be numbers"
|
||||
);
|
||||
}
|
||||
|
||||
std::vector<std::string> up = ghoul::tokenizeString(fields[5], ' ');
|
||||
if (up.size() != 0 && up.size() != 3) {
|
||||
throw ProfileParsingError(
|
||||
lineNumber,
|
||||
fmt::format(
|
||||
"Expected 0 or 3 fields for the camera's up vector, got {}",
|
||||
up.size()
|
||||
)
|
||||
);
|
||||
}
|
||||
if (up.size() == 3) {
|
||||
try {
|
||||
camera.up = glm::dvec3(
|
||||
std::stod(up[0]),
|
||||
std::stod(up[1]),
|
||||
std::stod(up[2])
|
||||
);
|
||||
}
|
||||
catch (const std::invalid_argument&) {
|
||||
throw ProfileParsingError(
|
||||
lineNumber,
|
||||
"Camera's up vector components must be numbers"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!fields[6].empty()) {
|
||||
try {
|
||||
camera.yaw = std::stod(fields[6]);
|
||||
}
|
||||
catch (const std::invalid_argument&) {
|
||||
throw ProfileParsingError(
|
||||
lineNumber,
|
||||
"Camera's yaw value must be a number"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!fields[7].empty()) {
|
||||
try {
|
||||
camera.pitch = std::stod(fields[7]);
|
||||
}
|
||||
catch (const std::invalid_argument&) {
|
||||
throw ProfileParsingError(
|
||||
lineNumber,
|
||||
"Camera's pitch value must be a number"
|
||||
);
|
||||
}
|
||||
}
|
||||
return camera;
|
||||
}
|
||||
if (type == Profile::CameraGoToGeo::Type) {
|
||||
@@ -364,18 +434,10 @@ void Profile::saveCurrentSettingsToProfile(const properties::PropertyOwner& root
|
||||
c.anchor = navState.anchor;
|
||||
c.aim = navState.aim;
|
||||
c.referenceFrame = navState.referenceFrame;
|
||||
c.position = fmt::format(
|
||||
"{},{},{}",
|
||||
navState.position.x, navState.position.y, navState.position.z
|
||||
);
|
||||
if (navState.up.has_value()) {
|
||||
c.up = fmt::format(
|
||||
"{},{},{}",
|
||||
navState.up->x, navState.up->y, navState.up->z
|
||||
);
|
||||
}
|
||||
c.yaw = std::to_string(navState.yaw);
|
||||
c.pitch = std::to_string(navState.pitch);
|
||||
c.position = navState.position;
|
||||
c.up = navState.up;
|
||||
c.yaw = navState.yaw;
|
||||
c.pitch = navState.pitch;
|
||||
camera = std::move(c);
|
||||
}
|
||||
|
||||
@@ -524,11 +586,27 @@ std::string Profile::serialize() const {
|
||||
output += std::visit(
|
||||
overloaded {
|
||||
[](const CameraNavState& camera) {
|
||||
std::string position = fmt::format(
|
||||
"{}, {}, {}",
|
||||
camera.position.x, camera.position.y, camera.position.z
|
||||
);
|
||||
std::string up = camera.up.has_value() ?
|
||||
fmt::format(
|
||||
"{}, {}, {}", camera.up->x, camera.up->y, camera.up->z
|
||||
) :
|
||||
"";
|
||||
std::string yaw = camera.yaw.has_value() ?
|
||||
fmt::format("{}", *camera.yaw) :
|
||||
"";
|
||||
std::string pitch = camera.pitch.has_value() ?
|
||||
fmt::format("{}", *camera.pitch) :
|
||||
"";
|
||||
|
||||
return fmt::format(
|
||||
"{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\n",
|
||||
CameraNavState::Type,
|
||||
camera.anchor, camera.aim, camera.referenceFrame, camera.position,
|
||||
camera.up, camera.yaw, camera.pitch
|
||||
camera.anchor, camera.aim, camera.referenceFrame, position, up,
|
||||
yaw, pitch
|
||||
);
|
||||
},
|
||||
[](const Profile::CameraGoToGeo& camera) {
|
||||
@@ -771,15 +849,21 @@ std::string Profile::convertToScene() const {
|
||||
if (!camera.referenceFrame.empty()) {
|
||||
result += fmt::format("ReferenceFrame = {}, ", camera.referenceFrame);
|
||||
}
|
||||
result += fmt::format("Position = {{ {} }}, ", camera.position);
|
||||
if (!camera.up.empty()) {
|
||||
result += fmt::format("Up = {{ {} }}, ", camera.up);
|
||||
result += fmt::format(
|
||||
"Position = {{ {}, {}, {} }}, ",
|
||||
camera.position.x, camera.position.y, camera.position.z
|
||||
);
|
||||
if (camera.up.has_value()) {
|
||||
result += fmt::format(
|
||||
"Up = {{ {}, {}, {} }}, ",
|
||||
camera.up->x, camera.up->y, camera.up->z
|
||||
);
|
||||
}
|
||||
if (!camera.yaw.empty()) {
|
||||
result += fmt::format("Yaw = {}, ", camera.yaw);
|
||||
if (camera.yaw.has_value()) {
|
||||
result += fmt::format("Yaw = {}, ", *camera.yaw);
|
||||
}
|
||||
if (!camera.pitch.empty()) {
|
||||
result += fmt::format("Pitch = {} ", camera.pitch);
|
||||
if (camera.pitch.has_value()) {
|
||||
result += fmt::format("Pitch = {} ", *camera.pitch);
|
||||
}
|
||||
result += "})\n";
|
||||
return result;
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
12.13
|
||||
|
||||
#Camera
|
||||
setNavigationState "node" "root" 1.0, 2.0, 3.0 4.0, 5.0, 6.0
|
||||
setNavigationState "node" "root" 1.0, 2.0, 3.0 4.0, 5.0, 6.0 10.0 -10.0
|
||||
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
#Version
|
||||
12.13
|
||||
|
||||
#Camera
|
||||
setNavigationState "node" "root" 1.0, 2.0 4.0, 5.0, 6.0
|
||||
@@ -0,0 +1,5 @@
|
||||
#Version
|
||||
12.13
|
||||
|
||||
#Camera
|
||||
setNavigationState "node" "root" 1.0, 2.0, 3.0 4.0, 5.0
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
#Version
|
||||
12.13
|
||||
|
||||
#Camera
|
||||
setNavigationState "node" "root" 1.0, 2.0, 3.0, 4.0 4.0, 5.0, 6.0
|
||||
@@ -0,0 +1,5 @@
|
||||
#Version
|
||||
12.13
|
||||
|
||||
#Camera
|
||||
setNavigationState "node" "root" 1.0, 2.0, 3.0 4.0, 5.0, 6.0 def
|
||||
@@ -0,0 +1,5 @@
|
||||
#Version
|
||||
12.13
|
||||
|
||||
#Camera
|
||||
setNavigationState "node" "root" 1.0, 2.0, 3.0 4.0, 5.0, 6.0 abc
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
#Version
|
||||
12.13
|
||||
|
||||
#Camera
|
||||
setNavigationState "node" "root" 1.0, 2.0, abc 4.0, 5.0, 6.0
|
||||
@@ -0,0 +1,5 @@
|
||||
#Version
|
||||
12.13
|
||||
|
||||
#Camera
|
||||
setNavigationState "node" "root" 1.0, 2.0, 3.0 4.0, abc, 6.0
|
||||
+125
-20
@@ -23,26 +23,11 @@
|
||||
****************************************************************************************/
|
||||
|
||||
#include "catch2/catch.hpp"
|
||||
//#include "test_common.h"
|
||||
//#include <openspace/engine/configuration.h>
|
||||
//#include <openspace/engine/globals.h>
|
||||
//#include <openspace/engine/openspaceengine.h>
|
||||
//
|
||||
//#include <openspace/scene/assetloader.h>
|
||||
//#include <openspace/scene/asset.h>
|
||||
//#include "openspace/scene/profile.h"
|
||||
//#include <openspace/scene/scene.h>
|
||||
//#include <openspace/scene/scenegraphnode.h>
|
||||
//#include <openspace/scene/sceneinitializer.h>
|
||||
//#include <openspace/scripting/scriptengine.h>
|
||||
//#include <ghoul/misc/exception.h>
|
||||
//#include <ghoul/lua/lua_helper.h>
|
||||
//
|
||||
//#include <iostream>
|
||||
//#include <iomanip>
|
||||
//#include <memory>
|
||||
|
||||
|
||||
#include <openspace/interaction/navigationhandler.h>
|
||||
#include <openspace/properties/propertyowner.h>
|
||||
#include <openspace/properties/stringproperty.h>
|
||||
#include <openspace/properties/scalar/floatproperty.h>
|
||||
#include <openspace/scene/profile.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <filesystem>
|
||||
@@ -393,7 +378,6 @@ TEST_CASE("Removing non-exisiting asset", "[profile]") {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("Removing non-exisiting asset (ignored)", "[profile]") {
|
||||
std::vector<std::string> source = {
|
||||
"#Version",
|
||||
@@ -409,6 +393,55 @@ TEST_CASE("Removing non-exisiting asset (ignored)", "[profile]") {
|
||||
REQUIRE_NOTHROW(p.removeAsset("unknown-asset"));
|
||||
}
|
||||
|
||||
//
|
||||
// Save settings to profile
|
||||
//
|
||||
TEST_CASE("Save settings to profile", "[profile]") {
|
||||
properties::PropertyOwner owner({ "base" });
|
||||
properties::FloatProperty p1(properties::Property::PropertyInfo("p1", "a", "b"), 1.f);
|
||||
owner.addProperty(p1);
|
||||
properties::StringProperty p2(properties::Property::PropertyInfo("p2", "c", "d"));
|
||||
owner.addProperty(p2);
|
||||
|
||||
p1 = 2.f;
|
||||
p2 = "test-string";
|
||||
|
||||
interaction::NavigationHandler::NavigationState state;
|
||||
state.anchor = "anchor";
|
||||
state.aim = "aim";
|
||||
state.referenceFrame = "refFrame";
|
||||
state.position = glm::dvec3(1.0, 2.0, 3.0);
|
||||
state.up = glm::dvec3(4.0, 5.0, 6.0);
|
||||
state.yaw = -1.0;
|
||||
state.pitch = -2.0;
|
||||
|
||||
std::vector<std::string> baseSource = {
|
||||
"#Version",
|
||||
"1.0"
|
||||
};
|
||||
Profile p(baseSource);
|
||||
p.saveCurrentSettingsToProfile(owner, "current-time", state);
|
||||
std::string serialized = p.serialize();
|
||||
|
||||
std::vector<std::string> targetSource = baseSource;
|
||||
targetSource.push_back("");
|
||||
targetSource.push_back("#Property");
|
||||
targetSource.push_back("setPropertyValueSingle\tbase.p1\t2.000000");
|
||||
targetSource.push_back("setPropertyValueSingle\tbase.p2\t\"test-string\"");
|
||||
targetSource.push_back("");
|
||||
targetSource.push_back("#Camera");
|
||||
targetSource.push_back(
|
||||
"setNavigationState\tanchor\taim\trefFrame\t1.0, 2.0, 3.0\t4.0, 5.0, 6.0\t"
|
||||
"-1.0\t-2.0"
|
||||
);
|
||||
targetSource.push_back("");
|
||||
targetSource.push_back("#Time");
|
||||
targetSource.push_back("absolute\tcurrent-time");
|
||||
|
||||
std::string targetSerialized = Profile(targetSource).serialize();
|
||||
|
||||
REQUIRE(serialized == targetSerialized);
|
||||
}
|
||||
|
||||
//
|
||||
// Error states
|
||||
@@ -609,6 +642,78 @@ TEST_CASE("Error camera navigation state too many parameters", "[profile]") {
|
||||
);
|
||||
}
|
||||
|
||||
TEST_CASE("Error camera navigation state too few parameters in position", "[profile]") {
|
||||
constexpr const char* TestFile =
|
||||
"${TESTDIR}/profile/"
|
||||
"error_camera_navstate_wrong_parameter_too_few_components_position.profile";
|
||||
REQUIRE_THROWS_WITH(
|
||||
loadProfile(TestFile),
|
||||
Catch::Matchers::Contains("Expected 3 fields for the camera's position, got 2")
|
||||
);
|
||||
}
|
||||
|
||||
TEST_CASE("Error camera navigation state too many parameters in position", "[profile]") {
|
||||
constexpr const char* TestFile =
|
||||
"${TESTDIR}/profile/"
|
||||
"error_camera_navstate_wrong_parameter_too_many_components_position.profile";
|
||||
REQUIRE_THROWS_WITH(
|
||||
loadProfile(TestFile),
|
||||
Catch::Matchers::Contains("Expected 3 fields for the camera's position, got 4")
|
||||
);
|
||||
}
|
||||
|
||||
TEST_CASE("Error camera navigation state wrong parameter type position", "[profile]") {
|
||||
constexpr const char* TestFile =
|
||||
"${TESTDIR}/profile/"
|
||||
"error_camera_navstate_wrong_parameter_wrong_component_type_position.profile";
|
||||
REQUIRE_THROWS_WITH(
|
||||
loadProfile(TestFile),
|
||||
Catch::Matchers::Contains("Camera's position components must be numbers")
|
||||
);
|
||||
}
|
||||
|
||||
TEST_CASE("Error camera navigation state too few parameters in up vector", "[profile]") {
|
||||
constexpr const char* TestFile =
|
||||
"${TESTDIR}/profile/"
|
||||
"error_camera_navstate_wrong_parameter_too_few_components_up.profile";
|
||||
REQUIRE_THROWS_WITH(
|
||||
loadProfile(TestFile),
|
||||
Catch::Matchers::Contains(
|
||||
"Expected 0 or 3 fields for the camera's up vector, got 2"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
TEST_CASE("Error camera navigation state wrong parameter type up vector", "[profile]") {
|
||||
constexpr const char* TestFile =
|
||||
"${TESTDIR}/profile/"
|
||||
"error_camera_navstate_wrong_parameter_wrong_component_type_up.profile";
|
||||
REQUIRE_THROWS_WITH(
|
||||
loadProfile(TestFile),
|
||||
Catch::Matchers::Contains("Camera's up vector components must be numbers")
|
||||
);
|
||||
}
|
||||
|
||||
TEST_CASE("Error camera navigation state wrong parameter type up yaw", "[profile]") {
|
||||
constexpr const char* TestFile =
|
||||
"${TESTDIR}/profile/"
|
||||
"error_camera_navstate_wrong_parameter_type_yaw.profile";
|
||||
REQUIRE_THROWS_WITH(
|
||||
loadProfile(TestFile),
|
||||
Catch::Matchers::Contains("Camera's yaw value must be a number")
|
||||
);
|
||||
}
|
||||
|
||||
TEST_CASE("Error camera navigation state wrong parameter type up pitch", "[profile]") {
|
||||
constexpr const char* TestFile =
|
||||
"${TESTDIR}/profile/"
|
||||
"error_camera_navstate_wrong_parameter_type_pitch.profile";
|
||||
REQUIRE_THROWS_WITH(
|
||||
loadProfile(TestFile),
|
||||
Catch::Matchers::Contains("Camera's pitch value must be a number")
|
||||
);
|
||||
}
|
||||
|
||||
TEST_CASE("Error camera goToGeo too few parameters", "[profile]") {
|
||||
constexpr const char* TestFile =
|
||||
"${TESTDIR}/profile/error_camera_gotogeo_too_few_parameters.profile";
|
||||
|
||||
Reference in New Issue
Block a user