gpt4 book ai didi

javascript - 使用二维点图查找轮廓

转载 作者:行者123 更新时间:2023-11-30 11:43:54 25 4
gpt4 key购买 nike

我有一个 x,y 坐标数组,它们在 Canvas 上绘制时创建一个形状,但是当我缩放图像时,我有一个“连接点”版本,因为每个点之间都有空格。

我尝试在每组坐标之间画一条线,但由于它没有遵循“轮廓”,所以导致了锯齿形绘图。

我怎样才能创建大纲?

编辑:我需要获取形状的“矢量”并将其传递给网络应用程序中的线条绘制功能。我无法直接访问 Canvas 。

var canvas = document.getElementById("myCanvas");
var canvasWidth = canvas.width;
var canvasHeight = canvas.height;
var ctx = canvas.getContext("2d");
var canvasData = ctx.getImageData(0, 0, canvasWidth, canvasHeight);

// That's how you define the value of a pixel //
function drawPixel (x, y, r=0, g=0, b=0, a=255) {
var index = (x + y * canvasWidth) * 4;

canvasData.data[index + 0] = r;
canvasData.data[index + 1] = g;
canvasData.data[index + 2] = b;
canvasData.data[index + 3] = a;
}

// That's how you update the canvas, so that your //
// modification are taken in consideration //
function updateCanvas() {
ctx.putImageData(canvasData, 0, 0);
}

var i;
var coords = [74,16,76,16,78,16,80,16,82,16,84,16,86,16,88,16,90,16,92,16,70,18,72,18,74,18,76,18,78,18,80,18,82,18,84,18,86,18,88,18,90,18,92,18,94,18,68,20,70,20,72,20,74,20,76,20,78,20,80,20,82,20,84,20,86,20,88,20,90,20,92,20,94,20,96,20,98,20,66,22,68,22,70,22,72,22,74,22,76,22,88,22,90,22,92,22,94,22,96,22,98,22,64,24,66,24,68,24,70,24,72,24,74,24,92,24,94,24,96,24,98,24,100,24,64,26,66,26,68,26,70,26,72,26,94,26,96,26,98,26,100,26,64,28,66,28,68,28,70,28,94,28,96,28,98,28,100,28,102,28,62,30,64,30,66,30,68,30,96,30,98,30,100,30,102,30,62,32,64,32,66,32,68,32,96,32,98,32,100,32,102,32,62,34,64,34,66,34,68,34,96,34,98,34,100,34,102,34,62,36,64,36,66,36,68,36,96,36,98,36,100,36,102,36,62,38,64,38,66,38,68,38,98,38,100,38,102,38,62,40,64,40,66,40,68,40,96,40,98,40,100,40,102,40,62,42,64,42,66,42,68,42,96,42,98,42,100,42,102,42,62,44,64,44,66,44,68,44,96,44,98,44,100,44,102,44,64,46,66,46,68,46,70,46,94,46,96,46,98,46,100,46,102,46,64,48,66,48,68,48,70,48,72,48,94,48,96,48,98,48,100,48,64,50,66,50,68,50,70,50,72,50,74,50,92,50,94,50,96,50,98,50,100,50,66,52,68,52,70,52,72,52,74,52,76,52,88,52,90,52,92,52,94,52,96,52,98,52,68,54,70,54,72,54,74,54,76,54,78,54,80,54,82,54,84,54,86,54,88,54,90,54,92,54,94,54,96,54,98,54,70,56,72,56,74,56,76,56,78,56,80,56,82,56,84,56,86,56,88,56,90,56,92,56,94,56,74,58,76,58,78,58,80,58,82,58,84,58,86,58,88,58,90,58,92,58];

for (i=0; i<coords.length; i+=2) {
drawPixel(coords[i],coords[i+1]);
}


updateCanvas();
<!DOCTYPE html>
<html>
<body>

<canvas id="myCanvas" width="300" height="150" style="border:1px solid #d3d3d3;"></canvas>

</body>
</html>

最佳答案

您很幸运,您的积分排列整齐。但是,如果您有其他点不是这样,那么您将遇到一些问题。

有些函数可以处理更多的随机点,但它们非常复杂,我还没有在网上找到任何可用的函数。

对于您给出的点,我使用了一种在一组点周围找到凸包的方法。 (称为格雷厄姆扫描)。我给它你的分数,它返回外面的路径。我不得不修改它以通过在 x 和 y 中排序来处理共线点,因此它只能处理高度高达 10000 像素的点云。

复杂的位是中心的孔。

为此,我创建了一组点,这些点在您的形状上创建了一个由点组成的矩形(称为 mask )。然后我删除坐标中蒙版中的所有点。我删除了上一步计算的船体外的所有点。

现在掩码只是船体内的点,而不是原始坐标的一部分。然后我围绕它创建一个船体并反转它的方向。

