490eae8d23
降低repGetTT 和 getTT 的堆栈分配 更新build逻辑 recTT 调整优先级 rt_device_read返回结果判断 ------- 缓存版本,后续版本采用外置sram加大内存
221 lines
6.7 KiB
C
221 lines
6.7 KiB
C
/*
|
||
* 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));
|
||
cJSON *tmp = cJSON_GetArrayItem(object, 0);
|
||
item = cJSON_GetObjectItem(tmp, "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))
|
||
{
|
||
cJSON *tmp2 = cJSON_GetArrayItem(sitem, 0);
|
||
if (cJSON_IsArray(tmp2))
|
||
{
|
||
size_t cnt = cJSON_GetArraySize(tmp2)-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(tmp2, var);
|
||
if (cJSON_IsArray(llp))
|
||
{
|
||
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]={};
|
||
// cmd_free();
|
||
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));
|
||
}
|
||
// cmd_free();
|
||
}
|
||
MSH_CMD_EXPORT_ALIAS(demo,d_parseFence,解析围栏);
|