1#include <vanetza/common/annotation.hpp>
2#include <vanetza/common/serialization.hpp>
3#include <vanetza/geodesy/geodesy.hpp>
4#include <vanetza/security/exception.hpp>
5#include <vanetza/security/v2/region.hpp>
6#include <vanetza/units/angle.hpp>
7#include <vanetza/units/length.hpp>
8#include <boost/algorithm/clamp.hpp>
9#include <boost/units/cmath.hpp>
10#include <boost/variant/static_visitor.hpp>
11#include <boost/variant/apply_visitor.hpp>
25RegionType get_type(
const GeographicRegion& reg)
27 struct geograpical_region_visitor :
public boost::static_visitor<RegionType>
31 return RegionType::None;
36 return RegionType::Circle;
39 RegionType operator()(
const std::list<RectangularRegion>&)
41 return RegionType::Rectangle;
44 RegionType operator()(
const PolygonalRegion&)
46 return RegionType::Polygon;
51 return RegionType::ID;
55 geograpical_region_visitor visit;
56 return boost::apply_visitor(visit, reg);
61 return this->latitude == other.latitude &&
this->longitude == other.longitude;
66 return !(*
this == other);
71 return this->latitude == other.latitude &&
this->longitude == other.longitude &&
this->elevation == other.elevation;
76 return !(*
this == other);
86 return !(*
this == other);
91 return this->center == other.center &&
this->radius == other.radius;
96 return !(*
this == other);
101 return this->northwest == other.northwest &&
this->southeast == other.southeast;
106 return !(*
this == other);
111 return this->region_dictionary == other.region_dictionary
112 &&
this->region_identifier == other.region_identifier
113 &&
this->local_region == other.local_region;
118 return !(*
this == other);
124 size +=
sizeof(loc.latitude);
125 size +=
sizeof(loc.longitude);
132 size +=
sizeof(loc.latitude);
133 size +=
sizeof(loc.longitude);
134 size += loc.elevation.size();
141 size += get_size(reg.center);
142 size +=
sizeof(reg.radius);
149 size += get_size(reg.northwest);
150 size += get_size(reg.southeast);
154size_t get_size(
const std::list<CircularRegion>& list)
157 for (
auto& circularRegion : list) {
158 size += get_size(circularRegion.center);
159 size +=
sizeof(circularRegion.radius);
164size_t get_size(
const std::list<RectangularRegion>& list)
167 for (
auto& rectangularRegion : list) {
168 size += get_size(rectangularRegion.northwest);
169 size += get_size(rectangularRegion.southeast);
174size_t get_size(
const PolygonalRegion& reg)
177 for (
auto& twoDLocation : reg) {
178 size +=
sizeof(twoDLocation.latitude);
179 size +=
sizeof(twoDLocation.longitude);
187 size +=
sizeof(reg.region_dictionary);
188 size +=
sizeof(reg.region_identifier);
189 size += get_size(reg.local_region);
193size_t get_size(
const GeographicRegion& reg)
195 size_t size =
sizeof(RegionType);
197 struct geograpical_region_visitor :
public boost::static_visitor<>
206 m_size = get_size(reg);
209 void operator()(
const std::list<RectangularRegion>& reg)
211 m_size = get_size(reg);
212 m_size += length_coding_size(m_size);
215 void operator()(
const PolygonalRegion& reg)
217 m_size = get_size(reg);
218 m_size += length_coding_size(m_size);
223 m_size = get_size(reg);
229 geograpical_region_visitor visit;
230 boost::apply_visitor(visit, reg);
231 size += visit.m_size;
237 serialize(ar, loc.latitude);
238 serialize(ar, loc.longitude);
243 serialize(ar, loc.latitude);
244 serialize(ar, loc.longitude);
245 ar << loc.elevation[0];
246 ar << loc.elevation[1];
251 serialize(ar, reg.center);
252 serialize(ar, reg.radius);
257 serialize(ar, reg.northwest);
258 serialize(ar, reg.southeast);
261void serialize(
OutputArchive& ar,
const std::list<RectangularRegion>& list)
264 size = get_size(list);
265 serialize_length(ar, size);
266 for (
auto& rectangularRegion : list) {
267 serialize(ar, rectangularRegion);
274 size = get_size(reg);
275 serialize_length(ar, size);
276 for (
auto& twoDLocation : reg) {
277 serialize(ar, twoDLocation);
283 serialize(ar, reg.region_dictionary);
284 serialize(ar, host_cast(reg.region_identifier));
285 serialize(ar, reg.local_region);
288void serialize(
OutputArchive& ar,
const GeographicRegion& reg)
290 struct geograpical_region_visitor :
public boost::static_visitor<>
304 serialize(m_archive, reg);
307 void operator()(
const std::list<RectangularRegion>& reg)
309 serialize(m_archive, reg);
312 void operator()(
const PolygonalRegion& reg)
314 serialize(m_archive, reg);
319 serialize(m_archive, reg);
325 RegionType type = get_type(reg);
327 geograpical_region_visitor visit(ar);
328 boost::apply_visitor(visit, reg);
333 deserialize(ar, loc.latitude);
334 deserialize(ar, loc.longitude);
335 return get_size(loc);
340 deserialize(ar, loc.latitude);
341 deserialize(ar, loc.longitude);
342 ar >> loc.elevation[0];
343 ar >> loc.elevation[1];
344 return get_size(loc);
350 size += deserialize(ar, reg.center);
351 deserialize(ar, reg.radius);
352 size +=
sizeof(reg.radius);
356size_t deserialize(
InputArchive& ar, std::list<RectangularRegion>& list)
358 size_t size, ret_size;
359 size = deserialize_length(ar);
363 size -= deserialize(ar, reg.northwest);
364 size -= deserialize(ar, reg.southeast);
370size_t deserialize(
InputArchive& ar, PolygonalRegion& reg)
372 size_t size, ret_size;
373 size = deserialize_length(ar);
377 size -= deserialize(ar, loc);
386 deserialize(ar, reg.region_dictionary);
387 size +=
sizeof(RegionDictionary);
388 deserialize(ar, reg.region_identifier);
389 size +=
sizeof(reg.region_identifier);
390 deserialize(ar, reg.local_region);
391 size += get_size(reg.local_region);
395size_t deserialize(
InputArchive& ar, GeographicRegion& reg)
398 deserialize(ar, type);
399 size_t size =
sizeof(RegionType);
401 case RegionType::None:
405 case RegionType::Circle: {
407 size += deserialize(ar, circle);
411 case RegionType::Rectangle: {
412 std::list<RectangularRegion> list;
413 size += deserialize(ar, list);
414 size += length_coding_size(size);
418 case RegionType::Polygon: {
419 PolygonalRegion polygon;
420 size += deserialize(ar, polygon);
421 size += length_coding_size(size);
425 case RegionType::ID: {
427 size += deserialize(ar, id);
439bool is_within(
const TwoDLocation& position,
const GeographicRegion& reg)
441 struct geograpical_region_visitor :
public boost::static_visitor<
bool>
443 geograpical_region_visitor(
const TwoDLocation& position) :
454 return is_within(m_position, reg);
457 bool operator()(
const std::list<RectangularRegion>& reg)
459 return is_within(m_position, reg);
462 bool operator()(
const PolygonalRegion& reg)
464 return is_within(m_position, reg);
469 return is_within(m_position, reg);
475 geograpical_region_visitor visit(position);
476 return boost::apply_visitor(visit, reg);
481 geodesy::
GeodeticPosition pos(units::GeoAngle{position.latitude}, units::GeoAngle{position.longitude});
482 geodesy::
GeodeticPosition center(units::GeoAngle{circular.center.latitude}, units::GeoAngle{circular.center.longitude});
483 auto dist = geodesy::distance(pos, center);
484 return dist <= circular.radius;
487bool is_within(
const TwoDLocation& position,
const std::list<RectangularRegion>& rectangles)
489 static const unsigned max_rectangles = 6;
491 if (rectangles.size() > max_rectangles) {
495 return std::any_of(rectangles.begin(), rectangles.end(),
496 [&position](
const RectangularRegion& rect) {
return is_within(position, rect); });
504 if (rectangle.northwest.latitude <= rectangle.southeast.latitude) {
506 }
else if (rectangle.northwest.longitude >= rectangle.southeast.longitude) {
510 if (rectangle.northwest.latitude < position.latitude) {
512 }
else if (rectangle.northwest.longitude > position.longitude) {
514 }
else if (rectangle.southeast.latitude > position.latitude) {
516 }
else if (rectangle.southeast.longitude < position.longitude) {
523bool is_within(
const TwoDLocation&,
const PolygonalRegion&)
535bool is_within(
const GeographicRegion& inner,
const GeographicRegion& outer)
537 struct outer_geograpical_region_visitor :
public boost::static_visitor<
bool>
539 outer_geograpical_region_visitor(
const GeographicRegion& inner) :
551 return is_within(inner, outer);
554 bool operator()(
const std::list<RectangularRegion>& outer)
556 return is_within(inner, outer);
559 bool operator()(
const PolygonalRegion& outer)
561 return is_within(inner, outer);
566 return is_within(inner, outer);
569 const GeographicRegion& inner;
572 outer_geograpical_region_visitor visit(inner);
573 return boost::apply_visitor(visit, outer);
576bool is_within(
const GeographicRegion& inner,
const CircularRegion& outer)
578 struct inner_geograpical_region_visitor :
public boost::static_visitor<
bool>
592 if (inner == outer) {
596 geodesy::
GeodeticPosition inner_pos(units::GeoAngle{inner.center.latitude}, units::GeoAngle{inner.center.longitude});
597 geodesy::
GeodeticPosition outer_pos(units::GeoAngle{outer.center.latitude}, units::GeoAngle{outer.center.longitude});
598 auto center_dist = geodesy::distance(inner_pos, outer_pos);
599 return center_dist + inner.radius <= outer.radius;
602 bool operator()(
const std::list<RectangularRegion>&)
606
607
608
609
610
611
612
613
614
618 bool operator()(
const PolygonalRegion&)
637 inner_geograpical_region_visitor visit(outer);
638 return boost::apply_visitor(visit, inner);
641bool is_within(
const GeographicRegion& inner,
const std::list<RectangularRegion>& outer)
648 struct inner_geograpical_region_visitor :
public boost::static_visitor<
bool>
650 inner_geograpical_region_visitor(
const std::list<RectangularRegion>& outer) :
666 bool operator()(
const std::list<RectangularRegion>& inner)
668 if (inner == outer) {
676 bool operator()(
const PolygonalRegion&)
688 const std::list<RectangularRegion>& outer;
691 inner_geograpical_region_visitor visit(outer);
692 return boost::apply_visitor(visit, inner);
695bool is_within(
const GeographicRegion& inner,
const PolygonalRegion& outer)
714 using boost::units::isnan;
717 ThreeDLocation::Elevation elevation { ThreeDLocation::unknown_elevation };
719 if (!isnan(altitude)) {
720 using boost::algorithm::clamp;
723 double altitude_dm = std::round(10.0 * (altitude / vanetza::units::si::meter));
724 if (altitude_dm >= 0.0) {
725 altitude_dm = clamp(altitude_dm, 0.0, 61439.0);
726 auto altitude_int =
static_cast<std::uint16_t>(altitude_dm);
727 elevation[0] = altitude_int >> 8;
728 elevation[1] = altitude_int & 0xFF;
730 altitude_dm = clamp(altitude_dm, -4095.0, -1.0);
731 auto altitude_int =
static_cast<std::int16_t>(altitude_dm);
732 elevation[0] = altitude_int >> 8 | 0xF0;
733 elevation[1] = altitude_int & 0xFF;
thrown when a deserialization error occurred
CircularRegion specified in TS 103 097 v1.2.1, section 4.2.22.
IdentifiedRegion specified in TS 103 097 v1.2.1, section 4.2.25.
Specified in TS 103 097 v1.2.1, section 4.2.20.
RectangularRegion specified in TS 103 097 v1.2.1, section 4.2.23.
ThreeDLocation specified in TS 103 097 v1.2.1, section 4.2.19.
TwoDLocation specified in TS 103 097 v1.2.1, section 4.2.18.