Skip to content

多边形操作

本页面介绍 Turf.js 中的多边形操作,包括布尔集合操作(union、intersect、difference)、凸包计算(convex、concave)、缓冲区创建、简化和工具操作。这些操作基于几何算法修改或创建多边形,通常利用专门的外部计算几何库。

对于多边形之间的空间关系测试(如 containswithinintersects),请参见 布尔谓词。对于线操作,请参见 线处理

概述

Turf.js 中的多边形操作可以分为五大类:

CategoryOperationsPrimary Use Cases
Boolean Set Operationsunion, intersect, differenceCombining or subtracting polygon areas
Hull Calculationsconvex, concaveFinding boundary shapes around point sets
Buffer OperationsbufferCreating offset zones around features
Simplificationsimplify, clean-coordsReducing geometric complexity
Utility Operationsenvelope, centroid, center-of-massBounding boxes and center calculations

所有多边形操作都依赖于基础模块 @turf/helpers 用于 GeoJSON 创建和 @turf/meta 用于 feature 迭代。

布尔集合操作

Union、Intersect 和 Difference

三个核心布尔操作通过 polyclip-ts 库使用 Martinez-Rueda 多边形裁剪算法。这些操作在多边形上实现集合论:

SVG
100%

Union 操作 - @turf/union 将两个或多个多边形合并为表示其组合面积的单个多边形。它接受多个 polygon features 并返回单个 Feature<Polygon|MultiPolygon>。

Intersect 操作 - @turf/intersect 查找两个多边形之间的共享区域。如果多边形不重叠则返回 undefined,否则返回重叠区域的 Feature<Polygon|MultiPolygon>。

Difference 操作 - @turf/difference 从第一个多边形中裁剪后续多边形。接受可变参数并按顺序处理,从累积结果中减去每个多边形。

这三个操作都使用 polyclip-ts 0.16.8 版本,该版本实现了 Martinez-Rueda 多边形裁剪算法。该算法高效处理具有孔洞和自相交的复杂多边形,并提供稳健的数值稳定性。

外部库:polyclip-ts

polyclip-ts 中实现的 Martinez-Rueda 算法在布尔操作中优于 JSTS,因为:

  • 更可靠地处理自相交多边形的边界情况
  • 复杂多多边形操作的性能更好
  • 原生 TypeScript 实现,具有正确的类型定义
  • 与完整 JSTS 库相比更小的包大小

该算法通过使用扫描线方法计算重叠多边形的平面细分,然后根据布尔操作类型提取适当的区域来工作。

凸包操作

Convex Hull

SVG
100%

@turf/convex 模块在点集周围创建凸包 - 包含所有输入点的最小凸多边形。尽管其名称如此,它使用 concaveman 库并将凹度设置为无穷大,从而产生凸包。

实现packages/turf-convex/package.json69 列出 concaveman v1.2.1 作为核心依赖。该模块使用 @turf/meta 实用程序迭代所有输入坐标并将它们传递给 concaveman 算法。

Concave Hull

SVG
100%

@turf/concave 模块创建凹包 - 一个比凸包更紧密地围绕点的多边形。它使用涉及 Delaunay 三角剖分和拓扑合并的复杂算法。

Algorithm Steps:

  1. Triangulation: Uses @turf/tin to create a Triangulated Irregular Network (TIN) from input points via Delaunay triangulation
  2. Topology Creation: Converts the TIN to TopoJSON format using topojson-server v3.x
  3. Edge Filtering: Filters triangulation edges that exceed maxEdge length using @turf/distance
  4. Boundary Merging: Uses topojson-client v3.x to merge triangle boundaries into a single polygon, excluding filtered edges

maxEdge 参数控制凹度 - 较小的值创建更紧密的包,更紧密地跟随点分布,而较大的值接近凸包行为。

Dependencies: packages/turf-concave/package.json86-87 shows the module depends on both topojson-client and topojson-server version 3.x for topology operations, plus @turf/tin @turf/distance @turf/clone and @turf/invariant for supporting operations.

缓冲区操作

@turf/buffer 模块在输入 features 周围以指定半径创建缓冲区。它支持正缓冲区(扩展)和负缓冲区(侵蚀/内缩)。

