diff --git a/ReleaseNotes.md b/ReleaseNotes.md index 64c5f815ba..81d74f4628 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -2,6 +2,13 @@ # SIX [Release](https://github.com/ngageoint/six-library/releases) Notes +## [Version 3.?.?](https://github.com/ngageoint/six-library/releases/tag/SIX-3.?.?); ??? ?, 202? +* [coda-oss](https://github.com/mdaus/coda-oss) version [202?-??-??](https://github.com/mdaus/coda-oss/releases/tag/2023-??-??) +* [nitro](https://github.com/mdaus/nitro) version [2.?.?](https://github.com/mdaus/nitro/releases/tag/NITRO-2.?.?) +* Prepare for deprecating [`std::complex`](https://en.cppreference.com/w/cpp/numeric/complex), et. al. +* Allow XML metadata to be parsed with `preserveCharacterData(true)` to keep white-space. +* Added support for [CPHD 1.1.0](https://nsgreg.nga.mil/doc/view?i=5388) XML metadata. + ## [Version 3.2.3](https://github.com/ngageoint/six-library/releases/tag/SIX-3.2.3); June 5, 2023 * [coda-oss](https://github.com/mdaus/coda-oss) version [2023-06-05](https://github.com/mdaus/coda-oss/releases/tag/2023-06-05) * [nitro](https://github.com/mdaus/nitro) version [2.11.3](https://github.com/mdaus/nitro/releases/tag/NITRO-2.11.3) diff --git a/docs/NGA.STND.0068-1_1.1.0_CPHD_DIDD_FINAL.pdf b/docs/NGA.STND.0068-1_1.1.0_CPHD_DIDD_FINAL.pdf new file mode 100644 index 0000000000..b68b1c4c9d Binary files /dev/null and b/docs/NGA.STND.0068-1_1.1.0_CPHD_DIDD_FINAL.pdf differ diff --git a/six/modules/c++/cphd/conf/schema/CPHD_schema_V1.1.0_2021_11_30.xsd b/six/modules/c++/cphd/conf/schema/CPHD_schema_V1.1.0_2021_11_30.xsd new file mode 100644 index 0000000000..f604494f20 --- /dev/null +++ b/six/modules/c++/cphd/conf/schema/CPHD_schema_V1.1.0_2021_11_30.xsd @@ -0,0 +1,1254 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/six/modules/c++/cphd/include/cphd/Antenna.h b/six/modules/c++/cphd/include/cphd/Antenna.h index 8863175398..300936e05a 100644 --- a/six/modules/c++/cphd/include/cphd/Antenna.h +++ b/six/modules/c++/cphd/include/cphd/Antenna.h @@ -20,14 +20,18 @@ * */ -#ifndef __CPHD_ANTENNA_H__ -#define __CPHD_ANTENNA_H__ +#pragma once +#ifndef SIX_cphd_Antenna_h_INCLUDED_ +#define SIX_cphd_Antenna_h_INCLUDED_ + +#include #include #include -#include +#include #include +#include #include #include @@ -43,7 +47,7 @@ namespace cphd * AntCoordFrame used by CPHD, representing the tag * . */ -struct AntCoordFrame +struct AntCoordFrame final { //! Constructor AntCoordFrame(); @@ -51,9 +55,10 @@ struct AntCoordFrame //! Equality operators bool operator==(const AntCoordFrame& other) const { - return identifier == other.identifier && - xAxisPoly == other.xAxisPoly && - yAxisPoly == other.yAxisPoly; + return (identifier == other.identifier) + && (xAxisPoly == other.xAxisPoly) + && (yAxisPoly == other.yAxisPoly) + && (useACFPVP == other.useACFPVP); } bool operator!=(const AntCoordFrame& other) const { @@ -71,6 +76,9 @@ struct AntCoordFrame //!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 }; /* @@ -118,8 +126,90 @@ struct AntPhaseCenter * AntPattern used by CPHD, representing the tag * . */ -struct AntPattern +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 @@ -202,6 +292,15 @@ struct AntPattern //! 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; @@ -264,9 +363,12 @@ struct Antenna //! 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 +#endif // SIX_cphd_Antenna_h_INCLUDED_ diff --git a/six/modules/c++/cphd/include/cphd/CPHDXMLParser.h b/six/modules/c++/cphd/include/cphd/CPHDXMLParser.h index 3d4d85f023..6961f0f1e0 100644 --- a/six/modules/c++/cphd/include/cphd/CPHDXMLParser.h +++ b/six/modules/c++/cphd/include/cphd/CPHDXMLParser.h @@ -98,11 +98,21 @@ class CPHDXMLParser : public six::XMLParser XMLElem toXML(const Global& obj, XMLElem parent); XMLElem toXML(const SceneCoordinates& obj, XMLElem parent); XMLElem toXML(const Data& obj, XMLElem parent); + XMLElem toXML(const six::XsElement_minOccurs0&, xml::lite::Element& parent); + XMLElem toXML(const Polarization&, xml::lite::Element& parent); XMLElem toXML(const Channel& obj, XMLElem parent); + XMLElem toXML(const six::XsElement&, xml::lite::Element& parent); + XMLElem toXML(const six::XsElement&, xml::lite::Element& parent); + XMLElem toXML(const six::XsElement_minOccurs0&, xml::lite::Element& parent); + XMLElem toXML(const six::XsElement_minOccurs0&, xml::lite::Element& parent); XMLElem toXML(const Pvp& obj, XMLElem parent); + void createSupportArray(const std::vector&, const std::string& tag, xml::lite::Element& parent); XMLElem toXML(const SupportArray& obj, XMLElem parent); XMLElem toXML(const Dwell& obj, XMLElem parent); XMLElem toXML(const ReferenceGeometry& obj, XMLElem parent); + XMLElem toXML(const six::XsElement_minOccurs0&, xml::lite::Element& parent); + XMLElem toXML(const six::XsElement_minOccurs0&, xml::lite::Element& parent); + XMLElem toXML(const six::XsElement_minOccurs0&, xml::lite::Element& parent); XMLElem toXML(const Antenna& obj, XMLElem parent); XMLElem toXML(const TxRcv& obj, XMLElem parent); XMLElem toXML(const ErrorParameters& obj, XMLElem parent); @@ -155,6 +165,7 @@ class CPHDXMLParser : public six::XMLParser void parseIAExtent(const xml::lite::Element* extentXML, ImageAreaYExtent& extent) const; void parseChannelParameters(const xml::lite::Element* paramXML, ChannelParameter& param) const; + size_t parsePVPType(const xml::lite::Element&, PVPType&) const; void parsePVPType(Pvp& p, const xml::lite::Element* paramXML, PVPType& param) const; void parsePVPType(Pvp& p, const xml::lite::Element* paramXML) const; bool parseOptionalPVPType(const xml::lite::Element* parent, const std::string& tag, Pvp& p, PVPType& param) const; @@ -164,7 +175,18 @@ class CPHDXMLParser : public six::XMLParser void parsePlatform(const xml::lite::Element* platXML, ErrorParameters::Bistatic::Platform& plat) const; void parseSupportArrayParameter(const xml::lite::Element* paramXML, SupportArrayParameter& param, bool additionalFlag) const; + std::vector parseSupportArray(const std::string& tag, const xml::lite::Element&) const; void parseTxRcvParameter(const xml::lite::Element* paramXML, ParameterType& param) const; + void parsePolarization(const xml::lite::Element& polarizationXML, Polarization&) const; + + void parse(const xml::lite::Element&, six::XsElement_minOccurs0&) const; + void parse(const xml::lite::Element&, six::XsElement_minOccurs0&) const; + void parse(const xml::lite::Element&, six::XsElement_minOccurs0&) const; + void parse(const xml::lite::Element&, six::XsElement_minOccurs0&) const; + void parse(const xml::lite::Element&, six::XsElement&) const; + void parse(const xml::lite::Element&, six::XsElement&) const; + void parse(const xml::lite::Element&, six::XsElement_minOccurs0&) const; + void parse(const xml::lite::Element&, six::XsElement_minOccurs0&) const; private: six::SICommonXMLParser10x mCommon; diff --git a/six/modules/c++/cphd/include/cphd/Channel.h b/six/modules/c++/cphd/include/cphd/Channel.h index be8ab5d346..84e3dd7faa 100644 --- a/six/modules/c++/cphd/include/cphd/Channel.h +++ b/six/modules/c++/cphd/include/cphd/Channel.h @@ -19,30 +19,66 @@ * see . * */ -#ifndef __CPHD_CHANNEL_H__ -#define __CPHD_CHANNEL_H__ -#include +#pragma once +#ifndef SIX_cphd_Channel_h_INCLUDED_ +#define SIX_cphd_Channel_h_INCLUDED_ + +#include #include +#include + +#include + #include #include #include namespace cphd { +/* +* \struct PolRefType +* +* \brief Polarization parameters for the pulse for the reference signal vector. +* (New in CPHD 1.1.0) +*/ +struct PolRef final +{ + bool operator==(const PolRef& other) const + { + return (ampH == other.ampH) + && (ampV == other.ampV) + && (phaseV == other.phaseV); + } + bool operator!=(const PolRef& other) const + { + return !(*this == other); + } + + //! E-field relative amplitude in H direction + six::XsElement ampH{ "AmpH" }; + + //! E-field relative amplitude in V direction + six::XsElement ampV{ "AmpV" }; + + //! Relative phase of the V E-field relative to the H E-field + six::XsElement phaseV{ "PhaseV" }; +}; /* * \struct Polarization * * \brief Polarization of the signals that formed the signal array. */ -struct Polarization +struct Polarization final { //! Equality operator bool operator==(const Polarization& other) const { - return txPol == other.txPol && - rcvPol == other.rcvPol; + return (txPol == other.txPol) + && (rcvPol == other.rcvPol) + && (txPolRef == other.txPolRef) + && (rcvPolRef == other.rcvPolRef); } bool operator!=(const Polarization& other) const { @@ -54,6 +90,12 @@ struct Polarization //! Receive polarization for the channel. PolarizationType rcvPol; + + //! Transmit polarization parameters for the transmit pulse for the reference signal vector (v_CH_REF). See Section 7.2.5. + six::XsElement_minOccurs0 txPolRef { "TxPolRef" }; // new in CPHD 1.1.0 + + //! Receive polarization parameters for the received signals for the reference signal vector (v_CH_REF). See Section 7.2.5. + six::XsElement_minOccurs0 rcvPolRef { "RcvPolRef" }; // new in CPHD 1.1.0 }; /* @@ -147,8 +189,10 @@ struct DwellTimes // Equality operator bool operator==(const DwellTimes& other) const { - return codId == other.codId && - dwellId == other.dwellId; + return (codId == other.codId) + && (dwellId == other.dwellId) + && (dtaId == other.dtaId) + && (useDTA == other.useDTA); } bool operator!=(const DwellTimes& other) const { @@ -162,6 +206,14 @@ struct DwellTimes //! Identifier of the dwell Time polynomial that //! maps reference surface position to dwell time std::string dwellId; + + //! Identifier of the Dwell Time support array that specifies COD times and + //! Dwell Times for a grid of points on the reference surface + six::XsElement_minOccurs0 dtaId { "DTAId" }; // new in CPHD 1.1.0 + + //! Indicates the provided Dwell Time array provides a more + //! accurate description dwell times for the channel. + six::XsElement_minOccurs0 useDTA { "UseDTA" }; // new in CPHD 1.1.0 }; /* @@ -520,6 +572,7 @@ struct Channel }; //! Ostream operators +std::ostream& operator<< (std::ostream& os, const PolRef& p); std::ostream& operator<< (std::ostream& os, const Polarization& p); std::ostream& operator<< (std::ostream& os, const TOAExtended& t); std::ostream& operator<< (std::ostream& os, const DwellTimes& d); @@ -531,4 +584,4 @@ std::ostream& operator<< (std::ostream& os, const ChannelParameter& c); std::ostream& operator<< (std::ostream& os, const Channel& c); } -#endif +#endif // SIX_cphd_Channel_h_INCLUDED_ diff --git a/six/modules/c++/cphd/include/cphd/Enums.h b/six/modules/c++/cphd/include/cphd/Enums.h index 55321c3c62..3c5fe2da2f 100644 --- a/six/modules/c++/cphd/include/cphd/Enums.h +++ b/six/modules/c++/cphd/include/cphd/Enums.h @@ -133,6 +133,10 @@ SIX_Enum_BEGIN_DEFINE(PolarizationType) RHC = 5, LHC = 6, UNSPECIFIED = 7, + // Making these new values larger than RHC, LHC, and UNSPECIFIED in case + // somebody is using the integeral values (5, 6, and 6). + S = 8, // CPHD 1.1.0 + E = 9, // CPHD 1.1.0 SIX_Enum_END_enum SIX_Enum_BEGIN_string_to_value @@ -143,6 +147,8 @@ SIX_Enum_BEGIN_DEFINE(PolarizationType) SIX_Enum_map_entry_(RHC), SIX_Enum_map_entry_(LHC), SIX_Enum_map_entry_(UNSPECIFIED), + SIX_Enum_map_entry_(S), + SIX_Enum_map_entry_(E), SIX_Enum_END_string_to_value SIX_Enum_END_DEFINE(PolarizationType); } diff --git a/six/modules/c++/cphd/include/cphd/ErrorParameters.h b/six/modules/c++/cphd/include/cphd/ErrorParameters.h index d0a3db0ea1..0f4be81343 100644 --- a/six/modules/c++/cphd/include/cphd/ErrorParameters.h +++ b/six/modules/c++/cphd/include/cphd/ErrorParameters.h @@ -20,15 +20,19 @@ * */ -#ifndef __CPHD_ERROR_PARAMETERS_H__ -#define __CPHD_ERROR_PARAMETERS_H__ +#pragma once +#ifndef SIX_cphd_ErrorParameters_h_INCLUDED_ +#define SIX_cphd_ErrorParameters_h_INCLUDED_ + +#include #include #include -#include +#include #include #include +#include #include #include @@ -128,14 +132,14 @@ struct ErrorParameters * * \brief (Conditional) Parameters for CollectType = "BISTATIC" */ - struct Bistatic + struct Bistatic final { /* * \struct RadarSensor * * \brief Error statistics for the Transmit platform */ - struct RadarSensor + struct RadarSensor final { //! Constructor RadarSensor(); @@ -143,16 +147,19 @@ struct ErrorParameters //! Equality operators bool operator==(const RadarSensor& other) const { - return clockFreqSF == other.clockFreqSF && - collectionStartTime == other.collectionStartTime; + return (delayBias == other.delayBias) + && (clockFreqSF == other.clockFreqSF) + && (collectionStartTime == other.collectionStartTime); } bool operator!=(const RadarSensor& other) const { return !((*this) == other); } - //! (Optional) Payload clock frequency scale factor standard - //! deviation + //! 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. @@ -230,4 +237,4 @@ std::ostream& operator<< (std::ostream& os, const six::PosVelError& p); std::ostream& operator<< (std::ostream& os, const ErrorParameters& e); } -#endif +#endif // SIX_cphd_ErrorParameters_h_INCLUDED_ diff --git a/six/modules/c++/cphd/include/cphd/PVP.h b/six/modules/c++/cphd/include/cphd/PVP.h index 77fbd46b41..f19341303c 100644 --- a/six/modules/c++/cphd/include/cphd/PVP.h +++ b/six/modules/c++/cphd/include/cphd/PVP.h @@ -20,17 +20,23 @@ * */ -#ifndef __CPHD_PVP_H__ -#define __CPHD_PVP_H__ +#pragma once +#ifndef SIX_cphd_PVP_h_INCLUDED_ +#define SIX_cphd_PVP_h_INCLUDED_ + +#include #include #include #include -#include + #include #include #include #include +#include + +#include "cphd/Types.h" namespace cphd { @@ -111,12 +117,14 @@ struct PVPType protected: //! Size of parameter - size_t mSize; + 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 * @@ -188,7 +306,7 @@ struct APVPType : PVPType * * Provided for each channel of a given product. */ -struct Pvp +struct Pvp final { /*! * Transmit time for the center of the transmitted pulse relative to the @@ -361,6 +479,12 @@ struct Pvp */ 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 */ @@ -388,7 +512,10 @@ struct Pvp ampSF == other.ampSF && fxN1 == other. fxN1 && fxN2 == other.fxN2 && toaE1 == other.toaE1 && toaE2 == other.toaE2 && tdIonoSRP == other.tdIonoSRP && - signal == other.signal && addedPVP == other.addedPVP; + signal == other.signal + && txAntenna == other.txAntenna + && rcvAntenna == other.rcvAntenna + && addedPVP == other.addedPVP; } bool operator!=(const Pvp& other) const { @@ -482,4 +609,4 @@ 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 +#endif // SIX_cphd_PVP_h_INCLUDED_ diff --git a/six/modules/c++/cphd/include/cphd/SupportArray.h b/six/modules/c++/cphd/include/cphd/SupportArray.h index d1eb462cda..464fe91b93 100644 --- a/six/modules/c++/cphd/include/cphd/SupportArray.h +++ b/six/modules/c++/cphd/include/cphd/SupportArray.h @@ -20,17 +20,21 @@ * */ -#ifndef __CPHD_SUPPORT_ARRAY_H__ -#define __CPHD_SUPPORT_ARRAY_H__ +#pragma once +#ifndef SIX_cphd_SupportArray_h_INCLUDED_ +#define SIX_cphd_SupportArray_h_INCLUDED_ + +#include #include #include #include -#include + +#include + #include #include - namespace cphd { @@ -111,6 +115,14 @@ struct SupportArrayParameter size_t identifier; }; +/*! + * \struct DwellTimeArray + * + * DTA(m,n) Array of COD times(sec) and Dwell Times(sec) for points + * on reference surface. Array coordinates are image area coordinates(IAX, IAY). + */ +using DwellTimeArray = SupportArrayParameter; + /*! * \struct AdditionalSupportArray * @@ -190,14 +202,15 @@ struct AdditionalSupportArray : SupportArrayParameter * array(s) content and grid coordinates. * See section 2.3 */ -struct SupportArray +struct SupportArray final { //! Equality operators bool operator==(const SupportArray& other) const { - return iazArray == other.iazArray && - antGainPhase == other.antGainPhase && - addedSupportArray == other.addedSupportArray; + return (iazArray == other.iazArray) + && (antGainPhase == other.antGainPhase) + && (dwellTimeArray == other.dwellTimeArray) + && (addedSupportArray == other.addedSupportArray); } bool operator!=(const SupportArray& other) const { @@ -210,6 +223,9 @@ struct SupportArray //! Get AGP support array by unique id SupportArrayParameter getAGPSupportArray(const std::string& key) const; + //! Get Dwell Time array by unique id + SupportArrayParameter getDWTSupportArray(const std::string& key) const; + //! Get AGP support array by unique id AdditionalSupportArray getAddedSupportArray(const std::string& key) const; @@ -219,6 +235,9 @@ struct SupportArray //! Vector of AGP type arrays std::vector antGainPhase; + //! Dwell Time Array + std::vector dwellTimeArray; // new in CPHD 1.1.0 + //! Map of additonally defined support arrays std::unordered_map addedSupportArray; }; @@ -229,4 +248,4 @@ std::ostream& operator<< (std::ostream& os, const AdditionalSupportArray& a); std::ostream& operator<< (std::ostream& os, const SupportArray& s); } -#endif +#endif // SIX_cphd_SupportArray_h_INCLUDED_ diff --git a/six/modules/c++/cphd/include/cphd/Types.h b/six/modules/c++/cphd/include/cphd/Types.h index a86a7b0055..7dabacced7 100644 --- a/six/modules/c++/cphd/include/cphd/Types.h +++ b/six/modules/c++/cphd/include/cphd/Types.h @@ -40,9 +40,9 @@ namespace cphd using zfloat = six::zfloat; using zdouble = six::zdouble; using zint16_t = six::zint16_t; -using zint8_t = six::ComplexInteger; // TODO: types::zint8_t; -using zint32_t = six::ComplexInteger; // TODO: types::zint32_t; -using zint64_t = six::ComplexInteger; // TODO: types::zint64_t; +using zint8_t = six::ComplexInteger; +using zint32_t = six::ComplexInteger; +using zint64_t = six::ComplexInteger; typedef six::Vector2 Vector2; @@ -100,6 +100,13 @@ enum class Version }; std::string to_string(Version); // "1.0.0", "1.0.1", "1.1.0" +// Existing code handles this via XML validation, not C++. +using ZeroToOne = double; +using NegHalfToHalf = double; // [-0.5–0.5] +using PositiveDouble = double; +using XsNonNegativeInteger = size_t; // type="xs:nonNegativeInteger"/> +using XsPositiveInteger_fixed2 = size_t; // type="xs:positiveInteger" fixed="2"/> + } diff --git a/six/modules/c++/cphd/source/Antenna.cpp b/six/modules/c++/cphd/source/Antenna.cpp index 90226ed94d..5a5dc9e916 100644 --- a/six/modules/c++/cphd/source/Antenna.cpp +++ b/six/modules/c++/cphd/source/Antenna.cpp @@ -56,7 +56,8 @@ std::ostream& operator<< (std::ostream& os, const AntCoordFrame& a) os << " AntCoordFrame:: \n" << " Identifier : " << a.identifier << "\n" << " XAxisPoly : " << a.xAxisPoly << "\n" - << " YAxisPoly : " << a.yAxisPoly << "\n"; + << " YAxisPoly : " << a.yAxisPoly << "\n" + << a.useACFPVP; return os; } @@ -69,6 +70,28 @@ std::ostream& operator<< (std::ostream& os, const AntPhaseCenter& a) 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" @@ -85,8 +108,11 @@ std::ostream& operator<< (std::ostream& os, const AntPattern& a) << " 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" diff --git a/six/modules/c++/cphd/source/CPHDXMLParser.cpp b/six/modules/c++/cphd/source/CPHDXMLParser.cpp index 419ddb65d3..61a24d3d1e 100644 --- a/six/modules/c++/cphd/source/CPHDXMLParser.cpp +++ b/six/modules/c++/cphd/source/CPHDXMLParser.cpp @@ -19,14 +19,17 @@ * see . * */ +#include + #include +#include + #include #include #include #include #include #include -#include #include #include #include @@ -69,12 +72,13 @@ std::unique_ptr CPHDXMLParser::toXML( 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); } - toXML(metadata.dwell, root); - toXML(metadata.referenceGeometry, root); if (metadata.antenna.get()) { toXML(*(metadata.antenna), root); @@ -99,6 +103,7 @@ std::unique_ptr CPHDXMLParser::toXML( { toXML(*(metadata.matchInfo), root); } + //set the XMLNS root->setNamespacePrefix("", getDefaultURI()); @@ -328,6 +333,32 @@ XMLElem CPHDXMLParser::toXML(const Data& data, XMLElem parent) 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); @@ -348,9 +379,8 @@ XMLElem CPHDXMLParser::toXML(const Channel& channel, XMLElem parent) { createBooleanType("SignalNormal", channel.parameters[ii].signalNormal, parametersXML); } - XMLElem polXML = newElement("Polarization", parametersXML); - createString("TxPol", channel.parameters[ii].polarization.txPol, polXML); - createString("RcvPol", channel.parameters[ii].polarization.rcvPol, polXML); + 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); @@ -372,6 +402,9 @@ XMLElem CPHDXMLParser::toXML(const Channel& channel, XMLElem parent) 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); @@ -438,6 +471,43 @@ XMLElem CPHDXMLParser::toXML(const Channel& channel, XMLElem parent) 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); @@ -486,6 +556,10 @@ XMLElem CPHDXMLParser::toXML(const Pvp& pvp, XMLElem parent) { 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); @@ -494,36 +568,30 @@ XMLElem CPHDXMLParser::toXML(const Pvp& pvp, XMLElem parent) 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); - if (!supports.iazArray.empty()) - { - for (size_t ii = 0; ii < supports.iazArray.size(); ++ii) - { - XMLElem iazArrayXML = newElement("IAZArray", supportsXML); - createInt("Identifier", supports.iazArray[ii].getIdentifier(), iazArrayXML); - createString("ElementFormat", supports.iazArray[ii].elementFormat, iazArrayXML); - createDouble("X0", supports.iazArray[ii].x0, iazArrayXML); - createDouble("Y0", supports.iazArray[ii].y0, iazArrayXML); - createDouble("XSS", supports.iazArray[ii].xSS, iazArrayXML); - createDouble("YSS", supports.iazArray[ii].ySS, iazArrayXML); - } - } - if (!supports.antGainPhase.empty()) - { - for (size_t ii = 0; ii < supports.antGainPhase.size(); ++ii) - { - XMLElem antGainPhaseXML = newElement("AntGainPhase", supportsXML); - createInt("Identifier", supports.antGainPhase[ii].getIdentifier(), antGainPhaseXML); - createString("ElementFormat", supports.antGainPhase[ii].elementFormat, antGainPhaseXML); - createDouble("X0", supports.antGainPhase[ii].x0, antGainPhaseXML); - createDouble("Y0", supports.antGainPhase[ii].y0, antGainPhaseXML); - createDouble("XSS", supports.antGainPhase[ii].xSS, antGainPhaseXML); - createDouble("YSS", supports.antGainPhase[ii].ySS, antGainPhaseXML); - } - } + 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) @@ -637,6 +705,46 @@ XMLElem CPHDXMLParser::toXML(const ReferenceGeometry& refGeo, XMLElem parent) 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); @@ -649,6 +757,7 @@ XMLElem CPHDXMLParser::toXML(const Antenna& antenna, XMLElem parent) 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) { @@ -667,20 +776,31 @@ XMLElem CPHDXMLParser::toXML(const Antenna& antenna, XMLElem parent) { 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); @@ -803,6 +923,7 @@ XMLElem CPHDXMLParser::toXML(const ErrorParameters& errParams, XMLElem parent) 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); @@ -907,16 +1028,16 @@ std::unique_ptr CPHDXMLParser::fromXML( 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"); - XMLElem matchInfoXML = getOptional(root, "MatchInfo"); - 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); @@ -927,6 +1048,7 @@ std::unique_ptr CPHDXMLParser::fromXML( fromXML(pvpXML, cphd->pvp); fromXML(dwellXML, cphd->dwell); fromXML(refGeoXML, cphd->referenceGeometry); + if(supportArrayXML) { cphd->supportArray.reset(new SupportArray()); @@ -952,15 +1074,15 @@ std::unique_ptr CPHDXMLParser::fromXML( cphd->productInfo.reset(new ProductInfo()); fromXML(productInfoXML, *(cphd->productInfo)); } - if(matchInfoXML) - { - cphd->matchInfo.reset(new MatchInformation()); - fromXML(matchInfoXML, *(cphd->matchInfo)); - } 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; } @@ -1290,12 +1412,9 @@ void CPHDXMLParser::fromXML(const xml::lite::Element* dataXML, Data& data) 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); + 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); @@ -1312,6 +1431,40 @@ void CPHDXMLParser::fromXML(const xml::lite::Element* channelXML, Channel& chann } } +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); @@ -1340,6 +1493,9 @@ void CPHDXMLParser::fromXML(const xml::lite::Element* pvpXML, Pvp& pvp) 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); @@ -1427,23 +1583,26 @@ void CPHDXMLParser::fromXML(const xml::lite::Element* refGeoXML, ReferenceGeomet } } -void CPHDXMLParser::fromXML(const xml::lite::Element* supportArrayXML, SupportArray& supportArray) +std::vector CPHDXMLParser::parseSupportArray(const std::string& tag, const xml::lite::Element& parent) const { - std::vector iazArrayXMLVec; - supportArrayXML->getElementsByTagName("IAZArray", iazArrayXMLVec); - supportArray.iazArray.resize(iazArrayXMLVec.size()); - for (size_t ii = 0; ii < iazArrayXMLVec.size(); ++ii) + std::vector elements; + parent.getElementsByTagName(tag, elements); + std::vector supportArray; + supportArray.reserve(elements.size()); + for (const auto& element : elements) { - parseSupportArrayParameter(iazArrayXMLVec[ii], supportArray.iazArray[ii], false); + SupportArrayParameter param; + parseSupportArrayParameter(element, param, false /*additionalFlag*/); + supportArray.push_back(std::move(param)); } + return supportArray; +} - std::vector antGainPhaseXMLVec; - supportArrayXML->getElementsByTagName("AntGainPhase", antGainPhaseXMLVec); - supportArray.antGainPhase.resize(antGainPhaseXMLVec.size()); - for (size_t ii = 0; ii < antGainPhaseXMLVec.size(); ++ii) - { - parseSupportArrayParameter(antGainPhaseXMLVec[ii], supportArray.antGainPhase[ii], false); - } +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); @@ -1467,6 +1626,36 @@ void CPHDXMLParser::fromXML(const xml::lite::Element* supportArrayXML, SupportAr } } +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) { @@ -1493,6 +1682,7 @@ void CPHDXMLParser::fromXML(const xml::lite::Element* antennaXML, Antenna& anten 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 @@ -1522,26 +1712,34 @@ void CPHDXMLParser::fromXML(const xml::lite::Element* antennaXML, Antenna& anten 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"); @@ -1552,6 +1750,7 @@ void CPHDXMLParser::fromXML(const xml::lite::Element* antennaXML, Antenna& anten 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; @@ -1953,6 +2152,8 @@ void CPHDXMLParser::parseChannelParameters( 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) @@ -2041,20 +2242,38 @@ void CPHDXMLParser::parseChannelParameters( } // 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); + paramXML.getElementsByTagName("Polarization", PolarizationXML); for (size_t ii = 0; ii < PolarizationXML.size(); ++ii) { const xml::lite::Element* TxPolXML = getFirstAndOnly(PolarizationXML[ii], "TxPol"); - param.polarization.txPol = PolarizationType::toType(TxPolXML->getCharacterData()); + polarization.txPol = PolarizationType::toType(TxPolXML->getCharacterData()); const xml::lite::Element* RcvPolXML = getFirstAndOnly(PolarizationXML[ii], "RcvPol"); - param.polarization.rcvPol = PolarizationType::toType(RcvPolXML->getCharacterData()); - } + 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 + } } -void CPHDXMLParser::parsePVPType(Pvp& pvp, const xml::lite::Element* paramXML, PVPType& param) const +size_t CPHDXMLParser::parsePVPType(const xml::lite::Element& paramXML, PVPType& param) const { size_t size; size_t offset; @@ -2065,19 +2284,20 @@ void CPHDXMLParser::parsePVPType(Pvp& pvp, const xml::lite::Element* paramXML, P if (param.getSize() != size) { std::ostringstream ostr; - ostr << "Specified size: " << size - << " does not match default size: " - << param.getSize(); + 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(); + 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); } @@ -2104,7 +2324,6 @@ bool CPHDXMLParser::parseOptionalPVPType(const xml::lite::Element* parent, const return false; } - void CPHDXMLParser::parsePlatformParams(const xml::lite::Element* platXML, Bistatic::PlatformParams& plat) const { parseDouble(getFirstAndOnly(platXML, "Time"), plat.time); @@ -2173,6 +2392,7 @@ void CPHDXMLParser::parsePlatform(const xml::lite::Element* platXML, ErrorParame { 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); } diff --git a/six/modules/c++/cphd/source/Channel.cpp b/six/modules/c++/cphd/source/Channel.cpp index 6bee3df5d2..351303a402 100644 --- a/six/modules/c++/cphd/source/Channel.cpp +++ b/six/modules/c++/cphd/source/Channel.cpp @@ -20,6 +20,9 @@ * */ #include + +#include + #include namespace cphd @@ -83,10 +86,17 @@ Channel::Channel() : { } +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"; + << " RcvPol : " << p.rcvPol << "\n" + << p.txPolRef << p.rcvPolRef; return os; } @@ -106,8 +116,10 @@ std::ostream& operator<< (std::ostream& os, const DwellTimes& d) { os << " DwellTimes:: \n" << " CODId : " << d.codId << "\n" - << " DwellId : " << d.dwellId << "\n"; - return os; + << " DwellId : " << d.dwellId << "\n" + << d.dtaId + << d.useDTA; + return os; } std::ostream& operator<< (std::ostream& os, const TgtRefLevel& t) diff --git a/six/modules/c++/cphd/source/ErrorParameters.cpp b/six/modules/c++/cphd/source/ErrorParameters.cpp index af3b6f8605..368773f7a2 100644 --- a/six/modules/c++/cphd/source/ErrorParameters.cpp +++ b/six/modules/c++/cphd/source/ErrorParameters.cpp @@ -48,7 +48,7 @@ static std::ostream& unchecked(std::ostream& os, const six::DecorrType& decorr_) } std::ostream& unchecked(std::ostream& os, const std::optional& decorr) { - return unchecked(os, decorr.value()); + return unchecked(os, *decorr); } static std::ostream& checked(std::ostream& os, const std::string& s, const six::DecorrType& decorr) @@ -112,6 +112,15 @@ std::ostream& operator<< (std::ostream& os, const six::PosVelError& p) 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 : " <txPlatform.posVelErr << "\n" - << " RadarSensor:: \n" - << " ClockFreqSF : " << e.bistatic->txPlatform.radarSensor.clockFreqSF << "\n" - << " CollectionStartTime : " << e.bistatic->txPlatform.radarSensor.collectionStartTime << "\n" + << e.bistatic->txPlatform.radarSensor << "\n" << " RcvPlatform:: \n" << e.bistatic->rcvPlatform.posVelErr << "\n" - << " RadarSensor:: \n" - << " ClockFreqSF : " << e.bistatic->rcvPlatform.radarSensor.clockFreqSF << "\n" - << " CollectionStartTime : " << e.bistatic->rcvPlatform.radarSensor.collectionStartTime << "\n"; + << e.bistatic->rcvPlatform.radarSensor; for (const auto& parameter : e.bistatic->parameter) { os << " Parameter Name : " << parameter.getName() << "\n" diff --git a/six/modules/c++/cphd/source/PVP.cpp b/six/modules/c++/cphd/source/PVP.cpp index f4318bb654..7400ac4bd0 100644 --- a/six/modules/c++/cphd/source/PVP.cpp +++ b/six/modules/c++/cphd/source/PVP.cpp @@ -88,8 +88,7 @@ void Pvp::validate(size_t size, size_t offset) { if(mParamLocations.at(offset + ii) == true) { - throw except::Exception(Ctxt( - "This byte block is occupied")); + throw except::Exception(Ctxt("This byte block is occupied")); } } @@ -100,13 +99,18 @@ void Pvp::validate(size_t size, size_t offset) } } -void Pvp::setOffset(size_t offset, PVPType& param) +void setOffset(PVPType& param, size_t offset) { - validate(param.getSize(), 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(); @@ -258,4 +262,19 @@ std::ostream& operator<< (std::ostream& os, const Pvp& p) } 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/SupportArray.cpp b/six/modules/c++/cphd/source/SupportArray.cpp index 8ff2a8a9cc..82cee42a0b 100644 --- a/six/modules/c++/cphd/source/SupportArray.cpp +++ b/six/modules/c++/cphd/source/SupportArray.cpp @@ -81,28 +81,31 @@ AdditionalSupportArray::AdditionalSupportArray( initializeParams(); } -SupportArrayParameter SupportArray::getIAZSupportArray(const std::string& key) const +static SupportArrayParameter getSupportArray(const std::vector& params, const std::string& key) { size_t keyNum = str::toType(key); - if (iazArray.size() <= keyNum) + if (params.size() <= keyNum) { std::ostringstream oss; oss << "SA_ID was not found " << (key); throw except::Exception(Ctxt(oss.str())); } - return iazArray[keyNum]; + return params[keyNum]; +} + +SupportArrayParameter SupportArray::getIAZSupportArray(const std::string& key) const +{ + return getSupportArray(iazArray, key); } SupportArrayParameter SupportArray::getAGPSupportArray(const std::string& key) const { - size_t keyNum = str::toType(key); - if (antGainPhase.size() <= keyNum) - { - std::ostringstream oss; - oss << "SA_ID was not found " << (key); - throw except::Exception(Ctxt(oss.str())); - } - return antGainPhase[keyNum]; + return getSupportArray(antGainPhase, key); +} + +SupportArrayParameter SupportArray::getDWTSupportArray(const std::string& key) const +{ + return getSupportArray(dwellTimeArray, key); } AdditionalSupportArray SupportArray::getAddedSupportArray(const std::string& key) const @@ -157,6 +160,11 @@ std::ostream& operator<< (std::ostream& os, const SupportArray& s) os << " Ant Gain Phase:: \n" << s.antGainPhase[ii]; } + for (size_t ii = 0; ii < s.dwellTimeArray.size(); ++ii) + { + os << " Dwell Time Array:: \n" + << s.dwellTimeArray[ii]; + } for (auto it = s.addedSupportArray.begin(); it != s.addedSupportArray.end(); ++it) { os << " Added Support Array:: \n" diff --git a/six/modules/c++/cphd/tests/sample_xml/cphd110.xml b/six/modules/c++/cphd/tests/sample_xml/cphd110.xml new file mode 100644 index 0000000000..aa11b6273f --- /dev/null +++ b/six/modules/c++/cphd/tests/sample_xml/cphd110.xml @@ -0,0 +1,849 @@ + + + Collector + Core + MONOSTATIC + + STRIPMAP + Mode + + U + Release + US,GB,AZ + val + + + FX + +1 + + 2013-04-10T08:52:09.000000Z + 2014-04-10T08:52:09.000000Z + 1.300000000000000E00 + 1.500000000000000E00 + + + 9.000000000000000E-01 + 1.700000000000000E00 + + + 3.400000000000000E00 + 6.100000000000000E00 + + + 6.520000000000000E01 + IARP + + + 5.800000000000000E00 + 3.000000000000000E00 + + + + WGS_84 + + + 1.200000000000000E00 + 2.300000000000000E00 + 3.400000000000000E00 + + + 4.500000000000000E01 + -1.020000000000000E02 + 3.400000000000000E00 + + + + + + 1.200000000000000E01 + 2.400000000000000E01 + + + 3.600000000000000E01 + 4.800000000000000E01 + + + + + + 3.500000000000000E00 + 5.300000000000000E00 + + + 5.300000000000000E00 + 3.500000000000000E00 + + + + 1.000000000000000E-01 + 3.000000000000000E-01 + + + 4.000000000000000E-01 + 2.000000000000000E-01 + + + 5.000000000000000E-01 + 9.000000000000000E-01 + + + + + + 1.000000000000000E01 + 1.100000000000000E01 + + + 2.000000000000000E01 + 2.100000000000000E01 + + + 3.000000000000000E01 + 3.100000000000000E01 + + + 4.000000000000000E01 + 4.100000000000000E01 + + + + Grid + + 1.230000000000000E00 + 3.210000000000000E00 + + + 3.140000000000000E00 + 4 + 50 + + + 6.280000000000000E00 + 8 + 100 + + + 2 + + Segment1 + 0 + 1 + 2 + 3 + + + 4.000000000000000E-01 + 6.000000000000000E-01 + + + 8.000000000000000E-01 + 1.200000000000000E00 + + + 1.200000000000000E00 + 1.800000000000000E00 + + + + + Segment2 + 1 + 2 + 3 + 4 + + + 4.000000000000000E-01 + 6.000000000000000E-01 + + + 8.000000000000000E-01 + 1.200000000000000E00 + + + 1.200000000000000E00 + 1.800000000000000E00 + + + + + + + + CI4 + 24 + 2 + Compress + + Channel + 2 + 3 + 0 + 1 + 3 + + + Channel + 2 + 3 + 0 + 1 + 3 + + 3 + + 1.0 + 3 + 4 + 8 + 0 + + + 2.0 + 3 + 4 + 4 + 96 + + + AddedSupportArray + 3 + 4 + 4 + 144 + + + + ChId + true + false + true + + CPI + 1 + false + true + true + false + + X + RHC + + 1.300000000000000E00 + 8.000000000000000E-01 + 5.000000000000000E-01 + 2.700000000000000E00 + + 1.000000000000000E00 + + 1.000000000000000E00 + 2.000000000000000E00 + 1.000000000000000E00 + 2.000000000000000E00 + + + + CODPolynomial + DwellPolynomial + DTAId + true + + + + 3.500000000000000E00 + 5.300000000000000E00 + + + 5.300000000000000E00 + 3.500000000000000E00 + + + + 1.000000000000000E-01 + 3.000000000000000E-01 + + + 4.000000000000000E-01 + 2.000000000000000E-01 + + + 5.000000000000000E-01 + 9.000000000000000E-01 + + + + + TxAPCId + TxAPATId + RcvAPCId + RcvAPATId + + + TxWFId + RcvId + + + 1.200000000000000E01 + + + 5.000000000000000E-01 + 8.000000000000000E-01 + + + 3.000000000000000E-01 + 2.700000000000000E00 + + + 5.000000000000000E-01 + 2.700000000000000E00 + + + + + + Param + Param + + + + + 0 + 1 + F8 + + + 1 + 3 + X=F8;Y=F8;Z=F8; + + + 4 + 3 + X=F8;Y=F8;Z=F8; + + + 7 + 1 + F8 + + + 8 + 3 + X=F8;Y=F8;Z=F8; + + + 11 + 3 + X=F8;Y=F8;Z=F8; + + + 14 + 3 + X=F8;Y=F8;Z=F8; + + + 17 + 1 + F8 + + + 18 + 1 + F8 + + + 19 + 1 + F8 + + + 20 + 1 + F8 + + + 21 + 1 + F8 + + + 22 + 1 + F8 + + + 23 + 1 + F8 + + + 24 + 1 + F8 + + + 25 + 1 + F8 + + + 26 + 1 + F8 + + + newParam1 + 27 + 1 + F8 + + + newParam2 + 28 + 1 + F8 + + + + + 1 + IAZ=F4; + 0.000000000000000E00 + 0.000000000000000E00 + 5.000000000000000E00 + 5.000000000000000E00 + + + 2 + Gain=F4;Phase=F4; + 0.000000000000000E00 + 0.000000000000000E00 + 5.000000000000000E00 + 5.000000000000000E00 + + + AddedSupportArray + F4 + 0.000000000000000E00 + 0.000000000000000E00 + 5.000000000000000E00 + 5.000000000000000E00 + XUnits + YUnits + ZUnits + Additional parameter + Additional parameter + + + + 1 + + codPolynomial1 + + 0.000000000000000E00 + 5.000000000000000E00 + 5.000000000000000E00 + 0.000000000000000E00 + + + 1 + + dwellPolynomial1 + + 0.000000000000000E00 + 2.000000000000000E00 + 3.000000000000000E00 + 0.000000000000000E00 + + + + + + + 1.000000000000000E00 + 2.000000000000000E00 + 3.500000000000000E00 + + + 1.500000000000000E00 + 2.500000000000000E00 + 4.000000000000000E00 + + + 0.000000000000000E00 + 2.300000000000000E01 + 2.500000000000000E01 + + + 1.000000000000000E01 + 1.000000000000000E01 + 1.000000000000000E01 + + + 1.000000000000000E01 + 1.000000000000000E01 + 1.000000000000000E01 + + L + 2.000000000000000E01 + 2.000000000000000E01 + 3.000000000000000E01 + 3.000000000000000E01 + 3.000000000000000E01 + 3.000000000000000E01 + 3.000000000000000E01 + 3.000000000000000E01 + 3.000000000000000E01 + + + + 2 + 1 + 1 + + ACF1 + + + 1.000000000000000E00 + 2.000000000000000E00 + 3.000000000000000E00 + 4.000000000000000E00 + + + 1.000000000000000E00 + 2.000000000000000E00 + 3.000000000000000E00 + 4.000000000000000E00 + + + 1.000000000000000E00 + 0.000000000000000E00 + 3.000000000000000E00 + 0.000000000000000E00 + + + + + 1.000000000000000E00 + 2.000000000000000E00 + + + 1.000000000000000E00 + 2.000000000000000E00 + + + 1.000000000000000E00 + 2.000000000000000E00 + + + true + + + ACF2 + + + 1.000000000000000E00 + 2.000000000000000E00 + + + 1.000000000000000E00 + 2.000000000000000E00 + + + 1.000000000000000E00 + 2.000000000000000E00 + + + + + 1.000000000000000E00 + 2.000000000000000E00 + + + 1.000000000000000E00 + 2.000000000000000E00 + + + 1.000000000000000E00 + 2.000000000000000E00 + + + false + + + APC + ACF1 + + 5.000000000000000E00 + 5.000000000000000E00 + 5.000000000000000E00 + + + + APAT + 2.300000000000000E00 + 2.300000000000000E00 + 1 + 0 + + 1.000000000000000E00 + 2.000000000000000E00 + + + + 5.000000000000000E00 + 0.000000000000000E00 + + + 0.000000000000000E00 + 5.000000000000000E00 + + + + + 0.000000000000000E00 + 1.000000000000000E00 + 1.000000000000000E00 + 5.000000000000000E00 + + + 0.000000000000000E00 + 1.000000000000000E00 + 1.000000000000000E00 + 5.000000000000000E00 + + + + + 0.000000000000000E00 + 1.000000000000000E00 + 1.000000000000000E00 + 5.000000000000000E00 + + + 0.000000000000000E00 + 1.000000000000000E00 + 1.000000000000000E00 + 5.000000000000000E00 + + + + 2.300000000000000E00 + Parameter1 + Parameter2 + + + 2.800000000000000E00 + Parameter1 + Parameter2 + + + + + 1 + + TxWFParam + 3.000000000000000E00 + 2.300000000000000E00 + 1.800000000000000E00 + 1.000000000000000E00 + LHC + 5.000000000000000E00 + + 2 + + RcvParam1 + 3.000000000000000E00 + 2.300000000000000E00 + 2.300000000000000E00 + 1.800000000000000E00 + 1.000000000000000E00 + LHC + 5.000000000000000E00 + + + RcvParam2 + 3.000000000000000E00 + 2.300000000000000E00 + 2.300000000000000E00 + 1.800000000000000E00 + 1.000000000000000E00 + LHC + 5.000000000000000E00 + + + + + + ECF + 1.000000000000000E00 + 1.000000000000000E00 + 1.000000000000000E00 + 1.000000000000000E00 + 1.000000000000000E00 + 1.000000000000000E00 + + 8.000000000000000E-01 + 8.000000000000000E-01 + 8.000000000000000E-01 + 8.000000000000000E-01 + 8.000000000000000E-01 + 8.000000000000000E-01 + 8.000000000000000E-01 + 8.000000000000000E-01 + 8.000000000000000E-01 + 8.000000000000000E-01 + 8.000000000000000E-01 + 8.000000000000000E-01 + 8.000000000000000E-01 + 8.000000000000000E-01 + 8.000000000000000E-01 + + + 5.000000000000000E-01 + 1.000000000000000E00 + + + + 5.000000000000000E-01 + 1.000000000000000E00 + 1.000000000000000E00 + + 5.000000000000000E-01 + 1.000000000000000E00 + + + + 5.000000000000000E00 + 5.000000000000000E00 + + 5.000000000000000E-01 + 1.000000000000000E00 + + + + 5.000000000000000E00 + 5.000000000000000E00 + 5.000000000000000E-01 + + 5.000000000000000E-01 + 1.000000000000000E00 + + + + + + Profile + + Application + 2014-04-10T08:52:09.000000Z + Area51 + Value1 + Value2 + + Value1 + + + 51 + + + + 0.000000000000000E00 + 0.000000000000000E00 + + + 1.000000000000000E-01 + 0.000000000000000E00 + + + 1.000000000000000E-01 + 1.000000000000000E-01 + + + 0.000000000000000E00 + 0.000000000000000E00 + + + + + 04/22 + + + 2.000000000000000E-02 + 3.000000000000000E-02 + + + 8.000000000000000E-02 + 8.000000000000000E-02 + + + + + 09/27 + + + 5.000000000000000E-02 + 2.000000000000000E-02 + + + 5.000000000000000E-02 + 8.000000000000000E-02 + + + + + Main + + 6.000000000000000E-01 + 4.000000000000000E-01 + + + + + + + 1.000000000000000E00 + 1.000000000000000E00 + + + 1.100000000000000E00 + 1.000000000000000E00 + + + 1.100000000000000E00 + 1.100000000000000E00 + + + 1.200000000000000E00 + 1.200000000000000E00 + + + 1.000000000000000E00 + 1.000000000000000E00 + + + + + 2 + + STEREO + 1 + 1 + + CollectionName + 1 + Match1 + + + + COHERENT + 1 + 1 + + CollectionName + 1 + Match1 + + + + diff --git a/six/modules/c++/cphd/unittests/test_cphd_xml_control.cpp b/six/modules/c++/cphd/unittests/test_cphd_xml_control.cpp index 4a4e5edbcd..d1737e76c4 100644 --- a/six/modules/c++/cphd/unittests/test_cphd_xml_control.cpp +++ b/six/modules/c++/cphd/unittests/test_cphd_xml_control.cpp @@ -263,6 +263,7 @@ static std::string testCPHDXMLBody() " \n" " X\n" " RHC\n" +" 0.10.20.3\n" " \n" " 1.300000000000000E00\n" " 8.000000000000000E-01\n" @@ -1046,6 +1047,14 @@ void runTest(const std::string& testName, const std::string& version) TEST_ASSERT_EQ(channel.parameters[0].polarization.rcvPol, cphd::PolarizationType::RHC); + // these are new in CPHD 1.1.0 + TEST_ASSERT_TRUE(has_value(channel.parameters[0].polarization.txPolRef)); + const auto& txPolRef = value(channel.parameters[0].polarization.txPolRef); + TEST_ASSERT_EQ(txPolRef.ampH, 0.1); + TEST_ASSERT_EQ(txPolRef.ampV, 0.2); + TEST_ASSERT_EQ(txPolRef.phaseV, 0.3); + TEST_ASSERT_FALSE(has_value(channel.parameters[0].polarization.rcvPolRef)); + TEST_ASSERT_EQ(channel.parameters[0].fxC, 1.3); TEST_ASSERT_EQ(channel.parameters[0].fxBW, 0.8); TEST_ASSERT_EQ(channel.parameters[0].toaSaved, 2.7); diff --git a/six/modules/c++/six.sicd/include/six/sicd/Antenna.h b/six/modules/c++/six.sicd/include/six/sicd/Antenna.h index b3c78cfb7e..45b79a3526 100644 --- a/six/modules/c++/six.sicd/include/six/sicd/Antenna.h +++ b/six/modules/c++/six.sicd/include/six/sicd/Antenna.h @@ -19,14 +19,19 @@ * see . * */ -#ifndef __SIX_ANTENNA_H__ -#define __SIX_ANTENNA_H__ + +#pragma once +#ifndef SIX_six_sicd_Antenna_h_INCLUDED_ +#define SIX_six_sicd_Antenna_h_INCLUDED_ #include +#include +#include #include "six/Types.h" #include "six/Init.h" #include "six/Parameter.h" +#include "six/XsElement.h" #include @@ -42,15 +47,16 @@ namespace sicd * the DCXPoly is the EB sterring x-axis direction * cosine (DCX) as a function of slow time */ -struct ElectricalBoresight +struct ElectricalBoresight final { //! Constructor ElectricalBoresight(); bool operator==(const ElectricalBoresight& other) const { - return dcxPoly == other.dcxPoly && - dcyPoly == other.dcyPoly; + return (dcxPoly == other.dcxPoly) + && (dcyPoly == other.dcyPoly) + && (useEBPVP == other.useEBPVP); } bool operator!=(const ElectricalBoresight& other) const @@ -63,6 +69,10 @@ struct ElectricalBoresight //! SICD DCYPoly Poly1D dcyPoly; + + //! CPHD 1.1.0 UseEBPVP + //! Indicates the provided EB PVP arrays provide a more accurate description the EB Steering vector vs. time. + six::XsElement_minOccurs0 useEBPVP{ "UseEBPVP" }; }; std::ostream& operator<< (std::ostream& os, const ElectricalBoresight& d); @@ -109,15 +119,16 @@ std::ostream& operator<< (std::ostream& os, const HalfPowerBeamwidths& d); * electronically steered arrays, the EB is steered to * DCX = 0, DCY = 0. */ -struct GainAndPhasePolys +struct GainAndPhasePolys final { //! No init right now, could do that and set const coef to zero GainAndPhasePolys(); bool operator==(const GainAndPhasePolys& other) const { - return gainPoly == other.gainPoly && - phasePoly == other.phasePoly; + return (gainPoly == other.gainPoly) + && (phasePoly == other.phasePoly) + && (antGPId == other.antGPId); } bool operator!=(const GainAndPhasePolys& other) const @@ -132,6 +143,9 @@ struct GainAndPhasePolys //! One way signal phase (in cycles) as a function of DCX and DCY. //! Phase relative to phase at DCX = 0, DCY = 0. Const coeff = 0 always Poly2D phasePoly; + + //! Identifier of the Antenna Gain/Phase support array that specifies the one-way array pattern + six::XsElement_minOccurs0 antGPId {"AntGPId"}; // new in CPHD 1.1.0 }; std::ostream& operator<< (std::ostream& os, const GainAndPhasePolys& d); @@ -251,5 +265,4 @@ struct Antenna } } -#endif - +#endif // SIX_six_sicd_Antenna_h_INCLUDED_ diff --git a/six/modules/c++/six.sicd/source/Antenna.cpp b/six/modules/c++/six.sicd/source/Antenna.cpp index ed665f53c8..58c2ffbcc5 100644 --- a/six/modules/c++/six.sicd/source/Antenna.cpp +++ b/six/modules/c++/six.sicd/source/Antenna.cpp @@ -20,6 +20,9 @@ * */ #include + +#include + #include namespace six @@ -36,7 +39,8 @@ std::ostream& operator<< (std::ostream& os, const ElectricalBoresight& d) { os << "ElectricalBoresight::" << "\n" << " dcxPoly: " << d.dcxPoly << "\n" - << " dcyPoly: " << d.dcyPoly << "\n"; + << " dcyPoly: " << d.dcyPoly << "\n" + << d.useEBPVP; return os; } @@ -63,7 +67,8 @@ GainAndPhasePolys::GainAndPhasePolys() : std::ostream& operator<< (std::ostream& os, const GainAndPhasePolys& d) { os << " gainPoly:\n" << d.gainPoly << "\n" - << " phasePoly:\n" << d.phasePoly << "\n"; + << " phasePoly:\n" << d.phasePoly << "\n" + << d.antGPId; return os; } AntennaParameters::AntennaParameters() : diff --git a/six/modules/c++/six.sicd/unittests/test_valid_sixsicd.cpp b/six/modules/c++/six.sicd/unittests/test_valid_sixsicd.cpp index 4482f7e5e6..f7a64b5556 100644 --- a/six/modules/c++/six.sicd/unittests/test_valid_sixsicd.cpp +++ b/six/modules/c++/six.sicd/unittests/test_valid_sixsicd.cpp @@ -89,12 +89,12 @@ static void test_assert_unmodeled_(const std::string& testName, const six::Unmod TEST_ASSERT_EQ(4.56, Unmodeled.Ycol); TEST_ASSERT_EQ(7.89, Unmodeled.XrowYcol); - const auto& UnmodeledDecor = Unmodeled.UnmodeledDecorr; - TEST_ASSERT(UnmodeledDecor.get() != nullptr); - TEST_ASSERT_EQ(12.34, UnmodeledDecor->Xrow.CorrCoefZero); - TEST_ASSERT_EQ(56.78, UnmodeledDecor->Xrow.DecorrRate); - TEST_ASSERT_EQ(123.4, UnmodeledDecor->Ycol.CorrCoefZero); - TEST_ASSERT_EQ(567.8, UnmodeledDecor->Ycol.DecorrRate); + const auto& unmodeledDecor = Unmodeled.unmodeledDecorr; + TEST_ASSERT(has_value(unmodeledDecor)); + TEST_ASSERT_EQ(12.34, value(unmodeledDecor).Xrow.CorrCoefZero); + TEST_ASSERT_EQ(56.78, value(unmodeledDecor).Xrow.DecorrRate); + TEST_ASSERT_EQ(123.4, value(unmodeledDecor).Ycol.CorrCoefZero); + TEST_ASSERT_EQ(567.8, value(unmodeledDecor).Ycol.DecorrRate); } static void test_assert(const std::string& testName, const six::sicd::ComplexData& complexData) { diff --git a/six/modules/c++/six.sidd/source/DerivedXMLControl.cpp b/six/modules/c++/six.sidd/source/DerivedXMLControl.cpp index ba3c0e54af..d6053ee705 100644 --- a/six/modules/c++/six.sidd/source/DerivedXMLControl.cpp +++ b/six/modules/c++/six.sidd/source/DerivedXMLControl.cpp @@ -397,7 +397,7 @@ std::optional six::sidd300::getISMVersion() const auto ismVersionFromEnv = getISMVersionFromEnv(); if (ismVersionFromEnv.has_value()) { - return *ismVersionFromEnv; + return ismVersionFromEnv; } // Then our global (static) variable; normally this won't be set diff --git a/six/modules/c++/six.sidd/unittests/test_valid_sixsidd.cpp b/six/modules/c++/six.sidd/unittests/test_valid_sixsidd.cpp index 036d1d9391..c2f8fba818 100644 --- a/six/modules/c++/six.sidd/unittests/test_valid_sixsidd.cpp +++ b/six/modules/c++/six.sidd/unittests/test_valid_sixsidd.cpp @@ -122,12 +122,12 @@ static void test_assert_unmodeled_(const std::string& testName, const six::Unmod TEST_ASSERT_EQ(4.56, Unmodeled.Ycol); TEST_ASSERT_EQ(7.89, Unmodeled.XrowYcol); - const auto& UnmodeledDecor = Unmodeled.UnmodeledDecorr; - TEST_ASSERT(UnmodeledDecor.get() != nullptr); - TEST_ASSERT_EQ(12.34, UnmodeledDecor->Xrow.CorrCoefZero); - TEST_ASSERT_EQ(56.78, UnmodeledDecor->Xrow.DecorrRate); - TEST_ASSERT_EQ(123.4, UnmodeledDecor->Ycol.CorrCoefZero); - TEST_ASSERT_EQ(567.8, UnmodeledDecor->Ycol.DecorrRate); + const auto& unmodeledDecor = Unmodeled.unmodeledDecorr; + TEST_ASSERT_TRUE(has_value(unmodeledDecor)); + TEST_ASSERT_EQ(12.34, value(unmodeledDecor).Xrow.CorrCoefZero); + TEST_ASSERT_EQ(56.78, value(unmodeledDecor).Xrow.DecorrRate); + TEST_ASSERT_EQ(123.4, value(unmodeledDecor).Ycol.CorrCoefZero); + TEST_ASSERT_EQ(567.8, value(unmodeledDecor).Ycol.DecorrRate); } static void test_assert_unmodeled(const std::string& testName, const six::sidd::DerivedData& derivedData) { diff --git a/six/modules/c++/six/include/six/Complex.h b/six/modules/c++/six/include/six/Complex.h index 88f1845f20..bd6b5ed8b4 100644 --- a/six/modules/c++/six/include/six/Complex.h +++ b/six/modules/c++/six/include/six/Complex.h @@ -38,7 +38,7 @@ namespace six #ifndef SIX_six_unique_ComplexInteger // Preserve existing behavior where `std::complex` is used. - #define SIX_six_unique_ComplexInteger 0 // TODO: set to 1 or CODA_OSS_types_unique_ComplexInteger + #define SIX_six_unique_ComplexInteger 0 // TODO: set to 1 #endif template #if SIX_six_unique_ComplexInteger @@ -47,7 +47,7 @@ namespace six using ComplexInteger = std::complex; #endif - using zint16_t = ComplexInteger; // TODO: types::zint16_t; + using zint16_t = ComplexInteger; } #endif // SIX_six_Complex_h_INCLUDED_ diff --git a/six/modules/c++/six/include/six/ErrorStatistics.h b/six/modules/c++/six/include/six/ErrorStatistics.h index 64914d6875..3e43256419 100644 --- a/six/modules/c++/six/include/six/ErrorStatistics.h +++ b/six/modules/c++/six/include/six/ErrorStatistics.h @@ -33,6 +33,7 @@ #include "six/Init.h" #include "six/Parameter.h" #include "six/ParameterCollection.h" +#include "six/XsElement.h" namespace six { @@ -256,11 +257,9 @@ struct IonoError */ struct UnmodeledS final { - // By making member names match XML element names, macros can - // help generate boilerplate code. - double Xrow = 0.0; - double Ycol = 0.0; - double XrowYcol = 0.0; + XsElement Xrow{ "Xrow" }; + XsElement Ycol{ "Ycol" }; + XsElement XrowYcol{ "XrowYcol" }; struct Decorr final { @@ -272,7 +271,7 @@ struct UnmodeledS final Xrow_Ycol Xrow; Xrow_Ycol Ycol; }; - mem::ScopedCopyablePtr UnmodeledDecorr; + XsElement_minOccurs0 unmodeledDecorr{ "UnmodeledDecorr" }; }; inline bool operator==(const UnmodeledS::Decorr& lhs, const UnmodeledS::Decorr& rhs) { @@ -291,7 +290,7 @@ inline bool operator==(const UnmodeledS& lhs, const UnmodeledS& rhs) return (lhs.Xrow == rhs.Xrow) && (lhs.Ycol == rhs.Ycol) && (lhs.XrowYcol == rhs.XrowYcol) - && (lhs.UnmodeledDecorr == rhs.UnmodeledDecorr) + && (lhs.unmodeledDecorr == rhs.unmodeledDecorr) ; } inline bool operator!=(const UnmodeledS& lhs, const UnmodeledS& rhs) diff --git a/six/modules/c++/six/include/six/Utilities.h b/six/modules/c++/six/include/six/Utilities.h index f178367eef..3703047d61 100644 --- a/six/modules/c++/six/include/six/Utilities.h +++ b/six/modules/c++/six/include/six/Utilities.h @@ -50,6 +50,7 @@ namespace six { struct Data; // forward + struct ErrorStatistics; /*! * Remaps angles into [0:360] diff --git a/six/modules/c++/six/include/six/XMLParser.h b/six/modules/c++/six/include/six/XMLParser.h index f931e8dbe1..647f551080 100644 --- a/six/modules/c++/six/include/six/XMLParser.h +++ b/six/modules/c++/six/include/six/XMLParser.h @@ -25,7 +25,7 @@ #include -#include +#include #include #include #include @@ -253,17 +253,20 @@ struct XMLParser void parseString(const xml::lite::Element* element, std::string& value) const; void parseString(const xml::lite::Element&, std::string&) const; bool parseString(const xml::lite::Element&, std::u8string&) const; + void parseBooleanType(const xml::lite::Element* element, BooleanType& value) const { assert(element != nullptr); mXmlLite.parseBooleanType(*element, value); } + bool parseOptionalString(const xml::lite::Element& parent, const std::string& tag, std::string& value) const; bool parseOptionalString(const xml::lite::Element* parent, const std::string& tag, std::string& value) const { assert(parent != nullptr); return parseOptionalString(*parent, tag, value); } + template bool parseOptionalInt(const xml::lite::Element* parent, const std::string& tag, T& value) const { @@ -312,6 +315,9 @@ struct XMLParser static XMLElem getFirstAndOnly(const xml::lite::Element* parent, const std::string& tag); static xml::lite::Element& getFirstAndOnly(const xml::lite::Element& parent, const std::string& tag); + void getFirstAndOnly(const xml::lite::Element& parent, const std::string& tag, double&) const; + + /*! * Require an element to be not nullptr * @throw throws an Exception if the element is nullptr @@ -319,6 +325,9 @@ struct XMLParser */ static XMLElem require(XMLElem element, const std::string& name); + const XmlLite& parser() const { return mXmlLite; } + XmlLite& parser() { return mXmlLite; } + private: XmlLite mXmlLite; }; diff --git a/six/modules/c++/six/include/six/XmlLite.h b/six/modules/c++/six/include/six/XmlLite.h index c7fe3be313..033eaaf96c 100644 --- a/six/modules/c++/six/include/six/XmlLite.h +++ b/six/modules/c++/six/include/six/XmlLite.h @@ -39,6 +39,7 @@ #include #include #include +#include namespace six { @@ -203,6 +204,9 @@ struct XmlLite final xml::lite::Element& createDateTime(const std::string& name, const DateTime& p, xml::lite::Element& parent) const; xml::lite::Element& createDate(const std::string& name, const DateTime& p, xml::lite::Element& parent) const; + xml::lite::Element* createOptional(const xml::lite::QName&, const std::optional&, xml::lite::Element& parent) const; + xml::lite::Element* createOptional(const xml::lite::QName&, const std::optional&, xml::lite::Element& parent) const; + template void parseInt(const xml::lite::Element& element, T& value) const { @@ -231,7 +235,10 @@ struct XmlLite final void parseComplex(const xml::lite::Element& element, six::zdouble& value) const; void parseString(const xml::lite::Element* element, std::string& value) const; void parseString(const xml::lite::Element&, std::string&) const; + void parseBooleanType(const xml::lite::Element& element, BooleanType& value) const; + BooleanType parseBooleanType(const xml::lite::Element& element) const; + bool parseBoolean(const xml::lite::Element& element) const; bool parseOptionalString(const xml::lite::Element& parent, const std::string& tag, std::string& value) const; @@ -254,9 +261,10 @@ struct XmlLite final } static xml::lite::Element* getOptional(const xml::lite::Element& parent, const std::string& tag); + static xml::lite::Element* getOptional(const xml::lite::Element& parent, const xml::lite::QName& tag); template - static xml::lite::Element* getOptional_reset(const xml::lite::Element& parent, const std::string& tag, mem::ScopedCopyablePtr& obj) + inline static xml::lite::Element* getOptional_reset(const xml::lite::Element& parent, const std::string& tag, mem::ScopedCopyablePtr& obj) { auto retval = getOptional(parent, tag); if (retval != nullptr) @@ -268,6 +276,7 @@ struct XmlLite final } static xml::lite::Element& getFirstAndOnly(const xml::lite::Element& parent, const std::string& tag); + static xml::lite::Element& getFirstAndOnly(const xml::lite::Element& parent, const xml::lite::QName&); /*! * Require an element to be not nullptr @@ -294,6 +303,18 @@ struct XmlLite final { return createString_(name, p, parent); } + + xml::lite::Element& create(const XmlLite&, const XsElement&, xml::lite::Element& parent); + void getFirstAndOnly(const XmlLite&, const xml::lite::Element&, XsElement&); + + xml::lite::Element* create(const XmlLite&, const XsElement_minOccurs0&, xml::lite::Element& parent); + xml::lite::Element* create(const XmlLite&, const XsElement_minOccurs0&, xml::lite::Element& parent); + xml::lite::Element* create(const XmlLite&, const XsElement_minOccurs0&, xml::lite::Element& parent); + + bool parse(const XmlLite&, const xml::lite::Element&, XsElement_minOccurs0&); + bool parse(const XmlLite&, const xml::lite::Element&, XsElement_minOccurs0&); + bool parse(const XmlLite&, const xml::lite::Element&, XsElement_minOccurs0&); + } #endif // SIX_six_XmlLite_h_INCLUDED_ diff --git a/six/modules/c++/six/include/six/XsElement.h b/six/modules/c++/six/include/six/XsElement.h new file mode 100644 index 0000000000..6601113966 --- /dev/null +++ b/six/modules/c++/six/include/six/XsElement.h @@ -0,0 +1,249 @@ +/* ========================================================================= + * This file is part of six-c++ + * ========================================================================= + * + * (C) Copyright 2004 - 2014, MDA Information Systems LLC + * (C) Copyright 2023, Maxar Technologies, Inc. + * + * 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 . + * + */ +#pragma once +#ifndef SIX_six_XsElement_h_INCLUDED_ +#define SIX_six_XsElement_h_INCLUDED_ + +#include +#include +#include +#include + +#include +#include +#include + +namespace six +{ + +// Make it easier to manipulate a Xml Element: XSD of `` Can be represented in C++ as +// ``` +// struct Foo final +// { XsElement foo {"Foo"}; }; +// ``` +// This is `xs::element` as opposed to `xs:comlexType`, `xs::sequence`, `xs:enumeration`, etc. +template +class XsElement final +{ + xml::lite::QName name_; + T value_{}; + +public: + using value_type = T; + + explicit XsElement(const xml::lite::QName& name) : name_(name) { } + explicit XsElement(const std::string& lName) : XsElement(xml::lite::QName(lName)) { } + XsElement(const xml::lite::QName& name, const value_type& value) : name_(name), value_(value) { } + XsElement(const std::string& lName, const value_type& value) : XsElement(xml::lite::QName(lName), value) { } + ~XsElement() = default; + XsElement(const XsElement&) = default; + XsElement& operator=(const XsElement&) = default; + XsElement(XsElement&&) = default; + XsElement& operator=(XsElement&&) = default; + + const auto& name() const + { + return name_; + } + XsElement& operator=(xml::lite::QName name) + { + name_ = std::move(name); + return *this; + } + void setAssociatedUri(const xml::lite::Uri& uri) + { + name_.setAssociatedUri(uri); + } + std::string tag() const + { + return name_.getName(); + } + + const value_type& value() const + { + return value_; + } + value_type& value() + { + return value_; + } + operator const value_type& () const + { + return value(); + } + operator value_type& () + { + return value(); + } + XsElement& operator=(const value_type& v) + { + value_ = v; + return *this; + } + XsElement& operator=(value_type&& v) + { + value_ = std::move(v); + return *this; + } +}; + +template +inline bool operator==(const XsElement& lhs, const U& rhs) +{ + return lhs.value() == rhs; +} +template +inline bool operator!=(const XsElement& lhs, const U& rhs) +{ + return !(lhs == rhs); +} + +template +inline bool operator==(const XsElement& lhs, const XsElement& rhs) +{ + return (lhs.name() == rhs.name()) && (lhs == value(rhs)); +} +template +inline bool operator!=(const XsElement& lhs, const XsElement& rhs) +{ + return !(lhs == rhs); +} + +template +inline auto&& value(const XsElement& o) +{ + return o.value(); +} +template +inline auto&& value(XsElement& o) +{ + return o.value(); +} + +template +inline std::ostream& operator<<(std::ostream& os, const XsElement& v) +{ + os << "\t" << v.tag() << "\t: " << value(v); + return os; +} +template <> +inline std::ostream& operator<<(std::ostream& os, const XsElement& v) +{ + os << "\t" << v.tag() << "\t: " << str::EncodedStringView(v).native(); + return os; +} + +// Make it easier to manipulate an optional Xml Element: +// XSD of `` +// Can be represented in C++ as +// ``` +// struct Foo final +// { XsElement_minOccurs0 foo {"Foo"}; }; +// ``` +template +using XsElement_minOccurs0 = XsElement>; + + +// A few convenience routines; this avoids the need for XsElement_minOccurs0 +// to be a seperate class. +namespace details +{ + // make it clear that o.value() is a std::optional<> + template + inline auto&& optional(const XsElement_minOccurs0& o) + { + return o.value(); + } + template + inline auto&& optional(XsElement_minOccurs0& o) + { + return o.value(); + } +} +template +inline bool has_value(const XsElement_minOccurs0& o) +{ + return details::optional(o).has_value(); +} +template +inline auto&& value(const XsElement_minOccurs0& o) +{ + return details::optional(o).value(); +} +template +inline auto&& value(XsElement_minOccurs0& o) +{ + return details::optional(o).value(); +} + +template +inline bool operator==(const XsElement_minOccurs0& lhs, const std::optional& rhs) +{ + return details::optional(lhs) == rhs; +} +template +inline bool operator!=(const XsElement_minOccurs0& lhs, const std::optional& rhs) +{ + return !(lhs == rhs); +} + +template +inline bool operator==(const XsElement_minOccurs0& lhs, const XsElement_minOccurs0& rhs) +{ + return (lhs.name() == rhs.name()) && (lhs == details::optional(rhs)); +} +template +inline bool operator!=(const XsElement_minOccurs0& lhs, const XsElement_minOccurs0& rhs) +{ + return !(lhs == rhs); +} + +template +inline std::ostream& operator<<(std::ostream& os, const XsElement_minOccurs0& o) +{ + if (has_value(o)) + { + os << XsElement(o.name(), value(o)); + } + else + { + os << "\t[ " << o.tag() << "\t: --- ]"; + } + return os; +} + +// Existing code uses mem::ScopedCopyablePtr rather than std::optional +template +inline auto get(const XsElement_minOccurs0& o) +{ + return has_value(o) ? &(value(o)) : nullptr; +} +template +inline auto get(XsElement_minOccurs0& o) +{ + return has_value(o) ? &(value(o)) : nullptr; +} + +} +#endif // SIX_six_XsElement_h_INCLUDED_ diff --git a/six/modules/c++/six/six.vcxproj b/six/modules/c++/six/six.vcxproj index 807078a96a..4be3df0970 100644 --- a/six/modules/c++/six/six.vcxproj +++ b/six/modules/c++/six/six.vcxproj @@ -150,6 +150,7 @@ + diff --git a/six/modules/c++/six/six.vcxproj.filters b/six/modules/c++/six/six.vcxproj.filters index 3413a9d4d1..899331248d 100644 --- a/six/modules/c++/six/six.vcxproj.filters +++ b/six/modules/c++/six/six.vcxproj.filters @@ -156,6 +156,9 @@ Header Files + + Header Files + diff --git a/six/modules/c++/six/source/SICommonXMLParser.cpp b/six/modules/c++/six/source/SICommonXMLParser.cpp index 6b9da165b7..3957d8d292 100644 --- a/six/modules/c++/six/source/SICommonXMLParser.cpp +++ b/six/modules/c++/six/source/SICommonXMLParser.cpp @@ -31,6 +31,7 @@ #include #include #include +#include namespace { @@ -940,22 +941,25 @@ XMLElem SICommonXMLParser::convertErrorStatisticsToXML( xmlNewElement(Unmodeled, getSICommonURI(), errorStatsXML); if (UnmodeledXML != nullptr) { - #define xmlCreateDouble_(name, value, elem) createDouble(#name, getSICommonURI(), (value).name, elem) - #define xmlCreateDouble(name, elem) xmlCreateDouble_(name, *elem, elem ## XML) - xmlCreateDouble(Xrow, Unmodeled); - xmlCreateDouble(Ycol, Unmodeled); - xmlCreateDouble(XrowYcol, Unmodeled); - - const auto UnmodeledDecorr = Unmodeled->UnmodeledDecorr.get(); - xmlNewElement(UnmodeledDecorr, getSICommonURI(), UnmodeledXML); + #define xmlCreateElement_(name, xml) createDouble((name).tag(), getSICommonURI(), (name).value(), xml) + #define xmlCreateElement(name, elem) xmlCreateElement_(elem->name, elem ## XML); + xmlCreateElement(Xrow, Unmodeled); + xmlCreateElement(Ycol, Unmodeled); + xmlCreateElement(XrowYcol, Unmodeled); + + const auto pUnmodeledDecorr = get(Unmodeled->unmodeledDecorr); + auto UnmodeledDecorrXML = newElement(pUnmodeledDecorr, "UnmodeledDecorr", getSICommonURI(), UnmodeledXML); if (UnmodeledDecorrXML != nullptr) { - const auto& Xrow = &(UnmodeledDecorr->Xrow); + #define xmlCreateDouble_(name, value, elem) createDouble(#name, getSICommonURI(), (value).name, elem) + #define xmlCreateDouble(name, elem) xmlCreateDouble_(name, *elem, elem ## XML) + + const auto& Xrow = &(pUnmodeledDecorr->Xrow); xmlNewElement(Xrow, getSICommonURI(), UnmodeledDecorrXML); xmlCreateDouble(CorrCoefZero, Xrow); xmlCreateDouble(DecorrRate, Xrow); - const auto& Ycol = &(UnmodeledDecorr->Ycol); + const auto& Ycol = &(pUnmodeledDecorr->Ycol); xmlNewElement(Ycol, getSICommonURI(), UnmodeledDecorrXML); xmlCreateDouble(CorrCoefZero, Ycol); xmlCreateDouble(DecorrRate, Ycol); @@ -974,6 +978,17 @@ XMLElem SICommonXMLParser::convertErrorStatisticsToXML( return errorStatsXML; } +inline static XMLElem getOptionalUnmodeledDecorr(const xml::lite::Element& parent, + XsElement_minOccurs0& unmodeledDecorr) +{ + auto retval = XmlLite::getOptional(parent, unmodeledDecorr.tag()); + if (retval != nullptr) + { + unmodeledDecorr = UnmodeledS::Decorr{}; + } + return retval; +} + void SICommonXMLParser::parseErrorStatisticsFromXML( const xml::lite::Element& errorStatsXML, ErrorStatistics& errorStatistics) const @@ -1033,14 +1048,14 @@ void SICommonXMLParser::parseErrorStatisticsFromXML( // macro to avoid copy/paste errors #define parseDouble_getFirstAndOnly(elem, name, storage) parseDouble(getFirstAndOnly(elem, #name), (storage).name) - parseDouble_getFirstAndOnly(tmpElem, Xrow, Unmodeled); - parseDouble_getFirstAndOnly(tmpElem, Ycol, Unmodeled); - parseDouble_getFirstAndOnly(tmpElem, XrowYcol, Unmodeled); + six::getFirstAndOnly(parser(), *tmpElem, Unmodeled.Xrow); + six::getFirstAndOnly(parser(), *tmpElem, Unmodeled.Ycol); + six::getFirstAndOnly(parser(), *tmpElem, Unmodeled.XrowYcol); - auto unmodeledDecorrXML = xml_getOptional_reset(*tmpElem, Unmodeled, UnmodeledDecorr); + auto unmodeledDecorrXML = getOptionalUnmodeledDecorr(*tmpElem, Unmodeled.unmodeledDecorr); if (unmodeledDecorrXML != nullptr) { - auto& UnmodeledDecorr = *(errorStatistics.Unmodeled->UnmodeledDecorr); + auto& UnmodeledDecorr = *get(errorStatistics.Unmodeled->unmodeledDecorr); auto xrowXML = getFirstAndOnly(unmodeledDecorrXML, "Xrow"); parseDouble_getFirstAndOnly(xrowXML, CorrCoefZero, UnmodeledDecorr.Xrow); @@ -1060,14 +1075,14 @@ void SICommonXMLParser::parseErrorStatisticsFromXML( // macro to avoid copy/paste errors #define parseDouble_getFirstAndOnly(elem, name, storage) parseDouble(getFirstAndOnly(elem, #name), (storage).name) - parseDouble_getFirstAndOnly(tmpElem, Xrow, Unmodeled); - parseDouble_getFirstAndOnly(tmpElem, Ycol, Unmodeled); - parseDouble_getFirstAndOnly(tmpElem, XrowYcol, Unmodeled); + six::getFirstAndOnly(parser(), *tmpElem, Unmodeled.Xrow); + six::getFirstAndOnly(parser(), *tmpElem, Unmodeled.Ycol); + six::getFirstAndOnly(parser(), *tmpElem, Unmodeled.XrowYcol); - auto unmodeledDecorrXML = xml_getOptional_reset(tmpElem, Unmodeled, UnmodeledDecorr); + auto unmodeledDecorrXML = getOptionalUnmodeledDecorr(*tmpElem, Unmodeled.unmodeledDecorr); if (unmodeledDecorrXML != nullptr) { - auto& UnmodeledDecorr = *(errorStatistics.Unmodeled->UnmodeledDecorr); + auto& UnmodeledDecorr = *get(errorStatistics.Unmodeled->unmodeledDecorr); auto xrowXML = getFirstAndOnly(unmodeledDecorrXML, "Xrow"); parseDouble_getFirstAndOnly(xrowXML, CorrCoefZero, UnmodeledDecorr.Xrow); diff --git a/six/modules/c++/six/source/Utilities.cpp b/six/modules/c++/six/source/Utilities.cpp index a2ae893467..0652332bae 100644 --- a/six/modules/c++/six/source/Utilities.cpp +++ b/six/modules/c++/six/source/Utilities.cpp @@ -839,13 +839,17 @@ void six::getErrors(const ErrorStatistics* errorStats, } else if (const auto unmodeled = errorStats->Unmodeled.get()) { + auto& unmodeledErrorCovar = errors.mUnmodeledErrorCovar; + auto&& Xrow = unmodeled->Xrow; + auto&& Ycol = unmodeled->Ycol; + auto&& XrowYcol = unmodeled->XrowYcol; + // From Bill: Here is the mapping from the UnmodeledError to the 2x2 covariance matrix: // [0][0] = Xrow; [1][1] = Ycol; // [1][0] = [0][1] = XrowYcol * Xrow * Ycol - auto& unmodeledErrorCovar = errors.mUnmodeledErrorCovar; - unmodeledErrorCovar(0, 0) = unmodeled->Xrow; - unmodeledErrorCovar(1, 1) = unmodeled->Ycol; - unmodeledErrorCovar(0, 1) = unmodeledErrorCovar(1, 0) = unmodeled->XrowYcol * unmodeled->Xrow * unmodeled->Ycol; + unmodeledErrorCovar(0, 0) = Xrow; + unmodeledErrorCovar(1, 1) = Ycol; + unmodeledErrorCovar(0, 1) = unmodeledErrorCovar(1, 0) = XrowYcol * Xrow * Ycol; } } } diff --git a/six/modules/c++/six/source/XMLParser.cpp b/six/modules/c++/six/source/XMLParser.cpp index d71c88a216..5cf83dbff1 100644 --- a/six/modules/c++/six/source/XMLParser.cpp +++ b/six/modules/c++/six/source/XMLParser.cpp @@ -191,6 +191,12 @@ XMLElem XMLParser::getFirstAndOnly(const xml::lite::Element* parent, const std:: return & getFirstAndOnly(*parent, tag); } +void XMLParser::getFirstAndOnly(const xml::lite::Element& parent, const std::string& tag, double& value) const +{ + parseDouble(getFirstAndOnly(parent, tag), value); +} + + xml::lite::Element* XMLParser::getOptional(const xml::lite::Element& parent, const std::string& tag) { return XmlLite::getOptional(parent, tag); @@ -257,4 +263,5 @@ bool XMLParser::parseOptionalString(const xml::lite::Element& parent, const std: { return mXmlLite.parseOptionalString(parent, tag, value); } + } diff --git a/six/modules/c++/six/source/XmlLite.cpp b/six/modules/c++/six/source/XmlLite.cpp index 24682ece59..7c33704371 100644 --- a/six/modules/c++/six/source/XmlLite.cpp +++ b/six/modules/c++/six/source/XmlLite.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -32,6 +33,7 @@ #include #include #include +#include namespace six { @@ -298,6 +300,19 @@ xml::lite::Element* XmlLite::createBooleanType(const std::string& name, BooleanT { return createBooleanType(makeQName(name), p, parent); } +xml::lite::Element* XmlLite::createOptional(const xml::lite::QName& name, const std::optional& v, xml::lite::Element& parent) const +{ + if (!v.has_value()) + { + return nullptr; + } + const auto p = *v ? BooleanType::IS_TRUE : BooleanType::IS_FALSE; + return createBooleanType(name, p, parent); +} +xml::lite::Element* XmlLite::createOptional(const xml::lite::QName& name, const std::optional& v, xml::lite::Element& parent) const +{ + return createOptionalValue(name, v, parent, mAddClassAttributes, "xs:string", getDefaultURI()); +} xml::lite::Element& XmlLite::createDateTime(const xml::lite::QName& name, const DateTime& p, xml::lite::Element& parent) const { @@ -326,11 +341,19 @@ xml::lite::Element& XmlLite::getFirstAndOnly(const xml::lite::Element& parent, c { return parent.getElementByTagName(tag); } +xml::lite::Element& XmlLite::getFirstAndOnly(const xml::lite::Element& parent, const xml::lite::QName& name) +{ + return parent.getElementByTagNameNS(name.toString()); +} xml::lite::Element* XmlLite::getOptional(const xml::lite::Element& parent, const std::string& tag) { return parent.getElementByTagName(std::nothrow, tag); } +xml::lite::Element* XmlLite::getOptional(const xml::lite::Element& parent, const xml::lite::QName& name) +{ + return parent.getElementByTagNameNS(std::nothrow, name.toString()); +} xml::lite::Element& XmlLite::require(xml::lite::Element* element, const std::string& name) { @@ -439,6 +462,22 @@ void XmlLite::parseBooleanType(const xml::lite::Element& element, BooleanType& v value = castValue(element, six::toType); }); } +BooleanType XmlLite::parseBooleanType(const xml::lite::Element& element) const +{ + BooleanType retval; + parseBooleanType(element, retval); + return retval; +} +bool XmlLite::parseBoolean(const xml::lite::Element& element) const +{ + switch (parseBooleanType(element)) + { + case BooleanType::IS_TRUE: return true; + case BooleanType::IS_FALSE: return false; + default: break; + } + throw std::logic_error("Unknown 'BooleanType' value."); +} void XmlLite::parseDateTime(const xml::lite::Element& element, DateTime& value) const { @@ -449,4 +488,56 @@ xml::lite::QName XmlLite::makeQName(const std::string& name) const { return xml::lite::QName(getDefaultURI(), name); } + +xml::lite::Element& create(const XmlLite& parser, const XsElement& v, xml::lite::Element& parent) +{ + return parser.createDouble(v.name(), v.value(), parent); +} +void getFirstAndOnly(const XmlLite& parser, const xml::lite::Element& parent, XsElement& v) +{ + auto& element = parser.getFirstAndOnly(parent, v.tag()); + v = xml::lite::getValue(element); // throws except::BadCastException on failure, see parseDouble() +} + +xml::lite::Element* create(const XmlLite& parser, const XsElement_minOccurs0& v, xml::lite::Element& parent) +{ + return parser.createOptional(v.name(), v, parent); +} +xml::lite::Element* create(const XmlLite& parser, const XsElement_minOccurs0& v, xml::lite::Element& parent) +{ + return parser.createOptionalDouble(v.name(), v, parent); +} +xml::lite::Element* create(const XmlLite& parser, const XsElement_minOccurs0& v, xml::lite::Element& parent) +{ + return parser.createOptional(v.name(), v, parent); +} + +bool parse(const XmlLite& parser, const xml::lite::Element& parent, XsElement_minOccurs0& v) +{ + if (auto element = parser.getOptional(parent, v.name())) + { + v = parser.parseBoolean(*element); + return true; + } + return false; +} +bool parse(const XmlLite& parser, const xml::lite::Element& parent, XsElement_minOccurs0& v) +{ + if (auto element = parser.getOptional(parent, v.name())) + { + parser.parseDouble(*element, v); + return true; + } + return false; +} +bool parse(const XmlLite& parser, const xml::lite::Element& parent, XsElement_minOccurs0& v) +{ + if (auto element = parser.getOptional(parent, v.name())) + { + v = getCharacterData(*element); + return true; + } + return false; +} + } diff --git a/six/projects/csm/source/SIXSensorModel.cpp b/six/projects/csm/source/SIXSensorModel.cpp index c81b1b21c0..7ca6ed1c40 100644 --- a/six/projects/csm/source/SIXSensorModel.cpp +++ b/six/projects/csm/source/SIXSensorModel.cpp @@ -1178,12 +1178,16 @@ std::vector SIXSensorModel::getSIXUnmodeledError_(const six::ErrorStatis { if (auto pUnmodeled = pErrorStatistics->Unmodeled.get()) { + auto&& Xrow = pUnmodeled->Xrow; + auto&& Ycol = pUnmodeled->Ycol; + auto&& XrowYcol = pUnmodeled->XrowYcol; + // From Bill: Here is the mapping from the UnmodeledError to the 2x2 covariance matrix: // [0][0] = Xrow; [1][1] = Ycol; // [1][0] = [0][1] = XrowYcol * Xrow * Ycol - const auto line_variance = pUnmodeled->Xrow; - const auto sample_variance = pUnmodeled->Ycol; - const auto linesample_covariance = pUnmodeled->XrowYcol * line_variance * sample_variance; + const auto line_variance = Xrow; + const auto sample_variance = Ycol; + const auto linesample_covariance = XrowYcol * line_variance * sample_variance; const auto sampleline_covariance = linesample_covariance; return { line_variance, linesample_covariance, sampleline_covariance, sample_variance }; }