Apr 8, 2014

起動時にエラーが出る。

----エラーメッセージ ----------------
IDE アドイン 'C:\Program Files\Borland\BDS\4.0\Bin\Borland.SCI.Gate.dll' 読み込みに失敗しました。
呼び出しのターゲットが例外をスローしました。
追加情報: "com.borland.tg.sci.SciModelAccess" のタイプ初期化子が例外をスローしました。


これ入れたらなんか直った。
Version 1.1 再頒布可能パッケージ http://www.microsoft.com/ja-jp/download/confirmation.aspx?id=12520

Mar 27, 2014

jQuery で Easing を追加する。 以下、JavaScript のみ。

// easing の定義
jQuery.extend(jQuery.easing, {
    newEasing: function (x, t, b, c, d) {
        var s = 1.70158;
        var p = 0;
        var a = c;
        if (t == 0) return b;
        if ((t /= d / 2) == 2) return b + c;
        if (!p) p = d * (.3 * 1.5);
        if (a < Math.abs(c)) {
            a = c;
            var s = p / 4;
        } else var s = p / (2 * Math.PI) * Math.asin(c / a);
        if (t < 1) return -.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
        return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
    }
});

// 追加した easing をアニメーションで指定
$(document).ready(function () {
    $("#target").click(function () {
        $("#target").animate({
            left: "300px",
            top: "200px"
        }, 1500, "newEasing");
    });
});

Mar 17, 2014

アプリケーション構成ファイル(app.config)をいじる必要があって、configuration > startup に 'useLegacyV2RuntimeActivationPolicy="true"' 属性を追加する。


  
    
  


startup 要素
Ctrl + Shift + F7 で「フォーマット・プロパティ」ダイアログが表示される。 ざっとメニューを見渡してもそれらしい項目が見当たらない。どっか深いとこにでもあるんだろうか。
前回やっと Delaunay 分割まで辿り着いた。お目当ての Delaunay 分割も片付いたので、あとは軽く仕上げるだけ。今回は Delaunay 分割した三角形を塗りたいと思います。 さっそくソースコード。 予め canvas のサイズをもとに色テーブルを作っておいて、Delaunay 分割した三角形の外接円の中心をみて色を決めます。んで、塗る。以下、JavaScript だけ。

