#ifndef _JFXMAP_COORDSYS_H_ #define _JFXMAP_COORDSYS_H_ #include <cmath> #include <iostream> #include <istream> #include <map> #include <ostream> #include <set> #include <vector> #include "MapConfig.h" #include "MapTypes.hpp" #include "Serialize.h" #include "Utils.h" #include "ajson.hpp" namespace jf { static const double PI = 3.1415926535897932384626; double Rad2Degree(double rad); inline double Dot(const XYZ &from, const XYZ &to) { return from.x * to.x + from.y * to.y; } inline double Cross(const XYZ &from, const XYZ &to) { return from.x * to.y - from.y * to.x; } // 右手坐标系 struct Rot { Rot() : angle(0) {} Rot(double in_angle) : angle(in_angle) {} Rot(const XYZ &from, const XYZ &to) : angle(0) { if (from == to) { angle = 0; } else { XYZ toward = to - from; XYZ norm_toward = norm(toward); XYZ x0(0, 1, 0); double cos = Dot(x0, norm_toward); angle = acos(cos) * 180 / PI; if (Cross(x0, norm_toward) < 0) { angle = -angle; } } } double angle; // 右手坐标系逆时针正,顺时针负 Rot operator+(const Rot &o) const { Rot ret; ret.angle = angle + o.angle; return ret; } // 新方向 - 旧方向 : 旧方向到新方向要至少旋转多少? 两个旋转方向取angle值小的 Rot operator-(const Rot &o) const { Rot ret; Rot new_rot = *this; Rot old_rot = o; if (new_rot.angle < 0) { new_rot.angle = new_rot.angle + 360.0; } if (old_rot.angle < 0) { old_rot.angle = old_rot.angle + 360.0; } ret.angle = new_rot.angle - old_rot.angle; return ret; } }; inline Rect2D TId2Rect(const TileId &tid) { double lonlb = tid.nLonId * MapConfig::tile_lon_interval; double latlb = tid.nLatId * MapConfig::tile_lat_interval; double lonrt = (tid.nLonId + 1) * MapConfig::tile_lon_interval; double latrt = (tid.nLatId + 1) * MapConfig::tile_lat_interval; return Rect2D(Point(lonlb, latlb, 0), Point(lonrt, latrt, 0)); } // point到tile左下角点 inline Point P2TLBP(const Point &p) { double lon = int(p.dLon / MapConfig::tile_lon_interval) * MapConfig::tile_lon_interval; double lat = int(p.dLat / MapConfig::tile_lat_interval) * MapConfig::tile_lat_interval; return Point(lon, lat, p.dAlt); } inline Point P2TRTP(const Point &p) { double lon = int(p.dLon / MapConfig::tile_lon_interval) * MapConfig::tile_lon_interval + MapConfig::tile_lon_interval; double lat = int(p.dLat / MapConfig::tile_lat_interval) * MapConfig::tile_lat_interval + MapConfig::tile_lat_interval; return Point(lon, lat, p.dAlt); } inline Rect2D P2TRect(const Point &p) { Point tlbp = P2TLBP(p); Point trtp = P2TRTP(p); return Rect2D(tlbp, trtp); } inline TileId String2TId(const std::string &s) { std::vector<int> tid; jf::Utils::SplitToArray(s, ',', tid); if (tid.size() >= 2) return TileId(tid[0], tid[1]); else return TileId(0, 0); } inline TileId P2TId(const Point &p, float tile_lon_interval, float tile_lat_interval) { int lonId = Utils::DoubleToInt(p.dLon / tile_lon_interval); int latId = Utils::DoubleToInt(p.dLat / tile_lat_interval); return TileId(lonId, latId); } inline std::set<TileId> R2TIds(const Rect2D &r) { Point fromlb = P2TLBP(r.lb); Point tort = P2TRTP(r.rt); std::vector<double> lons; std::vector<double> lats; std::set<TileId> ret; for (double lon = fromlb.dLon; lon < tort.dLon; lon += MapConfig::tile_lon_interval) { lons.push_back(lon); } for (double lat = fromlb.dLat; lat < tort.dLat; lat += MapConfig::tile_lat_interval) { lats.push_back(lat); } for (auto lon : lons) for (auto lat : lats) ret.insert(P2TId(Point(lon, lat, 0))); return ret; } Point TId2PointLB(const TileId &tid); void GaussProjCal(double longitude, double latitude, double &X, double &Y); void GaussProjInvCal(double X, double Y, double &longitude, double &latitude); inline std::vector<Point> InterP(const Point &p1, const Point &p2, float interval) { XYZ xyz1 = P2XYZ(p1); XYZ xyz2 = P2XYZ(p2); XYZ dir = xyz2 - xyz1; float len = dir.length(); XYZ unit = dir / len; std::vector<Point> ret; ret.push_back(p1); for (float l = interval; l < len; l += interval) { XYZ now = xyz1 + unit * l; ret.push_back(XYZ2P(now)); } ret.push_back(p2); return ret; } /** * @brief 笛卡尔坐标系下距离平方 * * @param l * @param r * @return double */ double D2XYZ(const XYZ &l, const XYZ &r, bool consider_alt = false); double D2XYZ(const Point &l, const Point &r, bool consider_alt = false); /** * @brief 笛卡尔坐标系下距离 * * @param l * @param r * @return double */ double DXYZ(const XYZ &l, const XYZ &r, bool consider_alt = false); double DXYZ(const Point &l, const Point &r, bool consider_alt = false); /** * @brief 84坐标系距离平方 * * @param l 点a * @param r 点b * @return double */ double D2_84(const Point &l, const Point &r); /** * @brief 84坐标系距离 * * @param l 点a * @param r 点b * @return double */ double D_84(const Point &l, const Point &r); inline bool test_near(const Point &p1, const Point &p2) { if (std::abs(p1.dLon - p2.dLon) < 0.001 && std::abs(p1.dLat - p2.dLat) < 0.001) { return true; } return false; } } // namespace jf #ifndef jfxmap_serialize_override_tileId jfxmap_serialize(jf::TileId, nLonId, nLatId); #endif #ifndef jfxmap_serialize_override_point jfxmap_serialize(jf::Point, dLon, dLat, dAlt); #endif #ifndef jfxmap_serialize_override_rot jfxmap_serialize(jf::Rot, angle); #endif #ifndef jfxmap_serialize_override_rect2d jfxmap_serialize(jf::Rect2D, lb, rt); #endif #endif