我现在有两条路径,一条用于外部,一条用于内部,如果将它们一起渲染,则可以根据需要绘制形状。

Warning. This only works for coordinates that are similar you what you have presented. Only for convex shapes. You can adapt it but it is a brute force method that will not work well past the current constraints.

哦,当我添加演示时,我刚刚注意到内圈已经出来了。没有办法修复它,所以我不会删除它,而是暂时保留这个答案。它可能有帮助,也可能没有帮助。

你看了之后我会把它删掉

    // create and add a canvas
var canvas = document.createElement("canvas");
canvas.width = canvas.height = 256;
var ctx = canvas.getContext("2d");
document.body.appendChild(canvas);

// clear it
ctx.setTransform(1,0,0,1,0,0)
ctx.clearRect(0,0,canvas.width,canvas.height)

//==============================================================================
// Many functions requiered for the example
//==============================================================================

// returns a convex hull around a set of points
// using Graham Scan. See wiki for details
// points in the form [[x,y],[x,y],...]
// returns the convex hull as a list of referances to points
function boundingHull(points) {
var pLen, p, s, hull, i, p1, j, len;
var isRight = (a, b, c) => 0 <= (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);
points.sort((a, b) => (a[0] + a[1] / 10000) - (b[0] + b[1] / 10000) );
pLen = points.length - 1;
p = points;
s = [];
hull = [];
s.push(p[0],p[1]);
for(j = 0; j < 2; j ++){
for (i = 2; i <= pLen; i++) {
p1 = j === 0 ? p[i] : p[pLen - i];
len = s.length;
while (len > 1 && !isRight(s[len - 2], s[len - 1], p1)) {
s.pop();
len = s.length;
}
s.push(p1);
}
hull.push(...s);
s.length = 0;
s.push(p[pLen],p[pLen-1]);
}
return hull;
}

// gets the center of a set of point
function findCenter(verts){
var x = 0;
var y = 0;
verts.forEach(v => { x += v[0]; y += v[1]; })
x /= verts.length;
y /= verts.length;
return {x,y};
}
// gets the extent of points
function findExtent(verts){
var minx = Infinity;
var maxx = -Infinity;
var miny = Infinity;
var maxy = -Infinity;
var y = 0;
verts.forEach(v => {
minx = v[0] < minx ? v[0] : minx;
miny = v[1] < miny ? v[1] : miny;
maxx = v[0] > maxx ? v[0] : maxx;
maxy = v[1] > maxy ? v[1] : maxy;
});
return {
top : miny,
left : minx,
width : maxx- minx,
height : maxy - miny,
}
}

// moves points
function translate(verts,by){
verts.forEach(v => { v[0] += by.x; v[1] += by.y; })
}

// converts flat array of points into an array of points
// [x,y,x,y,x,y,... ] into [[x,y],[x,y],[x,y],... ]
function formatVerts(verts) {
var v = [];
for (var i = 0; i < verts.length; i += 2) {
v.push([verts[i], verts[i + 1]]);
}
return v;
}
// returns true if point x,y is inside hull
function isInsideHull(x,y,hull){
var s,ss;
var vx,vy;
var px,py;

for(var i = 1; i < hull.length; i ++){
vx = hull[i][0] - hull[i-1][0]
vy = hull[i][1] - hull[i-1][1]
px = x - hull[i-1][0]
py = y - hull[i-1][1]
s = Math.sign(vx * py - vy * px);
s = s === 0 ? 1 : s;
if(ss === undefined){
ss = s;
}else if(ss !== s){
return false;
}
}
return true;
}
// returns only points inside the hull
function removePointsOutsideHull(points,hull){
return points.filter(p => isInsideHull(p[0],p[1],hull))
}
// returns only points that are not in hull
function removePointsFromPoints(hull,points){
return points.filter(p => !hull.some(h => h[0] === p[0] && h[1] === p[1]));
}
// creates a set of points covering extent and spaced by xS,yS
function createOrderedPoints(extent,xS,yS){
var a = [];
for(var y = extent.top; y <= extent.top + extent.height; y += yS ){
for(var x = extent.left; x <= extent.left + extent.width; x += xS ){
a.push([x,y]);
}
}
return a;
}
// display scale
var scale = 5;
ctx.setTransform(scale,0,0,scale,canvas.width /2 ,canvas.height / 2)

//==============================================================================
// drawing functions
//==============================================================================
// draws an array of points
function drawPoints(points, col = "black",size = 3){
var s = ((size - 1) / 2) / scale;
size = size / scale;
ctx.strokeStyle = col;
points.forEach(p => ctx.strokeRect(p[0]-s,p[1]-s,size,size))
}
// sets out a path from an array of points
function definePath(path){
path.forEach((p,i) =>{
if(i === 0){
ctx.moveTo(p[0],p[1]);
}else{
ctx.lineTo(p[0],p[1]);
}
});
}
// draws a path using stroke
function drawPath(path, col = "black", lineWidth = 1){
ctx.strokeStyle = col;
ctx.lineWidth = lineWidth/scale;
ctx.lineJoin = "round"
ctx.beginPath();
definePath(path)
ctx.stroke();
}
// draws a set of paths as a shape
function fillShape(paths, col = "black"){
ctx.fillStyle = col;
ctx.beginPath();
paths.forEach(definePath);
ctx.fill();
}

