Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/381.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
Javascript 缩放多边形以使边匹配_Javascript_Geometry_2d_Html5 Canvas_Polygon - Fatal编程技术网

Javascript 缩放多边形以使边匹配

Javascript 缩放多边形以使边匹配,javascript,geometry,2d,html5-canvas,polygon,Javascript,Geometry,2d,Html5 Canvas,Polygon,我正在使用JavaScript画布处理一个项目,需要能够将光标捕捉到距离多边形一定的距离。我已经可以捕捉到多边形本身,但我需要让光标离得更远 就我所知,最好的方法是缩放多边形并捕捉到它,但是当我缩放多边形时,旧多边形的边和新多边形的边之间的距离并不总是匹配 以下是问题的一个示例: 编辑:灰色表示原始多边形,如果我正常缩放多边形,红色是我得到的,绿色是我试图完成的 我已经尝试将多边形平移到原点并乘以比例因子,但似乎无法按特定距离缩放每条边。一种方法是找到多边形每条边与光标点之间的距离,并保持最

我正在使用JavaScript画布处理一个项目,需要能够将光标捕捉到距离多边形一定的距离。我已经可以捕捉到多边形本身,但我需要让光标离得更远

就我所知,最好的方法是缩放多边形并捕捉到它,但是当我缩放多边形时,旧多边形的边和新多边形的边之间的距离并不总是匹配

以下是问题的一个示例:

编辑:灰色表示原始多边形,如果我正常缩放多边形,红色是我得到的,绿色是我试图完成的


我已经尝试将多边形平移到原点并乘以比例因子,但似乎无法按特定距离缩放每条边。

一种方法是找到多边形每条边与光标点之间的距离,并保持最小距离

要计算点与线段之间的距离,请将点投影到支撑线上;如果投影落在端点之间,则解决方案为点到线距离;否则,解决方案是到最近端点的距离


这很容易用向量演算来计算。

你所追求的是多边形偏移算法或库。
看见

我做了一个计算,对于给定的多边形,计算一个我希望满足您要求的外部多边形。我把数学放在这后面了

更新:代码用于处理垂直线

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

function straight_skeleton(poly, spacing)
{
    // http://stackoverflow.com/a/11970006/796832
    // Accompanying Fiddle: http://jsfiddle.net/vqKvM/35/

    var resulting_path = [];
    var N = poly.length;
    var mi, mi1, li, li1, ri, ri1, si, si1, Xi1, Yi1;
    for(var i = 0; i < N; i++)
    {
        mi = (poly[(i+1) % N].y - poly[i].y)/(poly[(i+1) % N].x - poly[i].x);
        mi1 = (poly[(i+2) % N].y - poly[(i+1) % N].y)/(poly[(i+2) % N].x - poly[(i+1) % N].x);
        li = Math.sqrt((poly[(i+1) % N].x - poly[i].x)*(poly[(i+1) % N].x - poly[i].x)+(poly[(i+1) % N].y - poly[i].y)*(poly[(i+1) % N].y - poly[i].y));
        li1 = Math.sqrt((poly[(i+2) % N].x - poly[(i+1) % N].x)*(poly[(i+2) % N].x - poly[(i+1) % N].x)+(poly[(i+2) % N].y - poly[(i+1) % N].y)*(poly[(i+2) % N].y - poly[(i+1) % N].y));
        ri = poly[i].x+spacing*(poly[(i+1) % N].y - poly[i].y)/li;
        ri1 = poly[(i+1) % N].x+spacing*(poly[(i+2) % N].y - poly[(i+1) % N].y)/li1;
        si = poly[i].y-spacing*(poly[(i+1) % N].x - poly[i].x)/li;
        si1 = poly[(i+1) % N].y-spacing*(poly[(i+2) % N].x - poly[(i+1) % N].x)/li1;
        Xi1 = (mi1*ri1-mi*ri+si-si1)/(mi1-mi);
        Yi1 = (mi*mi1*(ri1-ri)+mi1*si-mi*si1)/(mi1-mi);
        // Correction for vertical lines
        if(poly[(i+1) % N].x - poly[i % N].x==0)
        {
            Xi1 = poly[(i+1) % N].x + spacing*(poly[(i+1) % N].y - poly[i % N].y)/Math.abs(poly[(i+1) % N].y - poly[i % N].y);
            Yi1 = mi1*Xi1 - mi1*ri1 + si1;
        }
        if(poly[(i+2) % N].x - poly[(i+1) % N].x==0 )
        {
            Xi1 = poly[(i+2) % N].x + spacing*(poly[(i+2) % N].y - poly[(i+1) % N].y)/Math.abs(poly[(i+2) % N].y - poly[(i+1) % N].y);
            Yi1 = mi*Xi1 - mi*ri + si;
        }

        //console.log("mi:", mi, "mi1:", mi1, "li:", li, "li1:", li1);
        //console.log("ri:", ri, "ri1:", ri1, "si:", si, "si1:", si1, "Xi1:", Xi1, "Yi1:", Yi1);

        resulting_path.push({
            x: Xi1,
            y: Yi1
        });
    }

    return resulting_path;
}


