Find the intersect area of two overlapping rectangles
up vote
2
down vote
favorite
This is my solution to find the coordinates of 2 overlapped rectangles implemented in JavaScript. Each rectangle is represented by 2 points, each with 2 (x,y) coordinates.
Can this code be improved?
const maxOfX = (rec) => (Math.max(rec.x1, rec.x2));
const maxOfY = (rec) => (Math.max(rec.y1, rec.y2));
const minOfX = (rec) => (Math.min(rec.x1, rec.x2));
const minOfY = (rec) => (Math.min(rec.y1, rec.y2));
const comBinedRectangle = (rec1, rec2) => {
let overlappedRec = {};
const NolappingFromX = maxOfX(rec1) <= minOfX(rec2) || minOfX(rec1) >= maxOfX(rec2);
const NolappingFromY = maxOfY(rec1) <= minOfY(rec2) || minOfY(rec1) >= maxOfY(rec2);
if (!(NolappingFromX || NolappingFromY)) {
overlappedRec.x1 = Math.max(minOfX(rec1), minOfX(rec2));
overlappedRec.y1 = Math.max(minOfY(rec1), minOfY(rec2));
overlappedRec.x2 = Math.min(maxOfX(rec1), maxOfX(rec2));
overlappedRec.y2 = Math.min(maxOfY(rec1), maxOfY(rec2));
}
return overlappedRec;
}
const rectangle1 = { x1: 2, y1: 2, x2: 4, y2: 4 };
const rectangle2 = { x1: 3, y1: 3, x2: 6, y2: 2 };
console.log(comBinedRectangle(rectangle1, rectangle2));
// { x1: 3, y1: 2, x2: 4, y2: 3 }
javascript performance algorithm interview-questions collision
add a comment |
up vote
2
down vote
favorite
This is my solution to find the coordinates of 2 overlapped rectangles implemented in JavaScript. Each rectangle is represented by 2 points, each with 2 (x,y) coordinates.
Can this code be improved?
const maxOfX = (rec) => (Math.max(rec.x1, rec.x2));
const maxOfY = (rec) => (Math.max(rec.y1, rec.y2));
const minOfX = (rec) => (Math.min(rec.x1, rec.x2));
const minOfY = (rec) => (Math.min(rec.y1, rec.y2));
const comBinedRectangle = (rec1, rec2) => {
let overlappedRec = {};
const NolappingFromX = maxOfX(rec1) <= minOfX(rec2) || minOfX(rec1) >= maxOfX(rec2);
const NolappingFromY = maxOfY(rec1) <= minOfY(rec2) || minOfY(rec1) >= maxOfY(rec2);
if (!(NolappingFromX || NolappingFromY)) {
overlappedRec.x1 = Math.max(minOfX(rec1), minOfX(rec2));
overlappedRec.y1 = Math.max(minOfY(rec1), minOfY(rec2));
overlappedRec.x2 = Math.min(maxOfX(rec1), maxOfX(rec2));
overlappedRec.y2 = Math.min(maxOfY(rec1), maxOfY(rec2));
}
return overlappedRec;
}
const rectangle1 = { x1: 2, y1: 2, x2: 4, y2: 4 };
const rectangle2 = { x1: 3, y1: 3, x2: 6, y2: 2 };
console.log(comBinedRectangle(rectangle1, rectangle2));
// { x1: 3, y1: 2, x2: 4, y2: 3 }
javascript performance algorithm interview-questions collision
Don't write, never present undocumented/uncommented code. Don't do(boolean expression) ? true : false
. Try to limit line length.
– greybeard
Jan 17 at 15:44
Are you talking about combination, intersection or even bounding rectangles? Why put 'overlapping' in the name when non-intersecting rectangles are equally valid input?
– le_m
Jan 17 at 17:43
Why not create a Rectange class? I did something similar whilst working on a visualisation project and it helped make sense of the code e.g.rect1.intersects(rect2)
– James
Jan 20 at 0:19
add a comment |
up vote
2
down vote
favorite
up vote
2
down vote
favorite
This is my solution to find the coordinates of 2 overlapped rectangles implemented in JavaScript. Each rectangle is represented by 2 points, each with 2 (x,y) coordinates.
Can this code be improved?
const maxOfX = (rec) => (Math.max(rec.x1, rec.x2));
const maxOfY = (rec) => (Math.max(rec.y1, rec.y2));
const minOfX = (rec) => (Math.min(rec.x1, rec.x2));
const minOfY = (rec) => (Math.min(rec.y1, rec.y2));
const comBinedRectangle = (rec1, rec2) => {
let overlappedRec = {};
const NolappingFromX = maxOfX(rec1) <= minOfX(rec2) || minOfX(rec1) >= maxOfX(rec2);
const NolappingFromY = maxOfY(rec1) <= minOfY(rec2) || minOfY(rec1) >= maxOfY(rec2);
if (!(NolappingFromX || NolappingFromY)) {
overlappedRec.x1 = Math.max(minOfX(rec1), minOfX(rec2));
overlappedRec.y1 = Math.max(minOfY(rec1), minOfY(rec2));
overlappedRec.x2 = Math.min(maxOfX(rec1), maxOfX(rec2));
overlappedRec.y2 = Math.min(maxOfY(rec1), maxOfY(rec2));
}
return overlappedRec;
}
const rectangle1 = { x1: 2, y1: 2, x2: 4, y2: 4 };
const rectangle2 = { x1: 3, y1: 3, x2: 6, y2: 2 };
console.log(comBinedRectangle(rectangle1, rectangle2));
// { x1: 3, y1: 2, x2: 4, y2: 3 }
javascript performance algorithm interview-questions collision
This is my solution to find the coordinates of 2 overlapped rectangles implemented in JavaScript. Each rectangle is represented by 2 points, each with 2 (x,y) coordinates.
Can this code be improved?
const maxOfX = (rec) => (Math.max(rec.x1, rec.x2));
const maxOfY = (rec) => (Math.max(rec.y1, rec.y2));
const minOfX = (rec) => (Math.min(rec.x1, rec.x2));
const minOfY = (rec) => (Math.min(rec.y1, rec.y2));
const comBinedRectangle = (rec1, rec2) => {
let overlappedRec = {};
const NolappingFromX = maxOfX(rec1) <= minOfX(rec2) || minOfX(rec1) >= maxOfX(rec2);
const NolappingFromY = maxOfY(rec1) <= minOfY(rec2) || minOfY(rec1) >= maxOfY(rec2);
if (!(NolappingFromX || NolappingFromY)) {
overlappedRec.x1 = Math.max(minOfX(rec1), minOfX(rec2));
overlappedRec.y1 = Math.max(minOfY(rec1), minOfY(rec2));
overlappedRec.x2 = Math.min(maxOfX(rec1), maxOfX(rec2));
overlappedRec.y2 = Math.min(maxOfY(rec1), maxOfY(rec2));
}
return overlappedRec;
}
const rectangle1 = { x1: 2, y1: 2, x2: 4, y2: 4 };
const rectangle2 = { x1: 3, y1: 3, x2: 6, y2: 2 };
console.log(comBinedRectangle(rectangle1, rectangle2));
// { x1: 3, y1: 2, x2: 4, y2: 3 }
javascript performance algorithm interview-questions collision
javascript performance algorithm interview-questions collision
edited Jun 19 at 10:29
Przemek
1,032213
1,032213
asked Jan 17 at 15:33
Achref Boukihili
112
112
Don't write, never present undocumented/uncommented code. Don't do(boolean expression) ? true : false
. Try to limit line length.
– greybeard
Jan 17 at 15:44
Are you talking about combination, intersection or even bounding rectangles? Why put 'overlapping' in the name when non-intersecting rectangles are equally valid input?
– le_m
Jan 17 at 17:43
Why not create a Rectange class? I did something similar whilst working on a visualisation project and it helped make sense of the code e.g.rect1.intersects(rect2)
– James
Jan 20 at 0:19
add a comment |
Don't write, never present undocumented/uncommented code. Don't do(boolean expression) ? true : false
. Try to limit line length.
– greybeard
Jan 17 at 15:44
Are you talking about combination, intersection or even bounding rectangles? Why put 'overlapping' in the name when non-intersecting rectangles are equally valid input?
– le_m
Jan 17 at 17:43
Why not create a Rectange class? I did something similar whilst working on a visualisation project and it helped make sense of the code e.g.rect1.intersects(rect2)
– James
Jan 20 at 0:19
Don't write, never present undocumented/uncommented code. Don't do
(boolean expression) ? true : false
. Try to limit line length.– greybeard
Jan 17 at 15:44
Don't write, never present undocumented/uncommented code. Don't do
(boolean expression) ? true : false
. Try to limit line length.– greybeard
Jan 17 at 15:44
Are you talking about combination, intersection or even bounding rectangles? Why put 'overlapping' in the name when non-intersecting rectangles are equally valid input?
– le_m
Jan 17 at 17:43
Are you talking about combination, intersection or even bounding rectangles? Why put 'overlapping' in the name when non-intersecting rectangles are equally valid input?
– le_m
Jan 17 at 17:43
Why not create a Rectange class? I did something similar whilst working on a visualisation project and it helped make sense of the code e.g.
rect1.intersects(rect2)
– James
Jan 20 at 0:19
Why not create a Rectange class? I did something similar whilst working on a visualisation project and it helped make sense of the code e.g.
rect1.intersects(rect2)
– James
Jan 20 at 0:19
add a comment |
2 Answers
2
active
oldest
votes
up vote
0
down vote
- Document/comment
I have no idea whether there are agreed standards for ECMAScript, e.g. JSDoc.
If I used what you calledOverX
I'd call itOverlapX
and invert it.OverlapX = minOfX(rec1) <= maxOfX(rec2) && minOfX(rec2) <= maxOfX(rec1);
- precomputing booleans the way of
OverX
andOverY
precludes short-circuiting the evaluation of the combined no-overlap-condition. - One could use "nomalised" rects:
minx
/miny
/maxx
/maxy
. - (I'd prefer plain function definitions over arrow functions if they are going to get a name, anyway.)
- (There is bound to be a way to have, e.g.
Math.min(values)
operate on all x-coordinates of a shape, my ignorance thereof notwithstanding.)
add a comment |
up vote
0
down vote
/**
* Returns intersecting part of two rectangles
* @param {object} r1 4 coordinates in form of {x1, y1, x2, y2} object
* @param {object} r2 4 coordinates in form of {x1, y1, x2, y2} object
* @return {boolean} False if there's no intersecting part
* @return {object} 4 coordinates in form of {x1, y1, x2, y2} object
*/
const getIntersectingRectangle = (r1, r2) => {
[r1, r2] = [r1, r2].map(r => {
return {x: [r.x1, r.x2].sort(), y: [r.y1, r.y2].sort()};
});
const noIntersect = r2.x[0] > r1.x[1] || r2.x[1] < r1.x[0] ||
r2.y[0] > r1.y[1] || r2.y[1] < r1.y[0];
return noIntersect ? false : {
x1: Math.max(r1.x[0], r2.x[0]), // _[0] is the lesser,
y1: Math.max(r1.y[0], r2.y[0]), // _[1] is the greater
x2: Math.min(r1.x[1], r2.x[1]),
y2: Math.min(r1.y[1], r2.y[1])
};
};
/* ↓ DEMO ↓ */
const rectangle1 = { x1: 2, y1: 2, x2: 4, y2: 4 };
const rectangle2 = { x1: 3, y1: 3, x2: 6, y2: 2 };
console.log(getIntersectingRectangle(rectangle1, rectangle2));
// { x1: 3, y1: 2, x2: 4, y2: 3 }
First, both rectangles get transformed into object with keys x
and y
and sorted arrays of two of corresponding them coordinates as values.
r1 = {
x: [2, 4], // x1, x2
y: [2, 4] // y1, y2
}
r2 = {
x: [3, 6], // x1, x2
y: [2, 3] // Y2, Y1 !
}
That's because for this job it is important to know which of x
s and y
s is lesser and which is greater. Rather than Math.max()
and Math.min()
a single .sort()
can be used.
Alternative would be to declare that (x1, y1)
is assumed to always be top-left corner, but as I see in rectangle2
in your question, that is apparently not always the case.
Now, noIntersect
is negated
!(a.left > b.right || b.left > a.right || a.top > b.bottom || b.top > a.bottom);
which tests if in both axes sides from one end of one figure exceed opposite-direction end side of the other figure, e.g. if left side of figure a
is more to the right than the right side of figure b
.
At the end we return false if there is no intersection of our rectangles, or an object with coordinates if there is. Intersecting part will always span from:
the greater of the 2 lesser x
s of both rectangles
to
the lesser of the 2 greater x
s of both rectangles.
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
- Document/comment
I have no idea whether there are agreed standards for ECMAScript, e.g. JSDoc.
If I used what you calledOverX
I'd call itOverlapX
and invert it.OverlapX = minOfX(rec1) <= maxOfX(rec2) && minOfX(rec2) <= maxOfX(rec1);
- precomputing booleans the way of
OverX
andOverY
precludes short-circuiting the evaluation of the combined no-overlap-condition. - One could use "nomalised" rects:
minx
/miny
/maxx
/maxy
. - (I'd prefer plain function definitions over arrow functions if they are going to get a name, anyway.)
- (There is bound to be a way to have, e.g.
Math.min(values)
operate on all x-coordinates of a shape, my ignorance thereof notwithstanding.)
add a comment |
up vote
0
down vote
- Document/comment
I have no idea whether there are agreed standards for ECMAScript, e.g. JSDoc.
If I used what you calledOverX
I'd call itOverlapX
and invert it.OverlapX = minOfX(rec1) <= maxOfX(rec2) && minOfX(rec2) <= maxOfX(rec1);
- precomputing booleans the way of
OverX
andOverY
precludes short-circuiting the evaluation of the combined no-overlap-condition. - One could use "nomalised" rects:
minx
/miny
/maxx
/maxy
. - (I'd prefer plain function definitions over arrow functions if they are going to get a name, anyway.)
- (There is bound to be a way to have, e.g.
Math.min(values)
operate on all x-coordinates of a shape, my ignorance thereof notwithstanding.)
add a comment |
up vote
0
down vote
up vote
0
down vote
- Document/comment
I have no idea whether there are agreed standards for ECMAScript, e.g. JSDoc.
If I used what you calledOverX
I'd call itOverlapX
and invert it.OverlapX = minOfX(rec1) <= maxOfX(rec2) && minOfX(rec2) <= maxOfX(rec1);
- precomputing booleans the way of
OverX
andOverY
precludes short-circuiting the evaluation of the combined no-overlap-condition. - One could use "nomalised" rects:
minx
/miny
/maxx
/maxy
. - (I'd prefer plain function definitions over arrow functions if they are going to get a name, anyway.)
- (There is bound to be a way to have, e.g.
Math.min(values)
operate on all x-coordinates of a shape, my ignorance thereof notwithstanding.)
- Document/comment
I have no idea whether there are agreed standards for ECMAScript, e.g. JSDoc.
If I used what you calledOverX
I'd call itOverlapX
and invert it.OverlapX = minOfX(rec1) <= maxOfX(rec2) && minOfX(rec2) <= maxOfX(rec1);
- precomputing booleans the way of
OverX
andOverY
precludes short-circuiting the evaluation of the combined no-overlap-condition. - One could use "nomalised" rects:
minx
/miny
/maxx
/maxy
. - (I'd prefer plain function definitions over arrow functions if they are going to get a name, anyway.)
- (There is bound to be a way to have, e.g.
Math.min(values)
operate on all x-coordinates of a shape, my ignorance thereof notwithstanding.)
edited Jan 17 at 16:38
answered Jan 17 at 16:09
greybeard
1,3391521
1,3391521
add a comment |
add a comment |
up vote
0
down vote
/**
* Returns intersecting part of two rectangles
* @param {object} r1 4 coordinates in form of {x1, y1, x2, y2} object
* @param {object} r2 4 coordinates in form of {x1, y1, x2, y2} object
* @return {boolean} False if there's no intersecting part
* @return {object} 4 coordinates in form of {x1, y1, x2, y2} object
*/
const getIntersectingRectangle = (r1, r2) => {
[r1, r2] = [r1, r2].map(r => {
return {x: [r.x1, r.x2].sort(), y: [r.y1, r.y2].sort()};
});
const noIntersect = r2.x[0] > r1.x[1] || r2.x[1] < r1.x[0] ||
r2.y[0] > r1.y[1] || r2.y[1] < r1.y[0];
return noIntersect ? false : {
x1: Math.max(r1.x[0], r2.x[0]), // _[0] is the lesser,
y1: Math.max(r1.y[0], r2.y[0]), // _[1] is the greater
x2: Math.min(r1.x[1], r2.x[1]),
y2: Math.min(r1.y[1], r2.y[1])
};
};
/* ↓ DEMO ↓ */
const rectangle1 = { x1: 2, y1: 2, x2: 4, y2: 4 };
const rectangle2 = { x1: 3, y1: 3, x2: 6, y2: 2 };
console.log(getIntersectingRectangle(rectangle1, rectangle2));
// { x1: 3, y1: 2, x2: 4, y2: 3 }
First, both rectangles get transformed into object with keys x
and y
and sorted arrays of two of corresponding them coordinates as values.
r1 = {
x: [2, 4], // x1, x2
y: [2, 4] // y1, y2
}
r2 = {
x: [3, 6], // x1, x2
y: [2, 3] // Y2, Y1 !
}
That's because for this job it is important to know which of x
s and y
s is lesser and which is greater. Rather than Math.max()
and Math.min()
a single .sort()
can be used.
Alternative would be to declare that (x1, y1)
is assumed to always be top-left corner, but as I see in rectangle2
in your question, that is apparently not always the case.
Now, noIntersect
is negated
!(a.left > b.right || b.left > a.right || a.top > b.bottom || b.top > a.bottom);
which tests if in both axes sides from one end of one figure exceed opposite-direction end side of the other figure, e.g. if left side of figure a
is more to the right than the right side of figure b
.
At the end we return false if there is no intersection of our rectangles, or an object with coordinates if there is. Intersecting part will always span from:
the greater of the 2 lesser x
s of both rectangles
to
the lesser of the 2 greater x
s of both rectangles.
add a comment |
up vote
0
down vote
/**
* Returns intersecting part of two rectangles
* @param {object} r1 4 coordinates in form of {x1, y1, x2, y2} object
* @param {object} r2 4 coordinates in form of {x1, y1, x2, y2} object
* @return {boolean} False if there's no intersecting part
* @return {object} 4 coordinates in form of {x1, y1, x2, y2} object
*/
const getIntersectingRectangle = (r1, r2) => {
[r1, r2] = [r1, r2].map(r => {
return {x: [r.x1, r.x2].sort(), y: [r.y1, r.y2].sort()};
});
const noIntersect = r2.x[0] > r1.x[1] || r2.x[1] < r1.x[0] ||
r2.y[0] > r1.y[1] || r2.y[1] < r1.y[0];
return noIntersect ? false : {
x1: Math.max(r1.x[0], r2.x[0]), // _[0] is the lesser,
y1: Math.max(r1.y[0], r2.y[0]), // _[1] is the greater
x2: Math.min(r1.x[1], r2.x[1]),
y2: Math.min(r1.y[1], r2.y[1])
};
};
/* ↓ DEMO ↓ */
const rectangle1 = { x1: 2, y1: 2, x2: 4, y2: 4 };
const rectangle2 = { x1: 3, y1: 3, x2: 6, y2: 2 };
console.log(getIntersectingRectangle(rectangle1, rectangle2));
// { x1: 3, y1: 2, x2: 4, y2: 3 }
First, both rectangles get transformed into object with keys x
and y
and sorted arrays of two of corresponding them coordinates as values.
r1 = {
x: [2, 4], // x1, x2
y: [2, 4] // y1, y2
}
r2 = {
x: [3, 6], // x1, x2
y: [2, 3] // Y2, Y1 !
}
That's because for this job it is important to know which of x
s and y
s is lesser and which is greater. Rather than Math.max()
and Math.min()
a single .sort()
can be used.
Alternative would be to declare that (x1, y1)
is assumed to always be top-left corner, but as I see in rectangle2
in your question, that is apparently not always the case.
Now, noIntersect
is negated
!(a.left > b.right || b.left > a.right || a.top > b.bottom || b.top > a.bottom);
which tests if in both axes sides from one end of one figure exceed opposite-direction end side of the other figure, e.g. if left side of figure a
is more to the right than the right side of figure b
.
At the end we return false if there is no intersection of our rectangles, or an object with coordinates if there is. Intersecting part will always span from:
the greater of the 2 lesser x
s of both rectangles
to
the lesser of the 2 greater x
s of both rectangles.
add a comment |
up vote
0
down vote
up vote
0
down vote
/**
* Returns intersecting part of two rectangles
* @param {object} r1 4 coordinates in form of {x1, y1, x2, y2} object
* @param {object} r2 4 coordinates in form of {x1, y1, x2, y2} object
* @return {boolean} False if there's no intersecting part
* @return {object} 4 coordinates in form of {x1, y1, x2, y2} object
*/
const getIntersectingRectangle = (r1, r2) => {
[r1, r2] = [r1, r2].map(r => {
return {x: [r.x1, r.x2].sort(), y: [r.y1, r.y2].sort()};
});
const noIntersect = r2.x[0] > r1.x[1] || r2.x[1] < r1.x[0] ||
r2.y[0] > r1.y[1] || r2.y[1] < r1.y[0];
return noIntersect ? false : {
x1: Math.max(r1.x[0], r2.x[0]), // _[0] is the lesser,
y1: Math.max(r1.y[0], r2.y[0]), // _[1] is the greater
x2: Math.min(r1.x[1], r2.x[1]),
y2: Math.min(r1.y[1], r2.y[1])
};
};
/* ↓ DEMO ↓ */
const rectangle1 = { x1: 2, y1: 2, x2: 4, y2: 4 };
const rectangle2 = { x1: 3, y1: 3, x2: 6, y2: 2 };
console.log(getIntersectingRectangle(rectangle1, rectangle2));
// { x1: 3, y1: 2, x2: 4, y2: 3 }
First, both rectangles get transformed into object with keys x
and y
and sorted arrays of two of corresponding them coordinates as values.
r1 = {
x: [2, 4], // x1, x2
y: [2, 4] // y1, y2
}
r2 = {
x: [3, 6], // x1, x2
y: [2, 3] // Y2, Y1 !
}
That's because for this job it is important to know which of x
s and y
s is lesser and which is greater. Rather than Math.max()
and Math.min()
a single .sort()
can be used.
Alternative would be to declare that (x1, y1)
is assumed to always be top-left corner, but as I see in rectangle2
in your question, that is apparently not always the case.
Now, noIntersect
is negated
!(a.left > b.right || b.left > a.right || a.top > b.bottom || b.top > a.bottom);
which tests if in both axes sides from one end of one figure exceed opposite-direction end side of the other figure, e.g. if left side of figure a
is more to the right than the right side of figure b
.
At the end we return false if there is no intersection of our rectangles, or an object with coordinates if there is. Intersecting part will always span from:
the greater of the 2 lesser x
s of both rectangles
to
the lesser of the 2 greater x
s of both rectangles.
/**
* Returns intersecting part of two rectangles
* @param {object} r1 4 coordinates in form of {x1, y1, x2, y2} object
* @param {object} r2 4 coordinates in form of {x1, y1, x2, y2} object
* @return {boolean} False if there's no intersecting part
* @return {object} 4 coordinates in form of {x1, y1, x2, y2} object
*/
const getIntersectingRectangle = (r1, r2) => {
[r1, r2] = [r1, r2].map(r => {
return {x: [r.x1, r.x2].sort(), y: [r.y1, r.y2].sort()};
});
const noIntersect = r2.x[0] > r1.x[1] || r2.x[1] < r1.x[0] ||
r2.y[0] > r1.y[1] || r2.y[1] < r1.y[0];
return noIntersect ? false : {
x1: Math.max(r1.x[0], r2.x[0]), // _[0] is the lesser,
y1: Math.max(r1.y[0], r2.y[0]), // _[1] is the greater
x2: Math.min(r1.x[1], r2.x[1]),
y2: Math.min(r1.y[1], r2.y[1])
};
};
/* ↓ DEMO ↓ */
const rectangle1 = { x1: 2, y1: 2, x2: 4, y2: 4 };
const rectangle2 = { x1: 3, y1: 3, x2: 6, y2: 2 };
console.log(getIntersectingRectangle(rectangle1, rectangle2));
// { x1: 3, y1: 2, x2: 4, y2: 3 }
First, both rectangles get transformed into object with keys x
and y
and sorted arrays of two of corresponding them coordinates as values.
r1 = {
x: [2, 4], // x1, x2
y: [2, 4] // y1, y2
}
r2 = {
x: [3, 6], // x1, x2
y: [2, 3] // Y2, Y1 !
}
That's because for this job it is important to know which of x
s and y
s is lesser and which is greater. Rather than Math.max()
and Math.min()
a single .sort()
can be used.
Alternative would be to declare that (x1, y1)
is assumed to always be top-left corner, but as I see in rectangle2
in your question, that is apparently not always the case.
Now, noIntersect
is negated
!(a.left > b.right || b.left > a.right || a.top > b.bottom || b.top > a.bottom);
which tests if in both axes sides from one end of one figure exceed opposite-direction end side of the other figure, e.g. if left side of figure a
is more to the right than the right side of figure b
.
At the end we return false if there is no intersection of our rectangles, or an object with coordinates if there is. Intersecting part will always span from:
the greater of the 2 lesser x
s of both rectangles
to
the lesser of the 2 greater x
s of both rectangles.
/**
* Returns intersecting part of two rectangles
* @param {object} r1 4 coordinates in form of {x1, y1, x2, y2} object
* @param {object} r2 4 coordinates in form of {x1, y1, x2, y2} object
* @return {boolean} False if there's no intersecting part
* @return {object} 4 coordinates in form of {x1, y1, x2, y2} object
*/
const getIntersectingRectangle = (r1, r2) => {
[r1, r2] = [r1, r2].map(r => {
return {x: [r.x1, r.x2].sort(), y: [r.y1, r.y2].sort()};
});
const noIntersect = r2.x[0] > r1.x[1] || r2.x[1] < r1.x[0] ||
r2.y[0] > r1.y[1] || r2.y[1] < r1.y[0];
return noIntersect ? false : {
x1: Math.max(r1.x[0], r2.x[0]), // _[0] is the lesser,
y1: Math.max(r1.y[0], r2.y[0]), // _[1] is the greater
x2: Math.min(r1.x[1], r2.x[1]),
y2: Math.min(r1.y[1], r2.y[1])
};
};
/* ↓ DEMO ↓ */
const rectangle1 = { x1: 2, y1: 2, x2: 4, y2: 4 };
const rectangle2 = { x1: 3, y1: 3, x2: 6, y2: 2 };
console.log(getIntersectingRectangle(rectangle1, rectangle2));
// { x1: 3, y1: 2, x2: 4, y2: 3 }
/**
* Returns intersecting part of two rectangles
* @param {object} r1 4 coordinates in form of {x1, y1, x2, y2} object
* @param {object} r2 4 coordinates in form of {x1, y1, x2, y2} object
* @return {boolean} False if there's no intersecting part
* @return {object} 4 coordinates in form of {x1, y1, x2, y2} object
*/
const getIntersectingRectangle = (r1, r2) => {
[r1, r2] = [r1, r2].map(r => {
return {x: [r.x1, r.x2].sort(), y: [r.y1, r.y2].sort()};
});
const noIntersect = r2.x[0] > r1.x[1] || r2.x[1] < r1.x[0] ||
r2.y[0] > r1.y[1] || r2.y[1] < r1.y[0];
return noIntersect ? false : {
x1: Math.max(r1.x[0], r2.x[0]), // _[0] is the lesser,
y1: Math.max(r1.y[0], r2.y[0]), // _[1] is the greater
x2: Math.min(r1.x[1], r2.x[1]),
y2: Math.min(r1.y[1], r2.y[1])
};
};
/* ↓ DEMO ↓ */
const rectangle1 = { x1: 2, y1: 2, x2: 4, y2: 4 };
const rectangle2 = { x1: 3, y1: 3, x2: 6, y2: 2 };
console.log(getIntersectingRectangle(rectangle1, rectangle2));
// { x1: 3, y1: 2, x2: 4, y2: 3 }
answered Jun 19 at 0:22
Przemek
1,032213
1,032213
add a comment |
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f185323%2ffind-the-intersect-area-of-two-overlapping-rectangles%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Don't write, never present undocumented/uncommented code. Don't do
(boolean expression) ? true : false
. Try to limit line length.– greybeard
Jan 17 at 15:44
Are you talking about combination, intersection or even bounding rectangles? Why put 'overlapping' in the name when non-intersecting rectangles are equally valid input?
– le_m
Jan 17 at 17:43
Why not create a Rectange class? I did something similar whilst working on a visualisation project and it helped make sense of the code e.g.
rect1.intersects(rect2)
– James
Jan 20 at 0:19