TT12-MCU/applications/map.c
CSSC-WORK\murmur ca4b8ee043 去掉 打印float功能,减少内存占用
临时屏蔽set_cfg功能
添加updateAlarm测试函数
2023-08-23 11:02:26 +08:00

219 lines
6.7 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-06-24 murmur the first version
*/
/**
* 本函数通过geojson文件构建电子围栏并判别是否在围栏内
* 解析geojson文件获取多边形经纬度
* 判断当前坐标是否在多边形内部
*/
#include <rtthread.h>
#define LOG_TAG "map"
#define LOG_LVL LOG_LVL_INFO
#include <ulog.h>
#include <dfs_file.h>
#include <cJSON.h>
/** .geojson文件
{
"type":"FeatureCollection",
"features":[
{
"type":"Feature",
"properties":{
},
"geometry":{
"coordinates":[
[
[
109.84662252076487,
18.40384100935684
],
[
109.84827972641727,
18.391934106424912
],
[
109.86043256475983,
18.391829269588243
],
[
109.86800046865523,
18.396651709843837
],
[
109.86811094900406,
18.41132787117354
],
[
109.85225701894615,
18.41284783067367
],
[
109.84662252076487,
18.40384100935684
]
]
],
"type":"Polygon"
}
}
]
}
*/
/**
* 解析电子围栏的各顶点
* @param fin 电子围栏文件,标准*.geojson文件可通过http://geojson.io/获取
* @param *x 用于存储经度的数组
* @param *y 由于存储纬度的数组
* @return 顶点个数
*/
int mapParse(const char *fin,float *x, float *y)
{
cJSON *root = RT_NULL, *object = RT_NULL, *item = RT_NULL;
int fd_in = -1;
int rst=-RT_ERROR;
fd_in = open(fin, O_RDONLY, 0);
if (fd_in < 0)
{
LOG_E("[hex] open the input file : %s error.", fin);
return rst;
}
size_t file_size = lseek(fd_in, 0, SEEK_END);
lseek(fd_in, 0, SEEK_SET);
rt_uint8_t *buffer = RT_NULL;
buffer = (rt_uint8_t *) rt_malloc(512);
read(fd_in, buffer, file_size);
close(fd_in);
// LOG_HEX("json",16,buffer,file_size);
root = cJSON_Parse((const char *) buffer);
if (!root)
{
LOG_W("No memory for cJSON root!");
goto _exit;
}
//坐标所在层级为 root->features[0]->geometry->coordinates[0]
object = cJSON_GetObjectItem(root, "features");
if (cJSON_IsArray(object))
{
// LOG_D("size of 'features' is %d",cJSON_GetArraySize(object));
object = cJSON_GetArrayItem(object, 0);
item = cJSON_GetObjectItem(object, "geometry");
if (item)
{
cJSON *sitem = cJSON_GetObjectItem(item, "type");
// LOG_D("type is %s",sitem->valuestring);
if (rt_strcmp(sitem->valuestring,"Polygon") != 0)
{
LOG_E("type is not match, needed to be 'Polygon'");
goto _exit;
}
sitem = cJSON_GetObjectItem(item, "coordinates");
if (cJSON_IsArray(sitem))
{
sitem = cJSON_GetArrayItem(sitem, 0);
if (cJSON_IsArray(sitem))
{
size_t cnt = cJSON_GetArraySize(sitem)-1;//最后一个是重复的
LOG_D("cnt of 'coordinates' pairs is %d", cnt);
if (cnt<3) {//至少是个三角形
rst = -RT_ERROR;
LOG_W("cnt of 'coordinates' pairs is too few.");
goto _exit;
}
for (size_t var = 0; var < cnt; var++)
{
cJSON *llp = cJSON_GetArrayItem(sitem, var);
if (cJSON_IsArray(sitem))
{
float lon = cJSON_GetNumberValue(cJSON_GetArrayItem(llp, 0)); //经度
x[var]= lon;
float lat = cJSON_GetNumberValue(cJSON_GetArrayItem(llp, 1)); //维度
y[var]= lat;
LOG_D("%lf-%lf", x[var], y[var]);
rst = cnt;
}
}
}
}
}
}
_exit:
cJSON_Delete(root);
rt_free(buffer);
return rst;
}
// Globals which should be set before calling this function:
//
// int polyCorners = how many corners the polygon has
// float polyX[] = horizontal coordinates of corners
// float polyY[] = vertical coordinates of corners
// float x, y = point to be tested
//
// (Globals are used in this example for purposes of speed. Change as
// desired.)
//
// The function will return YES if the point x,y is inside the polygon, or
// NO if it is not. If the point is exactly on the edge of the polygon,
// then the function may return YES or NO.
//
// Note that division by zero is avoided because the division is protected
// by the "if" clause which surrounds it.
/**
* 判断某点是否在多边形内部移植至http://alienryderflex.com/polygon/
* @param polyCorners 多边形顶点个数
* @param polyX x坐标数组对应经度
* @param polyY y坐标数组对应纬度
* @param x 点的x坐标
* @param y 点的y坐标
* @return
*/
int pointInPolygon(int polyCorners,float polyX[], float polyY[],float x,float y)
{
int i, j=polyCorners-1 ;
int oddNodes=0 ;
for (i=0; i<polyCorners; i++) {
if ((polyY[i]< y && polyY[j]>=y
|| polyY[j]< y && polyY[i]>=y)
&& (polyX[i]<=x || polyX[j]<=x)) {
oddNodes^=(polyX[i]+(y-polyY[i])/(polyY[j]-polyY[i])*(polyX[j]-polyX[i])<x); }
j=i; }
return oddNodes;
}
static demo(int argc, char **argv)
{
char *f = "/map.geojson";
if (argc == 2)
{
rt_strcpy(f,argv[1]);
}
float polyX[10]={},polyY[10]={};
int polyCorners = mapParse(f,polyX,polyY);
for (uint8_t var = 0; var < polyCorners; var++) {
LOG_I("%d=%d.%d,%d.%d",var+1,
(int)polyX[var],(int)((long)(polyX[var]*1000000) % 1000000),
(int)polyY[var],(int)((long)(polyY[var]*1000000) % 1000000));
}
}
MSH_CMD_EXPORT_ALIAS(demo,d_parseFence,);