在javascript

时间:2016-04-25 05:08:47

标签: javascript

我有这个问题,我一直试图自己解决,没有任何成功。

我有一个对象来表示一个矩形,它的位置(x,y)及其大小(宽度和高度)。

我有2个列表,两个列表都包含前面提到的对象,一个列表代表正面区域,另一个列表示负面区域。

根据这些信息,如果我们将正面和负面列表中的所有元素相加,我需要获得结果的总面积。如果总面积是一个矩形,我只对结果感兴趣,否则它对我来说无关紧要。

例如: 如果肯定列表包含这两个对象

  

{x:20,y:20,宽度:100,身高:20}   {x:20,y:40,宽度:80,身高:80}

,否定列表包含此对象

  

{x:100,y:20,width:20,height:20}

添加这3个对象的结果将是:

  

{x:20,y:20,宽度:80,身高:100}

此图像显示了这两个列表中3个对象的图形表示以及结果。

example http://oi64.tinypic.com/i1wkeo.jpg

感谢您提供的任何帮助。

编辑:我在3个对象中的一个中做了一个小的修正,我正在使用的坐标系是具有反转y轴的笛卡尔系统(如下图所示) reversedYaxis

1 个答案:

答案 0 :(得分:0)

这不是一个简单的问题,而是一个算法问题而不是JavaScript问题。

这适用于您的示例。



var pos = [{x:20, y:20, width:100, height:20}, {x:20, y:40, width:80, height:80}];
var neg = [{x:100, y:20, width:20, height:20}]; // Fixed it x: 80 -> x: 100

// Create one single array of rectangles and add an attribute indicating if
// a rectangle is neg or pos
var rects =  pos.map(function(o){
  return Object.assign({pos: true}, o);
}).concat(neg.map(function(o){
  return Object.assign({pos: false}, o);
}));



// Combine two rectangles.
function combine2Rects(r1, r2, maintainOrder){
  // width addition
  if(r1.pos && r2.pos && r1.x === r2.x && r1.width === r2.width && r2.y === r1.y + r1.height){
    return Object.assign({}, r1, { height: r1.height + r2.height });

  // Height addition
  } else if(r1.pos && r2.pos && r1.y === r2.y && r2.x === r1.x + r1.width && r1.height === r2.height) {
    return Object.assign({}, r1, { width: r1.width + r2.width });

  // Height bottom subtraction
  } else if(r1.pos && !r2.pos && r1.x === r2.x && r1.width === r2.width && r2.y === r1.y + r1.height - r2.height && r1.height - r2.height > 0){
    return Object.assign({}, r1, { height: r1.height - r2.height });
    
  // Height top subtraction
  } else if(r1.pos && !r2.pos && r1.x === r2.x && r1.width === r2.width && r2.y === r1.y  && r1.height > r2.height){
    return Object.assign({}, r1, { height: r1.height - r2.height, y: r1.y + r2.height });
    
  // Width right subtraction
  } else if(r1.pos && !r2.pos && r1.y === r2.y && r1.height === r2.height && r2.x === r1.x + r1.width - r2.width && r1.width - r2.width > 0){
    return Object.assign({}, r1, { width: r1.width - r2.width });
    
  // Width left subtraction
  } else if(r1.pos && !r2.pos && r1.y === r2.y && r1.height === r2.height && r2.x === r1.x && r2.width < r1.width){
    return Object.assign({}, r1, { x: r1.x + r2.width, width: r1.width - r2.width });
    

  // If two negative rectangle, treat them as pos then invert them again.
  } else if(!r1.pos && !r2.pos){
    var invertedResult = combine2Rects(
      Object.assign({}, r1, { pos: true }),
      Object.assign({}, r2, { pos: true }),
      maintainOrder
    );
    if(invertedResult){
      invertedResult.pos = false;
      return invertedResult;
    }
  
  // try with r2 at the place of r1 and vice-versa
  } else if(!maintainOrder){
    return combine2Rects(r2, r1, true);
  }
}

function combineRects(rects){
  var lastN = 0;
  var result = rects.slice();
  // While we still made at least one combination
  debugger
  while(result.length !== lastN){
    lastN = result.length;
    // For each rectangle in the list
    for(var i=0; i<result.length; i++){
      var r1 = result[i];
      // Try to combine it with one of the following rectangles in the list
      for(var j=i+1; j<result.length; j++){
        var r2 = result[j];
        var c = combine2Rects(r1, r2);
        if(c){
          // replace the combined rectangle by the combination
          result[i] = c;
          // and remove the rectangle it has been combined with
          result.splice(j, 1);
          break;
        }
      }
    }
  }
  return result;
}

document.write(JSON.stringify(combineRects(rects)));
&#13;
&#13;
&#13;