diff --git a/Makefile b/Makefile index cc3a9bc88ca66e0ef6de1a4af77aaa26c6a97135..c11ef81d12d280ab02092a92709fb8313383800a 100644 --- a/Makefile +++ b/Makefile @@ -23,7 +23,7 @@ $$(foreach I, $$(includes), $$(eval all_includes += $(1)/$$(I))) $$(foreach M, $$(modules), $$(eval $$(call IncludeModule, $$(if $$(filter /%, $$(M)), $$(M), $(1)/$$(M))))) endef -all_includes := $(TTCN3_DIR)/include $(TTCN3_DIR)/src $(TOPDIR)/ccsrc/Framework +all_includes := $(TTCN3_DIR)/include $(TTCN3_DIR)/src $(TOPDIR)/ccsrc/Framework /usr/include/jsoncpp defines += TITAN_RUNTIME_2 _NO_SOFTLINKS_ $(ATS) libs += $(TTCN3_DIR)/lib/libttcn3-rt2-parallel.a -lstdc++fs @@ -39,7 +39,7 @@ defines += LINUX libs += -lpcap -lrt -lpthread endif -libs += -lssl -lcrypto -lxml2 +libs += -lssl -lcrypto -lxml2 -ljsoncpp $(eval $(call IncludeModule, $(TOPDIR)/ttcn/$(ATS))) diff --git a/ccsrc/Externals/LibItsSecurity_externals.cc b/ccsrc/Externals/LibItsSecurity_externals.cc index b32ec8328d6229f03e4195c7e60414b78dadfaf6..8ccfedb31c1a1b848f497bd314c0bf10e4d092fe 100644 --- a/ccsrc/Externals/LibItsSecurity_externals.cc +++ b/ccsrc/Externals/LibItsSecurity_externals.cc @@ -20,6 +20,8 @@ #include "security_services.hh" +#include "geospacial.hh" + #include #include @@ -28,8 +30,10 @@ namespace LibItsSecurity__Functions { + static geospacial g; + // FIXME Unify code with security_services - + /** * \fn OCTETSTRING fx_hashWithSha256(const OCTETSTRING& p__toBeHashedData); * \brief Produces a 256-bit (32-bytes) hash value @@ -1452,7 +1456,7 @@ namespace LibItsSecurity__Functions return TRUE; } - // group geodesic + // group geospacial /* * \brief Check that given polygon doesn't have neither self-intersections nor holes. * \param p_region Polygonal Region diff --git a/ccsrc/geospacial/geospacial.cc b/ccsrc/geospacial/geospacial.cc new file mode 100644 index 0000000000000000000000000000000000000000..f7043b210c22b0bd659927a83b807df5d8272628 --- /dev/null +++ b/ccsrc/geospacial/geospacial.cc @@ -0,0 +1,200 @@ +#include "geospacial.hh" + +coordinates::coordinates() { + latitude = .0; + longitude = .0; + altitude = .0; +} + +coordinates::coordinates(const double p_latitude, const double p_longitude, const double p_altitude) { + latitude = p_latitude; + longitude = p_longitude; + altitude = p_altitude; +} + +const bool coordinates::is_valid_coordinates() const { + if (latitude > -90.0L && latitude < 90.L && longitude > -180.0L && longitude < 180L) { + return true; + } else if (latitude > -HALFPI && latitude < HALFPI && longitude > -PI && longitude < PI) { + return true; + } + return false; +} + +const double coordinates::distance_less_than_1km(const coordinates& p) const { // this position has origin + double a = HALFPI - latitude; + double b = HALFPI - p.latitude; + double c = sqrt(a * a + b * b - 2 * a * b * cos(p.longitude - longitude)); + return (double)(R * c); +} + +const double coordinates::distance(const coordinates& p) const { // this position has origin + double dlon = p.longitude - longitude; + double dlat = p.latitude - latitude; + double s1 = sin(dlat / 2); + double s2 = sin(dlon /2 ); + double a = (s1 * s1) + cos(latitude) * cos(p.latitude) * (s2 * s2); + double c = 2 * asin(std::min((double)1.0L, sqrt(a))); + return (double)(R * c); +} + +point::point() { + x = .0; + y = .0; + z = .0; +} + +point::point(const double p_x, const double p_y, const double p_z) { + x = p_x; + y = p_y; + z = p_z; +} + +int geospacial::load_countries_map(const std::string& p_file) { + std::ifstream ifs; + ifs.open(p_file); + if (ifs.fail()) { + ifs.close(); + return -1; + } + + Json::CharReaderBuilder builder; + builder["collectComments"] = true; + JSONCPP_STRING errs; + Json::Value root; + if (!parseFromStream(builder, ifs, &root, &errs)) { + std::cerr << errs << std::endl; + ifs.close(); + return -1; + } + // Get the value of the member of root named 'encoding', return a 'null' value if there is no such member. + const Json::Value plugins = root["features"]; + for (Json::Value::const_iterator it = plugins.begin() ; it != plugins.end() ; it++ ) { + const Json::Value v = *it; + Json::Value::Members m = v.getMemberNames(); + std::string key; + std::vector coord; + for (std::vector::const_iterator i = m.cbegin(); i != m.cend(); ++i) { + if (std::string(*i).compare("properties") == 0) { + key = process_properties(v[*i]); + } else if (std::string(*i).compare("geometry") == 0) { + coord = process_geometry(v[*i]); + } + } + std::pair>::iterator, bool> ret = _countries.insert(std::pair>(key, coord)); + if (ret.second == false) { + // Element already exist, add update it + //std::cerr << "element already existed: " << key << " - " << coord.size() << std::endl; + _countries[key].insert(_countries[key].end(), coord.begin(), coord.end()); + } + } // End of 'for' statement + ifs.close(); + + return 0; +} + +const int geospacial::is_in_country(const std::string& p_country, const coordinates& p_position) { + if (_countries.size() == 0) { + return -1; + } + std::map>::const_iterator it = _countries.find(p_country); + if (it == _countries.cend()) { + return -1; + } + + point p = wgs84_to_point(p_position.latitude, p_position.longitude); + for (auto ik = it->second.cbegin(); ik != it->second.cend(); ++ik) { + if (is_inside_polygon(*ik, p) == 0) { + return 0; + } + } // End of 'for' statement + + return -1; +} + +const std::string geospacial::process_properties(const Json::Value p_properties) { + return p_properties["iso_n3"].asString(); +} + +const std::vector geospacial::process_geometry(const Json::Value p_geometry) { + std::vector ar; + for (Json::Value::const_iterator it = p_geometry["coordinates"].begin() ; it != p_geometry["coordinates"].end() ; it++ ) { + std::vector polygons = extract_polygons(*it); + ar.insert(ar.end(), polygons.begin(), polygons.end()); + } + + return ar; +} + +const std::vector geospacial::extract_polygons(const Json::Value p_polygon) { + std::vector l; + Json::Value::const_iterator it = p_polygon.begin(); + Json::Value::const_iterator ik = static_cast(*it).begin(); + if (static_cast(*ik).isArray()) { + l = extract_polygons(*it); + } else if (static_cast(*ik).isDouble()) { + polygon p; + for ( ; it != p_polygon.end() ; it++ ) { + ik = static_cast(*it).begin(); + coordinates c( + static_cast(*++ik).asDouble(), // latitude + static_cast(*ik).asDouble(), // longitude + .0 + ); + p.push_back(std::make_tuple(c, wgs84_to_point(c.latitude, c.longitude))); + } // End of 'for' statement + l.push_back(p); + } else { + std::cerr << "extract_polygons: wrong type" << std::endl; + } + + return l; +} + +const point geospacial::wgs84_to_point(const double p_latitude, const double p_longitude) const { + double latitude_rad = p_latitude * PI / 180.0L; + double longitude_rad = p_longitude * PI / 180.0L; + return point( + (double)(R * cos(latitude_rad) * cos(longitude_rad)), + (double)(R * cos(latitude_rad) * sin(longitude_rad)), + (double)(R * sin(latitude_rad)) + ); +} + +const int geospacial::is_inside_polygon(const polygon& p_polygon, const point& q) const { + int i; + double angle = .0L; + point p1; + point p2; + int n = p_polygon.size(); + + for (i = 0; i < n; i++) { + //std::clog << "is_inside_polygon: Processing vertex " << i << " -> " << (i + 1) % n << std::endl; + point p = std::get<1>(p_polygon[i]); + point pnext = std::get<1>(p_polygon[(i + 1) % n]); + p1.x = p.x - q.x; + p1.y = p.y - q.y; + p2.x = pnext.x - q.x; + p2.y = pnext.y - q.y; + angle += CalcAngleSum_2d(p1, p2); + //std::clog << "is_inside_polygon: New angle " << angle << std::endl; + } + //std::clog << "is_inside_polygon: Final angle " << fabs(angle) << std::endl; + + if (fabs(angle) < PI) + return -1; + else + return 0; +} + +const double geospacial::CalcAngleSum_2d(const point& p1, const point& p2) const { + double theta1 = atan2(p1.y, p1.x); + double theta2 = atan2(p2.y, p2.x); + double dtheta = theta2 - theta1; + while (dtheta > PI) + dtheta -= TWOPI; + while (dtheta < -PI) + dtheta += TWOPI; + + return(dtheta); +} diff --git a/ccsrc/geospacial/geospacial.hh b/ccsrc/geospacial/geospacial.hh new file mode 100644 index 0000000000000000000000000000000000000000..d06456206bbd277a3b2ad914aa3cb7b30d0d94a9 --- /dev/null +++ b/ccsrc/geospacial/geospacial.hh @@ -0,0 +1,61 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#define EPSILON 0.0000001 +#define MODULUS(p) (sqrt(p.x * p.x + p.y * p.y + p.z * p.z)) +#define PI 3.1415926535897932384626435 +#define HALFPI 1.5707963267948966192313216916398 +#define TWOPI 6.283185307179586476925287 +//#define RTOD 57.2957795 +#define R 6378140.0 // Radius of the earth in meters + +class coordinates { +public: + double latitude; + double longitude; + double altitude; +public: + coordinates(); + coordinates(const double p_latitude, const double p_longitude, const double p_altitude); + virtual ~coordinates() { }; + inline const coordinates to_radian() const { return coordinates(latitude * PI / 180, longitude * PI / 180, altitude); }; + const bool is_valid_coordinates() const;; + const double distance_less_than_1km(const coordinates& p) const; // this position has origin + const double distance(const coordinates& p) const; // this position has origin +}; + +class point { +public: + double x, y, z; +public: + point(); + point(const double p_x, const double p_y, const double p_z); +}; + +typedef std::vector> polygon; + +class geospacial { + std::map> _countries; + const point wgs84_to_point(const double p_latitude, const double p_longitude) const; + const std::string process_properties(const Json::Value p_properties); + const std::vector process_geometry(const Json::Value p_geometry); + const std::vector extract_polygons(const Json::Value p_polygon); + const double CalcAngleSum_2d(const point& p1, const point& p2) const; + const int is_inside_polygon(const polygon& p_polygon, const point& q) const; +public: + geospacial() { }; + virtual ~geospacial() { }; + int load_countries_map(const std::string& p_file); + const int is_in_country(const std::string& p_country, const coordinates& p_position); +}; diff --git a/ccsrc/geospacial/module.mk b/ccsrc/geospacial/module.mk new file mode 100644 index 0000000000000000000000000000000000000000..5a05a64ea7ec63fc5aefc47ed400c0a673eba024 --- /dev/null +++ b/ccsrc/geospacial/module.mk @@ -0,0 +1,3 @@ +sources := geospacial.cc +includes := . + diff --git a/ttcn/AtsCAM/module.mk b/ttcn/AtsCAM/module.mk index 16395d72c7316068175167ead03624d646b14b46..0337741c5371de2af1d9d5bb2b0b32a57c68f37e 100644 --- a/ttcn/AtsCAM/module.mk +++ b/ttcn/AtsCAM/module.mk @@ -31,6 +31,7 @@ modules := ../LibCommon \ ../../ccsrc/Protocols/Pcap \ ../../ccsrc/Protocols/UpperTester \ ../../ccsrc/Protocols/Security \ + ../../ccsrc/geospacial \ # ../../ccsrc/Protocols/UDP \ # ../../ccsrc/Protocols/Http \ # ../../ccsrc/Protocols/DENM \ diff --git a/ttcn/LibIts b/ttcn/LibIts index 4682888ad6ef018ca1869c5e0cb5e2473b56d842..ec30313a90a101f519e9c41c5225981c3c3f02da 160000 --- a/ttcn/LibIts +++ b/ttcn/LibIts @@ -1 +1 @@ -Subproject commit 4682888ad6ef018ca1869c5e0cb5e2473b56d842 +Subproject commit ec30313a90a101f519e9c41c5225981c3c3f02da