GOOGLE S2算法简介

https://zsr.github.io/2016/10/17/Google-S2/ Google S2作用: 根据多边形的边界区域映射成由许多一维数值构成的集合,这样就可以由这个集合代替多边形区域,便于后续计算。典型的可以将不同国家(或者地区)的边界区域(经纬度)计算成一维数值的集合,可以用于判断该区域的任何一个坐标是否包涵在内,简单的说就是地理定位。 s2库提供了一个Cell的概念,每个Cell相当于一个单元格,在一个单元格内的所有Point,都可以算出同一个CellId。同时可以认为,一个Polygon可以用一个Cell的集合来表示。那么这时的步骤就是通过区域的坐标,来初始化其内包含的所有的CellId,将这些CellId的id放入redis中做key,对应的value是区域名称(譬如,上海浦东新区),构建完全国范围的CellId后,查询用户的区域就可以通过用户的坐标获得一个CellId,然后去redis中查询,在使用LocalCache后,基本就没有什么计算成本,完全可以满足性能需求。 操作步骤: 1)首先获取地域图形的坐标点集合,可以从Natural Earth网站获取全球的坐标元数据(.shp文件)。2)解析shp文件,生成区域坐标集合,这里选择pyshp(解析shp文件的python插件),这里需要注意:同一个国家可能包涵多个区域(muti Polygon),需要分开处理。下载地址:https://pypi.python.org/pypi/pyshp/3)使用Google S2将多边形的边界坐标集合转化为一维数值集合,代表这个多边形的覆盖区域。 S2原理: 1234567891011 S2RegionCoverer coverer = new S2RegionCoverer();ArrayList<S2CellId> covering = new ArrayList<S2CellId>();coverer.setMinLevel(minLevel);coverer.setMaxLevel(maxLevel);coverer.setMaxCells(1000000);S2Polygon s2Polygon = S2Polygon.makePolygon(polygonValue);//getCovering()表示可以最小程度覆盖整个区域,外接多边形coverer.getCovering(s2Polygon, covering);//getInteriorCovering()表示最大程度填充整个区域,内接多边形// coverer.getInteriorCovering(s2Polygon, covering);System.out.println(“covering of size:” + covering.size()); 这里采用getCovering()外接多边形模式,避免多边形区域有盲点。MinLevel=9,MaxLevel=14 说明:MaxLevel最多可以设置30级,每升一级精度提升接近4倍,14级单个Cell可以表示范围:200平米~400平米,层级越高,构建越慢。 S2需要将地理位置表示为计算机可以理解的方式,即二进制码的表示,所以我们的目标就是用二进制码来表示三维空间。如何来做呢?需要进行降维。 1) 首先从三维降到二维,我们将地球放在一个正方体中,假设地球中心发光,光线穿过球体表面到达正方体平面的点就是球体表面的点的投影。于是我们就可以将地球投影到正方体的六个正方形表面。 通过投影我们可以将三维球体映射到二维平面,但是这个方法有一个问题,就是投影长度的比例不同。水平方向上的投影长度比上下两端的投影长度小,这就造成了投射面积不均匀,会影响以后对地图的切分。解决方法就是再进行一次区间转换,对长度进行微挑,将长的拉短,短的拉长,尽量使投影面积分布均匀。 2) 将二维变成一维。我们有很多点组成的正方形平面,如何对这个平面进行一维表示呢?方法就是遍历,比如我们就可以用00 01 10 11来表示下面四个点组成的平面。将这种方法不断扩展到极限,我们可以得到填充整个二维平面的一条曲线,这就是著名的希尔伯特曲线(Hilbert Curve)。希尔伯特曲线可以把二维平面映射到一条线段上,它还有一个优势就是可以保存局部性,即空间位置相近的点在希尔伯特曲线上的位置也是相近的。 可以发现位置相近的二维坐标在一维线段上面也是邻近的。 3) 创建cell集合: 简单来说,就是将一个能完整覆盖多边形面积的cell,不断的划分(4块cell),如果4快仍然全部与多边形相交则继续划分,否则有一个或多个cell不与多边形相交则抛弃,直至最大划分到maxLevel。可以发现如果maxLevel设置的越大,则精度越高(测试效率来看,maxLevel设置为14,15级已经比较精确,层级大于15级非常影响生成cell的效率)。 这里假设多边形区域为二维图形,如果需要对该图形进行覆盖,可能有以下可能: cell被包含在多边形内部 cell与多边形相交(有一部分在外面)图中大的cell和多边形相交,如果该cell的level已经达到maxLevel则停止划分,并将这个cell加入最后集合;如果这时候该cell的level小于maxLevel,则继续划分为4小块(不一定等分),可以发现有2个小的cell仍然与多边形相交,如果这2个cell层级已经达到MaxLevel则将这2个加入最终集合,否则继续划分,另外2个cell已经在多边形的外面则抛弃, 如果多边形内部可以完整填充一个cell(注意限制:minLevel,maxLevel; 级别越小,cell越大),则将该cell直接添加到集合中。比如这里设置的minLevel=9(一般只有面积非常大的国家才会有level=9),所以多边形区域所能生成的最大面积cell只有可能是level=9. 根据实际测试来看,像美国,俄罗斯相对面积比较大的国家,最小的level可以达到7(目测地球所有国家中最小的level就是7),也就是说这些国家的面积可以内涵完整的level=7的cell,这么做可以将许多高层次的cell由一个低层次的cell替代,减少了生成的cell数量同时表示的范围没有变化。 之所以这里选择minLevel=9,是为了以后定位方便,目前的定位是通过经纬度由Google S2生成CellId,再由这个CellId查询所有的CellId集合,如果有匹配的则命中。匹配的代码 …

