Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
895991ba98 |
16
.vscode/settings.json
vendored
Normal file
16
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"fstream": "cpp",
|
||||||
|
"__hash_table": "cpp",
|
||||||
|
"deque": "cpp",
|
||||||
|
"forward_list": "cpp",
|
||||||
|
"string": "cpp",
|
||||||
|
"unordered_map": "cpp",
|
||||||
|
"vector": "cpp",
|
||||||
|
"__tree": "cpp",
|
||||||
|
"list": "cpp",
|
||||||
|
"map": "cpp",
|
||||||
|
"set": "cpp",
|
||||||
|
"unordered_set": "cpp"
|
||||||
|
}
|
||||||
|
}
|
BIN
example/ZJGFP01_OUT.kmz
Normal file
BIN
example/ZJGFP01_OUT.kmz
Normal file
Binary file not shown.
@@ -1,8 +1,8 @@
|
|||||||
author = "zhangyi"
|
author = "zhangyi"
|
||||||
kmzFile = "ZJGFP01_OUT.kmz"
|
kmzFile = "example/ZJGFP01_OUT.kmz"
|
||||||
|
|
||||||
[placemark]
|
[placemark]
|
||||||
PointFile = "ZJGFP01.kml"
|
PointFile = "example/ZJGFP01.kml"
|
||||||
useGlobalHeight = "yes"
|
useGlobalHeight = "yes"
|
||||||
useGlobalSpeed = "yes"
|
useGlobalSpeed = "yes"
|
||||||
useGlobalHeadingParam = "yes"
|
useGlobalHeadingParam = "yes"
|
||||||
|
@@ -1,10 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* dji_kmz.cpp - DJI Waypoint File Generator
|
||||||
|
*
|
||||||
|
* Converts Google Earth KML files or plain coordinate files to DJI-compatible KMZ wayline formats.
|
||||||
|
*
|
||||||
|
* Features:
|
||||||
|
* - Supports multiple drone models (Matrice series, Mavic series)
|
||||||
|
* - Configurable flight parameters (altitude, speed, heading modes)
|
||||||
|
* - Flexible waypoint import options (KML/CSV)
|
||||||
|
*
|
||||||
|
* Disclaimer:
|
||||||
|
* This open-source software is provided "as is" without warranty of any kind,
|
||||||
|
* and the author/contributors shall not be liable for any damages arising from its use.
|
||||||
|
*
|
||||||
|
* Author: Dr. Yi Zhang
|
||||||
|
* Contact: School of Earth Science, Zhejiang University
|
||||||
|
* Email: yizhang-geo@zju.edu.cn
|
||||||
|
*/
|
||||||
|
|
||||||
#include "iostream"
|
#include "iostream"
|
||||||
#include "fstream"
|
#include "fstream"
|
||||||
#include "sstream"
|
#include "sstream"
|
||||||
#include "iomanip"
|
#include "iomanip"
|
||||||
#include "vector"
|
#include "vector"
|
||||||
#include "filesystem"
|
//#include "filesystem"
|
||||||
#include "toml.hpp"
|
#include "toml.hpp"
|
||||||
|
#include "simple_kml.hpp"
|
||||||
|
#include "geometry_sph.hpp"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@@ -166,78 +187,11 @@ namespace dji_kmz
|
|||||||
throw std::runtime_error("dji_kmz: Invalid placemark use global turn-param mode.");
|
throw std::runtime_error("dji_kmz: Invalid placemark use global turn-param mode.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_googleEarth_coorpoints(string google_kml, vector<double> &plon, vector<double> &plat)
|
|
||||||
{
|
|
||||||
ifstream ifile(google_kml);
|
|
||||||
if (!ifile) throw std::runtime_error("dji_kmz: Fail to open the google earth's .kml file.");
|
|
||||||
|
|
||||||
plon.clear();
|
|
||||||
plat.clear();
|
|
||||||
|
|
||||||
double lon, lat;
|
|
||||||
string line, cor_str;
|
|
||||||
stringstream line_ss, cor_ss;
|
|
||||||
while (getline(ifile, line))
|
|
||||||
{
|
|
||||||
line.erase(0, line.find_first_not_of(" \t"));
|
|
||||||
line.erase(line.find_last_not_of(" \t") + 1);
|
|
||||||
|
|
||||||
if (line == "<coordinates>")
|
|
||||||
{
|
|
||||||
getline(ifile, line);
|
|
||||||
line.erase(0, line.find_first_not_of(" \t"));
|
|
||||||
line.erase(line.find_last_not_of(" \t") + 1);
|
|
||||||
|
|
||||||
line_ss.clear();
|
|
||||||
line_ss.str(line);
|
|
||||||
while (line_ss >> cor_str)
|
|
||||||
{
|
|
||||||
replace(cor_str.begin(), cor_str.end(), ',', ' ');
|
|
||||||
|
|
||||||
cor_ss.clear();
|
|
||||||
cor_ss.str(cor_str);
|
|
||||||
cor_ss >> lon >> lat;
|
|
||||||
plon.push_back(lon);
|
|
||||||
plat.push_back(lat);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ifile.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
void read_PointFile(string filename, vector<double> &lons, vector<double> &lats, vector<double> &hgts)
|
|
||||||
{
|
|
||||||
std::ifstream infile(filename);
|
|
||||||
if (!infile.is_open()) throw std::runtime_error("dji_kmz: Fail to open point file.");
|
|
||||||
|
|
||||||
lons.clear();
|
|
||||||
lats.clear();
|
|
||||||
hgts.clear();
|
|
||||||
|
|
||||||
string line;
|
|
||||||
stringstream ss_line;
|
|
||||||
double lon, lat, hgt;
|
|
||||||
while (getline(infile, line))
|
|
||||||
{
|
|
||||||
replace(line.begin(), line.end(), ',', ' ');
|
|
||||||
ss_line.clear();
|
|
||||||
ss_line.str(line);
|
|
||||||
ss_line >> lon >> lat >> hgt;
|
|
||||||
|
|
||||||
lons.push_back(lon);
|
|
||||||
lats.push_back(lat);
|
|
||||||
hgts.push_back(hgt);
|
|
||||||
}
|
|
||||||
infile.close();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 在多边形区域内按一定间隔生成航线点
|
* @brief 在多边形区域内按一定间隔生成航线点
|
||||||
*
|
*
|
||||||
* @param plon 多边形顶点经度数组
|
* @param plon 多边形顶点经度数组(首尾点重合)
|
||||||
* @param plat 多边形顶点纬度数组
|
* @param plat 多边形顶点纬度数组(首尾点重合)
|
||||||
* @param lon1 航线参考方向起点经度
|
* @param lon1 航线参考方向起点经度
|
||||||
* @param lat1 航线参考方向起点纬度
|
* @param lat1 航线参考方向起点纬度
|
||||||
* @param lon2 航线参考方向终点经度
|
* @param lon2 航线参考方向终点经度
|
||||||
@@ -403,10 +357,10 @@ This program can read coordinate marker files saved by Google Earth (in KML form
|
|||||||
exten_name = point_file.substr(point_file.find_last_of('.'));
|
exten_name = point_file.substr(point_file.find_last_of('.'));
|
||||||
if (exten_name == ".kml")
|
if (exten_name == ".kml")
|
||||||
{
|
{
|
||||||
dji_kmz::get_googleEarth_coorpoints(point_file, lons, lats);
|
read_kml_lineString(point_file, lons, lats);
|
||||||
hgts.resize(lons.size(), -1.0);
|
hgts.resize(lons.size(), -1.0);
|
||||||
}
|
}
|
||||||
else dji_kmz::read_PointFile(point_file, lons, lats, hgts);
|
else read_plainPoints(point_file, lons, lats, hgts);
|
||||||
|
|
||||||
// Create a template folder
|
// Create a template folder
|
||||||
// The following may diff between different OS-systems, improve later
|
// The following may diff between different OS-systems, improve later
|
||||||
|
104
src/geometry_sph.hpp
Normal file
104
src/geometry_sph.hpp
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
#include "cmath"
|
||||||
|
#include "algorithm"
|
||||||
|
|
||||||
|
#define Earth_R 6371008.8
|
||||||
|
#define WGS84_r 6356752.3142
|
||||||
|
#define WGS84_R 6378136.460
|
||||||
|
#define ZERO 1e-30
|
||||||
|
|
||||||
|
struct pointC
|
||||||
|
{
|
||||||
|
double x, y, z;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pointS
|
||||||
|
{
|
||||||
|
double lon, lat, rad;
|
||||||
|
};
|
||||||
|
|
||||||
|
double module(const pointC& a)
|
||||||
|
{
|
||||||
|
return sqrt(a.x*a.x + a.y*a.y + a.z*a.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
double dot(const pointC& a, const pointC& b)
|
||||||
|
{
|
||||||
|
return a.x*b.x+a.y*b.y+a.z*b.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
pointC cross(const pointC& a, const pointC& b, double cut_off = ZERO)
|
||||||
|
{
|
||||||
|
pointC v;
|
||||||
|
v.x = a.y*b.z-a.z*b.y;
|
||||||
|
v.y = a.z*b.x-a.x*b.z;
|
||||||
|
v.z = a.x*b.y-a.y*b.x;
|
||||||
|
if (fabs(v.x) <= cut_off) v.x = 0;
|
||||||
|
if (fabs(v.y) <= cut_off) v.y = 0;
|
||||||
|
if (fabs(v.z) <= cut_off) v.z = 0;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
pointC s2c(const pointS& ps)
|
||||||
|
{
|
||||||
|
pointC pc;
|
||||||
|
pc.x = ps.rad*cos(M_PI * ps.lat/180.0)*cos(M_PI * ps.lon/180.0);
|
||||||
|
pc.y = ps.rad*cos(M_PI * ps.lat/180.0)*sin(M_PI * ps.lon/180.0);
|
||||||
|
pc.z = ps.rad*sin(M_PI * ps.lat/180.0);
|
||||||
|
return pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
pointC e2c(const pointS& ps, double r, double R)
|
||||||
|
{
|
||||||
|
pointC v;
|
||||||
|
v.x = R*cos(M_PI*ps.lat/180.0)*cos(M_PI*ps.lon/180.0);
|
||||||
|
v.y = R*cos(M_PI*ps.lat/180.0)*sin(M_PI*ps.lon/180.0);
|
||||||
|
v.z = r*sin(M_PI*ps.lat/180.0);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
pointS c2s(const pointC& pc)
|
||||||
|
{
|
||||||
|
pointS ps;
|
||||||
|
ps.rad = sqrt(pow(pc.x,2)+pow(pc.y,2)+pow(pc.z,2));
|
||||||
|
if (fabs(ps.rad) < ZERO) //点距离原点极近 将点置于原点
|
||||||
|
{
|
||||||
|
ps.lat = ps.lon = ps.rad = 0.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ps.lat = 90.0 - acos(pc.z/ps.rad)*180.0/M_PI;
|
||||||
|
ps.lon = atan2(pc.y, pc.x)*180.0/M_PI;
|
||||||
|
}
|
||||||
|
return ps;
|
||||||
|
}
|
||||||
|
|
||||||
|
double bigArc_angle(const pointS& ps1, const pointS& ps2)
|
||||||
|
{
|
||||||
|
pointC a = s2c(ps1);
|
||||||
|
pointC b = s2c(ps2);
|
||||||
|
double d = std::min(1.0, std::max(-1.0, dot(a, b)/(module(a)*module(b))));
|
||||||
|
return acos(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
double bigArc_distance(const pointS& ps1, const pointS& ps2)
|
||||||
|
{
|
||||||
|
double arc = bigArc_angle(ps1, ps2);
|
||||||
|
return Earth_R*arc/(2*M_PI);
|
||||||
|
}
|
||||||
|
|
||||||
|
pointS bigArc_intersection(const pointS& ps11, const pointS& ps12,
|
||||||
|
const pointS& ps21, const pointS& ps22)
|
||||||
|
{
|
||||||
|
pointC p1 = cross(s2c(ps12), s2c(ps11));
|
||||||
|
pointC p2 = cross(s2c(ps22), s2c(ps21));
|
||||||
|
pointC c = cross(p1, p2);
|
||||||
|
|
||||||
|
// 这里假设大圆弧从1点到2点并延伸,因此交点与1点夹角应更大,否则反向
|
||||||
|
if (bigArc_angle(ps11, c2s(c)) < bigArc_angle(ps12, c2s(c)) ||
|
||||||
|
bigArc_angle(ps21, c2s(c)) < bigArc_angle(ps22, c2s(c)))
|
||||||
|
{
|
||||||
|
c.x *= -1.0; c.y *= -1.0; c.z *= -1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return c2s(c);
|
||||||
|
}
|
129
src/simple_kml.hpp
Normal file
129
src/simple_kml.hpp
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
#include "iostream"
|
||||||
|
#include "fstream"
|
||||||
|
#include "sstream"
|
||||||
|
#include "iomanip"
|
||||||
|
#include "vector"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
string trimstr(string s)
|
||||||
|
{
|
||||||
|
s.erase(0, s.find_first_not_of(" \t"));
|
||||||
|
s.erase(s.find_last_not_of(" \t") + 1);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_plainPoints(string filename, vector<double> &lons, vector<double> &lats, vector<double> &hgts)
|
||||||
|
{
|
||||||
|
std::ifstream infile(filename);
|
||||||
|
if (!infile.is_open()) throw std::runtime_error("dji_kmz: Fail to open point file.");
|
||||||
|
|
||||||
|
lons.clear();
|
||||||
|
lats.clear();
|
||||||
|
hgts.clear();
|
||||||
|
|
||||||
|
string line;
|
||||||
|
stringstream ss_line;
|
||||||
|
double lon, lat, hgt;
|
||||||
|
while (getline(infile, line))
|
||||||
|
{
|
||||||
|
replace(line.begin(), line.end(), ',', ' ');
|
||||||
|
ss_line.clear();
|
||||||
|
ss_line.str(line);
|
||||||
|
ss_line >> lon >> lat >> hgt;
|
||||||
|
|
||||||
|
lons.push_back(lon);
|
||||||
|
lats.push_back(lat);
|
||||||
|
hgts.push_back(hgt);
|
||||||
|
}
|
||||||
|
infile.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_kml_lineString(string google_kml, vector<double> &plon, vector<double> &plat)
|
||||||
|
{
|
||||||
|
ifstream ifile(google_kml);
|
||||||
|
if (!ifile) throw std::runtime_error("dji_kmz: Fail to open the google earth's .kml file.");
|
||||||
|
|
||||||
|
plon.clear();
|
||||||
|
plat.clear();
|
||||||
|
|
||||||
|
double lon, lat;
|
||||||
|
string line, cor_str, l_name;
|
||||||
|
stringstream line_ss, cor_ss;
|
||||||
|
while (getline(ifile, line))
|
||||||
|
{
|
||||||
|
if (trimstr(line) == "<LineString>") // 寻找路径标记段
|
||||||
|
{
|
||||||
|
while (getline(ifile, line))
|
||||||
|
{
|
||||||
|
if (trimstr(line) == "<coordinates>") // 找到坐标点开始行
|
||||||
|
{
|
||||||
|
getline(ifile, line);
|
||||||
|
|
||||||
|
line_ss.clear();
|
||||||
|
line_ss.str(trimstr(line));
|
||||||
|
while (line_ss >> cor_str)
|
||||||
|
{
|
||||||
|
replace(cor_str.begin(), cor_str.end(), ',', ' ');
|
||||||
|
|
||||||
|
cor_ss.clear();
|
||||||
|
cor_ss.str(cor_str);
|
||||||
|
cor_ss >> lon >> lat;
|
||||||
|
plon.push_back(lon);
|
||||||
|
plat.push_back(lat);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ifile.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_kml_polygon(string google_kml, vector<double> &plon, vector<double> &plat)
|
||||||
|
{
|
||||||
|
ifstream ifile(google_kml);
|
||||||
|
if (!ifile) throw std::runtime_error("dji_kmz: Fail to open the google earth's .kml file.");
|
||||||
|
|
||||||
|
plon.clear();
|
||||||
|
plat.clear();
|
||||||
|
|
||||||
|
double lon, lat;
|
||||||
|
string line, cor_str, l_name;
|
||||||
|
stringstream line_ss, cor_ss;
|
||||||
|
while (getline(ifile, line))
|
||||||
|
{
|
||||||
|
if (trimstr(line) == "<Polygon>") // 寻找路径标记段
|
||||||
|
{
|
||||||
|
while (getline(ifile, line))
|
||||||
|
{
|
||||||
|
if (trimstr(line) == "<coordinates>") // 找到坐标点开始行
|
||||||
|
{
|
||||||
|
getline(ifile, line);
|
||||||
|
|
||||||
|
line_ss.clear();
|
||||||
|
line_ss.str(trimstr(line));
|
||||||
|
while (line_ss >> cor_str)
|
||||||
|
{
|
||||||
|
replace(cor_str.begin(), cor_str.end(), ',', ' ');
|
||||||
|
|
||||||
|
cor_ss.clear();
|
||||||
|
cor_ss.str(cor_str);
|
||||||
|
cor_ss >> lon >> lat;
|
||||||
|
plon.push_back(lon);
|
||||||
|
plat.push_back(lat);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ifile.close();
|
||||||
|
return;
|
||||||
|
}
|
Reference in New Issue
Block a user