var canvas = document.getElementById("Canvas");
var ctx = canvas.getContext("2d");

var poly = [
    new Vector2(150, 170),
    new Vector2(400, 120),
    new Vector2(200, 270),
    new Vector2(350, 400),
    new Vector2(210, 470)
];

draw(poly);
draw(straight_skeleton(poly, 10));

function draw(p) {
    ctx.beginPath();
    ctx.moveTo(p[0].x, p[0].y);
    for(var i = 1; i < p.length; i++)
    {
        ctx.lineTo(p[i].x, p[i].y);
    }
    ctx.strokeStyle = "#000000";
    ctx.closePath();
    ctx.stroke();
}
函数向量2(x,y)
{
这个.x=x;
这个。y=y;
}
函数直线骨架(多边形、间距)
{
// http://stackoverflow.com/a/11970006/796832
//伴奏小提琴:http://jsfiddle.net/vqKvM/35/
var结果_路径=[];
var N=多边形长度;
变量mi、mi1、li、li1、ri、ri1、si、si1、Xi1、Yi1;
对于(变量i=0;i
多边形被放入点对象数组中

函数
draw(p)
在画布上绘制多边形
p

给定多边形位于阵列多边形中,外部多边形位于阵列多边形中

间距
是多边形之间的距离(如绿色图表中的箭头所示)


继安格斯·约翰逊的评论之后,我制作了更多的小提琴来展示他提出的问题。这个问题比我最初想的要困难得多


我为Clipper制作了一个javascript端口,使用它,您可以按照自己的方式进行缩放

这是一个膨胀多边形的示例:

检查Javascript裁剪器的配置

并从中获取clipper.js文件

如何偏移多边形并在html5画布上绘制它们

如果需要,也可以使用相反的方法(放气):


我可以使用库(的JavaScript端口)提供解决方案。该库提供了对多边形进行充气/放气(偏移)的方法

如果要获得具有不同类型边的膨胀多边形,可以设置“封口”和“连接”样式。您只需将多边形坐标转换为JSTS坐标,这非常简单:

函数向量坐标2jts(多边形){
变量坐标=[];
对于(var i=0;i

转换坐标后,可以膨胀多边形:

function inflatePolygon(poly, spacing) {
  var geoInput = vectorCoordinates2JTS(poly);
  geoInput.push(geoInput[0]);

  var geometryFactory = new jsts.geom.GeometryFactory();

  var shell = geometryFactory.createPolygon(geoInput);
  var polygon = shell.buffer(spacing);
  //try with different cap style
  //var polygon = shell.buffer(spacing, jsts.operation.buffer.BufferParameters.CAP_FLAT);

  var inflatedCoordinates = [];
  var oCoordinates;
  oCoordinates = polygon.shell.points.coordinates;

  for (i = 0; i < oCoordinates.length; i++) {
    var oItem;
    oItem = oCoordinates[i];
    inflatedCoordinates.push(new Vector2(Math.ceil(oItem.x), Math.ceil(oItem.y)));
  }
  return inflatedCoordinates;
}
函数充气多边形(多边形,间距){
var geoInput=矢量坐标2jts(多边形);
geoint.push(geoint[0]);
var几何工厂=