我目前正在使用Js进行投影,就我而言,我需要找到一种从随机点创建多边形的好方法。我不需要格雷厄姆或包装算法。确实,我需要将所有点都连接起来,并且多边形必须不与自身交叉。经过几次搜索,我没有发现任何令人满意的东西。
第一张照片是我想要的东西,第二张照片是我真正不想要的东西。所以我想知道是否有任何算法,是否可以讨论一个想法?
谢谢大家
答案 0 :(得分:2)
您可以:
确定一些好的出发点,而不必是给定的要点之一。使用一些启发式。例如,给定点的“质心”可能是一个有用的选择。但是,在凸包内的任何点的选择都会产生一个具有不相交边的多边形。根据选择,多边形可能会变少或变“光滑”。
将给定点的坐标转换为极坐标,其中第一步中选择的点是原点(0,0)。
按点的极坐标对它们进行排序:首先按极角,然后按半径(或实际上是使用平方根函数忽略的半径的平方)。
使用此顺序绘制多边形。
这是一个交互式代码段中的实现:
function squaredPolar(point, centre) {
return [
Math.atan2(point[1]-centre[1], point[0]-centre[0]),
(point[0]-centre[0])**2 + (point[1]-centre[1])**2 // Square of distance
];
}
// Main algorithm:
function polySort(points) {
// Get "centre of mass"
let centre = [points.reduce((sum, p) => sum + p[0], 0) / points.length,
points.reduce((sum, p) => sum + p[1], 0) / points.length];
// Sort by polar angle and distance, centered at this centre of mass.
for (let point of points) point.push(...squaredPolar(point, centre));
points.sort((a,b) => a[2] - b[2] || a[3] - b[3]);
// Throw away the temporary polar coordinates
for (let point of points) point.length -= 2;
}
let points = [];
// I/O management
let canvas = document.querySelector("canvas");
let ctx = canvas.getContext("2d");
function draw(points) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (!points.length) return;
for (let [x, y] of points) {
ctx.beginPath();
ctx.arc(x, y, 3, 0, 2 * Math.PI, true);
ctx.fill();
}
ctx.beginPath();
ctx.moveTo(...points[0]);
for (let [x, y] of points.slice(1)) ctx.lineTo(x, y);
ctx.closePath();
ctx.stroke();
}
canvas.onclick = function (e) {
let x = e.clientX - this.offsetLeft;
let y = e.clientY - this.offsetTop;
let match = points.findIndex(([x0, y0]) => Math.abs(x0-x) + Math.abs(y0-y) <= 6);
if (match < 0) points.push([x, y]);
else points.splice(match, 1); // delete point when user clicks near it.
polySort(points);
draw(points);
};
canvas { border: 1px solid }
Click to draw points. Polygon will be drawn in real-time:<br>
<canvas></canvas>