PHP环境下如何生成大小相近的GPS坐标地理聚类
解答
现有PHP工具说明
目前PHP生态中没有成熟的、可直接指定聚类大小范围的约束类k-means工具包,你可以选择自己实现轻量算法,或者用跨语言调用的方案解决需求。
可行解决思路
方案1:轻量改造标准k-means算法(聚类精度更高)
- 先确定聚类数量k:总点位数量除以单成员期望走访数量,向上取整即可,最终每组点位数量差最大为1,完全满足均等要求。
- 执行第一轮标准k-means聚类,得到初始的k个聚类中心,将所有点位分配到距离最近的中心对应的聚类中。
- 执行大小均衡调整:统计每个聚类的点位数量,对超出目标大小的聚类,将距离聚类中心最远的点位,迁移到当前仍有空位、且距离该点位最近的聚类中,循环调整直到所有聚类的大小差不超过1即可。
方案2:格网划分法(实现最简单,性能最优)
因为你的点位都在同一城镇区域,该方案完全满足需求:
- 先计算所有点位的经纬度边界:得到最大/最小经度、最大/最小纬度,确定整个区域的范围。
- 根据聚类数量k,将区域划分为对应数量的均匀矩形格网,比如k=6就划分为2行3列的格网。
- 先将每个点位按经纬度归属到对应格网的分组中,再对点位数量超出目标值的格网,将超出的点位就近分配到有空位的相邻格网分组,直到所有分组大小均等。
方案3:跨语言调用Python实现
如果不想自己开发算法逻辑,可直接在PHP中调用本地Python脚本:将点位数据导出为临时CSV文件,用Python的约束k-means工具计算得到聚类结果后,PHP再读取结果文件即可,开发成本极低。
常用工具函数
你可以直接使用以下经纬度距离计算函数,适配上述所有方案:
/** * 计算两个GPS坐标点的球面距离 * @param float $lat1 点1纬度 * @param float $lon1 点1经度 * @param float $lat2 点2纬度 * @param float $lon2 点2经度 * @return float 距离(单位:公里) */ function haversine(float $lat1, float $lon1, float $lat2, float $lon2): float { $earthRadius = 6371; $dLat = deg2rad($lat2 - $lat1); $dLon = deg2rad($lon2 - $lon1); $a = sin($dLat / 2) * sin($dLat / 2) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * sin($dLon / 2) * sin($dLon / 2); $c = 2 * atan2(sqrt($a), sqrt(1 - $a)); return $earthRadius * $c; }
内容的提问来源于stack exchange,提问作者Stacky Mark
相关产品推荐
相关产品推荐