缓冲区实现架构

SVG
100%

投影策略

在地理坐标中创建缓冲区需要特殊处理,因为距离随纬度变化。该实现使用两步投影方法:

  1. Project to Azimuthal Equidistant: packages/turf-buffer/index.js177-181 - Creates a projection centered on the feature using d3-geo's geoAzimuthalEquidistant(). This projection preserves distances from the center point.

  2. Convert to Meters: packages/turf-buffer/index.js111 - Converts the radius from the specified units to meters using radiansToLength(lengthToRadians(radius, units), "meters")

  3. Apply Buffer in Projected Space: packages/turf-buffer/index.js112 - Uses JSTS BufferOp.bufferOp() to perform the actual buffer operation in Cartesian coordinates

  4. Unproject to Geographic: packages/turf-buffer/index.js120-123 - Transforms results back to WGS84 geographic coordinates

这种方法确保了准确的缓冲区距离,而不管纬度如何,尽管对于远离投影中心的非常大的缓冲区可能会出现一些失真。

JSTS 集成

缓冲区操作使用 Java Topology Suite (JSTS) 进行核心几何计算:

JSTS Components: packages/turf-buffer/index.js13 imports BufferOp, GeoJSONReader, and GeoJSONWriter from @turf/jsts

Buffer Parameters:

  • Radius: Distance in meters after unit conversion
  • Steps: packages/turf-buffer/index.js44 - Number of segments per quadrant (default 8). Higher values create smoother curves but increase computation time and vertex count

负缓冲区packages/turf-buffer/index.js51-52 明确允许负半径值用于侵蚀。但是,packages/turf-buffer/index.js117 过滤掉 coordsIsNaN() 返回 true 的结果,当负缓冲区将多边形减少到可行大小以下时可能会发生这种情况。

空几何体处理packages/turf-buffer/index.js117 为产生无效几何体的单个 features 返回 undefined。对于 FeatureCollections,packages/turf-buffer/index.js56-72 过滤掉无效结果,可能返回空的 FeatureCollection。

缓冲区类型定义

// From packages/turf-buffer/index.d.ts
interface Options {
  units?: Units;      // kilometers, miles, meters, etc.
  steps?: number;     // 每象限的段数(默认 8)
}

function buffer(
  feature: Feature<GeometryObject> | Geometry,
  radius?: number,
  options?: Options
): Feature<Polygon | MultiPolygon> | undefined;

function buffer(
  feature: FeatureCollection<GeometryObject> | GeometryCollection,
  radius?: number,
  options?: Options
): FeatureCollection<Polygon | MultiPolygon> | undefined;

该模块为单个 features 与集合提供重载签名。如果缓冲失败,单个 features 返回 undefined,而集合始终返回 FeatureCollection(可能为空)。

简化操作

Douglas-Peucker 简化

@turf/simplify 模块使用 Ramer-Douglas-Peucker 算法在保留多边形或线的一般形状的同时减少顶点数量。

算法:Douglas-Peucker 算法递归地删除对形状整体外观的贡献小于容差阈值的顶点。它的工作原理是:

  1. 找到距离连接起点和终点的线最远的顶点
  2. 如果距离超过容差,保留该顶点并在两个段上递归
  3. 如果低于容差,丢弃所有中间顶点

Dependencies: packages/turf-simplify/package.json74-75 shows the module depends on @turf/clean-coords and @turf/clone in addition to the standard @turf/helpers and @turf/meta utilities.

坐标清理:简化过程包括调用 @turf/clean-coords 删除重复的连续坐标,这可能在简化过程中发生,否则会创建无效几何体。

变异预防packages/turf-simplify/package.json75 包括 @turf/clone 作为依赖项,表明该模块在修改之前创建输入几何体的副本以防止意外的副作用。

工具操作

Envelope

@turf/envelope 模块在输入 features 周围创建矩形边界框多边形。

实现packages/turf-envelope/package.json66-67 显示它使用 @turf/bbox 计算边界框坐标,然后使用 @turf/bbox-polygon 将这些坐标转换为 Polygon feature。

