}
#if 0
//使用随机数来进行测试
- srand(time(NULL));
- // 纬度范围: 22.45° 到 22.87° ,适当扩大一点范围
+ srand(time(NULL));
+ // 纬度范围:
float lat = (rand() % 420) / 10.0f + 224.5;
lat = lat / 10.0f;
- // 经度范围: 113.75° 到 114.64° ,适当扩大一点范围
+ // 经度范围:
float lng = (rand() % 890) / 10.0f + 1137.5;
lng = lng / 10.0f;
TraingModel::GetInstance()->AddGPSData(0, lat, lng);
static double getmax(double a, double b) { return a > b ? a : b; }
-// 通过经纬度数据集映射画布绘制轨迹坐标集
+// 计算点p到由p1和p2确定的线段的垂直距离
+static double perpendicularDistance(const Point &p, const Point &p1,
+ const Point &p2) {
+ double dx = p2.x - p1.x;
+ double dy = p2.y - p1.y;
+
+ // 线段长度的平方
+ double len2 = dx * dx + dy * dy;
+
+ // 如果线段实际上是一个点,返回点p到p1的距离
+ if (len2 == 0)
+ return std::sqrt((p.x - p1.x) * (p.x - p1.x) + (p.y - p1.y) * (p.y - p1.y));
+
+ // 考虑从p1到p的向量在从p1到p2的向量上的投影
+ double t = ((p.x - p1.x) * dx + (p.y - p1.y) * dy) / len2;
+
+ if (t < 0) {
+ // 投影在p1之前
+ return std::sqrt((p.x - p1.x) * (p.x - p1.x) + (p.y - p1.y) * (p.y - p1.y));
+ }
+ if (t > 1) {
+ // 投影在p2之后
+ return std::sqrt((p.x - p2.x) * (p.x - p2.x) + (p.y - p2.y) * (p.y - p2.y));
+ }
+
+ // 投影在线段上
+ Point projection;
+ projection.x = p1.x + t * dx;
+ projection.y = p1.y + t * dy;
+
+ return std::sqrt((p.x - projection.x) * (p.x - projection.x) +
+ (p.y - projection.y) * (p.y - projection.y));
+}
+
+// Douglas-Peucker算法实现
+static void douglasPeucker(const std::vector<Point> &points, double epsilon,
+ std::vector<Point> &result) {
+ double dmax = 0;
+ int index = 0;
+ int end = points.size() - 1;
+
+ // 找到距离最大的点
+ for (int i = 1; i < end; i++) {
+ double d = perpendicularDistance(points[i], points[0], points[end]);
+ if (d > dmax) {
+ index = i;
+ dmax = d;
+ }
+ }
+
+ // 如果最大距离大于阈值,则递归处理
+ if (dmax > epsilon) {
+ std::vector<Point> recResults1, recResults2;
+
+ // 递归处理前半部分
+ std::vector<Point> firstSegment(points.begin(), points.begin() + index + 1);
+ douglasPeucker(firstSegment, epsilon, recResults1);
+
+ // 递归处理后半部分
+ std::vector<Point> secondSegment(points.begin() + index, points.end());
+ douglasPeucker(secondSegment, epsilon, recResults2);
+
+ // 合并结果
+ result.assign(recResults1.begin(), recResults1.end() - 1);
+ result.insert(result.end(), recResults2.begin(), recResults2.end());
+ } else {
+ // 否则保留首尾点
+ result.clear();
+ result.push_back(points[0]);
+ result.push_back(points[end]);
+ }
+}
+
+// 修改后的GetPointData函数
void TraingModel::GetPointData() {
- // 1. 按比例采样最多100个点位
std::vector<GPSData> sampledData;
+
+ // 使用Douglas-Peucker算法简化轨迹
if (gpsData.size() > 100) {
- double step = static_cast<double>(gpsData.size() - 1) / 99;
- for (int i = 0; i < 100; i++) {
- int index = static_cast<int>(i * step);
- sampledData.push_back(gpsData[index]);
+ // 先将GPS数据转换为屏幕坐标
+ std::vector<Point> screenPoints;
+
+ // 计算经纬度范围
+ double minLat = 90.0, maxLat = -90.0;
+ double minLon = 180.0, maxLon = -180.0;
+ for (const auto &point : gpsData) {
+ minLat = getmin(minLat, point.latitude);
+ maxLat = getmax(maxLat, point.latitude);
+ minLon = getmin(minLon, point.longitude);
+ maxLon = getmax(maxLon, point.longitude);
+ }
+
+ // 转换为屏幕坐标
+ for (const auto &point : gpsData) {
+ double normLat = (point.latitude - minLat) / (maxLat - minLat);
+ double normLon = (point.longitude - minLon) / (maxLon - minLon);
+ screenPoints.push_back({normLon * 300 + 50, (1.0 - normLat) * 300 + 50});
+ }
+
+ // 使用Douglas-Peucker算法简化
+ std::vector<Point> simplifiedPoints;
+ douglasPeucker(screenPoints, 2.0, simplifiedPoints); // 阈值2.0可以调整
+
+ // 如果简化后的点仍然超过100个,则进行均匀采样
+ if (simplifiedPoints.size() > 100) {
+ double step = static_cast<double>(simplifiedPoints.size() - 1) / 99;
+ for (int i = 0; i < 100; i++) {
+ int index = static_cast<int>(i * step);
+ // 这里需要将屏幕坐标反推回GPS坐标
+ double normX = (simplifiedPoints[index].x - 50) / 300;
+ double normY = (simplifiedPoints[index].y - 50) / 300;
+ double lat = minLat + (1.0 - normY) * (maxLat - minLat);
+ double lon = minLon + normX * (maxLon - minLon);
+ sampledData.push_back({lat, lon});
+ }
+ } else {
+ // 简化后的点少于100个,直接使用
+ for (const auto &point : simplifiedPoints) {
+ double normX = (point.x - 50) / 300;
+ double normY = (point.y - 50) / 300;
+ double lat = minLat + (1.0 - normY) * (maxLat - minLat);
+ double lon = minLon + normX * (maxLon - minLon);
+ sampledData.push_back({lat, lon});
+ }
}
} else {
sampledData = gpsData;
}
- // 2. 计算经纬度的最小值和最大值
+ // 接下来的坐标映射部分保持不变
+ canvasData.clear();
+ const double canvasSize = 300.0;
+ const double offset = 50.0;
+
+ // 重新计算经纬度范围(基于采样后的数据)
double minLat = 90.0, maxLat = -90.0;
double minLon = 180.0, maxLon = -180.0;
for (const auto &point : sampledData) {
maxLon = getmax(maxLon, point.longitude);
}
- // 3. 将经纬度映射到350×350画布区域(居中在400×400画布)
- canvasData.clear();
- const double canvasSize = 300.0;
- const double offset = 50.0; // 400 - 300 = 100,两边各留50的边距
-
+ // 映射到画布坐标
for (const auto &point : sampledData) {
- // 归一化处理(0-1范围)
double normLat = (point.latitude - minLat) / (maxLat - minLat);
double normLon = (point.longitude - minLon) / (maxLon - minLon);
-
- // 映射到画布坐标(考虑偏移)
double x = normLon * canvasSize + offset;
- double y = (1.0 - normLat) * canvasSize +
- offset; // 注意:y轴需要反转(屏幕坐标系向下为正)
-
+ double y = (1.0 - normLat) * canvasSize + offset;
canvasData.push_back({x, y});
}
-
- //修改起点与终点
}
// 添加经纬度数据集
// return;
}
#if defined(SUPPORT_GNSS)
-
- TraingModel::GetInstance()->;
-
+ gps_data_t *gps_data = getGPSGlobaldata();
+ if (gps_data == NULL) {
+ PRINT("gps_data == NULL \n");
+ return;
+ }
+ //判断是否为第一次定位
+ if (gps_data->last_gps_time_ms > 0) {
+ memcpy_s(&send_gps_data, sizeof(gps_data_t), gps_data, sizeof(gps_data_t));
+ }
+ //判断是否定位成功
+ if (send_gps_data.status > 1) {
+ //定位成功
+ TraingModel::GetInstance()->SetGPSConnectState(true);
+ } else {
+ TraingModel::GetInstance()->SetGPSConnectState(false);
+ }
#endif
}
/*