$(document).ready(function () {

    var SAMPLE = {};

    SAMPLE.Main = (function () {

        var canJqObj = $("#can"),
            canDom = document.getElementById('can'),
            ctx = document.getElementById('can').getContext("2d"),

            // 色のコレクション(最低4色)
            colors = [
            // http://www.colourlovers.com/palette/2490997/HJ_Project_Palette
            ["#000000", "#FF0080", "#00D4ED", "#D2D2D2", "#FFFFFF"],
            // http://www.colourlovers.com/palette/2490986/all_night_long_.
            ["#ED146F", "#EDDE45", "#61D2D6", "#242424", "#FAFAFA"],
            // http://www.colourlovers.com/palette/2490977/SILVIA_PELISSERO_APC
            ["#110E19", "#B60F19", "#F86F07", "#FF9F33", "#C1D8A0"],
            // http://www.colourlovers.com/palette/2490968/navy_blend
            ["#14343C", "#DDE915", "#1C15E9", "#A83C17", "#159797"],
            // http://www.colourlovers.com/palette/2491000/w_a_t_e_r_m_e_l_o_n
            ["#E9625C", "#B5C368", "#0A3D5D", "#CCE9C7", "#C9D88A"],

            //http://www.colourlovers.com/palette/1483942/The_Autumn_Queen_HPP
            ["#4E2E1E", "#EA4F6C", "#F99548", "#FCCA55"],
            //http://www.colourlovers.com/palette/1297074/Autumn_Rainbow
            ["#6D2243", "#EC5E0C", "#F78F1E", "#85871A"],
            //http://www.colourlovers.com/palette/36998/french_roast
            ["#A7321C", "#FFDC68", "#928941", "#352504"],
            //http://www.colourlovers.com/palette/582235/October_Roads
            ["#821F29", "#F6E03F", "#ADBD06", "#D46600"], ],

            // 使用する色をランダムに選定
            colorIndex = Math.floor(Math.random() * (colors.length - 1));


        // ==================================================
        // 頂点
        // ==================================================
        function Vertex(x, y, vx, vy) {

            this.x = x;
            this.y = y;

            // 固定頂点かどうか(true:固定、false:移動)
            this.isStatic = ((vx == undefined || vy == undefined) ? true : false);
            // X 軸の移動速度
            this.velocityX = ((vx == undefined) ? Math.random() * 0.7 - 0.35 : vx);
            // Y 軸の移動速度
            this.velocityY = ((vy == undefined) ? Math.random() * 0.7 - 0.35 : vy);

            // ==================================================
            // 頂点を描画
            // ==================================================
            this.draw = function () {

                // 固定は黒、移動は赤
                ctx.fillStyle = (this.isStatic ? "rgb(66, 66, 66)" : "rgb(255, 66, 22)");

                ctx.beginPath();
                ctx.arc(this.x, this.y, 2, 0, 360, true);
                ctx.fill();

            };

            // ==================================================
            // 頂点を更新
            // ==================================================
            this.update = function () {

                // 移動する頂点の場合
                if (!this.isStatic) {

                    // canvas の端で跳ね返す(X)
                    if (0 > this.x || canDom.width < this.x) {
                        this.velocityX *= -1;
                    }

                    // canvas の端で跳ね返す(Y)
                    if (0 > this.y || canDom.height < this.y) {
                        this.velocityY *= -1;
                    }

                    // 座標を更新
                    this.x += this.velocityX;
                    this.y += this.velocityY;
                }

            };

        } // Vertex


        // ==================================================
        // エッジ
        // ==================================================
        function Edge(v0, v1) {

            this.v0 = v0;
            this.v1 = v1;

        } // Edge


        // ==================================================
        // 三角形
        // ==================================================
        function Triangle(v0, v1, v2) {

            // 外接円の求め方
            var x1 = v0.x,
                y1 = v0.y,
                x2 = v1.x,
                y2 = v1.y,
                x3 = v2.x,
                y3 = v2.y,
                c = 2.0 * ((x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1)),
                x = ((y3 - y1) * (x2 * x2 - x1 * x1 + y2 * y2 - y1 * y1) + (y1 - y2) * (x3 * x3 - x1 * x1 + y3 * y3 - y1 * y1)) / c,
                y = ((x1 - x3) * (x2 * x2 - x1 * x1 + y2 * y2 - y1 * y1) + (x2 - x1) * (x3 * x3 - x1 * x1 + y3 * y3 - y1 * y1)) / c,
                center = new Vertex(x, y), // 外接円の中心
                dx = center.x - v0.x,
                dy = center.y - v0.y,
                radius_squared = (dx * dx) + (dy * dy),
                radius = Math.sqrt(radius_squared), // 外接円の半径
                circle = new Circle(center, radius);

            this.v0 = v0;
            this.v1 = v1;
            this.v2 = v2;
            this.circle = circle;
            this.radius_squared = radius_squared;

            // ==================================================
            // 三角形を描画
            // ==================================================
            this.draw = function (colorTable) {

                if (colorTable != undefined) {
                    // 色を格納・設定
                    var rgb = colorTable.getColor(this.circle.center);
                    ctx.fillStyle = "rgb(" + rgb.R + ", " + rgb.G + ", " + rgb.B + ")";
                    // パスのリセット・三角形を指定
                    ctx.beginPath();
                    ctx.moveTo(v0.x, v0.y);
                    ctx.lineTo(v1.x, v1.y);
                    ctx.lineTo(v2.x, v2.y);
                    ctx.closePath();
                    // 塗る
                    ctx.fill();
                }

                var drawLine = function (vs, vd) {

                    var lineColor = "rgb(200, 200, 200)";

                    if (4 < colors[colorIndex].length) {
                        var lineRgb = new RGB(colors[colorIndex][4]);
                        lineColor = "rgb(" + lineRgb.R + ", " + lineRgb.G + ", " + lineRgb.B + ")";
                    }


                    // パスのリセット
                    ctx.beginPath();
                    // 線の太さ
                    ctx.lineWidth = 1;
                    // 線の色
                    ctx.strokeStyle = lineColor;
                    // 線を設定
                    ctx.moveTo(vs.x, vs.y);
                    ctx.lineTo(vd.x, vd.y);
                    // 描画
                    ctx.stroke();
                };

                drawLine(this.v0, this.v1);
                drawLine(this.v1, this.v2);
                drawLine(this.v2, this.v0);

            };

            // ==================================================
            // 指定された頂点が外接円の内側にあるかどうかを返す
            // ==================================================
            this.InCircumcircle = function (v) {

                var dx = this.circle.center.x - v.x,
                    dy = this.circle.center.y - v.y,
                    dist_squared = dx * dx + dy * dy;

                return (dist_squared <= this.radius_squared);

            }; // InCircumcircle

            // ==================================================
            // 外接円を描画
            // ==================================================
            this.drawCircle = function () {

                // 外接円の色
                ctx.strokeStyle = "rgb(191, 214, 191)";
                // 外接円を描画
                this.circle.draw();
                // 外接円の中心の色
                ctx.fillStyle = "rgb(191, 214, 191)";
                // 外接円の中心を描画
                this.circle.drawCenter();

            }; // drawCircle


        } // Triangle


        // ==================================================
        // 円
        // ==================================================
        function Circle(center, radius) {

            // 中心座標と半径  
            this.center = center;
            this.radius = radius;

            // ==================================================
            // 円を書く
            // ==================================================
            this.draw = function () {

                ctx.beginPath();
                ctx.arc(this.center.x, this.center.y, this.radius, 0, 360, true);
                ctx.stroke();

            };

            // ==================================================
            // 円の中心を書く
            // ==================================================
            this.drawCenter = function () {

                ctx.beginPath();
                ctx.arc(this.center.x, this.center.y, 2, 0, 360, true);
                ctx.fill();

            };

        } // Circle


        // ==================================================
        // RGB
        // ==================================================
        function RGB(hex) {
            var h = hex.substring(1, 7);
            return {
                R: parseInt(h.substring(0, 2), 16),
                G: parseInt(h.substring(2, 4), 16),
                B: parseInt(h.substring(4, 6), 16)
            }
        } // RGB


        // ==================================================
        // 色テーブル
        // ==================================================
        function ColorTable() {

            var colorTable = [],
                columnW = 20,
                columnH = 15;

            // ==================================================
            // 指定された頂点の色を取得
            // ==================================================
            this.getColor = function (v) {

                if (v == undefined) return new RGB("#000000");

                // 座標を補正
                var adjust = function (p, limit) {

                    var absP = Math.abs(p);
                    if (limit < absP) {
                        return (absP - (limit * Math.floor(absP / limit)));
                    } else {
                        return absP;
                    }

                };

                v.x = adjust(v.x, canDom.width);
                v.y = adjust(v.y, canDom.height);

                for (var i in colorTable) {
                    if (colorTable[i].start.x <= v.x && colorTable[i].end.x >= v.x && colorTable[i].start.y <= v.y && colorTable[i].end.y >= v.y) {
                        return colorTable[i].color;
                    }
                }

                return new RGB("#000000");

            }; // getColor

            // ==================================================
            // 色テーブルを描画(デバッグ用)
            // ==================================================
            this.draw = function () {

                for (var i in colorTable) {

                    ctx.fillStyle = "rgb(" + colorTable[i].color.R + ", " + colorTable[i].color.G + ", " + colorTable[i].color.B + ")";
                    ctx.fillRect(colorTable[i].start.x,
                    colorTable[i].start.y,
                    colorTable[i].end.x - colorTable[i].start.x,
                    colorTable[i].end.y - colorTable[i].start.y);
                }

            }; // draw

            // ==================================================
            // 色テーブルを初期化
            // ==================================================
            function initialize() {

                var x = 0,
                    y = 0;

                for (var i = 0; i < Math.ceil(canDom.width / columnW); i++) {

                    y = 0;
                    for (var j = 0; j < Math.ceil(canDom.height / columnH); j++) {
                        var col = Math.floor(Math.random() * 4);

                        colorTable.push({
                            color: new RGB(colors[colorIndex][col]),
                            start: new Vertex(x, y),
                            end: new Vertex(x + columnW, y + columnH)
                        });

                        y += columnH;
                    }
                    x += columnW;
                }

            } // initialize

            // 初期化
            initialize();

        } // ColorTable


        // ==================================================
        // canvas をクリア
        // ==================================================
        function clearCanvas() {

            ctx.clearRect(0, 0, canDom.width, canDom.height);
            ctx.globalAlpha = 1;

        } // clearCanvas

        // ==================================================
        // 頂点リストを初期化
        // ==================================================
        function initializeVertexList() {

            var vertexList = [];

            // 四隅に頂点を追加
            vertexList.push(new Vertex(0, 0));
            vertexList.push(new Vertex(canDom.width, 0));
            vertexList.push(new Vertex(0, canDom.height));
            vertexList.push(new Vertex(canDom.width, canDom.height));

            // ランダムに頂点を追加(固定)
            for (var i = 0; i < 10; i++) {
                vertexList.push(new Vertex(
                Math.floor(Math.random() * canDom.width),
                Math.floor(Math.random() * canDom.height)));
            }

            // ランダムに頂点を追加(移動)
            for (var j = 0; j < 40; j++) {
                vertexList.push(new Vertex(
                Math.floor(Math.random() * canDom.width),
                Math.floor(Math.random() * canDom.height),
                Math.random() * 0.7 - 0.35,
                Math.random() * 0.7 - 0.35));
            }

            return vertexList;

        } // initializeVertexList

        // ==================================================
        // 頂点リストを更新
        // ==================================================
        function updateVertexList(list) {

            for (var i = 0; i < list.length; i++) {

                // 頂点を更新
                list[i].update();

                // 頂点を描画(デバッグ用)
                //list[i].draw();

            }

        } // updateVertexList

        // ==================================================
        // 指定された座標を包含する円に外接する三角形を取得
        // ==================================================
        function getHugeTriangle(start, end) {

            // start が左上、end が右下になるように補正
            if (end.x < start.x) {
                var xTmp = start.x;
                start.x = end.x;
                end.x = xTmp;
            }
            if (end.y < start.y) {
                var yTmp = start.y;
                start.y = end.y;
                end.y = yTmp;
            }

            // 四角形を描画(デバッグ用)
            //ctx.strokeRect(start.x, start.y, end.x - start.x, end.y - start.y)

            // 渡された座標を包含する円を求める
            var center = new Vertex(((end.x - start.x) / 2.0) + start.x, ((end.y - start.y) / 2.0) + start.y),
                dx = center.x - start.x,
                dy = center.y - start.y,
                radius = Math.sqrt((dx * dx) + (dy * dy));

            // 円を描画(デバッグ用)
            //(new Circle(center, radius)).draw();
            //(new Circle(center, radius)).drawCenter();

            // その円に外接する正三角形を求める
            var x1 = center.x - Math.sqrt(3) * radius,
                y1 = center.y - radius,
                v1 = new Vertex(x1, y1),

                x2 = center.x + Math.sqrt(3) * radius,
                y2 = center.y - radius,
                v2 = new Vertex(x2, y2),

                x3 = center.x,
                y3 = center.y + 2 * radius,
                v3 = new Vertex(x3, y3);

            return new Triangle(v1, v2, v3);

        } // getHugeTriangle

        // ==================================================
        // 三角形のリストを初期化
        // ==================================================
        function initializeTriangleList(vertexList) {

            var triangleList = [];

            // canvas を包含する円に外接する三角形を格納
            triangleList.push(getHugeTriangle(new Vertex(0, 0), new Vertex(canDom.width, canDom.height)));

            // 1つずつ頂点を追加していく
            for (var i = 0; i < vertexList.length; i++) {
                var vertex = vertexList[i];
                AddVertex(vertex, triangleList);
            }

            return triangleList;

        } // initializeTriangleList

        // ==================================================
        // 三角形のリストに頂点を追加
        // ==================================================
        function AddVertex(vertex, triangleList) {

            // エッジリスト
            var edgeList = [];

            for (var i in triangleList) {
                var triangle = triangleList[i];

                // 追加する頂点が外接円の内側にある場合
                if (triangle.InCircumcircle(vertex)) {

                    // エッジに分解
                    edgeList.push(new Edge(triangle.v0, triangle.v1));
                    edgeList.push(new Edge(triangle.v1, triangle.v2));
                    edgeList.push(new Edge(triangle.v2, triangle.v0));

                    // 三角形のリストから削除
                    delete triangleList[i];
                }
            }

            // 分解したエッジの中からユニークなエッジを取得
            // 重複したエッジを除外することで不正な三角形が除外される
            // (ドロネー分割において不正な三角形が重複する特性を利用している)
            edgeList = UniqueEdges(edgeList);

            // ユニークなエッジをもとに三角形を生成
            for (var j in edgeList) {
                var edge = edgeList[j];

                // 追加する頂点とユニークなエッジをもとに新しい三角形を生成
                triangleList.push(new Triangle(edge.v0, edge.v1, vertex));
            }

        } // AddVertex

        // ==================================================
        // ユニークなエッジを取得
        // ==================================================
        function UniqueEdges(edgeList) {

            var uniqueEdges = [];

            for (var i in edgeList) {
                var edge1 = edgeList[i];
                var unique = true;

                for (var j in edgeList) {
                    if (i != j) {
                        var edge2 = edgeList[j];

                        // 重複したエッジの場合
                        if ((edge1.v0 == edge2.v0 && edge1.v1 == edge2.v1) || (edge1.v0 == edge2.v1 && edge1.v1 == edge2.v0)) {
                            unique = false;
                            break;
                        }
                    }
                }

                // ユニークなものだけ格納
                if (unique) {
                    uniqueEdges.push(edge1);
                }
            }

            return uniqueEdges;

        } // UniqueEdges

        // ==================================================
        // 三角形リストを描画
        // ==================================================
        function drawTriangleList(triangleList, colorTable) {

            for (var i in triangleList) {

                // 三角形を描画
                triangleList[i].draw(colorTable);

                // 外接円を描画
                //triangleList[i].drawCircle();

            }

        } // drawTriangleList

        // ==================================================
        // 開始
        // ==================================================
        function init() {

            var colorTable,
            vertexList,
            triangleList;

            // canvas のサイズを指定        
            canDom.width = 400;
            canDom.height = 350;

            // 色テーブルを初期化
            colorTable = new ColorTable();

            // 頂点リストを初期化
            vertexList = initializeVertexList();

            // 一定時間で繰り返す
            setInterval(function () {

                // canvas をクリア
                clearCanvas();

                // ドロネー分割
                triangleList = initializeTriangleList(vertexList);

                // 三角形リストを描画
                drawTriangleList(triangleList, colorTable);

                // 色テーブルを描画(デバッグ用)
                //colorTable.draw();

                // 頂点リストを更新
                updateVertexList(vertexList);

            }, 33);

        } // init

        // 開始
        init();

    })(); // Main


});

