Gis分析 POI空间聚合研究Demo实现

本文介绍了一种GIS中POI的空间聚合算法实现,通过改进拖动地图时的聚合运算方式,采用相对比例尺原点坐标及二次聚合等手段,提高了聚合效果的稳定性和效率。
Gis分析 POI空间聚合研究Demo实现
2010年06月09日
  前些时候领导让我们提前预言商业智能gis分析以及物流交通相关的业务。其中有个重要的技术就是 POI空间聚合。从网上找了些资料,大多是E文的,而且说的都巨复杂,不是特别容易理解。
  多亏了google,哥们后来无意中发现了一个esri做的一个聚合示例。 http://www.esrichina-bj.cn/market/H1N1/H1N1.swf ,哈哈如获至宝,通过httpwatch找到数据来源,发现他是通过客户端做聚合运算的。flex的引擎下几百个点的运算速度相当不错。而且聚合的效果也相当的明显。唯一不足的是,他是相对的屏幕坐标进行聚合运算的。也就是最大也就是1440*900(呵呵这是我的电脑分辨率)。所以每次移动屏幕,聚合的点都会因为吸收或者抛弃屏幕外新的POI而发生聚合变化,变来变去给人的感受不是很爽。而且从分析来看,这种运算是根据每次拖动地图的px来进行,也就是稍稍的拖动一次地图就会有大规模的聚合运算(代表大的for循环)。当然如果用js来实现的话可远远达不到这个效果。
  
  有了参考的样本和示例,呵呵,信心增强了不少。这世界上最难得就是创新,只要见别人实现过,研究研究就有门。
  注:gis圈小的很,正好有个特好的哥们在esir(哈,我们以前还一个宿舍住过呢) 趁机要了些算法看了看。
  决定用flex试试看以前没有用过flex,初次接触起来感觉也还凑活,有点像java和js的结合体,修改修改算法也没啥难的。导入eclips,算法还是基本都能看明白的。我梳理了一遍,也不是很复杂。
  我对算法做了一部分改进。目的是解决拖动时候,聚合不停变化,给人不舒服的感觉,其实也就做了3步:
  1、去掉了拖动地图聚合运算相应。改为了缩放比例尺时请求运算,这样能增加效率,甚至日后可以都放到服务端算提前聚合,这样速度就快多了。
  2、聚合时用到的相对屏幕坐标,改为相对比例尺的原点坐标。这样就不会变来变去了。
  3、更换了我们的flex 地图api 显示模式 ,增加了部分功能。
  呵呵,个人感觉比esir做的要好。改天要些大数据,搞个厕所分布图。
  先给大家来点直观的插图:
  
  点击可查看聚合得点。以及POI的位置,这点学spaclateKey的呵呵。
  
  聚合前 3个聚合圆
  
  聚合后。呵呵,增加了比例尺缩放效果后非常明显,能看到相邻的点快速进行了合并。
  
  
  其实,空间聚合所白了也就以下几步骤,有点基础的朋友相信看看就会明白的。 不清楚email给我哈。
  第一步、针对基础数据进行初步聚合。
  遍历POI数据转化为相对比例尺原点的屏幕坐标(要保证每个POI的屏幕数据都是唯一的),这里还不能用经纬度,因为经纬度相对比例尺来说都是固定的。但是的原点屏幕坐标相对原点是相同的。但不同比例尺下不同。循环过程中根据聚合的直径范围判断将POI放入不同的聚合数组对象中,并计算这些POI点的中心点(根据算法,他会像点多放偏移)。这样就初步得到多个聚合数组,并且记录的聚合中心点也是相对POI数量有侧重的。
  相对的Flex代码如下: private function assignMapPointsToClusters() : void { m_orig = new Dictionary(); //循环所有POI for each ( var tcar:TCar in sink ) { //经纬度转屏幕像素(固定屏幕像素) var sxy:SE_Point = getPixelCoord(tcar.lnglat); //根据直径的精度,进行聚合 Convert to cluster x/y values. var cx : int = sxy.x / m_diameter; var cy : int = sxy.y / m_diameter; //cx位移19位和cy组成Key cluster dictionary key. //var ci : int = (cx 地图上显示来说还是比较杂乱比较多。我们需要再次针对这些聚合圆进行聚合。根据四面八方的原则,再聚合圆的基础上在进行聚合直径的扩充。如果发现邻近的聚合圆存在就合并,并根据数量偏移聚合圆的位置(当然靠近数量多的一方哈)。这个循环直到发现每个聚合圆的直径都没有接触到附近的聚合圆为止。
  相对应的Flex如下: /** * 1.2判断相邻的两个聚合圆是否也需要聚合。 */ private function mergeOverlappingClusters() : void { m_overlapExists = false; // 建立一个新的dic存储圆圆聚合后的圆 Create a new set to hold non-overlapping clusters. const dest/**/ : Dictionary = new Dictionary(); // 循环所有聚合圆,进行再聚合 for each( var cluster : Cluster in m_orig ) { //忽略空的聚合数组 if( cluster.n === 0 ) { continue; } //8个方向寻找邻近可聚合的圆 Search all immediately adjacent clusters. searchAndMerge( cluster, 1, 0 ); searchAndMerge( cluster, -1, 0 ); searchAndMerge( cluster, 0, 1 ); searchAndMerge( cluster, 0, -1 ); searchAndMerge( cluster, 1, 1 ); searchAndMerge( cluster, 1, -1 ); searchAndMerge( cluster, -1, 1 ); searchAndMerge( cluster, -1, -1 ); //得到新的聚合圆 Find the new cluster centroid values. var cx : int = cluster.x / m_diameter; var cy : int = cluster.y / m_diameter; cluster.cx = cx; cluster.cy = cy; //var ci : int = (cx flex做主要是为了方便调试,因为一会还要用新的 flexapi做地图显示。
  第三步,范围判断显示聚合圆
  剩下的就最简单多了。你可以服务端来算、也可以客户端来算。就是根据屏幕经纬度区间去获取需要显示的聚合圆显示。因为我们对屏幕做了聚合,所以一般情况下,聚合圆的数量不会太多,当然如果18级别,你又是几十万的数据那您还是放到服务端好了。也不用oracle或者postSql的spatial。直接内存循环速度就没有问题。 /** * 2、根据屏幕范围显示绘制圆图 **/ public function showClustersOnMap():void { var bounds:SE_LngLatBounds = map.getLngLatBounds();//屏幕四角坐标 //循环聚合点,显示与地图上 for each ( var cluster : Cluster in m_orig ){ if (bounds.containsLngLat(new SE_LngLat(cluster.lng, cluster.lat))) { var cs:ClusterSymbol = new ClusterSymbol(cluster.tcars); cs.radius = cluster.n > 1 ? 20 : 8; //如果数量大于一则画大圆,否则小圆 cs.map = map; cs.draw(cluster); cs.lnglat.lng = cluster.lng; cs.lnglat.lat = cluster.lat; map.addOverLay(cs); source.addItem(cs); //图形增加到聚合数组中 cs.addEventListener(SE_OverlayMouseEvent.SE_OVERLA Y_MOUSE_CLICK, clusterClickedHandler); } } }
### 时空数据采集与预处理 分析兴趣点(POI)的时间-空间分布特征,首先需要获取包含时间戳和地理坐标的结构化数据。POI数据通常包含名称、类别、经纬度、营业时间、用户评分等属性,这些信息可以用于分类、检索和分析。通过爬虫技术,可以获取大量带有时间信息的POI数据,并将其转换为GIS可识别的格式,例如GeoJSON或Shapefile。在数据预处理阶段,需对坐标进行投影转换(如EPSG:3857),并清理异常值或重复点,以确保后续分析的准确性[^2]。 ### 空间分布分析方法 GIS平台支持多种空间分析方法,可用于评估POI空间分布模式。核密度估计(Kernel Density Estimation)是一种常用技术,能够识别POI的高密度区域和分布趋势。通过设置合适的带宽参数,可生成密度热力图,用于揭示商业中心、交通枢纽或人口密集区域的空间特征。此外,缓冲区分析可用于评估POI对周边区域的覆盖能力,例如创建1公里缓冲区以识别加油站、公交站点或零售网点的服务范围。空间聚类算法(如DBSCAN)可发现POI聚集区域,适用于城市功能区识别、商业选址和交通规划等场景[^5]。 ### 时间维度分析与动态建模 在时间维度上,可通过统计分析和可视化手段研究POI随时间的变化趋势。例如,将POI数据按年、月、日进行时间切片,分析其数量增长、类别变化或空间迁移规律。结合遥感数据或人口流动数据,可构建时态GIS模型,用于研究城市扩张、商圈演变或交通需求的动态特征。在商业智能分析中,时间维度可与空间分布结合,用于评估不同时间段(如工作日与节假日)的POI活跃度,从而指导资源配置和营销策略[^3]。 ### 时空可视化与决策支持 GIS平台支持多图层叠加和动态可视化,可将POI数据与人口密度、交通网络、土地利用等数据整合展示。通过交互式地图,可直观识别POI的时空分布模式,例如商业热点区域的形成过程、交通站点周边的POI密度变化等。使用Python的Geopandas和Matplotlib库,可实现POI数据的快速可视化,并结合时间戳进行动态图表展示。此外,结合WebGIS技术,可构建实时更新的时空分析平台,为城市规划、交通管理或商业运营提供决策支持[^4]。 ```python # 示例:使用Geopandas和Matplotlib进行POI数据可视化 import geopandas as gpd import matplotlib.pyplot as plt # 读取POI数据(假设为CSV格式,包含经纬度) poi_data = gpd.read_file("poi_data.csv") poi_data['geometry'] = gpd.points_from_xy(poi_data['longitude'], poi_data['latitude']) poi_gdf = gpd.GeoDataFrame(poi_data, geometry='geometry') # 设置投影 poi_gdf = poi_gdf.set_crs(epsg=4326).to_crs(epsg=3857) # 绘制地图 fig, ax = plt.subplots(figsize=(10, 8)) poi_gdf.plot(ax=ax, column='category', legend=True, markersize=5) plt.title("POI Spatial Distribution") plt.show() ``` ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值