JavaScript中给定坐标列表如何实现多边形无平移缩放
Canvas多边形等距外扩坐标获取方案
现有方案问题排查
- JSTS方案报错由代码逻辑错误导致,核心问题有三个:
BufferOp初始化时传入了原始点数组,而非JSTS构造完成的Polygon几何对象- 未传入外扩间距参数,缓冲操作缺少必要入参
- 结果取值路径错误,缓冲后的坐标需要从执行结果对象中读取,而非直接访问BufferOp实例属性
另外测试时传入仅2个点的数组本身不构成合法多边形,也会触发几何计算报错。
- TurfJS的
transformScale接口是基于多边形几何中心做等比例缩放,生成的新多边形各边到原多边形的距离不相等,不符合碰撞检测需要的等距缓冲垫需求。
可用实现方案
方案1:修正后的JSTS实现
修正入参、执行逻辑和取值路径后,可直接输出要求的一维坐标数组,TypeScript实现代码如下:
// 注意根据你的JSTS版本调整导入路径,不同版本包路径有差异 import Coordinate from 'jsts/org/locationtech/jts/geom/Coordinate'; import GeometryFactory from 'jsts/org/locationtech/jts/geom/GeometryFactory'; import BufferOp from 'jsts/org/locationtech/jts/operation/buffer/BufferOp'; function vectorCoordinates2JTS (polygon: Array<{x:number, y:number}>) { const coordinates: Coordinate[] = []; for (let i = 0; i < polygon.length; i++) { coordinates.push(new Coordinate(polygon[i].x, polygon[i].y)); } // 闭合多边形 coordinates.push(coordinates[0]); return coordinates; } function inflatePolygon(poly: Array<{x:number, y:number}>, spacing: number): number[] { const geoInput = vectorCoordinates2JTS(poly); const geometryFactory = new GeometryFactory(); // 构造合法JSTS多边形对象 const shell = geometryFactory.createPolygon(geoInput); // 传入几何对象初始化缓冲算子 const bufferOp = new BufferOp(shell); // 可根据需求选择端点样式:圆角/方角/平角 bufferOp.setEndCapStyle(BufferOp.CAP_ROUND); // 传入外扩距离执行计算 const bufferedGeom = bufferOp.getResultGeometry(spacing); // 提取外轮廓坐标 const oCoordinates = bufferedGeom.getExteriorRing().getCoordinates(); const inflatedCoordinates: number[] = []; // 去掉最后一个和起点重复的闭合点 for (let i = 0; i < oCoordinates.length - 1; i++) { const item = oCoordinates[i]; inflatedCoordinates.push(Math.round(item.x), Math.round(item.y)); } return inflatedCoordinates; }
方案2:轻量库实现(无重型几何库依赖)
如果觉得JSTS打包体积过大,可以用专门做多边形偏移的轻量库实现,代码更简洁:
import Offset from 'polygon-offset'; function inflatePolygonLight(poly: Array<{x:number, y:number}>, spacing: number): number[] { const offset = new Offset(); // 转换为库需要的二维点格式 const points = poly.map(p => [p.x, p.y]); // 执行外扩计算 const inflatedResult = offset.data(points).margin(spacing); // 拍平为要求的一维坐标数组 return inflatedResult[0].flat(); }
补充说明
Konva本身的缩放API是基于形状锚点做中心等比例缩放,和Turf的缩放逻辑一致,无法生成等距缓冲区域,不适合碰撞检测场景使用。
内容的提问来源于stack exchange,提问作者zoop
相关产品推荐
相关产品推荐

