Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/77.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Html 如何获得形状的所有坐标';s edge in<;画布>;?_Html_Canvas - Fatal编程技术网

Html 如何获得形状的所有坐标';s edge in<;画布>;?

Html 如何获得形状的所有坐标';s edge in<;画布>;?,html,canvas,Html,Canvas,在我的画布上有一个形状,我需要得到它边缘的所有坐标。形状可以是规则的,也可以是不规则的。您可以使用“行进方块”算法来检测闭合形状的边缘路径: Michael Bostock为其出色的d3可视化工具制作的这张照片很棒: 使用他版本的Marching Squares的关键是定义一个函数,该函数定义了形状内部的像素与形状外部的像素。下面是一个使用.getImageData像素数组(data)获取不透明像素的函数: // This is used by the marching ants a

在我的画布上有一个形状,我需要得到它边缘的所有坐标。形状可以是规则的,也可以是不规则的。

您可以使用“行进方块”算法来检测闭合形状的边缘路径:

Michael Bostock为其出色的d3可视化工具制作的这张照片很棒:

使用他版本的Marching Squares的关键是定义一个函数,该函数定义了形状内部的像素与形状外部的像素。下面是一个使用.getImageData像素数组(
data
)获取不透明像素的函数:

    // This is used by the marching ants algorithm
    // to determine the outline of the non-transparent
    // pixels on the image

    var defineNonTransparent=function(x,y){
        var a=data[(y*cw+x)*4+3];
        return(a>20);
    }
示例代码和演示:


