¿Cómo puedo conectar dos puntos usando una cadena de pequeñas elipses en lugar de la función stock line() en p5.js?
Estoy tratando de crear una función más 'artística' para reemplazar la función stock line() en p5.js. Para lograr esto, quiero escribir una función en la que, dados dos puntos (x, y) y (x1, y1), se dibujen densa y consistentemente pequeños círculos a lo largo de la línea que conecta los dos puntos.
Traté de escribir una función que primero encuentre todos los puntos x e y posibles y luego use un condicional para dibujar una elipse solo si la pendiente entre i y j y (x1, y1) coincide con la pendiente dada por (x, y) y (x1) , y1).
Esto solo da el resultado deseado si (x, y) y (x1, y1) tienen una pendiente de 0, 1 o indefinida; los espacios entre puntos cambian dramáticamente con cualquier otra pendiente. No puedo entender cómo obtener puntos colocados de manera consistente a lo largo de cualquier línea que ingrese.
Mi función es la siguiente:
function customLine(x, y, x1, y1) { for (var i = x; i >= x && i <= x1; i ++) { for (var j = y; j >= y && j <= y1; j ++) { if ((j - y) / (i - x) == (y1 - y) / (x1 - x)) { fill(0); circle(i, j, 5); } } } }También adjunté una imagen que muestra que obtengo el efecto deseado para valores de pendiente de 0, indefinido o 1, pero no cuando la pendiente es una fracción: salida del código anterior, que ilustra el problema
¿Cómo puedo arreglar mi función? ¿O hay alguna manera completamente más fácil de hacer esto? ¡Muchas gracias!
Creo que estás buscando lerp (interpolación lineal) entre dos puntos. Por ejemplo,
let anchor; function setup() { createCanvas(innerWidth, innerHeight); noLoop(); anchor = createVector(innerWidth / 2, innerHeight / 2); } function draw() { drawDottedLine(anchor, createVector(mouseX, mouseY)); } function mouseMoved() { clear(); drawDottedLine(anchor, createVector(mouseX, mouseY)); } const drawDottedLine = (p1, p2) => lerpLine(p1, p2).forEach(({x, y}) => circle(x, y, 10)) ; const lerpLine = (p1, p2, steps = 10) => [...Array(steps)] .map((_, i) => p5.Vector.lerp(p1, p2, norm(i, 0, steps))) ; <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.js"></script>Si está buscando que el espaciado permanezca consistente y use una cantidad variable de puntos, puede pasar la distancia entre los dos puntos como la cantidad de pasos:
let anchor; let mouse; function setup() { createCanvas(innerWidth, innerHeight); noLoop(); anchor = createVector(innerWidth / 2, innerHeight / 2); mouse = createVector(0, 0); } function draw() { drawDottedLine(anchor, mouse, anchor.dist(mouse) / 16); } function mouseMoved() { clear(); mouse.x = mouseX; mouse.y = mouseY; drawDottedLine(anchor, mouse, floor(anchor.dist(mouse) / 16)); } const drawDottedLine = (p1, p2, steps) => lerpLine(p1, p2, steps).forEach(({x, y}) => circle(x, y, 10)) ; const lerpLine = (p1, p2, steps = 10) => [...Array(steps)] .map((_, i) => p5.Vector.lerp(p1, p2, norm(i, 0, steps))) ; <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.js"></script>O agregue discretizando:
let anchor; let mouse; function setup() { createCanvas(innerWidth, innerHeight); noLoop(); anchor = createVector(innerWidth / 2, innerHeight / 2); mouse = createVector(0, 0); } function mouseMoved() { clear(); const spacing = 10; mouse.x = floor(mouseX / spacing) * spacing; mouse.y = floor(mouseY / spacing) * spacing; const steps = floor(anchor.dist(mouse) / spacing); drawDottedLine(anchor, mouse, steps); } const drawDottedLine = (p1, p2, steps) => lerpLine(p1, p2, steps).forEach(({x, y}) => circle(x, y, 10)) ; const lerpLine = (p1, p2, steps = 10) => [...Array(steps)] .map((_, i) => p5.Vector.lerp(p1, p2, norm(i, 0, steps))) ; <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.js"></script>Creo que la forma más fácil aquí es usar algunos vectores y trigonometría, intente esto:
function setup() { createCanvas(windowWidth, windowHeight); v = createVector(); } function draw() { background(255); customLine(width / 2, height / 2, mouseX, mouseY); } function customLine(x, y, x1, y1) { vx = x1 - x; vy = y1 - y; for (let i = 0; i < v.mag(); i++) { fill(0).circle(x + i * cos(v.heading()), y + i * sin(v.heading()), 5); } } <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.js"></script>