robindevouge
6/26/2018 - 12:14 PM

Math functions

// get distance between
function distanceBetween(x1, y1, x2, y2) {
    var dx = x1 - x2, 
        dy = y1 - y2;
    return Math.sqrt(dx * dx + dy * dy);
}
// square collision
function overlapSquare(x1, y1, w1, h1, x2, y2, w2, h2) {
    if (x1 + w1 > x2 && x1 < x2 + w2 && y1 + h1 > y2 && y1 < y2 + h2) {
        return true;
    }
    return false;
}

// circle collision
function overlapCircle(cx1, cy1, cr1, cx2, cy2, cr2) {
    var dx = cx1 - cx2, dy = cy1 - cy1, distance = (dx * dx + dy * dy);
    if (distance <= (cr1 + cr2) * (cr1 + cr2)) {
        return true;
    }
    return false;
}

// p1 is an object {x : 0, y:0 }
// p2 is an object {x : 0, y:0 }
// c is an object {x : 0, y:0 }
// r radius of the circle
function interceptOnCircle(p1, p2, c, r) {
    //p1 is the first line point
    //p2 is the second line point
    //c is the circle's center
    //r is the circle's radius

    var p3 = {x:p1.x - c.x, y:p1.y - c.y}; //shifted line points
    var p4 = {x:p2.x - c.x, y:p2.y - c.y};

    var m = (p4.y - p3.y) / (p4.x - p3.x); //slope of the line
    var b = p3.y - m * p3.x; //y-intercept of line

    var underRadical = Math.pow(r,2)*Math.pow(m,2) + Math.pow(r,2) - Math.pow(b,2); //the value under the square root sign 

    if (underRadical < 0) {
        //line completely missed
        return false;
    } else {
        var t1 = (-m*b + Math.sqrt(underRadical))/(Math.pow(m,2) + 1); //one of the intercept x's
        var t2 = (-m*b - Math.sqrt(underRadical))/(Math.pow(m,2) + 1); //other intercept's x
        var i1 = {x:t1+c.x, y:m*t1+b+c.y}; //intercept point 1
        var i2 = {x:t2+c.x, y:m*t2+b+c.y}; //intercept point 2
        return [i1, i2];
    }
}

// check isPointInCircle
function isPointInCircle(cx, cy, r, x, y){
    var dx = (cx - x)^2,  
        dy = (cy - y)^2, 
        d = Math.sqrt( dx + dy);
    return d <= r;
}

// check if two line intersects
function checkLineIntersection(line1StartX, line1StartY, line1EndX, line1EndY, line2StartX, line2StartY, line2EndX, line2EndY) {
    // if the lines intersect, the result contains the x and y of the intersection (treating the lines as infinite) and booleans for whether line segment 1 or line segment 2 contain the point
    var denominator, a, b, numerator1, numerator2, result = { x: null, y: null, onLine1: false, onLine2: false };
    denominator = ((line2EndY - line2StartY) * (line1EndX - line1StartX)) - ((line2EndX - line2StartX) * (line1EndY - line1StartY));
    if (denominator === 0) { return result; }
    a = line1StartY - line2StartY;
    b = line1StartX - line2StartX;
    numerator1 = ((line2EndX - line2StartX) * a) - ((line2EndY - line2StartY) * b);
    numerator2 = ((line1EndX - line1StartX) * a) - ((line1EndY - line1StartY) * b);
    a = numerator1 / denominator;
    b = numerator2 / denominator;
    // if we cast these lines infinitely in both directions, they intersect here:
    result.x = line1StartX + (a * (line1EndX - line1StartX));
    result.y = line1StartY + (a * (line1EndY - line1StartY));
    // if line1 is a segment and line2 is infinite, they intersect if:
    if (a > 0 && a < 1) { result.onLine1 = true; }
    // if line2 is a segment and line1 is infinite, they intersect if:
    if (b > 0 && b < 1) { result.onLine2 = true; }
    // if line1 and line2 are segments, they intersect if both of the above are true
    return result;
}

var hitTestCircle = function (ball1, ball2) {
    var retVal = false;
    var dx = ball1.nextX - ball2.nextX;
    var dy = ball1.nextY - ball2.nextY;
    var distance = (dx * dx + dy * dy);
    if (distance <= (ball1.radius + ball2.radius) * (ball1.radius + ball2.radius) ) {
        retVal = true;
    }
    return retVal;
}