前回、canvas にランダムな点を撒いて移動させるところまでやったので、やっとお目当ての Delaunay(ドロネー)分割に入れる。 Delaunay 分割の仕組みについては、素晴らしい記事があったのでそちらを参照されたい。 さて、じゃあさっそくソースコード。 以下、JavaScript だけ。

$(document).ready(function () {

    var SAMPLE = {};

    SAMPLE.Main = (function () {
        
        var canJqObj = $("#can"),
            canDom = document.getElementById('can'),
            ctx = document.getElementById('can').getContext("2d");
        
        // ==================================================
        // 頂点
        // ==================================================
        function Vertex(x, y, vx, vy) {

            this.x = x;
            this.y = y;

            // 固定頂点かどうか(true:固定、false:移動)
            this.isStatic = ((vx == undefined || vy == undefined) ? true : false);
            // X 軸の移動速度
            this.velocityX = ((vx == undefined) ? Math.random() * 0.7 - 0.35 : vx);
            // Y 軸の移動速度
            this.velocityY = ((vy == undefined) ? Math.random() * 0.7 - 0.35 : vy);

            // ==================================================
            // 頂点を描画
            // ==================================================
            this.draw = function () {

                // 固定は黒、移動は赤
                ctx.fillStyle = (this.isStatic ? "rgb(66, 66, 66)" : "rgb(255, 66, 22)");

                ctx.beginPath();
                ctx.arc(this.x, this.y, 2, 0, 360, true);
                ctx.fill();

            };

            // ==================================================
            // 頂点を更新
            // ==================================================
            this.update = function () {

                // 移動する頂点の場合
                if (!this.isStatic) {

                    // canvas の端で跳ね返す(X)
                    if (0 > this.x || canDom.width < this.x) {
                        this.velocityX *= -1;
                    }

                    // canvas の端で跳ね返す(Y)
                    if (0 > this.y || canDom.height < this.y) {
                        this.velocityY *= -1;
                    }

                    // 座標を更新
                    this.x += this.velocityX;
                    this.y += this.velocityY;
                }

            };

        } // Vertex


        // ==================================================
        // エッジ
        // ==================================================
        function Edge(v0, v1) {

            this.v0 = v0;
            this.v1 = v1;

        } // Edge


        // ==================================================
        // 三角形
        // ==================================================
        function Triangle(v0, v1, v2) {

            // 外接円の求め方
            var x1 = v0.x,
                y1 = v0.y,
                x2 = v1.x,
                y2 = v1.y,
                x3 = v2.x,
                y3 = v2.y,
                c = 2.0 * ((x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1)),
                x = ((y3 - y1) * (x2 * x2 - x1 * x1 + y2 * y2 - y1 * y1) + (y1 - y2) * (x3 * x3 - x1 * x1 + y3 * y3 - y1 * y1)) / c,
                y = ((x1 - x3) * (x2 * x2 - x1 * x1 + y2 * y2 - y1 * y1) + (x2 - x1) * (x3 * x3 - x1 * x1 + y3 * y3 - y1 * y1)) / c,
                center = new Vertex(x, y), // 外接円の中心
                dx = center.x - v0.x,
                dy = center.y - v0.y,
                radius_squared = (dx * dx) + (dy * dy),
                radius = Math.sqrt(radius_squared), // 外接円の半径
                circle = new Circle(center, radius);

            this.v0 = v0;
            this.v1 = v1;
            this.v2 = v2;
            this.circle = circle;
            this.radius_squared = radius_squared;

            // ==================================================
            // 三角形を描画
            // ==================================================
            this.draw = function () {

                var drawLine = function (vs, vd) {

                    // パスのリセット
                    ctx.beginPath();
                    // 線の太さ
                    ctx.lineWidth = 1;
                    // 線の色
                    ctx.strokeStyle = "rgb(162, 206, 226)";
                    // 開始位置
                    ctx.moveTo(vs.x, vs.y);
                    // 次の位置
                    ctx.lineTo(vd.x, vd.y);
                    // 描画 
                    ctx.stroke();
                };

                drawLine(this.v0, this.v1);
                drawLine(this.v1, this.v2);
                drawLine(this.v2, this.v0);

            };

            // ==================================================
            // 外接円を描画
            // ==================================================
            this.drawCircle = function () {

                // 外接円の色
                ctx.strokeStyle = "rgb(191, 214, 191)";
                // 外接円を描画
                this.circle.draw();
                // 外接円の中心の色
                ctx.fillStyle = "rgb(191, 214, 191)";
                // 外接円の中心を描画
                this.circle.drawCenter();

            }; // drawCircle

            // ==================================================
            // 指定された頂点が外接円の内側にあるかどうかを返す
            // ==================================================
            this.InCircumcircle = function (v) {

                var dx = this.circle.center.x - v.x,
                    dy = this.circle.center.y - v.y,
                    dist_squared = dx * dx + dy * dy;

                return (dist_squared <= this.radius_squared);

            }; // InCircumcircle


        } // Triangle


        // ==================================================
        // 円
        // ==================================================
        function Circle(center, radius) {

            // 中心座標と半径  
            this.center = center;
            this.radius = radius;

            // ==================================================
            // 円を書く
            // ==================================================
            this.draw = function () {

                ctx.beginPath();
                ctx.arc(this.center.x, this.center.y, this.radius, 0, 360, true);
                ctx.stroke();

            };

            // ==================================================
            // 円の中心を書く
            // ==================================================
            this.drawCenter = function () {

                ctx.beginPath();
                ctx.arc(this.center.x, this.center.y, 2, 0, 360, true);
                ctx.fill();

            };

        } // Circle

        
        // ==================================================
        // canvas をクリア
        // ==================================================
        function clearCanvas() {

            ctx.clearRect(0, 0, canDom.width, canDom.height);
            ctx.globalAlpha = 1;

        } // clearCanvas

        // ==================================================
        // 頂点リストを初期化
        // ==================================================
        function initializeVertexList() {

            var vertexList = [];

            // 四隅に頂点を追加
            vertexList.push(new Vertex(0, 0));
            vertexList.push(new Vertex(canDom.width, 0));
            vertexList.push(new Vertex(0, canDom.height));
            vertexList.push(new Vertex(canDom.width, canDom.height));

            // ランダムに頂点を追加(固定)
            for (var i = 0; i < 10; i++) {
                vertexList.push(new Vertex(
                Math.floor(Math.random() * canDom.width),
                Math.floor(Math.random() * canDom.height)));
            }

            // ランダムに頂点を追加(移動)
            for (var j = 0; j < 10; j++) {
                vertexList.push(new Vertex(
                Math.floor(Math.random() * canDom.width),
                Math.floor(Math.random() * canDom.height),
                Math.random() * 0.7 - 0.35,
                Math.random() * 0.7 - 0.35));
            }

            return vertexList;

        } // initializeVertexList

        // ==================================================
        // 頂点リストを描画
        // ==================================================
        function drawVertexList(list) {

            for (var i = 0; i < list.length; i++) {

                // 頂点を更新
                list[i].update();

                // 頂点を描画
                list[i].draw();

            }

        } // drawVertexList

        // ==================================================
        // 指定された座標を包含する円に外接する三角形を取得
        // ==================================================
        function getHugeTriangle(start, end) {

            // start が左上、end が右下になるように補正
            if (end.x < start.x) {
                var xTmp = start.x;
                start.x = end.x;
                end.x = xTmp;
            }
            if (end.y < start.y) {
                var yTmp = start.y;
                start.y = end.y;
                end.y = yTmp;
            }

            // 四角形を描画
            //ctx.strokeRect(start.x, start.y, end.x - start.x, end.y - start.y)

            // 渡された座標を包含する円を求める
            var center = new Vertex(((end.x - start.x) / 2.0) + start.x, ((end.y - start.y) / 2.0) + start.y),
                dx = center.x - start.x,
                dy = center.y - start.y,
                radius = Math.sqrt((dx * dx) + (dy * dy));

            // 円を描画
            //(new Circle(center, radius)).draw();
            //(new Circle(center, radius)).drawCenter();

            // その円に外接する正三角形を求める
            var x1 = center.x - Math.sqrt(3) * radius,
                y1 = center.y - radius,
                v1 = new Vertex(x1, y1),

                x2 = center.x + Math.sqrt(3) * radius,
                y2 = center.y - radius,
                v2 = new Vertex(x2, y2),

                x3 = center.x,
                y3 = center.y + 2 * radius,
                v3 = new Vertex(x3, y3);

            return new Triangle(v1, v2, v3);

        } // getHugeTriangle

        // ==================================================
        // 三角形のリストを初期化
        // ==================================================
        function initializeTriangleList(vertexList) {

            var triangleList = [];

            // canvas を包含する円に外接する三角形を格納
            triangleList.push(getHugeTriangle(new Vertex(0, 0), new Vertex(canDom.width, canDom.height)));

            // 1つずつ頂点を追加していく
            for (var i = 0; i < vertexList.length; i++) {
                var vertex = vertexList[i];
                AddVertex(vertex, triangleList);
            }

            return triangleList;

        } // initializeTriangleList

        // ==================================================
        // 三角形のリストに頂点を追加
        // ==================================================
        function AddVertex(vertex, triangleList) {

            // エッジリスト
            var edgeList = [];

            for (var i in triangleList) {
                var triangle = triangleList[i];

                // 追加する頂点が外接円の内側にある場合
                if (triangle.InCircumcircle(vertex)) {

                    // エッジに分解
                    edgeList.push(new Edge(triangle.v0, triangle.v1));
                    edgeList.push(new Edge(triangle.v1, triangle.v2));
                    edgeList.push(new Edge(triangle.v2, triangle.v0));

                    // 三角形のリストから削除
                    delete triangleList[i];
                }
            }

            // 分解したエッジの中からユニークなエッジを取得
            // 重複したエッジを除外することで不正な三角形が除外される
            // (ドロネー分割において不正な三角形が重複する特性を利用している)
            edgeList = UniqueEdges(edgeList);

            // ユニークなエッジをもとに三角形を生成
            for (var j in edgeList) {
                var edge = edgeList[j];

                // 追加する頂点とユニークなエッジをもとに新しい三角形を生成
                triangleList.push(new Triangle(edge.v0, edge.v1, vertex));
            }

        } // AddVertex

        // ==================================================
        // ユニークなエッジを取得
        // ==================================================
        function UniqueEdges(edgeList) {

            var uniqueEdges = [];
            for (var i in edgeList) {
                var edge1 = edgeList[i];
                var unique = true;

                for (var j in edgeList) {
                    if (i != j) {
                        var edge2 = edgeList[j];

                        // 重複したエッジの場合
                        if ((edge1.v0 == edge2.v0 && edge1.v1 == edge2.v1) || (edge1.v0 == edge2.v1 && edge1.v1 == edge2.v0)) {
                            unique = false;
                            break;
                        }
                    }
                }

                // ユニークなものだけ格納
                if (unique) {
                    uniqueEdges.push(edge1);
                }
            }

            return uniqueEdges;

        } // UniqueEdges

        // ==================================================
        // 三角形リストを描画
        // ==================================================
        function drawTriangleList(triangleList) {

            for (var i in triangleList) {

                // 三角形を描画
                triangleList[i].draw();

                // 外接円を描画
                triangleList[i].drawCircle();

            }

        } // drawTriangleList

        // ==================================================
        // 開始
        // ==================================================
        function init() {

            var vertexList,
                triangleList;

            // canvas のサイズを指定        
            canDom.width = 400;
            canDom.height = 350;

            // 頂点リストを初期化
            vertexList = initializeVertexList();

            // 一定時間で繰り返す
            setInterval(function () {

                // canvas をクリア
                clearCanvas();

                // ドロネー分割
                triangleList = initializeTriangleList(vertexList);

                // 三角形リストを描画
                drawTriangleList(triangleList);

                // 三角形の要素数をセット
                var count = 0;
                for (var i in triangleList)
                    count++;

                // ※確認用
                $("#triangleListLength").text("triangleList.length : " + triangleList.length);
                $("#triangleCount").text("triangle count : " + count);

                // 頂点リストを描画
                drawVertexList(vertexList);

            }, 33);

        } // init

        // 開始
        init();

    })(); // Main


});