// define the points
var coords = [74, 16, 76, 16, 78, 16, 80, 16, 82, 16, 84, 16, 86, 16, 88, 16, 90, 16, 92, 16, 70, 18, 72, 18, 74, 18, 76, 18, 78, 18, 80, 18, 82, 18, 84, 18, 86, 18, 88, 18, 90, 18, 92, 18, 94, 18, 68, 20, 70, 20, 72, 20, 74, 20, 76, 20, 78, 20, 80, 20, 82, 20, 84, 20, 86, 20, 88, 20, 90, 20, 92, 20, 94, 20, 96, 20, 98, 20, 66, 22, 68, 22, 70, 22, 72, 22, 74, 22, 76, 22, 88, 22, 90, 22, 92, 22, 94, 22, 96, 22, 98, 22, 64, 24, 66, 24, 68, 24, 70, 24, 72, 24, 74, 24, 92, 24, 94, 24, 96, 24, 98, 24, 100, 24, 64, 26, 66, 26, 68, 26, 70, 26, 72, 26, 94, 26, 96, 26, 98, 26, 100, 26, 64, 28, 66, 28, 68, 28, 70, 28, 94, 28, 96, 28, 98, 28, 100, 28, 102, 28, 62, 30, 64, 30, 66, 30, 68, 30, 96, 30, 98, 30, 100, 30, 102, 30, 62, 32, 64, 32, 66, 32, 68, 32, 96, 32, 98, 32, 100, 32, 102, 32, 62, 34, 64, 34, 66, 34, 68, 34, 96, 34, 98, 34, 100, 34, 102, 34, 62, 36, 64, 36, 66, 36, 68, 36, 96, 36, 98, 36, 100, 36, 102, 36, 62, 38, 64, 38, 66, 38, 68, 38, 98, 38, 100, 38, 102, 38, 62, 40, 64, 40, 66, 40, 68, 40, 96, 40, 98, 40, 100, 40, 102, 40, 62, 42, 64, 42, 66, 42, 68, 42, 96, 42, 98, 42, 100, 42, 102, 42, 62, 44, 64, 44, 66, 44, 68, 44, 96, 44, 98, 44, 100, 44, 102, 44, 64, 46, 66, 46, 68, 46, 70, 46, 94, 46, 96, 46, 98, 46, 100, 46, 102, 46, 64, 48, 66, 48, 68, 48, 70, 48, 72, 48, 94, 48, 96, 48, 98, 48, 100, 48, 64, 50, 66, 50, 68, 50, 70, 50, 72, 50, 74, 50, 92, 50, 94, 50, 96, 50, 98, 50, 100, 50, 66, 52, 68, 52, 70, 52, 72, 52, 74, 52, 76, 52, 88, 52, 90, 52, 92, 52, 94, 52, 96, 52, 98, 52, 68, 54, 70, 54, 72, 54, 74, 54, 76, 54, 78, 54, 80, 54, 82, 54, 84, 54, 86, 54, 88, 54, 90, 54, 92, 54, 94, 54, 96, 54, 98, 54, 70, 56, 72, 56, 74, 56, 76, 56, 78, 56, 80, 56, 82, 56, 84, 56, 86, 56, 88, 56, 90, 56, 92, 56, 94, 56, 74, 58, 76, 58, 78, 58, 80, 58, 82, 58, 84, 58, 86, 58, 88, 58, 90, 58, 92, 58];
// convert to correct format
coords = formatVerts(coords);
// find the center
var center = findCenter(coords);
// find the extent
var extent = findExtent(coords);
// create masking points from extent
var mask = createOrderedPoints(extent,2,2);
// remove points that are the in the coords list
mask = removePointsFromPoints(coords,mask);
// center the mask
translate(mask,{x : - center.x, y : -center.y})
// center the coords
translate(coords,{x : - center.x, y : -center.y})
// create a convex hull
var hull = boundingHull(coords);
// draw the hull
drawPath(hull);
// and the poitns
drawPoints(coords);
// remove all points from the mask outside the hull
mask = removePointsOutsideHull(mask,hull);
// draw remaining points in the mask
//drawPoints(mask,"red");
// create a hull around the mask
var hullInside = boundingHull(mask);
// reverse its direction
hullInside = hullInside.reverse();
// draw the mask points
drawPath(hullInside,"red");
// draw the shape
fillShape([hull,hullInside],"rgba(0,255,0,0.5)");

关于javascript - 使用二维点图查找轮廓,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41654535/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com