Question

I'm trying to write a function to detect if a line collsions with a rectangle shape. I have a function to detect if an image intersects with a rectangle but a line shape doesn't have all the properties I need like width and height etc.

function checkCollision(obj1, obj2){ //checks for collision
var status = false;
var obj1Top = obj1.getAttr('y');
var obj1Bottom = obj1.getAttr('y') + obj1.getAttr('height');
var obj1Left = obj1.getAttr('x');
var obj1Right = obj1.getAttr('x') + obj1.getAttr('width');

var obj2Top = obj2.getAttr('y');
var obj2Bottom = obj2.getAttr('y') + obj2.getAttr('height');
var obj2Left = obj2.getAttr('x');
var obj2Right = obj2.getAttr('x') + obj2.getAttr('width');

if (!(obj1Bottom < obj2Top || obj1Top > obj2Bottom || obj1Left > obj2Right || obj1Right < obj2Left))

status = true;

return status;
}

Any Ideas?

Était-ce utile?

La solution

A Demo: http://jsfiddle.net/m1erickson/eZHu7/

Line-Rect collisions are surprisingly complex!

This function tests whether a line segment intersects any of the 4 sides of a rectangle:

// test line vs the 4 rectangle lines
function lineRectIntersects(line,rect){

    // p=line startpoint, p2=line endpoint
    var p={x:line.x1,y:line.y1};
    var p2={x:line.x2,y:line.y2};

    // top rect line
    var q={x:rect.x,y:rect.y};
    var q2={x:rect.x+rect.width,y:rect.y};
    if(doLineSegmentsIntersect(p,p2,q,q2)){ return true; }

    // right rect line
    var q=q2;
    var q2={x:rect.x+rect.width,y:rect.y+rect.height};
    if(doLineSegmentsIntersect(p,p2,q,q2)){ return true; }

    // bottom rect line
    var q=q2;
    var q2={x:rect.x,y:rect.y+rect.height};
    if(doLineSegmentsIntersect(p,p2,q,q2)){ return true; }

    // left rect line
    var q=q2;
    var q2={x:rect.x,y:rect.y};
    if(doLineSegmentsIntersect(p,p2,q,q2)){ return true; }

    // If not intersecting with the 4 rect sides, then not intersecting
    return(false);
}

That function uses Peter Kelley's line-line intersection algorithm:

https://github.com/pgkelley4/line-segments-intersect/blob/master/js/line-segments-intersect.js

Peter's code is reproduced here in case the link rots:

/**
 * @author Peter Kelley
 * @author pgkelley4@gmail.com
 */


/**
 * See if two line segments intersect. This uses the 
 * vector cross product approach described below:
 * http://stackoverflow.com/a/565282/786339
 * 
 * @param {Object} p point object with x and y coordinates
 *  representing the start of the 1st line.
 * @param {Object} p2 point object with x and y coordinates
 *  representing the end of the 1st line.
 * @param {Object} q point object with x and y coordinates
 *  representing the start of the 2nd line.
 * @param {Object} q2 point object with x and y coordinates
 *  representing the end of the 2nd line.
 */
function doLineSegmentsIntersect(p, p2, q, q2) {
  var r = subtractPoints(p2, p);
  var s = subtractPoints(q2, q);


  var uNumerator = crossProduct(subtractPoints(q, p), r);
  var denominator = crossProduct(r, s);


  if (uNumerator == 0 && denominator == 0) {
    // colinear, so do they overlap?
    return ((q.x - p.x < 0) != (q.x - p2.x < 0) != (q2.x - p.x < 0) != (q2.x - p2.x < 0)) || 
      ((q.y - p.y < 0) != (q.y - p2.y < 0) != (q2.y - p.y < 0) != (q2.y - p2.y < 0));
  }


  if (denominator == 0) {
    // lines are paralell
    return false;
  }


  var u = uNumerator / denominator;
  var t = crossProduct(subtractPoints(q, p), s) / denominator;


  return (t >= 0) && (t <= 1) && (u >= 0) && (u <= 1);
}


/**
 * Calculate the cross product of the two points.
 * 
 * @param {Object} point1 point object with x and y coordinates
 * @param {Object} point2 point object with x and y coordinates
 * 
 * @return the cross product result as a float
 */
function crossProduct(point1, point2) {
  return point1.x * point2.y - point1.y * point2.x;
}


/**
 * Subtract the second point from the first.
 * 
 * @param {Object} point1 point object with x and y coordinates
 * @param {Object} point2 point object with x and y coordinates
 * 
 * @return the subtraction result as a point object.
 */ 
function subtractPoints(point1, point2) {
  var result = {};
  result.x = point1.x - point2.x;
  result.y = point1.y - point2.y;
  return result;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top