確認用で頂点、三角形、三角形の外接円とその中心が描画されます。分割できた途端満足しちゃったので配列からでっかい三角形も除去してないです。 参考記事「Tercel::Diary: ProcessingでDelaunay分割(実装篇)」とちょっと違うのは三角形の重複判定あたり。エッジを定義して判定する方が個人的にはわかり易かったので参考記事とは別の方法で判定してます。
前回は canvas にランダムな点を描画したけど、今回はその点を移動させてみようと思う。 おおまかな構造は前回からほとんど変わっていない。主にいじった箇所は Vertex あたりか。今回は点が移動するので、移動速度を格納する velocityX, velocityY を追加した。それと動かない点も欲しかったから isStatic も追加。これをもとにその点を動かすかどうかを判定する。velocityX, velocityY, isStatic はすべて Vertex 生成時に初期化する。 各点を移動するために Vertex に update を追加。isStatic が偽になるものは velocityX, velocityY をもとに座標を更新する。update は draw する前にコールする。 今回は点を移動させるので一度だけ描画して終わりってわけにはいかない。描画処理を一定時間で繰り返すために drawVertexList を setInterval で括る。 こんなとこでしょうか。結果は Result から。 以下、JavaScript だけ。

$(document).ready(function () {

    var SAMPLE = {};

    SAMPLE.Main = (function () {

        // 頂点
        function Vertex(x, y, vx, vy) {

            this.x = x;
            this.y = y;

            // 固定頂点かどうか(true:固定、false:移動)
            this.isStatic = ((vx == undefined || vy == undefined) ? true : false);
            // X 軸の移動速度
            this.velocityX = ((vx == undefined) ? Math.random() * 0.7 - 0.35 : vx);
            // Y 軸の移動速度
            this.velocityY = ((vy == undefined) ? Math.random() * 0.7 - 0.35 : vy);

            // 頂点を描画
            this.draw = function () {

                // 固定は黒、移動は赤
                ctx.fillStyle = (this.isStatic ? "rgb(66, 66, 66)" : "rgb(255, 66, 22)");

                ctx.beginPath();
                ctx.arc(this.x, this.y, 2, 0, 360, true);
                ctx.fill();

            };

            // 頂点を更新
            this.update = function () {

                // 移動する頂点の場合
                if (!this.isStatic) {

                    // canvas の端で跳ね返す(X)
                    if (0 > this.x || canDom.width < this.x) {
                        this.velocityX *= -1;
                    }

                    // canvas の端で跳ね返す(Y)
                    if (0 > this.y || canDom.height < this.y) {
                        this.velocityY *= -1;
                    }

                    // 座標を更新
                    this.x += this.velocityX;
                    this.y += this.velocityY;
                }

            };
        }

        var canJqObj = $("#can"),
            canDom = document.getElementById('can'),
            ctx = document.getElementById('can').getContext("2d"),
            vertexList = [];

        // 頂点リストを初期化
        function initializeVertexList(list) {

            // 四隅に頂点を追加
            list.push(new Vertex(0, 0));
            list.push(new Vertex(canDom.width, 0));
            list.push(new Vertex(0, canDom.height));
            list.push(new Vertex(canDom.width, canDom.height));

            // ランダムに頂点を追加(固定)
            for (i = 0; i < 10; i++) {
                list.push(new Vertex(
                Math.floor(Math.random() * canDom.width),
                Math.floor(Math.random() * canDom.height)));
            }

            // ランダムに頂点を追加(移動)
            for (i = 0; i < 10; i++) {
                list.push(new Vertex(
                Math.floor(Math.random() * canDom.width),
                Math.floor(Math.random() * canDom.height),
                Math.random() * 0.7 - 0.35,
                Math.random() * 0.7 - 0.35));
            }

        }

        // canvas をクリア
        function clearCanvas() {

            ctx.clearRect(0, 0, canDom.width, canDom.height);
            ctx.globalAlpha = 1;

        }

        // 描画リストを描画
        function drawVertexList(list) {

            // canvas をクリア
            clearCanvas();

            for (i = 0; i < list.length; i++) {

                // 頂点を更新
                list[i].update();

                // 頂点を描画
                list[i].draw();

            }
        }

        // 開始
        function init() {

            // canvas のサイズを指定        
            canDom.width = 400;
            canDom.height = 350;

            // 頂点リストを初期化
            initializeVertexList(vertexList);

            // 一定時間で繰り返す
            setInterval(function () {

                // 頂点リストを描画
                drawVertexList(vertexList);

            }, 33);
        }

        // 開始
        init();

    })();

});

