简体   繁体   中英

calculate an area based on x and y coordinates and width and height values in javascript

I have this problem I've been trying to solve by myself without any success.

I have an object to represent a rectangle, with it's position (x,y) and its size (width and height).

I have 2 lists, both contains the object mentioned before, one list represents the positive areas and the other represents the negative areas.

Based in this information, I need to get the total area that results if we add up all the elements in both positive and negative lists. I'm only interested in the result if the total area is a rectangle, otherwise it's irrelevant for me.

For example: If the positive list contains these 2 objects

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

and the negative list contains this object

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

The result of adding these 3 objects would be:

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

This image shows the graphical representation of the 3 objects in those 2 lists and the result.

例

I appreciate any help you could bring.

edit: I made a small correction in one of the 3 objects, and the coordinate system I'm using is cartesian system with reversed y-axis (as you can see in the next figure) 反向轴

This is not a simple question, and is more an algorithmic problem than a JavaScript problem.

This works with your example.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM