1votos

Mosca en Java

por josejuan hace 2 años

La misma estrategia que en Haskell pero 100 moscas volando por ahí...

Escribir un código que devuelva un punto que se mueva aleatoriamente en la pantalla.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
// 100 moscas en: https://www.youtube.com/watch?v=t7IQ7DNv3R8 
 
import com.jogamp.opengl.*; 
import com.jogamp.opengl.awt.GLCanvas; 
import com.jogamp.opengl.util.FPSAnimator; 
 
import javax.swing.*; 
import java.util.*; 
import java.util.concurrent.ThreadLocalRandom; 
 
class P { 
    private final double o; 
    private final double r; 
    private final double a; 
 
    public P(double o, double r, double a) { 
        this.o = o; 
        this.r = r; 
        this.a = a; 
 
    public double p(double t) { 
        return o + r * Math.cos(a * t); 
 
class T { 
    private final double d; 
    private final P p1; 
    private final P p2; 
 
    public T(P p1, P p2, double d) { 
        this.p1 = p1; 
        this.p2 = p2; 
        this.d = d; 
 
    public double p(double t, double h) { 
        double k = h / d; 
        return p1.p(t) * (1 - k) * p2.p(t) * k; 
 
    public double getDuration() { 
        return d; 
 
class PT { 
    private final List<T> xs; 
 
    public PT(T... xs) { 
        this.xs = Arrays.asList(xs); 
 
    public double p(double t) { 
        double tt = xs.stream().mapToDouble(T::getDuration).sum(); 
        double t0 = t % tt; 
        int i = 0; 
        double b = 0; 
        while (true) { 
            double d = xs.get(i).getDuration(); 
            if (t0 < b + d) 
                break; 
            b += d; 
            i += 1; 
        return xs.get(i).p(t, t0 - b); 
 
class M { 
    private final PT m; 
    private final double r, g, b; 
    private final double k1, k2; 
 
    public M(PT m, double k1, double k2, double r, double g, double b) { 
        this.m = m; 
        this.r = r; 
        this.g = g; 
        this.b = b; 
        this.k1 = k1; 
        this.k2 = k2; 
 
    public void draw(GL2 gl, double t) { 
        final double x = m.p(k1 * t); 
        final double y = m.p(k2 * t); 
        gl.glColor3d(r, g, b); 
        gl.glBegin(GL.GL_LINE_STRIP); 
        final double s = 0.0035; 
        gl.glVertex2d(x, y); 
        gl.glVertex2d(x + s, y + s); 
        gl.glVertex2d(x + s, y); 
        gl.glVertex2d(x, y + s); 
        gl.glVertex2d(x, y); 
        gl.glEnd(); 
        gl.glFlush(); 
 
    public static M random() { 
        Random r = ThreadLocalRandom.current(); 
        double a = r.nextDouble() + 1; 
        double b = r.nextDouble() + 1; 
        final P c0 = new P((b - a) * 0.5, 1 + r.nextDouble(), 5 + 2 * r.nextDouble()); 
        final P c1 = new P(-a, 0.1 + r.nextDouble() * 0.4, 7 + 3 * r.nextDouble()); 
        final P c2 = new P(b, 0.1 + r.nextDouble() * 0.4, 7 + 3 * r.nextDouble()); 
 
        final PT m = new PT( 
                new T(c1, c1, 1 + r.nextDouble() * 3), 
                new T(c1, c0, 0.25 + r.nextDouble() * 1), 
                new T(c0, c2, 0.25 + r.nextDouble() * 1), 
                new T(c2, c2, 1 + r.nextDouble() * 3), 
                new T(c2, c0, 0.25 + r.nextDouble() * 1), 
                new T(c0, c1, 0.25 + r.nextDouble() * 1) 
        ); 
 
        return new M(m, 0.2 + 0.8 * r.nextDouble(), 0.2 + 0.8 * r.nextDouble(), r.nextDouble(), r.nextDouble(), r.nextDouble()); 
 
public class Mosquitos implements GLEventListener { 
 
    private final static int N = 100; 
 
    private final M[] ms; 
 
    public Mosquitos() { 
        ms = new M[N]; 
        for (int i = 0; i < N; i++) 
            ms[i] = M.random(); 
 
    public void display(GLAutoDrawable g) { 
        final double t = 0.25 * 1e-3 * Calendar.getInstance().getTimeInMillis(); 
 
        final GL2 gl = g.getGL().getGL2(); 
        gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT); 
        for (M m : ms) 
            m.draw(gl, t); 
 
    public void dispose(GLAutoDrawable g) { 
 
    public void init(GLAutoDrawable g) { 
 
    public void reshape(GLAutoDrawable g, int a, int b, int c, int d) { 
 
    public static void main(String[] args) { 
        final GLProfile profile = GLProfile.get(GLProfile.GL2); 
        GLCapabilities capabilities = new GLCapabilities(profile); 
        capabilities.setDoubleBuffered(true); 
        final GLCanvas glcanvas = new GLCanvas(capabilities); 
        Mosquitos b = new Mosquitos(); 
        glcanvas.addGLEventListener(b); 
        glcanvas.setSize(900, 900); 
        final FPSAnimator animator = new FPSAnimator(glcanvas, 30, true); 
        final JFrame frame = new JFrame("Mosquito"); 
        frame.getContentPane().add(glcanvas); 
        frame.setSize(frame.getContentPane().getPreferredSize()); 
        frame.setVisible(true); 
        animator.start(); 
 
6 comentarios
0votos

Escrito por Germán M hace 2 años

Estimado José Juan, usté es un genio.
0votos

Escrito por josejuan hace 2 años

D en absoluto @Germán, no tiene nada de especial, es sólo un pasatiempo.
0votos

Escrito por JCarles hace 2 años

Demasiado random.

Los insectos no vuelan de forma tan caótica. Sólo hay que compararlo con el video inspirador: https://www.pond5.com/stock-footage/52800733/random-chaotic-movement-insects-and-flies.html

Creo que habría que añadir factores prefijados para que el vuelo tienda a ser más horizontal, más espasmótico (quizás relacionado con la proximidad de varios en un mismo espacio), y también con tendencia al zig-zag.

Tu programa está bien, José Juan, pero no veo moscas volando. Veo puntos moviéndose.
0votos

Escrito por josejuan hace 2 años

Vaya @JCarles, veo que tienes buena vista, efectivamente no son moscas volando sino puntos en movimiento :P

Sin embargo, me parece que el movimiento está razonablemente bien conseguido para ser la primera idea que me ha venido a la cabeza, la cual no debes haber entendido porque permite elegir sin problemas trayectorias más o menos horizontales, más o menos espasmódicas, con más o menos zig-zag, etc...

Si las animaciones particulares no te parecen suficientemente buenas es porque habría que dedicar unos minutos a tunear una buena configuración y básicamente he usado un zigzagueo a la izquierda (círculo `c1`) con un zigzagueo a la derecha (círculo `c2`) y la unión espasmódica de ambos con un círculo envolvente (círculo `c0`), para no tener que hacer dos, he usado la misma para las coordenadas `x` e `y`.

Si diseñar una a mano requiere tiempo, conseguir buenos parámetros para cientos de moscas es todavía más complicado porque requiere conocer algunos parámetros interesantes (globales) que desconozco, los intervalos sobre aleatorio de los parámetros los he puesto a ojo, haciendo lo que buenamente he podido.

Así, si te fijas en el vídeo y mantienes tu mirada en alguno de esos mosquitos (si bueno, puntos) verás que zigzaguean, cambian de dirección, tienen espasmos, tan pronto van lentos como despacio, etc... hablo de cada mosquito individualmente.

No me he parado a mirar ningún estudio al respecto (que sin duda lo habrá) pero si quieres conseguir un buen movimiento, te sugiero hacer un análisis estadístico de los movimientos de mosquitos reales y pasarlo al espacio de frecuencias (básicamente calcular la transformada de fourier), ello te dará aproximadamente el tipo de parámetro que debes fijar en mi solución o, mejor aún, en lugar de interpolar entre órbitas (mi solución), aplicar directamente los coeficientes de la transformada obtenida. A mi el esfuerzo aún no me merece la pena xD

Ya por último, mira a ver éstos mosquitos del siguiente vídeo, pues su vuelo parece, o yo estoy ciego, totalmente caótico: https://www.youtube.com/watch?v=oTCh-T54JsA

;P
0votos

Escrito por josejuan hace 2 años

He aquí un detallado estudio sobre el movimiento de las moscas de la fruta http://rsif.royalsocietypublishing.org/content/11/99/20140672

Como era de esperar, usan transformadas (tipo fourier) para clasificar el movimiento, en la figura 3, (imagen `e` central derecha) se ve cómo 50 tipos de movimientos forman el movimiento total. En mi solución de juguete he puesto sólo 3 (y dos de ellos son uno mismo de esos 50).

Texto del enlace

Como he comentado, a partir de ese estudio pueden obtenerse parámetros realistas y no "a ojo", pero no pensaba que estábamos tan exigentes xD xD
0votos

Escrito por josejuan hace 2 años

"a partir de ese estudio pueden obtenerse parámetros realistas"

realmente no, este estudio es del movimiento "en tierra" (no volando). Pues no encuentro ninguno específico del movimiento local (aquí uno sobre rutas de polinización http://digitalcommons.unl.edu/cgi/viewcontent.cgi?article=1050&context=mathstudent también usando fourier para clasificar y muchos sobre sensorial de las moscas y tal, pero de vuelo local nada...).

Comenta la solución

Tienes que identificarte para poder publicar tu comentario.