前回、Delaunay(ドロネー)分割の下準備を行ったけど今回もそれの続き。 内容は前回からほとんど変わっていない。追加したのは initializeVertexList と drawVertexList くらいか。Vertex を配列で格納する変数を定義しておいてあとは initialize で初期化して、draw で描画するといった感じだ。四隅以外の頂点はランダムで生成して push。あとは配列をぐるぐる。 ソースコードは以下となる。 以下、JavaScript だけ。

$(document).ready(function () {

    var SAMPLE = {};

    SAMPLE.Main = (function () {

        // 頂点
        function Vertex(x, y) {
            this.x = x;
            this.y = y;
            
            // 描画
            this.draw = function(){
                
                ctx.beginPath();
                ctx.arc(this.x, this.y, 2, 0, 360, true);
                ctx.fill();
                
            };
        }
        
        var canJqObj = $("#can"),
            canDom = document.getElementById('can'),
            ctx = document.getElementById('can').getContext("2d"),
            vertexList = [];

        // 頂点リストを初期化
        function initializeVertexList(list)
        {
            // 四隅に頂点を追加
            list.push(new Vertex(0, 0));
            list.push(new Vertex(canDom.width, 0));
            list.push(new Vertex(0, canDom.height));
            list.push(new Vertex(canDom.width, canDom.height));
            
            // ランダムに頂点を追加
            for(i = 0; i <= 10; i++)
            {
                list.push(new Vertex(
                    Math.floor(Math.random() * canDom.width),
                    Math.floor(Math.random() * canDom.height)));
            }
        }
        
        // 頂点リストを描画
        function drawVertexList(list)
        {
            for (i = 0; i < list.length; i++)
            {
                list[i].draw();
            }
        }
        
        // 開始
        function init() {

            // canvas のサイズを指定        
            canDom.width = 400;
            canDom.height = 350;

            // 頂点リストを初期化
            initializeVertexList(vertexList);
            
            // 頂点リストを描画
            drawVertexList(vertexList);
        }

        // 開始
        init();

    })();

});

