随便写点技术性的文章
地理围栏(Geo-fencing)是LBS的一种新应用,就是用一个虚拟的栅栏围出一个虚拟地理边界。当手机进入、离开某个特定地理区域,或在该区域内活动时,手机可以接收自动通知和警告。有了地理围栏技术,位置社交网站就可以帮助用户在进入某一地区时自动登记。
我们通常用经纬度来表示一个地理位置,但是由于一些原因,我们从不同渠道得到的经纬度信息可能并不是在同一个坐标系下。
不同的坐标系之间可能有几十到几百米的偏移,所以在开发基于地图的产品,或者做地理数据可视化时,我们需要修正不同坐标系之间的偏差。
WGS-84(World Geodetic System, WGS)是使用最广泛的坐标系,也是世界通用的坐标系,GPS设备得到的经纬度就是在WGS84坐标系下的经纬度。通常通过底层接口得到的定位信息都是WGS84坐标系。
GCJ-02(G-Guojia国家,C-Cehui测绘,J-Ju局),又被称为火星坐标系,是一种基于WGS-84制定的大地测量系统,由中国国测局制定。此坐标系所采用的混淆算法会在经纬度中加入随机的偏移。
国家规定,中国大陆所有公开地理数据都需要至少用GCJ-02进行加密,也就是说我们从国内公司的产品中得到的数据,一定是经过了加密的。绝大部分国内互联网地图提供商都是使用GCJ-02坐标系,包括高德地图,谷歌地图中国区等。
BD-09(Baidu, BD)是百度地图使用的地理坐标系,其在GCJ-02上多增加了一次变换,用来保护用户隐私。从百度产品中得到的坐标都是BD-09坐标系。
不同坐标系下的点在百度地图上会有偏移
坐标系 | 坐标格式 | 说明 |
---|---|---|
WGS84 | [lng,lat] | WGS-84坐标系,GPS设备获取的经纬度坐标 |
GCJ02 | [lng,lat] | GCJ-02坐标系,google中国地图、SoSo地图、AliYun地图、MapAbc地图和高德地图所用的经纬度坐标 |
BD09 | [lng,lat] | BD-09坐标系,百度地图采用的经纬度坐标 |
BD09LL | [lng,lat] | 同BD09 |
BD09MC | [x,y] | BD-09米制坐标,百度地图采用的米制坐标,单位:米 |
BD09Meter | [x,y] | 同BD09MC |
Baidu | [lng,lat] | 百度坐标系,BD-09坐标系别名,同BD-09 |
BMap | [lng,lat] | 百度地图,BD-09坐标系别名,同BD-09 |
AMap | [lng,lat] | 高德地图,同GCJ-02 |
WebMercator | [x,y] | Web Mercator投影,墨卡托投影,同EPSG3857,单位:米 |
WGS1984 | [lng,lat] | WGS-84坐标系别名,同WGS-84 |
EPSG4326 | [lng,lat] | WGS-84坐标系别名,同WGS-84 |
EPSG3857 | [x,y] | Web Mercator投影,同WebMercator,单位:米 |
EPSG900913 | [x,y] | Web Mercator投影,同WebMercator,单位:米 |
地理围栏或地理围栏集的数据由 rfc7946 中定义的、采用 GeoJSON
格式的 Feature
对象和 FeatureCollection
对象表示。 除此之外:
Feature
对象或 FeatureCollection
对象。Point
、MultiPoint
、LineString
、MultiLineString
、Polygon
、MultiPolygon
和 GeometryCollection
。geometryId
。Point
、MultiPoint
、LineString
、MultiLineString
的特征必须在属性中包含 radius
。 radius
值的计量单位为米,radius
值的范围为 1 到 10000。polygon
和 multipolygon
几何类型的特征没有半径属性。validityTime
是可选属性,可让用户为地理围栏数据设置过期时间和有效时间。 如果未指定该属性,则数据永不过期,而是一直有效。expiredTime
是地理围栏数据的过期日期和时间。 如果请求中 userTime
的值晚于此值,则将相应的地理围栏数据视为过期的数据,且不会查询这些数据。 基于这一点,此地理围栏数据的 geometryId 将包含在地理围栏响应中的 expiredGeofenceGeometryId
数组内。validityPeriod
是地理围栏有效时段的列表。 如果请求中 userTime
的值超出有效时段,则将相应的地理围栏数据视为无效,且不会查询这些数据。 此地理围栏数据的 geometryId 包含在地理围栏响应中的 invalidPeriodGeofenceGeometryId
数组内。 下表显示了 validityPeriod 元素的属性。名称 | 类型 | 必需 | 说明 |
---|---|---|---|
startTime | datetime | 是 | 有效时段的开始日期时间。 |
endTime | datetime | 是 | 有效时段的结束日期时间。 |
recurrenceType | 字符串 | false | 时段的重复类型。 值可为 Daily 、Weekly 、Monthly 或 Yearly 。 默认值为 Daily 。 |
businessDayOnly | Boolean | false | 指示数据是否仅在工作日有效。 默认值为 false 。 |
WGS84
。MultiPoint
、MultiLineString
、MultiPolygon
或 GeometryCollection
的每个特征,属性将应用到所有元素。 例如:中的所有点 MultiPoint
都将使用相同的半径形成多个圆形地域隔离区内。GeoJSON 规范仅支持以下几何图形:
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [125.6, 10.1]
},
"properties": {
"name": "Dinagat Islands"
}
}
{
"type": "LineString",
"coordinates": [
[30.0, 10.0], [10.0, 30.0], [40.0, 40.0]
]
}
{
"type": "Polygon",
"coordinates": [
[[30.0, 10.0], [40.0, 40.0], [20.0, 40.0], [10.0, 20.0], [30.0, 10.0]]
]
}
{
"type": "Polygon",
"coordinates": [
[[35.0, 10.0], [45.0, 45.0], [15.0, 40.0], [10.0, 20.0], [35.0, 10.0]],
[[20.0, 30.0], [35.0, 35.0], [30.0, 20.0], [20.0, 30.0]]
]
}
{
"type": "MultiPoint",
"coordinates": [
[10.0, 40.0], [40.0, 30.0], [20.0, 20.0], [30.0, 10.0]
]
}
{
"type": "MultiLineString",
"coordinates": [
[[10.0, 10.0], [20.0, 20.0], [10.0, 40.0]],
[[40.0, 40.0], [30.0, 30.0], [40.0, 20.0], [30.0, 10.0]]
]
}
{
"type": "MultiPolygon",
"coordinates": [
[
[[30.0, 20.0], [45.0, 40.0], [10.0, 40.0], [30.0, 20.0]]
],
[
[[15.0, 5.0], [40.0, 10.0], [10.0, 20.0], [5.0, 10.0], [15.0, 5.0]]
]
]
}
{
"type": "MultiPolygon",
"coordinates": [
[
[[40.0, 40.0], [20.0, 45.0], [45.0, 30.0], [40.0, 40.0]]
],
[
[[20.0, 35.0], [10.0, 30.0], [10.0, 10.0], [30.0, 5.0], [45.0, 20.0], [20.0, 35.0]],
[[30.0, 20.0], [20.0, 15.0], [20.0, 25.0], [30.0, 20.0]]
]
]
}
{
"type": "GeometryCollection",
"geometries": [
{
"type": "Point",
"coordinates": [40.0, 10.0]
},
{
"type": "LineString",
"coordinates": [
[10.0, 10.0], [20.0, 20.0], [10.0, 40.0]
]
},
{
"type": "Polygon",
"coordinates": [
[[40.0, 40.0], [20.0, 45.0], [45.0, 30.0], [40.0, 40.0]]
]
}
]
}
Circle
GeoJSON 规范不支持该几何图形。我们使用 GeoJSON Point Feature
对象来表示圆。
Circle
使用对象表示的几何图形 GeoJSON Feature
必须 包含以下坐标和属性:
圆心 (Center)
圆心使用 GeoJSON Point
对象表示。
半径 (Radius)
圆形的半径 radius
使用 GeoJSON Feature
的属性表示。 半径值以米为单位,并且其类型必须为 double
。
子类型 (subType)
圆形几何图形还必须包含 subType
属性。 此属性必须是的属性的一部分 GeoJSON Feature
,并且其值应为 Circle
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-122.126986, 47.639754]
},
"properties": {
"subType": "Circle",
"radius": 500
}
}
Rectangle
GeoJSON 规范不支持该几何图形。我们使用 GeoJSON Polygon Feature
对象来表示矩形。 矩形扩展主要由 Web SDK 的 “绘图工具” 模块使用。
Rectangle
使用对象表示的几何图形 GeoJSON Polygon Feature
必须 包含以下坐标和属性:
内角
使用对象的坐标表示矩形的角 GeoJSON Polygon
。 应该有五个坐标,每个角一个。 与第五个坐标相同,用于关闭多边形环。 假定这些坐标对齐,开发人员可以根据需要对其进行旋转。
子类型
矩形几何图形还必须包含 subType
属性。 此属性必须是的属性的一部分 GeoJSON Feature
,并且其值应为 Rectangle
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [[[5,25],[14,25],[14,29],[5,29],[5,25]]]
},
"properties": {
"subType": "Rectangle"
}
}
高德地图提供了以下几组API可用于地理围栏:
AMap.GeoJSON
AMap.PolyEditor
AMap.PolygonEditor
AMap.CircleEditor
AMap.RectangleEditor
AMap.EllipseEditor
AMap.BezierCurveEditor
AMap.MouseTool
它可以用来解析标准的GeoJSON,但是需要注意的是:它只支持FeatureCollection
形式的数据.
const geoJson = new AMap.GeoJSON({
geoJSON: geoJsonObject,
getMarker: function (geoJson, lngLats) {
console.log('点', lngLats);
},
getPolyline: function (geoJson, lngLats) {
console.log('线', lngLats);
},
getPolygon: function (geoJson, lngLats) {
console.log('面', lngLats);
},
});
function createPolygon(path: any, addToMap: boolean, fitView: boolean) {
const polygon = new AMap.Polygon({
path: path,
strokeColor: '#FF33FF',
strokeWeight: 6,
strokeOpacity: 0.2,
fillOpacity: 0.4,
fillColor: '#1791fc',
zIndex: 50,
});
polygon.on('mouseover', () => {
polygon.setOptions({
fillOpacity: 0.7,
fillColor: '#7bccc4',
});
});
polygon.on('mouseout', () => {
polygon.setOptions({
fillOpacity: 0.5,
fillColor: '#ccebc5',
});
});
if (addToMap) {
map.add(polygon);
}
if (fitView) {
setFitView();
}
currentGeofence = polygon;
return polygon;
}
它支持:圆形,折线,多边形,贝瑟尔曲线,椭圆,矩形.
虽然说,圆形,矩形绘制简单.但是,真正实用的只有:多边形.
// 编辑多边形
function editPolygon(path: any, open: boolean) {
closePolygonEditor();
// 创建编辑器
polygonEditor = new AMap.PolyEditor(map);
if (path.length > 0) {
const polygon = createPolygon(path, true, false);
// 吸附功能
polygonEditor.addAdsorbPolygons(polygon);
// 设置编辑目标
polygonEditor.setTarget(polygon);
polygon.on('dblclick', () => {
polygonEditor.setTarget(polygon);
polygonEditor.open();
});
} else {
polygonEditor.setTarget();
}
polygonEditor.on('add', function (event) {
console.log(event);
const polygon = event.target;
polygonEditor.addAdsorbPolygons(polygon);
polygon.on('dblclick', () => {
polygonEditor.setTarget(polygon);
polygonEditor.open();
});
});
polygonEditor.on('end', function (event) {
const paths = event.target.getPath();
console.log('结束多边形编辑', event.target, paths);
});
// 打开编辑
if (open) polygonEditor.open();
}
需要注意的是:
AMap.GeoJSON
所解析,GeoJson的数据必须封装成FeatureCollection
.并不实用,弃用.