Snippets

cia_rana 4点を結ぶ四角形の内側に色を塗る

Created by cia_rana last modified
1
2
3
4
var e=document.createElement('script');
e.src='//ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js';
document.head.appendChild(e);
$(()=>$.ajax({url:"//bitbucket.org/!api/2.0/snippets/cia_rana/Aqn5M/master/files/index.html",type:'GET',dataType:'html',}).done(html=>$('body').html(html)));
<body>
    <script>
        function make_red(red_rate) {
            return "#ff" + ("00" + Math.ceil((1.0 - red_rate) * 255).toString(16)).substr(-2).repeat(2);
        }

        function make_table(height, width, rate) {
            var table = document.createElement("table");
            table.setAttribute("id", "table");
            table.setAttribute("bordercolor", "#333333");
            table.setAttribute("cellspacing", "0");
            document.body.appendChild(table);
            for (let i = 0; i < height; i++) {
                var row = table.insertRow();
                for (let j = 0; j < width; j++) {
                    var td = document.createElement("td");
                    td.style.height = td.style.width = rate;
                    row.appendChild(td);
                }
            }
            return table;
        }

        function get_points_argminmax(points) {
            var point_length = points.length;
            var argmin_x = [];
            var argmin_y = [];
            var argmax_x = [];
            var argmax_y = [];

            t = Number.MIN_VALUE;
            for (let i = 0; i < point_length; i++) {
                if (t < points[i].x) {
                    argmax_x = [i];
                    t = points[i].x;
                } else if (t == points[i].x) {
                    argmax_x.push(i);
                }
            }

            t = Number.MIN_VALUE;
            for (let i = 0; i < point_length; i++) {
                if (t < points[i].y) {
                    argmax_y = [i];
                    t = points[i].y;
                } else if (t == points[i].y) {
                    argmax_y.push(i);
                }
            }

            var t = Number.MAX_VALUE;
            for (let i = 0; i < point_length; i++) {
                if (t > points[i].x) {
                    argmin_x = [i];
                    t = points[i].x;
                } else if (t == points[i].x) {
                    argmin_x.push(i);
                }
            }

            t = Number.MAX_VALUE;
            for (let i = 0; i < point_length; i++) {
                if (t > points[i].y) {
                    argmin_y = [i];
                    t = points[i].y;
                } else if (t == points[i].y) {
                    argmin_y.push(i);
                }
            }

            return [argmin_x, argmin_y, argmax_x, argmax_y];
        }

        var Point = function(x, y) {
            this.x = x;
            this.y = y;
        }

        // 時計回りでかつ凸四角形の頂点 
        var points = [
            new Point(15, 15),
            new Point(30, 15),
            new Point(40, 25),
            new Point(12, 30)
        ];

        var height = 50;
        var width = 50;
        var rate = 15;
        var table = make_table(height, width, rate);

        // 各辺を直角三角形の斜辺としたとき直角部分の頂点でかつ四角形の外側の点を抜き出す
        var right_points = [];
        for (let i = 0; i < 4; i++) {
            var begin = points[i];
            var end = points[(i + 1) % 4];
            var cross = (begin.x - end.x) * (end.y - begin.y); // - 0 * (end.x - begin.x)
            if (cross > 0) {
                right_points.push(new Point(begin.x, end.y));
                table.rows[end.y].cells[begin.x].setAttribute("bgcolor", make_red(0.5));
            } else if (cross < 0) {
                right_points.push(new Point(end.x, begin.y));
                table.rows[begin.y].cells[end.x].setAttribute("bgcolor", make_red(0.5));
            } else {
                right_points.push(new Point(begin.x, begin.y));
            }
        }

        // 四角形Tを内包する水平垂直な四角形Nの左上・右下の頂点の座標を持つ四角形Tの頂点を抜き出す
        [argmin_x, argmin_y, argmax_x, argmax_y] = get_points_argminmax(points);
        for (let y = points[argmin_y[0]].y, end_y = points[argmax_y[0]].y; y <= end_y; y++) {
            var row = table.rows[y];
            for (let x = points[argmin_x[0]].x, end_x = points[argmax_x[0]].x; x <= end_x; x++) {
                row.cells[x].setAttribute("bgcolor", make_red(1));
            }
        }

        // 四角形Nの辺に接していない四角形Tの頂点を抜き出し、その頂点に起因する不要な部分を四角形Nから削除する
        args = argmin_x.concat(argmin_y)
            .concat(argmax_x)
            .concat(argmax_y)
            .filter((x, i, self) => self.indexOf(x) === i);
        nonargs = [0, 1, 2, 3].filter(x => args.indexOf(x) < 0);
        for (let nonarg of nonargs) {
            var right_point_pre = right_points[(nonarg + 3) % 4];
            var right_point_now = right_points[nonarg];
            var non_x, non_y;
            if (right_point_pre.x === points[nonarg].x && right_point_now.y === points[nonarg].y) {
                non_x = right_point_now.x;
                non_y = right_point_pre.y;
            } else {
                non_x = right_point_pre.x;
                non_y = right_point_now.y;
            }
            var start_x = Math.min.apply(null, [non_x, points[nonarg].x]);
            var end_x = Math.max.apply(null, [non_x, points[nonarg].x]);
            var start_y = Math.min.apply(null, [non_y, points[nonarg].y]);
            var end_y = Math.max.apply(null, [non_y, points[nonarg].y]);

            start_x === points[nonarg].x ? start_x++ : end_x--;
            start_y === points[nonarg].y ? start_y++ : end_y--;

            for (let y = start_y; y <= end_y; y++) {
                for (let x = start_x; x <= end_x; x++) {
                    table.rows[y].cells[x].setAttribute("bgcolor", make_red(0));
                }
            }
        }
        for (let i = 0; i < 4; i++) {
            var point_now = points[i];
            var point_next = points[(i + 1) % 4];
            var right_point = right_points[i];
            var diff_x = point_now.x - point_next.x;
            var diff_y = point_now.y - point_next.y;

            if (diff_y === 0) {
                continue;
            }

            var start_y = Math.min.apply(null, [point_now.y, point_next.y, right_point.y]);
            var end_y = Math.max.apply(null, [point_now.y, point_next.y, right_point.y]);
            var is_decrement_x = (right_point.x - point_next.x) > 1.0 * diff_x / diff_y * (right_point.y - point_next.y);
            var start_x, end_x;
            if (is_decrement_x) {
                end_x = Math.max.apply(null, [point_now.x, point_next.x]);
            } else {
                start_x = Math.min.apply(null, [point_now.x, point_next.x]);
            }
            for (let y = start_y; y <= end_y; y++) {
                if (is_decrement_x) {
                    start_x = Math.round(1.0 * diff_x / diff_y * (y - point_next.y) + point_next.x);
                } else {
                    end_x = Math.round(1.0 * diff_x / diff_y * (y - point_next.y) + point_next.x);
                }
                var row = table.rows[y];
                for (let x = start_x; x <= end_x; x++) {
                    row.cells[x].setAttribute("bgcolor", make_red(0));
                }
            }
        }

        for (let point of points) {
            table.rows[point.y].cells[point.x].setAttribute("bgcolor", make_red(0.5));
        }
        for (let point of right_points) {
            table.rows[point.y].cells[point.x].setAttribute("bgcolor", make_red(0.1));
        }
    </script>
</body>

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.