Mar 14, 2014

スクロールさせたいだけなのに、いちいち座標の計算みたいなことをするのは面倒だ。こういった場合はメッセージを飛ばした方が楽。

    Declare Auto Function SendMessage Lib "User32" _
        (ByVal hWnd As IntPtr,
         ByVal uMsg As UInt32,
         ByVal wParam As Int32,
         ByVal lParam As Int32) As Int32

    Const WM_VSCROLL As UInt32 = &H115      ' 縦スクロール
    Const WM_HSCROLL As UInt32 = &H114      ' 横スクロール

    Const SB_LINEUP As UInt32 = 0           ' ↑
    Const SB_LINEDOWN As UInt32 = 1         ' ↓
    Const SB_PAGEUP As UInt32 = 2           ' PageUp
    Const SB_PAGEDOWN As UInt32 = 3         ' PageDown
    Const SB_THUMBPOSITION As UInt32 = 4    ' 絶対位置
    Const SB_THUMTRACK As UInt32 = 5        ' ドラッグ
    Const SB_TOP As UInt32 = 6              ' HOME
    Const SB_BOTTMOM As UInt32 = 7          ' END
    Const SB_ENDSCROLL As UInt32 = 8        ' スクロール終了

    ' 例:ハンドルを指定して縦スクロールの PageUp を飛ばす
    SendMessage(***.Handle, WM_VSCROLL, SB_PAGEUP, 0)
