Reputation: 61
I'm trying to create a sort of "polygon drawer" in p5.js. My intented behaviour is that a random triangle out of three vertices gets ctreated at start and the user can use his mouse to add triangles, which automatically connect to the two closest vertices from the mouseCursor. This allw orks fine, but sometimes when I start adding the new vertice by clicking (the current vector at the mouse get's pushed to the array of vertices and the triangle / index array get' updated), a triangle get's drawn which uses a different vertice, not the closest, second closest and the mouse cursor vector.
I have two arrays for the vertices and triangles (the later functions as an index array):
let vertices = [];
let triangles = [];
Globally I track the closest and second closest index of the vertices array:
let closest;
let secondClosest;
I start by creating a random triangle. I push each vertex' index to the triangle array and push the first one once again to complete the triangle:
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);
}
In my draw function I first draw every triangle by going through the triangles array and drawing lines from their vector equivalents in the vertices array.
I then calculate which two vertices are closest to the mouse cursor and update my globals.
As the last step I draw the trianlge from the mouse cursor as some sort of "guide".
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);
}
Now this function is probably the one causing harm, but I can't figure out why.
Once the user clicks, the mouse cursor vector get's pushed to the array of vertices, his index is pushed first to the triangles array, then the closest index, then the second closest index, then the mouse cursor index again.
function mouseClicked() {
let latestIndex = vertices.push(createVector(mouseX, mouseY)) - 1;
triangles.push(latestIndex);
triangles.push(closest);
triangles.push(secondClosest);
triangles.push(latestIndex);
}
Sometimes this method works fine and sometimes a new line suddenly appears.
I can't comprehend exactly why.
You can test thje p5.js sketch here: https://editor.p5js.org/etlam/sketches/4SAhIydAC
Upvotes: 1
Views: 93
Reputation: 10617
Here is a very basic example of how you might go about drawing a polygon. I really recommend creating a StateMaker, so you can keep track of everything, but that's more than I'm willing to go into right now.
//<![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>
Upvotes: 1