ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

@turf/collect 详解:使用 Turf 将点要素属性按多边形空间聚合

@turf/collect 详解:使用 Turf 将点要素属性按多边形空间聚合 数据分析【免费下载链接】turfA modular geospatial engine written in JavaScript and TypeScript项目地址https://gitcode.com/gh_mirrors/tu/turf点击查看免费下载导读turf/collect是 Turf 地理引擎中的一个空间聚合模块它解决的是一个非常典型且高频的地理数据分析问题统计落在每个多边形区域内的点并把点的某个属性值批量收集到该多边形的属性中。例如把每个小区多边形内所有居民点点的population人口属性收集成一个数组挂到小区的values属性上。阅读本文后你将掌握collect的完整参数用法、可运行的示例代码、R-tree 空间索引加粗筛 精确判定两阶段过滤的底层实现原理以及它的边界行为与测试验证方式。一、模块定位点 → 多边形的属性归并collect属于 Turf 的空间统计/聚合类工具其核心职责可以用一句话概括读取一张点要素集合FeatureCollection of Point的指定属性将其按空间归属关系汇总到一张多边形要素集合FeatureCollection of Polygon上。它的工作流程是给定点上的一个输入属性inProperty例如人口population对每个多边形找出落在它内部的全部点把这些点的inProperty取值收集成一个数组将该数组写入多边形的outProperty属性例如values。其官方描述为Merges a specified property from a FeatureCollection of points into a FeatureCollection of polygons见 packages/turf-collect/README.md。从仓库结构看该模块在聚合类模块turf-collect中自成一体并通过 packages/turf/index.ts 的export { collect } from turf/collect;统一导出到turf/turf全家桶中。二、安装方式turf/collect既可以作为独立模块安装也可以通过turf/turf全家桶统一引入# 单独安装该模块 $ npm install turf/collect# 安装包含全部模块的 turf/turf $ npm install turf/turf安装后独立模块以命名导出collect的方式使用ESM 风格type: module见 packages/turf-collect/package.jsonimport { collect } from turf/collect;若安装了turf/turf则通过turf.collect(...)调用。三、API 参数说明collect的函数签名为collect( polygons: FeatureCollectionPolygon, points: FeatureCollectionPoint, inProperty: string, outProperty: string ): FeatureCollectionPolygon参数类型说明polygonsFeatureCollectionPolygon承载聚合结果的多边形要素集合是聚合的目标与返回载体pointsFeatureCollectionPoint被聚合的点要素集合属性值来源inPropertystring从点上读取的嵌套来源属性名fromoutPropertystring写入多边形上的目标属性名into值为数组返回值FeatureCollectionPolygon——即带有outProperty数组属性的多边形集合。需要注意的是从源码实现看见下文原理分析该函数会原地修改传入的polygons对象并直接返回它而不是深拷贝后返回新对象。四、官方示例与运行结果README 中给出了一个非常直观的示例构造两个相邻多边形与 5 个带population属性的点然后执行聚合var poly1 turf.polygon([[[0,0],[10,0],[10,10],[0,10],[0,0]]]); var poly2 turf.polygon([[[10,0],[20,10],[20,20],[20,0],[10,0]]]); var polyFC turf.featureCollection([poly1, poly2]); var pt1 turf.point([5,5], {population: 200}); var pt2 turf.point([1,3], {population: 600}); var pt3 turf.point([14,2], {population: 100}); var pt4 turf.point([13,1], {population: 200}); var pt5 turf.point([19,7], {population: 300}); var pointFC turf.featureCollection([pt1, pt2, pt3, pt4, pt5]); var collected turf.collect(polyFC, pointFC, population, values); var values collected.features[0].properties.values //values [200, 600]结果解析poly1左下角多边形内部包含pt1(5,5)与pt2(1,3)因此collected.features[0].properties.values [200, 600]poly2右侧多边形内部包含pt3(14,2)、pt4(13,1)、pt5(19,7)对应值为[100, 200, 300]示例末尾的var addToMap [pointFC, collected]表示可将原始点与聚合结果一起放入地图可视化如 Leaflet / Mapbox 的 addToMap 习惯用法。使用 ESM TypeScript 的等价写法在仓库中同一数据场景以现代 ESM/TypeScript 风格运行的效果完全一致示例可对照 packages/turf-collect/test.tsimport { featureCollection, point, polygon } from turf/helpers; import { collect } from turf/collect; const poly1 polygon([[[0,0],[10,0],[10,10],[0,10],[0,0]]]); const poly2 polygon([[[10,0],[20,10],[20,20],[20,0],[10,0]]]); const polyFC featureCollection([poly1, poly2]); const ptFC featureCollection([ point([5,5], { population: 200 }), point([1,3], { population: 600 }), point([14,2], { population: 100 }), point([13,1], { population: 200 }), point([19,7], { population: 300 }), ]); const aggregated collect(polyFC, ptFC, population, values); console.log(aggregated.features[0].properties.values); // [200, 600] console.log(aggregated.features[1].properties.values); // [100, 200, 300]五、源码级实现原理R-tree 空间索引 两阶段过滤collect之所以能高效处理大量点 × 大量多边形的聚合任务是因为它在 packages/turf-collect/index.ts 中实现了一套经典的空间查询优化流程1. 构建点集 R-tree 空间索引var rtree new rbushEntry(6); var treeItems points.features.map(function (item) { return { minX: item.geometry.coordinates[0], minY: item.geometry.coordinates[1], maxX: item.geometry.coordinates[0], maxY: item.geometry.coordinates[1], property: item.properties?.[inProperty], }; }); rtree.load(treeItems);每个点被包装为一个minX/minY/maxX/maxY重合的退化包围盒点的包围盒就是它本身并携带从item.properties中读取的inProperty取值rtree.load()一次性批量构建索引而非逐条插入性能更优构造参数6是 rbush 的maxEntries每个节点最大条目数这是为减少树的深度/宽度而选择的常见平衡值使用item.properties?.[inProperty]可选链若某个点没有inProperty属性其取值为undefined该undefined仍会被写入结果数组见第六节的边界行为。2. 多边形 bbox 粗筛polygons.features.forEach(function (poly) { if (!poly.properties) { poly.properties {}; } var bbox turfbbox(poly); var potentialPoints rtree.search({ minX: bbox[0], minY: bbox[1], maxX: bbox[2], maxY: bbox[3], }); ... });若多边形原本没有properties先补一个空对象{}保证后续写入不出错借助turf/bbox依赖声明见 packages/turf-collect/package.json计算每个多边形的外接包围盒用该 bbox 在 R-tree 上执行search一次性拿到所有可能落在多边形内的候选点——这一阶段把全量遍历降级为只扫包围盒内的点是性能的关键。3. 精确点包含判定与属性收集var values: any[] []; potentialPoints.forEach(function (pt) { if (booleanPointInPolygon([pt.minX, pt.minY], poly)) { values.push(pt.property); } }); poly.properties[outProperty] values;包围盒粗筛的结果必然包含部分 bbox 相交但实际在多边形外的点例如凹多边形、斜边边界的情况因此必须用turf/boolean-point-in-polygon做精确的点在多边形内判定该判定模块的完整实现见 packages/turf-boolean-point-in-polygon/index.ts只有判定为true的点其property值才会被push进values最后poly.properties[outProperty] values完成属性写入。从源码结构可以推断该算法的时间复杂度大致为O(点数)建索引 O(多边形数 × bbox 内候选点数)查询与判定。相比朴素的两重循环多边形数 × 点数在点多、多边形也多的场景下收益显著。模块依赖的三个核心库turf/bbox、turf/boolean-point-in-polygon、turf/helpers以及空间索引库rbush都在 packages/turf-collect/package.json 的dependencies中明确声明构建引用关系也体现在 packages/turf-collect/tsconfig.json 的references中。六、边界行为与注意事项结合 packages/turf-collect/test.ts 的断言可以确认以下行为细节输入输出多边形数量保持一致t.equal(polyFC.features.length, aggregated.features.length)——聚合不会增删多边形要素仅修改属性每个多边形都会被写入outProperty数组即使某个多边形内部没有任何点其outProperty也不会缺失而是被赋值为空数组[]测试中poly3位于[100,0]附近、不包含任何点最终properties.values []。这在后续渲染、统计时非常友好无需再判空缺少属性的点会得到undefined值由于源码使用item.properties?.[inProperty]若点的inProperty不存在undefined会被推入结果数组。需要保证数据整洁时应先清洗点数据原地修改函数直接操作传入的polygons对象并返回它return polygons没有做深拷贝。如果调用方需要保留原始多边形属性不变应自行提前克隆如使用turf/clone再传入属性写入语义是收集成数组而非求和collect只负责归并原始值。若要进一步得到sum、avg、max/min等统计量需要在拿到values数组后自行聚合计算。七、测试与基准验证测试用例tests 使用tape编写覆盖了上述全部关键断言import { featureCollection, point, polygon } from turf/helpers; import { collect } from ./index.js; test(turf collect module, (t) { // ...构造 3 个多边形与 5 个点 const aggregated collect(polyFC, ptFC, population, values); t.equal(polyFC.features.length, aggregated.features.length); // 数量不变 t.deepEqual(aggregated.features[0].properties.values, [200, 600]); // poly1 两个点 t.deepEqual(aggregated.features[1].properties.values, [100, 200, 300]); // poly2 三个点 t.deepEqual(aggregated.features[2].properties.values, []); // 空多边形得到 [] t.end(); });运行测试pnpm test对应tsx test.ts基准脚本运行pnpm bench。基准脚本packages/turf-collect/bench.ts 使用benchmark构建了turf-collect的基准套件对同样的两个多边形 5 个点数据反复执行collect(polyFC, ptFC, population, outPopulation)输出吞吐率ops/sec供性能回归比对。它验证了在中小规模数据上collect的调用开销处于稳定、可接受的水平。八、典型应用场景人口 / 统计数据分析把普查点数据聚合到行政区块多边形为每个区划生成人口数值数组POI 归类统计将商铺、医院、学校等点要素按商圈/网格多边形归并得到每个区域内的 POI 列表传感器数据汇总将监测点读数按覆盖区域多边形收集供后续求均值、极值或绘制热力统计空间 join 预处理作为点落区关系的批量求解器为下游的 buffer、dissolve、intersect 等复杂空间分析提供基础数据。九、继续深入函数实现与 R-tree 细节packages/turf-collect/index.ts完整测试断言packages/turf-collect/test.ts性能基准packages/turf-collect/bench.ts依赖与脚本声明packages/turf-collect/package.json全家桶导出入口packages/turf/index.ts精确点包含判定packages/turf-boolean-point-in-polygon/index.ts包围盒计算packages/turf-bbox/依赖turf/bbox如果你需要按多边形求和/平均而非收集原始数组建议在collect结果之上自行对values做归约计算如果你需要把结果用于地图渲染可直接沿用示例中的addToMap [pointFC, collected]约定将原始点与聚合多边形一并叠加展示。赞分享数据分析【免费下载链接】turfA modular geospatial engine written in JavaScript and TypeScript项目地址https://gitcode.com/gh_mirrors/tu/turf点击查看免费下载相关推荐OpenSEO v0.0.4 版本深度解析Lighthouse 迁移 DataForSEO、R2 缓存架构与托管版认证体系OpenSEO v0.0.4 版本深度解析Lighthouse 迁移 DataForSEO、R2 缓存架构与托管版认证体系 v0.0.4 是 OpenSEO数据分析arduino-esp32 OpenThread 实战CoAP SimpleGet 客户端——仅凭 Network Key 入网并向 Leader RLOC 发起确认式 GETarduino esp32 OpenThread 实战CoAP SimpleGet 客户端——仅凭 Network Key 入网并向 Leader RLOC数据分析PyArrow 读写 Parquet 文件时如何只读取部分列并控制写入选项PyArrow 读写 Parquet 文件时如何只读取部分列并控制写入选项 用 PyArrow 处理 Parquet 文件时一个常见需求是文件里有几十列但数据分析上一篇突破性能极限Gunyah超虚拟器打造极致安全的实时虚拟化平台下一篇Fooocus 离线文生图怎么用3 步启动4GB 显存就能跑创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表