SendMessage
ロックの一覧が見れます。kill する方法はこっちで。
SELECT V$SESSION.SADDR,
  V$SESSION.SID,
  V$SESSION.SERIAL#,
  V$SESSION.USERNAME,
  DBA_OBJECTS.OBJECT_NAME,
  V$SESSION.OSUSER,
  V$SESSION.PROGRAM
FROM V$LOCKED_OBJECT
LEFT JOIN DBA_OBJECTS
ON V$LOCKED_OBJECT.OBJECT_ID = DBA_OBJECTS.OBJECT_ID
LEFT JOIN V$SESSION
ON V$LOCKED_OBJECT.SESSION_ID = V$SESSION.SID
ORDER BY V$SESSION.SID,
  DBA_OBJECTS.OBJECT_NAME
kill する。SID, SERIAL# の確認方法はこっちで。
alter system kill session 'SID, SERIAL#';

Feb 28, 2014

いつも忘れるので。

public T DeepCopy(T target)
{
    object result = null;

    // シリアル化した情報を格納する stream
    using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
    {
        // 指定されたオブジェクトをシリアライズ
        System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = 
            new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
        formatter.Serialize(stream, target);

        // デシリアライズ
        stream.Position = 0;
        result = formatter.Deserialize(stream);
    }

    return (T)result;
}

Feb 26, 2014

『"ファイル名"の保存中にエラーが検出されました。いくつかの機能を削除または修復することにより、ファイルを保存できる場合があります。新しいファイルで修復を実行するには、[継続]をクリックしてください。ファイルの保存を中止するには、[キャンセル]をクリックしてください』 継続しても保存できない。 レジストリの更新で復旧するとのこと。コマンドプロンプトで以下のコマンドをたたく。
regsvr32 c:\windows\System32\MSCOMCTL.OCX
regsvr32, 64 ビット版については以下を参照
注: 64 ビット版の Windows オペレーティング システムには、次の 2 つのバージョンの Regsv32.exe ファイルがあります。
  • 64 ビット版は %systemroot%\System32\regsvr32.exe です。
  • 32 ビット版は %systemroot%\SysWoW64\regsvr32.exe です。
Regsvr32 ツールを使用する方法および Regsvr32 のエラー メッセージをトラブルシューティングする方法
WordPress で個別ページの記事部分を ajax で取得して任意の場所に挿入するコードを書いたのでメモ。(※ jQuery の内容としては WordPress に特化したものではない)流れとしてはこんな感じ。
  • クリックイベントをバインド
  • ajax のリクエスト先 URL を初期化
  • ajax リクエストを行いページ内容を格納
  • ページ全体から目的の部分だけを取得して格納
  • 目的の部分をいったん非表示にしてから挿入
  • アニメーションで表示
