TT12-MCU/applications/map.c

221 lines
6.7 KiB
C
Raw Normal View History

/*
* 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,);