Diagrama de la resistencia de fluidos alrededor de un avión
La fricción también se produce cuando un cuerpo pasa a través de un líquido o un gas. Esta fuerza tiene muchos nombres diferentes, pero todos significan lo mismo: fuerza viscosa, fuerza de arrastre, resistencia del fluido. Mientras que el resultado es, en última instancia, el mismo que en nuestros ejemplos anteriores de fricción (el objeto se frena), la manera en que calculamos una fuerza de arrastre será ligeramente diferente. Echemos un vistazo a la fórmula:
Ahora vamos a desglozar esto y ver lo que realmente necesitamos para una simulación eficaz en ProcessingJS, haciendo nosotros mismos una fórmula mucho más simple en el proceso.
  • F, start subscript, d, end subscript se refiere a la fuerza de arrastre, el vector que en última instancia queremos calcular y pasarle a nuestra función applyForce().
  • -1/2 es una constante: -0.5. Esta es bastante irrelevante en términos de nuestro mundo de ProcessingJS, ya que estaremos inventando valores para otras constantes de todos modos. Sin embargo, el hecho de que sea negativa es importante, ya que nos dice que la fuerza apunta en la dirección opuesta de la velocidad (igual que la fricción).
  • rho es la letra griega rho y se refiere a la densidad del líquido, algo de lo que no tenemos que preocuparnos. Podemos simplificar el problema y considerar que tiene un valor constante de 1.
  • v se refiere a la velocidad del objeto que se está moviendo. Bien, ¡esta la tenemos! La rapidez del objeto es la magnitud del vector de velocidad: velocity.magnitude(). Y v, start superscript, 2, end superscript solamente significa v al cuadrado o v, times, v.
  • A se refiere a la superficie frontal del objeto que está empujando a través del líquido (o gas). Un Lamborghini aerodinámico, por ejemplo, experimentará menos resistencia al aire que un Volvo cuadrado. Sin embargo, para una simulación básica, podemos considerar nuestro objeto esférico e ignorar este elemento.
  • C, start subscript, d, end subscript es el coeficiente de arrastre, exactamente igual que el coeficiente de fricción (ρ). Esta es una constante que determinaremos con base en si queremos que la fuerza de arrastre sea fuerte o débil.
  • v^ \hat{v} ¿Te resulta familiar? Debería. Esto se refiere al vector unitario de velocidad, es decir, velocity.normalize(). Igual que con la fricción, el arrastre es una fuerza que apunta en la dirección opuesta a la velocidad.
Ya que analizamos cada uno de estos componentes y determinado lo que necesitamos para una simulación sencilla, podemos reducir nuestra fórmula a:
Fórmula simplificada: F_drag = ||v ^ 2|| * c_d * v - 1
o:
// Parte 1 de nuestra fórmula (magnitud): v^2 * Cd
var c = 0.1;
var speed = v.mag();
var dragMagnitude = c * speed * speed;

// Parte 2 de nuestra fórmula (dirección): vector unitario v * -1 
var drag = velocity.get();
drag.normalize();
drag.mult(-1);

// ¡Magnitud y dirección juntas!
drag.mult(dragMagnitude);
Vamos a implementar esta fuerza en nuestro tipo de objeto Mover con una adición. Cuando escribimos nuestro ejemplo de fricción, la fuerza de fricción siempre estaba presente. Siempre que un objeto se estaba moviendo, la fricción lo frenaba. Aquí, vamos a introducir un elemento al entorno: un “líquido” por el cual los objetos Mover atraviesan. El objeto Liquid será un rectángulo y sabrá acerca de su ubicación, ancho, alto y “coeficiente de arrastre”: es decir, ¿es fácil para los objetos moverse a través de él (como el aire) o difícil (como la melaza)? Además, debe incluir una función para dibujarse en la pantalla (y dos funciones más, que veremos en un momento).
var Liquid = function(x, y, w, h, c) {
  this.x = x;
  this.y = y;
  this.w = w;
  this.h = h;
  this.c = c;
};

Liquid.prototype.display = function() {
  noStroke();
  fill(50);
  rect(this.x, this.y, this.w, this.h);
};
El programa principal ahora declarará e inicializará una nueva instancia de objeto Liquid. Observa que el coeficiente es bajo (0.1), de lo contrario el objeto se detendría bastante rápido (que puede ser el efecto que quieras algún día).
var liquid = new Liquid(0, height/2, width, height/2, 0.1);
Ahora viene una pregunta interesante: ¿cómo hacemos que el objeto Mover le hable al objeto Liquid? En otras palabras, queremos ejecutar lo siguiente:
Cuando un mover pasa a través de un líquido, experimenta una fuerza de arrastre.
…o en idioma orientado a objetos (suponiendo que estamos iterando sobre un arreglo de objetos Mover con índice i):
// ¿El Mover está en el líquido?
if (liquid.contains(movers[i])) {
    // Calcular fuerza de arrastre
    var dragForce = liquid.calculateDrag(movers[i]);
    // Aplicar fuerza de arrastre al Mover
    movers[i].applyForce(dragForce);
}
El código anterior nos dice que tenemos que agregarle dos funciones al tipo de objeto Liquid: (1) una función que determine si un objeto Mover está dentro del objeto Liquid y (2) una función que calcule la fuerza de arrastre ejercida sobre el objeto Mover.
La primera es fácil; podemos simplemente usar una declaración condicional para determinar si el vector de posición se encuentra dentro del rectángulo definido por el líquido.
Liquid.prototype.contains = function(m) {
    var p = m.position;
    return p.x > this.x && p.x < this.x + this.w &&
         p.y > this.y && p.y < this.y + this.h;
};
La función drag() es un poco más complicada; sin embargo, ya escribimos el código para ella. Esto es simplemente una implementación de nuestra fórmula. ¡La fuerza de arrastre es igual al coeficiente de arrastre multiplicado por la velocidad del Mover al cuadrado en la dirección opuesta a la velocidad!
Liquid.prototype.calculateDrag = function(m) {
  // La magnitud es el coeficiente * velocidad al cuadrado
  var speed = m.velocity.mag();
  var dragMagnitude = this.c * speed * speed;

  // La dirección es opuesta a la de la velocidad
  var dragForce = m.velocity.get();
  dragForce.mult(-1);

  // Se escala de acuerdo con la magnitud
  // dragForce.setMag(dragMagnitude);
  dragForce.normalize();
  dragForce.mult(dragMagnitude);
  return dragForce;
};
Y con estas dos funciones agregadas al tipo de objeto Liquid, estamos listos para poner todo junto en un solo programa:
Al ejecutar el programa, debes darte cuenta de que estamos simulando pelotas cayendo en agua. Los objetos solo se frenan cuando cruzan a través de la zona gris en la parte inferior de la ventana (que representa al líquido). También te darás cuenta de que los objetos más pequeños se frenan mucho más que los objetos más grandes. ¿Recuerdas la segunda ley de Newton? A = F / M. La aceleración es igual a la fuerza dividida entre la masa. Un objeto masivo se acelerará menos. Un objeto pequeño se acelerará más. En este caso, la aceleración de la que estamos hablando es el “frenado” debido al arrastre. Los objetos más pequeños se frenarán más rápido que los más grandes.

Este curso de "Simulaciones Naturales" es un derivado de "La Naturaleza del Código" por Daniel Shiffman, usado bajo una Licencia Creative Commons Reconocimiento-NoComercial 3.0 Unported.