Quadrilateral "contains" function

Practical function "contains" to detect a point inside common quadrilaterals such as squares, rectangles and diamonds. Squares and rectangles are widely used on many elements, like in-game objects and buttons. Square diamonds are quite practical for screen buttons that need to be together in diagonals, such as virtual D-pads. Large diamonds are wide used on isometric tile-based games.

by Karl Tayfer

HTML

<canvas id="canvas" style="background:#999"></canvas>

JavaScript

(function () {
    'use strict';
    window.addEventListener('load', init, false);
    var canvas = null;
    var ctx = null;
    var mouse = {
        x: 0,
        y: 0
    };
    var square = new Rectangle(80, 80, 120, 60);
    var square45 = new Diamond(380, 50, 120, 120);
    var isoTile = new Diamond(200, 240, 160, 80);

    document.addEventListener('mousemove', function (evt) {
        mouse.x = evt.pageX - canvas.offsetLeft;
        mouse.y = evt.pageY - canvas.offsetTop;
    }, false);

    function Rectangle(x, y, width, height) {
        this.x = (x == null) ? 0 : x;
        this.y = (y == null) ? 0 : y;
        this.width = (width == null) ? 0 : width;
        this.height = (height == null) ? this.width : height;
    }

    Rectangle.prototype.contains = function (pos) {
        if (pos != null) {
            return (this.x < pos.x && this.x + this.width > pos.x && this.y < pos.y && this.y + this.height > pos.y);
        }
    }

    Rectangle.prototype.fill = function (ctx) {
        if (ctx) {
            ctx.fillRect(this.x, this.y, this.width, this.height);
        }
    }

    Rectangle.prototype.stroke = function (ctx) {
        if (ctx) {
            ctx.strokeRect(this.x, this.y, this.width, this.height);
        }
    }

    function Diamond(x, y, width, height) {
        this.x = (x == null) ? 0 : x;
        this.y = (y == null) ? 0 : y;
        this.width = (width == null) ? 0 : width;
        this.height = (height == null) ? this.width : height;
    }

    Diamond.prototype.contains = function (pos) {
        if (pos != null) {
            var halfWidth = this.width / 2;
            var halfHeight = this.height / 2;
            var x = Math.abs(pos.x - (this.x + halfWidth));
            var y = Math.abs(pos.y - (this.y + halfHeight));
            return (x * halfHeight + y * halfWidth < halfWidth * halfHeight);
        }
    }

    Diamond.prototype.fill = function (ctx) {
        if (ctx) {
            ctx.beginPath();
           ...