【问题标题】:Vertices with indexArray doesn't connect triangles properly带有 indexArray 的顶点不能正确连接三角形
【发布时间】:2021-02-12 07:23:32
【问题描述】:

我正在尝试在 p5.js 中创建一种“多边形抽屉”。 我的意图是在开始时对三个顶点中的一个随机三角形进行处理,并且用户可以使用鼠标添加三角形,这些三角形会自动连接到 mouseCursor 中最近的两个顶点。 这一切都很好,但有时当我开始通过单击添加新顶点时(鼠标上的当前向量被推送到顶点数组并且三角形/索引数组得到更新),绘制了一个使用不同顶点的三角形,不是最接近的,次接近的和鼠标光标向量。

我有两个顶点和三角形数组(后面的函数作为索引数组):

let vertices = [];
let triangles = [];

在全球范围内,我跟踪顶点数组的最近和第二近的索引:

let closest;
let secondClosest;

我首先创建一个随机三角形。我将每个顶点的索引推送到三角形数组并再次推送第一个以完成三角形:

function createRandomTriangle(){
  for(i = 0; i < 3; i++){
   let vert = createVector(random(0, width),random(0, height));
    vertices.push(vert);
    triangles.push(i);
  }
  triangles.push(0);
}

在我的绘图函数中,我首先通过遍历 triangles 数组并从 vertices 数组中的向量等效项绘制线来绘制每个三角形。

然后我计算哪两个顶点最接近鼠标光标并更新我的全局变量。

作为最后一步,我从鼠标光标绘制三角形作为某种“指南”。

function draw() {
  background(255);

  for(i = 0; i < triangles.length-1; i++){
    line(vertices[triangles[i]].x, vertices[triangles[i]].y,vertices[triangles[i+1]].x, vertices[triangles[i+1]].y);
  }

  let mouseVector = createVector(mouseX, mouseY);

  let distances = [];
  for(i = 0; i < vertices.length; i++){
    distances.push(mouseVector.dist(vertices[i]));
  }
  closest = distances.indexOf(Math.min( ...distances ));    
  distances[closest] = width + height;
  secondClosest = distances.indexOf(Math.min( ...distances ));

  line(mouseVector.x, mouseVector.y, vertices[closest].x, vertices[closest].y);
  line(mouseVector.x, mouseVector.y, vertices[secondClosest].x, vertices[secondClosest].y);
  line(vertices[closest].x, vertices[closest].y, vertices[secondClosest].x, vertices[secondClosest].y); 
    }

现在这个函数可能是造成伤害的那个,但我不知道为什么。

一旦用户点击,鼠标光标向量get被推送到顶点数组,他的索引首先被推送到三角形数组,然后是最近的索引,然后是第二最近的索引,然后再次是鼠标光标索引。

function mouseClicked() { 
    let latestIndex = vertices.push(createVector(mouseX, mouseY)) - 1;
    triangles.push(latestIndex);
    triangles.push(closest);
    triangles.push(secondClosest);
    triangles.push(latestIndex);
} 

有时这种方法效果很好,有时会突然出现一个新行。

我不明白为什么。

您可以在此处测试 p5.js 草图:https://editor.p5js.org/etlam/sketches/4SAhIydAC

【问题讨论】:

  • 您的三角形数组基于您绘制它们的方式,每次创建一个新三角形时添加 4 个点。但是,当您绘制它们时,您不会以 4 个为一组对其进行迭代,这意味着您的绘制方法将三角形的第一个(因此也是第四个)点连接到下一个三角形的第一个点。您可以通过将if (i % 4 != 3) 放在line() 命令之前快速解决此问题。更好的解决方案是为每个三角形创建一个包含三个点的数组并将其推送到三角形数组,然后使用嵌套循环来绘制它们。
  • let distanceBetween2Points = Math.sqrt(Math.pow(x_coord_1-x_coord_2, 2)+Math.pow(y_coord_1-y_coord_2, 2));
  • @Chris G:有道理!我是个哑巴。非常感谢!
  • 为什么不喜欢ctx.lineTo(x, y); ctx.closePath()
  • @z1on Delaunay triangulation 看起来与您想要实现的目标相似

标签: javascript indexing processing p5.js vertex


【解决方案1】:

这是一个关于如何绘制多边形的非常基本的示例。我真的建议创建一个 StateMaker,这样您就可以跟踪所有内容,但这比我现在愿意介绍的要多。

//<![CDATA[
/* js/external.js */ 
let doc, htm, bod, nav, M, I, mobile, S, Q;
addEventListener('load', ()=>{
doc = document; htm = doc.documentElement; bod = doc.body; nav = navigator; M = tag=>doc.createElement(tag); I = id=>doc.getElementById(id);
mobile = nav.userAgent.match(/Mobi/i) ? true : false;
S = (selector, within)=>{
  let w = within || doc;
  return w.querySelector(selector);
}
Q = (selector, within)=>{
  let w = within || doc;
  return w.querySelectorAll(selector);
}
rand = (min, max)=>{
  let mn = min, mx = max;
  if(mx === undefined){
    mx = mn; mn = 0;
  }
  return mn+Math.floor(Math.random()*(mx-mn+1));
}
// tiny library above magic below - can put on another page using a load Event (besides // end load line)
const can = I('can'), canB = can.getBoundingClientRect();
const canW = can.width = canB.width, canH = can.height = canB.height;
const ctx = can.getContext('2d'), points = [];
ctx.lineWidth = '1px'; ctx.lineStyle = '#000'; ctx.fillStyle = '#700';
function polyFun(e){
  let b = can.getBoundingClientRect();
  ctx.clearRect(0, 0, canW, canH);
  points.push([e.clientX-b.left, e.clientY-b.top]);
  ctx.beginPath(); ctx.moveTo(...points[0]);
  for(let i=1,l=points.length; i<l; i++){
    ctx.lineTo(...points[i]);
  }
  ctx.fill(); ctx.stroke(); ctx.closePath();
}
if(mobile){
  ontouchstart = e=>{
    polyFun(e.touches[0]);
  }
}
else{
  onmousedown = polyFun;
}
}); // end load
//]]>
/* css/external.css */
*{
  box-sizing:border-box; font-size:0; padding:0; margin:0;
}
html,body,#can{
  width:100%; height:100%;
}
#can{
  cursor:pointer;
}
<!DOCTYPE html>
<html lang='en'>
  <head>
    <meta charset='UTF-8' /><meta name='viewport' content='width=device-width, height=device-height, initial-scale:1, user-scalable=no' />
    <title>Title Here</title>
    <link type='text/css' rel='stylesheet' href='css/external.css' />
    <script src='js/external.js'></script>
  </head>
<body>
  <canvas id='can'></canvas>
</body>
</html>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-31
    • 2014-08-21
    • 2010-12-21
    • 1970-01-01
    • 1970-01-01
    • 2014-10-03
    • 2021-03-11
    • 2015-05-09
    相关资源
    最近更新 更多