这是一个简单的两步操作:计算范围 [minX, minY, maxX, maxY],然后从这些角创建矩形多边形。

Centroid 和 Center

三个模块提供不同的方法来查找多边形的"中心":

ModuleMethodDescription
@turf/centroidGeometric centroidAverage of all vertices
@turf/centerBounding box centerMidpoint of extent
@turf/center-of-massCenter of mass"Balance point" weighted by area

Centroid: packages/turf-centroid/package.json68-69 uses @turf/helpers and @turf/meta to iterate coordinates and calculate their mean position.

Center: packages/turf-center/package.json72 uses @turf/bbox to find the extent, then returns the midpoint of that bounding box.

Center of Masspackages/turf-center-of-mass/package.json66-70 依赖于 @turf/centroid@turf/convex 计算不规则形状的质心。它计算"平衡点",即如果多边形是均匀密度的物理物体,它会平衡的点。

外部库依赖摘要

SVG
100%

库选择理由

LibraryVersionUsed ByPurpose
polyclip-ts0.16.8union, intersect, differenceMartinez-Rueda boolean operations
@turf/jsts2.7.1bufferGeometric buffering algorithms
d3-geo1.7.1bufferGeographic projections
concaveman1.2.1convex, concaveHull generation algorithms
topojson-server3.xconcaveTopology construction
topojson-client3.xconcaveTopology merging

polyclip-ts 在布尔操作中优于 JSTS,因为它提供了专注的多边形裁剪实现,具有更好的性能和更小的包大小。它实现的 Martinez-Rueda 算法专门设计用于稳健的布尔操作。

JSTS 用于缓冲区操作,因为它提供了复杂的 BufferOp 算法,可以正确处理端帽、连接样式和负缓冲区。这是一个复杂的操作,受益于 JSTS 的全面实现。

d3-geo 提供了经过实战考验的地理投影实现。方位等距投影对于在不同纬度的缓冲区操作中准确保持距离至关重要。

topojson 库通过提供高效合并三角形边界的拓扑操作(同时根据 maxEdge 参数过滤边)来启用凹包算法。

网格生成集成

几个网格生成模块依赖于多边形操作:

Hex Grid: packages/turf-hex-grid/package.json81 uses @turf/intersect to clip hexagon cells to the input bounding box, ensuring only complete or partial hexagons within the area are returned.

Triangle Grid: packages/turf-triangle-grid/package.json73 similarly uses @turf/intersect to clip triangular cells to the bounding area.

这些集成展示了多边形布尔操作如何作为更复杂空间分析功能的构建块。

空间数据收集

@turf/collect 模块在点和多边形之间执行空间连接,聚合每个多边形内的点属性:

Spatial Indexing: packages/turf-collect/package.json74 uses rbush v3.0.1 for efficient spatial queries. The module builds an R-tree index of polygon bounding boxes to quickly identify candidate polygons for each point.

Point-in-Polygon Tests: packages/turf-collect/package.json71 uses @turf/boolean-point-in-polygon to test whether each point falls within a candidate polygon after the R-tree narrows the search space.

Process Flow:

  1. Calculate bounding boxes for all polygons using @turf/bbox
  2. Build R-tree spatial index with polygon bounding boxes
  3. For each point, query R-tree to find overlapping polygons
  4. Test point against candidate polygons using point-in-polygon algorithm
  5. Aggregate matching point properties into polygon's output property array

这展示了多边形操作如何与空间索引集成以进行高效的大规模数据处理。

测试和验证

大多数多边形操作模块都包含全面的测试套件:

变异预防packages/turf-buffer/test.ts102-129 包括验证输入 features 在缓冲区操作期间未被修改的测试,使用操作前后的深度相等性检查。

边界情况packages/turf-buffer/test.ts64-79 测试负缓冲区支持,packages/turf-buffer/test.ts133-157 测试过度负缓冲区返回空几何体的形态学闭合行为。

几何支持packages/turf-buffer/test.ts81-100 验证对原始 Geometry 对象的支持(除了 Features),并测试 GeometryCollection 处理。

这些测试模式在多边形操作模块中很常见,确保对边界情况的稳健处理并防止回归。