我有一个坐标列表
const coords = [{x:10, y:20}, {x:5, y:6}, {x:1, y:25}, {x:11, y:2}];
我想知道是否有一种方法可以计算仅具有这些坐标的边界框宽度和高度?
使用
map()
函数将输入数组转换为 x
或 y
值数组。然后,您可以将这些转换后的数组输入 Math.min()
和 Math.max()
以获得 left
、right
、bottom
和 top
来计算 bounding box
。当您有 bounding box
时,宽度和高度的计算就很简单(从最大值中减去最小值)。请参阅下面的代码片段。
const coords = [{x:10, y:20}, {x:5, y:6}, {x:1, y:25}, {x:11, y:2}];
const xArr = coords.map(c => c.x);
const yArr = coords.map(c => c.y);
const l = Math.min(...xArr);
const r = Math.max(...xArr);
const b = Math.min(...yArr);
const t = Math.max(...yArr);
const width = r - l;
const height = t - b;
console.log(width, height);
我猜,这就是
x
(宽度)和 y
(高度)的最小值和最大值之间的差异。
虽然计算这些的显而易见的方法似乎是在提取的坐标数组上使用
Math.max()
/Math.min()
,但它需要不必要地多次循环源数组,而单遍(例如使用Array.prototype.reduce()
)是相当的当输入数组相对较大时,足够并且可能执行明显更快:
const points = [{x:10, y:20}, {x:5, y:6}, {x:1, y:25}, {x:11, y:2}],
{width, height} = points.reduce((acc, {x,y}) => {
if(!acc.mX || x < acc.mX){
acc.mX = x
} else if (!acc.MX || x > acc.MX){
acc.MX = x
}
if(!acc.mY || y < acc.mY){
acc.mY = y
} else if (!acc.MY || y > acc.MY){
acc.MY = y
}
acc.width = acc.MX - acc.mX
acc.height = acc.MY - acc.mY
return acc
}, {width: 0, height: 0})
console.log(`width: ${width}; height: ${height}`)
看看这个片段。我猜这是一种开始的方法。
一些解释:
我们使用
Math.operationMinOrMax(...coords.map(c => c.propertyXorY))
计算坐标集中的 minX、maxX、minY 和 maxY 值。
尺寸(属性 w 和 h)可以通过减去
maxX - minX
和 maxY - minY
来计算。
const boundingBox = (coords) => {
const minX = Math.min(...coords.map(c => c.x)), maxX = Math.max(...coords.map(c => c.x));
const minY = Math.min(...coords.map(c => c.y)), maxY = Math.max(...coords.map(c => c.y));
return {
x: minX,
y: minY,
w: maxX - minX,
h: maxY - minY
}
}
console.log(
boundingBox( [ {x:10,y:5}, {x:100,y:0}, {x:100,y:100}, {x:12,y:50}, {x:0,y:100}, {x:27,y:22} ])
);