如何解决带有 indexArray 的顶点不能正确连接三角形
我正在尝试在 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);
}
在我的绘制函数中,我首先通过遍历三角形数组并从顶点数组中的等价向量绘制线条来绘制每个三角形。
然后我计算哪两个顶点最接近鼠标光标并更新我的全局变量。
作为最后一步,我从鼠标光标绘制三角形作为某种“指南”。
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,vertices[secondClosest].x,vertices[secondClosest].y);
line(vertices[closest].x,vertices[closest].y,vertices[secondClosest].y);
}
一旦用户点击,鼠标光标向量就会被推送到顶点数组,他的索引首先被推送到三角形数组,然后是最近的索引,然后是第二个最近的索引,然后再次是鼠标光标索引。
>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
解决方法
这是一个非常基本的示例,说明如何绘制多边形。我真的建议创建一个 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,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>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。