调整多边形上的线位置

Adjusting lines positions on polygon

我正在使用 FabricJS 生成具有 6 个点的多边形

var polygon = new fabric.Polygon([
  new fabric.Point(150, 50),
  new fabric.Point(250, 50),
  new fabric.Point(250, 150),
  new fabric.Point(150, 150),
  new fabric.Point(50, 250),
]);

在每个点上我都需要一条线,所以我遍历点并成功添加线:

return new fabric.Line([p.x, p.y, fromX, fromY], {
  stroke: colors[i],
  strokeWidth: 10,
  hasBorders: true,
  strokeDashArray: [20, 5]
});

此代码使用我想要的彩色线条成功生成了多边形:

现在的问题是我想调整线条的位置,例如我需要将红线粘在多边形的顶部,绿色的我需要它的一半在多边形内部,蓝色的距离多边形 5%,等等

在搜索时我发现 Check if Point Is Inside A Polygon 并尝试了那些给出不同结果的函数,所以我有两个函数,isinPolygonFirstisinPolygonSecond,它们基本上是在检查我的观点是否正确在多边形内。我想如果我能知道如果我的点在多边形内我可以添加一些值,例如如果点是 [20,20 并且如果它在多边形内我可以增加到 [21,21] 并重新检查它是否是。我正在发布调试信息(在下面的代码片段中需要移动多边形框才能看到调试消息):

// function to check if line exists in polygon
function isinPolygonFirst(points, longitude_x, latitude_y) {
  vertices_y = new Array();
  vertices_x = new Array();
  var r = 0;
  var i = 0;
  var j = 0;
  var c = 0;
  var point = 0;

  for (r = 0; r < points.length; r++) {
    vertices_y.push(points[r].y);
    vertices_x.push(points[r].x);
  }
  points_polygon = vertices_x.length;
  for (i = 0, j = points_polygon; i < points_polygon; j = i++) {
    point = i;
    if (point == points_polygon)
      point = 0;
    if (((vertices_y[point] > latitude_y != (vertices_y[j] > latitude_y)) && (longitude_x < (vertices_x[j] - vertices_x[point]) * (latitude_y - vertices_y[point]) / (vertices_y[j] - vertices_y[point]) + vertices_x[point])))
      c = !c;
  }
  return c;
}
// other function to check if line exist in polygon 

function isinPolygonSecond(points, x, y) {

  cornersX = new Array();
  cornersY = new Array();

  for (r = 0; r < points.length; r++) {
    cornersX.push(points[r].x);
    cornersY.push(points[r].y);
  }

  var i, j = cornersX.length - 1;
  var odd = false;

  var pX = cornersX;
  var pY = cornersY;

  for (i = 0; i < cornersX.length; i++) {
    if ((pY[i] < y && pY[j] >= y || pY[j] < y && pY[i] >= y) &&
      (pX[i] <= x || pX[j] <= x)) {
      odd ^= (pX[i] + (y - pY[i]) * (pX[j] - pX[i]) / (pY[j] - pY[i])) < x;
    }

    j = i;
  }

  return odd;
}

var canvas = new fabric.Canvas("c", {
  selection: false
});

var points = [];

var polygon = new fabric.Polygon([
  new fabric.Point(150, 50),
  new fabric.Point(250, 50),
  new fabric.Point(250, 150),
  new fabric.Point(150, 150),
  new fabric.Point(50, 250),
]);

polygon.on("modified", function() {
  //document.getElementById("p").innerHTML = JSON.stringify(this)+ "<br>";
  var matrix = this.calcTransformMatrix();
  var transformedPoints = this.get("points")
    .map(function(p) {
      return new fabric.Point(
        p.x - polygon.pathOffset.x,
        p.y - polygon.pathOffset.y);
    })
    .map(function(p) {
      return fabric.util.transformPoint(p, matrix);
    });
  var circles = transformedPoints.map(function(p) {
    return new fabric.Circle({
      left: p.x,
      top: p.y,
      radius: 3,
      fill: "red",
      originX: "center",
      originY: "center",
      hasControls: false,
      hasBorders: false,
      selectable: false
    });
  });
  //Lines Colors
  var colors = ['red', 'green', 'blue', 'violet', 'teal', 'brown'];
  //I need these distances from the polygon, where is negative value it should go inside polygon
  var LinesDistances = [10, -5, -20, 0, 20, 40];
  
  var lines = transformedPoints.map(function(p, i) {
    var po = (i < polygon.points.length) ? i + 1 : 0;

    if (typeof transformedPoints[po] === 'undefined')
      po = 0;

    var fromX = transformedPoints[po].x;
    var fromY = transformedPoints[po].y;
    var isinPolygon = isinPolygonFirst(transformedPoints, fromX, fromY);
    var isinPolygon2 = isinPolygonSecond(transformedPoints, fromX, fromY);

    var debug = '';
    debug += 'fromX:' + fromX;
    debug += ' ,fromY :' + fromY;
    debug += ' ,isinPolygon:' + isinPolygon;
    debug += ' ,isinPolygonSecond:' + isinPolygon2;

    document.getElementById("p").innerHTML += '<p style="color:#fff;background:' + colors[i] + '"> ' + debug + "</p>";

    return new fabric.Line([p.x, p.y, fromX, fromY], {
      stroke: colors[i],
      strokeWidth: 10,
      hasBorders: true,
      strokeDashArray: [20, 5]
    });
  });
  this.canvas.clear().add(this).add.apply(this.canvas, lines).add.apply(this.canvas, circles).setActiveObject(this).renderAll();
  polygon.set({
    opacity: 0.5
  });
  polygon.sendToBack();
});

canvas.add(polygon).renderAll();
canvas {
  border: 1px solid;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.2/fabric.min.js"></script>

<div id="p"></div>
<canvas id="c" width="600" height="400"></canvas>

我不确定我要采用的方法是否正确,我想根据需要在多边形周围动态地设置线的距离。

我需要与多边形的这些距离,负值应该在多边形内部

  var LinesDistances = [10, -5, -20, 0, 20, 40];

这是fiddle和代码。在 https://jsfiddle.net/DivMaster/0e34Lnyx/211/

有什么帮助吗?谢谢 <3

我能够使用 https://github.com/davidfig/intersects

中提供的 Intersects 库解决它

我计算了线的中点并对 x/y 个点执行了 plus/minus 操作以查看点是否位于多边形中

pointPolygon(x1, y1, points)