座標計算クラスソース

// 座標計算クラス
var clsCalcPoints = function()
{
};
// 図形の1辺の直線と中心点と検査点を結ぶ線分が内側にあるかを調べる
clsCalcPoints.prototype.InnerPont = function(px1, py1, px2, py2, cx, cy, gx, gy)
{
    var tc = (px1 - px2) * (cy - py1) + (py1 - py2) * (px1 - cx);
    var td = (px1 - px2) * (gy - py1) + (py1 - py2) * (px1 - gx);
    return ((tc * td) > 0);
}
// クライアント座標をHEX座標に変換
clsCalcPoints.prototype.GetHexPoint = function(gx, gy, gw, gh, cx, cy)
{
    // 格子の半分の量
    var wHalf = (gw / 2);
    var hHalf = (gh / 2);
    // 行列開始指標(六角形の高さの半分を1行と、幅の半分を1列とする)
    var row = Math.floor(gy / hHalf);
    var col = Math.floor(gx / wHalf);
    // 探索中心点配列
    var ary = null;
    // 行偶数フラグ
    var RowEven = ((row % 2) == 0);
    // 探索中心点設定分岐
    if ((col % 3) == 1) {
        ary = new Array({ x:col * wHalf + wHalf / 2, y:(row * hHalf + (RowEven ? hHalf : 0)) });
    }
    else if ((col % 3) == 2) {
        ary = (
            RowEven
            ? new Array({ x:col * wHalf - wHalf / 2, y:row * hHalf + hHalf }, { x:col * wHalf + wHalf, y:row * hHalf })
            : new Array({ x:col * wHalf - wHalf / 2, y:row * hHalf }, { x:col * wHalf + wHalf, y:row * hHalf + hHalf })
        );
    }
    else {
        ary = (
            RowEven
            ? new Array({ x:col * wHalf, y:row * hHalf }, { x:col * wHalf + wHalf * 1.5, y:row * hHalf + hHalf })
            : new Array({ x:col * wHalf, y:row * hHalf + hHalf }, { x:col * wHalf + wHalf * 1.5, y:row * hHalf })
        );
    }
    // 探索ループ
    if (ary) {
        for (var idx = 0; idx < ary.length; idx++) {
            // 座標を整数に変換
            var px = Math.floor(ary[idx].x);
            var py = Math.floor(ary[idx].y);
            // 点配列を生成
            var hex = this.GetHexPolygon(px, py, gw, gh);
            // 包含点なら中心座標を返す
            if (this.InnerHex(gx, gy, hex)) {
                return new Array(px, py, row, col);
            }
        }
    }
    // 探索不可を返す
    return null;
}
// 中心点から六角形座標を得る
clsCalcPoints.prototype.GetHexPolygon = function(x, y, gw, gh)
{
    // 格子の半分の量
    var wHalf = (gw / 2);
    var hHalf = (gh / 2);
    // 点配列を生成
    var hex = new Array(
        x + (wHalf / 2), y - hHalf     // 右上の点
        , x + wHalf, y                 // 右端の点
        , x + (wHalf / 2), y + hHalf   // 右下の点
        , x - (wHalf / 2), y + hHalf   // 左下の点
        , x - wHalf, y                 // 左端の点
        , x - (wHalf / 2), y - hHalf   // 左上の点
     );
    // 結果を返す
    return hex;
}
// 座標が六角形の内にあるかを判定
clsCalcPoints.prototype.InnerHex = function(gx, gy, hex)
{
    // 左端と右端から中心Xを求める
    var x = hex[8] + ((hex[2] - hex[8]) / 2);
    // 右上と右下中心Yを求める
    var y = hex[1] + ((hex[5] - hex[1]) / 2);
    // 右上と右端
    if (!this.InnerPont(
        hex[0], hex[1]      // 右上の点
        , hex[2], hex[3]    // 右端の点
        , x, y, gx, gy      // 中心点と検査する点
    )) return false;
    // 右端と右下
    if (!this.InnerPont(
        hex[2], hex[3]      // 右端の点
        , hex[4], hex[5]    // 右下の点
        , x, y, gx, gy      // 中心点と検査する点
    )) return false;
    // 右下と左下
    if (!this.InnerPont(
        hex[4], hex[5]      // 右下の点
        , hex[6], hex[7]    // 左下の点
        , x, y, gx, gy      // 中心点と検査する点
    )) return false;
    // 左下と左端
    if (!this.InnerPont(
        hex[6], hex[7]      // 左下の点
        , hex[8], hex[9]    // 左端の点
        , x, y, gx, gy      // 中心点と検査する点
    )) return false;
    // 左端と左下
    if (!this.InnerPont(
        hex[8], hex[9]      // 左端の点
        , hex[10], hex[11]  // 左上の点
        , x, y, gx, gy      // 中心点と検査する点
    )) return false;
    // 左上と右上
    if (!this.InnerPont(
        hex[10], hex[11]    // 左上の点
        , hex[0], hex[1]    // 右上の点
        , x, y, gx, gy      // 中心点と検査する点
    )) return false;
    // 点がHEX内部にある事を返す
    return true;
}
// サイズ内の座標に変換
clsCalcPoints.prototype.GetPtMapping = function(p, s)
{
    return Math.abs(Math.floor(p < 0 ? (s + p) % s : p % s));
}
clsCalcPoints.prototype.DrawRect = function(id, row, col, gw, gh, cx, cy)
{
    var canvas = document.getElementById(id);
    var ctx = canvas.getContext('2d');
    // 格子の半分の量
    var wHalf = (gw / 2);
    var hHalf = (gh / 2);
    // 消去
    ctx.clearRect(0, 0, cx, cy);
    // キャンバス属性を退避
    ctx.save();
    // 描画属性を設定
    ctx.lineWidth = 2;
    ctx.strokeStyle = "red";
    // パスを開始
    ctx.beginPath();
    // 四角形描画
    ctx.rect(col * wHalf, row * hHalf, wHalf, hHalf);
    // パスを描く
    ctx.stroke();
    // キャンバス属性を戻す
    ctx.restore();
}