Keep vanetza-idf in obu-firmware, so a plain clone builds the firmware
obu-firmware builds against the vanetza-idf C-ITS library, which until now came from the colleague's microbu-esp32c5 tree beside the repository and was not tracked here, so a clone of this repository could not build the firmware it ships. The library alone is now part of obu-firmware, as obu-firmware/external/vanetza-idf: their external/vanetza-idf at commit cf4b99f, unchanged (9775 files; see its PROVENANCE.md). CMake takes it from there by default; -DVANETZA_IDF_DIR still points the build elsewhere. The rest of the colleague's tree (their own VAM firmware, PKI tooling, station-link Python tools, the V2X2MAP bridge) stays out of this repository and gitignored; nothing is pushed to their repository. NOTES.md, docs/06, TODO.md and the pcap verifier's usage line point at the new location.
This commit is contained in:
@@ -0,0 +1,742 @@
|
||||
#include <vanetza/common/annotation.hpp>
|
||||
#include <vanetza/common/serialization.hpp>
|
||||
#include <vanetza/geodesy/geodesy.hpp>
|
||||
#include <vanetza/security/exception.hpp>
|
||||
#include <vanetza/security/v2/region.hpp>
|
||||
#include <vanetza/units/angle.hpp>
|
||||
#include <vanetza/units/length.hpp>
|
||||
#include <boost/algorithm/clamp.hpp>
|
||||
#include <boost/units/cmath.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <cmath>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace security
|
||||
{
|
||||
namespace v2
|
||||
{
|
||||
|
||||
const ThreeDLocation::Elevation ThreeDLocation::unknown_elevation {{ 0xF0, 0x00 }};
|
||||
const ThreeDLocation::Elevation ThreeDLocation::min_elevation {{ 0xF0, 0x01 }};
|
||||
const ThreeDLocation::Elevation ThreeDLocation::max_elevation {{ 0xEF, 0xFF }};
|
||||
|
||||
RegionType get_type(const GeographicRegion& reg)
|
||||
{
|
||||
struct geograpical_region_visitor : public boost::static_visitor<RegionType>
|
||||
{
|
||||
RegionType operator()(const NoneRegion&)
|
||||
{
|
||||
return RegionType::None;
|
||||
}
|
||||
|
||||
RegionType operator()(const CircularRegion&)
|
||||
{
|
||||
return RegionType::Circle;
|
||||
}
|
||||
|
||||
RegionType operator()(const std::list<RectangularRegion>&)
|
||||
{
|
||||
return RegionType::Rectangle;
|
||||
}
|
||||
|
||||
RegionType operator()(const PolygonalRegion&)
|
||||
{
|
||||
return RegionType::Polygon;
|
||||
}
|
||||
|
||||
RegionType operator()(const IdentifiedRegion&)
|
||||
{
|
||||
return RegionType::ID;
|
||||
}
|
||||
};
|
||||
|
||||
geograpical_region_visitor visit;
|
||||
return boost::apply_visitor(visit, reg);
|
||||
}
|
||||
|
||||
bool TwoDLocation::operator==(const TwoDLocation& other) const
|
||||
{
|
||||
return this->latitude == other.latitude && this->longitude == other.longitude;
|
||||
}
|
||||
|
||||
bool TwoDLocation::operator!=(const TwoDLocation& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
bool ThreeDLocation::operator==(const ThreeDLocation& other) const
|
||||
{
|
||||
return this->latitude == other.latitude && this->longitude == other.longitude && this->elevation == other.elevation;
|
||||
}
|
||||
|
||||
bool ThreeDLocation::operator!=(const ThreeDLocation& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
bool NoneRegion::operator==(const NoneRegion&) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NoneRegion::operator!=(const NoneRegion& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
bool CircularRegion::operator==(const CircularRegion& other) const
|
||||
{
|
||||
return this->center == other.center && this->radius == other.radius;
|
||||
}
|
||||
|
||||
bool CircularRegion::operator!=(const CircularRegion& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
bool RectangularRegion::operator==(const RectangularRegion& other) const
|
||||
{
|
||||
return this->northwest == other.northwest && this->southeast == other.southeast;
|
||||
}
|
||||
|
||||
bool RectangularRegion::operator!=(const RectangularRegion& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
bool IdentifiedRegion::operator==(const IdentifiedRegion& other) const
|
||||
{
|
||||
return this->region_dictionary == other.region_dictionary
|
||||
&& this->region_identifier == other.region_identifier
|
||||
&& this->local_region == other.local_region;
|
||||
}
|
||||
|
||||
bool IdentifiedRegion::operator!=(const IdentifiedRegion& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
size_t get_size(const TwoDLocation& loc)
|
||||
{
|
||||
size_t size = 0;
|
||||
size += sizeof(loc.latitude);
|
||||
size += sizeof(loc.longitude);
|
||||
return size;
|
||||
}
|
||||
|
||||
size_t get_size(const ThreeDLocation& loc)
|
||||
{
|
||||
size_t size = 0;
|
||||
size += sizeof(loc.latitude);
|
||||
size += sizeof(loc.longitude);
|
||||
size += loc.elevation.size();
|
||||
return size;
|
||||
}
|
||||
|
||||
size_t get_size(const CircularRegion& reg)
|
||||
{
|
||||
size_t size = 0;
|
||||
size += get_size(reg.center);
|
||||
size += sizeof(reg.radius);
|
||||
return size;
|
||||
}
|
||||
|
||||
size_t get_size(const RectangularRegion& reg)
|
||||
{
|
||||
size_t size = 0;
|
||||
size += get_size(reg.northwest);
|
||||
size += get_size(reg.southeast);
|
||||
return size;
|
||||
}
|
||||
|
||||
size_t get_size(const std::list<CircularRegion>& list)
|
||||
{
|
||||
size_t size = 0;
|
||||
for (auto& circularRegion : list) {
|
||||
size += get_size(circularRegion.center);
|
||||
size += sizeof(circularRegion.radius);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
size_t get_size(const std::list<RectangularRegion>& list)
|
||||
{
|
||||
size_t size = 0;
|
||||
for (auto& rectangularRegion : list) {
|
||||
size += get_size(rectangularRegion.northwest);
|
||||
size += get_size(rectangularRegion.southeast);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
size_t get_size(const PolygonalRegion& reg)
|
||||
{
|
||||
size_t size = 0;
|
||||
for (auto& twoDLocation : reg) {
|
||||
size += sizeof(twoDLocation.latitude);
|
||||
size += sizeof(twoDLocation.longitude);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
size_t get_size(const IdentifiedRegion& reg)
|
||||
{
|
||||
size_t size = 0;
|
||||
size += sizeof(reg.region_dictionary);
|
||||
size += sizeof(reg.region_identifier);
|
||||
size += get_size(reg.local_region);
|
||||
return size;
|
||||
}
|
||||
|
||||
size_t get_size(const GeographicRegion& reg)
|
||||
{
|
||||
size_t size = sizeof(RegionType);
|
||||
|
||||
struct geograpical_region_visitor : public boost::static_visitor<>
|
||||
{
|
||||
void operator()(const NoneRegion&)
|
||||
{
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
void operator()(const CircularRegion& reg)
|
||||
{
|
||||
m_size = get_size(reg);
|
||||
}
|
||||
|
||||
void operator()(const std::list<RectangularRegion>& reg)
|
||||
{
|
||||
m_size = get_size(reg);
|
||||
m_size += length_coding_size(m_size);
|
||||
}
|
||||
|
||||
void operator()(const PolygonalRegion& reg)
|
||||
{
|
||||
m_size = get_size(reg);
|
||||
m_size += length_coding_size(m_size);
|
||||
}
|
||||
|
||||
void operator()(const IdentifiedRegion& reg)
|
||||
{
|
||||
m_size = get_size(reg);
|
||||
}
|
||||
|
||||
size_t m_size;
|
||||
};
|
||||
|
||||
geograpical_region_visitor visit;
|
||||
boost::apply_visitor(visit, reg);
|
||||
size += visit.m_size;
|
||||
return size;
|
||||
}
|
||||
|
||||
void serialize(OutputArchive& ar, const TwoDLocation& loc)
|
||||
{
|
||||
serialize(ar, loc.latitude);
|
||||
serialize(ar, loc.longitude);
|
||||
}
|
||||
|
||||
void serialize(OutputArchive& ar, const ThreeDLocation& loc)
|
||||
{
|
||||
serialize(ar, loc.latitude);
|
||||
serialize(ar, loc.longitude);
|
||||
ar << loc.elevation[0];
|
||||
ar << loc.elevation[1];
|
||||
}
|
||||
|
||||
void serialize(OutputArchive& ar, const CircularRegion& reg)
|
||||
{
|
||||
serialize(ar, reg.center);
|
||||
serialize(ar, reg.radius);
|
||||
}
|
||||
|
||||
void serialize(OutputArchive& ar, const RectangularRegion& reg)
|
||||
{
|
||||
serialize(ar, reg.northwest);
|
||||
serialize(ar, reg.southeast);
|
||||
}
|
||||
|
||||
void serialize(OutputArchive& ar, const std::list<RectangularRegion>& list)
|
||||
{
|
||||
size_t size;
|
||||
size = get_size(list);
|
||||
serialize_length(ar, size);
|
||||
for (auto& rectangularRegion : list) {
|
||||
serialize(ar, rectangularRegion);
|
||||
}
|
||||
}
|
||||
|
||||
void serialize(OutputArchive& ar, const PolygonalRegion& reg)
|
||||
{
|
||||
size_t size;
|
||||
size = get_size(reg);
|
||||
serialize_length(ar, size);
|
||||
for (auto& twoDLocation : reg) {
|
||||
serialize(ar, twoDLocation);
|
||||
}
|
||||
}
|
||||
|
||||
void serialize(OutputArchive& ar, const IdentifiedRegion& reg)
|
||||
{
|
||||
serialize(ar, reg.region_dictionary);
|
||||
serialize(ar, host_cast(reg.region_identifier));
|
||||
serialize(ar, reg.local_region);
|
||||
}
|
||||
|
||||
void serialize(OutputArchive& ar, const GeographicRegion& reg)
|
||||
{
|
||||
struct geograpical_region_visitor : public boost::static_visitor<>
|
||||
{
|
||||
geograpical_region_visitor(OutputArchive& ar) :
|
||||
m_archive(ar)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(const NoneRegion&)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
void operator()(const CircularRegion& reg)
|
||||
{
|
||||
serialize(m_archive, reg);
|
||||
}
|
||||
|
||||
void operator()(const std::list<RectangularRegion>& reg)
|
||||
{
|
||||
serialize(m_archive, reg);
|
||||
}
|
||||
|
||||
void operator()(const PolygonalRegion& reg)
|
||||
{
|
||||
serialize(m_archive, reg);
|
||||
}
|
||||
|
||||
void operator()(const IdentifiedRegion& reg)
|
||||
{
|
||||
serialize(m_archive, reg);
|
||||
}
|
||||
|
||||
OutputArchive& m_archive;
|
||||
};
|
||||
|
||||
RegionType type = get_type(reg);
|
||||
serialize(ar, type);
|
||||
geograpical_region_visitor visit(ar);
|
||||
boost::apply_visitor(visit, reg);
|
||||
}
|
||||
|
||||
size_t deserialize(InputArchive& ar, TwoDLocation& loc)
|
||||
{
|
||||
deserialize(ar, loc.latitude);
|
||||
deserialize(ar, loc.longitude);
|
||||
return get_size(loc);
|
||||
}
|
||||
|
||||
size_t deserialize(InputArchive& ar, ThreeDLocation& loc)
|
||||
{
|
||||
deserialize(ar, loc.latitude);
|
||||
deserialize(ar, loc.longitude);
|
||||
ar >> loc.elevation[0];
|
||||
ar >> loc.elevation[1];
|
||||
return get_size(loc);
|
||||
}
|
||||
|
||||
size_t deserialize(InputArchive& ar, CircularRegion& reg)
|
||||
{
|
||||
size_t size = 0;
|
||||
size += deserialize(ar, reg.center);
|
||||
deserialize(ar, reg.radius);
|
||||
size += sizeof(reg.radius);
|
||||
return size;
|
||||
}
|
||||
|
||||
size_t deserialize(InputArchive& ar, std::list<RectangularRegion>& list)
|
||||
{
|
||||
size_t size, ret_size;
|
||||
size = deserialize_length(ar);
|
||||
ret_size = size;
|
||||
while (size > 0) {
|
||||
RectangularRegion reg;
|
||||
size -= deserialize(ar, reg.northwest);
|
||||
size -= deserialize(ar, reg.southeast);
|
||||
list.push_back(reg);
|
||||
}
|
||||
return ret_size;
|
||||
}
|
||||
|
||||
size_t deserialize(InputArchive& ar, PolygonalRegion& reg)
|
||||
{
|
||||
size_t size, ret_size;
|
||||
size = deserialize_length(ar);
|
||||
ret_size = size;
|
||||
while (size > 0) {
|
||||
TwoDLocation loc;
|
||||
size -= deserialize(ar, loc);
|
||||
reg.push_back(loc);
|
||||
}
|
||||
return ret_size;
|
||||
}
|
||||
|
||||
size_t deserialize(InputArchive& ar, IdentifiedRegion& reg)
|
||||
{
|
||||
size_t size = 0;
|
||||
deserialize(ar, reg.region_dictionary);
|
||||
size += sizeof(RegionDictionary);
|
||||
deserialize(ar, reg.region_identifier);
|
||||
size += sizeof(reg.region_identifier);
|
||||
deserialize(ar, reg.local_region);
|
||||
size += get_size(reg.local_region);
|
||||
return size;
|
||||
}
|
||||
|
||||
size_t deserialize(InputArchive& ar, GeographicRegion& reg)
|
||||
{
|
||||
RegionType type;
|
||||
deserialize(ar, type);
|
||||
size_t size = sizeof(RegionType);
|
||||
switch (type) {
|
||||
case RegionType::None:
|
||||
NoneRegion none;
|
||||
reg = none;
|
||||
break;
|
||||
case RegionType::Circle: {
|
||||
CircularRegion circle;
|
||||
size += deserialize(ar, circle);
|
||||
reg = circle;
|
||||
break;
|
||||
}
|
||||
case RegionType::Rectangle: {
|
||||
std::list<RectangularRegion> list;
|
||||
size += deserialize(ar, list);
|
||||
size += length_coding_size(size);
|
||||
reg = list;
|
||||
break;
|
||||
}
|
||||
case RegionType::Polygon: {
|
||||
PolygonalRegion polygon;
|
||||
size += deserialize(ar, polygon);
|
||||
size += length_coding_size(size);
|
||||
reg = polygon;
|
||||
break;
|
||||
}
|
||||
case RegionType::ID: {
|
||||
IdentifiedRegion id;
|
||||
size += deserialize(ar, id);
|
||||
reg = id;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw deserialization_error("Unknown RegionType");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (size);
|
||||
}
|
||||
|
||||
bool is_within(const TwoDLocation& position, const GeographicRegion& reg)
|
||||
{
|
||||
struct geograpical_region_visitor : public boost::static_visitor<bool>
|
||||
{
|
||||
geograpical_region_visitor(const TwoDLocation& position) :
|
||||
m_position(position)
|
||||
{
|
||||
}
|
||||
bool operator()(const NoneRegion&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator()(const CircularRegion& reg)
|
||||
{
|
||||
return is_within(m_position, reg);
|
||||
}
|
||||
|
||||
bool operator()(const std::list<RectangularRegion>& reg)
|
||||
{
|
||||
return is_within(m_position, reg);
|
||||
}
|
||||
|
||||
bool operator()(const PolygonalRegion& reg)
|
||||
{
|
||||
return is_within(m_position, reg);
|
||||
}
|
||||
|
||||
bool operator()(const IdentifiedRegion& reg)
|
||||
{
|
||||
return is_within(m_position, reg);
|
||||
}
|
||||
|
||||
const TwoDLocation& m_position;
|
||||
};
|
||||
|
||||
geograpical_region_visitor visit(position);
|
||||
return boost::apply_visitor(visit, reg);
|
||||
}
|
||||
|
||||
bool is_within(const TwoDLocation& position, const CircularRegion& circular)
|
||||
{
|
||||
geodesy::GeodeticPosition pos(units::GeoAngle{position.latitude}, units::GeoAngle{position.longitude});
|
||||
geodesy::GeodeticPosition center(units::GeoAngle{circular.center.latitude}, units::GeoAngle{circular.center.longitude});
|
||||
auto dist = geodesy::distance(pos, center);
|
||||
return dist <= circular.radius;
|
||||
}
|
||||
|
||||
bool is_within(const TwoDLocation& position, const std::list<RectangularRegion>& rectangles)
|
||||
{
|
||||
static const unsigned max_rectangles = 6; /*< see TS 103 097 v1.2.1, section 4.2.20 */
|
||||
|
||||
if (rectangles.size() > max_rectangles) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return std::any_of(rectangles.begin(), rectangles.end(),
|
||||
[&position](const RectangularRegion& rect) { return is_within(position, rect); });
|
||||
}
|
||||
|
||||
bool is_within(const TwoDLocation& position, const RectangularRegion& rectangle)
|
||||
{
|
||||
// basic coordinate checks according to TS 103 097 v1.2.1, 4.2.23 and IEEE 1609.2-2016, 6.4.20
|
||||
// - northwest is truly north of southeast (never equal)
|
||||
// - northwest is truly west of southeast (never equal)
|
||||
if (rectangle.northwest.latitude <= rectangle.southeast.latitude) {
|
||||
return false;
|
||||
} else if (rectangle.northwest.longitude >= rectangle.southeast.longitude) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rectangle.northwest.latitude < position.latitude) {
|
||||
return false; // position is north of rectangle
|
||||
} else if (rectangle.northwest.longitude > position.longitude) {
|
||||
return false; // position is west of rectangle
|
||||
} else if (rectangle.southeast.latitude > position.latitude) {
|
||||
return false; // position is south of rectangle
|
||||
} else if (rectangle.southeast.longitude < position.longitude) {
|
||||
return false; // position is east of rectangle
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool is_within(const TwoDLocation&, const PolygonalRegion&)
|
||||
{
|
||||
// TODO: Add support for polygonal region, see TS 103 097 v1.2.1, section 4.2.24
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_within(const TwoDLocation&, const IdentifiedRegion&)
|
||||
{
|
||||
// TODO: Add support for identified region, see TS 103 097 v1.2.1, section 4.2.25
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_within(const GeographicRegion& inner, const GeographicRegion& outer)
|
||||
{
|
||||
struct outer_geograpical_region_visitor : public boost::static_visitor<bool>
|
||||
{
|
||||
outer_geograpical_region_visitor(const GeographicRegion& inner) :
|
||||
inner(inner)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator()(const NoneRegion&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator()(const CircularRegion& outer)
|
||||
{
|
||||
return is_within(inner, outer);
|
||||
}
|
||||
|
||||
bool operator()(const std::list<RectangularRegion>& outer)
|
||||
{
|
||||
return is_within(inner, outer);
|
||||
}
|
||||
|
||||
bool operator()(const PolygonalRegion& outer)
|
||||
{
|
||||
return is_within(inner, outer);
|
||||
}
|
||||
|
||||
bool operator()(const IdentifiedRegion& outer)
|
||||
{
|
||||
return is_within(inner, outer);
|
||||
}
|
||||
|
||||
const GeographicRegion& inner;
|
||||
};
|
||||
|
||||
outer_geograpical_region_visitor visit(inner);
|
||||
return boost::apply_visitor(visit, outer);
|
||||
}
|
||||
|
||||
bool is_within(const GeographicRegion& inner, const CircularRegion& outer)
|
||||
{
|
||||
struct inner_geograpical_region_visitor : public boost::static_visitor<bool>
|
||||
{
|
||||
inner_geograpical_region_visitor(const CircularRegion& outer) :
|
||||
outer(outer)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator()(const NoneRegion&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator()(const CircularRegion& inner)
|
||||
{
|
||||
if (inner == outer) {
|
||||
return true;
|
||||
}
|
||||
|
||||
geodesy::GeodeticPosition inner_pos(units::GeoAngle{inner.center.latitude}, units::GeoAngle{inner.center.longitude});
|
||||
geodesy::GeodeticPosition outer_pos(units::GeoAngle{outer.center.latitude}, units::GeoAngle{outer.center.longitude});
|
||||
auto center_dist = geodesy::distance(inner_pos, outer_pos);
|
||||
return center_dist + inner.radius <= outer.radius;
|
||||
}
|
||||
|
||||
bool operator()(const std::list<RectangularRegion>&)
|
||||
{
|
||||
// TODO: Implement check whether reactangles are within the circle
|
||||
/* Note: The rectangles can be converted to a polygon and its implementation be reused then.
|
||||
* Note: Checking whether all corners of a rectangle are within the circle is NOT enough!
|
||||
* Example: The rectangle here is spanning the earth except for a small part within the circle.
|
||||
* ________
|
||||
* / \
|
||||
* _____/__ __\_____
|
||||
* | | | |
|
||||
* _____\__| |__/____
|
||||
* \_________/
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator()(const PolygonalRegion&)
|
||||
{
|
||||
// TODO: Implement check whether a polygon is within the circle.
|
||||
// Note: Same thoughts as for rectangles applies.
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
bool operator()(const IdentifiedRegion&)
|
||||
{
|
||||
// TODO: Implement check whether an identified region is within the circle.
|
||||
// Note: The identified region can be converted to a polygon and its implementation be reused then.
|
||||
// Note: Same thoughts as for rectangles applies.
|
||||
return false;
|
||||
}
|
||||
|
||||
const CircularRegion& outer;
|
||||
};
|
||||
|
||||
inner_geograpical_region_visitor visit(outer);
|
||||
return boost::apply_visitor(visit, inner);
|
||||
}
|
||||
|
||||
bool is_within(const GeographicRegion& inner, const std::list<RectangularRegion>& outer)
|
||||
{
|
||||
// Note: The rectangles cover an area combined, there's no need for the inner shape to be within a single one!
|
||||
// TODO: Implement check whether inner is within the set of rectangles
|
||||
// Note: The rectangles can be converted to a polygon and its implementation be reused then.
|
||||
// Note: Only exact matches are implemented for now.
|
||||
|
||||
struct inner_geograpical_region_visitor : public boost::static_visitor<bool>
|
||||
{
|
||||
inner_geograpical_region_visitor(const std::list<RectangularRegion>& outer) :
|
||||
outer(outer)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator()(const NoneRegion&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator()(const CircularRegion&)
|
||||
{
|
||||
// TODO: Implement.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator()(const std::list<RectangularRegion>& inner)
|
||||
{
|
||||
if (inner == outer) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: Implement.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator()(const PolygonalRegion&)
|
||||
{
|
||||
// TODO: Implement.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator()(const IdentifiedRegion&)
|
||||
{
|
||||
// TODO: Implement.
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::list<RectangularRegion>& outer;
|
||||
};
|
||||
|
||||
inner_geograpical_region_visitor visit(outer);
|
||||
return boost::apply_visitor(visit, inner);
|
||||
}
|
||||
|
||||
bool is_within(const GeographicRegion& inner, const PolygonalRegion& outer)
|
||||
{
|
||||
// TODO: Implement check whether inner is within the polygon
|
||||
mark_unused(inner);
|
||||
mark_unused(outer);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_within(const GeographicRegion& inner, const IdentifiedRegion& outer)
|
||||
{
|
||||
// TODO: Implement check whether inner is within the polygon identified by the outer region
|
||||
// Note: The identified region can be converted to a polygon and its implementation be reused then.
|
||||
mark_unused(inner);
|
||||
mark_unused(outer);
|
||||
return false;
|
||||
}
|
||||
|
||||
ThreeDLocation::Elevation to_elevation(units::Length altitude)
|
||||
{
|
||||
using boost::units::isnan;
|
||||
|
||||
// Default to special value for NaN elevation
|
||||
ThreeDLocation::Elevation elevation { ThreeDLocation::unknown_elevation };
|
||||
|
||||
if (!isnan(altitude)) {
|
||||
using boost::algorithm::clamp;
|
||||
|
||||
// see TS 103 097 v1.2.1, section 4.2.19
|
||||
double altitude_dm = std::round(10.0 * (altitude / vanetza::units::si::meter));
|
||||
if (altitude_dm >= 0.0) {
|
||||
altitude_dm = clamp(altitude_dm, 0.0, 61439.0);
|
||||
auto altitude_int = static_cast<std::uint16_t>(altitude_dm);
|
||||
elevation[0] = altitude_int >> 8;
|
||||
elevation[1] = altitude_int & 0xFF;
|
||||
} else {
|
||||
altitude_dm = clamp(altitude_dm, -4095.0, -1.0);
|
||||
auto altitude_int = static_cast<std::int16_t>(altitude_dm);
|
||||
elevation[0] = altitude_int >> 8 | 0xF0;
|
||||
elevation[1] = altitude_int & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
return elevation;
|
||||
}
|
||||
|
||||
} // namespace v2
|
||||
} // namespace security
|
||||
} // namespace vanetza
|
||||
Reference in New Issue
Block a user