Answers:
如果“最快”包括您所花费的时间,则解决方案将取决于您是否熟悉并可以快速使用什么软件。因此,以下备注集中于实现最快的计算时间的构想。
如果您使用固定程序,几乎可以肯定的是,您可以做的最好的事情是对多边形进行预处理,以建立点对点数据结构,例如KD树或四叉树,其性能通常为O(log(V )*(N + V)),其中V是多边形中顶点的总数,N是点数,因为创建数据结构至少需要O(log(V)* V)的努力,然后必须以每点成本O(log(V))为每个点进行探测。
您可以通过首先对多边形进行网格化(利用没有重叠的假设)来做得更好。每个网格单元要么完全位于多边形内部(包括“通用多边形”的内部),在这种情况下,应使用多边形的ID标记该单元,或者它包含一个或多个多边形边。栅格化的成本等于栅格化所有边缘时参考的栅格像元数,其成本为O(V / c),其中c是像元的大小,但是big-O表示法中的隐式常数很小。
(这种方法的一个优点是您可以利用标准的图形例程。例如,如果您有一个系统,该系统(a)使用(b)每个多边形的不同颜色在虚拟屏幕上绘制多边形,并且(c)允许您可以读取要处理的任何像素的颜色,就可以了。)
使用此网格后,通过计算包含每个点的单元格来预筛选点(O(1)操作仅需要几个时钟)。除非这些点聚集在多边形边界周围,否则通常只留下大约O(c)个点,结果不明确。因此,构建网格和进行预筛选的总成本为O(V / c + 1 / c ^ 2)+ O(N)。您必须使用其他方法(例如到目前为止推荐的任何一种方法)来处理其余点(即接近多边形边界的点),而代价为O(log(V)* N * c) 。
随着c变小,具有边缘的同一网格中的点将越来越少,因此需要后续O(log(V))处理的点越来越少。为此,需要存储O(1 / c ^ 2)网格单元并花费O(V / c + 1 / c ^ 2)的时间来对多边形进行栅格化。因此,将有一个最佳的网格大小c。使用它,总的计算成本是O(LOG(V)* N),但隐含常数通常方式比使用罐装程序,由于预筛分的O(N)的速度小。
20年前,我测试了这种方法(在整个英格兰和近海使用均匀间隔的点,并利用当时视频缓冲区提供的大约40万个单元的相对粗略的网格),并且与我可以发表的最佳算法相比,获得了两个数量级的加速找。即使多边形既小又简单(例如三角形),您实际上也可以保证数量级的加速。
以我的经验,计算是如此之快,以至于整个操作都受到数据I / O速度的限制,而不是CPU的限制。预期I / O可能会成为瓶颈,因此,通过将点以尽可能压缩的格式存储以最大程度地减少数据读取时间,可以达到最快的结果。还应考虑如何存储结果,以便可以限制磁盘写入。
就我而言,我可能会将CSV数据加载到shp文件中,然后使用shapefile和shapely编写python脚本,以获取包含的多边形ID并更新字段值。
我不知道geotools和JTS是否比shapefile / shapely更快...没有时间对其进行测试!
编辑:顺便说一句,可能不需要将csv转换为shapefile格式,因为可以很容易地将值格式化为使用多边形shapefile中的空间对象进行测试的值。
下载GUI。您可以同时打开Shapefile和CSV作为虚拟表。这意味着您实际上并没有将它们导入数据库,而是将它们显示为表,并且您可以按照自己喜欢的任何方式快速加入并查询它们。
您可以在C / C ++ / Python中使用OGR相当快地完成此操作(Python应该是3种中最慢的)。遍历所有多边形并在点上设置过滤器,遍历过滤后的点,您将知道遍历的每个点都属于当前多边形。这是使用OGR的python示例代码,它将遍历多边形并相应地过滤点。C / C ++代码看起来与此非常相似,并且我想您会比python显着提高速度。您必须添加几行代码来更新CSV:
from osgeo import ogr
from osgeo.gdalconst import *
inPolyDS = ogr.Open("winnipeg.shp", GA_ReadOnly)
inPolyLayer = inPolyDS.GetLayer(0)
inPointDS = ogr.Open("busstops.vrt", GA_ReadOnly)
inPointLayer = inPointDS.GetLayerByName("busstops")
inPolyFeat = inPolyLayer.GetNextFeature()
while inPolyFeat is not None:
inPtFeat = inPointLayer.GetNextFeature()
while inPtFeat is not None:
ptGeom = inPtFeat.GetGeometryRef()
# Do work here...
inPtFeat = inPointLayer.GetNextFeature()
inPolyFeat = inPolyLayer.GetNextFeature()
VRT文件(busstops.vrt):
<OGRVRTDataSource>
<OGRVRTLayer name="busstops">
<SrcDataSource>busstops.csv</SrcDataSource>
<GeometryType>wkbPoint</GeometryType>
<LayerSRS>WGS84</LayerSRS>
<GeometryField encoding="PointFromColumns" x="X" y="Y" reportSrcColumn="FALSE" />
</OGRVRTLayer>
</OGRVRTDataSource>
CSV档案(busstops.csv):
FID,X,Y,stop_name
1,-97.1394781371062,49.8712241633646,Southbound Osborne at Mulvey
CSVT文件(busstops.csvt,OGR需要它来标识列类型,否则将不执行空间过滤):
Integer,Real,Real,String
可以尝试csv2shp csv2shp
想知道十亿位CSV属于哪个行业?