Generating a model from an existing database

https://www.learnentityframeworkcore.com/walkthroughs/existing-database In previous versions of Entity Framework, you had the option to take a Database-First approach to modelling from an existing database, resulting in the generation of an EDMX file. Support for the EDMX file was dropped in Entity Framework Core in favour of using commands to reverse-engineering files for the model from an existing …

ubuntu下安装程序的三种方法

https://www.cnblogs.com/xwdreamer/p/3623454.html 在ubuntu当中,安装应用程序我所知道的有三种方法,分别是apt-get,dpkg安装deb和make install安装源码包三种。下面针对每一种方法各举例来说明。 apt-get方法 使用apt-get install来安装应用程序算是最常见的一种安装方法了,比如我要安装build-essential这个软件,使用以下,他会帮我把所有的依赖包都一起安装了。 sudo apt-get install build-essential 执行上述命令以后,我们可以看到一下信息,The following extra packages will be installed:表示所有需要再安装的依赖包。 sudo apt-get install build-essential password for enadmin: Reading package lists… Done Building dependency tree Reading state information… Done The following extra packages will be installed: binutils cpp cpp-4.6 dpkg-dev fakeroot g++ g++-4.6 gcc gcc-4.6 libalgorithm-diff-perl libalgorithm-diff-xs-perl libalgorithm-merge-perl libc-bin …

Google S2 library的使用(C++)

https://smithnote.com/programing/google_s2/ 关于google s2算法的详细的介绍有一篇很好的中文博客,可以浏览《高效的多维空间点索引算法》。这里就只介绍google s2库的具体使用 安装 直接源码编译安装,步骤如下 预先了解的概念 地球(S2Earth): 地球的表示类,它提供了一系列对于S2Point, S2Latlng等相关的操作,例如两个坐标点之间的 距离,将距离装换为S2ChorAngle,方便其他接口调用 点(S2Point): 三维空间中的某个点的表示class, 由地球上的经纬度转换成实际的三维坐标而来 角度(S1Angle): 表示一维角度,具体的理解就如同经纬度中的其中一个维度,如经度或纬度 弦角(S1ChordAngle): 相较于一维角度,弦角是球体上两个点分别与球心连线的夹角,取值范围[0, 180] 坐标(S2LatLng): 地球经纬度坐标的表示class, 其内部由两个S1Angle表示 区域(S2Region): 地球上的某个区域的base class表示, 实际的区域都继承于它 矩形区域(S2LatLngRect):由两个坐标或者两个点初始化。具体就是由一个最小经纬度p1(矩形左下角的坐标) 和最大经纬度坐标p2(矩形右上角的坐标)初始化,所以要保证-90 <=p1.lat <= p2.lat <= 90,而经度则无要求 圆形区域(S2Cap):由一个圆心坐标和一段半径距离初始化(也可以是一个角度), 在球体上就是一个帽盖形状 闭环多边形(S2Loop): 闭环多边形, 由给定一系列坐标点的列表的顺序形成一个闭环,也就是说最后的连线的终点就是起点, 这个要注意的是多边形内部是定义在连线方向的左边 线形区域(S2Polyline):由给定的点连成的直线组成 多个闭环区域(S2Polygon): 由多个S2Loop组成 点索引(S2PointIndex): 点的索引实现类,是个模板类,是为了方便的添加每个point的额外信息。 它主要跟他相关的查询接口类来配合实现对索引的操作。 形状(S2Shape): 并不是具体指额某个形状,它表示同一维度的几何形集合,例如point的集合,闭环多边形的集合, 线形区域等, 那些几何形都实现了S2Shape的接口, 例如S2Loop::Shape, S2Polygon::Shape, S2Polyline::Shape等 形状索引(S2ShapeIndex): shape索引抽象class, 它跟一系列其他相关的类配合来实现对索引的操作 …