// var point = {x: 1, y: 2};
// var rectangle = {x1: 0, x2: 10, y1: 1, y2: 7};
// pointRectangleIntersection(point, rectangle);
function isPointInRect(point, rect) {
    return point.x > rect.x && point.x < rect.width && point.y > rect.y && point.y < rect.height;
}

function isPointInPoly(poly, pt){
    for(var i = -1, l = poly.length, j = l - 1; ++i < l; j = i){
        if(((poly[i].y <= pt.y && pt.y < poly[j].y) || (poly[j].y <= pt.y && pt.y < poly[i].y)) && 
        	(pt.x < (poly[j].x - poly[i].x) * (pt.y - poly[i].y) / (poly[j].y - poly[i].y) + poly[i].x) ){
        	return true;
        }
    }
    return false;
}
// check if two svg path eleme,nt intersects
function checkPathIntersection(path1, path2, accuracy, debug){
  var collision, line1StartX, line1StartY, line1EndX, line1EndY,l,m,
      line1 = pathToPolyline(path1, accuracy, debug),
      line2 = pathToPolyline(path2, accuracy, debug),
      colisions = [];
  if(debug){
    svg.appendChild(line1.polyline);
    svg.appendChild(line2.polyline);
  }
  for(l = 1; l < line1.points.length; l++){
    line1StartX = line1.points[l-1][0];
    line1StartY = line1.points[l-1][1];
    line1EndX = line1.points[l][0];
    line1EndY = line1.points[l][1];

    for(m = 1; m < line2.points.length; m++){
      line2StartX = line2.points[m-1][0];
      line2StartY = line2.points[m-1][1];
      line2EndX = line2.points[m][0];
      line2EndY = line2.points[m][1];
      collision = checkLineIntersection(line1StartX, line1StartY, line1EndX, line1EndY, line2StartX, line2StartY, line2EndX, line2EndY);
      if(collision.onLine1 && collision.onLine2){
        colisions.push(collision);
      }
    }
  }
  if(colisions.length){
    return colisions;
  }
  return false;
}

/* transform a svh path tag to an array of points [[x,y],[x,y],...] */
function pathToPolyline(path, segments, debug){
  var division = Math.round(segments),
  curveLength = path.getTotalLength(),
  step = curveLength / segments,
  currentPosition = curveLength,
  point = path.getPointAtLength(currentPosition),
  polyline = false,
  points = [];
  for(var i = 0; i <= segments; i++){
    currentPosition -= step;
    point = path.getPointAtLength(currentPosition+step);
    points.push([parseFloat((point.x).toFixed(2)), parseFloat((point.y).toFixed(2))]);
  }
  if(debug){polyline = arrayToPolyline(points); }
  return { polyline : polyline, points : points };
}

/*

isIntersecting = function(r1, r2) {

return !(r2.x > (r1.x + r1.width) || 

           (r2.x + r2.width) < r1.x || 

           r2.y > (r1.y + r1.height) ||

           (r2.y + r2.height) < r1.y);

}

*/
var PI = Math.PI;
var RADIANS = PI / 180;
var DEGREES = 180 / PI;
 
// degrees to radians
function toRadians(degrees) {
    return degrees * Math.PI / 180;
}
 
// radians to degrees
function toDegrees(radians) {
    return radians * 180 / Math.PI;
}
 
function getAngle(x1, y1, x2, y2) {
    /*var deltaX = x2 - x1;
    var deltaY = y2 - y1;
    var rad = Math.atan2(deltaY, deltaX); // In radians
    */
    return - Math.atan2(y2 - y1, x2 - x1);
}
 
function pointInAngleDist(offset, start, to){
  var angle = Math.atan2(to.y - start.y - offset, to.x - start.x - offset),
  angleDeg = (angle * 180 / Math.PI).toFixed(2),
  dist = distanceBetween(start.x, start.y, to.x, to.y),
  x =  (start.x - offset) + Math.cos(angle) * (dist*.5), 
  y =  (start.y - offset) + Math.sin(angle) * (dist*.5); 
  return { x : x, y : y, angle : angleDeg}
}
 
function getDegreeDirection(x1, y1, x2, y2){
    return Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI;
}
// Get percentage of x between range of a to b
const percent = (x - a) / (b - a) * 100;