从给定的坐标(x,y)计算边界框的宽度和高度

Calculate bounding box width and height from given coordinates(x,y)

我有一个坐标列表

const coords = [{x:10, y:20}, {x:5, y:6}, {x:1, y:25}, {x:11, y:2}];

我想知道是否有一种方法可以仅使用这些坐标来计算边界框的宽度和高度?

使用 map() 函数将输入数组转换为 xy 值的数组。然后,您可以将这些转换后的数组提供给 Math.min()Math.max() 以获得 leftrightbottomtop 来计算 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(高度)的最小值和最大值之间的差异。

to calculate those may seem to be using of Math.max()/Math.min() over extracted arrays of coordinates, it requires looping source array several times unnecessarily, whereas single pass (e.g. with Array.prototype.reduce()) is quite enough and may perform noticeably faster,当输入数组比较大时:

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}) => {
            const {min, max} = Math
            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 值。

  • 边界框(=>左角)的min-x坐标是minX值。
  • 边界框(=> top)的min-y坐标为minY值

  • 边界框(=>右角)的max-x坐标是maxX值。
  • 边界框(=>底部)的max-y坐标是maxY值。

大小(属性wh)可以通过减去maxX - minX和[=13来计算=].

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} ])
);