2011-02-23 11 views
9

¿Cuál es la forma más simple de aplicar de forma asincrónica mejoras consecutivas a un objeto Graphics en una configuración dinámica (y cancelar la evaluación de los resultados innecesarios si la entrada cambia mientras se calculan)?Mathematica: generación incremental asíncrona de gráficos dinámicos

Como un simple ejemplo, considere esto:

speed[r_] := [email protected]{Red, Circle[{0, 0}, r]} 
qualityA[r_] := (Pause[1]; [email protected]{Red, Disk[{0, 0}, r]}) 
qualityB[r_] := (Pause[1]; [email protected]{Black, Circle[{0, 0}, r]}) 
Manipulate[Show[ 
    ControlActive[speed[r], {qualityA[r], qualityB[r]}], 
    PlotRange -> {{-1, 1}, {-1, 1}} 
    ], {{r, .5}, 0, 1}] 

Mathematica graphics

¿Cómo se puede evaluar lo qualityA y qualityB consecutivamente, y anexar su producción a la pantalla cuando está listo?

Puntos de bonificación para Abort 'la evaluación de resultados innecesarios, y para permitir que una parte del resultado se calcule varias veces, de modo que después de liberar el control vería, p. {qualityA[r]} luego {qualityA[r],qualityB[r]}, y finalmente {qualityA2[r],qualityB[r]}.

Respuesta

5

Mi colega Lou, un experto en dinámica, sugirió esta respuesta ordenada:

Manipulate[ 
ControlActive[ 
    Graphics[{LightRed, Circle[{0, 0}, r]}, 
    PlotRange -> {{-1, 1}, {-1, 1}}], 
    DynamicModule[{exprs = {Red, Circle[{0, 0}, r]}, rr = r}, 
    Graphics[Dynamic[exprs], PlotRange -> {{-1, 1}, {-1, 1}}], 
    Initialization :> (Pause[1]; 
    AppendTo[exprs, {Red, Disk[{0, 0}, rr]}]; Pause[1]; 
    AppendTo[exprs, {Black, Circle[{0, 0}, rr]}]), 
    SynchronousInitialization -> False]], {{r, 0.5}, 0, 1}] 

Cómo funciona:

Cuando no ControlActive, el resultado de la expresión dinámica es una DynamicModule. El código para refinar los gráficos está en la opción Initialization de este DynamicModule. El SynchronousInitialization -> False hace que esta inicialización se ejecute de forma asincrónica.

Renombrar rr = r en el DynamicModule sirve para dos propósitos. En primer lugar, hace que el resultado siempre dependa de la variable Manipular r. En segundo lugar, se puede comprobar rr != r para decidir si el usuario ha movido el cursor durante la inicialización, y abortar temprano, el ahorro de tiempo de cálculo:

Manipulate[ 
ControlActive[ 
    Graphics[{LightRed, Circle[{0, 0}, r]}, 
    PlotRange -> {{-1, 1}, {-1, 1}}], 
    DynamicModule[{exprs = {Red, Circle[{0, 0}, r]}, rr = r}, 
    Graphics[Dynamic[exprs], PlotRange -> {{-1, 1}, {-1, 1}}], 
    Initialization :> (If[rr =!= r, Abort[]]; Pause[1]; 
    AppendTo[exprs, {Red, Disk[{0, 0}, rr]}]; If[rr =!= r, Abort[]]; 
    Pause[1]; AppendTo[exprs, {Black, Circle[{0, 0}, rr]}]), 
    SynchronousInitialization -> False]], {{r, 0.5}, 0, 1}] 

espero que esto ayude.

+0

¡Este no puedo romperlo! Realmente esperaba que tu primera persona trabajara, pero como mencioné, muere en 'pruebas de mono'. Éste con el que puedo jugar todo lo que quiero y me sigo comportando como debería. ¡Muchas gracias por seguir con esto! – Janus

2

Muy buena pregunta.

Estoy pasando por alto de una manera más simple. A menudo hay una cuando se trata de la dinámica ... Pero aquí está mi sugerencia:

DynamicModule[{quality = 0, exprs = {}}, 
Manipulate[ 
    Show[ 
    ControlActive[ 
    exprs = {}; quality = 0; [email protected]{Red, Circle[{0, 0}, r]}, 
    Switch[quality, 
    0, Pause[1]; quality = 1; 
    AppendTo[exprs, [email protected]{Red, Disk[{0, 0}, r]}], 
    1, Pause[1]; quality = 2; 
    AppendTo[exprs, [email protected]{Black, Circle[{0, 0}, r]}], 
    _, r]; 
    exprs 
    ], 
    PlotRange -> {{-1, 1}, {-1, 1}}], 
    {{r, .5}, 0, 1} 
    ] 
] 

Primero definimos algunas variables que controlan cada vez más gráficos de alta calidad: quality (que van a 0 a la máxima calidad, 2 en este caso) y exprs (una lista de expresiones para mostrar, al igual que en su ejemplo).

Ahora tenga en cuenta lo que ocurre en los dos casos de ControlActive:

Cuando ControlActive, el resultado es el mismo que el suyo, salvo que tomamos la oportunidad de restablecer quality y exprs relativa a los gráficos de "alta calidad".

Cuando no ControlActive, la expresión dinámica evalúa a

code; exprs 

Esta expresión tiene las siguientes propiedades clave.

  1. Devuelve la lista exprs todo el tiempo.
  2. Cada vez que se evalúa code, mejora los gráficos agregando algo al exprs.
  3. Cada vez que se evalúa code, se modifica al menos una de las variables contenidas léxicamente en code; exprs (como quality). Esto significa que Dynamic continuará y evaluará nuestra expresión dinámica nuevamente, y nuevamente, y nuevamente, hasta ...
  4. Eventualmente code evalúa sin ninguna de las variables léxicas contenidas en code; exprs cambiando. Esto significa que Dynamic dejará de volver a evaluar.
  5. La evaluación final contiene léxicamente r. (A través del caso predeterminado inútil en el Switch, _, r). Esto es importante para que el control deslizante siga activando las actualizaciones.

Pruébalo y avísame si eso funciona para ti.

Editar: ¿Qué versión de $ de Mathematica estás usando? Veo cierta dependencia de versión en el comportamiento de mi código anterior.

Editar 2: Le pregunté a un experto en Dynamic y encontró una mejor manera, que describiré en una respuesta separada.

+0

Gracias, Andrew! Esto se parece mucho a la idea que estaba tratando de obtener. Desafortunadamente, no funciona demasiado bien para mí (v8.0, 64 bits OS-X): la primera ronda de movimientos y lanzamientos está bien, pero luego el control deslizante deja de seguir, y luego todo se detiene ... Y como siempre con Dynamics, No tengo ni idea de lo que está pasando :) – Janus

Cuestiones relacionadas