diff --git a/DeserializerApi.cpp b/DeserializerApi.cpp index f25a62b..c9494b7 100644 --- a/DeserializerApi.cpp +++ b/DeserializerApi.cpp @@ -1,5 +1,4 @@ #include "DeserializerApi.h" -#include "Settings.h" #include #include @@ -17,33 +16,33 @@ qualisys_cpp_sdk::DeserializerApi::DeserializerApi(const char* data) mPtr = mDocument->RootElement(); } -qualisys_cpp_sdk::DeserializerApi qualisys_cpp_sdk::DeserializerApi::FirstChildElement(const char* elementName) const +qualisys_cpp_sdk::DeserializerApi qualisys_cpp_sdk::DeserializerApi::FindChild(const char* elementName) const { return {mDocument, mPtr->FirstChildElement(elementName)}; } -qualisys_cpp_sdk::DeserializerApi qualisys_cpp_sdk::DeserializerApi::NextSiblingElement(const char* elementName) const +qualisys_cpp_sdk::DeserializerApi qualisys_cpp_sdk::DeserializerApi::FindNextSibling(const char* elementName) const { return {mDocument, mPtr->NextSiblingElement(elementName)}; } -double qualisys_cpp_sdk::DeserializerApi::DoubleAttribute(const char* attributeName, double defaultValue) const +double qualisys_cpp_sdk::DeserializerApi::ReadAttributeDouble(const char* attributeName, double defaultValue) const { return mPtr->DoubleAttribute(attributeName, defaultValue); } -std::uint32_t qualisys_cpp_sdk::DeserializerApi::UnsignedAttribute(const char* attributeName, +std::uint32_t qualisys_cpp_sdk::DeserializerApi::ReadAttributeUnsignedInt(const char* attributeName, std::uint32_t defaultValue) const { return mPtr->UnsignedAttribute(attributeName, defaultValue); } -std::int32_t qualisys_cpp_sdk::DeserializerApi::IntAttribute(const char* attributeName, std::int32_t defaultValue) const +std::int32_t qualisys_cpp_sdk::DeserializerApi::ReadAttributeInt(const char* attributeName, std::int32_t defaultValue) const { return mPtr->IntAttribute(attributeName, defaultValue); } -bool qualisys_cpp_sdk::DeserializerApi::BoolAttribute(const char* attributeName, bool defaultValue) const +bool qualisys_cpp_sdk::DeserializerApi::ReadAttributeBool(const char* attributeName, bool defaultValue) const { return mPtr->BoolAttribute(attributeName, defaultValue); } @@ -63,22 +62,22 @@ qualisys_cpp_sdk::DeserializerApi::operator bool() const return mPtr != nullptr; } -int qualisys_cpp_sdk::DeserializerApi::IntText(std::int32_t defaultValue) const +int qualisys_cpp_sdk::DeserializerApi::ReadInt(std::int32_t defaultValue) const { return mPtr->IntText(defaultValue); } -unsigned int qualisys_cpp_sdk::DeserializerApi::UnsignedText(std::int32_t defaultValue) const +unsigned int qualisys_cpp_sdk::DeserializerApi::ReadUnsignedInt(std::int32_t defaultValue) const { return mPtr->UnsignedText(defaultValue); } -float qualisys_cpp_sdk::DeserializerApi::FloatText(float defaultValue) const +float qualisys_cpp_sdk::DeserializerApi::ReadFloat(float defaultValue) const { return mPtr->FloatText(defaultValue); } -std::string qualisys_cpp_sdk::DeserializerApi::Attribute(const char* name) const +std::string qualisys_cpp_sdk::DeserializerApi::ReadAttributeString(const char* name) const { if (auto charPtr = mPtr->Attribute(name)) { @@ -88,12 +87,12 @@ std::string qualisys_cpp_sdk::DeserializerApi::Attribute(const char* name) const return {}; } -float qualisys_cpp_sdk::DeserializerApi::FloatAttribute(const char* name, float defaultValue) const +float qualisys_cpp_sdk::DeserializerApi::ReadAttributeFloat(const char* name, float defaultValue) const { return mPtr->FloatAttribute(name, defaultValue); } -std::string qualisys_cpp_sdk::DeserializerApi::GetText() const +std::string qualisys_cpp_sdk::DeserializerApi::ReadString() const { if (auto charPtr = mPtr->GetText()) { @@ -106,41 +105,36 @@ std::string qualisys_cpp_sdk::DeserializerApi::GetText() const /// /// ChildElementRange /// -qualisys_cpp_sdk::ChildElementRange::ChildElementRange(DeserializerApi& parent, const char* elementName) : parent(parent), - elementNameGenerator([elementName](auto& buff, std::size_t, std::size_t) { return elementName; }) +qualisys_cpp_sdk::ChildElementRange::ChildElementRange(DeserializerApi& parent, const char* elementName) + : mParent(parent), mElementName(elementName) { } -qualisys_cpp_sdk::ChildElementRange::ChildElementRange(DeserializerApi& parent, TElementNameGenerator generator) : - parent(parent), elementNameGenerator(std::move(generator)) +qualisys_cpp_sdk::ChildElementRange::Iterator::Iterator(const ChildElementRange& range) : mCurrent(nullptr), + mChildElementRange(range) { } -qualisys_cpp_sdk::ChildElementRange::Iterator::Iterator(const ChildElementRange& range) : buffer{}, current(nullptr), - range(range), index(std::numeric_limits::max()) +qualisys_cpp_sdk::ChildElementRange::Iterator::Iterator(const ChildElementRange& range, std::size_t index) + : mCurrent(nullptr), mChildElementRange(range) { -} - -qualisys_cpp_sdk::ChildElementRange::Iterator::Iterator(const ChildElementRange& range, std::size_t index) : - buffer{}, current(nullptr), range(range), index(index) -{ - current = range.parent.FirstChildElement(range.elementNameGenerator(buffer, buffSize, index++)); + mCurrent = range.mParent.FindChild(mChildElementRange.mElementName); } qualisys_cpp_sdk::DeserializerApi qualisys_cpp_sdk::ChildElementRange::Iterator::operator*() const { - return current; + return mCurrent; } qualisys_cpp_sdk::ChildElementRange::Iterator& qualisys_cpp_sdk::ChildElementRange::Iterator::operator++() { - current = current.NextSiblingElement(range.elementNameGenerator(buffer, buffSize, index++)); + mCurrent = mCurrent.FindNextSibling(mChildElementRange.mElementName); return *this; } bool qualisys_cpp_sdk::ChildElementRange::Iterator::operator!=(const Iterator& other) const { - return current != other.current; + return mCurrent != other.mCurrent; } qualisys_cpp_sdk::ChildElementRange::Iterator qualisys_cpp_sdk::ChildElementRange::begin() const @@ -153,22 +147,9 @@ qualisys_cpp_sdk::ChildElementRange::Iterator qualisys_cpp_sdk::ChildElementRang return Iterator(*this); } - -/// -/// Helper functions -/// -std::string qualisys_cpp_sdk::ToLowerXmlString(std::string str) -{ - std::transform(str.begin(), str.end(), str.begin(), [](unsigned char c) - { - return static_cast(std::tolower(c)); - }); - return str; -} - -bool qualisys_cpp_sdk::TryReadElementDouble(DeserializerApi& element, const char* elementName, double& output) +bool qualisys_cpp_sdk::DeserializerApi::TryReadElementDouble(const char* elementName, double& output) const { - if (auto childElem = element.FirstChildElement(elementName)) + if (auto childElem = FindChild(elementName)) { return childElem.mPtr->QueryDoubleText(&output) == tinyxml2::XML_SUCCESS; } @@ -176,9 +157,9 @@ bool qualisys_cpp_sdk::TryReadElementDouble(DeserializerApi& element, const char return false; } -bool qualisys_cpp_sdk::TryReadElementFloat(DeserializerApi& element, const char* elementName, float& output) +bool qualisys_cpp_sdk::DeserializerApi::TryReadElementFloat(const char* elementName, float& output) const { - if (auto childElem = element.FirstChildElement(elementName)) + if (auto childElem = FindChild(elementName)) { return childElem.mPtr->QueryFloatText(&output) == tinyxml2::XML_SUCCESS; } @@ -186,10 +167,10 @@ bool qualisys_cpp_sdk::TryReadElementFloat(DeserializerApi& element, const char* return false; } -bool qualisys_cpp_sdk::TryReadElementUnsignedInt32(DeserializerApi& element, const char* elementName, - std::uint32_t& output) +bool qualisys_cpp_sdk::DeserializerApi::TryReadElementUnsignedInt32(const char* elementName, + std::uint32_t& output) const { - if (auto childElem = element.FirstChildElement(elementName)) + if (auto childElem = FindChild(elementName)) { return childElem.mPtr->QueryUnsignedText(&output) == tinyxml2::XML_SUCCESS; } @@ -197,11 +178,11 @@ bool qualisys_cpp_sdk::TryReadElementUnsignedInt32(DeserializerApi& element, con return false; } -bool qualisys_cpp_sdk::TryReadElementString(DeserializerApi& element, const char* elementName, std::string& output) +bool qualisys_cpp_sdk::DeserializerApi::TryReadElementString(const char* elementName, std::string& output) const { output.clear(); - if (auto childElem = element.FirstChildElement(elementName)) + if (auto childElem = FindChild(elementName)) { if (auto charPtr = childElem.mPtr->GetText()) { @@ -228,9 +209,9 @@ namespace } } -bool qualisys_cpp_sdk::ReadXmlBool(DeserializerApi xml, const std::string& element, bool& value) +bool qualisys_cpp_sdk::DeserializerApi::TryReadElementBool(const std::string& element, bool& value) const { - auto xmlElem = xml.FirstChildElement(element.c_str()); + auto xmlElem = FindChild(element.c_str()); if (!xmlElem) { return false; @@ -257,33 +238,15 @@ bool qualisys_cpp_sdk::ReadXmlBool(DeserializerApi xml, const std::string& eleme return true; } -qualisys_cpp_sdk::SPosition qualisys_cpp_sdk::ReadSPosition(DeserializerApi& parentElem, const std::string& element) -{ - auto positionElem = parentElem.FirstChildElement(element.data()); - if (positionElem) - { - return { - positionElem.DoubleAttribute("X"), - positionElem.DoubleAttribute("Y"), - positionElem.DoubleAttribute("Z"), - }; - } - - return {}; -} - -qualisys_cpp_sdk::SRotation qualisys_cpp_sdk::ReadSRotation(DeserializerApi& parentElem, const std::string& element) +/// +/// Helper functions +/// +/// names +std::string qualisys_cpp_sdk::ToLowerXmlString(std::string& str) { - auto rotationElem = parentElem.FirstChildElement(element.data()); - if (rotationElem) - { - return { - rotationElem.DoubleAttribute("X"), - rotationElem.DoubleAttribute("Y"), - rotationElem.DoubleAttribute("Z"), - rotationElem.DoubleAttribute("W") - }; - } - - return {}; + std::transform(str.begin(), str.end(), str.begin(), [](unsigned char c) + { + return static_cast(std::tolower(c)); + }); + return str; } diff --git a/DeserializerApi.h b/DeserializerApi.h index 8195cd7..5548352 100644 --- a/DeserializerApi.h +++ b/DeserializerApi.h @@ -12,9 +12,6 @@ namespace tinyxml2 namespace qualisys_cpp_sdk { - struct SPosition; - struct SRotation; - struct DeserializerApi { private: @@ -24,45 +21,46 @@ namespace qualisys_cpp_sdk public: tinyxml2::XMLElement* mPtr; DeserializerApi(const char* data); - DeserializerApi FirstChildElement(const char* elementName) const; - DeserializerApi NextSiblingElement(const char* elementName) const; - double DoubleAttribute(const char* attributeName, double defaultValue = 0) const; - std::uint32_t UnsignedAttribute(const char* attributeName, std::uint32_t defaultValue = 0) const; - std::int32_t IntAttribute(const char* attributeName, std::int32_t defaultValue = 0) const; - bool BoolAttribute(const char* attributeName, bool defaultValue = 0) const; + + DeserializerApi FindChild(const char* elementName) const; + DeserializerApi FindNextSibling(const char* elementName) const; + + bool TryReadElementDouble(const char* elementName, double& output) const; + bool TryReadElementFloat(const char* elementName, float& output) const; + bool TryReadElementUnsignedInt32(const char* elementName, std::uint32_t& output) const ; + bool TryReadElementString(const char* elementName, std::string& output) const; + bool TryReadElementBool(const std::string& element, bool& value) const; + + double ReadAttributeDouble(const char* attributeName, double defaultValue = 0) const; + std::uint32_t ReadAttributeUnsignedInt(const char* attributeName, std::uint32_t defaultValue = 0) const; + std::int32_t ReadAttributeInt(const char* attributeName, std::int32_t defaultValue = 0) const; + std::string ReadAttributeString(const char* name) const; + float ReadAttributeFloat(const char* name, float defaultValue = .0f) const; + bool ReadAttributeBool(const char* attributeName, bool defaultValue = 0) const; + + std::string ReadString() const; + int ReadInt(std::int32_t defaultValue = 0) const; + unsigned int ReadUnsignedInt(std::int32_t defaultValue = 0) const; + float ReadFloat(float defaultValue = .0f) const; + bool operator==(const DeserializerApi& other) const; bool operator!=(const DeserializerApi& other) const; explicit operator bool() const; - int IntText(std::int32_t defaultValue = 0) const; - unsigned int UnsignedText(std::int32_t defaultValue = 0) const; - float FloatText(float defaultValue = .0f) const; - std::string Attribute(const char* name) const; - float FloatAttribute(const char* name, float defaultValue = .0f) const; - std::string GetText() const; }; struct ChildElementRange { - static constexpr std::size_t buffSize = 128; - using TElementNameGenerator = std::function; - private: - DeserializerApi& parent; - TElementNameGenerator elementNameGenerator; - + DeserializerApi& mParent; + const char* mElementName; public: ChildElementRange() = delete; ChildElementRange(DeserializerApi& parent, const char* elementName); - ChildElementRange(DeserializerApi& parent, - TElementNameGenerator generator); struct Iterator { - char buffer[buffSize]; - DeserializerApi current; - const ChildElementRange& range; - std::size_t index; + DeserializerApi mCurrent; + const ChildElementRange& mChildElementRange; explicit Iterator(const ChildElementRange& range); Iterator(const ChildElementRange& range, std::size_t index); DeserializerApi operator*() const; @@ -74,12 +72,5 @@ namespace qualisys_cpp_sdk Iterator end() const; }; - std::string ToLowerXmlString(std::string str); - bool TryReadElementDouble(DeserializerApi& element, const char* elementName, double& output); - bool TryReadElementFloat(DeserializerApi& element, const char* elementName, float& output); - bool TryReadElementUnsignedInt32(DeserializerApi& element, const char* elementName, std::uint32_t& output); - bool TryReadElementString(DeserializerApi& element, const char* elementName, std::string& output); - bool ReadXmlBool(DeserializerApi xml, const std::string& element, bool& value); - SPosition ReadSPosition(DeserializerApi& parentElem, const std::string& element); - SRotation ReadSRotation(DeserializerApi& parentElem, const std::string& element); + std::string ToLowerXmlString(std::string& str); } diff --git a/RTProtocol.cpp b/RTProtocol.cpp index bd47c83..8a6258b 100644 --- a/RTProtocol.cpp +++ b/RTProtocol.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include "Network.h" #include "SettingsDeserializer.h" @@ -683,7 +684,9 @@ bool CRTProtocol::GetCapture(const char* pFileName, bool bC3D) } else { - sprintf(mErrorStr, "No packet received. %s.", mErrorStr); + char tmp[sizeof(mErrorStr)]; + std::memcpy(tmp, mErrorStr, sizeof(mErrorStr)); + (void)snprintf(mErrorStr, sizeof(mErrorStr), "No packet received. %s.", tmp); } } else diff --git a/SerializerApi.cpp b/SerializerApi.cpp index 2dbafb4..9ec3786 100644 --- a/SerializerApi.cpp +++ b/SerializerApi.cpp @@ -5,973 +5,109 @@ using namespace qualisys_cpp_sdk; -SerializerApi::SerializerApi(std::uint32_t majorVersion, std::uint32_t minorVersion) - : mMajorVersion(majorVersion), mMinorVersion(minorVersion) -{ -} - -void SerializerApi::AddXMLElementBool(tinyxml2::XMLElement& parentElem, const char* elementName, const bool* value, tinyxml2::XMLDocument& document, const char* trueText, const char* falseText) -{ - if (value) - { - tinyxml2::XMLElement* elem = document.NewElement(elementName); - elem->SetText(*value ? trueText : falseText); - parentElem.InsertEndChild(elem); - } -} - -void SerializerApi::AddXMLElementBool(tinyxml2::XMLElement& parentElem, const char* elementName, const bool value, tinyxml2::XMLDocument& document, const char* trueText, const char* falseText) -{ - tinyxml2::XMLElement* elem = document.NewElement(elementName); - elem->SetText(value ? trueText : falseText); - parentElem.InsertEndChild(elem); -} - -void SerializerApi::AddXMLElementInt(tinyxml2::XMLElement& parentElem, const char* elementName, const int* value, tinyxml2::XMLDocument& document) -{ - if (value) - { - tinyxml2::XMLElement* elem = document.NewElement(elementName); - elem->SetText(*value); - parentElem.InsertEndChild(elem); - } -} - -void SerializerApi::AddXMLElementUnsignedInt(tinyxml2::XMLElement& parentElem, const char* elementName, const unsigned int value, tinyxml2::XMLDocument& document) +SerializerApi::SerializerApi(const SerializerApi& src, tinyxml2::XMLElement* element): mDocument(src.mDocument), mCurrentElement(element), mMajorVersion(src.mMajorVersion), mMinorVersion(src.mMinorVersion) { - tinyxml2::XMLElement* elem = document.NewElement(elementName); - elem->SetText(value); - parentElem.InsertEndChild(elem); } -void SerializerApi::AddXMLElementUnsignedInt(tinyxml2::XMLElement& parentElem, const char* elementName, const unsigned int* value, tinyxml2::XMLDocument& document) +SerializerApi SerializerApi::Element(const char* name) { - if (value) + if (mCurrentElement) { - AddXMLElementUnsignedInt(parentElem, elementName, *value, document); + return SerializerApi{ *this, mCurrentElement->InsertNewChildElement(name) }; } -} - -void SerializerApi::AddXMLElementFloat(tinyxml2::XMLElement& parentElem, const char* elementName, const float* value, unsigned int decimals, tinyxml2::XMLDocument& document) -{ - char formattedValue[32]; - snprintf(formattedValue, sizeof(formattedValue), "%.*f", decimals, *value); - - tinyxml2::XMLElement* elem = document.NewElement(elementName); - elem->SetText(formattedValue); - parentElem.InsertEndChild(elem); -} - -void SerializerApi::AddXMLElementFloatWithTextAttribute(tinyxml2::XMLDocument& document, tinyxml2::XMLElement& parentElem, const char* elementName, const char* attributeName, const float& value, unsigned int decimals) -{ - char formattedValue[32]; - snprintf(formattedValue, sizeof(formattedValue), "%.*f", decimals, value); - tinyxml2::XMLElement* elem = document.NewElement(elementName); - elem->SetAttribute(attributeName, formattedValue); - parentElem.InsertEndChild(elem); + auto newElement = mDocument->NewElement(name); + mDocument->InsertFirstChild(newElement); + return SerializerApi{ *this, newElement}; } -void SerializerApi::AddXMLElementTransform(tinyxml2::XMLDocument& document, tinyxml2::XMLElement& parentElem, const std::string& name, const SPosition& position, const SRotation& rotation) +SerializerApi SerializerApi::ElementBool(const char* name, bool value) { - tinyxml2::XMLElement* transformElem = document.NewElement(name.c_str()); - parentElem.InsertEndChild(transformElem); - - tinyxml2::XMLElement* positionElem = document.NewElement("Position"); - positionElem->SetAttribute("X", std::to_string(position.x).c_str()); - positionElem->SetAttribute("Y", std::to_string(position.y).c_str()); - positionElem->SetAttribute("Z", std::to_string(position.z).c_str()); - transformElem->InsertEndChild(positionElem); - - tinyxml2::XMLElement* rotationElem = document.NewElement("Rotation"); - rotationElem->SetAttribute("X", std::to_string(rotation.x).c_str()); - rotationElem->SetAttribute("Y", std::to_string(rotation.y).c_str()); - rotationElem->SetAttribute("Z", std::to_string(rotation.z).c_str()); - rotationElem->SetAttribute("W", std::to_string(rotation.w).c_str()); - transformElem->InsertEndChild(rotationElem); + auto newElement = Element(name); + newElement.mCurrentElement->SetText(value); + return SerializerApi{ *this, newElement.mCurrentElement }; } -void SerializerApi::AddXMLElementDOF(tinyxml2::XMLDocument& document, tinyxml2::XMLElement& parentElem, const std::string& name, const SDegreeOfFreedom& degreesOfFreedom) +SerializerApi SerializerApi::ElementInt(const char* name, std::int32_t value) { - tinyxml2::XMLElement* dofElem = document.NewElement(name.c_str()); - parentElem.InsertEndChild(dofElem); - - if (!std::isnan(degreesOfFreedom.lowerBound) && !std::isnan(degreesOfFreedom.upperBound)) - { - if (mMajorVersion > 1 || mMinorVersion > 21) - { - tinyxml2::XMLElement* constraintElem = document.NewElement("Constraint"); - constraintElem->SetAttribute("LowerBound", std::to_string(degreesOfFreedom.lowerBound).c_str()); - constraintElem->SetAttribute("UpperBound", std::to_string(degreesOfFreedom.upperBound).c_str()); - dofElem->InsertEndChild(constraintElem); - } - else - { - // If not in a 'Constraint' block, add 'LowerBound' & 'UpperBound' directly to dofElem - dofElem->SetAttribute("LowerBound", std::to_string(degreesOfFreedom.lowerBound).c_str()); - dofElem->SetAttribute("UpperBound", std::to_string(degreesOfFreedom.upperBound).c_str()); - } - } - - if (!degreesOfFreedom.couplings.empty()) - { - tinyxml2::XMLElement* couplingsElem = document.NewElement("Couplings"); - dofElem->InsertEndChild(couplingsElem); - - for (const auto& coupling : degreesOfFreedom.couplings) - { - tinyxml2::XMLElement* couplingElem = document.NewElement("Coupling"); - couplingElem->SetAttribute("Segment", coupling.segment.c_str()); - couplingElem->SetAttribute("DegreeOfFreedom", SkeletonDofToStringSettings(coupling.degreeOfFreedom)); - couplingElem->SetAttribute("Coefficient", std::to_string(coupling.coefficient).c_str()); - couplingsElem->InsertEndChild(couplingElem); - } - } - - if (!std::isnan(degreesOfFreedom.goalValue) && !std::isnan(degreesOfFreedom.goalWeight)) - { - tinyxml2::XMLElement* goalElem = document.NewElement("Goal"); - goalElem->SetAttribute("Value", std::to_string(degreesOfFreedom.goalValue).c_str()); - goalElem->SetAttribute("Weight", std::to_string(degreesOfFreedom.goalWeight).c_str()); - dofElem->InsertEndChild(goalElem); - } -} - -std::string SerializerApi::SetGeneralSettings(const unsigned int* captureFrequency, - const float* captureTime, const bool* startOnExtTrig, - const bool* startOnTrigNO, const bool* startOnTrigNC, - const bool* startOnTrigSoftware, const EProcessingActions* processingActions, - const EProcessingActions* rtProcessingActions, const EProcessingActions* reprocessingActions) -{ - tinyxml2::XMLDocument document; - - tinyxml2::XMLElement* rootElem = document.NewElement("QTM_Settings"); - document.InsertFirstChild(rootElem); - - tinyxml2::XMLElement* generalElem = document.NewElement("General"); - rootElem->InsertEndChild(generalElem); - - if (captureFrequency) - { - AddXMLElementUnsignedInt(*generalElem, "Frequency", captureFrequency, document); - } - - if (captureTime) - { - AddXMLElementFloat(*generalElem, "Capture_Time", captureTime, 3, document); - } - - // External Trigger and additional triggers - if (startOnExtTrig) - { - AddXMLElementBool(*generalElem, "Start_On_External_Trigger", startOnExtTrig, document); - - if (mMajorVersion > 1 || mMinorVersion > 14) - { - AddXMLElementBool(*generalElem, "Start_On_Trigger_NO", startOnTrigNO, document); - AddXMLElementBool(*generalElem, "Start_On_Trigger_NC", startOnTrigNC, document); - AddXMLElementBool(*generalElem, "Start_On_Trigger_Software", startOnTrigSoftware, document); - } - } - - const char* processingActionTags[3] = { "Processing_Actions", "RealTime_Processing_Actions", "Reprocessing_Actions" }; - const EProcessingActions* processingActionSets[3] = { processingActions, rtProcessingActions, reprocessingActions }; - - auto actionsCount = (mMajorVersion > 1 || mMinorVersion > 13) ? 3 : 1; - - for (auto i = 0; i < actionsCount; i++) - { - if (processingActionSets[i]) - { - tinyxml2::XMLElement* processing = document.NewElement(processingActionTags[i]); - generalElem->InsertEndChild(processing); - - if (mMajorVersion > 1 || mMinorVersion > 13) - { - AddXMLElementBool(*processing, "PreProcessing2D", (*processingActionSets[i] & ProcessingPreProcess2D) != 0, document); - } - - if (*processingActionSets[i] & ProcessingTracking2D && i != 1) // i != 1 => Not RtProcessingSettings - { - tinyxml2::XMLElement* trackingElem = document.NewElement("Tracking"); - trackingElem->SetText("2D"); - processing->InsertEndChild(trackingElem); - } - else if (*processingActionSets[i] & ProcessingTracking3D) - { - tinyxml2::XMLElement* trackingElem = document.NewElement("Tracking"); - trackingElem->SetText("3D"); - processing->InsertEndChild(trackingElem); - } - else - { - tinyxml2::XMLElement* trackingElem = document.NewElement("Tracking"); - trackingElem->SetText("False"); - processing->InsertEndChild(trackingElem); - } - - if (i != 1) // Not RtProcessingSettings - { - AddXMLElementBool(*processing, "TwinSystemMerge", (*processingActionSets[i] & ProcessingTwinSystemMerge) != 0, document); - AddXMLElementBool(*processing, "SplineFill", (*processingActionSets[i] & ProcessingSplineFill) != 0, document); - } - - AddXMLElementBool(*processing, "AIM", (*processingActionSets[i] & ProcessingAIM) != 0, document); - AddXMLElementBool(*processing, "Track6DOF", (*processingActionSets[i] & Processing6DOFTracking) != 0, document); - AddXMLElementBool(*processing, "ForceData", (*processingActionSets[i] & ProcessingForceData) != 0, document); - AddXMLElementBool(*processing, "GazeVector", (*processingActionSets[i] & ProcessingGazeVector) != 0, document); - - if (i != 1) // Not RtProcessingSettings - { - AddXMLElementBool(*processing, "ExportTSV", (*processingActionSets[i] & ProcessingExportTSV) != 0, document); - AddXMLElementBool(*processing, "ExportC3D", (*processingActionSets[i] & ProcessingExportC3D) != 0, document); - AddXMLElementBool(*processing, "ExportMatlabFile", (*processingActionSets[i] & ProcessingExportMatlabFile) != 0, document); - AddXMLElementBool(*processing, "ExportAviFile", (*processingActionSets[i] & ProcessingExportAviFile) != 0, document); - } - } - } - - tinyxml2::XMLPrinter printer; - document.Print(&printer); - return printer.CStr(); + auto newElement = Element(name); + newElement.mCurrentElement->SetText(value); + return SerializerApi{ *this, newElement.mCurrentElement }; } -std::string SerializerApi::SetExtTimeBaseSettings(const bool* enabled, const ESignalSource* signalSource, const bool* signalModePeriodic, - const unsigned int* freqMultiplier, const unsigned int* freqDivisor, const unsigned int* freqTolerance, - const float* nominalFrequency, const bool* negativeEdge, const unsigned int* signalShutterDelay, const float* nonPeriodicTimeout) +SerializerApi SerializerApi::ElementFloat(const char* name, float value) { - tinyxml2::XMLDocument document; - - tinyxml2::XMLElement* rootElem = document.NewElement("QTM_Settings"); - document.InsertFirstChild(rootElem); - - tinyxml2::XMLElement* generalElem = document.NewElement("General"); - rootElem->InsertEndChild(generalElem); - - tinyxml2::XMLElement* timeBaseElem = document.NewElement("External_Time_Base"); - generalElem->InsertEndChild(timeBaseElem); - - AddXMLElementBool(*timeBaseElem, "Enabled", enabled, document); - - if (signalSource) - { - tinyxml2::XMLElement* signalSourceElem = document.NewElement("Signal_Source"); - switch (*signalSource) - { - case SourceControlPort: - signalSourceElem->SetText("Control port"); - break; - case SourceIRReceiver: - signalSourceElem->SetText("IR receiver"); - break; - case SourceSMPTE: - signalSourceElem->SetText("SMPTE"); - break; - case SourceVideoSync: - signalSourceElem->SetText("Video sync"); - break; - case SourceIRIG: - signalSourceElem->SetText("IRIG"); - break; - } - timeBaseElem->InsertEndChild(signalSourceElem); - } - - AddXMLElementBool(*timeBaseElem, "Signal_Mode", signalModePeriodic, document, "Periodic", "Non-periodic"); - AddXMLElementUnsignedInt(*timeBaseElem, "Frequency_Multiplier", freqMultiplier, document); - AddXMLElementUnsignedInt(*timeBaseElem, "Frequency_Divisor", freqDivisor, document); - AddXMLElementUnsignedInt(*timeBaseElem, "Frequency_Tolerance", freqTolerance, document); - - if (nominalFrequency) - { - if (*nominalFrequency < 0) - { - tinyxml2::XMLElement* nominalFreqElem = document.NewElement("Nominal_Frequency"); - nominalFreqElem->SetText("None"); - timeBaseElem->InsertEndChild(nominalFreqElem); - } - else - { - AddXMLElementFloat(*timeBaseElem, "Nominal_Frequency", nominalFrequency, 3, document); - } - } - - AddXMLElementBool(*timeBaseElem, "Signal_Edge", negativeEdge, document, "Negative", "Positive"); - AddXMLElementUnsignedInt(*timeBaseElem, "Signal_Shutter_Delay", signalShutterDelay, document); - AddXMLElementFloat(*timeBaseElem, "Non_Periodic_Timeout", nonPeriodicTimeout, 3, document); - - tinyxml2::XMLPrinter printer; - document.Print(&printer); - return printer.CStr(); + auto newElement = Element(name); + newElement.mCurrentElement->SetText(std::to_string(value).c_str()); + return SerializerApi{ *this, newElement.mCurrentElement }; } -std::string SerializerApi::SetExtTimestampSettings(const SSettingsGeneralExternalTimestamp& timestampSettings) +SerializerApi SerializerApi::ElementDouble(const char* name, double value) { - tinyxml2::XMLDocument document; - - tinyxml2::XMLElement* rootElem = document.NewElement("QTM_Settings"); - document.InsertFirstChild(rootElem); - - tinyxml2::XMLElement* generalElem = document.NewElement("General"); - rootElem->InsertEndChild(generalElem); - - tinyxml2::XMLElement* timeStampElem = document.NewElement("External_Timestamp"); - generalElem->InsertEndChild(timeStampElem); - - AddXMLElementBool(*timeStampElem, "Enabled", timestampSettings.bEnabled, document); - - tinyxml2::XMLElement* typeElem = document.NewElement("Type"); - switch (timestampSettings.nType) - { - case ETimestampType::Timestamp_SMPTE: - typeElem->SetText("SMPTE"); - break; - case ETimestampType::Timestamp_IRIG: - typeElem->SetText("IRIG"); - break; - case ETimestampType::Timestamp_CameraTime: - typeElem->SetText("CameraTime"); - break; - default: - break; - } - timeStampElem->InsertEndChild(typeElem); - - AddXMLElementUnsignedInt(*timeStampElem, "Frequency", timestampSettings.nFrequency, document); - - tinyxml2::XMLPrinter printer; - document.Print(&printer); - return printer.CStr(); + auto newElement = Element(name); + newElement.mCurrentElement->SetText(std::to_string(value).c_str()); + return SerializerApi{ *this, newElement.mCurrentElement }; } -std::string SerializerApi::SetCameraSettings( - const unsigned int cameraId, const ECameraMode* mode, - const float* markerExposure, const float* markerThreshold, - const int* orientation) +SerializerApi SerializerApi::ElementUnsignedInt(const char* name, std::uint32_t value) { - tinyxml2::XMLDocument document; - - tinyxml2::XMLElement* rootElem = document.NewElement("QTM_Settings"); - document.InsertFirstChild(rootElem); - - tinyxml2::XMLElement* generalElem = document.NewElement("General"); - rootElem->InsertEndChild(generalElem); - - tinyxml2::XMLElement* cameraElem = document.NewElement("Camera"); - generalElem->InsertEndChild(cameraElem); - - AddXMLElementUnsignedInt(*cameraElem, "ID", &cameraId, document); - - if (mode) - { - tinyxml2::XMLElement* modeElem = document.NewElement("Mode"); - switch (*mode) - { - case ModeMarker: - modeElem->SetText("Marker"); - break; - case ModeMarkerIntensity: - modeElem->SetText("Marker Intensity"); - break; - case ModeVideo: - modeElem->SetText("Video"); - break; - } - cameraElem->InsertEndChild(modeElem); - } - - AddXMLElementFloat(*cameraElem, "Marker_Exposure", markerExposure, 6, document); - AddXMLElementFloat(*cameraElem, "Marker_Threshold", markerThreshold, 6, document); - AddXMLElementInt(*cameraElem, "Orientation", orientation, document); - - tinyxml2::XMLPrinter printer; - document.Print(&printer); - return printer.CStr(); + auto newElement = Element(name); + newElement.mCurrentElement->SetText(value); + return SerializerApi{ *this, newElement.mCurrentElement }; } -std::string SerializerApi::SetCameraVideoSettings(const unsigned int cameraId, const EVideoResolution* videoResolution, - const EVideoAspectRatio* videoAspectRatio, const unsigned int* videoFrequency, const float* videoExposure, const float* videoFlashTime) +SerializerApi SerializerApi::ElementString(const char* name, const char* value) { - tinyxml2::XMLDocument document; - - tinyxml2::XMLElement* rootElem = document.NewElement("QTM_Settings"); - document.InsertFirstChild(rootElem); - - tinyxml2::XMLElement* generalElem = document.NewElement("General"); - rootElem->InsertEndChild(generalElem); - - tinyxml2::XMLElement* cameraElem = document.NewElement("Camera"); - generalElem->InsertEndChild(cameraElem); - - AddXMLElementUnsignedInt(*cameraElem, "ID", &cameraId, document); - - if (videoResolution) - { - tinyxml2::XMLElement* resolutionElem = document.NewElement("Video_Resolution"); - switch (*videoResolution) - { - case VideoResolution1440p: - resolutionElem->SetText("1440p"); - break; - case VideoResolution1080p: - resolutionElem->SetText("1080p"); - break; - case VideoResolution720p: - resolutionElem->SetText("720p"); - break; - case VideoResolution540p: - resolutionElem->SetText("540p"); - break; - case VideoResolution480p: - resolutionElem->SetText("480p"); - break; - case VideoResolutionNone: - break; - } - cameraElem->InsertEndChild(resolutionElem); - } - - if (videoAspectRatio) - { - tinyxml2::XMLElement* videoAspectRatioElem = document.NewElement("Video_Aspect_Ratio"); - switch (*videoAspectRatio) - { - case VideoAspectRatio16x9: - videoAspectRatioElem->SetText("16x9"); - break; - case VideoAspectRatio4x3: - videoAspectRatioElem->SetText("4x3"); - break; - case VideoAspectRatio1x1: - videoAspectRatioElem->SetText("1x1"); - break; - case VideoAspectRatioNone: - break; - } - cameraElem->InsertEndChild(videoAspectRatioElem); - } - - AddXMLElementUnsignedInt(*cameraElem, "Video_Frequency", videoFrequency, document); - AddXMLElementFloat(*cameraElem, "Video_Exposure", videoExposure, 6, document); - AddXMLElementFloat(*cameraElem, "Video_Flash_Time", videoFlashTime, 6, document); - - tinyxml2::XMLPrinter printer; - document.Print(&printer); - return printer.CStr(); + auto newElement = Element(name); + newElement.mCurrentElement->SetText(value); + return SerializerApi{ *this, newElement.mCurrentElement }; } -std::string SerializerApi::SetCameraSyncOutSettings(const unsigned int cameraId, const unsigned int portNumber, - const ESyncOutFreqMode* syncOutMode, const unsigned int* syncOutValue, const float* syncOutDutyCycle, - const bool* syncOutNegativePolarity) +SerializerApi SerializerApi::AttributeBool(const char* name, bool value) { - tinyxml2::XMLDocument document; - - tinyxml2::XMLElement* rootElem = document.NewElement("QTM_Settings"); - document.InsertFirstChild(rootElem); - - tinyxml2::XMLElement* generalElem = document.NewElement("General"); - rootElem->InsertEndChild(generalElem); - - tinyxml2::XMLElement* cameraElem = document.NewElement("Camera"); - generalElem->InsertEndChild(cameraElem); - - AddXMLElementUnsignedInt(*cameraElem, "ID", &cameraId, document); - - int port = portNumber - 1; - if (((port == 0 || port == 1) && syncOutMode) || (port == 2)) - { - tinyxml2::XMLElement* syncOutElem = nullptr; - if (port == 0) - syncOutElem = document.NewElement("Sync_Out"); - else if (port == 1) - syncOutElem = document.NewElement("Sync_Out2"); - else - syncOutElem = document.NewElement("Sync_Out_MT"); - - cameraElem->InsertEndChild(syncOutElem); - - // Add Sync Out Mode - if (port == 0 || port == 1) - { - tinyxml2::XMLElement* modeElem = document.NewElement("Mode"); - switch (*syncOutMode) - { - case ModeShutterOut: - modeElem->SetText("Shutter out"); - break; - case ModeMultiplier: - modeElem->SetText("Multiplier"); - break; - case ModeDivisor: - modeElem->SetText("Divisor"); - break; - case ModeIndependentFreq: - modeElem->SetText("Camera independent"); - break; - case ModeMeasurementTime: - modeElem->SetText("Measurement time"); - break; - case ModeFixed100Hz: - modeElem->SetText("Continuous 100Hz"); - break; - case ModeSystemLiveTime: - modeElem->SetText("System live time"); - break; - default: - return ""; - } - syncOutElem->InsertEndChild(modeElem); - - if (*syncOutMode == ModeMultiplier || - *syncOutMode == ModeDivisor || - *syncOutMode == ModeIndependentFreq) - { - AddXMLElementUnsignedInt(*syncOutElem, "Value", syncOutValue, document); - AddXMLElementFloat(*syncOutElem, "Duty_Cycle", syncOutDutyCycle, 3, document); - } - } - - if (syncOutNegativePolarity && (port == 2 || - (syncOutMode && *syncOutMode != ModeFixed100Hz))) - { - AddXMLElementBool(*syncOutElem, "Signal_Polarity", syncOutNegativePolarity, document, "Negative", "Positive"); - } - } - - tinyxml2::XMLPrinter printer; - document.Print(&printer); - return printer.CStr(); + mCurrentElement->SetAttribute(name, value); + return *this; } -std::string SerializerApi::SetCameraLensControlSettings(const unsigned int cameraId, const float focus, const float aperture) +SerializerApi SerializerApi::AttributeInt(const char* name, std::int32_t value) { - tinyxml2::XMLDocument document; - - tinyxml2::XMLElement* rootElem = document.NewElement("QTM_Settings"); - document.InsertFirstChild(rootElem); - - tinyxml2::XMLElement* generalElem = document.NewElement("General"); - rootElem->InsertEndChild(generalElem); - - tinyxml2::XMLElement* cameraElem = document.NewElement("Camera"); - generalElem->InsertEndChild(cameraElem); - - AddXMLElementUnsignedInt(*cameraElem, "ID", &cameraId, document); - - tinyxml2::XMLElement* lensControlElem = document.NewElement("LensControl"); - cameraElem->InsertEndChild(lensControlElem); - - AddXMLElementFloatWithTextAttribute(document, *lensControlElem, "Focus", "Value", focus, 6); - AddXMLElementFloatWithTextAttribute(document, *lensControlElem, "Aperture", "Value", aperture, 6); - - tinyxml2::XMLPrinter printer; - document.Print(&printer); - return printer.CStr(); + mCurrentElement->SetAttribute(name, value); + return *this; } -std::string SerializerApi::SetCameraAutoExposureSettings(const unsigned int cameraId, const bool autoExposure, const float compensation) +SerializerApi SerializerApi::AttributeFloat(const char* name, float value) { - tinyxml2::XMLDocument document; - - tinyxml2::XMLElement* rootElem = document.NewElement("QTM_Settings"); - document.InsertFirstChild(rootElem); - - tinyxml2::XMLElement* generalElem = document.NewElement("General"); - rootElem->InsertEndChild(generalElem); - - tinyxml2::XMLElement* cameraElem = document.NewElement("Camera"); - generalElem->InsertEndChild(cameraElem); - - AddXMLElementUnsignedInt(*cameraElem, "ID", &cameraId, document); - - tinyxml2::XMLElement* lensControlElem = document.NewElement("LensControl"); - cameraElem->InsertEndChild(lensControlElem); - - tinyxml2::XMLElement* autoExposureElem = document.NewElement("AutoExposure"); - autoExposureElem->SetAttribute("Enabled", autoExposure ? "true" : "false"); - - char compensationStr[32]; - snprintf(compensationStr, sizeof(compensationStr), "%.6f", compensation); - autoExposureElem->SetAttribute("Compensation", compensationStr); - - lensControlElem->InsertEndChild(autoExposureElem); - - tinyxml2::XMLPrinter printer; - document.Print(&printer); - return printer.CStr(); + mCurrentElement->SetAttribute(name, std::to_string(value).c_str()); + return *this; } -std::string SerializerApi::SetCameraAutoWhiteBalance(const unsigned int cameraId, const bool enable) +SerializerApi SerializerApi::AttributeDouble(const char* name, double value) { - tinyxml2::XMLDocument document; - - tinyxml2::XMLElement* rootElem = document.NewElement("QTM_Settings"); - document.InsertFirstChild(rootElem); - - tinyxml2::XMLElement* generalElem = document.NewElement("General"); - rootElem->InsertEndChild(generalElem); - - tinyxml2::XMLElement* cameraElem = document.NewElement("Camera"); - generalElem->InsertEndChild(cameraElem); - - AddXMLElementUnsignedInt(*cameraElem, "ID", &cameraId, document); - - tinyxml2::XMLElement* autoWhiteBalanceElem = document.NewElement("AutoWhiteBalance"); - autoWhiteBalanceElem->SetText(enable ? "true" : "false"); - cameraElem->InsertEndChild(autoWhiteBalanceElem); - - tinyxml2::XMLPrinter printer; - document.Print(&printer); - return printer.CStr(); + mCurrentElement->SetAttribute(name, std::to_string(value).c_str()); + return *this; } -std::string SerializerApi::SetImageSettings(const unsigned int cameraId, const bool* enable, const CRTPacket::EImageFormat* format, - const unsigned int* width, const unsigned int* height, const float* leftCrop, - const float* topCrop, const float* rightCrop, const float* bottomCrop) +SerializerApi SerializerApi::AttributeUnsignedInt(const char* name, std::uint32_t value) { - tinyxml2::XMLDocument document; - - tinyxml2::XMLElement* rootElem = document.NewElement("QTM_Settings"); - document.InsertFirstChild(rootElem); - - tinyxml2::XMLElement* imageElem = document.NewElement("Image"); - rootElem->InsertEndChild(imageElem); - - tinyxml2::XMLElement* cameraElem = document.NewElement("Camera"); - imageElem->InsertEndChild(cameraElem); - - AddXMLElementUnsignedInt(*cameraElem, "ID", cameraId, document); - - AddXMLElementBool(*cameraElem, "Enabled", enable, document); - - if (format) - { - const char* formatStr = nullptr; - switch (*format) - { - case CRTPacket::FormatRawGrayscale: - formatStr = "RAWGrayscale"; - break; - case CRTPacket::FormatRawBGR: - formatStr = "RAWBGR"; - break; - case CRTPacket::FormatJPG: - formatStr = "JPG"; - break; - case CRTPacket::FormatPNG: - formatStr = "PNG"; - break; - } - - if (formatStr) - { - tinyxml2::XMLElement* formatElem = document.NewElement("Format"); - formatElem->SetText(formatStr); - cameraElem->InsertEndChild(formatElem); - } - } - - AddXMLElementUnsignedInt(*cameraElem, "Width", width, document); - AddXMLElementUnsignedInt(*cameraElem, "Height", height, document); - AddXMLElementFloat(*cameraElem, "Left_Crop", leftCrop, 6, document); - AddXMLElementFloat(*cameraElem, "Top_Crop", topCrop, 6, document); - AddXMLElementFloat(*cameraElem, "Right_Crop", rightCrop, 6, document); - AddXMLElementFloat(*cameraElem, "Bottom_Crop", bottomCrop, 6, document); - - tinyxml2::XMLPrinter printer; - document.Print(&printer); - return printer.CStr(); + mCurrentElement->SetAttribute(name, value); + return *this; } -std::string SerializerApi::SetForceSettings(const unsigned int plateId, const SPoint* corner1, const SPoint* corner2, - const SPoint* corner3, const SPoint* corner4) +SerializerApi SerializerApi::AttributeString(const char* name, const char* value) { - tinyxml2::XMLDocument document; - tinyxml2::XMLElement* rootElem = document.NewElement("QTM_Settings"); - document.InsertFirstChild(rootElem); - - tinyxml2::XMLElement* forceElem = document.NewElement("Force"); - rootElem->InsertEndChild(forceElem); - - tinyxml2::XMLElement* plateElem = document.NewElement("Plate"); - forceElem->InsertEndChild(plateElem); - - if (mMajorVersion > 1 || mMinorVersion > 7) - { - AddXMLElementUnsignedInt(*plateElem, "Plate_ID", &plateId, document); - } - else - { - AddXMLElementUnsignedInt(*plateElem, "Force_Plate_Index", &plateId, document); - } - - auto addCorner = [&](const char* name, const SPoint* pCorner) - { - if (pCorner) - { - tinyxml2::XMLElement* cornerElem = document.NewElement(name); - plateElem->InsertEndChild(cornerElem); - - AddXMLElementFloat(*cornerElem, "X", &(pCorner->fX), 6, document); - AddXMLElementFloat(*cornerElem, "Y", &(pCorner->fY), 6, document); - AddXMLElementFloat(*cornerElem, "Z", &(pCorner->fZ), 6, document); - } - }; - - addCorner("Corner1", corner1); - addCorner("Corner2", corner2); - addCorner("Corner3", corner3); - addCorner("Corner4", corner4); - - tinyxml2::XMLPrinter printer; - document.Print(&printer); - return printer.CStr(); + mCurrentElement->SetAttribute(name, value); + return *this; } -std::string SerializerApi::Set6DOFBodySettings(const std::vector& settings6Dofs) +std::string SerializerApi::ToString() const { - tinyxml2::XMLDocument document; - auto* rootElem = document.NewElement("QTM_Settings"); - document.InsertFirstChild(rootElem); - - auto* the6D = document.NewElement("The_6D"); - rootElem->InsertEndChild(the6D); - - for (const auto& body : settings6Dofs) - { - auto* bodyElem = document.NewElement("Body"); - the6D->InsertEndChild(bodyElem); - - auto* nameElem = document.NewElement("Name"); - nameElem->SetText(body.name.c_str()); - bodyElem->InsertEndChild(nameElem); - - auto* enabledElem = document.NewElement("Enabled"); - enabledElem->SetText(body.enabled ? "true" : "false"); - bodyElem->InsertEndChild(enabledElem); - - auto* colorElem = document.NewElement("Color"); - colorElem->SetAttribute("R", body.color & 0xff); - colorElem->SetAttribute("G", (body.color >> 8) & 0xff); - colorElem->SetAttribute("B", (body.color >> 16) & 0xff); - bodyElem->InsertEndChild(colorElem); - - auto* maxResidualElem = document.NewElement("MaximumResidual"); - maxResidualElem->SetText(std::to_string(body.maxResidual).c_str()); - bodyElem->InsertEndChild(maxResidualElem); - - auto* minMarkersElem = document.NewElement("MinimumMarkersInBody"); - minMarkersElem->SetText(std::to_string(body.minMarkersInBody).c_str()); - bodyElem->InsertEndChild(minMarkersElem); - - auto* boneToleranceElem = document.NewElement("BoneLengthTolerance"); - boneToleranceElem->SetText(std::to_string(body.boneLengthTolerance).c_str()); - bodyElem->InsertEndChild(boneToleranceElem); - - auto* filterElem = document.NewElement("Filter"); - filterElem->SetAttribute("Preset", body.filterPreset.c_str()); - bodyElem->InsertEndChild(filterElem); - - if (!body.mesh.name.empty()) - { - auto* meshElem = document.NewElement("Mesh"); - bodyElem->InsertEndChild(meshElem); - - auto* meshNameElem = document.NewElement("Name"); - meshNameElem->SetText(body.mesh.name.c_str()); - meshElem->InsertEndChild(meshNameElem); - - auto* positionElem = document.NewElement("Position"); - positionElem->SetAttribute("X", std::to_string(body.mesh.position.fX).c_str()); - positionElem->SetAttribute("Y", std::to_string(body.mesh.position.fY).c_str()); - positionElem->SetAttribute("Z", std::to_string(body.mesh.position.fZ).c_str()); - meshElem->InsertEndChild(positionElem); - - auto* rotationElem = document.NewElement("Rotation"); - rotationElem->SetAttribute("X", std::to_string(body.mesh.rotation.fX).c_str()); - rotationElem->SetAttribute("Y", std::to_string(body.mesh.rotation.fY).c_str()); - rotationElem->SetAttribute("Z", std::to_string(body.mesh.rotation.fZ).c_str()); - meshElem->InsertEndChild(rotationElem); - - auto* scaleElem = document.NewElement("Scale"); - scaleElem->SetText(std::to_string(body.mesh.scale).c_str()); - meshElem->InsertEndChild(scaleElem); - - auto* opacityElem = document.NewElement("Opacity"); - opacityElem->SetText(std::to_string(body.mesh.opacity).c_str()); - meshElem->InsertEndChild(opacityElem); - } - - if (!body.points.empty()) - { - auto* pointsElem = document.NewElement("Points"); - bodyElem->InsertEndChild(pointsElem); - - for (const auto& point : body.points) - { - auto* pointElem = document.NewElement("Point"); - pointElem->SetAttribute("X", std::to_string(point.fX).c_str()); - pointElem->SetAttribute("Y", std::to_string(point.fY).c_str()); - pointElem->SetAttribute("Z", std::to_string(point.fZ).c_str()); - pointElem->SetAttribute("Virtual", point.virtual_ ? "1" : "0"); - pointElem->SetAttribute("PhysicalId", point.physicalId); - pointElem->SetAttribute("Name", point.name.c_str()); - pointsElem->InsertEndChild(pointElem); - } - } - - auto* dataOriginElem = document.NewElement("Data_origin"); - dataOriginElem->SetText(std::to_string(body.origin.type).c_str()); - dataOriginElem->SetAttribute("X", std::to_string(body.origin.position.fX).c_str()); - dataOriginElem->SetAttribute("Y", std::to_string(body.origin.position.fY).c_str()); - dataOriginElem->SetAttribute("Z", std::to_string(body.origin.position.fZ).c_str()); - dataOriginElem->SetAttribute("Relative_body", body.origin.relativeBody); - bodyElem->InsertEndChild(dataOriginElem); - - auto* dataOrientationElem = document.NewElement("Data_orientation"); - dataOrientationElem->SetText(std::to_string(body.origin.type).c_str()); - for (std::uint32_t i = 0; i < 9; i++) - { - char tmpStr[16]; - sprintf_s(tmpStr, sizeof(tmpStr), "R%u%u", (i / 3) + 1, (i % 3) + 1); - dataOrientationElem->SetAttribute(tmpStr, std::to_string(body.origin.rotation[i]).c_str()); - } - dataOrientationElem->SetAttribute("Relative_body", body.origin.relativeBody); - bodyElem->InsertEndChild(dataOrientationElem); - } - - tinyxml2::XMLPrinter printer; - document.Print(&printer); + tinyxml2::XMLPrinter printer{}; + mDocument->Print(&printer); return printer.CStr(); } -std::string SerializerApi::SetSkeletonSettings(const std::vector& settingsSkeletons) +SerializerApi::SerializerApi(std::uint32_t majorVersion, std::uint32_t minorVersion) + : mMajorVersion(majorVersion), mMinorVersion(minorVersion), mDocument(new tinyxml2::XMLDocument) { - tinyxml2::XMLDocument document; - tinyxml2::XMLElement* rootElem = document.NewElement("QTM_Settings"); - document.InsertFirstChild(rootElem); - - tinyxml2::XMLElement* skeletonsElem = document.NewElement("Skeletons"); - rootElem->InsertEndChild(skeletonsElem); - - for (const auto& skeleton : settingsSkeletons) - { - tinyxml2::XMLElement* skeletonElem = document.NewElement("Skeleton"); - skeletonElem->SetAttribute("Name", skeleton.name.c_str()); - skeletonsElem->InsertEndChild(skeletonElem); - - if (mMajorVersion == 1 && mMinorVersion < 22) - { - tinyxml2::XMLElement* solverElem = document.NewElement("Solver"); - solverElem->SetText(skeleton.rootSegment.solver.c_str()); - skeletonElem->InsertEndChild(solverElem); - } - - tinyxml2::XMLElement* scaleElem = document.NewElement("Scale"); - scaleElem->SetText(std::to_string(skeleton.scale).c_str()); - skeletonElem->InsertEndChild(scaleElem); - - tinyxml2::XMLElement* segmentsElem = document.NewElement("Segments"); - skeletonElem->InsertEndChild(segmentsElem); - - std::function recurseSegments; - recurseSegments = [&](const SSettingsSkeletonSegmentHierarchical& segment, tinyxml2::XMLElement* parentElem) - { - tinyxml2::XMLElement* segmentElem = document.NewElement("Segment"); - segmentElem->SetAttribute("Name", segment.name.c_str()); - parentElem->InsertEndChild(segmentElem); - - if (mMajorVersion > 1 || mMinorVersion > 21) - { - tinyxml2::XMLElement* solverElem = document.NewElement("Solver"); - solverElem->SetText(segment.solver.c_str()); - segmentElem->InsertEndChild(solverElem); - } - - if (!std::isnan(segment.position.x)) - { - AddXMLElementTransform(document, *segmentElem, "Transform", segment.position, segment.rotation); - } - - if (!std::isnan(segment.defaultPosition.x)) - { - AddXMLElementTransform(document, *segmentElem, "DefaultTransform", segment.defaultPosition, segment.defaultRotation); - } - - tinyxml2::XMLElement* dofElem = document.NewElement("DegreesOfFreedom"); - segmentElem->InsertEndChild(dofElem); - for (const auto& dof : segment.degreesOfFreedom) - { - AddXMLElementDOF(document, *dofElem, SkeletonDofToStringSettings(dof.type), dof); - } - - tinyxml2::XMLElement* endpointElem = document.NewElement("Endpoint"); - if (!std::isnan(segment.endpoint.x) && !std::isnan(segment.endpoint.y) && !std::isnan(segment.endpoint.z)) - { - endpointElem->SetAttribute("X", std::to_string(segment.endpoint.x).c_str()); - endpointElem->SetAttribute("Y", std::to_string(segment.endpoint.y).c_str()); - endpointElem->SetAttribute("Z", std::to_string(segment.endpoint.z).c_str()); - } - segmentElem->InsertEndChild(endpointElem); - - tinyxml2::XMLElement* markersElem = document.NewElement("Markers"); - segmentElem->InsertEndChild(markersElem); - for (const auto& marker : segment.markers) - { - tinyxml2::XMLElement* markerElem = document.NewElement("Marker"); - markerElem->SetAttribute("Name", marker.name.c_str()); - markersElem->InsertEndChild(markerElem); - - tinyxml2::XMLElement* positionElem = document.NewElement("Position"); - positionElem->SetAttribute("X", std::to_string(marker.position.x).c_str()); - positionElem->SetAttribute("Y", std::to_string(marker.position.y).c_str()); - positionElem->SetAttribute("Z", std::to_string(marker.position.z).c_str()); - markerElem->InsertEndChild(positionElem); - - tinyxml2::XMLElement* weightElem = document.NewElement("Weight"); - weightElem->SetText(std::to_string(marker.weight).c_str()); - markerElem->InsertEndChild(weightElem); - } - - tinyxml2::XMLElement* rigidBodiesElem = document.NewElement("RigidBodies"); - segmentElem->InsertEndChild(rigidBodiesElem); - for (const auto& rigidBody : segment.bodies) - { - tinyxml2::XMLElement* rigidBodyElem = document.NewElement("RigidBody"); - rigidBodyElem->SetAttribute("Name", rigidBody.name.c_str()); - rigidBodiesElem->InsertEndChild(rigidBodyElem); - - tinyxml2::XMLElement* transformElem = document.NewElement("Transform"); - rigidBodyElem->InsertEndChild(transformElem); - - tinyxml2::XMLElement* positionElem = document.NewElement("Position"); - positionElem->SetAttribute("X", std::to_string(rigidBody.position.x).c_str()); - positionElem->SetAttribute("Y", std::to_string(rigidBody.position.y).c_str()); - positionElem->SetAttribute("Z", std::to_string(rigidBody.position.z).c_str()); - transformElem->InsertEndChild(positionElem); - - tinyxml2::XMLElement* rotationElem = document.NewElement("Rotation"); - rotationElem->SetAttribute("X", std::to_string(rigidBody.rotation.x).c_str()); - rotationElem->SetAttribute("Y", std::to_string(rigidBody.rotation.y).c_str()); - rotationElem->SetAttribute("Z", std::to_string(rigidBody.rotation.z).c_str()); - rotationElem->SetAttribute("W", std::to_string(rigidBody.rotation.w).c_str()); - transformElem->InsertEndChild(rotationElem); - - tinyxml2::XMLElement* weightElem = document.NewElement("Weight"); - weightElem->SetText(std::to_string(rigidBody.weight).c_str()); - rigidBodyElem->InsertEndChild(weightElem); - } - - for (const auto& childSegment : segment.segments) - { - recurseSegments(childSegment, segmentElem); - } - }; - - recurseSegments(skeleton.rootSegment, segmentsElem); - } - - tinyxml2::XMLPrinter printer; - document.Print(&printer); - return printer.CStr(); + mCurrentElement = mDocument->RootElement(); } diff --git a/SerializerApi.h b/SerializerApi.h index 2c557de..85926af 100644 --- a/SerializerApi.h +++ b/SerializerApi.h @@ -1,8 +1,6 @@ #pragma once -#include #include -#include "Settings.h" namespace tinyxml2 { @@ -12,63 +10,46 @@ namespace tinyxml2 namespace qualisys_cpp_sdk { - struct SPosition; - struct SRotation; - struct SerializerApi { private: - std::shared_ptr mDocument; + tinyxml2::XMLDocument* mDocument; + tinyxml2::XMLElement* mCurrentElement = nullptr; + std::uint32_t mMajorVersion; std::uint32_t mMinorVersion; - void AddXMLElementBool(tinyxml2::XMLElement& parentElem, const char* elementName, const bool* value, tinyxml2::XMLDocument& document, const char* trueText = "True", const char* falseText = "False"); - void AddXMLElementBool(tinyxml2::XMLElement& parentElem, const char* elementName, const bool value, tinyxml2::XMLDocument& document, const char* trueText = "True", const char* falseText = "False"); - void AddXMLElementInt(tinyxml2::XMLElement& parentElem, const char* elementName, const int* value, tinyxml2::XMLDocument& document); - void AddXMLElementUnsignedInt(tinyxml2::XMLElement& parentElem, const char* elementName, const unsigned int value, tinyxml2::XMLDocument& document); - void AddXMLElementUnsignedInt(tinyxml2::XMLElement& parentElem, const char* elementName, const unsigned int* value, tinyxml2::XMLDocument& document); - void AddXMLElementFloat(tinyxml2::XMLElement& parentElem, const char* elementName, const float* value, unsigned int decimals, tinyxml2::XMLDocument& document); - void AddXMLElementFloatWithTextAttribute(tinyxml2::XMLDocument& document, tinyxml2::XMLElement& parentElem, const char* elementName, const char* attributeName, const float& value, unsigned int decimals); - void AddXMLElementTransform(tinyxml2::XMLDocument& document, tinyxml2::XMLElement& parentElem, const std::string& name, const SPosition& position, const SRotation& rotation); - void AddXMLElementDOF(tinyxml2::XMLDocument& document, tinyxml2::XMLElement& parentElem, const std::string& name, const SDegreeOfFreedom& degreesOfFreedom); + SerializerApi(const SerializerApi& src, tinyxml2::XMLElement* element); public: SerializerApi(std::uint32_t majorVersion, std::uint32_t minorVersion); - std::string SetGeneralSettings(const unsigned int* captureFrequency, const float* captureTime, - const bool* startOnExtTrig, const bool* startOnTrigNO, const bool* startOnTrigNC, const bool* startOnTrigSoftware, - const EProcessingActions* processingActions, const EProcessingActions* rtProcessingActions, const EProcessingActions* reprocessingActions); + SerializerApi Element(const char* name); + + SerializerApi ElementBool(const char* name, bool value); - std::string SetExtTimeBaseSettings(const bool* enabled, const ESignalSource* signalSource, const bool* signalModePeriodic, - const unsigned int* freqMultiplier, const unsigned int* freqDivisor, const unsigned int* freqTolerance, - const float* nominalFrequency, const bool* negativeEdge, const unsigned int* signalShutterDelay, const float* nonPeriodicTimeout); + SerializerApi ElementInt(const char* name, std::int32_t value); - std::string SetExtTimestampSettings(const SSettingsGeneralExternalTimestamp& timestampSettings); + SerializerApi ElementFloat(const char* name, float value); - std::string SetCameraSettings(const unsigned int cameraId, const ECameraMode* mode, const float* markerExposure, - const float* markerThreshold, const int* orientation); + SerializerApi ElementDouble(const char* name, double value); - std::string SetCameraVideoSettings(const unsigned int cameraId, const EVideoResolution* videoResolution, - const EVideoAspectRatio* videoAspectRatio, const unsigned int* videoFrequency, const float* videoExposure, const float* videoFlashTime); + SerializerApi ElementUnsignedInt(const char* name, std::uint32_t value); - std::string SetCameraSyncOutSettings(const unsigned int cameraId, const unsigned int portNumber, const ESyncOutFreqMode* syncOutMode, - const unsigned int* syncOutValue, const float* syncOutDutyCycle, const bool* syncOutNegativePolarity); + SerializerApi ElementString(const char* name, const char* value); - std::string SetCameraLensControlSettings(const unsigned int cameraId, const float focus, const float aperture); + SerializerApi AttributeBool(const char* name, bool value); - std::string SetCameraAutoExposureSettings(const unsigned int cameraId, const bool autoExposure, const float compensation); + SerializerApi AttributeInt(const char* name, std::int32_t value); - std::string SetCameraAutoWhiteBalance(const unsigned int cameraId, const bool enable); + SerializerApi AttributeFloat(const char* name, float value); - std::string SetImageSettings(const unsigned int cameraId, const bool* enable, const CRTPacket::EImageFormat* format, - const unsigned int* width, const unsigned int* height, const float* leftCrop, - const float* topCrop, const float* rightCrop, const float* bottomCrop); + SerializerApi AttributeDouble(const char* name, double value); - std::string SetForceSettings(const unsigned int plateId, const SPoint* corner1, const SPoint* corner2, - const SPoint* corner3, const SPoint* corner4); + SerializerApi AttributeUnsignedInt(const char* name, std::uint32_t value); - std::string Set6DOFBodySettings(const std::vector& settings6Dofs); + SerializerApi AttributeString(const char* name, const char* value); - std::string SetSkeletonSettings(const std::vector& settingsSkeletons); + std::string ToString() const; }; } diff --git a/Settings.cpp b/Settings.cpp index 21d1c82..bef3bf5 100644 --- a/Settings.cpp +++ b/Settings.cpp @@ -1,4 +1,5 @@ #include "Settings.h" +#include "algorithm" const char* qualisys_cpp_sdk::SkeletonDofToStringSettings(EDegreeOfFreedom dof) { diff --git a/SettingsDeserializer.cpp b/SettingsDeserializer.cpp index 454fc09..99e1048 100644 --- a/SettingsDeserializer.cpp +++ b/SettingsDeserializer.cpp @@ -36,62 +36,62 @@ bool SettingsDeserializer::DeserializeGeneralSettings(SSettingsGeneral& generalS return true; } - auto generalElem = mDeserializer->FirstChildElement("General"); + auto generalElem = mDeserializer->FindChild("General"); if (!generalElem) { return true; } - if (auto frequencyElem = generalElem.FirstChildElement("Frequency")) + if (auto frequencyElem = generalElem.FindChild("Frequency")) { - generalSettings.nCaptureFrequency = frequencyElem.UnsignedText(0); + generalSettings.nCaptureFrequency = frequencyElem.ReadUnsignedInt(0); } else { return false; } - if (auto captureTimeElem = generalElem.FirstChildElement("Capture_Time")) + if (auto captureTimeElem = generalElem.FindChild("Capture_Time")) { - generalSettings.fCaptureTime = captureTimeElem.FloatText(.0f); + generalSettings.fCaptureTime = captureTimeElem.ReadFloat(.0f); } else { return false; } - if (!ReadXmlBool(generalElem, "Start_On_External_Trigger", generalSettings.bStartOnExternalTrigger)) + if (!generalElem.TryReadElementBool("Start_On_External_Trigger", generalSettings.bStartOnExternalTrigger)) { return false; } if (mMajorVersion > 1 || mMinorVersion > 14) { - if (!ReadXmlBool(generalElem, "Start_On_Trigger_NO", generalSettings.bStartOnTrigNO)) + if (!generalElem.TryReadElementBool("Start_On_Trigger_NO", generalSettings.bStartOnTrigNO)) { return false; } - if (!ReadXmlBool(generalElem, "Start_On_Trigger_NC", generalSettings.bStartOnTrigNC)) + if (!generalElem.TryReadElementBool("Start_On_Trigger_NC", generalSettings.bStartOnTrigNC)) { return false; } - if (!ReadXmlBool(generalElem, "Start_On_Trigger_Software", generalSettings.bStartOnTrigSoftware)) + if (!generalElem.TryReadElementBool("Start_On_Trigger_Software", generalSettings.bStartOnTrigSoftware)) { return false; } } - if (auto extTimeBaseElem = generalElem.FirstChildElement("External_Time_Base")) + if (auto extTimeBaseElem = generalElem.FindChild("External_Time_Base")) { - if (!ReadXmlBool(extTimeBaseElem, "Enabled", generalSettings.sExternalTimebase.bEnabled)) + if (!extTimeBaseElem.TryReadElementBool("Enabled", generalSettings.sExternalTimebase.bEnabled)) { return false; } std::string signalSource; - if (!TryReadElementString(extTimeBaseElem, "Signal_Source", signalSource)) + if (!extTimeBaseElem.TryReadElementString("Signal_Source", signalSource)) { return false; } @@ -123,7 +123,7 @@ bool SettingsDeserializer::DeserializeGeneralSettings(SSettingsGeneral& generalS } std::string signalMode; - if (!TryReadElementString(extTimeBaseElem, "Signal_Mode", signalMode)) + if (!extTimeBaseElem.TryReadElementString("Signal_Mode", signalMode)) { return false; } @@ -142,29 +142,29 @@ bool SettingsDeserializer::DeserializeGeneralSettings(SSettingsGeneral& generalS return false; } - if (!TryReadElementUnsignedInt32(extTimeBaseElem, "Frequency_Multiplier", + if (!extTimeBaseElem.TryReadElementUnsignedInt32("Frequency_Multiplier", generalSettings.sExternalTimebase.nFreqMultiplier)) { return false; } - if (!TryReadElementUnsignedInt32(extTimeBaseElem, "Frequency_Divisor", + if (!extTimeBaseElem.TryReadElementUnsignedInt32("Frequency_Divisor", generalSettings.sExternalTimebase.nFreqDivisor)) { return false; } - if (!TryReadElementUnsignedInt32(extTimeBaseElem, "Frequency_Tolerance", + if (!extTimeBaseElem.TryReadElementUnsignedInt32("Frequency_Tolerance", generalSettings.sExternalTimebase.nFreqTolerance)) { return false; } - if (!TryReadElementFloat(extTimeBaseElem, "Nominal_Frequency", + if (!extTimeBaseElem.TryReadElementFloat("Nominal_Frequency", generalSettings.sExternalTimebase.fNominalFrequency)) { std::string nominalFrequency; - if (TryReadElementString(extTimeBaseElem, "Nominal_Frequency", nominalFrequency)) + if (extTimeBaseElem.TryReadElementString("Nominal_Frequency", nominalFrequency)) { if (ToLowerXmlString(nominalFrequency) == "none") { @@ -178,7 +178,7 @@ bool SettingsDeserializer::DeserializeGeneralSettings(SSettingsGeneral& generalS } std::string signalEdge; - if (TryReadElementString(extTimeBaseElem, "Signal_Edge", signalEdge)) + if (extTimeBaseElem.TryReadElementString("Signal_Edge", signalEdge)) { signalEdge = ToLowerXmlString(signalEdge); if (signalEdge == "negative") @@ -199,11 +199,11 @@ bool SettingsDeserializer::DeserializeGeneralSettings(SSettingsGeneral& generalS return false; } - if (!TryReadElementFloat(extTimeBaseElem, "Nominal_Frequency", + if (!extTimeBaseElem.TryReadElementFloat("Nominal_Frequency", generalSettings.sExternalTimebase.fNominalFrequency)) { std::string nominalFrequency; - if (TryReadElementString(extTimeBaseElem, "Nominal_Frequency", nominalFrequency)) + if (extTimeBaseElem.TryReadElementString("Nominal_Frequency", nominalFrequency)) { if (ToLowerXmlString(nominalFrequency) == "none") { @@ -216,13 +216,13 @@ bool SettingsDeserializer::DeserializeGeneralSettings(SSettingsGeneral& generalS } } - if (!TryReadElementUnsignedInt32(extTimeBaseElem, "Signal_Shutter_Delay", + if (!extTimeBaseElem.TryReadElementUnsignedInt32("Signal_Shutter_Delay", generalSettings.sExternalTimebase.nSignalShutterDelay)) { return false; } - if (!TryReadElementFloat(extTimeBaseElem, "Non_Periodic_Timeout", + if (!extTimeBaseElem.TryReadElementFloat("Non_Periodic_Timeout", generalSettings.sExternalTimebase.fNonPeriodicTimeout)) { return false; @@ -233,15 +233,15 @@ bool SettingsDeserializer::DeserializeGeneralSettings(SSettingsGeneral& generalS return false; } - if (auto externalTimestampElem = generalElem.FirstChildElement("External_Timestamp")) + if (auto externalTimestampElem = generalElem.FindChild("External_Timestamp")) { - if (!ReadXmlBool(externalTimestampElem, "Enabled", generalSettings.sTimestamp.bEnabled)) + if (!externalTimestampElem.TryReadElementBool("Enabled", generalSettings.sTimestamp.bEnabled)) { return false; } std::string type; - if (TryReadElementString(externalTimestampElem, "Type", type)) + if (externalTimestampElem.TryReadElementString("Type", type)) { type = ToLowerXmlString(type); if (type == "smpte") @@ -258,7 +258,7 @@ bool SettingsDeserializer::DeserializeGeneralSettings(SSettingsGeneral& generalS } } - TryReadElementUnsignedInt32(externalTimestampElem, "Frequency", generalSettings.sTimestamp.nFrequency); + externalTimestampElem.TryReadElementUnsignedInt32("Frequency", generalSettings.sTimestamp.nFrequency); } const char* processingActionTags[3] = {"Processing_Actions", "RealTime_Processing_Actions", "Reprocessing_Actions"}; @@ -273,7 +273,7 @@ bool SettingsDeserializer::DeserializeGeneralSettings(SSettingsGeneral& generalS EProcessingActions& target) -> bool { bool value; - if (ReadXmlBool(parent, elementName, value)) + if (parent.TryReadElementBool(elementName, value)) { if (value) { @@ -290,7 +290,7 @@ bool SettingsDeserializer::DeserializeGeneralSettings(SSettingsGeneral& generalS { // ==================== Processing actions ==================== - auto processingElem = generalElem.FirstChildElement(processingActionTags[i]); + auto processingElem = generalElem.FindChild(processingActionTags[i]); if (!processingElem) { return false; @@ -308,7 +308,7 @@ bool SettingsDeserializer::DeserializeGeneralSettings(SSettingsGeneral& generalS } std::string trackingMode; - if (!TryReadElementString(processingElem, "Tracking", trackingMode)) + if (!processingElem.TryReadElementString("Tracking", trackingMode)) { return false; } @@ -389,24 +389,24 @@ bool SettingsDeserializer::DeserializeGeneralSettings(SSettingsGeneral& generalS } } - auto eulerElem = generalElem.FirstChildElement("EulerAngles"); + auto eulerElem = generalElem.FindChild("EulerAngles"); if (eulerElem) { - generalSettings.eulerRotations[0] = eulerElem.Attribute("First"); - generalSettings.eulerRotations[1] = eulerElem.Attribute("Second"); - generalSettings.eulerRotations[2] = eulerElem.Attribute("Third"); + generalSettings.eulerRotations[0] = eulerElem.ReadAttributeString("First"); + generalSettings.eulerRotations[1] = eulerElem.ReadAttributeString("Second"); + generalSettings.eulerRotations[2] = eulerElem.ReadAttributeString("Third"); } for (auto cameraElem : ChildElementRange{generalElem, "Camera"}) { SSettingsGeneralCamera cameraSettings{}; - if (!TryReadElementUnsignedInt32(cameraElem, "ID", cameraSettings.nID)) + if (!cameraElem.TryReadElementUnsignedInt32("ID", cameraSettings.nID)) { return false; } std::string model; - if (!TryReadElementString(cameraElem, "Model", model)) + if (!cameraElem.TryReadElementString("Model", model)) { return false; } @@ -526,16 +526,16 @@ bool SettingsDeserializer::DeserializeGeneralSettings(SSettingsGeneral& generalS cameraSettings.eModel = ModelUnknown; } - ReadXmlBool(cameraElem, "Underwater", cameraSettings.bUnderwater); - ReadXmlBool(cameraElem, "Supports_HW_Sync", cameraSettings.bSupportsHwSync); + cameraElem.TryReadElementBool("Underwater", cameraSettings.bUnderwater); + cameraElem.TryReadElementBool("Supports_HW_Sync", cameraSettings.bSupportsHwSync); - if (!TryReadElementUnsignedInt32(cameraElem, "Serial", cameraSettings.nSerial)) + if (!cameraElem.TryReadElementUnsignedInt32("Serial", cameraSettings.nSerial)) { return false; } std::string mode; - if (!TryReadElementString(cameraElem, "Mode", mode)) + if (!cameraElem.TryReadElementString("Mode", mode)) { return false; } @@ -560,14 +560,14 @@ bool SettingsDeserializer::DeserializeGeneralSettings(SSettingsGeneral& generalS if (mMajorVersion > 1 || mMinorVersion > 11) { - if (!TryReadElementUnsignedInt32(cameraElem, "Video_Frequency", cameraSettings.nVideoFrequency)) + if (!cameraElem.TryReadElementUnsignedInt32("Video_Frequency", cameraSettings.nVideoFrequency)) { return false; } } std::string videoResolution; - if (TryReadElementString(cameraElem, "Video_Resolution", videoResolution)) + if (cameraElem.TryReadElementString("Video_Resolution", videoResolution)) { videoResolution = ToLowerXmlString(videoResolution); if (videoResolution == "1440p") @@ -601,7 +601,7 @@ bool SettingsDeserializer::DeserializeGeneralSettings(SSettingsGeneral& generalS } std::string videoAspectRatio; - if (TryReadElementString(cameraElem, "Video_Aspect_Ratio", videoAspectRatio)) + if (cameraElem.TryReadElementString("Video_Aspect_Ratio", videoAspectRatio)) { videoAspectRatio = ToLowerXmlString(videoAspectRatio); if (videoAspectRatio == "16x9") @@ -626,11 +626,11 @@ bool SettingsDeserializer::DeserializeGeneralSettings(SSettingsGeneral& generalS cameraSettings.eVideoAspectRatio = VideoAspectRatioNone; } - if (auto videoExposureElem = cameraElem.FirstChildElement("Video_Exposure")) + if (auto videoExposureElem = cameraElem.FindChild("Video_Exposure")) { - if (!TryReadElementUnsignedInt32(videoExposureElem, "Current", cameraSettings.nVideoExposure) - || !TryReadElementUnsignedInt32(videoExposureElem, "Min", cameraSettings.nVideoExposureMin) - || !TryReadElementUnsignedInt32(videoExposureElem, "Max", cameraSettings.nVideoExposureMax)) + if (!videoExposureElem.TryReadElementUnsignedInt32("Current", cameraSettings.nVideoExposure) + || !videoExposureElem.TryReadElementUnsignedInt32("Min", cameraSettings.nVideoExposureMin) + || !videoExposureElem.TryReadElementUnsignedInt32("Max", cameraSettings.nVideoExposureMax)) { return false; } @@ -640,11 +640,11 @@ bool SettingsDeserializer::DeserializeGeneralSettings(SSettingsGeneral& generalS return false; } - if (auto videoFlashTime = cameraElem.FirstChildElement("Video_Flash_Time")) + if (auto videoFlashTime = cameraElem.FindChild("Video_Flash_Time")) { - if (!TryReadElementUnsignedInt32(videoFlashTime, "Current", cameraSettings.nVideoFlashTime) - || !TryReadElementUnsignedInt32(videoFlashTime, "Min", cameraSettings.nVideoFlashTimeMin) - || !TryReadElementUnsignedInt32(videoFlashTime, "Max", cameraSettings.nVideoFlashTimeMax)) + if (!videoFlashTime.TryReadElementUnsignedInt32("Current", cameraSettings.nVideoFlashTime) + || !videoFlashTime.TryReadElementUnsignedInt32("Min", cameraSettings.nVideoFlashTimeMin) + || !videoFlashTime.TryReadElementUnsignedInt32("Max", cameraSettings.nVideoFlashTimeMax)) { return false; } @@ -654,11 +654,11 @@ bool SettingsDeserializer::DeserializeGeneralSettings(SSettingsGeneral& generalS return false; } - if (auto markerExposureElem = cameraElem.FirstChildElement("Marker_Exposure")) + if (auto markerExposureElem = cameraElem.FindChild("Marker_Exposure")) { - if (!TryReadElementUnsignedInt32(markerExposureElem, "Current", cameraSettings.nMarkerExposure) - || !TryReadElementUnsignedInt32(markerExposureElem, "Min", cameraSettings.nMarkerExposureMin) - || !TryReadElementUnsignedInt32(markerExposureElem, "Max", cameraSettings.nMarkerExposureMax)) + if (!markerExposureElem.TryReadElementUnsignedInt32("Current", cameraSettings.nMarkerExposure) + || !markerExposureElem.TryReadElementUnsignedInt32("Min", cameraSettings.nMarkerExposureMin) + || !markerExposureElem.TryReadElementUnsignedInt32("Max", cameraSettings.nMarkerExposureMax)) { return false; } @@ -668,11 +668,11 @@ bool SettingsDeserializer::DeserializeGeneralSettings(SSettingsGeneral& generalS return false; } - if (auto markerThresholdElem = cameraElem.FirstChildElement("Marker_Threshold")) + if (auto markerThresholdElem = cameraElem.FindChild("Marker_Threshold")) { - if (!TryReadElementUnsignedInt32(markerThresholdElem, "Current", cameraSettings.nMarkerThreshold) - || !TryReadElementUnsignedInt32(markerThresholdElem, "Min", cameraSettings.nMarkerThresholdMin) - || !TryReadElementUnsignedInt32(markerThresholdElem, "Max", cameraSettings.nMarkerThresholdMax)) + if (!markerThresholdElem.TryReadElementUnsignedInt32("Current", cameraSettings.nMarkerThreshold) + || !markerThresholdElem.TryReadElementUnsignedInt32("Min", cameraSettings.nMarkerThresholdMin) + || !markerThresholdElem.TryReadElementUnsignedInt32("Max", cameraSettings.nMarkerThresholdMax)) { return false; } @@ -682,20 +682,20 @@ bool SettingsDeserializer::DeserializeGeneralSettings(SSettingsGeneral& generalS return false; } - if (auto positionElem = cameraElem.FirstChildElement("Position")) + if (auto positionElem = cameraElem.FindChild("Position")) { - if (!TryReadElementFloat(positionElem, "X", cameraSettings.fPositionX) - || !TryReadElementFloat(positionElem, "Y", cameraSettings.fPositionY) - || !TryReadElementFloat(positionElem, "Z", cameraSettings.fPositionZ) - || !TryReadElementFloat(positionElem, "Rot_1_1", cameraSettings.fPositionRotMatrix[0][0]) - || !TryReadElementFloat(positionElem, "Rot_2_1", cameraSettings.fPositionRotMatrix[1][0]) - || !TryReadElementFloat(positionElem, "Rot_3_1", cameraSettings.fPositionRotMatrix[2][0]) - || !TryReadElementFloat(positionElem, "Rot_1_2", cameraSettings.fPositionRotMatrix[0][1]) - || !TryReadElementFloat(positionElem, "Rot_2_2", cameraSettings.fPositionRotMatrix[1][1]) - || !TryReadElementFloat(positionElem, "Rot_3_2", cameraSettings.fPositionRotMatrix[2][1]) - || !TryReadElementFloat(positionElem, "Rot_1_3", cameraSettings.fPositionRotMatrix[0][2]) - || !TryReadElementFloat(positionElem, "Rot_2_3", cameraSettings.fPositionRotMatrix[1][2]) - || !TryReadElementFloat(positionElem, "Rot_3_3", cameraSettings.fPositionRotMatrix[2][2])) + if (!positionElem.TryReadElementFloat("X", cameraSettings.fPositionX) + || !positionElem.TryReadElementFloat("Y", cameraSettings.fPositionY) + || !positionElem.TryReadElementFloat("Z", cameraSettings.fPositionZ) + || !positionElem.TryReadElementFloat("Rot_1_1", cameraSettings.fPositionRotMatrix[0][0]) + || !positionElem.TryReadElementFloat("Rot_2_1", cameraSettings.fPositionRotMatrix[1][0]) + || !positionElem.TryReadElementFloat("Rot_3_1", cameraSettings.fPositionRotMatrix[2][0]) + || !positionElem.TryReadElementFloat("Rot_1_2", cameraSettings.fPositionRotMatrix[0][1]) + || !positionElem.TryReadElementFloat("Rot_2_2", cameraSettings.fPositionRotMatrix[1][1]) + || !positionElem.TryReadElementFloat("Rot_3_2", cameraSettings.fPositionRotMatrix[2][1]) + || !positionElem.TryReadElementFloat("Rot_1_3", cameraSettings.fPositionRotMatrix[0][2]) + || !positionElem.TryReadElementFloat("Rot_2_3", cameraSettings.fPositionRotMatrix[1][2]) + || !positionElem.TryReadElementFloat("Rot_3_3", cameraSettings.fPositionRotMatrix[2][2])) { return false; } @@ -705,15 +705,15 @@ bool SettingsDeserializer::DeserializeGeneralSettings(SSettingsGeneral& generalS return false; } - if (!TryReadElementUnsignedInt32(cameraElem, "Orientation", cameraSettings.nOrientation)) + if (!cameraElem.TryReadElementUnsignedInt32("Orientation", cameraSettings.nOrientation)) { return false; } - if (auto markerResElem = cameraElem.FirstChildElement("Marker_Res")) + if (auto markerResElem = cameraElem.FindChild("Marker_Res")) { - if (!TryReadElementUnsignedInt32(markerResElem, "Width", cameraSettings.nMarkerResolutionWidth) - || !TryReadElementUnsignedInt32(markerResElem, "Height", cameraSettings.nMarkerResolutionHeight)) + if (!markerResElem.TryReadElementUnsignedInt32("Width", cameraSettings.nMarkerResolutionWidth) + || !markerResElem.TryReadElementUnsignedInt32("Height", cameraSettings.nMarkerResolutionHeight)) { return false; } @@ -723,10 +723,10 @@ bool SettingsDeserializer::DeserializeGeneralSettings(SSettingsGeneral& generalS return false; } - if (auto videoResElem = cameraElem.FirstChildElement("Video_Res")) + if (auto videoResElem = cameraElem.FindChild("Video_Res")) { - if (!TryReadElementUnsignedInt32(videoResElem, "Width", cameraSettings.nVideoResolutionWidth) - || !TryReadElementUnsignedInt32(videoResElem, "Height", cameraSettings.nVideoResolutionHeight)) + if (!videoResElem.TryReadElementUnsignedInt32("Width", cameraSettings.nVideoResolutionWidth) + || !videoResElem.TryReadElementUnsignedInt32("Height", cameraSettings.nVideoResolutionHeight)) { return false; } @@ -736,12 +736,12 @@ bool SettingsDeserializer::DeserializeGeneralSettings(SSettingsGeneral& generalS return false; } - if (auto markerFovElem = cameraElem.FirstChildElement("Marker_FOV")) + if (auto markerFovElem = cameraElem.FindChild("Marker_FOV")) { - if (!TryReadElementUnsignedInt32(markerFovElem, "Left", cameraSettings.nMarkerFOVLeft) - || !TryReadElementUnsignedInt32(markerFovElem, "Top", cameraSettings.nMarkerFOVTop) - || !TryReadElementUnsignedInt32(markerFovElem, "Right", cameraSettings.nMarkerFOVRight) - || !TryReadElementUnsignedInt32(markerFovElem, "Bottom", cameraSettings.nMarkerFOVBottom)) + if (!markerFovElem.TryReadElementUnsignedInt32("Left", cameraSettings.nMarkerFOVLeft) + || !markerFovElem.TryReadElementUnsignedInt32("Top", cameraSettings.nMarkerFOVTop) + || !markerFovElem.TryReadElementUnsignedInt32("Right", cameraSettings.nMarkerFOVRight) + || !markerFovElem.TryReadElementUnsignedInt32("Bottom", cameraSettings.nMarkerFOVBottom)) { return false; } @@ -751,12 +751,12 @@ bool SettingsDeserializer::DeserializeGeneralSettings(SSettingsGeneral& generalS return false; } - if (auto videoFovElem = cameraElem.FirstChildElement("Marker_FOV")) + if (auto videoFovElem = cameraElem.FindChild("Marker_FOV")) { - if (!TryReadElementUnsignedInt32(videoFovElem, "Left", cameraSettings.nVideoFOVLeft) - || !TryReadElementUnsignedInt32(videoFovElem, "Top", cameraSettings.nVideoFOVTop) - || !TryReadElementUnsignedInt32(videoFovElem, "Right", cameraSettings.nVideoFOVRight) - || !TryReadElementUnsignedInt32(videoFovElem, "Bottom", cameraSettings.nVideoFOVBottom)) + if (!videoFovElem.TryReadElementUnsignedInt32("Left", cameraSettings.nVideoFOVLeft) + || !videoFovElem.TryReadElementUnsignedInt32("Top", cameraSettings.nVideoFOVTop) + || !videoFovElem.TryReadElementUnsignedInt32("Right", cameraSettings.nVideoFOVRight) + || !videoFovElem.TryReadElementUnsignedInt32("Bottom", cameraSettings.nVideoFOVBottom)) { return false; } @@ -772,13 +772,13 @@ bool SettingsDeserializer::DeserializeGeneralSettings(SSettingsGeneral& generalS char syncOutStr[16]; (void)sprintf_s(syncOutStr, 16, "Sync_Out%s", port == 0 ? "" : (port == 1 ? "2" : "_MT")); - auto syncOutElem = cameraElem.FirstChildElement(syncOutStr); + auto syncOutElem = cameraElem.FindChild(syncOutStr); if (syncOutElem) { if (port < 2) { std::string mode; - if (!TryReadElementString(syncOutElem, "Mode", mode)) + if (!syncOutElem.TryReadElementString("Mode", mode)) { return false; } @@ -821,8 +821,8 @@ bool SettingsDeserializer::DeserializeGeneralSettings(SSettingsGeneral& generalS cameraSettings.eSyncOutMode[port] == ModeDivisor || cameraSettings.eSyncOutMode[port] == ModeIndependentFreq) { - if (!TryReadElementUnsignedInt32(syncOutElem, "Value", cameraSettings.nSyncOutValue[port]) - || !TryReadElementFloat(syncOutElem, "Duty_Cycle", cameraSettings.fSyncOutDutyCycle[port])) + if (!syncOutElem.TryReadElementUnsignedInt32("Value", cameraSettings.nSyncOutValue[port]) + || !syncOutElem.TryReadElementFloat("Duty_Cycle", cameraSettings.fSyncOutDutyCycle[port])) { return false; } @@ -832,7 +832,7 @@ bool SettingsDeserializer::DeserializeGeneralSettings(SSettingsGeneral& generalS if (port == 2 || (cameraSettings.eSyncOutMode[port] != ModeFixed100Hz)) { std::string signalPolarity; - if (TryReadElementString(syncOutElem, "Signal_Polarity", signalPolarity)) + if (syncOutElem.TryReadElementString("Signal_Polarity", signalPolarity)) { cameraSettings.bSyncOutNegativePolarity[port] = ToLowerXmlString(signalPolarity) == "negative"; } @@ -851,19 +851,19 @@ bool SettingsDeserializer::DeserializeGeneralSettings(SSettingsGeneral& generalS } } - if (auto lensControlElem = cameraElem.FirstChildElement("LensControl")) + if (auto lensControlElem = cameraElem.FindChild("LensControl")) { - auto focusElem = lensControlElem.FirstChildElement("Focus"); + auto focusElem = lensControlElem.FindChild("Focus"); if (focusElem) { - cameraSettings.fFocus = focusElem.FloatAttribute("Value", std::numeric_limits::quiet_NaN()); + cameraSettings.fFocus = focusElem.ReadAttributeFloat("Value", std::numeric_limits::quiet_NaN()); } - auto apertureElem = lensControlElem.FirstChildElement("Aperture"); + auto apertureElem = lensControlElem.FindChild("Aperture"); if (apertureElem) { cameraSettings.fAperture = apertureElem. - FloatAttribute("Value", std::numeric_limits::quiet_NaN()); + ReadAttributeFloat("Value", std::numeric_limits::quiet_NaN()); } } else @@ -872,10 +872,10 @@ bool SettingsDeserializer::DeserializeGeneralSettings(SSettingsGeneral& generalS cameraSettings.fAperture = std::numeric_limits::quiet_NaN(); } - if (auto autoExposureElem = cameraElem.FirstChildElement("AutoExposure")) + if (auto autoExposureElem = cameraElem.FindChild("AutoExposure")) { - cameraSettings.autoExposureEnabled = autoExposureElem.BoolAttribute("Enabled", false); - cameraSettings.autoExposureCompensation = autoExposureElem.FloatAttribute( + cameraSettings.autoExposureEnabled = autoExposureElem.ReadAttributeBool("Enabled", false); + cameraSettings.autoExposureCompensation = autoExposureElem.ReadAttributeFloat( "Compensation", std::numeric_limits::quiet_NaN()); } else @@ -885,7 +885,7 @@ bool SettingsDeserializer::DeserializeGeneralSettings(SSettingsGeneral& generalS } bool autoWhiteBalance; - if (ReadXmlBool(cameraElem, "AutoWhiteBalance", autoWhiteBalance)) + if (cameraElem.TryReadElementBool("AutoWhiteBalance", autoWhiteBalance)) { cameraSettings.autoWhiteBalance = autoWhiteBalance ? 1 : 0; } @@ -911,15 +911,15 @@ bool SettingsDeserializer::Deserialize3DSettings(SSettings3D& settings3D, bool& return true; } - auto threeDElem = mDeserializer->FirstChildElement("The_3D"); + auto threeDElem = mDeserializer->FindChild("The_3D"); if (!threeDElem) { return true; } - if (auto axisUpwards = threeDElem.FirstChildElement("AxisUpwards")) + if (auto axisUpwards = threeDElem.FindChild("AxisUpwards")) { - auto str = ToLowerXmlString(axisUpwards.GetText()); + auto str = ToLowerXmlString(axisUpwards.ReadString()); if (str == "+x") { settings3D.eAxisUpwards = XPos; @@ -954,9 +954,9 @@ bool SettingsDeserializer::Deserialize3DSettings(SSettings3D& settings3D, bool& return false; } - if (auto calibrationTimeElem = threeDElem.FirstChildElement("CalibrationTime")) + if (auto calibrationTimeElem = threeDElem.FindChild("CalibrationTime")) { - auto str = calibrationTimeElem.GetText(); + auto str = calibrationTimeElem.ReadString(); strcpy_s(settings3D.pCalibrationTime, 32, str.data()); } else @@ -965,9 +965,9 @@ bool SettingsDeserializer::Deserialize3DSettings(SSettings3D& settings3D, bool& } std::size_t labelCount; - if (auto labelsElem = threeDElem.FirstChildElement("Labels")) + if (auto labelsElem = threeDElem.FindChild("Labels")) { - labelCount = labelsElem.IntText(0); + labelCount = labelsElem.ReadInt(0); } else { @@ -980,19 +980,19 @@ bool SettingsDeserializer::Deserialize3DSettings(SSettings3D& settings3D, bool& for (auto labelElem : ChildElementRange{threeDElem, "Label"}) { SSettings3DLabel label{}; - if (auto nameElem = labelElem.FirstChildElement("Name")) + if (auto nameElem = labelElem.FindChild("Name")) { - label.oName = nameElem.GetText(); + label.oName = nameElem.ReadString(); } - if (auto colorElem = labelElem.FirstChildElement("RGBColor")) + if (auto colorElem = labelElem.FindChild("RGBColor")) { - label.nRGBColor = colorElem.IntText(0); + label.nRGBColor = colorElem.ReadInt(0); } - if (auto typeElem = labelElem.FirstChildElement("Trajectory_Type")) + if (auto typeElem = labelElem.FindChild("Trajectory_Type")) { - label.type = typeElem.GetText(); + label.type = typeElem.ReadString(); } settings3D.s3DLabels.push_back(label); @@ -1003,14 +1003,14 @@ bool SettingsDeserializer::Deserialize3DSettings(SSettings3D& settings3D, bool& return false; } - if (auto bonesElem = threeDElem.FirstChildElement("Bones")) + if (auto bonesElem = threeDElem.FindChild("Bones")) { for (auto boneElem : ChildElementRange{bonesElem, "Bone"}) { SSettingsBone bone{}; - bone.fromName = boneElem.Attribute("From"); - bone.toName = boneElem.Attribute("To"); - bone.color = boneElem.UnsignedAttribute("Color", bone.color); + bone.fromName = boneElem.ReadAttributeString("From"); + bone.toName = boneElem.ReadAttributeString("To"); + bone.color = boneElem.ReadAttributeUnsignedInt("Color", bone.color); settings3D.sBones.push_back(bone); } } @@ -1026,9 +1026,9 @@ namespace { if (majorVer > 1 || minorVer > 23) { - if (auto enabledElem = deserializer.FirstChildElement("Enabled")) + if (auto enabledElem = deserializer.FindChild("Enabled")) { - target = enabledElem.GetText() == "true"; + target = enabledElem.ReadString() == "true"; return true; } } @@ -1041,11 +1041,11 @@ namespace bool TryReadAttributesRGBColor(DeserializerApi& deserializer, std::uint32_t& target) { - if (auto elem = deserializer.FirstChildElement("Color")) + if (auto elem = deserializer.FindChild("Color")) { - std::uint32_t colorR = elem.UnsignedAttribute("R"); - std::uint32_t colorG = elem.UnsignedAttribute("G"); - std::uint32_t colorB = elem.UnsignedAttribute("B"); + std::uint32_t colorR = elem.ReadAttributeUnsignedInt("R"); + std::uint32_t colorG = elem.ReadAttributeUnsignedInt("G"); + std::uint32_t colorB = elem.ReadAttributeUnsignedInt("B"); target = (colorR & 0xff) | ((colorG << 8) & 0xff00) | ((colorB << 16) & 0xff0000); return true; } @@ -1056,9 +1056,9 @@ namespace bool TryReadSetFilter(DeserializerApi& deserializer, std::string& target) { - if (auto elem = deserializer.FirstChildElement("Filter")) + if (auto elem = deserializer.FindChild("Filter")) { - target = elem.Attribute("Preset"); + target = elem.ReadAttributeString("Preset"); return true; } @@ -1067,11 +1067,11 @@ namespace bool TryReadSetPos(DeserializerApi& deserializer, float& targetX, float& targetY, float& targetZ) { - if (auto elem = deserializer.FirstChildElement("Position")) + if (auto elem = deserializer.FindChild("Position")) { - targetX = elem.FloatAttribute("X"); - targetY = elem.FloatAttribute("Y"); - targetZ = elem.FloatAttribute("Z"); + targetX = elem.ReadAttributeFloat("X"); + targetY = elem.ReadAttributeFloat("Y"); + targetZ = elem.ReadAttributeFloat("Z"); return true; } @@ -1081,11 +1081,11 @@ namespace bool TryReadSetRotation(DeserializerApi& deserializer, float& targetX, float& targetY, float& targetZ) { - if (auto elem = deserializer.FirstChildElement("Rotation")) + if (auto elem = deserializer.FindChild("Rotation")) { - targetX = elem.FloatAttribute("X"); - targetY = elem.FloatAttribute("Y"); - targetZ = elem.FloatAttribute("Z"); + targetX = elem.ReadAttributeFloat("X"); + targetY = elem.ReadAttributeFloat("Y"); + targetZ = elem.ReadAttributeFloat("Z"); return true; } @@ -1096,19 +1096,19 @@ namespace bool TryReadSetPoints(DeserializerApi& deserializer, std::vector& target) { - if (auto pointsElem = deserializer.FirstChildElement("Points")) + if (auto pointsElem = deserializer.FindChild("Points")) { for (auto pointElem : ChildElementRange{pointsElem, "Point"}) { SBodyPoint bodyPoint; - bodyPoint.fX = pointElem.FloatAttribute("X"); - bodyPoint.fY = pointElem.FloatAttribute("Y"); - bodyPoint.fZ = pointElem.FloatAttribute("Z"); + bodyPoint.fX = pointElem.ReadAttributeFloat("X"); + bodyPoint.fY = pointElem.ReadAttributeFloat("Y"); + bodyPoint.fZ = pointElem.ReadAttributeFloat("Z"); - bodyPoint.virtual_ = 0 != pointElem.UnsignedAttribute("Virtual"); - bodyPoint.physicalId = pointElem.UnsignedAttribute("PhysicalId"); - bodyPoint.name = pointElem.Attribute("Name"); + bodyPoint.virtual_ = 0 != pointElem.ReadAttributeUnsignedInt("Virtual"); + bodyPoint.physicalId = pointElem.ReadAttributeUnsignedInt("PhysicalId"); + bodyPoint.name = pointElem.ReadAttributeString("Name"); target.push_back(bodyPoint); } @@ -1120,13 +1120,13 @@ namespace bool TryReadSetDataOrigin(DeserializerApi& deserializer, SOrigin& target) { - if (auto elem = deserializer.FirstChildElement("Data_origin")) + if (auto elem = deserializer.FindChild("Data_origin")) { - target.type = static_cast(elem.UnsignedText()); - target.position.fX = elem.FloatAttribute("X"); - target.position.fY = elem.FloatAttribute("Y"); - target.position.fZ = elem.FloatAttribute("Z"); - target.relativeBody = elem.UnsignedAttribute("Relative_body"); + target.type = static_cast(elem.ReadUnsignedInt()); + target.position.fX = elem.ReadAttributeFloat("X"); + target.position.fY = elem.ReadAttributeFloat("Y"); + target.position.fZ = elem.ReadAttributeFloat("Z"); + target.relativeBody = elem.ReadAttributeUnsignedInt("Relative_body"); } else { @@ -1134,18 +1134,18 @@ namespace return false; } - if (auto elem = deserializer.FirstChildElement("Data_orientation")) + if (auto elem = deserializer.FindChild("Data_orientation")) { char tmpStr[10]; for (std::uint32_t i = 0; i < 9; i++) { (void)sprintf_s(tmpStr, 10, "R%u%u", (i / 3) + 1, (i % 3) + 1); - target.rotation[i] = elem.FloatAttribute(tmpStr); + target.rotation[i] = elem.ReadAttributeFloat(tmpStr); } - auto type = static_cast(elem.UnsignedText()); - auto body = static_cast(elem.UnsignedAttribute("Relative_body")); + auto type = static_cast(elem.ReadUnsignedInt()); + auto body = static_cast(elem.ReadAttributeUnsignedInt("Relative_body")); // Validation: type and relativeBody must be the same between orientation and origin return type == target.type && body == target.relativeBody; @@ -1157,9 +1157,9 @@ namespace bool TryReadElementRGBColor(DeserializerApi& deserializer, std::uint32_t& target) { - if (auto elem = deserializer.FirstChildElement("RGBColor")) + if (auto elem = deserializer.FindChild("RGBColor")) { - target = elem.IntText(); + target = elem.ReadInt(); return true; } @@ -1174,17 +1174,17 @@ namespace { SBodyPoint point; - if (!TryReadElementFloat(pointElem, "X", point.fX)) + if (!pointElem.TryReadElementFloat("X", point.fX)) { return false; } - if (!TryReadElementFloat(pointElem, "Y", point.fY)) + if (!pointElem.TryReadElementFloat("Y", point.fY)) { return false; } - if (!TryReadElementFloat(pointElem, "Z", point.fZ)) + if (!pointElem.TryReadElementFloat("Z", point.fZ)) { return false; } @@ -1197,11 +1197,11 @@ namespace bool TryReadSetEuler(DeserializerApi& deserializer, std::string& targetFirst, std::string& targetSecond, std::string& targetThird) { - if (auto elem = deserializer.FirstChildElement("Euler")) + if (auto elem = deserializer.FindChild("Euler")) { - return TryReadElementString(elem, "First", targetFirst) - && TryReadElementString(elem, "Second", targetSecond) - && TryReadElementString(elem, "Third", targetThird); + return elem.TryReadElementString("First", targetFirst) + && elem.TryReadElementString("Second", targetSecond) + && elem.TryReadElementString("Third", targetThird); } return false; @@ -1223,7 +1223,7 @@ bool SettingsDeserializer::Deserialize6DOFSettings(std::vectorFirstChildElement("The_6D"); + DeserializerApi sixDofElem = mDeserializer->FindChild("The_6D"); if (!sixDofElem) { return true; // NO eye tracker data available. @@ -1235,7 +1235,7 @@ bool SettingsDeserializer::Deserialize6DOFSettings(std::vectorFirstChildElement("Bodies")) + if (!mDeserializer->FindChild("Bodies")) { return false; } @@ -1295,7 +1295,7 @@ bool SettingsDeserializer::Deserialize6DOFSettings(std::vectorFirstChildElement("Gaze_Vector"); + DeserializerApi gazeVectorElem = mDeserializer->FindChild("Gaze_Vector"); if (!gazeVectorElem) { return true; // NO eye tracker data available. @@ -1344,9 +1344,9 @@ bool SettingsDeserializer::DeserializeGazeVectorSettings(std::vectorFirstChildElement("Eye_Tracker"); + DeserializerApi eyeTrackerElem = mDeserializer->FindChild("Eye_Tracker"); if (!eyeTrackerElem) { @@ -1394,9 +1394,9 @@ bool SettingsDeserializer::DeserializeEyeTrackerSettings(std::vector& return true; } - auto analogElem = mDeserializer->FirstChildElement("Analog"); + auto analogElem = mDeserializer->FindChild("Analog"); if (!analogElem) { // No analog data available. @@ -1442,17 +1442,17 @@ bool SettingsDeserializer::DeserializeAnalogSettings(std::vector& SAnalogDevice analogDevice{}; analogDevice.nDeviceID = 1; // Always channel 1 analogDevice.oName = "AnalogDevice"; - if (!TryReadElementUnsignedInt32(analogElem, "Channels", analogDevice.nChannels) - || !TryReadElementUnsignedInt32(analogElem, "Frequency", analogDevice.nFrequency) - || !TryReadElementString(analogElem, "Unit", analogDevice.oUnit)) + if (!analogElem.TryReadElementUnsignedInt32("Channels", analogDevice.nChannels) + || !analogElem.TryReadElementUnsignedInt32("Frequency", analogDevice.nFrequency) + || !analogElem.TryReadElementString("Unit", analogDevice.oUnit)) { return false; } - auto rangeElem = analogElem.FirstChildElement("Range"); + auto rangeElem = analogElem.FindChild("Range"); if (!rangeElem - || !TryReadElementFloat(rangeElem, "Min", analogDevice.fMinRange) - || !TryReadElementFloat(rangeElem, "Max", analogDevice.fMaxRange)) + || !rangeElem.TryReadElementFloat("Min", analogDevice.fMinRange) + || !rangeElem.TryReadElementFloat("Max", analogDevice.fMaxRange)) { return false; } @@ -1465,10 +1465,10 @@ bool SettingsDeserializer::DeserializeAnalogSettings(std::vector& for (auto deviceElem : ChildElementRange{analogElem, "Device"}) { SAnalogDevice analogDevice{}; - if (!TryReadElementUnsignedInt32(deviceElem, "Device_ID", analogDevice.nDeviceID) - || !TryReadElementString(deviceElem, "Device_Name", analogDevice.oName) - || !TryReadElementUnsignedInt32(deviceElem, "Channels", analogDevice.nChannels) - || !TryReadElementUnsignedInt32(deviceElem, "Frequency", analogDevice.nFrequency) + if (!deviceElem.TryReadElementUnsignedInt32("Device_ID", analogDevice.nDeviceID) + || !deviceElem.TryReadElementString("Device_Name", analogDevice.oName) + || !deviceElem.TryReadElementUnsignedInt32("Channels", analogDevice.nChannels) + || !deviceElem.TryReadElementUnsignedInt32("Frequency", analogDevice.nFrequency) ) { continue; @@ -1476,16 +1476,16 @@ bool SettingsDeserializer::DeserializeAnalogSettings(std::vector& if (mMajorVersion == 1 && mMinorVersion < 11) { - if (!TryReadElementString(analogElem, "Unit", analogDevice.oUnit)) + if (!analogElem.TryReadElementString("Unit", analogDevice.oUnit)) { continue; } } - auto rangeElem = deviceElem.FirstChildElement("Range"); + auto rangeElem = deviceElem.FindChild("Range"); if (!rangeElem - || !TryReadElementFloat(rangeElem, "Min", analogDevice.fMinRange) - || !TryReadElementFloat(rangeElem, "Max", analogDevice.fMaxRange)) + || !rangeElem.TryReadElementFloat("Min", analogDevice.fMinRange) + || !rangeElem.TryReadElementFloat("Max", analogDevice.fMaxRange)) { continue; } @@ -1495,7 +1495,7 @@ bool SettingsDeserializer::DeserializeAnalogSettings(std::vector& for (std::size_t i = 0; i < analogDevice.nChannels; i++) { std::string label; - if (TryReadElementString(deviceElem, "Label", label)) + if (deviceElem.TryReadElementString("Label", label)) { analogDevice.voLabels.push_back(label); } @@ -1511,13 +1511,13 @@ bool SettingsDeserializer::DeserializeAnalogSettings(std::vector& for (auto channelElem : ChildElementRange{deviceElem, "Channel"}) { std::string label; - if (TryReadElementString(channelElem, "Label", label)) + if (channelElem.TryReadElementString("Label", label)) { analogDevice.voLabels.push_back(label); } std::string unit; - if (TryReadElementString(channelElem, "Unit", unit)) + if (channelElem.TryReadElementString("Unit", unit)) { analogDevice.voUnits.push_back(unit); } @@ -1548,7 +1548,7 @@ bool SettingsDeserializer::DeserializeForceSettings(SSettingsForce& forceSetting return true; } - auto forceElem = mDeserializer->FirstChildElement("Force"); + auto forceElem = mDeserializer->FindChild("Force"); if (!forceElem) { // No analog data available. @@ -1560,12 +1560,12 @@ bool SettingsDeserializer::DeserializeForceSettings(SSettingsForce& forceSetting forcePlate.nCalibrationMatrixRows = 6; forcePlate.nCalibrationMatrixColumns = 6; - if (!TryReadElementString(forceElem, "Unit_Length", forceSettings.oUnitLength)) + if (!forceElem.TryReadElementString("Unit_Length", forceSettings.oUnitLength)) { return false; } - if (!TryReadElementString(forceElem, "Unit_Force", forceSettings.oUnitForce)) + if (!forceElem.TryReadElementString("Unit_Force", forceSettings.oUnitForce)) { return false; } @@ -1575,39 +1575,39 @@ bool SettingsDeserializer::DeserializeForceSettings(SSettingsForce& forceSetting { iPlate++; - if (!TryReadElementUnsignedInt32(plateElem, "Plate_ID", forcePlate.nID)) + if (!plateElem.TryReadElementUnsignedInt32("Plate_ID", forcePlate.nID)) { - if (!TryReadElementUnsignedInt32(plateElem, "Force_Plate_Index", forcePlate.nID)) - // Version 1.7 and earlier. + if (!plateElem.TryReadElementUnsignedInt32("Force_Plate_Index", forcePlate.nID)) + // Version 1.7 and earlier. { return false; } } - if (!TryReadElementUnsignedInt32(plateElem, "Analog_Device_ID", forcePlate.nAnalogDeviceID)) + if (!plateElem.TryReadElementUnsignedInt32("Analog_Device_ID", forcePlate.nAnalogDeviceID)) { forcePlate.nAnalogDeviceID = 0; } - if (!TryReadElementUnsignedInt32(plateElem, "Frequency", forcePlate.nFrequency)) + if (!plateElem.TryReadElementUnsignedInt32("Frequency", forcePlate.nFrequency)) { return false; } - if (!TryReadElementString(plateElem, "Type", forcePlate.oType)) + if (!plateElem.TryReadElementString("Type", forcePlate.oType)) { forcePlate.oType = "unknown"; } - if (!TryReadElementString(plateElem, "Name", forcePlate.oName)) + if (!plateElem.TryReadElementString("Name", forcePlate.oName)) { forcePlate.oName = "#" + std::to_string(iPlate); } - TryReadElementFloat(plateElem, "Length", forcePlate.fLength); - TryReadElementFloat(plateElem, "Width", forcePlate.fWidth); + plateElem.TryReadElementFloat("Length", forcePlate.fLength); + plateElem.TryReadElementFloat("Width", forcePlate.fWidth); - if (auto locationElem = plateElem.FirstChildElement("Location")) + if (auto locationElem = plateElem.FindChild("Location")) { struct Corner { @@ -1625,81 +1625,85 @@ bool SettingsDeserializer::DeserializeForceSettings(SSettingsForce& forceSetting for (const auto& c : corners) { - auto cornerElem = locationElem.FirstChildElement(c.name); - TryReadElementFloat(cornerElem, "X", forcePlate.asCorner[c.index].fX); - TryReadElementFloat(cornerElem, "Y", forcePlate.asCorner[c.index].fY); - TryReadElementFloat(cornerElem, "Z", forcePlate.asCorner[c.index].fZ); + auto cornerElem = locationElem.FindChild(c.name); + cornerElem.TryReadElementFloat("X", forcePlate.asCorner[c.index].fX); + cornerElem.TryReadElementFloat("Y", forcePlate.asCorner[c.index].fY); + cornerElem.TryReadElementFloat("Z", forcePlate.asCorner[c.index].fZ); } } - if (auto originElem = plateElem.FirstChildElement("Origin")) + if (auto originElem = plateElem.FindChild("Origin")) { - TryReadElementFloat(originElem, "X", forcePlate.sOrigin.fX); - TryReadElementFloat(originElem, "Y", forcePlate.sOrigin.fY); - TryReadElementFloat(originElem, "Z", forcePlate.sOrigin.fZ); + originElem.TryReadElementFloat("X", forcePlate.sOrigin.fX); + originElem.TryReadElementFloat("Y", forcePlate.sOrigin.fY); + originElem.TryReadElementFloat("Z", forcePlate.sOrigin.fZ); } forcePlate.vChannels.clear(); - if (auto channelsElem = plateElem.FirstChildElement("Channels")) + if (auto channelsElem = plateElem.FindChild("Channels")) { SForceChannel forceChannel{}; for (auto channelElem : ChildElementRange{channelsElem, "Channel"}) { - TryReadElementUnsignedInt32(channelElem, "Channel_No", forceChannel.nChannelNumber); - TryReadElementFloat(channelElem, "ConversionFactor", forceChannel.fConversionFactor); + channelElem.TryReadElementUnsignedInt32("Channel_No", forceChannel.nChannelNumber); + channelElem.TryReadElementFloat("ConversionFactor", forceChannel.fConversionFactor); forcePlate.vChannels.push_back(forceChannel); } } - if (auto calibrationMatrix = plateElem.FirstChildElement("Calibration_Matrix")) + if (auto calibrationMatrix = plateElem.FindChild("Calibration_Matrix")) { + forcePlate.nCalibrationMatrixRows = 0; + forcePlate.nCalibrationMatrixColumns = 0; + if (mMajorVersion == 1 && mMinorVersion < 12) { - auto getRowStr = [](auto& buff, std::size_t buffSize, std::size_t index)-> const char* { - sprintf_s(buff, buffSize, "Row%zd", index + 1); - return buff; - }; + auto getRowStr = [](std::size_t index) -> std::string { + return "Row" + std::to_string(index + 1); + }; - auto getColStr = [](auto& buff, std::size_t buffSize, std::size_t index)-> const char* { - sprintf_s(buff, buffSize, "Col%zd", index + 1); - return buff; - }; + auto getColStr = [](std::size_t index) -> std::string { + return "Col" + std::to_string(index + 1); + }; - unsigned int iRow = 0; - for (auto row : ChildElementRange{calibrationMatrix, getRowStr}) + std::size_t iRow = 0; + for (auto rowElem = calibrationMatrix.FindChild(getRowStr(iRow).c_str()); rowElem; rowElem = rowElem.FindNextSibling(getRowStr(++iRow).c_str())) { - unsigned int iCol = 0; - for (auto col : ChildElementRange{row, getColStr}) + std::size_t iCol = 0; + for (auto colElem = rowElem.FindChild(getColStr(iCol).c_str()); colElem; colElem = colElem.FindNextSibling(getColStr(++iCol).c_str())) { - forcePlate.afCalibrationMatrix[iRow][iCol++] = col.FloatText(); + forcePlate.afCalibrationMatrix[iRow][iCol] = colElem.ReadFloat(); } - iRow++; - forcePlate.nCalibrationMatrixColumns = iCol; + + forcePlate.nCalibrationMatrixColumns = std::max(static_cast(iCol),forcePlate.nCalibrationMatrixColumns); } - forcePlate.nCalibrationMatrixRows = iRow; + + forcePlate.nCalibrationMatrixRows = std::max(static_cast(iRow), forcePlate.nCalibrationMatrixRows); forcePlate.bValidCalibrationMatrix = true; } else { - auto rows = calibrationMatrix.FirstChildElement("Rows"); + auto rows = calibrationMatrix.FindChild("Rows"); if (rows) { unsigned int iRow = 0; for (auto rowElement : ChildElementRange{rows, "Row"}) { - auto columns = rowElement.FirstChildElement("Columns"); + auto columns = rowElement.FindChild("Columns"); if (columns) { unsigned int iCol = 0; for (const auto col : ChildElementRange{columns, "Column"}) { - forcePlate.afCalibrationMatrix[iRow][iCol++] = col.FloatText(); + forcePlate.afCalibrationMatrix[iRow][iCol++] = col.ReadFloat(); } - forcePlate.nCalibrationMatrixColumns = iCol; + + forcePlate.nCalibrationMatrixColumns = std::max(iCol, forcePlate.nCalibrationMatrixColumns); } iRow++; } - forcePlate.nCalibrationMatrixRows = iRow; + + forcePlate.nCalibrationMatrixRows = std::max(iRow, forcePlate.nCalibrationMatrixRows); forcePlate.bValidCalibrationMatrix = true; } } @@ -1723,28 +1727,28 @@ bool SettingsDeserializer::DeserializeImageSettings(std::vector& i return true; } - auto imageElem = mDeserializer->FirstChildElement("Image"); + auto imageElem = mDeserializer->FindChild("Image"); if (!imageElem) { return true; } - for (auto camera : ChildElementRange{imageElem, "Camera"}) + for (auto cameraElem : ChildElementRange{imageElem, "Camera"}) { SImageCamera imageCamera{}; - if (!TryReadElementUnsignedInt32(camera, "ID", imageCamera.nID)) + if (!cameraElem.TryReadElementUnsignedInt32("ID", imageCamera.nID)) { return false; } - if (!ReadXmlBool(camera, "Enabled", imageCamera.bEnabled)) + if (!cameraElem.TryReadElementBool("Enabled", imageCamera.bEnabled)) { return false; } std::string format; - if (!TryReadElementString(camera, "Format", format)) + if (!cameraElem.TryReadElementString("Format", format)) { return false; } @@ -1771,16 +1775,16 @@ bool SettingsDeserializer::DeserializeImageSettings(std::vector& i return false; } - if (!TryReadElementUnsignedInt32(camera, "Width", imageCamera.nWidth) - || !TryReadElementUnsignedInt32(camera, "Height", imageCamera.nHeight)) + if (!cameraElem.TryReadElementUnsignedInt32("Width", imageCamera.nWidth) + || !cameraElem.TryReadElementUnsignedInt32("Height", imageCamera.nHeight)) { return false; } - if (!TryReadElementFloat(camera, "Left_Crop", imageCamera.fCropLeft) - || !TryReadElementFloat(camera, "Top_Crop", imageCamera.fCropTop) - || !TryReadElementFloat(camera, "Right_Crop", imageCamera.fCropRight) - || !TryReadElementFloat(camera, "Bottom_Crop", imageCamera.fCropBottom)) + if (!cameraElem.TryReadElementFloat("Left_Crop", imageCamera.fCropLeft) + || !cameraElem.TryReadElementFloat("Top_Crop", imageCamera.fCropTop) + || !cameraElem.TryReadElementFloat("Right_Crop", imageCamera.fCropRight) + || !cameraElem.TryReadElementFloat("Bottom_Crop", imageCamera.fCropBottom)) { return false; } @@ -1794,12 +1798,43 @@ bool SettingsDeserializer::DeserializeImageSettings(std::vector& i namespace { + SPosition ReadSPosition(DeserializerApi& parentElem, const std::string& element) + { + auto positionElem = parentElem.FindChild(element.data()); + if (positionElem) + { + return { + positionElem.ReadAttributeDouble("X"), + positionElem.ReadAttributeDouble("Y"), + positionElem.ReadAttributeDouble("Z"), + }; + } + + return {}; + } + + SRotation ReadSRotation(DeserializerApi& parentElem, const std::string& element) + { + auto rotationElem = parentElem.FindChild(element.data()); + if (rotationElem) + { + return { + rotationElem.ReadAttributeDouble("X"), + rotationElem.ReadAttributeDouble("Y"), + rotationElem.ReadAttributeDouble("Z"), + rotationElem.ReadAttributeDouble("W") + }; + } + + return {}; + } + bool TryReadSDegreeOfFreedom(DeserializerApi& parentElement, const std::string& elementName, std::vector& degreesOfFreedom) { SDegreeOfFreedom degreeOfFreedom; - auto degreeOfFreedomElement = parentElement.FirstChildElement(elementName.data()); + auto degreeOfFreedomElement = parentElement.FindChild(elementName.data()); if (!degreeOfFreedomElement) { return false; @@ -1807,34 +1842,34 @@ namespace degreeOfFreedom.type = SkeletonStringToDofSettings(elementName); - if (auto constraintElem = degreeOfFreedomElement.FirstChildElement("Constraint")) + if (auto constraintElem = degreeOfFreedomElement.FindChild("Constraint")) { - degreeOfFreedom.lowerBound = constraintElem.DoubleAttribute("LowerBound"); - degreeOfFreedom.upperBound = constraintElem.DoubleAttribute("UpperBound"); + degreeOfFreedom.lowerBound = constraintElem.ReadAttributeDouble("LowerBound"); + degreeOfFreedom.upperBound = constraintElem.ReadAttributeDouble("UpperBound"); } else { - degreeOfFreedom.lowerBound = degreeOfFreedomElement.DoubleAttribute("LowerBound"); - degreeOfFreedom.upperBound = degreeOfFreedomElement.DoubleAttribute("UpperBound"); + degreeOfFreedom.lowerBound = degreeOfFreedomElement.ReadAttributeDouble("LowerBound"); + degreeOfFreedom.upperBound = degreeOfFreedomElement.ReadAttributeDouble("UpperBound"); } - if (auto couplingsElem = degreeOfFreedomElement.FirstChildElement("Couplings")) + if (auto couplingsElem = degreeOfFreedomElement.FindChild("Couplings")) { for (auto couplingElem : ChildElementRange{couplingsElem, "Coupling"}) { SCoupling coupling{}; - coupling.segment = couplingElem.Attribute("Segment"); - auto dof = couplingElem.Attribute("DegreeOfFreedom"); + coupling.segment = couplingElem.ReadAttributeString("Segment"); + auto dof = couplingElem.ReadAttributeString("DegreeOfFreedom"); coupling.degreeOfFreedom = SkeletonStringToDofSettings(dof); - coupling.coefficient = couplingElem.DoubleAttribute("Coefficient"); + coupling.coefficient = couplingElem.ReadAttributeDouble("Coefficient"); degreeOfFreedom.couplings.push_back(coupling); } } - if (auto goalElem = degreeOfFreedomElement.FirstChildElement("Goal")) + if (auto goalElem = degreeOfFreedomElement.FindChild("Goal")) { - degreeOfFreedom.goalValue = goalElem.DoubleAttribute("Value"); - degreeOfFreedom.goalWeight = goalElem.DoubleAttribute("Weight"); + degreeOfFreedom.goalValue = goalElem.ReadAttributeDouble("Value"); + degreeOfFreedom.goalWeight = goalElem.ReadAttributeDouble("Weight"); } degreesOfFreedom.push_back(degreeOfFreedom); @@ -1858,7 +1893,7 @@ bool SettingsDeserializer::DeserializeSkeletonSettings(bool skeletonGlobalData, return true; } - auto skeletonsElem = mDeserializer->FirstChildElement("Skeletons"); + auto skeletonsElem = mDeserializer->FindChild("Skeletons"); if (!skeletonsElem) { return true; @@ -1875,13 +1910,13 @@ bool SettingsDeserializer::DeserializeSkeletonSettings(bool skeletonGlobalData, SSettingsSkeleton skeleton{}; segmentIndex = 0; - skeletonHierarchical.name = skeletonElem.Attribute("Name"); + skeletonHierarchical.name = skeletonElem.ReadAttributeString("Name"); skeleton.name = skeletonHierarchical.name; - TryReadElementString(skeletonElem, "Solver", skeletonHierarchical.rootSegment.solver); - TryReadElementDouble(skeletonElem, "Scale", skeletonHierarchical.scale); + skeletonElem.TryReadElementString("Solver", skeletonHierarchical.rootSegment.solver); + skeletonElem.TryReadElementDouble("Scale", skeletonHierarchical.scale); - if (auto segmentsElem = skeletonElem.FirstChildElement("Segments")) + if (auto segmentsElem = skeletonElem.FindChild("Segments")) { std::function&, std::uint32_t)> recurseSegments @@ -1889,26 +1924,26 @@ bool SettingsDeserializer::DeserializeSkeletonSettings(bool skeletonGlobalData, DeserializerApi& segmentElem, SSettingsSkeletonSegmentHierarchical& segmentHierarchical, std::vector& segments, std::uint32_t parentId) { - segmentHierarchical.name = segmentElem.Attribute("Name"); + segmentHierarchical.name = segmentElem.ReadAttributeString("Name"); - TryReadElementUnsignedInt32(segmentElem, "ID", segmentHierarchical.id); + segmentElem.TryReadElementUnsignedInt32("ID", segmentHierarchical.id); segmentIdIndexMap[segmentHierarchical.id] = segmentIndex++; - TryReadElementString(segmentElem, "Solver", segmentHierarchical.solver); + segmentElem.TryReadElementString("Solver", segmentHierarchical.solver); - if (auto transformElem = segmentElem.FirstChildElement("Transform")) + if (auto transformElem = segmentElem.FindChild("Transform")) { segmentHierarchical.position = ReadSPosition(transformElem, "Position"); segmentHierarchical.rotation = ReadSRotation(transformElem, "Rotation"); } - if (auto defaultTransformElem = segmentElem.FirstChildElement("DefaultTransform")) + if (auto defaultTransformElem = segmentElem.FindChild("DefaultTransform")) { segmentHierarchical.defaultPosition = ReadSPosition(defaultTransformElem, "Position"); segmentHierarchical.defaultRotation = ReadSRotation(defaultTransformElem, "Rotation"); } - if (auto degreesOfFreedomElem = segmentElem.FirstChildElement("DegreesOfFreedom")) + if (auto degreesOfFreedomElem = segmentElem.FindChild("DegreesOfFreedom")) { TryReadSDegreeOfFreedom(degreesOfFreedomElem, "RotationX", segmentHierarchical.degreesOfFreedom); @@ -1926,17 +1961,17 @@ bool SettingsDeserializer::DeserializeSkeletonSettings(bool skeletonGlobalData, segmentHierarchical.endpoint = ReadSPosition(segmentElem, "Endpoint"); - if (auto markersElem = segmentElem.FirstChildElement("Markers")) + if (auto markersElem = segmentElem.FindChild("Markers")) { for (auto markerElem : ChildElementRange{markersElem, "Marker"}) { SMarker marker; - marker.name = markerElem.Attribute("Name"); + marker.name = markerElem.ReadAttributeString("Name"); marker.position = ReadSPosition(markerElem, "Position"); - if (!TryReadElementDouble(markerElem, "Weight", marker.weight)) + if (!markerElem.TryReadElementDouble("Weight", marker.weight)) { marker.weight = 1.0; } @@ -1945,22 +1980,22 @@ bool SettingsDeserializer::DeserializeSkeletonSettings(bool skeletonGlobalData, } } - if (auto rigidBodiesElem = segmentElem.FirstChildElement("Markers")) + if (auto rigidBodiesElem = segmentElem.FindChild("Markers")) { for (auto rigidBodyElem : ChildElementRange{rigidBodiesElem, "RigidBody"}) { SBody body; - body.name = rigidBodyElem.Attribute("Name"); + body.name = rigidBodyElem.ReadAttributeString("Name"); - auto rbodyTransformElem = rigidBodyElem.FirstChildElement("Transform"); + auto rbodyTransformElem = rigidBodyElem.FindChild("Transform"); if (rbodyTransformElem) { body.position = ReadSPosition(rbodyTransformElem, "Position"); body.rotation = ReadSRotation(rbodyTransformElem, "Rotation"); } - if (!TryReadElementDouble(rbodyTransformElem, "Weight", body.weight)) + if (!rbodyTransformElem.TryReadElementDouble("Weight", body.weight)) { body.weight = 1.0; } @@ -1992,7 +2027,7 @@ bool SettingsDeserializer::DeserializeSkeletonSettings(bool skeletonGlobalData, } }; - if (auto rootSegmentElem = segmentsElem.FirstChildElement("Segment")) + if (auto rootSegmentElem = segmentsElem.FindChild("Segment")) { recurseSegments(rootSegmentElem, skeletonHierarchical.rootSegment, skeleton.segments, -1); } @@ -2010,34 +2045,33 @@ bool SettingsDeserializer::DeserializeSkeletonSettings(bool skeletonGlobalData, { SSettingsSkeleton skeleton{}; segmentIndex = 0; - skeleton.name = skeletonElem.Attribute("Name"); + skeleton.name = skeletonElem.ReadAttributeString("Name"); for (auto segmentElem : ChildElementRange{skeletonElem, "Segment"}) { SSettingsSkeletonSegment segment{}; - segment.name = segmentElem.Attribute("Name"); - segment.id = segmentElem.UnsignedAttribute("ID"); + segment.name = segmentElem.ReadAttributeString("Name"); + segment.id = segmentElem.ReadAttributeUnsignedInt("ID"); segmentIdIndexMap[segment.id] = segmentIndex++; - segment.parentId = segmentElem.IntAttribute("Parent_ID", -1); + segment.parentId = segmentElem.ReadAttributeInt("Parent_ID", -1); segment.parentIndex = -1; if (segmentIdIndexMap.count(segment.parentId) > 0) { segment.parentIndex = segmentIdIndexMap[segment.parentId]; } - - if (auto positionElement = segmentElem.FirstChildElement("Position")) + if (auto positionElement = segmentElem.FindChild("Position")) { - segment.positionX = positionElement.FloatAttribute("X"); - segment.positionY = positionElement.FloatAttribute("Y"); - segment.positionZ = positionElement.FloatAttribute("Z"); + segment.positionX = positionElement.ReadAttributeFloat("X"); + segment.positionY = positionElement.ReadAttributeFloat("Y"); + segment.positionZ = positionElement.ReadAttributeFloat("Z"); } - if (auto rotationElement = segmentElem.FirstChildElement("Rotation")) + if (auto rotationElement = segmentElem.FindChild("Rotation")) { - segment.rotationX = rotationElement.FloatAttribute("X"); - segment.rotationY = rotationElement.FloatAttribute("Y"); - segment.rotationZ = rotationElement.FloatAttribute("Z"); - segment.rotationW = rotationElement.FloatAttribute("W"); + segment.rotationX = rotationElement.ReadAttributeFloat("X"); + segment.rotationY = rotationElement.ReadAttributeFloat("Y"); + segment.rotationZ = rotationElement.ReadAttributeFloat("Z"); + segment.rotationW = rotationElement.ReadAttributeFloat("W"); } skeleton.segments.push_back(segment); @@ -2054,16 +2088,16 @@ namespace { bool TryReadXmlFov(std::string name, DeserializerApi& parentElement, SCalibrationFov& fov) { - auto childElement = parentElement.FirstChildElement(name.data()); + auto childElement = parentElement.FindChild(name.data()); if (!childElement) { return false; } - fov.left = childElement.UnsignedAttribute("left"); - fov.top = childElement.UnsignedAttribute("top"); - fov.right = childElement.UnsignedAttribute("right"); - fov.bottom = childElement.UnsignedAttribute("bottom"); + fov.left = childElement.ReadAttributeUnsignedInt("left"); + fov.top = childElement.ReadAttributeUnsignedInt("top"); + fov.right = childElement.ReadAttributeUnsignedInt("right"); + fov.bottom = childElement.ReadAttributeUnsignedInt("bottom"); return true; } @@ -2078,7 +2112,7 @@ bool SettingsDeserializer::DeserializeCalibrationSettings(SCalibration& calibrat return true; } - auto calibrationElem = mDeserializer->FirstChildElement("calibration"); + auto calibrationElem = mDeserializer->FindChild("calibration"); if (!calibrationElem) { return false; @@ -2086,12 +2120,12 @@ bool SettingsDeserializer::DeserializeCalibrationSettings(SCalibration& calibrat try { - settings.calibrated = calibrationElem.BoolAttribute("calibrated"); - settings.source = calibrationElem.Attribute("source"); - settings.created = calibrationElem.Attribute("created"); - settings.qtm_version = calibrationElem.Attribute("qtm-version"); + settings.calibrated = calibrationElem.ReadAttributeBool("calibrated"); + settings.source = calibrationElem.ReadAttributeString("source"); + settings.created = calibrationElem.ReadAttributeString("created"); + settings.qtm_version = calibrationElem.ReadAttributeString("qtm-version"); - std::string typeStr = ToLowerXmlString(calibrationElem.Attribute("type")); + std::string typeStr = ToLowerXmlString(calibrationElem.ReadAttributeString("type")); if (typeStr == "regular") { settings.type = ECalibrationType::regular; @@ -2107,34 +2141,34 @@ bool SettingsDeserializer::DeserializeCalibrationSettings(SCalibration& calibrat if (settings.type == ECalibrationType::refine) { - settings.refit_residual = calibrationElem.DoubleAttribute("refit-residual"); + settings.refit_residual = calibrationElem.ReadAttributeDouble("refit-residual"); } if (settings.type != ECalibrationType::fixed) { - settings.wand_length = calibrationElem.DoubleAttribute("wandLength"); - settings.max_frames = calibrationElem.UnsignedAttribute("maximumFrames"); - settings.short_arm_end = calibrationElem.DoubleAttribute("shortArmEnd"); - settings.long_arm_end = calibrationElem.DoubleAttribute("longArmEnd"); - settings.long_arm_middle = calibrationElem.DoubleAttribute("longArmMiddle"); + settings.wand_length = calibrationElem.ReadAttributeDouble("wandLength"); + settings.max_frames = calibrationElem.ReadAttributeUnsignedInt("maximumFrames"); + settings.short_arm_end = calibrationElem.ReadAttributeDouble("shortArmEnd"); + settings.long_arm_end = calibrationElem.ReadAttributeDouble("longArmEnd"); + settings.long_arm_middle = calibrationElem.ReadAttributeDouble("longArmMiddle"); - auto resultsElem = calibrationElem.FirstChildElement("results"); + auto resultsElem = calibrationElem.FindChild("results"); if (!resultsElem) { return false; } - settings.result_std_dev = resultsElem.DoubleAttribute("std-dev"); - settings.result_min_max_diff = resultsElem.DoubleAttribute("min-max-diff"); + settings.result_std_dev = resultsElem.ReadAttributeDouble("std-dev"); + settings.result_min_max_diff = resultsElem.ReadAttributeDouble("min-max-diff"); if (settings.type == ECalibrationType::refine) { - settings.result_refit_residual = resultsElem.DoubleAttribute("refit-residual"); - settings.result_consecutive = resultsElem.UnsignedAttribute("consecutive"); + settings.result_refit_residual = resultsElem.ReadAttributeDouble("refit-residual"); + settings.result_consecutive = resultsElem.ReadAttributeUnsignedInt("consecutive"); } } - auto camerasElem = calibrationElem.FirstChildElement("cameras"); + auto camerasElem = calibrationElem.FindChild("cameras"); if (!camerasElem) { return false; @@ -2143,15 +2177,15 @@ bool SettingsDeserializer::DeserializeCalibrationSettings(SCalibration& calibrat for (auto cameraElem : ChildElementRange{camerasElem, "camera"}) { SCalibrationCamera camera{}; - camera.active = cameraElem.UnsignedAttribute("active") != 0; - camera.calibrated = cameraElem.BoolAttribute("calibrated"); - camera.message = cameraElem.Attribute("message"); + camera.active = cameraElem.ReadAttributeUnsignedInt("active") != 0; + camera.calibrated = cameraElem.ReadAttributeBool("calibrated"); + camera.message = cameraElem.ReadAttributeString("message"); - camera.point_count = cameraElem.UnsignedAttribute("point-count"); - camera.avg_residual = cameraElem.DoubleAttribute("avg-residual"); - camera.serial = cameraElem.UnsignedAttribute("serial"); - camera.model = cameraElem.Attribute("model"); - camera.view_rotation = cameraElem.UnsignedAttribute("viewrotation"); + camera.point_count = cameraElem.ReadAttributeUnsignedInt("point-count"); + camera.avg_residual = cameraElem.ReadAttributeDouble("avg-residual"); + camera.serial = cameraElem.ReadAttributeUnsignedInt("serial"); + camera.model = cameraElem.ReadAttributeString("model"); + camera.view_rotation = cameraElem.ReadAttributeUnsignedInt("viewrotation"); if (!TryReadXmlFov("fov_marker", cameraElem, camera.fov_marker)) { @@ -2173,46 +2207,46 @@ bool SettingsDeserializer::DeserializeCalibrationSettings(SCalibration& calibrat return false; } - auto transformElem = cameraElem.FirstChildElement("transform"); + auto transformElem = cameraElem.FindChild("transform"); if (!transformElem) { return false; } - camera.transform.x = transformElem.DoubleAttribute("x"); - camera.transform.y = transformElem.DoubleAttribute("y"); - camera.transform.z = transformElem.DoubleAttribute("z"); - camera.transform.r11 = transformElem.DoubleAttribute("r11"); - camera.transform.r12 = transformElem.DoubleAttribute("r12"); - camera.transform.r13 = transformElem.DoubleAttribute("r13"); - camera.transform.r21 = transformElem.DoubleAttribute("r21"); - camera.transform.r22 = transformElem.DoubleAttribute("r22"); - camera.transform.r23 = transformElem.DoubleAttribute("r23"); - camera.transform.r31 = transformElem.DoubleAttribute("r31"); - camera.transform.r32 = transformElem.DoubleAttribute("r32"); - camera.transform.r33 = transformElem.DoubleAttribute("r33"); - - auto intrinsicElem = cameraElem.FirstChildElement("intrinsic"); + camera.transform.x = transformElem.ReadAttributeDouble("x"); + camera.transform.y = transformElem.ReadAttributeDouble("y"); + camera.transform.z = transformElem.ReadAttributeDouble("z"); + camera.transform.r11 = transformElem.ReadAttributeDouble("r11"); + camera.transform.r12 = transformElem.ReadAttributeDouble("r12"); + camera.transform.r13 = transformElem.ReadAttributeDouble("r13"); + camera.transform.r21 = transformElem.ReadAttributeDouble("r21"); + camera.transform.r22 = transformElem.ReadAttributeDouble("r22"); + camera.transform.r23 = transformElem.ReadAttributeDouble("r23"); + camera.transform.r31 = transformElem.ReadAttributeDouble("r31"); + camera.transform.r32 = transformElem.ReadAttributeDouble("r32"); + camera.transform.r33 = transformElem.ReadAttributeDouble("r33"); + + auto intrinsicElem = cameraElem.FindChild("intrinsic"); if (!intrinsicElem) { return false; } - camera.intrinsic.focal_length = intrinsicElem.DoubleAttribute("focallength", 0); - camera.intrinsic.sensor_min_u = intrinsicElem.DoubleAttribute("sensorMinU"); - camera.intrinsic.sensor_max_u = intrinsicElem.DoubleAttribute("sensorMaxU"); - camera.intrinsic.sensor_min_v = intrinsicElem.DoubleAttribute("sensorMinV"); - camera.intrinsic.sensor_max_v = intrinsicElem.DoubleAttribute("sensorMaxV"); - camera.intrinsic.focal_length_u = intrinsicElem.DoubleAttribute("focalLengthU"); - camera.intrinsic.focal_length_v = intrinsicElem.DoubleAttribute("focalLengthV"); - camera.intrinsic.center_point_u = intrinsicElem.DoubleAttribute("centerPointU"); - camera.intrinsic.center_point_v = intrinsicElem.DoubleAttribute("centerPointV"); - camera.intrinsic.skew = intrinsicElem.DoubleAttribute("skew"); - camera.intrinsic.radial_distortion_1 = intrinsicElem.DoubleAttribute("radialDistortion1"); - camera.intrinsic.radial_distortion_2 = intrinsicElem.DoubleAttribute("radialDistortion2"); - camera.intrinsic.radial_distortion_3 = intrinsicElem.DoubleAttribute("radialDistortion3"); - camera.intrinsic.tangental_distortion_1 = intrinsicElem.DoubleAttribute("tangentalDistortion1"); - camera.intrinsic.tangental_distortion_2 = intrinsicElem.DoubleAttribute("tangentalDistortion2"); + camera.intrinsic.focal_length = intrinsicElem.ReadAttributeDouble("focallength", 0); + camera.intrinsic.sensor_min_u = intrinsicElem.ReadAttributeDouble("sensorMinU"); + camera.intrinsic.sensor_max_u = intrinsicElem.ReadAttributeDouble("sensorMaxU"); + camera.intrinsic.sensor_min_v = intrinsicElem.ReadAttributeDouble("sensorMinV"); + camera.intrinsic.sensor_max_v = intrinsicElem.ReadAttributeDouble("sensorMaxV"); + camera.intrinsic.focal_length_u = intrinsicElem.ReadAttributeDouble("focalLengthU"); + camera.intrinsic.focal_length_v = intrinsicElem.ReadAttributeDouble("focalLengthV"); + camera.intrinsic.center_point_u = intrinsicElem.ReadAttributeDouble("centerPointU"); + camera.intrinsic.center_point_v = intrinsicElem.ReadAttributeDouble("centerPointV"); + camera.intrinsic.skew = intrinsicElem.ReadAttributeDouble("skew"); + camera.intrinsic.radial_distortion_1 = intrinsicElem.ReadAttributeDouble("radialDistortion1"); + camera.intrinsic.radial_distortion_2 = intrinsicElem.ReadAttributeDouble("radialDistortion2"); + camera.intrinsic.radial_distortion_3 = intrinsicElem.ReadAttributeDouble("radialDistortion3"); + camera.intrinsic.tangental_distortion_1 = intrinsicElem.ReadAttributeDouble("tangentalDistortion1"); + camera.intrinsic.tangental_distortion_2 = intrinsicElem.ReadAttributeDouble("tangentalDistortion2"); settings.cameras.push_back(camera); } } diff --git a/SettingsSerializer.cpp b/SettingsSerializer.cpp index 89089b5..664af7f 100644 --- a/SettingsSerializer.cpp +++ b/SettingsSerializer.cpp @@ -23,7 +23,84 @@ std::string SettingsSerializer::SetGeneralSettings(const unsigned int* captureFr const bool* startOnTrigSoftware, const EProcessingActions* processingActions, const EProcessingActions* rtProcessingActions, const EProcessingActions* reprocessingActions) { - return mSerializer->SetGeneralSettings(captureFrequency, captureTime, startOnExtTrig, startOnTrigNO, startOnTrigNC, startOnTrigSoftware, processingActions, rtProcessingActions, reprocessingActions); + auto theGeneral = mSerializer + ->Element("QTM_Settings") + .Element("General"); + + if (captureFrequency) + { + theGeneral.ElementUnsignedInt("Frequency", *captureFrequency); + } + + if (captureTime) + { + theGeneral.ElementFloat("Capture_Time", *captureTime); + } + + // External Trigger and additional triggers + if (startOnExtTrig) + { + theGeneral.ElementBool("Start_On_External_Trigger", startOnExtTrig); + + if (mMajorVersion > 1 || mMinorVersion > 14) + { + theGeneral.ElementBool("Start_On_Trigger_NO", startOnTrigNO); + theGeneral.ElementBool("Start_On_Trigger_NC", startOnTrigNC); + theGeneral.ElementBool("Start_On_Trigger_Software", startOnTrigSoftware); + } + } + + const char* processingActionTags[3] = { "Processing_Actions", "RealTime_Processing_Actions", "Reprocessing_Actions" }; + const EProcessingActions* processingActionSets[3] = { processingActions, rtProcessingActions, reprocessingActions }; + + auto actionsCount = (mMajorVersion > 1 || mMinorVersion > 13) ? 3 : 1; + + for (auto i = 0; i < actionsCount; i++) + { + if (processingActionSets[i]) + { + auto processingActionsElem = theGeneral.Element(processingActionTags[i]); + + if (mMajorVersion > 1 || mMinorVersion > 13) + { + processingActionsElem.ElementBool("PreProcessing2D", (*processingActionSets[i] & ProcessingPreProcess2D) != 0); + } + + if (*processingActionSets[i] & ProcessingTracking2D && i != 1) // i != 1 => Not RtProcessingSettings + { + processingActionsElem.ElementString("Tracking", "2D"); + } + else if (*processingActionSets[i] & ProcessingTracking3D) + { + processingActionsElem.ElementString("Tracking", "3D"); + } + else + { + processingActionsElem.ElementString("Tracking", "false"); + } + + if (i != 1) // Not RtProcessingSettings + { + processingActionsElem.ElementBool("TwinSystemMerge", (*processingActionSets[i] & ProcessingTwinSystemMerge) != 0); + processingActionsElem.ElementBool("SplineFill", (*processingActionSets[i] & ProcessingSplineFill) != 0); + } + + processingActionsElem.ElementBool("AIM", (*processingActionSets[i] & ProcessingAIM) != 0); + processingActionsElem.ElementBool("Track6DOF", (*processingActionSets[i] & Processing6DOFTracking) != 0); + processingActionsElem.ElementBool("ForceData", (*processingActionSets[i] & ProcessingForceData) != 0); + processingActionsElem.ElementBool("GazeVector", (*processingActionSets[i] & ProcessingGazeVector) != 0); + + if (i != 1) // Not RtProcessingSettings + { + processingActionsElem.ElementBool("ExportTSV", (*processingActionSets[i] & ProcessingExportTSV) != 0); + processingActionsElem.ElementBool("ExportC3D", (*processingActionSets[i] & ProcessingExportC3D) != 0); + processingActionsElem.ElementBool("ExportMatlabFile", (*processingActionSets[i] & ProcessingExportMatlabFile) != 0); + processingActionsElem.ElementBool("ExportAviFile", (*processingActionSets[i] & ProcessingExportAviFile) != 0); + } + } + } + + return mSerializer->ToString(); } std::string SettingsSerializer::SetExtTimeBaseSettings(const bool* enabled, const ESignalSource* signalSource, @@ -31,13 +108,96 @@ std::string SettingsSerializer::SetExtTimeBaseSettings(const bool* enabled, cons const unsigned int* freqTolerance, const float* nominalFrequency, const bool* negativeEdge, const unsigned int* signalShutterDelay, const float* nonPeriodicTimeout) { - return mSerializer->SetExtTimeBaseSettings(enabled, signalSource, signalModePeriodic, freqMultiplier, freqDivisor, freqTolerance, nominalFrequency, negativeEdge, signalShutterDelay, nonPeriodicTimeout); -} + auto timeBaseElem = mSerializer + ->Element("QTM_Settings") + .Element("General") + .Element("External_Time_Base"); + + timeBaseElem.ElementBool("Enabled", enabled); + + if (signalSource) + { + switch (*signalSource) + { + case SourceControlPort: + timeBaseElem.ElementString("Signal_Source", "Control_port"); + break; + case SourceIRReceiver: + timeBaseElem.ElementString("Signal_Source", "IR receiver"); + break; + case SourceSMPTE: + timeBaseElem.ElementString("Signal_Source", "SMPTE"); + break; + case SourceVideoSync: + timeBaseElem.ElementString("Signal_Source", "Video sync"); + break; + case SourceIRIG: + timeBaseElem.ElementString("Signal_Source", "IRIG"); + break; + } + } + + timeBaseElem.ElementString("Signal_Mode", (*signalModePeriodic ? "Periodic" : "Non-periodic")); + + if (freqMultiplier) + { + timeBaseElem.ElementUnsignedInt("Frequency_Multiplier", *freqMultiplier); + } + if (freqDivisor) + { + timeBaseElem.ElementUnsignedInt("Frequency_Divisor", *freqDivisor); + } + if (freqTolerance) + { + timeBaseElem.ElementUnsignedInt("Frequency_Tolerance", *freqTolerance); + } + + if (nominalFrequency) + { + if (*nominalFrequency < 0) + { + timeBaseElem.ElementString("Nominal_Frequency", "None"); + } + else + { + timeBaseElem.ElementFloat("Nominal_Frequency", *nominalFrequency); + } + } + timeBaseElem.ElementString("Signal_Edge", (*negativeEdge ? "Negative" : "Positive")); + timeBaseElem.ElementUnsignedInt("Signal_Shutter_Delay", *signalShutterDelay); + timeBaseElem.ElementFloat("Non_Periodic_Timeout", *nonPeriodicTimeout); + + return timeBaseElem.ToString(); +} std::string SettingsSerializer::SetExtTimestampSettings(const SSettingsGeneralExternalTimestamp& timestampSettings) { - return mSerializer->SetExtTimestampSettings(timestampSettings); + auto timeStampElem = mSerializer + ->Element("QTM_Settings") + .Element("General") + .Element("External_Timestamp"); + + timeStampElem.ElementBool("Enabled", timestampSettings.bEnabled); + + switch (timestampSettings.nType) + { + case ETimestampType::Timestamp_SMPTE: + timeStampElem.ElementString("Type", "SMPTE"); + break; + case ETimestampType::Timestamp_IRIG: + timeStampElem.ElementString("Type", "IRIG"); + break; + case ETimestampType::Timestamp_CameraTime: + timeStampElem.ElementString("Type", "CameraTime"); + break; + default: + break; + } + + timeStampElem.ElementUnsignedInt("Frequency", timestampSettings.nFrequency); + + return mSerializer->ToString(); } std::string SettingsSerializer::SetCameraSettings( @@ -45,56 +205,591 @@ std::string SettingsSerializer::SetCameraSettings( const float* markerExposure, const float* markerThreshold, const int* orientation) { - return mSerializer->SetCameraSettings(cameraId, mode, markerExposure, markerThreshold, orientation); + auto cameraElem = mSerializer + ->Element("QTM_Settings") + .Element("General") + .Element("Camera"); + + cameraElem.ElementUnsignedInt("ID", cameraId); + + if (mode) + { + switch (*mode) + { + case ModeMarker: + cameraElem.ElementString("Mode", "Marker"); + break; + case ModeMarkerIntensity: + cameraElem.ElementString("Mode", "Marker Intensity"); + break; + case ModeVideo: + cameraElem.ElementString("Mode", "Video"); + break; + } + } + + if (markerExposure) + { + cameraElem.ElementFloat("Marker_Exposure", *markerExposure); + } + if (markerThreshold) + { + cameraElem.ElementFloat("Marker_Threshold", *markerThreshold); + } + if (orientation) + { + cameraElem.ElementInt("Orientation", *orientation); + } + + return mSerializer->ToString(); } std::string SettingsSerializer::SetCameraVideoSettings(const unsigned int cameraId, const EVideoResolution* videoResolution, const EVideoAspectRatio* videoAspectRatio, const unsigned int* videoFrequency, const float* videoExposure, const float* videoFlashTime) { - return mSerializer->SetCameraVideoSettings(cameraId, videoResolution, videoAspectRatio, videoFrequency, videoExposure, videoFlashTime); + auto cameraElem = mSerializer + ->Element("QTM_Settings") + .Element("General") + .Element("Camera"); + + cameraElem.ElementUnsignedInt("ID", cameraId); + + if (videoResolution) + { + switch (*videoResolution) + { + case VideoResolution1440p: + cameraElem.ElementString("Video_Resolution", "1440p"); + break; + case VideoResolution1080p: + cameraElem.ElementString("Video_Resolution", "1080p"); + break; + case VideoResolution720p: + cameraElem.ElementString("Video_Resolution", "720p"); + break; + case VideoResolution540p: + cameraElem.ElementString("Video_Resolution", "540p"); + break; + case VideoResolution480p: + cameraElem.ElementString("Video_Resolution", "480p"); + break; + case VideoResolutionNone: + break; + } + } + + if (videoAspectRatio) + { + switch (*videoAspectRatio) + { + case VideoAspectRatio16x9: + cameraElem.ElementString("Video_Aspect_Ratio", "16x9"); + break; + case VideoAspectRatio4x3: + cameraElem.ElementString("Video_Aspect_Ratio", "4x3"); + break; + case VideoAspectRatio1x1: + cameraElem.ElementString("Video_Aspect_Ratio", "1x1"); + break; + case VideoAspectRatioNone: + break; + } + } + + if (videoFrequency) + { + cameraElem.ElementUnsignedInt("Video_Frequency", *videoFrequency); + } + if (videoExposure) + { + cameraElem.ElementFloat("Video_Exposure", *videoExposure); + } + if (videoFlashTime) + { + cameraElem.ElementFloat("Video_Flash_Time", *videoFlashTime); + } + + return mSerializer->ToString(); } std::string SettingsSerializer::SetCameraSyncOutSettings(const unsigned int cameraId, const unsigned int portNumber, const ESyncOutFreqMode* syncOutMode, const unsigned int* syncOutValue, const float* syncOutDutyCycle, const bool* syncOutNegativePolarity) { - return mSerializer->SetCameraSyncOutSettings(cameraId, portNumber, syncOutMode, syncOutValue, syncOutDutyCycle, syncOutNegativePolarity); + auto cameraElem = mSerializer + ->Element("QTM_Settings") + .Element("General") + .Element("Camera"); + + cameraElem.ElementUnsignedInt("ID", cameraId); + + int port = static_cast(portNumber) - 1; + if (((port == 0 || port == 1) && syncOutMode) || (port == 2)) + { + auto syncOutElem = [&port, &cameraElem](){ + if (port == 0) + return cameraElem.Element("Sync_Out"); + else if (port == 1) + return cameraElem.Element("Sync_Out2"); + else + return cameraElem.Element("Sync_Out_MT"); + }(); + + // Add Sync Out Mode + if (port == 0 || port == 1) + { + switch (*syncOutMode) + { + case ModeShutterOut: + syncOutElem.ElementString("Mode", "Shutter out"); + break; + case ModeMultiplier: + syncOutElem.ElementString("Mode", "Multiplier"); + break; + case ModeDivisor: + syncOutElem.ElementString("Mode", "Divisor"); + break; + case ModeIndependentFreq: + syncOutElem.ElementString("Mode", "Camera independent"); + break; + case ModeMeasurementTime: + syncOutElem.ElementString("Mode", "Measurement time"); + break; + case ModeFixed100Hz: + syncOutElem.ElementString("Mode", "Continuous 100Hz"); + break; + case ModeSystemLiveTime: + syncOutElem.ElementString("Mode", "System live time"); + break; + default: + return ""; + } + + if (*syncOutMode == ModeMultiplier || + *syncOutMode == ModeDivisor || + *syncOutMode == ModeIndependentFreq) + { + if (syncOutValue) + { + syncOutElem.ElementUnsignedInt("Value", *syncOutValue); + } + if (syncOutDutyCycle) + { + syncOutElem.ElementFloat("Duty_Cycle", *syncOutDutyCycle); + } + } + } + + if (syncOutNegativePolarity && (port == 2 || + (syncOutMode && *syncOutMode != ModeFixed100Hz))) + { + syncOutElem.ElementString("Signal_Polarity", (syncOutNegativePolarity ? "Negative" : "Positive")); + } + } + + return mSerializer->ToString(); } std::string SettingsSerializer::SetCameraLensControlSettings(const unsigned int cameraId, const float focus, const float aperture) { - return mSerializer->SetCameraLensControlSettings(cameraId, focus, aperture); + auto cameraElem = mSerializer + ->Element("QTM_Settings") + .Element("General") + .Element("Camera"); + + cameraElem.ElementUnsignedInt("ID", cameraId); + + auto lensControlElem = cameraElem.Element("LensControl"); + + lensControlElem.Element("Focus") + .AttributeFloat("Value", focus); + + lensControlElem.Element("Aperture") + .AttributeFloat("Value", aperture); + + return mSerializer->ToString(); } std::string SettingsSerializer::SetCameraAutoExposureSettings(const unsigned int cameraId, const bool autoExposure, const float compensation) { - return mSerializer->SetCameraAutoExposureSettings(cameraId, autoExposure, compensation); + auto cameraElem = mSerializer + ->Element("QTM_Settings") + .Element("General") + .Element("Camera"); + + cameraElem.ElementUnsignedInt("ID", cameraId); + + auto lensControlElem = cameraElem.Element("LensControl"); + + char compensationStr[32]; + (void)snprintf(compensationStr, sizeof(compensationStr), "%.6f", compensation); + + lensControlElem.Element("AutoExposure") + .AttributeBool("Enabled", autoExposure) + .AttributeString("Compensation", compensationStr); + + return mSerializer->ToString(); } std::string SettingsSerializer::SetCameraAutoWhiteBalance(const unsigned int cameraId, const bool enable) { - return mSerializer->SetCameraAutoWhiteBalance(cameraId, enable); + auto cameraElem = mSerializer + ->Element("QTM_Settings") + .Element("General") + .Element("Camera"); + + cameraElem.ElementUnsignedInt("ID", cameraId); + cameraElem.ElementString("AutoWhiteBalance", (enable ? "true" : "false")); + + return mSerializer->ToString(); } std::string SettingsSerializer::SetImageSettings(const unsigned int cameraId, const bool* enable, const CRTPacket::EImageFormat* format, const unsigned int* width, const unsigned int* height, const float* leftCrop, const float* topCrop, const float* rightCrop, const float* bottomCrop) { - return mSerializer->SetImageSettings(cameraId, enable, format, width, height, leftCrop, topCrop, rightCrop, bottomCrop); + auto cameraElem = mSerializer + ->Element("QTM_Settings") + .Element("Image") + .Element("Camera"); + + cameraElem.ElementUnsignedInt("ID", cameraId); + if (enable) + { + cameraElem.ElementBool("Enabled", *enable); + } + + if (format) + { + const char* formatStr = nullptr; + switch (*format) + { + case CRTPacket::FormatRawGrayscale: + formatStr = "RAWGrayscale"; + break; + case CRTPacket::FormatRawBGR: + formatStr = "RAWBGR"; + break; + case CRTPacket::FormatJPG: + formatStr = "JPG"; + break; + case CRTPacket::FormatPNG: + formatStr = "PNG"; + break; + } + + if (formatStr) + { + cameraElem.ElementString("Format", formatStr); + } + } + + if (width) + { + cameraElem.ElementUnsignedInt("Width", *width); + } + if (height) + { + cameraElem.ElementUnsignedInt("Height", *height); + } + if (leftCrop) + { + cameraElem.ElementFloat("Left_Crop", *leftCrop); + } + if (topCrop) + { + cameraElem.ElementFloat("Top_Crop", *topCrop); + } + if (rightCrop) + { + cameraElem.ElementFloat("Right_Crop", *rightCrop); + } + if (bottomCrop) + { + cameraElem.ElementFloat("Bottom_Crop", *bottomCrop); + } + + return mSerializer->ToString(); } std::string SettingsSerializer::SetForceSettings(const unsigned int plateId, const SPoint* corner1, const SPoint* corner2, const SPoint* corner3, const SPoint* corner4) { - return mSerializer->SetForceSettings(plateId, corner1, corner2, corner3, corner4); + auto plateElem = mSerializer + ->Element("QTM_Settings") + .Element("Force") + .Element("Plate"); + + if (mMajorVersion > 1 || mMinorVersion > 7) + { + plateElem.ElementUnsignedInt("Plate_ID", plateId); + } + else + { + plateElem.ElementUnsignedInt("Force_Plate_Index", plateId); + } + + auto addCorner = [&](const char* name, const SPoint* pCorner) + { + if (pCorner) + { + auto cornerElem = plateElem.Element(name); + + if (pCorner->fX) + { + cornerElem.ElementFloat("X", pCorner->fX); + } + if (pCorner->fY) + { + cornerElem.ElementFloat("Y", pCorner->fY); + } + if (pCorner->fZ) + { + cornerElem.ElementFloat("Z", pCorner->fZ); + } + } + }; + + addCorner("Corner1", corner1); + addCorner("Corner2", corner2); + addCorner("Corner3", corner3); + addCorner("Corner4", corner4); + + return mSerializer->ToString(); } std::string SettingsSerializer::Set6DOFBodySettings(const std::vector& settings6Dofs) { - return mSerializer->Set6DOFBodySettings(settings6Dofs); + auto the6D = mSerializer + ->Element("QTM_Settings") + .Element("The_6D"); + + for (const auto& body : settings6Dofs) + { + auto bodyElem = the6D.Element("Body"); + + bodyElem.ElementString("Name", body.name.c_str()); + bodyElem.ElementBool("Enabled", body.enabled); + + auto colorElem = bodyElem.Element("Color"); + colorElem.AttributeUnsignedInt("R", body.color & 0xff); + colorElem.AttributeUnsignedInt("G", (body.color >> 8) & 0xff); + colorElem.AttributeUnsignedInt("B", (body.color >> 16) & 0xff); + + bodyElem.ElementFloat("MaximumResidual", body.maxResidual); + bodyElem.ElementUnsignedInt("MinimumMarkersInBody", body.minMarkersInBody); + bodyElem.ElementFloat("BoneLengthTolerance", body.boneLengthTolerance); + bodyElem.Element("Filter").AttributeString("Preset", body.filterPreset.c_str()); + + if (!body.mesh.name.empty()) + { + auto meshElem = bodyElem.Element("Mesh"); + meshElem.ElementString("Name", body.mesh.name.c_str()); + + meshElem.Element("Position") + .AttributeFloat("X",body.mesh.position.fX) + .AttributeFloat("Y", body.mesh.position.fY) + .AttributeFloat("Z", body.mesh.position.fZ); + + meshElem.Element("Rotation") + .AttributeFloat("X", body.mesh.rotation.fX) + .AttributeFloat("Y", body.mesh.rotation.fY) + .AttributeFloat("Z", body.mesh.rotation.fZ); + + meshElem.ElementFloat("Scale", body.mesh.scale); + meshElem.ElementFloat("Opacity", body.mesh.opacity); + } + + if (!body.points.empty()) + { + auto pointsElem = bodyElem.Element("Points"); + for (const auto& point : body.points) + { + pointsElem.Element("Point") + .AttributeFloat("X", point.fX) + .AttributeFloat("Y", point.fY) + .AttributeFloat("Z", point.fZ) + .AttributeUnsignedInt("Virtual", point.virtual_ ? 1 : 0) + .AttributeUnsignedInt("PhysicalId", point.physicalId) + .AttributeString("Name", point.name.c_str()); + } + } + + bodyElem.ElementUnsignedInt("Data_origin", body.origin.type) + .AttributeFloat("X", body.origin.position.fX) + .AttributeFloat("Y", body.origin.position.fY) + .AttributeFloat("Z", body.origin.position.fZ) + .AttributeUnsignedInt("Relative_body", body.origin.relativeBody); + + auto orientationElem = bodyElem.ElementUnsignedInt("Data_orientation", body.origin.type); + for (std::uint32_t i = 0; i < 9; i++) + { + char tmpStr[16]; + (void)sprintf_s(tmpStr, sizeof(tmpStr), "R%u%u", (i / 3) + 1, (i % 3) + 1); + orientationElem.AttributeFloat(tmpStr, body.origin.rotation[i]); + } + orientationElem.AttributeUnsignedInt("Relative_body", body.origin.relativeBody); + } + + return mSerializer->ToString(); } std::string SettingsSerializer::SetSkeletonSettings(const std::vector& settingsSkeletons) { - return mSerializer->SetSkeletonSettings(settingsSkeletons); + auto skeletonsElem = mSerializer + ->Element("QTM_Settings") + .Element("Skeletons"); + + for (const auto& skeleton : settingsSkeletons) + { + auto skeletonElem = skeletonsElem.Element("Skeleton") + .AttributeString("Name", skeleton.name.c_str()); + + if (mMajorVersion == 1 && mMinorVersion < 22) + { + skeletonElem.ElementString("Solver", skeleton.rootSegment.solver.c_str()); + } + + skeletonElem.ElementDouble("Scale", skeleton.scale); + auto segmentsElem = skeletonElem.Element("Segments"); + + std::function recurseSegments; + recurseSegments = [&](const SSettingsSkeletonSegmentHierarchical& segment, SerializerApi& parentElem) + { + auto segmentElem = parentElem.Element("Segment") + .AttributeString("Name", segment.name.c_str()); + + if (mMajorVersion > 1 || mMinorVersion > 21) + { + segmentElem.ElementString("Solver", segment.solver.c_str()); + } + + if (!std::isnan(segment.position.x)) + { + auto transformElem = segmentElem.Element("Transform"); + transformElem.Element("Position") + .AttributeDouble("X", segment.position.x) + .AttributeDouble("Y", segment.position.y) + .AttributeDouble("Z", segment.position.z); + transformElem.Element("Rotation") + .AttributeDouble("X", segment.rotation.x) + .AttributeDouble("Y", segment.rotation.y) + .AttributeDouble("Z", segment.rotation.z) + .AttributeDouble("W", segment.rotation.w); + } + + if (!std::isnan(segment.defaultPosition.x)) + { + auto transformElem = segmentElem.Element("DefaultTransform"); + transformElem.Element("Position") + .AttributeDouble("X", segment.defaultPosition.x) + .AttributeDouble("Y", segment.defaultPosition.y) + .AttributeDouble("Z", segment.defaultPosition.z); + transformElem.Element("Rotation") + .AttributeDouble("X", segment.defaultRotation.x) + .AttributeDouble("Y", segment.defaultRotation.y) + .AttributeDouble("Z", segment.defaultRotation.z) + .AttributeDouble("W", segment.defaultRotation.w); + } + + auto degreesOfFreedomElem = segmentElem.Element("DegreesOfFreedom"); + + for (const auto& dof : segment.degreesOfFreedom) + { + auto dofElem = degreesOfFreedomElem.Element(SkeletonDofToStringSettings(dof.type)); + + if (!std::isnan(dof.lowerBound) && !std::isnan(dof.upperBound)) + { + if (mMajorVersion > 1 || mMinorVersion > 21) + { + dofElem.Element("Constraint") + .AttributeDouble("LowerBound", dof.lowerBound) + .AttributeDouble("UpperBound", dof.upperBound); + } + else + { + // If not in a 'Constraint' block, add 'LowerBound' & 'UpperBound' directly to dofElem + dofElem.AttributeDouble("LowerBound", dof.lowerBound); + dofElem.AttributeDouble("UpperBound", dof.upperBound); + } + } + + if (!dof.couplings.empty()) + { + auto couplingsElem = dofElem.Element("Couplings"); + for (const auto& coupling : dof.couplings) + { + couplingsElem.Element("Coupling") + .AttributeString("Segment", coupling.segment.c_str()) + .AttributeString("DegreeOfFreedom", SkeletonDofToStringSettings(coupling.degreeOfFreedom)) + .AttributeDouble("Coefficient", coupling.coefficient); + } + } + + if (!std::isnan(dof.goalValue) && !std::isnan(dof.goalWeight)) + { + dofElem.Element("Goal") + .AttributeDouble("Value", dof.goalValue) + .AttributeDouble("Weight", dof.goalWeight); + } + } + + if (!std::isnan(segment.endpoint.x) && !std::isnan(segment.endpoint.y) && !std::isnan(segment.endpoint.z)) + { + segmentElem.Element("Endpoint") + .AttributeDouble("X", segment.endpoint.x) + .AttributeDouble("Y", segment.endpoint.y) + .AttributeDouble("Z", segment.endpoint.z); + } + else + { + segmentElem.Element("Endpoint"); + } + + auto markersElem = segmentElem.Element("Markers"); + + for (const auto& marker : segment.markers) + { + auto markerElem = markersElem.Element("Marker") + .AttributeString("Name", marker.name.c_str()); + + markerElem.Element("Position") + .AttributeDouble("X", marker.position.x) + .AttributeDouble("Y", marker.position.y) + .AttributeDouble("Z", marker.position.z); + + markerElem.ElementDouble("Weight", marker.weight); + } + + auto rigidBodiesElem = segmentElem.Element("RigidBodies"); + for (const auto& rigidBody : segment.bodies) + { + auto rigidBodyElem = rigidBodiesElem.Element("RigidBody") + .AttributeString("Name", rigidBody.name.c_str()); + + auto transformElem = rigidBodyElem.Element("Transform"); + + transformElem.Element("Position") + .AttributeDouble("X", rigidBody.position.x) + .AttributeDouble("Y", rigidBody.position.y) + .AttributeDouble("Z", rigidBody.position.z); + transformElem.Element("Rotation") + .AttributeDouble("X", rigidBody.rotation.x) + .AttributeDouble("Y", rigidBody.rotation.y) + .AttributeDouble("Z", rigidBody.rotation.z) + .AttributeDouble("W", rigidBody.rotation.w); + + rigidBodyElem.ElementDouble("Weight", rigidBody.weight); + } + + for (const auto& childSegment : segment.segments) + { + recurseSegments(childSegment, segmentElem); + } + }; + + recurseSegments(skeleton.rootSegment, segmentsElem); + } + + return mSerializer->ToString(); } diff --git a/Tests/Data/General.h b/Tests/Data/General.h index 5b5c722..9e02044 100644 --- a/Tests/Data/General.h +++ b/Tests/Data/General.h @@ -5,16 +5,16 @@ namespace qualisys_cpp_sdk::tests::data R"XMLDATA( - True + true Video sync Periodic 999 998 997 - 996.000 + 996.000000 Negative 995 - 994.000 + 994.000000 @@ -24,7 +24,7 @@ R"XMLDATA( R"XMLDATA( - True + true IRIG 999 @@ -743,46 +743,46 @@ R"XMLDATA( 1 - 999.000 - True - True - True - True + 999.000000 + true + true + true + true - False - False - False - False - False - False - False - True - False - False - False - False + false + false + false + false + false + false + false + true + false + false + false + false - False - False - False - False - False - False + false + false + false + false + false + false - False - False - True - False - False - False - False - False - False - False - False - False + false + false + true + false + false + false + false + false + false + false + false + false diff --git a/Tests/Data/Image.h b/Tests/Data/Image.h index 48b5ce0..647170a 100644 --- a/Tests/Data/Image.h +++ b/Tests/Data/Image.h @@ -24,7 +24,7 @@ namespace qualisys_cpp_sdk::tests::data 1 - True + true RAWGrayscale 99 98