コードはこんな感じ。
$(document).ready(function () {

 // クリックイベントをバインド
 $(".hoge").click(function(){
  var url, html, target;
  
  // ajax のリクエスト先 URL を初期化
  url = $(this).find("a.hoge").attr("href");
  
  // ajax リクエストを行いページ内容を格納
  html = $.ajax({
   url: url,
   async: false
  }).responseText;
  
  // ページ全体から目的の部分だけを取得して格納
  target = $(html).find(".fuga");
  
  // 目的の部分をいったん非表示にしてから挿入
  target.css({display: "none", opacity: "toggle"});
  $(this).after(target);
  
  // アニメーションで表示
  target.animate({height: "show", opacity: "toggle"});
 });
 
});
2013-02-27 追記: responseText からそのまま jQuery オブジェクトを生成するような書き方は IE だとダメみたい。(IE9 は動いてる)IE で同じことをやろうと思ったら上のサンプルだと全然だめ。手抜きしすぎ。 なんもないところから jQuery オブジェクトを生成したいときは、

var hoge = $("
");
じゃなくて、

var hoge = $(document.createElement("div"));

こう書く。
jQuery オブジェクトから親要素の jQuery オブジェクトを取得したい。これすぐ忘れる。 以下の例は、クラス "hoge" とマッチする要素の直近の親要素(a)に対して css をセットしている。
$(".hoge").closest("a").css("border", "none");
自身からもっとも近い親要素(a)の jQuery オブジェクトを格納する。
var target = $(this).closest("a");
親要素を選択したいだけなら parent で良い。closest は "もっとも近い親要素" であることがポイント。 parent([expr]) - jQuery 日本語リファレンス closest([expr]) - jQuery 日本語リファレンス
jQuery の toggle と既に表示されている要素(インデックス)の管理。
jQuery でインデックスをとってくる方法。
css からは指定できません。ってことで、html はこんな感じで。

canvas を指定してプロパティにセット。
$(document).ready(function(){
    document.getElementById('can').width = 400;
    document.getElementById('can').height = 350;
});​

Feb 25, 2014

Delaunay(ドロネー)分割の勉強。まずは基本的な描画(線、円)とドロネー分割で必要な外接円の求め方から。 以下、JavaScript だけ。

$(document).ready(function () {

    var SAMPLE = {};

    SAMPLE.Main = (function () {

        // 頂点
        function Vertex(x, y) {
            this.x = x;
            this.y = y;
        }

        // 三角形
        function Triangle(v0, v1, v2) {

            this.v0 = v0;
            this.v1 = v1;
            this.v2 = v2;

            // 三角形を描画
            this.draw = function () {

                var drawLine = function (vs, vd) {
                    // パスのリセット
                    ctx.beginPath();
                    // 線の太さ
                    ctx.lineWidth = 1;
                    // 線の色
                    ctx.strokeStyle = "#454545";
                    // 開始位置
                    ctx.moveTo(vs.x, vs.y);
                    // 次の位置
                    ctx.lineTo(vd.x, vd.y);
                    // 描画 
                    ctx.stroke();
                };

                drawLine(this.v0, this.v1);
                drawLine(this.v1, this.v2);
                drawLine(this.v2, this.v0);

            };

            // 外接円を描画
            this.drawCircle = function () {

                // 外接円の求め方
                var x1 = this.v0.x,
                    y1 = this.v0.y,
                    x2 = this.v1.x,
                    y2 = this.v1.y,
                    x3 = this.v2.x,
                    y3 = this.v2.y,
                    c = 2.0 * ((x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1)),
                    x = ((y3 - y1) * (x2 * x2 - x1 * x1 + y2 * y2 - y1 * y1) + (y1 - y2) * (x3 * x3 - x1 * x1 + y3 * y3 - y1 * y1)) / c,
                    y = ((x1 - x3) * (x2 * x2 - x1 * x1 + y2 * y2 - y1 * y1) + (x2 - x1) * (x3 * x3 - x1 * x1 + y3 * y3 - y1 * y1)) / c,
                    center = new Vertex(x, y),                    // 外接円の中心
                    dx = center.x - v0.x,
                    dy = center.y - v0.y,
                    radius = Math.sqrt((dx * dx) + (dy * dy)),    // 外接円の半径
                    circle = new Circle(center, radius);

                // 外接円を描画
                circle.draw();
                
                // 外接円の中心を描画
                circle.drawCenter();
            };
        }

        // 円
        function Circle(center, radius) {
            
            // 中心座標と半径  
            this.center = center;
            this.radius = radius;

            // 円を書く
            this.draw = function () {
                
                ctx.beginPath();
                ctx.arc(this.center.x, this.center.y, this.radius, 0, 360, true);
                ctx.stroke();
                
            };
            
            // 円の中心を書く
             this.drawCenter = function () {
                
                ctx.beginPath();
                ctx.arc(this.center.x, this.center.y, 2, 0, 360, true);
                ctx.fill();
                
            };

        }

        var canJqObj = $("#can"),
            canDom = document.getElementById('can'),
            ctx = document.getElementById('can').getContext("2d"),
            // 三角形の定義
            triangle = new Triangle(
            new Vertex(100, 120),
            new Vertex(220, 270),
            new Vertex(300, 160));

        // 開始
        function init() {

            // canvas のサイズを指定        
            canDom.width = 400;
            canDom.height = 350;

            // 三角形を描画
            triangle.draw();
            
            // 円を描画
            triangle.drawCircle();
        }

        // 開始
        init();

    })();


});

jQuery でフッタ要素を強引に最下部に固定してみる。定石がわからん。


$(document).ready(function () {

     // 基準の高さを格納
     var bodyBaseH = $('body').height();
     var windowH = 0;
    
     // リサイズ時の css 切り替え
     function ReSize() {

          winH = $(window).height();

          // ウィンドウの方が高い場合フッタを最下部に固定
          if (winH > bodyBaseH)
          {
               $('#footer').css("position", "fixed");
               $('#footer').css("bottom", "0");
          }
          else
          {
               $('#footer').css("position", "relative");
          }
     }
    
     // リサイズイベントにハンドラをバインド
     $(window).resize(function(){
          ReSize();
     });
    
     // 切り替え
     ReSize();
});