OpenLayers中绘制指定米数正方形/矩形的方案验证
OpenLayers结合Turf.js绘制米制正方形/矩形的正确实现
需求
根据用户提供的起点经纬度(lng, lat)和米制宽高,在OpenLayers中生成对应几何要素,当宽高数值相同时,需生成面积等于width²的正方形。
初始实现的问题
直接将米制距离转换为经纬度度数后生成矩形,会出现横向距离不符合预期的问题:
const startingPoint = [-8, 37]; // lng, lat const width = 1000; // meters const height = 1000; // meters const widthDeg = turf.convertLength(width, "meters", "degrees"); // 0.00899320363724538 const heightDeg = turf.convertLength(height, "meters", "degrees"); // 0.00899320363724538 const lng = startingPoint[0]; const lat = startingPoint[1]; const coordinates = [ [lng, lat], // [-8, 37 ] [lng, lat + heightDeg], // [-8, 37.008993203637246 ] [lng + widthDeg, lat + heightDeg], // [-7.991006796362755, 37.008993203637246 ] [lng + widthDeg, lat], // [-7.991006796362755, 37 ] [lng, lat],// [-8, 37 ] ]; const poly = new Polygon([coordinates]); const feature = new Feature(poly); this._vectorSource?.addFeature(feature); console.log("distance1", turf.distance([lng, lat], [lng, lat + heightDeg], { units: "meters" })); // output: 1000 console.log("distance2", turf.distance([lng, lat + heightDeg], [lng + widthDeg, lat + heightDeg], { units: "meters" })); // output: 799 console.log("area", turf.area(turf.polygon([coordinates]))); // output: 798588.2760202035
问题核心:经度方向的度数对应的地面距离随纬度变化,纬度越高,相同经度差的实际距离越短,直接转换米到度数没有考虑这个因素,导致横向距离偏小。
改进后的实现
对经度方向的度数转换结果进行纬度校正,除以当前纬度的余弦值:
const startingPoint = [-8, 37]; // lng, lat const width = 1000; // meters const height = 1000; // meters const widthDeg = turf.convertLength(width, "meters", "degrees") / Math.cos((startingPoint[1] * Math.PI) / 180); // 0.011260710955255207 const heightDeg = turf.convertLength(height, "meters", "degrees"); // 0.00899320363724538 const lng = startingPoint[0]; const lat = startingPoint[1]; const coordinates = [ [lng, lat], // [-8, 37 ] [lng, lat + heightDeg], // [-8, 37.008993203637246 ] [lng + widthDeg, lat + heightDeg], // [-7.988739289044744, 37.008993203637246 ] [lng + widthDeg, lat], // [-7.988739289044744, 37 ] [lng, lat], // [-8, 37 ] ]; const poly = new Polygon([coordinates]); const feature = new Feature(poly); this._vectorSource?.addFeature(feature); console.log("distance1", turf.distance([lng, lat], [lng, lat + heightDeg], { units: "meters" })); // output: 1000 console.log( "distance2", turf.distance([lng, lat + heightDeg], [lng + widthDeg, lat + heightDeg], { units: "meters" }) ); // output: 999.85 console.log("area", turf.area(turf.polygon([coordinates]))); // output: 999941
结论
第二种解决方案是正确的。
- 纬度方向的度数距离在全球范围内相对统一(约111公里/度),无需额外校正;
- 经度方向的度数距离与纬度余弦值成正比,转换时必须除以当前纬度的余弦值,才能保证地面距离符合输入的米制数值;
- 改进后的代码生成的要素横向距离接近1000米,面积接近1000000平方米,完全符合正方形的需求。
内容的提问来源于stack exchange,提问作者tuga74
相关产品推荐
相关产品推荐

