37 #include <libxml/parser.h> 40 const std::string sSubRootName,
41 double dMissingValue):
42 dMissingValue_{dMissingValue}
44 xmlParserCtxtPtr pContext{xmlNewParserCtxt()};
51 xmlDocPtr pDoc{xmlCtxtReadFile(pContext,sAntennaPatternURI.c_str(),
nullptr,XML_PARSE_DTDVALID)};
56 xmlFreeParserCtxt(pContext);
57 throw makeException<AntennaProfileException>(
"Unable to read %s",sAntennaPatternURI.c_str());
60 if(pContext->valid ==
false)
63 xmlFreeParserCtxt(pContext);
64 throw makeException<AntennaProfileException>(
"Validation failure %s",sAntennaPatternURI.c_str());
67 xmlNodePtr pRoot{xmlDocGetRootElement(pDoc)};
72 xmlFreeParserCtxt(pContext);
73 throw makeException<AntennaProfileException>(
"Invalid document root %s",
74 sAntennaPatternURI.c_str());
78 for(xmlNodePtr pNode = pRoot->children; pNode; pNode = pNode->next)
80 if(pNode->type == XML_ELEMENT_NODE)
82 if(!xmlStrcmp(pNode->name,BAD_CAST sSubRootName.c_str()))
84 std::int16_t i16ElevationRangeMax{};
86 for(xmlNodePtr pElevationNode = pNode->children;
88 pElevationNode = pElevationNode->next)
90 if(pElevationNode->type == XML_ELEMENT_NODE)
92 if(!xmlStrcmp(pElevationNode->name,BAD_CAST
"elevation"))
94 xmlChar * pMin{xmlGetProp(pElevationNode,BAD_CAST
"min")};
96 std::int16_t i16ElevationMin =
101 xmlChar * pMax{xmlGetProp(pElevationNode,BAD_CAST
"max")};
103 std::int16_t i16ElevationMax =
108 if(i16ElevationMin > i16ElevationMax)
110 throw makeException<AntennaProfileException>(
"Bad entry %s: elevation [%hd,%hd] min > max",
111 sAntennaPatternURI.c_str(),
116 if(i16ElevationRangeMax >= i16ElevationMin && !elevationBearingGainMap_.empty())
118 throw makeException<AntennaProfileException>(
"Bad entry %s: elevation [%hd,%hd] may may be" 119 " out of order or overlap with a previous elevation",
120 sAntennaPatternURI.c_str(),
126 i16ElevationRangeMax = i16ElevationMax;
129 BearingGainMap * pBearingGainMap{
new BearingGainMap};
131 bearings_.push_back(std::unique_ptr<BearingGainMap>(pBearingGainMap));
133 std::int16_t i16BearingRangeMax{};
135 for(xmlNodePtr pBearingNode = pElevationNode->children;
137 pBearingNode = pBearingNode->next)
139 if(pBearingNode->type == XML_ELEMENT_NODE)
141 if(!xmlStrcmp(pBearingNode->name,BAD_CAST
"bearing"))
143 xmlChar * pMin{xmlGetProp(pBearingNode,BAD_CAST
"min")};
145 std::int16_t i16BearingMin =
150 xmlChar * pMax{xmlGetProp(pBearingNode,BAD_CAST
"max")};
152 std::int16_t i16BearingMax =
157 if(i16BearingMin > i16BearingMax)
159 throw makeException<AntennaProfileException>(
"Bad entry %s: elevation [%hd,%hd] bearing [%hd,%hd] min > max",
160 sAntennaPatternURI.c_str(),
167 if(i16BearingRangeMax >= i16BearingMin && !pBearingGainMap->empty())
169 throw makeException<AntennaProfileException>(
"Bad entry %s: elevation [%hd,%hd] bearing [%hd,%hd]" 170 " may be out of order or overlap with a previous bearing",
171 sAntennaPatternURI.c_str(),
179 i16BearingRangeMax = i16BearingMax;
182 for(xmlNodePtr pGainNode = pBearingNode->children;
184 pGainNode = pGainNode->next)
186 if(pGainNode->type == XML_ELEMENT_NODE)
188 if(!xmlStrcmp(pGainNode->name,BAD_CAST
"gain"))
190 xmlChar * pGain{xmlGetProp(pGainNode,BAD_CAST
"value")};
197 if(pBearingGainMap->find(i16BearingMin-1) == pBearingGainMap->end())
199 (*pBearingGainMap)[i16BearingMin-1] = dMissingValue_;
202 (*pBearingGainMap)[i16BearingMax] = dGain;
210 if(elevationBearingGainMap_.find(i16ElevationMin-1) == elevationBearingGainMap_.end())
212 elevationBearingGainMap_[i16ElevationMin-1] =
nullptr;
215 elevationBearingGainMap_[i16ElevationMax] = pBearingGainMap;
224 xmlFreeParserCtxt(pContext);
229 double dGain{dMissingValue_};
237 const auto iter = elevationBearingGainMap_.lower_bound(iElevation);
239 if(iter != elevationBearingGainMap_.end())
243 const auto bearingIter = iter->second->lower_bound(iBearing);
245 if(bearingIter != iter->second->end())
247 dGain = bearingIter->second;
double toDouble(double dMin=std::numeric_limits< double >::lowest(), double dMax=std::numeric_limits< double >::max()) const
double getGain(std::int16_t iBearing, std::int16_t iElevation) const
std::int16_t toINT16(std::int16_t i16Min=std::numeric_limits< std::int16_t >::min(), std::int16_t i16Max=std::numeric_limits< std::int16_t >::max()) const
AntennaPattern(const std::string &sAntennaPatternURI, const std::string sSubRootName, double dMissingValue)
Parameter conversion class with range checks.