3

I am trying to see when my two divs are going to overlap and touch each other. The two yellow divs on this example.

Why is it that the collision returns true at a stage when the divs aren't even overlapping or touching each other ?

http://jsfiddle.net/HWfMt/156/

    var degree = 0;
var degreeSmall = 0;
var timer=30;
var $spin = $(".gear");
var $spinSmall = $(".gear-small");
var to;
var toSmall;

function collision($div1, $div2) {
  var x1 = $div1.offset().left;
  var y1 = $div1.offset().top;
  var h1 = $div1.outerHeight(true);
  var w1 = $div1.outerWidth(true);
  var b1 = y1 + h1;
  var r1 = x1 + w1;
  var x2 = $div2.offset().left;
  var y2 = $div2.offset().top;
  var h2 = $div2.outerHeight(true);
  var w2 = $div2.outerWidth(true);
  var b2 = y2 + h2;
  var r2 = x2 + w2;

  if (b1 < y2 || y1 > b2 || r1 < x2 || x1 > r2) return false;
  return true;
}

$( document ).ready(function() {

    rotate();
});


function rotate() {
    degree++;
    $spin.css({ 'WebkitTransform': 'rotate(' + degree + 'deg)'});  
    $spin.css({ '-moz-transform': 'rotate(' + degree + 'deg)'});

    to = setTimeout(function() {
        rotate();
    }, timer);

    $('#result').text(collision($('.gear .inner-gear.yellow'), $('.gear-small .inner-gear.yellow')));

}

Thanks

Kiwimoisi
  • 4,086
  • 6
  • 33
  • 64
  • 2
    here is a test i'm running http://jsfiddle.net/abc123/HWfMt/162/ it appears the x axis changes. – abc123 Apr 05 '15 at 11:16
  • What is your suggestion @abc123 – Kiwimoisi Apr 05 '15 at 11:51
  • I think a solution would be to detect is there is a collision when they are not rotating or stopped. I will check only when they are stopped anyway so I don't think it's necessary to check during the rotation. This way the results might actually be accurate. @abc123 – Kiwimoisi Apr 07 '15 at 05:18

3 Answers3

3

Edit: See below for both gears rotating with polygon detection since you've added comments that say you want both gears to rotate.

Only one gear rotates: I've forked your JSFiddle to work how I think you want here. It shows "true" for collision 25% of the time as I think you wanted. I see a few issues with what I think you are trying to do; your boxes are calculated wrong. You probably want to exclude borders, so I've changed the code to subtract them from x1,y1 and x2,y2. To exclude borders you also want to use innerWidth/innerHeight, not outerWidth/outerHeight.

Most importantly, you want to make sure your rectangles don't include an extra pixel from simply adding the width or height. For example, look at this line of 3 characters with positions:
0 1 2
a b c

The first a (x1) is at position 0. The width is 3, but 0+3 = 3 when c (r1) should clearly be at position 2. Including that extra pixel causes the collision of the left corner to go wrong and appear to collide much earlier than it does. Subtract 1 as I do in the code below to fix this problem:

function collision($div1, $div2) {
  var x1 = $div1.offset().left + parseInt($div1.css('borderLeftWidth'),10);
  var y1 = $div1.offset().top + parseInt($div1.css('borderTopWidth'),10);
  var h1 = $div1.innerHeight();
  var w1 = $div1.innerWidth();
  var b1 = y1 + h1 - 1;
  var r1 = x1 + w1 - 1;
  var x2 = $div2.offset().left + parseInt($div2.css('borderLeftWidth'),10);
  var y2 = $div2.offset().top + parseInt($div2.css('borderTopWidth'),10);
  var h2 = $div2.innerHeight();
  var w2 = $div2.innerWidth();
  var b2 = y2 + h2 - 1;
  var r2 = x2 + w2 - 1;

  return (r1 >= x2 && r2 >= x1 && b1 >= y2 && b2 >= y1);
}

Both gears rotating: For this to work, you need full polygon detection with the sides of the polygons formed by the rotated corners. I've added corner divs to the yellow areas, added go/stop/step buttons for debugging, and made the other divs translucent to make it more obvious. JSFiddle here. Both gears rotate as your second example, and now it shows collisions properly. The polygon collision code was taken from a StackOverflow question.

Community
  • 1
  • 1
Ed Bayiates
  • 11,060
  • 4
  • 43
  • 62
  • Hi, give me a few seconds and I will show you what I think is a counter example. I am not sure yet, if it's not then your answer will be perfect :) – Kiwimoisi Apr 08 '15 at 00:42
  • This is my example, stop the wheel 10px after they match, it does say tru when you stop it. When it keeps rotating the status is right, but as soon as you stop the wheel the collision status is wrong when they are very close to collision .http://jsfiddle.net/HWfMt/175/ @Ed Bayiates – Kiwimoisi Apr 08 '15 at 01:11
  • Forget about the borders, I removed them to make it easier to understand. – Kiwimoisi Apr 08 '15 at 01:12
  • If you stop the first main gear first by clicking on it and let the smaller one spin you will see what I am talking about. @EdBayiates – Kiwimoisi Apr 08 '15 at 01:31
  • @Kiwimoisi, you've changed the question with this new example. I've edited my answer since for both gears to rotate, you need polygon collision detection. – Ed Bayiates Apr 08 '15 at 18:24
  • Fantastic, yesterday I actually saw this code but didn't try to use it. – Kiwimoisi Apr 09 '15 at 04:03
  • I went way too far away in what I tried by cutting the page in 4 corners and detecting which corner the old top position was etc ... That way is much more easier and perfect. Thank you so much for your help. KR – Kiwimoisi Apr 09 '15 at 04:04
2

The intersection test code is right for axis-aligned bounding boxes. If that's what you were trying to check, then the problem you have here is that the box coordinates that you are checking are wrong. I won't fix this for you, but I'll show you how to debug this easily:

Add a semitransparent overlay:

<div id="bb" style="background:rgba(0,0,0,0.5); position:absolute;"></div>

And see what you are comparing:

$('#bb').offset({left:x1,top:y1}).width(w1).height(y1);

Updated JSFiddle.

user
  • 23,260
  • 9
  • 113
  • 101
  • Hi, So technically I would have to get the top left bottom and right, get the whole area ... – Kiwimoisi Apr 07 '15 at 23:09
  • Yes, and after that be very careful with positioning, because any pixel (central one, for example) can lead to a touch. – user Apr 08 '15 at 00:03
  • @user, Nice way of illustrating the non-rotative nature of just using x,y,w,h on rotating rectangles. – Ed Bayiates Apr 08 '15 at 20:43
0

Try this demo:

remove border and width change 49% to 50%

demo

OR another solution

width & height change 49% to calc(50% - 1px) and top & left change 149px to 148px

demo

Ahosan Karim Asik
  • 3,219
  • 1
  • 18
  • 27