我有这个问题,我一直试图自己解决,没有任何成功。
我有一个对象来表示一个矩形,它的位置(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轴的笛卡尔系统(如下图所示)
答案 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;