找出点的密集区域,javascript实现,html5 canvas效果图

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
    <style type="text/css">
        html, body {
            margin: 0;
            padding: 0;
            border: none;
            width: 100%;
            height: 100%;
        }
    </style>
    <script type="text/javascript">
        onload = function () {
            demoCanvas.height = document.body.clientHeight - paramsPanel.clientHeight;
            demoCanvas.width = document.body.clientWidth;
        }

    </script>
</head>
<body>
    <div id="paramsPanel">
        <label for="radius">radius</label><input id="radius" type="range" value="5" max="111" min="1" />
        <label for="density">density</label><input id="density" type="range" value="5" max="111" min="1" />
        <label for="areaRange">areaRange</label><input id="areaRange" type="range" value="32" max="111" min="1" />
    </div>
    <canvas id="demoCanvas"></canvas>
    <script type="text/javascript">
        onkeydown = function (e) {
            switch (e.keyCode) {
                case 49:
                    radius.focus();
                    break;
                case 50:
                    density.focus();
                    break;
                case 51:
                    areaRange.focus();
                    break;
            }
        };
        function dropDots() {
            var ctx = demoCanvas.getContext("2d");
            var ps = [];
            function drop(e) {
                ctx.beginPath();
                ctx.arc(e.x, e.y, .5, 0, Math.PI * 2);
                ps.push([e.x, e.y]);
                ctx.fillStyle = "#000";
                ctx.fill();
            }
            demoCanvas.onmousedown = function (e) {
                demoCanvas.getContext("2d").clearRect(0, 0, 12344, 12344);
                ps = [];
                drop(e);
                addEventListener("mousemove", drop);
            };
            onmouseup = onblur = function () {
                if (!ps.length) {
                    return;
                }
                removeEventListener("mousemove", drop);
                var radius = parseFloat(document.getElementById("radius").value);
                var density = parseInt(document.getElementById("density").value);
                var areaRange = parseInt(document.getElementById("areaRange").value);
                var areas = getAreas(ps, radius, density, areaRange);
                for (var i = 0; i < areas.length; i++) {
                    var e = areas[i][0][0];
                    ctx.beginPath();
                    ctx.arc(e[0], e[1], areaRange / 2, 0, Math.PI * 2);
                    ctx.strokeStyle = "#00a";
                    ctx.stroke();
                    ctx.closePath();
                }
            }
        }
        dropDots();
        function getAreas(ps, radius, density, areaRange) {
            var vps = [];//所有符合条件的点与附近点集,格式为[point,[points]]
            for (var i = 0; i < ps.length; i++) {
                var nps = [];//遍历附近的点,找出附近点的点集
                for (var j = 0; j < ps.length; j++) {//
                    if (i === j) {
                        continue;
                    }
                    if (xy2(ps[i], ps[j]) > radius) {
                        continue;
                    }
                    nps.push(ps[j]);
                }
                if (nps.length > density) {//检查附近的点的密度
                    vps.push([ps[i], nps]);
                }
            }
            var idxs = [];
            for (var i = 0; i < vps.length; i++) {//生成所有符合条件的点集的坐标集
                idxs.push(i);
            }
            vps.sort(function (np0, np1) {//附近点集
                return np1[1].length - np0[1].length;
            });
            var areas = [];//返回值
            while (idxs.length) {
                var nps0 = vps[idxs[0]];
                var g = [nps0];
                var new_idxs = [];//不符合条件点集,如有元素将重新开始判断
                for (var i = 1; i < idxs.length; i++) {
                    var idxi = idxs[i];
                    var npsi = vps[idxi];
                    if (xy2(nps0[0], npsi[0]) > areaRange * areaRange) {
                        new_idxs.push(idxi);
                    } else {
                        g.push(npsi);//一个区域
                    }
                }
                g.sort(function (g0, g1) {//找出附近点集数量最大的点
                    return g1[1].length - g0[1].length;
                });
                areas.push(g);
                idxs = new_idxs;//不符合条件点集,如存在将重新开始判断
            }
            return areas;
        }
        function xy2(p0, p1) {//算距离
            return (p0[0] - p1[0]) * (p0[0] - p1[0]) + (p0[1] - p1[1]) * (p0[1] - p1[1]);
        }
    </script>
</body>
</html>

 

posted @ 2017-01-18 17:51  大胡子毛绒老头  阅读(412)  评论(0编辑  收藏  举报