Теорема о разделяющих осях

206
22 марта 2018, 10:49

Здравствуйте, сделал столкновение двух правильных многоугольников с помощью теоремы о разделяющих осях. может подскажет кто, как переделать на множество фигур, так как возник вопрос как отслеживать с какой фигурой я хочу столкнуть выбранную фигуру?

function Shape(points, x, y, color, stroke) { 
    this.x = x || 0; 
    this.y = y || 0; 
    this.points = points.map(function (el) { 
        return {x: el[0], y: el[1]}; 
    }); 
    this.color = color || "rgba(0,0,0,0)"; 
    this.stroke = stroke || "black"; 
    this.getNormals(); 
    this.getMedians(); 
} 
 
Shape.prototype.draw = function (ctx) { 
    var p = this.points; 
 
    ctx.save(); 
    ctx.fillStyle = this.color; 
    ctx.strokeStyle = this.stroke; 
    ctx.lineWidth = 3; 
    ctx.translate(this.x, this.y); 
    p.forEach(function (point, i) { 
        if (i === 0) { 
            ctx.beginPath(); 
            ctx.moveTo(point.x, point.y); 
        } else if (i === (p.length - 1)) { 
            ctx.lineTo(point.x, point.y); 
            ctx.lineTo(p[0].x, p[0].y); 
            ctx.stroke(); 
            ctx.fill(); 
        } else { 
            ctx.lineTo(point.x, point.y); 
        } 
    }); 
    ctx.closePath(); 
    ctx.restore(); 
}; 
 
Shape.prototype.getNormals = function () { 
    var p = this.points, 
        n = p.length, 
        crt, nxt, l, x1, y1; 
 
    this.normals = []; 
    for (var i = 0; i < n; i++) { 
        crt = p[i]; 
        nxt = p[i + 1] || p[0]; 
        x1 = (nxt.y - crt.y); 
        y1 = -(nxt.x - crt.x); 
        l = Math.sqrt(x1 * x1 + y1 * y1); 
        this.normals[i] = {x: x1 / l, y: y1 / l}; 
        this.normals[n + i] = {x: - x1 / l, y: - y1 / l}; 
    } 
}; 
 
Shape.prototype.getMedians = function () { 
    var p = this.points, 
        crt, nxt; 
 
    this.medians = []; 
 
    for (var i = 0; i < p.length; i++) { 
        crt = p[i]; 
        nxt = p[i + 1] || p[0]; 
        this.medians.push({x: (crt.x + nxt.x) / 2, y: (crt.y + nxt.y) / 2}); 
    } 
}; 
 
Shape.prototype.move = function (x, y) { 
    this.x = x; 
    this.y = y; 
}; 
 
Shape.prototype.checkCollision = function (shape) { 
    var me = this, 
        p1, p2; 
 
    return me.normals.concat(shape.normals).every(function (v) { 
        p1 = me.project(v); 
        p2 = shape.project(v); 
 
        return (((p1.min <= p2.max) && (p1.max >= p2.min)) || 
        (p2.min >= p1.max) && (p2.max >= p1.min)); 
    }); 
}; 
 
Shape.prototype.project = function (vector) { 
    var me = this, 
        p = this.points, 
        min = Infinity, max = -Infinity, 
        x, y, proj; 
 
    p.forEach(function (p) { 
        x = me.x + p.x; 
        y = me.y + p.y; 
        proj = (x * vector.x + y * vector.y); 
        min = proj < min ? proj : min; 
        max = proj > max ? proj : max; 
    }); 
 
    return {min: min, max: max}; 
}; 
 
var canvas = document.getElementById("scene"), 
    ctx = canvas.getContext("2d"), 
    w = window.innerWidth, 
    h = window.innerHeight, 
    isDown = false, 
    list = { 
        triangle: new Shape([[30, 0], [60, 60], [0, 60]], 50, 50), 
        rhombus: new Shape([[50, 0], [100, 50], [50, 100], [0, 50]], 200, 50) 
    }, 
    render = function () { 
        ctx.fillStyle = "#FFFFFF"; 
        ctx.fillRect(0, 0, w, h); 
        for (var shape in list) { 
            if (list.hasOwnProperty(shape)) { 
                list[shape].draw(ctx); 
            } 
        } 
        requestAnimationFrame(render); 
    }; 
 
canvas.addEventListener("mousedown", function (e) { 
    isDown = true; 
    checkFigures({x: e.clientX, y: e.clientY}); 
}); 
 
canvas.addEventListener("mouseup", function () { 
    isDown = false; 
    for (var figure in list) { 
        list[figure].moving = false; 
    } 
}); 
 
canvas.addEventListener("mousemove", function (e) { 
    var fig; 
    if (isDown) { 
        for (var figure in list) { 
            fig = list[figure]; 
            if (fig.moving) { 
                fig.move(e.clientX - fig.delta.x, e.clientY - fig.delta.y); 
                if (list.triangle.checkCollision(list.rhombus)) { 
                    list.triangle.stroke = 'red'; 
                    list.rhombus.stroke = 'red'; 
                } else { 
                    list.triangle.stroke = 'black'; 
                    list.rhombus.stroke = 'black'; 
                } 
            } 
        } 
    } 
}); 
 
function checkFigures(mp) { 
    for (var fig in list) { 
        if (isPointInPoly(list[fig].points, {x: mp.x - list[fig].x, y: mp.y - list[fig].y})) { 
            list[fig].moving = true; 
            list[fig].delta = { 
                x: mp.x - list[fig].x, 
                y: mp.y - list[fig].y 
            }; 
        } 
    } 
} 
 
function isPointInPoly(poly, pt) { 
    for (var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i) 
        ((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) 
        && (c = !c); 
    return c; 
} 
 
canvas.width = w; 
canvas.height = h; 
 
requestAnimationFrame(render);
<!DOCTYPE html> 
<html> 
<head lang="en"> 
    <meta charset="UTF-8"> 
    <title></title> 
</head> 
<body> 
    <canvas id="scene"></canvas> 
    <script src="Shape.js" type="text/javascript"></script> 
    <script src="main.js" type="text/javascript"></script> 
</body> 
</html>

READ ALSO
Исключение дней недели для html5 поля ввода типа date

Исключение дней недели для html5 поля ввода типа date

ЗдравствуйтеЕсть ли способ, js-ом исключить из выбора или ввода в <input type="date"> определенные дни недели? Т

244
Массив localStorage не сохраняет данные, если сделать refresh страницы

Массив localStorage не сохраняет данные, если сделать refresh страницы

Есть форма, в нее пользователь вписывает данные и они сохраняются в localStorage массиве под названием todoДанные вписанные в форму оказываются...

253
Как превратить строку utf-16 в верстку

Как превратить строку utf-16 в верстку

Нужно динамически рендерить элементы в браузереС сервера приходит верстка в юникоде

202