首先是要获取geojson数据
geojson
离线区域地图数据,由经纬度数组组成
http://datav.aliyun.com/tools/atlas/#&lat=27.059125784374068&lng=105.205078125&zoom=3
# 流程
判断一个gps的经纬度处于哪个区域,国内按省市划分
判断算法:
向量直线相交,交点为偶数就不处于该区域,奇数则在
算法地址: http://turfjs.org/docs/#pointOnFeature
# GeoJSON
http://geojson.io/
地理要素 | 描述 |
---|---|
Point | 点 |
MultiPoint | 多点 |
LineString | 线 |
MultiLineString | 多线 |
Polygon | 多边形 |
MultiPolygon | 多个多边形 列表的层级不一样会出现不一样的效果 |
GeometryCollection | 多种基本地理要素的集合 |
一个行政区域的Geo边界为 MultiPolygon 对象,及其领域为多个多边形组成,另需注意多边形的层级差异,中空多边形行成等
# 判断点在多边形内部的方法
射线法:
以被测点Q为端点,向任意方向作射线(一般水平向右作射线),统计该射线与多边形的交点数。如果为奇数,Q在多边形内;如果为偶数,Q在多边形外。
// c
const double eps = 1e-6;
const double PI = acos(-1);
//三态函数,判断两个double在eps精度下的大小关系
int dcmp(double x)
{
if(fabs(x)<eps) return 0;
else
return x<0?-1:1;
}
//判断点Q是否在P1和P2的线段上
bool OnSegment(Point P1,Point P2,Point Q)
{
//前一个判断点Q在P1P2直线上 后一个判断在P1P2范围上
return dcmp((P1-Q)^(P2-Q))==0&&dcmp((P1-Q)*(P2-Q))<=0;
}
//判断点P在多边形内-射线法
bool InPolygon(Point P)
{
bool flag = false; //相当于计数
Point P1,P2; //多边形一条边的两个顶点
for(int i=1,j=n;i<=n;j=i++)
{
//polygon[]是给出多边形的顶点
P1 = polygon[i];
P2 = polygon[j];
if(OnSegment(P1,P2,P)) return true; //点在多边形一条边上
//前一个判断min(P1.y,P2.y)<P.y<=max(P1.y,P2.y)
//这个判断代码我觉得写的很精妙 我网上看的 应该是大神模版
//后一个判断被测点 在 射线与边交点 的左边
if( (dcmp(P1.y-P.y)>0 != dcmp(P2.y-P.y)>0)
&& dcmp(P.x - (P.y-P1.y)*(P1.x-P2.x)/(P1.y-P2.y)-P1.x)<0)
flag = !flag;
}
return flag;
}
另一种做法:
如果多边形是凸的,则可以将多边形视为从第一个顶点开始的“路径”。如果一个点始终位于构成路径的所有线段的同一侧,则该点位于该多边形的内部。
给定P0(x0,y0)和P1(x1,y1)之间的线段,另一个点P(x,y)与该线段具有以下关系。计算(y-y0)(x1-x0)-(x-x0)(y1-y0)
如果小于0,则P位于线段的右侧;如果大于0,则P位于线段的左侧;如果等于0,则其位于线段上。
// c#
/// <summary>
/// 确定给定点是否在多边形内
/// </summary>
/// <param name="polygon">多边形的顶点</param>
/// <param name="point">给定的点</param>
/// <returns>在内部为真,否则假</returns>
public static bool IsPointInPolygon(this List<List<float>> polygon, List<float> point)
{
bool result = false;
int j = polygon.Count() - 1;
for (int i = 0; i < polygon.Count(); i++)
{
// 相交
if ((polygon[i][1] < point[1] && polygon[j][1] >= point[1]) || (polygon[j][1] < point[1] && polygon[i][1] >= point[1]))
{
// 判断被测点 在 射线与边交点 的左边(X更小)
if (polygon[i][0] + (point[1] - polygon[i][1]) / (polygon[j][1] - polygon[i][1]) * (polygon[j][0] - polygon[i][0]) < point[0])
{
result = !result;
}
}
j = i;
}
return result;
}