Turf.js如何计算考虑多边形旋转的最小外接矩形bbox
Turf.js 实现旋转贴合的最小矩形边界方案
你之前使用的turf.bboxPolygon、turf.envelope接口生成的都是轴对齐包围盒(AABB),矩形边强制与经纬度坐标轴平行,遇到整体存在旋转角度的多边形组时,必然会在两侧产生冗余空白,无法满足贴合最外侧点位的需求。你需要的是可随要素旋转的最小有向包围盒(OBB,所有内角为90度、包裹所有要素的面积最小矩形),Turf.js没有提供直接生成该结果的单API,但可以通过现有接口组合实现,计算逻辑如下:
- 第一步:将所有输入多边形合并为要素集,调用
turf.convex()计算所有要素的整体凸包。最小外接矩形必然与凸包的某条边共边,先算凸包可以大幅减少后续遍历的计算量。 - 第二步:遍历凸包的每一条边,计算边对应的方向角,也就是将该边旋转至与X轴平行需要的角度。
- 第三步:对每个遍历到的角度,将凸包反向旋转使当前边与X轴对齐,调用
turf.bbox()计算旋转后凸包的轴对齐包围盒,记录该包围盒的面积、对应旋转角度、包围盒坐标参数。 - 第四步:所有边遍历完成后,筛选出面积最小的一组包围盒参数,将对应的轴对齐矩形按记录的角度正向旋转回原坐标系,得到的就是完全贴合所有要素最外侧点位的最小矩形。
核心实现代码
import * as turf from '@turf/turf' /** * 计算要素集的最小旋转外接矩形(内角均为90度) * @param {GeoJSON.Feature[]} features 输入多边形要素数组 * @returns {GeoJSON.Feature<Polygon>} 最小外接矩形要素 */ function getMinRotatedBoundingRect(features) { const featureCollection = turf.featureCollection(features) const convexHull = turf.convex(featureCollection) if (!convexHull) throw new Error('无法为输入要素生成凸包,请检查要素有效性') const hullCoordinates = convexHull.geometry.coordinates[0] let minArea = Number.POSITIVE_INFINITY let optimalBbox = null let optimalRotateAngle = 0 // 遍历凸包所有边找最小面积对应的旋转角 for (let i = 0; i < hullCoordinates.length - 1; i++) { const startPoint = hullCoordinates[i] const endPoint = hullCoordinates[i + 1] // 计算当前边的方向角 const angle = Math.atan2( endPoint[1] - startPoint[1], endPoint[0] - startPoint[0] ) * 180 / Math.PI // 旋转凸包使当前边与X轴平行 const rotatedHull = turf.transformRotate(convexHull, -angle, { pivot: startPoint }) // 计算旋转后的轴对齐包围盒与面积 const currentBbox = turf.bbox(rotatedHull) const currentArea = (currentBbox[2] - currentBbox[0]) * (currentBbox[3] - currentBbox[1]) // 更新最小面积记录 if (currentArea < minArea) { minArea = currentArea optimalBbox = currentBbox optimalRotateAngle = angle } } // 将最优轴对齐包围盒旋转回原角度 const axisAlignedRect = turf.bboxPolygon(optimalBbox) return turf.transformRotate(axisAlignedRect, optimalRotateAngle) }
注意事项
- 上述代码要求输入坐标为平面投影坐标(如UTM投影、高斯克吕格投影,单位为米),如果直接传入WGS84经纬度坐标,由于经纬度单位“度”在不同纬度对应的实际距离不一致,计算出的角度、面积会存在偏差,仅适合小范围、中低纬度场景近似使用,大范围或高纬度场景需要先完成坐标投影转换再计算。
- 该算法计算出的矩形会自动贴合要素最外侧的凸顶点,刚好满足你提到的贴住多边形
101最顶部点位、多边形202最底部点位的需求,不会产生多余空白。
效果参考

内容的提问来源于stack exchange,提问作者myoda999
相关产品推荐
相关产品推荐

