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.



Cases of overlapped rectangles

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 }









share|improve this question
























  • 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















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.



Cases of overlapped rectangles

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 }









share|improve this question
























  • 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













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.



Cases of overlapped rectangles

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 }









share|improve this question















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.



Cases of overlapped rectangles

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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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


















  • 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










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 called OverX I'd call it OverlapX and invert it.
    OverlapX = minOfX(rec1) <= maxOfX(rec2) && minOfX(rec2) <= maxOfX(rec1);

  • precomputing booleans the way of OverX and OverY 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.)






share|improve this answer






























    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 xs and ys 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 xs of both rectangles



    to



    the lesser of the 2 greater xs of both rectangles.






    share|improve this answer





















      Your Answer





      StackExchange.ifUsing("editor", function () {
      return StackExchange.using("mathjaxEditing", function () {
      StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
      StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
      });
      });
      }, "mathjax-editing");

      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "196"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      convertImagesToLinks: false,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














       

      draft saved


      draft discarded


















      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

























      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 called OverX I'd call it OverlapX and invert it.
        OverlapX = minOfX(rec1) <= maxOfX(rec2) && minOfX(rec2) <= maxOfX(rec1);

      • precomputing booleans the way of OverX and OverY 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.)






      share|improve this answer



























        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 called OverX I'd call it OverlapX and invert it.
          OverlapX = minOfX(rec1) <= maxOfX(rec2) && minOfX(rec2) <= maxOfX(rec1);

        • precomputing booleans the way of OverX and OverY 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.)






        share|improve this answer

























          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 called OverX I'd call it OverlapX and invert it.
            OverlapX = minOfX(rec1) <= maxOfX(rec2) && minOfX(rec2) <= maxOfX(rec1);

          • precomputing booleans the way of OverX and OverY 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.)






          share|improve this answer















          • Document/comment

            I have no idea whether there are agreed standards for ECMAScript, e.g. JSDoc.


          • If I used what you called OverX I'd call it OverlapX and invert it.
            OverlapX = minOfX(rec1) <= maxOfX(rec2) && minOfX(rec2) <= maxOfX(rec1);

          • precomputing booleans the way of OverX and OverY 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.)







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Jan 17 at 16:38

























          answered Jan 17 at 16:09









          greybeard

          1,3391521




          1,3391521
























              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 xs and ys 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 xs of both rectangles



              to



              the lesser of the 2 greater xs of both rectangles.






              share|improve this answer

























                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 xs and ys 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 xs of both rectangles



                to



                the lesser of the 2 greater xs of both rectangles.






                share|improve this answer























                  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 xs and ys 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 xs of both rectangles



                  to



                  the lesser of the 2 greater xs of both rectangles.






                  share|improve this answer















                  /**
                  * 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 xs and ys 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 xs of both rectangles



                  to



                  the lesser of the 2 greater xs 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 }






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Jun 19 at 0:22









                  Przemek

                  1,032213




                  1,032213






























                       

                      draft saved


                      draft discarded



















































                       


                      draft saved


                      draft discarded














                      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





















































                      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







                      Popular posts from this blog

                      Quarter-circle Tiles

                      build a pushdown automaton that recognizes the reverse language of a given pushdown automaton?

                      Mont Emei