正文{背景色:象牙;}
画布{边框:1px纯红;}
$(函数(){
//行军方块边缘检测
//这是一个用于计算轮廓路径的“行进蚂蚁”算法
(功能(){
//用于计算轮廓路径的d3插件
//许可证:https://github.com/d3/d3-plugins/blob/master/LICENSE
//
//版权所有(c)2012-2014,Michael Bostock
//版权所有。
//
//以源代码和二进制形式重新分发和使用,带或不带
//如果满足以下条件,则允许进行修改:
//*源代码的重新分发必须保留上述版权声明,本
//条件列表和以下免责声明。
//*以二进制形式重新分发必须复制上述版权声明,
//此条件列表和文档中的以下免责声明
//和/或分发时提供的其他材料。
//*迈克尔·博斯托克(Michael Bostock)的名字不得用于支持或推广产品
//未经事先书面许可,从本软件派生。
//本软件由版权所有者和贡献者“按原样”提供任何明示或默示保证,包括但不限于对适销性和特定用途适用性的默示保证,均不予承认。在任何情况下,MICHAEL BOSTOCK均不对任何直接、间接、偶然、特殊、惩戒性或后果性损害负责(包括但不限于替代货物或服务的采购;使用、数据或利润的损失;或业务中断)无论是合同、严格责任还是侵权(包括疏忽或其他)中的任何责任理论造成的因使用本软件而产生的任何后果,即使告知可能发生此类损害。
geom={};
geom.contour=函数(网格,开始){
var s=start | | d3_geom_轮廓起点(网格),//起点
c=[],//等高线多边形
x=s[0],//当前x位置
y=s[1],//当前y位置
dx=0,//下一个x方向
dy=0,//下一个y方向
pdx=NaN,//上一个x方向
pdy=NaN,//上一个y方向
i=0;
做{
//确定行进广场指数
i=0;
如果(网格(x-1,y-1))i+=1;
如果(网格(x,y-1))i+=2;
如果(网格(x-1,y))i+=4;
如果(网格(x,y))i+=8;
//确定下一个方向
如果(i==6){
dx=pdy==-1?-1:1;
dy=0;
}如果(i==9){
dx=0;
dy=pdx==1?-1:1;
}否则{
dx=d3_geom_contourDx[i];
dy=d3_几何体_轮廓dy[i];
} 
//更新等高线多边形
如果(dx!=pdx&&dy!=pdy){
c、 推力([x,y]);
pdx=dx;
pdy=dy;
} 
x+=dx;
y+=dy;
}而(s[0]!=x | | s[1]!=y);
返回c;
}; 
//行进方向查找表
变量d3_geom_contourDx=[1,0,1,1,-1,0,0,0,0,-1,0,0,0,-1,0,-1,NaN],
d3_geom_contourDy=[0,-1,0,0,0,-1,0,0,1,-1,1,0,-1,0,NaN];
函数d3_geom_轮廓起点(网格){
var x=0,
y=0;
//搜索起点;从原点开始
//然后沿着向外扩展的对角线前进
虽然(正确){
如果(网格(x,y)){
返回[x,y];
} 
如果(x==0){
x=y+1;
y=0;
}否则{
x=x-1;
y=y+1;
} 
} 
} 
})();
//////////////////////////////////////////
//画布相关变量
var canvas=document.getElementById(“canvas”);
var ctx=canvas.getContext(“2d”);
var cw=画布宽度;
var ch=画布高度;
//复选框以显示/隐藏原始图像
var$showImage=$(“#showImage”);
$showImage.prop('checked',true);
//用于显示/隐藏路径轮廓的复选框
var$showOutline=$(“#showOutline”);
$showOutline.prop('checked',true);
//定义轮廓路径的点阵列
var点;
//DefineOnTransparent的此图像的像素数据
//要使用的函数
var imgData,数据;
//这是由行军蚂蚁算法使用的
//以确定不透明的轮廓
//图像上的像素
var defineNonTransparent=函数(x,y){
var a=数据[(y*cw+x)*4+3];
返回(a>20);
}
//加载图像
var img=新图像();
img.crossOrigin=“匿名”;
img.onload=函数(){
//画图像
//(这一次是为了获取图像的像素数据
ctx.drawImage(img,canvas.width/2-img.width/2,canvas.height/2-img.height/2);
//获取图像的像素数据
imgData=ctx.getImageData(0,0,canvas.width,canvas.height);
数据=imgData.data;
//称之为行军蚂蚁算法
//获取图像的轮廓路径
//(轮廓=透明像素的外部路径
点=几何轮廓(定义非平移);
ctx.strokeStyle=“红色”;
ctx.线宽=2;
$showImage.change(函数(){redraw();});
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
    body{ background-color: ivory; }
    canvas{border:1px solid red;}
</style>
<script>
$(function(){

// Marching Squares Edge Detection
// this is a "marching ants" algorithm used to calc the outline path
(function() {
    // d3-plugin for calculating outline paths
    // License: https://github.com/d3/d3-plugins/blob/master/LICENSE
    //
    // Copyright (c) 2012-2014, Michael Bostock
    // All rights reserved.
    //
    //  Redistribution and use in source and binary forms, with or without
    //  modification, are permitted provided that the following conditions are met:
    //* Redistributions of source code must retain the above copyright notice, this
    //  list of conditions and the following disclaimer.
    //* Redistributions in binary form must reproduce the above copyright notice,
    //  this list of conditions and the following disclaimer in the documentation
    //  and/or other materials provided with the distribution.
    //* The name Michael Bostock may not be used to endorse or promote products
    //  derived from this software without specific prior written permission.
    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
    geom = {}; 
    geom.contour = function(grid, start) { 
      var s = start || d3_geom_contourStart(grid), // starting point 
          c = [],    // contour polygon 
          x = s[0],  // current x position 
          y = s[1],  // current y position 
          dx = 0,    // next x direction 
          dy = 0,    // next y direction 
          pdx = NaN, // previous x direction 
          pdy = NaN, // previous y direction 
          i = 0; 

      do { 
        // determine marching squares index 
        i = 0; 
        if (grid(x-1, y-1)) i += 1; 
        if (grid(x,   y-1)) i += 2; 
        if (grid(x-1, y  )) i += 4; 
        if (grid(x,   y  )) i += 8; 

        // determine next direction 
        if (i === 6) { 
          dx = pdy === -1 ? -1 : 1; 
          dy = 0; 
        } else if (i === 9) { 
          dx = 0; 
          dy = pdx === 1 ? -1 : 1; 
        } else { 
          dx = d3_geom_contourDx[i]; 
          dy = d3_geom_contourDy[i]; 
        } 

        // update contour polygon 
        if (dx != pdx && dy != pdy) { 
          c.push([x, y]); 
          pdx = dx; 
          pdy = dy; 
        } 

        x += dx; 
        y += dy; 
      } while (s[0] != x || s[1] != y); 

      return c; 
    }; 

    // lookup tables for marching directions 
    var d3_geom_contourDx = [1, 0, 1, 1,-1, 0,-1, 1,0, 0,0,0,-1, 0,-1,NaN], 
        d3_geom_contourDy = [0,-1, 0, 0, 0,-1, 0, 0,1,-1,1,1, 0,-1, 0,NaN]; 

    function d3_geom_contourStart(grid) { 
      var x = 0, 
          y = 0; 

      // search for a starting point; begin at origin 
      // and proceed along outward-expanding diagonals 
      while (true) { 
        if (grid(x,y)) { 
          return [x,y]; 
        } 
        if (x === 0) { 
          x = y + 1; 
          y = 0; 
        } else { 
          x = x - 1; 
          y = y + 1; 
        } 
      } 
    } 

    })();


    //////////////////////////////////////////

    // canvas related variables
    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");
    var cw=canvas.width;
    var ch=canvas.height;

    // checkbox to show/hide the original image
    var $showImage=$("#showImage");
    $showImage.prop('checked', true);

    // checkbox to show/hide the path outline
    var $showOutline=$("#showOutline");
    $showOutline.prop('checked', true);

    // an array of points that defines the outline path
    var points;

    // pixel data of this image for the defineNonTransparent 
    // function to use
    var imgData,data;

    // This is used by the marching ants algorithm
    // to determine the outline of the non-transparent
    // pixels on the image
    var defineNonTransparent=function(x,y){
        var a=data[(y*cw+x)*4+3];
        return(a>20);
    }

    // load the image
    var img=new Image();
    img.crossOrigin="anonymous";
    img.onload=function(){

        // draw the image
        // (this time to grab the image's pixel data
        ctx.drawImage(img,canvas.width/2-img.width/2,canvas.height/2-img.height/2);

        // grab the image's pixel data
        imgData=ctx.getImageData(0,0,canvas.width,canvas.height);
        data=imgData.data;

        // call the marching ants algorithm
        // to get the outline path of the image
        // (outline=outside path of transparent pixels
        points=geom.contour(defineNonTransparent);

        ctx.strokeStyle="red";
        ctx.lineWidth=2;

        $showImage.change(function(){ redraw(); });

        $showOutline.change(function(){ redraw(); });

        redraw();

    }
    img.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/sun.png";

    // redraw the canvas
    // user determines if original-image or outline path or both are visible
    function redraw(){

        // clear the canvas
        ctx.clearRect(0,0,canvas.width,canvas.height);

        // draw the image
        if($showImage.is(':checked')){
            ctx.drawImage(img,canvas.width/2-img.width/2,canvas.height/2-img.height/2);
        }

        // draw the path (consisting of connected points)
        if($showOutline.is(':checked')){
            // draw outline path
            ctx.beginPath();
            ctx.moveTo(points[0][0],points[0][1]);
            for(var i=1;i<points.length;i++){
                var point=points[i];
                ctx.lineTo(point[0],point[1]);
            }
            ctx.closePath();
            ctx.stroke();
        }

    }

}); // end $(function(){});
</script>
</head>
<body>
    <input type="checkbox" id="showImage" />Show Image<br>
    <input type="checkbox" id="showOutline" />Show Outline Path<br>
    <canvas id="canvas" width=300 height=450></canvas>    </body>
</html>