高效的多维空间点索引算法 — Geohash 和 Google S2

https://halfrost.com/go_spatial_search/ 引 每天我们晚上加班回家,可能都会用到滴滴或者共享单车。打开 app 会看到如下的界面: app 界面上会显示出自己附近一个范围内可用的出租车或者共享单车。假设地图上会显示以自己为圆心,5公里为半径,这个范围内的车。如何实现呢?最直观的想法就是去数据库里面查表,计算并查询车距离用户小于等于5公里的,筛选出来,把数据返回给客户端。 这种做法比较笨,一般也不会这么做。为什么呢?因为这种做法需要对整个表里面的每一项都计算一次相对距离。太耗时了。既然数据量太大,我们就需要分而治之。那么就会想到把地图分块。这样即使每一块里面的每条数据都计算一次相对距离,也比之前全表都计算一次要快很多。 我们也都知道,现在用的比较多的数据库 MySQL、PostgreSQL 都原生支持 B+ 树。这种数据结构能高效的查询。地图分块的过程其实就是一种添加索引的过程,如果能想到一个办法,把地图上的点添加一个合适的索引,并且能够排序,那么就可以利用类似二分查找的方法进行快速查询。 问题就来了,地图上的点是二维的,有经度和纬度,这如何索引呢?如果只针对其中的一个维度,经度或者纬度进行搜索,那搜出来一遍以后还要进行二次搜索。那要是更高维度呢?三维。可能有人会说可以设置维度的优先级,比如拼接一个联合键,那在三维空间中,x,y,z 谁的优先级高呢?设置优先级好像并不是很合理。 本篇文章就来介绍2种比较通用的空间点索引算法。 一. GeoHash 算法 1. Geohash 算法简介 Geohash 是一种地理编码,由 Gustavo Niemeyer 发明的。它是一种分级的数据结构,把空间划分为网格。Geohash 属于空间填充曲线中的 Z 阶曲线(Z-order curve)的实际应用。 何为 Z 阶曲线? 上图就是 Z 阶曲线。这个曲线比较简单,生成它也比较容易,只需要把每个 Z 首尾相连即可。 Z 阶曲线同样可以扩展到三维空间。只要 Z 形状足够小并且足够密,也能填满整个三维空间。 说到这里可能读者依旧一头雾水,不知道 Geohash 和 Z 曲线究竟有啥关系?其实 Geohash算法 的理论基础就是基于 Z 曲线的生成原理。继续说回 Geohash。 Geohash 能够提供任意精度的分段级别。一般分级从 1-12 级。 …

Error cs0012 the type ‘object’ is defined in an assembly that is not referenced. you must add a reference to assembly ‘netstandard, version=2.0.0.0, culture=neutral, publickeytoken=cc7b13ffcd2ddd51’.

Error cs0012 the type ‘object’ is defined in an assembly that is not referenced. you must add a reference to assembly ‘netstandard, version=2.0.0.0, culture=neutral, publickeytoken=cc7b13ffcd2ddd51’. Solve: Add <Reference Include=”netstandard” /> into .csproj file.