From 4be18f7a58a46507bac0d7254a2bd93d60594694 Mon Sep 17 00:00:00 2001 From: Dan Smith Date: Mon, 21 Aug 2023 10:05:12 -0400 Subject: [PATCH] CRLF --- UnitTest/CppUnitTestAssert.cpp | 86 +- UnitTest/Test.cpp | 192 +- UnitTest/Test.h | 20 +- UnitTest/UnitTest.vcxproj.filters | 386 +- processFiles.py | 198 +- six.sln | 262 +- six/modules/c++/cphd/cphd.vcxproj.filters | 388 +- six/modules/c++/cphd/include/cphd/Antenna.h | 748 +-- six/modules/c++/cphd/include/cphd/Dwell.h | 256 +- .../c++/cphd/include/cphd/ErrorParameters.h | 480 +- .../c++/cphd/include/cphd/MetadataBase.h | 222 +- six/modules/c++/cphd/include/cphd/PVP.h | 1224 ++--- .../c++/cphd/include/cphd/ProductInfo.h | 234 +- .../c++/cphd/include/cphd/ReferenceGeometry.h | 700 +-- six/modules/c++/cphd/include/cphd/TxRcv.h | 368 +- six/modules/c++/cphd/source/Antenna.cpp | 296 +- six/modules/c++/cphd/source/CPHDXMLParser.cpp | 4844 ++++++++--------- six/modules/c++/cphd/source/Channel.cpp | 454 +- six/modules/c++/cphd/source/Dwell.cpp | 146 +- .../c++/cphd/source/ErrorParameters.cpp | 382 +- six/modules/c++/cphd/source/PVP.cpp | 560 +- six/modules/c++/cphd/source/ProductInfo.cpp | 126 +- .../c++/cphd/source/ReferenceGeometry.cpp | 348 +- six/modules/c++/cphd/source/TxRcv.cpp | 198 +- .../c++/cphd/unittests/test_channel.cpp | 170 +- .../cphd/unittests/test_cphd_xml_optional.cpp | 2256 ++++---- six/modules/c++/cphd/unittests/test_dwell.cpp | 240 +- six/modules/c++/cphd/unittests/test_pvp.cpp | 218 +- .../cphd/unittests/test_pvp_block_round.cpp | 506 +- .../unittests/test_reference_geometry.cpp | 126 +- .../unittests/test_signal_block_round.cpp | 448 +- .../unittests/test_support_block_round.cpp | 336 +- six/modules/c++/samples/check_valid_six.cpp | 556 +- six/modules/c++/samples/utils.h | 122 +- .../c++/scene/include/scene/sys_Conf.h | 30 +- six/modules/c++/scene/scene.ruleset | 62 +- six/modules/c++/scene/scene.vcxproj.filters | 244 +- .../source/ProjectionPolynomialFitter.cpp | 978 ++-- six/modules/c++/six.ruleset | 62 +- .../six.sicd/include/six/sicd/ImageCreation.h | 126 +- .../six/sicd/NITFReadComplexXMLControl.h | 212 +- .../c++/six.sicd/include/six/sicd/PFA.h | 254 +- .../c++/six.sicd/include/six/sicd/Position.h | 194 +- .../c++/six.sicd/include/six/sicd/Timeline.h | 222 +- .../c++/six.sicd/six.sicd.vcxproj.filters | 496 +- six/modules/c++/six.sicd/source/Grid.cpp | 1820 +++---- six/modules/c++/six.sicd/source/ImageData.cpp | 556 +- .../source/NITFReadComplexXMLControl.cpp | 258 +- six/modules/c++/six.sicd/source/PFA.cpp | 174 +- six/modules/c++/six.sicd/source/Position.cpp | 92 +- .../c++/six.sicd/source/RadarCollection.cpp | 1200 ++-- 51 files changed, 12538 insertions(+), 12538 deletions(-) diff --git a/UnitTest/CppUnitTestAssert.cpp b/UnitTest/CppUnitTestAssert.cpp index fdcf5f92b5..9b2594ac58 100644 --- a/UnitTest/CppUnitTestAssert.cpp +++ b/UnitTest/CppUnitTestAssert.cpp @@ -1,43 +1,43 @@ -#include "pch.h" -#include "TestCase.h" - -#include "str/EncodedStringView.h" - -using namespace Microsoft::VisualStudio::CppUnitTestFramework; - -// EQUALS_MESSAGE() wants ToString() specializations (or overloads) for our types, which is a nusiance. -// This hooks up our existing str::toString() into the VC++ unit-test infrastructure - -// C++ hack to call private methods -// https://stackoverflow.com/a/71578383/8877 - -using FailOnCondition_t = void(bool condition, const unsigned short* message, const __LineInfo* pLineInfo); // declare method's type -using GetAssertMessage_t = std::wstring(bool equality, const std::wstring& expected, const std::wstring& actual, const wchar_t *message); // declare method's type -template -struct caller final // helper structure to inject call() code -{ - friend void FailOnCondition(bool condition, const unsigned short* message, const __LineInfo* pLineInfo) - { - fFailOnCondition(condition, message, pLineInfo); - } - - friend std::wstring GetAssertMessage(bool equality, const std::wstring& expected, const std::wstring& actual, const wchar_t *message) - { - return fGetAssertMessage(equality, expected, actual, message); - } -}; -template struct caller<&Assert::FailOnCondition, &Assert::GetAssertMessage>; // even instantiation of the helper - -void FailOnCondition(bool condition, const unsigned short* message, const __LineInfo* pLineInfo); // declare caller -void test::Assert::FailOnCondition(bool condition, const unsigned short* message, const __LineInfo* pLineInfo) -{ - ::FailOnCondition(condition, message, pLineInfo); // and call! -} - -std::wstring GetAssertMessage(bool equality, const std::wstring& expected, const std::wstring& actual, const wchar_t *message); // declare caller -std::wstring test::Assert::GetAssertMessage(bool equality, const std::string& expected, const std::string& actual, const wchar_t *message) -{ - const str::EncodedStringView vExpected(expected); - const str::EncodedStringView vActual(actual); - return ::GetAssertMessage(equality, vExpected.wstring(), vActual.wstring(), message); // and call! -} +#include "pch.h" +#include "TestCase.h" + +#include "str/EncodedStringView.h" + +using namespace Microsoft::VisualStudio::CppUnitTestFramework; + +// EQUALS_MESSAGE() wants ToString() specializations (or overloads) for our types, which is a nusiance. +// This hooks up our existing str::toString() into the VC++ unit-test infrastructure + +// C++ hack to call private methods +// https://stackoverflow.com/a/71578383/8877 + +using FailOnCondition_t = void(bool condition, const unsigned short* message, const __LineInfo* pLineInfo); // declare method's type +using GetAssertMessage_t = std::wstring(bool equality, const std::wstring& expected, const std::wstring& actual, const wchar_t *message); // declare method's type +template +struct caller final // helper structure to inject call() code +{ + friend void FailOnCondition(bool condition, const unsigned short* message, const __LineInfo* pLineInfo) + { + fFailOnCondition(condition, message, pLineInfo); + } + + friend std::wstring GetAssertMessage(bool equality, const std::wstring& expected, const std::wstring& actual, const wchar_t *message) + { + return fGetAssertMessage(equality, expected, actual, message); + } +}; +template struct caller<&Assert::FailOnCondition, &Assert::GetAssertMessage>; // even instantiation of the helper + +void FailOnCondition(bool condition, const unsigned short* message, const __LineInfo* pLineInfo); // declare caller +void test::Assert::FailOnCondition(bool condition, const unsigned short* message, const __LineInfo* pLineInfo) +{ + ::FailOnCondition(condition, message, pLineInfo); // and call! +} + +std::wstring GetAssertMessage(bool equality, const std::wstring& expected, const std::wstring& actual, const wchar_t *message); // declare caller +std::wstring test::Assert::GetAssertMessage(bool equality, const std::string& expected, const std::string& actual, const wchar_t *message) +{ + const str::EncodedStringView vExpected(expected); + const str::EncodedStringView vActual(actual); + return ::GetAssertMessage(equality, vExpected.wstring(), vActual.wstring(), message); // and call! +} diff --git a/UnitTest/Test.cpp b/UnitTest/Test.cpp index 1b5022b55b..288bc85ad2 100644 --- a/UnitTest/Test.cpp +++ b/UnitTest/Test.cpp @@ -1,96 +1,96 @@ -#include "pch.h" -#include "Test.h" - -#include - -#include - -namespace fs = std::filesystem; - -static bool is_x64_Configuration(const fs::path& path) // "Configuration" is typically "Debug" or "Release" -{ - const std::string build_configuration = -#if defined(NDEBUG) // i.e., release - "Release"; -#else - "Debug"; -#endif - - const auto Configuration = path.filename(); - const auto path_parent_path = path.parent_path(); - const auto x64 = path_parent_path.filename(); - return (Configuration == build_configuration) && (x64 == "x64"); -} - -static bool is_install_unittests(const fs::path& path) -{ - const auto unittests = path.filename(); - const auto path_parent_path = path.parent_path(); - const auto install = path_parent_path.filename(); - return (unittests == "unittests") && (install == "install"); -} -static bool is_install_tests(const fs::path& path) -{ - const auto tests = path.filename(); - const auto path_parent_path = path.parent_path(); - const auto install = path_parent_path.filename(); - return (tests == "tests") && (install == "install"); -} - -fs::path six::Test::buildSchemaDir() -{ - const auto cwd = fs::current_path(); - - const sys::OS os; - const auto exec = fs::path(os.getCurrentExecutable()); - const auto argv0 = exec.filename(); - if ((argv0 == "Test.exe") || (argv0 == "testhost.exe")) - { - // Running GTest unit-tests in Visual Studio on Windows - if (is_x64_Configuration(cwd)) - { - const auto root_path = cwd.parent_path().parent_path(); - return root_path / "six" / "modules" / "c++" / "six.sidd" / "conf" / "schema"; - } - } - - if (argv0 == "unittests.exe") - { - // stand-alone unittest executable on Windows (ends in .EXE) - const auto parent_path = exec.parent_path(); - if (is_x64_Configuration(parent_path)) - { - const auto parent_path_ = parent_path.parent_path().parent_path(); - return parent_path_ / "dev" / "tests" / "images"; - } - } - - // stand-alone unit-test on Linux - const auto exec_dir = exec.parent_path(); - if (is_install_unittests(exec_dir)) - { - const auto install = exec_dir.parent_path(); - return install / "unittests" / "data"; - } - if (is_install_tests(exec_dir)) - { - const auto install = exec_dir.parent_path(); - return install / "unittests" / "data"; - } - - if (argv0 == "unittests") - { - // stand-alone unittest executable on Linux - const auto bin = exec.parent_path(); - if (bin.filename() == "bin") - { - const auto unittests = bin.parent_path(); - return unittests / "unittests" / "data"; - } - } - - //fprintf(stderr, "cwd = %s\n", cwd.c_str()); - //fprintf(stderr, "exec = %s\n", exec.c_str()); - - return cwd; -} +#include "pch.h" +#include "Test.h" + +#include + +#include + +namespace fs = std::filesystem; + +static bool is_x64_Configuration(const fs::path& path) // "Configuration" is typically "Debug" or "Release" +{ + const std::string build_configuration = +#if defined(NDEBUG) // i.e., release + "Release"; +#else + "Debug"; +#endif + + const auto Configuration = path.filename(); + const auto path_parent_path = path.parent_path(); + const auto x64 = path_parent_path.filename(); + return (Configuration == build_configuration) && (x64 == "x64"); +} + +static bool is_install_unittests(const fs::path& path) +{ + const auto unittests = path.filename(); + const auto path_parent_path = path.parent_path(); + const auto install = path_parent_path.filename(); + return (unittests == "unittests") && (install == "install"); +} +static bool is_install_tests(const fs::path& path) +{ + const auto tests = path.filename(); + const auto path_parent_path = path.parent_path(); + const auto install = path_parent_path.filename(); + return (tests == "tests") && (install == "install"); +} + +fs::path six::Test::buildSchemaDir() +{ + const auto cwd = fs::current_path(); + + const sys::OS os; + const auto exec = fs::path(os.getCurrentExecutable()); + const auto argv0 = exec.filename(); + if ((argv0 == "Test.exe") || (argv0 == "testhost.exe")) + { + // Running GTest unit-tests in Visual Studio on Windows + if (is_x64_Configuration(cwd)) + { + const auto root_path = cwd.parent_path().parent_path(); + return root_path / "six" / "modules" / "c++" / "six.sidd" / "conf" / "schema"; + } + } + + if (argv0 == "unittests.exe") + { + // stand-alone unittest executable on Windows (ends in .EXE) + const auto parent_path = exec.parent_path(); + if (is_x64_Configuration(parent_path)) + { + const auto parent_path_ = parent_path.parent_path().parent_path(); + return parent_path_ / "dev" / "tests" / "images"; + } + } + + // stand-alone unit-test on Linux + const auto exec_dir = exec.parent_path(); + if (is_install_unittests(exec_dir)) + { + const auto install = exec_dir.parent_path(); + return install / "unittests" / "data"; + } + if (is_install_tests(exec_dir)) + { + const auto install = exec_dir.parent_path(); + return install / "unittests" / "data"; + } + + if (argv0 == "unittests") + { + // stand-alone unittest executable on Linux + const auto bin = exec.parent_path(); + if (bin.filename() == "bin") + { + const auto unittests = bin.parent_path(); + return unittests / "unittests" / "data"; + } + } + + //fprintf(stderr, "cwd = %s\n", cwd.c_str()); + //fprintf(stderr, "exec = %s\n", exec.c_str()); + + return cwd; +} diff --git a/UnitTest/Test.h b/UnitTest/Test.h index 232a94cf1b..057b8d5209 100644 --- a/UnitTest/Test.h +++ b/UnitTest/Test.h @@ -1,11 +1,11 @@ -#pragma once - -#include - -namespace six -{ - namespace Test - { - extern std::filesystem::path buildSchemaDir(); - } +#pragma once + +#include + +namespace six +{ + namespace Test + { + extern std::filesystem::path buildSchemaDir(); + } } \ No newline at end of file diff --git a/UnitTest/UnitTest.vcxproj.filters b/UnitTest/UnitTest.vcxproj.filters index 924b309cfc..440a0297ed 100644 --- a/UnitTest/UnitTest.vcxproj.filters +++ b/UnitTest/UnitTest.vcxproj.filters @@ -1,194 +1,194 @@ - - - - - - - - cphd - - - cphd - - - cphd - - - cphd - - - cphd - - - cphd - - - cphd - - - cphd - - - cphd - - - cphd - - - cphd - - - cphd - - - cphd - - - cphd - - - cphd03 - - - cphd03 - - - cphd03 - - - cphd03 - - - sicd - - - sicd - - - sicd - - - sicd - - - sicd - - - sicd - - - sicd - - - sicd - - - sicd - - - sicd - - - sicd - - - sicd - - - sicd - - - sicd - - - sicd - - - sicd - - - sicd - - - sicd - - - sidd - - - sidd - - - sidd - - - sidd - - - sidd - - - sidd - - - six - - - six - - - six - - - six - - - six - - - - - - - - cphd - - - cphd03 - - - sicd - - - sidd - - - six - - - - - {004a37ca-2175-4642-988e-94516ea1a147} - - - {ef494548-4aed-4ebb-a93c-b56a11f17f5e} - - - {593807ae-bc84-424f-ba11-0537277cd2fc} - - - {f8053c57-ba04-41c4-8dd8-2056f5a19f25} - - - {8d8a73fb-96b1-4bdf-a055-2b34d7f94e14} - - - - - sidd - - - sidd - - + + + + + + + + cphd + + + cphd + + + cphd + + + cphd + + + cphd + + + cphd + + + cphd + + + cphd + + + cphd + + + cphd + + + cphd + + + cphd + + + cphd + + + cphd + + + cphd03 + + + cphd03 + + + cphd03 + + + cphd03 + + + sicd + + + sicd + + + sicd + + + sicd + + + sicd + + + sicd + + + sicd + + + sicd + + + sicd + + + sicd + + + sicd + + + sicd + + + sicd + + + sicd + + + sicd + + + sicd + + + sicd + + + sicd + + + sidd + + + sidd + + + sidd + + + sidd + + + sidd + + + sidd + + + six + + + six + + + six + + + six + + + six + + + + + + + + cphd + + + cphd03 + + + sicd + + + sidd + + + six + + + + + {004a37ca-2175-4642-988e-94516ea1a147} + + + {ef494548-4aed-4ebb-a93c-b56a11f17f5e} + + + {593807ae-bc84-424f-ba11-0537277cd2fc} + + + {f8053c57-ba04-41c4-8dd8-2056f5a19f25} + + + {8d8a73fb-96b1-4bdf-a055-2b34d7f94e14} + + + + + sidd + + + sidd + + \ No newline at end of file diff --git a/processFiles.py b/processFiles.py index 1e3904ec43..67d13fc9ab 100644 --- a/processFiles.py +++ b/processFiles.py @@ -1,99 +1,99 @@ -import sys, os, re, subprocess -from os.path import isdir, join, split, exists - - -def cosmoSkyMed(filename): - path, fname = split(filename) - if re.match(r'CSK.*.MBI.tif', fname): - xmlName = join(path, fname.rsplit('MBI.tif')[0] + 'attribs.xml') - if exists(xmlName): - return (xmlName, filename) - return None - -def radarsat2(filename): - path, fname = split(filename) -# if re.match(r'RS2_.*', split(path)[1]) and re.match(r'imagery_.*.tif', fname): - if re.match(r'imagery_.*.tif', fname): - xmlName = join(path, 'product.xml') - if exists(xmlName): - return (xmlName, filename) - return None - -def terraSAR(filename): - path, fname = split(filename) - if re.match(r'IMAGEDATA', split(path)[1]) and re.match(r'IMAGE_.*.tif', fname): - parDir, xmlName = split(split(path)[0]) - xmlName = join(parDir, xmlName, '%s.xml' % xmlName) - if exists(xmlName): - return (xmlName, filename) - return None - - -if __name__ == '__main__': - from optparse import OptionParser - parser = OptionParser(usage="usage: %prog [options] [path(s)]") - parser.add_option("-d", "--dir", dest='outDir', metavar='DIR', - help="specify the output directory (default=cwd)") - parser.add_option("-x", "--xml", dest='xml', action='store_true', - help="Write An XML output") - parser.add_option("-n", "--nitf", dest='nitf', action='store_true', - help="Write A NITF output") - parser.add_option("-t", "--tiff", dest='tiff', action='store_true', - help="Write A TIFF output") - parser.add_option("-k", "--kml", dest='kml', action='store_true', - help="Write A KML output") - parser.add_option("-l", "--level", dest='level', metavar='LEVEL', default=None, - help="Level at which to log ") - parser.add_option("--limit", dest='limit', metavar='NUM', default=0, type='int', - help="Specify a limit on the number of images to process") - (options, args) = parser.parse_args() - - #default to cwd if none provided - outDir = options.outDir or os.getcwd() - if not exists(outDir): - os.makedirs(outDir) - - inputs = [] - paths = args[:] - while paths: - path = paths.pop(0) - if isdir(path): - paths.extend(map(lambda x: join(path, x), os.listdir(path))) - else: - f = cosmoSkyMed(path) - if not f: - f = radarsat2(path) - if not f: - f = terraSAR(path) - if f: - inputs.append(f) - - appName = os.path.abspath(join(split(__file__)[0], './install/bin/ScanSARConverter')) - if 'win32' in sys.platform: - appName += '.exe' - - cmd = [appName] - cmd.extend(['-d', outDir]) - if options.xml: - cmd.append('-x') - if options.nitf: - cmd.append('-n') - if options.tiff: - cmd.append('-t') - if options.kml: - cmd.append('-k') - if options.level: - cmd.extend(['-l', options.level]) - - def process(xml, image): - command = cmd[:] - command.append('%s,%s' % (xml, image)) - print command - p = subprocess.Popen(command).communicate() - - limit = (options.limit > 0 and min(options.limit, len(inputs)) or len(inputs)) - print 'Processing %d files' % limit - for i, (xml, image) in enumerate(inputs): - if i >= limit: - break - process(xml, image) +import sys, os, re, subprocess +from os.path import isdir, join, split, exists + + +def cosmoSkyMed(filename): + path, fname = split(filename) + if re.match(r'CSK.*.MBI.tif', fname): + xmlName = join(path, fname.rsplit('MBI.tif')[0] + 'attribs.xml') + if exists(xmlName): + return (xmlName, filename) + return None + +def radarsat2(filename): + path, fname = split(filename) +# if re.match(r'RS2_.*', split(path)[1]) and re.match(r'imagery_.*.tif', fname): + if re.match(r'imagery_.*.tif', fname): + xmlName = join(path, 'product.xml') + if exists(xmlName): + return (xmlName, filename) + return None + +def terraSAR(filename): + path, fname = split(filename) + if re.match(r'IMAGEDATA', split(path)[1]) and re.match(r'IMAGE_.*.tif', fname): + parDir, xmlName = split(split(path)[0]) + xmlName = join(parDir, xmlName, '%s.xml' % xmlName) + if exists(xmlName): + return (xmlName, filename) + return None + + +if __name__ == '__main__': + from optparse import OptionParser + parser = OptionParser(usage="usage: %prog [options] [path(s)]") + parser.add_option("-d", "--dir", dest='outDir', metavar='DIR', + help="specify the output directory (default=cwd)") + parser.add_option("-x", "--xml", dest='xml', action='store_true', + help="Write An XML output") + parser.add_option("-n", "--nitf", dest='nitf', action='store_true', + help="Write A NITF output") + parser.add_option("-t", "--tiff", dest='tiff', action='store_true', + help="Write A TIFF output") + parser.add_option("-k", "--kml", dest='kml', action='store_true', + help="Write A KML output") + parser.add_option("-l", "--level", dest='level', metavar='LEVEL', default=None, + help="Level at which to log ") + parser.add_option("--limit", dest='limit', metavar='NUM', default=0, type='int', + help="Specify a limit on the number of images to process") + (options, args) = parser.parse_args() + + #default to cwd if none provided + outDir = options.outDir or os.getcwd() + if not exists(outDir): + os.makedirs(outDir) + + inputs = [] + paths = args[:] + while paths: + path = paths.pop(0) + if isdir(path): + paths.extend(map(lambda x: join(path, x), os.listdir(path))) + else: + f = cosmoSkyMed(path) + if not f: + f = radarsat2(path) + if not f: + f = terraSAR(path) + if f: + inputs.append(f) + + appName = os.path.abspath(join(split(__file__)[0], './install/bin/ScanSARConverter')) + if 'win32' in sys.platform: + appName += '.exe' + + cmd = [appName] + cmd.extend(['-d', outDir]) + if options.xml: + cmd.append('-x') + if options.nitf: + cmd.append('-n') + if options.tiff: + cmd.append('-t') + if options.kml: + cmd.append('-k') + if options.level: + cmd.extend(['-l', options.level]) + + def process(xml, image): + command = cmd[:] + command.append('%s,%s' % (xml, image)) + print command + p = subprocess.Popen(command).communicate() + + limit = (options.limit > 0 and min(options.limit, len(inputs)) or len(inputs)) + print 'Processing %d files' % limit + for i, (xml, image) in enumerate(inputs): + if i >= limit: + break + process(xml, image) diff --git a/six.sln b/six.sln index 258b1a0eb1..d4bf483ca1 100644 --- a/six.sln +++ b/six.sln @@ -1,131 +1,131 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.31903.59 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nitf-c", "externals\nitro\modules\c\nitf-c.vcxproj", "{F06550AD-CFC7-40B8-8727-6C82C69A8982}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nitf-c++", "externals\nitro\modules\c++\nitf-c++.vcxproj", "{8F357A19-799E-4971-850E-3F28485C130B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "six", "six\modules\c++\six\six.vcxproj", "{62AAD4DD-35BA-41A0-8263-1F4DFD755689}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "scene", "six\modules\c++\scene\scene.vcxproj", "{1CFCDE59-6410-4037-95EB-B37D31E10820}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cphd", "six\modules\c++\cphd\cphd.vcxproj", "{01BE4480-9620-4DED-B34F-D2E3AB4B7C8B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cphd03", "six\modules\c++\cphd03\cphd03.vcxproj", "{016EF417-E41C-404C-B3B5-34B6CDD94BB3}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "six.sicd", "six\modules\c++\six.sicd\six.sicd.vcxproj", "{34AC2314-FBD1-42AD-AAF4-0CEBC6BF737E}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "six.sidd", "six\modules\c++\six.sidd\six.sidd.vcxproj", "{DDC587C2-53BA-44A9-94E7-07BE52AF3D0B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "six.convert", "six\modules\c++\six.convert\six.convert.vcxproj", "{DB4ECC28-A862-4CF4-8A03-69B3CC0C4E8B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XML_DATA_CONTENT", "externals\nitro\modules\c\nitf\XML_DATA_CONTENT.vcxproj", "{78849481-D356-4CC7-B182-31C21F857ED1}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3AD152C2-1F3D-4108-826C-79BA5011874F}" - ProjectSection(SolutionItems) = preProject - six\modules\c++\cpp_pch.h = six\modules\c++\cpp_pch.h - README.md = README.md - ReleaseNotes.md = ReleaseNotes.md - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "check_valid_six", "six\modules\c++\samples\check_valid_six.dir\check_valid_six.vcxproj", "{F0E2C8FF-57D4-4331-9BD2-76FF01CB54EB}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "crop_sicd", "six\modules\c++\samples\crop_sicd.dir\crop_sicd.vcxproj", "{7DCFF6D2-72E8-43E8-8085-35C1721E8DAC}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "csm", "six\projects\csm\csm.vcxproj", "{6E767B43-D1A9-4B02-8D08-42037B7C9262}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTest", "UnitTest\UnitTest.vcxproj", "{F6888896-E658-414C-90CD-1208FA31A22E}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "externals", "externals", "{F033066A-4172-4AC0-96AD-BF5090F713C2}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "coda-oss", "externals\coda-oss\modules\c++\coda-oss.vcxproj", "{9997E895-5161-4DDF-8F3F-099894CB2F21}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github-workflows", ".github-workflows", "{DB2B94ED-952C-4794-A692-E6B64AA9EE5A}" - ProjectSection(SolutionItems) = preProject - .github\workflows\codeql.yml = .github\workflows\codeql.yml - .github\workflows\frequent_check.yml = .github\workflows\frequent_check.yml - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {F06550AD-CFC7-40B8-8727-6C82C69A8982}.Debug|x64.ActiveCfg = Debug|x64 - {F06550AD-CFC7-40B8-8727-6C82C69A8982}.Debug|x64.Build.0 = Debug|x64 - {F06550AD-CFC7-40B8-8727-6C82C69A8982}.Release|x64.ActiveCfg = Release|x64 - {F06550AD-CFC7-40B8-8727-6C82C69A8982}.Release|x64.Build.0 = Release|x64 - {8F357A19-799E-4971-850E-3F28485C130B}.Debug|x64.ActiveCfg = Debug|x64 - {8F357A19-799E-4971-850E-3F28485C130B}.Debug|x64.Build.0 = Debug|x64 - {8F357A19-799E-4971-850E-3F28485C130B}.Release|x64.ActiveCfg = Release|x64 - {8F357A19-799E-4971-850E-3F28485C130B}.Release|x64.Build.0 = Release|x64 - {62AAD4DD-35BA-41A0-8263-1F4DFD755689}.Debug|x64.ActiveCfg = Debug|x64 - {62AAD4DD-35BA-41A0-8263-1F4DFD755689}.Debug|x64.Build.0 = Debug|x64 - {62AAD4DD-35BA-41A0-8263-1F4DFD755689}.Release|x64.ActiveCfg = Release|x64 - {62AAD4DD-35BA-41A0-8263-1F4DFD755689}.Release|x64.Build.0 = Release|x64 - {1CFCDE59-6410-4037-95EB-B37D31E10820}.Debug|x64.ActiveCfg = Debug|x64 - {1CFCDE59-6410-4037-95EB-B37D31E10820}.Debug|x64.Build.0 = Debug|x64 - {1CFCDE59-6410-4037-95EB-B37D31E10820}.Release|x64.ActiveCfg = Release|x64 - {1CFCDE59-6410-4037-95EB-B37D31E10820}.Release|x64.Build.0 = Release|x64 - {01BE4480-9620-4DED-B34F-D2E3AB4B7C8B}.Debug|x64.ActiveCfg = Debug|x64 - {01BE4480-9620-4DED-B34F-D2E3AB4B7C8B}.Debug|x64.Build.0 = Debug|x64 - {01BE4480-9620-4DED-B34F-D2E3AB4B7C8B}.Release|x64.ActiveCfg = Release|x64 - {01BE4480-9620-4DED-B34F-D2E3AB4B7C8B}.Release|x64.Build.0 = Release|x64 - {016EF417-E41C-404C-B3B5-34B6CDD94BB3}.Debug|x64.ActiveCfg = Debug|x64 - {016EF417-E41C-404C-B3B5-34B6CDD94BB3}.Debug|x64.Build.0 = Debug|x64 - {016EF417-E41C-404C-B3B5-34B6CDD94BB3}.Release|x64.ActiveCfg = Release|x64 - {016EF417-E41C-404C-B3B5-34B6CDD94BB3}.Release|x64.Build.0 = Release|x64 - {34AC2314-FBD1-42AD-AAF4-0CEBC6BF737E}.Debug|x64.ActiveCfg = Debug|x64 - {34AC2314-FBD1-42AD-AAF4-0CEBC6BF737E}.Debug|x64.Build.0 = Debug|x64 - {34AC2314-FBD1-42AD-AAF4-0CEBC6BF737E}.Release|x64.ActiveCfg = Release|x64 - {34AC2314-FBD1-42AD-AAF4-0CEBC6BF737E}.Release|x64.Build.0 = Release|x64 - {DDC587C2-53BA-44A9-94E7-07BE52AF3D0B}.Debug|x64.ActiveCfg = Debug|x64 - {DDC587C2-53BA-44A9-94E7-07BE52AF3D0B}.Debug|x64.Build.0 = Debug|x64 - {DDC587C2-53BA-44A9-94E7-07BE52AF3D0B}.Release|x64.ActiveCfg = Release|x64 - {DDC587C2-53BA-44A9-94E7-07BE52AF3D0B}.Release|x64.Build.0 = Release|x64 - {DB4ECC28-A862-4CF4-8A03-69B3CC0C4E8B}.Debug|x64.ActiveCfg = Debug|x64 - {DB4ECC28-A862-4CF4-8A03-69B3CC0C4E8B}.Debug|x64.Build.0 = Debug|x64 - {DB4ECC28-A862-4CF4-8A03-69B3CC0C4E8B}.Release|x64.ActiveCfg = Release|x64 - {DB4ECC28-A862-4CF4-8A03-69B3CC0C4E8B}.Release|x64.Build.0 = Release|x64 - {78849481-D356-4CC7-B182-31C21F857ED1}.Debug|x64.ActiveCfg = Debug|x64 - {78849481-D356-4CC7-B182-31C21F857ED1}.Debug|x64.Build.0 = Debug|x64 - {78849481-D356-4CC7-B182-31C21F857ED1}.Release|x64.ActiveCfg = Release|x64 - {78849481-D356-4CC7-B182-31C21F857ED1}.Release|x64.Build.0 = Release|x64 - {F0E2C8FF-57D4-4331-9BD2-76FF01CB54EB}.Debug|x64.ActiveCfg = Debug|x64 - {F0E2C8FF-57D4-4331-9BD2-76FF01CB54EB}.Debug|x64.Build.0 = Debug|x64 - {F0E2C8FF-57D4-4331-9BD2-76FF01CB54EB}.Release|x64.ActiveCfg = Release|x64 - {F0E2C8FF-57D4-4331-9BD2-76FF01CB54EB}.Release|x64.Build.0 = Release|x64 - {7DCFF6D2-72E8-43E8-8085-35C1721E8DAC}.Debug|x64.ActiveCfg = Debug|x64 - {7DCFF6D2-72E8-43E8-8085-35C1721E8DAC}.Debug|x64.Build.0 = Debug|x64 - {7DCFF6D2-72E8-43E8-8085-35C1721E8DAC}.Release|x64.ActiveCfg = Release|x64 - {7DCFF6D2-72E8-43E8-8085-35C1721E8DAC}.Release|x64.Build.0 = Release|x64 - {6E767B43-D1A9-4B02-8D08-42037B7C9262}.Debug|x64.ActiveCfg = Debug|x64 - {6E767B43-D1A9-4B02-8D08-42037B7C9262}.Debug|x64.Build.0 = Debug|x64 - {6E767B43-D1A9-4B02-8D08-42037B7C9262}.Release|x64.ActiveCfg = Release|x64 - {6E767B43-D1A9-4B02-8D08-42037B7C9262}.Release|x64.Build.0 = Release|x64 - {F6888896-E658-414C-90CD-1208FA31A22E}.Debug|x64.ActiveCfg = Debug|x64 - {F6888896-E658-414C-90CD-1208FA31A22E}.Debug|x64.Build.0 = Debug|x64 - {F6888896-E658-414C-90CD-1208FA31A22E}.Release|x64.ActiveCfg = Release|x64 - {F6888896-E658-414C-90CD-1208FA31A22E}.Release|x64.Build.0 = Release|x64 - {9997E895-5161-4DDF-8F3F-099894CB2F21}.Debug|x64.ActiveCfg = Debug|x64 - {9997E895-5161-4DDF-8F3F-099894CB2F21}.Debug|x64.Build.0 = Debug|x64 - {9997E895-5161-4DDF-8F3F-099894CB2F21}.Release|x64.ActiveCfg = Release|x64 - {9997E895-5161-4DDF-8F3F-099894CB2F21}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {F06550AD-CFC7-40B8-8727-6C82C69A8982} = {F033066A-4172-4AC0-96AD-BF5090F713C2} - {8F357A19-799E-4971-850E-3F28485C130B} = {F033066A-4172-4AC0-96AD-BF5090F713C2} - {78849481-D356-4CC7-B182-31C21F857ED1} = {F033066A-4172-4AC0-96AD-BF5090F713C2} - {9997E895-5161-4DDF-8F3F-099894CB2F21} = {F033066A-4172-4AC0-96AD-BF5090F713C2} - {DB2B94ED-952C-4794-A692-E6B64AA9EE5A} = {3AD152C2-1F3D-4108-826C-79BA5011874F} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {E20E9FC7-D138-4517-8597-79C1FAC3E28D} - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nitf-c", "externals\nitro\modules\c\nitf-c.vcxproj", "{F06550AD-CFC7-40B8-8727-6C82C69A8982}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nitf-c++", "externals\nitro\modules\c++\nitf-c++.vcxproj", "{8F357A19-799E-4971-850E-3F28485C130B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "six", "six\modules\c++\six\six.vcxproj", "{62AAD4DD-35BA-41A0-8263-1F4DFD755689}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "scene", "six\modules\c++\scene\scene.vcxproj", "{1CFCDE59-6410-4037-95EB-B37D31E10820}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cphd", "six\modules\c++\cphd\cphd.vcxproj", "{01BE4480-9620-4DED-B34F-D2E3AB4B7C8B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cphd03", "six\modules\c++\cphd03\cphd03.vcxproj", "{016EF417-E41C-404C-B3B5-34B6CDD94BB3}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "six.sicd", "six\modules\c++\six.sicd\six.sicd.vcxproj", "{34AC2314-FBD1-42AD-AAF4-0CEBC6BF737E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "six.sidd", "six\modules\c++\six.sidd\six.sidd.vcxproj", "{DDC587C2-53BA-44A9-94E7-07BE52AF3D0B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "six.convert", "six\modules\c++\six.convert\six.convert.vcxproj", "{DB4ECC28-A862-4CF4-8A03-69B3CC0C4E8B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XML_DATA_CONTENT", "externals\nitro\modules\c\nitf\XML_DATA_CONTENT.vcxproj", "{78849481-D356-4CC7-B182-31C21F857ED1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3AD152C2-1F3D-4108-826C-79BA5011874F}" + ProjectSection(SolutionItems) = preProject + six\modules\c++\cpp_pch.h = six\modules\c++\cpp_pch.h + README.md = README.md + ReleaseNotes.md = ReleaseNotes.md + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "check_valid_six", "six\modules\c++\samples\check_valid_six.dir\check_valid_six.vcxproj", "{F0E2C8FF-57D4-4331-9BD2-76FF01CB54EB}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "crop_sicd", "six\modules\c++\samples\crop_sicd.dir\crop_sicd.vcxproj", "{7DCFF6D2-72E8-43E8-8085-35C1721E8DAC}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "csm", "six\projects\csm\csm.vcxproj", "{6E767B43-D1A9-4B02-8D08-42037B7C9262}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTest", "UnitTest\UnitTest.vcxproj", "{F6888896-E658-414C-90CD-1208FA31A22E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "externals", "externals", "{F033066A-4172-4AC0-96AD-BF5090F713C2}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "coda-oss", "externals\coda-oss\modules\c++\coda-oss.vcxproj", "{9997E895-5161-4DDF-8F3F-099894CB2F21}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github-workflows", ".github-workflows", "{DB2B94ED-952C-4794-A692-E6B64AA9EE5A}" + ProjectSection(SolutionItems) = preProject + .github\workflows\codeql.yml = .github\workflows\codeql.yml + .github\workflows\frequent_check.yml = .github\workflows\frequent_check.yml + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F06550AD-CFC7-40B8-8727-6C82C69A8982}.Debug|x64.ActiveCfg = Debug|x64 + {F06550AD-CFC7-40B8-8727-6C82C69A8982}.Debug|x64.Build.0 = Debug|x64 + {F06550AD-CFC7-40B8-8727-6C82C69A8982}.Release|x64.ActiveCfg = Release|x64 + {F06550AD-CFC7-40B8-8727-6C82C69A8982}.Release|x64.Build.0 = Release|x64 + {8F357A19-799E-4971-850E-3F28485C130B}.Debug|x64.ActiveCfg = Debug|x64 + {8F357A19-799E-4971-850E-3F28485C130B}.Debug|x64.Build.0 = Debug|x64 + {8F357A19-799E-4971-850E-3F28485C130B}.Release|x64.ActiveCfg = Release|x64 + {8F357A19-799E-4971-850E-3F28485C130B}.Release|x64.Build.0 = Release|x64 + {62AAD4DD-35BA-41A0-8263-1F4DFD755689}.Debug|x64.ActiveCfg = Debug|x64 + {62AAD4DD-35BA-41A0-8263-1F4DFD755689}.Debug|x64.Build.0 = Debug|x64 + {62AAD4DD-35BA-41A0-8263-1F4DFD755689}.Release|x64.ActiveCfg = Release|x64 + {62AAD4DD-35BA-41A0-8263-1F4DFD755689}.Release|x64.Build.0 = Release|x64 + {1CFCDE59-6410-4037-95EB-B37D31E10820}.Debug|x64.ActiveCfg = Debug|x64 + {1CFCDE59-6410-4037-95EB-B37D31E10820}.Debug|x64.Build.0 = Debug|x64 + {1CFCDE59-6410-4037-95EB-B37D31E10820}.Release|x64.ActiveCfg = Release|x64 + {1CFCDE59-6410-4037-95EB-B37D31E10820}.Release|x64.Build.0 = Release|x64 + {01BE4480-9620-4DED-B34F-D2E3AB4B7C8B}.Debug|x64.ActiveCfg = Debug|x64 + {01BE4480-9620-4DED-B34F-D2E3AB4B7C8B}.Debug|x64.Build.0 = Debug|x64 + {01BE4480-9620-4DED-B34F-D2E3AB4B7C8B}.Release|x64.ActiveCfg = Release|x64 + {01BE4480-9620-4DED-B34F-D2E3AB4B7C8B}.Release|x64.Build.0 = Release|x64 + {016EF417-E41C-404C-B3B5-34B6CDD94BB3}.Debug|x64.ActiveCfg = Debug|x64 + {016EF417-E41C-404C-B3B5-34B6CDD94BB3}.Debug|x64.Build.0 = Debug|x64 + {016EF417-E41C-404C-B3B5-34B6CDD94BB3}.Release|x64.ActiveCfg = Release|x64 + {016EF417-E41C-404C-B3B5-34B6CDD94BB3}.Release|x64.Build.0 = Release|x64 + {34AC2314-FBD1-42AD-AAF4-0CEBC6BF737E}.Debug|x64.ActiveCfg = Debug|x64 + {34AC2314-FBD1-42AD-AAF4-0CEBC6BF737E}.Debug|x64.Build.0 = Debug|x64 + {34AC2314-FBD1-42AD-AAF4-0CEBC6BF737E}.Release|x64.ActiveCfg = Release|x64 + {34AC2314-FBD1-42AD-AAF4-0CEBC6BF737E}.Release|x64.Build.0 = Release|x64 + {DDC587C2-53BA-44A9-94E7-07BE52AF3D0B}.Debug|x64.ActiveCfg = Debug|x64 + {DDC587C2-53BA-44A9-94E7-07BE52AF3D0B}.Debug|x64.Build.0 = Debug|x64 + {DDC587C2-53BA-44A9-94E7-07BE52AF3D0B}.Release|x64.ActiveCfg = Release|x64 + {DDC587C2-53BA-44A9-94E7-07BE52AF3D0B}.Release|x64.Build.0 = Release|x64 + {DB4ECC28-A862-4CF4-8A03-69B3CC0C4E8B}.Debug|x64.ActiveCfg = Debug|x64 + {DB4ECC28-A862-4CF4-8A03-69B3CC0C4E8B}.Debug|x64.Build.0 = Debug|x64 + {DB4ECC28-A862-4CF4-8A03-69B3CC0C4E8B}.Release|x64.ActiveCfg = Release|x64 + {DB4ECC28-A862-4CF4-8A03-69B3CC0C4E8B}.Release|x64.Build.0 = Release|x64 + {78849481-D356-4CC7-B182-31C21F857ED1}.Debug|x64.ActiveCfg = Debug|x64 + {78849481-D356-4CC7-B182-31C21F857ED1}.Debug|x64.Build.0 = Debug|x64 + {78849481-D356-4CC7-B182-31C21F857ED1}.Release|x64.ActiveCfg = Release|x64 + {78849481-D356-4CC7-B182-31C21F857ED1}.Release|x64.Build.0 = Release|x64 + {F0E2C8FF-57D4-4331-9BD2-76FF01CB54EB}.Debug|x64.ActiveCfg = Debug|x64 + {F0E2C8FF-57D4-4331-9BD2-76FF01CB54EB}.Debug|x64.Build.0 = Debug|x64 + {F0E2C8FF-57D4-4331-9BD2-76FF01CB54EB}.Release|x64.ActiveCfg = Release|x64 + {F0E2C8FF-57D4-4331-9BD2-76FF01CB54EB}.Release|x64.Build.0 = Release|x64 + {7DCFF6D2-72E8-43E8-8085-35C1721E8DAC}.Debug|x64.ActiveCfg = Debug|x64 + {7DCFF6D2-72E8-43E8-8085-35C1721E8DAC}.Debug|x64.Build.0 = Debug|x64 + {7DCFF6D2-72E8-43E8-8085-35C1721E8DAC}.Release|x64.ActiveCfg = Release|x64 + {7DCFF6D2-72E8-43E8-8085-35C1721E8DAC}.Release|x64.Build.0 = Release|x64 + {6E767B43-D1A9-4B02-8D08-42037B7C9262}.Debug|x64.ActiveCfg = Debug|x64 + {6E767B43-D1A9-4B02-8D08-42037B7C9262}.Debug|x64.Build.0 = Debug|x64 + {6E767B43-D1A9-4B02-8D08-42037B7C9262}.Release|x64.ActiveCfg = Release|x64 + {6E767B43-D1A9-4B02-8D08-42037B7C9262}.Release|x64.Build.0 = Release|x64 + {F6888896-E658-414C-90CD-1208FA31A22E}.Debug|x64.ActiveCfg = Debug|x64 + {F6888896-E658-414C-90CD-1208FA31A22E}.Debug|x64.Build.0 = Debug|x64 + {F6888896-E658-414C-90CD-1208FA31A22E}.Release|x64.ActiveCfg = Release|x64 + {F6888896-E658-414C-90CD-1208FA31A22E}.Release|x64.Build.0 = Release|x64 + {9997E895-5161-4DDF-8F3F-099894CB2F21}.Debug|x64.ActiveCfg = Debug|x64 + {9997E895-5161-4DDF-8F3F-099894CB2F21}.Debug|x64.Build.0 = Debug|x64 + {9997E895-5161-4DDF-8F3F-099894CB2F21}.Release|x64.ActiveCfg = Release|x64 + {9997E895-5161-4DDF-8F3F-099894CB2F21}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {F06550AD-CFC7-40B8-8727-6C82C69A8982} = {F033066A-4172-4AC0-96AD-BF5090F713C2} + {8F357A19-799E-4971-850E-3F28485C130B} = {F033066A-4172-4AC0-96AD-BF5090F713C2} + {78849481-D356-4CC7-B182-31C21F857ED1} = {F033066A-4172-4AC0-96AD-BF5090F713C2} + {9997E895-5161-4DDF-8F3F-099894CB2F21} = {F033066A-4172-4AC0-96AD-BF5090F713C2} + {DB2B94ED-952C-4794-A692-E6B64AA9EE5A} = {3AD152C2-1F3D-4108-826C-79BA5011874F} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E20E9FC7-D138-4517-8597-79C1FAC3E28D} + EndGlobalSection +EndGlobal diff --git a/six/modules/c++/cphd/cphd.vcxproj.filters b/six/modules/c++/cphd/cphd.vcxproj.filters index 0eace9d1af..5c6354173b 100644 --- a/six/modules/c++/cphd/cphd.vcxproj.filters +++ b/six/modules/c++/cphd/cphd.vcxproj.filters @@ -1,195 +1,195 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + \ No newline at end of file diff --git a/six/modules/c++/cphd/include/cphd/Antenna.h b/six/modules/c++/cphd/include/cphd/Antenna.h index 300936e05a..0e7a29b7e6 100644 --- a/six/modules/c++/cphd/include/cphd/Antenna.h +++ b/six/modules/c++/cphd/include/cphd/Antenna.h @@ -1,374 +1,374 @@ -/* ========================================================================= - * This file is part of cphd-c++ - * ========================================================================= - * - * (C) Copyright 2004 - 2019, MDA Information Systems LLC - * - * cphd-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ - -#pragma once -#ifndef SIX_cphd_Antenna_h_INCLUDED_ -#define SIX_cphd_Antenna_h_INCLUDED_ - -#include - -#include -#include -#include - -#include -#include - -#include -#include - -namespace cphd -{ -/* - * \struct AntCoordFrame - * \brief CPHD Antenna Coordinate Frame parameter - * - * Unit vectors that describe the orientation of an - * Antenna Coordinate Frame as a function of time. - * AntCoordFrame used by CPHD, representing the tag - * . - */ -struct AntCoordFrame final -{ - //! Constructor - AntCoordFrame(); - - //! Equality operators - bool operator==(const AntCoordFrame& other) const - { - return (identifier == other.identifier) - && (xAxisPoly == other.xAxisPoly) - && (yAxisPoly == other.yAxisPoly) - && (useACFPVP == other.useACFPVP); - } - bool operator!=(const AntCoordFrame& other) const - { - return !((*this) == other); - } - - //! String that uniquely identifies this ACF - //! (ACF_ID) - std::string identifier; - - //!Antenna coordinate frame X-Axis unit vector in - //! ECF coordinates as a function time (sec). - PolyXYZ xAxisPoly; - - //!Antenna coordinate frame Y-Axis unit vector in - //! ECF coordinates as a function time (sec). - PolyXYZ yAxisPoly; - - //!Indicates the provided ACF PVP arrays provide a more accurate description the ACF orientation vs.time. - six::XsElement_minOccurs0 useACFPVP{ "UseACFPVP" }; // new in CPHD 1.1.0 -}; - -/* - * \struct AntPhaseCenter - * \brief Parameters that describe each Antenna Phase Center. - * - * AntPhaseCenter used by CPHD, representing the tag - * . - */ -struct AntPhaseCenter -{ - //! Constructor - AntPhaseCenter(); - - //! Equality operators - bool operator==(const AntPhaseCenter& other) const - { - return identifier == other.identifier && - acfId == other.acfId && apcXYZ == other.apcXYZ; - } - bool operator!=(const AntPhaseCenter& other) const - { - return !((*this) == other); - } - - //! String that uniquely identifies this APC - //! (APC_ID). - std::string identifier; - - //! Identifier of Antenna Coordinate Frame used for - //! computing the antenna gain and phase patterns - std::string acfId; - - //! The APC location in the ACF XYZ coordinate - //! frame - Vector3 apcXYZ; -}; - -/* - * \struct AntPattern - * \brief CPHD Antenna Pattern parameter - * - * Parameter set that defines each Antenna Pattern - * as a function of time. - * AntPattern used by CPHD, representing the tag - * . - */ -struct AntPattern final -{ - /* - * \struct EBFreqShiftSF - * \brief Scale factors used compute the EB shift vs. frequency - * - * (Optional) Scale factors used compute the EB shift vs. frequency in DCX and DCY. - * - */ - struct EBFreqShiftSF final - { - bool operator==(const EBFreqShiftSF& other) const - { - return (dcxsf == other.dcxsf) - && (dcysf == other.dcysf); - } - bool operator!=(const EBFreqShiftSF& other) const - { - return !((*this) == other); - } - - //! Scale factor used to compute the ML dilation factor in DCX vs. frequency. - six::XsElement dcxsf{ "DCXSF" }; - - //! Scale factor used to compute the ML dilation factor in DCY vs. frequency. - six::XsElement dcysf{ "DCYSF" }; - }; - - /* - * \struct MLFreqDilationSF - * \brief Scale factors used to compute the array pattern - * - * (Optional) Scale factors used to compute the array pattern mainlobe dilation vs. frequency in DCX and DCY. - * - */ - struct MLFreqDilationSF final - { - bool operator==(const MLFreqDilationSF& other) const - { - return (dcxsf == other.dcxsf) - && (dcysf == other.dcysf); - } - bool operator!=(const MLFreqDilationSF& other) const - { - return !((*this) == other); - } - - //! Scale factor used to compute the ML dilation factor in DCX vs. frequency. - six::XsElement dcxsf{ "DCXSF" }; - - //! Scale factor used to compute the ML dilation factor in DCY vs. frequency. - six::XsElement dcysf{ "DCYSF" }; - }; - - /* - * \struct AntPolRef - * \brief Polarization parameters - * - * (Optional) Polarization parameters for the EB steered to mechanical boresight - * - */ - struct AntPolRef final - { - bool operator==(const AntPolRef& other) const - { - return (ampX == other.ampX) - && (ampY == other.ampY) - && (phaseY == other.phaseY); - } - bool operator!=(const AntPolRef& other) const - { - return !((*this) == other); - } - - //! E-field relative amplitude in ACF X direction at f = f_0. - six::XsElement ampX{ "AmpX" }; - - //! E-field relative amplitude in ACY direction at f = f_0. - six::XsElement ampY{ "AmpY" }; - - //! Relative phase of the Y E-field relative to the X E-field at f = f_0. - six::XsElement phaseY{ "PhaseY" }; - }; - - /* - * \struct GainPhaseArray - * \brief Gain Phase Array parameter - * - * (Optional) Parameters that identify 2-D sampled Grain & Phase patterns at - * a single frequency value. - * - */ - struct GainPhaseArray - { - //! Constructor - GainPhaseArray(); - - //! Equality operators - bool operator==(const GainPhaseArray& other) const - { - return freq == other.freq && arrayId == other.arrayId && - elementId == other.elementId; - } - bool operator!=(const GainPhaseArray& other) const - { - return !((*this) == other); - } - - //! Frequency value for which the sampled Array & - //! Element pattern(s) are provided. - double freq; - - //! Support Array identifier of the sampled - //! Gain/Phase of the Array at RefFrequency - std::string arrayId; - - //! (Optional) Support Array identifier of the sampled - //! Gain/Phase of the Element at RefFrequency - std::string elementId; - }; - - //! Default constructor - AntPattern(); - - //! Equality operators - bool operator==(const AntPattern& other) const - { - return identifier == other.identifier && - freqZero == other.freqZero && gainZero == other.gainZero && - ebFreqShift == other.ebFreqShift && - mlFreqDilation == other.mlFreqDilation && - gainBSPoly == other.gainBSPoly && eb == other.eb && - array == other.array && element == other.element && - gainPhaseArray == other.gainPhaseArray; - } - bool operator!=(const AntPattern& other) const - { - return !((*this) == other); - } - - //! String that uniquely identifies this Antenna - //! Pattern (APAT_ID). - std::string identifier; - - //! The reference frequency (f_0) value for which - //! the Electrical Boresight and array pattern - //! polynomials are computed. - double freqZero; - - //! (Optional) The reference antenna gain (G_0) at zero steering - //! angle at the reference frequency (f_0) - double gainZero; - - //! (Optional) Parameter to indicate the EB steering direction - //! shifts with frequency. - six::BooleanType ebFreqShift; - - //! (Optional) Parameter to indicate the mainlobe width varies - //! with frequency. - six::BooleanType mlFreqDilation; - - //! (Optional) Gain polynomial (dB) vs. frequency for the array - //! pattern at boresight. Gain relative to gain at f_0. - //! Poly1D gainBSPoly; - Poly1D gainBSPoly; - - //! (Optional) Scale factors used compute the EB shift vs. frequency - six::XsElement_minOccurs0 ebFreqShiftSF{ "EBFreqShiftSF" }; // new in CPHD 1.1.0 - - //! (Optional) Scale factors used to compute the array pattern - six::XsElement_minOccurs0 mlFreqDilationSF{ "MLFreqDilationSF" }; // new in CPHD 1.1.0 - - //! (Optional) Polarization parameters for the EB steered to mechanical boresight - six::XsElement_minOccurs0 antPolRef{ "AntPolRef" }; // new in CPHD 1.1.0 - - //! The Electrical Boresight steering direction versus - //! time. Defines array pattern pointing direction - six::sicd::ElectricalBoresight eb; - - //! Array Pattern polynomials that describe the - //! mainlobe gain and phase patterns. Patterns - //! defined at f = f_0 - six::sicd::GainAndPhasePolys array; - - //! Element Pattern polynomials that describe the - //! gain and phase patterns - six::sicd::GainAndPhasePolys element; - - //! Parameters that identify 2-D sampled Gain & - //! Phase patterns at single frequency value. - std::vector gainPhaseArray; -}; - -/* - * \struct Antenna - * \brief (Optional) Antenna parameters - * - * Parameters that describe the transmit and - * receive antennas used to collect the signal array. - * See section 8.2 - */ -struct Antenna -{ - //! Default constructor - Antenna(); - - //! Equality operators - bool operator==(const Antenna& other) const - { - return antCoordFrame == other.antCoordFrame && - antPhaseCenter == other.antPhaseCenter && - antPattern == other.antPattern; - } - bool operator!=(const Antenna& other) const - { - return !((*this) == other); - } - - //! Unit vectors that describe the orientation of an - //! Antenna Coordinate Frame (ACF) as function of - //! time. - std::vector antCoordFrame; - - //! Parameters that describe each Antenna Phase - //! Center (APC). Parameter set repeated for each - //! APC - std::vector antPhaseCenter; - - //! Parameter set that defines each Antenna Pattern - //! as function time. Parameters set repeated for - //! each Antenna Pattern - std::vector antPattern; -}; - -//! Ostream operators -std::ostream& operator<< (std::ostream& os, const AntCoordFrame& a); -std::ostream& operator<< (std::ostream& os, const AntPhaseCenter& a); -std::ostream& operator<< (std::ostream& os, const AntPattern::EBFreqShiftSF&); -std::ostream& operator<< (std::ostream& os, const AntPattern::AntPolRef&); -std::ostream& operator<< (std::ostream& os, const AntPattern::MLFreqDilationSF&); -std::ostream& operator<< (std::ostream& os, const AntPattern::GainPhaseArray& g); -std::ostream& operator<< (std::ostream& os, const AntPattern& a); -std::ostream& operator<< (std::ostream& os, const Antenna& a); -} - -#endif // SIX_cphd_Antenna_h_INCLUDED_ +/* ========================================================================= + * This file is part of cphd-c++ + * ========================================================================= + * + * (C) Copyright 2004 - 2019, MDA Information Systems LLC + * + * cphd-c++ is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; If not, + * see . + * + */ + +#pragma once +#ifndef SIX_cphd_Antenna_h_INCLUDED_ +#define SIX_cphd_Antenna_h_INCLUDED_ + +#include + +#include +#include +#include + +#include +#include + +#include +#include + +namespace cphd +{ +/* + * \struct AntCoordFrame + * \brief CPHD Antenna Coordinate Frame parameter + * + * Unit vectors that describe the orientation of an + * Antenna Coordinate Frame as a function of time. + * AntCoordFrame used by CPHD, representing the tag + * . + */ +struct AntCoordFrame final +{ + //! Constructor + AntCoordFrame(); + + //! Equality operators + bool operator==(const AntCoordFrame& other) const + { + return (identifier == other.identifier) + && (xAxisPoly == other.xAxisPoly) + && (yAxisPoly == other.yAxisPoly) + && (useACFPVP == other.useACFPVP); + } + bool operator!=(const AntCoordFrame& other) const + { + return !((*this) == other); + } + + //! String that uniquely identifies this ACF + //! (ACF_ID) + std::string identifier; + + //!Antenna coordinate frame X-Axis unit vector in + //! ECF coordinates as a function time (sec). + PolyXYZ xAxisPoly; + + //!Antenna coordinate frame Y-Axis unit vector in + //! ECF coordinates as a function time (sec). + PolyXYZ yAxisPoly; + + //!Indicates the provided ACF PVP arrays provide a more accurate description the ACF orientation vs.time. + six::XsElement_minOccurs0 useACFPVP{ "UseACFPVP" }; // new in CPHD 1.1.0 +}; + +/* + * \struct AntPhaseCenter + * \brief Parameters that describe each Antenna Phase Center. + * + * AntPhaseCenter used by CPHD, representing the tag + * . + */ +struct AntPhaseCenter +{ + //! Constructor + AntPhaseCenter(); + + //! Equality operators + bool operator==(const AntPhaseCenter& other) const + { + return identifier == other.identifier && + acfId == other.acfId && apcXYZ == other.apcXYZ; + } + bool operator!=(const AntPhaseCenter& other) const + { + return !((*this) == other); + } + + //! String that uniquely identifies this APC + //! (APC_ID). + std::string identifier; + + //! Identifier of Antenna Coordinate Frame used for + //! computing the antenna gain and phase patterns + std::string acfId; + + //! The APC location in the ACF XYZ coordinate + //! frame + Vector3 apcXYZ; +}; + +/* + * \struct AntPattern + * \brief CPHD Antenna Pattern parameter + * + * Parameter set that defines each Antenna Pattern + * as a function of time. + * AntPattern used by CPHD, representing the tag + * . + */ +struct AntPattern final +{ + /* + * \struct EBFreqShiftSF + * \brief Scale factors used compute the EB shift vs. frequency + * + * (Optional) Scale factors used compute the EB shift vs. frequency in DCX and DCY. + * + */ + struct EBFreqShiftSF final + { + bool operator==(const EBFreqShiftSF& other) const + { + return (dcxsf == other.dcxsf) + && (dcysf == other.dcysf); + } + bool operator!=(const EBFreqShiftSF& other) const + { + return !((*this) == other); + } + + //! Scale factor used to compute the ML dilation factor in DCX vs. frequency. + six::XsElement dcxsf{ "DCXSF" }; + + //! Scale factor used to compute the ML dilation factor in DCY vs. frequency. + six::XsElement dcysf{ "DCYSF" }; + }; + + /* + * \struct MLFreqDilationSF + * \brief Scale factors used to compute the array pattern + * + * (Optional) Scale factors used to compute the array pattern mainlobe dilation vs. frequency in DCX and DCY. + * + */ + struct MLFreqDilationSF final + { + bool operator==(const MLFreqDilationSF& other) const + { + return (dcxsf == other.dcxsf) + && (dcysf == other.dcysf); + } + bool operator!=(const MLFreqDilationSF& other) const + { + return !((*this) == other); + } + + //! Scale factor used to compute the ML dilation factor in DCX vs. frequency. + six::XsElement dcxsf{ "DCXSF" }; + + //! Scale factor used to compute the ML dilation factor in DCY vs. frequency. + six::XsElement dcysf{ "DCYSF" }; + }; + + /* + * \struct AntPolRef + * \brief Polarization parameters + * + * (Optional) Polarization parameters for the EB steered to mechanical boresight + * + */ + struct AntPolRef final + { + bool operator==(const AntPolRef& other) const + { + return (ampX == other.ampX) + && (ampY == other.ampY) + && (phaseY == other.phaseY); + } + bool operator!=(const AntPolRef& other) const + { + return !((*this) == other); + } + + //! E-field relative amplitude in ACF X direction at f = f_0. + six::XsElement ampX{ "AmpX" }; + + //! E-field relative amplitude in ACY direction at f = f_0. + six::XsElement ampY{ "AmpY" }; + + //! Relative phase of the Y E-field relative to the X E-field at f = f_0. + six::XsElement phaseY{ "PhaseY" }; + }; + + /* + * \struct GainPhaseArray + * \brief Gain Phase Array parameter + * + * (Optional) Parameters that identify 2-D sampled Grain & Phase patterns at + * a single frequency value. + * + */ + struct GainPhaseArray + { + //! Constructor + GainPhaseArray(); + + //! Equality operators + bool operator==(const GainPhaseArray& other) const + { + return freq == other.freq && arrayId == other.arrayId && + elementId == other.elementId; + } + bool operator!=(const GainPhaseArray& other) const + { + return !((*this) == other); + } + + //! Frequency value for which the sampled Array & + //! Element pattern(s) are provided. + double freq; + + //! Support Array identifier of the sampled + //! Gain/Phase of the Array at RefFrequency + std::string arrayId; + + //! (Optional) Support Array identifier of the sampled + //! Gain/Phase of the Element at RefFrequency + std::string elementId; + }; + + //! Default constructor + AntPattern(); + + //! Equality operators + bool operator==(const AntPattern& other) const + { + return identifier == other.identifier && + freqZero == other.freqZero && gainZero == other.gainZero && + ebFreqShift == other.ebFreqShift && + mlFreqDilation == other.mlFreqDilation && + gainBSPoly == other.gainBSPoly && eb == other.eb && + array == other.array && element == other.element && + gainPhaseArray == other.gainPhaseArray; + } + bool operator!=(const AntPattern& other) const + { + return !((*this) == other); + } + + //! String that uniquely identifies this Antenna + //! Pattern (APAT_ID). + std::string identifier; + + //! The reference frequency (f_0) value for which + //! the Electrical Boresight and array pattern + //! polynomials are computed. + double freqZero; + + //! (Optional) The reference antenna gain (G_0) at zero steering + //! angle at the reference frequency (f_0) + double gainZero; + + //! (Optional) Parameter to indicate the EB steering direction + //! shifts with frequency. + six::BooleanType ebFreqShift; + + //! (Optional) Parameter to indicate the mainlobe width varies + //! with frequency. + six::BooleanType mlFreqDilation; + + //! (Optional) Gain polynomial (dB) vs. frequency for the array + //! pattern at boresight. Gain relative to gain at f_0. + //! Poly1D gainBSPoly; + Poly1D gainBSPoly; + + //! (Optional) Scale factors used compute the EB shift vs. frequency + six::XsElement_minOccurs0 ebFreqShiftSF{ "EBFreqShiftSF" }; // new in CPHD 1.1.0 + + //! (Optional) Scale factors used to compute the array pattern + six::XsElement_minOccurs0 mlFreqDilationSF{ "MLFreqDilationSF" }; // new in CPHD 1.1.0 + + //! (Optional) Polarization parameters for the EB steered to mechanical boresight + six::XsElement_minOccurs0 antPolRef{ "AntPolRef" }; // new in CPHD 1.1.0 + + //! The Electrical Boresight steering direction versus + //! time. Defines array pattern pointing direction + six::sicd::ElectricalBoresight eb; + + //! Array Pattern polynomials that describe the + //! mainlobe gain and phase patterns. Patterns + //! defined at f = f_0 + six::sicd::GainAndPhasePolys array; + + //! Element Pattern polynomials that describe the + //! gain and phase patterns + six::sicd::GainAndPhasePolys element; + + //! Parameters that identify 2-D sampled Gain & + //! Phase patterns at single frequency value. + std::vector gainPhaseArray; +}; + +/* + * \struct Antenna + * \brief (Optional) Antenna parameters + * + * Parameters that describe the transmit and + * receive antennas used to collect the signal array. + * See section 8.2 + */ +struct Antenna +{ + //! Default constructor + Antenna(); + + //! Equality operators + bool operator==(const Antenna& other) const + { + return antCoordFrame == other.antCoordFrame && + antPhaseCenter == other.antPhaseCenter && + antPattern == other.antPattern; + } + bool operator!=(const Antenna& other) const + { + return !((*this) == other); + } + + //! Unit vectors that describe the orientation of an + //! Antenna Coordinate Frame (ACF) as function of + //! time. + std::vector antCoordFrame; + + //! Parameters that describe each Antenna Phase + //! Center (APC). Parameter set repeated for each + //! APC + std::vector antPhaseCenter; + + //! Parameter set that defines each Antenna Pattern + //! as function time. Parameters set repeated for + //! each Antenna Pattern + std::vector antPattern; +}; + +//! Ostream operators +std::ostream& operator<< (std::ostream& os, const AntCoordFrame& a); +std::ostream& operator<< (std::ostream& os, const AntPhaseCenter& a); +std::ostream& operator<< (std::ostream& os, const AntPattern::EBFreqShiftSF&); +std::ostream& operator<< (std::ostream& os, const AntPattern::AntPolRef&); +std::ostream& operator<< (std::ostream& os, const AntPattern::MLFreqDilationSF&); +std::ostream& operator<< (std::ostream& os, const AntPattern::GainPhaseArray& g); +std::ostream& operator<< (std::ostream& os, const AntPattern& a); +std::ostream& operator<< (std::ostream& os, const Antenna& a); +} + +#endif // SIX_cphd_Antenna_h_INCLUDED_ diff --git a/six/modules/c++/cphd/include/cphd/Dwell.h b/six/modules/c++/cphd/include/cphd/Dwell.h index 44c2537371..86092806f6 100644 --- a/six/modules/c++/cphd/include/cphd/Dwell.h +++ b/six/modules/c++/cphd/include/cphd/Dwell.h @@ -1,128 +1,128 @@ -/* ========================================================================= - * This file is part of cphd-c++ - * ========================================================================= - * - * (C) Copyright 2004 - 2019, MDA Information Systems LLC - * - * cphd-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ - -#ifndef __CPHD_DWELL_H__ -#define __CPHD_DWELL_H__ - -#include -#include - -#include -#include - -#include - -namespace cphd -{ - -/* - * \struct DwellTime - * - * \brief Dwell Time Polynomial - */ -struct DwellTime -{ - //! Constructor - DwellTime(); - - //! Equality operators - bool operator==(const DwellTime& other) const - { - return identifier == other.identifier && dwellTimePoly == other.dwellTimePoly; - } - bool operator!=(const DwellTime& other) const - { - return !((*this) == other); - } - - //! String that uniquely identifies this Dwell Time polynomial (Dwell_ID) - std::string identifier; - - //! Polynomial that yields Dwell Time as a function of IAX and IAY - Poly2D dwellTimePoly; -}; - -/* - * \struct COD - * - * \brief Center of Dwell Time Polynomial - */ -struct COD -{ - //! Constructor - COD(); - - //! Equality operators - bool operator==(const COD& other) const - { - return identifier == other.identifier && codTimePoly == other.codTimePoly; - } - bool operator!=(const COD& other) const - { - return !((*this) == other); - } - - //! String that uniquely identifies this COD Time polynomial (COD_ID) - std::string identifier; - - //! Polynomial that yields COD Time as a function of IAX and IAY - Poly2D codTimePoly; -}; - -/* - * \struct Dwell - * - * \brief Dwell Time parameters - * - * Parameters that specify the dwell time supported by the signal arrays - * contained in the CPHD product - * See section 7.3 - */ -struct Dwell -{ - //! Constructor - Dwell(); - - // Equality operator - bool operator==(const Dwell& other) const - { - return cod == other.cod && dtime == other.dtime; - } - bool operator!=(const Dwell& other) const - { - return !((*this) == other); - } - - //! Center of Dwell (COD) Time Polynomial - std::vector cod; - - //! Dwell Time Polynomial - std::vector dtime; -}; - -//! Ostream operators -std::ostream& operator<< (std::ostream& os, const DwellTime& d); -std::ostream& operator<< (std::ostream& os, const COD& c); -std::ostream& operator<< (std::ostream& os, const Dwell& d); -} - -#endif +/* ========================================================================= + * This file is part of cphd-c++ + * ========================================================================= + * + * (C) Copyright 2004 - 2019, MDA Information Systems LLC + * + * cphd-c++ is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; If not, + * see . + * + */ + +#ifndef __CPHD_DWELL_H__ +#define __CPHD_DWELL_H__ + +#include +#include + +#include +#include + +#include + +namespace cphd +{ + +/* + * \struct DwellTime + * + * \brief Dwell Time Polynomial + */ +struct DwellTime +{ + //! Constructor + DwellTime(); + + //! Equality operators + bool operator==(const DwellTime& other) const + { + return identifier == other.identifier && dwellTimePoly == other.dwellTimePoly; + } + bool operator!=(const DwellTime& other) const + { + return !((*this) == other); + } + + //! String that uniquely identifies this Dwell Time polynomial (Dwell_ID) + std::string identifier; + + //! Polynomial that yields Dwell Time as a function of IAX and IAY + Poly2D dwellTimePoly; +}; + +/* + * \struct COD + * + * \brief Center of Dwell Time Polynomial + */ +struct COD +{ + //! Constructor + COD(); + + //! Equality operators + bool operator==(const COD& other) const + { + return identifier == other.identifier && codTimePoly == other.codTimePoly; + } + bool operator!=(const COD& other) const + { + return !((*this) == other); + } + + //! String that uniquely identifies this COD Time polynomial (COD_ID) + std::string identifier; + + //! Polynomial that yields COD Time as a function of IAX and IAY + Poly2D codTimePoly; +}; + +/* + * \struct Dwell + * + * \brief Dwell Time parameters + * + * Parameters that specify the dwell time supported by the signal arrays + * contained in the CPHD product + * See section 7.3 + */ +struct Dwell +{ + //! Constructor + Dwell(); + + // Equality operator + bool operator==(const Dwell& other) const + { + return cod == other.cod && dtime == other.dtime; + } + bool operator!=(const Dwell& other) const + { + return !((*this) == other); + } + + //! Center of Dwell (COD) Time Polynomial + std::vector cod; + + //! Dwell Time Polynomial + std::vector dtime; +}; + +//! Ostream operators +std::ostream& operator<< (std::ostream& os, const DwellTime& d); +std::ostream& operator<< (std::ostream& os, const COD& c); +std::ostream& operator<< (std::ostream& os, const Dwell& d); +} + +#endif diff --git a/six/modules/c++/cphd/include/cphd/ErrorParameters.h b/six/modules/c++/cphd/include/cphd/ErrorParameters.h index 0f4be81343..6bd94d91c7 100644 --- a/six/modules/c++/cphd/include/cphd/ErrorParameters.h +++ b/six/modules/c++/cphd/include/cphd/ErrorParameters.h @@ -1,240 +1,240 @@ -/* ========================================================================= - * This file is part of cphd-c++ - * ========================================================================= - * - * (C) Copyright 2004 - 2019, MDA Information Systems LLC - * - * cphd-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ - -#pragma once -#ifndef SIX_cphd_ErrorParameters_h_INCLUDED_ -#define SIX_cphd_ErrorParameters_h_INCLUDED_ - -#include - -#include -#include -#include - -#include -#include -#include - -#include -#include - -namespace cphd -{ - -/* - * \struct ErrorParameters - * - * \brief Describes error parameters - * - * (Optional) Parameters that describe the statistics of errors - * in measured or estimated parameters that describe - * the collection - */ -struct ErrorParameters -{ - /* - * \struct Monostatic - * - * \brief (Conditional) Parameters for CollectType = "MONOSTATIC" - */ - struct Monostatic - { - /* - * \struct RadarSensor - * - * \brief Position and velocity error statistics for the - * sensor platform - */ - struct RadarSensor - { - //! Constructor - RadarSensor(); - - //! Equality operators - bool operator==(const RadarSensor& other) const - { - return rangeBias == other.rangeBias && - clockFreqSF == other.clockFreqSF && - collectionStartTime == other.collectionStartTime && - rangeBiasDecorr == other.rangeBiasDecorr; - } - bool operator!=(const RadarSensor& other) const - { - return !((*this) == other); - } - - //! Range bias error standard deviation. - double rangeBias; - - //! (Optional) Payload clock frequency scale factor standard deviation - double clockFreqSF; - - //! (Optional) Collection Start time error standard deviation - double collectionStartTime; - - //! (Optional) Range Bias error decorrelation function - mem::ScopedCopyablePtr rangeBiasDecorr; - }; - - //! Equality operators - bool operator==(const Monostatic& other) const - { - return posVelErr == other.posVelErr && - radarSensor == other.radarSensor && - tropoError == other.tropoError && - ionoError == other.ionoError && - parameter == other.parameter; - } - bool operator!=(const Monostatic& other) const - { - return !((*this) == other); - } - - //! Position and velocity error statistics for the - //! Transmit platform. - six::PosVelError posVelErr; - - //! Radar sensor error statistics - RadarSensor radarSensor; - - //! (Optional) Error parameters related to the Troposphere - mem::ScopedCopyablePtr tropoError; - - //! (Optional) Error parameters related to the Ionosphere - mem::ScopedCopyablePtr ionoError; - - //! (Optional) Additional error parameters to be added for - //! Monostatic collections - six::ParameterCollection parameter; - }; - - /* - * \struct Bistatic - * - * \brief (Conditional) Parameters for CollectType = "BISTATIC" - */ - struct Bistatic final - { - /* - * \struct RadarSensor - * - * \brief Error statistics for the Transmit platform - */ - struct RadarSensor final - { - //! Constructor - RadarSensor(); - - //! Equality operators - bool operator==(const RadarSensor& other) const - { - return (delayBias == other.delayBias) - && (clockFreqSF == other.clockFreqSF) - && (collectionStartTime == other.collectionStartTime); - } - bool operator!=(const RadarSensor& other) const - { - return !((*this) == other); - } - - //! Transmit time delay bias error standard deviation - six::XsElement_minOccurs0 delayBias{ "DelayBias" }; // new in CPHD 1.1.0 - - //! (Optional) Payload clock frequency scale factor standard deviation - double clockFreqSF; - - //! Collection Start time error standard deviation. - double collectionStartTime; - }; - - /* - * \struct Platform - * - * \brief Error statisitcs of platforms - */ - struct Platform - { - //! Equality operators - bool operator==(const Platform& other) const - { - return posVelErr == other.posVelErr && - radarSensor == other.radarSensor; - } - bool operator!=(const Platform& other) const - { - return !((*this) == other); - } - - //! Position and velocity error statistics - six::PosVelError posVelErr; - - //! Transmit sensor error statistics - RadarSensor radarSensor; - }; - - //! Equality operators - bool operator==(const Bistatic& other) const - { - return txPlatform == other.txPlatform && - rcvPlatform == other.rcvPlatform && - parameter == other.parameter; - } - bool operator!=(const Bistatic& other) const - { - return !((*this) == other); - } - - //! Error statistics for the Transmit platform - Platform txPlatform; - - //! Error statistics for the Receive Only platform. - Platform rcvPlatform; - - //! Additional error parameters to be added for - //! Bistatic collections - six::ParameterCollection parameter; - }; - - //! Equality operators - bool operator==(const ErrorParameters& other) const - { - return monostatic == other.monostatic && - bistatic == other.bistatic; - } - bool operator!=(const ErrorParameters& other) const - { - return !((*this) == other); - } - - //! (Conditional) Parameters for CollectType = "MONOSTATIC" - mem::ScopedCopyablePtr monostatic; - - //! (Conditional) Parameters for CollectType = "BISTATIC" - mem::ScopedCopyablePtr bistatic; -}; - -//! Ostream operators -std::ostream& operator<< (std::ostream& os, const six::PosVelError& p); -std::ostream& operator<< (std::ostream& os, const ErrorParameters& e); -} - -#endif // SIX_cphd_ErrorParameters_h_INCLUDED_ +/* ========================================================================= + * This file is part of cphd-c++ + * ========================================================================= + * + * (C) Copyright 2004 - 2019, MDA Information Systems LLC + * + * cphd-c++ is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; If not, + * see . + * + */ + +#pragma once +#ifndef SIX_cphd_ErrorParameters_h_INCLUDED_ +#define SIX_cphd_ErrorParameters_h_INCLUDED_ + +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +namespace cphd +{ + +/* + * \struct ErrorParameters + * + * \brief Describes error parameters + * + * (Optional) Parameters that describe the statistics of errors + * in measured or estimated parameters that describe + * the collection + */ +struct ErrorParameters +{ + /* + * \struct Monostatic + * + * \brief (Conditional) Parameters for CollectType = "MONOSTATIC" + */ + struct Monostatic + { + /* + * \struct RadarSensor + * + * \brief Position and velocity error statistics for the + * sensor platform + */ + struct RadarSensor + { + //! Constructor + RadarSensor(); + + //! Equality operators + bool operator==(const RadarSensor& other) const + { + return rangeBias == other.rangeBias && + clockFreqSF == other.clockFreqSF && + collectionStartTime == other.collectionStartTime && + rangeBiasDecorr == other.rangeBiasDecorr; + } + bool operator!=(const RadarSensor& other) const + { + return !((*this) == other); + } + + //! Range bias error standard deviation. + double rangeBias; + + //! (Optional) Payload clock frequency scale factor standard deviation + double clockFreqSF; + + //! (Optional) Collection Start time error standard deviation + double collectionStartTime; + + //! (Optional) Range Bias error decorrelation function + mem::ScopedCopyablePtr rangeBiasDecorr; + }; + + //! Equality operators + bool operator==(const Monostatic& other) const + { + return posVelErr == other.posVelErr && + radarSensor == other.radarSensor && + tropoError == other.tropoError && + ionoError == other.ionoError && + parameter == other.parameter; + } + bool operator!=(const Monostatic& other) const + { + return !((*this) == other); + } + + //! Position and velocity error statistics for the + //! Transmit platform. + six::PosVelError posVelErr; + + //! Radar sensor error statistics + RadarSensor radarSensor; + + //! (Optional) Error parameters related to the Troposphere + mem::ScopedCopyablePtr tropoError; + + //! (Optional) Error parameters related to the Ionosphere + mem::ScopedCopyablePtr ionoError; + + //! (Optional) Additional error parameters to be added for + //! Monostatic collections + six::ParameterCollection parameter; + }; + + /* + * \struct Bistatic + * + * \brief (Conditional) Parameters for CollectType = "BISTATIC" + */ + struct Bistatic final + { + /* + * \struct RadarSensor + * + * \brief Error statistics for the Transmit platform + */ + struct RadarSensor final + { + //! Constructor + RadarSensor(); + + //! Equality operators + bool operator==(const RadarSensor& other) const + { + return (delayBias == other.delayBias) + && (clockFreqSF == other.clockFreqSF) + && (collectionStartTime == other.collectionStartTime); + } + bool operator!=(const RadarSensor& other) const + { + return !((*this) == other); + } + + //! Transmit time delay bias error standard deviation + six::XsElement_minOccurs0 delayBias{ "DelayBias" }; // new in CPHD 1.1.0 + + //! (Optional) Payload clock frequency scale factor standard deviation + double clockFreqSF; + + //! Collection Start time error standard deviation. + double collectionStartTime; + }; + + /* + * \struct Platform + * + * \brief Error statisitcs of platforms + */ + struct Platform + { + //! Equality operators + bool operator==(const Platform& other) const + { + return posVelErr == other.posVelErr && + radarSensor == other.radarSensor; + } + bool operator!=(const Platform& other) const + { + return !((*this) == other); + } + + //! Position and velocity error statistics + six::PosVelError posVelErr; + + //! Transmit sensor error statistics + RadarSensor radarSensor; + }; + + //! Equality operators + bool operator==(const Bistatic& other) const + { + return txPlatform == other.txPlatform && + rcvPlatform == other.rcvPlatform && + parameter == other.parameter; + } + bool operator!=(const Bistatic& other) const + { + return !((*this) == other); + } + + //! Error statistics for the Transmit platform + Platform txPlatform; + + //! Error statistics for the Receive Only platform. + Platform rcvPlatform; + + //! Additional error parameters to be added for + //! Bistatic collections + six::ParameterCollection parameter; + }; + + //! Equality operators + bool operator==(const ErrorParameters& other) const + { + return monostatic == other.monostatic && + bistatic == other.bistatic; + } + bool operator!=(const ErrorParameters& other) const + { + return !((*this) == other); + } + + //! (Conditional) Parameters for CollectType = "MONOSTATIC" + mem::ScopedCopyablePtr monostatic; + + //! (Conditional) Parameters for CollectType = "BISTATIC" + mem::ScopedCopyablePtr bistatic; +}; + +//! Ostream operators +std::ostream& operator<< (std::ostream& os, const six::PosVelError& p); +std::ostream& operator<< (std::ostream& os, const ErrorParameters& e); +} + +#endif // SIX_cphd_ErrorParameters_h_INCLUDED_ diff --git a/six/modules/c++/cphd/include/cphd/MetadataBase.h b/six/modules/c++/cphd/include/cphd/MetadataBase.h index abdac611bc..5852887e5f 100644 --- a/six/modules/c++/cphd/include/cphd/MetadataBase.h +++ b/six/modules/c++/cphd/include/cphd/MetadataBase.h @@ -1,111 +1,111 @@ -/* ========================================================================= - * This file is part of cphd-c++ - * ========================================================================= - * - * (C) Copyright 2004 - 2019, MDA Information Systems LLC - * - * cphd-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ - -#ifndef __CPHD_METADATA_BASE_H__ -#define __CPHD_METADATA_BASE_H__ - -#include -#include -#include - -namespace cphd -{ -/*! - * \class MetadataBase - * \brief Abstract base class for the CPHD and CPHD03 Metdata objects. - * - * The metadata object is derived for CPHD and CPHD03 - *. This class provides the interface needed - * to interact with the signal block reader Wideband, currently in CPHD - * - */ -struct MetadataBase -{ - //! Default constructor - MetadataBase() - { - } - - //! Destructor - virtual ~MetadataBase() - { - } - - /* - * Getter functions - */ - virtual size_t getNumChannels() const = 0; - virtual size_t getNumVectors(size_t channel) const = 0; // 0-based channel number - virtual size_t getNumSamples(size_t channel) const = 0; // 0-based channel number - virtual size_t getNumBytesPerSample() const = 0; // 2, 4, or 8 bytes/complex sample - - /* - * \func getCompressedSignalSize - * \brief Gets the size of compressed signal array - * if applicable - * - * This function returns default value. Can be overridden - * if required (Ex: CPHD::Metadata) - * - * \return undefined value by default - */ - virtual size_t getCompressedSignalSize(size_t /*channel*/) const - { - return six::Init::undefined(); - } - - /* - * \func isCompressed - * \brief Check if signal data is compressed - * - * This function returns default value false. Function can - * be overridden if required (Ex: CPHD::Metadata) - * - * \return false by default - */ - virtual bool isCompressed() const - { - return false; - } - - /*! - * Get domain type - * FX for frequency domain, - * TOA for time-of-arrival domain - */ - virtual DomainType getDomainType() const = 0; - - //! Is this CPHD formed in the transmit frequency domain? - bool isFX() const - { - return (getDomainType() == cphd::DomainType::FX); - } - - //! Is this CPHD formed in the Time of Arrival domain? - bool isTOA() const - { - return (getDomainType() == cphd::DomainType::TOA); - } -}; -} - -#endif +/* ========================================================================= + * This file is part of cphd-c++ + * ========================================================================= + * + * (C) Copyright 2004 - 2019, MDA Information Systems LLC + * + * cphd-c++ is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; If not, + * see . + * + */ + +#ifndef __CPHD_METADATA_BASE_H__ +#define __CPHD_METADATA_BASE_H__ + +#include +#include +#include + +namespace cphd +{ +/*! + * \class MetadataBase + * \brief Abstract base class for the CPHD and CPHD03 Metdata objects. + * + * The metadata object is derived for CPHD and CPHD03 + *. This class provides the interface needed + * to interact with the signal block reader Wideband, currently in CPHD + * + */ +struct MetadataBase +{ + //! Default constructor + MetadataBase() + { + } + + //! Destructor + virtual ~MetadataBase() + { + } + + /* + * Getter functions + */ + virtual size_t getNumChannels() const = 0; + virtual size_t getNumVectors(size_t channel) const = 0; // 0-based channel number + virtual size_t getNumSamples(size_t channel) const = 0; // 0-based channel number + virtual size_t getNumBytesPerSample() const = 0; // 2, 4, or 8 bytes/complex sample + + /* + * \func getCompressedSignalSize + * \brief Gets the size of compressed signal array + * if applicable + * + * This function returns default value. Can be overridden + * if required (Ex: CPHD::Metadata) + * + * \return undefined value by default + */ + virtual size_t getCompressedSignalSize(size_t /*channel*/) const + { + return six::Init::undefined(); + } + + /* + * \func isCompressed + * \brief Check if signal data is compressed + * + * This function returns default value false. Function can + * be overridden if required (Ex: CPHD::Metadata) + * + * \return false by default + */ + virtual bool isCompressed() const + { + return false; + } + + /*! + * Get domain type + * FX for frequency domain, + * TOA for time-of-arrival domain + */ + virtual DomainType getDomainType() const = 0; + + //! Is this CPHD formed in the transmit frequency domain? + bool isFX() const + { + return (getDomainType() == cphd::DomainType::FX); + } + + //! Is this CPHD formed in the Time of Arrival domain? + bool isTOA() const + { + return (getDomainType() == cphd::DomainType::TOA); + } +}; +} + +#endif diff --git a/six/modules/c++/cphd/include/cphd/PVP.h b/six/modules/c++/cphd/include/cphd/PVP.h index f19341303c..d302b60a8c 100644 --- a/six/modules/c++/cphd/include/cphd/PVP.h +++ b/six/modules/c++/cphd/include/cphd/PVP.h @@ -1,612 +1,612 @@ -/* ========================================================================= - * This file is part of cphd-c++ - * ========================================================================= - * - * (C) Copyright 2004 - 2019, MDA Information Systems LLC - * - * cphd-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ - -#pragma once -#ifndef SIX_cphd_PVP_h_INCLUDED_ -#define SIX_cphd_PVP_h_INCLUDED_ - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "cphd/Types.h" - -namespace cphd -{ - -/*! - * \struct PVPType - * - * \brief Specifies a defined Per Vector Parameter. - * - * Size and Offset specify the size and placement of - * the binary parameter in the set of Per Vector - * parameters provided for each vector. - */ -struct PVPType -{ - static constexpr size_t WORD_BYTE_SIZE = 8; - - /*! - * \func PVPType - * - * \brief Default constructor - */ - PVPType(); - - //! Equality operators - bool operator==(const PVPType& other) const - { - return mSize == other.getSize() && - mOffset == other.getOffset() && - mFormat == other.getFormat(); - } - bool operator!=(const PVPType& other) const - { - return !((*this) == other); - } - - //! Setter Functions - void setOffset(size_t offset) - { - mOffset = offset; - } - void setSize(size_t size) - { - mSize = size; - } - void setFormat(const std::string& format) - { - mFormat = format; - } - - //! Get size - size_t getSize() const - { - return mSize; - } - //! Get size in bytes - size_t getByteSize() const - { - return mSize * WORD_BYTE_SIZE; - } - //! Get offset - size_t getOffset() const - { - return mOffset; - } - - //! Get offset in bytes - size_t getByteOffset() const - { - return mOffset * WORD_BYTE_SIZE; - } - - //! Get format - std::string getFormat() const - { - return mFormat; - } - -protected: - //! Size of parameter - XsPositiveInteger_fixed2 mSize; // txACX{ "TxACX" }; - - //! TxACY PVP Structure - six::XsElement txACY{ "TxACY" }; - - //! TxEB PVP Structure - six::XsElement txEB{ "TxEB" }; -}; - -/*! - * \struct RcvAntenna - * \brief Specify the Receive Antenna orientation and the Steering vector. - * - * Parameters included that specify the Receive Antenna ACF orientation and the EB Steering vector. - * (New in CPHD 1.1.0) - */ -struct RcvAntenna final -{ - bool operator==(const RcvAntenna& other) const - { - return (rcvACX == other.rcvACX) - && (rcvACY == other.rcvACY) - && (rcvEB == other.rcvEB); - } - bool operator!=(const RcvAntenna& other) const - { - return !((*this) == other); - } - - //! RcvACX PVP Structure - six::XsElement rcvACX{ "RcvACX" }; - - //! RcvACY PVP Structure - six::XsElement rcvACY{ "RcvACY" }; - - //! RcvEB PVP Structure - six::XsElement rcvEB{ "RcvEB" }; -}; - -/*! - * \struct Pvp - * - * \brief Structure used to specify the Per Vector - * parameters - * - * Provided for each channel of a given product. - */ -struct Pvp final -{ - /*! - * Transmit time for the center of the transmitted pulse relative to the - * transmit platform Collection Start Time (sec). - */ - PVPType txTime; - - /*! - * Transmit APC position at time txc(v) in Earth Centered Fixed - * (ECF) coordinates (meters). Components in X, Y, Z order. - * 3 8-byte floats required. - */ - PVPType txPos; - - /*! - * Transmit APC velocity at time txc(v) in ECF coordinates - * (meters/sec). - * 3 8-byte floats required. - */ - PVPType txVel; - - /*! - * Receive time for the center of the echo from the srp relative to the - * transmit platform Collection Start Time (sec). Time is the Time of - * Arrival (toa) of the received echo from the srp for the signal - * transmitted at txc(v). - */ - PVPType rcvTime; - - - /*! - * Receive APC position at time trc(v)srp in ECF coordinates - * (meters). - * 3 8-byte floats required. - */ - PVPType rcvPos; - - /*! - * Receive APC velocity at time trc(v)srp in ECF coordinates - * (meters/sec). - * 3 8-byte floats required - */ - PVPType rcvVel; - - /*! - * Stabilization Reference Point (srp) position in ECF coordinates - * (meters). - * 3 8-byte floats required. - */ - PVPType srpPos; - - /*! - * (Optional) Amplitude scale Factor to be applied to all samples of the signal - * vector. For signal vector v, each sample value is multiplied by - * Amp_SF(v) to yield the proper sample values for the vector. - */ - PVPType ampSF; - - /*! - * The DOPPLER shift micro parameter. Parameter accounts for the - * time dilation/Doppler shift for the echoes from all targets with the - * same time dilation/Doppler shift as the srp echo. - */ - PVPType aFDOP; - - /*! - * First order phase micro parameter (i.e. linear phase). Accounts for - * linear phase vs. FX frequency for targets with time - * dilation/Doppler shift different than the echo from the srp. - * Provides precise linear phase prediction for Linear FM waveforms. - */ - PVPType aFRR1; - - /*! - * Second order phase micro parameter (i.e. quadratic phase). - * Accounts for quadratic phase vs. FX frequency for targets with - * time dilation/Doppler shift different than the echo from the srp. - * Provides precise quadratic phase prediction for Linear FM - * waveforms. - */ - PVPType aFRR2; - - /*! - * The FX domain frequency limits of the transmitted waveform - * retained in the signal vector (Hz). - * Saved transmit band is from fx_1(v) < fx < fx_2(v) - * For the vector: FX_BW(v) = fx_2(v) – fx_1(v) - */ - PVPType fx1; - - /*! - * The FX domain frequency limits of the transmitted waveform - * retained in the signal vector (Hz). - * Saved transmit band is from fx_1(v) < fx < fx_2(v) - * For the vector: FX_BW(v) = fx_2(v) – fx_1(v) - */ - PVPType fx2; - - /*! - * (Optional) The FX domain frequency limits for out-of-band noise signal for - * frequencies below fx_1(v) and above fx_2(v). May ONLY be - * included for Domain_Type = FX. - * For any vector: fx_N1 < fx_1 & fx_2 < fx_N2 - * When included in a product, fx_N1 & fx_N2 are both included. - */ - PVPType fxN1; - - /*! - * (Optional) The FX domain frequency limits for out-of-band noise signal for - * frequencies below fx_1(v) and above fx_2(v). May ONLY be - * included for Domain_Type = FX. - * For any vector: fx_N1 < fx_1 & fx_2 < fx_N2 - * When included in a product, fx_N1 & fx_N2 are both included. - */ - PVPType fxN2; - - /*! - * The change in toa limits for the full resolution echoes retained in the - * signal vector (sec). Full resolution echoes are formed with - * FX_BW(v) saved bandwidth. - * Full resolution toa limits: Dtoa_1 < Dtoa < Dtoa_2 - */ - PVPType toa1; - - /*! - * The change in toa limits for the full resolution echoes retained in the - * signal vector (sec). Full resolution echoes are formed with - * FX_BW(v) saved bandwidth. - * Full resolution toa limits: Dtoa_1 < Dtoa < Dtoa_2 - */ - PVPType toa2; - - /*! - * (Optional) The TOA limits for all echoes retained in the signal vector (sec). - */ - PVPType toaE1; - - /*! - * (Optional) The TOA limits for all echoes retained in the signal vector (sec). - */ - PVPType toaE2; - - /*! - * Two-way time delay due to the troposphere (sec) that was added - * when computing the propagation time for the SRP - */ - PVPType tdTropoSRP; - - /*! - * (Optional) Two-way time delay due to the ionosphere (sec) that was added - * when computing the propagation time for the SRP - */ - PVPType tdIonoSRP; - - /*! - * FX DOMAIN & TOA DOMAIN: The domain signal vector coordinate value for - * sample s = 0 (Hz). - */ - PVPType sc0; - - /*! - * FX DOMAIN & TOA DOMAIN: The domain signal vector coordinate value for - * signal coordinate sample spacing (Hz). - */ - PVPType scss; - - /*! - * (Optional) Integer parameter that may be included to indicate the signal - * content for some vectors is known or is likely to be distorted. - */ - PVPType signal; - - //! (Optional) Parameters included that specify the Transmit Antenna ACF orientation and the EB Steering vector - six::XsElement_minOccurs0 txAntenna{ "TxAntenna" }; // new in CPHD 1.1.0 - - //! (Optional) Parameters included that specify the Receive Antenna ACF orientation and the EB Steering vector - six::XsElement_minOccurs0 rcvAntenna{ "RcvAntenna" }; // new in CPHD 1.1.0 - - /* - * (Optional) User defined PV parameters - */ - std::map addedPVP; - - /* - * \func Constructor - * \brief Initialize default values for each parameter - * - */ - Pvp(); - - //! Equality operators - bool operator==(const Pvp& other) const - { - return txTime == other.txTime && txPos == other.txPos && - txVel == other.txVel && rcvTime == other.rcvTime && - rcvPos == other.rcvPos && rcvVel == other.rcvVel && - srpPos == other.srpPos && aFDOP == other.aFDOP && - aFRR1 == other.aFRR1 && aFRR2 == other.aFRR2 && - fx1 == other.fx1 && fx2 == other.fx2 && - toa1 == other.toa1 && toa2 == other.toa2 && - tdTropoSRP == other.tdTropoSRP && sc0 == other.sc0 && - scss == other.scss && - ampSF == other.ampSF && fxN1 == other. fxN1 && - fxN2 == other.fxN2 && toaE1 == other.toaE1 && - toaE2 == other.toaE2 && tdIonoSRP == other.tdIonoSRP && - signal == other.signal - && txAntenna == other.txAntenna - && rcvAntenna == other.rcvAntenna - && addedPVP == other.addedPVP; - } - bool operator!=(const Pvp& other) const - { - return !((*this) == other); - } - - //! Get size of pvp set in blocks - size_t getReqSetSize() const; - - //! Get total byte size of pvp set - size_t sizeInBytes() const; - - /* - * \func setOffset - * - * \brief Validate and set the offset of parameters - * - * \param offset The offset of the parameter to be expected for the param - * \param[out] param The PVPType parameter that should be set - * - * \throws except::Exception If param offset or size overlaps another parameter, or - * if format is invalid - */ - void setOffset(size_t offset, PVPType& param); - - /* - * \func append - * - * \brief Validate and append parameter to the next available block - * - * \param[out] param The PVPType parameter that should be set - * - * \throws except::Exception If param offset or size overlaps another parameter, or - * if format is invalid - */ - void append(PVPType& param); - - /* - * \func setParameter - * - * \brief Validate and set the metadata of an additional parameter identified by name - * - * \param size The size of the parameter to be expected for the param - * \param offset The offset of the parameter to be expected for the param - * \param format The string format of the parameter to be expected for the param - * \param name The unique identifier of the additional parameter that should be set - * - * \throws except::Exception If param offset or size overlaps another parameter, - * if format is invalid or if name is not unique - */ - void setCustomParameter(size_t size, size_t offset, const std::string& format, const std::string& name); - - /* - * \func setCustomParameter - * - * \brief Validate and append additional parameter to the next available block - * - * \param size The size of the parameter to be expected for the param - * \param format The string format of the parameter to be expected for the param - * \param name The unique identifier of the additional parameter that should be set - * - * \throws except::Exception If param offset or size overlaps another parameter, - * if format is invalid or if name is not unique - */ - void appendCustomParameter(size_t size, const std::string& format, const std::string& name); - -private: - /* - * Validate parameter size and offset when setting parameter - */ - void validate(size_t size, size_t offset); - - /* - * Marks filled bytes - */ - std::vector mParamLocations; - - /* - * Set default size and format for each parameter - */ - void setDefaultValues(size_t size, const std::string& format, PVPType& param); - - /* - * Initializes default size and format for parameters - */ - void initialize(); -}; - -//! Ostream operators -std::ostream& operator<< (std::ostream& os, const PVPType& p); -std::ostream& operator<< (std::ostream& os, const APVPType& a); -std::ostream& operator<< (std::ostream& os, const Pvp& p); -} -#endif // SIX_cphd_PVP_h_INCLUDED_ +/* ========================================================================= + * This file is part of cphd-c++ + * ========================================================================= + * + * (C) Copyright 2004 - 2019, MDA Information Systems LLC + * + * cphd-c++ is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; If not, + * see . + * + */ + +#pragma once +#ifndef SIX_cphd_PVP_h_INCLUDED_ +#define SIX_cphd_PVP_h_INCLUDED_ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "cphd/Types.h" + +namespace cphd +{ + +/*! + * \struct PVPType + * + * \brief Specifies a defined Per Vector Parameter. + * + * Size and Offset specify the size and placement of + * the binary parameter in the set of Per Vector + * parameters provided for each vector. + */ +struct PVPType +{ + static constexpr size_t WORD_BYTE_SIZE = 8; + + /*! + * \func PVPType + * + * \brief Default constructor + */ + PVPType(); + + //! Equality operators + bool operator==(const PVPType& other) const + { + return mSize == other.getSize() && + mOffset == other.getOffset() && + mFormat == other.getFormat(); + } + bool operator!=(const PVPType& other) const + { + return !((*this) == other); + } + + //! Setter Functions + void setOffset(size_t offset) + { + mOffset = offset; + } + void setSize(size_t size) + { + mSize = size; + } + void setFormat(const std::string& format) + { + mFormat = format; + } + + //! Get size + size_t getSize() const + { + return mSize; + } + //! Get size in bytes + size_t getByteSize() const + { + return mSize * WORD_BYTE_SIZE; + } + //! Get offset + size_t getOffset() const + { + return mOffset; + } + + //! Get offset in bytes + size_t getByteOffset() const + { + return mOffset * WORD_BYTE_SIZE; + } + + //! Get format + std::string getFormat() const + { + return mFormat; + } + +protected: + //! Size of parameter + XsPositiveInteger_fixed2 mSize; // txACX{ "TxACX" }; + + //! TxACY PVP Structure + six::XsElement txACY{ "TxACY" }; + + //! TxEB PVP Structure + six::XsElement txEB{ "TxEB" }; +}; + +/*! + * \struct RcvAntenna + * \brief Specify the Receive Antenna orientation and the Steering vector. + * + * Parameters included that specify the Receive Antenna ACF orientation and the EB Steering vector. + * (New in CPHD 1.1.0) + */ +struct RcvAntenna final +{ + bool operator==(const RcvAntenna& other) const + { + return (rcvACX == other.rcvACX) + && (rcvACY == other.rcvACY) + && (rcvEB == other.rcvEB); + } + bool operator!=(const RcvAntenna& other) const + { + return !((*this) == other); + } + + //! RcvACX PVP Structure + six::XsElement rcvACX{ "RcvACX" }; + + //! RcvACY PVP Structure + six::XsElement rcvACY{ "RcvACY" }; + + //! RcvEB PVP Structure + six::XsElement rcvEB{ "RcvEB" }; +}; + +/*! + * \struct Pvp + * + * \brief Structure used to specify the Per Vector + * parameters + * + * Provided for each channel of a given product. + */ +struct Pvp final +{ + /*! + * Transmit time for the center of the transmitted pulse relative to the + * transmit platform Collection Start Time (sec). + */ + PVPType txTime; + + /*! + * Transmit APC position at time txc(v) in Earth Centered Fixed + * (ECF) coordinates (meters). Components in X, Y, Z order. + * 3 8-byte floats required. + */ + PVPType txPos; + + /*! + * Transmit APC velocity at time txc(v) in ECF coordinates + * (meters/sec). + * 3 8-byte floats required. + */ + PVPType txVel; + + /*! + * Receive time for the center of the echo from the srp relative to the + * transmit platform Collection Start Time (sec). Time is the Time of + * Arrival (toa) of the received echo from the srp for the signal + * transmitted at txc(v). + */ + PVPType rcvTime; + + + /*! + * Receive APC position at time trc(v)srp in ECF coordinates + * (meters). + * 3 8-byte floats required. + */ + PVPType rcvPos; + + /*! + * Receive APC velocity at time trc(v)srp in ECF coordinates + * (meters/sec). + * 3 8-byte floats required + */ + PVPType rcvVel; + + /*! + * Stabilization Reference Point (srp) position in ECF coordinates + * (meters). + * 3 8-byte floats required. + */ + PVPType srpPos; + + /*! + * (Optional) Amplitude scale Factor to be applied to all samples of the signal + * vector. For signal vector v, each sample value is multiplied by + * Amp_SF(v) to yield the proper sample values for the vector. + */ + PVPType ampSF; + + /*! + * The DOPPLER shift micro parameter. Parameter accounts for the + * time dilation/Doppler shift for the echoes from all targets with the + * same time dilation/Doppler shift as the srp echo. + */ + PVPType aFDOP; + + /*! + * First order phase micro parameter (i.e. linear phase). Accounts for + * linear phase vs. FX frequency for targets with time + * dilation/Doppler shift different than the echo from the srp. + * Provides precise linear phase prediction for Linear FM waveforms. + */ + PVPType aFRR1; + + /*! + * Second order phase micro parameter (i.e. quadratic phase). + * Accounts for quadratic phase vs. FX frequency for targets with + * time dilation/Doppler shift different than the echo from the srp. + * Provides precise quadratic phase prediction for Linear FM + * waveforms. + */ + PVPType aFRR2; + + /*! + * The FX domain frequency limits of the transmitted waveform + * retained in the signal vector (Hz). + * Saved transmit band is from fx_1(v) < fx < fx_2(v) + * For the vector: FX_BW(v) = fx_2(v) – fx_1(v) + */ + PVPType fx1; + + /*! + * The FX domain frequency limits of the transmitted waveform + * retained in the signal vector (Hz). + * Saved transmit band is from fx_1(v) < fx < fx_2(v) + * For the vector: FX_BW(v) = fx_2(v) – fx_1(v) + */ + PVPType fx2; + + /*! + * (Optional) The FX domain frequency limits for out-of-band noise signal for + * frequencies below fx_1(v) and above fx_2(v). May ONLY be + * included for Domain_Type = FX. + * For any vector: fx_N1 < fx_1 & fx_2 < fx_N2 + * When included in a product, fx_N1 & fx_N2 are both included. + */ + PVPType fxN1; + + /*! + * (Optional) The FX domain frequency limits for out-of-band noise signal for + * frequencies below fx_1(v) and above fx_2(v). May ONLY be + * included for Domain_Type = FX. + * For any vector: fx_N1 < fx_1 & fx_2 < fx_N2 + * When included in a product, fx_N1 & fx_N2 are both included. + */ + PVPType fxN2; + + /*! + * The change in toa limits for the full resolution echoes retained in the + * signal vector (sec). Full resolution echoes are formed with + * FX_BW(v) saved bandwidth. + * Full resolution toa limits: Dtoa_1 < Dtoa < Dtoa_2 + */ + PVPType toa1; + + /*! + * The change in toa limits for the full resolution echoes retained in the + * signal vector (sec). Full resolution echoes are formed with + * FX_BW(v) saved bandwidth. + * Full resolution toa limits: Dtoa_1 < Dtoa < Dtoa_2 + */ + PVPType toa2; + + /*! + * (Optional) The TOA limits for all echoes retained in the signal vector (sec). + */ + PVPType toaE1; + + /*! + * (Optional) The TOA limits for all echoes retained in the signal vector (sec). + */ + PVPType toaE2; + + /*! + * Two-way time delay due to the troposphere (sec) that was added + * when computing the propagation time for the SRP + */ + PVPType tdTropoSRP; + + /*! + * (Optional) Two-way time delay due to the ionosphere (sec) that was added + * when computing the propagation time for the SRP + */ + PVPType tdIonoSRP; + + /*! + * FX DOMAIN & TOA DOMAIN: The domain signal vector coordinate value for + * sample s = 0 (Hz). + */ + PVPType sc0; + + /*! + * FX DOMAIN & TOA DOMAIN: The domain signal vector coordinate value for + * signal coordinate sample spacing (Hz). + */ + PVPType scss; + + /*! + * (Optional) Integer parameter that may be included to indicate the signal + * content for some vectors is known or is likely to be distorted. + */ + PVPType signal; + + //! (Optional) Parameters included that specify the Transmit Antenna ACF orientation and the EB Steering vector + six::XsElement_minOccurs0 txAntenna{ "TxAntenna" }; // new in CPHD 1.1.0 + + //! (Optional) Parameters included that specify the Receive Antenna ACF orientation and the EB Steering vector + six::XsElement_minOccurs0 rcvAntenna{ "RcvAntenna" }; // new in CPHD 1.1.0 + + /* + * (Optional) User defined PV parameters + */ + std::map addedPVP; + + /* + * \func Constructor + * \brief Initialize default values for each parameter + * + */ + Pvp(); + + //! Equality operators + bool operator==(const Pvp& other) const + { + return txTime == other.txTime && txPos == other.txPos && + txVel == other.txVel && rcvTime == other.rcvTime && + rcvPos == other.rcvPos && rcvVel == other.rcvVel && + srpPos == other.srpPos && aFDOP == other.aFDOP && + aFRR1 == other.aFRR1 && aFRR2 == other.aFRR2 && + fx1 == other.fx1 && fx2 == other.fx2 && + toa1 == other.toa1 && toa2 == other.toa2 && + tdTropoSRP == other.tdTropoSRP && sc0 == other.sc0 && + scss == other.scss && + ampSF == other.ampSF && fxN1 == other. fxN1 && + fxN2 == other.fxN2 && toaE1 == other.toaE1 && + toaE2 == other.toaE2 && tdIonoSRP == other.tdIonoSRP && + signal == other.signal + && txAntenna == other.txAntenna + && rcvAntenna == other.rcvAntenna + && addedPVP == other.addedPVP; + } + bool operator!=(const Pvp& other) const + { + return !((*this) == other); + } + + //! Get size of pvp set in blocks + size_t getReqSetSize() const; + + //! Get total byte size of pvp set + size_t sizeInBytes() const; + + /* + * \func setOffset + * + * \brief Validate and set the offset of parameters + * + * \param offset The offset of the parameter to be expected for the param + * \param[out] param The PVPType parameter that should be set + * + * \throws except::Exception If param offset or size overlaps another parameter, or + * if format is invalid + */ + void setOffset(size_t offset, PVPType& param); + + /* + * \func append + * + * \brief Validate and append parameter to the next available block + * + * \param[out] param The PVPType parameter that should be set + * + * \throws except::Exception If param offset or size overlaps another parameter, or + * if format is invalid + */ + void append(PVPType& param); + + /* + * \func setParameter + * + * \brief Validate and set the metadata of an additional parameter identified by name + * + * \param size The size of the parameter to be expected for the param + * \param offset The offset of the parameter to be expected for the param + * \param format The string format of the parameter to be expected for the param + * \param name The unique identifier of the additional parameter that should be set + * + * \throws except::Exception If param offset or size overlaps another parameter, + * if format is invalid or if name is not unique + */ + void setCustomParameter(size_t size, size_t offset, const std::string& format, const std::string& name); + + /* + * \func setCustomParameter + * + * \brief Validate and append additional parameter to the next available block + * + * \param size The size of the parameter to be expected for the param + * \param format The string format of the parameter to be expected for the param + * \param name The unique identifier of the additional parameter that should be set + * + * \throws except::Exception If param offset or size overlaps another parameter, + * if format is invalid or if name is not unique + */ + void appendCustomParameter(size_t size, const std::string& format, const std::string& name); + +private: + /* + * Validate parameter size and offset when setting parameter + */ + void validate(size_t size, size_t offset); + + /* + * Marks filled bytes + */ + std::vector mParamLocations; + + /* + * Set default size and format for each parameter + */ + void setDefaultValues(size_t size, const std::string& format, PVPType& param); + + /* + * Initializes default size and format for parameters + */ + void initialize(); +}; + +//! Ostream operators +std::ostream& operator<< (std::ostream& os, const PVPType& p); +std::ostream& operator<< (std::ostream& os, const APVPType& a); +std::ostream& operator<< (std::ostream& os, const Pvp& p); +} +#endif // SIX_cphd_PVP_h_INCLUDED_ diff --git a/six/modules/c++/cphd/include/cphd/ProductInfo.h b/six/modules/c++/cphd/include/cphd/ProductInfo.h index bb520e7cd3..6abef48c6e 100644 --- a/six/modules/c++/cphd/include/cphd/ProductInfo.h +++ b/six/modules/c++/cphd/include/cphd/ProductInfo.h @@ -1,117 +1,117 @@ -/* ========================================================================= - * This file is part of cphd-c++ - * ========================================================================= - * - * (C) Copyright 2004 - 2019, MDA Information Systems LLC - * - * cphd-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ - -#ifndef __CPHD_PRODUCT_INFO_H__ -#define __CPHD_PRODUCT_INFO_H__ - -#include -#include -#include - -#include -#include - -namespace cphd -{ -/* - * \struct ProductInfo - * - * \brief Contains product information - * - * (Optional) Parameters that provide general information about the - * CPHD product and/or the derived products that may be created from it - */ -struct ProductInfo -{ - /* - * \struct CreationInfo - * - * \brief Contains creation information - * - * (Optional) Parameters that provide general information about - * the CPHD product generation - */ - struct CreationInfo - { - //! Constructor - CreationInfo(); - - //! Equality operators - bool operator==(const CreationInfo& other) const - { - return application == other.application && - dateTime == other.dateTime && site == other.site && - parameter == other.parameter; - } - bool operator!=(const CreationInfo& other) const - { - return !((*this) == other); - } - - //! (Optional) Name and version of the applications that created - //! the CPHD product - std::string application; - - //! Date and time the CPHD product was created (UTC). - DateTime dateTime; - - //! (Optional) Name of the site where the product was created - std::string site; - - //! (Optional) Text field that can be used for program specific - //! name and value - six::ParameterCollection parameter; - }; - - //! Constructor - ProductInfo(); - - //! Equality operators - bool operator==(const ProductInfo& other) const - { - return profile == other.profile && - creationInfo == other.creationInfo && - parameter == other.parameter; - } - bool operator!=(const ProductInfo& other) const - { - return !((*this) == other); - } - - //! (Optional) Identifies what profile was used to create this - //! CPHD product - std::string profile; - - //! (Optional) Parameters that provide general information - //! about the CPHD product generation. - std::vector creationInfo; - - //! (Optional) Text field that can be used for program specific - //! parameter name & value - six::ParameterCollection parameter; -}; - -//! Ostream operator -std::ostream& operator<< (std::ostream& os, const ProductInfo& p); -} - -#endif +/* ========================================================================= + * This file is part of cphd-c++ + * ========================================================================= + * + * (C) Copyright 2004 - 2019, MDA Information Systems LLC + * + * cphd-c++ is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; If not, + * see . + * + */ + +#ifndef __CPHD_PRODUCT_INFO_H__ +#define __CPHD_PRODUCT_INFO_H__ + +#include +#include +#include + +#include +#include + +namespace cphd +{ +/* + * \struct ProductInfo + * + * \brief Contains product information + * + * (Optional) Parameters that provide general information about the + * CPHD product and/or the derived products that may be created from it + */ +struct ProductInfo +{ + /* + * \struct CreationInfo + * + * \brief Contains creation information + * + * (Optional) Parameters that provide general information about + * the CPHD product generation + */ + struct CreationInfo + { + //! Constructor + CreationInfo(); + + //! Equality operators + bool operator==(const CreationInfo& other) const + { + return application == other.application && + dateTime == other.dateTime && site == other.site && + parameter == other.parameter; + } + bool operator!=(const CreationInfo& other) const + { + return !((*this) == other); + } + + //! (Optional) Name and version of the applications that created + //! the CPHD product + std::string application; + + //! Date and time the CPHD product was created (UTC). + DateTime dateTime; + + //! (Optional) Name of the site where the product was created + std::string site; + + //! (Optional) Text field that can be used for program specific + //! name and value + six::ParameterCollection parameter; + }; + + //! Constructor + ProductInfo(); + + //! Equality operators + bool operator==(const ProductInfo& other) const + { + return profile == other.profile && + creationInfo == other.creationInfo && + parameter == other.parameter; + } + bool operator!=(const ProductInfo& other) const + { + return !((*this) == other); + } + + //! (Optional) Identifies what profile was used to create this + //! CPHD product + std::string profile; + + //! (Optional) Parameters that provide general information + //! about the CPHD product generation. + std::vector creationInfo; + + //! (Optional) Text field that can be used for program specific + //! parameter name & value + six::ParameterCollection parameter; +}; + +//! Ostream operator +std::ostream& operator<< (std::ostream& os, const ProductInfo& p); +} + +#endif diff --git a/six/modules/c++/cphd/include/cphd/ReferenceGeometry.h b/six/modules/c++/cphd/include/cphd/ReferenceGeometry.h index 13d73968ad..4bccc9203b 100644 --- a/six/modules/c++/cphd/include/cphd/ReferenceGeometry.h +++ b/six/modules/c++/cphd/include/cphd/ReferenceGeometry.h @@ -1,350 +1,350 @@ -/* ========================================================================= - * This file is part of cphd-c++ - * ========================================================================= - * - * (C) Copyright 2004 - 2019, MDA Information Systems LLC - * - * cphd-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ - -#ifndef __CPHD_REFERENCE_GEOMETRY_H__ -#define __CPHD_REFERENCE_GEOMETRY_H__ - -#include - -#include -#include -#include - -namespace cphd -{ - -/*! - * \struct SRP - * - * \brief The SRP position for the reference vector of the - * reference channel - */ -struct SRP -{ - //! Constructor - SRP(); - - //! Equality operator - bool operator==(const SRP& other) const - { - return ecf == other.ecf && iac == other.iac; - } - bool operator!=(const SRP& other) const - { - return !((*this) == other); - } - - //! SRP position in ECF coordinates. Value - //! included in the SRPPos PVP - Vector3 ecf; - - //! SRP position in Image Area Coordinates (IAX, - //! IAY, IAZ). - Vector3 iac; -}; - -/*! - * \struct ImagingType - * - * \brief Base class for both Monostatic and - * Bistatic imaging types - */ -struct ImagingType -{ - //! Constructor - ImagingType(); - - //! Equality operators - bool operator==(const ImagingType& other) const - { - return azimuthAngle == other.azimuthAngle && - grazeAngle == other.grazeAngle && - twistAngle == other.twistAngle && - slopeAngle == other.slopeAngle && - layoverAngle == other.layoverAngle; - } - bool operator!=(const ImagingType& other) const - { - return !((*this) == other); - } - - //! Destructor - virtual ~ImagingType() {} - - //! Angle from north to the line from the SRP to the - //! ARP ETP Nadir (i.e. North to +GPX). Measured - //! clockwise from +North toward +East. - double azimuthAngle; - - //! Grazing angle for the ARP to SRP LOS and the - //! Earth Tangent Plane (ETP) at the SRP. - double grazeAngle; - - //! Twist angle between cross range in the ETP and - //! cross range in the slant plane at the SRP - double twistAngle; - - //! Angle between the ETP normal (uUP) and the - //! slant plane normal (uSPN) at the SRP - double slopeAngle; - - //! Angle from north to the layover direction in the - //! ETP. Measured clockwise from +North toward - //! +East - double layoverAngle; -}; - -/*! - * \struct Monostatic - * - * \brief (Conditional) Collection Type Monostatic metadata. - * - * Single radar platform that is both the transmitter - * and the receiver - */ -struct Monostatic : public ImagingType -{ - //! Constructor - Monostatic(); - - //! Equality operators - bool operator==(const Monostatic& other) const - { - if((ImagingType)(*this) != (ImagingType)other) { - return false; - } - - return sideOfTrack == other.sideOfTrack && - slantRange == other.slantRange && - groundRange == other.groundRange && - dopplerConeAngle == other.dopplerConeAngle && - incidenceAngle == other.incidenceAngle && - arpPos == other.arpPos && arpVel == other.arpVel; - } - bool operator!=(const Monostatic& other) const - { - return !((*this) == other); - } - - //! Side of Track parameter for the collection. - //! L Left-looking or R Right-looking - six::SideOfTrackType sideOfTrack; - - //! Slant range from the ARP to the SRP - double slantRange; - - //! Ground range from the ARP nadir to the SRP. - //! Distance measured along spherical earth model - //! passing through the SRP. - double groundRange; - - //! Doppler Cone Angle between ARP velocity and - //! SRP Line of Sight (LOS). - double dopplerConeAngle; - - //! Incidence angle for the ARP to SRP LOS and the - //! Earth Tangent Plane (ETP) at the SRP - double incidenceAngle; - - //! ARP position in ECF coordinates (ARP) - Vector3 arpPos; - - //! ARP velocity in ECF coordinates (VARP). - Vector3 arpVel; -}; - -/*! - * \struct Bistatic - * - * \brief (Conditional) Collection Type Bistatic metadata. - * - * Pair of radar platforms, with a seperate transmitter - * and a passive receiver. - */ -struct Bistatic : public ImagingType -{ - /*! - * \struct PlatformParams - * - * \brief Describe transmit and recieve platform parameters - */ - struct PlatformParams - { - //! Constructor - PlatformParams(); - - //! Equality operator - bool operator==(const PlatformParams& other) const - { - return sideOfTrack == other.sideOfTrack && - azimuthAngle == other.azimuthAngle && - grazeAngle == other.grazeAngle && - dopplerConeAngle == other.dopplerConeAngle && - groundRange == other.groundRange && - slantRange == other.slantRange && - time == other.time && - pos == other.pos && vel == other.vel; - } - bool operator!=(const PlatformParams& other) const - { - return !((*this) == other); - } - - //! Side of Track parameter for the collection. - //! L Left-looking or R Right-looking - six::SideOfTrackType sideOfTrack; - - //! The transmit time for the vector (txc = TxTime). - double time; - - //! Angle from north to the line from the SCP to the - //! Pos Nadir in the ETP - double azimuthAngle; - - //! Grazing angle between the RefPt LOS and Earth - //! Tangent Plane (ETP - double grazeAngle; - - //! Incidence angle between the RefPt LOS and ETP - //! normal - double incidenceAngle; - - //! Doppler Cone Angle between VXmt and line of - //! sight to the ARP - double dopplerConeAngle; - - //! Ground range from the transmit APC to the SRP - //! (measured on the spherical surface containing the - //! SRP). - double groundRange; - - //! Slant range from the transmit APC to the SRP. - double slantRange; - - //! Transmit APC position (Xmt) in ECF - //! coordinates at txc - Vector3 pos; - - //! Transmit APC velocity (VXmt) in ECF - //! coordinates at txc. - Vector3 vel; - }; - - //! Constructor - Bistatic(); - - //! Equality operator - bool operator==(const Bistatic& other) const - { - if((ImagingType)(*this) != (ImagingType)other) { - return false; - } - - return azimuthAngleRate == other.azimuthAngleRate && - bistaticAngle == other.bistaticAngle && - bistaticAngleRate == other.bistaticAngleRate && - txPlatform == other.txPlatform && - rcvPlatform == other.rcvPlatform; - } - bool operator!=(const Bistatic& other) const - { - return !((*this) == other); - } - - //! Angle from north to the line from the SCP to the - //! Pos Nadir in the ETP - double azimuthAngleRate; - - //! Bistatic angle (Beta) between unit vector from - //! SRP to transmit APC (uXmt) and the unit vector - //! from the SRP to the receive APC (uRcv). - double bistaticAngle; - - //! Instantaneous rate of change of the bistatic angle - //! (d(Beta)/dt). - double bistaticAngleRate; - - //! Parameters that describe the Transmit platform. - PlatformParams txPlatform; - - //! Parameters that describe the Receive platform - PlatformParams rcvPlatform; - -}; - -/*! - * \struct ReferenceGeometry - * - * \brief Parameters that describe the collection geometry - */ -struct ReferenceGeometry -{ - //! Constructor - ReferenceGeometry(); - - //! Equality operator - bool operator==(const ReferenceGeometry& other) const - { - return referenceTime == other.referenceTime && - srpCODTime == other.srpCODTime && - srpDwellTime == other.srpDwellTime && - srp == other.srp && - monostatic == other.monostatic && - bistatic == other.bistatic; - } - bool operator!=(const ReferenceGeometry& other) const - { - return !((*this) == other); - } - - //! Reference time for the selected reference vector - double referenceTime; - - //! The COD Time for point on the reference surface - //! at (SRP_IAX, SRP_IAY). - double srpCODTime; - - //! The Dwell Time for point on the reference - //! surface at (SRP_IAX, SRP_IAY) - double srpDwellTime; - - //! The SRP position for the reference vector of the - //! reference channel. - SRP srp; - - //! Parameters for CollectType = "MONOSTATIC" - mem::ScopedCopyablePtr monostatic; - - //! Parameters for CollectType = "BISTATIC" - mem::ScopedCopyablePtr bistatic; -}; - -//! Ostream operators -std::ostream& operator<< (std::ostream& os, const SRP& s); -std::ostream& operator<< (std::ostream& os, const ImagingType& i); -std::ostream& operator<< (std::ostream& os, const Monostatic& m); -std::ostream& operator<< (std::ostream& os, const Bistatic::PlatformParams& p); -std::ostream& operator<< (std::ostream& os, const Bistatic& b); -std::ostream& operator<< (std::ostream& os, const ReferenceGeometry& r); -} - -#endif +/* ========================================================================= + * This file is part of cphd-c++ + * ========================================================================= + * + * (C) Copyright 2004 - 2019, MDA Information Systems LLC + * + * cphd-c++ is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; If not, + * see . + * + */ + +#ifndef __CPHD_REFERENCE_GEOMETRY_H__ +#define __CPHD_REFERENCE_GEOMETRY_H__ + +#include + +#include +#include +#include + +namespace cphd +{ + +/*! + * \struct SRP + * + * \brief The SRP position for the reference vector of the + * reference channel + */ +struct SRP +{ + //! Constructor + SRP(); + + //! Equality operator + bool operator==(const SRP& other) const + { + return ecf == other.ecf && iac == other.iac; + } + bool operator!=(const SRP& other) const + { + return !((*this) == other); + } + + //! SRP position in ECF coordinates. Value + //! included in the SRPPos PVP + Vector3 ecf; + + //! SRP position in Image Area Coordinates (IAX, + //! IAY, IAZ). + Vector3 iac; +}; + +/*! + * \struct ImagingType + * + * \brief Base class for both Monostatic and + * Bistatic imaging types + */ +struct ImagingType +{ + //! Constructor + ImagingType(); + + //! Equality operators + bool operator==(const ImagingType& other) const + { + return azimuthAngle == other.azimuthAngle && + grazeAngle == other.grazeAngle && + twistAngle == other.twistAngle && + slopeAngle == other.slopeAngle && + layoverAngle == other.layoverAngle; + } + bool operator!=(const ImagingType& other) const + { + return !((*this) == other); + } + + //! Destructor + virtual ~ImagingType() {} + + //! Angle from north to the line from the SRP to the + //! ARP ETP Nadir (i.e. North to +GPX). Measured + //! clockwise from +North toward +East. + double azimuthAngle; + + //! Grazing angle for the ARP to SRP LOS and the + //! Earth Tangent Plane (ETP) at the SRP. + double grazeAngle; + + //! Twist angle between cross range in the ETP and + //! cross range in the slant plane at the SRP + double twistAngle; + + //! Angle between the ETP normal (uUP) and the + //! slant plane normal (uSPN) at the SRP + double slopeAngle; + + //! Angle from north to the layover direction in the + //! ETP. Measured clockwise from +North toward + //! +East + double layoverAngle; +}; + +/*! + * \struct Monostatic + * + * \brief (Conditional) Collection Type Monostatic metadata. + * + * Single radar platform that is both the transmitter + * and the receiver + */ +struct Monostatic : public ImagingType +{ + //! Constructor + Monostatic(); + + //! Equality operators + bool operator==(const Monostatic& other) const + { + if((ImagingType)(*this) != (ImagingType)other) { + return false; + } + + return sideOfTrack == other.sideOfTrack && + slantRange == other.slantRange && + groundRange == other.groundRange && + dopplerConeAngle == other.dopplerConeAngle && + incidenceAngle == other.incidenceAngle && + arpPos == other.arpPos && arpVel == other.arpVel; + } + bool operator!=(const Monostatic& other) const + { + return !((*this) == other); + } + + //! Side of Track parameter for the collection. + //! L Left-looking or R Right-looking + six::SideOfTrackType sideOfTrack; + + //! Slant range from the ARP to the SRP + double slantRange; + + //! Ground range from the ARP nadir to the SRP. + //! Distance measured along spherical earth model + //! passing through the SRP. + double groundRange; + + //! Doppler Cone Angle between ARP velocity and + //! SRP Line of Sight (LOS). + double dopplerConeAngle; + + //! Incidence angle for the ARP to SRP LOS and the + //! Earth Tangent Plane (ETP) at the SRP + double incidenceAngle; + + //! ARP position in ECF coordinates (ARP) + Vector3 arpPos; + + //! ARP velocity in ECF coordinates (VARP). + Vector3 arpVel; +}; + +/*! + * \struct Bistatic + * + * \brief (Conditional) Collection Type Bistatic metadata. + * + * Pair of radar platforms, with a seperate transmitter + * and a passive receiver. + */ +struct Bistatic : public ImagingType +{ + /*! + * \struct PlatformParams + * + * \brief Describe transmit and recieve platform parameters + */ + struct PlatformParams + { + //! Constructor + PlatformParams(); + + //! Equality operator + bool operator==(const PlatformParams& other) const + { + return sideOfTrack == other.sideOfTrack && + azimuthAngle == other.azimuthAngle && + grazeAngle == other.grazeAngle && + dopplerConeAngle == other.dopplerConeAngle && + groundRange == other.groundRange && + slantRange == other.slantRange && + time == other.time && + pos == other.pos && vel == other.vel; + } + bool operator!=(const PlatformParams& other) const + { + return !((*this) == other); + } + + //! Side of Track parameter for the collection. + //! L Left-looking or R Right-looking + six::SideOfTrackType sideOfTrack; + + //! The transmit time for the vector (txc = TxTime). + double time; + + //! Angle from north to the line from the SCP to the + //! Pos Nadir in the ETP + double azimuthAngle; + + //! Grazing angle between the RefPt LOS and Earth + //! Tangent Plane (ETP + double grazeAngle; + + //! Incidence angle between the RefPt LOS and ETP + //! normal + double incidenceAngle; + + //! Doppler Cone Angle between VXmt and line of + //! sight to the ARP + double dopplerConeAngle; + + //! Ground range from the transmit APC to the SRP + //! (measured on the spherical surface containing the + //! SRP). + double groundRange; + + //! Slant range from the transmit APC to the SRP. + double slantRange; + + //! Transmit APC position (Xmt) in ECF + //! coordinates at txc + Vector3 pos; + + //! Transmit APC velocity (VXmt) in ECF + //! coordinates at txc. + Vector3 vel; + }; + + //! Constructor + Bistatic(); + + //! Equality operator + bool operator==(const Bistatic& other) const + { + if((ImagingType)(*this) != (ImagingType)other) { + return false; + } + + return azimuthAngleRate == other.azimuthAngleRate && + bistaticAngle == other.bistaticAngle && + bistaticAngleRate == other.bistaticAngleRate && + txPlatform == other.txPlatform && + rcvPlatform == other.rcvPlatform; + } + bool operator!=(const Bistatic& other) const + { + return !((*this) == other); + } + + //! Angle from north to the line from the SCP to the + //! Pos Nadir in the ETP + double azimuthAngleRate; + + //! Bistatic angle (Beta) between unit vector from + //! SRP to transmit APC (uXmt) and the unit vector + //! from the SRP to the receive APC (uRcv). + double bistaticAngle; + + //! Instantaneous rate of change of the bistatic angle + //! (d(Beta)/dt). + double bistaticAngleRate; + + //! Parameters that describe the Transmit platform. + PlatformParams txPlatform; + + //! Parameters that describe the Receive platform + PlatformParams rcvPlatform; + +}; + +/*! + * \struct ReferenceGeometry + * + * \brief Parameters that describe the collection geometry + */ +struct ReferenceGeometry +{ + //! Constructor + ReferenceGeometry(); + + //! Equality operator + bool operator==(const ReferenceGeometry& other) const + { + return referenceTime == other.referenceTime && + srpCODTime == other.srpCODTime && + srpDwellTime == other.srpDwellTime && + srp == other.srp && + monostatic == other.monostatic && + bistatic == other.bistatic; + } + bool operator!=(const ReferenceGeometry& other) const + { + return !((*this) == other); + } + + //! Reference time for the selected reference vector + double referenceTime; + + //! The COD Time for point on the reference surface + //! at (SRP_IAX, SRP_IAY). + double srpCODTime; + + //! The Dwell Time for point on the reference + //! surface at (SRP_IAX, SRP_IAY) + double srpDwellTime; + + //! The SRP position for the reference vector of the + //! reference channel. + SRP srp; + + //! Parameters for CollectType = "MONOSTATIC" + mem::ScopedCopyablePtr monostatic; + + //! Parameters for CollectType = "BISTATIC" + mem::ScopedCopyablePtr bistatic; +}; + +//! Ostream operators +std::ostream& operator<< (std::ostream& os, const SRP& s); +std::ostream& operator<< (std::ostream& os, const ImagingType& i); +std::ostream& operator<< (std::ostream& os, const Monostatic& m); +std::ostream& operator<< (std::ostream& os, const Bistatic::PlatformParams& p); +std::ostream& operator<< (std::ostream& os, const Bistatic& b); +std::ostream& operator<< (std::ostream& os, const ReferenceGeometry& r); +} + +#endif diff --git a/six/modules/c++/cphd/include/cphd/TxRcv.h b/six/modules/c++/cphd/include/cphd/TxRcv.h index 856966ac88..7e80674ce2 100644 --- a/six/modules/c++/cphd/include/cphd/TxRcv.h +++ b/six/modules/c++/cphd/include/cphd/TxRcv.h @@ -1,184 +1,184 @@ -/* ========================================================================= - * This file is part of cphd-c++ - * ========================================================================= - * - * (C) Copyright 2004 - 2019, MDA Information Systems LLC - * - * cphd-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ - -#ifndef __CPHD_TXRCV_H__ -#define __CPHD_TXRCV_H__ - -#include -#include -#include - -#include -#include - - -namespace cphd -{ - -/*! - * \struct ParameterType - * - * \brief Base parameter class for both TxWF and Rcv type parameters - */ -struct ParameterType -{ - //! Constructor - ParameterType(); - - //! Equality operators - bool operator==(const ParameterType& other) const - { - return identifier == other.identifier && - freqCenter == other.freqCenter && - lfmRate == other.lfmRate && - polarization == other.polarization; - } - - bool operator!=(const ParameterType& other) const - { - return !((*this) == other); - } - - //! String that uniquely identifies this Transmit Waveform - std::string identifier; - - //! Center frequency of the transmitted waveform - double freqCenter; - - //! (Optional) Chirp rate of transmitted pulse if LFM - // Allowed lfmRate != 0 - double lfmRate; - - //! Transmit polarization - PolarizationType polarization; -}; - -/*! - * \struct TxWFParameters - * - * \brief Parameters that describe a Transmit Waveform - */ -struct TxWFParameters : public ParameterType -{ - //! Constructor - TxWFParameters(); - - //! Equality operators - bool operator==(const TxWFParameters& other) const - { - return pulseLength == other.pulseLength && - rfBandwidth == other.rfBandwidth && - power == other.power; - } - bool operator!=(const TxWFParameters& other) const - { - return !((*this) == other); - } - - //! Length of transmitted pulse - double pulseLength; - - //! Bandwidth if transmitted pulse - double rfBandwidth; - - //! Peak transmitted power at the interface to the - //! antenna - double power; -}; - -/* - * \struct RcvParameters - * - * \brief Parameters that describe a Receive configuration - */ -struct RcvParameters : public ParameterType -{ - //! Constructor - RcvParameters(); - - //! Equality operators - bool operator==(const RcvParameters& other) const - { - return windowLength == other.windowLength && - sampleRate == other.sampleRate && - ifFilterBW == other.ifFilterBW && - pathGain == other.pathGain; - } - bool operator!=(const RcvParameters& other) const - { - return !((*this) == other); - } - - //! Length of the receive window - double windowLength; - - //! Rate at which the signal in the receive window - //! is sampled - double sampleRate; - - //! Bandwidth of the anti-aliasing filter prior to - //! sampling - double ifFilterBW; - - //! Receiver gain from the antenna interface to the - //! ADC. - double pathGain; -}; - -/*! - * \struct TxRcv - * - * (Optional) Parameters that describe the transmitted - * waveform(s) and receiver configurations used in - * the collection - */ -struct TxRcv -{ - //! Constructor - TxRcv(); - - //! Equality operators - bool operator==(const TxRcv& other) const - { - return txWFParameters == other.txWFParameters && - rcvParameters == other.rcvParameters; - } - bool operator!=(const TxRcv& other) const - { - return !((*this) == other); - } - - //! Parameters that describe a Transmit Waveform - std::vector txWFParameters; - - //! Parameters that describe a Receive configuration - std::vector rcvParameters; -}; - -//! Ostream operators -std::ostream& operator<< (std::ostream& os, const ParameterType& p); -std::ostream& operator<< (std::ostream& os, const TxWFParameters& t); -std::ostream& operator<< (std::ostream& os, const RcvParameters& r); -std::ostream& operator<< (std::ostream& os, const TxRcv& t); -} - -#endif +/* ========================================================================= + * This file is part of cphd-c++ + * ========================================================================= + * + * (C) Copyright 2004 - 2019, MDA Information Systems LLC + * + * cphd-c++ is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; If not, + * see . + * + */ + +#ifndef __CPHD_TXRCV_H__ +#define __CPHD_TXRCV_H__ + +#include +#include +#include + +#include +#include + + +namespace cphd +{ + +/*! + * \struct ParameterType + * + * \brief Base parameter class for both TxWF and Rcv type parameters + */ +struct ParameterType +{ + //! Constructor + ParameterType(); + + //! Equality operators + bool operator==(const ParameterType& other) const + { + return identifier == other.identifier && + freqCenter == other.freqCenter && + lfmRate == other.lfmRate && + polarization == other.polarization; + } + + bool operator!=(const ParameterType& other) const + { + return !((*this) == other); + } + + //! String that uniquely identifies this Transmit Waveform + std::string identifier; + + //! Center frequency of the transmitted waveform + double freqCenter; + + //! (Optional) Chirp rate of transmitted pulse if LFM + // Allowed lfmRate != 0 + double lfmRate; + + //! Transmit polarization + PolarizationType polarization; +}; + +/*! + * \struct TxWFParameters + * + * \brief Parameters that describe a Transmit Waveform + */ +struct TxWFParameters : public ParameterType +{ + //! Constructor + TxWFParameters(); + + //! Equality operators + bool operator==(const TxWFParameters& other) const + { + return pulseLength == other.pulseLength && + rfBandwidth == other.rfBandwidth && + power == other.power; + } + bool operator!=(const TxWFParameters& other) const + { + return !((*this) == other); + } + + //! Length of transmitted pulse + double pulseLength; + + //! Bandwidth if transmitted pulse + double rfBandwidth; + + //! Peak transmitted power at the interface to the + //! antenna + double power; +}; + +/* + * \struct RcvParameters + * + * \brief Parameters that describe a Receive configuration + */ +struct RcvParameters : public ParameterType +{ + //! Constructor + RcvParameters(); + + //! Equality operators + bool operator==(const RcvParameters& other) const + { + return windowLength == other.windowLength && + sampleRate == other.sampleRate && + ifFilterBW == other.ifFilterBW && + pathGain == other.pathGain; + } + bool operator!=(const RcvParameters& other) const + { + return !((*this) == other); + } + + //! Length of the receive window + double windowLength; + + //! Rate at which the signal in the receive window + //! is sampled + double sampleRate; + + //! Bandwidth of the anti-aliasing filter prior to + //! sampling + double ifFilterBW; + + //! Receiver gain from the antenna interface to the + //! ADC. + double pathGain; +}; + +/*! + * \struct TxRcv + * + * (Optional) Parameters that describe the transmitted + * waveform(s) and receiver configurations used in + * the collection + */ +struct TxRcv +{ + //! Constructor + TxRcv(); + + //! Equality operators + bool operator==(const TxRcv& other) const + { + return txWFParameters == other.txWFParameters && + rcvParameters == other.rcvParameters; + } + bool operator!=(const TxRcv& other) const + { + return !((*this) == other); + } + + //! Parameters that describe a Transmit Waveform + std::vector txWFParameters; + + //! Parameters that describe a Receive configuration + std::vector rcvParameters; +}; + +//! Ostream operators +std::ostream& operator<< (std::ostream& os, const ParameterType& p); +std::ostream& operator<< (std::ostream& os, const TxWFParameters& t); +std::ostream& operator<< (std::ostream& os, const RcvParameters& r); +std::ostream& operator<< (std::ostream& os, const TxRcv& t); +} + +#endif diff --git a/six/modules/c++/cphd/source/Antenna.cpp b/six/modules/c++/cphd/source/Antenna.cpp index 5a5dc9e916..7dc9d1b781 100644 --- a/six/modules/c++/cphd/source/Antenna.cpp +++ b/six/modules/c++/cphd/source/Antenna.cpp @@ -1,148 +1,148 @@ -/* ========================================================================= - * This file is part of cphd-c++ - * ========================================================================= - * - * (C) Copyright 2004 - 2019, MDA Information Systems LLC - * - * cphd-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ -#include -#include - -namespace cphd -{ - -AntCoordFrame::AntCoordFrame() -{ -} - -AntPhaseCenter::AntPhaseCenter() -{ -} - -AntPattern::AntPattern(): - freqZero(six::Init::undefined()), - gainZero(six::Init::undefined()), - ebFreqShift(six::Init::undefined()), - mlFreqDilation(six::Init::undefined()), - gainBSPoly(six::Init::undefined()) -{ -} - -AntPattern::GainPhaseArray::GainPhaseArray() : - freq(six::Init::undefined()) -{ -} - -Antenna::Antenna() -{ -} - -std::ostream& operator<< (std::ostream& os, const AntCoordFrame& a) -{ - os << " AntCoordFrame:: \n" - << " Identifier : " << a.identifier << "\n" - << " XAxisPoly : " << a.xAxisPoly << "\n" - << " YAxisPoly : " << a.yAxisPoly << "\n" - << a.useACFPVP; - return os; -} - -std::ostream& operator<< (std::ostream& os, const AntPhaseCenter& a) -{ - os << " AntPhaseCenter:: \n" - << " Identifier : " << a.identifier << "\n" - << " ACFId : " << a.acfId << "\n" - << " APCXYZ : " << a.apcXYZ << "\n"; - return os; -} - -std::ostream& operator<< (std::ostream& os, const AntPattern::EBFreqShiftSF& v) -{ - os << " EBFreqShiftSF:: \n" - << v.dcxsf << v.dcysf << "\n"; - return os; -} - -std::ostream& operator<< (std::ostream& os, const AntPattern::MLFreqDilationSF& v) -{ - os << " MLFreqDilationSF:: \n" - << v.dcxsf << v.dcysf << "\n"; - return os; -} - - -std::ostream& operator<< (std::ostream& os, const AntPattern::AntPolRef& v) -{ - os << " AntPolRef:: \n" - << v.ampX << v.ampY << v.phaseY << "\n"; - return os; -} - -std::ostream& operator<< (std::ostream& os, const AntPattern::GainPhaseArray& g) -{ - os << " GainPhaseArray:: \n" - << " Freq : " << g.freq << "\n" - << " ArrayId : " << g.arrayId << "\n" - << " ElementId : " << g.elementId << "\n"; - return os; -} - -std::ostream& operator<< (std::ostream& os, const AntPattern& a) -{ - os << " AntPattern \n" - << " Identifier : " << a.identifier << "\n" - << " FreqZero : " << a.freqZero << "\n" - << " GainZero : " << a.gainZero << "\n" - << " EBFreqShift : " << a.ebFreqShift << "\n" - << a.ebFreqShiftSF << "\n" - << " MLFreqDilation : " << a.mlFreqDilation << "\n" - << a.mlFreqDilationSF << "\n" - << " GainBSPoly : " << a.gainBSPoly << "\n" - << a.antPolRef << "\n" - << a.eb << "\n" - << " Array:: \n" - << a.array << "\n" - << " Element:: \n" - << a.element << "\n"; - for (const auto& gainPhase : a.gainPhaseArray) - { - os << gainPhase << "\n"; - } - return os; -} - -std::ostream& operator<< (std::ostream& os, const Antenna& a) -{ - os << "Antenna:: \n" - << " NumACFs : " << a.antCoordFrame.size() << "\n" - << " NumAPCs : " << a.antPhaseCenter.size() << "\n" - << " NumAntPats : " << a.antPattern.size() << "\n"; - for (size_t ii = 0; ii < a.antCoordFrame.size(); ++ii) - { - os << a.antCoordFrame[ii] << "\n"; - } - for (size_t ii = 0; ii < a.antPhaseCenter.size(); ++ii) - { - os << a.antPhaseCenter[ii] << "\n"; - } - for (size_t ii = 0; ii < a.antPattern.size(); ++ii) - { - os << a.antPattern[ii] << "\n"; - } - return os; -} -} +/* ========================================================================= + * This file is part of cphd-c++ + * ========================================================================= + * + * (C) Copyright 2004 - 2019, MDA Information Systems LLC + * + * cphd-c++ is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; If not, + * see . + * + */ +#include +#include + +namespace cphd +{ + +AntCoordFrame::AntCoordFrame() +{ +} + +AntPhaseCenter::AntPhaseCenter() +{ +} + +AntPattern::AntPattern(): + freqZero(six::Init::undefined()), + gainZero(six::Init::undefined()), + ebFreqShift(six::Init::undefined()), + mlFreqDilation(six::Init::undefined()), + gainBSPoly(six::Init::undefined()) +{ +} + +AntPattern::GainPhaseArray::GainPhaseArray() : + freq(six::Init::undefined()) +{ +} + +Antenna::Antenna() +{ +} + +std::ostream& operator<< (std::ostream& os, const AntCoordFrame& a) +{ + os << " AntCoordFrame:: \n" + << " Identifier : " << a.identifier << "\n" + << " XAxisPoly : " << a.xAxisPoly << "\n" + << " YAxisPoly : " << a.yAxisPoly << "\n" + << a.useACFPVP; + return os; +} + +std::ostream& operator<< (std::ostream& os, const AntPhaseCenter& a) +{ + os << " AntPhaseCenter:: \n" + << " Identifier : " << a.identifier << "\n" + << " ACFId : " << a.acfId << "\n" + << " APCXYZ : " << a.apcXYZ << "\n"; + return os; +} + +std::ostream& operator<< (std::ostream& os, const AntPattern::EBFreqShiftSF& v) +{ + os << " EBFreqShiftSF:: \n" + << v.dcxsf << v.dcysf << "\n"; + return os; +} + +std::ostream& operator<< (std::ostream& os, const AntPattern::MLFreqDilationSF& v) +{ + os << " MLFreqDilationSF:: \n" + << v.dcxsf << v.dcysf << "\n"; + return os; +} + + +std::ostream& operator<< (std::ostream& os, const AntPattern::AntPolRef& v) +{ + os << " AntPolRef:: \n" + << v.ampX << v.ampY << v.phaseY << "\n"; + return os; +} + +std::ostream& operator<< (std::ostream& os, const AntPattern::GainPhaseArray& g) +{ + os << " GainPhaseArray:: \n" + << " Freq : " << g.freq << "\n" + << " ArrayId : " << g.arrayId << "\n" + << " ElementId : " << g.elementId << "\n"; + return os; +} + +std::ostream& operator<< (std::ostream& os, const AntPattern& a) +{ + os << " AntPattern \n" + << " Identifier : " << a.identifier << "\n" + << " FreqZero : " << a.freqZero << "\n" + << " GainZero : " << a.gainZero << "\n" + << " EBFreqShift : " << a.ebFreqShift << "\n" + << a.ebFreqShiftSF << "\n" + << " MLFreqDilation : " << a.mlFreqDilation << "\n" + << a.mlFreqDilationSF << "\n" + << " GainBSPoly : " << a.gainBSPoly << "\n" + << a.antPolRef << "\n" + << a.eb << "\n" + << " Array:: \n" + << a.array << "\n" + << " Element:: \n" + << a.element << "\n"; + for (const auto& gainPhase : a.gainPhaseArray) + { + os << gainPhase << "\n"; + } + return os; +} + +std::ostream& operator<< (std::ostream& os, const Antenna& a) +{ + os << "Antenna:: \n" + << " NumACFs : " << a.antCoordFrame.size() << "\n" + << " NumAPCs : " << a.antPhaseCenter.size() << "\n" + << " NumAntPats : " << a.antPattern.size() << "\n"; + for (size_t ii = 0; ii < a.antCoordFrame.size(); ++ii) + { + os << a.antCoordFrame[ii] << "\n"; + } + for (size_t ii = 0; ii < a.antPhaseCenter.size(); ++ii) + { + os << a.antPhaseCenter[ii] << "\n"; + } + for (size_t ii = 0; ii < a.antPattern.size(); ++ii) + { + os << a.antPattern[ii] << "\n"; + } + return os; +} +} diff --git a/six/modules/c++/cphd/source/CPHDXMLParser.cpp b/six/modules/c++/cphd/source/CPHDXMLParser.cpp index 61a24d3d1e..1ea206ba35 100644 --- a/six/modules/c++/cphd/source/CPHDXMLParser.cpp +++ b/six/modules/c++/cphd/source/CPHDXMLParser.cpp @@ -1,2422 +1,2422 @@ -/* ========================================================================= - * This file is part of cphd-c++ - * ========================================================================= - * - * (C) Copyright 2004 - 2019, MDA Information Systems LLC - * - * cphd-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#define ENFORCESPEC 0 - -namespace -{ -typedef xml::lite::Element* XMLElem; -} - -namespace cphd -{ - -CPHDXMLParser::CPHDXMLParser( - const std::string& uri, - bool addClassAttributes, - logging::Logger* log, - bool ownLog) : - six::XMLParser(uri, addClassAttributes, log, ownLog), - mCommon(getDefaultURI(), addClassAttributes, getDefaultURI(), log) -{ -} - -/* - * TO XML - */ -std::unique_ptr CPHDXMLParser::toXML( - const Metadata& metadata) -{ - std::unique_ptr doc(new xml::lite::Document()); - - XMLElem root = newElement("CPHD"); - doc->setRootElement(root); - - toXML(metadata.collectionID, root); - toXML(metadata.global, root); - toXML(metadata.sceneCoordinates, root); - toXML(metadata.data, root); - toXML(metadata.channel, root); - toXML(metadata.pvp, root); - toXML(metadata.dwell, root); - toXML(metadata.referenceGeometry, root); - - if (metadata.supportArray.get()) - { - toXML(*(metadata.supportArray), root); - } - if (metadata.antenna.get()) - { - toXML(*(metadata.antenna), root); - } - if (metadata.txRcv.get()) - { - toXML(*(metadata.txRcv), root); - } - if (metadata.errorParameters.get()) - { - toXML(*(metadata.errorParameters), root); - } - if (metadata.productInfo.get()) - { - toXML(*(metadata.productInfo), root); - } - for (const auto& geoInfo : metadata.geoInfo) - { - toXML(geoInfo, root); - } - if (metadata.matchInfo.get()) - { - toXML(*(metadata.matchInfo), root); - } - - //set the XMLNS - root->setNamespacePrefix("", getDefaultURI()); - - return doc; -} - -XMLElem CPHDXMLParser::toXML(const CollectionInformation& collectionID, XMLElem parent) -{ - XMLElem collectionXML = newElement("CollectionID", parent); - - createString("CollectorName", collectionID.collectorName, collectionXML); - if(!six::Init::isUndefined(collectionID.illuminatorName)) - { - createString("IlluminatorName", collectionID.illuminatorName, collectionXML); - } - createString("CoreName", collectionID.coreName, collectionXML); - createString("CollectType", collectionID.collectType, collectionXML); - - // RadarMode - XMLElem radarModeXML = newElement("RadarMode", collectionXML); - createSixString("ModeType", collectionID.radarMode, radarModeXML); - if(!six::Init::isUndefined(collectionID.radarModeID)) - { - createString("ModeID", collectionID.radarModeID, radarModeXML); - } - createString("Classification", collectionID.getClassificationLevel(), collectionXML); - createString("ReleaseInfo", collectionID.releaseInfo, collectionXML); - if (!collectionID.countryCodes.empty()) - { - std::string countryCodes = str::join(collectionID.countryCodes, ","); - createString("CountryCode", countryCodes, collectionXML); - } - mCommon.addParameters("Parameter", getDefaultURI(), collectionID.parameters, collectionXML); - return collectionXML; -} - -XMLElem CPHDXMLParser::toXML(const Global& global, XMLElem parent) -{ - XMLElem globalXML = newElement("Global", parent); - createString("DomainType", global.domainType, globalXML); - createString("SGN", global.sgn, globalXML); - - //Timeline - XMLElem timelineXML = newElement("Timeline", globalXML); - createDateTime("CollectionStart", global.timeline.collectionStart, timelineXML); - if (!six::Init::isUndefined(global.timeline.rcvCollectionStart)) - { - createDateTime("RcvCollectionStart", global.timeline.rcvCollectionStart, timelineXML); - } - createDouble("TxTime1", global.timeline.txTime1, timelineXML); - createDouble("TxTime2", global.timeline.txTime2, timelineXML); - - XMLElem fxBandXML = newElement("FxBand", globalXML); - createDouble("FxMin", global.fxBand.fxMin, fxBandXML); - createDouble("FxMax", global.fxBand.fxMax, fxBandXML); - - XMLElem toaSwathXML = newElement("TOASwath", globalXML); - createDouble("TOAMin", global.toaSwath.toaMin, toaSwathXML); - createDouble("TOAMax", global.toaSwath.toaMax, toaSwathXML); - - if (global.tropoParameters.get()) - { - XMLElem tropoXML = newElement("TropoParameters", globalXML); - createDouble("N0", global.tropoParameters->n0, tropoXML); - createString("RefHeight", global.tropoParameters->refHeight, tropoXML); - } - if (global.ionoParameters.get()) - { - XMLElem ionoXML = newElement("IonoParameters", globalXML); - createDouble("TECV", global.ionoParameters->tecv, ionoXML); - createOptionalDouble("F2Height", global.ionoParameters->f2Height, ionoXML); - } - return globalXML; -} - -XMLElem CPHDXMLParser::toXML(const SceneCoordinates& sceneCoords, XMLElem parent) -{ - XMLElem sceneCoordsXML = newElement("SceneCoordinates", parent); - createString("EarthModel", sceneCoords.earthModel, sceneCoordsXML); - - XMLElem iarpXML = newElement("IARP", sceneCoordsXML); - mCommon.createVector3D("ECF", sceneCoords.iarp.ecf, iarpXML); - mCommon.createLatLonAlt("LLH", sceneCoords.iarp.llh, iarpXML); - - XMLElem refSurfXML = newElement("ReferenceSurface", sceneCoordsXML); - if (sceneCoords.referenceSurface.planar.get()) - { - XMLElem planarXML = newElement("Planar", refSurfXML); - mCommon.createVector3D("uIAX", sceneCoords.referenceSurface.planar->uIax, planarXML); - mCommon.createVector3D("uIAY", sceneCoords.referenceSurface.planar->uIay, planarXML); - } - else if (sceneCoords.referenceSurface.hae.get()) - { - XMLElem haeXML = newElement("HAE", refSurfXML); - mCommon.createLatLon("uIAXLL", sceneCoords.referenceSurface.hae->uIax, haeXML); - mCommon.createLatLon("uIAYLL", sceneCoords.referenceSurface.hae->uIay, haeXML); - } - else - { - throw except::Exception(Ctxt( - "Reference Surface must be one of two types")); - } - - XMLElem imageAreaXML = newElement("ImageArea", sceneCoordsXML); - mCommon.createVector2D("X1Y1", sceneCoords.imageArea.x1y1, imageAreaXML); - mCommon.createVector2D("X2Y2", sceneCoords.imageArea.x2y2, imageAreaXML); - - if (!sceneCoords.imageArea.polygon.empty()) - { - XMLElem polygonXML = newElement("Polygon", imageAreaXML); - setAttribute(polygonXML, "size", sceneCoords.imageArea.polygon.size()); - for (size_t ii = 0; ii < sceneCoords.imageArea.polygon.size(); ++ii) - { - XMLElem vertexXML = mCommon.createVector2D("Vertex", sceneCoords.imageArea.polygon[ii], polygonXML); - setAttribute(vertexXML, "index", ii+1); - } - } - createLatLonFootprint("ImageAreaCornerPoints", "IACP", sceneCoords.imageAreaCorners, sceneCoordsXML); - - // Extended Area (Optional) - if(sceneCoords.extendedArea.get()) - { - XMLElem extendedAreaXML = newElement("ExtendedArea", sceneCoordsXML); - mCommon.createVector2D("X1Y1", sceneCoords.extendedArea->x1y1, extendedAreaXML); - mCommon.createVector2D("X2Y2", sceneCoords.extendedArea->x2y2, extendedAreaXML); - - if (!sceneCoords.extendedArea->polygon.empty()) - { - XMLElem polygonXML = newElement("Polygon", sceneCoordsXML); - setAttribute(polygonXML, "size", sceneCoords.extendedArea->polygon.size()); - for (size_t ii = 0; ii < sceneCoords.extendedArea->polygon.size(); ++ii) - { - XMLElem vertexXML = mCommon.createVector2D("Vertex", sceneCoords.extendedArea->polygon[ii], polygonXML); - setAttribute(vertexXML, "index", ii+1); - } - } - } - - // ImageGrid (Optional) - if(sceneCoords.imageGrid.get()) - { - XMLElem imageGridXML = newElement("ImageGrid", sceneCoordsXML); - if(!six::Init::isUndefined(sceneCoords.imageGrid->identifier)) - { - createString("Identifier", sceneCoords.imageGrid->identifier, imageGridXML); - } - XMLElem iarpLocationXML = newElement("IARPLocation", imageGridXML); - createDouble("Line", sceneCoords.imageGrid->iarpLocation.line, iarpLocationXML); - createDouble("Sample", sceneCoords.imageGrid->iarpLocation.sample, iarpLocationXML); - - XMLElem iaxExtentXML = newElement("IAXExtent", imageGridXML); - createDouble("LineSpacing", sceneCoords.imageGrid->xExtent.lineSpacing, iaxExtentXML); - createInt("FirstLine", sceneCoords.imageGrid->xExtent.firstLine, iaxExtentXML); - createInt("NumLines", sceneCoords.imageGrid->xExtent.numLines, iaxExtentXML); - - XMLElem iayExtentXML = newElement("IAYExtent", imageGridXML); - createDouble("SampleSpacing", sceneCoords.imageGrid->yExtent.sampleSpacing, iayExtentXML); - createInt("FirstSample", sceneCoords.imageGrid->yExtent.firstSample, iayExtentXML); - createInt("NumSamples", sceneCoords.imageGrid->yExtent.numSamples, iayExtentXML); - - if (!sceneCoords.imageGrid->segments.empty()) - { - XMLElem segmentListXML = newElement("SegmentList", imageGridXML); - createInt("NumSegments", sceneCoords.imageGrid->segments.size(), segmentListXML); - - for (size_t ii = 0; ii < sceneCoords.imageGrid->segments.size(); ++ii) - { - XMLElem segmentXML = newElement("Segment", segmentListXML); - createString("Identifier", sceneCoords.imageGrid->segments[ii].identifier, segmentXML); - createInt("StartLine", sceneCoords.imageGrid->segments[ii].startLine, segmentXML); - createInt("StartSample", sceneCoords.imageGrid->segments[ii].startSample, segmentXML); - createInt("EndLine", sceneCoords.imageGrid->segments[ii].endLine, segmentXML); - createInt("EndSample", sceneCoords.imageGrid->segments[ii].endSample, segmentXML); - - if (!sceneCoords.imageGrid->segments[ii].polygon.empty()) - { - XMLElem polygonXML = newElement("SegmentPolygon", segmentXML); - setAttribute(polygonXML, "size", sceneCoords.imageGrid->segments[ii].polygon.size()); - for (size_t jj = 0; jj < sceneCoords.imageGrid->segments[ii].polygon.size(); ++jj) - { - XMLElem svXML = newElement("SV", polygonXML); - setAttribute(svXML, "index", sceneCoords.imageGrid->segments[ii].polygon[jj].getIndex()); - createDouble("Line", sceneCoords.imageGrid->segments[ii].polygon[jj].line, svXML); - createDouble("Sample", sceneCoords.imageGrid->segments[ii].polygon[jj].sample, svXML); - } - } - } - } - } - return sceneCoordsXML; -} - -XMLElem CPHDXMLParser::toXML(const Data& data, XMLElem parent) -{ - XMLElem dataXML = newElement("Data", parent); - createString("SignalArrayFormat", data.signalArrayFormat, dataXML); - createInt("NumBytesPVP", data.numBytesPVP, dataXML); - createInt("NumCPHDChannels", data.channels.size(), dataXML); - if (!six::Init::isUndefined(data.signalCompressionID)) - { - createString("SignalCompressionID", data.signalCompressionID, dataXML); - } - - for (size_t ii = 0; ii < data.channels.size(); ++ii) - { - XMLElem channelXML = newElement("Channel", dataXML); - createString("Identifier", data.channels[ii].identifier, channelXML); - createInt("NumVectors", data.channels[ii].numVectors, channelXML); - createInt("NumSamples", data.channels[ii].numSamples, channelXML); - createInt("SignalArrayByteOffset", data.channels[ii].signalArrayByteOffset, channelXML); - createInt("PVPArrayByteOffset", data.channels[ii].pvpArrayByteOffset, channelXML); - if(!six::Init::isUndefined(data.channels[ii].compressedSignalSize)) - { - createInt("CompressedSignalSize", data.channels[ii].compressedSignalSize, channelXML); - } - } - createInt("NumSupportArrays", data.supportArrayMap.size(), dataXML); - for (const auto& entry : data.supportArrayMap) - { - XMLElem supportArrayXML = newElement("SupportArray", dataXML); - createString("Identifier", entry.second.identifier, supportArrayXML); - createInt("NumRows", entry.second.numRows, supportArrayXML); - createInt("NumCols", entry.second.numCols, supportArrayXML); - createInt("BytesPerElement", entry.second.bytesPerElement, supportArrayXML); - createInt("ArrayByteOffset", entry.second.arrayByteOffset, supportArrayXML); - } - return dataXML; -} - -XMLElem CPHDXMLParser::toXML(const six::XsElement_minOccurs0& o, xml::lite::Element& parent) -{ - XMLElem pXML = nullptr; - if (has_value(o)) - { - pXML = newElement(o.tag(), &parent); - std::ignore = create(parser(), value(o).ampH, *pXML); - std::ignore = create(parser(), value(o).ampV, *pXML); - std::ignore = create(parser(), value(o).phaseV, *pXML); - } - - return pXML; -} - -XMLElem CPHDXMLParser::toXML(const Polarization& obj, xml::lite::Element& parent) -{ - auto polXML = newElement("Polarization", &parent); - createString("TxPol", obj.txPol, polXML); - createString("RcvPol", obj.rcvPol, polXML); - - toXML(obj.txPolRef, *polXML); // added in CPHD 1.1.0 - toXML(obj.rcvPolRef, *polXML); // added in CPHD 1.1.0 - - return polXML; -} - -XMLElem CPHDXMLParser::toXML(const Channel& channel, XMLElem parent) -{ - XMLElem channelXML = newElement("Channel", parent); - createString("RefChId", channel.refChId, channelXML); - createBooleanType("FXFixedCPHD", channel.fxFixedCphd, channelXML); - createBooleanType("TOAFixedCPHD", channel.toaFixedCphd, channelXML); - createBooleanType("SRPFixedCPHD", channel.srpFixedCphd, channelXML); - - for (size_t ii = 0; ii < channel.parameters.size(); ++ii) - { - XMLElem parametersXML = newElement("Parameters", channelXML); - createString("Identifier", channel.parameters[ii].identifier, parametersXML); - createInt("RefVectorIndex", channel.parameters[ii].refVectorIndex, parametersXML); - createBooleanType("FXFixed", channel.parameters[ii].fxFixed, parametersXML); - createBooleanType("TOAFixed", channel.parameters[ii].toaFixed, parametersXML); - createBooleanType("SRPFixed", channel.parameters[ii].srpFixed, parametersXML); - if (!six::Init::isUndefined(channel.parameters[ii].signalNormal)) - { - createBooleanType("SignalNormal", channel.parameters[ii].signalNormal, parametersXML); - } - std::ignore = toXML(channel.parameters[ii].polarization, *parametersXML); - - createDouble("FxC", channel.parameters[ii].fxC, parametersXML); - createDouble("FxBW", channel.parameters[ii].fxBW, parametersXML); - createOptionalDouble("FxBWNoise", channel.parameters[ii].fxBWNoise, parametersXML); - createDouble("TOASaved", channel.parameters[ii].toaSaved, parametersXML); - - if(channel.parameters[ii].toaExtended.get()) - { - XMLElem toaExtendedXML = newElement("TOAExtended", parametersXML); - createDouble("TOAExtSaved", channel.parameters[ii].toaExtended->toaExtSaved, toaExtendedXML); - if(channel.parameters[ii].toaExtended->lfmEclipse.get()) - { - XMLElem lfmEclipseXML = newElement("LFMEclipse", toaExtendedXML); - createDouble("FxEarlyLow", channel.parameters[ii].toaExtended->lfmEclipse->fxEarlyLow, lfmEclipseXML); - createDouble("FxEarlyHigh", channel.parameters[ii].toaExtended->lfmEclipse->fxEarlyHigh, lfmEclipseXML); - createDouble("FxLateLow", channel.parameters[ii].toaExtended->lfmEclipse->fxLateLow, lfmEclipseXML); - createDouble("FxLateHigh", channel.parameters[ii].toaExtended->lfmEclipse->fxLateHigh, lfmEclipseXML); - } - } - XMLElem dwellTimesXML = newElement("DwellTimes", parametersXML); - createString("CODId", channel.parameters[ii].dwellTimes.codId, dwellTimesXML); - createString("DwellId", channel.parameters[ii].dwellTimes.dwellId, dwellTimesXML); - std::ignore = create(parser(), channel.parameters[ii].dwellTimes.dtaId, *dwellTimesXML); - std::ignore = create(parser(), channel.parameters[ii].dwellTimes.useDTA, *dwellTimesXML); - - if(!six::Init::isUndefined(channel.parameters[ii].imageArea)) - { - XMLElem imageAreaXML = newElement("ImageArea", parametersXML); - mCommon.createVector2D("X1Y1", channel.parameters[ii].imageArea.x1y1, imageAreaXML); - mCommon.createVector2D("X2Y2", channel.parameters[ii].imageArea.x2y2, imageAreaXML); - if(!channel.parameters[ii].imageArea.polygon.empty()) - { - XMLElem polygonXML = newElement("Polygon", imageAreaXML); - setAttribute(polygonXML, "size", channel.parameters[ii].imageArea.polygon.size()); - for (size_t jj = 0; jj < channel.parameters[ii].imageArea.polygon.size(); ++jj) - { - XMLElem vertexXML = mCommon.createVector2D("Vertex", channel.parameters[ii].imageArea.polygon[jj], polygonXML); - setAttribute(vertexXML, "index", jj+1); - } - } - } - if(channel.parameters[ii].antenna.get()) - { - XMLElem antennaXML = newElement("Antenna", parametersXML); - createString("TxAPCId", channel.parameters[ii].antenna->txAPCId, antennaXML); - createString("TxAPATId", channel.parameters[ii].antenna->txAPATId, antennaXML); - createString("RcvAPCId", channel.parameters[ii].antenna->rcvAPCId, antennaXML); - createString("RcvAPATId", channel.parameters[ii].antenna->rcvAPATId, antennaXML); - } - if(channel.parameters[ii].txRcv.get()) - { - XMLElem txRcvXML = newElement("TxRcv", parametersXML); - for (size_t jj = 0; jj < channel.parameters[ii].txRcv->txWFId.size(); ++jj) - { - createString("TxWFId", channel.parameters[ii].txRcv->txWFId[jj], txRcvXML); - } - for (size_t jj = 0; jj < channel.parameters[ii].txRcv->rcvId.size(); ++jj) - { - createString("RcvId", channel.parameters[ii].txRcv->rcvId[jj], txRcvXML); - } - } - if(channel.parameters[ii].tgtRefLevel.get()) - { - XMLElem tgtRefXML = newElement("TgtRefLevel", parametersXML); - createDouble("PTRef", channel.parameters[ii].tgtRefLevel->ptRef, tgtRefXML); - } - if(channel.parameters[ii].noiseLevel.get()) - { - XMLElem noiseLevelXML = newElement("NoiseLevel", parametersXML); - createDouble("PNRef", channel.parameters[ii].noiseLevel->pnRef, noiseLevelXML); - createDouble("BNRef", channel.parameters[ii].noiseLevel->bnRef, noiseLevelXML); - if(channel.parameters[ii].noiseLevel->fxNoiseProfile.get()) - { - XMLElem fxNoiseProfileXML = newElement("FxNoiseProfile", noiseLevelXML); - for (size_t jj = 0; jj < channel.parameters[ii].noiseLevel->fxNoiseProfile->point.size(); ++jj) - { - XMLElem pointXML = newElement("Point", fxNoiseProfileXML); - createDouble("Fx", channel.parameters[ii].noiseLevel->fxNoiseProfile->point[jj].fx, pointXML); - createDouble("PN", channel.parameters[ii].noiseLevel->fxNoiseProfile->point[jj].pn, pointXML); - } - } - } - } - if(!channel.addedParameters.empty()) - { - XMLElem addedParamsXML = newElement("AddedParameters", channelXML); - mCommon.addParameters("Parameter", getDefaultURI(), channel.addedParameters, addedParamsXML); - } - return channelXML; -} - -XMLElem CPHDXMLParser::toXML(const six::XsElement& v, xml::lite::Element& parent) -{ - return createPVPType(v.tag(), v.value().param, &parent); -} -XMLElem CPHDXMLParser::toXML(const six::XsElement& v, xml::lite::Element& parent) -{ - return createPVPType(v.tag(), v.value().param, &parent); -} - -XMLElem CPHDXMLParser::toXML(const six::XsElement_minOccurs0& o, xml::lite::Element& parent) -{ - XMLElem pXML = nullptr; - if (has_value(o)) - { - pXML = newElement(o.tag(), &parent); - std::ignore = toXML(value(o).txACX, *pXML); - std::ignore = toXML(value(o).txACY, *pXML); - std::ignore = toXML(value(o).txEB, *pXML); - } - - return pXML; -} - -XMLElem CPHDXMLParser::toXML(const six::XsElement_minOccurs0& o, xml::lite::Element& parent) -{ - XMLElem pXML = nullptr; - if (has_value(o)) - { - pXML = newElement(o.tag(), &parent); - std::ignore = toXML(value(o).rcvACX, *pXML); - std::ignore = toXML(value(o).rcvACY, *pXML); - std::ignore = toXML(value(o).rcvEB, *pXML); - } - - return pXML; -} - -XMLElem CPHDXMLParser::toXML(const Pvp& pvp, XMLElem parent) -{ - XMLElem pvpXML = newElement("PVP", parent); - createPVPType("TxTime", pvp.txTime, pvpXML); - createPVPType("TxPos", pvp.txPos, pvpXML); - createPVPType("TxVel", pvp.txVel, pvpXML); - createPVPType("RcvTime", pvp.rcvTime, pvpXML); - createPVPType("RcvPos", pvp.rcvPos, pvpXML); - createPVPType("RcvVel", pvp.rcvVel, pvpXML); - createPVPType("SRPPos", pvp.srpPos, pvpXML); - if (!six::Init::isUndefined(pvp.ampSF.getOffset())) - { - createPVPType("AmpSF", pvp.ampSF, pvpXML); - } - createPVPType("aFDOP", pvp.aFDOP, pvpXML); - createPVPType("aFRR1", pvp.aFRR1, pvpXML); - createPVPType("aFRR2", pvp.aFRR2, pvpXML); - createPVPType("FX1", pvp.fx1, pvpXML); - createPVPType("FX2", pvp.fx2, pvpXML); - if (!six::Init::isUndefined(pvp.fxN1.getOffset())) - { - createPVPType("FXN1", pvp.fxN1, pvpXML); - } - if (!six::Init::isUndefined(pvp.fxN2.getOffset())) - { - createPVPType("FXN2", pvp.fxN2, pvpXML); - } - createPVPType("TOA1", pvp.toa1, pvpXML); - createPVPType("TOA2", pvp.toa2, pvpXML); - if (!six::Init::isUndefined(pvp.toaE1.getOffset())) - { - createPVPType("TOAE1", pvp.toaE1, pvpXML); - } - if (!six::Init::isUndefined(pvp.toaE2.getOffset())) - { - createPVPType("TOAE2", pvp.toaE2, pvpXML); - } - createPVPType("TDTropoSRP", pvp.tdTropoSRP, pvpXML); - if (!six::Init::isUndefined(pvp.tdIonoSRP.getOffset())) - { - createPVPType("TDIonoSRP", pvp.tdIonoSRP, pvpXML); - } - createPVPType("SC0", pvp.sc0, pvpXML); - createPVPType("SCSS", pvp.scss, pvpXML); - if (!six::Init::isUndefined(pvp.signal.getOffset())) - { - createPVPType("SIGNAL", pvp.signal, pvpXML); - } - - std::ignore = toXML(pvp.txAntenna, *pvpXML); - std::ignore = toXML(pvp.rcvAntenna, *pvpXML); - - for (auto it = pvp.addedPVP.begin(); it != pvp.addedPVP.end(); ++it) - { - createAPVPType("AddedPVP", it->second, pvpXML); - } - - return pvpXML; -} - -void CPHDXMLParser::createSupportArray(const std::vector& supportArray, - const std::string& tag, xml::lite::Element& parent) -{ - for (auto&& param : supportArray) - { - XMLElem pXML = newElement(tag, &parent); - createInt("Identifier", param.getIdentifier(), pXML); - createString("ElementFormat", param.elementFormat, pXML); - createDouble("X0", param.x0, pXML); - createDouble("Y0", param.y0, pXML); - createDouble("XSS", param.xSS, pXML); - createDouble("YSS", param.ySS, pXML); - - } -} - -//Assumes optional handled by caller -XMLElem CPHDXMLParser::toXML(const SupportArray& supports, XMLElem parent) -{ - XMLElem supportsXML = newElement("SupportArray", parent); - createSupportArray(supports.iazArray, "IAZArray", *supportsXML); - createSupportArray(supports.antGainPhase, "AntGainPhase", *supportsXML); - createSupportArray(supports.dwellTimeArray, "DwellTimeArray", *supportsXML); // added in CPHD 1.1.0 - - if (!supports.addedSupportArray.empty()) - { - for (auto it = supports.addedSupportArray.begin(); it != supports.addedSupportArray.end(); ++it) - { - XMLElem addedSupportArrayXML = newElement("AddedSupportArray", supportsXML); - createString("Identifier", it->first, addedSupportArrayXML); - createString("ElementFormat", it->second.elementFormat, addedSupportArrayXML); - createDouble("X0", it->second.x0, addedSupportArrayXML); - createDouble("Y0", it->second.y0, addedSupportArrayXML); - createDouble("XSS", it->second.xSS, addedSupportArrayXML); - createDouble("YSS", it->second.ySS, addedSupportArrayXML); - createString("XUnits", it->second.xUnits, addedSupportArrayXML); - createString("YUnits", it->second.yUnits, addedSupportArrayXML); - createString("ZUnits", it->second.zUnits, addedSupportArrayXML); - mCommon.addParameters("Parameter", getDefaultURI(), it->second.parameter, addedSupportArrayXML); - } - } - return supportsXML; -} - -XMLElem CPHDXMLParser::toXML(const Dwell& dwell, XMLElem parent) -{ - XMLElem dwellXML = newElement("Dwell", parent); - createInt("NumCODTimes", dwell.cod.size(), dwellXML); - - for (size_t ii = 0; ii < dwell.cod.size(); ++ii) - { - XMLElem codTimeXML = newElement("CODTime", dwellXML); - createString("Identifier", dwell.cod[ii].identifier, codTimeXML); - mCommon.createPoly2D("CODTimePoly", dwell.cod[ii].codTimePoly, codTimeXML); - } - createInt("NumDwellTimes", dwell.dtime.size(), dwellXML); - for (size_t ii = 0; ii < dwell.dtime.size(); ++ii) - { - XMLElem dwellTimeXML = newElement("DwellTime", dwellXML); - createString("Identifier", dwell.dtime[ii].identifier, dwellTimeXML); - mCommon.createPoly2D("DwellTimePoly", dwell.dtime[ii].dwellTimePoly, dwellTimeXML); - } - return dwellXML; -} - -XMLElem CPHDXMLParser::toXML(const ReferenceGeometry& refGeo, XMLElem parent) -{ - XMLElem refGeoXML = newElement("ReferenceGeometry", parent); - XMLElem srpXML = newElement("SRP", refGeoXML); - mCommon.createVector3D("ECF", refGeo.srp.ecf, srpXML); - mCommon.createVector3D("IAC", refGeo.srp.iac, srpXML); - createDouble("ReferenceTime", refGeo.referenceTime, refGeoXML); - createDouble("SRPCODTime", refGeo.srpCODTime, refGeoXML); - createDouble("SRPDwellTime", refGeo.srpDwellTime, refGeoXML); - - if (refGeo.monostatic.get()) - { - XMLElem monoXML = newElement("Monostatic", refGeoXML); - mCommon.createVector3D("ARPPos", refGeo.monostatic->arpPos, monoXML); - mCommon.createVector3D("ARPVel", refGeo.monostatic->arpVel, monoXML); - const auto side = refGeo.monostatic->sideOfTrack.toString(); - createString("SideOfTrack", (side == "LEFT" ? "L" : "R"), monoXML); - createDouble("SlantRange", refGeo.monostatic->slantRange, monoXML); - createDouble("GroundRange", refGeo.monostatic->groundRange, monoXML); - createDouble("DopplerConeAngle", refGeo.monostatic->dopplerConeAngle, monoXML); - createDouble("GrazeAngle", refGeo.monostatic->grazeAngle, monoXML); - createDouble("IncidenceAngle", refGeo.monostatic->incidenceAngle, monoXML); - createDouble("AzimuthAngle", refGeo.monostatic->azimuthAngle, monoXML); - createDouble("TwistAngle", refGeo.monostatic->twistAngle, monoXML); - createDouble("SlopeAngle", refGeo.monostatic->slopeAngle, monoXML); - createDouble("LayoverAngle", refGeo.monostatic->layoverAngle, monoXML); - } - else if(refGeo.bistatic.get()) - { - XMLElem biXML = newElement("Bistatic", refGeoXML); - createDouble("AzimuthAngle", refGeo.bistatic->azimuthAngle, biXML); - createDouble("AzimuthAngleRate", refGeo.bistatic->azimuthAngleRate, biXML); - createDouble("BistaticAngle", refGeo.bistatic->bistaticAngle, biXML); - createDouble("BistaticAngleRate", refGeo.bistatic->bistaticAngleRate, biXML); - createDouble("GrazeAngle", refGeo.bistatic->grazeAngle, biXML); - createDouble("TwistAngle", refGeo.bistatic->twistAngle, biXML); - createDouble("SlopeAngle", refGeo.bistatic->slopeAngle, biXML); - createDouble("LayoverAngle", refGeo.bistatic->layoverAngle, biXML); - XMLElem txPlatXML = newElement("TxPlatform", biXML); - createDouble("Time", refGeo.bistatic->txPlatform.time, txPlatXML); - mCommon.createVector3D("Pos", refGeo.bistatic->txPlatform.pos, txPlatXML); - mCommon.createVector3D("Vel", refGeo.bistatic->txPlatform.vel, txPlatXML); - - { - const auto side = refGeo.bistatic->txPlatform.sideOfTrack.toString(); - createString("SideOfTrack", (side == "LEFT" ? "L" : "R"), txPlatXML); - } - createDouble("SlantRange", refGeo.bistatic->txPlatform.slantRange, txPlatXML); - createDouble("GroundRange", refGeo.bistatic->txPlatform.groundRange, txPlatXML); - createDouble("DopplerConeAngle", refGeo.bistatic->txPlatform.dopplerConeAngle, txPlatXML); - createDouble("GrazeAngle", refGeo.bistatic->txPlatform.grazeAngle, txPlatXML); - createDouble("IncidenceAngle", refGeo.bistatic->txPlatform.incidenceAngle, txPlatXML); - createDouble("AzimuthAngle", refGeo.bistatic->txPlatform.azimuthAngle, txPlatXML); - XMLElem rcvPlatXML = newElement("RcvPlatform", biXML); - createDouble("Time", refGeo.bistatic->rcvPlatform.time, rcvPlatXML); - mCommon.createVector3D("Pos", refGeo.bistatic->rcvPlatform.pos, rcvPlatXML); - mCommon.createVector3D("Vel", refGeo.bistatic->rcvPlatform.vel, rcvPlatXML); - - { - const auto side = refGeo.bistatic->rcvPlatform.sideOfTrack.toString(); - createString("SideOfTrack", (side == "LEFT" ? "L" : "R"), rcvPlatXML); - } - createDouble("SlantRange", refGeo.bistatic->rcvPlatform.slantRange, rcvPlatXML); - createDouble("GroundRange", refGeo.bistatic->rcvPlatform.groundRange, rcvPlatXML); - createDouble("DopplerConeAngle", refGeo.bistatic->rcvPlatform.dopplerConeAngle, rcvPlatXML); - createDouble("GrazeAngle", refGeo.bistatic->rcvPlatform.grazeAngle, rcvPlatXML); - createDouble("IncidenceAngle", refGeo.bistatic->rcvPlatform.incidenceAngle, rcvPlatXML); - createDouble("AzimuthAngle", refGeo.bistatic->rcvPlatform.azimuthAngle, rcvPlatXML); - } - return refGeoXML; -} - -XMLElem CPHDXMLParser::toXML(const six::XsElement_minOccurs0& o, xml::lite::Element& parent) -{ - XMLElem retval = nullptr; - if (has_value(o)) - { - retval = newElement(o.tag(), &parent); - std::ignore = create(parser(), value(o).dcxsf, *retval); - std::ignore = create(parser(), value(o).dcysf, *retval); - } - - return retval; -} - -XMLElem CPHDXMLParser::toXML(const six::XsElement_minOccurs0& o, xml::lite::Element& parent) -{ - XMLElem retval = nullptr; - if (has_value(o)) - { - retval = newElement(o.tag(), &parent); - std::ignore = create(parser(), value(o).dcxsf, *retval); - std::ignore = create(parser(), value(o).dcysf, *retval); - } - - return retval; -} - -XMLElem CPHDXMLParser::toXML(const six::XsElement_minOccurs0& o, xml::lite::Element& parent) -{ - XMLElem retval = nullptr; - if (has_value(o)) - { - retval = newElement(o.tag(), &parent); - std::ignore = create(parser(), value(o).ampX, *retval); - std::ignore = create(parser(), value(o).ampY, *retval); - std::ignore = create(parser(), value(o).phaseY, *retval); - } - - return retval; -} - -XMLElem CPHDXMLParser::toXML(const Antenna& antenna, XMLElem parent) -{ - XMLElem antennaXML = newElement("Antenna", parent); - createInt("NumACFs", antenna.antCoordFrame.size(), antennaXML); - createInt("NumAPCs", antenna.antPhaseCenter.size(), antennaXML); - createInt("NumAntPats", antenna.antPattern.size(), antennaXML); - for (size_t ii = 0; ii < antenna.antCoordFrame.size(); ++ii) - { - XMLElem antCoordFrameXML = newElement("AntCoordFrame", antennaXML); - createString("Identifier", antenna.antCoordFrame[ii].identifier, antCoordFrameXML); - mCommon.createPolyXYZ("XAxisPoly", antenna.antCoordFrame[ii].xAxisPoly, antCoordFrameXML); - mCommon.createPolyXYZ("YAxisPoly", antenna.antCoordFrame[ii].yAxisPoly, antCoordFrameXML); - create(parser(), antenna.antCoordFrame[ii].useACFPVP, *antCoordFrameXML); - } - for (size_t ii = 0; ii < antenna.antPhaseCenter.size(); ++ii) - { - XMLElem antPhaseCenterXML = newElement("AntPhaseCenter", antennaXML); - createString("Identifier", antenna.antPhaseCenter[ii].identifier, antPhaseCenterXML); - createString("ACFId", antenna.antPhaseCenter[ii].acfId, antPhaseCenterXML); - mCommon.createVector3D("APCXYZ", antenna.antPhaseCenter[ii].apcXYZ, antPhaseCenterXML); - } - for (size_t ii = 0; ii < antenna.antPattern.size(); ++ii) - { - XMLElem antPatternXML = newElement("AntPattern", antennaXML); - createString("Identifier", antenna.antPattern[ii].identifier, antPatternXML); - createDouble("FreqZero", antenna.antPattern[ii].freqZero, antPatternXML); - createOptionalDouble("GainZero", antenna.antPattern[ii].gainZero, antPatternXML); - if (!six::Init::isUndefined(antenna.antPattern[ii].ebFreqShift)) - { - createBooleanType("EBFreqShift", antenna.antPattern[ii].ebFreqShift, antPatternXML); - } - std::ignore = toXML(antenna.antPattern[ii].ebFreqShiftSF, *antPatternXML); - - if (!six::Init::isUndefined(antenna.antPattern[ii].mlFreqDilation)) - { - createBooleanType("MLFreqDilation", antenna.antPattern[ii].mlFreqDilation, antPatternXML); - } - std::ignore = toXML(antenna.antPattern[ii].mlFreqDilationSF, *antPatternXML); - - if (!six::Init::isUndefined(antenna.antPattern[ii].gainBSPoly)) - { - mCommon.createPoly1D("GainBSPoly", antenna.antPattern[ii].gainBSPoly, antPatternXML); - } - - std::ignore = toXML(antenna.antPattern[ii].antPolRef, *antPatternXML); - - XMLElem ebXML = newElement("EB", antPatternXML); - mCommon.createPoly1D("DCXPoly", antenna.antPattern[ii].eb.dcxPoly, ebXML); - mCommon.createPoly1D("DCYPoly", antenna.antPattern[ii].eb.dcyPoly, ebXML); - create(parser(), antenna.antPattern[ii].eb.useEBPVP, *ebXML); - - XMLElem arrayXML = newElement("Array", antPatternXML); - mCommon.createPoly2D("GainPoly", antenna.antPattern[ii].array.gainPoly, arrayXML); - mCommon.createPoly2D("PhasePoly", antenna.antPattern[ii].array.phasePoly, arrayXML); - create(parser(), antenna.antPattern[ii].array.antGPId, *arrayXML); - - XMLElem elementXML = newElement("Element", antPatternXML); - mCommon.createPoly2D("GainPoly", antenna.antPattern[ii].element.gainPoly, elementXML); - mCommon.createPoly2D("PhasePoly", antenna.antPattern[ii].element.phasePoly, elementXML); - for (size_t jj = 0; jj < antenna.antPattern[ii].gainPhaseArray.size(); ++jj) - { - XMLElem gainPhaseArrayXML = newElement("GainPhaseArray", antPatternXML); - createDouble("Freq", antenna.antPattern[ii].gainPhaseArray[jj].freq, gainPhaseArrayXML); - createString("ArrayId", antenna.antPattern[ii].gainPhaseArray[jj].arrayId, gainPhaseArrayXML); - if (!six::Init::isUndefined(antenna.antPattern[ii].gainPhaseArray[jj].elementId)) - { - createString("ElementId", antenna.antPattern[ii].gainPhaseArray[jj].elementId, gainPhaseArrayXML); - } - } - } - return antennaXML; -} - -XMLElem CPHDXMLParser::toXML(const TxRcv& txRcv, XMLElem parent) -{ - XMLElem txRcvXML = newElement("TxRcv", parent); - createInt("NumTxWFs", txRcv.txWFParameters.size(), txRcvXML); - for (size_t ii = 0; ii < txRcv.txWFParameters.size(); ++ii) - { - XMLElem txWFParamsXML = newElement("TxWFParameters", txRcvXML); - createString("Identifier", txRcv.txWFParameters[ii].identifier, txWFParamsXML); - createDouble("PulseLength", txRcv.txWFParameters[ii].pulseLength, txWFParamsXML); - createDouble("RFBandwidth", txRcv.txWFParameters[ii].rfBandwidth, txWFParamsXML); - createDouble("FreqCenter", txRcv.txWFParameters[ii].freqCenter, txWFParamsXML); - createOptionalDouble("LFMRate", txRcv.txWFParameters[ii].lfmRate, txWFParamsXML); - createString("Polarization", txRcv.txWFParameters[ii].polarization, txWFParamsXML); - createOptionalDouble("Power", txRcv.txWFParameters[ii].power, txWFParamsXML); - } - createInt("NumRcvs", txRcv.rcvParameters.size(), txRcvXML); - for (size_t ii = 0; ii < txRcv.rcvParameters.size(); ++ii) - { - XMLElem rcvParamsXML = newElement("RcvParameters", txRcvXML); - createString("Identifier", txRcv.rcvParameters[ii].identifier, rcvParamsXML); - createDouble("WindowLength", txRcv.rcvParameters[ii].windowLength, rcvParamsXML); - createDouble("SampleRate", txRcv.rcvParameters[ii].sampleRate, rcvParamsXML); - createDouble("IFFilterBW", txRcv.rcvParameters[ii].ifFilterBW, rcvParamsXML); - createDouble("FreqCenter", txRcv.rcvParameters[ii].freqCenter, rcvParamsXML); - createOptionalDouble("LFMRate", txRcv.rcvParameters[ii].lfmRate, rcvParamsXML); - createString("Polarization", txRcv.rcvParameters[ii].polarization, rcvParamsXML); - createOptionalDouble("PathGain", txRcv.rcvParameters[ii].pathGain, rcvParamsXML); - } - return txRcvXML; -} - -XMLElem CPHDXMLParser::toXML(const ErrorParameters& errParams, XMLElem parent) -{ - XMLElem errParamsXML = newElement("ErrorParameters", parent); - if (errParams.monostatic.get()) - { - XMLElem monoXML = newElement("Monostatic", errParamsXML); - XMLElem posVelErrXML = newElement("PosVelErr", monoXML); - createString("Frame", errParams.monostatic->posVelErr.frame, posVelErrXML); - createDouble("P1", errParams.monostatic->posVelErr.p1, posVelErrXML); - createDouble("P2", errParams.monostatic->posVelErr.p2, posVelErrXML); - createDouble("P3", errParams.monostatic->posVelErr.p3, posVelErrXML); - createDouble("V1", errParams.monostatic->posVelErr.v1, posVelErrXML); - createDouble("V2", errParams.monostatic->posVelErr.v2, posVelErrXML); - createDouble("V3", errParams.monostatic->posVelErr.v3, posVelErrXML); - if(errParams.monostatic->posVelErr.corrCoefs.get()) - { - XMLElem corrCoefsXML = newElement("CorrCoefs", posVelErrXML); - createDouble("P1P2", errParams.monostatic->posVelErr.corrCoefs->p1p2, corrCoefsXML); - createDouble("P1P3", errParams.monostatic->posVelErr.corrCoefs->p1p3, corrCoefsXML); - createDouble("P1V1", errParams.monostatic->posVelErr.corrCoefs->p1v1, corrCoefsXML); - createDouble("P1V2", errParams.monostatic->posVelErr.corrCoefs->p1v2, corrCoefsXML); - createDouble("P1V3", errParams.monostatic->posVelErr.corrCoefs->p1v3, corrCoefsXML); - createDouble("P2P3", errParams.monostatic->posVelErr.corrCoefs->p2p3, corrCoefsXML); - createDouble("P2V1", errParams.monostatic->posVelErr.corrCoefs->p2v1, corrCoefsXML); - createDouble("P2V2", errParams.monostatic->posVelErr.corrCoefs->p2v2, corrCoefsXML); - createDouble("P2V3", errParams.monostatic->posVelErr.corrCoefs->p2v3, corrCoefsXML); - createDouble("P3V1", errParams.monostatic->posVelErr.corrCoefs->p3v1, corrCoefsXML); - createDouble("P3V2", errParams.monostatic->posVelErr.corrCoefs->p3v2, corrCoefsXML); - createDouble("P3V3", errParams.monostatic->posVelErr.corrCoefs->p3v3, corrCoefsXML); - createDouble("V1V2", errParams.monostatic->posVelErr.corrCoefs->v1v2, corrCoefsXML); - createDouble("V1V3", errParams.monostatic->posVelErr.corrCoefs->v1v3, corrCoefsXML); - createDouble("V2V3", errParams.monostatic->posVelErr.corrCoefs->v2v3, corrCoefsXML); - } - createDecorrType("PositionDecorr", errParams.monostatic->posVelErr.positionDecorr, posVelErrXML); - - // RadarSensor - XMLElem radarXML = newElement("RadarSensor", monoXML); - createDouble("RangeBias", errParams.monostatic->radarSensor.rangeBias, radarXML); - createOptionalDouble("ClockFreqSF", errParams.monostatic->radarSensor.clockFreqSF, radarXML); - createOptionalDouble("CollectionStartTime", errParams.monostatic->radarSensor.collectionStartTime, radarXML); - if (errParams.monostatic->radarSensor.rangeBiasDecorr.get()) - { - XMLElem rangeBiasDecorrXML = newElement("RangeBiasDecorr", radarXML); - createDouble("CorrCoefZero", errParams.monostatic->radarSensor.rangeBiasDecorr->corrCoefZero, rangeBiasDecorrXML); - createDouble("DecorrRate", errParams.monostatic->radarSensor.rangeBiasDecorr->decorrRate, rangeBiasDecorrXML); - } - - if (errParams.monostatic->tropoError.get()) - { - XMLElem tropoXML = newElement("TropoError", monoXML); - createOptionalDouble("TropoRangeVertical", errParams.monostatic->tropoError->tropoRangeVertical, tropoXML); - createOptionalDouble("TropoRangeSlant", errParams.monostatic->tropoError->tropoRangeSlant, tropoXML); - createDecorrType("TropoRangeDecorr", errParams.monostatic->tropoError->tropoRangeDecorr, tropoXML); - } - if (errParams.monostatic->ionoError.get()) - { - XMLElem ionoXML = newElement("IonoError", monoXML); - createDouble("IonoRangeVertical", errParams.monostatic->ionoError->ionoRangeVertical, ionoXML); - createOptionalDouble("IonoRangeRateVertical", errParams.monostatic->ionoError->ionoRangeRateVertical, ionoXML); - createOptionalDouble("IonoRgRgRateCC", errParams.monostatic->ionoError->ionoRgRgRateCC, ionoXML); - createDecorrType("IonoRangeVertDecorr", errParams.monostatic->tropoError->tropoRangeDecorr, ionoXML); - } - if (!errParams.monostatic->parameter.empty()) - { - XMLElem addedParamsXML = newElement("AddedParameters", monoXML); - mCommon.addParameters("Parameter", getDefaultURI(), errParams.monostatic->parameter, addedParamsXML); - } - } - else if (errParams.bistatic.get()) - { - XMLElem biXML = newElement("Bistatic", errParamsXML); - XMLElem txPlatXML = newElement("TxPlatform", biXML); - createErrorParamPlatform("TxPlatform", errParams.bistatic->txPlatform, txPlatXML); - XMLElem radarTxXML = newElement("RadarSensor", txPlatXML); - create(parser(), errParams.bistatic->txPlatform.radarSensor.delayBias, *radarTxXML); - createOptionalDouble("ClockFreqSF", errParams.bistatic->txPlatform.radarSensor.clockFreqSF, radarTxXML); - createDouble("CollectionStartTime", errParams.bistatic->txPlatform.radarSensor.collectionStartTime, radarTxXML); - - XMLElem rcvPlatXML = newElement("RcvPlatform", biXML); - createErrorParamPlatform("RcvPlatform", errParams.bistatic->rcvPlatform, rcvPlatXML); - XMLElem radarRcvXML = newElement("RadarSensor", rcvPlatXML); - createOptionalDouble("ClockFreqSF", errParams.bistatic->rcvPlatform.radarSensor.clockFreqSF, radarRcvXML); - createDouble("CollectionStartTime", errParams.bistatic->rcvPlatform.radarSensor.collectionStartTime, radarRcvXML); - - if (!errParams.bistatic->parameter.empty()) - { - XMLElem addedParamsXML = newElement("AddedParameters", biXML); - mCommon.addParameters("Parameter", getDefaultURI(), errParams.bistatic->parameter, addedParamsXML); - } - } - - return errParamsXML; -} - -XMLElem CPHDXMLParser::toXML(const ProductInfo& productInfo, XMLElem parent) -{ - XMLElem productInfoXML = newElement("ProductInfo", parent); - if(!six::Init::isUndefined(productInfo.profile)) - { - createString("Profile", productInfo.profile, productInfoXML); - } - for (size_t ii = 0; ii < productInfo.creationInfo.size(); ++ii) - { - XMLElem creationInfoXML = newElement("CreationInfo", productInfoXML); - if(!six::Init::isUndefined(productInfo.creationInfo[ii].application)) - { - createString("Application", productInfo.creationInfo[ii].application, creationInfoXML); - } - createDateTime("DateTime", productInfo.creationInfo[ii].dateTime, creationInfoXML); - if (!six::Init::isUndefined(productInfo.creationInfo[ii].site)) - { - createString("Site", productInfo.creationInfo[ii].site, creationInfoXML); - } - mCommon.addParameters("Parameter", getDefaultURI(), productInfo.creationInfo[ii].parameter, creationInfoXML); - } - mCommon.addParameters("Parameter", getDefaultURI(), productInfo.parameter, productInfoXML); - return productInfoXML; -} - -XMLElem CPHDXMLParser::toXML(const GeoInfo& geoInfo, XMLElem parent) -{ - XMLElem geoInfoXML = newElement("GeoInfo", parent); - - mCommon.addParameters("Desc", geoInfo.desc, geoInfoXML); - - const size_t numLatLons = geoInfo.geometryLatLon.size(); - if (numLatLons == 1) - { - mCommon.createLatLon("Point", geoInfo.geometryLatLon[0], geoInfoXML); - } - else if (numLatLons >= 2) - { - XMLElem linePolyXML = newElement(numLatLons == 2 ? "Line" : "Polygon", - geoInfoXML); - setAttribute(linePolyXML, "size", numLatLons); - - for (size_t ii = 0; ii < numLatLons; ++ii) - { - XMLElem v = mCommon.createLatLon(numLatLons == 2 ? "Endpoint" : "Vertex", - geoInfo.geometryLatLon[ii], linePolyXML); - setAttribute(v, "index", ii + 1); - } - } - - if (!geoInfo.name.empty()) - setAttribute(geoInfoXML, "name", geoInfo.name); - - for (size_t ii = 0; ii < geoInfo.geoInfos.size(); ++ii) - { - toXML(*geoInfo.geoInfos[ii], geoInfoXML); - } - - return geoInfoXML; -} - -XMLElem CPHDXMLParser::toXML(const MatchInformation& matchInfo, XMLElem parent) -{ - return mCommon.convertMatchInformationToXML(matchInfo, parent); -} - -/* - * FROM XML - */ - -std::unique_ptr CPHDXMLParser::fromXML( - const xml::lite::Document* doc) -{ - std::unique_ptr cphd(new Metadata()); - - const auto root = doc->getRootElement(); - - XMLElem collectionIDXML = getFirstAndOnly(root, "CollectionID"); - XMLElem globalXML = getFirstAndOnly(root, "Global"); - XMLElem sceneCoordsXML = getFirstAndOnly(root, "SceneCoordinates"); - XMLElem dataXML = getFirstAndOnly(root, "Data"); - XMLElem channelXML = getFirstAndOnly(root, "Channel"); - XMLElem pvpXML = getFirstAndOnly(root, "PVP"); - XMLElem dwellXML = getFirstAndOnly(root, "Dwell"); - XMLElem refGeoXML = getFirstAndOnly(root, "ReferenceGeometry"); - - XMLElem supportArrayXML = getOptional(root, "SupportArray"); - XMLElem antennaXML = getOptional(root, "Antenna"); - XMLElem txRcvXML = getOptional(root, "TxRcv"); - XMLElem errParamXML = getOptional(root, "ErrorParameters"); - XMLElem productInfoXML = getOptional(root, "ProductInfo"); - std::vector geoInfoXMLVec; - root->getElementsByTagName("GeoInfo", geoInfoXMLVec); - cphd->geoInfo.resize(geoInfoXMLVec.size()); - XMLElem matchInfoXML = getOptional(root, "MatchInfo"); - - // Parse XML for each section - fromXML(collectionIDXML, cphd->collectionID); - fromXML(globalXML, cphd->global); - fromXML(sceneCoordsXML, cphd->sceneCoordinates); - fromXML(dataXML, cphd->data); - fromXML(channelXML, cphd->channel); - fromXML(pvpXML, cphd->pvp); - fromXML(dwellXML, cphd->dwell); - fromXML(refGeoXML, cphd->referenceGeometry); - - if(supportArrayXML) - { - cphd->supportArray.reset(new SupportArray()); - fromXML(supportArrayXML, *(cphd->supportArray)); - } - if(antennaXML) - { - cphd->antenna.reset(new Antenna()); - fromXML(antennaXML, *(cphd->antenna)); - } - if(txRcvXML) - { - cphd->txRcv.reset(new TxRcv()); - fromXML(txRcvXML, *(cphd->txRcv)); - } - if(errParamXML) - { - cphd->errorParameters.reset(new ErrorParameters()); - fromXML(errParamXML, *(cphd->errorParameters)); - } - if(productInfoXML) - { - cphd->productInfo.reset(new ProductInfo()); - fromXML(productInfoXML, *(cphd->productInfo)); - } - for (size_t ii = 0; ii < geoInfoXMLVec.size(); ++ii) - { - fromXML(geoInfoXMLVec[ii], cphd->geoInfo[ii]); - } - if (matchInfoXML) - { - cphd->matchInfo.reset(new MatchInformation()); - fromXML(matchInfoXML, *(cphd->matchInfo)); - } - - return cphd; -} - -void CPHDXMLParser::fromXML(const xml::lite::Element* collectionIDXML, CollectionInformation& collectionID) -{ - parseString(getFirstAndOnly(collectionIDXML, "CollectorName"), - collectionID.collectorName); - - XMLElem element = getOptional(collectionIDXML, "IlluminatorName"); - if (element) - { - parseString(element, collectionID.illuminatorName); - } - - element = getOptional(collectionIDXML, "CoreName"); - if (element) - { - parseString(element, collectionID.coreName); - } - - element = getOptional(collectionIDXML, "CollectType"); - if (element) - { - collectionID.collectType - = six::toType(element->getCharacterData()); - } - - XMLElem radarModeXML = getFirstAndOnly(collectionIDXML, "RadarMode"); - - collectionID.radarMode - = six::toType(getFirstAndOnly(radarModeXML, - "ModeType")->getCharacterData()); - - element = getOptional(radarModeXML, "ModeID"); - if (element) - { - parseString(element, collectionID.radarModeID); - } - - element = getFirstAndOnly(collectionIDXML, "ReleaseInfo"); - parseString(element, collectionID.releaseInfo); - - std::string classification; - parseString(getFirstAndOnly(collectionIDXML, "Classification"), - classification); - collectionID.setClassificationLevel(classification); - - // Optional - std::vector countryCodes; - element = getOptional(collectionIDXML, "CountryCode"); - if (element) - { - std::string countryCodeStr; - parseString(element, countryCodeStr); - collectionID.countryCodes = str::split(countryCodeStr, ","); - for (size_t ii = 0; ii < collectionID.countryCodes.size(); ++ii) - { - str::trim(collectionID.countryCodes[ii]); - } - } - - //optional - mCommon.parseParameters(collectionIDXML, "Parameter", collectionID.parameters); -} - -void CPHDXMLParser::fromXML(const xml::lite::Element* globalXML, Global& global) -{ - global.domainType = DomainType::toType( - getFirstAndOnly(globalXML, "DomainType")->getCharacterData()); - global.sgn = PhaseSGN::toType( - getFirstAndOnly(globalXML, "SGN")->getCharacterData()); - - // Timeline - const xml::lite::Element* timelineXML = getFirstAndOnly(globalXML, "Timeline"); - parseDateTime( - getFirstAndOnly(timelineXML, "CollectionStart"), - global.timeline.collectionStart); - - // Optional - const xml::lite::Element* rcvCollectionXML = getOptional(timelineXML, - "RcvCollectionStart"); - if (rcvCollectionXML) - { - parseDateTime(rcvCollectionXML, - global.timeline.rcvCollectionStart); - } - - parseDouble( - getFirstAndOnly(timelineXML, "TxTime1"), global.timeline.txTime1); - parseDouble( - getFirstAndOnly(timelineXML, "TxTime2"), global.timeline.txTime2); - - // FxBand - const xml::lite::Element* fxBandXML = getFirstAndOnly(globalXML, "FxBand"); - parseDouble(getFirstAndOnly(fxBandXML, "FxMin"), global.fxBand.fxMin); - parseDouble(getFirstAndOnly(fxBandXML, "FxMax"), global.fxBand.fxMax); - - // TOASwath - const xml::lite::Element* toaSwathXML = getFirstAndOnly(globalXML, "TOASwath"); - parseDouble(getFirstAndOnly(toaSwathXML, "TOAMin"), global.toaSwath.toaMin); - parseDouble(getFirstAndOnly(toaSwathXML, "TOAMax"), global.toaSwath.toaMax); - - // TropoParameters - const xml::lite::Element* tropoXML = getOptional(globalXML, "TropoParameters"); - if (tropoXML) - { - // Optional - global.tropoParameters.reset(new TropoParameters()); - parseDouble(getFirstAndOnly(tropoXML, "N0"), global.tropoParameters->n0); - global.tropoParameters->refHeight = - RefHeight::toType(getFirstAndOnly(tropoXML, "RefHeight")->getCharacterData()); - } - - // IonoParameters - if (const auto ionoXML = getOptional(globalXML, "IonoParameters")) - { - // Optional - global.ionoParameters.reset(new IonoParameters()); - parseDouble(getFirstAndOnly(ionoXML, "TECV"), global.ionoParameters->tecv); - if (const auto f2HeightXML = getOptional(ionoXML, "F2Height")) - { - parseDouble(f2HeightXML, global.ionoParameters->f2Height); - } - } -} - -void CPHDXMLParser::fromXML(const xml::lite::Element* sceneCoordsXML, - SceneCoordinates& scene) -{ - scene.earthModel = EarthModelType::toType( - getFirstAndOnly(sceneCoordsXML, "EarthModel")->getCharacterData()); - - // IARP - const xml::lite::Element* iarpXML = getFirstAndOnly(sceneCoordsXML, "IARP"); - mCommon.parseVector3D(getFirstAndOnly(iarpXML, "ECF"), scene.iarp.ecf); - mCommon.parseLatLonAlt(getFirstAndOnly(iarpXML, "LLH"), scene.iarp.llh); - - // ReferenceSurface - const xml::lite::Element* surfaceXML = getFirstAndOnly(sceneCoordsXML, "ReferenceSurface"); - const xml::lite::Element* planarXML = getOptional(surfaceXML, "Planar"); - const xml::lite::Element* haeXML = getOptional(surfaceXML, "HAE"); - if (planarXML && !haeXML) - { - // Choice type - scene.referenceSurface.planar.reset(new Planar()); - mCommon.parseVector3D(getFirstAndOnly(planarXML, "uIAX"), - scene.referenceSurface.planar->uIax); - mCommon.parseVector3D(getFirstAndOnly(planarXML, "uIAY"), - scene.referenceSurface.planar->uIay); - } - else if (haeXML && !planarXML) - { - // Choice type - scene.referenceSurface.hae.reset(new HAE()); - mCommon.parseLatLon(getFirstAndOnly(haeXML, "uIAXLL"), - scene.referenceSurface.hae->uIax); - mCommon.parseLatLon(getFirstAndOnly(haeXML, "uIAYLL"), - scene.referenceSurface.hae->uIay); - } - else - { - throw except::Exception(Ctxt( - "ReferenceSurface must exactly one of Planar or HAE element")); - } - - // ImageArea - const xml::lite::Element* imageAreaXML = getFirstAndOnly(sceneCoordsXML, "ImageArea"); - parseAreaType(imageAreaXML, scene.imageArea); - - // ImageAreaCorners - const xml::lite::Element* cornersXML = getFirstAndOnly(sceneCoordsXML, - "ImageAreaCornerPoints"); - mCommon.parseFootprint(cornersXML, "IACP", scene.imageAreaCorners); - - // Extended Area - const xml::lite::Element* extendedAreaXML = getOptional(sceneCoordsXML, "ExtendedArea"); - if (extendedAreaXML) - { - scene.extendedArea.reset(new AreaType()); - parseAreaType(extendedAreaXML, *scene.extendedArea); - } - - // Image Grid - const xml::lite::Element* gridXML = getOptional(sceneCoordsXML, "ImageGrid"); - if (gridXML) - { - // Optional - scene.imageGrid.reset(new ImageGrid()); - const xml::lite::Element* identifierXML = getOptional(gridXML, "Identifier"); - if (identifierXML) - { - parseString(identifierXML, scene.imageGrid->identifier); - } - parseLineSample(getFirstAndOnly(gridXML, "IARPLocation"), - scene.imageGrid->iarpLocation); - parseIAExtent(getFirstAndOnly(gridXML, "IAXExtent"), - scene.imageGrid->xExtent); - parseIAExtent(getFirstAndOnly(gridXML, "IAYExtent"), - scene.imageGrid->yExtent); - - // Segment List - const xml::lite::Element* segListXML = getOptional(gridXML, "SegmentList"); - if (segListXML) - { - // Optional - size_t numSegments; - parseUInt(getFirstAndOnly(segListXML, "NumSegments"), numSegments); - scene.imageGrid->segments.resize(numSegments); - - std::vector segmentsXML; - segListXML->getElementsByTagName("Segment", segmentsXML); - - for (size_t ii = 0; ii < segmentsXML.size(); ++ii) - { - const xml::lite::Element* segmentXML = segmentsXML[ii]; - parseString(getFirstAndOnly(segmentXML, "Identifier"), - scene.imageGrid->segments[ii].identifier); - parseInt(getFirstAndOnly(segmentXML, "StartLine"), - scene.imageGrid->segments[ii].startLine); - parseInt(getFirstAndOnly(segmentXML, "StartSample"), - scene.imageGrid->segments[ii].startSample); - parseInt(getFirstAndOnly(segmentXML, "EndLine"), - scene.imageGrid->segments[ii].endLine); - parseInt(getFirstAndOnly(segmentXML, "EndSample"), - scene.imageGrid->segments[ii].endSample); - - const xml::lite::Element* polygonXML = getOptional(segmentXML, - "SegmentPolygon"); - if (polygonXML) - { - // Optional - size_t polygonSize = 0; - sscanf(const_cast(polygonXML)->attribute("size").c_str(), "%zu", &polygonSize); - scene.imageGrid->segments[ii].polygon.resize(polygonSize); - std::vector polyVerticesXMLVec; - polygonXML->getElementsByTagName("SV", polyVerticesXMLVec); - if (scene.imageGrid->segments[ii].polygon.size() != polyVerticesXMLVec.size()) - { - throw except::Exception(Ctxt( - "Incorrect polygon vertices provided")); - } - if (polyVerticesXMLVec.size() < 3) - { - throw except::Exception(Ctxt( - "Polygon must have at least 3 vertices")); - } - std::vector& vertices = - scene.imageGrid->segments[ii].polygon; - vertices.resize(polyVerticesXMLVec.size()); - for (size_t jj = 0; jj < polyVerticesXMLVec.size(); ++jj) - { - size_t tempIdx; - sscanf(polyVerticesXMLVec[jj]->attribute("index").c_str(), "%zu", &tempIdx); - vertices[jj].setIndex(tempIdx); - parseLineSample(polyVerticesXMLVec[jj], vertices[jj]); - } - } - } - } - } -} - -void CPHDXMLParser::fromXML(const xml::lite::Element* dataXML, Data& data) -{ - const xml::lite::Element* signalXML = getFirstAndOnly(dataXML, "SignalArrayFormat"); - data.signalArrayFormat = SignalArrayFormat::toType(signalXML->getCharacterData()); - - size_t numBytesPVP_temp = 0; - XMLElem numBytesPVPXML = getFirstAndOnly(dataXML, "NumBytesPVP"); - parseUInt(numBytesPVPXML, numBytesPVP_temp); - if(numBytesPVP_temp % 8 != 0) - { - throw except::Exception(Ctxt( - "Number of bytes must be multiple of 8")); - } - data.numBytesPVP = numBytesPVP_temp; - - // Channels - std::vector channelsXML; - dataXML->getElementsByTagName("Channel", channelsXML); - data.channels.resize(channelsXML.size()); - for (size_t ii = 0; ii < channelsXML.size(); ++ii) - { - parseString(getFirstAndOnly(channelsXML[ii], "Identifier"), - data.channels[ii].identifier); - parseUInt(getFirstAndOnly(channelsXML[ii], "NumVectors"), - data.channels[ii].numVectors); - parseUInt(getFirstAndOnly(channelsXML[ii], "NumSamples"), - data.channels[ii].numSamples); - parseUInt(getFirstAndOnly(channelsXML[ii], "SignalArrayByteOffset"), - data.channels[ii].signalArrayByteOffset); - parseUInt(getFirstAndOnly(channelsXML[ii], "PVPArrayByteOffset"), - data.channels[ii].pvpArrayByteOffset); - XMLElem compressionXML = getOptional(channelsXML[ii], "CompressedSignalSize"); - if (compressionXML) - { - parseUInt(compressionXML, data.channels[ii].compressedSignalSize); - } - } - XMLElem compressionXML = getOptional(dataXML, "SignalCompressionID"); - if (compressionXML) - { - parseString(compressionXML, - data.signalCompressionID); - } - - // Support Arrays - std::vector supportsXML; - dataXML->getElementsByTagName("SupportArray", supportsXML); - for (size_t ii = 0; ii < supportsXML.size(); ++ii) - { - std::string id; - size_t offset; - size_t numRows; - size_t numCols; - size_t numBytes; - parseString(getFirstAndOnly(supportsXML[ii], "Identifier"), id); - parseUInt(getFirstAndOnly(supportsXML[ii], "ArrayByteOffset"), offset); - parseUInt(getFirstAndOnly(supportsXML[ii], "NumRows"), numRows); - parseUInt(getFirstAndOnly(supportsXML[ii], "NumCols"), numCols); - parseUInt(getFirstAndOnly(supportsXML[ii], "BytesPerElement"), numBytes); - data.setSupportArray(id, numRows, numCols, numBytes, offset); - } -} - -void CPHDXMLParser::fromXML(const xml::lite::Element* channelXML, Channel& channel) -{ - parseString(getFirstAndOnly(channelXML, "RefChId"), channel.refChId); - parseBooleanType(getFirstAndOnly(channelXML, "FXFixedCPHD"), channel.fxFixedCphd); - parseBooleanType(getFirstAndOnly(channelXML, "TOAFixedCPHD"), channel.toaFixedCphd); - parseBooleanType(getFirstAndOnly(channelXML, "SRPFixedCPHD"), channel.srpFixedCphd); - - std::vector parametersXML; - channelXML->getElementsByTagName("Parameters", parametersXML); - channel.parameters.resize(parametersXML.size()); - for (size_t ii = 0; ii < parametersXML.size(); ++ii) - { - parseChannelParameters(parametersXML[ii], channel.parameters[ii]); - } - - XMLElem addedParametersXML = getOptional(channelXML, "AddedParameters"); - if(addedParametersXML) - { - mCommon.parseParameters(addedParametersXML, "Parameter", channel.addedParameters); - } -} - -void CPHDXMLParser::parse(const xml::lite::Element& parent, six::XsElement& v) const -{ - auto& param = value(v).param; - const auto offset = parsePVPType(parent, param); - setOffset(param, offset); -} -void CPHDXMLParser::parse(const xml::lite::Element& parent, six::XsElement& v) const -{ - auto& param = value(v).param; - const auto offset = parsePVPType(parent, param); - setOffset(param, offset); -} - -void CPHDXMLParser::parse(const xml::lite::Element& parent, six::XsElement_minOccurs0& o) const -{ - if (const auto pXML = getOptional(parent, o.tag())) - { - o = TxAntenna{}; - parse(*pXML, value(o).txACX); - parse(*pXML, value(o).txACY); - parse(*pXML, value(o).txEB); - } -} -void CPHDXMLParser::parse(const xml::lite::Element& parent, six::XsElement_minOccurs0& o) const -{ - if (const auto pXML = getOptional(parent, o.tag())) - { - o = RcvAntenna{}; - parse(*pXML, value(o).rcvACX); - parse(*pXML, value(o).rcvACY); - parse(*pXML, value(o).rcvEB); - } -} - -void CPHDXMLParser::fromXML(const xml::lite::Element* pvpXML, Pvp& pvp) -{ - parsePVPType(pvp, getFirstAndOnly(pvpXML, "TxTime"), pvp.txTime); - parsePVPType(pvp, getFirstAndOnly(pvpXML, "TxPos"), pvp.txPos); - parsePVPType(pvp, getFirstAndOnly(pvpXML, "TxVel"), pvp.txVel); - parsePVPType(pvp, getFirstAndOnly(pvpXML, "RcvTime"), pvp.rcvTime); - parsePVPType(pvp, getFirstAndOnly(pvpXML, "RcvPos"), pvp.rcvPos); - parsePVPType(pvp, getFirstAndOnly(pvpXML, "RcvVel"), pvp.rcvVel); - parsePVPType(pvp, getFirstAndOnly(pvpXML, "SRPPos"), pvp.srpPos); - parsePVPType(pvp, getFirstAndOnly(pvpXML, "aFDOP"), pvp.aFDOP); - parsePVPType(pvp, getFirstAndOnly(pvpXML, "aFRR1"), pvp.aFRR1); - parsePVPType(pvp, getFirstAndOnly(pvpXML, "aFRR2"), pvp.aFRR2); - parsePVPType(pvp, getFirstAndOnly(pvpXML, "FX1"), pvp.fx1); - parsePVPType(pvp, getFirstAndOnly(pvpXML, "FX2"), pvp.fx2); - parsePVPType(pvp, getFirstAndOnly(pvpXML, "TOA1"), pvp.toa1); - parsePVPType(pvp, getFirstAndOnly(pvpXML, "TOA2"), pvp.toa2); - parsePVPType(pvp, getFirstAndOnly(pvpXML, "TDTropoSRP"), pvp.tdTropoSRP); - parsePVPType(pvp, getFirstAndOnly(pvpXML, "SC0"), pvp.sc0); - parsePVPType(pvp, getFirstAndOnly(pvpXML, "SCSS"), pvp.scss); - - parseOptionalPVPType(pvpXML, "AmpSF", pvp, pvp.ampSF); - parseOptionalPVPType(pvpXML, "FXN1", pvp, pvp.fxN1); - parseOptionalPVPType(pvpXML, "FXN2", pvp, pvp.fxN2); - parseOptionalPVPType(pvpXML, "TOAE1", pvp, pvp.toaE1); - parseOptionalPVPType(pvpXML, "TOAE2", pvp, pvp.toaE2); - parseOptionalPVPType(pvpXML, "TDIonoSRP", pvp, pvp.tdIonoSRP); - parseOptionalPVPType(pvpXML, "SIGNAL", pvp, pvp.signal); - - parse(*pvpXML, pvp.txAntenna); - parse(*pvpXML, pvp.rcvAntenna); - - std::vector addedParamsXML; - const std::string str = "AddedPVP"; - pvpXML->getElementsByTagName(str, addedParamsXML); - if(addedParamsXML.empty()) - { - return; - } - for (size_t ii = 0; ii < addedParamsXML.size(); ++ii) - { - parsePVPType(pvp, addedParamsXML[ii]); - } -} - -void CPHDXMLParser::fromXML(const xml::lite::Element* DwellXML, - Dwell& dwell) -{ - // CODTime - size_t numCODTimes; - parseUInt(getFirstAndOnly(DwellXML, "NumCODTimes"), numCODTimes); - dwell.cod.resize(numCODTimes); - - std::vector codXMLVec; - DwellXML->getElementsByTagName("CODTime", codXMLVec); - for(size_t ii = 0; ii < codXMLVec.size(); ++ii) - { - parseString(getFirstAndOnly(codXMLVec[ii], "Identifier"), dwell.cod[ii].identifier); - mCommon.parsePoly2D(getFirstAndOnly(codXMLVec[ii], "CODTimePoly"), dwell.cod[ii].codTimePoly); - } - - // DwellTime - size_t numDwellTimes = 0; - parseUInt(getFirstAndOnly(DwellXML, "NumDwellTimes"), numDwellTimes); - dwell.dtime.resize(numDwellTimes); - - std::vector dtimeXMLVec; - DwellXML->getElementsByTagName("DwellTime", dtimeXMLVec); - for(size_t ii = 0; ii < dtimeXMLVec.size(); ++ii) - { - parseString(getFirstAndOnly(dtimeXMLVec[ii], "Identifier"), dwell.dtime[ii].identifier); - mCommon.parsePoly2D(getFirstAndOnly(dtimeXMLVec[ii], "DwellTimePoly"), dwell.dtime[ii].dwellTimePoly); - } -} - -void CPHDXMLParser::fromXML(const xml::lite::Element* refGeoXML, ReferenceGeometry& refGeo) -{ - XMLElem srpXML = getFirstAndOnly(refGeoXML, "SRP"); - mCommon.parseVector3D(getFirstAndOnly(srpXML, "ECF"), refGeo.srp.ecf); - mCommon.parseVector3D(getFirstAndOnly(srpXML, "IAC"), refGeo.srp.iac); - parseDouble(getFirstAndOnly(refGeoXML, "ReferenceTime"), refGeo.referenceTime); - parseDouble(getFirstAndOnly(refGeoXML, "SRPCODTime"), refGeo.srpCODTime); - parseDouble(getFirstAndOnly(refGeoXML, "SRPDwellTime"), refGeo.srpDwellTime); - - const xml::lite::Element* monoXML = getOptional(refGeoXML, "Monostatic"); - const xml::lite::Element* biXML = getOptional(refGeoXML, "Bistatic"); - if (monoXML && !biXML) - { - refGeo.monostatic.reset(new Monostatic()); - parseCommon(monoXML, (ImagingType*)refGeo.monostatic.get()); - parseDouble(getFirstAndOnly(monoXML, "SlantRange"), refGeo.monostatic->slantRange); - parseDouble(getFirstAndOnly(monoXML, "GroundRange"), refGeo.monostatic->groundRange); - parseDouble(getFirstAndOnly(monoXML, "DopplerConeAngle"), refGeo.monostatic->dopplerConeAngle); - parseDouble(getFirstAndOnly(monoXML, "IncidenceAngle"), refGeo.monostatic->incidenceAngle); - mCommon.parseVector3D(getFirstAndOnly(monoXML, "ARPPos"), refGeo.monostatic->arpPos); - mCommon.parseVector3D(getFirstAndOnly(monoXML, "ARPVel"), refGeo.monostatic->arpVel); - std::string side = ""; - parseString(getFirstAndOnly(monoXML, "SideOfTrack"), side); - refGeo.monostatic->sideOfTrack = (side == "L" ? six::SideOfTrackType::LEFT : six::SideOfTrackType::RIGHT); - - } - else if (!monoXML && biXML) - { - refGeo.bistatic.reset(new Bistatic()); - parseCommon(biXML, (ImagingType*)refGeo.bistatic.get()); - parseDouble(getFirstAndOnly(biXML, "AzimuthAngleRate"), refGeo.bistatic->azimuthAngleRate); - parseDouble(getFirstAndOnly(biXML, "BistaticAngle"), refGeo.bistatic->bistaticAngle); - parseDouble(getFirstAndOnly(biXML, "BistaticAngleRate"), refGeo.bistatic->bistaticAngleRate); - - parsePlatformParams(getFirstAndOnly(biXML, "TxPlatform"), refGeo.bistatic->txPlatform); - parsePlatformParams(getFirstAndOnly(biXML, "RcvPlatform"), refGeo.bistatic->rcvPlatform); - } - else - { - throw except::Exception(Ctxt( - "One of the two types Mono or Bi must be provided")); - } -} - -std::vector CPHDXMLParser::parseSupportArray(const std::string& tag, const xml::lite::Element& parent) const -{ - std::vector elements; - parent.getElementsByTagName(tag, elements); - std::vector supportArray; - supportArray.reserve(elements.size()); - for (const auto& element : elements) - { - SupportArrayParameter param; - parseSupportArrayParameter(element, param, false /*additionalFlag*/); - supportArray.push_back(std::move(param)); - } - return supportArray; -} - -void CPHDXMLParser::fromXML(const xml::lite::Element* supportArrayXML, SupportArray& supportArray) -{ - supportArray.iazArray = parseSupportArray("IAZArray", *supportArrayXML); - supportArray.antGainPhase = parseSupportArray("AntGainPhase", *supportArrayXML); - supportArray.dwellTimeArray = parseSupportArray("DwellTimeArray", *supportArrayXML); - - std::vector addedSupportArrayXMLVec; - supportArrayXML->getElementsByTagName("AddedSupportArray", addedSupportArrayXMLVec); - for (size_t ii = 0; ii < addedSupportArrayXMLVec.size(); ++ii) - { - std::string id; - parseString(getFirstAndOnly(addedSupportArrayXMLVec[ii], "Identifier"), id); - if (supportArray.addedSupportArray.count(id) == 0) - { - parseSupportArrayParameter(addedSupportArrayXMLVec[ii], supportArray.addedSupportArray[id], true); - parseString(getFirstAndOnly(addedSupportArrayXMLVec[ii], "XUnits"), supportArray.addedSupportArray[id].xUnits); - parseString(getFirstAndOnly(addedSupportArrayXMLVec[ii], "YUnits"), supportArray.addedSupportArray[id].yUnits); - parseString(getFirstAndOnly(addedSupportArrayXMLVec[ii], "ZUnits"), supportArray.addedSupportArray[id].zUnits); - mCommon.parseParameters(addedSupportArrayXMLVec[ii], "Parameter", supportArray.addedSupportArray[id].parameter); - } - else - { - throw except::Exception(Ctxt( - "Support array identifier for support array is not unique: " + id)); - } - } -} - -void CPHDXMLParser::parse(const xml::lite::Element& parent, six::XsElement_minOccurs0& o) const -{ - if (const auto pXML = getOptional(parent, o.tag())) - { - o = AntPattern::EBFreqShiftSF{}; - six::getFirstAndOnly(parser(), *pXML, value(o).dcxsf); - six::getFirstAndOnly(parser(), *pXML, value(o).dcysf); - } -} - -void CPHDXMLParser::parse(const xml::lite::Element& parent, six::XsElement_minOccurs0& o) const -{ - if (const auto pXML = getOptional(parent, o.tag())) - { - o = AntPattern::MLFreqDilationSF{}; - six::getFirstAndOnly(parser(), *pXML, value(o).dcxsf); - six::getFirstAndOnly(parser(), *pXML, value(o).dcysf); - } -} - -void CPHDXMLParser::parse(const xml::lite::Element& parent, six::XsElement_minOccurs0& o) const -{ - if (const auto pXML = getOptional(parent, o.tag())) - { - o = AntPattern::AntPolRef{}; - six::getFirstAndOnly(parser(), *pXML, value(o).ampX); - six::getFirstAndOnly(parser(), *pXML, value(o).ampY); - six::getFirstAndOnly(parser(), *pXML, value(o).phaseY); - } -} - -void CPHDXMLParser::fromXML(const xml::lite::Element* antennaXML, Antenna& antenna) -{ - size_t numACFs = 0; - size_t numAPCs = 0; - size_t numAntPats = 0; - parseUInt(getFirstAndOnly(antennaXML, "NumACFs"), numACFs); - antenna.antCoordFrame.resize(numACFs); - parseUInt(getFirstAndOnly(antennaXML, "NumAPCs"), numAPCs); - antenna.antPhaseCenter.resize(numAPCs); - parseUInt(getFirstAndOnly(antennaXML, "NumAntPats"), numAntPats); - antenna.antPattern.resize(numAntPats); - - // Parse AntCoordFrame - std::vector antCoordFrameXMLVec; - antennaXML->getElementsByTagName("AntCoordFrame", antCoordFrameXMLVec); - if(antenna.antCoordFrame.size() != antCoordFrameXMLVec.size()) - { - throw except::Exception(Ctxt( - "Incorrect number of AntCoordFrames provided")); - } - for( size_t ii = 0; ii < antCoordFrameXMLVec.size(); ++ii) - { - parseString(getFirstAndOnly(antCoordFrameXMLVec[ii], "Identifier"), antenna.antCoordFrame[ii].identifier); - mCommon.parsePolyXYZ(getFirstAndOnly(antCoordFrameXMLVec[ii], "XAxisPoly"), antenna.antCoordFrame[ii].xAxisPoly); - mCommon.parsePolyXYZ(getFirstAndOnly(antCoordFrameXMLVec[ii], "YAxisPoly"), antenna.antCoordFrame[ii].yAxisPoly); - std::ignore = six::parse(parser(), *antCoordFrameXMLVec[ii], antenna.antCoordFrame[ii].useACFPVP); - } - - // Parse AntPhaseCenter - std::vector antPhaseCenterXMLVec; - antennaXML->getElementsByTagName("AntPhaseCenter", antPhaseCenterXMLVec); - if(antenna.antPhaseCenter.size() != antPhaseCenterXMLVec.size()) - { - throw except::Exception(Ctxt( - "Incorrect number of AntPhaseCenters provided")); - } - for( size_t ii = 0; ii < antPhaseCenterXMLVec.size(); ++ii) - { - parseString(getFirstAndOnly(antPhaseCenterXMLVec[ii], "Identifier"), antenna.antPhaseCenter[ii].identifier); - parseString(getFirstAndOnly(antPhaseCenterXMLVec[ii], "ACFId"), antenna.antPhaseCenter[ii].acfId); - mCommon.parseVector3D(getFirstAndOnly(antPhaseCenterXMLVec[ii], "APCXYZ"), antenna.antPhaseCenter[ii].apcXYZ); - } - - std::vector antPatternXMLVec; - antennaXML->getElementsByTagName("AntPattern", antPatternXMLVec); - if(antenna.antPattern.size() != antPatternXMLVec.size()) - { - throw except::Exception(Ctxt( - "Incorrect number of AntPatterns provided")); - } - for( size_t ii = 0; ii < antPatternXMLVec.size(); ++ii) - { - parseString(getFirstAndOnly(antPatternXMLVec[ii], "Identifier"), antenna.antPattern[ii].identifier); - parseDouble(getFirstAndOnly(antPatternXMLVec[ii], "FreqZero"), antenna.antPattern[ii].freqZero); - parseOptionalDouble(antPatternXMLVec[ii], "GainZero", antenna.antPattern[ii].gainZero); - - XMLElem ebFreqShiftXML = getOptional(antPatternXMLVec[ii], "EBFreqShift"); - if(ebFreqShiftXML) - { - parseBooleanType(ebFreqShiftXML, antenna.antPattern[ii].ebFreqShift); - } - parse(*antPatternXMLVec[ii], antenna.antPattern[ii].ebFreqShiftSF); - - XMLElem mlFreqDilationXML = getOptional(antPatternXMLVec[ii], "MLFreqDilation"); - if(mlFreqDilationXML) - { - parseBooleanType(mlFreqDilationXML, antenna.antPattern[ii].mlFreqDilation); - } - parse(*antPatternXMLVec[ii], antenna.antPattern[ii].mlFreqDilationSF); - - XMLElem gainBSPoly = getOptional(antPatternXMLVec[ii], "GainBSPoly"); - if(gainBSPoly) - { - mCommon.parsePoly1D(gainBSPoly, antenna.antPattern[ii].gainBSPoly); - } - - parse(*antPatternXMLVec[ii], antenna.antPattern[ii].antPolRef); - - // Parse EB - XMLElem ebXML = getFirstAndOnly(antPatternXMLVec[ii], "EB"); - mCommon.parsePoly1D(getFirstAndOnly(ebXML, "DCXPoly"), antenna.antPattern[ii].eb.dcxPoly); - mCommon.parsePoly1D(getFirstAndOnly(ebXML, "DCYPoly"), antenna.antPattern[ii].eb.dcyPoly); - std::ignore = six::parse(parser(), *ebXML, antenna.antPattern[ii].eb.useEBPVP); - - // Parse Array - XMLElem arrayXML = getFirstAndOnly(antPatternXMLVec[ii], "Array"); - mCommon.parsePoly2D(getFirstAndOnly(arrayXML, "GainPoly"), antenna.antPattern[ii].array.gainPoly); - mCommon.parsePoly2D(getFirstAndOnly(arrayXML, "PhasePoly"), antenna.antPattern[ii].array.phasePoly); - - // Parse Element - XMLElem elementXML = getFirstAndOnly(antPatternXMLVec[ii], "Element"); - mCommon.parsePoly2D(getFirstAndOnly(elementXML, "GainPoly"), antenna.antPattern[ii].element.gainPoly); - mCommon.parsePoly2D(getFirstAndOnly(elementXML, "PhasePoly"), antenna.antPattern[ii].element.phasePoly); - std::ignore = six::parse(parser(), *elementXML, antenna.antPattern[ii].element.antGPId); - - // Parse GainPhaseArray - std::vector gainPhaseArrayXMLVec; - antPatternXMLVec[ii]->getElementsByTagName("GainPhaseArray", gainPhaseArrayXMLVec); - antenna.antPattern[ii].gainPhaseArray.resize(gainPhaseArrayXMLVec.size()); - for (size_t jj = 0; jj < gainPhaseArrayXMLVec.size(); ++jj) - { - parseDouble(getFirstAndOnly(gainPhaseArrayXMLVec[jj], "Freq"), antenna.antPattern[ii].gainPhaseArray[jj].freq); - parseString(getFirstAndOnly(gainPhaseArrayXMLVec[jj], "ArrayId"), antenna.antPattern[ii].gainPhaseArray[jj].arrayId); - XMLElem elementIdXML = getOptional(gainPhaseArrayXMLVec[jj], "ElementId"); - if(elementIdXML) - { - parseString(elementIdXML, antenna.antPattern[ii].gainPhaseArray[jj].elementId); - } - - } - } -} - -void CPHDXMLParser::fromXML(const xml::lite::Element* txRcvXML, TxRcv& txRcv) -{ - size_t numTxWFs = 0; - size_t numRcvs = 0; - parseUInt(getFirstAndOnly(txRcvXML, "NumTxWFs"), numTxWFs); - txRcv.txWFParameters.resize(numTxWFs); - parseUInt(getFirstAndOnly(txRcvXML, "NumRcvs"), numRcvs); - txRcv.rcvParameters.resize(numRcvs); - - std::vector txWFXMLVec; - txRcvXML->getElementsByTagName("TxWFParameters", txWFXMLVec); - if(txRcv.txWFParameters.size() != txWFXMLVec.size()) - { - throw except::Exception(Ctxt( - "Incorrect number of TxWF parameters provided")); - } - for(size_t ii = 0; ii < txWFXMLVec.size(); ++ii) - { - parseTxRcvParameter(txWFXMLVec[ii], txRcv.txWFParameters[ii]); - parseDouble(getFirstAndOnly(txWFXMLVec[ii], "PulseLength"), txRcv.txWFParameters[ii].pulseLength); - parseDouble(getFirstAndOnly(txWFXMLVec[ii], "RFBandwidth"), txRcv.txWFParameters[ii].rfBandwidth); - parseOptionalDouble(txWFXMLVec[ii], "Power", txRcv.txWFParameters[ii].power); - } - - std::vector rcvXMLVec; - txRcvXML->getElementsByTagName("RcvParameters", rcvXMLVec); - if(txRcv.rcvParameters.size() != rcvXMLVec.size()) - { - throw except::Exception(Ctxt( - "Incorrect number of Rcv parameters provided")); - } - for(size_t ii = 0; ii < rcvXMLVec.size(); ++ii) - { - parseTxRcvParameter(rcvXMLVec[ii], txRcv.rcvParameters[ii]); - parseDouble(getFirstAndOnly(rcvXMLVec[ii], "WindowLength"), txRcv.rcvParameters[ii].windowLength); - parseDouble(getFirstAndOnly(rcvXMLVec[ii], "SampleRate"), txRcv.rcvParameters[ii].sampleRate); - parseDouble(getFirstAndOnly(rcvXMLVec[ii], "IFFilterBW"), txRcv.rcvParameters[ii].ifFilterBW); - parseOptionalDouble(rcvXMLVec[ii], "PathGain", txRcv.rcvParameters[ii].pathGain); - } - -} - -void CPHDXMLParser::fromXML(const xml::lite::Element* errParamXML, ErrorParameters& errParam) -{ - XMLElem monostaticXML = getOptional(errParamXML, "Monostatic"); - XMLElem bistaticXML = getOptional(errParamXML, "Bistatic"); - - if(monostaticXML && !bistaticXML) - { - errParam.monostatic.reset(new ErrorParameters::Monostatic()); - parsePosVelErr(getFirstAndOnly(monostaticXML, "PosVelErr"), errParam.monostatic->posVelErr); - - XMLElem radarSensorXML = getFirstAndOnly(monostaticXML, "RadarSensor"); - parseDouble(getFirstAndOnly(radarSensorXML, "RangeBias"), errParam.monostatic->radarSensor.rangeBias); - - parseOptionalDouble(radarSensorXML, "ClockFreqSF", errParam.monostatic->radarSensor.clockFreqSF); - parseOptionalDouble(radarSensorXML, "CollectionStartTime", errParam.monostatic->radarSensor.collectionStartTime); - - XMLElem rangeBiasDecorrXML = getOptional(radarSensorXML, "RangeBiasDecorr"); - if(rangeBiasDecorrXML) - { - errParam.monostatic->radarSensor.rangeBiasDecorr.reset(new six::DecorrType()); - mCommon.parseDecorrType(rangeBiasDecorrXML, *(errParam.monostatic->radarSensor.rangeBiasDecorr)); - } - - XMLElem tropoErrorXML = getOptional(monostaticXML, "TropoError"); - if(tropoErrorXML) - { - errParam.monostatic->tropoError.reset(new six::TropoError()); - parseOptionalDouble(tropoErrorXML, "TropoRangeVertical", errParam.monostatic->tropoError->tropoRangeVertical); - parseOptionalDouble(tropoErrorXML, "TropoRangeSlant", errParam.monostatic->tropoError->tropoRangeSlant); - mCommon.parseOptionalDecorrType(tropoErrorXML, "TropoRangeDecorr", errParam.monostatic->tropoError->tropoRangeDecorr); - } - - XMLElem ionoErrorXML = getOptional(monostaticXML, "IonoError"); - if(ionoErrorXML) - { - errParam.monostatic->ionoError.reset(new six::IonoError()); - parseDouble(getFirstAndOnly(ionoErrorXML, "IonoRangeVertical"), errParam.monostatic->ionoError->ionoRangeVertical); - - parseOptionalDouble(ionoErrorXML, "IonoRangeRateVertical", errParam.monostatic->ionoError->ionoRangeRateVertical); - parseOptionalDouble(ionoErrorXML, "IonoRgRgRateCC", errParam.monostatic->ionoError->ionoRgRgRateCC); - mCommon.parseOptionalDecorrType(ionoErrorXML, "IonoRangeVertDecorr", errParam.monostatic->ionoError->ionoRangeVertDecorr); - } - mCommon.parseParameters(monostaticXML, "Parameter", errParam.monostatic->parameter); - } - else if(!monostaticXML && bistaticXML) - { - errParam.bistatic.reset(new ErrorParameters::Bistatic()); - parsePlatform(getFirstAndOnly(bistaticXML, "TxPlatform"), errParam.bistatic->txPlatform); - parsePlatform(getFirstAndOnly(bistaticXML, "RcvPlatform"), errParam.bistatic->rcvPlatform); - mCommon.parseParameters(bistaticXML, "Parameter", errParam.bistatic->parameter); - } - else - { - throw except::Exception(Ctxt( - "Must be one of monostatic or bistatic")); - } -} - - -void CPHDXMLParser::fromXML(const xml::lite::Element* productInfoXML, ProductInfo& productInfo) -{ - XMLElem profileXML = getOptional(productInfoXML, "Profile"); - if(profileXML) - { - parseString(profileXML, productInfo.profile); - } - - std::vector creationInfoXML; - productInfoXML->getElementsByTagName("CreationInfo", creationInfoXML); - productInfo.creationInfo.resize(creationInfoXML.size()); - - for (size_t ii = 0; ii < creationInfoXML.size(); ++ii) - { - XMLElem applicationXML = getOptional(creationInfoXML[ii], "Application"); - if(applicationXML) - { - parseString(applicationXML, productInfo.creationInfo[ii].application); - } - - parseDateTime(getFirstAndOnly(creationInfoXML[ii], "DateTime"), productInfo.creationInfo[ii].dateTime); - - XMLElem siteXML = getOptional(creationInfoXML[ii], "Site"); - if(siteXML) - { - parseString(siteXML, productInfo.creationInfo[ii].site); - } - mCommon.parseParameters(creationInfoXML[ii], "Parameter", productInfo.creationInfo[ii].parameter); - } - mCommon.parseParameters(productInfoXML, "Parameter", productInfo.parameter); - -} - -void CPHDXMLParser::fromXML(const xml::lite::Element* geoInfoXML, GeoInfo& geoInfo) -{ - std::vector < XMLElem > geoInfosXML; - geoInfoXML->getElementsByTagName("GeoInfo", geoInfosXML); - geoInfo.name = geoInfoXML->getAttributes().getValue("name"); - - //optional - mCommon.parseParameters(geoInfoXML, "Desc", geoInfo.desc); - - XMLElem tmpElem = getOptional(geoInfoXML, "Point"); - if (tmpElem) - { - LatLon ll; - mCommon.parseLatLon(tmpElem, ll); - geoInfo.geometryLatLon.push_back(ll); - } - else - { - std::string pointName = "Endpoint"; - tmpElem = getOptional(geoInfoXML, "Line"); - if (!tmpElem) - { - pointName = "Vertex"; - tmpElem = getOptional(geoInfoXML, "Polygon"); - } - if (tmpElem) - { - mCommon.parseLatLons(tmpElem, pointName, geoInfo.geometryLatLon); - } - } - - //optional - size_t idx(geoInfo.geoInfos.size()); - geoInfo.geoInfos.resize(idx + geoInfosXML.size()); - - for (auto it = geoInfosXML.begin(); it - != geoInfosXML.end(); ++it, ++idx) - { - geoInfo.geoInfos[idx].reset(new GeoInfo()); - fromXML(*it, *geoInfo.geoInfos[idx]); - } -} - -void CPHDXMLParser::fromXML(const xml::lite::Element* matchInfoXML, MatchInformation& matchInfo) -{ - mCommon.parseMatchInformationFromXML(matchInfoXML, &matchInfo); -} - - -XMLElem CPHDXMLParser::createLatLonFootprint(const std::string& name, - const std::string& cornerName, - const cphd::LatLonCorners& corners, - XMLElem parent) const -{ - XMLElem footprint = newElement(name, parent); - - // Write the corners in CW order - XMLElem vertex = - mCommon.createLatLon(cornerName, corners.upperLeft, footprint); - setAttribute(vertex, "index", "1"); - - vertex = mCommon.createLatLon(cornerName, corners.upperRight, footprint); - setAttribute(vertex, "index", "2"); - - vertex = mCommon.createLatLon(cornerName, corners.lowerRight, footprint); - setAttribute(vertex, "index", "3"); - - vertex = mCommon.createLatLon(cornerName, corners.lowerLeft, footprint); - setAttribute(vertex, "index", "4"); - - return footprint; -} - -XMLElem CPHDXMLParser::createPVPType(const std::string& name, - const PVPType& p, - XMLElem parent) const -{ - XMLElem pvpXML = newElement(name, parent); - createInt("Offset", p.getOffset(), pvpXML); - createInt("Size", p.getSize(), pvpXML); - createString("Format", p.getFormat(), pvpXML); - return pvpXML; -} - -XMLElem CPHDXMLParser::createAPVPType(const std::string& name, - const APVPType& p, - XMLElem parent) const -{ - XMLElem apvpXML = newElement(name, parent); - createString("Name", p.getName(), apvpXML); - createInt("Offset", p.getOffset(), apvpXML); - createInt("Size", p.getSize(), apvpXML); - createString("Format", p.getFormat(), apvpXML); - return apvpXML; -} - -XMLElem CPHDXMLParser::createErrorParamPlatform( - const std::string& /*name*/, - const ErrorParameters::Bistatic::Platform p, - XMLElem parent) const -{ - XMLElem posVelErrXML = newElement("PosVelErr", parent); - createString("Frame", p.posVelErr.frame, posVelErrXML); - createDouble("P1", p.posVelErr.p1, posVelErrXML); - createDouble("P2", p.posVelErr.p2, posVelErrXML); - createDouble("P3", p.posVelErr.p3, posVelErrXML); - createDouble("V1", p.posVelErr.v1, posVelErrXML); - createDouble("V2", p.posVelErr.v2, posVelErrXML); - createDouble("V3", p.posVelErr.v3, posVelErrXML); - if(p.posVelErr.corrCoefs.get()) - { - XMLElem corrCoefsXML = newElement("CorrCoefs", posVelErrXML); - createDouble("P1P2", p.posVelErr.corrCoefs->p1p2, corrCoefsXML); - createDouble("P1P3", p.posVelErr.corrCoefs->p1p3, corrCoefsXML); - createDouble("P1V1", p.posVelErr.corrCoefs->p1v1, corrCoefsXML); - createDouble("P1V2", p.posVelErr.corrCoefs->p1v2, corrCoefsXML); - createDouble("P1V3", p.posVelErr.corrCoefs->p1v3, corrCoefsXML); - createDouble("P2P3", p.posVelErr.corrCoefs->p2p3, corrCoefsXML); - createDouble("P2V1", p.posVelErr.corrCoefs->p2v1, corrCoefsXML); - createDouble("P2V2", p.posVelErr.corrCoefs->p2v2, corrCoefsXML); - createDouble("P2V3", p.posVelErr.corrCoefs->p2v3, corrCoefsXML); - createDouble("P3V1", p.posVelErr.corrCoefs->p3v1, corrCoefsXML); - createDouble("P3V2", p.posVelErr.corrCoefs->p3v2, corrCoefsXML); - createDouble("P3V3", p.posVelErr.corrCoefs->p3v3, corrCoefsXML); - createDouble("V1V2", p.posVelErr.corrCoefs->v1v2, corrCoefsXML); - createDouble("V1V3", p.posVelErr.corrCoefs->v1v3, corrCoefsXML); - createDouble("V2V3", p.posVelErr.corrCoefs->v2v3, corrCoefsXML); - } - createDecorrType("PositionDecorr", p.posVelErr.positionDecorr, posVelErrXML); - return posVelErrXML; -} - -XMLElem CPHDXMLParser::createDecorrType(const std::string& name, const six::DecorrType& dt, - XMLElem parent) const -{ - if (six::Init::isDefined(dt)) - { - XMLElem element = newElement(name, parent); - createDouble("CorrCoefZero", dt.corrCoefZero, element); - createDouble("DecorrRate", dt.decorrRate, element); - return element; - } - return nullptr; -} -XMLElem CPHDXMLParser::createDecorrType(const std::string& name, const std::optional& dt, - XMLElem parent) const -{ - if (dt.has_value()) - { - return createDecorrType(name, *dt, parent); - } - return nullptr; -} - -/* - * Parser helper functions - */ -void CPHDXMLParser::parseAreaType(const xml::lite::Element* areaXML, AreaType& area) const -{ - mCommon.parseVector2D(getFirstAndOnly(areaXML, "X1Y1"), area.x1y1); - mCommon.parseVector2D(getFirstAndOnly(areaXML, "X2Y2"), area.x2y2); - const xml::lite::Element* polygonXML = getOptional(areaXML, "Polygon"); - if (polygonXML) - { - std::vector verticesXML; - polygonXML->getElementsByTagName("Vertex", verticesXML); - if (verticesXML.size() < 3) - { - throw except::Exception(Ctxt( - "Polygons must have at least 3 sides")); - } - area.polygon.resize(verticesXML.size()); - for (size_t ii = 0; ii < area.polygon.size(); ++ii) - { - Vector2& vertex = area.polygon[ii]; - const xml::lite::Element* vertexXML = verticesXML[ii]; - mCommon.parseVector2D(vertexXML, vertex); - } - } -} - -void CPHDXMLParser::parseLineSample(const xml::lite::Element* lsXML, LineSample& ls) const -{ - parseDouble(getFirstAndOnly(lsXML, "Line"), ls.line); - parseDouble(getFirstAndOnly(lsXML, "Sample"), ls.sample); -} - -void CPHDXMLParser::parseIAExtent(const xml::lite::Element* extentXML, - ImageAreaXExtent& extent) const -{ - parseDouble(getFirstAndOnly(extentXML, "LineSpacing"), - extent.lineSpacing); - parseInt(getFirstAndOnly(extentXML, "FirstLine"), - extent.firstLine); - parseUInt(getFirstAndOnly(extentXML, "NumLines"), - extent.numLines); -} - -void CPHDXMLParser::parseIAExtent(const xml::lite::Element* extentXML, - ImageAreaYExtent& extent) const -{ - parseDouble(getFirstAndOnly(extentXML, "SampleSpacing"), - extent.sampleSpacing); - parseInt(getFirstAndOnly(extentXML, "FirstSample"), - extent.firstSample); - parseUInt(getFirstAndOnly(extentXML, "NumSamples"), - extent.numSamples); -} - -void CPHDXMLParser::parseChannelParameters( - const xml::lite::Element* paramXML, ChannelParameter& param) const -{ - parseString(getFirstAndOnly(paramXML, "Identifier"), param.identifier); - parseUInt(getFirstAndOnly(paramXML, "RefVectorIndex"), param.refVectorIndex); - parseBooleanType(getFirstAndOnly(paramXML, "FXFixed"), param.fxFixed); - parseBooleanType(getFirstAndOnly(paramXML, "TOAFixed"), param.toaFixed); - parseBooleanType(getFirstAndOnly(paramXML, "SRPFixed"), param.srpFixed); - - XMLElem signalXML = getOptional(paramXML, "SignalNormal"); - if (signalXML) - { - parseBooleanType(signalXML, param.signalNormal); - } - - parseDouble(getFirstAndOnly(paramXML, "FxC"), param.fxC); - parseDouble(getFirstAndOnly(paramXML, "FxBW"), param.fxBW); - parseOptionalDouble(paramXML, "FxBWNoise", param.fxBWNoise); - parseDouble(getFirstAndOnly(paramXML, "TOASaved"), param.toaSaved); - - XMLElem toaExtendedXML = getOptional(paramXML, "TOAExtended"); - if(toaExtendedXML) - { - param.toaExtended.reset(new TOAExtended()); - parseDouble(getFirstAndOnly(toaExtendedXML, "TOAExtSaved"), param.toaExtended->toaExtSaved); - XMLElem lfmEclipseXML = getOptional(toaExtendedXML, "LFMEclipse"); - if(lfmEclipseXML) - { - param.toaExtended->lfmEclipse.reset(new TOAExtended::LFMEclipse()); - parseDouble(getFirstAndOnly(lfmEclipseXML, "FxEarlyLow"), param.toaExtended->lfmEclipse->fxEarlyLow); - parseDouble(getFirstAndOnly(lfmEclipseXML, "FxEarlyHigh"), param.toaExtended->lfmEclipse->fxEarlyHigh); - parseDouble(getFirstAndOnly(lfmEclipseXML, "FxLateLow"), param.toaExtended->lfmEclipse->fxLateLow); - parseDouble(getFirstAndOnly(lfmEclipseXML, "FxLateHigh"), param.toaExtended->lfmEclipse->fxLateHigh); - } - } - - XMLElem dwellTimesXML = getFirstAndOnly(paramXML, "DwellTimes"); - parseString(getFirstAndOnly(dwellTimesXML, "CODId"), param.dwellTimes.codId); - parseString(getFirstAndOnly(dwellTimesXML, "DwellId"), param.dwellTimes.dwellId); - std::ignore = six::parse(parser(), *dwellTimesXML, param.dwellTimes.dtaId); - std::ignore = six::parse(parser(), *dwellTimesXML, param.dwellTimes.useDTA); - - XMLElem imageAreaXML = getOptional(paramXML, "ImageArea"); - if(imageAreaXML) - { - parseAreaType(imageAreaXML, param.imageArea); - } - - XMLElem antennaXML = getOptional(paramXML, "Antenna"); - if(antennaXML) - { - param.antenna.reset(new ChannelParameter::Antenna()); - parseString(getFirstAndOnly(antennaXML, "TxAPCId"), param.antenna->txAPCId); - parseString(getFirstAndOnly(antennaXML, "TxAPATId"), param.antenna->txAPATId); - parseString(getFirstAndOnly(antennaXML, "RcvAPCId"), param.antenna->rcvAPCId); - parseString(getFirstAndOnly(antennaXML, "RcvAPATId"), param.antenna->rcvAPATId); - } - - XMLElem txRcvXML = getOptional(paramXML, "TxRcv"); - if(txRcvXML) - { - std::vector txWFIdXML; - txRcvXML->getElementsByTagName("TxWFId", txWFIdXML); - param.txRcv.reset(new ChannelParameter::TxRcv()); - param.txRcv->txWFId.resize(txWFIdXML.size()); - for(size_t ii = 0; ii < txWFIdXML.size(); ++ii) - { - parseString(txWFIdXML[ii], param.txRcv->txWFId[ii]); - } - - std::vector rcvIdXML; - txRcvXML->getElementsByTagName("RcvId", rcvIdXML); - param.txRcv->rcvId.resize(rcvIdXML.size()); - for(size_t ii = 0; ii < rcvIdXML.size(); ++ii) - { - parseString(rcvIdXML[ii], param.txRcv->rcvId[ii]); - } - } - - XMLElem tgtRefLevelXML = getOptional(paramXML, "TgtRefLevel"); - if(tgtRefLevelXML) - { - param.tgtRefLevel.reset(new TgtRefLevel()); - parseDouble(getFirstAndOnly(tgtRefLevelXML, "PTRef"), param.tgtRefLevel->ptRef); - } - - XMLElem noiseLevelXML = getOptional(paramXML, "NoiseLevel"); - if(noiseLevelXML) - { - param.noiseLevel.reset(new NoiseLevel()); - parseDouble(getFirstAndOnly(noiseLevelXML, "PNRef"), param.noiseLevel->pnRef); - parseDouble(getFirstAndOnly(noiseLevelXML, "BNRef"), param.noiseLevel->bnRef); - if(!(param.noiseLevel->bnRef > 0 && param.noiseLevel->bnRef <= 1)) - { - throw except::Exception(Ctxt( - "Noise equivalent BW value must be > 0.0 and <= 1.0")); - } - - XMLElem fxNoiseProfileXML = getOptional(noiseLevelXML, "FxNoiseProfile"); - if(fxNoiseProfileXML) - { - param.noiseLevel->fxNoiseProfile.reset(new FxNoiseProfile()); - std::vector pointXMLVec; - fxNoiseProfileXML->getElementsByTagName("Point", pointXMLVec); - if(pointXMLVec.size() < 2) - { - throw except::Exception(Ctxt( - "Atleast 2 noise profile points must be provided")); - } - param.noiseLevel->fxNoiseProfile->point.resize(pointXMLVec.size()); - double prevPoint = six::Init::undefined(); - for(size_t ii = 0; ii < pointXMLVec.size(); ++ii) - { - double fx; - parseDouble(getFirstAndOnly(pointXMLVec[ii], "Fx"), fx); - parseDouble(getFirstAndOnly(pointXMLVec[ii], "PN"), param.noiseLevel->fxNoiseProfile->point[ii].pn); - - if(!six::Init::isUndefined(prevPoint) && fx <= prevPoint) - { - throw except::Exception(Ctxt( - "Fx values are strictly increasing")); - } - param.noiseLevel->fxNoiseProfile->point[ii].fx = fx; - prevPoint = fx; - } - } - } - - // Polarization - parsePolarization(*paramXML, param.polarization); -} - -void CPHDXMLParser::parse(const xml::lite::Element& polarizationXML, six::XsElement_minOccurs0& o) const -{ - if (const auto pXML = getOptional(polarizationXML, o.tag())) - { - o = PolRef{}; - six::getFirstAndOnly(parser(), *pXML, value(o).ampH); - six::getFirstAndOnly(parser(), *pXML, value(o).ampV); - six::getFirstAndOnly(parser(), *pXML, value(o).phaseV); - } -} - -void CPHDXMLParser::parsePolarization(const xml::lite::Element& paramXML, Polarization& polarization) const -{ - std::vector PolarizationXML; - paramXML.getElementsByTagName("Polarization", PolarizationXML); - for (size_t ii = 0; ii < PolarizationXML.size(); ++ii) - { - const xml::lite::Element* TxPolXML = getFirstAndOnly(PolarizationXML[ii], "TxPol"); - polarization.txPol = PolarizationType::toType(TxPolXML->getCharacterData()); - - const xml::lite::Element* RcvPolXML = getFirstAndOnly(PolarizationXML[ii], "RcvPol"); - polarization.rcvPol = PolarizationType::toType(RcvPolXML->getCharacterData()); - - parse(*(PolarizationXML[ii]), polarization.txPolRef); // added in CPHD 1.1.0 - parse(*(PolarizationXML[ii]), polarization.rcvPolRef); // added in CPHD 1.1.0 - } -} - -size_t CPHDXMLParser::parsePVPType(const xml::lite::Element& paramXML, PVPType& param) const -{ - size_t size; - size_t offset; - std::string format; - parseUInt(getFirstAndOnly(paramXML, "Size"), size); - parseUInt(getFirstAndOnly(paramXML, "Offset"), offset); - parseString(getFirstAndOnly(paramXML, "Format"), format); - if (param.getSize() != size) - { - std::ostringstream ostr; - ostr << "Specified size: " << size << " does not match default size: " << param.getSize(); - throw except::Exception(Ctxt(ostr.str())); - } - if (param.getFormat() != format) - { - std::ostringstream ostr; - ostr << "Specified format: " << format << " does not match default format: " << param.getFormat(); - throw except::Exception(Ctxt(ostr.str())); - } - return offset; -} -void CPHDXMLParser::parsePVPType(Pvp& pvp, const xml::lite::Element* paramXML, PVPType& param) const -{ - const auto offset = parsePVPType(*paramXML, param); - pvp.setOffset(offset, param); -} - -void CPHDXMLParser::parsePVPType(Pvp& pvp, const xml::lite::Element* paramXML) const -{ - std::string name; - size_t size; - size_t offset; - std::string format; - parseString(getFirstAndOnly(paramXML, "Name"), name); - parseUInt(getFirstAndOnly(paramXML, "Size"), size); - parseUInt(getFirstAndOnly(paramXML, "Offset"), offset); - parseString(getFirstAndOnly(paramXML, "Format"), format); - pvp.setCustomParameter(size, offset, format, name); -} - -bool CPHDXMLParser::parseOptionalPVPType(const xml::lite::Element* parent, const std::string& tag, Pvp& pvp, PVPType& param) const -{ - if (const xml::lite::Element* const element = getOptional(parent, tag)) - { - parsePVPType(pvp, element, param); - return true; - } - return false; -} - -void CPHDXMLParser::parsePlatformParams(const xml::lite::Element* platXML, Bistatic::PlatformParams& plat) const -{ - parseDouble(getFirstAndOnly(platXML, "Time"), plat.time); - parseDouble(getFirstAndOnly(platXML, "SlantRange"), plat.slantRange); - parseDouble(getFirstAndOnly(platXML, "GroundRange"), plat.groundRange); - parseDouble(getFirstAndOnly(platXML, "DopplerConeAngle"), plat.dopplerConeAngle); - parseDouble(getFirstAndOnly(platXML, "AzimuthAngle"), plat.azimuthAngle); - parseDouble(getFirstAndOnly(platXML, "GrazeAngle"), plat.grazeAngle); - parseDouble(getFirstAndOnly(platXML, "IncidenceAngle"), plat.incidenceAngle); - mCommon.parseVector3D(getFirstAndOnly(platXML, "Pos"), plat.pos); - mCommon.parseVector3D(getFirstAndOnly(platXML, "Vel"), plat.vel); - std::string side = ""; - parseString(getFirstAndOnly(platXML, "SideOfTrack"), side); - plat.sideOfTrack = (side == "L" ? six::SideOfTrackType::LEFT : six::SideOfTrackType::RIGHT); - -} - -void CPHDXMLParser::parseCommon(const xml::lite::Element* imgTypeXML, ImagingType* imgType) const -{ - parseDouble(getFirstAndOnly(imgTypeXML, "TwistAngle"), imgType->twistAngle); - parseDouble(getFirstAndOnly(imgTypeXML, "SlopeAngle"), imgType->slopeAngle); - parseDouble(getFirstAndOnly(imgTypeXML, "LayoverAngle"), imgType->layoverAngle); - parseDouble(getFirstAndOnly(imgTypeXML, "AzimuthAngle"), imgType->azimuthAngle); - parseDouble(getFirstAndOnly(imgTypeXML, "GrazeAngle"), imgType->grazeAngle); -} - -void CPHDXMLParser::parsePosVelErr(const xml::lite::Element* posVelErrXML, six::PosVelError& posVelErr) const -{ - std::string frameStr; - parseString(getFirstAndOnly(posVelErrXML, "Frame"), frameStr); - posVelErr.frame.mValue = scene::FrameType::fromString(frameStr); - parseDouble(getFirstAndOnly(posVelErrXML, "P1"), posVelErr.p1); - parseDouble(getFirstAndOnly(posVelErrXML, "P2"), posVelErr.p2); - parseDouble(getFirstAndOnly(posVelErrXML, "P3"), posVelErr.p3); - parseDouble(getFirstAndOnly(posVelErrXML, "V1"), posVelErr.v1); - parseDouble(getFirstAndOnly(posVelErrXML, "V2"), posVelErr.v2); - parseDouble(getFirstAndOnly(posVelErrXML, "V3"), posVelErr.v3); - - XMLElem corrCoefsXML = getOptional(posVelErrXML, "CorrCoefs"); - - if(corrCoefsXML) - { - posVelErr.corrCoefs.reset(new six::CorrCoefs()); - parseDouble(getFirstAndOnly(corrCoefsXML, "P1P2"), posVelErr.corrCoefs->p1p2); - parseDouble(getFirstAndOnly(corrCoefsXML, "P1P3"), posVelErr.corrCoefs->p1p3); - parseDouble(getFirstAndOnly(corrCoefsXML, "P1V1"), posVelErr.corrCoefs->p1v1); - parseDouble(getFirstAndOnly(corrCoefsXML, "P1V2"), posVelErr.corrCoefs->p1v2); - parseDouble(getFirstAndOnly(corrCoefsXML, "P1V3"), posVelErr.corrCoefs->p1v3); - parseDouble(getFirstAndOnly(corrCoefsXML, "P2P3"), posVelErr.corrCoefs->p2p3); - parseDouble(getFirstAndOnly(corrCoefsXML, "P2V1"), posVelErr.corrCoefs->p2v1); - parseDouble(getFirstAndOnly(corrCoefsXML, "P2V2"), posVelErr.corrCoefs->p2v2); - parseDouble(getFirstAndOnly(corrCoefsXML, "P2V3"), posVelErr.corrCoefs->p2v3); - parseDouble(getFirstAndOnly(corrCoefsXML, "P3V1"), posVelErr.corrCoefs->p3v1); - parseDouble(getFirstAndOnly(corrCoefsXML, "P3V2"), posVelErr.corrCoefs->p3v2); - parseDouble(getFirstAndOnly(corrCoefsXML, "P3V3"), posVelErr.corrCoefs->p3v3); - parseDouble(getFirstAndOnly(corrCoefsXML, "V1V2"), posVelErr.corrCoefs->v1v2); - parseDouble(getFirstAndOnly(corrCoefsXML, "V1V3"), posVelErr.corrCoefs->v1v3); - parseDouble(getFirstAndOnly(corrCoefsXML, "V2V3"), posVelErr.corrCoefs->v2v3); - } - - // posVelErr.positionDecorr.reset(new six::DecorrType()); - mCommon.parseOptionalDecorrType(posVelErrXML, "PositionDecorr", posVelErr.positionDecorr); -} - -void CPHDXMLParser::parsePlatform(const xml::lite::Element* platXML, ErrorParameters::Bistatic::Platform& plat) const -{ - parsePosVelErr(getFirstAndOnly(platXML, "PosVelErr"), plat.posVelErr); - XMLElem radarSensorXML = getFirstAndOnly(platXML, "RadarSensor"); - six::parse(parser(), *radarSensorXML, plat.radarSensor.delayBias); - parseOptionalDouble(radarSensorXML, "ClockFreqSF", plat.radarSensor.clockFreqSF); - parseDouble(getFirstAndOnly(radarSensorXML, "CollectionStartTime"), plat.radarSensor.collectionStartTime); -} - -void CPHDXMLParser::parseSupportArrayParameter(const xml::lite::Element* paramXML, SupportArrayParameter& param, bool additionalFlag) const -{ - if(!additionalFlag) - { - size_t identifierVal; - parseUInt(getFirstAndOnly(paramXML, "Identifier"), identifierVal); - param.setIdentifier(identifierVal); - } - parseString(getFirstAndOnly(paramXML, "ElementFormat"), param.elementFormat); - parseDouble(getFirstAndOnly(paramXML, "X0"), param.x0); - parseDouble(getFirstAndOnly(paramXML, "Y0"), param.y0); - parseDouble(getFirstAndOnly(paramXML, "XSS"), param.xSS); - parseDouble(getFirstAndOnly(paramXML, "YSS"), param.ySS); -} - -void CPHDXMLParser::parseTxRcvParameter(const xml::lite::Element* paramXML, ParameterType& param) const -{ - parseString(getFirstAndOnly(paramXML, "Identifier"), param.identifier); - parseDouble(getFirstAndOnly(paramXML, "FreqCenter"), param.freqCenter); - parseOptionalDouble(paramXML, "LFMRate", param.lfmRate); - param.polarization = PolarizationType::toType(getFirstAndOnly(paramXML, "Polarization")->getCharacterData()); -} -} +/* ========================================================================= + * This file is part of cphd-c++ + * ========================================================================= + * + * (C) Copyright 2004 - 2019, MDA Information Systems LLC + * + * cphd-c++ is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; If not, + * see . + * + */ +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define ENFORCESPEC 0 + +namespace +{ +typedef xml::lite::Element* XMLElem; +} + +namespace cphd +{ + +CPHDXMLParser::CPHDXMLParser( + const std::string& uri, + bool addClassAttributes, + logging::Logger* log, + bool ownLog) : + six::XMLParser(uri, addClassAttributes, log, ownLog), + mCommon(getDefaultURI(), addClassAttributes, getDefaultURI(), log) +{ +} + +/* + * TO XML + */ +std::unique_ptr CPHDXMLParser::toXML( + const Metadata& metadata) +{ + std::unique_ptr doc(new xml::lite::Document()); + + XMLElem root = newElement("CPHD"); + doc->setRootElement(root); + + toXML(metadata.collectionID, root); + toXML(metadata.global, root); + toXML(metadata.sceneCoordinates, root); + toXML(metadata.data, root); + toXML(metadata.channel, root); + toXML(metadata.pvp, root); + toXML(metadata.dwell, root); + toXML(metadata.referenceGeometry, root); + + if (metadata.supportArray.get()) + { + toXML(*(metadata.supportArray), root); + } + if (metadata.antenna.get()) + { + toXML(*(metadata.antenna), root); + } + if (metadata.txRcv.get()) + { + toXML(*(metadata.txRcv), root); + } + if (metadata.errorParameters.get()) + { + toXML(*(metadata.errorParameters), root); + } + if (metadata.productInfo.get()) + { + toXML(*(metadata.productInfo), root); + } + for (const auto& geoInfo : metadata.geoInfo) + { + toXML(geoInfo, root); + } + if (metadata.matchInfo.get()) + { + toXML(*(metadata.matchInfo), root); + } + + //set the XMLNS + root->setNamespacePrefix("", getDefaultURI()); + + return doc; +} + +XMLElem CPHDXMLParser::toXML(const CollectionInformation& collectionID, XMLElem parent) +{ + XMLElem collectionXML = newElement("CollectionID", parent); + + createString("CollectorName", collectionID.collectorName, collectionXML); + if(!six::Init::isUndefined(collectionID.illuminatorName)) + { + createString("IlluminatorName", collectionID.illuminatorName, collectionXML); + } + createString("CoreName", collectionID.coreName, collectionXML); + createString("CollectType", collectionID.collectType, collectionXML); + + // RadarMode + XMLElem radarModeXML = newElement("RadarMode", collectionXML); + createSixString("ModeType", collectionID.radarMode, radarModeXML); + if(!six::Init::isUndefined(collectionID.radarModeID)) + { + createString("ModeID", collectionID.radarModeID, radarModeXML); + } + createString("Classification", collectionID.getClassificationLevel(), collectionXML); + createString("ReleaseInfo", collectionID.releaseInfo, collectionXML); + if (!collectionID.countryCodes.empty()) + { + std::string countryCodes = str::join(collectionID.countryCodes, ","); + createString("CountryCode", countryCodes, collectionXML); + } + mCommon.addParameters("Parameter", getDefaultURI(), collectionID.parameters, collectionXML); + return collectionXML; +} + +XMLElem CPHDXMLParser::toXML(const Global& global, XMLElem parent) +{ + XMLElem globalXML = newElement("Global", parent); + createString("DomainType", global.domainType, globalXML); + createString("SGN", global.sgn, globalXML); + + //Timeline + XMLElem timelineXML = newElement("Timeline", globalXML); + createDateTime("CollectionStart", global.timeline.collectionStart, timelineXML); + if (!six::Init::isUndefined(global.timeline.rcvCollectionStart)) + { + createDateTime("RcvCollectionStart", global.timeline.rcvCollectionStart, timelineXML); + } + createDouble("TxTime1", global.timeline.txTime1, timelineXML); + createDouble("TxTime2", global.timeline.txTime2, timelineXML); + + XMLElem fxBandXML = newElement("FxBand", globalXML); + createDouble("FxMin", global.fxBand.fxMin, fxBandXML); + createDouble("FxMax", global.fxBand.fxMax, fxBandXML); + + XMLElem toaSwathXML = newElement("TOASwath", globalXML); + createDouble("TOAMin", global.toaSwath.toaMin, toaSwathXML); + createDouble("TOAMax", global.toaSwath.toaMax, toaSwathXML); + + if (global.tropoParameters.get()) + { + XMLElem tropoXML = newElement("TropoParameters", globalXML); + createDouble("N0", global.tropoParameters->n0, tropoXML); + createString("RefHeight", global.tropoParameters->refHeight, tropoXML); + } + if (global.ionoParameters.get()) + { + XMLElem ionoXML = newElement("IonoParameters", globalXML); + createDouble("TECV", global.ionoParameters->tecv, ionoXML); + createOptionalDouble("F2Height", global.ionoParameters->f2Height, ionoXML); + } + return globalXML; +} + +XMLElem CPHDXMLParser::toXML(const SceneCoordinates& sceneCoords, XMLElem parent) +{ + XMLElem sceneCoordsXML = newElement("SceneCoordinates", parent); + createString("EarthModel", sceneCoords.earthModel, sceneCoordsXML); + + XMLElem iarpXML = newElement("IARP", sceneCoordsXML); + mCommon.createVector3D("ECF", sceneCoords.iarp.ecf, iarpXML); + mCommon.createLatLonAlt("LLH", sceneCoords.iarp.llh, iarpXML); + + XMLElem refSurfXML = newElement("ReferenceSurface", sceneCoordsXML); + if (sceneCoords.referenceSurface.planar.get()) + { + XMLElem planarXML = newElement("Planar", refSurfXML); + mCommon.createVector3D("uIAX", sceneCoords.referenceSurface.planar->uIax, planarXML); + mCommon.createVector3D("uIAY", sceneCoords.referenceSurface.planar->uIay, planarXML); + } + else if (sceneCoords.referenceSurface.hae.get()) + { + XMLElem haeXML = newElement("HAE", refSurfXML); + mCommon.createLatLon("uIAXLL", sceneCoords.referenceSurface.hae->uIax, haeXML); + mCommon.createLatLon("uIAYLL", sceneCoords.referenceSurface.hae->uIay, haeXML); + } + else + { + throw except::Exception(Ctxt( + "Reference Surface must be one of two types")); + } + + XMLElem imageAreaXML = newElement("ImageArea", sceneCoordsXML); + mCommon.createVector2D("X1Y1", sceneCoords.imageArea.x1y1, imageAreaXML); + mCommon.createVector2D("X2Y2", sceneCoords.imageArea.x2y2, imageAreaXML); + + if (!sceneCoords.imageArea.polygon.empty()) + { + XMLElem polygonXML = newElement("Polygon", imageAreaXML); + setAttribute(polygonXML, "size", sceneCoords.imageArea.polygon.size()); + for (size_t ii = 0; ii < sceneCoords.imageArea.polygon.size(); ++ii) + { + XMLElem vertexXML = mCommon.createVector2D("Vertex", sceneCoords.imageArea.polygon[ii], polygonXML); + setAttribute(vertexXML, "index", ii+1); + } + } + createLatLonFootprint("ImageAreaCornerPoints", "IACP", sceneCoords.imageAreaCorners, sceneCoordsXML); + + // Extended Area (Optional) + if(sceneCoords.extendedArea.get()) + { + XMLElem extendedAreaXML = newElement("ExtendedArea", sceneCoordsXML); + mCommon.createVector2D("X1Y1", sceneCoords.extendedArea->x1y1, extendedAreaXML); + mCommon.createVector2D("X2Y2", sceneCoords.extendedArea->x2y2, extendedAreaXML); + + if (!sceneCoords.extendedArea->polygon.empty()) + { + XMLElem polygonXML = newElement("Polygon", sceneCoordsXML); + setAttribute(polygonXML, "size", sceneCoords.extendedArea->polygon.size()); + for (size_t ii = 0; ii < sceneCoords.extendedArea->polygon.size(); ++ii) + { + XMLElem vertexXML = mCommon.createVector2D("Vertex", sceneCoords.extendedArea->polygon[ii], polygonXML); + setAttribute(vertexXML, "index", ii+1); + } + } + } + + // ImageGrid (Optional) + if(sceneCoords.imageGrid.get()) + { + XMLElem imageGridXML = newElement("ImageGrid", sceneCoordsXML); + if(!six::Init::isUndefined(sceneCoords.imageGrid->identifier)) + { + createString("Identifier", sceneCoords.imageGrid->identifier, imageGridXML); + } + XMLElem iarpLocationXML = newElement("IARPLocation", imageGridXML); + createDouble("Line", sceneCoords.imageGrid->iarpLocation.line, iarpLocationXML); + createDouble("Sample", sceneCoords.imageGrid->iarpLocation.sample, iarpLocationXML); + + XMLElem iaxExtentXML = newElement("IAXExtent", imageGridXML); + createDouble("LineSpacing", sceneCoords.imageGrid->xExtent.lineSpacing, iaxExtentXML); + createInt("FirstLine", sceneCoords.imageGrid->xExtent.firstLine, iaxExtentXML); + createInt("NumLines", sceneCoords.imageGrid->xExtent.numLines, iaxExtentXML); + + XMLElem iayExtentXML = newElement("IAYExtent", imageGridXML); + createDouble("SampleSpacing", sceneCoords.imageGrid->yExtent.sampleSpacing, iayExtentXML); + createInt("FirstSample", sceneCoords.imageGrid->yExtent.firstSample, iayExtentXML); + createInt("NumSamples", sceneCoords.imageGrid->yExtent.numSamples, iayExtentXML); + + if (!sceneCoords.imageGrid->segments.empty()) + { + XMLElem segmentListXML = newElement("SegmentList", imageGridXML); + createInt("NumSegments", sceneCoords.imageGrid->segments.size(), segmentListXML); + + for (size_t ii = 0; ii < sceneCoords.imageGrid->segments.size(); ++ii) + { + XMLElem segmentXML = newElement("Segment", segmentListXML); + createString("Identifier", sceneCoords.imageGrid->segments[ii].identifier, segmentXML); + createInt("StartLine", sceneCoords.imageGrid->segments[ii].startLine, segmentXML); + createInt("StartSample", sceneCoords.imageGrid->segments[ii].startSample, segmentXML); + createInt("EndLine", sceneCoords.imageGrid->segments[ii].endLine, segmentXML); + createInt("EndSample", sceneCoords.imageGrid->segments[ii].endSample, segmentXML); + + if (!sceneCoords.imageGrid->segments[ii].polygon.empty()) + { + XMLElem polygonXML = newElement("SegmentPolygon", segmentXML); + setAttribute(polygonXML, "size", sceneCoords.imageGrid->segments[ii].polygon.size()); + for (size_t jj = 0; jj < sceneCoords.imageGrid->segments[ii].polygon.size(); ++jj) + { + XMLElem svXML = newElement("SV", polygonXML); + setAttribute(svXML, "index", sceneCoords.imageGrid->segments[ii].polygon[jj].getIndex()); + createDouble("Line", sceneCoords.imageGrid->segments[ii].polygon[jj].line, svXML); + createDouble("Sample", sceneCoords.imageGrid->segments[ii].polygon[jj].sample, svXML); + } + } + } + } + } + return sceneCoordsXML; +} + +XMLElem CPHDXMLParser::toXML(const Data& data, XMLElem parent) +{ + XMLElem dataXML = newElement("Data", parent); + createString("SignalArrayFormat", data.signalArrayFormat, dataXML); + createInt("NumBytesPVP", data.numBytesPVP, dataXML); + createInt("NumCPHDChannels", data.channels.size(), dataXML); + if (!six::Init::isUndefined(data.signalCompressionID)) + { + createString("SignalCompressionID", data.signalCompressionID, dataXML); + } + + for (size_t ii = 0; ii < data.channels.size(); ++ii) + { + XMLElem channelXML = newElement("Channel", dataXML); + createString("Identifier", data.channels[ii].identifier, channelXML); + createInt("NumVectors", data.channels[ii].numVectors, channelXML); + createInt("NumSamples", data.channels[ii].numSamples, channelXML); + createInt("SignalArrayByteOffset", data.channels[ii].signalArrayByteOffset, channelXML); + createInt("PVPArrayByteOffset", data.channels[ii].pvpArrayByteOffset, channelXML); + if(!six::Init::isUndefined(data.channels[ii].compressedSignalSize)) + { + createInt("CompressedSignalSize", data.channels[ii].compressedSignalSize, channelXML); + } + } + createInt("NumSupportArrays", data.supportArrayMap.size(), dataXML); + for (const auto& entry : data.supportArrayMap) + { + XMLElem supportArrayXML = newElement("SupportArray", dataXML); + createString("Identifier", entry.second.identifier, supportArrayXML); + createInt("NumRows", entry.second.numRows, supportArrayXML); + createInt("NumCols", entry.second.numCols, supportArrayXML); + createInt("BytesPerElement", entry.second.bytesPerElement, supportArrayXML); + createInt("ArrayByteOffset", entry.second.arrayByteOffset, supportArrayXML); + } + return dataXML; +} + +XMLElem CPHDXMLParser::toXML(const six::XsElement_minOccurs0& o, xml::lite::Element& parent) +{ + XMLElem pXML = nullptr; + if (has_value(o)) + { + pXML = newElement(o.tag(), &parent); + std::ignore = create(parser(), value(o).ampH, *pXML); + std::ignore = create(parser(), value(o).ampV, *pXML); + std::ignore = create(parser(), value(o).phaseV, *pXML); + } + + return pXML; +} + +XMLElem CPHDXMLParser::toXML(const Polarization& obj, xml::lite::Element& parent) +{ + auto polXML = newElement("Polarization", &parent); + createString("TxPol", obj.txPol, polXML); + createString("RcvPol", obj.rcvPol, polXML); + + toXML(obj.txPolRef, *polXML); // added in CPHD 1.1.0 + toXML(obj.rcvPolRef, *polXML); // added in CPHD 1.1.0 + + return polXML; +} + +XMLElem CPHDXMLParser::toXML(const Channel& channel, XMLElem parent) +{ + XMLElem channelXML = newElement("Channel", parent); + createString("RefChId", channel.refChId, channelXML); + createBooleanType("FXFixedCPHD", channel.fxFixedCphd, channelXML); + createBooleanType("TOAFixedCPHD", channel.toaFixedCphd, channelXML); + createBooleanType("SRPFixedCPHD", channel.srpFixedCphd, channelXML); + + for (size_t ii = 0; ii < channel.parameters.size(); ++ii) + { + XMLElem parametersXML = newElement("Parameters", channelXML); + createString("Identifier", channel.parameters[ii].identifier, parametersXML); + createInt("RefVectorIndex", channel.parameters[ii].refVectorIndex, parametersXML); + createBooleanType("FXFixed", channel.parameters[ii].fxFixed, parametersXML); + createBooleanType("TOAFixed", channel.parameters[ii].toaFixed, parametersXML); + createBooleanType("SRPFixed", channel.parameters[ii].srpFixed, parametersXML); + if (!six::Init::isUndefined(channel.parameters[ii].signalNormal)) + { + createBooleanType("SignalNormal", channel.parameters[ii].signalNormal, parametersXML); + } + std::ignore = toXML(channel.parameters[ii].polarization, *parametersXML); + + createDouble("FxC", channel.parameters[ii].fxC, parametersXML); + createDouble("FxBW", channel.parameters[ii].fxBW, parametersXML); + createOptionalDouble("FxBWNoise", channel.parameters[ii].fxBWNoise, parametersXML); + createDouble("TOASaved", channel.parameters[ii].toaSaved, parametersXML); + + if(channel.parameters[ii].toaExtended.get()) + { + XMLElem toaExtendedXML = newElement("TOAExtended", parametersXML); + createDouble("TOAExtSaved", channel.parameters[ii].toaExtended->toaExtSaved, toaExtendedXML); + if(channel.parameters[ii].toaExtended->lfmEclipse.get()) + { + XMLElem lfmEclipseXML = newElement("LFMEclipse", toaExtendedXML); + createDouble("FxEarlyLow", channel.parameters[ii].toaExtended->lfmEclipse->fxEarlyLow, lfmEclipseXML); + createDouble("FxEarlyHigh", channel.parameters[ii].toaExtended->lfmEclipse->fxEarlyHigh, lfmEclipseXML); + createDouble("FxLateLow", channel.parameters[ii].toaExtended->lfmEclipse->fxLateLow, lfmEclipseXML); + createDouble("FxLateHigh", channel.parameters[ii].toaExtended->lfmEclipse->fxLateHigh, lfmEclipseXML); + } + } + XMLElem dwellTimesXML = newElement("DwellTimes", parametersXML); + createString("CODId", channel.parameters[ii].dwellTimes.codId, dwellTimesXML); + createString("DwellId", channel.parameters[ii].dwellTimes.dwellId, dwellTimesXML); + std::ignore = create(parser(), channel.parameters[ii].dwellTimes.dtaId, *dwellTimesXML); + std::ignore = create(parser(), channel.parameters[ii].dwellTimes.useDTA, *dwellTimesXML); + + if(!six::Init::isUndefined(channel.parameters[ii].imageArea)) + { + XMLElem imageAreaXML = newElement("ImageArea", parametersXML); + mCommon.createVector2D("X1Y1", channel.parameters[ii].imageArea.x1y1, imageAreaXML); + mCommon.createVector2D("X2Y2", channel.parameters[ii].imageArea.x2y2, imageAreaXML); + if(!channel.parameters[ii].imageArea.polygon.empty()) + { + XMLElem polygonXML = newElement("Polygon", imageAreaXML); + setAttribute(polygonXML, "size", channel.parameters[ii].imageArea.polygon.size()); + for (size_t jj = 0; jj < channel.parameters[ii].imageArea.polygon.size(); ++jj) + { + XMLElem vertexXML = mCommon.createVector2D("Vertex", channel.parameters[ii].imageArea.polygon[jj], polygonXML); + setAttribute(vertexXML, "index", jj+1); + } + } + } + if(channel.parameters[ii].antenna.get()) + { + XMLElem antennaXML = newElement("Antenna", parametersXML); + createString("TxAPCId", channel.parameters[ii].antenna->txAPCId, antennaXML); + createString("TxAPATId", channel.parameters[ii].antenna->txAPATId, antennaXML); + createString("RcvAPCId", channel.parameters[ii].antenna->rcvAPCId, antennaXML); + createString("RcvAPATId", channel.parameters[ii].antenna->rcvAPATId, antennaXML); + } + if(channel.parameters[ii].txRcv.get()) + { + XMLElem txRcvXML = newElement("TxRcv", parametersXML); + for (size_t jj = 0; jj < channel.parameters[ii].txRcv->txWFId.size(); ++jj) + { + createString("TxWFId", channel.parameters[ii].txRcv->txWFId[jj], txRcvXML); + } + for (size_t jj = 0; jj < channel.parameters[ii].txRcv->rcvId.size(); ++jj) + { + createString("RcvId", channel.parameters[ii].txRcv->rcvId[jj], txRcvXML); + } + } + if(channel.parameters[ii].tgtRefLevel.get()) + { + XMLElem tgtRefXML = newElement("TgtRefLevel", parametersXML); + createDouble("PTRef", channel.parameters[ii].tgtRefLevel->ptRef, tgtRefXML); + } + if(channel.parameters[ii].noiseLevel.get()) + { + XMLElem noiseLevelXML = newElement("NoiseLevel", parametersXML); + createDouble("PNRef", channel.parameters[ii].noiseLevel->pnRef, noiseLevelXML); + createDouble("BNRef", channel.parameters[ii].noiseLevel->bnRef, noiseLevelXML); + if(channel.parameters[ii].noiseLevel->fxNoiseProfile.get()) + { + XMLElem fxNoiseProfileXML = newElement("FxNoiseProfile", noiseLevelXML); + for (size_t jj = 0; jj < channel.parameters[ii].noiseLevel->fxNoiseProfile->point.size(); ++jj) + { + XMLElem pointXML = newElement("Point", fxNoiseProfileXML); + createDouble("Fx", channel.parameters[ii].noiseLevel->fxNoiseProfile->point[jj].fx, pointXML); + createDouble("PN", channel.parameters[ii].noiseLevel->fxNoiseProfile->point[jj].pn, pointXML); + } + } + } + } + if(!channel.addedParameters.empty()) + { + XMLElem addedParamsXML = newElement("AddedParameters", channelXML); + mCommon.addParameters("Parameter", getDefaultURI(), channel.addedParameters, addedParamsXML); + } + return channelXML; +} + +XMLElem CPHDXMLParser::toXML(const six::XsElement& v, xml::lite::Element& parent) +{ + return createPVPType(v.tag(), v.value().param, &parent); +} +XMLElem CPHDXMLParser::toXML(const six::XsElement& v, xml::lite::Element& parent) +{ + return createPVPType(v.tag(), v.value().param, &parent); +} + +XMLElem CPHDXMLParser::toXML(const six::XsElement_minOccurs0& o, xml::lite::Element& parent) +{ + XMLElem pXML = nullptr; + if (has_value(o)) + { + pXML = newElement(o.tag(), &parent); + std::ignore = toXML(value(o).txACX, *pXML); + std::ignore = toXML(value(o).txACY, *pXML); + std::ignore = toXML(value(o).txEB, *pXML); + } + + return pXML; +} + +XMLElem CPHDXMLParser::toXML(const six::XsElement_minOccurs0& o, xml::lite::Element& parent) +{ + XMLElem pXML = nullptr; + if (has_value(o)) + { + pXML = newElement(o.tag(), &parent); + std::ignore = toXML(value(o).rcvACX, *pXML); + std::ignore = toXML(value(o).rcvACY, *pXML); + std::ignore = toXML(value(o).rcvEB, *pXML); + } + + return pXML; +} + +XMLElem CPHDXMLParser::toXML(const Pvp& pvp, XMLElem parent) +{ + XMLElem pvpXML = newElement("PVP", parent); + createPVPType("TxTime", pvp.txTime, pvpXML); + createPVPType("TxPos", pvp.txPos, pvpXML); + createPVPType("TxVel", pvp.txVel, pvpXML); + createPVPType("RcvTime", pvp.rcvTime, pvpXML); + createPVPType("RcvPos", pvp.rcvPos, pvpXML); + createPVPType("RcvVel", pvp.rcvVel, pvpXML); + createPVPType("SRPPos", pvp.srpPos, pvpXML); + if (!six::Init::isUndefined(pvp.ampSF.getOffset())) + { + createPVPType("AmpSF", pvp.ampSF, pvpXML); + } + createPVPType("aFDOP", pvp.aFDOP, pvpXML); + createPVPType("aFRR1", pvp.aFRR1, pvpXML); + createPVPType("aFRR2", pvp.aFRR2, pvpXML); + createPVPType("FX1", pvp.fx1, pvpXML); + createPVPType("FX2", pvp.fx2, pvpXML); + if (!six::Init::isUndefined(pvp.fxN1.getOffset())) + { + createPVPType("FXN1", pvp.fxN1, pvpXML); + } + if (!six::Init::isUndefined(pvp.fxN2.getOffset())) + { + createPVPType("FXN2", pvp.fxN2, pvpXML); + } + createPVPType("TOA1", pvp.toa1, pvpXML); + createPVPType("TOA2", pvp.toa2, pvpXML); + if (!six::Init::isUndefined(pvp.toaE1.getOffset())) + { + createPVPType("TOAE1", pvp.toaE1, pvpXML); + } + if (!six::Init::isUndefined(pvp.toaE2.getOffset())) + { + createPVPType("TOAE2", pvp.toaE2, pvpXML); + } + createPVPType("TDTropoSRP", pvp.tdTropoSRP, pvpXML); + if (!six::Init::isUndefined(pvp.tdIonoSRP.getOffset())) + { + createPVPType("TDIonoSRP", pvp.tdIonoSRP, pvpXML); + } + createPVPType("SC0", pvp.sc0, pvpXML); + createPVPType("SCSS", pvp.scss, pvpXML); + if (!six::Init::isUndefined(pvp.signal.getOffset())) + { + createPVPType("SIGNAL", pvp.signal, pvpXML); + } + + std::ignore = toXML(pvp.txAntenna, *pvpXML); + std::ignore = toXML(pvp.rcvAntenna, *pvpXML); + + for (auto it = pvp.addedPVP.begin(); it != pvp.addedPVP.end(); ++it) + { + createAPVPType("AddedPVP", it->second, pvpXML); + } + + return pvpXML; +} + +void CPHDXMLParser::createSupportArray(const std::vector& supportArray, + const std::string& tag, xml::lite::Element& parent) +{ + for (auto&& param : supportArray) + { + XMLElem pXML = newElement(tag, &parent); + createInt("Identifier", param.getIdentifier(), pXML); + createString("ElementFormat", param.elementFormat, pXML); + createDouble("X0", param.x0, pXML); + createDouble("Y0", param.y0, pXML); + createDouble("XSS", param.xSS, pXML); + createDouble("YSS", param.ySS, pXML); + + } +} + +//Assumes optional handled by caller +XMLElem CPHDXMLParser::toXML(const SupportArray& supports, XMLElem parent) +{ + XMLElem supportsXML = newElement("SupportArray", parent); + createSupportArray(supports.iazArray, "IAZArray", *supportsXML); + createSupportArray(supports.antGainPhase, "AntGainPhase", *supportsXML); + createSupportArray(supports.dwellTimeArray, "DwellTimeArray", *supportsXML); // added in CPHD 1.1.0 + + if (!supports.addedSupportArray.empty()) + { + for (auto it = supports.addedSupportArray.begin(); it != supports.addedSupportArray.end(); ++it) + { + XMLElem addedSupportArrayXML = newElement("AddedSupportArray", supportsXML); + createString("Identifier", it->first, addedSupportArrayXML); + createString("ElementFormat", it->second.elementFormat, addedSupportArrayXML); + createDouble("X0", it->second.x0, addedSupportArrayXML); + createDouble("Y0", it->second.y0, addedSupportArrayXML); + createDouble("XSS", it->second.xSS, addedSupportArrayXML); + createDouble("YSS", it->second.ySS, addedSupportArrayXML); + createString("XUnits", it->second.xUnits, addedSupportArrayXML); + createString("YUnits", it->second.yUnits, addedSupportArrayXML); + createString("ZUnits", it->second.zUnits, addedSupportArrayXML); + mCommon.addParameters("Parameter", getDefaultURI(), it->second.parameter, addedSupportArrayXML); + } + } + return supportsXML; +} + +XMLElem CPHDXMLParser::toXML(const Dwell& dwell, XMLElem parent) +{ + XMLElem dwellXML = newElement("Dwell", parent); + createInt("NumCODTimes", dwell.cod.size(), dwellXML); + + for (size_t ii = 0; ii < dwell.cod.size(); ++ii) + { + XMLElem codTimeXML = newElement("CODTime", dwellXML); + createString("Identifier", dwell.cod[ii].identifier, codTimeXML); + mCommon.createPoly2D("CODTimePoly", dwell.cod[ii].codTimePoly, codTimeXML); + } + createInt("NumDwellTimes", dwell.dtime.size(), dwellXML); + for (size_t ii = 0; ii < dwell.dtime.size(); ++ii) + { + XMLElem dwellTimeXML = newElement("DwellTime", dwellXML); + createString("Identifier", dwell.dtime[ii].identifier, dwellTimeXML); + mCommon.createPoly2D("DwellTimePoly", dwell.dtime[ii].dwellTimePoly, dwellTimeXML); + } + return dwellXML; +} + +XMLElem CPHDXMLParser::toXML(const ReferenceGeometry& refGeo, XMLElem parent) +{ + XMLElem refGeoXML = newElement("ReferenceGeometry", parent); + XMLElem srpXML = newElement("SRP", refGeoXML); + mCommon.createVector3D("ECF", refGeo.srp.ecf, srpXML); + mCommon.createVector3D("IAC", refGeo.srp.iac, srpXML); + createDouble("ReferenceTime", refGeo.referenceTime, refGeoXML); + createDouble("SRPCODTime", refGeo.srpCODTime, refGeoXML); + createDouble("SRPDwellTime", refGeo.srpDwellTime, refGeoXML); + + if (refGeo.monostatic.get()) + { + XMLElem monoXML = newElement("Monostatic", refGeoXML); + mCommon.createVector3D("ARPPos", refGeo.monostatic->arpPos, monoXML); + mCommon.createVector3D("ARPVel", refGeo.monostatic->arpVel, monoXML); + const auto side = refGeo.monostatic->sideOfTrack.toString(); + createString("SideOfTrack", (side == "LEFT" ? "L" : "R"), monoXML); + createDouble("SlantRange", refGeo.monostatic->slantRange, monoXML); + createDouble("GroundRange", refGeo.monostatic->groundRange, monoXML); + createDouble("DopplerConeAngle", refGeo.monostatic->dopplerConeAngle, monoXML); + createDouble("GrazeAngle", refGeo.monostatic->grazeAngle, monoXML); + createDouble("IncidenceAngle", refGeo.monostatic->incidenceAngle, monoXML); + createDouble("AzimuthAngle", refGeo.monostatic->azimuthAngle, monoXML); + createDouble("TwistAngle", refGeo.monostatic->twistAngle, monoXML); + createDouble("SlopeAngle", refGeo.monostatic->slopeAngle, monoXML); + createDouble("LayoverAngle", refGeo.monostatic->layoverAngle, monoXML); + } + else if(refGeo.bistatic.get()) + { + XMLElem biXML = newElement("Bistatic", refGeoXML); + createDouble("AzimuthAngle", refGeo.bistatic->azimuthAngle, biXML); + createDouble("AzimuthAngleRate", refGeo.bistatic->azimuthAngleRate, biXML); + createDouble("BistaticAngle", refGeo.bistatic->bistaticAngle, biXML); + createDouble("BistaticAngleRate", refGeo.bistatic->bistaticAngleRate, biXML); + createDouble("GrazeAngle", refGeo.bistatic->grazeAngle, biXML); + createDouble("TwistAngle", refGeo.bistatic->twistAngle, biXML); + createDouble("SlopeAngle", refGeo.bistatic->slopeAngle, biXML); + createDouble("LayoverAngle", refGeo.bistatic->layoverAngle, biXML); + XMLElem txPlatXML = newElement("TxPlatform", biXML); + createDouble("Time", refGeo.bistatic->txPlatform.time, txPlatXML); + mCommon.createVector3D("Pos", refGeo.bistatic->txPlatform.pos, txPlatXML); + mCommon.createVector3D("Vel", refGeo.bistatic->txPlatform.vel, txPlatXML); + + { + const auto side = refGeo.bistatic->txPlatform.sideOfTrack.toString(); + createString("SideOfTrack", (side == "LEFT" ? "L" : "R"), txPlatXML); + } + createDouble("SlantRange", refGeo.bistatic->txPlatform.slantRange, txPlatXML); + createDouble("GroundRange", refGeo.bistatic->txPlatform.groundRange, txPlatXML); + createDouble("DopplerConeAngle", refGeo.bistatic->txPlatform.dopplerConeAngle, txPlatXML); + createDouble("GrazeAngle", refGeo.bistatic->txPlatform.grazeAngle, txPlatXML); + createDouble("IncidenceAngle", refGeo.bistatic->txPlatform.incidenceAngle, txPlatXML); + createDouble("AzimuthAngle", refGeo.bistatic->txPlatform.azimuthAngle, txPlatXML); + XMLElem rcvPlatXML = newElement("RcvPlatform", biXML); + createDouble("Time", refGeo.bistatic->rcvPlatform.time, rcvPlatXML); + mCommon.createVector3D("Pos", refGeo.bistatic->rcvPlatform.pos, rcvPlatXML); + mCommon.createVector3D("Vel", refGeo.bistatic->rcvPlatform.vel, rcvPlatXML); + + { + const auto side = refGeo.bistatic->rcvPlatform.sideOfTrack.toString(); + createString("SideOfTrack", (side == "LEFT" ? "L" : "R"), rcvPlatXML); + } + createDouble("SlantRange", refGeo.bistatic->rcvPlatform.slantRange, rcvPlatXML); + createDouble("GroundRange", refGeo.bistatic->rcvPlatform.groundRange, rcvPlatXML); + createDouble("DopplerConeAngle", refGeo.bistatic->rcvPlatform.dopplerConeAngle, rcvPlatXML); + createDouble("GrazeAngle", refGeo.bistatic->rcvPlatform.grazeAngle, rcvPlatXML); + createDouble("IncidenceAngle", refGeo.bistatic->rcvPlatform.incidenceAngle, rcvPlatXML); + createDouble("AzimuthAngle", refGeo.bistatic->rcvPlatform.azimuthAngle, rcvPlatXML); + } + return refGeoXML; +} + +XMLElem CPHDXMLParser::toXML(const six::XsElement_minOccurs0& o, xml::lite::Element& parent) +{ + XMLElem retval = nullptr; + if (has_value(o)) + { + retval = newElement(o.tag(), &parent); + std::ignore = create(parser(), value(o).dcxsf, *retval); + std::ignore = create(parser(), value(o).dcysf, *retval); + } + + return retval; +} + +XMLElem CPHDXMLParser::toXML(const six::XsElement_minOccurs0& o, xml::lite::Element& parent) +{ + XMLElem retval = nullptr; + if (has_value(o)) + { + retval = newElement(o.tag(), &parent); + std::ignore = create(parser(), value(o).dcxsf, *retval); + std::ignore = create(parser(), value(o).dcysf, *retval); + } + + return retval; +} + +XMLElem CPHDXMLParser::toXML(const six::XsElement_minOccurs0& o, xml::lite::Element& parent) +{ + XMLElem retval = nullptr; + if (has_value(o)) + { + retval = newElement(o.tag(), &parent); + std::ignore = create(parser(), value(o).ampX, *retval); + std::ignore = create(parser(), value(o).ampY, *retval); + std::ignore = create(parser(), value(o).phaseY, *retval); + } + + return retval; +} + +XMLElem CPHDXMLParser::toXML(const Antenna& antenna, XMLElem parent) +{ + XMLElem antennaXML = newElement("Antenna", parent); + createInt("NumACFs", antenna.antCoordFrame.size(), antennaXML); + createInt("NumAPCs", antenna.antPhaseCenter.size(), antennaXML); + createInt("NumAntPats", antenna.antPattern.size(), antennaXML); + for (size_t ii = 0; ii < antenna.antCoordFrame.size(); ++ii) + { + XMLElem antCoordFrameXML = newElement("AntCoordFrame", antennaXML); + createString("Identifier", antenna.antCoordFrame[ii].identifier, antCoordFrameXML); + mCommon.createPolyXYZ("XAxisPoly", antenna.antCoordFrame[ii].xAxisPoly, antCoordFrameXML); + mCommon.createPolyXYZ("YAxisPoly", antenna.antCoordFrame[ii].yAxisPoly, antCoordFrameXML); + create(parser(), antenna.antCoordFrame[ii].useACFPVP, *antCoordFrameXML); + } + for (size_t ii = 0; ii < antenna.antPhaseCenter.size(); ++ii) + { + XMLElem antPhaseCenterXML = newElement("AntPhaseCenter", antennaXML); + createString("Identifier", antenna.antPhaseCenter[ii].identifier, antPhaseCenterXML); + createString("ACFId", antenna.antPhaseCenter[ii].acfId, antPhaseCenterXML); + mCommon.createVector3D("APCXYZ", antenna.antPhaseCenter[ii].apcXYZ, antPhaseCenterXML); + } + for (size_t ii = 0; ii < antenna.antPattern.size(); ++ii) + { + XMLElem antPatternXML = newElement("AntPattern", antennaXML); + createString("Identifier", antenna.antPattern[ii].identifier, antPatternXML); + createDouble("FreqZero", antenna.antPattern[ii].freqZero, antPatternXML); + createOptionalDouble("GainZero", antenna.antPattern[ii].gainZero, antPatternXML); + if (!six::Init::isUndefined(antenna.antPattern[ii].ebFreqShift)) + { + createBooleanType("EBFreqShift", antenna.antPattern[ii].ebFreqShift, antPatternXML); + } + std::ignore = toXML(antenna.antPattern[ii].ebFreqShiftSF, *antPatternXML); + + if (!six::Init::isUndefined(antenna.antPattern[ii].mlFreqDilation)) + { + createBooleanType("MLFreqDilation", antenna.antPattern[ii].mlFreqDilation, antPatternXML); + } + std::ignore = toXML(antenna.antPattern[ii].mlFreqDilationSF, *antPatternXML); + + if (!six::Init::isUndefined(antenna.antPattern[ii].gainBSPoly)) + { + mCommon.createPoly1D("GainBSPoly", antenna.antPattern[ii].gainBSPoly, antPatternXML); + } + + std::ignore = toXML(antenna.antPattern[ii].antPolRef, *antPatternXML); + + XMLElem ebXML = newElement("EB", antPatternXML); + mCommon.createPoly1D("DCXPoly", antenna.antPattern[ii].eb.dcxPoly, ebXML); + mCommon.createPoly1D("DCYPoly", antenna.antPattern[ii].eb.dcyPoly, ebXML); + create(parser(), antenna.antPattern[ii].eb.useEBPVP, *ebXML); + + XMLElem arrayXML = newElement("Array", antPatternXML); + mCommon.createPoly2D("GainPoly", antenna.antPattern[ii].array.gainPoly, arrayXML); + mCommon.createPoly2D("PhasePoly", antenna.antPattern[ii].array.phasePoly, arrayXML); + create(parser(), antenna.antPattern[ii].array.antGPId, *arrayXML); + + XMLElem elementXML = newElement("Element", antPatternXML); + mCommon.createPoly2D("GainPoly", antenna.antPattern[ii].element.gainPoly, elementXML); + mCommon.createPoly2D("PhasePoly", antenna.antPattern[ii].element.phasePoly, elementXML); + for (size_t jj = 0; jj < antenna.antPattern[ii].gainPhaseArray.size(); ++jj) + { + XMLElem gainPhaseArrayXML = newElement("GainPhaseArray", antPatternXML); + createDouble("Freq", antenna.antPattern[ii].gainPhaseArray[jj].freq, gainPhaseArrayXML); + createString("ArrayId", antenna.antPattern[ii].gainPhaseArray[jj].arrayId, gainPhaseArrayXML); + if (!six::Init::isUndefined(antenna.antPattern[ii].gainPhaseArray[jj].elementId)) + { + createString("ElementId", antenna.antPattern[ii].gainPhaseArray[jj].elementId, gainPhaseArrayXML); + } + } + } + return antennaXML; +} + +XMLElem CPHDXMLParser::toXML(const TxRcv& txRcv, XMLElem parent) +{ + XMLElem txRcvXML = newElement("TxRcv", parent); + createInt("NumTxWFs", txRcv.txWFParameters.size(), txRcvXML); + for (size_t ii = 0; ii < txRcv.txWFParameters.size(); ++ii) + { + XMLElem txWFParamsXML = newElement("TxWFParameters", txRcvXML); + createString("Identifier", txRcv.txWFParameters[ii].identifier, txWFParamsXML); + createDouble("PulseLength", txRcv.txWFParameters[ii].pulseLength, txWFParamsXML); + createDouble("RFBandwidth", txRcv.txWFParameters[ii].rfBandwidth, txWFParamsXML); + createDouble("FreqCenter", txRcv.txWFParameters[ii].freqCenter, txWFParamsXML); + createOptionalDouble("LFMRate", txRcv.txWFParameters[ii].lfmRate, txWFParamsXML); + createString("Polarization", txRcv.txWFParameters[ii].polarization, txWFParamsXML); + createOptionalDouble("Power", txRcv.txWFParameters[ii].power, txWFParamsXML); + } + createInt("NumRcvs", txRcv.rcvParameters.size(), txRcvXML); + for (size_t ii = 0; ii < txRcv.rcvParameters.size(); ++ii) + { + XMLElem rcvParamsXML = newElement("RcvParameters", txRcvXML); + createString("Identifier", txRcv.rcvParameters[ii].identifier, rcvParamsXML); + createDouble("WindowLength", txRcv.rcvParameters[ii].windowLength, rcvParamsXML); + createDouble("SampleRate", txRcv.rcvParameters[ii].sampleRate, rcvParamsXML); + createDouble("IFFilterBW", txRcv.rcvParameters[ii].ifFilterBW, rcvParamsXML); + createDouble("FreqCenter", txRcv.rcvParameters[ii].freqCenter, rcvParamsXML); + createOptionalDouble("LFMRate", txRcv.rcvParameters[ii].lfmRate, rcvParamsXML); + createString("Polarization", txRcv.rcvParameters[ii].polarization, rcvParamsXML); + createOptionalDouble("PathGain", txRcv.rcvParameters[ii].pathGain, rcvParamsXML); + } + return txRcvXML; +} + +XMLElem CPHDXMLParser::toXML(const ErrorParameters& errParams, XMLElem parent) +{ + XMLElem errParamsXML = newElement("ErrorParameters", parent); + if (errParams.monostatic.get()) + { + XMLElem monoXML = newElement("Monostatic", errParamsXML); + XMLElem posVelErrXML = newElement("PosVelErr", monoXML); + createString("Frame", errParams.monostatic->posVelErr.frame, posVelErrXML); + createDouble("P1", errParams.monostatic->posVelErr.p1, posVelErrXML); + createDouble("P2", errParams.monostatic->posVelErr.p2, posVelErrXML); + createDouble("P3", errParams.monostatic->posVelErr.p3, posVelErrXML); + createDouble("V1", errParams.monostatic->posVelErr.v1, posVelErrXML); + createDouble("V2", errParams.monostatic->posVelErr.v2, posVelErrXML); + createDouble("V3", errParams.monostatic->posVelErr.v3, posVelErrXML); + if(errParams.monostatic->posVelErr.corrCoefs.get()) + { + XMLElem corrCoefsXML = newElement("CorrCoefs", posVelErrXML); + createDouble("P1P2", errParams.monostatic->posVelErr.corrCoefs->p1p2, corrCoefsXML); + createDouble("P1P3", errParams.monostatic->posVelErr.corrCoefs->p1p3, corrCoefsXML); + createDouble("P1V1", errParams.monostatic->posVelErr.corrCoefs->p1v1, corrCoefsXML); + createDouble("P1V2", errParams.monostatic->posVelErr.corrCoefs->p1v2, corrCoefsXML); + createDouble("P1V3", errParams.monostatic->posVelErr.corrCoefs->p1v3, corrCoefsXML); + createDouble("P2P3", errParams.monostatic->posVelErr.corrCoefs->p2p3, corrCoefsXML); + createDouble("P2V1", errParams.monostatic->posVelErr.corrCoefs->p2v1, corrCoefsXML); + createDouble("P2V2", errParams.monostatic->posVelErr.corrCoefs->p2v2, corrCoefsXML); + createDouble("P2V3", errParams.monostatic->posVelErr.corrCoefs->p2v3, corrCoefsXML); + createDouble("P3V1", errParams.monostatic->posVelErr.corrCoefs->p3v1, corrCoefsXML); + createDouble("P3V2", errParams.monostatic->posVelErr.corrCoefs->p3v2, corrCoefsXML); + createDouble("P3V3", errParams.monostatic->posVelErr.corrCoefs->p3v3, corrCoefsXML); + createDouble("V1V2", errParams.monostatic->posVelErr.corrCoefs->v1v2, corrCoefsXML); + createDouble("V1V3", errParams.monostatic->posVelErr.corrCoefs->v1v3, corrCoefsXML); + createDouble("V2V3", errParams.monostatic->posVelErr.corrCoefs->v2v3, corrCoefsXML); + } + createDecorrType("PositionDecorr", errParams.monostatic->posVelErr.positionDecorr, posVelErrXML); + + // RadarSensor + XMLElem radarXML = newElement("RadarSensor", monoXML); + createDouble("RangeBias", errParams.monostatic->radarSensor.rangeBias, radarXML); + createOptionalDouble("ClockFreqSF", errParams.monostatic->radarSensor.clockFreqSF, radarXML); + createOptionalDouble("CollectionStartTime", errParams.monostatic->radarSensor.collectionStartTime, radarXML); + if (errParams.monostatic->radarSensor.rangeBiasDecorr.get()) + { + XMLElem rangeBiasDecorrXML = newElement("RangeBiasDecorr", radarXML); + createDouble("CorrCoefZero", errParams.monostatic->radarSensor.rangeBiasDecorr->corrCoefZero, rangeBiasDecorrXML); + createDouble("DecorrRate", errParams.monostatic->radarSensor.rangeBiasDecorr->decorrRate, rangeBiasDecorrXML); + } + + if (errParams.monostatic->tropoError.get()) + { + XMLElem tropoXML = newElement("TropoError", monoXML); + createOptionalDouble("TropoRangeVertical", errParams.monostatic->tropoError->tropoRangeVertical, tropoXML); + createOptionalDouble("TropoRangeSlant", errParams.monostatic->tropoError->tropoRangeSlant, tropoXML); + createDecorrType("TropoRangeDecorr", errParams.monostatic->tropoError->tropoRangeDecorr, tropoXML); + } + if (errParams.monostatic->ionoError.get()) + { + XMLElem ionoXML = newElement("IonoError", monoXML); + createDouble("IonoRangeVertical", errParams.monostatic->ionoError->ionoRangeVertical, ionoXML); + createOptionalDouble("IonoRangeRateVertical", errParams.monostatic->ionoError->ionoRangeRateVertical, ionoXML); + createOptionalDouble("IonoRgRgRateCC", errParams.monostatic->ionoError->ionoRgRgRateCC, ionoXML); + createDecorrType("IonoRangeVertDecorr", errParams.monostatic->tropoError->tropoRangeDecorr, ionoXML); + } + if (!errParams.monostatic->parameter.empty()) + { + XMLElem addedParamsXML = newElement("AddedParameters", monoXML); + mCommon.addParameters("Parameter", getDefaultURI(), errParams.monostatic->parameter, addedParamsXML); + } + } + else if (errParams.bistatic.get()) + { + XMLElem biXML = newElement("Bistatic", errParamsXML); + XMLElem txPlatXML = newElement("TxPlatform", biXML); + createErrorParamPlatform("TxPlatform", errParams.bistatic->txPlatform, txPlatXML); + XMLElem radarTxXML = newElement("RadarSensor", txPlatXML); + create(parser(), errParams.bistatic->txPlatform.radarSensor.delayBias, *radarTxXML); + createOptionalDouble("ClockFreqSF", errParams.bistatic->txPlatform.radarSensor.clockFreqSF, radarTxXML); + createDouble("CollectionStartTime", errParams.bistatic->txPlatform.radarSensor.collectionStartTime, radarTxXML); + + XMLElem rcvPlatXML = newElement("RcvPlatform", biXML); + createErrorParamPlatform("RcvPlatform", errParams.bistatic->rcvPlatform, rcvPlatXML); + XMLElem radarRcvXML = newElement("RadarSensor", rcvPlatXML); + createOptionalDouble("ClockFreqSF", errParams.bistatic->rcvPlatform.radarSensor.clockFreqSF, radarRcvXML); + createDouble("CollectionStartTime", errParams.bistatic->rcvPlatform.radarSensor.collectionStartTime, radarRcvXML); + + if (!errParams.bistatic->parameter.empty()) + { + XMLElem addedParamsXML = newElement("AddedParameters", biXML); + mCommon.addParameters("Parameter", getDefaultURI(), errParams.bistatic->parameter, addedParamsXML); + } + } + + return errParamsXML; +} + +XMLElem CPHDXMLParser::toXML(const ProductInfo& productInfo, XMLElem parent) +{ + XMLElem productInfoXML = newElement("ProductInfo", parent); + if(!six::Init::isUndefined(productInfo.profile)) + { + createString("Profile", productInfo.profile, productInfoXML); + } + for (size_t ii = 0; ii < productInfo.creationInfo.size(); ++ii) + { + XMLElem creationInfoXML = newElement("CreationInfo", productInfoXML); + if(!six::Init::isUndefined(productInfo.creationInfo[ii].application)) + { + createString("Application", productInfo.creationInfo[ii].application, creationInfoXML); + } + createDateTime("DateTime", productInfo.creationInfo[ii].dateTime, creationInfoXML); + if (!six::Init::isUndefined(productInfo.creationInfo[ii].site)) + { + createString("Site", productInfo.creationInfo[ii].site, creationInfoXML); + } + mCommon.addParameters("Parameter", getDefaultURI(), productInfo.creationInfo[ii].parameter, creationInfoXML); + } + mCommon.addParameters("Parameter", getDefaultURI(), productInfo.parameter, productInfoXML); + return productInfoXML; +} + +XMLElem CPHDXMLParser::toXML(const GeoInfo& geoInfo, XMLElem parent) +{ + XMLElem geoInfoXML = newElement("GeoInfo", parent); + + mCommon.addParameters("Desc", geoInfo.desc, geoInfoXML); + + const size_t numLatLons = geoInfo.geometryLatLon.size(); + if (numLatLons == 1) + { + mCommon.createLatLon("Point", geoInfo.geometryLatLon[0], geoInfoXML); + } + else if (numLatLons >= 2) + { + XMLElem linePolyXML = newElement(numLatLons == 2 ? "Line" : "Polygon", + geoInfoXML); + setAttribute(linePolyXML, "size", numLatLons); + + for (size_t ii = 0; ii < numLatLons; ++ii) + { + XMLElem v = mCommon.createLatLon(numLatLons == 2 ? "Endpoint" : "Vertex", + geoInfo.geometryLatLon[ii], linePolyXML); + setAttribute(v, "index", ii + 1); + } + } + + if (!geoInfo.name.empty()) + setAttribute(geoInfoXML, "name", geoInfo.name); + + for (size_t ii = 0; ii < geoInfo.geoInfos.size(); ++ii) + { + toXML(*geoInfo.geoInfos[ii], geoInfoXML); + } + + return geoInfoXML; +} + +XMLElem CPHDXMLParser::toXML(const MatchInformation& matchInfo, XMLElem parent) +{ + return mCommon.convertMatchInformationToXML(matchInfo, parent); +} + +/* + * FROM XML + */ + +std::unique_ptr CPHDXMLParser::fromXML( + const xml::lite::Document* doc) +{ + std::unique_ptr cphd(new Metadata()); + + const auto root = doc->getRootElement(); + + XMLElem collectionIDXML = getFirstAndOnly(root, "CollectionID"); + XMLElem globalXML = getFirstAndOnly(root, "Global"); + XMLElem sceneCoordsXML = getFirstAndOnly(root, "SceneCoordinates"); + XMLElem dataXML = getFirstAndOnly(root, "Data"); + XMLElem channelXML = getFirstAndOnly(root, "Channel"); + XMLElem pvpXML = getFirstAndOnly(root, "PVP"); + XMLElem dwellXML = getFirstAndOnly(root, "Dwell"); + XMLElem refGeoXML = getFirstAndOnly(root, "ReferenceGeometry"); + + XMLElem supportArrayXML = getOptional(root, "SupportArray"); + XMLElem antennaXML = getOptional(root, "Antenna"); + XMLElem txRcvXML = getOptional(root, "TxRcv"); + XMLElem errParamXML = getOptional(root, "ErrorParameters"); + XMLElem productInfoXML = getOptional(root, "ProductInfo"); + std::vector geoInfoXMLVec; + root->getElementsByTagName("GeoInfo", geoInfoXMLVec); + cphd->geoInfo.resize(geoInfoXMLVec.size()); + XMLElem matchInfoXML = getOptional(root, "MatchInfo"); + + // Parse XML for each section + fromXML(collectionIDXML, cphd->collectionID); + fromXML(globalXML, cphd->global); + fromXML(sceneCoordsXML, cphd->sceneCoordinates); + fromXML(dataXML, cphd->data); + fromXML(channelXML, cphd->channel); + fromXML(pvpXML, cphd->pvp); + fromXML(dwellXML, cphd->dwell); + fromXML(refGeoXML, cphd->referenceGeometry); + + if(supportArrayXML) + { + cphd->supportArray.reset(new SupportArray()); + fromXML(supportArrayXML, *(cphd->supportArray)); + } + if(antennaXML) + { + cphd->antenna.reset(new Antenna()); + fromXML(antennaXML, *(cphd->antenna)); + } + if(txRcvXML) + { + cphd->txRcv.reset(new TxRcv()); + fromXML(txRcvXML, *(cphd->txRcv)); + } + if(errParamXML) + { + cphd->errorParameters.reset(new ErrorParameters()); + fromXML(errParamXML, *(cphd->errorParameters)); + } + if(productInfoXML) + { + cphd->productInfo.reset(new ProductInfo()); + fromXML(productInfoXML, *(cphd->productInfo)); + } + for (size_t ii = 0; ii < geoInfoXMLVec.size(); ++ii) + { + fromXML(geoInfoXMLVec[ii], cphd->geoInfo[ii]); + } + if (matchInfoXML) + { + cphd->matchInfo.reset(new MatchInformation()); + fromXML(matchInfoXML, *(cphd->matchInfo)); + } + + return cphd; +} + +void CPHDXMLParser::fromXML(const xml::lite::Element* collectionIDXML, CollectionInformation& collectionID) +{ + parseString(getFirstAndOnly(collectionIDXML, "CollectorName"), + collectionID.collectorName); + + XMLElem element = getOptional(collectionIDXML, "IlluminatorName"); + if (element) + { + parseString(element, collectionID.illuminatorName); + } + + element = getOptional(collectionIDXML, "CoreName"); + if (element) + { + parseString(element, collectionID.coreName); + } + + element = getOptional(collectionIDXML, "CollectType"); + if (element) + { + collectionID.collectType + = six::toType(element->getCharacterData()); + } + + XMLElem radarModeXML = getFirstAndOnly(collectionIDXML, "RadarMode"); + + collectionID.radarMode + = six::toType(getFirstAndOnly(radarModeXML, + "ModeType")->getCharacterData()); + + element = getOptional(radarModeXML, "ModeID"); + if (element) + { + parseString(element, collectionID.radarModeID); + } + + element = getFirstAndOnly(collectionIDXML, "ReleaseInfo"); + parseString(element, collectionID.releaseInfo); + + std::string classification; + parseString(getFirstAndOnly(collectionIDXML, "Classification"), + classification); + collectionID.setClassificationLevel(classification); + + // Optional + std::vector countryCodes; + element = getOptional(collectionIDXML, "CountryCode"); + if (element) + { + std::string countryCodeStr; + parseString(element, countryCodeStr); + collectionID.countryCodes = str::split(countryCodeStr, ","); + for (size_t ii = 0; ii < collectionID.countryCodes.size(); ++ii) + { + str::trim(collectionID.countryCodes[ii]); + } + } + + //optional + mCommon.parseParameters(collectionIDXML, "Parameter", collectionID.parameters); +} + +void CPHDXMLParser::fromXML(const xml::lite::Element* globalXML, Global& global) +{ + global.domainType = DomainType::toType( + getFirstAndOnly(globalXML, "DomainType")->getCharacterData()); + global.sgn = PhaseSGN::toType( + getFirstAndOnly(globalXML, "SGN")->getCharacterData()); + + // Timeline + const xml::lite::Element* timelineXML = getFirstAndOnly(globalXML, "Timeline"); + parseDateTime( + getFirstAndOnly(timelineXML, "CollectionStart"), + global.timeline.collectionStart); + + // Optional + const xml::lite::Element* rcvCollectionXML = getOptional(timelineXML, + "RcvCollectionStart"); + if (rcvCollectionXML) + { + parseDateTime(rcvCollectionXML, + global.timeline.rcvCollectionStart); + } + + parseDouble( + getFirstAndOnly(timelineXML, "TxTime1"), global.timeline.txTime1); + parseDouble( + getFirstAndOnly(timelineXML, "TxTime2"), global.timeline.txTime2); + + // FxBand + const xml::lite::Element* fxBandXML = getFirstAndOnly(globalXML, "FxBand"); + parseDouble(getFirstAndOnly(fxBandXML, "FxMin"), global.fxBand.fxMin); + parseDouble(getFirstAndOnly(fxBandXML, "FxMax"), global.fxBand.fxMax); + + // TOASwath + const xml::lite::Element* toaSwathXML = getFirstAndOnly(globalXML, "TOASwath"); + parseDouble(getFirstAndOnly(toaSwathXML, "TOAMin"), global.toaSwath.toaMin); + parseDouble(getFirstAndOnly(toaSwathXML, "TOAMax"), global.toaSwath.toaMax); + + // TropoParameters + const xml::lite::Element* tropoXML = getOptional(globalXML, "TropoParameters"); + if (tropoXML) + { + // Optional + global.tropoParameters.reset(new TropoParameters()); + parseDouble(getFirstAndOnly(tropoXML, "N0"), global.tropoParameters->n0); + global.tropoParameters->refHeight = + RefHeight::toType(getFirstAndOnly(tropoXML, "RefHeight")->getCharacterData()); + } + + // IonoParameters + if (const auto ionoXML = getOptional(globalXML, "IonoParameters")) + { + // Optional + global.ionoParameters.reset(new IonoParameters()); + parseDouble(getFirstAndOnly(ionoXML, "TECV"), global.ionoParameters->tecv); + if (const auto f2HeightXML = getOptional(ionoXML, "F2Height")) + { + parseDouble(f2HeightXML, global.ionoParameters->f2Height); + } + } +} + +void CPHDXMLParser::fromXML(const xml::lite::Element* sceneCoordsXML, + SceneCoordinates& scene) +{ + scene.earthModel = EarthModelType::toType( + getFirstAndOnly(sceneCoordsXML, "EarthModel")->getCharacterData()); + + // IARP + const xml::lite::Element* iarpXML = getFirstAndOnly(sceneCoordsXML, "IARP"); + mCommon.parseVector3D(getFirstAndOnly(iarpXML, "ECF"), scene.iarp.ecf); + mCommon.parseLatLonAlt(getFirstAndOnly(iarpXML, "LLH"), scene.iarp.llh); + + // ReferenceSurface + const xml::lite::Element* surfaceXML = getFirstAndOnly(sceneCoordsXML, "ReferenceSurface"); + const xml::lite::Element* planarXML = getOptional(surfaceXML, "Planar"); + const xml::lite::Element* haeXML = getOptional(surfaceXML, "HAE"); + if (planarXML && !haeXML) + { + // Choice type + scene.referenceSurface.planar.reset(new Planar()); + mCommon.parseVector3D(getFirstAndOnly(planarXML, "uIAX"), + scene.referenceSurface.planar->uIax); + mCommon.parseVector3D(getFirstAndOnly(planarXML, "uIAY"), + scene.referenceSurface.planar->uIay); + } + else if (haeXML && !planarXML) + { + // Choice type + scene.referenceSurface.hae.reset(new HAE()); + mCommon.parseLatLon(getFirstAndOnly(haeXML, "uIAXLL"), + scene.referenceSurface.hae->uIax); + mCommon.parseLatLon(getFirstAndOnly(haeXML, "uIAYLL"), + scene.referenceSurface.hae->uIay); + } + else + { + throw except::Exception(Ctxt( + "ReferenceSurface must exactly one of Planar or HAE element")); + } + + // ImageArea + const xml::lite::Element* imageAreaXML = getFirstAndOnly(sceneCoordsXML, "ImageArea"); + parseAreaType(imageAreaXML, scene.imageArea); + + // ImageAreaCorners + const xml::lite::Element* cornersXML = getFirstAndOnly(sceneCoordsXML, + "ImageAreaCornerPoints"); + mCommon.parseFootprint(cornersXML, "IACP", scene.imageAreaCorners); + + // Extended Area + const xml::lite::Element* extendedAreaXML = getOptional(sceneCoordsXML, "ExtendedArea"); + if (extendedAreaXML) + { + scene.extendedArea.reset(new AreaType()); + parseAreaType(extendedAreaXML, *scene.extendedArea); + } + + // Image Grid + const xml::lite::Element* gridXML = getOptional(sceneCoordsXML, "ImageGrid"); + if (gridXML) + { + // Optional + scene.imageGrid.reset(new ImageGrid()); + const xml::lite::Element* identifierXML = getOptional(gridXML, "Identifier"); + if (identifierXML) + { + parseString(identifierXML, scene.imageGrid->identifier); + } + parseLineSample(getFirstAndOnly(gridXML, "IARPLocation"), + scene.imageGrid->iarpLocation); + parseIAExtent(getFirstAndOnly(gridXML, "IAXExtent"), + scene.imageGrid->xExtent); + parseIAExtent(getFirstAndOnly(gridXML, "IAYExtent"), + scene.imageGrid->yExtent); + + // Segment List + const xml::lite::Element* segListXML = getOptional(gridXML, "SegmentList"); + if (segListXML) + { + // Optional + size_t numSegments; + parseUInt(getFirstAndOnly(segListXML, "NumSegments"), numSegments); + scene.imageGrid->segments.resize(numSegments); + + std::vector segmentsXML; + segListXML->getElementsByTagName("Segment", segmentsXML); + + for (size_t ii = 0; ii < segmentsXML.size(); ++ii) + { + const xml::lite::Element* segmentXML = segmentsXML[ii]; + parseString(getFirstAndOnly(segmentXML, "Identifier"), + scene.imageGrid->segments[ii].identifier); + parseInt(getFirstAndOnly(segmentXML, "StartLine"), + scene.imageGrid->segments[ii].startLine); + parseInt(getFirstAndOnly(segmentXML, "StartSample"), + scene.imageGrid->segments[ii].startSample); + parseInt(getFirstAndOnly(segmentXML, "EndLine"), + scene.imageGrid->segments[ii].endLine); + parseInt(getFirstAndOnly(segmentXML, "EndSample"), + scene.imageGrid->segments[ii].endSample); + + const xml::lite::Element* polygonXML = getOptional(segmentXML, + "SegmentPolygon"); + if (polygonXML) + { + // Optional + size_t polygonSize = 0; + sscanf(const_cast(polygonXML)->attribute("size").c_str(), "%zu", &polygonSize); + scene.imageGrid->segments[ii].polygon.resize(polygonSize); + std::vector polyVerticesXMLVec; + polygonXML->getElementsByTagName("SV", polyVerticesXMLVec); + if (scene.imageGrid->segments[ii].polygon.size() != polyVerticesXMLVec.size()) + { + throw except::Exception(Ctxt( + "Incorrect polygon vertices provided")); + } + if (polyVerticesXMLVec.size() < 3) + { + throw except::Exception(Ctxt( + "Polygon must have at least 3 vertices")); + } + std::vector& vertices = + scene.imageGrid->segments[ii].polygon; + vertices.resize(polyVerticesXMLVec.size()); + for (size_t jj = 0; jj < polyVerticesXMLVec.size(); ++jj) + { + size_t tempIdx; + sscanf(polyVerticesXMLVec[jj]->attribute("index").c_str(), "%zu", &tempIdx); + vertices[jj].setIndex(tempIdx); + parseLineSample(polyVerticesXMLVec[jj], vertices[jj]); + } + } + } + } + } +} + +void CPHDXMLParser::fromXML(const xml::lite::Element* dataXML, Data& data) +{ + const xml::lite::Element* signalXML = getFirstAndOnly(dataXML, "SignalArrayFormat"); + data.signalArrayFormat = SignalArrayFormat::toType(signalXML->getCharacterData()); + + size_t numBytesPVP_temp = 0; + XMLElem numBytesPVPXML = getFirstAndOnly(dataXML, "NumBytesPVP"); + parseUInt(numBytesPVPXML, numBytesPVP_temp); + if(numBytesPVP_temp % 8 != 0) + { + throw except::Exception(Ctxt( + "Number of bytes must be multiple of 8")); + } + data.numBytesPVP = numBytesPVP_temp; + + // Channels + std::vector channelsXML; + dataXML->getElementsByTagName("Channel", channelsXML); + data.channels.resize(channelsXML.size()); + for (size_t ii = 0; ii < channelsXML.size(); ++ii) + { + parseString(getFirstAndOnly(channelsXML[ii], "Identifier"), + data.channels[ii].identifier); + parseUInt(getFirstAndOnly(channelsXML[ii], "NumVectors"), + data.channels[ii].numVectors); + parseUInt(getFirstAndOnly(channelsXML[ii], "NumSamples"), + data.channels[ii].numSamples); + parseUInt(getFirstAndOnly(channelsXML[ii], "SignalArrayByteOffset"), + data.channels[ii].signalArrayByteOffset); + parseUInt(getFirstAndOnly(channelsXML[ii], "PVPArrayByteOffset"), + data.channels[ii].pvpArrayByteOffset); + XMLElem compressionXML = getOptional(channelsXML[ii], "CompressedSignalSize"); + if (compressionXML) + { + parseUInt(compressionXML, data.channels[ii].compressedSignalSize); + } + } + XMLElem compressionXML = getOptional(dataXML, "SignalCompressionID"); + if (compressionXML) + { + parseString(compressionXML, + data.signalCompressionID); + } + + // Support Arrays + std::vector supportsXML; + dataXML->getElementsByTagName("SupportArray", supportsXML); + for (size_t ii = 0; ii < supportsXML.size(); ++ii) + { + std::string id; + size_t offset; + size_t numRows; + size_t numCols; + size_t numBytes; + parseString(getFirstAndOnly(supportsXML[ii], "Identifier"), id); + parseUInt(getFirstAndOnly(supportsXML[ii], "ArrayByteOffset"), offset); + parseUInt(getFirstAndOnly(supportsXML[ii], "NumRows"), numRows); + parseUInt(getFirstAndOnly(supportsXML[ii], "NumCols"), numCols); + parseUInt(getFirstAndOnly(supportsXML[ii], "BytesPerElement"), numBytes); + data.setSupportArray(id, numRows, numCols, numBytes, offset); + } +} + +void CPHDXMLParser::fromXML(const xml::lite::Element* channelXML, Channel& channel) +{ + parseString(getFirstAndOnly(channelXML, "RefChId"), channel.refChId); + parseBooleanType(getFirstAndOnly(channelXML, "FXFixedCPHD"), channel.fxFixedCphd); + parseBooleanType(getFirstAndOnly(channelXML, "TOAFixedCPHD"), channel.toaFixedCphd); + parseBooleanType(getFirstAndOnly(channelXML, "SRPFixedCPHD"), channel.srpFixedCphd); + + std::vector parametersXML; + channelXML->getElementsByTagName("Parameters", parametersXML); + channel.parameters.resize(parametersXML.size()); + for (size_t ii = 0; ii < parametersXML.size(); ++ii) + { + parseChannelParameters(parametersXML[ii], channel.parameters[ii]); + } + + XMLElem addedParametersXML = getOptional(channelXML, "AddedParameters"); + if(addedParametersXML) + { + mCommon.parseParameters(addedParametersXML, "Parameter", channel.addedParameters); + } +} + +void CPHDXMLParser::parse(const xml::lite::Element& parent, six::XsElement& v) const +{ + auto& param = value(v).param; + const auto offset = parsePVPType(parent, param); + setOffset(param, offset); +} +void CPHDXMLParser::parse(const xml::lite::Element& parent, six::XsElement& v) const +{ + auto& param = value(v).param; + const auto offset = parsePVPType(parent, param); + setOffset(param, offset); +} + +void CPHDXMLParser::parse(const xml::lite::Element& parent, six::XsElement_minOccurs0& o) const +{ + if (const auto pXML = getOptional(parent, o.tag())) + { + o = TxAntenna{}; + parse(*pXML, value(o).txACX); + parse(*pXML, value(o).txACY); + parse(*pXML, value(o).txEB); + } +} +void CPHDXMLParser::parse(const xml::lite::Element& parent, six::XsElement_minOccurs0& o) const +{ + if (const auto pXML = getOptional(parent, o.tag())) + { + o = RcvAntenna{}; + parse(*pXML, value(o).rcvACX); + parse(*pXML, value(o).rcvACY); + parse(*pXML, value(o).rcvEB); + } +} + +void CPHDXMLParser::fromXML(const xml::lite::Element* pvpXML, Pvp& pvp) +{ + parsePVPType(pvp, getFirstAndOnly(pvpXML, "TxTime"), pvp.txTime); + parsePVPType(pvp, getFirstAndOnly(pvpXML, "TxPos"), pvp.txPos); + parsePVPType(pvp, getFirstAndOnly(pvpXML, "TxVel"), pvp.txVel); + parsePVPType(pvp, getFirstAndOnly(pvpXML, "RcvTime"), pvp.rcvTime); + parsePVPType(pvp, getFirstAndOnly(pvpXML, "RcvPos"), pvp.rcvPos); + parsePVPType(pvp, getFirstAndOnly(pvpXML, "RcvVel"), pvp.rcvVel); + parsePVPType(pvp, getFirstAndOnly(pvpXML, "SRPPos"), pvp.srpPos); + parsePVPType(pvp, getFirstAndOnly(pvpXML, "aFDOP"), pvp.aFDOP); + parsePVPType(pvp, getFirstAndOnly(pvpXML, "aFRR1"), pvp.aFRR1); + parsePVPType(pvp, getFirstAndOnly(pvpXML, "aFRR2"), pvp.aFRR2); + parsePVPType(pvp, getFirstAndOnly(pvpXML, "FX1"), pvp.fx1); + parsePVPType(pvp, getFirstAndOnly(pvpXML, "FX2"), pvp.fx2); + parsePVPType(pvp, getFirstAndOnly(pvpXML, "TOA1"), pvp.toa1); + parsePVPType(pvp, getFirstAndOnly(pvpXML, "TOA2"), pvp.toa2); + parsePVPType(pvp, getFirstAndOnly(pvpXML, "TDTropoSRP"), pvp.tdTropoSRP); + parsePVPType(pvp, getFirstAndOnly(pvpXML, "SC0"), pvp.sc0); + parsePVPType(pvp, getFirstAndOnly(pvpXML, "SCSS"), pvp.scss); + + parseOptionalPVPType(pvpXML, "AmpSF", pvp, pvp.ampSF); + parseOptionalPVPType(pvpXML, "FXN1", pvp, pvp.fxN1); + parseOptionalPVPType(pvpXML, "FXN2", pvp, pvp.fxN2); + parseOptionalPVPType(pvpXML, "TOAE1", pvp, pvp.toaE1); + parseOptionalPVPType(pvpXML, "TOAE2", pvp, pvp.toaE2); + parseOptionalPVPType(pvpXML, "TDIonoSRP", pvp, pvp.tdIonoSRP); + parseOptionalPVPType(pvpXML, "SIGNAL", pvp, pvp.signal); + + parse(*pvpXML, pvp.txAntenna); + parse(*pvpXML, pvp.rcvAntenna); + + std::vector addedParamsXML; + const std::string str = "AddedPVP"; + pvpXML->getElementsByTagName(str, addedParamsXML); + if(addedParamsXML.empty()) + { + return; + } + for (size_t ii = 0; ii < addedParamsXML.size(); ++ii) + { + parsePVPType(pvp, addedParamsXML[ii]); + } +} + +void CPHDXMLParser::fromXML(const xml::lite::Element* DwellXML, + Dwell& dwell) +{ + // CODTime + size_t numCODTimes; + parseUInt(getFirstAndOnly(DwellXML, "NumCODTimes"), numCODTimes); + dwell.cod.resize(numCODTimes); + + std::vector codXMLVec; + DwellXML->getElementsByTagName("CODTime", codXMLVec); + for(size_t ii = 0; ii < codXMLVec.size(); ++ii) + { + parseString(getFirstAndOnly(codXMLVec[ii], "Identifier"), dwell.cod[ii].identifier); + mCommon.parsePoly2D(getFirstAndOnly(codXMLVec[ii], "CODTimePoly"), dwell.cod[ii].codTimePoly); + } + + // DwellTime + size_t numDwellTimes = 0; + parseUInt(getFirstAndOnly(DwellXML, "NumDwellTimes"), numDwellTimes); + dwell.dtime.resize(numDwellTimes); + + std::vector dtimeXMLVec; + DwellXML->getElementsByTagName("DwellTime", dtimeXMLVec); + for(size_t ii = 0; ii < dtimeXMLVec.size(); ++ii) + { + parseString(getFirstAndOnly(dtimeXMLVec[ii], "Identifier"), dwell.dtime[ii].identifier); + mCommon.parsePoly2D(getFirstAndOnly(dtimeXMLVec[ii], "DwellTimePoly"), dwell.dtime[ii].dwellTimePoly); + } +} + +void CPHDXMLParser::fromXML(const xml::lite::Element* refGeoXML, ReferenceGeometry& refGeo) +{ + XMLElem srpXML = getFirstAndOnly(refGeoXML, "SRP"); + mCommon.parseVector3D(getFirstAndOnly(srpXML, "ECF"), refGeo.srp.ecf); + mCommon.parseVector3D(getFirstAndOnly(srpXML, "IAC"), refGeo.srp.iac); + parseDouble(getFirstAndOnly(refGeoXML, "ReferenceTime"), refGeo.referenceTime); + parseDouble(getFirstAndOnly(refGeoXML, "SRPCODTime"), refGeo.srpCODTime); + parseDouble(getFirstAndOnly(refGeoXML, "SRPDwellTime"), refGeo.srpDwellTime); + + const xml::lite::Element* monoXML = getOptional(refGeoXML, "Monostatic"); + const xml::lite::Element* biXML = getOptional(refGeoXML, "Bistatic"); + if (monoXML && !biXML) + { + refGeo.monostatic.reset(new Monostatic()); + parseCommon(monoXML, (ImagingType*)refGeo.monostatic.get()); + parseDouble(getFirstAndOnly(monoXML, "SlantRange"), refGeo.monostatic->slantRange); + parseDouble(getFirstAndOnly(monoXML, "GroundRange"), refGeo.monostatic->groundRange); + parseDouble(getFirstAndOnly(monoXML, "DopplerConeAngle"), refGeo.monostatic->dopplerConeAngle); + parseDouble(getFirstAndOnly(monoXML, "IncidenceAngle"), refGeo.monostatic->incidenceAngle); + mCommon.parseVector3D(getFirstAndOnly(monoXML, "ARPPos"), refGeo.monostatic->arpPos); + mCommon.parseVector3D(getFirstAndOnly(monoXML, "ARPVel"), refGeo.monostatic->arpVel); + std::string side = ""; + parseString(getFirstAndOnly(monoXML, "SideOfTrack"), side); + refGeo.monostatic->sideOfTrack = (side == "L" ? six::SideOfTrackType::LEFT : six::SideOfTrackType::RIGHT); + + } + else if (!monoXML && biXML) + { + refGeo.bistatic.reset(new Bistatic()); + parseCommon(biXML, (ImagingType*)refGeo.bistatic.get()); + parseDouble(getFirstAndOnly(biXML, "AzimuthAngleRate"), refGeo.bistatic->azimuthAngleRate); + parseDouble(getFirstAndOnly(biXML, "BistaticAngle"), refGeo.bistatic->bistaticAngle); + parseDouble(getFirstAndOnly(biXML, "BistaticAngleRate"), refGeo.bistatic->bistaticAngleRate); + + parsePlatformParams(getFirstAndOnly(biXML, "TxPlatform"), refGeo.bistatic->txPlatform); + parsePlatformParams(getFirstAndOnly(biXML, "RcvPlatform"), refGeo.bistatic->rcvPlatform); + } + else + { + throw except::Exception(Ctxt( + "One of the two types Mono or Bi must be provided")); + } +} + +std::vector CPHDXMLParser::parseSupportArray(const std::string& tag, const xml::lite::Element& parent) const +{ + std::vector elements; + parent.getElementsByTagName(tag, elements); + std::vector supportArray; + supportArray.reserve(elements.size()); + for (const auto& element : elements) + { + SupportArrayParameter param; + parseSupportArrayParameter(element, param, false /*additionalFlag*/); + supportArray.push_back(std::move(param)); + } + return supportArray; +} + +void CPHDXMLParser::fromXML(const xml::lite::Element* supportArrayXML, SupportArray& supportArray) +{ + supportArray.iazArray = parseSupportArray("IAZArray", *supportArrayXML); + supportArray.antGainPhase = parseSupportArray("AntGainPhase", *supportArrayXML); + supportArray.dwellTimeArray = parseSupportArray("DwellTimeArray", *supportArrayXML); + + std::vector addedSupportArrayXMLVec; + supportArrayXML->getElementsByTagName("AddedSupportArray", addedSupportArrayXMLVec); + for (size_t ii = 0; ii < addedSupportArrayXMLVec.size(); ++ii) + { + std::string id; + parseString(getFirstAndOnly(addedSupportArrayXMLVec[ii], "Identifier"), id); + if (supportArray.addedSupportArray.count(id) == 0) + { + parseSupportArrayParameter(addedSupportArrayXMLVec[ii], supportArray.addedSupportArray[id], true); + parseString(getFirstAndOnly(addedSupportArrayXMLVec[ii], "XUnits"), supportArray.addedSupportArray[id].xUnits); + parseString(getFirstAndOnly(addedSupportArrayXMLVec[ii], "YUnits"), supportArray.addedSupportArray[id].yUnits); + parseString(getFirstAndOnly(addedSupportArrayXMLVec[ii], "ZUnits"), supportArray.addedSupportArray[id].zUnits); + mCommon.parseParameters(addedSupportArrayXMLVec[ii], "Parameter", supportArray.addedSupportArray[id].parameter); + } + else + { + throw except::Exception(Ctxt( + "Support array identifier for support array is not unique: " + id)); + } + } +} + +void CPHDXMLParser::parse(const xml::lite::Element& parent, six::XsElement_minOccurs0& o) const +{ + if (const auto pXML = getOptional(parent, o.tag())) + { + o = AntPattern::EBFreqShiftSF{}; + six::getFirstAndOnly(parser(), *pXML, value(o).dcxsf); + six::getFirstAndOnly(parser(), *pXML, value(o).dcysf); + } +} + +void CPHDXMLParser::parse(const xml::lite::Element& parent, six::XsElement_minOccurs0& o) const +{ + if (const auto pXML = getOptional(parent, o.tag())) + { + o = AntPattern::MLFreqDilationSF{}; + six::getFirstAndOnly(parser(), *pXML, value(o).dcxsf); + six::getFirstAndOnly(parser(), *pXML, value(o).dcysf); + } +} + +void CPHDXMLParser::parse(const xml::lite::Element& parent, six::XsElement_minOccurs0& o) const +{ + if (const auto pXML = getOptional(parent, o.tag())) + { + o = AntPattern::AntPolRef{}; + six::getFirstAndOnly(parser(), *pXML, value(o).ampX); + six::getFirstAndOnly(parser(), *pXML, value(o).ampY); + six::getFirstAndOnly(parser(), *pXML, value(o).phaseY); + } +} + +void CPHDXMLParser::fromXML(const xml::lite::Element* antennaXML, Antenna& antenna) +{ + size_t numACFs = 0; + size_t numAPCs = 0; + size_t numAntPats = 0; + parseUInt(getFirstAndOnly(antennaXML, "NumACFs"), numACFs); + antenna.antCoordFrame.resize(numACFs); + parseUInt(getFirstAndOnly(antennaXML, "NumAPCs"), numAPCs); + antenna.antPhaseCenter.resize(numAPCs); + parseUInt(getFirstAndOnly(antennaXML, "NumAntPats"), numAntPats); + antenna.antPattern.resize(numAntPats); + + // Parse AntCoordFrame + std::vector antCoordFrameXMLVec; + antennaXML->getElementsByTagName("AntCoordFrame", antCoordFrameXMLVec); + if(antenna.antCoordFrame.size() != antCoordFrameXMLVec.size()) + { + throw except::Exception(Ctxt( + "Incorrect number of AntCoordFrames provided")); + } + for( size_t ii = 0; ii < antCoordFrameXMLVec.size(); ++ii) + { + parseString(getFirstAndOnly(antCoordFrameXMLVec[ii], "Identifier"), antenna.antCoordFrame[ii].identifier); + mCommon.parsePolyXYZ(getFirstAndOnly(antCoordFrameXMLVec[ii], "XAxisPoly"), antenna.antCoordFrame[ii].xAxisPoly); + mCommon.parsePolyXYZ(getFirstAndOnly(antCoordFrameXMLVec[ii], "YAxisPoly"), antenna.antCoordFrame[ii].yAxisPoly); + std::ignore = six::parse(parser(), *antCoordFrameXMLVec[ii], antenna.antCoordFrame[ii].useACFPVP); + } + + // Parse AntPhaseCenter + std::vector antPhaseCenterXMLVec; + antennaXML->getElementsByTagName("AntPhaseCenter", antPhaseCenterXMLVec); + if(antenna.antPhaseCenter.size() != antPhaseCenterXMLVec.size()) + { + throw except::Exception(Ctxt( + "Incorrect number of AntPhaseCenters provided")); + } + for( size_t ii = 0; ii < antPhaseCenterXMLVec.size(); ++ii) + { + parseString(getFirstAndOnly(antPhaseCenterXMLVec[ii], "Identifier"), antenna.antPhaseCenter[ii].identifier); + parseString(getFirstAndOnly(antPhaseCenterXMLVec[ii], "ACFId"), antenna.antPhaseCenter[ii].acfId); + mCommon.parseVector3D(getFirstAndOnly(antPhaseCenterXMLVec[ii], "APCXYZ"), antenna.antPhaseCenter[ii].apcXYZ); + } + + std::vector antPatternXMLVec; + antennaXML->getElementsByTagName("AntPattern", antPatternXMLVec); + if(antenna.antPattern.size() != antPatternXMLVec.size()) + { + throw except::Exception(Ctxt( + "Incorrect number of AntPatterns provided")); + } + for( size_t ii = 0; ii < antPatternXMLVec.size(); ++ii) + { + parseString(getFirstAndOnly(antPatternXMLVec[ii], "Identifier"), antenna.antPattern[ii].identifier); + parseDouble(getFirstAndOnly(antPatternXMLVec[ii], "FreqZero"), antenna.antPattern[ii].freqZero); + parseOptionalDouble(antPatternXMLVec[ii], "GainZero", antenna.antPattern[ii].gainZero); + + XMLElem ebFreqShiftXML = getOptional(antPatternXMLVec[ii], "EBFreqShift"); + if(ebFreqShiftXML) + { + parseBooleanType(ebFreqShiftXML, antenna.antPattern[ii].ebFreqShift); + } + parse(*antPatternXMLVec[ii], antenna.antPattern[ii].ebFreqShiftSF); + + XMLElem mlFreqDilationXML = getOptional(antPatternXMLVec[ii], "MLFreqDilation"); + if(mlFreqDilationXML) + { + parseBooleanType(mlFreqDilationXML, antenna.antPattern[ii].mlFreqDilation); + } + parse(*antPatternXMLVec[ii], antenna.antPattern[ii].mlFreqDilationSF); + + XMLElem gainBSPoly = getOptional(antPatternXMLVec[ii], "GainBSPoly"); + if(gainBSPoly) + { + mCommon.parsePoly1D(gainBSPoly, antenna.antPattern[ii].gainBSPoly); + } + + parse(*antPatternXMLVec[ii], antenna.antPattern[ii].antPolRef); + + // Parse EB + XMLElem ebXML = getFirstAndOnly(antPatternXMLVec[ii], "EB"); + mCommon.parsePoly1D(getFirstAndOnly(ebXML, "DCXPoly"), antenna.antPattern[ii].eb.dcxPoly); + mCommon.parsePoly1D(getFirstAndOnly(ebXML, "DCYPoly"), antenna.antPattern[ii].eb.dcyPoly); + std::ignore = six::parse(parser(), *ebXML, antenna.antPattern[ii].eb.useEBPVP); + + // Parse Array + XMLElem arrayXML = getFirstAndOnly(antPatternXMLVec[ii], "Array"); + mCommon.parsePoly2D(getFirstAndOnly(arrayXML, "GainPoly"), antenna.antPattern[ii].array.gainPoly); + mCommon.parsePoly2D(getFirstAndOnly(arrayXML, "PhasePoly"), antenna.antPattern[ii].array.phasePoly); + + // Parse Element + XMLElem elementXML = getFirstAndOnly(antPatternXMLVec[ii], "Element"); + mCommon.parsePoly2D(getFirstAndOnly(elementXML, "GainPoly"), antenna.antPattern[ii].element.gainPoly); + mCommon.parsePoly2D(getFirstAndOnly(elementXML, "PhasePoly"), antenna.antPattern[ii].element.phasePoly); + std::ignore = six::parse(parser(), *elementXML, antenna.antPattern[ii].element.antGPId); + + // Parse GainPhaseArray + std::vector gainPhaseArrayXMLVec; + antPatternXMLVec[ii]->getElementsByTagName("GainPhaseArray", gainPhaseArrayXMLVec); + antenna.antPattern[ii].gainPhaseArray.resize(gainPhaseArrayXMLVec.size()); + for (size_t jj = 0; jj < gainPhaseArrayXMLVec.size(); ++jj) + { + parseDouble(getFirstAndOnly(gainPhaseArrayXMLVec[jj], "Freq"), antenna.antPattern[ii].gainPhaseArray[jj].freq); + parseString(getFirstAndOnly(gainPhaseArrayXMLVec[jj], "ArrayId"), antenna.antPattern[ii].gainPhaseArray[jj].arrayId); + XMLElem elementIdXML = getOptional(gainPhaseArrayXMLVec[jj], "ElementId"); + if(elementIdXML) + { + parseString(elementIdXML, antenna.antPattern[ii].gainPhaseArray[jj].elementId); + } + + } + } +} + +void CPHDXMLParser::fromXML(const xml::lite::Element* txRcvXML, TxRcv& txRcv) +{ + size_t numTxWFs = 0; + size_t numRcvs = 0; + parseUInt(getFirstAndOnly(txRcvXML, "NumTxWFs"), numTxWFs); + txRcv.txWFParameters.resize(numTxWFs); + parseUInt(getFirstAndOnly(txRcvXML, "NumRcvs"), numRcvs); + txRcv.rcvParameters.resize(numRcvs); + + std::vector txWFXMLVec; + txRcvXML->getElementsByTagName("TxWFParameters", txWFXMLVec); + if(txRcv.txWFParameters.size() != txWFXMLVec.size()) + { + throw except::Exception(Ctxt( + "Incorrect number of TxWF parameters provided")); + } + for(size_t ii = 0; ii < txWFXMLVec.size(); ++ii) + { + parseTxRcvParameter(txWFXMLVec[ii], txRcv.txWFParameters[ii]); + parseDouble(getFirstAndOnly(txWFXMLVec[ii], "PulseLength"), txRcv.txWFParameters[ii].pulseLength); + parseDouble(getFirstAndOnly(txWFXMLVec[ii], "RFBandwidth"), txRcv.txWFParameters[ii].rfBandwidth); + parseOptionalDouble(txWFXMLVec[ii], "Power", txRcv.txWFParameters[ii].power); + } + + std::vector rcvXMLVec; + txRcvXML->getElementsByTagName("RcvParameters", rcvXMLVec); + if(txRcv.rcvParameters.size() != rcvXMLVec.size()) + { + throw except::Exception(Ctxt( + "Incorrect number of Rcv parameters provided")); + } + for(size_t ii = 0; ii < rcvXMLVec.size(); ++ii) + { + parseTxRcvParameter(rcvXMLVec[ii], txRcv.rcvParameters[ii]); + parseDouble(getFirstAndOnly(rcvXMLVec[ii], "WindowLength"), txRcv.rcvParameters[ii].windowLength); + parseDouble(getFirstAndOnly(rcvXMLVec[ii], "SampleRate"), txRcv.rcvParameters[ii].sampleRate); + parseDouble(getFirstAndOnly(rcvXMLVec[ii], "IFFilterBW"), txRcv.rcvParameters[ii].ifFilterBW); + parseOptionalDouble(rcvXMLVec[ii], "PathGain", txRcv.rcvParameters[ii].pathGain); + } + +} + +void CPHDXMLParser::fromXML(const xml::lite::Element* errParamXML, ErrorParameters& errParam) +{ + XMLElem monostaticXML = getOptional(errParamXML, "Monostatic"); + XMLElem bistaticXML = getOptional(errParamXML, "Bistatic"); + + if(monostaticXML && !bistaticXML) + { + errParam.monostatic.reset(new ErrorParameters::Monostatic()); + parsePosVelErr(getFirstAndOnly(monostaticXML, "PosVelErr"), errParam.monostatic->posVelErr); + + XMLElem radarSensorXML = getFirstAndOnly(monostaticXML, "RadarSensor"); + parseDouble(getFirstAndOnly(radarSensorXML, "RangeBias"), errParam.monostatic->radarSensor.rangeBias); + + parseOptionalDouble(radarSensorXML, "ClockFreqSF", errParam.monostatic->radarSensor.clockFreqSF); + parseOptionalDouble(radarSensorXML, "CollectionStartTime", errParam.monostatic->radarSensor.collectionStartTime); + + XMLElem rangeBiasDecorrXML = getOptional(radarSensorXML, "RangeBiasDecorr"); + if(rangeBiasDecorrXML) + { + errParam.monostatic->radarSensor.rangeBiasDecorr.reset(new six::DecorrType()); + mCommon.parseDecorrType(rangeBiasDecorrXML, *(errParam.monostatic->radarSensor.rangeBiasDecorr)); + } + + XMLElem tropoErrorXML = getOptional(monostaticXML, "TropoError"); + if(tropoErrorXML) + { + errParam.monostatic->tropoError.reset(new six::TropoError()); + parseOptionalDouble(tropoErrorXML, "TropoRangeVertical", errParam.monostatic->tropoError->tropoRangeVertical); + parseOptionalDouble(tropoErrorXML, "TropoRangeSlant", errParam.monostatic->tropoError->tropoRangeSlant); + mCommon.parseOptionalDecorrType(tropoErrorXML, "TropoRangeDecorr", errParam.monostatic->tropoError->tropoRangeDecorr); + } + + XMLElem ionoErrorXML = getOptional(monostaticXML, "IonoError"); + if(ionoErrorXML) + { + errParam.monostatic->ionoError.reset(new six::IonoError()); + parseDouble(getFirstAndOnly(ionoErrorXML, "IonoRangeVertical"), errParam.monostatic->ionoError->ionoRangeVertical); + + parseOptionalDouble(ionoErrorXML, "IonoRangeRateVertical", errParam.monostatic->ionoError->ionoRangeRateVertical); + parseOptionalDouble(ionoErrorXML, "IonoRgRgRateCC", errParam.monostatic->ionoError->ionoRgRgRateCC); + mCommon.parseOptionalDecorrType(ionoErrorXML, "IonoRangeVertDecorr", errParam.monostatic->ionoError->ionoRangeVertDecorr); + } + mCommon.parseParameters(monostaticXML, "Parameter", errParam.monostatic->parameter); + } + else if(!monostaticXML && bistaticXML) + { + errParam.bistatic.reset(new ErrorParameters::Bistatic()); + parsePlatform(getFirstAndOnly(bistaticXML, "TxPlatform"), errParam.bistatic->txPlatform); + parsePlatform(getFirstAndOnly(bistaticXML, "RcvPlatform"), errParam.bistatic->rcvPlatform); + mCommon.parseParameters(bistaticXML, "Parameter", errParam.bistatic->parameter); + } + else + { + throw except::Exception(Ctxt( + "Must be one of monostatic or bistatic")); + } +} + + +void CPHDXMLParser::fromXML(const xml::lite::Element* productInfoXML, ProductInfo& productInfo) +{ + XMLElem profileXML = getOptional(productInfoXML, "Profile"); + if(profileXML) + { + parseString(profileXML, productInfo.profile); + } + + std::vector creationInfoXML; + productInfoXML->getElementsByTagName("CreationInfo", creationInfoXML); + productInfo.creationInfo.resize(creationInfoXML.size()); + + for (size_t ii = 0; ii < creationInfoXML.size(); ++ii) + { + XMLElem applicationXML = getOptional(creationInfoXML[ii], "Application"); + if(applicationXML) + { + parseString(applicationXML, productInfo.creationInfo[ii].application); + } + + parseDateTime(getFirstAndOnly(creationInfoXML[ii], "DateTime"), productInfo.creationInfo[ii].dateTime); + + XMLElem siteXML = getOptional(creationInfoXML[ii], "Site"); + if(siteXML) + { + parseString(siteXML, productInfo.creationInfo[ii].site); + } + mCommon.parseParameters(creationInfoXML[ii], "Parameter", productInfo.creationInfo[ii].parameter); + } + mCommon.parseParameters(productInfoXML, "Parameter", productInfo.parameter); + +} + +void CPHDXMLParser::fromXML(const xml::lite::Element* geoInfoXML, GeoInfo& geoInfo) +{ + std::vector < XMLElem > geoInfosXML; + geoInfoXML->getElementsByTagName("GeoInfo", geoInfosXML); + geoInfo.name = geoInfoXML->getAttributes().getValue("name"); + + //optional + mCommon.parseParameters(geoInfoXML, "Desc", geoInfo.desc); + + XMLElem tmpElem = getOptional(geoInfoXML, "Point"); + if (tmpElem) + { + LatLon ll; + mCommon.parseLatLon(tmpElem, ll); + geoInfo.geometryLatLon.push_back(ll); + } + else + { + std::string pointName = "Endpoint"; + tmpElem = getOptional(geoInfoXML, "Line"); + if (!tmpElem) + { + pointName = "Vertex"; + tmpElem = getOptional(geoInfoXML, "Polygon"); + } + if (tmpElem) + { + mCommon.parseLatLons(tmpElem, pointName, geoInfo.geometryLatLon); + } + } + + //optional + size_t idx(geoInfo.geoInfos.size()); + geoInfo.geoInfos.resize(idx + geoInfosXML.size()); + + for (auto it = geoInfosXML.begin(); it + != geoInfosXML.end(); ++it, ++idx) + { + geoInfo.geoInfos[idx].reset(new GeoInfo()); + fromXML(*it, *geoInfo.geoInfos[idx]); + } +} + +void CPHDXMLParser::fromXML(const xml::lite::Element* matchInfoXML, MatchInformation& matchInfo) +{ + mCommon.parseMatchInformationFromXML(matchInfoXML, &matchInfo); +} + + +XMLElem CPHDXMLParser::createLatLonFootprint(const std::string& name, + const std::string& cornerName, + const cphd::LatLonCorners& corners, + XMLElem parent) const +{ + XMLElem footprint = newElement(name, parent); + + // Write the corners in CW order + XMLElem vertex = + mCommon.createLatLon(cornerName, corners.upperLeft, footprint); + setAttribute(vertex, "index", "1"); + + vertex = mCommon.createLatLon(cornerName, corners.upperRight, footprint); + setAttribute(vertex, "index", "2"); + + vertex = mCommon.createLatLon(cornerName, corners.lowerRight, footprint); + setAttribute(vertex, "index", "3"); + + vertex = mCommon.createLatLon(cornerName, corners.lowerLeft, footprint); + setAttribute(vertex, "index", "4"); + + return footprint; +} + +XMLElem CPHDXMLParser::createPVPType(const std::string& name, + const PVPType& p, + XMLElem parent) const +{ + XMLElem pvpXML = newElement(name, parent); + createInt("Offset", p.getOffset(), pvpXML); + createInt("Size", p.getSize(), pvpXML); + createString("Format", p.getFormat(), pvpXML); + return pvpXML; +} + +XMLElem CPHDXMLParser::createAPVPType(const std::string& name, + const APVPType& p, + XMLElem parent) const +{ + XMLElem apvpXML = newElement(name, parent); + createString("Name", p.getName(), apvpXML); + createInt("Offset", p.getOffset(), apvpXML); + createInt("Size", p.getSize(), apvpXML); + createString("Format", p.getFormat(), apvpXML); + return apvpXML; +} + +XMLElem CPHDXMLParser::createErrorParamPlatform( + const std::string& /*name*/, + const ErrorParameters::Bistatic::Platform p, + XMLElem parent) const +{ + XMLElem posVelErrXML = newElement("PosVelErr", parent); + createString("Frame", p.posVelErr.frame, posVelErrXML); + createDouble("P1", p.posVelErr.p1, posVelErrXML); + createDouble("P2", p.posVelErr.p2, posVelErrXML); + createDouble("P3", p.posVelErr.p3, posVelErrXML); + createDouble("V1", p.posVelErr.v1, posVelErrXML); + createDouble("V2", p.posVelErr.v2, posVelErrXML); + createDouble("V3", p.posVelErr.v3, posVelErrXML); + if(p.posVelErr.corrCoefs.get()) + { + XMLElem corrCoefsXML = newElement("CorrCoefs", posVelErrXML); + createDouble("P1P2", p.posVelErr.corrCoefs->p1p2, corrCoefsXML); + createDouble("P1P3", p.posVelErr.corrCoefs->p1p3, corrCoefsXML); + createDouble("P1V1", p.posVelErr.corrCoefs->p1v1, corrCoefsXML); + createDouble("P1V2", p.posVelErr.corrCoefs->p1v2, corrCoefsXML); + createDouble("P1V3", p.posVelErr.corrCoefs->p1v3, corrCoefsXML); + createDouble("P2P3", p.posVelErr.corrCoefs->p2p3, corrCoefsXML); + createDouble("P2V1", p.posVelErr.corrCoefs->p2v1, corrCoefsXML); + createDouble("P2V2", p.posVelErr.corrCoefs->p2v2, corrCoefsXML); + createDouble("P2V3", p.posVelErr.corrCoefs->p2v3, corrCoefsXML); + createDouble("P3V1", p.posVelErr.corrCoefs->p3v1, corrCoefsXML); + createDouble("P3V2", p.posVelErr.corrCoefs->p3v2, corrCoefsXML); + createDouble("P3V3", p.posVelErr.corrCoefs->p3v3, corrCoefsXML); + createDouble("V1V2", p.posVelErr.corrCoefs->v1v2, corrCoefsXML); + createDouble("V1V3", p.posVelErr.corrCoefs->v1v3, corrCoefsXML); + createDouble("V2V3", p.posVelErr.corrCoefs->v2v3, corrCoefsXML); + } + createDecorrType("PositionDecorr", p.posVelErr.positionDecorr, posVelErrXML); + return posVelErrXML; +} + +XMLElem CPHDXMLParser::createDecorrType(const std::string& name, const six::DecorrType& dt, + XMLElem parent) const +{ + if (six::Init::isDefined(dt)) + { + XMLElem element = newElement(name, parent); + createDouble("CorrCoefZero", dt.corrCoefZero, element); + createDouble("DecorrRate", dt.decorrRate, element); + return element; + } + return nullptr; +} +XMLElem CPHDXMLParser::createDecorrType(const std::string& name, const std::optional& dt, + XMLElem parent) const +{ + if (dt.has_value()) + { + return createDecorrType(name, *dt, parent); + } + return nullptr; +} + +/* + * Parser helper functions + */ +void CPHDXMLParser::parseAreaType(const xml::lite::Element* areaXML, AreaType& area) const +{ + mCommon.parseVector2D(getFirstAndOnly(areaXML, "X1Y1"), area.x1y1); + mCommon.parseVector2D(getFirstAndOnly(areaXML, "X2Y2"), area.x2y2); + const xml::lite::Element* polygonXML = getOptional(areaXML, "Polygon"); + if (polygonXML) + { + std::vector verticesXML; + polygonXML->getElementsByTagName("Vertex", verticesXML); + if (verticesXML.size() < 3) + { + throw except::Exception(Ctxt( + "Polygons must have at least 3 sides")); + } + area.polygon.resize(verticesXML.size()); + for (size_t ii = 0; ii < area.polygon.size(); ++ii) + { + Vector2& vertex = area.polygon[ii]; + const xml::lite::Element* vertexXML = verticesXML[ii]; + mCommon.parseVector2D(vertexXML, vertex); + } + } +} + +void CPHDXMLParser::parseLineSample(const xml::lite::Element* lsXML, LineSample& ls) const +{ + parseDouble(getFirstAndOnly(lsXML, "Line"), ls.line); + parseDouble(getFirstAndOnly(lsXML, "Sample"), ls.sample); +} + +void CPHDXMLParser::parseIAExtent(const xml::lite::Element* extentXML, + ImageAreaXExtent& extent) const +{ + parseDouble(getFirstAndOnly(extentXML, "LineSpacing"), + extent.lineSpacing); + parseInt(getFirstAndOnly(extentXML, "FirstLine"), + extent.firstLine); + parseUInt(getFirstAndOnly(extentXML, "NumLines"), + extent.numLines); +} + +void CPHDXMLParser::parseIAExtent(const xml::lite::Element* extentXML, + ImageAreaYExtent& extent) const +{ + parseDouble(getFirstAndOnly(extentXML, "SampleSpacing"), + extent.sampleSpacing); + parseInt(getFirstAndOnly(extentXML, "FirstSample"), + extent.firstSample); + parseUInt(getFirstAndOnly(extentXML, "NumSamples"), + extent.numSamples); +} + +void CPHDXMLParser::parseChannelParameters( + const xml::lite::Element* paramXML, ChannelParameter& param) const +{ + parseString(getFirstAndOnly(paramXML, "Identifier"), param.identifier); + parseUInt(getFirstAndOnly(paramXML, "RefVectorIndex"), param.refVectorIndex); + parseBooleanType(getFirstAndOnly(paramXML, "FXFixed"), param.fxFixed); + parseBooleanType(getFirstAndOnly(paramXML, "TOAFixed"), param.toaFixed); + parseBooleanType(getFirstAndOnly(paramXML, "SRPFixed"), param.srpFixed); + + XMLElem signalXML = getOptional(paramXML, "SignalNormal"); + if (signalXML) + { + parseBooleanType(signalXML, param.signalNormal); + } + + parseDouble(getFirstAndOnly(paramXML, "FxC"), param.fxC); + parseDouble(getFirstAndOnly(paramXML, "FxBW"), param.fxBW); + parseOptionalDouble(paramXML, "FxBWNoise", param.fxBWNoise); + parseDouble(getFirstAndOnly(paramXML, "TOASaved"), param.toaSaved); + + XMLElem toaExtendedXML = getOptional(paramXML, "TOAExtended"); + if(toaExtendedXML) + { + param.toaExtended.reset(new TOAExtended()); + parseDouble(getFirstAndOnly(toaExtendedXML, "TOAExtSaved"), param.toaExtended->toaExtSaved); + XMLElem lfmEclipseXML = getOptional(toaExtendedXML, "LFMEclipse"); + if(lfmEclipseXML) + { + param.toaExtended->lfmEclipse.reset(new TOAExtended::LFMEclipse()); + parseDouble(getFirstAndOnly(lfmEclipseXML, "FxEarlyLow"), param.toaExtended->lfmEclipse->fxEarlyLow); + parseDouble(getFirstAndOnly(lfmEclipseXML, "FxEarlyHigh"), param.toaExtended->lfmEclipse->fxEarlyHigh); + parseDouble(getFirstAndOnly(lfmEclipseXML, "FxLateLow"), param.toaExtended->lfmEclipse->fxLateLow); + parseDouble(getFirstAndOnly(lfmEclipseXML, "FxLateHigh"), param.toaExtended->lfmEclipse->fxLateHigh); + } + } + + XMLElem dwellTimesXML = getFirstAndOnly(paramXML, "DwellTimes"); + parseString(getFirstAndOnly(dwellTimesXML, "CODId"), param.dwellTimes.codId); + parseString(getFirstAndOnly(dwellTimesXML, "DwellId"), param.dwellTimes.dwellId); + std::ignore = six::parse(parser(), *dwellTimesXML, param.dwellTimes.dtaId); + std::ignore = six::parse(parser(), *dwellTimesXML, param.dwellTimes.useDTA); + + XMLElem imageAreaXML = getOptional(paramXML, "ImageArea"); + if(imageAreaXML) + { + parseAreaType(imageAreaXML, param.imageArea); + } + + XMLElem antennaXML = getOptional(paramXML, "Antenna"); + if(antennaXML) + { + param.antenna.reset(new ChannelParameter::Antenna()); + parseString(getFirstAndOnly(antennaXML, "TxAPCId"), param.antenna->txAPCId); + parseString(getFirstAndOnly(antennaXML, "TxAPATId"), param.antenna->txAPATId); + parseString(getFirstAndOnly(antennaXML, "RcvAPCId"), param.antenna->rcvAPCId); + parseString(getFirstAndOnly(antennaXML, "RcvAPATId"), param.antenna->rcvAPATId); + } + + XMLElem txRcvXML = getOptional(paramXML, "TxRcv"); + if(txRcvXML) + { + std::vector txWFIdXML; + txRcvXML->getElementsByTagName("TxWFId", txWFIdXML); + param.txRcv.reset(new ChannelParameter::TxRcv()); + param.txRcv->txWFId.resize(txWFIdXML.size()); + for(size_t ii = 0; ii < txWFIdXML.size(); ++ii) + { + parseString(txWFIdXML[ii], param.txRcv->txWFId[ii]); + } + + std::vector rcvIdXML; + txRcvXML->getElementsByTagName("RcvId", rcvIdXML); + param.txRcv->rcvId.resize(rcvIdXML.size()); + for(size_t ii = 0; ii < rcvIdXML.size(); ++ii) + { + parseString(rcvIdXML[ii], param.txRcv->rcvId[ii]); + } + } + + XMLElem tgtRefLevelXML = getOptional(paramXML, "TgtRefLevel"); + if(tgtRefLevelXML) + { + param.tgtRefLevel.reset(new TgtRefLevel()); + parseDouble(getFirstAndOnly(tgtRefLevelXML, "PTRef"), param.tgtRefLevel->ptRef); + } + + XMLElem noiseLevelXML = getOptional(paramXML, "NoiseLevel"); + if(noiseLevelXML) + { + param.noiseLevel.reset(new NoiseLevel()); + parseDouble(getFirstAndOnly(noiseLevelXML, "PNRef"), param.noiseLevel->pnRef); + parseDouble(getFirstAndOnly(noiseLevelXML, "BNRef"), param.noiseLevel->bnRef); + if(!(param.noiseLevel->bnRef > 0 && param.noiseLevel->bnRef <= 1)) + { + throw except::Exception(Ctxt( + "Noise equivalent BW value must be > 0.0 and <= 1.0")); + } + + XMLElem fxNoiseProfileXML = getOptional(noiseLevelXML, "FxNoiseProfile"); + if(fxNoiseProfileXML) + { + param.noiseLevel->fxNoiseProfile.reset(new FxNoiseProfile()); + std::vector pointXMLVec; + fxNoiseProfileXML->getElementsByTagName("Point", pointXMLVec); + if(pointXMLVec.size() < 2) + { + throw except::Exception(Ctxt( + "Atleast 2 noise profile points must be provided")); + } + param.noiseLevel->fxNoiseProfile->point.resize(pointXMLVec.size()); + double prevPoint = six::Init::undefined(); + for(size_t ii = 0; ii < pointXMLVec.size(); ++ii) + { + double fx; + parseDouble(getFirstAndOnly(pointXMLVec[ii], "Fx"), fx); + parseDouble(getFirstAndOnly(pointXMLVec[ii], "PN"), param.noiseLevel->fxNoiseProfile->point[ii].pn); + + if(!six::Init::isUndefined(prevPoint) && fx <= prevPoint) + { + throw except::Exception(Ctxt( + "Fx values are strictly increasing")); + } + param.noiseLevel->fxNoiseProfile->point[ii].fx = fx; + prevPoint = fx; + } + } + } + + // Polarization + parsePolarization(*paramXML, param.polarization); +} + +void CPHDXMLParser::parse(const xml::lite::Element& polarizationXML, six::XsElement_minOccurs0& o) const +{ + if (const auto pXML = getOptional(polarizationXML, o.tag())) + { + o = PolRef{}; + six::getFirstAndOnly(parser(), *pXML, value(o).ampH); + six::getFirstAndOnly(parser(), *pXML, value(o).ampV); + six::getFirstAndOnly(parser(), *pXML, value(o).phaseV); + } +} + +void CPHDXMLParser::parsePolarization(const xml::lite::Element& paramXML, Polarization& polarization) const +{ + std::vector PolarizationXML; + paramXML.getElementsByTagName("Polarization", PolarizationXML); + for (size_t ii = 0; ii < PolarizationXML.size(); ++ii) + { + const xml::lite::Element* TxPolXML = getFirstAndOnly(PolarizationXML[ii], "TxPol"); + polarization.txPol = PolarizationType::toType(TxPolXML->getCharacterData()); + + const xml::lite::Element* RcvPolXML = getFirstAndOnly(PolarizationXML[ii], "RcvPol"); + polarization.rcvPol = PolarizationType::toType(RcvPolXML->getCharacterData()); + + parse(*(PolarizationXML[ii]), polarization.txPolRef); // added in CPHD 1.1.0 + parse(*(PolarizationXML[ii]), polarization.rcvPolRef); // added in CPHD 1.1.0 + } +} + +size_t CPHDXMLParser::parsePVPType(const xml::lite::Element& paramXML, PVPType& param) const +{ + size_t size; + size_t offset; + std::string format; + parseUInt(getFirstAndOnly(paramXML, "Size"), size); + parseUInt(getFirstAndOnly(paramXML, "Offset"), offset); + parseString(getFirstAndOnly(paramXML, "Format"), format); + if (param.getSize() != size) + { + std::ostringstream ostr; + ostr << "Specified size: " << size << " does not match default size: " << param.getSize(); + throw except::Exception(Ctxt(ostr.str())); + } + if (param.getFormat() != format) + { + std::ostringstream ostr; + ostr << "Specified format: " << format << " does not match default format: " << param.getFormat(); + throw except::Exception(Ctxt(ostr.str())); + } + return offset; +} +void CPHDXMLParser::parsePVPType(Pvp& pvp, const xml::lite::Element* paramXML, PVPType& param) const +{ + const auto offset = parsePVPType(*paramXML, param); + pvp.setOffset(offset, param); +} + +void CPHDXMLParser::parsePVPType(Pvp& pvp, const xml::lite::Element* paramXML) const +{ + std::string name; + size_t size; + size_t offset; + std::string format; + parseString(getFirstAndOnly(paramXML, "Name"), name); + parseUInt(getFirstAndOnly(paramXML, "Size"), size); + parseUInt(getFirstAndOnly(paramXML, "Offset"), offset); + parseString(getFirstAndOnly(paramXML, "Format"), format); + pvp.setCustomParameter(size, offset, format, name); +} + +bool CPHDXMLParser::parseOptionalPVPType(const xml::lite::Element* parent, const std::string& tag, Pvp& pvp, PVPType& param) const +{ + if (const xml::lite::Element* const element = getOptional(parent, tag)) + { + parsePVPType(pvp, element, param); + return true; + } + return false; +} + +void CPHDXMLParser::parsePlatformParams(const xml::lite::Element* platXML, Bistatic::PlatformParams& plat) const +{ + parseDouble(getFirstAndOnly(platXML, "Time"), plat.time); + parseDouble(getFirstAndOnly(platXML, "SlantRange"), plat.slantRange); + parseDouble(getFirstAndOnly(platXML, "GroundRange"), plat.groundRange); + parseDouble(getFirstAndOnly(platXML, "DopplerConeAngle"), plat.dopplerConeAngle); + parseDouble(getFirstAndOnly(platXML, "AzimuthAngle"), plat.azimuthAngle); + parseDouble(getFirstAndOnly(platXML, "GrazeAngle"), plat.grazeAngle); + parseDouble(getFirstAndOnly(platXML, "IncidenceAngle"), plat.incidenceAngle); + mCommon.parseVector3D(getFirstAndOnly(platXML, "Pos"), plat.pos); + mCommon.parseVector3D(getFirstAndOnly(platXML, "Vel"), plat.vel); + std::string side = ""; + parseString(getFirstAndOnly(platXML, "SideOfTrack"), side); + plat.sideOfTrack = (side == "L" ? six::SideOfTrackType::LEFT : six::SideOfTrackType::RIGHT); + +} + +void CPHDXMLParser::parseCommon(const xml::lite::Element* imgTypeXML, ImagingType* imgType) const +{ + parseDouble(getFirstAndOnly(imgTypeXML, "TwistAngle"), imgType->twistAngle); + parseDouble(getFirstAndOnly(imgTypeXML, "SlopeAngle"), imgType->slopeAngle); + parseDouble(getFirstAndOnly(imgTypeXML, "LayoverAngle"), imgType->layoverAngle); + parseDouble(getFirstAndOnly(imgTypeXML, "AzimuthAngle"), imgType->azimuthAngle); + parseDouble(getFirstAndOnly(imgTypeXML, "GrazeAngle"), imgType->grazeAngle); +} + +void CPHDXMLParser::parsePosVelErr(const xml::lite::Element* posVelErrXML, six::PosVelError& posVelErr) const +{ + std::string frameStr; + parseString(getFirstAndOnly(posVelErrXML, "Frame"), frameStr); + posVelErr.frame.mValue = scene::FrameType::fromString(frameStr); + parseDouble(getFirstAndOnly(posVelErrXML, "P1"), posVelErr.p1); + parseDouble(getFirstAndOnly(posVelErrXML, "P2"), posVelErr.p2); + parseDouble(getFirstAndOnly(posVelErrXML, "P3"), posVelErr.p3); + parseDouble(getFirstAndOnly(posVelErrXML, "V1"), posVelErr.v1); + parseDouble(getFirstAndOnly(posVelErrXML, "V2"), posVelErr.v2); + parseDouble(getFirstAndOnly(posVelErrXML, "V3"), posVelErr.v3); + + XMLElem corrCoefsXML = getOptional(posVelErrXML, "CorrCoefs"); + + if(corrCoefsXML) + { + posVelErr.corrCoefs.reset(new six::CorrCoefs()); + parseDouble(getFirstAndOnly(corrCoefsXML, "P1P2"), posVelErr.corrCoefs->p1p2); + parseDouble(getFirstAndOnly(corrCoefsXML, "P1P3"), posVelErr.corrCoefs->p1p3); + parseDouble(getFirstAndOnly(corrCoefsXML, "P1V1"), posVelErr.corrCoefs->p1v1); + parseDouble(getFirstAndOnly(corrCoefsXML, "P1V2"), posVelErr.corrCoefs->p1v2); + parseDouble(getFirstAndOnly(corrCoefsXML, "P1V3"), posVelErr.corrCoefs->p1v3); + parseDouble(getFirstAndOnly(corrCoefsXML, "P2P3"), posVelErr.corrCoefs->p2p3); + parseDouble(getFirstAndOnly(corrCoefsXML, "P2V1"), posVelErr.corrCoefs->p2v1); + parseDouble(getFirstAndOnly(corrCoefsXML, "P2V2"), posVelErr.corrCoefs->p2v2); + parseDouble(getFirstAndOnly(corrCoefsXML, "P2V3"), posVelErr.corrCoefs->p2v3); + parseDouble(getFirstAndOnly(corrCoefsXML, "P3V1"), posVelErr.corrCoefs->p3v1); + parseDouble(getFirstAndOnly(corrCoefsXML, "P3V2"), posVelErr.corrCoefs->p3v2); + parseDouble(getFirstAndOnly(corrCoefsXML, "P3V3"), posVelErr.corrCoefs->p3v3); + parseDouble(getFirstAndOnly(corrCoefsXML, "V1V2"), posVelErr.corrCoefs->v1v2); + parseDouble(getFirstAndOnly(corrCoefsXML, "V1V3"), posVelErr.corrCoefs->v1v3); + parseDouble(getFirstAndOnly(corrCoefsXML, "V2V3"), posVelErr.corrCoefs->v2v3); + } + + // posVelErr.positionDecorr.reset(new six::DecorrType()); + mCommon.parseOptionalDecorrType(posVelErrXML, "PositionDecorr", posVelErr.positionDecorr); +} + +void CPHDXMLParser::parsePlatform(const xml::lite::Element* platXML, ErrorParameters::Bistatic::Platform& plat) const +{ + parsePosVelErr(getFirstAndOnly(platXML, "PosVelErr"), plat.posVelErr); + XMLElem radarSensorXML = getFirstAndOnly(platXML, "RadarSensor"); + six::parse(parser(), *radarSensorXML, plat.radarSensor.delayBias); + parseOptionalDouble(radarSensorXML, "ClockFreqSF", plat.radarSensor.clockFreqSF); + parseDouble(getFirstAndOnly(radarSensorXML, "CollectionStartTime"), plat.radarSensor.collectionStartTime); +} + +void CPHDXMLParser::parseSupportArrayParameter(const xml::lite::Element* paramXML, SupportArrayParameter& param, bool additionalFlag) const +{ + if(!additionalFlag) + { + size_t identifierVal; + parseUInt(getFirstAndOnly(paramXML, "Identifier"), identifierVal); + param.setIdentifier(identifierVal); + } + parseString(getFirstAndOnly(paramXML, "ElementFormat"), param.elementFormat); + parseDouble(getFirstAndOnly(paramXML, "X0"), param.x0); + parseDouble(getFirstAndOnly(paramXML, "Y0"), param.y0); + parseDouble(getFirstAndOnly(paramXML, "XSS"), param.xSS); + parseDouble(getFirstAndOnly(paramXML, "YSS"), param.ySS); +} + +void CPHDXMLParser::parseTxRcvParameter(const xml::lite::Element* paramXML, ParameterType& param) const +{ + parseString(getFirstAndOnly(paramXML, "Identifier"), param.identifier); + parseDouble(getFirstAndOnly(paramXML, "FreqCenter"), param.freqCenter); + parseOptionalDouble(paramXML, "LFMRate", param.lfmRate); + param.polarization = PolarizationType::toType(getFirstAndOnly(paramXML, "Polarization")->getCharacterData()); +} +} diff --git a/six/modules/c++/cphd/source/Channel.cpp b/six/modules/c++/cphd/source/Channel.cpp index 351303a402..e9e6df6ad0 100644 --- a/six/modules/c++/cphd/source/Channel.cpp +++ b/six/modules/c++/cphd/source/Channel.cpp @@ -1,227 +1,227 @@ -/* ========================================================================= - * This file is part of cphd-c++ - * ========================================================================= - * - * (C) Copyright 2004 - 2019, MDA Information Systems LLC - * - * cphd-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ -#include - -#include - -#include - -namespace cphd -{ - -TOAExtended::TOAExtended() : - toaExtSaved(six::Init::undefined()) -{ -} - -TOAExtended::LFMEclipse::LFMEclipse() : - fxEarlyLow(six::Init::undefined()), - fxEarlyHigh(six::Init::undefined()), - fxLateLow(six::Init::undefined()), - fxLateHigh(six::Init::undefined()) -{ -} - -DwellTimes::DwellTimes() -{ -} - -TgtRefLevel::TgtRefLevel() : - ptRef(six::Init::undefined()) -{ -} - -Point::Point() : - fx(six::Init::undefined()), - pn(six::Init::undefined()) -{ -} - -NoiseLevel::NoiseLevel() : - pnRef(six::Init::undefined()), - bnRef(six::Init::undefined()) -{ -} - -ChannelParameter::ChannelParameter() : - refVectorIndex(six::Init::undefined()), - fxFixed(six::Init::undefined()), - toaFixed(six::Init::undefined()), - srpFixed(six::Init::undefined()), - signalNormal(six::Init::undefined()), - fxC(six::Init::undefined()), - fxBW(six::Init::undefined()), - fxBWNoise(six::Init::undefined()), - toaSaved(six::Init::undefined()) -{ -} - -ChannelParameter::Antenna::Antenna() -{ -} - -Channel::Channel() : - fxFixedCphd(six::Init::undefined()), - toaFixedCphd(six::Init::undefined()), - srpFixedCphd(six::Init::undefined()) -{ -} - -std::ostream& operator<< (std::ostream& os, const PolRef& v) -{ - os << v.ampH << v.ampV << v.phaseV << "\n"; - return os; -} - -std::ostream& operator<< (std::ostream& os, const Polarization& p) -{ - os << " TxPol : " << p.txPol << "\n" - << " RcvPol : " << p.rcvPol << "\n" - << p.txPolRef << p.rcvPolRef; - return os; -} - -std::ostream& operator<< (std::ostream& os, const TOAExtended& t) -{ - os << " TOAExtended:: \n" - << " TOAExtSaved : " << t.toaExtSaved << "\n" - << " LFMEclipse:: \n" - << " FxEarlyLow : " << t.lfmEclipse->fxEarlyLow << "\n" - << " FxEarlyHigh : " << t.lfmEclipse->fxEarlyHigh << "\n" - << " FxLateLow : " << t.lfmEclipse->fxLateLow << "\n" - << " FxLateHigh : " << t.lfmEclipse->fxLateHigh << "\n"; - return os; -} - -std::ostream& operator<< (std::ostream& os, const DwellTimes& d) -{ - os << " DwellTimes:: \n" - << " CODId : " << d.codId << "\n" - << " DwellId : " << d.dwellId << "\n" - << d.dtaId - << d.useDTA; - return os; -} - -std::ostream& operator<< (std::ostream& os, const TgtRefLevel& t) -{ - os << " TgtRefLevel:: \n" - << " PtRef : " << t.ptRef << "\n"; - return os; -} - -std::ostream& operator<< (std::ostream& os, const Point& p) -{ - os << " Point:: \n" - << " Fx : " << p.fx << "\n" - << " Pn : " << p.pn << "\n"; - return os; -} - -std::ostream& operator<< (std::ostream& os, const FxNoiseProfile& f) -{ - os << " FxNoiseProfile:: \n"; - for (const auto& point : f.point) - { - os << " Point : " << point << "\n"; - } - return os; -} - -std::ostream& operator<< (std::ostream& os, const NoiseLevel& n) -{ - os << " NoiseLevel:: \n" - << " PnRef : " << n.pnRef << "\n" - << " BnRef : " << n.bnRef << "\n"; - if(n.fxNoiseProfile.get()) - { - os << *(n.fxNoiseProfile) << "\n"; - } - return os; -} - -std::ostream& operator<< (std::ostream& os, const ChannelParameter& c) -{ - os << " ChannelParameter:: \n" - << " Identifier : " << c.identifier << "\n" - << " RefVectorIndex : " << c.refVectorIndex << "\n" - << " FxFixed : " << c.fxFixed << "\n" - << " TOAFixed : " << c.toaFixed << "\n" - << " SRPFixed : " << c.srpFixed << "\n" - << " SginalNormal : " << c.signalNormal << "\n" - << " Polarization:: \n" - << c.polarization << "\n" - << " FxC : " << c.fxC << "\n" - << " FxBW : " << c.fxBW << "\n" - << " FxBWNoise : " << c.fxBWNoise << "\n" - << " TOASaved : " << c.toaSaved << "\n"; - if (c.toaExtended.get()) - { - os << *(c.toaExtended) << "\n"; - } - os << c.dwellTimes << "\n" - << c.imageArea << "\n" - << " Antenna:: \n" - << " TxAPCId : " << c.antenna->txAPCId << "\n" - << " TxAPATId : " << c.antenna->txAPATId << "\n" - << " RcvAPCId : " << c.antenna->rcvAPCId << "\n" - << " RcvAPATId : " << c.antenna->rcvAPATId << "\n" - << " TxRcv:: \n"; - for (size_t ii = 0; ii < c.txRcv->txWFId.size(); ++ii) - { - os << " TxWFId : " << c.txRcv->txWFId[ii] << "\n"; - } - for (size_t ii = 0; ii < c.txRcv->rcvId.size(); ++ii) - { - os << " RcvId : " << c.txRcv->rcvId[ii] << "\n"; - } - if (c.tgtRefLevel.get()) - { - os << *(c.tgtRefLevel) << "\n"; - } - if (c.noiseLevel.get()) - { - os << *(c.noiseLevel) << "\n"; - } - return os; -} - -std::ostream& operator<< (std::ostream& os, const Channel& c) -{ - os << "Channel:: \n" - << " RefChId : " << c.refChId << "\n" - << " FxFixedCphd : " << c.fxFixedCphd << "\n" - << " TOAFixedCphd : " << c.toaFixedCphd << "\n" - << " SRPFixedCphd : " << c.srpFixedCphd << "\n" - << " Parameters:: \n"; - for (size_t ii = 0; ii < c.parameters.size(); ++ii) - { - os << c.parameters[ii] << "\n"; - } - for (size_t ii = 0; ii < c.addedParameters.size(); ++ii) - { - os << " Parameter name : " << c.addedParameters[ii].getName() << "\n"; - os << " Parameter value : " << c.addedParameters[ii].str() << "\n"; - } - return os; -} -} +/* ========================================================================= + * This file is part of cphd-c++ + * ========================================================================= + * + * (C) Copyright 2004 - 2019, MDA Information Systems LLC + * + * cphd-c++ is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; If not, + * see . + * + */ +#include + +#include + +#include + +namespace cphd +{ + +TOAExtended::TOAExtended() : + toaExtSaved(six::Init::undefined()) +{ +} + +TOAExtended::LFMEclipse::LFMEclipse() : + fxEarlyLow(six::Init::undefined()), + fxEarlyHigh(six::Init::undefined()), + fxLateLow(six::Init::undefined()), + fxLateHigh(six::Init::undefined()) +{ +} + +DwellTimes::DwellTimes() +{ +} + +TgtRefLevel::TgtRefLevel() : + ptRef(six::Init::undefined()) +{ +} + +Point::Point() : + fx(six::Init::undefined()), + pn(six::Init::undefined()) +{ +} + +NoiseLevel::NoiseLevel() : + pnRef(six::Init::undefined()), + bnRef(six::Init::undefined()) +{ +} + +ChannelParameter::ChannelParameter() : + refVectorIndex(six::Init::undefined()), + fxFixed(six::Init::undefined()), + toaFixed(six::Init::undefined()), + srpFixed(six::Init::undefined()), + signalNormal(six::Init::undefined()), + fxC(six::Init::undefined()), + fxBW(six::Init::undefined()), + fxBWNoise(six::Init::undefined()), + toaSaved(six::Init::undefined()) +{ +} + +ChannelParameter::Antenna::Antenna() +{ +} + +Channel::Channel() : + fxFixedCphd(six::Init::undefined()), + toaFixedCphd(six::Init::undefined()), + srpFixedCphd(six::Init::undefined()) +{ +} + +std::ostream& operator<< (std::ostream& os, const PolRef& v) +{ + os << v.ampH << v.ampV << v.phaseV << "\n"; + return os; +} + +std::ostream& operator<< (std::ostream& os, const Polarization& p) +{ + os << " TxPol : " << p.txPol << "\n" + << " RcvPol : " << p.rcvPol << "\n" + << p.txPolRef << p.rcvPolRef; + return os; +} + +std::ostream& operator<< (std::ostream& os, const TOAExtended& t) +{ + os << " TOAExtended:: \n" + << " TOAExtSaved : " << t.toaExtSaved << "\n" + << " LFMEclipse:: \n" + << " FxEarlyLow : " << t.lfmEclipse->fxEarlyLow << "\n" + << " FxEarlyHigh : " << t.lfmEclipse->fxEarlyHigh << "\n" + << " FxLateLow : " << t.lfmEclipse->fxLateLow << "\n" + << " FxLateHigh : " << t.lfmEclipse->fxLateHigh << "\n"; + return os; +} + +std::ostream& operator<< (std::ostream& os, const DwellTimes& d) +{ + os << " DwellTimes:: \n" + << " CODId : " << d.codId << "\n" + << " DwellId : " << d.dwellId << "\n" + << d.dtaId + << d.useDTA; + return os; +} + +std::ostream& operator<< (std::ostream& os, const TgtRefLevel& t) +{ + os << " TgtRefLevel:: \n" + << " PtRef : " << t.ptRef << "\n"; + return os; +} + +std::ostream& operator<< (std::ostream& os, const Point& p) +{ + os << " Point:: \n" + << " Fx : " << p.fx << "\n" + << " Pn : " << p.pn << "\n"; + return os; +} + +std::ostream& operator<< (std::ostream& os, const FxNoiseProfile& f) +{ + os << " FxNoiseProfile:: \n"; + for (const auto& point : f.point) + { + os << " Point : " << point << "\n"; + } + return os; +} + +std::ostream& operator<< (std::ostream& os, const NoiseLevel& n) +{ + os << " NoiseLevel:: \n" + << " PnRef : " << n.pnRef << "\n" + << " BnRef : " << n.bnRef << "\n"; + if(n.fxNoiseProfile.get()) + { + os << *(n.fxNoiseProfile) << "\n"; + } + return os; +} + +std::ostream& operator<< (std::ostream& os, const ChannelParameter& c) +{ + os << " ChannelParameter:: \n" + << " Identifier : " << c.identifier << "\n" + << " RefVectorIndex : " << c.refVectorIndex << "\n" + << " FxFixed : " << c.fxFixed << "\n" + << " TOAFixed : " << c.toaFixed << "\n" + << " SRPFixed : " << c.srpFixed << "\n" + << " SginalNormal : " << c.signalNormal << "\n" + << " Polarization:: \n" + << c.polarization << "\n" + << " FxC : " << c.fxC << "\n" + << " FxBW : " << c.fxBW << "\n" + << " FxBWNoise : " << c.fxBWNoise << "\n" + << " TOASaved : " << c.toaSaved << "\n"; + if (c.toaExtended.get()) + { + os << *(c.toaExtended) << "\n"; + } + os << c.dwellTimes << "\n" + << c.imageArea << "\n" + << " Antenna:: \n" + << " TxAPCId : " << c.antenna->txAPCId << "\n" + << " TxAPATId : " << c.antenna->txAPATId << "\n" + << " RcvAPCId : " << c.antenna->rcvAPCId << "\n" + << " RcvAPATId : " << c.antenna->rcvAPATId << "\n" + << " TxRcv:: \n"; + for (size_t ii = 0; ii < c.txRcv->txWFId.size(); ++ii) + { + os << " TxWFId : " << c.txRcv->txWFId[ii] << "\n"; + } + for (size_t ii = 0; ii < c.txRcv->rcvId.size(); ++ii) + { + os << " RcvId : " << c.txRcv->rcvId[ii] << "\n"; + } + if (c.tgtRefLevel.get()) + { + os << *(c.tgtRefLevel) << "\n"; + } + if (c.noiseLevel.get()) + { + os << *(c.noiseLevel) << "\n"; + } + return os; +} + +std::ostream& operator<< (std::ostream& os, const Channel& c) +{ + os << "Channel:: \n" + << " RefChId : " << c.refChId << "\n" + << " FxFixedCphd : " << c.fxFixedCphd << "\n" + << " TOAFixedCphd : " << c.toaFixedCphd << "\n" + << " SRPFixedCphd : " << c.srpFixedCphd << "\n" + << " Parameters:: \n"; + for (size_t ii = 0; ii < c.parameters.size(); ++ii) + { + os << c.parameters[ii] << "\n"; + } + for (size_t ii = 0; ii < c.addedParameters.size(); ++ii) + { + os << " Parameter name : " << c.addedParameters[ii].getName() << "\n"; + os << " Parameter value : " << c.addedParameters[ii].str() << "\n"; + } + return os; +} +} diff --git a/six/modules/c++/cphd/source/Dwell.cpp b/six/modules/c++/cphd/source/Dwell.cpp index c3e5ef39c1..16d77eb0a5 100644 --- a/six/modules/c++/cphd/source/Dwell.cpp +++ b/six/modules/c++/cphd/source/Dwell.cpp @@ -1,73 +1,73 @@ -/* ========================================================================= - * This file is part of cphd-c++ - * ========================================================================= - * - * (C) Copyright 2004 - 2019, MDA Information Systems LLC - * - * cphd-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ -#include -#include - -namespace cphd -{ - -DwellTime::DwellTime() : - dwellTimePoly(six::Init::undefined()) -{ -} - -COD::COD() : - codTimePoly(six::Init::undefined()) -{ -} - -Dwell::Dwell() -{ -} - -std::ostream& operator<< (std::ostream& os, const DwellTime& d) -{ - os << " DwellTime:: \n" - << " Identifier : " << d.identifier << "\n" - << " DwellTimePoly : " << d.dwellTimePoly << "\n"; - return os; -} - -std::ostream& operator<< (std::ostream& os, const COD& c) -{ - os << " COD:: \n" - << " Identifier : " << c.identifier << "\n" - << " CODTimePoly : " << c.codTimePoly << "\n"; - return os; -} - -std::ostream& operator<< (std::ostream& os, const Dwell& d) -{ - os << "Dwell:: \n" - << " NumCODTimes : " << d.cod.size() << "\n" - << " NumDwellTimes : " << d.dtime.size() << "\n"; - for (const auto& cod : d.cod) - { - os << cod << "\n"; - } - for (const auto& dtime : d.dtime) - { - os << dtime << "\n"; - } - return os; -} -} +/* ========================================================================= + * This file is part of cphd-c++ + * ========================================================================= + * + * (C) Copyright 2004 - 2019, MDA Information Systems LLC + * + * cphd-c++ is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; If not, + * see . + * + */ +#include +#include + +namespace cphd +{ + +DwellTime::DwellTime() : + dwellTimePoly(six::Init::undefined()) +{ +} + +COD::COD() : + codTimePoly(six::Init::undefined()) +{ +} + +Dwell::Dwell() +{ +} + +std::ostream& operator<< (std::ostream& os, const DwellTime& d) +{ + os << " DwellTime:: \n" + << " Identifier : " << d.identifier << "\n" + << " DwellTimePoly : " << d.dwellTimePoly << "\n"; + return os; +} + +std::ostream& operator<< (std::ostream& os, const COD& c) +{ + os << " COD:: \n" + << " Identifier : " << c.identifier << "\n" + << " CODTimePoly : " << c.codTimePoly << "\n"; + return os; +} + +std::ostream& operator<< (std::ostream& os, const Dwell& d) +{ + os << "Dwell:: \n" + << " NumCODTimes : " << d.cod.size() << "\n" + << " NumDwellTimes : " << d.dtime.size() << "\n"; + for (const auto& cod : d.cod) + { + os << cod << "\n"; + } + for (const auto& dtime : d.dtime) + { + os << dtime << "\n"; + } + return os; +} +} diff --git a/six/modules/c++/cphd/source/ErrorParameters.cpp b/six/modules/c++/cphd/source/ErrorParameters.cpp index 368773f7a2..4dfe3550b8 100644 --- a/six/modules/c++/cphd/source/ErrorParameters.cpp +++ b/six/modules/c++/cphd/source/ErrorParameters.cpp @@ -1,191 +1,191 @@ -/* ========================================================================= - * This file is part of cphd-c++ - * ========================================================================= - * - * (C) Copyright 2004 - 2019, MDA Information Systems LLC - * - * cphd-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ - -#include -#include -#include - -namespace cphd -{ -ErrorParameters::Monostatic::RadarSensor::RadarSensor() : - rangeBias(six::Init::undefined()), - clockFreqSF(six::Init::undefined()), - collectionStartTime(six::Init::undefined()) -{ -} - -ErrorParameters::Bistatic::RadarSensor::RadarSensor() : - clockFreqSF(six::Init::undefined()), - collectionStartTime(six::Init::undefined()) -{ -} - -static std::ostream& unchecked(std::ostream& os, const six::DecorrType& decorr_) -{ - const auto decorr = six::value(decorr_); - os << " CorrCoefZero : " << decorr.corrCoefZero << "\n" - << " DecorrRate : " << decorr.decorrRate << "\n"; - return os; -} -std::ostream& unchecked(std::ostream& os, const std::optional& decorr) -{ - return unchecked(os, *decorr); -} - -static std::ostream& checked(std::ostream& os, const std::string& s, const six::DecorrType& decorr) -{ - if (six::Init::isDefined(decorr)) - { - os << s; - return unchecked(os, decorr); - } - return os; -} -std::ostream& checked(std::ostream& os, const std::string& s, const std::optional& decorr) -{ - return decorr.has_value() ? checked(os, s, *decorr) : os; -} - - -static std::ostream& checked(std::ostream& os, const std::string& s, const double& v) -{ - if (six::Init::isDefined(v)) - { - os << s << v << "\n"; - } - return os; -} -std::ostream& checked(std::ostream& os, const std::string& s, const std::optional& v) -{ - return v.has_value() ? checked(os, s, *v) : os; -} - -std::ostream& operator<< (std::ostream& os, const six::PosVelError& p) -{ - os << " PosVelError:: \n" - << " Frame : " << p.frame << "\n" - << " P1 : " << p.p1 << "\n" - << " P2 : " << p.p2 << "\n" - << " P3 : " << p.p3 << "\n" - << " V1 : " << p.v1 << "\n" - << " V2 : " << p.v2 << "\n" - << " V3 : " << p.v3 << "\n"; - if (p.corrCoefs.get()) - { - os << " CorrCoefs:: \n" - << " p1p2 : " << p.corrCoefs->p1p2 << "\n" - << " p1p3 : " << p.corrCoefs->p1p3 << "\n" - << " p1v1 : " << p.corrCoefs->p1v1 << "\n" - << " p1v2 : " << p.corrCoefs->p1v2 << "\n" - << " p1v3 : " << p.corrCoefs->p1v3 << "\n" - << " p2p3 : " << p.corrCoefs->p2p3 << "\n" - << " p2v1 : " << p.corrCoefs->p2v1 << "\n" - << " p2v2 : " << p.corrCoefs->p2v2 << "\n" - << " p2v3 : " << p.corrCoefs->p2v3 << "\n" - << " p3v1 : " << p.corrCoefs->p3v1 << "\n" - << " p3v2 : " << p.corrCoefs->p3v2 << "\n" - << " p3v3 : " << p.corrCoefs->p3v3 << "\n" - << " v1v2 : " << p.corrCoefs->v1v2 << "\n" - << " v1v3 : " << p.corrCoefs->v1v3 << "\n" - << " v2v3 : " << p.corrCoefs->v2v3 << "\n"; - } - os << " Decorr:: \n"; - return unchecked(os, p.positionDecorr); -} - -static std::ostream& operator<< (std::ostream& os, const ErrorParameters::Bistatic::RadarSensor& v) -{ - os << " RadarSensor:: \n" - << v.delayBias - << " ClockFreqSF : " << v.clockFreqSF << "\n" - << " CollectionStartTime : " <posVelErr << "\n" - << " RadarSensor:: \n" - << " RangeBias : " << e.monostatic->radarSensor.rangeBias << "\n"; - if (!six::Init::isUndefined(e.monostatic->radarSensor.clockFreqSF)) - { - os << " ClockFreqSF : " << e.monostatic->radarSensor.clockFreqSF << "\n"; - } - if (!six::Init::isUndefined(e.monostatic->radarSensor.collectionStartTime)) - { - os << " CollectionStartTime : " << e.monostatic->radarSensor.collectionStartTime << "\n"; - } - if (e.monostatic->radarSensor.rangeBiasDecorr.get()) - { - os << " RangeBiasDecorr:: \n" - << " CorrCoefZero : " << e.monostatic->radarSensor.rangeBiasDecorr->corrCoefZero << "\n" - << " DecorrRate : " << e.monostatic->radarSensor.rangeBiasDecorr->decorrRate << "\n"; - } - if (e.monostatic->tropoError.get()) - { - os << " TropoError:: \n"; - checked(os, " TropoRangeVertical : ", e.monostatic->tropoError->tropoRangeVertical); - checked(os, " TropoRangeSlant : ", e.monostatic->tropoError->tropoRangeSlant); - checked(os, " TropoRangeDecorr:: \n", e.monostatic->tropoError->tropoRangeDecorr); - } - if (e.monostatic->ionoError.get()) - { - os << " IonoError:: \n"; - checked(os, " IonoRangeVertical : ", e.monostatic->ionoError->ionoRangeVertical); - checked(os, " IonoRangeRateVertical : ", e.monostatic->ionoError->ionoRangeRateVertical); - os << " IonoRgRgRateCC : " << six::value(e.monostatic->ionoError->ionoRgRgRateCC) << "\n"; - checked(os, " IonoRangeDecorr:: \n", e.monostatic->ionoError->ionoRangeVertDecorr); - } - for (const auto& parameter : e.monostatic->parameter) - { - os << " Parameter Name : " << parameter.getName() << "\n" - << " Parameter Value : " << parameter.str() << "\n"; - } - } - else if (e.bistatic.get()) - { - os << " Bistatic:: \n" - << " TxPlatform:: \n" - << e.bistatic->txPlatform.posVelErr << "\n" - << e.bistatic->txPlatform.radarSensor - << "\n" - << " RcvPlatform:: \n" - << e.bistatic->rcvPlatform.posVelErr << "\n" - << e.bistatic->rcvPlatform.radarSensor; - for (const auto& parameter : e.bistatic->parameter) - { - os << " Parameter Name : " << parameter.getName() << "\n" - << " Parameter Value : " << parameter.str() << "\n"; - } - } - else - { - throw except::Exception(Ctxt( - "One of either monostatic or bistatic is required")); - } - return os; -} -} +/* ========================================================================= + * This file is part of cphd-c++ + * ========================================================================= + * + * (C) Copyright 2004 - 2019, MDA Information Systems LLC + * + * cphd-c++ is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; If not, + * see . + * + */ + +#include +#include +#include + +namespace cphd +{ +ErrorParameters::Monostatic::RadarSensor::RadarSensor() : + rangeBias(six::Init::undefined()), + clockFreqSF(six::Init::undefined()), + collectionStartTime(six::Init::undefined()) +{ +} + +ErrorParameters::Bistatic::RadarSensor::RadarSensor() : + clockFreqSF(six::Init::undefined()), + collectionStartTime(six::Init::undefined()) +{ +} + +static std::ostream& unchecked(std::ostream& os, const six::DecorrType& decorr_) +{ + const auto decorr = six::value(decorr_); + os << " CorrCoefZero : " << decorr.corrCoefZero << "\n" + << " DecorrRate : " << decorr.decorrRate << "\n"; + return os; +} +std::ostream& unchecked(std::ostream& os, const std::optional& decorr) +{ + return unchecked(os, *decorr); +} + +static std::ostream& checked(std::ostream& os, const std::string& s, const six::DecorrType& decorr) +{ + if (six::Init::isDefined(decorr)) + { + os << s; + return unchecked(os, decorr); + } + return os; +} +std::ostream& checked(std::ostream& os, const std::string& s, const std::optional& decorr) +{ + return decorr.has_value() ? checked(os, s, *decorr) : os; +} + + +static std::ostream& checked(std::ostream& os, const std::string& s, const double& v) +{ + if (six::Init::isDefined(v)) + { + os << s << v << "\n"; + } + return os; +} +std::ostream& checked(std::ostream& os, const std::string& s, const std::optional& v) +{ + return v.has_value() ? checked(os, s, *v) : os; +} + +std::ostream& operator<< (std::ostream& os, const six::PosVelError& p) +{ + os << " PosVelError:: \n" + << " Frame : " << p.frame << "\n" + << " P1 : " << p.p1 << "\n" + << " P2 : " << p.p2 << "\n" + << " P3 : " << p.p3 << "\n" + << " V1 : " << p.v1 << "\n" + << " V2 : " << p.v2 << "\n" + << " V3 : " << p.v3 << "\n"; + if (p.corrCoefs.get()) + { + os << " CorrCoefs:: \n" + << " p1p2 : " << p.corrCoefs->p1p2 << "\n" + << " p1p3 : " << p.corrCoefs->p1p3 << "\n" + << " p1v1 : " << p.corrCoefs->p1v1 << "\n" + << " p1v2 : " << p.corrCoefs->p1v2 << "\n" + << " p1v3 : " << p.corrCoefs->p1v3 << "\n" + << " p2p3 : " << p.corrCoefs->p2p3 << "\n" + << " p2v1 : " << p.corrCoefs->p2v1 << "\n" + << " p2v2 : " << p.corrCoefs->p2v2 << "\n" + << " p2v3 : " << p.corrCoefs->p2v3 << "\n" + << " p3v1 : " << p.corrCoefs->p3v1 << "\n" + << " p3v2 : " << p.corrCoefs->p3v2 << "\n" + << " p3v3 : " << p.corrCoefs->p3v3 << "\n" + << " v1v2 : " << p.corrCoefs->v1v2 << "\n" + << " v1v3 : " << p.corrCoefs->v1v3 << "\n" + << " v2v3 : " << p.corrCoefs->v2v3 << "\n"; + } + os << " Decorr:: \n"; + return unchecked(os, p.positionDecorr); +} + +static std::ostream& operator<< (std::ostream& os, const ErrorParameters::Bistatic::RadarSensor& v) +{ + os << " RadarSensor:: \n" + << v.delayBias + << " ClockFreqSF : " << v.clockFreqSF << "\n" + << " CollectionStartTime : " <posVelErr << "\n" + << " RadarSensor:: \n" + << " RangeBias : " << e.monostatic->radarSensor.rangeBias << "\n"; + if (!six::Init::isUndefined(e.monostatic->radarSensor.clockFreqSF)) + { + os << " ClockFreqSF : " << e.monostatic->radarSensor.clockFreqSF << "\n"; + } + if (!six::Init::isUndefined(e.monostatic->radarSensor.collectionStartTime)) + { + os << " CollectionStartTime : " << e.monostatic->radarSensor.collectionStartTime << "\n"; + } + if (e.monostatic->radarSensor.rangeBiasDecorr.get()) + { + os << " RangeBiasDecorr:: \n" + << " CorrCoefZero : " << e.monostatic->radarSensor.rangeBiasDecorr->corrCoefZero << "\n" + << " DecorrRate : " << e.monostatic->radarSensor.rangeBiasDecorr->decorrRate << "\n"; + } + if (e.monostatic->tropoError.get()) + { + os << " TropoError:: \n"; + checked(os, " TropoRangeVertical : ", e.monostatic->tropoError->tropoRangeVertical); + checked(os, " TropoRangeSlant : ", e.monostatic->tropoError->tropoRangeSlant); + checked(os, " TropoRangeDecorr:: \n", e.monostatic->tropoError->tropoRangeDecorr); + } + if (e.monostatic->ionoError.get()) + { + os << " IonoError:: \n"; + checked(os, " IonoRangeVertical : ", e.monostatic->ionoError->ionoRangeVertical); + checked(os, " IonoRangeRateVertical : ", e.monostatic->ionoError->ionoRangeRateVertical); + os << " IonoRgRgRateCC : " << six::value(e.monostatic->ionoError->ionoRgRgRateCC) << "\n"; + checked(os, " IonoRangeDecorr:: \n", e.monostatic->ionoError->ionoRangeVertDecorr); + } + for (const auto& parameter : e.monostatic->parameter) + { + os << " Parameter Name : " << parameter.getName() << "\n" + << " Parameter Value : " << parameter.str() << "\n"; + } + } + else if (e.bistatic.get()) + { + os << " Bistatic:: \n" + << " TxPlatform:: \n" + << e.bistatic->txPlatform.posVelErr << "\n" + << e.bistatic->txPlatform.radarSensor + << "\n" + << " RcvPlatform:: \n" + << e.bistatic->rcvPlatform.posVelErr << "\n" + << e.bistatic->rcvPlatform.radarSensor; + for (const auto& parameter : e.bistatic->parameter) + { + os << " Parameter Name : " << parameter.getName() << "\n" + << " Parameter Value : " << parameter.str() << "\n"; + } + } + else + { + throw except::Exception(Ctxt( + "One of either monostatic or bistatic is required")); + } + return os; +} +} diff --git a/six/modules/c++/cphd/source/PVP.cpp b/six/modules/c++/cphd/source/PVP.cpp index 7400ac4bd0..ab675012aa 100644 --- a/six/modules/c++/cphd/source/PVP.cpp +++ b/six/modules/c++/cphd/source/PVP.cpp @@ -1,280 +1,280 @@ -/* ========================================================================= - * This file is part of cphd-c++ - * ========================================================================= - * - * (C) Copyright 2004 - 2019, MDA Information Systems LLC - * - * cphd-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ - -#include - -#include -#include - -#include -#include - -namespace cphd -{ -PVPType::PVPType() : - mSize(0), - mOffset(six::Init::undefined()) -{ -} - -APVPType::APVPType() -{ -} - -Pvp::Pvp() -{ - initialize(); -} - -void Pvp::initialize() -{ - // Default size and formats for each PVP - // listed in Table 11-6 CPHD1.0 Spec - setDefaultValues(1,"F8", txTime); - setDefaultValues(3,"X=F8;Y=F8;Z=F8;", txPos); - setDefaultValues(3,"X=F8;Y=F8;Z=F8;", txVel); - setDefaultValues(1,"F8", rcvTime); - setDefaultValues(3,"X=F8;Y=F8;Z=F8;", rcvPos); - setDefaultValues(3,"X=F8;Y=F8;Z=F8;", rcvVel); - setDefaultValues(3,"X=F8;Y=F8;Z=F8;", srpPos); - setDefaultValues(1,"F8", ampSF); - setDefaultValues(1,"F8", aFDOP); - setDefaultValues(1,"F8", aFRR1); - setDefaultValues(1,"F8", aFRR2); - setDefaultValues(1,"F8", fx1); - setDefaultValues(1,"F8", fx2); - setDefaultValues(1,"F8", fxN1); - setDefaultValues(1,"F8", fxN2); - setDefaultValues(1,"F8", toa1); - setDefaultValues(1,"F8", toa2); - setDefaultValues(1,"F8", toaE1); - setDefaultValues(1,"F8", toaE2); - setDefaultValues(1,"F8", tdTropoSRP); - setDefaultValues(1,"F8", tdIonoSRP); - setDefaultValues(1,"F8", sc0); - setDefaultValues(1,"F8", scss); - setDefaultValues(1,"I8", signal); -} - -void Pvp::validate(size_t size, size_t offset) -{ - //Check if size of array is sufficient for write - if (offset + size > mParamLocations.size()) - { - mParamLocations.resize(offset+size); - } - - //Check if any blocks will be overwritten - for (size_t ii = 0; ii < size; ++ii) - { - if(mParamLocations.at(offset + ii) == true) - { - throw except::Exception(Ctxt("This byte block is occupied")); - } - } - - // Mark each block as written - for (size_t ii = 0; ii < size; ++ii) - { - mParamLocations.at(offset + ii) = true; - } -} - -void setOffset(PVPType& param, size_t offset) -{ - validateFormat(param.getFormat()); - param.setOffset(offset); -} - -void Pvp::setOffset(size_t offset, PVPType& param) -{ - validate(param.getSize(), offset); - cphd::setOffset(param, offset); -} - -void Pvp::append(PVPType& param) -{ - size_t currentOffset = mParamLocations.size(); - setOffset(currentOffset, param); -} - -// Assumes addedPVP is already correct size -void Pvp::setCustomParameter(size_t size, size_t offset, const std::string& format, const std::string& name) -{ - validate(size, offset); - validateFormat(format); - if (addedPVP.count(name) == 0) - { - addedPVP[name] = APVPType(); - addedPVP.find(name)->second.setData(size, offset, format, name); - return; - } - throw except::Exception(Ctxt( - "Additional parameter name is not unique")); -} - -void Pvp::appendCustomParameter(size_t size, const std::string& format, const std::string& name) -{ - size_t currentOffset = mParamLocations.size(); - setCustomParameter(size, currentOffset, format, name); -} - -void Pvp::setDefaultValues(size_t size, const std::string& format, PVPType& param) -{ - param.setSize(size); - param.setFormat(format); -} - -// Returns num blocks (not bytes) -size_t Pvp::getReqSetSize() const -{ - size_t res = txTime.getSize() + txPos.getSize() + txVel.getSize() + - rcvTime.getSize() + rcvPos.getSize() + rcvVel.getSize() + srpPos.getSize() + - aFDOP.getSize() + aFRR1.getSize() + aFRR2.getSize() + fx1.getSize() + - fx2.getSize() + toa1.getSize() + toa2.getSize() + tdTropoSRP.getSize() + - sc0.getSize() + scss.getSize(); - if(!six::Init::isUndefined(ampSF.getOffset())) - { - res += ampSF.getSize(); - } - if(!six::Init::isUndefined(fxN1.getOffset())) - { - res += fxN1.getSize(); - } - if(!six::Init::isUndefined(fxN2.getOffset())) - { - res += fxN2.getSize(); - } - if(!six::Init::isUndefined(toaE1.getOffset())) - { - res += toaE1.getSize(); - } - if(!six::Init::isUndefined(toaE2.getOffset())) - { - res += toaE2.getSize(); - } - if(!six::Init::isUndefined(tdIonoSRP.getOffset())) - { - res += tdIonoSRP.getSize(); - } - if(!six::Init::isUndefined(signal.getOffset())) - { - res += signal.getSize(); - } - for (auto it = addedPVP.begin(); it != addedPVP.end(); ++it) - { - res += it->second.getSize(); - } - return res; -} - -size_t Pvp::sizeInBytes() const -{ - return getReqSetSize() * PVPType::WORD_BYTE_SIZE; -} - -std::ostream& operator<< (std::ostream& os, const PVPType& p) -{ - os << " Size : " << p.getSize() << "\n" - << " Offset : " << p.getOffset() << "\n" - << " Format : " << p.getFormat() << "\n"; - return os; -} - -std::ostream& operator<< (std::ostream& os, const APVPType& a) -{ - os << " Name : " << a.getName() << "\n" - << (PVPType)a; - - return os; -} - -std::ostream& operator<< (std::ostream& os, const Pvp& p) -{ - os << " TxTime : \n" << p.txTime << "\n" - << " TxPos : \n" << p.txPos << "\n" - << " TxVel : \n" << p.txVel << "\n" - << " RcvTime : \n" << p.rcvTime << "\n" - << " RcvPos : \n" << p.rcvPos << "\n" - << " RcvVel : \n" << p.rcvVel << "\n" - << " SRPPos : \n" << p.srpPos << "\n" - << " aFDOP : \n" << p.aFDOP << "\n" - << " aFRR1 : \n" << p.aFRR1 << "\n" - << " aFRR2 : \n" << p.aFRR2 << "\n" - << " Fx1 : \n" << p.fx1 << "\n" - << " Fx2 : \n" << p.fx2 << "\n" - << " TOA1 : \n" << p.toa1 << "\n" - << " TOA2 : \n" << p.toa2 << "\n" - << " TdTropoSRP : \n" << p.tdTropoSRP << "\n" - << " SC0 : \n" << p.sc0 << "\n" - << " SCSS : \n" << p.scss << "\n"; - - if(!six::Init::isUndefined(p.ampSF.getOffset())) - { - os << " AmpSF : \n" << p.ampSF << "\n"; - } - if(!six::Init::isUndefined(p.fxN1.getOffset())) - { - os << " FxN1 : \n" << p.fxN1 << "\n"; - } - if(!six::Init::isUndefined(p.fxN2.getOffset())) - { - os << " FxN2 : \n" << p.fxN2 << "\n"; - } - if(!six::Init::isUndefined(p.toaE1.getOffset())) - { - os << " TOAE1 : \n" << p.toaE1 << "\n"; - } - if(!six::Init::isUndefined(p.toaE2.getOffset())) - { - os << " TOAE2 : \n" << p.toaE2 << "\n"; - } - if(!six::Init::isUndefined(p.tdIonoSRP.getOffset())) - { - os << " TdIonoSRP : \n" << p.tdIonoSRP << "\n"; - } - if(!six::Init::isUndefined(p.signal.getOffset())) - { - os << " SIGNAL : \n" << p.signal << "\n"; - } - for (auto it = p.addedPVP.begin(); it != p.addedPVP.end(); ++it) - { - os << " Additional Parameter : " << it->second << "\n"; - } - return os; -} - -PerVectorParameterXYZ::PerVectorParameterXYZ() -{ - // setDefaultValues(3,"X=F8;Y=F8;Z=F8;", rcvPos); - param.setSize(3); // - param.setFormat("X=F8;Y=F8;Z=F8;"); // -} - -PerVectorParameterEB::PerVectorParameterEB() -{ - // setDefaultValues(3,"X=F8;Y=F8;Z=F8;", rcvPos); - param.setSize(2); // - param.setFormat("DCX=F8;DCY=F8;"); // -} - -} +/* ========================================================================= + * This file is part of cphd-c++ + * ========================================================================= + * + * (C) Copyright 2004 - 2019, MDA Information Systems LLC + * + * cphd-c++ is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; If not, + * see . + * + */ + +#include + +#include +#include + +#include +#include + +namespace cphd +{ +PVPType::PVPType() : + mSize(0), + mOffset(six::Init::undefined()) +{ +} + +APVPType::APVPType() +{ +} + +Pvp::Pvp() +{ + initialize(); +} + +void Pvp::initialize() +{ + // Default size and formats for each PVP + // listed in Table 11-6 CPHD1.0 Spec + setDefaultValues(1,"F8", txTime); + setDefaultValues(3,"X=F8;Y=F8;Z=F8;", txPos); + setDefaultValues(3,"X=F8;Y=F8;Z=F8;", txVel); + setDefaultValues(1,"F8", rcvTime); + setDefaultValues(3,"X=F8;Y=F8;Z=F8;", rcvPos); + setDefaultValues(3,"X=F8;Y=F8;Z=F8;", rcvVel); + setDefaultValues(3,"X=F8;Y=F8;Z=F8;", srpPos); + setDefaultValues(1,"F8", ampSF); + setDefaultValues(1,"F8", aFDOP); + setDefaultValues(1,"F8", aFRR1); + setDefaultValues(1,"F8", aFRR2); + setDefaultValues(1,"F8", fx1); + setDefaultValues(1,"F8", fx2); + setDefaultValues(1,"F8", fxN1); + setDefaultValues(1,"F8", fxN2); + setDefaultValues(1,"F8", toa1); + setDefaultValues(1,"F8", toa2); + setDefaultValues(1,"F8", toaE1); + setDefaultValues(1,"F8", toaE2); + setDefaultValues(1,"F8", tdTropoSRP); + setDefaultValues(1,"F8", tdIonoSRP); + setDefaultValues(1,"F8", sc0); + setDefaultValues(1,"F8", scss); + setDefaultValues(1,"I8", signal); +} + +void Pvp::validate(size_t size, size_t offset) +{ + //Check if size of array is sufficient for write + if (offset + size > mParamLocations.size()) + { + mParamLocations.resize(offset+size); + } + + //Check if any blocks will be overwritten + for (size_t ii = 0; ii < size; ++ii) + { + if(mParamLocations.at(offset + ii) == true) + { + throw except::Exception(Ctxt("This byte block is occupied")); + } + } + + // Mark each block as written + for (size_t ii = 0; ii < size; ++ii) + { + mParamLocations.at(offset + ii) = true; + } +} + +void setOffset(PVPType& param, size_t offset) +{ + validateFormat(param.getFormat()); + param.setOffset(offset); +} + +void Pvp::setOffset(size_t offset, PVPType& param) +{ + validate(param.getSize(), offset); + cphd::setOffset(param, offset); +} + +void Pvp::append(PVPType& param) +{ + size_t currentOffset = mParamLocations.size(); + setOffset(currentOffset, param); +} + +// Assumes addedPVP is already correct size +void Pvp::setCustomParameter(size_t size, size_t offset, const std::string& format, const std::string& name) +{ + validate(size, offset); + validateFormat(format); + if (addedPVP.count(name) == 0) + { + addedPVP[name] = APVPType(); + addedPVP.find(name)->second.setData(size, offset, format, name); + return; + } + throw except::Exception(Ctxt( + "Additional parameter name is not unique")); +} + +void Pvp::appendCustomParameter(size_t size, const std::string& format, const std::string& name) +{ + size_t currentOffset = mParamLocations.size(); + setCustomParameter(size, currentOffset, format, name); +} + +void Pvp::setDefaultValues(size_t size, const std::string& format, PVPType& param) +{ + param.setSize(size); + param.setFormat(format); +} + +// Returns num blocks (not bytes) +size_t Pvp::getReqSetSize() const +{ + size_t res = txTime.getSize() + txPos.getSize() + txVel.getSize() + + rcvTime.getSize() + rcvPos.getSize() + rcvVel.getSize() + srpPos.getSize() + + aFDOP.getSize() + aFRR1.getSize() + aFRR2.getSize() + fx1.getSize() + + fx2.getSize() + toa1.getSize() + toa2.getSize() + tdTropoSRP.getSize() + + sc0.getSize() + scss.getSize(); + if(!six::Init::isUndefined(ampSF.getOffset())) + { + res += ampSF.getSize(); + } + if(!six::Init::isUndefined(fxN1.getOffset())) + { + res += fxN1.getSize(); + } + if(!six::Init::isUndefined(fxN2.getOffset())) + { + res += fxN2.getSize(); + } + if(!six::Init::isUndefined(toaE1.getOffset())) + { + res += toaE1.getSize(); + } + if(!six::Init::isUndefined(toaE2.getOffset())) + { + res += toaE2.getSize(); + } + if(!six::Init::isUndefined(tdIonoSRP.getOffset())) + { + res += tdIonoSRP.getSize(); + } + if(!six::Init::isUndefined(signal.getOffset())) + { + res += signal.getSize(); + } + for (auto it = addedPVP.begin(); it != addedPVP.end(); ++it) + { + res += it->second.getSize(); + } + return res; +} + +size_t Pvp::sizeInBytes() const +{ + return getReqSetSize() * PVPType::WORD_BYTE_SIZE; +} + +std::ostream& operator<< (std::ostream& os, const PVPType& p) +{ + os << " Size : " << p.getSize() << "\n" + << " Offset : " << p.getOffset() << "\n" + << " Format : " << p.getFormat() << "\n"; + return os; +} + +std::ostream& operator<< (std::ostream& os, const APVPType& a) +{ + os << " Name : " << a.getName() << "\n" + << (PVPType)a; + + return os; +} + +std::ostream& operator<< (std::ostream& os, const Pvp& p) +{ + os << " TxTime : \n" << p.txTime << "\n" + << " TxPos : \n" << p.txPos << "\n" + << " TxVel : \n" << p.txVel << "\n" + << " RcvTime : \n" << p.rcvTime << "\n" + << " RcvPos : \n" << p.rcvPos << "\n" + << " RcvVel : \n" << p.rcvVel << "\n" + << " SRPPos : \n" << p.srpPos << "\n" + << " aFDOP : \n" << p.aFDOP << "\n" + << " aFRR1 : \n" << p.aFRR1 << "\n" + << " aFRR2 : \n" << p.aFRR2 << "\n" + << " Fx1 : \n" << p.fx1 << "\n" + << " Fx2 : \n" << p.fx2 << "\n" + << " TOA1 : \n" << p.toa1 << "\n" + << " TOA2 : \n" << p.toa2 << "\n" + << " TdTropoSRP : \n" << p.tdTropoSRP << "\n" + << " SC0 : \n" << p.sc0 << "\n" + << " SCSS : \n" << p.scss << "\n"; + + if(!six::Init::isUndefined(p.ampSF.getOffset())) + { + os << " AmpSF : \n" << p.ampSF << "\n"; + } + if(!six::Init::isUndefined(p.fxN1.getOffset())) + { + os << " FxN1 : \n" << p.fxN1 << "\n"; + } + if(!six::Init::isUndefined(p.fxN2.getOffset())) + { + os << " FxN2 : \n" << p.fxN2 << "\n"; + } + if(!six::Init::isUndefined(p.toaE1.getOffset())) + { + os << " TOAE1 : \n" << p.toaE1 << "\n"; + } + if(!six::Init::isUndefined(p.toaE2.getOffset())) + { + os << " TOAE2 : \n" << p.toaE2 << "\n"; + } + if(!six::Init::isUndefined(p.tdIonoSRP.getOffset())) + { + os << " TdIonoSRP : \n" << p.tdIonoSRP << "\n"; + } + if(!six::Init::isUndefined(p.signal.getOffset())) + { + os << " SIGNAL : \n" << p.signal << "\n"; + } + for (auto it = p.addedPVP.begin(); it != p.addedPVP.end(); ++it) + { + os << " Additional Parameter : " << it->second << "\n"; + } + return os; +} + +PerVectorParameterXYZ::PerVectorParameterXYZ() +{ + // setDefaultValues(3,"X=F8;Y=F8;Z=F8;", rcvPos); + param.setSize(3); // + param.setFormat("X=F8;Y=F8;Z=F8;"); // +} + +PerVectorParameterEB::PerVectorParameterEB() +{ + // setDefaultValues(3,"X=F8;Y=F8;Z=F8;", rcvPos); + param.setSize(2); // + param.setFormat("DCX=F8;DCY=F8;"); // +} + +} diff --git a/six/modules/c++/cphd/source/ProductInfo.cpp b/six/modules/c++/cphd/source/ProductInfo.cpp index 44607d601f..caf266aaa1 100644 --- a/six/modules/c++/cphd/source/ProductInfo.cpp +++ b/six/modules/c++/cphd/source/ProductInfo.cpp @@ -1,63 +1,63 @@ -/* ========================================================================= - * This file is part of cphd-c++ - * ========================================================================= - * - * (C) Copyright 2004 - 2019, MDA Information Systems LLC - * - * cphd-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ - -#include -#include - -namespace cphd -{ -ProductInfo::ProductInfo() -{ -} - -ProductInfo::CreationInfo::CreationInfo(): - dateTime(six::Init::undefined()) -{ -} - -std::ostream& operator<< (std::ostream& os, const ProductInfo& p) -{ - os << "Product Information : \n" - << " Profile : " << p.profile << "\n"; - for (size_t ii = 0; ii < p.creationInfo.size(); ++ii) - { - os << " Creation Information : " << "\n" - << " Application : " << p.creationInfo[ii].application << "\n" - << " DateTime : " << p.creationInfo[ii].dateTime.getMonth() << "/" - << p.creationInfo[ii].dateTime.getDayOfMonth() << "/" - << p.creationInfo[ii].dateTime.getYear() << "\n" - << " Site : " << p.creationInfo[ii].site << "\n"; - for (size_t jj = 0; jj < p.creationInfo[ii].parameter.size(); ++jj) - { - os << " Parameter name : " - << p.creationInfo[ii].parameter[jj].getName() << "\n" - << " Parameter value : " << p.creationInfo[ii].parameter[jj].str() << "\n"; - } - } - for (size_t ii = 0; ii < p.parameter.size(); ++ii) - { - os << " Parameter name : " << p.parameter[ii].getName() << "\n" - << " Parameter value : " << p.parameter[ii].str() << "\n"; - } - return os; -} -} +/* ========================================================================= + * This file is part of cphd-c++ + * ========================================================================= + * + * (C) Copyright 2004 - 2019, MDA Information Systems LLC + * + * cphd-c++ is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; If not, + * see . + * + */ + +#include +#include + +namespace cphd +{ +ProductInfo::ProductInfo() +{ +} + +ProductInfo::CreationInfo::CreationInfo(): + dateTime(six::Init::undefined()) +{ +} + +std::ostream& operator<< (std::ostream& os, const ProductInfo& p) +{ + os << "Product Information : \n" + << " Profile : " << p.profile << "\n"; + for (size_t ii = 0; ii < p.creationInfo.size(); ++ii) + { + os << " Creation Information : " << "\n" + << " Application : " << p.creationInfo[ii].application << "\n" + << " DateTime : " << p.creationInfo[ii].dateTime.getMonth() << "/" + << p.creationInfo[ii].dateTime.getDayOfMonth() << "/" + << p.creationInfo[ii].dateTime.getYear() << "\n" + << " Site : " << p.creationInfo[ii].site << "\n"; + for (size_t jj = 0; jj < p.creationInfo[ii].parameter.size(); ++jj) + { + os << " Parameter name : " + << p.creationInfo[ii].parameter[jj].getName() << "\n" + << " Parameter value : " << p.creationInfo[ii].parameter[jj].str() << "\n"; + } + } + for (size_t ii = 0; ii < p.parameter.size(); ++ii) + { + os << " Parameter name : " << p.parameter[ii].getName() << "\n" + << " Parameter value : " << p.parameter[ii].str() << "\n"; + } + return os; +} +} diff --git a/six/modules/c++/cphd/source/ReferenceGeometry.cpp b/six/modules/c++/cphd/source/ReferenceGeometry.cpp index 0823dd4950..7c6bb22b1e 100644 --- a/six/modules/c++/cphd/source/ReferenceGeometry.cpp +++ b/six/modules/c++/cphd/source/ReferenceGeometry.cpp @@ -1,174 +1,174 @@ -/* ========================================================================= - * This file is part of cphd-c++ - * ========================================================================= - * - * (C) Copyright 2004 - 2019, MDA Information Systems LLC - * - * cphd-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ - -#include -#include - -namespace cphd -{ - -SRP::SRP() : - ecf(six::Init::undefined()), - iac(six::Init::undefined()) -{ -} - -ImagingType::ImagingType() : - azimuthAngle(0), - grazeAngle(0), - twistAngle(0), - slopeAngle(0), - layoverAngle(0) -{ -} - -Monostatic::Monostatic() : - sideOfTrack(six::Init::undefined()), - slantRange(0), - groundRange(0), - dopplerConeAngle(0), - incidenceAngle(0), - arpPos(six::Init::undefined()), - arpVel(six::Init::undefined()) -{ -} - -Bistatic::Bistatic() : - azimuthAngleRate(0), - bistaticAngle(0), - bistaticAngleRate(0) -{ -} - -Bistatic::PlatformParams::PlatformParams() : - sideOfTrack(six::Init::undefined()), - time(0), - azimuthAngle(0), - grazeAngle(0), - incidenceAngle(0), - dopplerConeAngle(0), - groundRange(0), - slantRange(0), - pos(six::Init::undefined()), - vel(six::Init::undefined()) -{ -} - -ReferenceGeometry::ReferenceGeometry() : - referenceTime(0), - srpCODTime(0), - srpDwellTime(0) -{ -} - -std::ostream& operator<< (std::ostream& os, const SRP& s) -{ - os << "SRP:: \n" - << " ECF : " << s.ecf << "\n" - << " IAC : " << s.iac << "\n"; - return os; -} - -std::ostream& operator<< (std::ostream& os, const ImagingType& i) -{ - os << " AzimuthAngle : " << i.azimuthAngle << "\n" - << " GrazeAngle : " << i.grazeAngle << "\n" - << " TwistAngle : " << i.twistAngle << "\n" - << " SlopeAngle : " << i.slopeAngle << "\n" - << " layoverAngle : " << i.layoverAngle << "\n"; - return os; -} - -std::ostream& operator<< (std::ostream& os, const Monostatic& m) -{ - os << "Monostatic:: \n" - << (ImagingType)m << "\n" - << " SideOfTrack : " << m.sideOfTrack << "\n" - << " SlantRange : " << m.slantRange << "\n" - << " GroundRange : " << m.groundRange << "\n" - << " DopplerConeAngle : " << m.dopplerConeAngle << "\n" - << " IncidenceAngle : " << m.incidenceAngle << "\n" - << " ArpPos:: \n" - << " X : " << m.arpPos[0] << "\n" - << " Y : " << m.arpPos[1] << "\n" - << " Z : " << m.arpPos[2] << "\n" - << " ArpVel:: \n" - << " X : " << m.arpVel[0] << "\n" - << " Y : " << m.arpVel[1] << "\n" - << " Z : " << m.arpVel[2] << "\n"; - return os; -} - -std::ostream& operator<< (std::ostream& os, const Bistatic::PlatformParams& p) -{ - os << " SideOfTrack : " << p.sideOfTrack << "\n" - << " Time: : " << p.time << "\n" - << " AzimuthAngle : " << p.azimuthAngle << "\n" - << " GrazeAngle : " << p.grazeAngle << "\n" - << " IncidenceAngle : " << p.incidenceAngle << "\n" - << " DopplerConeAngle : " << p.dopplerConeAngle << "\n" - << " GroundRange : " << p.groundRange << "\n" - << " SlantRange : " << p.slantRange << "\n" - << " Pos:: \n" - << " X : " << p.pos[0] << "\n" - << " Y : " << p.pos[1] << "\n" - << " Z : " << p.pos[2] << "\n" - << " Vel:: \n" - << " X : " << p.vel[0] << "\n" - << " Y : " << p.vel[1] << "\n" - << " Z : " << p.vel[2] << "\n"; - - return os; -} - -std::ostream& operator<< (std::ostream& os, const Bistatic& b) -{ - os << "Bistatic:: \n" - << (ImagingType)b << "\n" - << " AzimuthAngleRate : " << b.azimuthAngleRate << "\n" - << " BistaticAngle : " << b.bistaticAngle << "\n" - << " BistaticAngleRate : " << b.bistaticAngleRate << "\n" - << " TxPlatform:: \n" - << b.txPlatform << "\n" - << b.rcvPlatform << "\n"; - return os; -} - -std::ostream& operator<< (std::ostream& os, const ReferenceGeometry& r) -{ - os << "Reference Geometry:: \n" - << " ReferenceTime : " << r.referenceTime << "\n" - << " SRPCODTime : " << r.srpCODTime << "\n" - << " SRPDwellTime : " << r.srpDwellTime << "\n" - << r.srp; - - if (r.monostatic.get()) - { - os << *r.monostatic << "\n"; - } - else if (r.bistatic.get()) - { - os << *r.bistatic << "\n"; - } - return os; -} -} +/* ========================================================================= + * This file is part of cphd-c++ + * ========================================================================= + * + * (C) Copyright 2004 - 2019, MDA Information Systems LLC + * + * cphd-c++ is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; If not, + * see . + * + */ + +#include +#include + +namespace cphd +{ + +SRP::SRP() : + ecf(six::Init::undefined()), + iac(six::Init::undefined()) +{ +} + +ImagingType::ImagingType() : + azimuthAngle(0), + grazeAngle(0), + twistAngle(0), + slopeAngle(0), + layoverAngle(0) +{ +} + +Monostatic::Monostatic() : + sideOfTrack(six::Init::undefined()), + slantRange(0), + groundRange(0), + dopplerConeAngle(0), + incidenceAngle(0), + arpPos(six::Init::undefined()), + arpVel(six::Init::undefined()) +{ +} + +Bistatic::Bistatic() : + azimuthAngleRate(0), + bistaticAngle(0), + bistaticAngleRate(0) +{ +} + +Bistatic::PlatformParams::PlatformParams() : + sideOfTrack(six::Init::undefined()), + time(0), + azimuthAngle(0), + grazeAngle(0), + incidenceAngle(0), + dopplerConeAngle(0), + groundRange(0), + slantRange(0), + pos(six::Init::undefined()), + vel(six::Init::undefined()) +{ +} + +ReferenceGeometry::ReferenceGeometry() : + referenceTime(0), + srpCODTime(0), + srpDwellTime(0) +{ +} + +std::ostream& operator<< (std::ostream& os, const SRP& s) +{ + os << "SRP:: \n" + << " ECF : " << s.ecf << "\n" + << " IAC : " << s.iac << "\n"; + return os; +} + +std::ostream& operator<< (std::ostream& os, const ImagingType& i) +{ + os << " AzimuthAngle : " << i.azimuthAngle << "\n" + << " GrazeAngle : " << i.grazeAngle << "\n" + << " TwistAngle : " << i.twistAngle << "\n" + << " SlopeAngle : " << i.slopeAngle << "\n" + << " layoverAngle : " << i.layoverAngle << "\n"; + return os; +} + +std::ostream& operator<< (std::ostream& os, const Monostatic& m) +{ + os << "Monostatic:: \n" + << (ImagingType)m << "\n" + << " SideOfTrack : " << m.sideOfTrack << "\n" + << " SlantRange : " << m.slantRange << "\n" + << " GroundRange : " << m.groundRange << "\n" + << " DopplerConeAngle : " << m.dopplerConeAngle << "\n" + << " IncidenceAngle : " << m.incidenceAngle << "\n" + << " ArpPos:: \n" + << " X : " << m.arpPos[0] << "\n" + << " Y : " << m.arpPos[1] << "\n" + << " Z : " << m.arpPos[2] << "\n" + << " ArpVel:: \n" + << " X : " << m.arpVel[0] << "\n" + << " Y : " << m.arpVel[1] << "\n" + << " Z : " << m.arpVel[2] << "\n"; + return os; +} + +std::ostream& operator<< (std::ostream& os, const Bistatic::PlatformParams& p) +{ + os << " SideOfTrack : " << p.sideOfTrack << "\n" + << " Time: : " << p.time << "\n" + << " AzimuthAngle : " << p.azimuthAngle << "\n" + << " GrazeAngle : " << p.grazeAngle << "\n" + << " IncidenceAngle : " << p.incidenceAngle << "\n" + << " DopplerConeAngle : " << p.dopplerConeAngle << "\n" + << " GroundRange : " << p.groundRange << "\n" + << " SlantRange : " << p.slantRange << "\n" + << " Pos:: \n" + << " X : " << p.pos[0] << "\n" + << " Y : " << p.pos[1] << "\n" + << " Z : " << p.pos[2] << "\n" + << " Vel:: \n" + << " X : " << p.vel[0] << "\n" + << " Y : " << p.vel[1] << "\n" + << " Z : " << p.vel[2] << "\n"; + + return os; +} + +std::ostream& operator<< (std::ostream& os, const Bistatic& b) +{ + os << "Bistatic:: \n" + << (ImagingType)b << "\n" + << " AzimuthAngleRate : " << b.azimuthAngleRate << "\n" + << " BistaticAngle : " << b.bistaticAngle << "\n" + << " BistaticAngleRate : " << b.bistaticAngleRate << "\n" + << " TxPlatform:: \n" + << b.txPlatform << "\n" + << b.rcvPlatform << "\n"; + return os; +} + +std::ostream& operator<< (std::ostream& os, const ReferenceGeometry& r) +{ + os << "Reference Geometry:: \n" + << " ReferenceTime : " << r.referenceTime << "\n" + << " SRPCODTime : " << r.srpCODTime << "\n" + << " SRPDwellTime : " << r.srpDwellTime << "\n" + << r.srp; + + if (r.monostatic.get()) + { + os << *r.monostatic << "\n"; + } + else if (r.bistatic.get()) + { + os << *r.bistatic << "\n"; + } + return os; +} +} diff --git a/six/modules/c++/cphd/source/TxRcv.cpp b/six/modules/c++/cphd/source/TxRcv.cpp index 99e03aadac..11a9b9017f 100644 --- a/six/modules/c++/cphd/source/TxRcv.cpp +++ b/six/modules/c++/cphd/source/TxRcv.cpp @@ -1,99 +1,99 @@ -/* ========================================================================= - * This file is part of cphd-c++ - * ========================================================================= - * - * (C) Copyright 2004 - 2019, MDA Information Systems LLC - * - * cphd-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ - -#include -#include - -namespace cphd -{ - -ParameterType::ParameterType() : - freqCenter(six::Init::undefined()), - lfmRate(six::Init::undefined()) -{ -} - -TxWFParameters::TxWFParameters() : - pulseLength(six::Init::undefined()), - rfBandwidth(six::Init::undefined()), - power(six::Init::undefined()) -{ -} - -RcvParameters::RcvParameters() : - windowLength(six::Init::undefined()), - sampleRate(six::Init::undefined()), - ifFilterBW(six::Init::undefined()), - pathGain(six::Init::undefined()) -{ -} - -TxRcv::TxRcv() -{ -} - -std::ostream& operator<< (std::ostream& os, const ParameterType& p) -{ - os << " Identifier : " << p.identifier << "\n" - << " FreqCenter : " << p.freqCenter << "\n" - << " LFMRate : " << p.lfmRate << "\n" - << " Polarization : " << p.polarization << "\n"; - return os; -} - -std::ostream& operator<< (std::ostream& os, const TxWFParameters& t) -{ - os << " TxWFParamters:: \n" - << (ParameterType)t - << " PulseLength : " << t.pulseLength << "\n" - << " RFBandwidth : " << t.rfBandwidth << "\n" - << " Power : " << t.power << "\n"; - return os; -} - -std::ostream& operator<< (std::ostream& os, const RcvParameters& r) -{ - os << " RcvParamters:: \n" - << (ParameterType)r - << " WindowLength : " << r.windowLength << "\n" - << " SampleRate : " << r.sampleRate << "\n" - << " IFFilterBW : " << r.ifFilterBW << "\n" - << " PathGain : " << r.pathGain << "\n"; - return os; -} - -std::ostream& operator<< (std::ostream& os, const TxRcv& t) -{ - os << "TxRcv:: \n" - << " NumTxWFs : " << t.txWFParameters.size() << "\n" - << " NumRcvs : " << t.rcvParameters.size() << "\n"; - for (size_t ii = 0; ii < t.txWFParameters.size(); ++ii) - { - os << t.txWFParameters[ii] << "\n"; - } - for (size_t ii = 0; ii < t.rcvParameters.size(); ++ii) - { - os << t.rcvParameters[ii] << "\n"; - } - return os; -} -} +/* ========================================================================= + * This file is part of cphd-c++ + * ========================================================================= + * + * (C) Copyright 2004 - 2019, MDA Information Systems LLC + * + * cphd-c++ is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; If not, + * see . + * + */ + +#include +#include + +namespace cphd +{ + +ParameterType::ParameterType() : + freqCenter(six::Init::undefined()), + lfmRate(six::Init::undefined()) +{ +} + +TxWFParameters::TxWFParameters() : + pulseLength(six::Init::undefined()), + rfBandwidth(six::Init::undefined()), + power(six::Init::undefined()) +{ +} + +RcvParameters::RcvParameters() : + windowLength(six::Init::undefined()), + sampleRate(six::Init::undefined()), + ifFilterBW(six::Init::undefined()), + pathGain(six::Init::undefined()) +{ +} + +TxRcv::TxRcv() +{ +} + +std::ostream& operator<< (std::ostream& os, const ParameterType& p) +{ + os << " Identifier : " << p.identifier << "\n" + << " FreqCenter : " << p.freqCenter << "\n" + << " LFMRate : " << p.lfmRate << "\n" + << " Polarization : " << p.polarization << "\n"; + return os; +} + +std::ostream& operator<< (std::ostream& os, const TxWFParameters& t) +{ + os << " TxWFParamters:: \n" + << (ParameterType)t + << " PulseLength : " << t.pulseLength << "\n" + << " RFBandwidth : " << t.rfBandwidth << "\n" + << " Power : " << t.power << "\n"; + return os; +} + +std::ostream& operator<< (std::ostream& os, const RcvParameters& r) +{ + os << " RcvParamters:: \n" + << (ParameterType)r + << " WindowLength : " << r.windowLength << "\n" + << " SampleRate : " << r.sampleRate << "\n" + << " IFFilterBW : " << r.ifFilterBW << "\n" + << " PathGain : " << r.pathGain << "\n"; + return os; +} + +std::ostream& operator<< (std::ostream& os, const TxRcv& t) +{ + os << "TxRcv:: \n" + << " NumTxWFs : " << t.txWFParameters.size() << "\n" + << " NumRcvs : " << t.rcvParameters.size() << "\n"; + for (size_t ii = 0; ii < t.txWFParameters.size(); ++ii) + { + os << t.txWFParameters[ii] << "\n"; + } + for (size_t ii = 0; ii < t.rcvParameters.size(); ++ii) + { + os << t.rcvParameters[ii] << "\n"; + } + return os; +} +} diff --git a/six/modules/c++/cphd/unittests/test_channel.cpp b/six/modules/c++/cphd/unittests/test_channel.cpp index 00820eaf35..ae679bc374 100644 --- a/six/modules/c++/cphd/unittests/test_channel.cpp +++ b/six/modules/c++/cphd/unittests/test_channel.cpp @@ -1,85 +1,85 @@ -/* ========================================================================= - * This file is part of cphd-c++ - * ========================================================================= - * - * (C) Copyright 2004 - 2019, MDA Information Systems LLC - * - * cphd-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ -#include - -#include - -#include -#include -#include -#include - -#include "TestCase.h" - -TEST_CASE(EmptyChannel) -{ - cphd::Channel channel1, channel2; - channel1.parameters.resize(3); - channel2.parameters.resize(3); - TEST_ASSERT_TRUE((channel1.parameters == channel2.parameters)); - TEST_ASSERT_TRUE((channel1 == channel2)); -} - -TEST_CASE(TestPolygonInvalid) -{ - cphd::Channel channel; - - six::Vector2 vertex1, vertex2; - vertex1[0] = 0; - vertex1[1] = 0; - vertex2[0] = 5; - vertex2[1] = 5; - - channel.parameters.resize(1); - channel.parameters[0].imageArea.x1y1[0] = 0; - channel.parameters[0].imageArea.x1y1[1] = 0; - channel.parameters[0].imageArea.x2y2[0] = 10; - channel.parameters[0].imageArea.x2y2[1] = 10; - channel.parameters[0].imageArea.polygon.push_back(vertex1); - channel.parameters[0].imageArea.polygon.push_back(vertex2); - - TEST_ASSERT_FALSE(channel.parameters[0].imageArea.polygon.size() >= 3); -} - - -TEST_CASE(TxRcvMultIds) -{ - cphd::Channel channel; - channel.parameters.resize(2); - channel.parameters[0].txRcv.reset(new cphd::ChannelParameter::TxRcv()); - channel.parameters[0].txRcv->txWFId.push_back("TransmitWaveformParam1"); - channel.parameters[0].txRcv->txWFId.push_back("TransmitWaveformParam2"); - channel.parameters[0].txRcv->txWFId.push_back("TransmitWaveformParam3"); - - channel.parameters[0].txRcv->rcvId.push_back("ReceiverWaveformParam1"); - channel.parameters[0].txRcv->rcvId.push_back("ReceiverWaveformParam2"); - - TEST_ASSERT_EQ(channel.parameters[0].txRcv->txWFId.size(), static_cast(3)); - TEST_ASSERT_EQ(channel.parameters[0].txRcv->rcvId.size(), static_cast(2)); -} - -TEST_MAIN( - TEST_CHECK(EmptyChannel); - TEST_CHECK(TestPolygonInvalid); - TEST_CHECK(TxRcvMultIds); - ) - +/* ========================================================================= + * This file is part of cphd-c++ + * ========================================================================= + * + * (C) Copyright 2004 - 2019, MDA Information Systems LLC + * + * cphd-c++ is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; If not, + * see . + * + */ +#include + +#include + +#include +#include +#include +#include + +#include "TestCase.h" + +TEST_CASE(EmptyChannel) +{ + cphd::Channel channel1, channel2; + channel1.parameters.resize(3); + channel2.parameters.resize(3); + TEST_ASSERT_TRUE((channel1.parameters == channel2.parameters)); + TEST_ASSERT_TRUE((channel1 == channel2)); +} + +TEST_CASE(TestPolygonInvalid) +{ + cphd::Channel channel; + + six::Vector2 vertex1, vertex2; + vertex1[0] = 0; + vertex1[1] = 0; + vertex2[0] = 5; + vertex2[1] = 5; + + channel.parameters.resize(1); + channel.parameters[0].imageArea.x1y1[0] = 0; + channel.parameters[0].imageArea.x1y1[1] = 0; + channel.parameters[0].imageArea.x2y2[0] = 10; + channel.parameters[0].imageArea.x2y2[1] = 10; + channel.parameters[0].imageArea.polygon.push_back(vertex1); + channel.parameters[0].imageArea.polygon.push_back(vertex2); + + TEST_ASSERT_FALSE(channel.parameters[0].imageArea.polygon.size() >= 3); +} + + +TEST_CASE(TxRcvMultIds) +{ + cphd::Channel channel; + channel.parameters.resize(2); + channel.parameters[0].txRcv.reset(new cphd::ChannelParameter::TxRcv()); + channel.parameters[0].txRcv->txWFId.push_back("TransmitWaveformParam1"); + channel.parameters[0].txRcv->txWFId.push_back("TransmitWaveformParam2"); + channel.parameters[0].txRcv->txWFId.push_back("TransmitWaveformParam3"); + + channel.parameters[0].txRcv->rcvId.push_back("ReceiverWaveformParam1"); + channel.parameters[0].txRcv->rcvId.push_back("ReceiverWaveformParam2"); + + TEST_ASSERT_EQ(channel.parameters[0].txRcv->txWFId.size(), static_cast(3)); + TEST_ASSERT_EQ(channel.parameters[0].txRcv->rcvId.size(), static_cast(2)); +} + +TEST_MAIN( + TEST_CHECK(EmptyChannel); + TEST_CHECK(TestPolygonInvalid); + TEST_CHECK(TxRcvMultIds); + ) + diff --git a/six/modules/c++/cphd/unittests/test_cphd_xml_optional.cpp b/six/modules/c++/cphd/unittests/test_cphd_xml_optional.cpp index 2bfe76f733..ebc55372f2 100644 --- a/six/modules/c++/cphd/unittests/test_cphd_xml_optional.cpp +++ b/six/modules/c++/cphd/unittests/test_cphd_xml_optional.cpp @@ -1,1129 +1,1129 @@ -/* ========================================================================= - * This file is part of cphd-c++ - * ========================================================================= - * - * (C) Copyright 2004 - 2019, MDA Information Systems LLC - * - * cphd-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "TestCase.h" - -const char* test_cphd_xml_optional_XML = -"\n" -" \n" -" Collector\n" -" Core\n" -" MONOSTATIC\n" -" \n" -" STRIPMAP\n" -" Mode\n" -" \n" -" U\n" -" Release\n" -" US,GB,AZ\n" -" val\n" -" \n" -" \n" -" FX\n" -" +1\n" -" \n" -" 2013-04-10T08:52:09.000000Z\n" -" 2014-04-10T08:52:09.000000Z\n" -" 1.300000000000000E00\n" -" 1.500000000000000E00\n" -" \n" -" \n" -" 9.000000000000000E-01\n" -" 1.700000000000000E00\n" -" \n" -" \n" -" 3.400000000000000E00\n" -" 6.100000000000000E00\n" -" \n" -" \n" -" 6.520000000000000E01\n" -" IARP\n" -" \n" -" \n" -" 5.800000000000000E00\n" -" 3.000000000000000E00\n" -" \n" -" \n" -" \n" -" WGS_84\n" -" \n" -" \n" -" 1.200000000000000E00\n" -" 2.300000000000000E00\n" -" 3.400000000000000E00\n" -" \n" -" \n" -" 4.500000000000000E01\n" -" -1.020000000000000E02\n" -" 3.400000000000000E00\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" 1.200000000000000E01\n" -" 2.400000000000000E01\n" -" \n" -" \n" -" 3.600000000000000E01\n" -" 4.800000000000000E01\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" 3.500000000000000E00\n" -" 5.300000000000000E00\n" -" \n" -" \n" -" 5.300000000000000E00\n" -" 3.500000000000000E00\n" -" \n" -" \n" -" \n" -" 1.000000000000000E-01\n" -" 3.000000000000000E-01\n" -" \n" -" \n" -" 4.000000000000000E-01\n" -" 2.000000000000000E-01\n" -" \n" -" \n" -" 5.000000000000000E-01\n" -" 9.000000000000000E-01\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" 1.000000000000000E01\n" -" 1.100000000000000E01\n" -" \n" -" \n" -" 2.000000000000000E01\n" -" 2.100000000000000E01\n" -" \n" -" \n" -" 3.000000000000000E01\n" -" 3.100000000000000E01\n" -" \n" -" \n" -" 4.000000000000000E01\n" -" 4.100000000000000E01\n" -" \n" -" \n" -" \n" -" Grid\n" -" \n" -" 1.230000000000000E00\n" -" 3.210000000000000E00\n" -" \n" -" \n" -" 3.140000000000000E00\n" -" 4\n" -" 50\n" -" \n" -" \n" -" 6.280000000000000E00\n" -" 8\n" -" 100\n" -" \n" -" \n" -" 2\n" -" \n" -" Segment1\n" -" 0\n" -" 1\n" -" 2\n" -" 3\n" -" \n" -" \n" -" 4.000000000000000E-01\n" -" 6.000000000000000E-01\n" -" \n" -" \n" -" 8.000000000000000E-01\n" -" 1.200000000000000E00\n" -" \n" -" \n" -" 1.200000000000000E00\n" -" 1.800000000000000E00\n" -" \n" -" \n" -" \n" -" \n" -" Segment2\n" -" 1\n" -" 2\n" -" 3\n" -" 4\n" -" \n" -" \n" -" 4.000000000000000E-01\n" -" 6.000000000000000E-01\n" -" \n" -" \n" -" 8.000000000000000E-01\n" -" 1.200000000000000E00\n" -" \n" -" \n" -" 1.200000000000000E00\n" -" 1.800000000000000E00\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" CI4\n" -" 24\n" -" 2\n" -" Compress\n" -" \n" -" Channel\n" -" 2\n" -" 3\n" -" 0\n" -" 1\n" -" 3\n" -" \n" -" \n" -" Channel\n" -" 2\n" -" 3\n" -" 0\n" -" 1\n" -" 3\n" -" \n" -" 3\n" -" \n" -" 1.0\n" -" 3\n" -" 4\n" -" 8\n" -" 0\n" -" \n" -" \n" -" 2.0\n" -" 3\n" -" 4\n" -" 4\n" -" 96\n" -" \n" -" \n" -" AddedSupportArray\n" -" 3\n" -" 4\n" -" 4\n" -" 144\n" -" \n" -" \n" -" \n" -" ChId\n" -" true\n" -" false\n" -" true\n" -" \n" -" CPI\n" -" 1\n" -" false\n" -" true\n" -" true\n" -" false\n" -" \n" -" X\n" -" RHC\n" -" \n" -" 1.300000000000000E00\n" -" 8.000000000000000E-01\n" -" 5.000000000000000E-01\n" -" 2.700000000000000E00\n" -" \n" -" 1.000000000000000E00\n" -" \n" -" 1.000000000000000E00\n" -" 2.000000000000000E00\n" -" 1.000000000000000E00\n" -" 2.000000000000000E00\n" -" \n" -" \n" -" \n" -" CODPolynomial\n" -" DwellPolynomial\n" -" \n" -" \n" -" \n" -" 3.500000000000000E00\n" -" 5.300000000000000E00\n" -" \n" -" \n" -" 5.300000000000000E00\n" -" 3.500000000000000E00\n" -" \n" -" \n" -" \n" -" 1.000000000000000E-01\n" -" 3.000000000000000E-01\n" -" \n" -" \n" -" 4.000000000000000E-01\n" -" 2.000000000000000E-01\n" -" \n" -" \n" -" 5.000000000000000E-01\n" -" 9.000000000000000E-01\n" -" \n" -" \n" -" \n" -" \n" -" TxAPCId\n" -" TxAPATId\n" -" RcvAPCId\n" -" RcvAPATId\n" -" \n" -" \n" -" TxWFId\n" -" RcvId\n" -" \n" -" \n" -" 1.200000000000000E01\n" -" \n" -" \n" -" 5.000000000000000E-01\n" -" 8.000000000000000E-01\n" -" \n" -" \n" -" 3.000000000000000E-01\n" -" 2.700000000000000E00\n" -" \n" -" \n" -" 5.000000000000000E-01\n" -" 2.700000000000000E00\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" Param\n" -" Param\n" -" \n" -" \n" -" \n" -" \n" -" 0\n" -" 1\n" -" F8\n" -" \n" -" \n" -" 1\n" -" 3\n" -" X=F8;Y=F8;Z=F8;\n" -" \n" -" \n" -" 4\n" -" 3\n" -" X=F8;Y=F8;Z=F8;\n" -" \n" -" \n" -" 7\n" -" 1\n" -" F8\n" -" \n" -" \n" -" 8\n" -" 3\n" -" X=F8;Y=F8;Z=F8;\n" -" \n" -" \n" -" 11\n" -" 3\n" -" X=F8;Y=F8;Z=F8;\n" -" \n" -" \n" -" 14\n" -" 3\n" -" X=F8;Y=F8;Z=F8;\n" -" \n" -" \n" -" 17\n" -" 1\n" -" F8\n" -" \n" -" \n" -" 18\n" -" 1\n" -" F8\n" -" \n" -" \n" -" 19\n" -" 1\n" -" F8\n" -" \n" -" \n" -" 20\n" -" 1\n" -" F8\n" -" \n" -" \n" -" 21\n" -" 1\n" -" F8\n" -" \n" -" \n" -" 22\n" -" 1\n" -" F8\n" -" \n" -" \n" -" 23\n" -" 1\n" -" F8\n" -" \n" -" \n" -" 24\n" -" 1\n" -" F8\n" -" \n" -" \n" -" 25\n" -" 1\n" -" F8\n" -" \n" -" \n" -" 26\n" -" 1\n" -" F8\n" -" \n" -" \n" -" newParam1\n" -" 27\n" -" 1\n" -" F8\n" -" \n" -" \n" -" newParam2\n" -" 28\n" -" 1\n" -" F8\n" -" \n" -" \n" -" \n" -" \n" -" 1\n" -" IAZ=F4;\n" -" 0.000000000000000E00\n" -" 0.000000000000000E00\n" -" 5.000000000000000E00\n" -" 5.000000000000000E00\n" -" \n" -" \n" -" 2\n" -" Gain=F4;Phase=F4;\n" -" 0.000000000000000E00\n" -" 0.000000000000000E00\n" -" 5.000000000000000E00\n" -" 5.000000000000000E00\n" -" \n" -" \n" -" AddedSupportArray\n" -" F4\n" -" 0.000000000000000E00\n" -" 0.000000000000000E00\n" -" 5.000000000000000E00\n" -" 5.000000000000000E00\n" -" XUnits\n" -" YUnits\n" -" ZUnits\n" -" Additional parameter\n" -" Additional parameter\n" -" \n" -" \n" -" \n" -" 1\n" -" \n" -" codPolynomial1\n" -" \n" -" 0.000000000000000E00\n" -" 5.000000000000000E00\n" -" 5.000000000000000E00\n" -" 0.000000000000000E00\n" -" \n" -" \n" -" 1\n" -" \n" -" dwellPolynomial1\n" -" \n" -" 0.000000000000000E00\n" -" 2.000000000000000E00\n" -" 3.000000000000000E00\n" -" 0.000000000000000E00\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" 1.000000000000000E00\n" -" 2.000000000000000E00\n" -" 3.500000000000000E00\n" -" \n" -" \n" -" 1.500000000000000E00\n" -" 2.500000000000000E00\n" -" 4.000000000000000E00\n" -" \n" -" \n" -" 0.000000000000000E00\n" -" 2.300000000000000E01\n" -" 2.500000000000000E01\n" -" \n" -" \n" -" 1.000000000000000E01\n" -" 1.000000000000000E01\n" -" 1.000000000000000E01\n" -" \n" -" \n" -" 1.000000000000000E01\n" -" 1.000000000000000E01\n" -" 1.000000000000000E01\n" -" \n" -" L\n" -" 2.000000000000000E01\n" -" 2.000000000000000E01\n" -" 3.000000000000000E01\n" -" 3.000000000000000E01\n" -" 3.000000000000000E01\n" -" 3.000000000000000E01\n" -" 3.000000000000000E01\n" -" 3.000000000000000E01\n" -" 3.000000000000000E01\n" -" \n" -" \n" -" \n" -" 2\n" -" 1\n" -" 1\n" -" \n" -" ACF1\n" -" \n" -" \n" -" 1.000000000000000E00\n" -" 2.000000000000000E00\n" -" 3.000000000000000E00\n" -" 4.000000000000000E00\n" -" \n" -" \n" -" 1.000000000000000E00\n" -" 2.000000000000000E00\n" -" 3.000000000000000E00\n" -" 4.000000000000000E00\n" -" \n" -" \n" -" 1.000000000000000E00\n" -" 0.000000000000000E00\n" -" 3.000000000000000E00\n" -" 0.000000000000000E00\n" -" \n" -" \n" -" \n" -" \n" -" 1.000000000000000E00\n" -" 2.000000000000000E00\n" -" \n" -" \n" -" 1.000000000000000E00\n" -" 2.000000000000000E00\n" -" \n" -" \n" -" 1.000000000000000E00\n" -" 2.000000000000000E00\n" -" \n" -" \n" -" \n" -" \n" -" ACF2\n" -" \n" -" \n" -" 1.000000000000000E00\n" -" 2.000000000000000E00\n" -" \n" -" \n" -" 1.000000000000000E00\n" -" 2.000000000000000E00\n" -" \n" -" \n" -" 1.000000000000000E00\n" -" 2.000000000000000E00\n" -" \n" -" \n" -" \n" -" \n" -" 1.000000000000000E00\n" -" 2.000000000000000E00\n" -" \n" -" \n" -" 1.000000000000000E00\n" -" 2.000000000000000E00\n" -" \n" -" \n" -" 1.000000000000000E00\n" -" 2.000000000000000E00\n" -" \n" -" \n" -" \n" -" \n" -" APC\n" -" ACF1\n" -" \n" -" 5.000000000000000E00\n" -" 5.000000000000000E00\n" -" 5.000000000000000E00\n" -" \n" -" \n" -" \n" -" APAT\n" -" 2.300000000000000E00\n" -" 2.300000000000000E00\n" -" 1\n" -" 0\n" -" \n" -" 1.000000000000000E00\n" -" 2.000000000000000E00\n" -" \n" -" \n" -" \n" -" 5.000000000000000E00\n" -" 0.000000000000000E00\n" -" \n" -" \n" -" 0.000000000000000E00\n" -" 5.000000000000000E00\n" -" \n" -" \n" -" \n" -" \n" -" 0.000000000000000E00\n" -" 1.000000000000000E00\n" -" 1.000000000000000E00\n" -" 5.000000000000000E00\n" -" \n" -" \n" -" 0.000000000000000E00\n" -" 1.000000000000000E00\n" -" 1.000000000000000E00\n" -" 5.000000000000000E00\n" -" \n" -" \n" -" \n" -" \n" -" 0.000000000000000E00\n" -" 1.000000000000000E00\n" -" 1.000000000000000E00\n" -" 5.000000000000000E00\n" -" \n" -" \n" -" 0.000000000000000E00\n" -" 1.000000000000000E00\n" -" 1.000000000000000E00\n" -" 5.000000000000000E00\n" -" \n" -" \n" -" \n" -" 2.300000000000000E00\n" -" Parameter1\n" -" Parameter2\n" -" \n" -" \n" -" 2.800000000000000E00\n" -" Parameter1\n" -" Parameter2\n" -" \n" -" \n" -" \n" -" \n" -" 1\n" -" \n" -" TxWFParam\n" -" 3.000000000000000E00\n" -" 2.300000000000000E00\n" -" 1.800000000000000E00\n" -" 1.000000000000000E00\n" -" LHC\n" -" 5.000000000000000E00\n" -" \n" -" 2\n" -" \n" -" RcvParam1\n" -" 3.000000000000000E00\n" -" 2.300000000000000E00\n" -" 2.300000000000000E00\n" -" 1.800000000000000E00\n" -" 1.000000000000000E00\n" -" LHC\n" -" 5.000000000000000E00\n" -" \n" -" \n" -" RcvParam2\n" -" 3.000000000000000E00\n" -" 2.300000000000000E00\n" -" 2.300000000000000E00\n" -" 1.800000000000000E00\n" -" 1.000000000000000E00\n" -" LHC\n" -" 5.000000000000000E00\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" ECF\n" -" 1.000000000000000E00\n" -" 1.000000000000000E00\n" -" 1.000000000000000E00\n" -" 1.000000000000000E00\n" -" 1.000000000000000E00\n" -" 1.000000000000000E00\n" -" \n" -" 8.000000000000000E-01\n" -" 8.000000000000000E-01\n" -" 8.000000000000000E-01\n" -" 8.000000000000000E-01\n" -" 8.000000000000000E-01\n" -" 8.000000000000000E-01\n" -" 8.000000000000000E-01\n" -" 8.000000000000000E-01\n" -" 8.000000000000000E-01\n" -" 8.000000000000000E-01\n" -" 8.000000000000000E-01\n" -" 8.000000000000000E-01\n" -" 8.000000000000000E-01\n" -" 8.000000000000000E-01\n" -" 8.000000000000000E-01\n" -" \n" -" \n" -" 5.000000000000000E-01\n" -" 1.000000000000000E00\n" -" \n" -" \n" -" \n" -" 5.000000000000000E-01\n" -" 1.000000000000000E00\n" -" 1.000000000000000E00\n" -" \n" -" 5.000000000000000E-01\n" -" 1.000000000000000E00\n" -" \n" -" \n" -" \n" -" 5.000000000000000E00\n" -" 5.000000000000000E00\n" -" \n" -" 5.000000000000000E-01\n" -" 1.000000000000000E00\n" -" \n" -" \n" -" \n" -" 5.000000000000000E00\n" -" 5.000000000000000E00\n" -" 5.000000000000000E-01\n" -" \n" -" 5.000000000000000E-01\n" -" 1.000000000000000E00\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" Profile\n" -" \n" -" Application\n" -" 2014-04-10T08:52:09.000000Z\n" -" Area51\n" -" Value1\n" -" Value2\n" -" \n" -" Value1\n" -" \n" -" \n" -" 51\n" -" \n" -" \n" -" \n" -" 0.000000000000000E00\n" -" 0.000000000000000E00\n" -" \n" -" \n" -" 1.000000000000000E-01\n" -" 0.000000000000000E00\n" -" \n" -" \n" -" 1.000000000000000E-01\n" -" 1.000000000000000E-01\n" -" \n" -" \n" -" 0.000000000000000E00\n" -" 0.000000000000000E00\n" -" \n" -" \n" -" \n" -" \n" -" 04/22\n" -" \n" -" \n" -" 2.000000000000000E-02\n" -" 3.000000000000000E-02\n" -" \n" -" \n" -" 8.000000000000000E-02\n" -" 8.000000000000000E-02\n" -" \n" -" \n" -" \n" -" \n" -" 09/27\n" -" \n" -" \n" -" 5.000000000000000E-02\n" -" 2.000000000000000E-02\n" -" \n" -" \n" -" 5.000000000000000E-02\n" -" 8.000000000000000E-02\n" -" \n" -" \n" -" \n" -" \n" -" Main\n" -" \n" -" 6.000000000000000E-01\n" -" 4.000000000000000E-01\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" 1.000000000000000E00\n" -" 1.000000000000000E00\n" -" \n" -" \n" -" 1.100000000000000E00\n" -" 1.000000000000000E00\n" -" \n" -" \n" -" 1.100000000000000E00\n" -" 1.100000000000000E00\n" -" \n" -" \n" -" 1.200000000000000E00\n" -" 1.200000000000000E00\n" -" \n" -" \n" -" 1.000000000000000E00\n" -" 1.000000000000000E00\n" -" \n" -" \n" -" \n" -" \n" -" 2\n" -" \n" -" STEREO\n" -" 1\n" -" 1\n" -" \n" -" CollectionName\n" -" 1\n" -" Match1\n" -" \n" -" \n" -" \n" -" COHERENT\n" -" 1\n" -" 1\n" -" \n" -" CollectionName\n" -" 1\n" -" Match1\n" -" \n" -" \n" -" \n" -"\n"; - -TEST_CASE(testOptional) -{ - io::StringStream cphdStream; - cphdStream.write(test_cphd_xml_optional_XML, strlen(test_cphd_xml_optional_XML)); - - xml::lite::MinidomParser xmlParser; - xmlParser.preserveCharacterData(true); - xmlParser.parse(cphdStream, cphdStream.available()); - const std::unique_ptr metadata = - cphd::CPHDXMLControl().fromXML(xmlParser.getDocument()); - - const cphd::SupportArray& supportArray = *(metadata->supportArray); - TEST_ASSERT_EQ(supportArray.iazArray.size(), static_cast(1)); - TEST_ASSERT_EQ(supportArray.iazArray[0].getIdentifier(), static_cast(1)); - TEST_ASSERT_EQ(supportArray.iazArray[0].elementFormat, "IAZ=F4;"); - TEST_ASSERT_EQ(supportArray.iazArray[0].x0, 0.0); - TEST_ASSERT_EQ(supportArray.iazArray[0].y0, 0.0); - TEST_ASSERT_EQ(supportArray.iazArray[0].xSS, 5.0); - TEST_ASSERT_EQ(supportArray.iazArray[0].ySS, 5.0); - - TEST_ASSERT_EQ(supportArray.antGainPhase.size(), static_cast(1)); - TEST_ASSERT_EQ(supportArray.antGainPhase[0].getIdentifier(), static_cast(2)); - TEST_ASSERT_EQ(supportArray.antGainPhase[0].elementFormat, "Gain=F4;Phase=F4;"); - TEST_ASSERT_EQ(supportArray.antGainPhase[0].x0, 0.0); - TEST_ASSERT_EQ(supportArray.antGainPhase[0].y0, 0.0); - TEST_ASSERT_EQ(supportArray.antGainPhase[0].xSS, 5.0); - TEST_ASSERT_EQ(supportArray.antGainPhase[0].ySS, 5.0); - - TEST_ASSERT_EQ(supportArray.addedSupportArray.size(), static_cast(1)); - TEST_ASSERT_EQ(supportArray.addedSupportArray.count("AddedSupportArray"), static_cast(1)); - TEST_ASSERT_EQ(supportArray.addedSupportArray.find("AddedSupportArray")->second.elementFormat, "F4"); - TEST_ASSERT_EQ(supportArray.addedSupportArray.find("AddedSupportArray")->second.x0, 0.0); - TEST_ASSERT_EQ(supportArray.addedSupportArray.find("AddedSupportArray")->second.y0, 0.0); - TEST_ASSERT_EQ(supportArray.addedSupportArray.find("AddedSupportArray")->second.xSS, 5.0); - TEST_ASSERT_EQ(supportArray.addedSupportArray.find("AddedSupportArray")->second.ySS, 5.0); - TEST_ASSERT_EQ(supportArray.addedSupportArray.find("AddedSupportArray")->second.xUnits, "XUnits"); - TEST_ASSERT_EQ(supportArray.addedSupportArray.find("AddedSupportArray")->second.yUnits, "YUnits"); - TEST_ASSERT_EQ(supportArray.addedSupportArray.find("AddedSupportArray")->second.zUnits, "ZUnits"); - TEST_ASSERT_EQ(supportArray.addedSupportArray.find("AddedSupportArray")->second.parameter.size(), static_cast(2)); - TEST_ASSERT_EQ(supportArray.addedSupportArray.find("AddedSupportArray")->second.parameter[0].getName(), "Parameter1"); - TEST_ASSERT_EQ(supportArray.addedSupportArray.find("AddedSupportArray")->second.parameter[1].getName(), "Parameter2"); - TEST_ASSERT_EQ(supportArray.addedSupportArray.find("AddedSupportArray")->second.parameter[0].str(), "Additional parameter"); - TEST_ASSERT_EQ(supportArray.addedSupportArray.find("AddedSupportArray")->second.parameter[1].str(), "Additional parameter"); - - const cphd::Antenna& antenna = *(metadata->antenna); - TEST_ASSERT_EQ(antenna.antCoordFrame.size(), static_cast(2)); - TEST_ASSERT_EQ(antenna.antCoordFrame[0].identifier, "ACF1"); - TEST_ASSERT_EQ(antenna.antCoordFrame[0].xAxisPoly.order(), static_cast(3)); - TEST_ASSERT_EQ(antenna.antCoordFrame[0].xAxisPoly.coeffs()[0][0], 1); - TEST_ASSERT_EQ(antenna.antCoordFrame[0].xAxisPoly.coeffs()[1][0], 2); - TEST_ASSERT_EQ(antenna.antCoordFrame[0].xAxisPoly.coeffs()[2][0], 3); - TEST_ASSERT_EQ(antenna.antCoordFrame[0].xAxisPoly.coeffs()[3][0], 4); - TEST_ASSERT_EQ(antenna.antCoordFrame[0].xAxisPoly.coeffs()[0][1], 1); - TEST_ASSERT_EQ(antenna.antCoordFrame[0].xAxisPoly.coeffs()[1][1], 2); - TEST_ASSERT_EQ(antenna.antCoordFrame[0].xAxisPoly.coeffs()[2][1], 3); - TEST_ASSERT_EQ(antenna.antCoordFrame[0].xAxisPoly.coeffs()[3][1], 4); - TEST_ASSERT_EQ(antenna.antCoordFrame[0].xAxisPoly.coeffs()[0][2], 1); - TEST_ASSERT_EQ(antenna.antCoordFrame[0].xAxisPoly.coeffs()[1][2], 0); - TEST_ASSERT_EQ(antenna.antCoordFrame[0].xAxisPoly.coeffs()[2][2], 3); - TEST_ASSERT_EQ(antenna.antCoordFrame[0].xAxisPoly.coeffs()[3][2], 0); - - TEST_ASSERT_EQ(antenna.antCoordFrame[0].yAxisPoly.order(), static_cast(1)); - TEST_ASSERT_EQ(antenna.antCoordFrame[0].yAxisPoly.coeffs()[0][0], 1); - TEST_ASSERT_EQ(antenna.antCoordFrame[0].yAxisPoly.coeffs()[1][0], 2); - TEST_ASSERT_EQ(antenna.antCoordFrame[0].yAxisPoly.coeffs()[0][1], 1); - TEST_ASSERT_EQ(antenna.antCoordFrame[0].yAxisPoly.coeffs()[1][1], 2); - - TEST_ASSERT_EQ(antenna.antCoordFrame[1].identifier, "ACF2"); - TEST_ASSERT_EQ(antenna.antCoordFrame[1].xAxisPoly.order(), static_cast(1)); - TEST_ASSERT_EQ(antenna.antCoordFrame[1].xAxisPoly.coeffs()[0][0], 1); - TEST_ASSERT_EQ(antenna.antCoordFrame[1].xAxisPoly.coeffs()[1][0], 2); - TEST_ASSERT_EQ(antenna.antCoordFrame[1].xAxisPoly.coeffs()[0][1], 1); - TEST_ASSERT_EQ(antenna.antCoordFrame[1].xAxisPoly.coeffs()[1][1], 2); - - TEST_ASSERT_EQ(antenna.antCoordFrame[1].yAxisPoly.order(), static_cast(1)); - TEST_ASSERT_EQ(antenna.antCoordFrame[1].yAxisPoly.coeffs()[0][0], 1); - TEST_ASSERT_EQ(antenna.antCoordFrame[1].yAxisPoly.coeffs()[1][0], 2); - TEST_ASSERT_EQ(antenna.antCoordFrame[1].yAxisPoly.coeffs()[0][1], 1); - TEST_ASSERT_EQ(antenna.antCoordFrame[1].yAxisPoly.coeffs()[1][1], 2); - - TEST_ASSERT_EQ(antenna.antPhaseCenter.size(), static_cast(1)); - TEST_ASSERT_EQ(antenna.antPhaseCenter[0].identifier, "APC"); - TEST_ASSERT_EQ(antenna.antPhaseCenter[0].acfId, "ACF1"); - TEST_ASSERT_EQ(antenna.antPhaseCenter[0].apcXYZ[0], 5.0); - TEST_ASSERT_EQ(antenna.antPhaseCenter[0].apcXYZ[1], 5.0); - TEST_ASSERT_EQ(antenna.antPhaseCenter[0].apcXYZ[2], 5.0); - - TEST_ASSERT_EQ(antenna.antPhaseCenter[0].identifier, "APC"); - TEST_ASSERT_EQ(antenna.antPhaseCenter[0].acfId, "ACF1"); - TEST_ASSERT_EQ(antenna.antPhaseCenter[0].apcXYZ[0], 5.0); - TEST_ASSERT_EQ(antenna.antPhaseCenter[0].apcXYZ[1], 5.0); - TEST_ASSERT_EQ(antenna.antPhaseCenter[0].apcXYZ[2], 5.0); - - TEST_ASSERT_EQ(antenna.antPattern.size(), static_cast(1)); - TEST_ASSERT_EQ(antenna.antPattern[0].identifier, "APAT"); - TEST_ASSERT_EQ(antenna.antPattern[0].freqZero, 2.3); - TEST_ASSERT_EQ(antenna.antPattern[0].gainZero, 2.3); - TEST_ASSERT_EQ(antenna.antPattern[0].ebFreqShift, 1); - TEST_ASSERT_EQ(antenna.antPattern[0].mlFreqDilation, 0); - TEST_ASSERT_EQ(antenna.antPattern[0].gainBSPoly.order(), static_cast(1)); - TEST_ASSERT_EQ(antenna.antPattern[0].gainBSPoly.coeffs()[0], 1.0); - TEST_ASSERT_EQ(antenna.antPattern[0].gainBSPoly.coeffs()[1], 2.0); - TEST_ASSERT_EQ(antenna.antPattern[0].eb.dcxPoly.order(), static_cast(1)); - TEST_ASSERT_EQ(antenna.antPattern[0].eb.dcxPoly.coeffs()[0], 5.0); - TEST_ASSERT_EQ(antenna.antPattern[0].eb.dcyPoly.order(), static_cast(1)); - TEST_ASSERT_EQ(antenna.antPattern[0].eb.dcyPoly.coeffs()[0], 0.0); - TEST_ASSERT_EQ(antenna.antPattern[0].eb.dcyPoly.coeffs()[1], 5.0); - TEST_ASSERT_EQ(antenna.antPattern[0].array.gainPoly.orderX(), static_cast(1)); - TEST_ASSERT_EQ(antenna.antPattern[0].array.gainPoly.orderY(), static_cast(1)); - TEST_ASSERT_EQ(antenna.antPattern[0].array.phasePoly.orderX(), static_cast(1)); - TEST_ASSERT_EQ(antenna.antPattern[0].array.phasePoly.orderY(), static_cast(1)); - TEST_ASSERT_EQ(antenna.antPattern[0].element.gainPoly.orderX(), static_cast(1)); - TEST_ASSERT_EQ(antenna.antPattern[0].element.gainPoly.orderY(), static_cast(1)); - TEST_ASSERT_EQ(antenna.antPattern[0].element.phasePoly.orderX(), static_cast(1)); - TEST_ASSERT_EQ(antenna.antPattern[0].element.phasePoly.orderY(), static_cast(1)); - TEST_ASSERT_EQ(antenna.antPattern[0].gainPhaseArray[0].freq, 2.3); - TEST_ASSERT_EQ(antenna.antPattern[0].gainPhaseArray[0].arrayId, "Parameter1"); - TEST_ASSERT_EQ(antenna.antPattern[0].gainPhaseArray[0].elementId, "Parameter2"); - TEST_ASSERT_EQ(antenna.antPattern[0].gainPhaseArray[1].freq, 2.8); - TEST_ASSERT_EQ(antenna.antPattern[0].gainPhaseArray[1].arrayId, "Parameter1"); - TEST_ASSERT_EQ(antenna.antPattern[0].gainPhaseArray[1].elementId, "Parameter2"); - - const cphd::TxRcv& txRcv = *(metadata->txRcv); - TEST_ASSERT_EQ(txRcv.txWFParameters.size(), static_cast(1)); - TEST_ASSERT_EQ(txRcv.txWFParameters[0].identifier, "TxWFParam"); - TEST_ASSERT_EQ(txRcv.txWFParameters[0].pulseLength, 3.0); - TEST_ASSERT_EQ(txRcv.txWFParameters[0].rfBandwidth, 2.3); - TEST_ASSERT_EQ(txRcv.txWFParameters[0].freqCenter, 1.8); - TEST_ASSERT_EQ(txRcv.txWFParameters[0].lfmRate, 1.0); - TEST_ASSERT(txRcv.txWFParameters[0].polarization.toString() == "LHC"); - TEST_ASSERT_EQ(txRcv.txWFParameters[0].polarization, cphd::PolarizationType::LHC); - TEST_ASSERT_EQ(txRcv.txWFParameters[0].power, 5.0); - - TEST_ASSERT_EQ(txRcv.rcvParameters.size(), static_cast(2)); - TEST_ASSERT_EQ(txRcv.rcvParameters[0].identifier, "RcvParam1"); - TEST_ASSERT_EQ(txRcv.rcvParameters[0].windowLength, 3.0); - TEST_ASSERT_EQ(txRcv.rcvParameters[0].sampleRate, 2.3); - TEST_ASSERT_EQ(txRcv.rcvParameters[0].ifFilterBW, 2.3); - TEST_ASSERT_EQ(txRcv.rcvParameters[0].freqCenter, 1.8); - TEST_ASSERT_EQ(txRcv.rcvParameters[0].lfmRate, 1.0); - TEST_ASSERT(txRcv.rcvParameters[0].polarization.toString() == "LHC"); - TEST_ASSERT_EQ(txRcv.rcvParameters[0].polarization, cphd::PolarizationType::LHC); - TEST_ASSERT_EQ(txRcv.rcvParameters[0].pathGain, 5.0); - - TEST_ASSERT_EQ(txRcv.rcvParameters[1].identifier, "RcvParam2"); - TEST_ASSERT_EQ(txRcv.rcvParameters[1].windowLength, 3.0); - TEST_ASSERT_EQ(txRcv.rcvParameters[1].sampleRate, 2.3); - TEST_ASSERT_EQ(txRcv.rcvParameters[1].ifFilterBW, 2.3); - TEST_ASSERT_EQ(txRcv.rcvParameters[1].freqCenter, 1.8); - TEST_ASSERT_EQ(txRcv.rcvParameters[1].lfmRate, 1.0); - TEST_ASSERT(txRcv.rcvParameters[1].polarization.toString() == "LHC"); - TEST_ASSERT_EQ(txRcv.rcvParameters[1].polarization, cphd::PolarizationType::LHC); - TEST_ASSERT_EQ(txRcv.rcvParameters[1].pathGain, 5.0); - - const cphd::ErrorParameters& errorParams = *(metadata->errorParameters); - TEST_ASSERT(errorParams.monostatic->posVelErr.frame == "ECF"); - TEST_ASSERT_EQ(errorParams.monostatic->posVelErr.frame, six::FrameType(six::FrameType::ECF)); - TEST_ASSERT_EQ(errorParams.monostatic->posVelErr.p1, 1.0); - TEST_ASSERT_EQ(errorParams.monostatic->posVelErr.p2, 1.0); - TEST_ASSERT_EQ(errorParams.monostatic->posVelErr.corrCoefs->p1p2, 0.8); - TEST_ASSERT_EQ(errorParams.monostatic->posVelErr.corrCoefs->v2v3, 0.8); - TEST_ASSERT_EQ(six::value(errorParams.monostatic->posVelErr.positionDecorr).corrCoefZero, 0.5); - TEST_ASSERT_EQ(six::value(errorParams.monostatic->posVelErr.positionDecorr).decorrRate, 1.0); - TEST_ASSERT_EQ(errorParams.monostatic->radarSensor.rangeBias, 0.5); - TEST_ASSERT_EQ(errorParams.monostatic->radarSensor.clockFreqSF, 1.0); - TEST_ASSERT_EQ(errorParams.monostatic->radarSensor.collectionStartTime, 1.0); - TEST_ASSERT_EQ(errorParams.monostatic->radarSensor.rangeBiasDecorr->corrCoefZero, 0.5); - TEST_ASSERT_EQ(errorParams.monostatic->radarSensor.rangeBiasDecorr->decorrRate, 1.0); - TEST_ASSERT_EQ(six::value(errorParams.monostatic->tropoError->tropoRangeVertical), 5.0); - TEST_ASSERT_EQ(six::value(errorParams.monostatic->tropoError->tropoRangeSlant), 5.0); - const auto& tropoRangeDecorr = value(errorParams.monostatic->tropoError->tropoRangeDecorr); - TEST_ASSERT_EQ(tropoRangeDecorr.corrCoefZero, 0.5); - TEST_ASSERT_EQ(tropoRangeDecorr.decorrRate, 1.0); - TEST_ASSERT_EQ(six::value(errorParams.monostatic->ionoError->ionoRangeVertical), 5.0); - TEST_ASSERT_EQ(six::value(errorParams.monostatic->ionoError->ionoRangeRateVertical), 5.0); - TEST_ASSERT_EQ(six::value(errorParams.monostatic->ionoError->ionoRgRgRateCC), 0.5); - const auto& ionoRangeVertDecorr = six::value(errorParams.monostatic->ionoError->ionoRangeVertDecorr); - TEST_ASSERT_EQ(ionoRangeVertDecorr.corrCoefZero, 0.5); - TEST_ASSERT_EQ(ionoRangeVertDecorr.decorrRate, 1.0); - - const cphd::ProductInfo& productInfo = *(metadata->productInfo); - TEST_ASSERT_EQ(productInfo.profile, "Profile"); - TEST_ASSERT_EQ(productInfo.creationInfo[0].application, "Application"); - TEST_ASSERT_EQ(productInfo.creationInfo[0].dateTime.getYear(), 2014); - TEST_ASSERT_EQ(productInfo.creationInfo[0].site, "Area51"); - TEST_ASSERT_EQ(productInfo.creationInfo[0].parameter[0].getName(), "Param1"); - TEST_ASSERT_EQ(productInfo.creationInfo[0].parameter[1].getName(), "Param2"); - TEST_ASSERT_EQ(productInfo.parameter[0].getName(), "Param1"); - - std::vector geoInfo = metadata->geoInfo; - TEST_ASSERT_EQ(geoInfo[0].name, "Airport"); - TEST_ASSERT_EQ(geoInfo[0].desc[0].getName(), "Airport ID"); - TEST_ASSERT_EQ(geoInfo[0].desc[0].str(), "51"); - TEST_ASSERT_EQ(geoInfo[0].geoInfos[0]->name, "Perimeter"); - TEST_ASSERT_EQ(geoInfo[0].geoInfos[0]->geometryLatLon.size(), static_cast(4)); - TEST_ASSERT_EQ(geoInfo[0].geoInfos[0]->geometryLatLon[0].getLat(), 0.0); - TEST_ASSERT_EQ(geoInfo[0].geoInfos[0]->geometryLatLon[0].getLon(), 0.0); - TEST_ASSERT_EQ(geoInfo[0].geoInfos[0]->geometryLatLon[1].getLat(), 0.1); - TEST_ASSERT_EQ(geoInfo[0].geoInfos[0]->geometryLatLon[1].getLon(), 0.0); - TEST_ASSERT_EQ(geoInfo[0].geoInfos[0]->geometryLatLon[2].getLat(), 0.1); - TEST_ASSERT_EQ(geoInfo[0].geoInfos[0]->geometryLatLon[2].getLon(), 0.1); - TEST_ASSERT_EQ(geoInfo[0].geoInfos[0]->geometryLatLon[3].getLat(), 0.0); - TEST_ASSERT_EQ(geoInfo[0].geoInfos[0]->geometryLatLon[3].getLon(), 0.0); - - TEST_ASSERT_EQ(geoInfo[0].geoInfos[1]->name, "Runway"); - TEST_ASSERT_EQ(geoInfo[0].geoInfos[1]->desc[0].getName(), "ID"); - TEST_ASSERT_EQ(geoInfo[0].geoInfos[1]->desc[0].str(), "04/22"); - TEST_ASSERT_EQ(geoInfo[0].geoInfos[1]->geometryLatLon.size(), static_cast(2)); - TEST_ASSERT_EQ(geoInfo[0].geoInfos[1]->geometryLatLon[0].getLat(), 0.02); - TEST_ASSERT_EQ(geoInfo[0].geoInfos[1]->geometryLatLon[0].getLon(), 0.03); - TEST_ASSERT_EQ(geoInfo[0].geoInfos[1]->geometryLatLon[1].getLat(), 0.08); - TEST_ASSERT_EQ(geoInfo[0].geoInfos[1]->geometryLatLon[1].getLon(), 0.08); - - TEST_ASSERT_EQ(geoInfo[0].geoInfos[3]->name, "Control Tower"); - TEST_ASSERT_EQ(geoInfo[0].geoInfos[3]->desc[0].getName(), "ID"); - TEST_ASSERT_EQ(geoInfo[0].geoInfos[3]->desc[0].str(), "Main"); - TEST_ASSERT_EQ(geoInfo[0].geoInfos[3]->geometryLatLon[0].getLat(), 0.6); - TEST_ASSERT_EQ(geoInfo[0].geoInfos[3]->geometryLatLon[0].getLon(), 0.4); - - TEST_ASSERT_EQ(geoInfo[1].name, "Farm"); - TEST_ASSERT_EQ(geoInfo[1].geometryLatLon.size(), static_cast(5)); - TEST_ASSERT_EQ(geoInfo[1].geometryLatLon[0].getLat(), 1.0); - TEST_ASSERT_EQ(geoInfo[1].geometryLatLon[0].getLon(), 1.0); - TEST_ASSERT_EQ(geoInfo[1].geometryLatLon[1].getLat(), 1.1); - TEST_ASSERT_EQ(geoInfo[1].geometryLatLon[1].getLon(), 1.0); - TEST_ASSERT_EQ(geoInfo[1].geometryLatLon[4].getLat(), 1.0); - TEST_ASSERT_EQ(geoInfo[1].geometryLatLon[4].getLon(), 1.0); - - const cphd::MatchInformation& matchInfo = *(metadata->matchInfo); - TEST_ASSERT_EQ(matchInfo.types.size(), static_cast(2)); - TEST_ASSERT_EQ(matchInfo.types[0].typeID, "STEREO"); - TEST_ASSERT_EQ(matchInfo.types[0].currentIndex, 1); - TEST_ASSERT_EQ(matchInfo.types[0].matchCollects.size(), static_cast(1)); - TEST_ASSERT_EQ(matchInfo.types[0].matchCollects[0].coreName, "CollectionName"); - TEST_ASSERT_EQ(matchInfo.types[0].matchCollects[0].matchIndex, 1); - TEST_ASSERT_EQ(matchInfo.types[0].matchCollects[0].parameters[0].getName(), "param1"); - TEST_ASSERT_EQ(matchInfo.types[1].typeID, "COHERENT"); - TEST_ASSERT_EQ(matchInfo.types[1].currentIndex, 1); - TEST_ASSERT_EQ(matchInfo.types[1].matchCollects.size(), static_cast(1)); - TEST_ASSERT_EQ(matchInfo.types[1].matchCollects[0].coreName, "CollectionName"); - TEST_ASSERT_EQ(matchInfo.types[1].matchCollects[0].matchIndex, 1); - TEST_ASSERT_EQ(matchInfo.types[1].matchCollects[0].parameters[0].getName(), "param1"); -} - -TEST_MAIN( - TEST_CHECK(testOptional); +/* ========================================================================= + * This file is part of cphd-c++ + * ========================================================================= + * + * (C) Copyright 2004 - 2019, MDA Information Systems LLC + * + * cphd-c++ is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; If not, + * see . + * + */ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "TestCase.h" + +const char* test_cphd_xml_optional_XML = +"\n" +" \n" +" Collector\n" +" Core\n" +" MONOSTATIC\n" +" \n" +" STRIPMAP\n" +" Mode\n" +" \n" +" U\n" +" Release\n" +" US,GB,AZ\n" +" val\n" +" \n" +" \n" +" FX\n" +" +1\n" +" \n" +" 2013-04-10T08:52:09.000000Z\n" +" 2014-04-10T08:52:09.000000Z\n" +" 1.300000000000000E00\n" +" 1.500000000000000E00\n" +" \n" +" \n" +" 9.000000000000000E-01\n" +" 1.700000000000000E00\n" +" \n" +" \n" +" 3.400000000000000E00\n" +" 6.100000000000000E00\n" +" \n" +" \n" +" 6.520000000000000E01\n" +" IARP\n" +" \n" +" \n" +" 5.800000000000000E00\n" +" 3.000000000000000E00\n" +" \n" +" \n" +" \n" +" WGS_84\n" +" \n" +" \n" +" 1.200000000000000E00\n" +" 2.300000000000000E00\n" +" 3.400000000000000E00\n" +" \n" +" \n" +" 4.500000000000000E01\n" +" -1.020000000000000E02\n" +" 3.400000000000000E00\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" 1.200000000000000E01\n" +" 2.400000000000000E01\n" +" \n" +" \n" +" 3.600000000000000E01\n" +" 4.800000000000000E01\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" 3.500000000000000E00\n" +" 5.300000000000000E00\n" +" \n" +" \n" +" 5.300000000000000E00\n" +" 3.500000000000000E00\n" +" \n" +" \n" +" \n" +" 1.000000000000000E-01\n" +" 3.000000000000000E-01\n" +" \n" +" \n" +" 4.000000000000000E-01\n" +" 2.000000000000000E-01\n" +" \n" +" \n" +" 5.000000000000000E-01\n" +" 9.000000000000000E-01\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" 1.000000000000000E01\n" +" 1.100000000000000E01\n" +" \n" +" \n" +" 2.000000000000000E01\n" +" 2.100000000000000E01\n" +" \n" +" \n" +" 3.000000000000000E01\n" +" 3.100000000000000E01\n" +" \n" +" \n" +" 4.000000000000000E01\n" +" 4.100000000000000E01\n" +" \n" +" \n" +" \n" +" Grid\n" +" \n" +" 1.230000000000000E00\n" +" 3.210000000000000E00\n" +" \n" +" \n" +" 3.140000000000000E00\n" +" 4\n" +" 50\n" +" \n" +" \n" +" 6.280000000000000E00\n" +" 8\n" +" 100\n" +" \n" +" \n" +" 2\n" +" \n" +" Segment1\n" +" 0\n" +" 1\n" +" 2\n" +" 3\n" +" \n" +" \n" +" 4.000000000000000E-01\n" +" 6.000000000000000E-01\n" +" \n" +" \n" +" 8.000000000000000E-01\n" +" 1.200000000000000E00\n" +" \n" +" \n" +" 1.200000000000000E00\n" +" 1.800000000000000E00\n" +" \n" +" \n" +" \n" +" \n" +" Segment2\n" +" 1\n" +" 2\n" +" 3\n" +" 4\n" +" \n" +" \n" +" 4.000000000000000E-01\n" +" 6.000000000000000E-01\n" +" \n" +" \n" +" 8.000000000000000E-01\n" +" 1.200000000000000E00\n" +" \n" +" \n" +" 1.200000000000000E00\n" +" 1.800000000000000E00\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" CI4\n" +" 24\n" +" 2\n" +" Compress\n" +" \n" +" Channel\n" +" 2\n" +" 3\n" +" 0\n" +" 1\n" +" 3\n" +" \n" +" \n" +" Channel\n" +" 2\n" +" 3\n" +" 0\n" +" 1\n" +" 3\n" +" \n" +" 3\n" +" \n" +" 1.0\n" +" 3\n" +" 4\n" +" 8\n" +" 0\n" +" \n" +" \n" +" 2.0\n" +" 3\n" +" 4\n" +" 4\n" +" 96\n" +" \n" +" \n" +" AddedSupportArray\n" +" 3\n" +" 4\n" +" 4\n" +" 144\n" +" \n" +" \n" +" \n" +" ChId\n" +" true\n" +" false\n" +" true\n" +" \n" +" CPI\n" +" 1\n" +" false\n" +" true\n" +" true\n" +" false\n" +" \n" +" X\n" +" RHC\n" +" \n" +" 1.300000000000000E00\n" +" 8.000000000000000E-01\n" +" 5.000000000000000E-01\n" +" 2.700000000000000E00\n" +" \n" +" 1.000000000000000E00\n" +" \n" +" 1.000000000000000E00\n" +" 2.000000000000000E00\n" +" 1.000000000000000E00\n" +" 2.000000000000000E00\n" +" \n" +" \n" +" \n" +" CODPolynomial\n" +" DwellPolynomial\n" +" \n" +" \n" +" \n" +" 3.500000000000000E00\n" +" 5.300000000000000E00\n" +" \n" +" \n" +" 5.300000000000000E00\n" +" 3.500000000000000E00\n" +" \n" +" \n" +" \n" +" 1.000000000000000E-01\n" +" 3.000000000000000E-01\n" +" \n" +" \n" +" 4.000000000000000E-01\n" +" 2.000000000000000E-01\n" +" \n" +" \n" +" 5.000000000000000E-01\n" +" 9.000000000000000E-01\n" +" \n" +" \n" +" \n" +" \n" +" TxAPCId\n" +" TxAPATId\n" +" RcvAPCId\n" +" RcvAPATId\n" +" \n" +" \n" +" TxWFId\n" +" RcvId\n" +" \n" +" \n" +" 1.200000000000000E01\n" +" \n" +" \n" +" 5.000000000000000E-01\n" +" 8.000000000000000E-01\n" +" \n" +" \n" +" 3.000000000000000E-01\n" +" 2.700000000000000E00\n" +" \n" +" \n" +" 5.000000000000000E-01\n" +" 2.700000000000000E00\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" Param\n" +" Param\n" +" \n" +" \n" +" \n" +" \n" +" 0\n" +" 1\n" +" F8\n" +" \n" +" \n" +" 1\n" +" 3\n" +" X=F8;Y=F8;Z=F8;\n" +" \n" +" \n" +" 4\n" +" 3\n" +" X=F8;Y=F8;Z=F8;\n" +" \n" +" \n" +" 7\n" +" 1\n" +" F8\n" +" \n" +" \n" +" 8\n" +" 3\n" +" X=F8;Y=F8;Z=F8;\n" +" \n" +" \n" +" 11\n" +" 3\n" +" X=F8;Y=F8;Z=F8;\n" +" \n" +" \n" +" 14\n" +" 3\n" +" X=F8;Y=F8;Z=F8;\n" +" \n" +" \n" +" 17\n" +" 1\n" +" F8\n" +" \n" +" \n" +" 18\n" +" 1\n" +" F8\n" +" \n" +" \n" +" 19\n" +" 1\n" +" F8\n" +" \n" +" \n" +" 20\n" +" 1\n" +" F8\n" +" \n" +" \n" +" 21\n" +" 1\n" +" F8\n" +" \n" +" \n" +" 22\n" +" 1\n" +" F8\n" +" \n" +" \n" +" 23\n" +" 1\n" +" F8\n" +" \n" +" \n" +" 24\n" +" 1\n" +" F8\n" +" \n" +" \n" +" 25\n" +" 1\n" +" F8\n" +" \n" +" \n" +" 26\n" +" 1\n" +" F8\n" +" \n" +" \n" +" newParam1\n" +" 27\n" +" 1\n" +" F8\n" +" \n" +" \n" +" newParam2\n" +" 28\n" +" 1\n" +" F8\n" +" \n" +" \n" +" \n" +" \n" +" 1\n" +" IAZ=F4;\n" +" 0.000000000000000E00\n" +" 0.000000000000000E00\n" +" 5.000000000000000E00\n" +" 5.000000000000000E00\n" +" \n" +" \n" +" 2\n" +" Gain=F4;Phase=F4;\n" +" 0.000000000000000E00\n" +" 0.000000000000000E00\n" +" 5.000000000000000E00\n" +" 5.000000000000000E00\n" +" \n" +" \n" +" AddedSupportArray\n" +" F4\n" +" 0.000000000000000E00\n" +" 0.000000000000000E00\n" +" 5.000000000000000E00\n" +" 5.000000000000000E00\n" +" XUnits\n" +" YUnits\n" +" ZUnits\n" +" Additional parameter\n" +" Additional parameter\n" +" \n" +" \n" +" \n" +" 1\n" +" \n" +" codPolynomial1\n" +" \n" +" 0.000000000000000E00\n" +" 5.000000000000000E00\n" +" 5.000000000000000E00\n" +" 0.000000000000000E00\n" +" \n" +" \n" +" 1\n" +" \n" +" dwellPolynomial1\n" +" \n" +" 0.000000000000000E00\n" +" 2.000000000000000E00\n" +" 3.000000000000000E00\n" +" 0.000000000000000E00\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" 1.000000000000000E00\n" +" 2.000000000000000E00\n" +" 3.500000000000000E00\n" +" \n" +" \n" +" 1.500000000000000E00\n" +" 2.500000000000000E00\n" +" 4.000000000000000E00\n" +" \n" +" \n" +" 0.000000000000000E00\n" +" 2.300000000000000E01\n" +" 2.500000000000000E01\n" +" \n" +" \n" +" 1.000000000000000E01\n" +" 1.000000000000000E01\n" +" 1.000000000000000E01\n" +" \n" +" \n" +" 1.000000000000000E01\n" +" 1.000000000000000E01\n" +" 1.000000000000000E01\n" +" \n" +" L\n" +" 2.000000000000000E01\n" +" 2.000000000000000E01\n" +" 3.000000000000000E01\n" +" 3.000000000000000E01\n" +" 3.000000000000000E01\n" +" 3.000000000000000E01\n" +" 3.000000000000000E01\n" +" 3.000000000000000E01\n" +" 3.000000000000000E01\n" +" \n" +" \n" +" \n" +" 2\n" +" 1\n" +" 1\n" +" \n" +" ACF1\n" +" \n" +" \n" +" 1.000000000000000E00\n" +" 2.000000000000000E00\n" +" 3.000000000000000E00\n" +" 4.000000000000000E00\n" +" \n" +" \n" +" 1.000000000000000E00\n" +" 2.000000000000000E00\n" +" 3.000000000000000E00\n" +" 4.000000000000000E00\n" +" \n" +" \n" +" 1.000000000000000E00\n" +" 0.000000000000000E00\n" +" 3.000000000000000E00\n" +" 0.000000000000000E00\n" +" \n" +" \n" +" \n" +" \n" +" 1.000000000000000E00\n" +" 2.000000000000000E00\n" +" \n" +" \n" +" 1.000000000000000E00\n" +" 2.000000000000000E00\n" +" \n" +" \n" +" 1.000000000000000E00\n" +" 2.000000000000000E00\n" +" \n" +" \n" +" \n" +" \n" +" ACF2\n" +" \n" +" \n" +" 1.000000000000000E00\n" +" 2.000000000000000E00\n" +" \n" +" \n" +" 1.000000000000000E00\n" +" 2.000000000000000E00\n" +" \n" +" \n" +" 1.000000000000000E00\n" +" 2.000000000000000E00\n" +" \n" +" \n" +" \n" +" \n" +" 1.000000000000000E00\n" +" 2.000000000000000E00\n" +" \n" +" \n" +" 1.000000000000000E00\n" +" 2.000000000000000E00\n" +" \n" +" \n" +" 1.000000000000000E00\n" +" 2.000000000000000E00\n" +" \n" +" \n" +" \n" +" \n" +" APC\n" +" ACF1\n" +" \n" +" 5.000000000000000E00\n" +" 5.000000000000000E00\n" +" 5.000000000000000E00\n" +" \n" +" \n" +" \n" +" APAT\n" +" 2.300000000000000E00\n" +" 2.300000000000000E00\n" +" 1\n" +" 0\n" +" \n" +" 1.000000000000000E00\n" +" 2.000000000000000E00\n" +" \n" +" \n" +" \n" +" 5.000000000000000E00\n" +" 0.000000000000000E00\n" +" \n" +" \n" +" 0.000000000000000E00\n" +" 5.000000000000000E00\n" +" \n" +" \n" +" \n" +" \n" +" 0.000000000000000E00\n" +" 1.000000000000000E00\n" +" 1.000000000000000E00\n" +" 5.000000000000000E00\n" +" \n" +" \n" +" 0.000000000000000E00\n" +" 1.000000000000000E00\n" +" 1.000000000000000E00\n" +" 5.000000000000000E00\n" +" \n" +" \n" +" \n" +" \n" +" 0.000000000000000E00\n" +" 1.000000000000000E00\n" +" 1.000000000000000E00\n" +" 5.000000000000000E00\n" +" \n" +" \n" +" 0.000000000000000E00\n" +" 1.000000000000000E00\n" +" 1.000000000000000E00\n" +" 5.000000000000000E00\n" +" \n" +" \n" +" \n" +" 2.300000000000000E00\n" +" Parameter1\n" +" Parameter2\n" +" \n" +" \n" +" 2.800000000000000E00\n" +" Parameter1\n" +" Parameter2\n" +" \n" +" \n" +" \n" +" \n" +" 1\n" +" \n" +" TxWFParam\n" +" 3.000000000000000E00\n" +" 2.300000000000000E00\n" +" 1.800000000000000E00\n" +" 1.000000000000000E00\n" +" LHC\n" +" 5.000000000000000E00\n" +" \n" +" 2\n" +" \n" +" RcvParam1\n" +" 3.000000000000000E00\n" +" 2.300000000000000E00\n" +" 2.300000000000000E00\n" +" 1.800000000000000E00\n" +" 1.000000000000000E00\n" +" LHC\n" +" 5.000000000000000E00\n" +" \n" +" \n" +" RcvParam2\n" +" 3.000000000000000E00\n" +" 2.300000000000000E00\n" +" 2.300000000000000E00\n" +" 1.800000000000000E00\n" +" 1.000000000000000E00\n" +" LHC\n" +" 5.000000000000000E00\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" ECF\n" +" 1.000000000000000E00\n" +" 1.000000000000000E00\n" +" 1.000000000000000E00\n" +" 1.000000000000000E00\n" +" 1.000000000000000E00\n" +" 1.000000000000000E00\n" +" \n" +" 8.000000000000000E-01\n" +" 8.000000000000000E-01\n" +" 8.000000000000000E-01\n" +" 8.000000000000000E-01\n" +" 8.000000000000000E-01\n" +" 8.000000000000000E-01\n" +" 8.000000000000000E-01\n" +" 8.000000000000000E-01\n" +" 8.000000000000000E-01\n" +" 8.000000000000000E-01\n" +" 8.000000000000000E-01\n" +" 8.000000000000000E-01\n" +" 8.000000000000000E-01\n" +" 8.000000000000000E-01\n" +" 8.000000000000000E-01\n" +" \n" +" \n" +" 5.000000000000000E-01\n" +" 1.000000000000000E00\n" +" \n" +" \n" +" \n" +" 5.000000000000000E-01\n" +" 1.000000000000000E00\n" +" 1.000000000000000E00\n" +" \n" +" 5.000000000000000E-01\n" +" 1.000000000000000E00\n" +" \n" +" \n" +" \n" +" 5.000000000000000E00\n" +" 5.000000000000000E00\n" +" \n" +" 5.000000000000000E-01\n" +" 1.000000000000000E00\n" +" \n" +" \n" +" \n" +" 5.000000000000000E00\n" +" 5.000000000000000E00\n" +" 5.000000000000000E-01\n" +" \n" +" 5.000000000000000E-01\n" +" 1.000000000000000E00\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" Profile\n" +" \n" +" Application\n" +" 2014-04-10T08:52:09.000000Z\n" +" Area51\n" +" Value1\n" +" Value2\n" +" \n" +" Value1\n" +" \n" +" \n" +" 51\n" +" \n" +" \n" +" \n" +" 0.000000000000000E00\n" +" 0.000000000000000E00\n" +" \n" +" \n" +" 1.000000000000000E-01\n" +" 0.000000000000000E00\n" +" \n" +" \n" +" 1.000000000000000E-01\n" +" 1.000000000000000E-01\n" +" \n" +" \n" +" 0.000000000000000E00\n" +" 0.000000000000000E00\n" +" \n" +" \n" +" \n" +" \n" +" 04/22\n" +" \n" +" \n" +" 2.000000000000000E-02\n" +" 3.000000000000000E-02\n" +" \n" +" \n" +" 8.000000000000000E-02\n" +" 8.000000000000000E-02\n" +" \n" +" \n" +" \n" +" \n" +" 09/27\n" +" \n" +" \n" +" 5.000000000000000E-02\n" +" 2.000000000000000E-02\n" +" \n" +" \n" +" 5.000000000000000E-02\n" +" 8.000000000000000E-02\n" +" \n" +" \n" +" \n" +" \n" +" Main\n" +" \n" +" 6.000000000000000E-01\n" +" 4.000000000000000E-01\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" 1.000000000000000E00\n" +" 1.000000000000000E00\n" +" \n" +" \n" +" 1.100000000000000E00\n" +" 1.000000000000000E00\n" +" \n" +" \n" +" 1.100000000000000E00\n" +" 1.100000000000000E00\n" +" \n" +" \n" +" 1.200000000000000E00\n" +" 1.200000000000000E00\n" +" \n" +" \n" +" 1.000000000000000E00\n" +" 1.000000000000000E00\n" +" \n" +" \n" +" \n" +" \n" +" 2\n" +" \n" +" STEREO\n" +" 1\n" +" 1\n" +" \n" +" CollectionName\n" +" 1\n" +" Match1\n" +" \n" +" \n" +" \n" +" COHERENT\n" +" 1\n" +" 1\n" +" \n" +" CollectionName\n" +" 1\n" +" Match1\n" +" \n" +" \n" +" \n" +"\n"; + +TEST_CASE(testOptional) +{ + io::StringStream cphdStream; + cphdStream.write(test_cphd_xml_optional_XML, strlen(test_cphd_xml_optional_XML)); + + xml::lite::MinidomParser xmlParser; + xmlParser.preserveCharacterData(true); + xmlParser.parse(cphdStream, cphdStream.available()); + const std::unique_ptr metadata = + cphd::CPHDXMLControl().fromXML(xmlParser.getDocument()); + + const cphd::SupportArray& supportArray = *(metadata->supportArray); + TEST_ASSERT_EQ(supportArray.iazArray.size(), static_cast(1)); + TEST_ASSERT_EQ(supportArray.iazArray[0].getIdentifier(), static_cast(1)); + TEST_ASSERT_EQ(supportArray.iazArray[0].elementFormat, "IAZ=F4;"); + TEST_ASSERT_EQ(supportArray.iazArray[0].x0, 0.0); + TEST_ASSERT_EQ(supportArray.iazArray[0].y0, 0.0); + TEST_ASSERT_EQ(supportArray.iazArray[0].xSS, 5.0); + TEST_ASSERT_EQ(supportArray.iazArray[0].ySS, 5.0); + + TEST_ASSERT_EQ(supportArray.antGainPhase.size(), static_cast(1)); + TEST_ASSERT_EQ(supportArray.antGainPhase[0].getIdentifier(), static_cast(2)); + TEST_ASSERT_EQ(supportArray.antGainPhase[0].elementFormat, "Gain=F4;Phase=F4;"); + TEST_ASSERT_EQ(supportArray.antGainPhase[0].x0, 0.0); + TEST_ASSERT_EQ(supportArray.antGainPhase[0].y0, 0.0); + TEST_ASSERT_EQ(supportArray.antGainPhase[0].xSS, 5.0); + TEST_ASSERT_EQ(supportArray.antGainPhase[0].ySS, 5.0); + + TEST_ASSERT_EQ(supportArray.addedSupportArray.size(), static_cast(1)); + TEST_ASSERT_EQ(supportArray.addedSupportArray.count("AddedSupportArray"), static_cast(1)); + TEST_ASSERT_EQ(supportArray.addedSupportArray.find("AddedSupportArray")->second.elementFormat, "F4"); + TEST_ASSERT_EQ(supportArray.addedSupportArray.find("AddedSupportArray")->second.x0, 0.0); + TEST_ASSERT_EQ(supportArray.addedSupportArray.find("AddedSupportArray")->second.y0, 0.0); + TEST_ASSERT_EQ(supportArray.addedSupportArray.find("AddedSupportArray")->second.xSS, 5.0); + TEST_ASSERT_EQ(supportArray.addedSupportArray.find("AddedSupportArray")->second.ySS, 5.0); + TEST_ASSERT_EQ(supportArray.addedSupportArray.find("AddedSupportArray")->second.xUnits, "XUnits"); + TEST_ASSERT_EQ(supportArray.addedSupportArray.find("AddedSupportArray")->second.yUnits, "YUnits"); + TEST_ASSERT_EQ(supportArray.addedSupportArray.find("AddedSupportArray")->second.zUnits, "ZUnits"); + TEST_ASSERT_EQ(supportArray.addedSupportArray.find("AddedSupportArray")->second.parameter.size(), static_cast(2)); + TEST_ASSERT_EQ(supportArray.addedSupportArray.find("AddedSupportArray")->second.parameter[0].getName(), "Parameter1"); + TEST_ASSERT_EQ(supportArray.addedSupportArray.find("AddedSupportArray")->second.parameter[1].getName(), "Parameter2"); + TEST_ASSERT_EQ(supportArray.addedSupportArray.find("AddedSupportArray")->second.parameter[0].str(), "Additional parameter"); + TEST_ASSERT_EQ(supportArray.addedSupportArray.find("AddedSupportArray")->second.parameter[1].str(), "Additional parameter"); + + const cphd::Antenna& antenna = *(metadata->antenna); + TEST_ASSERT_EQ(antenna.antCoordFrame.size(), static_cast(2)); + TEST_ASSERT_EQ(antenna.antCoordFrame[0].identifier, "ACF1"); + TEST_ASSERT_EQ(antenna.antCoordFrame[0].xAxisPoly.order(), static_cast(3)); + TEST_ASSERT_EQ(antenna.antCoordFrame[0].xAxisPoly.coeffs()[0][0], 1); + TEST_ASSERT_EQ(antenna.antCoordFrame[0].xAxisPoly.coeffs()[1][0], 2); + TEST_ASSERT_EQ(antenna.antCoordFrame[0].xAxisPoly.coeffs()[2][0], 3); + TEST_ASSERT_EQ(antenna.antCoordFrame[0].xAxisPoly.coeffs()[3][0], 4); + TEST_ASSERT_EQ(antenna.antCoordFrame[0].xAxisPoly.coeffs()[0][1], 1); + TEST_ASSERT_EQ(antenna.antCoordFrame[0].xAxisPoly.coeffs()[1][1], 2); + TEST_ASSERT_EQ(antenna.antCoordFrame[0].xAxisPoly.coeffs()[2][1], 3); + TEST_ASSERT_EQ(antenna.antCoordFrame[0].xAxisPoly.coeffs()[3][1], 4); + TEST_ASSERT_EQ(antenna.antCoordFrame[0].xAxisPoly.coeffs()[0][2], 1); + TEST_ASSERT_EQ(antenna.antCoordFrame[0].xAxisPoly.coeffs()[1][2], 0); + TEST_ASSERT_EQ(antenna.antCoordFrame[0].xAxisPoly.coeffs()[2][2], 3); + TEST_ASSERT_EQ(antenna.antCoordFrame[0].xAxisPoly.coeffs()[3][2], 0); + + TEST_ASSERT_EQ(antenna.antCoordFrame[0].yAxisPoly.order(), static_cast(1)); + TEST_ASSERT_EQ(antenna.antCoordFrame[0].yAxisPoly.coeffs()[0][0], 1); + TEST_ASSERT_EQ(antenna.antCoordFrame[0].yAxisPoly.coeffs()[1][0], 2); + TEST_ASSERT_EQ(antenna.antCoordFrame[0].yAxisPoly.coeffs()[0][1], 1); + TEST_ASSERT_EQ(antenna.antCoordFrame[0].yAxisPoly.coeffs()[1][1], 2); + + TEST_ASSERT_EQ(antenna.antCoordFrame[1].identifier, "ACF2"); + TEST_ASSERT_EQ(antenna.antCoordFrame[1].xAxisPoly.order(), static_cast(1)); + TEST_ASSERT_EQ(antenna.antCoordFrame[1].xAxisPoly.coeffs()[0][0], 1); + TEST_ASSERT_EQ(antenna.antCoordFrame[1].xAxisPoly.coeffs()[1][0], 2); + TEST_ASSERT_EQ(antenna.antCoordFrame[1].xAxisPoly.coeffs()[0][1], 1); + TEST_ASSERT_EQ(antenna.antCoordFrame[1].xAxisPoly.coeffs()[1][1], 2); + + TEST_ASSERT_EQ(antenna.antCoordFrame[1].yAxisPoly.order(), static_cast(1)); + TEST_ASSERT_EQ(antenna.antCoordFrame[1].yAxisPoly.coeffs()[0][0], 1); + TEST_ASSERT_EQ(antenna.antCoordFrame[1].yAxisPoly.coeffs()[1][0], 2); + TEST_ASSERT_EQ(antenna.antCoordFrame[1].yAxisPoly.coeffs()[0][1], 1); + TEST_ASSERT_EQ(antenna.antCoordFrame[1].yAxisPoly.coeffs()[1][1], 2); + + TEST_ASSERT_EQ(antenna.antPhaseCenter.size(), static_cast(1)); + TEST_ASSERT_EQ(antenna.antPhaseCenter[0].identifier, "APC"); + TEST_ASSERT_EQ(antenna.antPhaseCenter[0].acfId, "ACF1"); + TEST_ASSERT_EQ(antenna.antPhaseCenter[0].apcXYZ[0], 5.0); + TEST_ASSERT_EQ(antenna.antPhaseCenter[0].apcXYZ[1], 5.0); + TEST_ASSERT_EQ(antenna.antPhaseCenter[0].apcXYZ[2], 5.0); + + TEST_ASSERT_EQ(antenna.antPhaseCenter[0].identifier, "APC"); + TEST_ASSERT_EQ(antenna.antPhaseCenter[0].acfId, "ACF1"); + TEST_ASSERT_EQ(antenna.antPhaseCenter[0].apcXYZ[0], 5.0); + TEST_ASSERT_EQ(antenna.antPhaseCenter[0].apcXYZ[1], 5.0); + TEST_ASSERT_EQ(antenna.antPhaseCenter[0].apcXYZ[2], 5.0); + + TEST_ASSERT_EQ(antenna.antPattern.size(), static_cast(1)); + TEST_ASSERT_EQ(antenna.antPattern[0].identifier, "APAT"); + TEST_ASSERT_EQ(antenna.antPattern[0].freqZero, 2.3); + TEST_ASSERT_EQ(antenna.antPattern[0].gainZero, 2.3); + TEST_ASSERT_EQ(antenna.antPattern[0].ebFreqShift, 1); + TEST_ASSERT_EQ(antenna.antPattern[0].mlFreqDilation, 0); + TEST_ASSERT_EQ(antenna.antPattern[0].gainBSPoly.order(), static_cast(1)); + TEST_ASSERT_EQ(antenna.antPattern[0].gainBSPoly.coeffs()[0], 1.0); + TEST_ASSERT_EQ(antenna.antPattern[0].gainBSPoly.coeffs()[1], 2.0); + TEST_ASSERT_EQ(antenna.antPattern[0].eb.dcxPoly.order(), static_cast(1)); + TEST_ASSERT_EQ(antenna.antPattern[0].eb.dcxPoly.coeffs()[0], 5.0); + TEST_ASSERT_EQ(antenna.antPattern[0].eb.dcyPoly.order(), static_cast(1)); + TEST_ASSERT_EQ(antenna.antPattern[0].eb.dcyPoly.coeffs()[0], 0.0); + TEST_ASSERT_EQ(antenna.antPattern[0].eb.dcyPoly.coeffs()[1], 5.0); + TEST_ASSERT_EQ(antenna.antPattern[0].array.gainPoly.orderX(), static_cast(1)); + TEST_ASSERT_EQ(antenna.antPattern[0].array.gainPoly.orderY(), static_cast(1)); + TEST_ASSERT_EQ(antenna.antPattern[0].array.phasePoly.orderX(), static_cast(1)); + TEST_ASSERT_EQ(antenna.antPattern[0].array.phasePoly.orderY(), static_cast(1)); + TEST_ASSERT_EQ(antenna.antPattern[0].element.gainPoly.orderX(), static_cast(1)); + TEST_ASSERT_EQ(antenna.antPattern[0].element.gainPoly.orderY(), static_cast(1)); + TEST_ASSERT_EQ(antenna.antPattern[0].element.phasePoly.orderX(), static_cast(1)); + TEST_ASSERT_EQ(antenna.antPattern[0].element.phasePoly.orderY(), static_cast(1)); + TEST_ASSERT_EQ(antenna.antPattern[0].gainPhaseArray[0].freq, 2.3); + TEST_ASSERT_EQ(antenna.antPattern[0].gainPhaseArray[0].arrayId, "Parameter1"); + TEST_ASSERT_EQ(antenna.antPattern[0].gainPhaseArray[0].elementId, "Parameter2"); + TEST_ASSERT_EQ(antenna.antPattern[0].gainPhaseArray[1].freq, 2.8); + TEST_ASSERT_EQ(antenna.antPattern[0].gainPhaseArray[1].arrayId, "Parameter1"); + TEST_ASSERT_EQ(antenna.antPattern[0].gainPhaseArray[1].elementId, "Parameter2"); + + const cphd::TxRcv& txRcv = *(metadata->txRcv); + TEST_ASSERT_EQ(txRcv.txWFParameters.size(), static_cast(1)); + TEST_ASSERT_EQ(txRcv.txWFParameters[0].identifier, "TxWFParam"); + TEST_ASSERT_EQ(txRcv.txWFParameters[0].pulseLength, 3.0); + TEST_ASSERT_EQ(txRcv.txWFParameters[0].rfBandwidth, 2.3); + TEST_ASSERT_EQ(txRcv.txWFParameters[0].freqCenter, 1.8); + TEST_ASSERT_EQ(txRcv.txWFParameters[0].lfmRate, 1.0); + TEST_ASSERT(txRcv.txWFParameters[0].polarization.toString() == "LHC"); + TEST_ASSERT_EQ(txRcv.txWFParameters[0].polarization, cphd::PolarizationType::LHC); + TEST_ASSERT_EQ(txRcv.txWFParameters[0].power, 5.0); + + TEST_ASSERT_EQ(txRcv.rcvParameters.size(), static_cast(2)); + TEST_ASSERT_EQ(txRcv.rcvParameters[0].identifier, "RcvParam1"); + TEST_ASSERT_EQ(txRcv.rcvParameters[0].windowLength, 3.0); + TEST_ASSERT_EQ(txRcv.rcvParameters[0].sampleRate, 2.3); + TEST_ASSERT_EQ(txRcv.rcvParameters[0].ifFilterBW, 2.3); + TEST_ASSERT_EQ(txRcv.rcvParameters[0].freqCenter, 1.8); + TEST_ASSERT_EQ(txRcv.rcvParameters[0].lfmRate, 1.0); + TEST_ASSERT(txRcv.rcvParameters[0].polarization.toString() == "LHC"); + TEST_ASSERT_EQ(txRcv.rcvParameters[0].polarization, cphd::PolarizationType::LHC); + TEST_ASSERT_EQ(txRcv.rcvParameters[0].pathGain, 5.0); + + TEST_ASSERT_EQ(txRcv.rcvParameters[1].identifier, "RcvParam2"); + TEST_ASSERT_EQ(txRcv.rcvParameters[1].windowLength, 3.0); + TEST_ASSERT_EQ(txRcv.rcvParameters[1].sampleRate, 2.3); + TEST_ASSERT_EQ(txRcv.rcvParameters[1].ifFilterBW, 2.3); + TEST_ASSERT_EQ(txRcv.rcvParameters[1].freqCenter, 1.8); + TEST_ASSERT_EQ(txRcv.rcvParameters[1].lfmRate, 1.0); + TEST_ASSERT(txRcv.rcvParameters[1].polarization.toString() == "LHC"); + TEST_ASSERT_EQ(txRcv.rcvParameters[1].polarization, cphd::PolarizationType::LHC); + TEST_ASSERT_EQ(txRcv.rcvParameters[1].pathGain, 5.0); + + const cphd::ErrorParameters& errorParams = *(metadata->errorParameters); + TEST_ASSERT(errorParams.monostatic->posVelErr.frame == "ECF"); + TEST_ASSERT_EQ(errorParams.monostatic->posVelErr.frame, six::FrameType(six::FrameType::ECF)); + TEST_ASSERT_EQ(errorParams.monostatic->posVelErr.p1, 1.0); + TEST_ASSERT_EQ(errorParams.monostatic->posVelErr.p2, 1.0); + TEST_ASSERT_EQ(errorParams.monostatic->posVelErr.corrCoefs->p1p2, 0.8); + TEST_ASSERT_EQ(errorParams.monostatic->posVelErr.corrCoefs->v2v3, 0.8); + TEST_ASSERT_EQ(six::value(errorParams.monostatic->posVelErr.positionDecorr).corrCoefZero, 0.5); + TEST_ASSERT_EQ(six::value(errorParams.monostatic->posVelErr.positionDecorr).decorrRate, 1.0); + TEST_ASSERT_EQ(errorParams.monostatic->radarSensor.rangeBias, 0.5); + TEST_ASSERT_EQ(errorParams.monostatic->radarSensor.clockFreqSF, 1.0); + TEST_ASSERT_EQ(errorParams.monostatic->radarSensor.collectionStartTime, 1.0); + TEST_ASSERT_EQ(errorParams.monostatic->radarSensor.rangeBiasDecorr->corrCoefZero, 0.5); + TEST_ASSERT_EQ(errorParams.monostatic->radarSensor.rangeBiasDecorr->decorrRate, 1.0); + TEST_ASSERT_EQ(six::value(errorParams.monostatic->tropoError->tropoRangeVertical), 5.0); + TEST_ASSERT_EQ(six::value(errorParams.monostatic->tropoError->tropoRangeSlant), 5.0); + const auto& tropoRangeDecorr = value(errorParams.monostatic->tropoError->tropoRangeDecorr); + TEST_ASSERT_EQ(tropoRangeDecorr.corrCoefZero, 0.5); + TEST_ASSERT_EQ(tropoRangeDecorr.decorrRate, 1.0); + TEST_ASSERT_EQ(six::value(errorParams.monostatic->ionoError->ionoRangeVertical), 5.0); + TEST_ASSERT_EQ(six::value(errorParams.monostatic->ionoError->ionoRangeRateVertical), 5.0); + TEST_ASSERT_EQ(six::value(errorParams.monostatic->ionoError->ionoRgRgRateCC), 0.5); + const auto& ionoRangeVertDecorr = six::value(errorParams.monostatic->ionoError->ionoRangeVertDecorr); + TEST_ASSERT_EQ(ionoRangeVertDecorr.corrCoefZero, 0.5); + TEST_ASSERT_EQ(ionoRangeVertDecorr.decorrRate, 1.0); + + const cphd::ProductInfo& productInfo = *(metadata->productInfo); + TEST_ASSERT_EQ(productInfo.profile, "Profile"); + TEST_ASSERT_EQ(productInfo.creationInfo[0].application, "Application"); + TEST_ASSERT_EQ(productInfo.creationInfo[0].dateTime.getYear(), 2014); + TEST_ASSERT_EQ(productInfo.creationInfo[0].site, "Area51"); + TEST_ASSERT_EQ(productInfo.creationInfo[0].parameter[0].getName(), "Param1"); + TEST_ASSERT_EQ(productInfo.creationInfo[0].parameter[1].getName(), "Param2"); + TEST_ASSERT_EQ(productInfo.parameter[0].getName(), "Param1"); + + std::vector geoInfo = metadata->geoInfo; + TEST_ASSERT_EQ(geoInfo[0].name, "Airport"); + TEST_ASSERT_EQ(geoInfo[0].desc[0].getName(), "Airport ID"); + TEST_ASSERT_EQ(geoInfo[0].desc[0].str(), "51"); + TEST_ASSERT_EQ(geoInfo[0].geoInfos[0]->name, "Perimeter"); + TEST_ASSERT_EQ(geoInfo[0].geoInfos[0]->geometryLatLon.size(), static_cast(4)); + TEST_ASSERT_EQ(geoInfo[0].geoInfos[0]->geometryLatLon[0].getLat(), 0.0); + TEST_ASSERT_EQ(geoInfo[0].geoInfos[0]->geometryLatLon[0].getLon(), 0.0); + TEST_ASSERT_EQ(geoInfo[0].geoInfos[0]->geometryLatLon[1].getLat(), 0.1); + TEST_ASSERT_EQ(geoInfo[0].geoInfos[0]->geometryLatLon[1].getLon(), 0.0); + TEST_ASSERT_EQ(geoInfo[0].geoInfos[0]->geometryLatLon[2].getLat(), 0.1); + TEST_ASSERT_EQ(geoInfo[0].geoInfos[0]->geometryLatLon[2].getLon(), 0.1); + TEST_ASSERT_EQ(geoInfo[0].geoInfos[0]->geometryLatLon[3].getLat(), 0.0); + TEST_ASSERT_EQ(geoInfo[0].geoInfos[0]->geometryLatLon[3].getLon(), 0.0); + + TEST_ASSERT_EQ(geoInfo[0].geoInfos[1]->name, "Runway"); + TEST_ASSERT_EQ(geoInfo[0].geoInfos[1]->desc[0].getName(), "ID"); + TEST_ASSERT_EQ(geoInfo[0].geoInfos[1]->desc[0].str(), "04/22"); + TEST_ASSERT_EQ(geoInfo[0].geoInfos[1]->geometryLatLon.size(), static_cast(2)); + TEST_ASSERT_EQ(geoInfo[0].geoInfos[1]->geometryLatLon[0].getLat(), 0.02); + TEST_ASSERT_EQ(geoInfo[0].geoInfos[1]->geometryLatLon[0].getLon(), 0.03); + TEST_ASSERT_EQ(geoInfo[0].geoInfos[1]->geometryLatLon[1].getLat(), 0.08); + TEST_ASSERT_EQ(geoInfo[0].geoInfos[1]->geometryLatLon[1].getLon(), 0.08); + + TEST_ASSERT_EQ(geoInfo[0].geoInfos[3]->name, "Control Tower"); + TEST_ASSERT_EQ(geoInfo[0].geoInfos[3]->desc[0].getName(), "ID"); + TEST_ASSERT_EQ(geoInfo[0].geoInfos[3]->desc[0].str(), "Main"); + TEST_ASSERT_EQ(geoInfo[0].geoInfos[3]->geometryLatLon[0].getLat(), 0.6); + TEST_ASSERT_EQ(geoInfo[0].geoInfos[3]->geometryLatLon[0].getLon(), 0.4); + + TEST_ASSERT_EQ(geoInfo[1].name, "Farm"); + TEST_ASSERT_EQ(geoInfo[1].geometryLatLon.size(), static_cast(5)); + TEST_ASSERT_EQ(geoInfo[1].geometryLatLon[0].getLat(), 1.0); + TEST_ASSERT_EQ(geoInfo[1].geometryLatLon[0].getLon(), 1.0); + TEST_ASSERT_EQ(geoInfo[1].geometryLatLon[1].getLat(), 1.1); + TEST_ASSERT_EQ(geoInfo[1].geometryLatLon[1].getLon(), 1.0); + TEST_ASSERT_EQ(geoInfo[1].geometryLatLon[4].getLat(), 1.0); + TEST_ASSERT_EQ(geoInfo[1].geometryLatLon[4].getLon(), 1.0); + + const cphd::MatchInformation& matchInfo = *(metadata->matchInfo); + TEST_ASSERT_EQ(matchInfo.types.size(), static_cast(2)); + TEST_ASSERT_EQ(matchInfo.types[0].typeID, "STEREO"); + TEST_ASSERT_EQ(matchInfo.types[0].currentIndex, 1); + TEST_ASSERT_EQ(matchInfo.types[0].matchCollects.size(), static_cast(1)); + TEST_ASSERT_EQ(matchInfo.types[0].matchCollects[0].coreName, "CollectionName"); + TEST_ASSERT_EQ(matchInfo.types[0].matchCollects[0].matchIndex, 1); + TEST_ASSERT_EQ(matchInfo.types[0].matchCollects[0].parameters[0].getName(), "param1"); + TEST_ASSERT_EQ(matchInfo.types[1].typeID, "COHERENT"); + TEST_ASSERT_EQ(matchInfo.types[1].currentIndex, 1); + TEST_ASSERT_EQ(matchInfo.types[1].matchCollects.size(), static_cast(1)); + TEST_ASSERT_EQ(matchInfo.types[1].matchCollects[0].coreName, "CollectionName"); + TEST_ASSERT_EQ(matchInfo.types[1].matchCollects[0].matchIndex, 1); + TEST_ASSERT_EQ(matchInfo.types[1].matchCollects[0].parameters[0].getName(), "param1"); +} + +TEST_MAIN( + TEST_CHECK(testOptional); ) \ No newline at end of file diff --git a/six/modules/c++/cphd/unittests/test_dwell.cpp b/six/modules/c++/cphd/unittests/test_dwell.cpp index 7651f6b180..0f4dd45c6e 100644 --- a/six/modules/c++/cphd/unittests/test_dwell.cpp +++ b/six/modules/c++/cphd/unittests/test_dwell.cpp @@ -1,120 +1,120 @@ -/* ========================================================================= - * This file is part of cphd-c++ - * ========================================================================= - * - * (C) Copyright 2004 - 2019, MDA Information Systems LLC - * - * cphd-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ -#include -#include - -#include -#include -#include -#include -#include - -#include "TestCase.h" - -TEST_CASE(testDerivativeCODValid) -{ - cphd::Dwell dwell; - cphd::COD cod1; - size_t numCODTimes = 1; - dwell.cod.resize(numCODTimes); - dwell.cod[0] = cod1; - - cphd::Poly2D p2D(1, 1); - dwell.cod[0].codTimePoly = p2D; - dwell.cod[0].codTimePoly[0][0] = 1; - dwell.cod[0].codTimePoly[1][0] = 2; - dwell.cod[0].codTimePoly[0][1] = 3; - dwell.cod[0].codTimePoly[1][1] = 4; - - // Test Derivative in terms of x - cphd::Poly2D derivativeX2D(1,1); - derivativeX2D[0][0] = 2; - derivativeX2D[0][1] = 4; - TEST_ASSERT_EQ(dwell.cod[0].codTimePoly.derivativeX(),derivativeX2D); -} - -TEST_CASE(testDerivativeDwellValid) -{ - cphd::Dwell dwell; - cphd::DwellTime dtime1; - size_t numDwellTimes = 1; - dwell.dtime.resize(numDwellTimes); - dwell.dtime[0] = dtime1; - - cphd::Poly2D p2D(1, 1); - dwell.dtime[0].dwellTimePoly = p2D; - dwell.dtime[0].dwellTimePoly[0][0] = 1; - dwell.dtime[0].dwellTimePoly[1][0] = 2; - dwell.dtime[0].dwellTimePoly[0][1] = 3; - dwell.dtime[0].dwellTimePoly[1][1] = 4; - - // Test Derivative in terms of x - cphd::Poly2D derivativeY2D(1,1); - derivativeY2D[0][0] = 3; - derivativeY2D[1][0] = 4; - TEST_ASSERT_EQ(dwell.dtime[0].dwellTimePoly.derivativeY(),derivativeY2D); -} - - -TEST_CASE(testEquality) -{ - cphd::Dwell dwell; - cphd::DwellTime dtime1, dtime2; - - size_t numDwellTimes = 2; - dwell.dtime.resize(numDwellTimes); - dwell.dtime[0] = dtime1; - dwell.dtime[1] = dtime2; - - cphd:: Poly2D p2D_1(2,1), p2D_2(2,1); - - dwell.dtime[0].dwellTimePoly = p2D_1; - dwell.dtime[1].dwellTimePoly = p2D_2; - for (size_t i = 0; i < dwell.dtime.size(); ++i) { - dwell.dtime[i].dwellTimePoly[0][0] = 1; - dwell.dtime[i].dwellTimePoly[0][1] = 2; - dwell.dtime[i].dwellTimePoly[1][0] = 3; - dwell.dtime[i].dwellTimePoly[1][1] = 4; - dwell.dtime[i].dwellTimePoly[2][0] = 5; - } - - cphd:: Poly2D derivX(1,1); - derivX[0][0] = 3; - derivX[0][1] = 4; - derivX[1][0] = 10; - - // Test identical polynomial vectors - TEST_ASSERT_EQ(dwell.dtime[0].dwellTimePoly.derivativeX(), derivX); - TEST_ASSERT_TRUE((dwell.dtime[0] == dwell.dtime[1])); - - dwell.dtime[1].dwellTimePoly = dwell.dtime[1].dwellTimePoly.flipXY(); - - // Test different polynomial vectors - TEST_ASSERT_NOT_EQ(dwell.dtime[0].dwellTimePoly.derivativeX(), dwell.dtime[1].dwellTimePoly.derivativeX()); - TEST_ASSERT_TRUE((dwell.dtime[0] != dwell.dtime[1])); -} - -TEST_MAIN( - TEST_CHECK(testDerivativeCODValid); - TEST_CHECK(testDerivativeDwellValid); - TEST_CHECK(testEquality); - ) +/* ========================================================================= + * This file is part of cphd-c++ + * ========================================================================= + * + * (C) Copyright 2004 - 2019, MDA Information Systems LLC + * + * cphd-c++ is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; If not, + * see . + * + */ +#include +#include + +#include +#include +#include +#include +#include + +#include "TestCase.h" + +TEST_CASE(testDerivativeCODValid) +{ + cphd::Dwell dwell; + cphd::COD cod1; + size_t numCODTimes = 1; + dwell.cod.resize(numCODTimes); + dwell.cod[0] = cod1; + + cphd::Poly2D p2D(1, 1); + dwell.cod[0].codTimePoly = p2D; + dwell.cod[0].codTimePoly[0][0] = 1; + dwell.cod[0].codTimePoly[1][0] = 2; + dwell.cod[0].codTimePoly[0][1] = 3; + dwell.cod[0].codTimePoly[1][1] = 4; + + // Test Derivative in terms of x + cphd::Poly2D derivativeX2D(1,1); + derivativeX2D[0][0] = 2; + derivativeX2D[0][1] = 4; + TEST_ASSERT_EQ(dwell.cod[0].codTimePoly.derivativeX(),derivativeX2D); +} + +TEST_CASE(testDerivativeDwellValid) +{ + cphd::Dwell dwell; + cphd::DwellTime dtime1; + size_t numDwellTimes = 1; + dwell.dtime.resize(numDwellTimes); + dwell.dtime[0] = dtime1; + + cphd::Poly2D p2D(1, 1); + dwell.dtime[0].dwellTimePoly = p2D; + dwell.dtime[0].dwellTimePoly[0][0] = 1; + dwell.dtime[0].dwellTimePoly[1][0] = 2; + dwell.dtime[0].dwellTimePoly[0][1] = 3; + dwell.dtime[0].dwellTimePoly[1][1] = 4; + + // Test Derivative in terms of x + cphd::Poly2D derivativeY2D(1,1); + derivativeY2D[0][0] = 3; + derivativeY2D[1][0] = 4; + TEST_ASSERT_EQ(dwell.dtime[0].dwellTimePoly.derivativeY(),derivativeY2D); +} + + +TEST_CASE(testEquality) +{ + cphd::Dwell dwell; + cphd::DwellTime dtime1, dtime2; + + size_t numDwellTimes = 2; + dwell.dtime.resize(numDwellTimes); + dwell.dtime[0] = dtime1; + dwell.dtime[1] = dtime2; + + cphd:: Poly2D p2D_1(2,1), p2D_2(2,1); + + dwell.dtime[0].dwellTimePoly = p2D_1; + dwell.dtime[1].dwellTimePoly = p2D_2; + for (size_t i = 0; i < dwell.dtime.size(); ++i) { + dwell.dtime[i].dwellTimePoly[0][0] = 1; + dwell.dtime[i].dwellTimePoly[0][1] = 2; + dwell.dtime[i].dwellTimePoly[1][0] = 3; + dwell.dtime[i].dwellTimePoly[1][1] = 4; + dwell.dtime[i].dwellTimePoly[2][0] = 5; + } + + cphd:: Poly2D derivX(1,1); + derivX[0][0] = 3; + derivX[0][1] = 4; + derivX[1][0] = 10; + + // Test identical polynomial vectors + TEST_ASSERT_EQ(dwell.dtime[0].dwellTimePoly.derivativeX(), derivX); + TEST_ASSERT_TRUE((dwell.dtime[0] == dwell.dtime[1])); + + dwell.dtime[1].dwellTimePoly = dwell.dtime[1].dwellTimePoly.flipXY(); + + // Test different polynomial vectors + TEST_ASSERT_NOT_EQ(dwell.dtime[0].dwellTimePoly.derivativeX(), dwell.dtime[1].dwellTimePoly.derivativeX()); + TEST_ASSERT_TRUE((dwell.dtime[0] != dwell.dtime[1])); +} + +TEST_MAIN( + TEST_CHECK(testDerivativeCODValid); + TEST_CHECK(testDerivativeDwellValid); + TEST_CHECK(testEquality); + ) diff --git a/six/modules/c++/cphd/unittests/test_pvp.cpp b/six/modules/c++/cphd/unittests/test_pvp.cpp index fe498fb10f..79a4128b7f 100644 --- a/six/modules/c++/cphd/unittests/test_pvp.cpp +++ b/six/modules/c++/cphd/unittests/test_pvp.cpp @@ -1,110 +1,110 @@ -/* ========================================================================= - * This file is part of cphd-c++ - * ========================================================================= - * - * (C) Copyright 2004 - 2019, MDA Information Systems LLC - * - * cphd-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ -#include -#include - -#include -#include - -#include - -#include "TestCase.h" - - -TEST_CASE(testSimpleEqualityOperatorTrue) -{ - cphd::Pvp pvp1, pvp2; - - pvp1.txTime.setOffset(0); - pvp2.txTime.setOffset(0); - - TEST_ASSERT_TRUE((pvp1 == pvp2)); -} - -TEST_CASE(testAppend) -{ - cphd::Pvp pvp; - pvp.append(pvp.txTime); - pvp.append(pvp.txPos); - pvp.append(pvp.txVel); - pvp.append(pvp.ampSF); - pvp.appendCustomParameter(8, "S8", "AddedParam1"); - pvp.append(pvp.signal); - - TEST_ASSERT_TRUE(pvp.txTime.getOffset() == 0); - TEST_ASSERT_TRUE(pvp.txPos.getOffset() == 1); - TEST_ASSERT_TRUE(pvp.txVel.getOffset() == 4); - TEST_ASSERT_TRUE(pvp.ampSF.getOffset() == 7); - TEST_ASSERT_TRUE(pvp.addedPVP["AddedParam1"].getOffset() == 8); - TEST_ASSERT_TRUE(pvp.signal.getOffset() == 16); -} - -TEST_CASE(testAddedParamsEqualityOperatorTrue) -{ - cphd::Pvp pvp1; - pvp1.setCustomParameter(1, 0, "F8", "AddedParam1"); - pvp1.setCustomParameter(1, 1, "F8", "AddedParam2"); - - cphd::Pvp pvp2; - pvp2.setCustomParameter(1, 0, "F8", "AddedParam1"); - pvp2.setCustomParameter(1, 1, "F8", "AddedParam2"); - - TEST_ASSERT_TRUE((pvp1 == pvp2)); -} - - -TEST_CASE(testSimpleEqualityOperatorFalse) -{ - cphd::Pvp pvp1; - pvp1.fxN1.setOffset(0); - - cphd::Pvp pvp2; - pvp2.txTime.setOffset(1); - - TEST_ASSERT_TRUE((pvp1 != pvp2)); - -} - -TEST_CASE(testAddedParamsEqualityOperatorFalse) -{ - cphd::Pvp pvp1; - pvp1.setCustomParameter(1, 0, "F8", "AddedParam1"); - pvp1.setCustomParameter(1, 1, "F8", "AddedParam2"); - - cphd::Pvp pvp2; - pvp2.setCustomParameter(1, 0, "F8", "AddedParam1"); - - cphd::Pvp pvp3; - pvp3.setCustomParameter(1, 0, "F8", "AddedParam1"); - pvp3.setCustomParameter(1, 1, "F8", "AddedParam3"); - - TEST_ASSERT_TRUE((pvp1 != pvp2)); - TEST_ASSERT_TRUE((pvp1 != pvp3)); -} - -TEST_MAIN( - TEST_CHECK(testSimpleEqualityOperatorTrue); - TEST_CHECK(testAppend); - TEST_CHECK(testAddedParamsEqualityOperatorTrue); - TEST_CHECK(testSimpleEqualityOperatorFalse); - TEST_CHECK(testAddedParamsEqualityOperatorFalse); +/* ========================================================================= + * This file is part of cphd-c++ + * ========================================================================= + * + * (C) Copyright 2004 - 2019, MDA Information Systems LLC + * + * cphd-c++ is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; If not, + * see . + * + */ +#include +#include + +#include +#include + +#include + +#include "TestCase.h" + + +TEST_CASE(testSimpleEqualityOperatorTrue) +{ + cphd::Pvp pvp1, pvp2; + + pvp1.txTime.setOffset(0); + pvp2.txTime.setOffset(0); + + TEST_ASSERT_TRUE((pvp1 == pvp2)); +} + +TEST_CASE(testAppend) +{ + cphd::Pvp pvp; + pvp.append(pvp.txTime); + pvp.append(pvp.txPos); + pvp.append(pvp.txVel); + pvp.append(pvp.ampSF); + pvp.appendCustomParameter(8, "S8", "AddedParam1"); + pvp.append(pvp.signal); + + TEST_ASSERT_TRUE(pvp.txTime.getOffset() == 0); + TEST_ASSERT_TRUE(pvp.txPos.getOffset() == 1); + TEST_ASSERT_TRUE(pvp.txVel.getOffset() == 4); + TEST_ASSERT_TRUE(pvp.ampSF.getOffset() == 7); + TEST_ASSERT_TRUE(pvp.addedPVP["AddedParam1"].getOffset() == 8); + TEST_ASSERT_TRUE(pvp.signal.getOffset() == 16); +} + +TEST_CASE(testAddedParamsEqualityOperatorTrue) +{ + cphd::Pvp pvp1; + pvp1.setCustomParameter(1, 0, "F8", "AddedParam1"); + pvp1.setCustomParameter(1, 1, "F8", "AddedParam2"); + + cphd::Pvp pvp2; + pvp2.setCustomParameter(1, 0, "F8", "AddedParam1"); + pvp2.setCustomParameter(1, 1, "F8", "AddedParam2"); + + TEST_ASSERT_TRUE((pvp1 == pvp2)); +} + + +TEST_CASE(testSimpleEqualityOperatorFalse) +{ + cphd::Pvp pvp1; + pvp1.fxN1.setOffset(0); + + cphd::Pvp pvp2; + pvp2.txTime.setOffset(1); + + TEST_ASSERT_TRUE((pvp1 != pvp2)); + +} + +TEST_CASE(testAddedParamsEqualityOperatorFalse) +{ + cphd::Pvp pvp1; + pvp1.setCustomParameter(1, 0, "F8", "AddedParam1"); + pvp1.setCustomParameter(1, 1, "F8", "AddedParam2"); + + cphd::Pvp pvp2; + pvp2.setCustomParameter(1, 0, "F8", "AddedParam1"); + + cphd::Pvp pvp3; + pvp3.setCustomParameter(1, 0, "F8", "AddedParam1"); + pvp3.setCustomParameter(1, 1, "F8", "AddedParam3"); + + TEST_ASSERT_TRUE((pvp1 != pvp2)); + TEST_ASSERT_TRUE((pvp1 != pvp3)); +} + +TEST_MAIN( + TEST_CHECK(testSimpleEqualityOperatorTrue); + TEST_CHECK(testAppend); + TEST_CHECK(testAddedParamsEqualityOperatorTrue); + TEST_CHECK(testSimpleEqualityOperatorFalse); + TEST_CHECK(testAddedParamsEqualityOperatorFalse); ) \ No newline at end of file diff --git a/six/modules/c++/cphd/unittests/test_pvp_block_round.cpp b/six/modules/c++/cphd/unittests/test_pvp_block_round.cpp index 3bb70ad502..93ec99c9c6 100644 --- a/six/modules/c++/cphd/unittests/test_pvp_block_round.cpp +++ b/six/modules/c++/cphd/unittests/test_pvp_block_round.cpp @@ -1,253 +1,253 @@ -/* ========================================================================= - * This file is part of cphd-c++ - * ========================================================================= - * - * (C) Copyright 2004 - 2019, MDA Information Systems LLC - * - * cphd-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -template -auto generateComplexData(size_t length) -{ - using value_type = typename TComplex::value_type; - std::vector data(length); - srand(0); - for (size_t ii = 0; ii < data.size(); ++ii) - { - auto real = static_cast(rand() / 100); - auto imag = static_cast(rand() / 100); - data[ii] = TComplex(real, imag); - } - return data; -} - -void setPVPBlock(const types::RowCol dims, - cphd::PVPBlock& pvpBlock, - bool isAmpSF, - bool isFxN1, - bool isFxN2, - bool isTOAE1, - bool isTOAE2, - bool isSignal, - const std::vector& addedParams) -{ - const size_t numChannels = 1; - const std::vector numVectors(numChannels, dims.row); - - for (size_t ii = 0; ii < numChannels; ++ii) - { - for (size_t jj = 0; jj < numVectors[ii]; ++jj) - { - setVectorParameters(ii, jj, pvpBlock); - - if (isAmpSF) - { - const double ampSF = cphd::getRandom(); - pvpBlock.setAmpSF(ampSF, ii, jj); - } - if (isFxN1) - { - const double fxN1 = cphd::getRandom(); - pvpBlock.setFxN1(fxN1, ii, jj); - } - if (isFxN2) - { - const double fxN2 = cphd::getRandom(); - pvpBlock.setFxN2(fxN2, ii, jj); - } - if (isTOAE1) - { - const double toaE1 = cphd::getRandom(); - pvpBlock.setTOAE1(toaE1, ii, jj); - } - if (isTOAE2) - { - const double toaE2 = cphd::getRandom(); - pvpBlock.setTOAE2(toaE2, ii, jj); - } - if (isSignal) - { - const double signal = cphd::getRandom(); - pvpBlock.setTOAE2(signal, ii, jj); - } - - for (size_t idx = 0; idx < addedParams.size(); ++idx) - { - const double val = cphd::getRandom(); - pvpBlock.setAddedPVP(val, ii, jj, addedParams[idx]); - } - } - } -} - -template -void writeCPHD(const std::string& outPathname, - size_t numThreads, - const types::RowCol dims, - const TCxVector& writeData, - cphd::Metadata& metadata, - cphd::PVPBlock& pvpBlock) -{ - const size_t numChannels = 1; - - cphd::CPHDWriter writer(metadata, - outPathname, - std::vector(), - numThreads); - writer.writeMetadata(pvpBlock); - writer.writePVPData(pvpBlock); - for (size_t ii = 0; ii < numChannels; ++ii) - { - writer.writeCPHDData(writeData.data(), dims.area()); - } -} - -bool checkData(const std::string& pathname, - size_t numThreads, - cphd::Metadata& metadata, - cphd::PVPBlock& pvpBlock) -{ - cphd::CPHDReader reader(pathname, numThreads); - - if (metadata.pvp != reader.getMetadata().pvp) - { - return false; - } - if (pvpBlock != reader.getPVPBlock()) - { - return false; - } - return true; -} - -template -bool runTest(bool /*scale*/, - const TCxVector& writeData, - cphd::Metadata& meta, - cphd::PVPBlock& pvpBlock, - const types::RowCol dims) -{ - io::TempFile tempfile; - const size_t numThreads = std::thread::hardware_concurrency(); - writeCPHD(tempfile.pathname(), numThreads, dims, writeData, meta, pvpBlock); - return checkData(tempfile.pathname(), numThreads, meta, pvpBlock); -} - -TEST_CASE(testPVPBlockSimple) -{ - const types::RowCol dims(128, 256); - const auto writeData = generateComplexData(dims.area()); - const bool scale = false; - cphd::Metadata meta = cphd::Metadata(); - cphd::setUpData(meta, dims, writeData); - cphd::setPVPXML(meta.pvp); - cphd::PVPBlock pvpBlock(meta.pvp, meta.data); - std::vector addedParams; - setPVPBlock(dims, - pvpBlock, - false, - false, - false, - false, - false, - false, - addedParams); - - TEST_ASSERT_TRUE(runTest(scale, writeData, meta, pvpBlock, dims)); -} - -TEST_CASE(testPVPBlockOptional) -{ - const types::RowCol dims(128, 256); - const auto writeData = generateComplexData(dims.area()); - const bool scale = false; - cphd::Metadata meta = cphd::Metadata(); - cphd::setUpData(meta, dims, writeData); - cphd::setPVPXML(meta.pvp); - meta.pvp.setOffset(27, meta.pvp.fxN1); - meta.pvp.setOffset(28, meta.pvp.fxN2); - meta.data.numBytesPVP += 2 * 8; - cphd::PVPBlock pvpBlock(meta.pvp, meta.data); - std::vector addedParams; - setPVPBlock(dims, - pvpBlock, - false, - true, - true, - false, - false, - false, - addedParams); - - TEST_ASSERT_TRUE(runTest(scale, writeData, meta, pvpBlock, dims)); -} - -TEST_CASE(testPVPBlockAdditional) -{ - const types::RowCol dims(128, 256); - const auto writeData = generateComplexData(dims.area()); - const bool scale = false; - cphd::Metadata meta = cphd::Metadata(); - cphd::setUpData(meta, dims, writeData); - cphd::setPVPXML(meta.pvp); - meta.pvp.setCustomParameter(1, 27, "F8", "param1"); - meta.pvp.setCustomParameter(1, 28, "F8", "param2"); - meta.data.numBytesPVP += 2 * 8; - cphd::PVPBlock pvpBlock(meta.pvp, meta.data); - std::vector addedParams; - addedParams.push_back("param1"); - addedParams.push_back("param2"); - setPVPBlock(dims, - pvpBlock, - false, - false, - false, - false, - false, - false, - addedParams); - - TEST_ASSERT_TRUE(runTest(scale, writeData, meta, pvpBlock, dims)); -} - -TEST_MAIN( - TEST_CHECK(testPVPBlockSimple); - TEST_CHECK(testPVPBlockOptional); - TEST_CHECK(testPVPBlockAdditional); - ) +/* ========================================================================= + * This file is part of cphd-c++ + * ========================================================================= + * + * (C) Copyright 2004 - 2019, MDA Information Systems LLC + * + * cphd-c++ is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; If not, + * see . + * + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +template +auto generateComplexData(size_t length) +{ + using value_type = typename TComplex::value_type; + std::vector data(length); + srand(0); + for (size_t ii = 0; ii < data.size(); ++ii) + { + auto real = static_cast(rand() / 100); + auto imag = static_cast(rand() / 100); + data[ii] = TComplex(real, imag); + } + return data; +} + +void setPVPBlock(const types::RowCol dims, + cphd::PVPBlock& pvpBlock, + bool isAmpSF, + bool isFxN1, + bool isFxN2, + bool isTOAE1, + bool isTOAE2, + bool isSignal, + const std::vector& addedParams) +{ + const size_t numChannels = 1; + const std::vector numVectors(numChannels, dims.row); + + for (size_t ii = 0; ii < numChannels; ++ii) + { + for (size_t jj = 0; jj < numVectors[ii]; ++jj) + { + setVectorParameters(ii, jj, pvpBlock); + + if (isAmpSF) + { + const double ampSF = cphd::getRandom(); + pvpBlock.setAmpSF(ampSF, ii, jj); + } + if (isFxN1) + { + const double fxN1 = cphd::getRandom(); + pvpBlock.setFxN1(fxN1, ii, jj); + } + if (isFxN2) + { + const double fxN2 = cphd::getRandom(); + pvpBlock.setFxN2(fxN2, ii, jj); + } + if (isTOAE1) + { + const double toaE1 = cphd::getRandom(); + pvpBlock.setTOAE1(toaE1, ii, jj); + } + if (isTOAE2) + { + const double toaE2 = cphd::getRandom(); + pvpBlock.setTOAE2(toaE2, ii, jj); + } + if (isSignal) + { + const double signal = cphd::getRandom(); + pvpBlock.setTOAE2(signal, ii, jj); + } + + for (size_t idx = 0; idx < addedParams.size(); ++idx) + { + const double val = cphd::getRandom(); + pvpBlock.setAddedPVP(val, ii, jj, addedParams[idx]); + } + } + } +} + +template +void writeCPHD(const std::string& outPathname, + size_t numThreads, + const types::RowCol dims, + const TCxVector& writeData, + cphd::Metadata& metadata, + cphd::PVPBlock& pvpBlock) +{ + const size_t numChannels = 1; + + cphd::CPHDWriter writer(metadata, + outPathname, + std::vector(), + numThreads); + writer.writeMetadata(pvpBlock); + writer.writePVPData(pvpBlock); + for (size_t ii = 0; ii < numChannels; ++ii) + { + writer.writeCPHDData(writeData.data(), dims.area()); + } +} + +bool checkData(const std::string& pathname, + size_t numThreads, + cphd::Metadata& metadata, + cphd::PVPBlock& pvpBlock) +{ + cphd::CPHDReader reader(pathname, numThreads); + + if (metadata.pvp != reader.getMetadata().pvp) + { + return false; + } + if (pvpBlock != reader.getPVPBlock()) + { + return false; + } + return true; +} + +template +bool runTest(bool /*scale*/, + const TCxVector& writeData, + cphd::Metadata& meta, + cphd::PVPBlock& pvpBlock, + const types::RowCol dims) +{ + io::TempFile tempfile; + const size_t numThreads = std::thread::hardware_concurrency(); + writeCPHD(tempfile.pathname(), numThreads, dims, writeData, meta, pvpBlock); + return checkData(tempfile.pathname(), numThreads, meta, pvpBlock); +} + +TEST_CASE(testPVPBlockSimple) +{ + const types::RowCol dims(128, 256); + const auto writeData = generateComplexData(dims.area()); + const bool scale = false; + cphd::Metadata meta = cphd::Metadata(); + cphd::setUpData(meta, dims, writeData); + cphd::setPVPXML(meta.pvp); + cphd::PVPBlock pvpBlock(meta.pvp, meta.data); + std::vector addedParams; + setPVPBlock(dims, + pvpBlock, + false, + false, + false, + false, + false, + false, + addedParams); + + TEST_ASSERT_TRUE(runTest(scale, writeData, meta, pvpBlock, dims)); +} + +TEST_CASE(testPVPBlockOptional) +{ + const types::RowCol dims(128, 256); + const auto writeData = generateComplexData(dims.area()); + const bool scale = false; + cphd::Metadata meta = cphd::Metadata(); + cphd::setUpData(meta, dims, writeData); + cphd::setPVPXML(meta.pvp); + meta.pvp.setOffset(27, meta.pvp.fxN1); + meta.pvp.setOffset(28, meta.pvp.fxN2); + meta.data.numBytesPVP += 2 * 8; + cphd::PVPBlock pvpBlock(meta.pvp, meta.data); + std::vector addedParams; + setPVPBlock(dims, + pvpBlock, + false, + true, + true, + false, + false, + false, + addedParams); + + TEST_ASSERT_TRUE(runTest(scale, writeData, meta, pvpBlock, dims)); +} + +TEST_CASE(testPVPBlockAdditional) +{ + const types::RowCol dims(128, 256); + const auto writeData = generateComplexData(dims.area()); + const bool scale = false; + cphd::Metadata meta = cphd::Metadata(); + cphd::setUpData(meta, dims, writeData); + cphd::setPVPXML(meta.pvp); + meta.pvp.setCustomParameter(1, 27, "F8", "param1"); + meta.pvp.setCustomParameter(1, 28, "F8", "param2"); + meta.data.numBytesPVP += 2 * 8; + cphd::PVPBlock pvpBlock(meta.pvp, meta.data); + std::vector addedParams; + addedParams.push_back("param1"); + addedParams.push_back("param2"); + setPVPBlock(dims, + pvpBlock, + false, + false, + false, + false, + false, + false, + addedParams); + + TEST_ASSERT_TRUE(runTest(scale, writeData, meta, pvpBlock, dims)); +} + +TEST_MAIN( + TEST_CHECK(testPVPBlockSimple); + TEST_CHECK(testPVPBlockOptional); + TEST_CHECK(testPVPBlockAdditional); + ) diff --git a/six/modules/c++/cphd/unittests/test_reference_geometry.cpp b/six/modules/c++/cphd/unittests/test_reference_geometry.cpp index 28fa51ffe8..f8ad96b91c 100644 --- a/six/modules/c++/cphd/unittests/test_reference_geometry.cpp +++ b/six/modules/c++/cphd/unittests/test_reference_geometry.cpp @@ -1,63 +1,63 @@ -/* ========================================================================= - * This file is part of cphd-c++ - * ========================================================================= - * - * (C) Copyright 2004 - 2019, MDA Information Systems LLC - * - * cphd-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ -#include - -#include -#include - -#include -#include -#include -#include - -#include "TestCase.h" - -TEST_CASE(testEquality) -{ - cphd::ReferenceGeometry refGeo; - cphd::ReferenceGeometry refGeoOther; - refGeo.monostatic.reset(new cphd::Monostatic()); - refGeoOther.monostatic.reset(new cphd::Monostatic()); - - // Fill Values - refGeo.monostatic->azimuthAngle = 1.0; - refGeo.monostatic->grazeAngle = 1.0; - refGeo.monostatic->twistAngle = 1.0; - refGeo.monostatic->slopeAngle = 1.0; - refGeo.monostatic->layoverAngle = 1.0; - refGeo.monostatic->sideOfTrack = six::SideOfTrackType::LEFT; - refGeo.monostatic->slantRange = 20.0; - - refGeoOther.monostatic->azimuthAngle = 2.0; - refGeoOther.monostatic->grazeAngle = 2.0; - refGeoOther.monostatic->twistAngle = 2.0; - refGeoOther.monostatic->slopeAngle = 2.0; - refGeoOther.monostatic->layoverAngle = 2.0; - refGeoOther.monostatic->sideOfTrack = six::SideOfTrackType::LEFT; - refGeoOther.monostatic->slantRange = 20.0; - - TEST_ASSERT_NOT_EQ(refGeo, refGeoOther); -} - -TEST_MAIN( - TEST_CHECK(testEquality); -) +/* ========================================================================= + * This file is part of cphd-c++ + * ========================================================================= + * + * (C) Copyright 2004 - 2019, MDA Information Systems LLC + * + * cphd-c++ is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; If not, + * see . + * + */ +#include + +#include +#include + +#include +#include +#include +#include + +#include "TestCase.h" + +TEST_CASE(testEquality) +{ + cphd::ReferenceGeometry refGeo; + cphd::ReferenceGeometry refGeoOther; + refGeo.monostatic.reset(new cphd::Monostatic()); + refGeoOther.monostatic.reset(new cphd::Monostatic()); + + // Fill Values + refGeo.monostatic->azimuthAngle = 1.0; + refGeo.monostatic->grazeAngle = 1.0; + refGeo.monostatic->twistAngle = 1.0; + refGeo.monostatic->slopeAngle = 1.0; + refGeo.monostatic->layoverAngle = 1.0; + refGeo.monostatic->sideOfTrack = six::SideOfTrackType::LEFT; + refGeo.monostatic->slantRange = 20.0; + + refGeoOther.monostatic->azimuthAngle = 2.0; + refGeoOther.monostatic->grazeAngle = 2.0; + refGeoOther.monostatic->twistAngle = 2.0; + refGeoOther.monostatic->slopeAngle = 2.0; + refGeoOther.monostatic->layoverAngle = 2.0; + refGeoOther.monostatic->sideOfTrack = six::SideOfTrackType::LEFT; + refGeoOther.monostatic->slantRange = 20.0; + + TEST_ASSERT_NOT_EQ(refGeo, refGeoOther); +} + +TEST_MAIN( + TEST_CHECK(testEquality); +) diff --git a/six/modules/c++/cphd/unittests/test_signal_block_round.cpp b/six/modules/c++/cphd/unittests/test_signal_block_round.cpp index 197bc10698..3953c8bd63 100644 --- a/six/modules/c++/cphd/unittests/test_signal_block_round.cpp +++ b/six/modules/c++/cphd/unittests/test_signal_block_round.cpp @@ -1,224 +1,224 @@ -/* ========================================================================= - * This file is part of cphd-c++ - * ========================================================================= - * - * (C) Copyright 2004 - 2019, MDA Information Systems LLC - * - * cphd-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/*! - * Tests write and read of Signal Block - * Fails if values don't match - */ - -template -auto generateData(size_t length) -{ - using value_type = typename TComplex::value_type; - std::vector data(length); - srand(0); - for (size_t ii = 0; ii < data.size(); ++ii) - { - auto real = static_cast(rand() / 100); - auto imag = static_cast(rand() / 100); - data[ii] = TComplex(real, imag); - } - return data; -} - -inline std::vector generateScaleFactors(size_t length, bool scale) -{ - std::vector scaleFactors(length, 1); - if (scale) - { - for (size_t ii = 0; ii < scaleFactors.size(); ++ii) - { - scaleFactors[ii] *= 2; - } - } - return scaleFactors; -} - -template -void writeCPHD(const std::string& outPathname, size_t /*numThreads*/, - const types::RowCol dims, - const TCxVector& writeData, - cphd::Metadata& metadata, - cphd::PVPBlock& pvpBlock) -{ - const size_t numChannels = 1; - const std::vector numVectors(numChannels, dims.row); - - for (size_t ii = 0; ii < numChannels; ++ii) - { - for (size_t jj = 0; jj < numVectors[ii]; ++jj) - { - cphd::setVectorParameters(ii, jj, pvpBlock); - } - } - - cphd::CPHDWriter writer(metadata, outPathname); - writer.writeMetadata(pvpBlock); - writer.writePVPData(pvpBlock); - for (size_t ii = 0; ii < numChannels; ++ii) - { - writer.writeCPHDData(writeData.data(),dims.area()); - } -} - -std::vector checkData(const std::string& pathname, - size_t numThreads, - const std::vector& scaleFactors, - const types::RowCol dims) -{ - cphd::CPHDReader reader(pathname, numThreads); - const cphd::Wideband& wideband = reader.getWideband(); - std::vector readData(dims.area()); - - size_t sizeInBytes = readData.size() * sizeof(readData[0]); - std::vector scratchData(sizeInBytes); - std::span scratch(scratchData.data(), scratchData.size()); - std::span data(readData.data(), readData.size()); - - wideband.read(0, 0, cphd::Wideband::ALL, 0, cphd::Wideband::ALL, - scaleFactors, numThreads, scratch, data); - - return readData; -} - -template -bool compareVectors(const std::vector& readData, - const TCxVector& writeData, - const std::vector& scaleFactors, - bool scale) -{ - size_t pointsPerScale = readData.size() / scaleFactors.size(); - for (size_t ii = 0; ii < readData.size(); ++ii) - { - cphd::zfloat val(writeData[ii].real(), writeData[ii].imag()); - if (scale) - { - val *= scaleFactors[ii / pointsPerScale]; - } - - if (val != readData[ii]) - { - std::cerr << "Value mismatch at index " << ii << std::endl; - return false; - } - } - return true; -} - -template -bool runTest(bool scale, const TCxVector& writeData) -{ - io::TempFile tempfile; - const size_t numThreads = std::thread::hardware_concurrency(); - const types::RowCol dims(128, 128); - const std::vector scaleFactors = - generateScaleFactors(dims.row, scale); - cphd::Metadata meta = cphd::Metadata(); - setUpData(meta, dims, writeData); - cphd::setPVPXML(meta.pvp); - cphd::PVPBlock pvpBlock(meta.pvp, meta.data); - - writeCPHD(tempfile.pathname(), numThreads, dims, writeData, meta, pvpBlock); - const std::vector readData = - checkData(tempfile.pathname(), numThreads, - scaleFactors, dims); - return compareVectors(readData, writeData, scaleFactors, scale); - return true; -} - -TEST_CASE(testUnscaledInt8) -{ - const types::RowCol dims(128, 128); - const auto writeData = generateData(dims.area()); - const bool scale = false; - TEST_ASSERT_TRUE(runTest(scale, writeData)); -} - -TEST_CASE(testScaledInt8) -{ - const types::RowCol dims(128, 128); - const auto writeData = generateData(dims.area()); - const bool scale = true; - TEST_ASSERT_TRUE(runTest(scale, writeData)); -} - -TEST_CASE(testUnscaledInt16) -{ - const types::RowCol dims(128, 128); - const auto writeData = generateData(dims.area()); - const bool scale = false; - TEST_ASSERT_TRUE(runTest(scale, writeData)); -} - -TEST_CASE(testScaledInt16) -{ - const types::RowCol dims(128, 128); - const auto writeData = generateData(dims.area()); - const bool scale = true; - TEST_ASSERT_TRUE(runTest(scale, writeData)); -} - -TEST_CASE(testUnscaledFloat) -{ - const types::RowCol dims(128, 128); - const auto writeData = generateData(dims.area()); - const bool scale = false; - TEST_ASSERT_TRUE(runTest(scale, writeData)); -} - -TEST_CASE(testScaledFloat) -{ - const types::RowCol dims(128, 128); - const auto writeData = generateData(dims.area()); - const bool scale = true; - TEST_ASSERT_TRUE(runTest(scale, writeData)); -} - -TEST_MAIN( - TEST_CHECK(testUnscaledInt8); - TEST_CHECK(testScaledInt8); - TEST_CHECK(testUnscaledInt16); - TEST_CHECK(testScaledInt16); - TEST_CHECK(testUnscaledFloat); - TEST_CHECK(testScaledFloat); - ) +/* ========================================================================= + * This file is part of cphd-c++ + * ========================================================================= + * + * (C) Copyright 2004 - 2019, MDA Information Systems LLC + * + * cphd-c++ is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; If not, + * see . + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*! + * Tests write and read of Signal Block + * Fails if values don't match + */ + +template +auto generateData(size_t length) +{ + using value_type = typename TComplex::value_type; + std::vector data(length); + srand(0); + for (size_t ii = 0; ii < data.size(); ++ii) + { + auto real = static_cast(rand() / 100); + auto imag = static_cast(rand() / 100); + data[ii] = TComplex(real, imag); + } + return data; +} + +inline std::vector generateScaleFactors(size_t length, bool scale) +{ + std::vector scaleFactors(length, 1); + if (scale) + { + for (size_t ii = 0; ii < scaleFactors.size(); ++ii) + { + scaleFactors[ii] *= 2; + } + } + return scaleFactors; +} + +template +void writeCPHD(const std::string& outPathname, size_t /*numThreads*/, + const types::RowCol dims, + const TCxVector& writeData, + cphd::Metadata& metadata, + cphd::PVPBlock& pvpBlock) +{ + const size_t numChannels = 1; + const std::vector numVectors(numChannels, dims.row); + + for (size_t ii = 0; ii < numChannels; ++ii) + { + for (size_t jj = 0; jj < numVectors[ii]; ++jj) + { + cphd::setVectorParameters(ii, jj, pvpBlock); + } + } + + cphd::CPHDWriter writer(metadata, outPathname); + writer.writeMetadata(pvpBlock); + writer.writePVPData(pvpBlock); + for (size_t ii = 0; ii < numChannels; ++ii) + { + writer.writeCPHDData(writeData.data(),dims.area()); + } +} + +std::vector checkData(const std::string& pathname, + size_t numThreads, + const std::vector& scaleFactors, + const types::RowCol dims) +{ + cphd::CPHDReader reader(pathname, numThreads); + const cphd::Wideband& wideband = reader.getWideband(); + std::vector readData(dims.area()); + + size_t sizeInBytes = readData.size() * sizeof(readData[0]); + std::vector scratchData(sizeInBytes); + std::span scratch(scratchData.data(), scratchData.size()); + std::span data(readData.data(), readData.size()); + + wideband.read(0, 0, cphd::Wideband::ALL, 0, cphd::Wideband::ALL, + scaleFactors, numThreads, scratch, data); + + return readData; +} + +template +bool compareVectors(const std::vector& readData, + const TCxVector& writeData, + const std::vector& scaleFactors, + bool scale) +{ + size_t pointsPerScale = readData.size() / scaleFactors.size(); + for (size_t ii = 0; ii < readData.size(); ++ii) + { + cphd::zfloat val(writeData[ii].real(), writeData[ii].imag()); + if (scale) + { + val *= scaleFactors[ii / pointsPerScale]; + } + + if (val != readData[ii]) + { + std::cerr << "Value mismatch at index " << ii << std::endl; + return false; + } + } + return true; +} + +template +bool runTest(bool scale, const TCxVector& writeData) +{ + io::TempFile tempfile; + const size_t numThreads = std::thread::hardware_concurrency(); + const types::RowCol dims(128, 128); + const std::vector scaleFactors = + generateScaleFactors(dims.row, scale); + cphd::Metadata meta = cphd::Metadata(); + setUpData(meta, dims, writeData); + cphd::setPVPXML(meta.pvp); + cphd::PVPBlock pvpBlock(meta.pvp, meta.data); + + writeCPHD(tempfile.pathname(), numThreads, dims, writeData, meta, pvpBlock); + const std::vector readData = + checkData(tempfile.pathname(), numThreads, + scaleFactors, dims); + return compareVectors(readData, writeData, scaleFactors, scale); + return true; +} + +TEST_CASE(testUnscaledInt8) +{ + const types::RowCol dims(128, 128); + const auto writeData = generateData(dims.area()); + const bool scale = false; + TEST_ASSERT_TRUE(runTest(scale, writeData)); +} + +TEST_CASE(testScaledInt8) +{ + const types::RowCol dims(128, 128); + const auto writeData = generateData(dims.area()); + const bool scale = true; + TEST_ASSERT_TRUE(runTest(scale, writeData)); +} + +TEST_CASE(testUnscaledInt16) +{ + const types::RowCol dims(128, 128); + const auto writeData = generateData(dims.area()); + const bool scale = false; + TEST_ASSERT_TRUE(runTest(scale, writeData)); +} + +TEST_CASE(testScaledInt16) +{ + const types::RowCol dims(128, 128); + const auto writeData = generateData(dims.area()); + const bool scale = true; + TEST_ASSERT_TRUE(runTest(scale, writeData)); +} + +TEST_CASE(testUnscaledFloat) +{ + const types::RowCol dims(128, 128); + const auto writeData = generateData(dims.area()); + const bool scale = false; + TEST_ASSERT_TRUE(runTest(scale, writeData)); +} + +TEST_CASE(testScaledFloat) +{ + const types::RowCol dims(128, 128); + const auto writeData = generateData(dims.area()); + const bool scale = true; + TEST_ASSERT_TRUE(runTest(scale, writeData)); +} + +TEST_MAIN( + TEST_CHECK(testUnscaledInt8); + TEST_CHECK(testScaledInt8); + TEST_CHECK(testUnscaledInt16); + TEST_CHECK(testScaledInt16); + TEST_CHECK(testUnscaledFloat); + TEST_CHECK(testScaledFloat); + ) diff --git a/six/modules/c++/cphd/unittests/test_support_block_round.cpp b/six/modules/c++/cphd/unittests/test_support_block_round.cpp index 8dd52bbd82..0e075b58b3 100644 --- a/six/modules/c++/cphd/unittests/test_support_block_round.cpp +++ b/six/modules/c++/cphd/unittests/test_support_block_round.cpp @@ -1,168 +1,168 @@ -/* ========================================================================= - * This file is part of cphd-c++ - * ========================================================================= - * - * (C) Copyright 2004 - 2019, MDA Information Systems LLC - * - * cphd-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static constexpr size_t NUM_SUPPORT = 3; -static constexpr size_t NUM_ROWS = 3; -static constexpr size_t NUM_COLS = 4; - -template -std::vector generateSupportData(size_t length) -{ - std::vector data(length); - srand(0); - for (size_t ii = 0; ii < data.size(); ++ii) - { - data[ii] = rand() % 16; - } - return data; -} - -template -void setSupport(cphd::Data& d) -{ - d.setSupportArray("1.0", NUM_ROWS, NUM_COLS, sizeof(T), 0); - d.setSupportArray("2.0", NUM_ROWS, NUM_COLS, sizeof(T), NUM_ROWS*NUM_COLS*sizeof(T)); - d.setSupportArray("AddedSupport", NUM_ROWS, NUM_COLS, sizeof(T), 2*NUM_ROWS*NUM_COLS*sizeof(T)); -} - -template -void writeSupportData(const std::string& outPathname, size_t numThreads, - const std::vector& writeData, - cphd::Metadata& metadata, - cphd::PVPBlock& pvpBlock) -{ - const size_t numChannels = 1; - // Required but doesn't matter - const std::vector numVectors(numChannels, 128); - - for (size_t ii = 0; ii < numChannels; ++ii) - { - for (size_t jj = 0; jj < numVectors[ii]; ++jj) - { - cphd::setVectorParameters(ii, jj, pvpBlock); - } - } - cphd::CPHDWriter writer(metadata, outPathname, std::vector(), numThreads); - writer.writeMetadata(pvpBlock); - writer.writeSupportData(writeData.data()); - writer.writePVPData(pvpBlock); -} - -std::vector checkSupportData( - const std::string& pathname, - size_t /*size*/, - size_t numThreads) -{ - cphd::CPHDReader reader(pathname, numThreads); - const cphd::SupportBlock& supportBlock = reader.getSupportBlock(); - - std::unique_ptr readPtr; - supportBlock.readAll(numThreads, readPtr); - - std::vector readData(readPtr.get(), readPtr.get() + reader.getMetadata().data.getAllSupportSize()); - return readData; -} - -template -bool compareVectors(const std::vector& readData, - const T* writeData, - size_t writeDataSize) -{ - if (writeDataSize * sizeof(T) != readData.size()) - { - std::cerr << "Size mismatch. Writedata size: "<< writeDataSize * sizeof(T) - << "ReadData size: " << readData.size() << "\n"; - return false; - } - const std::byte* ptr = reinterpret_cast(writeData); - for (size_t ii = 0; ii < readData.size(); ++ii, ++ptr) - { - if (*ptr != readData[ii]) - { - std::cerr << "Value mismatch at index " << ii << std::endl; - std::cerr << "readData: " << static_cast(readData[ii]) << " " << "writeData: " << static_cast(*ptr) << "\n"; - return false; - } - } - return true; -} - -template -bool runTest(const std::vector& writeData) -{ - io::TempFile tempfile; - const size_t numThreads = 1; - cphd::Metadata meta = cphd::Metadata(); - cphd::setUpData(meta, types::RowCol(128,256), std::vector()); - setSupport(meta.data); - cphd::setPVPXML(meta.pvp); - cphd::PVPBlock pvpBlock(meta.pvp, meta.data); - writeSupportData(tempfile.pathname(), numThreads, writeData, meta, pvpBlock); - const std::vector readData = - checkSupportData(tempfile.pathname(), NUM_SUPPORT*NUM_ROWS*NUM_COLS*sizeof(T), numThreads); - - return compareVectors(readData, writeData.data(), writeData.size()); -} - -TEST_CASE(testSupportsInt) -{ - const types::RowCol dims(NUM_ROWS, NUM_COLS); - const std::vector writeData = - generateSupportData(NUM_SUPPORT*dims.area()); - TEST_ASSERT_TRUE(runTest(writeData)); -} - -TEST_CASE(testSupportsDouble) -{ - const types::RowCol dims(NUM_ROWS, NUM_COLS); - const std::vector writeData = - generateSupportData(NUM_SUPPORT*dims.area()); - TEST_ASSERT_TRUE(runTest(writeData)); -} - -TEST_MAIN( - TEST_CHECK(testSupportsInt); - TEST_CHECK(testSupportsDouble); - ) +/* ========================================================================= + * This file is part of cphd-c++ + * ========================================================================= + * + * (C) Copyright 2004 - 2019, MDA Information Systems LLC + * + * cphd-c++ is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; If not, + * see . + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static constexpr size_t NUM_SUPPORT = 3; +static constexpr size_t NUM_ROWS = 3; +static constexpr size_t NUM_COLS = 4; + +template +std::vector generateSupportData(size_t length) +{ + std::vector data(length); + srand(0); + for (size_t ii = 0; ii < data.size(); ++ii) + { + data[ii] = rand() % 16; + } + return data; +} + +template +void setSupport(cphd::Data& d) +{ + d.setSupportArray("1.0", NUM_ROWS, NUM_COLS, sizeof(T), 0); + d.setSupportArray("2.0", NUM_ROWS, NUM_COLS, sizeof(T), NUM_ROWS*NUM_COLS*sizeof(T)); + d.setSupportArray("AddedSupport", NUM_ROWS, NUM_COLS, sizeof(T), 2*NUM_ROWS*NUM_COLS*sizeof(T)); +} + +template +void writeSupportData(const std::string& outPathname, size_t numThreads, + const std::vector& writeData, + cphd::Metadata& metadata, + cphd::PVPBlock& pvpBlock) +{ + const size_t numChannels = 1; + // Required but doesn't matter + const std::vector numVectors(numChannels, 128); + + for (size_t ii = 0; ii < numChannels; ++ii) + { + for (size_t jj = 0; jj < numVectors[ii]; ++jj) + { + cphd::setVectorParameters(ii, jj, pvpBlock); + } + } + cphd::CPHDWriter writer(metadata, outPathname, std::vector(), numThreads); + writer.writeMetadata(pvpBlock); + writer.writeSupportData(writeData.data()); + writer.writePVPData(pvpBlock); +} + +std::vector checkSupportData( + const std::string& pathname, + size_t /*size*/, + size_t numThreads) +{ + cphd::CPHDReader reader(pathname, numThreads); + const cphd::SupportBlock& supportBlock = reader.getSupportBlock(); + + std::unique_ptr readPtr; + supportBlock.readAll(numThreads, readPtr); + + std::vector readData(readPtr.get(), readPtr.get() + reader.getMetadata().data.getAllSupportSize()); + return readData; +} + +template +bool compareVectors(const std::vector& readData, + const T* writeData, + size_t writeDataSize) +{ + if (writeDataSize * sizeof(T) != readData.size()) + { + std::cerr << "Size mismatch. Writedata size: "<< writeDataSize * sizeof(T) + << "ReadData size: " << readData.size() << "\n"; + return false; + } + const std::byte* ptr = reinterpret_cast(writeData); + for (size_t ii = 0; ii < readData.size(); ++ii, ++ptr) + { + if (*ptr != readData[ii]) + { + std::cerr << "Value mismatch at index " << ii << std::endl; + std::cerr << "readData: " << static_cast(readData[ii]) << " " << "writeData: " << static_cast(*ptr) << "\n"; + return false; + } + } + return true; +} + +template +bool runTest(const std::vector& writeData) +{ + io::TempFile tempfile; + const size_t numThreads = 1; + cphd::Metadata meta = cphd::Metadata(); + cphd::setUpData(meta, types::RowCol(128,256), std::vector()); + setSupport(meta.data); + cphd::setPVPXML(meta.pvp); + cphd::PVPBlock pvpBlock(meta.pvp, meta.data); + writeSupportData(tempfile.pathname(), numThreads, writeData, meta, pvpBlock); + const std::vector readData = + checkSupportData(tempfile.pathname(), NUM_SUPPORT*NUM_ROWS*NUM_COLS*sizeof(T), numThreads); + + return compareVectors(readData, writeData.data(), writeData.size()); +} + +TEST_CASE(testSupportsInt) +{ + const types::RowCol dims(NUM_ROWS, NUM_COLS); + const std::vector writeData = + generateSupportData(NUM_SUPPORT*dims.area()); + TEST_ASSERT_TRUE(runTest(writeData)); +} + +TEST_CASE(testSupportsDouble) +{ + const types::RowCol dims(NUM_ROWS, NUM_COLS); + const std::vector writeData = + generateSupportData(NUM_SUPPORT*dims.area()); + TEST_ASSERT_TRUE(runTest(writeData)); +} + +TEST_MAIN( + TEST_CHECK(testSupportsInt); + TEST_CHECK(testSupportsDouble); + ) diff --git a/six/modules/c++/samples/check_valid_six.cpp b/six/modules/c++/samples/check_valid_six.cpp index f6d6efecc9..0a9c287528 100644 --- a/six/modules/c++/samples/check_valid_six.cpp +++ b/six/modules/c++/samples/check_valid_six.cpp @@ -1,279 +1,279 @@ -/* ========================================================================= - * This file is part of six-c++ - * ========================================================================= - * - * (C) Copyright 2004 - 2014, MDA Information Systems LLC - * - * six-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ - -#include - -#include - -#include -#include -#include -#include -#include -#include "utils.h" - -namespace fs = std::filesystem; - -namespace -{ -// TODO: Does this belong in sys? -class ExtensionsPredicate : public sys::FileOnlyPredicate -{ -public: - ExtensionsPredicate(const std::vector& extensions, - bool ignoreCase = true) : - mExtensions(extensions), - mIgnoreCase(ignoreCase) - { - if (mIgnoreCase) - { - for (size_t ii = 0; ii < mExtensions.size(); ++ii) - { - str::lower(mExtensions[ii]); - } - } - } - - virtual bool operator()(const std::string& pathname) const - { - if (!sys::FileOnlyPredicate::operator()(pathname)) - { - return false; - } - - std::string ext = fs::path(pathname).extension().string(); - if (mIgnoreCase) - { - str::lower(ext); - } - - for (size_t ii = 0; ii < mExtensions.size(); ++ii) - { - if (ext == mExtensions[ii]) - { - return true; - } - } - - return false; - } - -private: - std::vector mExtensions; - const bool mIgnoreCase; -}; - -std::vector getPathnames(const std::string& dirname) -{ - std::vector extensions; - extensions.push_back(".nitf"); - extensions.push_back(".ntf"); - extensions.push_back(".xml"); - - return sys::FileFinder::search(ExtensionsPredicate(extensions), - std::vector(1, dirname), - false); -} - -bool runValidation(const std::unique_ptr& data, - std::unique_ptr& log) -{ - if (data->getDataType() == six::DataType::COMPLEX) - { - six::sicd::ComplexData* complexData = - static_cast( - data.get()); - - if (complexData->validate(*log)) - { - log->info(Ctxt("Successful: No Errors Found!")); - return true; - } - return false; - } - else - { - // Nothing to validate - log->info(Ctxt("Nothing done: not a SICD.")); - return true; - } -} -} - -// make it a little easier to use from MSVC -#if defined(_DEBUG) && defined(_MSC_VER) -static fs::path getNitfPath() -{ - const auto cwd = fs::current_path(); - const auto root_dir = cwd.parent_path().parent_path(); - return root_dir / "six" / "tests" / "nitf" / "sicd_1.1.0.nitf"; -} - -static void setNitfPluginPath() -{ - const auto cwd = fs::current_path(); - const auto root_dir = cwd.parent_path().parent_path().parent_path().parent_path().parent_path(); - - const std::string configuration = -#if defined(NDEBUG) // i.e., release - "Release"; -#else - "Debug"; -#endif - const std::string platform = "x64"; - - const auto path = root_dir / "externals" / "nitro" / platform / configuration / "share" / "nitf" / "plugins"; - sys::OS().setEnv("NITF_PLUGIN_PATH", path.string(), true /*overwrite*/); -} -#endif - -static int main_(int argc, char** argv) -{ - // make it a little easier to use from MSVC - #if defined(_DEBUG) && defined(_MSC_VER) - if (argc == 1) - { - setNitfPluginPath(); - - // ./six/modules/c++/six/tests/nitf/sidd_1.0.0.nitf - static const std::string nitf_path = getNitfPath().string(); - argc = 2; - auto argv_ = static_cast(malloc(argc * sizeof(char*))); - argv_[0] = argv[0]; - argv_[1] = const_cast(nitf_path.c_str()); - //argv[1] - argv = argv_; - } - #endif - - - // create a parser and add our options to it - cli::ArgumentParser parser; - parser.setDescription("This program reads a SIDD/SICD along with a "\ - "directory of schemas, and returns any error messages "\ - "that may be contained in the DES XML"); - parser.addArgument("-f --log", "Specify a log file", cli::STORE, "log", - "FILE")->setDefault("console"); - parser.addArgument("-l --level", "Specify log level", cli::STORE, - "level", "LEVEL")->setChoices( - str::split("debug info warn error"))->setDefault( - "info"); - parser.addArgument("-s --schema", - "Specify a schema or directory of schemas", - cli::STORE, "schema", "FILE"); - parser.addArgument("input", "Input SICD/SIDD file or directory of files", cli::STORE, "input", - "INPUT", 1, 1); - - const std::unique_ptr - options(parser.parse(argc, (const char**) argv)); - - const std::string inputPath(options->get("input")); - std::vector inputPathnames = getPathnames(inputPath); - const std::string logFile(options->get("log")); - std::string level(options->get("level")); - std::vector schemaPaths; - getSchemaPaths(*options, "--schema", "schema", schemaPaths); - - // create an XML registry - // The reason to do this is to avoid adding XMLControlCreators to the - // XMLControlFactory singleton - this way has more fine-grained control - six::XMLControlRegistry xmlRegistry; - xmlRegistry.addCreator(); - xmlRegistry.addCreator(); - - str::upper(level); - str::trim(level); - std::unique_ptr log = - logging::setupLogger(fs::path(argv[0]).filename().string(), level, logFile); - - // this validates the DES of the input against the - // best available schema - six::NITFReadControl reader; - reader.setLogger(*log); - reader.setXMLControlRegistry(&xmlRegistry); - bool allValid = true; - for (size_t ii = 0; ii < inputPathnames.size(); ++ii) - { - const std::string& inputPathname(inputPathnames[ii]); - log->info(Ctxt("Reading " + inputPathname)); - std::unique_ptr data; - try - { - if (nitf::Reader::getNITFVersion(inputPathname) == - NITF_VER_UNKNOWN) - { - data = six::parseDataFromFile(xmlRegistry, - inputPathname, - schemaPaths, - *log); - allValid = allValid && runValidation(data, log); - } - else - { - reader.load(inputPathname, schemaPaths); - auto container = reader.getContainer(); - for (size_t jj = 0; jj < container->size(); ++jj) - { - data.reset(container->getData(jj)->clone()); - allValid = allValid && runValidation(data, log); - } - } - - } - catch (const six::DESValidationException& ex) - { - log->error(ex); - log->error(Ctxt("Unsuccessful: Please contact your product " - "vendor with these details!")); - allValid = false; - } - catch (const except::Exception& ex) - { - log->error(ex); - allValid = false; - } - } - - return allValid ? EXIT_SUCCESS : EXIT_FAILURE; -} -int main(int argc, char** argv) -{ - try - { - return main_(argc, argv); - } - catch (const std::exception& ex) - { - std::cerr << ex.what() << std::endl; - } - catch (const except::Exception& ex) - { - std::cerr << ex.toString() << std::endl; - return 1; - } - catch (...) - { - std::cerr << "Unknown exception\n"; - } - - return EXIT_FAILURE; +/* ========================================================================= + * This file is part of six-c++ + * ========================================================================= + * + * (C) Copyright 2004 - 2014, MDA Information Systems LLC + * + * six-c++ is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; If not, + * see . + * + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include "utils.h" + +namespace fs = std::filesystem; + +namespace +{ +// TODO: Does this belong in sys? +class ExtensionsPredicate : public sys::FileOnlyPredicate +{ +public: + ExtensionsPredicate(const std::vector& extensions, + bool ignoreCase = true) : + mExtensions(extensions), + mIgnoreCase(ignoreCase) + { + if (mIgnoreCase) + { + for (size_t ii = 0; ii < mExtensions.size(); ++ii) + { + str::lower(mExtensions[ii]); + } + } + } + + virtual bool operator()(const std::string& pathname) const + { + if (!sys::FileOnlyPredicate::operator()(pathname)) + { + return false; + } + + std::string ext = fs::path(pathname).extension().string(); + if (mIgnoreCase) + { + str::lower(ext); + } + + for (size_t ii = 0; ii < mExtensions.size(); ++ii) + { + if (ext == mExtensions[ii]) + { + return true; + } + } + + return false; + } + +private: + std::vector mExtensions; + const bool mIgnoreCase; +}; + +std::vector getPathnames(const std::string& dirname) +{ + std::vector extensions; + extensions.push_back(".nitf"); + extensions.push_back(".ntf"); + extensions.push_back(".xml"); + + return sys::FileFinder::search(ExtensionsPredicate(extensions), + std::vector(1, dirname), + false); +} + +bool runValidation(const std::unique_ptr& data, + std::unique_ptr& log) +{ + if (data->getDataType() == six::DataType::COMPLEX) + { + six::sicd::ComplexData* complexData = + static_cast( + data.get()); + + if (complexData->validate(*log)) + { + log->info(Ctxt("Successful: No Errors Found!")); + return true; + } + return false; + } + else + { + // Nothing to validate + log->info(Ctxt("Nothing done: not a SICD.")); + return true; + } +} +} + +// make it a little easier to use from MSVC +#if defined(_DEBUG) && defined(_MSC_VER) +static fs::path getNitfPath() +{ + const auto cwd = fs::current_path(); + const auto root_dir = cwd.parent_path().parent_path(); + return root_dir / "six" / "tests" / "nitf" / "sicd_1.1.0.nitf"; +} + +static void setNitfPluginPath() +{ + const auto cwd = fs::current_path(); + const auto root_dir = cwd.parent_path().parent_path().parent_path().parent_path().parent_path(); + + const std::string configuration = +#if defined(NDEBUG) // i.e., release + "Release"; +#else + "Debug"; +#endif + const std::string platform = "x64"; + + const auto path = root_dir / "externals" / "nitro" / platform / configuration / "share" / "nitf" / "plugins"; + sys::OS().setEnv("NITF_PLUGIN_PATH", path.string(), true /*overwrite*/); +} +#endif + +static int main_(int argc, char** argv) +{ + // make it a little easier to use from MSVC + #if defined(_DEBUG) && defined(_MSC_VER) + if (argc == 1) + { + setNitfPluginPath(); + + // ./six/modules/c++/six/tests/nitf/sidd_1.0.0.nitf + static const std::string nitf_path = getNitfPath().string(); + argc = 2; + auto argv_ = static_cast(malloc(argc * sizeof(char*))); + argv_[0] = argv[0]; + argv_[1] = const_cast(nitf_path.c_str()); + //argv[1] + argv = argv_; + } + #endif + + + // create a parser and add our options to it + cli::ArgumentParser parser; + parser.setDescription("This program reads a SIDD/SICD along with a "\ + "directory of schemas, and returns any error messages "\ + "that may be contained in the DES XML"); + parser.addArgument("-f --log", "Specify a log file", cli::STORE, "log", + "FILE")->setDefault("console"); + parser.addArgument("-l --level", "Specify log level", cli::STORE, + "level", "LEVEL")->setChoices( + str::split("debug info warn error"))->setDefault( + "info"); + parser.addArgument("-s --schema", + "Specify a schema or directory of schemas", + cli::STORE, "schema", "FILE"); + parser.addArgument("input", "Input SICD/SIDD file or directory of files", cli::STORE, "input", + "INPUT", 1, 1); + + const std::unique_ptr + options(parser.parse(argc, (const char**) argv)); + + const std::string inputPath(options->get("input")); + std::vector inputPathnames = getPathnames(inputPath); + const std::string logFile(options->get("log")); + std::string level(options->get("level")); + std::vector schemaPaths; + getSchemaPaths(*options, "--schema", "schema", schemaPaths); + + // create an XML registry + // The reason to do this is to avoid adding XMLControlCreators to the + // XMLControlFactory singleton - this way has more fine-grained control + six::XMLControlRegistry xmlRegistry; + xmlRegistry.addCreator(); + xmlRegistry.addCreator(); + + str::upper(level); + str::trim(level); + std::unique_ptr log = + logging::setupLogger(fs::path(argv[0]).filename().string(), level, logFile); + + // this validates the DES of the input against the + // best available schema + six::NITFReadControl reader; + reader.setLogger(*log); + reader.setXMLControlRegistry(&xmlRegistry); + bool allValid = true; + for (size_t ii = 0; ii < inputPathnames.size(); ++ii) + { + const std::string& inputPathname(inputPathnames[ii]); + log->info(Ctxt("Reading " + inputPathname)); + std::unique_ptr data; + try + { + if (nitf::Reader::getNITFVersion(inputPathname) == + NITF_VER_UNKNOWN) + { + data = six::parseDataFromFile(xmlRegistry, + inputPathname, + schemaPaths, + *log); + allValid = allValid && runValidation(data, log); + } + else + { + reader.load(inputPathname, schemaPaths); + auto container = reader.getContainer(); + for (size_t jj = 0; jj < container->size(); ++jj) + { + data.reset(container->getData(jj)->clone()); + allValid = allValid && runValidation(data, log); + } + } + + } + catch (const six::DESValidationException& ex) + { + log->error(ex); + log->error(Ctxt("Unsuccessful: Please contact your product " + "vendor with these details!")); + allValid = false; + } + catch (const except::Exception& ex) + { + log->error(ex); + allValid = false; + } + } + + return allValid ? EXIT_SUCCESS : EXIT_FAILURE; +} +int main(int argc, char** argv) +{ + try + { + return main_(argc, argv); + } + catch (const std::exception& ex) + { + std::cerr << ex.what() << std::endl; + } + catch (const except::Exception& ex) + { + std::cerr << ex.toString() << std::endl; + return 1; + } + catch (...) + { + std::cerr << "Unknown exception\n"; + } + + return EXIT_FAILURE; } \ No newline at end of file diff --git a/six/modules/c++/samples/utils.h b/six/modules/c++/samples/utils.h index 52e6cd4ced..a6c47df222 100644 --- a/six/modules/c++/samples/utils.h +++ b/six/modules/c++/samples/utils.h @@ -1,61 +1,61 @@ -#ifndef __SIX_TEST_UTILS_H__ -#define __SIX_TEST_UTILS_H__ - -#include -#include -#include - -/*! - * This function converts DMS corners into decimal degrees using NITRO, - * and then puts them into a lat-lon - */ -inline -six::LatLonCorners makeUpCornersFromDMS() -{ - int latTopDMS[3] = { 42, 17, 50 }; - int latBottomDMS[3] = { 42, 15, 14 }; - int lonEastDMS[3] = { -83, 42, 12 }; - int lonWestDMS[3] = { -83, 45, 44 }; - - const double latTopDecimal = - nitf::Utils::geographicToDecimal(latTopDMS[0], - latTopDMS[1], - latTopDMS[2]); - - const double latBottomDecimal = - nitf::Utils::geographicToDecimal(latBottomDMS[0], - latBottomDMS[1], - latBottomDMS[2]); - - const double lonEastDecimal = - nitf::Utils::geographicToDecimal(lonEastDMS[0], - lonEastDMS[1], - lonEastDMS[2]); - - const double lonWestDecimal = - nitf::Utils::geographicToDecimal(lonWestDMS[0], - lonWestDMS[1], - lonWestDMS[2]); - - six::LatLonCorners corners; - corners.upperLeft = six::LatLon(latTopDecimal, lonWestDecimal); - corners.upperRight = six::LatLon(latTopDecimal, lonEastDecimal); - corners.lowerRight = six::LatLon(latBottomDecimal, lonEastDecimal); - corners.lowerLeft = six::LatLon(latBottomDecimal, lonWestDecimal); - return corners; -} - -inline -void getSchemaPaths(const cli::Results& options, - const std::string& /*commandLineArg*/, - const std::string& cliArgName, - std::vector& schemaPaths) -{ - if(options.hasValue(cliArgName)) - { - schemaPaths.push_back(options.get(cliArgName)); - } - six::XMLControl::loadSchemaPaths(schemaPaths); -} - -#endif +#ifndef __SIX_TEST_UTILS_H__ +#define __SIX_TEST_UTILS_H__ + +#include +#include +#include + +/*! + * This function converts DMS corners into decimal degrees using NITRO, + * and then puts them into a lat-lon + */ +inline +six::LatLonCorners makeUpCornersFromDMS() +{ + int latTopDMS[3] = { 42, 17, 50 }; + int latBottomDMS[3] = { 42, 15, 14 }; + int lonEastDMS[3] = { -83, 42, 12 }; + int lonWestDMS[3] = { -83, 45, 44 }; + + const double latTopDecimal = + nitf::Utils::geographicToDecimal(latTopDMS[0], + latTopDMS[1], + latTopDMS[2]); + + const double latBottomDecimal = + nitf::Utils::geographicToDecimal(latBottomDMS[0], + latBottomDMS[1], + latBottomDMS[2]); + + const double lonEastDecimal = + nitf::Utils::geographicToDecimal(lonEastDMS[0], + lonEastDMS[1], + lonEastDMS[2]); + + const double lonWestDecimal = + nitf::Utils::geographicToDecimal(lonWestDMS[0], + lonWestDMS[1], + lonWestDMS[2]); + + six::LatLonCorners corners; + corners.upperLeft = six::LatLon(latTopDecimal, lonWestDecimal); + corners.upperRight = six::LatLon(latTopDecimal, lonEastDecimal); + corners.lowerRight = six::LatLon(latBottomDecimal, lonEastDecimal); + corners.lowerLeft = six::LatLon(latBottomDecimal, lonWestDecimal); + return corners; +} + +inline +void getSchemaPaths(const cli::Results& options, + const std::string& /*commandLineArg*/, + const std::string& cliArgName, + std::vector& schemaPaths) +{ + if(options.hasValue(cliArgName)) + { + schemaPaths.push_back(options.get(cliArgName)); + } + six::XMLControl::loadSchemaPaths(schemaPaths); +} + +#endif diff --git a/six/modules/c++/scene/include/scene/sys_Conf.h b/six/modules/c++/scene/include/scene/sys_Conf.h index 4828d27d57..46a06c3260 100644 --- a/six/modules/c++/scene/include/scene/sys_Conf.h +++ b/six/modules/c++/scene/include/scene/sys_Conf.h @@ -1,15 +1,15 @@ -#ifndef SIX_scene_sys_Conf_h_INCLUDED_ -#define SIX_scene_sys_Conf_h_INCLUDED_ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#include - -#endif // SIX_scene_sys_Conf_h_INCLUDED_ +#ifndef SIX_scene_sys_Conf_h_INCLUDED_ +#define SIX_scene_sys_Conf_h_INCLUDED_ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include + +#endif // SIX_scene_sys_Conf_h_INCLUDED_ diff --git a/six/modules/c++/scene/scene.ruleset b/six/modules/c++/scene/scene.ruleset index 2a2edcef36..598fbdbd65 100644 --- a/six/modules/c++/scene/scene.ruleset +++ b/six/modules/c++/scene/scene.ruleset @@ -1,32 +1,32 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/six/modules/c++/scene/scene.vcxproj.filters b/six/modules/c++/scene/scene.vcxproj.filters index ca51817fe9..61d0fcdcbc 100644 --- a/six/modules/c++/scene/scene.vcxproj.filters +++ b/six/modules/c++/scene/scene.vcxproj.filters @@ -1,123 +1,123 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + \ No newline at end of file diff --git a/six/modules/c++/scene/source/ProjectionPolynomialFitter.cpp b/six/modules/c++/scene/source/ProjectionPolynomialFitter.cpp index 233d7f8b93..10f3fb9654 100644 --- a/six/modules/c++/scene/source/ProjectionPolynomialFitter.cpp +++ b/six/modules/c++/scene/source/ProjectionPolynomialFitter.cpp @@ -1,489 +1,489 @@ -/* ========================================================================= - * This file is part of scene-c++ - * ========================================================================= - * - * (C) Copyright 2004 - 2014, MDA Information Systems LLC - * - * scene-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ - -#include - -#include -#include - -#undef min -#undef max - -namespace -{ -struct Shift final -{ - Shift(double shift) : - mShift(shift) - { - } - Shift(const Shift& other) = delete; - Shift& operator=(const Shift& other) = delete; - - inline double operator()(double input) const - { - return (input - mShift); - } - -private: - const double mShift; -}; -} - -namespace scene -{ -const size_t ProjectionPolynomialFitter::DEFAULTS_POINTS_1D = 10; - -ProjectionPolynomialFitter::ProjectionPolynomialFitter( - const ProjectionModel& projModel, - const GridECEFTransform& gridTransform, - const types::RowCol& outPixelStart, - const types::RowCol& outExtent, - size_t numPoints1D) : - mNumPoints1D(numPoints1D), - mOutputPlaneRows(numPoints1D, numPoints1D), - mOutputPlaneCols(numPoints1D, numPoints1D), - mSceneCoordinates(numPoints1D, - numPoints1D, - types::RowCol(0.0, 0.0)), - mTimeCOA(numPoints1D, numPoints1D) -{ - // Want to sample [outPixelStart, outPixelStart + outExtent) in the loop - // below. That is, we are marching through the portion of interest of the - // output grid in pixel space. In the case of multi-segment SICDs, we'll - // only sample our part of the grid defined by outPixelStart and - // outExtent. - const types::RowCol skip( - static_cast(outExtent.row - 1) / static_cast(mNumPoints1D - 1), - static_cast(outExtent.col - 1) / static_cast(mNumPoints1D - 1)); - - types::RowCol currentOffset(outPixelStart); - - for (size_t ii = 0; - ii < mNumPoints1D; - ++ii, currentOffset.row += skip.row) - { - currentOffset.col = outPixelStart.col; - - for (size_t jj = 0; - jj < mNumPoints1D; - ++jj, currentOffset.col += skip.col) - { - projectToSlantPlane(projModel, gridTransform, outPixelStart, - currentOffset, ii, jj); - } - } -} - -ProjectionPolynomialFitter::ProjectionPolynomialFitter( - const ProjectionModel& projModel, - const GridECEFTransform& gridTransform, - const types::RowCol& fullExtent, - const types::RowCol& outPixelStart, - const types::RowCol& /*outExtent*/, - const std::vector >& polygon, - size_t numPoints1D) : - mNumPoints1D(numPoints1D), - mOutputPlaneRows(numPoints1D, numPoints1D), - mOutputPlaneCols(numPoints1D, numPoints1D), - mSceneCoordinates(numPoints1D, - numPoints1D, - types::RowCol(0.0, 0.0)), - mTimeCOA(numPoints1D, numPoints1D) -{ - // Get bounding rectangle of output plane polygon. - double minRow = std::numeric_limits::max(); - double maxRow = -std::numeric_limits::max(); - double minCol = std::numeric_limits::max(); - double maxCol = -std::numeric_limits::max(); - - for (size_t ii = 0; ii < polygon.size(); ++ii) - { - minRow = std::min(minRow, polygon[ii].row); - maxRow = std::max(maxRow, polygon[ii].row); - minCol = std::min(minCol, polygon[ii].col); - maxCol = std::max(maxCol, polygon[ii].col); - } - - if (minRow > static_cast(fullExtent.row) || - maxRow < 0 || - minCol > static_cast(fullExtent.col) || - maxCol < 0) - { - throw except::Exception(Ctxt( - "Bounding rectangle is outside of output extent")); - } - - // Only interested in pixels inside the fullExtent. - minRow = std::max(minRow, 0.0); - minCol = std::max(minCol, 0.0); - maxRow = std::min(maxRow, static_cast(fullExtent.row) - 1); - maxCol = std::min(maxCol, static_cast(fullExtent.col) - 1); - - // Get size_t extent of the set of points. - const auto minRowI = gsl::narrow_cast(std::ceil(minRow)); - const auto minColI = gsl::narrow_cast(std::ceil(minCol)); - const auto maxRowI = gsl::narrow_cast(std::floor(maxRow)); - const auto maxColI = gsl::narrow_cast(std::floor(maxCol)); - - if (minRowI > maxRowI || minColI > maxColI) - { - throw except::Exception(Ctxt( - "Bounding rectangle has no area")); - } - - // The offset and extent are relative to the entire global output plane. - const types::RowCol boundingOffset(types::RowCol(minRowI, minColI)); - const types::RowCol boundingExtent(maxRowI - minRowI + 1, - maxColI - minColI + 1); - - // Get the PolygonMas. For each row of the polygon this will determine - // the first and last column of the row inside the convex hull of the - // polygon sent in. - const polygon::PolygonMask polygonMask(polygon, fullExtent); - - // Compute a delta in the row direction as if the entire bounding row - // extent will be covered by the point grid. - const double initialDeltaRow = - static_cast(boundingExtent.row - 1) / static_cast(numPoints1D - 1); - - // Scale factor for shrinking the row extent. - constexpr double shrinkFactor = 0.1; - - // Shring the row extent a bit. - const double deltaToRemove = initialDeltaRow * shrinkFactor; - - // Get the new row start and end values. - const size_t newStartRow = gsl::narrow_cast( - std::ceil(boundingOffset.row + deltaToRemove)); - const size_t newEndRow = gsl::narrow_cast( - std::floor(boundingOffset.row + static_cast(boundingExtent.row) - 1 - - deltaToRemove)); - - // Check the new row extent. - if (newStartRow > newEndRow) - { - throw except::Exception(Ctxt( - "New bounding rectangle has no area")); - } - - // Compute the row exent. - const size_t newExtentRow = (newEndRow - newStartRow + 1); - - // Compute the delta in the row direction for the new extent. - const double newDeltaRow = - static_cast(newExtentRow - 1) / - static_cast(numPoints1D - 1); - - double currentOffsetRow = static_cast(newStartRow); - for (size_t ii = 0; ii < numPoints1D; ++ii, currentOffsetRow += newDeltaRow) - { - const double currentRow = std::floor(currentOffsetRow); - const auto row = gsl::narrow_cast(currentRow); - - // Get the start column and number of columns inside the polygon row - // the current row. - const types::Range colRange = polygonMask.getRange(row); - - // Check that there are internal points. - if (colRange.mNumElements == 0) - { - throw except::Exception(Ctxt( - "Column range has no elements")); - } - - // Compute the delta in the column direction to cover the internal - // points. - const double newDeltaCol = - static_cast(colRange.mNumElements - 1) / - static_cast(numPoints1D - 1); - - double currentCol = static_cast(colRange.mStartElement); - for (size_t jj = 0; jj < numPoints1D; ++jj, currentCol += newDeltaCol) - { - const types::RowCol currentOffset(currentRow, currentCol); - projectToSlantPlane(projModel, gridTransform, outPixelStart, - currentOffset, ii, jj); - } - } -} - -void ProjectionPolynomialFitter::projectToSlantPlane( - const ProjectionModel& projModel, - const GridECEFTransform& gridTransform, - const types::RowCol& outPixelStart, - const types::RowCol& currentOffset, - size_t row, - size_t col) -{ - // Get the coordinate relative to the outPixelStart. - mOutputPlaneRows(row, col) = currentOffset.row - outPixelStart.row; - mOutputPlaneCols(row, col) = currentOffset.col - outPixelStart.col; - - // Find ECEF of the output plane pixel. - const scene::Vector3 ecef = - gridTransform.rowColToECEF(currentOffset); - - // Project ECEF coordinate into the slant plane and get meters from - // the slant plane scene center point. - double timeCOA(0.0); - mSceneCoordinates(row, col) = projModel.sceneToImage(ecef, &timeCOA); - mTimeCOA(row, col) = timeCOA; -} - -void ProjectionPolynomialFitter::getSlantPlaneSamples( - const types::RowCol& inPixelStart, - const types::RowCol& inSceneCenter, - const types::RowCol& interimSceneCenter, - const types::RowCol& interimSampleSpacing, - math::linear::Matrix2D& slantPlaneRows, - math::linear::Matrix2D& slantPlaneCols) const -{ - const types::RowCol ratio(interimSceneCenter / inSceneCenter); - - const types::RowCol aoiOffset(static_cast(inPixelStart.row) * ratio.row, - static_cast(inPixelStart.col) * ratio.col); - - for (size_t ii = 0; ii < mNumPoints1D; ++ii) - { - for (size_t jj = 0; jj < mNumPoints1D; ++jj) - { - // sceneCoord is in meters from the slant plane SCP - // So, divide by the sample spacing to get it in pixels, then - // offset by the slant plane SCP pixel. Need to further offset to - // take non-zero inPixelStart into account. - const types::RowCol sceneCoord(mSceneCoordinates(ii, jj)); - - slantPlaneRows(ii, jj) = - sceneCoord.row / interimSampleSpacing.row + - interimSceneCenter.row - aoiOffset.row; - - slantPlaneCols(ii, jj) = - sceneCoord.col / interimSampleSpacing.col + - interimSceneCenter.col - aoiOffset.col; - } - } -} - -void ProjectionPolynomialFitter::fitOutputToSlantPolynomials( - const types::RowCol& inPixelStart, - const types::RowCol& inSceneCenter, - const types::RowCol& interimSceneCenter, - const types::RowCol& interimSampleSpacing, - size_t polyOrderX, - size_t polyOrderY, - math::poly::TwoD& outputToSlantRow, - math::poly::TwoD& outputToSlantCol, - double* meanResidualErrorRow, - double* meanResidualErrorCol) const -{ - // Collect up slant plane pixel locations for the output plane samples we - // have - math::linear::Matrix2D slantPlaneRows(mNumPoints1D, mNumPoints1D); - math::linear::Matrix2D slantPlaneCols(mNumPoints1D, mNumPoints1D); - getSlantPlaneSamples(inPixelStart, - inSceneCenter, - interimSceneCenter, - interimSampleSpacing, - slantPlaneRows, - slantPlaneCols); - - // Now fit the polynomials - outputToSlantRow = math::poly::fit(mOutputPlaneRows, - mOutputPlaneCols, - slantPlaneRows, - polyOrderX, polyOrderY); - - outputToSlantCol = math::poly::fit(mOutputPlaneRows, - mOutputPlaneCols, - slantPlaneCols, - polyOrderX, polyOrderY); - - // Optionally report the residual error - if (meanResidualErrorRow || meanResidualErrorCol) - { - double errorSumRow(0.0); - double errorSumCol(0.0); - - for (size_t ii = 0; ii < mNumPoints1D; ++ii) - { - for (size_t jj = 0; jj < mNumPoints1D; ++jj) - { - const double row(mOutputPlaneRows(ii, jj)); - const double col(mOutputPlaneCols(ii, jj)); - - double diff = - slantPlaneRows(ii, jj) - outputToSlantRow(row, col); - errorSumRow += diff * diff; - - diff = slantPlaneCols(ii, jj) - outputToSlantCol(row, col); - errorSumCol += diff * diff; - } - } - - const auto numPoints = static_cast(mNumPoints1D * mNumPoints1D); - if (meanResidualErrorRow) - { - *meanResidualErrorRow = errorSumRow / numPoints; - } - if (meanResidualErrorCol) - { - *meanResidualErrorCol = errorSumCol / numPoints; - } - } -} - -void ProjectionPolynomialFitter::fitSlantToOutputPolynomials( - const types::RowCol& inPixelStart, - const types::RowCol& inSceneCenter, - const types::RowCol& interimSceneCenter, - const types::RowCol& interimSampleSpacing, - size_t polyOrderX, - size_t polyOrderY, - math::poly::TwoD& slantToOutputRow, - math::poly::TwoD& slantToOutputCol, - double* meanResidualErrorRow, - double* meanResidualErrorCol) const -{ - // Collect up slant plane pixel locations for the output plane samples we - // have - math::linear::Matrix2D slantPlaneRows(mNumPoints1D, mNumPoints1D); - math::linear::Matrix2D slantPlaneCols(mNumPoints1D, mNumPoints1D); - getSlantPlaneSamples(inPixelStart, - inSceneCenter, - interimSceneCenter, - interimSampleSpacing, - slantPlaneRows, - slantPlaneCols); - - // Now fit the polynomials - slantToOutputRow = math::poly::fit(slantPlaneRows, - slantPlaneCols, - mOutputPlaneRows, - polyOrderX, polyOrderY); - - slantToOutputCol = math::poly::fit(slantPlaneRows, - slantPlaneCols, - mOutputPlaneCols, - polyOrderX, polyOrderY); - - // Optionally report the residual error - if (meanResidualErrorRow || meanResidualErrorCol) - { - double errorSumRow(0.0); - double errorSumCol(0.0); - - for (size_t ii = 0; ii < mNumPoints1D; ++ii) - { - for (size_t jj = 0; jj < mNumPoints1D; ++jj) - { - const double row(slantPlaneRows(ii, jj)); - const double col(slantPlaneCols(ii, jj)); - - double diff = - mOutputPlaneRows(ii, jj) - slantToOutputRow(row, col); - errorSumRow += diff * diff; - - diff = mOutputPlaneCols(ii, jj) - slantToOutputCol(row, col); - errorSumCol += diff * diff; - } - } - - const auto numPoints = static_cast(mNumPoints1D * mNumPoints1D); - if (meanResidualErrorRow) - { - *meanResidualErrorRow = errorSumRow / numPoints; - } - if (meanResidualErrorCol) - { - *meanResidualErrorCol = errorSumCol / numPoints; - } - } -} - -void ProjectionPolynomialFitter::fitTimeCOAPolynomial( - const types::RowCol& outSceneCenter, - const types::RowCol& outSampleSpacing, - size_t polyOrderX, - size_t polyOrderY, - math::poly::TwoD& timeCOAPoly, - double* meanResidualError) const -{ - math::linear::Matrix2D rowMapping(mNumPoints1D, mNumPoints1D); - math::linear::Matrix2D colMapping(mNumPoints1D, mNumPoints1D); - - for (size_t ii = 0; ii < mNumPoints1D; ++ii) - { - for (size_t jj = 0; jj < mNumPoints1D; ++jj) - { - // Need to map output plane pixels to meters from the output - // plane SCP - rowMapping(ii, jj) = - (mOutputPlaneRows(ii,jj) - outSceneCenter.row) * - outSampleSpacing.row; - - colMapping(ii, jj) = - (mOutputPlaneCols(ii,jj) - outSceneCenter.col) * - outSampleSpacing.col; - } - } - - // Now fit the polynomial - timeCOAPoly = math::poly::fit(rowMapping, colMapping, mTimeCOA, - polyOrderX, polyOrderY); - - // Optionally report the residual error - if (meanResidualError) - { - double errorSum(0.0); - - for (size_t ii = 0; ii < mNumPoints1D; ++ii) - { - for (size_t jj = 0; jj < mNumPoints1D; ++jj) - { - const double row(rowMapping(ii, jj)); - const double col(colMapping(ii, jj)); - - const double diff = mTimeCOA(ii, jj) - timeCOAPoly(row, col); - errorSum += diff * diff; - } - } - - *meanResidualError = errorSum / static_cast(mNumPoints1D * mNumPoints1D); - } -} - -void ProjectionPolynomialFitter::fitPixelBasedTimeCOAPolynomial( - const types::RowCol& outPixelShift, - size_t polyOrderX, - size_t polyOrderY, - math::poly::TwoD& timeCOAPoly, - double* meanResidualError) const -{ - fitPixelBasedTimeCOAPolynomial(Shift(outPixelShift.row), - Shift(outPixelShift.col), - polyOrderX, - polyOrderY, - timeCOAPoly, - meanResidualError); -} -} +/* ========================================================================= + * This file is part of scene-c++ + * ========================================================================= + * + * (C) Copyright 2004 - 2014, MDA Information Systems LLC + * + * scene-c++ is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; If not, + * see . + * + */ + +#include + +#include +#include + +#undef min +#undef max + +namespace +{ +struct Shift final +{ + Shift(double shift) : + mShift(shift) + { + } + Shift(const Shift& other) = delete; + Shift& operator=(const Shift& other) = delete; + + inline double operator()(double input) const + { + return (input - mShift); + } + +private: + const double mShift; +}; +} + +namespace scene +{ +const size_t ProjectionPolynomialFitter::DEFAULTS_POINTS_1D = 10; + +ProjectionPolynomialFitter::ProjectionPolynomialFitter( + const ProjectionModel& projModel, + const GridECEFTransform& gridTransform, + const types::RowCol& outPixelStart, + const types::RowCol& outExtent, + size_t numPoints1D) : + mNumPoints1D(numPoints1D), + mOutputPlaneRows(numPoints1D, numPoints1D), + mOutputPlaneCols(numPoints1D, numPoints1D), + mSceneCoordinates(numPoints1D, + numPoints1D, + types::RowCol(0.0, 0.0)), + mTimeCOA(numPoints1D, numPoints1D) +{ + // Want to sample [outPixelStart, outPixelStart + outExtent) in the loop + // below. That is, we are marching through the portion of interest of the + // output grid in pixel space. In the case of multi-segment SICDs, we'll + // only sample our part of the grid defined by outPixelStart and + // outExtent. + const types::RowCol skip( + static_cast(outExtent.row - 1) / static_cast(mNumPoints1D - 1), + static_cast(outExtent.col - 1) / static_cast(mNumPoints1D - 1)); + + types::RowCol currentOffset(outPixelStart); + + for (size_t ii = 0; + ii < mNumPoints1D; + ++ii, currentOffset.row += skip.row) + { + currentOffset.col = outPixelStart.col; + + for (size_t jj = 0; + jj < mNumPoints1D; + ++jj, currentOffset.col += skip.col) + { + projectToSlantPlane(projModel, gridTransform, outPixelStart, + currentOffset, ii, jj); + } + } +} + +ProjectionPolynomialFitter::ProjectionPolynomialFitter( + const ProjectionModel& projModel, + const GridECEFTransform& gridTransform, + const types::RowCol& fullExtent, + const types::RowCol& outPixelStart, + const types::RowCol& /*outExtent*/, + const std::vector >& polygon, + size_t numPoints1D) : + mNumPoints1D(numPoints1D), + mOutputPlaneRows(numPoints1D, numPoints1D), + mOutputPlaneCols(numPoints1D, numPoints1D), + mSceneCoordinates(numPoints1D, + numPoints1D, + types::RowCol(0.0, 0.0)), + mTimeCOA(numPoints1D, numPoints1D) +{ + // Get bounding rectangle of output plane polygon. + double minRow = std::numeric_limits::max(); + double maxRow = -std::numeric_limits::max(); + double minCol = std::numeric_limits::max(); + double maxCol = -std::numeric_limits::max(); + + for (size_t ii = 0; ii < polygon.size(); ++ii) + { + minRow = std::min(minRow, polygon[ii].row); + maxRow = std::max(maxRow, polygon[ii].row); + minCol = std::min(minCol, polygon[ii].col); + maxCol = std::max(maxCol, polygon[ii].col); + } + + if (minRow > static_cast(fullExtent.row) || + maxRow < 0 || + minCol > static_cast(fullExtent.col) || + maxCol < 0) + { + throw except::Exception(Ctxt( + "Bounding rectangle is outside of output extent")); + } + + // Only interested in pixels inside the fullExtent. + minRow = std::max(minRow, 0.0); + minCol = std::max(minCol, 0.0); + maxRow = std::min(maxRow, static_cast(fullExtent.row) - 1); + maxCol = std::min(maxCol, static_cast(fullExtent.col) - 1); + + // Get size_t extent of the set of points. + const auto minRowI = gsl::narrow_cast(std::ceil(minRow)); + const auto minColI = gsl::narrow_cast(std::ceil(minCol)); + const auto maxRowI = gsl::narrow_cast(std::floor(maxRow)); + const auto maxColI = gsl::narrow_cast(std::floor(maxCol)); + + if (minRowI > maxRowI || minColI > maxColI) + { + throw except::Exception(Ctxt( + "Bounding rectangle has no area")); + } + + // The offset and extent are relative to the entire global output plane. + const types::RowCol boundingOffset(types::RowCol(minRowI, minColI)); + const types::RowCol boundingExtent(maxRowI - minRowI + 1, + maxColI - minColI + 1); + + // Get the PolygonMas. For each row of the polygon this will determine + // the first and last column of the row inside the convex hull of the + // polygon sent in. + const polygon::PolygonMask polygonMask(polygon, fullExtent); + + // Compute a delta in the row direction as if the entire bounding row + // extent will be covered by the point grid. + const double initialDeltaRow = + static_cast(boundingExtent.row - 1) / static_cast(numPoints1D - 1); + + // Scale factor for shrinking the row extent. + constexpr double shrinkFactor = 0.1; + + // Shring the row extent a bit. + const double deltaToRemove = initialDeltaRow * shrinkFactor; + + // Get the new row start and end values. + const size_t newStartRow = gsl::narrow_cast( + std::ceil(boundingOffset.row + deltaToRemove)); + const size_t newEndRow = gsl::narrow_cast( + std::floor(boundingOffset.row + static_cast(boundingExtent.row) - 1 - + deltaToRemove)); + + // Check the new row extent. + if (newStartRow > newEndRow) + { + throw except::Exception(Ctxt( + "New bounding rectangle has no area")); + } + + // Compute the row exent. + const size_t newExtentRow = (newEndRow - newStartRow + 1); + + // Compute the delta in the row direction for the new extent. + const double newDeltaRow = + static_cast(newExtentRow - 1) / + static_cast(numPoints1D - 1); + + double currentOffsetRow = static_cast(newStartRow); + for (size_t ii = 0; ii < numPoints1D; ++ii, currentOffsetRow += newDeltaRow) + { + const double currentRow = std::floor(currentOffsetRow); + const auto row = gsl::narrow_cast(currentRow); + + // Get the start column and number of columns inside the polygon row + // the current row. + const types::Range colRange = polygonMask.getRange(row); + + // Check that there are internal points. + if (colRange.mNumElements == 0) + { + throw except::Exception(Ctxt( + "Column range has no elements")); + } + + // Compute the delta in the column direction to cover the internal + // points. + const double newDeltaCol = + static_cast(colRange.mNumElements - 1) / + static_cast(numPoints1D - 1); + + double currentCol = static_cast(colRange.mStartElement); + for (size_t jj = 0; jj < numPoints1D; ++jj, currentCol += newDeltaCol) + { + const types::RowCol currentOffset(currentRow, currentCol); + projectToSlantPlane(projModel, gridTransform, outPixelStart, + currentOffset, ii, jj); + } + } +} + +void ProjectionPolynomialFitter::projectToSlantPlane( + const ProjectionModel& projModel, + const GridECEFTransform& gridTransform, + const types::RowCol& outPixelStart, + const types::RowCol& currentOffset, + size_t row, + size_t col) +{ + // Get the coordinate relative to the outPixelStart. + mOutputPlaneRows(row, col) = currentOffset.row - outPixelStart.row; + mOutputPlaneCols(row, col) = currentOffset.col - outPixelStart.col; + + // Find ECEF of the output plane pixel. + const scene::Vector3 ecef = + gridTransform.rowColToECEF(currentOffset); + + // Project ECEF coordinate into the slant plane and get meters from + // the slant plane scene center point. + double timeCOA(0.0); + mSceneCoordinates(row, col) = projModel.sceneToImage(ecef, &timeCOA); + mTimeCOA(row, col) = timeCOA; +} + +void ProjectionPolynomialFitter::getSlantPlaneSamples( + const types::RowCol& inPixelStart, + const types::RowCol& inSceneCenter, + const types::RowCol& interimSceneCenter, + const types::RowCol& interimSampleSpacing, + math::linear::Matrix2D& slantPlaneRows, + math::linear::Matrix2D& slantPlaneCols) const +{ + const types::RowCol ratio(interimSceneCenter / inSceneCenter); + + const types::RowCol aoiOffset(static_cast(inPixelStart.row) * ratio.row, + static_cast(inPixelStart.col) * ratio.col); + + for (size_t ii = 0; ii < mNumPoints1D; ++ii) + { + for (size_t jj = 0; jj < mNumPoints1D; ++jj) + { + // sceneCoord is in meters from the slant plane SCP + // So, divide by the sample spacing to get it in pixels, then + // offset by the slant plane SCP pixel. Need to further offset to + // take non-zero inPixelStart into account. + const types::RowCol sceneCoord(mSceneCoordinates(ii, jj)); + + slantPlaneRows(ii, jj) = + sceneCoord.row / interimSampleSpacing.row + + interimSceneCenter.row - aoiOffset.row; + + slantPlaneCols(ii, jj) = + sceneCoord.col / interimSampleSpacing.col + + interimSceneCenter.col - aoiOffset.col; + } + } +} + +void ProjectionPolynomialFitter::fitOutputToSlantPolynomials( + const types::RowCol& inPixelStart, + const types::RowCol& inSceneCenter, + const types::RowCol& interimSceneCenter, + const types::RowCol& interimSampleSpacing, + size_t polyOrderX, + size_t polyOrderY, + math::poly::TwoD& outputToSlantRow, + math::poly::TwoD& outputToSlantCol, + double* meanResidualErrorRow, + double* meanResidualErrorCol) const +{ + // Collect up slant plane pixel locations for the output plane samples we + // have + math::linear::Matrix2D slantPlaneRows(mNumPoints1D, mNumPoints1D); + math::linear::Matrix2D slantPlaneCols(mNumPoints1D, mNumPoints1D); + getSlantPlaneSamples(inPixelStart, + inSceneCenter, + interimSceneCenter, + interimSampleSpacing, + slantPlaneRows, + slantPlaneCols); + + // Now fit the polynomials + outputToSlantRow = math::poly::fit(mOutputPlaneRows, + mOutputPlaneCols, + slantPlaneRows, + polyOrderX, polyOrderY); + + outputToSlantCol = math::poly::fit(mOutputPlaneRows, + mOutputPlaneCols, + slantPlaneCols, + polyOrderX, polyOrderY); + + // Optionally report the residual error + if (meanResidualErrorRow || meanResidualErrorCol) + { + double errorSumRow(0.0); + double errorSumCol(0.0); + + for (size_t ii = 0; ii < mNumPoints1D; ++ii) + { + for (size_t jj = 0; jj < mNumPoints1D; ++jj) + { + const double row(mOutputPlaneRows(ii, jj)); + const double col(mOutputPlaneCols(ii, jj)); + + double diff = + slantPlaneRows(ii, jj) - outputToSlantRow(row, col); + errorSumRow += diff * diff; + + diff = slantPlaneCols(ii, jj) - outputToSlantCol(row, col); + errorSumCol += diff * diff; + } + } + + const auto numPoints = static_cast(mNumPoints1D * mNumPoints1D); + if (meanResidualErrorRow) + { + *meanResidualErrorRow = errorSumRow / numPoints; + } + if (meanResidualErrorCol) + { + *meanResidualErrorCol = errorSumCol / numPoints; + } + } +} + +void ProjectionPolynomialFitter::fitSlantToOutputPolynomials( + const types::RowCol& inPixelStart, + const types::RowCol& inSceneCenter, + const types::RowCol& interimSceneCenter, + const types::RowCol& interimSampleSpacing, + size_t polyOrderX, + size_t polyOrderY, + math::poly::TwoD& slantToOutputRow, + math::poly::TwoD& slantToOutputCol, + double* meanResidualErrorRow, + double* meanResidualErrorCol) const +{ + // Collect up slant plane pixel locations for the output plane samples we + // have + math::linear::Matrix2D slantPlaneRows(mNumPoints1D, mNumPoints1D); + math::linear::Matrix2D slantPlaneCols(mNumPoints1D, mNumPoints1D); + getSlantPlaneSamples(inPixelStart, + inSceneCenter, + interimSceneCenter, + interimSampleSpacing, + slantPlaneRows, + slantPlaneCols); + + // Now fit the polynomials + slantToOutputRow = math::poly::fit(slantPlaneRows, + slantPlaneCols, + mOutputPlaneRows, + polyOrderX, polyOrderY); + + slantToOutputCol = math::poly::fit(slantPlaneRows, + slantPlaneCols, + mOutputPlaneCols, + polyOrderX, polyOrderY); + + // Optionally report the residual error + if (meanResidualErrorRow || meanResidualErrorCol) + { + double errorSumRow(0.0); + double errorSumCol(0.0); + + for (size_t ii = 0; ii < mNumPoints1D; ++ii) + { + for (size_t jj = 0; jj < mNumPoints1D; ++jj) + { + const double row(slantPlaneRows(ii, jj)); + const double col(slantPlaneCols(ii, jj)); + + double diff = + mOutputPlaneRows(ii, jj) - slantToOutputRow(row, col); + errorSumRow += diff * diff; + + diff = mOutputPlaneCols(ii, jj) - slantToOutputCol(row, col); + errorSumCol += diff * diff; + } + } + + const auto numPoints = static_cast(mNumPoints1D * mNumPoints1D); + if (meanResidualErrorRow) + { + *meanResidualErrorRow = errorSumRow / numPoints; + } + if (meanResidualErrorCol) + { + *meanResidualErrorCol = errorSumCol / numPoints; + } + } +} + +void ProjectionPolynomialFitter::fitTimeCOAPolynomial( + const types::RowCol& outSceneCenter, + const types::RowCol& outSampleSpacing, + size_t polyOrderX, + size_t polyOrderY, + math::poly::TwoD& timeCOAPoly, + double* meanResidualError) const +{ + math::linear::Matrix2D rowMapping(mNumPoints1D, mNumPoints1D); + math::linear::Matrix2D colMapping(mNumPoints1D, mNumPoints1D); + + for (size_t ii = 0; ii < mNumPoints1D; ++ii) + { + for (size_t jj = 0; jj < mNumPoints1D; ++jj) + { + // Need to map output plane pixels to meters from the output + // plane SCP + rowMapping(ii, jj) = + (mOutputPlaneRows(ii,jj) - outSceneCenter.row) * + outSampleSpacing.row; + + colMapping(ii, jj) = + (mOutputPlaneCols(ii,jj) - outSceneCenter.col) * + outSampleSpacing.col; + } + } + + // Now fit the polynomial + timeCOAPoly = math::poly::fit(rowMapping, colMapping, mTimeCOA, + polyOrderX, polyOrderY); + + // Optionally report the residual error + if (meanResidualError) + { + double errorSum(0.0); + + for (size_t ii = 0; ii < mNumPoints1D; ++ii) + { + for (size_t jj = 0; jj < mNumPoints1D; ++jj) + { + const double row(rowMapping(ii, jj)); + const double col(colMapping(ii, jj)); + + const double diff = mTimeCOA(ii, jj) - timeCOAPoly(row, col); + errorSum += diff * diff; + } + } + + *meanResidualError = errorSum / static_cast(mNumPoints1D * mNumPoints1D); + } +} + +void ProjectionPolynomialFitter::fitPixelBasedTimeCOAPolynomial( + const types::RowCol& outPixelShift, + size_t polyOrderX, + size_t polyOrderY, + math::poly::TwoD& timeCOAPoly, + double* meanResidualError) const +{ + fitPixelBasedTimeCOAPolynomial(Shift(outPixelShift.row), + Shift(outPixelShift.col), + polyOrderX, + polyOrderY, + timeCOAPoly, + meanResidualError); +} +} diff --git a/six/modules/c++/six.ruleset b/six/modules/c++/six.ruleset index 5f1780c77b..f3bf8df8a1 100644 --- a/six/modules/c++/six.ruleset +++ b/six/modules/c++/six.ruleset @@ -1,32 +1,32 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/six/modules/c++/six.sicd/include/six/sicd/ImageCreation.h b/six/modules/c++/six.sicd/include/six/sicd/ImageCreation.h index a632c4bc11..c368953555 100644 --- a/six/modules/c++/six.sicd/include/six/sicd/ImageCreation.h +++ b/six/modules/c++/six.sicd/include/six/sicd/ImageCreation.h @@ -19,67 +19,67 @@ * see . * */ -#ifndef __SIX_IMAGE_CREATION_H__ -#define __SIX_IMAGE_CREATION_H__ - -#include "six/Types.h" - -namespace six -{ -namespace sicd -{ -/*! - * \struct ImageCreation - * \brief Contains SICD ImageCreation parameters - * - * The ImageCreation block is the first sub-block under the 'SICD' - * tag. It is optional altogether, and contains, information about - * the image creation (and processing). - */ -struct ImageCreation -{ - /*! - * (Optional) The name and version of the application used to - * create the image - */ - std::string application; - - /*! - * (Optional) Date and time that the image creation application - * processed the image (UTC) - */ - DateTime dateTime; - - /*! - * (Optional) The creation site of this SICD product - */ - std::string site; - - /*! - * (Optional) Identifies what profile was used to create this - * SICD product - */ - std::string profile; - - ImageCreation* clone() const - { - return new ImageCreation(*this); - } - - //! Equality operator - bool operator==(const ImageCreation& rhs) const - { - return (application == rhs.application && - dateTime == rhs.dateTime && site == rhs.site && - profile == rhs.profile); - } - bool operator!=(const ImageCreation& rhs) const - { - return !(*this == rhs); - } -}; - -} -} -#endif +#ifndef __SIX_IMAGE_CREATION_H__ +#define __SIX_IMAGE_CREATION_H__ + +#include "six/Types.h" + +namespace six +{ +namespace sicd +{ +/*! + * \struct ImageCreation + * \brief Contains SICD ImageCreation parameters + * + * The ImageCreation block is the first sub-block under the 'SICD' + * tag. It is optional altogether, and contains, information about + * the image creation (and processing). + */ +struct ImageCreation +{ + /*! + * (Optional) The name and version of the application used to + * create the image + */ + std::string application; + + /*! + * (Optional) Date and time that the image creation application + * processed the image (UTC) + */ + DateTime dateTime; + + /*! + * (Optional) The creation site of this SICD product + */ + std::string site; + + /*! + * (Optional) Identifies what profile was used to create this + * SICD product + */ + std::string profile; + + ImageCreation* clone() const + { + return new ImageCreation(*this); + } + + //! Equality operator + bool operator==(const ImageCreation& rhs) const + { + return (application == rhs.application && + dateTime == rhs.dateTime && site == rhs.site && + profile == rhs.profile); + } + bool operator!=(const ImageCreation& rhs) const + { + return !(*this == rhs); + } +}; + +} +} +#endif diff --git a/six/modules/c++/six.sicd/include/six/sicd/NITFReadComplexXMLControl.h b/six/modules/c++/six.sicd/include/six/sicd/NITFReadComplexXMLControl.h index 97f8ee03fc..331d49b3d0 100644 --- a/six/modules/c++/six.sicd/include/six/sicd/NITFReadComplexXMLControl.h +++ b/six/modules/c++/six.sicd/include/six/sicd/NITFReadComplexXMLControl.h @@ -1,107 +1,107 @@ -/* ========================================================================= - * This file is part of six.sicd-c++ - * ========================================================================= - * - * (C) Copyright 2021 Maxar Technologies, Inc. - * - * six.sicd-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ -#ifndef SIX_sicd_NITFReadComplexXMLControl_h_INCLUDED_ -#define SIX_sicd_NITFReadComplexXMLControl_h_INCLUDED_ -#pragma once - -#include -#include -#include -#include - -#include -#include - -#include "six/XMLControlFactory.h" -#include "six/NITFReadControl.h" -#include "six/Region.h" -#include "six/sicd/ComplexData.h" -#include "six/sicd/SICDMesh.h" - -namespace six -{ - namespace sicd - { - class NITFReadComplexXMLControl final - { - six::XMLControlRegistry xmlRegistry; - six::NITFReadControl reader; - - public: - NITFReadComplexXMLControl(); - ~NITFReadComplexXMLControl() = default; - NITFReadComplexXMLControl(const NITFReadComplexXMLControl&) = delete; - NITFReadComplexXMLControl& operator=(const NITFReadComplexXMLControl&) = delete; - NITFReadComplexXMLControl(NITFReadComplexXMLControl&&) = delete; - NITFReadComplexXMLControl& operator=(NITFReadComplexXMLControl&&) = delete; - - template - void addCreator() - { - xmlRegistry.addCreator(); - reader.setXMLControlRegistry(&xmlRegistry); - } - - const six::NITFReadControl& NITFReadControl() const { return reader; } - six::NITFReadControl& NITFReadControl() { return reader; } - - void load(const std::string& fromFile, const std::vector* pSchemaPaths); - void load(const std::filesystem::path& fromFile, const std::vector* pSchemaPaths); - template - void load(const TPath& fromFile, const std::vector& schemaPaths) - { - load(fromFile, &schemaPaths); - } - void load(const std::filesystem::path& fromFile) - { - load(fromFile, nullptr /*schemaPaths*/); - } - - void load(io::FileInputStream&, const std::vector* pSchemaPaths); - void load(io::FileInputStream&, const std::vector* pSchemaPaths); - template - void load(io::FileInputStream& fis, const std::vector& schemaPaths) - { - load(fis, &schemaPaths); - } - - std::shared_ptr getContainer() const; - std::shared_ptr getContainer(); - - std::unique_ptr getComplexData(); - - std::vector getWidebandData(const ComplexData&); - void getWidebandData(const ComplexData&, const types::RowCol& offset, const types::RowCol& extent, - six::zfloat* buffer); - - void getMeshes(std::unique_ptr&, std::unique_ptr&) const; - - void setXMLControlRegistry(); - void setLogger(); - - void interleaved(Region& region); - std::vector interleaved(); - }; - } -} - +/* ========================================================================= + * This file is part of six.sicd-c++ + * ========================================================================= + * + * (C) Copyright 2021 Maxar Technologies, Inc. + * + * six.sicd-c++ is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; If not, + * see . + * + */ +#ifndef SIX_sicd_NITFReadComplexXMLControl_h_INCLUDED_ +#define SIX_sicd_NITFReadComplexXMLControl_h_INCLUDED_ +#pragma once + +#include +#include +#include +#include + +#include +#include + +#include "six/XMLControlFactory.h" +#include "six/NITFReadControl.h" +#include "six/Region.h" +#include "six/sicd/ComplexData.h" +#include "six/sicd/SICDMesh.h" + +namespace six +{ + namespace sicd + { + class NITFReadComplexXMLControl final + { + six::XMLControlRegistry xmlRegistry; + six::NITFReadControl reader; + + public: + NITFReadComplexXMLControl(); + ~NITFReadComplexXMLControl() = default; + NITFReadComplexXMLControl(const NITFReadComplexXMLControl&) = delete; + NITFReadComplexXMLControl& operator=(const NITFReadComplexXMLControl&) = delete; + NITFReadComplexXMLControl(NITFReadComplexXMLControl&&) = delete; + NITFReadComplexXMLControl& operator=(NITFReadComplexXMLControl&&) = delete; + + template + void addCreator() + { + xmlRegistry.addCreator(); + reader.setXMLControlRegistry(&xmlRegistry); + } + + const six::NITFReadControl& NITFReadControl() const { return reader; } + six::NITFReadControl& NITFReadControl() { return reader; } + + void load(const std::string& fromFile, const std::vector* pSchemaPaths); + void load(const std::filesystem::path& fromFile, const std::vector* pSchemaPaths); + template + void load(const TPath& fromFile, const std::vector& schemaPaths) + { + load(fromFile, &schemaPaths); + } + void load(const std::filesystem::path& fromFile) + { + load(fromFile, nullptr /*schemaPaths*/); + } + + void load(io::FileInputStream&, const std::vector* pSchemaPaths); + void load(io::FileInputStream&, const std::vector* pSchemaPaths); + template + void load(io::FileInputStream& fis, const std::vector& schemaPaths) + { + load(fis, &schemaPaths); + } + + std::shared_ptr getContainer() const; + std::shared_ptr getContainer(); + + std::unique_ptr getComplexData(); + + std::vector getWidebandData(const ComplexData&); + void getWidebandData(const ComplexData&, const types::RowCol& offset, const types::RowCol& extent, + six::zfloat* buffer); + + void getMeshes(std::unique_ptr&, std::unique_ptr&) const; + + void setXMLControlRegistry(); + void setLogger(); + + void interleaved(Region& region); + std::vector interleaved(); + }; + } +} + #endif // SIX_sicd_NITFReadComplexXMLControl_h_INCLUDED_ \ No newline at end of file diff --git a/six/modules/c++/six.sicd/include/six/sicd/PFA.h b/six/modules/c++/six.sicd/include/six/sicd/PFA.h index bd44dca4db..a9ea0dc513 100644 --- a/six/modules/c++/six.sicd/include/six/sicd/PFA.h +++ b/six/modules/c++/six.sicd/include/six/sicd/PFA.h @@ -19,134 +19,134 @@ * see . * */ -#ifndef __SIX_PFA_H__ -#define __SIX_PFA_H__ - -#include "logging/Logger.h" -#include "six/Types.h" -#include "six/Init.h" -#include "six/Parameter.h" +#ifndef __SIX_PFA_H__ +#define __SIX_PFA_H__ + +#include "logging/Logger.h" +#include "six/Types.h" +#include "six/Init.h" +#include "six/Parameter.h" #include "six/sicd/GeoData.h" #include "six/sicd/Position.h" #include "six/sicd/SCPCOA.h" - -namespace six -{ -namespace sicd -{ -struct Grid; -/*! - * \struct SlowTimeDeskew - * \brief SICD STDeskew - * - * Parameters to describe image domain slow time - * deskew processing. Name changed for API consistency - */ -struct SlowTimeDeskew -{ - //! Constructor - SlowTimeDeskew(); - - //! Was slow time deskew phase function applied? - BooleanType applied; - - //! Slow time deskew phase function to perform the slow-time/Kaz - //! shift. 2D poly function of image range coord and az coord - Poly2D slowTimeDeskewPhasePoly; - - //! Equality operator - bool operator==(const SlowTimeDeskew& rhs) const - { - return (applied == rhs.applied && - slowTimeDeskewPhasePoly == rhs.slowTimeDeskewPhasePoly); - } - - bool operator!=(const SlowTimeDeskew& rhs) const - { - return !(*this == rhs); - } -}; - -/*! - * \struct PFA - * \brief SICD Polar format algorithm block - * - * Parameters used when the image is formed using the polar format - * algorithm (imageFormationAlgorithm = PFA). - * - * \note This is currently limited to a one item choice in SICD, - * which would make it hard to do anything else - */ -struct PFA -{ - //! Constructor, nothing defined - PFA(); - - /*! - * SICD FPN parameter. - * Focus plane normal (ECEF), pointing away from center of earth - */ - Vector3 focusPlaneNormal; - - /*! - * SICD IPN parameter. - * Image formation plane normal pointing away from center of earth - */ - Vector3 imagePlaneNormal; - - /*! - * SICD PolarAngRefTime (name change for API consistency) - * Polar image formation ref. time. Polar angle = 0 at the ref time - * Measured relative to collect start. Ref time is typically set - * to SCP COA time but may be different - */ - double polarAngleRefTime; - - /*! - * SICD PolarAngPoly (name change for API consistency) - * Poly that yields polar angle in radians as a function of slow time - * IOW, Time (sec) -> Polar angle (radians) - */ - Poly1D polarAnglePoly; - - /*! - * SICD SpatialFreqSFPoly parametr (name change for API consistency) - * Poly that yields the spatial frequency scale factor as a function - * of Polar angle - * Polar angle (radians) -> KSF - */ - Poly1D spatialFrequencyScaleFactorPoly; - - //! Minimum range spatial freq (Krg) output from polar->rect resampling - double krg1; - - //! Maximum range spatial freq (Krg) output from polar->rect resampling - double krg2; - - //! Minimum az spatial freq output from polar->rect resampling - double kaz1; - - //! Minimum az spatial freq output from polar->rect resampling - double kaz2; - - //! SICD STDeskew parameter - mem::ScopedCopyablePtr slowTimeDeskew; - - //! Equality operator - bool operator==(const PFA& rhs) const; - bool operator!=(const PFA& rhs) const - { - return !(*this == rhs); - } - - void fillDerivedFields(const Position& position); - void fillDefaultFields(const GeoData& geoData, const Grid&, - const SCPCOA& scpcoa); - - bool validate(const SCPCOA& scpcoa, logging::Logger& log); -}; - -} -} -#endif + +namespace six +{ +namespace sicd +{ +struct Grid; +/*! + * \struct SlowTimeDeskew + * \brief SICD STDeskew + * + * Parameters to describe image domain slow time + * deskew processing. Name changed for API consistency + */ +struct SlowTimeDeskew +{ + //! Constructor + SlowTimeDeskew(); + + //! Was slow time deskew phase function applied? + BooleanType applied; + + //! Slow time deskew phase function to perform the slow-time/Kaz + //! shift. 2D poly function of image range coord and az coord + Poly2D slowTimeDeskewPhasePoly; + + //! Equality operator + bool operator==(const SlowTimeDeskew& rhs) const + { + return (applied == rhs.applied && + slowTimeDeskewPhasePoly == rhs.slowTimeDeskewPhasePoly); + } + + bool operator!=(const SlowTimeDeskew& rhs) const + { + return !(*this == rhs); + } +}; + +/*! + * \struct PFA + * \brief SICD Polar format algorithm block + * + * Parameters used when the image is formed using the polar format + * algorithm (imageFormationAlgorithm = PFA). + * + * \note This is currently limited to a one item choice in SICD, + * which would make it hard to do anything else + */ +struct PFA +{ + //! Constructor, nothing defined + PFA(); + + /*! + * SICD FPN parameter. + * Focus plane normal (ECEF), pointing away from center of earth + */ + Vector3 focusPlaneNormal; + + /*! + * SICD IPN parameter. + * Image formation plane normal pointing away from center of earth + */ + Vector3 imagePlaneNormal; + + /*! + * SICD PolarAngRefTime (name change for API consistency) + * Polar image formation ref. time. Polar angle = 0 at the ref time + * Measured relative to collect start. Ref time is typically set + * to SCP COA time but may be different + */ + double polarAngleRefTime; + + /*! + * SICD PolarAngPoly (name change for API consistency) + * Poly that yields polar angle in radians as a function of slow time + * IOW, Time (sec) -> Polar angle (radians) + */ + Poly1D polarAnglePoly; + + /*! + * SICD SpatialFreqSFPoly parametr (name change for API consistency) + * Poly that yields the spatial frequency scale factor as a function + * of Polar angle + * Polar angle (radians) -> KSF + */ + Poly1D spatialFrequencyScaleFactorPoly; + + //! Minimum range spatial freq (Krg) output from polar->rect resampling + double krg1; + + //! Maximum range spatial freq (Krg) output from polar->rect resampling + double krg2; + + //! Minimum az spatial freq output from polar->rect resampling + double kaz1; + + //! Minimum az spatial freq output from polar->rect resampling + double kaz2; + + //! SICD STDeskew parameter + mem::ScopedCopyablePtr slowTimeDeskew; + + //! Equality operator + bool operator==(const PFA& rhs) const; + bool operator!=(const PFA& rhs) const + { + return !(*this == rhs); + } + + void fillDerivedFields(const Position& position); + void fillDefaultFields(const GeoData& geoData, const Grid&, + const SCPCOA& scpcoa); + + bool validate(const SCPCOA& scpcoa, logging::Logger& log); +}; + +} +} +#endif diff --git a/six/modules/c++/six.sicd/include/six/sicd/Position.h b/six/modules/c++/six.sicd/include/six/sicd/Position.h index 7b63c2e682..efb8c3e088 100644 --- a/six/modules/c++/six.sicd/include/six/sicd/Position.h +++ b/six/modules/c++/six.sicd/include/six/sicd/Position.h @@ -19,103 +19,103 @@ * see . * */ -#ifndef __SIX_POSITION_H__ -#define __SIX_POSITION_H__ +#ifndef __SIX_POSITION_H__ +#define __SIX_POSITION_H__ #include -#include -#include "six/Types.h" -#include "six/Init.h" -#include "six/Parameter.h" - -namespace six -{ -namespace sicd -{ -struct SCPCOA; - -/*! - * \struct RcvAPC - * \brief SICD RcvAPC - * - * Receive aperture phase center (APC). The size of the vector - * of the vector the number of receive APC polys - */ -struct RcvAPC -{ - //! Constructor - RcvAPC() - { - } - - std::vector rcvAPCPolys; - - //! Equality operator - bool operator==(const RcvAPC& rhs) const - { - return rcvAPCPolys == rhs.rcvAPCPolys; - } - - bool operator!=(const RcvAPC& rhs) const - { - return !(*this == rhs); - } -}; - -/*! - * \struct Position - * \brief SICD Position - * - * This block describes the platform and ground reference - * positions vs. time. - */ -struct Position -{ - /*! - * Aperture reference point as a function of time in ECEF meters - * t = 0 at collection start - */ - PolyXYZ arpPoly; - - /*! - * Ground reference point as a function of time in ECEF meters. - * t = 0 at collection start - */ - PolyXYZ grpPoly; - - /*! - * Transmit aperture phase center (APC) in ECEF as a function of time - * t = 0 at collection start. - * Always included for bistatic collections - */ - PolyXYZ txAPCPoly; - - /*! - * (Optional) Receive aperture phase center. - * - */ - mem::ScopedCopyablePtr rcvAPC; - - //! Constructor - Position(); - - //! Equality operator - bool operator==(const Position& rhs) const - { - return (arpPoly == rhs.arpPoly && grpPoly == rhs.grpPoly && - txAPCPoly == rhs.txAPCPoly && rcvAPC == rhs.rcvAPC); - } - - bool operator!=(const Position& rhs) const - { - return !(*this == rhs); - } - - void fillDerivedFields(const SCPCOA& scpcoa); - bool validate(logging::Logger& log) const; -}; - -} -} -#endif +#include +#include "six/Types.h" +#include "six/Init.h" +#include "six/Parameter.h" + +namespace six +{ +namespace sicd +{ +struct SCPCOA; + +/*! + * \struct RcvAPC + * \brief SICD RcvAPC + * + * Receive aperture phase center (APC). The size of the vector + * of the vector the number of receive APC polys + */ +struct RcvAPC +{ + //! Constructor + RcvAPC() + { + } + + std::vector rcvAPCPolys; + + //! Equality operator + bool operator==(const RcvAPC& rhs) const + { + return rcvAPCPolys == rhs.rcvAPCPolys; + } + + bool operator!=(const RcvAPC& rhs) const + { + return !(*this == rhs); + } +}; + +/*! + * \struct Position + * \brief SICD Position + * + * This block describes the platform and ground reference + * positions vs. time. + */ +struct Position +{ + /*! + * Aperture reference point as a function of time in ECEF meters + * t = 0 at collection start + */ + PolyXYZ arpPoly; + + /*! + * Ground reference point as a function of time in ECEF meters. + * t = 0 at collection start + */ + PolyXYZ grpPoly; + + /*! + * Transmit aperture phase center (APC) in ECEF as a function of time + * t = 0 at collection start. + * Always included for bistatic collections + */ + PolyXYZ txAPCPoly; + + /*! + * (Optional) Receive aperture phase center. + * + */ + mem::ScopedCopyablePtr rcvAPC; + + //! Constructor + Position(); + + //! Equality operator + bool operator==(const Position& rhs) const + { + return (arpPoly == rhs.arpPoly && grpPoly == rhs.grpPoly && + txAPCPoly == rhs.txAPCPoly && rcvAPC == rhs.rcvAPC); + } + + bool operator!=(const Position& rhs) const + { + return !(*this == rhs); + } + + void fillDerivedFields(const SCPCOA& scpcoa); + bool validate(logging::Logger& log) const; +}; + +} +} +#endif diff --git a/six/modules/c++/six.sicd/include/six/sicd/Timeline.h b/six/modules/c++/six.sicd/include/six/sicd/Timeline.h index 89e9cfdae7..fda8daffbc 100644 --- a/six/modules/c++/six.sicd/include/six/sicd/Timeline.h +++ b/six/modules/c++/six.sicd/include/six/sicd/Timeline.h @@ -19,121 +19,121 @@ * see . * */ -#ifndef __SIX_TIMELINE_H__ -#define __SIX_TIMELINE_H__ - -#include -#include "six/Types.h" -#include "six/Init.h" -#include "six/Parameter.h" - -namespace six -{ -namespace sicd -{ -/*! - * \class TimelineSet - * \brief SICD/Timeline/IPP/Set parameters - * - * Identifies a set of IPP parameters. Minimum of 1 set of - * parameters are required for IPP - */ -struct TimelineSet +#ifndef __SIX_TIMELINE_H__ +#define __SIX_TIMELINE_H__ + +#include +#include "six/Types.h" +#include "six/Init.h" +#include "six/Parameter.h" + +namespace six +{ +namespace sicd +{ +/*! + * \class TimelineSet + * \brief SICD/Timeline/IPP/Set parameters + * + * Identifies a set of IPP parameters. Minimum of 1 set of + * parameters are required for IPP + */ +struct TimelineSet { //! Constructor TimelineSet(); - - //! Start time for the period relative to collect start - double tStart; - - //! End time for the period relative to collect start - double tEnd; - - //! Starting ipp index for the period described - int interPulsePeriodStart; - - //! Ending ipp index for the period described - int interPulsePeriodEnd; - - /*! - * ipp index poly coefs yield IPP index as a function of time t - * Starting tStart to tEnd - */ - Poly1D interPulsePeriodPoly; - - //! Equality operators - bool operator==(const TimelineSet& rhs) const; - bool operator!=(const TimelineSet& rhs) const - { - return !(*this == rhs); - } -}; - -/*! - * \class InterPulsePeriod - * \brief SICD 'IPP' parameter - * Describes the interpulse period (IPP) parameters. This section - * of SICD is optional, and contains one or more Sets (TimelineSet) - */ -struct InterPulsePeriod -{ - /*! - * Constructor. - */ - InterPulsePeriod() - { - } - - //! Vector of TimelineSet objects - std::vector sets; - - //! Equality operators - bool operator==(const InterPulsePeriod& rhs) const - { - return sets == rhs.sets; - } - - bool operator!=(const InterPulsePeriod& rhs) const - { - return !(*this == rhs); - } -}; - -/*! - * \struct Timeline - * \brief SICD Timeline block - * - * Describes the imaging collection timeline. This is a required block, - * and it requires that collectStart and collectDuration are written (or - * read). The IPP parameter (referred to here as interPulsePeriod) is - * optional. - * - */ -struct Timeline + + //! Start time for the period relative to collect start + double tStart; + + //! End time for the period relative to collect start + double tEnd; + + //! Starting ipp index for the period described + int interPulsePeriodStart; + + //! Ending ipp index for the period described + int interPulsePeriodEnd; + + /*! + * ipp index poly coefs yield IPP index as a function of time t + * Starting tStart to tEnd + */ + Poly1D interPulsePeriodPoly; + + //! Equality operators + bool operator==(const TimelineSet& rhs) const; + bool operator!=(const TimelineSet& rhs) const + { + return !(*this == rhs); + } +}; + +/*! + * \class InterPulsePeriod + * \brief SICD 'IPP' parameter + * Describes the interpulse period (IPP) parameters. This section + * of SICD is optional, and contains one or more Sets (TimelineSet) + */ +struct InterPulsePeriod +{ + /*! + * Constructor. + */ + InterPulsePeriod() + { + } + + //! Vector of TimelineSet objects + std::vector sets; + + //! Equality operators + bool operator==(const InterPulsePeriod& rhs) const + { + return sets == rhs.sets; + } + + bool operator!=(const InterPulsePeriod& rhs) const + { + return !(*this == rhs); + } +}; + +/*! + * \struct Timeline + * \brief SICD Timeline block + * + * Describes the imaging collection timeline. This is a required block, + * and it requires that collectStart and collectDuration are written (or + * read). The IPP parameter (referred to here as interPulsePeriod) is + * optional. + * + */ +struct Timeline { //! Constructor Timeline(); - - //! Collection date/time UTC, measured from collection start - DateTime collectStart; - - //! Duration of collection period - double collectDuration; - - //! Optional IPP parameter description - mem::ScopedCopyablePtr interPulsePeriod; - - bool operator==(const Timeline& rhs) const - { - return (collectStart == rhs.collectStart && collectDuration == rhs.collectDuration && - interPulsePeriod == rhs.interPulsePeriod); - } - bool operator!=(const Timeline& rhs) const - { - return !(*this == rhs); - } -}; -} -} -#endif + + //! Collection date/time UTC, measured from collection start + DateTime collectStart; + + //! Duration of collection period + double collectDuration; + + //! Optional IPP parameter description + mem::ScopedCopyablePtr interPulsePeriod; + + bool operator==(const Timeline& rhs) const + { + return (collectStart == rhs.collectStart && collectDuration == rhs.collectDuration && + interPulsePeriod == rhs.interPulsePeriod); + } + bool operator!=(const Timeline& rhs) const + { + return !(*this == rhs); + } +}; +} +} +#endif diff --git a/six/modules/c++/six.sicd/six.sicd.vcxproj.filters b/six/modules/c++/six.sicd/six.sicd.vcxproj.filters index 3196090413..2517c17120 100644 --- a/six/modules/c++/six.sicd/six.sicd.vcxproj.filters +++ b/six/modules/c++/six.sicd/six.sicd.vcxproj.filters @@ -1,249 +1,249 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + \ No newline at end of file diff --git a/six/modules/c++/six.sicd/source/Grid.cpp b/six/modules/c++/six.sicd/source/Grid.cpp index fc4cf5bbc7..7c9ce29dfe 100644 --- a/six/modules/c++/six.sicd/source/Grid.cpp +++ b/six/modules/c++/six.sicd/source/Grid.cpp @@ -19,23 +19,23 @@ * see . * */ -#include "six/sicd/Grid.h" +#include "six/sicd/Grid.h" #include #include "six/sicd/GeoData.h" -#include "six/sicd/ImageData.h" -#include "six/sicd/PFA.h" -#include "six/sicd/SCPCOA.h" -#include "six/sicd/RadarCollection.h" -#include "six/sicd/RgAzComp.h" -#include "six/sicd/RMA.h" -#include "six/sicd/Utilities.h" +#include "six/sicd/ImageData.h" +#include "six/sicd/PFA.h" +#include "six/sicd/SCPCOA.h" +#include "six/sicd/RadarCollection.h" +#include "six/sicd/RgAzComp.h" +#include "six/sicd/RMA.h" +#include "six/sicd/Utilities.h" #include - -using namespace six; -using namespace six::sicd; - + +using namespace six; +using namespace six::sicd; + const double DirectionParameters::WGT_TOL = 1e-3; const size_t DirectionParameters::DEFAULT_WEIGHT_SIZE = 512; const char DirectionParameters::BOUNDS_ERROR_MESSAGE[] = @@ -47,448 +47,448 @@ const char Grid::WF_INCONSISTENT_STR[] = "Waveform fields not consistent"; const char Grid::BOUNDS_ERROR_MESSAGE[] = "Violation of spatial frequency extent bounds"; -WeightType::WeightType() -{ -} - -DirectionParameters::DirectionParameters() : - unitVector(Init::undefined()), - sampleSpacing(Init::undefined()), - impulseResponseWidth(Init::undefined()), - sign(Init::undefined()), - impulseResponseBandwidth(Init::undefined()), - kCenter(Init::undefined()), - deltaK1(Init::undefined()), - deltaK2(Init::undefined()), - deltaKCOAPoly(Init::undefined()) -{ -} - -DirectionParameters* DirectionParameters::clone() const -{ - return new DirectionParameters(*this); -} - -bool DirectionParameters::operator==(const DirectionParameters& rhs) const -{ - return (unitVector == rhs.unitVector && - sampleSpacing == rhs.sampleSpacing && - impulseResponseWidth == rhs.impulseResponseWidth && - sign == rhs.sign && - impulseResponseBandwidth == rhs.impulseResponseBandwidth && - kCenter == rhs.kCenter && - deltaK1 == rhs.deltaK1 && - deltaK2 == rhs.deltaK2 && - deltaKCOAPoly == rhs.deltaKCOAPoly && - weightType == rhs.weightType && - weights == rhs.weights); -} - -std::pair DirectionParameters::calculateDeltaKs( - const ImageData& imageData) const -{ - //Here, we assume the min and max of DeltaKCOAPoly must be - // on the vertices of the image, since it is smooth and monotonic in most cases-- - // although in actuality this is not always the case. To be totally generic, - // we would have to search for an interior min and max as well - double derivedDeltaK1 = 0; - double derivedDeltaK2 = 0; - - std::vector vertices = calculateImageVertices(imageData); - - if (!Init::isUndefined(deltaKCOAPoly)) - { - derivedDeltaK1 = std::numeric_limits::infinity(); - derivedDeltaK2 = -std::numeric_limits::infinity(); - - for (size_t ii = 0; ii < vertices.size(); ++ii) - { - double currentDeltaK = deltaKCOAPoly.atY( - static_cast(vertices[ii].col))( - static_cast(vertices[ii].row)); - derivedDeltaK1 = std::min(currentDeltaK, derivedDeltaK1); - derivedDeltaK2 = std::max(currentDeltaK, derivedDeltaK2); - } - } - - derivedDeltaK1 -= (impulseResponseBandwidth / 2); - derivedDeltaK2 += (impulseResponseBandwidth / 2); - - if (derivedDeltaK1 < -(1 / sampleSpacing) / 2 || - derivedDeltaK2 > (1 / sampleSpacing) / 2) - { - derivedDeltaK1 = -(1 / sampleSpacing) / 2; - derivedDeltaK2 = -derivedDeltaK1; - } - - return std::pair(derivedDeltaK1, derivedDeltaK2); -} - -std::unique_ptr -DirectionParameters::calculateWeightFunction() const -{ - if (weightType.get() == nullptr) - { - return nullptr; - } - - std::string windowName(weightType->windowName); - str::upper(windowName); - - if (windowName == "UNIFORM") - { - return std::make_unique(); - } - if (windowName == "HAMMING") - { - double coef = 0.0; - if (weightType->parameters.empty() || weightType->parameters[0].str().empty()) - { - //A Hamming window is defined in many places as a raised cosine of weight .54, - //so this is the default. However, some data use a generalized raised cosine and - //call it HAMMING, so we allow for both uses. - coef = .54; - } - else - { +WeightType::WeightType() +{ +} + +DirectionParameters::DirectionParameters() : + unitVector(Init::undefined()), + sampleSpacing(Init::undefined()), + impulseResponseWidth(Init::undefined()), + sign(Init::undefined()), + impulseResponseBandwidth(Init::undefined()), + kCenter(Init::undefined()), + deltaK1(Init::undefined()), + deltaK2(Init::undefined()), + deltaKCOAPoly(Init::undefined()) +{ +} + +DirectionParameters* DirectionParameters::clone() const +{ + return new DirectionParameters(*this); +} + +bool DirectionParameters::operator==(const DirectionParameters& rhs) const +{ + return (unitVector == rhs.unitVector && + sampleSpacing == rhs.sampleSpacing && + impulseResponseWidth == rhs.impulseResponseWidth && + sign == rhs.sign && + impulseResponseBandwidth == rhs.impulseResponseBandwidth && + kCenter == rhs.kCenter && + deltaK1 == rhs.deltaK1 && + deltaK2 == rhs.deltaK2 && + deltaKCOAPoly == rhs.deltaKCOAPoly && + weightType == rhs.weightType && + weights == rhs.weights); +} + +std::pair DirectionParameters::calculateDeltaKs( + const ImageData& imageData) const +{ + //Here, we assume the min and max of DeltaKCOAPoly must be + // on the vertices of the image, since it is smooth and monotonic in most cases-- + // although in actuality this is not always the case. To be totally generic, + // we would have to search for an interior min and max as well + double derivedDeltaK1 = 0; + double derivedDeltaK2 = 0; + + std::vector vertices = calculateImageVertices(imageData); + + if (!Init::isUndefined(deltaKCOAPoly)) + { + derivedDeltaK1 = std::numeric_limits::infinity(); + derivedDeltaK2 = -std::numeric_limits::infinity(); + + for (size_t ii = 0; ii < vertices.size(); ++ii) + { + double currentDeltaK = deltaKCOAPoly.atY( + static_cast(vertices[ii].col))( + static_cast(vertices[ii].row)); + derivedDeltaK1 = std::min(currentDeltaK, derivedDeltaK1); + derivedDeltaK2 = std::max(currentDeltaK, derivedDeltaK2); + } + } + + derivedDeltaK1 -= (impulseResponseBandwidth / 2); + derivedDeltaK2 += (impulseResponseBandwidth / 2); + + if (derivedDeltaK1 < -(1 / sampleSpacing) / 2 || + derivedDeltaK2 > (1 / sampleSpacing) / 2) + { + derivedDeltaK1 = -(1 / sampleSpacing) / 2; + derivedDeltaK2 = -derivedDeltaK1; + } + + return std::pair(derivedDeltaK1, derivedDeltaK2); +} + +std::unique_ptr +DirectionParameters::calculateWeightFunction() const +{ + if (weightType.get() == nullptr) + { + return nullptr; + } + + std::string windowName(weightType->windowName); + str::upper(windowName); + + if (windowName == "UNIFORM") + { + return std::make_unique(); + } + if (windowName == "HAMMING") + { + double coef = 0.0; + if (weightType->parameters.empty() || weightType->parameters[0].str().empty()) + { + //A Hamming window is defined in many places as a raised cosine of weight .54, + //so this is the default. However, some data use a generalized raised cosine and + //call it HAMMING, so we allow for both uses. + coef = .54; + } + else + { coef = weightType->parameters[0]; - } - - return std::make_unique(coef); - } - if (windowName == "HANNING") - { - return std::make_unique(0.50); - } - if (windowName == "KAISER") - { + } + + return std::make_unique(coef); + } + if (windowName == "HANNING") + { + return std::make_unique(0.50); + } + if (windowName == "KAISER") + { return std::make_unique(double(weightType->parameters[0])); - } - - return nullptr; -} - -std::vector -DirectionParameters::calculateImageVertices(const ImageData& imageData) const -{ - std::vector vertices; - + } + + return nullptr; +} + +std::vector +DirectionParameters::calculateImageVertices(const ImageData& imageData) const +{ + std::vector vertices; + if (!imageData.validData.empty()) - { - vertices = imageData.validData; - } - else - { - vertices.resize(4); - //use edges of full image - vertices[0] = RowColInt(0, 0); - vertices[1] = RowColInt(static_cast(imageData.numCols) - 1, 0); - vertices[2] = RowColInt(static_cast(imageData.numCols) - 1, static_cast(imageData.numCols) - 1); - vertices[3] = RowColInt(0, static_cast(imageData.numCols) - 1); - } - return vertices; -} - -void DirectionParameters::fillDerivedFields(const ImageData& imageData) -{ - // Calulating resolution requires fzero and fft functions - - // DeltaK1/2 are approximated from DeltaKCOAPoly - if (!Init::isUndefined(deltaKCOAPoly) && - !Init::isUndefined(impulseResponseBandwidth) && - !Init::isUndefined(sampleSpacing) && - Init::isUndefined(deltaK1) && - Init::isUndefined(deltaK2)) - { - // Here, we assume the min and max of DeltaKCOAPoly must be on the vertices - // of the image, since it is smooth and monotonic in most cases--although in - // actuality this is not always the case. To be totally generic, we would - // have to search for an interior min and max as well. - const std::pair deltas = calculateDeltaKs(imageData); - deltaK1 = deltas.first; - deltaK2 = deltas.second; - } - - if (weightType.get() != nullptr && - weights.empty() && - weightType->windowName != "UNKNOWN") - { - std::unique_ptr weightFunction = calculateWeightFunction(); - if (weightFunction.get()) - { - weights = (*weightFunction)(DEFAULT_WEIGHT_SIZE); - } - } - return; -} - -bool DirectionParameters::validate(const ImageData& imageData, - logging::Logger& log) const -{ - bool valid = true; - std::ostringstream messageBuilder; - constexpr auto epsilon = std::numeric_limits::epsilon(); - //2.3.1, 2.3.5 - if (deltaK2 <= deltaK1) - { - messageBuilder.str(""); - messageBuilder << BOUNDS_ERROR_MESSAGE << std::endl - << "SICD.Grid.Row/Col.DeltaK1: " << deltaK1 << std::endl - << "SICD.Grid.Row/Col.DetalK2: " << deltaK2 << std::endl; - log.error(messageBuilder.str()); - valid = false; - } - - else - { - // 2.3.2, 2.3.6 - if (deltaK2 > (1 / (2 * sampleSpacing)) + epsilon) - { - messageBuilder.str(""); - messageBuilder << BOUNDS_ERROR_MESSAGE << std::endl - << "0.5/SICD.Grid.Row/Col.SampleSpacing: " << - 0.5 / sampleSpacing << std::endl - << "SICD.Grid.Row/Col.DetalK2: " << deltaK2 << std::endl; - log.error(messageBuilder.str()); - valid = false; - } - - // 2.3.3, 2.3.7 - if (deltaK1 < (-1 / (2 * sampleSpacing)) - epsilon) - { - messageBuilder.str(""); - messageBuilder << BOUNDS_ERROR_MESSAGE << std::endl - << "0.5/SICD.Grid.Row/Col.SampleSpacing: " << - 0.5 / sampleSpacing << std::endl - << "SICD.Grid.Row/Col.DetalK1: " << deltaK1 << std::endl; - log.error(messageBuilder.str()); - valid = false; - } - - // 2.3.4, 2.3.8 - if (impulseResponseBandwidth > (deltaK2 - deltaK1) + epsilon) - { - messageBuilder.str(""); - messageBuilder << BOUNDS_ERROR_MESSAGE << std::endl - << "SICD.Grid.Row/Col.impulseResponseBandwidth: " << - impulseResponseBandwidth << std::endl - << "SICD.Grid.Row/Col.DeltaK2 - SICD.Grid.Row/COl.DeltaK1: " - << deltaK2 - deltaK1 << std::endl; - log.error(messageBuilder.str()); - valid = false; - } - } - - // 2.3.9. Compute our own DeltaK1/K2 and test for consistency with DelaKCOAPoly, - // ImpRespBW, and SS. - const auto deltas = calculateDeltaKs(imageData); - const double minDk = deltas.first; - const double maxDk = deltas.second; - - constexpr double DK_TOL = 1e-2; - - //2.3.9.1, 2.3.9.3 - if (std::abs((deltaK1 / minDk) - 1) > DK_TOL) - { - messageBuilder.str(""); - messageBuilder << BOUNDS_ERROR_MESSAGE << std::endl - << "SICD.Grid.Row/Col.DeltaK1: " << deltaK1 << std::endl - << "Derived DeltaK1: " << minDk << std::endl; - log.error(messageBuilder.str()); - valid = false; - } - //2.3.9.2, 2.3.9.4 - if (std::abs((deltaK2 / maxDk) - 1) > DK_TOL) - { - messageBuilder.str(""); - messageBuilder << BOUNDS_ERROR_MESSAGE << std::endl - << "SICD.Grid.Row/Col.DeltaK2: " << deltaK2 << std::endl - << "Derived DeltaK2: " << maxDk << std::endl; - log.error(messageBuilder.str()); - valid = false; - } - - // Check weight functions - std::unique_ptr weightFunction; - - if (weightType.get()) - { - weightFunction.reset(calculateWeightFunction().release()); - - if (weightFunction.get()) - { - if (!weights.empty()) - { + { + vertices = imageData.validData; + } + else + { + vertices.resize(4); + //use edges of full image + vertices[0] = RowColInt(0, 0); + vertices[1] = RowColInt(static_cast(imageData.numCols) - 1, 0); + vertices[2] = RowColInt(static_cast(imageData.numCols) - 1, static_cast(imageData.numCols) - 1); + vertices[3] = RowColInt(0, static_cast(imageData.numCols) - 1); + } + return vertices; +} + +void DirectionParameters::fillDerivedFields(const ImageData& imageData) +{ + // Calulating resolution requires fzero and fft functions + + // DeltaK1/2 are approximated from DeltaKCOAPoly + if (!Init::isUndefined(deltaKCOAPoly) && + !Init::isUndefined(impulseResponseBandwidth) && + !Init::isUndefined(sampleSpacing) && + Init::isUndefined(deltaK1) && + Init::isUndefined(deltaK2)) + { + // Here, we assume the min and max of DeltaKCOAPoly must be on the vertices + // of the image, since it is smooth and monotonic in most cases--although in + // actuality this is not always the case. To be totally generic, we would + // have to search for an interior min and max as well. + const std::pair deltas = calculateDeltaKs(imageData); + deltaK1 = deltas.first; + deltaK2 = deltas.second; + } + + if (weightType.get() != nullptr && + weights.empty() && + weightType->windowName != "UNKNOWN") + { + std::unique_ptr weightFunction = calculateWeightFunction(); + if (weightFunction.get()) + { + weights = (*weightFunction)(DEFAULT_WEIGHT_SIZE); + } + } + return; +} + +bool DirectionParameters::validate(const ImageData& imageData, + logging::Logger& log) const +{ + bool valid = true; + std::ostringstream messageBuilder; + constexpr auto epsilon = std::numeric_limits::epsilon(); + //2.3.1, 2.3.5 + if (deltaK2 <= deltaK1) + { + messageBuilder.str(""); + messageBuilder << BOUNDS_ERROR_MESSAGE << std::endl + << "SICD.Grid.Row/Col.DeltaK1: " << deltaK1 << std::endl + << "SICD.Grid.Row/Col.DetalK2: " << deltaK2 << std::endl; + log.error(messageBuilder.str()); + valid = false; + } + + else + { + // 2.3.2, 2.3.6 + if (deltaK2 > (1 / (2 * sampleSpacing)) + epsilon) + { + messageBuilder.str(""); + messageBuilder << BOUNDS_ERROR_MESSAGE << std::endl + << "0.5/SICD.Grid.Row/Col.SampleSpacing: " << + 0.5 / sampleSpacing << std::endl + << "SICD.Grid.Row/Col.DetalK2: " << deltaK2 << std::endl; + log.error(messageBuilder.str()); + valid = false; + } + + // 2.3.3, 2.3.7 + if (deltaK1 < (-1 / (2 * sampleSpacing)) - epsilon) + { + messageBuilder.str(""); + messageBuilder << BOUNDS_ERROR_MESSAGE << std::endl + << "0.5/SICD.Grid.Row/Col.SampleSpacing: " << + 0.5 / sampleSpacing << std::endl + << "SICD.Grid.Row/Col.DetalK1: " << deltaK1 << std::endl; + log.error(messageBuilder.str()); + valid = false; + } + + // 2.3.4, 2.3.8 + if (impulseResponseBandwidth > (deltaK2 - deltaK1) + epsilon) + { + messageBuilder.str(""); + messageBuilder << BOUNDS_ERROR_MESSAGE << std::endl + << "SICD.Grid.Row/Col.impulseResponseBandwidth: " << + impulseResponseBandwidth << std::endl + << "SICD.Grid.Row/Col.DeltaK2 - SICD.Grid.Row/COl.DeltaK1: " + << deltaK2 - deltaK1 << std::endl; + log.error(messageBuilder.str()); + valid = false; + } + } + + // 2.3.9. Compute our own DeltaK1/K2 and test for consistency with DelaKCOAPoly, + // ImpRespBW, and SS. + const auto deltas = calculateDeltaKs(imageData); + const double minDk = deltas.first; + const double maxDk = deltas.second; + + constexpr double DK_TOL = 1e-2; + + //2.3.9.1, 2.3.9.3 + if (std::abs((deltaK1 / minDk) - 1) > DK_TOL) + { + messageBuilder.str(""); + messageBuilder << BOUNDS_ERROR_MESSAGE << std::endl + << "SICD.Grid.Row/Col.DeltaK1: " << deltaK1 << std::endl + << "Derived DeltaK1: " << minDk << std::endl; + log.error(messageBuilder.str()); + valid = false; + } + //2.3.9.2, 2.3.9.4 + if (std::abs((deltaK2 / maxDk) - 1) > DK_TOL) + { + messageBuilder.str(""); + messageBuilder << BOUNDS_ERROR_MESSAGE << std::endl + << "SICD.Grid.Row/Col.DeltaK2: " << deltaK2 << std::endl + << "Derived DeltaK2: " << maxDk << std::endl; + log.error(messageBuilder.str()); + valid = false; + } + + // Check weight functions + std::unique_ptr weightFunction; + + if (weightType.get()) + { + weightFunction.reset(calculateWeightFunction().release()); + + if (weightFunction.get()) + { + if (!weights.empty()) + { valid = validateWeights(*weightFunction, log) && valid; - } - } - else - { - messageBuilder.str(""); - messageBuilder << "Unrecognized weighting description" << std::endl - << "WeightType.WindowName: " - << weightType->windowName << std::endl; - log.warn(messageBuilder.str()); - valid = false; - } - } - - // 2.4.3, 2.4.4 - if (weightType.get() && - weightType->windowName != "UNIFORM" && - weightType->windowName != "UNKNOWN" && - weights.empty()) - { - messageBuilder.str(""); - messageBuilder << "Non-uniform weighting, but no WgtFunct provided" - << std::endl << "WgtType.WindowName: " << weightType->windowName - << std::endl; - log.warn(messageBuilder.str()); - } - - return valid; -} - -bool DirectionParameters::validateWeights(const Functor& weightFunction, - logging::Logger& log) const -{ - bool consistentValues = true; - bool valid = true; - std::ostringstream messageBuilder; - - //Arg doesn't matter. Just checking for Uniform-type Functor - if (weightFunction(5).empty()) - { - const auto key = weights[0]; - for (size_t ii = 0; ii < weights.size(); ++ii) - { - if (key != weights[ii]) - { - consistentValues = false; - } - } - } - else - { - std::vector expectedWeights = weightFunction(weights.size()); - for (size_t ii = 0; ii < weights.size(); ++ii) - { - if (std::abs(expectedWeights[ii] - weights[ii]) > WGT_TOL) - { - consistentValues = false; - break; - } - } - } - - if (!consistentValues) - { - messageBuilder.str(""); - messageBuilder << "DirectionParameters weights values " - << "inconsistent with weightType" << std::endl - << "WeightType.WindowName: " - << weightType->windowName << std::endl; - log.warn(messageBuilder.str()); - valid = false; - } - - return valid; -} - -void DirectionParameters::fillDerivedFields(const RgAzComp& rgAzComp, - double offset) -{ - if (Init::isUndefined(kCenter)) - { - kCenter = derivedKCenter(rgAzComp, offset); - } - - if (Init::isUndefined(deltaKCOAPoly) && - !Init::isUndefined(kCenter)) - { - deltaKCOAPoly = derivedKcoaPoly(rgAzComp, offset); - } -} - -double DirectionParameters::derivedKCenter(const RgAzComp& /*rgAzComp*/, - double offset) const -{ - double derivedCenter = offset; - if (!Init::isUndefined(deltaKCOAPoly)) - { - derivedCenter -= deltaKCOAPoly[0][0]; - } - return derivedCenter; -} - -Poly2D DirectionParameters::derivedKcoaPoly(const RgAzComp& /*rgAzComp*/, - double offset) const -{ - // Create a Poly2D with one term - std::vector coefs(1, offset - kCenter); - return Poly2D(0, 0, coefs); -} - -bool DirectionParameters::validate(const RgAzComp& rgAzComp, - logging::Logger& log, - double offset) const -{ - bool valid = true; - std::ostringstream messageBuilder; - - // 2.12.1.8, 2.12.1.9 - if (std::abs(kCenter - derivedKCenter(rgAzComp, offset)) - > std::numeric_limits::epsilon()) - { - messageBuilder.str(""); - messageBuilder << "KCenter: " << kCenter << std::endl - << "DeltaKCOAPoly: " << deltaKCOAPoly[0][0]; - log.error(messageBuilder.str()); - valid = false; - } - - //2.12.1.10, 2.12.1.11 - if (!Init::isUndefined(deltaKCOAPoly) && deltaKCOAPoly.orderX() > 1) - { - messageBuilder.str(""); - messageBuilder << "DetlaKCOAPoly must be a single value for RGAZCOMP data"; - log.error(messageBuilder.str()); - valid = false; - } - return valid; -} - -Grid::Grid() : - // This is a good assumption, I think - imagePlane(ComplexImagePlaneType::SLANT), - // Not so sure about this one - type(ComplexImageGridType::RGAZIM), - row(new DirectionParameters()), - col(new DirectionParameters()) -{ -} - -Grid* Grid::clone() const -{ - return new Grid(*this); -} - -bool Grid::operator==(const Grid& rhs) const -{ - return (imagePlane == rhs.imagePlane && - type == rhs.type && - timeCOAPoly == rhs.timeCOAPoly && - row == rhs.row && col == rhs.col); -} - -bool Grid::validateTimeCOAPoly( - const CollectionInformation& collectionInformation, - logging::Logger& log) const -{ - const RadarModeType& mode = collectionInformation.radarMode; - - //2.1. Scalar TimeCOAPoly means SPOTLIGHT data - bool valid = true; + } + } + else + { + messageBuilder.str(""); + messageBuilder << "Unrecognized weighting description" << std::endl + << "WeightType.WindowName: " + << weightType->windowName << std::endl; + log.warn(messageBuilder.str()); + valid = false; + } + } + + // 2.4.3, 2.4.4 + if (weightType.get() && + weightType->windowName != "UNIFORM" && + weightType->windowName != "UNKNOWN" && + weights.empty()) + { + messageBuilder.str(""); + messageBuilder << "Non-uniform weighting, but no WgtFunct provided" + << std::endl << "WgtType.WindowName: " << weightType->windowName + << std::endl; + log.warn(messageBuilder.str()); + } + + return valid; +} + +bool DirectionParameters::validateWeights(const Functor& weightFunction, + logging::Logger& log) const +{ + bool consistentValues = true; + bool valid = true; + std::ostringstream messageBuilder; + + //Arg doesn't matter. Just checking for Uniform-type Functor + if (weightFunction(5).empty()) + { + const auto key = weights[0]; + for (size_t ii = 0; ii < weights.size(); ++ii) + { + if (key != weights[ii]) + { + consistentValues = false; + } + } + } + else + { + std::vector expectedWeights = weightFunction(weights.size()); + for (size_t ii = 0; ii < weights.size(); ++ii) + { + if (std::abs(expectedWeights[ii] - weights[ii]) > WGT_TOL) + { + consistentValues = false; + break; + } + } + } + + if (!consistentValues) + { + messageBuilder.str(""); + messageBuilder << "DirectionParameters weights values " + << "inconsistent with weightType" << std::endl + << "WeightType.WindowName: " + << weightType->windowName << std::endl; + log.warn(messageBuilder.str()); + valid = false; + } + + return valid; +} + +void DirectionParameters::fillDerivedFields(const RgAzComp& rgAzComp, + double offset) +{ + if (Init::isUndefined(kCenter)) + { + kCenter = derivedKCenter(rgAzComp, offset); + } + + if (Init::isUndefined(deltaKCOAPoly) && + !Init::isUndefined(kCenter)) + { + deltaKCOAPoly = derivedKcoaPoly(rgAzComp, offset); + } +} + +double DirectionParameters::derivedKCenter(const RgAzComp& /*rgAzComp*/, + double offset) const +{ + double derivedCenter = offset; + if (!Init::isUndefined(deltaKCOAPoly)) + { + derivedCenter -= deltaKCOAPoly[0][0]; + } + return derivedCenter; +} + +Poly2D DirectionParameters::derivedKcoaPoly(const RgAzComp& /*rgAzComp*/, + double offset) const +{ + // Create a Poly2D with one term + std::vector coefs(1, offset - kCenter); + return Poly2D(0, 0, coefs); +} + +bool DirectionParameters::validate(const RgAzComp& rgAzComp, + logging::Logger& log, + double offset) const +{ + bool valid = true; + std::ostringstream messageBuilder; + + // 2.12.1.8, 2.12.1.9 + if (std::abs(kCenter - derivedKCenter(rgAzComp, offset)) + > std::numeric_limits::epsilon()) + { + messageBuilder.str(""); + messageBuilder << "KCenter: " << kCenter << std::endl + << "DeltaKCOAPoly: " << deltaKCOAPoly[0][0]; + log.error(messageBuilder.str()); + valid = false; + } + + //2.12.1.10, 2.12.1.11 + if (!Init::isUndefined(deltaKCOAPoly) && deltaKCOAPoly.orderX() > 1) + { + messageBuilder.str(""); + messageBuilder << "DetlaKCOAPoly must be a single value for RGAZCOMP data"; + log.error(messageBuilder.str()); + valid = false; + } + return valid; +} + +Grid::Grid() : + // This is a good assumption, I think + imagePlane(ComplexImagePlaneType::SLANT), + // Not so sure about this one + type(ComplexImageGridType::RGAZIM), + row(new DirectionParameters()), + col(new DirectionParameters()) +{ +} + +Grid* Grid::clone() const +{ + return new Grid(*this); +} + +bool Grid::operator==(const Grid& rhs) const +{ + return (imagePlane == rhs.imagePlane && + type == rhs.type && + timeCOAPoly == rhs.timeCOAPoly && + row == rhs.row && col == rhs.col); +} + +bool Grid::validateTimeCOAPoly( + const CollectionInformation& collectionInformation, + logging::Logger& log) const +{ + const RadarModeType& mode = collectionInformation.radarMode; + + //2.1. Scalar TimeCOAPoly means SPOTLIGHT data + bool valid = true; if (timeCOAPoly.empty()) { log.error("No timeCOAPoly for Grid."); @@ -497,70 +497,70 @@ bool Grid::validateTimeCOAPoly( else { const auto isScalar = timeCOAPoly.isScalar(); - - if (mode == RadarModeType::SPOTLIGHT && !isScalar) - { - log.error("SPOTLIGHT data should only have scalar TimeCOAPoly."); - valid = false; - } - - if (mode != RadarModeType::SPOTLIGHT && isScalar) - { + + if (mode == RadarModeType::SPOTLIGHT && !isScalar) + { + log.error("SPOTLIGHT data should only have scalar TimeCOAPoly."); + valid = false; + } + + if (mode != RadarModeType::SPOTLIGHT && isScalar) + { log.warn("Non-SPOTLIGHT data will generally have more than one " - "nonzero term in TimeCOAPoly unless \"formed as spotlight\"."); - valid = false; - } - } - - return valid; -} - -bool Grid::validateFFTSigns(logging::Logger& log) const -{ - bool valid = true; - std::ostringstream messageBuilder; - - //2.2. FFT signs in both dimensions almost certainly have to be equal - if (row->sign != col->sign) - { - messageBuilder.str(""); - messageBuilder << - "FFT signs in row and column direction should be the same." << - std::endl << "Grid.Row.Sign: " << row->sign << std::endl - << "Grid.Col.Sign: " << col->sign << std::endl; - log.error(messageBuilder.str()); - valid = false; - } - return valid; -} - -bool Grid::validate(const CollectionInformation& collectionInformation, - const ImageData& imageData, - logging::Logger& log) const -{ - bool valid = validateTimeCOAPoly(collectionInformation, log);//2.1 - valid = validateFFTSigns(log) && valid; //2.2 + "nonzero term in TimeCOAPoly unless \"formed as spotlight\"."); + valid = false; + } + } + + return valid; +} + +bool Grid::validateFFTSigns(logging::Logger& log) const +{ + bool valid = true; + std::ostringstream messageBuilder; + + //2.2. FFT signs in both dimensions almost certainly have to be equal + if (row->sign != col->sign) + { + messageBuilder.str(""); + messageBuilder << + "FFT signs in row and column direction should be the same." << + std::endl << "Grid.Row.Sign: " << row->sign << std::endl + << "Grid.Col.Sign: " << col->sign << std::endl; + log.error(messageBuilder.str()); + valid = false; + } + return valid; +} + +bool Grid::validate(const CollectionInformation& collectionInformation, + const ImageData& imageData, + logging::Logger& log) const +{ + bool valid = validateTimeCOAPoly(collectionInformation, log);//2.1 + valid = validateFFTSigns(log) && valid; //2.2 valid = row->validate(imageData, log) && valid; //2.3.1 - 2.3.9 - valid = col->validate(imageData, log) && valid; + valid = col->validate(imageData, log) && valid; return valid; -} - -void Grid::fillDerivedFields( - const CollectionInformation& collectionInformation, - const ImageData& imageData, - const SCPCOA& scpcoa) -{ - if (!Init::isUndefined(scpcoa.scpTime) && - collectionInformation.radarMode == RadarModeType::SPOTLIGHT && - Init::isUndefined(timeCOAPoly)) - { - timeCOAPoly = Poly2D(0, 0); - timeCOAPoly[0][0] = scpcoa.scpTime; - } - - row->fillDerivedFields(imageData); - col->fillDerivedFields(imageData); -} +} + +void Grid::fillDerivedFields( + const CollectionInformation& collectionInformation, + const ImageData& imageData, + const SCPCOA& scpcoa) +{ + if (!Init::isUndefined(scpcoa.scpTime) && + collectionInformation.radarMode == RadarModeType::SPOTLIGHT && + Init::isUndefined(timeCOAPoly)) + { + timeCOAPoly = Poly2D(0, 0); + timeCOAPoly[0][0] = scpcoa.scpTime; + } + + row->fillDerivedFields(imageData); + col->fillDerivedFields(imageData); +} void Grid::fillDerivedFields(const RMA& rma, const Vector3& scp, const PolyXYZ& arpPoly) @@ -580,48 +580,48 @@ void Grid::fillDerivedFields(const RMA& rma, const Vector3& scp, } void Grid::fillDerivedFields(const RMAT& rmat, const Vector3& scp) -{ - // Row/Col.UnitVector and Derived fields - if (Init::isUndefined(row->unitVector) && - Init::isUndefined(col->unitVector)) - { - row->unitVector = derivedRowUnitVector(rmat, scp); - col->unitVector = derivedColUnitVector(rmat, scp); +{ + // Row/Col.UnitVector and Derived fields + if (Init::isUndefined(row->unitVector) && + Init::isUndefined(col->unitVector)) + { + row->unitVector = derivedRowUnitVector(rmat, scp); + col->unitVector = derivedColUnitVector(rmat, scp); } } void Grid::fillDerivedFields(const RMCR& rmcr, const Vector3& scp) -{ - // Row/Col.UnitVector and Derived fields - if (Init::isUndefined(row->unitVector) && - Init::isUndefined(col->unitVector)) - { - row->unitVector = derivedRowUnitVector(rmcr, scp); - col->unitVector = derivedColUnitVector(rmcr, scp); +{ + // Row/Col.UnitVector and Derived fields + if (Init::isUndefined(row->unitVector) && + Init::isUndefined(col->unitVector)) + { + row->unitVector = derivedRowUnitVector(rmcr, scp); + col->unitVector = derivedColUnitVector(rmcr, scp); } } void Grid::fillDerivedFields(const INCA& inca, const Vector3& scp, const PolyXYZ& arpPoly) { - if (!Init::isUndefined(inca.timeCAPoly) && - !Init::isUndefined(arpPoly) && - Init::isUndefined(row->unitVector) && - Init::isUndefined(col->unitVector)) - { - row->unitVector = derivedRowUnitVector(inca, scp, arpPoly); - col->unitVector = derivedColUnitVector(inca, scp, arpPoly); + if (!Init::isUndefined(inca.timeCAPoly) && + !Init::isUndefined(arpPoly) && + Init::isUndefined(row->unitVector) && + Init::isUndefined(col->unitVector)) + { + row->unitVector = derivedRowUnitVector(inca, scp, arpPoly); + col->unitVector = derivedColUnitVector(inca, scp, arpPoly); } - if (Init::isUndefined(col->kCenter)) - { - col->kCenter = 0; + if (Init::isUndefined(col->kCenter)) + { + col->kCenter = 0; } - if (!Init::isUndefined(inca.freqZero) && - Init::isUndefined(row->kCenter)) - { - row->kCenter = derivedRowKCenter(inca); + if (!Init::isUndefined(inca.freqZero) && + Init::isUndefined(row->kCenter)) + { + row->kCenter = derivedRowKCenter(inca); } } @@ -632,21 +632,21 @@ void Grid::fillDerivedFields(const RgAzComp& rgAzComp, { const Vector3& scp = geoData.scp.ecf; - if (imagePlane == ComplexImagePlaneType::NOT_SET) - { - imagePlane = ComplexImagePlaneType::SLANT; - } - if (type == ComplexImageGridType::NOT_SET) - { - type = ComplexImageGridType::RGAZIM; - } - - if (Init::isUndefined(row->unitVector)) - { - row->unitVector = derivedRowUnitVector(scpcoa, scp); - } - if (Init::isUndefined(col->unitVector)) - { + if (imagePlane == ComplexImagePlaneType::NOT_SET) + { + imagePlane = ComplexImagePlaneType::SLANT; + } + if (type == ComplexImageGridType::NOT_SET) + { + type = ComplexImageGridType::RGAZIM; + } + + if (Init::isUndefined(row->unitVector)) + { + row->unitVector = derivedRowUnitVector(scpcoa, scp); + } + if (Init::isUndefined(col->unitVector)) + { col->unitVector = derivedColUnitVector(scpcoa, scp); } if (!Init::isUndefined(fc)) @@ -697,16 +697,16 @@ void Grid::fillDefaultFields(const RMA& rma, double fc) void Grid::fillDefaultFields(const RMAT& rmat, double fc) { - if (!Init::isUndefined(fc)) - { - if (Init::isUndefined(row->kCenter)) - { - row->kCenter = derivedRowKCenter(rmat, fc); - } - - if (Init::isUndefined(col->kCenter)) - { - col->kCenter = derivedColKCenter(rmat, fc); + if (!Init::isUndefined(fc)) + { + if (Init::isUndefined(row->kCenter)) + { + row->kCenter = derivedRowKCenter(rmat, fc); + } + + if (Init::isUndefined(col->kCenter)) + { + col->kCenter = derivedColKCenter(rmat, fc); } } } @@ -759,47 +759,47 @@ Vector3 Grid::derivedColUnitVector(const INCA& inca, const Vector3& scp, void Grid::fillDefaultFields(const RMCR& rmcr, double fc) { - if (!Init::isUndefined(fc)) - { - if (Init::isUndefined(row->kCenter)) - { - row->kCenter = derivedRowKCenter(rmcr, fc); - } - if (Init::isUndefined(col->kCenter)) - { - col->kCenter = 0; - } + if (!Init::isUndefined(fc)) + { + if (Init::isUndefined(row->kCenter)) + { + row->kCenter = derivedRowKCenter(rmcr, fc); + } + if (Init::isUndefined(col->kCenter)) + { + col->kCenter = 0; + } } } void Grid::fillDefaultFields(const PFA& pfa, double fc) { - if (type == ComplexImageGridType::NOT_SET) - { - type = ComplexImageGridType::RGAZIM; - } - - if (Init::isUndefined(col->kCenter)) - { - col->kCenter = 0; - } - if (Init::isUndefined(row->kCenter)) - { - if (!Init::isUndefined(pfa.krg1) && - !Init::isUndefined(pfa.krg2)) - { - // Default: the most reasonable way to compute this - row->kCenter = (pfa.krg1 + pfa.krg2) / 2; - } - else if (!Init::isUndefined(fc)) - { - // Approximation: this may not be quite right, due to - // rectangular inscription loss in PFA, but it should - // be close. - row->kCenter = fc * - (2 / math::Constants::SPEED_OF_LIGHT_METERS_PER_SEC) * - pfa.spatialFrequencyScaleFactorPoly[0]; - } + if (type == ComplexImageGridType::NOT_SET) + { + type = ComplexImageGridType::RGAZIM; + } + + if (Init::isUndefined(col->kCenter)) + { + col->kCenter = 0; + } + if (Init::isUndefined(row->kCenter)) + { + if (!Init::isUndefined(pfa.krg1) && + !Init::isUndefined(pfa.krg2)) + { + // Default: the most reasonable way to compute this + row->kCenter = (pfa.krg1 + pfa.krg2) / 2; + } + else if (!Init::isUndefined(fc)) + { + // Approximation: this may not be quite right, due to + // rectangular inscription loss in PFA, but it should + // be close. + row->kCenter = fc * + (2 / math::Constants::SPEED_OF_LIGHT_METERS_PER_SEC) * + pfa.spatialFrequencyScaleFactorPoly[0]; + } } } @@ -811,9 +811,9 @@ bool Grid::validate(const RMA& rma, const Vector3& scp, // 2.12.3.2.1, 2.12.3.4.1 if (type != defaultGridType(rma)) { - std::ostringstream messageBuilder; - messageBuilder << "Given image formation algorithm expects " - << defaultGridType(rma) << ".\nFound " << type; + std::ostringstream messageBuilder; + messageBuilder << "Given image formation algorithm expects " + << defaultGridType(rma) << ".\nFound " << type; log.error(messageBuilder.str()); valid = false; } @@ -842,49 +842,49 @@ bool Grid::validate(const RMAT& rmat, const Vector3& scp, std::ostringstream messageBuilder; bool valid = true; - // 2.12.3.2.3 - if ((row->unitVector - derivedRowUnitVector(rmat, scp)).norm() > UVECT_TOL) - { - messageBuilder.str(""); - messageBuilder << "UVect fields inconsistent." << std::endl + // 2.12.3.2.3 + if ((row->unitVector - derivedRowUnitVector(rmat, scp)).norm() > UVECT_TOL) + { + messageBuilder.str(""); + messageBuilder << "UVect fields inconsistent." << std::endl << "Grid.Row.UVectECF: " << row->unitVector << std::endl - << "Derived grid.Row.UVectECT: " - << derivedRowUnitVector(rmat, scp); - log.error(messageBuilder.str()); - valid = false; + << "Derived grid.Row.UVectECT: " + << derivedRowUnitVector(rmat, scp); + log.error(messageBuilder.str()); + valid = false; } - // 2.12.3.2.4 - if ((col->unitVector - derivedColUnitVector(rmat, scp)).norm() > UVECT_TOL) - { - messageBuilder.str(""); - messageBuilder << "UVect fields inconsistent." << std::endl + // 2.12.3.2.4 + if ((col->unitVector - derivedColUnitVector(rmat, scp)).norm() > UVECT_TOL) + { + messageBuilder.str(""); + messageBuilder << "UVect fields inconsistent." << std::endl << "Grid.Col.UVectECF: " << col->unitVector << std::endl - << "Derived Grid.Col.UVectECF: " - << derivedColUnitVector(rmat, scp); - log.error(messageBuilder.str()); - valid = false; - } - - // 2.12.3.2.6 - if (std::abs((derivedRowKCenter(rmat, fc) / row->kCenter) - 1) > WF_TOL) - { - messageBuilder.str(""); - messageBuilder << WF_INCONSISTENT_STR - << "Grid.Row.KCtr: " << row->kCenter << std::endl - << "Derived KCtr: " << derivedRowKCenter(rmat, fc); - log.warn(messageBuilder.str()); + << "Derived Grid.Col.UVectECF: " + << derivedColUnitVector(rmat, scp); + log.error(messageBuilder.str()); + valid = false; + } + + // 2.12.3.2.6 + if (std::abs((derivedRowKCenter(rmat, fc) / row->kCenter) - 1) > WF_TOL) + { + messageBuilder.str(""); + messageBuilder << WF_INCONSISTENT_STR + << "Grid.Row.KCtr: " << row->kCenter << std::endl + << "Derived KCtr: " << derivedRowKCenter(rmat, fc); + log.warn(messageBuilder.str()); valid = false; } //2.12.3.2.7 - if (std::abs((derivedColKCenter(rmat, fc) / col->kCenter) - 1) > WF_TOL) - { - messageBuilder.str(""); - messageBuilder << WF_INCONSISTENT_STR - << "Grid.Col.KCtr: " << col->kCenter << std::endl - << "Derived KCtr: " << derivedColKCenter(rmat, fc); - log.warn(messageBuilder.str()); + if (std::abs((derivedColKCenter(rmat, fc) / col->kCenter) - 1) > WF_TOL) + { + messageBuilder.str(""); + messageBuilder << WF_INCONSISTENT_STR + << "Grid.Col.KCtr: " << col->kCenter << std::endl + << "Derived KCtr: " << derivedColKCenter(rmat, fc); + log.warn(messageBuilder.str()); valid = false; } @@ -897,52 +897,52 @@ bool Grid::validate(const RMCR& rmcr, const Vector3& scp, bool valid = true; std::ostringstream messageBuilder; - //2.12.3.3.3 - if ((row->unitVector - derivedRowUnitVector(rmcr, scp)).norm() > UVECT_TOL) - { - messageBuilder.str(""); - messageBuilder << "UVect fields inconsistent." << std::endl - << "Grid.Row.UVectECF: " << row->unitVector << std::endl - << "Derived Grid.Row.UVectECF: " - << derivedRowUnitVector(rmcr, scp); - log.error(messageBuilder.str()); - valid = false; - } - - // 2.12.3.3.4 - if ((col->unitVector - derivedColUnitVector(rmcr, scp)).norm() > UVECT_TOL) - { - messageBuilder.str(""); - messageBuilder << "UVect fields inconsistent." << std::endl - << "Grid.Col.UVectECF: " << col->unitVector << std::endl - << "Derived Grid.Col.UVectECF: " + //2.12.3.3.3 + if ((row->unitVector - derivedRowUnitVector(rmcr, scp)).norm() > UVECT_TOL) + { + messageBuilder.str(""); + messageBuilder << "UVect fields inconsistent." << std::endl + << "Grid.Row.UVectECF: " << row->unitVector << std::endl + << "Derived Grid.Row.UVectECF: " + << derivedRowUnitVector(rmcr, scp); + log.error(messageBuilder.str()); + valid = false; + } + + // 2.12.3.3.4 + if ((col->unitVector - derivedColUnitVector(rmcr, scp)).norm() > UVECT_TOL) + { + messageBuilder.str(""); + messageBuilder << "UVect fields inconsistent." << std::endl + << "Grid.Col.UVectECF: " << col->unitVector << std::endl + << "Derived Grid.Col.UVectECF: " << derivedColUnitVector(rmcr, scp); - log.error(messageBuilder.str()); - valid = false; - } - - // 2.12.3.3.6 - if (col->kCenter != 0) - { - messageBuilder.str(""); - messageBuilder << "Grid.Col.KCtr must be zero for RMA/RMCR data." - << std::endl << "Grid.Col.KCtr = " << col->kCenter; - log.error(messageBuilder.str()); - valid = false; - } - - // 2.12.3.3.7 - if (!Init::isUndefined(fc)) - { - if (std::abs(row->kCenter / derivedRowKCenter(rmcr, fc) - 1) > WF_TOL) - { - messageBuilder.str(""); - messageBuilder << WF_INCONSISTENT_STR << std::endl - << "Grid.Row.KCtr: " << row->kCenter << std::endl - << "Center frequency * 2/c: " << derivedRowKCenter(rmcr, fc); - log.warn(messageBuilder.str()); - valid = false; - } + log.error(messageBuilder.str()); + valid = false; + } + + // 2.12.3.3.6 + if (col->kCenter != 0) + { + messageBuilder.str(""); + messageBuilder << "Grid.Col.KCtr must be zero for RMA/RMCR data." + << std::endl << "Grid.Col.KCtr = " << col->kCenter; + log.error(messageBuilder.str()); + valid = false; + } + + // 2.12.3.3.7 + if (!Init::isUndefined(fc)) + { + if (std::abs(row->kCenter / derivedRowKCenter(rmcr, fc) - 1) > WF_TOL) + { + messageBuilder.str(""); + messageBuilder << WF_INCONSISTENT_STR << std::endl + << "Grid.Row.KCtr: " << row->kCenter << std::endl + << "Center frequency * 2/c: " << derivedRowKCenter(rmcr, fc); + log.warn(messageBuilder.str()); + valid = false; + } } return valid; @@ -964,7 +964,7 @@ bool Grid::validate(const INCA& inca, const Vector3& scp, if (!Init::isUndefined(inca.dopplerCentroidPoly) && inca.dopplerCentroidCOA == BooleanType::IS_TRUE) { - const Poly2D& kcoaPoly = col->deltaKCOAPoly; + const Poly2D& kcoaPoly = col->deltaKCOAPoly; const Poly2D& centroidPoly = inca.dopplerCentroidPoly; if (kcoaPoly.orderX() != centroidPoly.orderX() && @@ -990,14 +990,14 @@ bool Grid::validate(const INCA& inca, const Vector3& scp, } norm = std::sqrt(norm); - if(norm > IFP_POLY_TOL) - { - messageBuilder.str(""); - messageBuilder << "RMA.INCA fields inconsistent." << std::endl - << "Compare Grid.Col.KCOAPoly to RMA.INCA.DopCentroidPoly " - << "* RMA.INCA.TimeCAPoly[1]."; - log.error(messageBuilder.str()); - valid = false; + if(norm > IFP_POLY_TOL) + { + messageBuilder.str(""); + messageBuilder << "RMA.INCA fields inconsistent." << std::endl + << "Compare Grid.Col.KCOAPoly to RMA.INCA.DopCentroidPoly " + << "* RMA.INCA.TimeCAPoly[1]."; + log.error(messageBuilder.str()); + valid = false; } } } @@ -1006,50 +1006,50 @@ bool Grid::validate(const INCA& inca, const Vector3& scp, if ((row->unitVector - derivedRowUnitVector(inca, scp, arpPoly)).norm() > UVECT_TOL) { - messageBuilder.str(""); - messageBuilder << "UVectFields inconsistent" << std::endl + messageBuilder.str(""); + messageBuilder << "UVectFields inconsistent" << std::endl << "Grid.Row.UVectECF: " << row->unitVector << std::endl - << "Derived Grid.Row.UVectECF: " - << derivedRowUnitVector(inca, scp, arpPoly); - log.error(messageBuilder.str()); + << "Derived Grid.Row.UVectECF: " + << derivedRowUnitVector(inca, scp, arpPoly); + log.error(messageBuilder.str()); valid = false; } - // 2.12.3.4.7 - if ((col->unitVector - - derivedRowUnitVector(inca, scp, arpPoly)).norm() > UVECT_TOL) - { - messageBuilder.str(""); - messageBuilder << "UVectFields inconsistent" << std::endl + // 2.12.3.4.7 + if ((col->unitVector - + derivedRowUnitVector(inca, scp, arpPoly)).norm() > UVECT_TOL) + { + messageBuilder.str(""); + messageBuilder << "UVectFields inconsistent" << std::endl << "Grid.Col.UVectECF: " << col->unitVector << std::endl - << "Derived Grid.Col.UVectECF: " - << derivedRowUnitVector(inca, scp, arpPoly); - log.error(messageBuilder.str()); - valid = false; - } - - // 2.12.3.4.8 - if (col->kCenter != 0) - { - messageBuilder.str(""); - messageBuilder << "Grid.Col.KCtr must be zero " - << "for RMA/INCA data." << std::endl - << "Grid.Col.KCtr: " << col->kCenter; - log.error(messageBuilder.str()); - valid = false; - } - - // 2.12.3.4.11 - if (Init::isUndefined(fc) && - std::abs(row->kCenter - derivedRowKCenter(inca)) > - std::numeric_limits::epsilon()) - { - messageBuilder.str(""); - messageBuilder << WF_INCONSISTENT_STR << std::endl + << "Derived Grid.Col.UVectECF: " + << derivedRowUnitVector(inca, scp, arpPoly); + log.error(messageBuilder.str()); + valid = false; + } + + // 2.12.3.4.8 + if (col->kCenter != 0) + { + messageBuilder.str(""); + messageBuilder << "Grid.Col.KCtr must be zero " + << "for RMA/INCA data." << std::endl + << "Grid.Col.KCtr: " << col->kCenter; + log.error(messageBuilder.str()); + valid = false; + } + + // 2.12.3.4.11 + if (Init::isUndefined(fc) && + std::abs(row->kCenter - derivedRowKCenter(inca)) > + std::numeric_limits::epsilon()) + { + messageBuilder.str(""); + messageBuilder << WF_INCONSISTENT_STR << std::endl << "RMA.INCA.FreqZero * 2 / c: " << derivedRowKCenter(inca) - << std::endl << "Grid.Row.KCenter: " << row->kCenter; - log.error(messageBuilder.str()); - valid = false; + << std::endl << "Grid.Row.KCenter: " << row->kCenter; + log.error(messageBuilder.str()); + valid = false; } return valid; } @@ -1061,138 +1061,138 @@ bool Grid::validate(const PFA& pfa, const RadarCollection& radarCollection, std::ostringstream messageBuilder; const double& epsilon = std::numeric_limits::epsilon(); - //2.12.2.1 - if (type != ComplexImageGridType::RGAZIM) - { - messageBuilder.str(""); - messageBuilder << "PFA image formation should result in a RGAZIM grid." - << std::endl << "Grid.Type: " << type; - log.error(messageBuilder.str()); - valid = false; - } - - // Make sure Row.kCtr is consistent with processed RF frequency bandwidth - if (Init::isUndefined(radarCollection.refFrequencyIndex) && - !Init::isUndefined(fc)) - { - // PFA.SpatialFreqSFPoly affects Row.KCtr - const auto kapCtr = fc * pfa.spatialFrequencyScaleFactorPoly[0] * - 2 / math::Constants::SPEED_OF_LIGHT_METERS_PER_SEC; - - // PFA inscription could cause kapCtr and Row.KCtr - // to be somewhat different - const auto theta = std::atan((col->impulseResponseBandwidth / 2) / - row->kCenter); - double kCtrTol = 1 - std::cos(theta); - kCtrTol = std::max(0.01, kCtrTol); - - if (std::abs(row->kCenter / kapCtr - 1) > kCtrTol) - { - messageBuilder.str(""); - messageBuilder << WF_INCONSISTENT_STR - << "Grid.Row.KCtr: " << row->kCenter << std::endl - << "Derived KapCtr: " << kapCtr; - log.error(messageBuilder.str()); - valid = false; - } - } - - //Slow-time deskew would allow for PFA.Kaz2-PFA.Kaz1>(1/Grid.Col.SS), - //since Kaz bandwidth is compressed from original polar annulus. + //2.12.2.1 + if (type != ComplexImageGridType::RGAZIM) + { + messageBuilder.str(""); + messageBuilder << "PFA image formation should result in a RGAZIM grid." + << std::endl << "Grid.Type: " << type; + log.error(messageBuilder.str()); + valid = false; + } + + // Make sure Row.kCtr is consistent with processed RF frequency bandwidth + if (Init::isUndefined(radarCollection.refFrequencyIndex) && + !Init::isUndefined(fc)) + { + // PFA.SpatialFreqSFPoly affects Row.KCtr + const auto kapCtr = fc * pfa.spatialFrequencyScaleFactorPoly[0] * + 2 / math::Constants::SPEED_OF_LIGHT_METERS_PER_SEC; + + // PFA inscription could cause kapCtr and Row.KCtr + // to be somewhat different + const auto theta = std::atan((col->impulseResponseBandwidth / 2) / + row->kCenter); + double kCtrTol = 1 - std::cos(theta); + kCtrTol = std::max(0.01, kCtrTol); + + if (std::abs(row->kCenter / kapCtr - 1) > kCtrTol) + { + messageBuilder.str(""); + messageBuilder << WF_INCONSISTENT_STR + << "Grid.Row.KCtr: " << row->kCenter << std::endl + << "Derived KapCtr: " << kapCtr; + log.error(messageBuilder.str()); + valid = false; + } + } + + //Slow-time deskew would allow for PFA.Kaz2-PFA.Kaz1>(1/Grid.Col.SS), + //since Kaz bandwidth is compressed from original polar annulus. if (pfa.slowTimeDeskew.get() != nullptr && - pfa.slowTimeDeskew->applied != BooleanType::IS_TRUE) - { - //2.3.10 - if ((pfa.kaz2 - col->kCenter) > - (1 / (2 * col->sampleSpacing)) + epsilon) - { - messageBuilder.str(""); - messageBuilder << BOUNDS_ERROR_MESSAGE << std::endl - << "0.5/SICD.Grid.Col.SampleSpacing: " - << 0.5 / col->sampleSpacing << std::endl - << "PFA.Kaz2 - Grid.Col.KCenter: " - << pfa.kaz2 - col->kCenter << std::endl; - log.error(messageBuilder.str()); - valid = false; - } - //2.3.11 - if ((pfa.kaz1 - col->kCenter) < - (-1 / (2 * col->sampleSpacing)) - epsilon) - { - messageBuilder.str(""); - messageBuilder << BOUNDS_ERROR_MESSAGE << std::endl - << "0.5/SICD.Grid.Col.SampleSpacing: " - << 0.5 / col->sampleSpacing << std::endl - << "PFA.Kaz1 - Grid.Col.KCenter: " - << pfa.kaz1 - col->kCenter << std::endl; - log.error(messageBuilder.str()); - valid = false; - } - } - - //2.3.12 - if ((pfa.krg2 - row->kCenter) > - (1 / (2 * row->sampleSpacing)) + epsilon) - { - messageBuilder.str(""); - messageBuilder << BOUNDS_ERROR_MESSAGE << std::endl - << "0.5/SICD.Grid.Row.SampleSpacing: " - << 0.5 / row->sampleSpacing << std::endl - << "PFA.Krg2 - Grid.Row.KCenter: " - << pfa.krg2 - row->kCenter << std::endl; - log.error(messageBuilder.str()); - valid = false; - } - - //2.3.13 - if (pfa.krg1 - row->kCenter < - (-1 / (2 * row->sampleSpacing)) - epsilon) - { - messageBuilder.str(""); - messageBuilder << BOUNDS_ERROR_MESSAGE << std::endl - << "0.5/SICD.Grid.Row.SampleSpacing: " - << 0.5 / row->sampleSpacing << std::endl - << "PFA.Krg1 - Grid.Row.KCenter: " - << pfa.krg1 - row->kCenter << std::endl; - log.error(messageBuilder.str()); - valid = false; - } - - //2.3.14 - if (col->impulseResponseBandwidth > pfa.kaz2 - pfa.kaz1 + epsilon) - { - messageBuilder.str(""); - messageBuilder << BOUNDS_ERROR_MESSAGE << std::endl - << "Grid.Col.ImpulseResponseBandwidth: " - << col->impulseResponseBandwidth << std::endl - << "SICD.PFA.Kaz2 - SICD.PFA.Kaz1: " - << pfa.kaz2 - pfa.kaz1 << std::endl; - log.error(messageBuilder.str()); - valid = false; - } - //2.3.15 - if (row->impulseResponseBandwidth > pfa.krg2 - pfa.krg1 + epsilon) - { - messageBuilder.str(""); - messageBuilder << BOUNDS_ERROR_MESSAGE << std::endl - << "Grid.Row.ImpulseResponseBandwidth: " - << row->impulseResponseBandwidth << std::endl - << "SICD.PFA.Krg2 - SICD.PFA.Krg1: " - << pfa.krg2 - pfa.krg1 << std::endl; - log.error(messageBuilder.str()); - valid = false; - } - //2.3.16 - if (col->kCenter != 0 && - std::abs(col->kCenter - (pfa.kaz1 + pfa.kaz2) / 2) > 1e-5) - { - messageBuilder.str(""); - messageBuilder << BOUNDS_ERROR_MESSAGE << std::endl - << "Grid.Col.KCenter: " << col->kCenter << std::endl - << "mean(SICD.PFA.Kaz1, SICD.PFA.Kaz2): " - << (pfa.kaz1 + pfa.kaz2) / 2 << std::endl; - log.error(messageBuilder.str()); - valid = false; + pfa.slowTimeDeskew->applied != BooleanType::IS_TRUE) + { + //2.3.10 + if ((pfa.kaz2 - col->kCenter) > + (1 / (2 * col->sampleSpacing)) + epsilon) + { + messageBuilder.str(""); + messageBuilder << BOUNDS_ERROR_MESSAGE << std::endl + << "0.5/SICD.Grid.Col.SampleSpacing: " + << 0.5 / col->sampleSpacing << std::endl + << "PFA.Kaz2 - Grid.Col.KCenter: " + << pfa.kaz2 - col->kCenter << std::endl; + log.error(messageBuilder.str()); + valid = false; + } + //2.3.11 + if ((pfa.kaz1 - col->kCenter) < + (-1 / (2 * col->sampleSpacing)) - epsilon) + { + messageBuilder.str(""); + messageBuilder << BOUNDS_ERROR_MESSAGE << std::endl + << "0.5/SICD.Grid.Col.SampleSpacing: " + << 0.5 / col->sampleSpacing << std::endl + << "PFA.Kaz1 - Grid.Col.KCenter: " + << pfa.kaz1 - col->kCenter << std::endl; + log.error(messageBuilder.str()); + valid = false; + } + } + + //2.3.12 + if ((pfa.krg2 - row->kCenter) > + (1 / (2 * row->sampleSpacing)) + epsilon) + { + messageBuilder.str(""); + messageBuilder << BOUNDS_ERROR_MESSAGE << std::endl + << "0.5/SICD.Grid.Row.SampleSpacing: " + << 0.5 / row->sampleSpacing << std::endl + << "PFA.Krg2 - Grid.Row.KCenter: " + << pfa.krg2 - row->kCenter << std::endl; + log.error(messageBuilder.str()); + valid = false; + } + + //2.3.13 + if (pfa.krg1 - row->kCenter < + (-1 / (2 * row->sampleSpacing)) - epsilon) + { + messageBuilder.str(""); + messageBuilder << BOUNDS_ERROR_MESSAGE << std::endl + << "0.5/SICD.Grid.Row.SampleSpacing: " + << 0.5 / row->sampleSpacing << std::endl + << "PFA.Krg1 - Grid.Row.KCenter: " + << pfa.krg1 - row->kCenter << std::endl; + log.error(messageBuilder.str()); + valid = false; + } + + //2.3.14 + if (col->impulseResponseBandwidth > pfa.kaz2 - pfa.kaz1 + epsilon) + { + messageBuilder.str(""); + messageBuilder << BOUNDS_ERROR_MESSAGE << std::endl + << "Grid.Col.ImpulseResponseBandwidth: " + << col->impulseResponseBandwidth << std::endl + << "SICD.PFA.Kaz2 - SICD.PFA.Kaz1: " + << pfa.kaz2 - pfa.kaz1 << std::endl; + log.error(messageBuilder.str()); + valid = false; + } + //2.3.15 + if (row->impulseResponseBandwidth > pfa.krg2 - pfa.krg1 + epsilon) + { + messageBuilder.str(""); + messageBuilder << BOUNDS_ERROR_MESSAGE << std::endl + << "Grid.Row.ImpulseResponseBandwidth: " + << row->impulseResponseBandwidth << std::endl + << "SICD.PFA.Krg2 - SICD.PFA.Krg1: " + << pfa.krg2 - pfa.krg1 << std::endl; + log.error(messageBuilder.str()); + valid = false; + } + //2.3.16 + if (col->kCenter != 0 && + std::abs(col->kCenter - (pfa.kaz1 + pfa.kaz2) / 2) > 1e-5) + { + messageBuilder.str(""); + messageBuilder << BOUNDS_ERROR_MESSAGE << std::endl + << "Grid.Col.KCenter: " << col->kCenter << std::endl + << "mean(SICD.PFA.Kaz1, SICD.PFA.Kaz2): " + << (pfa.kaz1 + pfa.kaz2) / 2 << std::endl; + log.error(messageBuilder.str()); + valid = false; } return valid; @@ -1206,59 +1206,59 @@ bool Grid::validate(const RgAzComp& rgAzComp, { bool valid = true; std::ostringstream messageBuilder; - - // 2.12.1.1 - if (imagePlane != ComplexImagePlaneType::SLANT) - { - messageBuilder.str(""); - messageBuilder << - "RGAZCOMP image formation should result in a SLANT plane image." - << std::endl << "Grid.ImagePlane: " << imagePlane; - log.error(messageBuilder.str()); - valid = false; - } - - //2.12.1.2 - if (type != ComplexImageGridType::RGAZIM) - { - messageBuilder.str(""); - messageBuilder << - "RGAZCOMP image formation should result in a RGAZIM grid." - << std::endl << "Grid.Type: " << type; - log.error(messageBuilder.str()); - valid = false; - } - - //2.12.1.8 - const Vector3& scp = geoData.scp.ecf; + + // 2.12.1.1 + if (imagePlane != ComplexImagePlaneType::SLANT) + { + messageBuilder.str(""); + messageBuilder << + "RGAZCOMP image formation should result in a SLANT plane image." + << std::endl << "Grid.ImagePlane: " << imagePlane; + log.error(messageBuilder.str()); + valid = false; + } + + //2.12.1.2 + if (type != ComplexImageGridType::RGAZIM) + { + messageBuilder.str(""); + messageBuilder << + "RGAZCOMP image formation should result in a RGAZIM grid." + << std::endl << "Grid.Type: " << type; + log.error(messageBuilder.str()); + valid = false; + } + + //2.12.1.8 + const Vector3& scp = geoData.scp.ecf; valid = col->validate(rgAzComp, log) && valid; valid = row->validate(rgAzComp, log, fc *(2 / math::Constants::SPEED_OF_LIGHT_METERS_PER_SEC)) && valid; - //2.12.1.6 - if ((derivedRowUnitVector(scpcoa, scp) - row->unitVector).norm() - > UVECT_TOL) - { - messageBuilder.str(""); - messageBuilder << "UVect fields inconsistent." << std::endl - << "Grid.Row.UVectECEF: " << row->unitVector << std::endl - << "Derived Grid.Row.UVectECEF: " << - derivedRowUnitVector(scpcoa, scp); - log.error(messageBuilder.str()); - valid = false; - } - - //2.12.1.7 - if ((derivedColUnitVector(scpcoa, scp) - col->unitVector).norm() - > UVECT_TOL) - { - messageBuilder.str(""); - messageBuilder << "UVect fields inconsistent." << std::endl - << "Grid.Col.UVectECF: " << col->unitVector << std::endl - << "Derived Grid.Col.UVectECF: " << - derivedColUnitVector(scpcoa, scp); - log.error(messageBuilder.str()); - valid = false; + //2.12.1.6 + if ((derivedRowUnitVector(scpcoa, scp) - row->unitVector).norm() + > UVECT_TOL) + { + messageBuilder.str(""); + messageBuilder << "UVect fields inconsistent." << std::endl + << "Grid.Row.UVectECEF: " << row->unitVector << std::endl + << "Derived Grid.Row.UVectECEF: " << + derivedRowUnitVector(scpcoa, scp); + log.error(messageBuilder.str()); + valid = false; + } + + //2.12.1.7 + if ((derivedColUnitVector(scpcoa, scp) - col->unitVector).norm() + > UVECT_TOL) + { + messageBuilder.str(""); + messageBuilder << "UVect fields inconsistent." << std::endl + << "Grid.Col.UVectECF: " << col->unitVector << std::endl + << "Derived Grid.Col.UVectECF: " << + derivedColUnitVector(scpcoa, scp); + log.error(messageBuilder.str()); + valid = false; } return valid; diff --git a/six/modules/c++/six.sicd/source/ImageData.cpp b/six/modules/c++/six.sicd/source/ImageData.cpp index 3e35f81d69..147383a979 100644 --- a/six/modules/c++/six.sicd/source/ImageData.cpp +++ b/six/modules/c++/six.sicd/source/ImageData.cpp @@ -1,278 +1,278 @@ -/* ========================================================================= - * This file is part of six.sicd-c++ - * ========================================================================= - * - * (C) Copyright 2004 - 2014, MDA Information Systems LLC - * - * six.sicd-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ -#include "six/sicd/ImageData.h" - -#include -#include -#include -#include // std::ignore -#include -#include -#include - -#include -#include -#include -#if CODA_OSS_cpp17 - // is broken with the older version of GCC we're using - #if (__GNUC__ >= 10) || _MSC_VER - #include - #define SIX_six_sicd_ImageData_has_execution 1 - #endif -#endif - -#include "six/AmplitudeTable.h" -#include "six/sicd/GeoData.h" -#include "six/sicd/Utilities.h" - -using namespace six; -using namespace six::sicd; - - // This was in coda-oss, but I removed it. - // - // First of all, C++11's std::async() is now (in 2023) thought of as maybe a - // bit "half baked," and perhaps shouldn't be emulated. Then, C++17 added - // parallel algorithms which might be a better way of satisfying our immediate - // needs (below) ... although we're still at C++14. -template -static inline OutputIt transform_async(const InputIt first1, const InputIt last1, OutputIt d_first, TFunc f, - typename std::iterator_traits::difference_type cutoff) -{ - // https://en.cppreference.com/w/cpp/thread/async - const auto len = std::distance(first1, last1); - if (len < cutoff) - { - return std::transform(first1, last1, d_first, f); - } - - constexpr auto policy = std::launch::async; - - const auto mid1 = first1 + len / 2; - const auto d_mid = d_first + len / 2; - auto handle = std::async(policy, transform_async, mid1, last1, d_mid, f, cutoff); - transform_async(first1, mid1, d_first, f, cutoff); - return handle.get(); -} -template -static inline void transform(std::span inputs, std::span results, TFunc f) -{ -#if SIX_six_sicd_ImageData_has_execution - std::ignore = std::transform(std::execution::par, inputs.begin(), inputs.end(), results.begin(), f); -#else - constexpr ptrdiff_t cutoff_ = 0; // too slow w/o multi-threading - //if (cutoff_ < 0) - //{ - // std::ignore = std::transform(inputs.begin(), inputs.end(), results.begin(), f); - //} - //else - { - // The value of "default_cutoff" was determined by testing; there is nothing special about it, feel free to change it. - constexpr auto dimension = 128 * 8; - constexpr auto default_cutoff = dimension * dimension; - const auto cutoff = cutoff_ == 0 ? default_cutoff : cutoff_; - - std::ignore = transform_async(inputs.begin(), inputs.end(), results.begin(), f, cutoff); - } -#endif // CODA_OSS_cpp17 -} - -bool ImageData::operator==(const ImageData& rhs) const -{ - return (pixelType == rhs.pixelType && - amplitudeTable == rhs.amplitudeTable && - numRows == rhs.numRows && - numCols == rhs.numCols && - firstRow == rhs.firstRow && - firstCol == rhs.firstCol && - fullImage == rhs.fullImage && - scpPixel == rhs.scpPixel && - validData == rhs.validData); -} - -bool ImageData::validate(const GeoData& geoData, logging::Logger& log) const -{ - bool valid = true; - std::ostringstream messageBuilder; - - // 2.11.1 - if (!validData.empty() && geoData.validData.empty()) - { - messageBuilder << "ImageData.ValidData/GeoData.ValidData " - << "required together." << std::endl - << "ImageData.ValidData exists, but GeoData.ValidData does not."; - log.error(messageBuilder.str()); - valid = false; - } - - // 2.11.2 - if (validData.empty() && !geoData.validData.empty()) - { - messageBuilder << "ImageData.ValidData/GeoData.ValidData " - << "required together." << std::endl - << "GeoData.ValidData exists, but ImageData.ValidData does not."; - log.error(messageBuilder.str()); - valid = false; - } - - // 2.11.3 In ValidData, first vertex should have (1) minimum row index - // and (2) minimum column index if 2 vertices exist with equal minimum - // row index. - if (!validData.empty()) - { - bool minimumRowComesFirst = true; - - for (size_t ii = 1; ii < validData.size(); ++ii) - { - if (validData[ii].row < validData[0].row) - { - minimumRowComesFirst = false; - break; - } - } - if (!minimumRowComesFirst) - { - messageBuilder << "ImageData.ValidData first row should have" - << "minimum row index"; - log.error(messageBuilder.str()); - valid = false; - } - else - { - bool minimumColComesFirst = true; - std::vector minimumIndices; - for (size_t ii = 0; ii < validData.size(); ++ii) - { - if (validData[0].row == validData[ii].row && - validData[ii].col < validData[0].col) - { - minimumColComesFirst = false; - break; - } - } - if (!minimumColComesFirst) - { - messageBuilder << "ImageData.ValidData first col of matching" - << "minimum row index should have minimum col index"; - log.error(messageBuilder.str()); - valid = false; - } - } - if (!Utilities::isClockwise(validData)) - { - messageBuilder << "ImageData.ValidData should be arrange clockwise"; - log.error(messageBuilder.str()); - valid = false; - } - } - - return valid; -} - -template -static auto createLookup(TToComplexFunc toComplex) -{ - auto retval = std::make_unique(); // too big for the stack - auto& values = *retval; - - // For all possible amp/phase values (there are "only" 256*256=65536), get and save the - // complex value. - for (const auto amplitude : Utilities::iota_0_256()) - { - for (const auto phase : Utilities::iota_0_256()) - { - values[amplitude][phase] = toComplex(amplitude, phase); - } - } - - return retval; -} -static auto createLookup(const six::AmplitudeTable& amplitudeTable) -{ - const auto toComplex = [&litudeTable](auto amplitude, auto phase) { - return six::sicd::Utilities::toComplex(amplitude, phase, amplitudeTable); - }; - return createLookup(toComplex); -} -static auto createLookup() -{ - static const auto toComplex = [](auto amplitude, auto phase) { - return six::sicd::Utilities::toComplex(amplitude, phase); - }; - return createLookup(toComplex); -} - -static const six::Amp8iPhs8iLookup_t* getCachedLookup(const six::AmplitudeTable* pAmplitudeTable) -{ - if (pAmplitudeTable == nullptr) - { - static const auto lookup_no_table = createLookup(); - return lookup_no_table.get(); - } - - // Maybe one has already been created and stored on the table? - return pAmplitudeTable->getLookup(); -} - -const six::Amp8iPhs8iLookup_t& ImageData::getLookup(const six::AmplitudeTable* pAmplitudeTable) -{ - auto pLookup = getCachedLookup(pAmplitudeTable); - if (pLookup == nullptr) - { - assert(pAmplitudeTable != nullptr); - auto& amplitudeTable = *pAmplitudeTable; - auto lookup = createLookup(amplitudeTable); - amplitudeTable.cacheLookup_(std::move(lookup)); - pLookup = amplitudeTable.getLookup(); - } - assert(pLookup != nullptr); - return *pLookup; -} - -void ImageData::toComplex(const six::Amp8iPhs8iLookup_t& values, std::span inputs, std::span results) -{ - const auto toComplex_ = [&values](const auto& v) - { - return values[v.amplitude][v.phase]; - }; - transform(inputs, results, toComplex_); -} -void ImageData::toComplex(std::span inputs, std::span results) const -{ - if (pixelType != PixelType::AMP8I_PHS8I) - { - throw std::runtime_error("pxielType must be AMP8I_PHS8I"); - } - - const auto& values = getLookup(amplitudeTable.get()); - toComplex(values, inputs, results); -} - -void ImageData::fromComplex(std::span inputs, std::span results) const -{ - six::sicd::details::ComplexToAMP8IPHS8I::nearest_neighbors(inputs, results, amplitudeTable.get()); -} -void ImageData::testing_fromComplex_(std::span inputs, std::span results) -{ - static const ImageData imageData; - assert(imageData.amplitudeTable.get() == nullptr); - imageData.fromComplex(inputs, results); -} +/* ========================================================================= + * This file is part of six.sicd-c++ + * ========================================================================= + * + * (C) Copyright 2004 - 2014, MDA Information Systems LLC + * + * six.sicd-c++ is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; If not, + * see . + * + */ +#include "six/sicd/ImageData.h" + +#include +#include +#include +#include // std::ignore +#include +#include +#include + +#include +#include +#include +#if CODA_OSS_cpp17 + // is broken with the older version of GCC we're using + #if (__GNUC__ >= 10) || _MSC_VER + #include + #define SIX_six_sicd_ImageData_has_execution 1 + #endif +#endif + +#include "six/AmplitudeTable.h" +#include "six/sicd/GeoData.h" +#include "six/sicd/Utilities.h" + +using namespace six; +using namespace six::sicd; + + // This was in coda-oss, but I removed it. + // + // First of all, C++11's std::async() is now (in 2023) thought of as maybe a + // bit "half baked," and perhaps shouldn't be emulated. Then, C++17 added + // parallel algorithms which might be a better way of satisfying our immediate + // needs (below) ... although we're still at C++14. +template +static inline OutputIt transform_async(const InputIt first1, const InputIt last1, OutputIt d_first, TFunc f, + typename std::iterator_traits::difference_type cutoff) +{ + // https://en.cppreference.com/w/cpp/thread/async + const auto len = std::distance(first1, last1); + if (len < cutoff) + { + return std::transform(first1, last1, d_first, f); + } + + constexpr auto policy = std::launch::async; + + const auto mid1 = first1 + len / 2; + const auto d_mid = d_first + len / 2; + auto handle = std::async(policy, transform_async, mid1, last1, d_mid, f, cutoff); + transform_async(first1, mid1, d_first, f, cutoff); + return handle.get(); +} +template +static inline void transform(std::span inputs, std::span results, TFunc f) +{ +#if SIX_six_sicd_ImageData_has_execution + std::ignore = std::transform(std::execution::par, inputs.begin(), inputs.end(), results.begin(), f); +#else + constexpr ptrdiff_t cutoff_ = 0; // too slow w/o multi-threading + //if (cutoff_ < 0) + //{ + // std::ignore = std::transform(inputs.begin(), inputs.end(), results.begin(), f); + //} + //else + { + // The value of "default_cutoff" was determined by testing; there is nothing special about it, feel free to change it. + constexpr auto dimension = 128 * 8; + constexpr auto default_cutoff = dimension * dimension; + const auto cutoff = cutoff_ == 0 ? default_cutoff : cutoff_; + + std::ignore = transform_async(inputs.begin(), inputs.end(), results.begin(), f, cutoff); + } +#endif // CODA_OSS_cpp17 +} + +bool ImageData::operator==(const ImageData& rhs) const +{ + return (pixelType == rhs.pixelType && + amplitudeTable == rhs.amplitudeTable && + numRows == rhs.numRows && + numCols == rhs.numCols && + firstRow == rhs.firstRow && + firstCol == rhs.firstCol && + fullImage == rhs.fullImage && + scpPixel == rhs.scpPixel && + validData == rhs.validData); +} + +bool ImageData::validate(const GeoData& geoData, logging::Logger& log) const +{ + bool valid = true; + std::ostringstream messageBuilder; + + // 2.11.1 + if (!validData.empty() && geoData.validData.empty()) + { + messageBuilder << "ImageData.ValidData/GeoData.ValidData " + << "required together." << std::endl + << "ImageData.ValidData exists, but GeoData.ValidData does not."; + log.error(messageBuilder.str()); + valid = false; + } + + // 2.11.2 + if (validData.empty() && !geoData.validData.empty()) + { + messageBuilder << "ImageData.ValidData/GeoData.ValidData " + << "required together." << std::endl + << "GeoData.ValidData exists, but ImageData.ValidData does not."; + log.error(messageBuilder.str()); + valid = false; + } + + // 2.11.3 In ValidData, first vertex should have (1) minimum row index + // and (2) minimum column index if 2 vertices exist with equal minimum + // row index. + if (!validData.empty()) + { + bool minimumRowComesFirst = true; + + for (size_t ii = 1; ii < validData.size(); ++ii) + { + if (validData[ii].row < validData[0].row) + { + minimumRowComesFirst = false; + break; + } + } + if (!minimumRowComesFirst) + { + messageBuilder << "ImageData.ValidData first row should have" + << "minimum row index"; + log.error(messageBuilder.str()); + valid = false; + } + else + { + bool minimumColComesFirst = true; + std::vector minimumIndices; + for (size_t ii = 0; ii < validData.size(); ++ii) + { + if (validData[0].row == validData[ii].row && + validData[ii].col < validData[0].col) + { + minimumColComesFirst = false; + break; + } + } + if (!minimumColComesFirst) + { + messageBuilder << "ImageData.ValidData first col of matching" + << "minimum row index should have minimum col index"; + log.error(messageBuilder.str()); + valid = false; + } + } + if (!Utilities::isClockwise(validData)) + { + messageBuilder << "ImageData.ValidData should be arrange clockwise"; + log.error(messageBuilder.str()); + valid = false; + } + } + + return valid; +} + +template +static auto createLookup(TToComplexFunc toComplex) +{ + auto retval = std::make_unique(); // too big for the stack + auto& values = *retval; + + // For all possible amp/phase values (there are "only" 256*256=65536), get and save the + // complex value. + for (const auto amplitude : Utilities::iota_0_256()) + { + for (const auto phase : Utilities::iota_0_256()) + { + values[amplitude][phase] = toComplex(amplitude, phase); + } + } + + return retval; +} +static auto createLookup(const six::AmplitudeTable& amplitudeTable) +{ + const auto toComplex = [&litudeTable](auto amplitude, auto phase) { + return six::sicd::Utilities::toComplex(amplitude, phase, amplitudeTable); + }; + return createLookup(toComplex); +} +static auto createLookup() +{ + static const auto toComplex = [](auto amplitude, auto phase) { + return six::sicd::Utilities::toComplex(amplitude, phase); + }; + return createLookup(toComplex); +} + +static const six::Amp8iPhs8iLookup_t* getCachedLookup(const six::AmplitudeTable* pAmplitudeTable) +{ + if (pAmplitudeTable == nullptr) + { + static const auto lookup_no_table = createLookup(); + return lookup_no_table.get(); + } + + // Maybe one has already been created and stored on the table? + return pAmplitudeTable->getLookup(); +} + +const six::Amp8iPhs8iLookup_t& ImageData::getLookup(const six::AmplitudeTable* pAmplitudeTable) +{ + auto pLookup = getCachedLookup(pAmplitudeTable); + if (pLookup == nullptr) + { + assert(pAmplitudeTable != nullptr); + auto& amplitudeTable = *pAmplitudeTable; + auto lookup = createLookup(amplitudeTable); + amplitudeTable.cacheLookup_(std::move(lookup)); + pLookup = amplitudeTable.getLookup(); + } + assert(pLookup != nullptr); + return *pLookup; +} + +void ImageData::toComplex(const six::Amp8iPhs8iLookup_t& values, std::span inputs, std::span results) +{ + const auto toComplex_ = [&values](const auto& v) + { + return values[v.amplitude][v.phase]; + }; + transform(inputs, results, toComplex_); +} +void ImageData::toComplex(std::span inputs, std::span results) const +{ + if (pixelType != PixelType::AMP8I_PHS8I) + { + throw std::runtime_error("pxielType must be AMP8I_PHS8I"); + } + + const auto& values = getLookup(amplitudeTable.get()); + toComplex(values, inputs, results); +} + +void ImageData::fromComplex(std::span inputs, std::span results) const +{ + six::sicd::details::ComplexToAMP8IPHS8I::nearest_neighbors(inputs, results, amplitudeTable.get()); +} +void ImageData::testing_fromComplex_(std::span inputs, std::span results) +{ + static const ImageData imageData; + assert(imageData.amplitudeTable.get() == nullptr); + imageData.fromComplex(inputs, results); +} diff --git a/six/modules/c++/six.sicd/source/NITFReadComplexXMLControl.cpp b/six/modules/c++/six.sicd/source/NITFReadComplexXMLControl.cpp index 0f8327f01e..bad638fffc 100644 --- a/six/modules/c++/six.sicd/source/NITFReadComplexXMLControl.cpp +++ b/six/modules/c++/six.sicd/source/NITFReadComplexXMLControl.cpp @@ -1,129 +1,129 @@ -/* ========================================================================= - * This file is part of six.sicd-c++ - * ========================================================================= - * - * (C) Copyright 2021 Maxar Technologies, Inc. - * - * six.sicd-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ -#include "six/sicd/NITFReadComplexXMLControl.h" - -#include -#include -#include - -#include "six/sicd/ComplexXMLControl.h" -#include "six/sicd/Utilities.h" - -namespace fs = std::filesystem; - -six::sicd::NITFReadComplexXMLControl::NITFReadComplexXMLControl() -{ - // create an XML registry - // The reason to do this is to avoid adding XMLControlCreators to the - // XMLControlFactory singleton - this way has more fine-grained control - addCreator(); -} - -void six::sicd::NITFReadComplexXMLControl::load(const std::string& fromFile, - const std::vector* pSchemaPaths) -{ - reader.load(fromFile, pSchemaPaths); -} -void six::sicd::NITFReadComplexXMLControl::load(const std::filesystem::path& fromFile, - const std::vector* pSchemaPaths) -{ - reader.load(fromFile, pSchemaPaths); -} -void six::sicd::NITFReadComplexXMLControl::load(io::FileInputStream& fis, const std::vector* pSchemaPaths) -{ - reader.load(fis, pSchemaPaths); -} -void six::sicd::NITFReadComplexXMLControl::load(io::FileInputStream& fis, const std::vector* pSchemaPaths) -{ - reader.load(fis, pSchemaPaths); -} - - -std::shared_ptr six::sicd::NITFReadComplexXMLControl::getContainer() const -{ - return reader.getContainer(); -} -std::shared_ptr six::sicd::NITFReadComplexXMLControl::getContainer() -{ - return reader.getContainer(); -} - -void six::sicd::NITFReadComplexXMLControl::setXMLControlRegistry() -{ - // This tells the reader that it doesn't own an XMLControlRegistry - reader.setXMLControlRegistry(nullptr); -} - -std::unique_ptr six::sicd::NITFReadComplexXMLControl::getComplexData() -{ - auto result = Utilities::getComplexData(reader); - return std::unique_ptr< six::sicd::ComplexData>(result.release()); -} - -std::vector six::sicd::NITFReadComplexXMLControl::getWidebandData(const ComplexData& complexData) -{ - std::vector retval; - Utilities::getWidebandData(reader, complexData, retval); - return retval; -} -void six::sicd::NITFReadComplexXMLControl::getWidebandData(const ComplexData& complexData, - const types::RowCol& offset, const types::RowCol& extent, - six::zfloat* buffer) -{ - Utilities::getWidebandData(reader, complexData, offset, extent, buffer); -} - -void six::sicd::NITFReadComplexXMLControl::setLogger() -{ - reader.setLogger(std::make_unique()); -} - -void six::sicd::NITFReadComplexXMLControl::interleaved(Region& region) -{ - constexpr size_t imageNumber = 0; - (void)reader.interleaved(region, imageNumber); -} - -std::vector six::sicd::NITFReadComplexXMLControl::interleaved() -{ - auto pComplexData = getComplexData(); - const auto extent = getExtent(*pComplexData); - const auto numPixels = extent.area(); - const auto numBytesPerPixel = pComplexData->getNumBytesPerPixel(); - size_t offset = 0; - - std::vector buffer(numPixels * numBytesPerPixel); - - six::Region region; - setDims(region, extent); - region.setBuffer(buffer.data() + offset); - interleaved(region); - - return buffer; -} - -void six::sicd::NITFReadComplexXMLControl::getMeshes(std::unique_ptr& noiseMesh, - std::unique_ptr& scalarMesh) const -{ - noiseMesh = Utilities::getNoiseMesh(reader); - scalarMesh = Utilities::getScalarMesh(reader); -} +/* ========================================================================= + * This file is part of six.sicd-c++ + * ========================================================================= + * + * (C) Copyright 2021 Maxar Technologies, Inc. + * + * six.sicd-c++ is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; If not, + * see . + * + */ +#include "six/sicd/NITFReadComplexXMLControl.h" + +#include +#include +#include + +#include "six/sicd/ComplexXMLControl.h" +#include "six/sicd/Utilities.h" + +namespace fs = std::filesystem; + +six::sicd::NITFReadComplexXMLControl::NITFReadComplexXMLControl() +{ + // create an XML registry + // The reason to do this is to avoid adding XMLControlCreators to the + // XMLControlFactory singleton - this way has more fine-grained control + addCreator(); +} + +void six::sicd::NITFReadComplexXMLControl::load(const std::string& fromFile, + const std::vector* pSchemaPaths) +{ + reader.load(fromFile, pSchemaPaths); +} +void six::sicd::NITFReadComplexXMLControl::load(const std::filesystem::path& fromFile, + const std::vector* pSchemaPaths) +{ + reader.load(fromFile, pSchemaPaths); +} +void six::sicd::NITFReadComplexXMLControl::load(io::FileInputStream& fis, const std::vector* pSchemaPaths) +{ + reader.load(fis, pSchemaPaths); +} +void six::sicd::NITFReadComplexXMLControl::load(io::FileInputStream& fis, const std::vector* pSchemaPaths) +{ + reader.load(fis, pSchemaPaths); +} + + +std::shared_ptr six::sicd::NITFReadComplexXMLControl::getContainer() const +{ + return reader.getContainer(); +} +std::shared_ptr six::sicd::NITFReadComplexXMLControl::getContainer() +{ + return reader.getContainer(); +} + +void six::sicd::NITFReadComplexXMLControl::setXMLControlRegistry() +{ + // This tells the reader that it doesn't own an XMLControlRegistry + reader.setXMLControlRegistry(nullptr); +} + +std::unique_ptr six::sicd::NITFReadComplexXMLControl::getComplexData() +{ + auto result = Utilities::getComplexData(reader); + return std::unique_ptr< six::sicd::ComplexData>(result.release()); +} + +std::vector six::sicd::NITFReadComplexXMLControl::getWidebandData(const ComplexData& complexData) +{ + std::vector retval; + Utilities::getWidebandData(reader, complexData, retval); + return retval; +} +void six::sicd::NITFReadComplexXMLControl::getWidebandData(const ComplexData& complexData, + const types::RowCol& offset, const types::RowCol& extent, + six::zfloat* buffer) +{ + Utilities::getWidebandData(reader, complexData, offset, extent, buffer); +} + +void six::sicd::NITFReadComplexXMLControl::setLogger() +{ + reader.setLogger(std::make_unique()); +} + +void six::sicd::NITFReadComplexXMLControl::interleaved(Region& region) +{ + constexpr size_t imageNumber = 0; + (void)reader.interleaved(region, imageNumber); +} + +std::vector six::sicd::NITFReadComplexXMLControl::interleaved() +{ + auto pComplexData = getComplexData(); + const auto extent = getExtent(*pComplexData); + const auto numPixels = extent.area(); + const auto numBytesPerPixel = pComplexData->getNumBytesPerPixel(); + size_t offset = 0; + + std::vector buffer(numPixels * numBytesPerPixel); + + six::Region region; + setDims(region, extent); + region.setBuffer(buffer.data() + offset); + interleaved(region); + + return buffer; +} + +void six::sicd::NITFReadComplexXMLControl::getMeshes(std::unique_ptr& noiseMesh, + std::unique_ptr& scalarMesh) const +{ + noiseMesh = Utilities::getNoiseMesh(reader); + scalarMesh = Utilities::getScalarMesh(reader); +} diff --git a/six/modules/c++/six.sicd/source/PFA.cpp b/six/modules/c++/six.sicd/source/PFA.cpp index 892b415532..4e3d94d27c 100644 --- a/six/modules/c++/six.sicd/source/PFA.cpp +++ b/six/modules/c++/six.sicd/source/PFA.cpp @@ -21,13 +21,13 @@ */ #include "six/sicd/GeoData.h" #include "six/sicd/Grid.h" -#include "six/sicd/PFA.h" -#include "six/sicd/Position.h" -#include "six/sicd/SCPCOA.h" +#include "six/sicd/PFA.h" +#include "six/sicd/Position.h" +#include "six/sicd/SCPCOA.h" #include "six/sicd/Utilities.h" - + namespace six -{ +{ namespace sicd { SlowTimeDeskew::SlowTimeDeskew() : @@ -44,91 +44,91 @@ PFA::PFA() : kaz1(Init::undefined()), kaz2(Init::undefined()) { -} - -bool PFA::operator==(const PFA& rhs) const -{ - return (focusPlaneNormal == rhs.focusPlaneNormal && - imagePlaneNormal == rhs.imagePlaneNormal && - polarAngleRefTime == rhs.polarAngleRefTime && - polarAnglePoly == rhs.polarAnglePoly && - spatialFrequencyScaleFactorPoly == rhs.spatialFrequencyScaleFactorPoly && - krg1 == rhs.krg1 && - krg2 == rhs.krg2 && - kaz1 == rhs.kaz1 && - kaz2 == rhs.kaz2 && - slowTimeDeskew == rhs.slowTimeDeskew); -} - -void PFA::fillDerivedFields(const Position& position) -{ - if (!Init::isUndefined(position.arpPoly) && - !Init::isUndefined(polarAngleRefTime)) - { - // This doesn't actually do anything currently. - // Requires re-implemenation of polyfit, pfa_polar_coords, and bsxfun - const Vector3 polRefPos = position.arpPoly(polarAngleRefTime); - } -} - -void PFA::fillDefaultFields(const GeoData& geoData, - const Grid& grid, const SCPCOA& scpcoa) -{ - const Vector3& scp = geoData.scp.ecf; - if (Init::isUndefined(imagePlaneNormal)) - { +} + +bool PFA::operator==(const PFA& rhs) const +{ + return (focusPlaneNormal == rhs.focusPlaneNormal && + imagePlaneNormal == rhs.imagePlaneNormal && + polarAngleRefTime == rhs.polarAngleRefTime && + polarAnglePoly == rhs.polarAnglePoly && + spatialFrequencyScaleFactorPoly == rhs.spatialFrequencyScaleFactorPoly && + krg1 == rhs.krg1 && + krg2 == rhs.krg2 && + kaz1 == rhs.kaz1 && + kaz2 == rhs.kaz2 && + slowTimeDeskew == rhs.slowTimeDeskew); +} + +void PFA::fillDerivedFields(const Position& position) +{ + if (!Init::isUndefined(position.arpPoly) && + !Init::isUndefined(polarAngleRefTime)) + { + // This doesn't actually do anything currently. + // Requires re-implemenation of polyfit, pfa_polar_coords, and bsxfun + const Vector3 polRefPos = position.arpPoly(polarAngleRefTime); + } +} + +void PFA::fillDefaultFields(const GeoData& geoData, + const Grid& grid, const SCPCOA& scpcoa) +{ + const Vector3& scp = geoData.scp.ecf; + if (Init::isUndefined(imagePlaneNormal)) + { scene::WGS84EllipsoidModel model; - switch (grid.imagePlane) - { - case ComplexImagePlaneType::SLANT: - case ComplexImagePlaneType::NOT_SET: - imagePlaneNormal = scpcoa.slantPlaneNormal(scp); - break; - case ComplexImagePlaneType::GROUND: + switch (grid.imagePlane) + { + case ComplexImagePlaneType::SLANT: + case ComplexImagePlaneType::NOT_SET: + imagePlaneNormal = scpcoa.slantPlaneNormal(scp); + break; + case ComplexImagePlaneType::GROUND: imagePlaneNormal = model.getNormalVector(scp); - break; - case ComplexImagePlaneType::OTHER: - default: - // Nothing we can do - break; - } - } - - if (Init::isUndefined(focusPlaneNormal)) - { + break; + case ComplexImagePlaneType::OTHER: + default: + // Nothing we can do + break; + } + } + + if (Init::isUndefined(focusPlaneNormal)) + { scene::WGS84EllipsoidModel model; focusPlaneNormal = model.getNormalVector(scp); - } - - if (!Init::isUndefined(scpcoa.scpTime) && - Init::isUndefined(polarAngleRefTime)) - { - polarAngleRefTime = scpcoa.scpTime; - } - - //Vector3 polRefPos = arpPos; - //for when the other functions get implemented -} - -bool PFA::validate(const SCPCOA& scpcoa, logging::Logger& log) -{ - bool valid = true; - std::ostringstream messageBuilder; - - //2.12.2.3 - if (polarAngleRefTime - scpcoa.scpTime > - std::numeric_limits::epsilon()) - { - messageBuilder.str(""); - messageBuilder << "Polar angle reference time and center of aperture " - << "time for center are usuallly the same." << std::endl - << "PFA.PolarAngRefTime: " << polarAngleRefTime << std::endl - << "SCPCOA.SCPTime: " << scpcoa.scpTime; - log.warn(messageBuilder.str()); - valid = false; - } - - return valid; -} + } + + if (!Init::isUndefined(scpcoa.scpTime) && + Init::isUndefined(polarAngleRefTime)) + { + polarAngleRefTime = scpcoa.scpTime; + } + + //Vector3 polRefPos = arpPos; + //for when the other functions get implemented +} + +bool PFA::validate(const SCPCOA& scpcoa, logging::Logger& log) +{ + bool valid = true; + std::ostringstream messageBuilder; + + //2.12.2.3 + if (polarAngleRefTime - scpcoa.scpTime > + std::numeric_limits::epsilon()) + { + messageBuilder.str(""); + messageBuilder << "Polar angle reference time and center of aperture " + << "time for center are usuallly the same." << std::endl + << "PFA.PolarAngRefTime: " << polarAngleRefTime << std::endl + << "SCPCOA.SCPTime: " << scpcoa.scpTime; + log.warn(messageBuilder.str()); + valid = false; + } + + return valid; +} } } diff --git a/six/modules/c++/six.sicd/source/Position.cpp b/six/modules/c++/six.sicd/source/Position.cpp index cacde05b90..8dd5483628 100644 --- a/six/modules/c++/six.sicd/source/Position.cpp +++ b/six/modules/c++/six.sicd/source/Position.cpp @@ -19,11 +19,11 @@ * see . * */ -#include "six/sicd/Position.h" -#include "six/sicd/SCPCOA.h" +#include "six/sicd/Position.h" +#include "six/sicd/SCPCOA.h" #include - -namespace six + +namespace six { namespace sicd { @@ -32,47 +32,47 @@ Position::Position() : grpPoly(Init::undefined()), txAPCPoly(Init::undefined()) { -} - -void Position::fillDerivedFields(const SCPCOA& scpcoa) -{ - if (!Init::isUndefined(scpcoa.arpPos) && - !Init::isUndefined(scpcoa.arpVel) && - !Init::isUndefined(scpcoa.scpTime) && - (Init::isUndefined(arpPoly))) - { - const Vector3 tempArpAcc = Init::isUndefined(scpcoa.arpAcc) ? - Vector3(0.0) : scpcoa.arpAcc; - - std::vector coefs; - coefs.resize(3); - - //constant - coefs[0] = scpcoa.arpPos - - scpcoa.arpVel * scpcoa.scpTime + +} + +void Position::fillDerivedFields(const SCPCOA& scpcoa) +{ + if (!Init::isUndefined(scpcoa.arpPos) && + !Init::isUndefined(scpcoa.arpVel) && + !Init::isUndefined(scpcoa.scpTime) && + (Init::isUndefined(arpPoly))) + { + const Vector3 tempArpAcc = Init::isUndefined(scpcoa.arpAcc) ? + Vector3(0.0) : scpcoa.arpAcc; + + std::vector coefs; + coefs.resize(3); + + //constant + coefs[0] = scpcoa.arpPos - + scpcoa.arpVel * scpcoa.scpTime + (tempArpAcc / 2) * math::square(scpcoa.scpTime); - - //linear - coefs[1] = scpcoa.arpVel - - tempArpAcc * scpcoa.scpTime; - - //quadratic - coefs[2] = tempArpAcc / 2; - - arpPoly = PolyXYZ(coefs); - } -} - -bool Position::validate(logging::Logger& log) const -{ - // 2.6 - if (arpPoly.order() < 2) - { - log.error("Position.arpPoly should have at least position" - " and velocity terms."); - return false; - } - return true; -} -} + + //linear + coefs[1] = scpcoa.arpVel - + tempArpAcc * scpcoa.scpTime; + + //quadratic + coefs[2] = tempArpAcc / 2; + + arpPoly = PolyXYZ(coefs); + } +} + +bool Position::validate(logging::Logger& log) const +{ + // 2.6 + if (arpPoly.order() < 2) + { + log.error("Position.arpPoly should have at least position" + " and velocity terms."); + return false; + } + return true; +} +} } diff --git a/six/modules/c++/six.sicd/source/RadarCollection.cpp b/six/modules/c++/six.sicd/source/RadarCollection.cpp index cc598e4959..e90ea5b3b3 100644 --- a/six/modules/c++/six.sicd/source/RadarCollection.cpp +++ b/six/modules/c++/six.sicd/source/RadarCollection.cpp @@ -1,600 +1,600 @@ -/* ========================================================================= - * This file is part of six.sicd-c++ - * ========================================================================= - * - * (C) Copyright 2004 - 2014, MDA Information Systems LLC - * - * six.sicd-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ -#include - -#include -#include - -#undef min -#undef max - -namespace -{ -template -types::RowCol rotatePixel(size_t origNumCols, const types::RowCol& pixel) -{ - types::RowCol rotatedPixel; - rotatedPixel.col = pixel.row; - rotatedPixel.row = static_cast(origNumCols) - pixel.col; - return rotatedPixel; -} -} - -namespace six -{ -namespace sicd -{ -TxStep::TxStep() : - waveformIndex(Init::undefined()), - txPolarization(PolarizationType::NOT_SET) -{ -} - -TxStep* TxStep::clone() const -{ - return new TxStep(*this); -} - -WaveformParameters::WaveformParameters() : - txPulseLength(Init::undefined()), - txRFBandwidth(Init::undefined()), - txFrequencyStart(Init::undefined()), - txFMRate(Init::undefined()), - rcvDemodType(DemodType::NOT_SET), - rcvWindowLength(Init::undefined()), - adcSampleRate(Init::undefined()), - rcvIFBandwidth(Init::undefined()), - rcvFrequencyStart(Init::undefined()), - rcvFMRate(Init::undefined()) -{ -} - -const double WaveformParameters::WF_TOL = 1e-3; -const double WaveformParameters::WGT_TOL = 1e-3; -const char WaveformParameters::WF_INCONSISTENT_STR[] = - "Waveform fields not consistent"; - -const double RadarCollection::WF_TOL = 1e-3; -const char RadarCollection::WF_INCONSISTENT_STR[] = - "Waveform fields not consistent"; - -bool WaveformParameters::operator==(const WaveformParameters& rhs) const -{ - return (txPulseLength == rhs.txPulseLength && - txRFBandwidth == rhs.txRFBandwidth && - txFrequencyStart == rhs.txFrequencyStart && - txFMRate == rhs.txFMRate && - rcvDemodType == rhs.rcvDemodType && - rcvWindowLength == rhs.rcvWindowLength && - adcSampleRate == rhs.adcSampleRate && - rcvIFBandwidth == rhs.rcvIFBandwidth && - rcvFrequencyStart == rhs.rcvFrequencyStart && - rcvFMRate == rhs.rcvFMRate); -} - -WaveformParameters* WaveformParameters::clone() const -{ - return new WaveformParameters(*this); -} - -void WaveformParameters::fillDerivedFields() -{ - if (rcvDemodType == DemodType::CHIRP && - Init::isUndefined(rcvFMRate)) - { - rcvFMRate = 0; - } - - if (rcvFMRate == 0 && - rcvDemodType == DemodType::NOT_SET) - { - rcvDemodType = DemodType::CHIRP; - } - - if (Init::isUndefined(txRFBandwidth) && - !Init::isUndefined(txPulseLength) && - !Init::isUndefined(txFMRate)) - { - txRFBandwidth = txPulseLength * txFMRate; - } - - if (!Init::isUndefined(txRFBandwidth) && - Init::isUndefined(txPulseLength) && - !Init::isUndefined(txFMRate)) - { - txPulseLength = txRFBandwidth / txFMRate; - } - - if (!Init::isUndefined(txRFBandwidth) && - !Init::isUndefined(txPulseLength) && - Init::isUndefined(txFMRate)) - { - txFMRate = txRFBandwidth / txPulseLength; - } -} - -bool WaveformParameters::validate(int refFrequencyIndex, - logging::Logger& log) const -{ - bool valid = true; - std::ostringstream messageBuilder; - - //2.8.3 - if (std::abs(txRFBandwidth / (txPulseLength * txFMRate) - 1) > WF_TOL) - { - messageBuilder.str(""); - messageBuilder << WF_INCONSISTENT_STR << std::endl - << "SICD.RadarCollection.Waveform.WFParameters.TxFRBandwidth: " - << txRFBandwidth << std::endl - << "SICD.RadarCollection.TxFrequency.txFMRate * txPulseLength: " - << txFMRate * txPulseLength << std::endl; - log.error(messageBuilder.str()); - valid = false; - } - - //2.8.4 - if (rcvDemodType == DemodType::CHIRP && - rcvFMRate != 0) - { - messageBuilder.str(""); - messageBuilder << WF_INCONSISTENT_STR << std::endl - << "SICD.RadarCollection.Waveform.WFParameters.RcvDemodType: " - << rcvDemodType << std::endl - << "SICD.RadarCollection.Waveform.WFParameters.RcvFMRate: " - << rcvFMRate << std::endl; - log.error(messageBuilder.str()); - valid = false; - } - - //2.8.5 - if (rcvDemodType == DemodType::STRETCH && - std::abs(rcvFMRate / txFMRate - 1) > WGT_TOL) - { - messageBuilder.str(""); - messageBuilder << WF_INCONSISTENT_STR << std::endl - << "SICD.RadarCollection.Waveform.WFParameters.RcvDemodType: " - << rcvDemodType << std::endl - << "SICD.RadarCollection.Waveform.WFParameters.RcvFMRate: " - << rcvFMRate << std::endl - << "SICD.RadarCollection.Waveform.WFParameters.TxFMRate: " - << txFMRate << std::endl; - log.error(messageBuilder.str()); - valid = false; - } - - //2.8.7 - //Absolute frequencies must be positive - if (six::Init::isUndefined(refFrequencyIndex) && - txFrequencyStart <= 0) - { - messageBuilder.str(""); - messageBuilder << WF_INCONSISTENT_STR << std::endl - << "SICD.RadarCollection.txFreqStart: " - << txFrequencyStart << std::endl; - log.error(messageBuilder.str()); - valid = false; - } - - //2.8.8 - //Absolute frequencies must be positive - if (six::Init::isUndefined(refFrequencyIndex) && - rcvFrequencyStart <= 0) - { - messageBuilder.str(""); - messageBuilder << WF_INCONSISTENT_STR << std::endl - << "SICD.RadarCollection.rcvFreqStart: " - << rcvFrequencyStart << std::endl; - log.error(messageBuilder.str()); - valid = false; - } - - //2.8.9 - if (six::Init::isDefined(txPulseLength) && (txPulseLength > rcvWindowLength)) // TxPulseLength is optional - { - messageBuilder.str(""); - messageBuilder << WF_INCONSISTENT_STR << std::endl - << "SICD.RadarCollection.Waveform.WFParameters.TxPulseLength: " - << txPulseLength << std::endl - << "SICD.RadarCollection.Waveform.WFPArameters.RcvWindowLength: " - << rcvWindowLength << std::endl; - log.error(messageBuilder.str()); - valid = false; - } - - //2.8.10 - if (six::Init::isDefined(rcvIFBandwidth) && (rcvIFBandwidth > adcSampleRate)) // RcvIFBandwidth is optional - { - messageBuilder.str(""); - messageBuilder << WF_INCONSISTENT_STR << std::endl - << "SICD.RadarCollection.Waveform.WFParameters.RcvIFBandwidth: " - << rcvIFBandwidth << std::endl - << "SICD.RadarCollection.Waveform.WFPArameters.ADCSampleRate: " - << adcSampleRate << std::endl; - log.error(messageBuilder.str()); - valid = false; - } - - //2.8.11 - if (rcvDemodType == DemodType::CHIRP && txRFBandwidth > adcSampleRate) - { - messageBuilder.str(""); - messageBuilder << WF_INCONSISTENT_STR << std::endl - << "SICD.RadarCollection.Waveform.WFParameters.RcvDemodType: " - << rcvDemodType << std::endl - << "SICD.RadarCollection.Waveform.WFParameters.TxRFBandwidth: " - << txRFBandwidth << std::endl - << "SICD.RadarCollection.Waveform.WFPArameters.ADCSampleRate: " - << adcSampleRate << std::endl; - log.error(messageBuilder.str()); - valid = false; - } - - //2.8.12 - if (six::Init::isDefined(rcvFrequencyStart)) // RcvFreqStart is optional - { - const auto freq_tol = (rcvWindowLength - txPulseLength) * txFMRate; - if (rcvFrequencyStart >= (txFrequencyStart + txRFBandwidth + freq_tol) || - rcvFrequencyStart <= txFrequencyStart - freq_tol) - { - messageBuilder.str(""); - messageBuilder << WF_INCONSISTENT_STR << std::endl - << "SICD.RadarCollection.Waveform.WFParameters.RcvFreqStart: " - << rcvFrequencyStart << std::endl; - log.error(messageBuilder.str()); - valid = false; - } - } - - return valid; -} - -ChannelParameters::ChannelParameters() : - txRcvPolarization(DualPolarizationType::NOT_SET), - rcvAPCIndex(Init::undefined()) -{ -} - -ChannelParameters* ChannelParameters::clone() const -{ - return new ChannelParameters(*this); -} - -AreaDirectionParameters::AreaDirectionParameters() : - unitVector(Init::undefined()), - spacing(Init::undefined()), - elements(Init::undefined()), - first(Init::undefined()) -{ -} - -AreaDirectionParameters* AreaDirectionParameters::clone() const -{ - return new AreaDirectionParameters(*this); -} - -std::ostream& operator<< (std::ostream& os, const AreaDirectionParameters& d) -{ - os << "AreaDirectionParameters::\n" - << " unitVector: " << toString(d.unitVector) << "\n" - << " spacing : " << d.spacing << "\n" - << " elements : " << d.elements << "\n" - << " first : " << d.first << "\n"; - return os; -} - -Segment::Segment() : - startLine(Init::undefined()), - startSample(Init::undefined()), - endLine(Init::undefined()), - endSample(Init::undefined()) -{ -} - -bool Segment::operator==(const Segment& rhs) const -{ - return (startLine == rhs.startLine && - startSample == rhs.startSample && - endLine == rhs.endLine && - endSample == rhs.endSample && - identifier == rhs.identifier); -} - -Segment* Segment::clone() const -{ - return new Segment(*this); -} - -AreaPlane::AreaPlane() : - referencePoint(Init::undefined()), - xDirection(new AreaDirectionParameters()), - yDirection(new AreaDirectionParameters()), - orientation(OrientationType::NOT_SET) -{ -} - -AreaPlane* AreaPlane::clone() const -{ - return new AreaPlane(*this); -} - -types::RowCol AreaPlane::getAdjustedReferencePoint() const -{ - types::RowCol refPt = referencePoint.rowCol; - - // NOTE: The calculation done by SICD producers appears to be - // orpRow = (numRows + 1) / 2.0 - // This gives you a pixel-centered, 1-based ORP. We want - // pixel-centered 0-based. More generally than this, we need to - // account for the SICD FirstLine/FirstSample offset - // - refPt.row -= gsl::narrow_cast(xDirection->first); - refPt.col -= gsl::narrow_cast(yDirection->first); - - return refPt; -} - -const Segment& AreaPlane::getSegment(const std::string& segmentId) const -{ - for (size_t ii = 0; ii < segmentList.size(); ++ii) - { - if (segmentList[ii].get() && segmentList[ii]->identifier == segmentId) - { - return *segmentList[ii]; - } - } - throw except::Exception(Ctxt("No segment with identifier " + segmentId)); -} - -void AreaPlane::rotateToShadowsDown() -{ - switch(orientation) - { - case OrientationType::RIGHT: - rotateCCW(); - rotateCCW(); - rotateCCW(); - break; - case OrientationType::UP: - rotateCCW(); - rotateCCW(); - break; - case OrientationType::LEFT: - rotateCCW(); - break; - default: - break; - } -} - -void AreaPlane::rotateCCW() -{ - switch (orientation) - { - case OrientationType::LEFT: - orientation = OrientationType::DOWN; - break; - case OrientationType::DOWN: - orientation = OrientationType::RIGHT; - break; - case OrientationType::RIGHT: - orientation = OrientationType::UP; - break; - case OrientationType::UP: - orientation = OrientationType::LEFT; - break; - default: - break; - } - referencePoint.rowCol = rotatePixel(yDirection->elements, referencePoint.rowCol); - - std::swap(yDirection->elements, xDirection->elements); - std::swap(yDirection->spacing, xDirection->spacing); - std::swap(yDirection->unitVector, xDirection->unitVector); - xDirection->unitVector *= -1; - - for (size_t ii = 0; ii < segmentList.size(); ++ii) - { - segmentList[ii]->rotateCCW(xDirection->elements); - } -} - -void Segment::rotateCCW(size_t numColumns) -{ - /* - * 5 wth -- ! is reference corner - * !----- | | 2 right, 1 down becomes - * | . | 2 ht. --> | | 1 right, 2 up - * | | | | - * ------ |. | - * | | - * !-- - */ - - const auto numColumns_ = gsl::narrow(numColumns); - const six::RowColDouble start(types::RowCol(numColumns_ - 1 - endSample, startLine)); - const six::RowColDouble end(types::RowCol(numColumns_ - 1 - startSample, endLine)); - startLine = gsl::narrow_cast(start.row); - startSample = gsl::narrow_cast(start.col); - endLine = gsl::narrow_cast(end.row); - endSample = gsl::narrow_cast(end.col); -} - - -Area::Area() -{ - const LatLonAlt initial = Init::undefined(); - for (size_t ii = 0; ii < LatLonAltCorners::NUM_CORNERS; ++ii) - { - acpCorners.getCorner(ii) = initial; - } -} - -Area* Area::clone() const -{ - return new Area(*this); -} - -RadarCollection* RadarCollection::clone() const -{ - return new RadarCollection(*this); -} - -bool RadarCollection::operator==(const RadarCollection& rhs) const -{ - return (refFrequencyIndex == rhs.refFrequencyIndex && - txFrequencyMin == rhs.txFrequencyMin && - txFrequencyMax == rhs.txFrequencyMax && - txPolarization == rhs.txPolarization && - polarizationHVAnglePoly == rhs.polarizationHVAnglePoly && - txSequence == rhs.txSequence && - waveform == rhs.waveform && - rcvChannels == rhs.rcvChannels && - area == rhs.area && - parameters == rhs.parameters); -} - -double RadarCollection::waveformMax() const -{ - double derivedMax = -std::numeric_limits::infinity(); - for (size_t ii = 0; ii < waveform.size(); ++ii) - { - if (waveform[ii].get() != nullptr) - { - derivedMax = std::max(derivedMax, - waveform[ii]->txFrequencyStart + - waveform[ii]->txRFBandwidth); - } - } - return derivedMax; -} - -double RadarCollection::waveformMin() const -{ - double derivedMin = std::numeric_limits::infinity(); - for (size_t ii = 0; ii < waveform.size(); ++ii) - { - if (waveform[ii].get() != nullptr) - { - derivedMin = std::min(derivedMin, - waveform[ii]->txFrequencyStart); - } - } - return derivedMin; -} - -void RadarCollection::fillDerivedFields() -{ - // Transmit bandwidth - if (!waveform.empty()) - { - if (Init::isUndefined(txFrequencyMin)) - { - txFrequencyMin = waveformMin(); - } - if (Init::isUndefined(txFrequencyMax)) - { - txFrequencyMax = waveformMax(); - } - - for (size_t ii = 0; ii < waveform.size(); ++ii) - { - if (waveform[ii].get() != nullptr) - { - waveform[ii]->fillDerivedFields(); - } - } - } - - if (waveform.size() == 1 && - waveform[0].get() != nullptr) - { - if (Init::isUndefined(waveform[0]->txFrequencyStart)) - { - waveform[0]->txFrequencyStart = txFrequencyMin; - } - if (Init::isUndefined(waveform[0]->txRFBandwidth)) - { - waveform[0]->txRFBandwidth = txFrequencyMax - txFrequencyMin; - } - } -} - -bool RadarCollection::validate(logging::Logger& log) const -{ - bool valid = true; - std::ostringstream messageBuilder; - - // 2.8 Waveform description consistency - const auto wfMin = waveformMin(); - const auto wfMax = waveformMax(); - - // 2.8.1 - if (wfMin != std::numeric_limits::infinity() && - std::abs((wfMin / txFrequencyMin) - 1) > WF_TOL) - { - messageBuilder.str(""); - messageBuilder << WF_INCONSISTENT_STR << std::endl - << "SICD.RadarCollection.Waveform.WFParameters.TxFreqStart: " - << wfMin << std::endl - << "SICD.RadarCollection.TxFrequency.Min: " << txFrequencyMin - << std::endl; - log.error(messageBuilder.str()); - valid = false; - } - - //2.8.2 - if (wfMax != -std::numeric_limits::infinity() && - std::abs((wfMax / txFrequencyMax) - 1) > WF_TOL) - { - messageBuilder.str(""); - messageBuilder << WF_INCONSISTENT_STR << std::endl - << "SICD.RadarCollection.Waveform.WFParameters.TxFreqStart" - << " + TxFRBandwidth: " << wfMax << std::endl - << "SICD.RadarCollection.TxFrequency.Max: " - << txFrequencyMax << std::endl; - log.error(messageBuilder.str()); - valid = false; - } - - //2.8.6 - //Absolute frequencies must be positive - if (six::Init::isUndefined(refFrequencyIndex) && txFrequencyMin <= 0) - { - messageBuilder.str(""); - messageBuilder << WF_INCONSISTENT_STR << std::endl - << "SICD.RadarCollection.txFrequencyMin: " - << txFrequencyMin << std::endl; - log.error(messageBuilder.str()); - valid = false; - } - - for (size_t ii = 0; ii < waveform.size(); ++ii) - { - if (waveform[ii].get()) - { - valid = waveform[ii]->validate(refFrequencyIndex, log) && valid; - } - } - return valid; -} -} -} +/* ========================================================================= + * This file is part of six.sicd-c++ + * ========================================================================= + * + * (C) Copyright 2004 - 2014, MDA Information Systems LLC + * + * six.sicd-c++ is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; If not, + * see . + * + */ +#include + +#include +#include + +#undef min +#undef max + +namespace +{ +template +types::RowCol rotatePixel(size_t origNumCols, const types::RowCol& pixel) +{ + types::RowCol rotatedPixel; + rotatedPixel.col = pixel.row; + rotatedPixel.row = static_cast(origNumCols) - pixel.col; + return rotatedPixel; +} +} + +namespace six +{ +namespace sicd +{ +TxStep::TxStep() : + waveformIndex(Init::undefined()), + txPolarization(PolarizationType::NOT_SET) +{ +} + +TxStep* TxStep::clone() const +{ + return new TxStep(*this); +} + +WaveformParameters::WaveformParameters() : + txPulseLength(Init::undefined()), + txRFBandwidth(Init::undefined()), + txFrequencyStart(Init::undefined()), + txFMRate(Init::undefined()), + rcvDemodType(DemodType::NOT_SET), + rcvWindowLength(Init::undefined()), + adcSampleRate(Init::undefined()), + rcvIFBandwidth(Init::undefined()), + rcvFrequencyStart(Init::undefined()), + rcvFMRate(Init::undefined()) +{ +} + +const double WaveformParameters::WF_TOL = 1e-3; +const double WaveformParameters::WGT_TOL = 1e-3; +const char WaveformParameters::WF_INCONSISTENT_STR[] = + "Waveform fields not consistent"; + +const double RadarCollection::WF_TOL = 1e-3; +const char RadarCollection::WF_INCONSISTENT_STR[] = + "Waveform fields not consistent"; + +bool WaveformParameters::operator==(const WaveformParameters& rhs) const +{ + return (txPulseLength == rhs.txPulseLength && + txRFBandwidth == rhs.txRFBandwidth && + txFrequencyStart == rhs.txFrequencyStart && + txFMRate == rhs.txFMRate && + rcvDemodType == rhs.rcvDemodType && + rcvWindowLength == rhs.rcvWindowLength && + adcSampleRate == rhs.adcSampleRate && + rcvIFBandwidth == rhs.rcvIFBandwidth && + rcvFrequencyStart == rhs.rcvFrequencyStart && + rcvFMRate == rhs.rcvFMRate); +} + +WaveformParameters* WaveformParameters::clone() const +{ + return new WaveformParameters(*this); +} + +void WaveformParameters::fillDerivedFields() +{ + if (rcvDemodType == DemodType::CHIRP && + Init::isUndefined(rcvFMRate)) + { + rcvFMRate = 0; + } + + if (rcvFMRate == 0 && + rcvDemodType == DemodType::NOT_SET) + { + rcvDemodType = DemodType::CHIRP; + } + + if (Init::isUndefined(txRFBandwidth) && + !Init::isUndefined(txPulseLength) && + !Init::isUndefined(txFMRate)) + { + txRFBandwidth = txPulseLength * txFMRate; + } + + if (!Init::isUndefined(txRFBandwidth) && + Init::isUndefined(txPulseLength) && + !Init::isUndefined(txFMRate)) + { + txPulseLength = txRFBandwidth / txFMRate; + } + + if (!Init::isUndefined(txRFBandwidth) && + !Init::isUndefined(txPulseLength) && + Init::isUndefined(txFMRate)) + { + txFMRate = txRFBandwidth / txPulseLength; + } +} + +bool WaveformParameters::validate(int refFrequencyIndex, + logging::Logger& log) const +{ + bool valid = true; + std::ostringstream messageBuilder; + + //2.8.3 + if (std::abs(txRFBandwidth / (txPulseLength * txFMRate) - 1) > WF_TOL) + { + messageBuilder.str(""); + messageBuilder << WF_INCONSISTENT_STR << std::endl + << "SICD.RadarCollection.Waveform.WFParameters.TxFRBandwidth: " + << txRFBandwidth << std::endl + << "SICD.RadarCollection.TxFrequency.txFMRate * txPulseLength: " + << txFMRate * txPulseLength << std::endl; + log.error(messageBuilder.str()); + valid = false; + } + + //2.8.4 + if (rcvDemodType == DemodType::CHIRP && + rcvFMRate != 0) + { + messageBuilder.str(""); + messageBuilder << WF_INCONSISTENT_STR << std::endl + << "SICD.RadarCollection.Waveform.WFParameters.RcvDemodType: " + << rcvDemodType << std::endl + << "SICD.RadarCollection.Waveform.WFParameters.RcvFMRate: " + << rcvFMRate << std::endl; + log.error(messageBuilder.str()); + valid = false; + } + + //2.8.5 + if (rcvDemodType == DemodType::STRETCH && + std::abs(rcvFMRate / txFMRate - 1) > WGT_TOL) + { + messageBuilder.str(""); + messageBuilder << WF_INCONSISTENT_STR << std::endl + << "SICD.RadarCollection.Waveform.WFParameters.RcvDemodType: " + << rcvDemodType << std::endl + << "SICD.RadarCollection.Waveform.WFParameters.RcvFMRate: " + << rcvFMRate << std::endl + << "SICD.RadarCollection.Waveform.WFParameters.TxFMRate: " + << txFMRate << std::endl; + log.error(messageBuilder.str()); + valid = false; + } + + //2.8.7 + //Absolute frequencies must be positive + if (six::Init::isUndefined(refFrequencyIndex) && + txFrequencyStart <= 0) + { + messageBuilder.str(""); + messageBuilder << WF_INCONSISTENT_STR << std::endl + << "SICD.RadarCollection.txFreqStart: " + << txFrequencyStart << std::endl; + log.error(messageBuilder.str()); + valid = false; + } + + //2.8.8 + //Absolute frequencies must be positive + if (six::Init::isUndefined(refFrequencyIndex) && + rcvFrequencyStart <= 0) + { + messageBuilder.str(""); + messageBuilder << WF_INCONSISTENT_STR << std::endl + << "SICD.RadarCollection.rcvFreqStart: " + << rcvFrequencyStart << std::endl; + log.error(messageBuilder.str()); + valid = false; + } + + //2.8.9 + if (six::Init::isDefined(txPulseLength) && (txPulseLength > rcvWindowLength)) // TxPulseLength is optional + { + messageBuilder.str(""); + messageBuilder << WF_INCONSISTENT_STR << std::endl + << "SICD.RadarCollection.Waveform.WFParameters.TxPulseLength: " + << txPulseLength << std::endl + << "SICD.RadarCollection.Waveform.WFPArameters.RcvWindowLength: " + << rcvWindowLength << std::endl; + log.error(messageBuilder.str()); + valid = false; + } + + //2.8.10 + if (six::Init::isDefined(rcvIFBandwidth) && (rcvIFBandwidth > adcSampleRate)) // RcvIFBandwidth is optional + { + messageBuilder.str(""); + messageBuilder << WF_INCONSISTENT_STR << std::endl + << "SICD.RadarCollection.Waveform.WFParameters.RcvIFBandwidth: " + << rcvIFBandwidth << std::endl + << "SICD.RadarCollection.Waveform.WFPArameters.ADCSampleRate: " + << adcSampleRate << std::endl; + log.error(messageBuilder.str()); + valid = false; + } + + //2.8.11 + if (rcvDemodType == DemodType::CHIRP && txRFBandwidth > adcSampleRate) + { + messageBuilder.str(""); + messageBuilder << WF_INCONSISTENT_STR << std::endl + << "SICD.RadarCollection.Waveform.WFParameters.RcvDemodType: " + << rcvDemodType << std::endl + << "SICD.RadarCollection.Waveform.WFParameters.TxRFBandwidth: " + << txRFBandwidth << std::endl + << "SICD.RadarCollection.Waveform.WFPArameters.ADCSampleRate: " + << adcSampleRate << std::endl; + log.error(messageBuilder.str()); + valid = false; + } + + //2.8.12 + if (six::Init::isDefined(rcvFrequencyStart)) // RcvFreqStart is optional + { + const auto freq_tol = (rcvWindowLength - txPulseLength) * txFMRate; + if (rcvFrequencyStart >= (txFrequencyStart + txRFBandwidth + freq_tol) || + rcvFrequencyStart <= txFrequencyStart - freq_tol) + { + messageBuilder.str(""); + messageBuilder << WF_INCONSISTENT_STR << std::endl + << "SICD.RadarCollection.Waveform.WFParameters.RcvFreqStart: " + << rcvFrequencyStart << std::endl; + log.error(messageBuilder.str()); + valid = false; + } + } + + return valid; +} + +ChannelParameters::ChannelParameters() : + txRcvPolarization(DualPolarizationType::NOT_SET), + rcvAPCIndex(Init::undefined()) +{ +} + +ChannelParameters* ChannelParameters::clone() const +{ + return new ChannelParameters(*this); +} + +AreaDirectionParameters::AreaDirectionParameters() : + unitVector(Init::undefined()), + spacing(Init::undefined()), + elements(Init::undefined()), + first(Init::undefined()) +{ +} + +AreaDirectionParameters* AreaDirectionParameters::clone() const +{ + return new AreaDirectionParameters(*this); +} + +std::ostream& operator<< (std::ostream& os, const AreaDirectionParameters& d) +{ + os << "AreaDirectionParameters::\n" + << " unitVector: " << toString(d.unitVector) << "\n" + << " spacing : " << d.spacing << "\n" + << " elements : " << d.elements << "\n" + << " first : " << d.first << "\n"; + return os; +} + +Segment::Segment() : + startLine(Init::undefined()), + startSample(Init::undefined()), + endLine(Init::undefined()), + endSample(Init::undefined()) +{ +} + +bool Segment::operator==(const Segment& rhs) const +{ + return (startLine == rhs.startLine && + startSample == rhs.startSample && + endLine == rhs.endLine && + endSample == rhs.endSample && + identifier == rhs.identifier); +} + +Segment* Segment::clone() const +{ + return new Segment(*this); +} + +AreaPlane::AreaPlane() : + referencePoint(Init::undefined()), + xDirection(new AreaDirectionParameters()), + yDirection(new AreaDirectionParameters()), + orientation(OrientationType::NOT_SET) +{ +} + +AreaPlane* AreaPlane::clone() const +{ + return new AreaPlane(*this); +} + +types::RowCol AreaPlane::getAdjustedReferencePoint() const +{ + types::RowCol refPt = referencePoint.rowCol; + + // NOTE: The calculation done by SICD producers appears to be + // orpRow = (numRows + 1) / 2.0 + // This gives you a pixel-centered, 1-based ORP. We want + // pixel-centered 0-based. More generally than this, we need to + // account for the SICD FirstLine/FirstSample offset + // + refPt.row -= gsl::narrow_cast(xDirection->first); + refPt.col -= gsl::narrow_cast(yDirection->first); + + return refPt; +} + +const Segment& AreaPlane::getSegment(const std::string& segmentId) const +{ + for (size_t ii = 0; ii < segmentList.size(); ++ii) + { + if (segmentList[ii].get() && segmentList[ii]->identifier == segmentId) + { + return *segmentList[ii]; + } + } + throw except::Exception(Ctxt("No segment with identifier " + segmentId)); +} + +void AreaPlane::rotateToShadowsDown() +{ + switch(orientation) + { + case OrientationType::RIGHT: + rotateCCW(); + rotateCCW(); + rotateCCW(); + break; + case OrientationType::UP: + rotateCCW(); + rotateCCW(); + break; + case OrientationType::LEFT: + rotateCCW(); + break; + default: + break; + } +} + +void AreaPlane::rotateCCW() +{ + switch (orientation) + { + case OrientationType::LEFT: + orientation = OrientationType::DOWN; + break; + case OrientationType::DOWN: + orientation = OrientationType::RIGHT; + break; + case OrientationType::RIGHT: + orientation = OrientationType::UP; + break; + case OrientationType::UP: + orientation = OrientationType::LEFT; + break; + default: + break; + } + referencePoint.rowCol = rotatePixel(yDirection->elements, referencePoint.rowCol); + + std::swap(yDirection->elements, xDirection->elements); + std::swap(yDirection->spacing, xDirection->spacing); + std::swap(yDirection->unitVector, xDirection->unitVector); + xDirection->unitVector *= -1; + + for (size_t ii = 0; ii < segmentList.size(); ++ii) + { + segmentList[ii]->rotateCCW(xDirection->elements); + } +} + +void Segment::rotateCCW(size_t numColumns) +{ + /* + * 5 wth -- ! is reference corner + * !----- | | 2 right, 1 down becomes + * | . | 2 ht. --> | | 1 right, 2 up + * | | | | + * ------ |. | + * | | + * !-- + */ + + const auto numColumns_ = gsl::narrow(numColumns); + const six::RowColDouble start(types::RowCol(numColumns_ - 1 - endSample, startLine)); + const six::RowColDouble end(types::RowCol(numColumns_ - 1 - startSample, endLine)); + startLine = gsl::narrow_cast(start.row); + startSample = gsl::narrow_cast(start.col); + endLine = gsl::narrow_cast(end.row); + endSample = gsl::narrow_cast(end.col); +} + + +Area::Area() +{ + const LatLonAlt initial = Init::undefined(); + for (size_t ii = 0; ii < LatLonAltCorners::NUM_CORNERS; ++ii) + { + acpCorners.getCorner(ii) = initial; + } +} + +Area* Area::clone() const +{ + return new Area(*this); +} + +RadarCollection* RadarCollection::clone() const +{ + return new RadarCollection(*this); +} + +bool RadarCollection::operator==(const RadarCollection& rhs) const +{ + return (refFrequencyIndex == rhs.refFrequencyIndex && + txFrequencyMin == rhs.txFrequencyMin && + txFrequencyMax == rhs.txFrequencyMax && + txPolarization == rhs.txPolarization && + polarizationHVAnglePoly == rhs.polarizationHVAnglePoly && + txSequence == rhs.txSequence && + waveform == rhs.waveform && + rcvChannels == rhs.rcvChannels && + area == rhs.area && + parameters == rhs.parameters); +} + +double RadarCollection::waveformMax() const +{ + double derivedMax = -std::numeric_limits::infinity(); + for (size_t ii = 0; ii < waveform.size(); ++ii) + { + if (waveform[ii].get() != nullptr) + { + derivedMax = std::max(derivedMax, + waveform[ii]->txFrequencyStart + + waveform[ii]->txRFBandwidth); + } + } + return derivedMax; +} + +double RadarCollection::waveformMin() const +{ + double derivedMin = std::numeric_limits::infinity(); + for (size_t ii = 0; ii < waveform.size(); ++ii) + { + if (waveform[ii].get() != nullptr) + { + derivedMin = std::min(derivedMin, + waveform[ii]->txFrequencyStart); + } + } + return derivedMin; +} + +void RadarCollection::fillDerivedFields() +{ + // Transmit bandwidth + if (!waveform.empty()) + { + if (Init::isUndefined(txFrequencyMin)) + { + txFrequencyMin = waveformMin(); + } + if (Init::isUndefined(txFrequencyMax)) + { + txFrequencyMax = waveformMax(); + } + + for (size_t ii = 0; ii < waveform.size(); ++ii) + { + if (waveform[ii].get() != nullptr) + { + waveform[ii]->fillDerivedFields(); + } + } + } + + if (waveform.size() == 1 && + waveform[0].get() != nullptr) + { + if (Init::isUndefined(waveform[0]->txFrequencyStart)) + { + waveform[0]->txFrequencyStart = txFrequencyMin; + } + if (Init::isUndefined(waveform[0]->txRFBandwidth)) + { + waveform[0]->txRFBandwidth = txFrequencyMax - txFrequencyMin; + } + } +} + +bool RadarCollection::validate(logging::Logger& log) const +{ + bool valid = true; + std::ostringstream messageBuilder; + + // 2.8 Waveform description consistency + const auto wfMin = waveformMin(); + const auto wfMax = waveformMax(); + + // 2.8.1 + if (wfMin != std::numeric_limits::infinity() && + std::abs((wfMin / txFrequencyMin) - 1) > WF_TOL) + { + messageBuilder.str(""); + messageBuilder << WF_INCONSISTENT_STR << std::endl + << "SICD.RadarCollection.Waveform.WFParameters.TxFreqStart: " + << wfMin << std::endl + << "SICD.RadarCollection.TxFrequency.Min: " << txFrequencyMin + << std::endl; + log.error(messageBuilder.str()); + valid = false; + } + + //2.8.2 + if (wfMax != -std::numeric_limits::infinity() && + std::abs((wfMax / txFrequencyMax) - 1) > WF_TOL) + { + messageBuilder.str(""); + messageBuilder << WF_INCONSISTENT_STR << std::endl + << "SICD.RadarCollection.Waveform.WFParameters.TxFreqStart" + << " + TxFRBandwidth: " << wfMax << std::endl + << "SICD.RadarCollection.TxFrequency.Max: " + << txFrequencyMax << std::endl; + log.error(messageBuilder.str()); + valid = false; + } + + //2.8.6 + //Absolute frequencies must be positive + if (six::Init::isUndefined(refFrequencyIndex) && txFrequencyMin <= 0) + { + messageBuilder.str(""); + messageBuilder << WF_INCONSISTENT_STR << std::endl + << "SICD.RadarCollection.txFrequencyMin: " + << txFrequencyMin << std::endl; + log.error(messageBuilder.str()); + valid = false; + } + + for (size_t ii = 0; ii < waveform.size(); ++ii) + { + if (waveform[ii].get()) + { + valid = waveform[ii]->validate(refFrequencyIndex, log) && valid; + } + } + return valid; +} +} +}