QF DSL v1
Describe construcciones exactas y reproducibles. No es necesario para usar QF, pero es útil para secuencias largas y material reutilizable. Un error de escritura rechaza el script entero indicando la línea: nunca dibuja algo distinto de lo que pediste.
/qf-dsl sirve a tres gramáticas. Cuál se usa no depende de lo que escribas, sino del lienzo en el que estés: en geometría se parsea la construcción sintética; en el plano cartesiano, las gráficas; en física, la escena mecánica. Varios constructores se llaman igual en más de una —point, segment, circle, intersection, angle, label— a propósito.Geometría
Construcción sintética en un lienzo sin ejes: puntos, segmentos, polígonos y circunferencias, con sus puntos y figuras derivadas vivos — un cuadrado apoyado en un lado se rehace cuando ese lado se mueve.
/qf-dsl
T = triangle(A, B, C)
H = foot(B, A, C)
altura = segment(B, H)
M = midpoint(A, C)
mediana = segment(B, M)
G = centroid(T)Objetos básicos
- point(x, y)
- Punto libre
- segment(A, B)
- Segmento
- line(A, B)
- Recta infinita por dos puntos: llega hasta el borde de la figura y no la agranda (segment(A, B) es el tramo)
- circle((0, 0), 3)
- Circunferencia de centro fijo
- triangle(A, B, C)
- Triángulo. Con letras nuevas lo construye el motor; sobre puntos ya definidos usa sus coordenadas, y sobre puntos construidos (on_side, cruces, pies) se mueve con ellos; con angles= o right_at= marca sus ángulos
- quadrilateral(A, B, C, D)
- Cuadrilátero cualquiera; nombra sus lados AB, BC, CD, DA
- polygon(A, B, C, D, E)
- Polígono de n vértices
- polygon((0, 0), (4, 0), (1, 3))
- Polígono por coordenadas, sin letras ni puntos
Puntos derivados
- midpoint(A, B)
- Punto medio
- foot(P, A, B)
- Pie perpendicular
- intersection(r, s)
- Cruce de segmentos, rectas, circunferencias, arcos o rectas construidas; un segmento cuenta solo en su tramo
- intersection(k, r, lejos_de=M)
- Elige uno de dos cruces sin que salte al arrastrar: cerca_de=P, lejos_de=P, sobre=s, arriba, abajo, izquierda o derecha
- on_circle(c, 55)
- Punto atado a la circunferencia
- on_segment(s, 0.35)
- Atado al segmento: se desliza por él
- on_side(AB, 0.35)
- Atado a un lado del polígono
- center(Q)
- Centro de una figura: el promedio de sus vértices (en un paralelogramo, el cruce de sus diagonales)
- center(c)
- Centro de una circunferencia, con nombre y vivo: se mueve con ella
Compás (vivo)
- circle(O, 2)
- Centro en un punto con nombre (libre, medio, cruce, vértice): la circunferencia lo sigue
- circle(O, P)
- Con centro en O y que pasa por P: el radio cambia al mover O o P
- circle(C, AB)
- Copia la longitud del segmento o lado AB
- circle(O, P, dashed)
- Punteada: circunferencia auxiliar de la construcción
- circle(A, 3, arcs)
- Marcas de compás: solo un arco corto junto a cada cruce que la usa
- intersection(k1, k2)
- Cruce de dos circunferencias; la otra rama con second. La rama no salta al arrastrar
- arc(O, A, B)
- Arco de centro O desde A, antihorario, hasta la dirección de B; vivo, acepta dashed y se interseca
Relaciones
- parallel(A, B, P)
- Paralela
- perpendicular(A, B, P)
- Perpendicular, con su cuadradito de 90° donde corta a AB
- perpendicular_bisector(A, B)
- Mediatriz
- tangent(c, P)
- Tangente: de P al punto de tangencia. Con P sobre la circunferencia (on_circle), la tangente EN P, perpendicular al radio; con P adentro no hay tangente
- tangent(c, P, extend=2)
- Tangente prolongada 2 unidades más allá del punto de tangencia (en P, 2 unidades a cada lado)
- secant(c, P)
- Secante
Circunferencias tangentes
- tangente_a(k0, k1, k2)
- Circunferencia tangente a tres objetos: circunferencias, rectas o segmentos, lados AB o puntos; sin más, la de menor radio (second, la siguiente). Viva: sigue la misma solución sin saltar. Alias tangent_circle
- tangente_a(k0, k1, k2, tipo=(int, ext, ext), derecha)
- tipo= por objeto: int (la nueva queda dentro), ext (por fuera), contiene o _ (no importa); después, un selector de intersection. Sin solución no se dibuja y el motor lo dice
- tangencia(k1, k2)
- Punto donde se tocan dos circunferencias, o una circunferencia y una recta; vivo. Si no son tangentes, no compila. Alias tangency
- apoloniano(k0, k1, k2, k3, profundidad=3)
- Relleno apoloniano de cuatro tangentes dos a dos: profundidad= (generaciones) o radio_min=; tope de 500. Piezas G_gen1_1…; G y G.gen2 son grupos en /qf-style; animate va por generación. Alias apollonian
Figuras y marcas
- square_on(AB, external)
- Cuadrado sobre el lado de un polígono, hacia afuera
- square_on(A, B, left)
- Sobre dos puntos sueltos: izquierda o derecha de A→B
- region(A, E, P, H)
- Sombrea la región sobre puntos que ya existen (3 o más)
- region(A, E, P, fill=ambar)
- La misma región con un color elegido
- region((0, 0), (4, 0), (2, 3))
- Vértices por coordenadas (solos o con puntos); queda fija
- angle(A, B, C)
- Marca de ángulo viva en el vértice B; reemplaza la que el triángulo ya ponga ahí
- angle(A, B, C, alfa)
- La misma marca con un símbolo en vez de la medida: alfa dibuja α (también beta, theta, Delta → Δ…, o la letra escrita). Entre comillas, el texto tal cual, también una fórmula: "$\alpha_1$"
Marcas
- angle(r, s)
- Ángulo entre dos segmentos o rectas por dos puntos: en su extremo común (angle(AB, AC) es angle(B, A, C)) o en su cruce, hacia el segundo punto de cada una; vivo
- marca(AC, BC, 1)
- Rayitas de igualdad (1, 2 o 3) sobre cada tramo: un segmento, un lado (AB) o dos puntos (BD); vivas. Si los tramos no miden lo mismo, las notas lo dicen. Alias mark
- paralela_marca(AB, DC)
- Puntas de flecha de paralelismo, todas en el sentido del primer tramo; 2 o 3 al final para otro par. Si no son paralelos, las notas lo dicen. Alias parallel_mark
- angle(A, P, B, alfa, radio=1.5)
- radio= multiplica el radio del arco (de 0,5 a 4) y manda sobre el automático. Sin él, los ángulos que comparten vértice se anidan: el que contiene a otros va afuera (+14 px por nivel, o lo que pida el rótulo de adentro), los adyacentes comparten radio y uno de menos de 25° se agranda
- angle(A, O, B, rotulo=dentro)
- El rótulo entre el vértice y el arco; por defecto, fuera
- marca(b1, b2, 2)
- Igualdad de ángulos con nombre: 1, 2 o 3 arcos concéntricos en cada uno; se combina con el símbolo del ángulo. Si no miden lo mismo, las notas lo dicen
- marca(b1, b2, 2, rayitas)
- La misma igualdad con rayitas que cruzan el arco
Textos y medidas vivas
- note((0, 3), "AB = 4")
- Texto suelto centrado en (x, y)
- note((0, 4), "Teorema", tamaño=20, peso=negrita, giro=15)
- Tamaño en px, negrita y giro en grados (antihorario)
- label(s, "MO = {{length(s)}}")
- Rótulo de un punto, segmento o recta (alias rótulo). En {{…}} van medidas vivas: dist(P, Q), length(s), angle(A, B, C), area(T), perimeter(T); se recalculan al mover la figura
- label(P1, "$P_1$")
- Subíndices explícitos: el punto P1 se rotula «P1»; P₁ se pide con una fórmula entre $…$ o con el carácter, label(P1, "P₁")
Centros y círculos
- centroid(T)
- Baricentro
- orthocenter(T)
- Ortocentro
- incenter(T)
- Incentro
- circumcenter(T)
- Circuncentro
- incircle(T)
- Círculo inscrito
- circumcircle(T)
- Círculo circunscrito
- circumcircle(A, F, E)
- Circunferencia por tres puntos cualesquiera, también construidos; viva
Elipses
- ellipse(focos=(B, C), pasa_por=A)
- Elipse de focos B y C que pasa por A; viva: sigue a los tres. Con a=5 en lugar de pasa_por=, por su semieje mayor. Se corta con rectas, circunferencias y otras elipses. Alias elipse
- ellipse((0, 0), a=4, b=2, giro=30)
- Por su centro (un par o un punto con nombre) y sus semiejes; giro en grados, antihorario; dashed la dibuja punteada. El relleno va en /qf-style, como el de una circunferencia: k { relleno: translúcido amarillo }
Homotecia
- homothety(A, O, 2)
- La imagen viva desde el centro O con razón 2 (negativa: del otro lado de O) de un punto, segmento, recta, circunferencia, elipse o figura. Alias homotecia
- homothety(h1, V, T1, T2)
- Con la razón que lleva T1 a T2: con V en el punto de fuga y T2 sobre la fila, la imagen escala sola al mover T2
- homothety(T, O, -1)
- Los vértices de la imagen de una figura, con prima (A′B′C′), se llaman T2_A, T2_B…; los extremos de la de un segmento s2 no se ven y se llaman s2_A y s2_B
Plano cartesiano
Curvas, cónicas, regiones y sumas de Riemann. Aquí los ejes SON el sistema de coordenadas, así que no hay escala en píxeles que declarar.
/qf-dsl
window x: [-3, 4], y: [-2, 8]
f = plot(x^2)
g = plot(2*x + 1)
P = intersection(f, g)
S = area(f, g, [-1:3], donde g > f)Lienzo y parámetros
- window x: [-4, 4], y: [-1, 10]
- Ventana de los ejes
- frame x: [0.05, 0.95], y: [0, 0.55]
- En qué parte del lienzo se dibuja el plano, en fracciones de 0 a 1 (la y, desde arriba). Sin ella el plano se centra ocupando todo; dentro de un panel, coloca ese plano solo
- axis x: "t (s)", y: "v"
- Etiquetas
- grid on · title "…"
- Rejilla y título
- axes off
- Sin ejes ni sus números (también axis off); la rejilla va aparte: grid off
- param a = 2 in [-5, 5]
- Deslizador
- panel "Velocidad"
- Plano debajo del anterior con el mismo eje x (hasta 3); dentro, window y, axis y, grid y sus objetos
Curvas y cónicas
- plot(x^2 + 2, [-1:3])
- Curva y = f(x), con dominio
- plot(f(x - 2) + 1)
- Una curva y = f(x) del script dentro de otra expresión: traslada, refleja o compone (se copia su expresión, no su dominio)
- curve(cos(t), sin(t), [0:2*pi])
- Paramétrica
- polar(2*cos(3*theta), [0:2*pi])
- Polar
- plot(sen(x), punteado, color=gris)
- Trazo discontinuo («puntos»: de puntos; «punto-raya»: de raya y punto) y color; también en curve, polar, cónicas y objetos lineales
- circle((0, 0), 3)
- Circunferencia
- ellipse((1, 0), a=4, b=2)
- Elipse
- ellipse(focos=(B, C), pasa_por=A)
- Elipse por sus focos y un punto (o con a=, su semieje mayor); sigue a sus puntos
- hyperbola((0,0), a=2, b=1)
- Hipérbola
- parabola((0,-1), p=2, abajo)
- Parábola
Puntos y objetos lineales
- point(2, 3)
- Punto por coordenadas
- point(4*cos(30°), sqrt(3))
- Coordenadas con expresiones y grados; con parámetros, el punto sigue al deslizador
- segment(A, B) · vector(A, B) · ray(A, B) · line(A, B)
- Segmento, vector, rayo y recta por dos puntos
- polygon(A, B, C, fill=azul)
- Polígono por sus vértices
Puntos derivados
- intersection(f, g)
- TODAS las intersecciones, por x ascendente
- P[0] · P[1]
- Un miembro de la colección; A = P[0] lo rotula «A»
- intersection(f, g, segunda)
- Atajo de P[1]
- intersection(f, g, cerca_de=M)
- Un solo cruce, por lo que es: cerca_de= y lejos_de= (un punto o un par), sobre= (otra curva), arriba, abajo, izquierda o derecha. Sigue siendo el mismo al mover un deslizador; si ninguno la cumple, no se dibuja y se avisa
- roots(f) · root(f, branch=0)
- Cortes con el eje x; uno solo con root
- at(f, 0)
- El punto (0, f(0))
- on_curve(c, pi/2)
- Sobre una paramétrica en su t, una polar en su θ o y = f(x) en su x; con un parámetro recorre la curva. at() acepta lo mismo
- intersection(r1, r2)
- Entre rectas, segmentos y semirrectas: UN punto, si se cortan
- on_circle(k, 55)
- Sobre la cónica, en grados
Regiones y texto
- area(f, [0:3])
- Entre la curva y el eje x
- area(f, g, [0:3], donde g > f)
- Sombreado condicional
- region(arriba f)
- Inecuación y ≥ f(x)
- region(abajo f, abajo g, x in [0:6])
- Bajo las dos curvas a la vez (su mínimo); con varias «arriba», sobre su máximo
- riemann(f, [0:3], n=8)
- Suma de Riemann
- riemann(f, [0:3], n=k)
- Ligada a un parámetro entero (step 1, entre 1 y 200): los rectángulos siguen a su deslizador
- inequality(2*x + 3*y <= 6)
- Semiplano con su recta frontera (discontinua si es estricta); varias del mismo plano se pintan como una región, su intersección
- sistema(x + y <= 8, x >= 0, y >= 0)
- La región que cumple TODAS (programación lineal), con la frontera de cada desigualdad; cada sistema es su propia región. Alias system
- vertices(F)
- Las esquinas de la región de un sistema: V[0], V[1]… en sentido antihorario desde la de más abajo; con coords, rotuladas con sus coordenadas
- note((1, 5), "…") · label(A, "P")
- Texto suelto y rótulo (de un punto, una curva y = f(x), un segmento, una recta o un polígono; en una cónica o una región todavía no se dibuja, y se avisa)
- note((1, 4), "dx = {{1/n}}")
- Entre llaves dobles, una expresión con los parámetros: imprime su valor y cambia al mover el deslizador
- note((0, 5), "AB = {{dist(A, B)}}")
- dist(P, Q) en las llaves: la distancia viva entre dos puntos
- note((0, 4), "{{angle(A, B, C)}}°")
- Más medidas vivas: angle(A, B, C) en grados (el ° va afuera), length(s) de un segmento o vector, area(T) y perimeter(T) de un polígono, o area(A, B, C) con los puntos de su contorno
- label(s, "s = {{length(s)}}")
- Las medidas también van en un rótulo
- label(P1, "$P_1$")
- Subíndices y letras griegas, explícitos: con una fórmula entre $…$ ("$\alpha$") o con el carácter, label(P1, "P₁"). Sin pedirlo, P1 se rotula «P1»
Física (mecánica)
Cuerpos, soportes y conectores unidos por relaciones: no se declaran coordenadas — la posición de cada cuerpo sale del grafo (on, stack, pin, attach, route) y las fuerzas de un diagrama de cuerpo libre se deducen de él, no se dibujan a mano. Las magnitudes sí se pueden declarar en newtons cuando el enunciado las da, y el largo de cada flecha las respeta.
/qf-dsl
rampa = ramp(30)
A = block(4kg, "m₁")
on(A, rampa, at=0.55, mu=0.3)
fbd(A)
axes(A, decompose=on)
angle(rampa, "θ")Cuerpos
- block(4kg, "m₁")
- Bloque; masa y etiqueta opcionales
- sphere(2kg, r=20)
- Esfera, con radio en píxeles
- sphere(2kg, color=rojo)
- Color del cuerpo: rojo, verde, azul, amarillo, naranja, morado, rosa, celeste, gris, negro, blanco, marron (o en inglés), o hex sin #: color=dc2626. Vale también en block()
- sphere(2kg, v0=5, angle=30)
- Esfera LANZADA: v0 en m/s y angle en grados desde +x (y hacia arriba). Sin apoyo ni cuerda sale como proyectil; sobre un apoyo, v0 tiene que ir a lo largo de él. Vale también en block()
- beam(length=220)
- Barra rígida (alias: bar): el peso en su centro; cuerdas y fuerzas hacen momento donde se atan
- pulley(24)
- Polea, con su radio
Soportes
- floor()
- Piso horizontal
- table()
- Mesa: tablero y dos patas hasta el piso; length= (500) y height= (160, del tablero al piso). Para la física es un apoyo como floor()
- anchor(mesa, at=1)
- Soporte en una esquina de la mesa (at=0, la izquierda), en el canto. Con pin(P.axle, ancla), la polea queda afuera: la cuerda del apoyado llega horizontal arriba del disco y lo que cuelga baja vertical, afuera de la mesa. pin(P.axle, mesa) es la esquina derecha
- ramp(30)
- Rampa, con su ángulo en grados: entre 0 y 90, sin incluirlos
- surface(length=600)
- Superficie horizontal genérica; para inclinarla, ramp(θ)
- surface(path=[(180,200), (360,380), arc(480,440, 600,380), (780,200)])
- Superficie POR TRAMOS: rectas y arcos en un mismo apoyo (un valle con fondo curvo, un tobogán). Cada (x,y) es un tramo recto; arc(porX,porY, hastaX,hastaY) es un arco de circunferencia que pasa por el primer punto y termina en el segundo — los tres puntos fijan radio y sentido, no hay que declararlos. Al reproducir, un cuerpo apoyado con on() corre por los arcos como partícula guiada sin rozamiento: la normal lleva el término centrípeto y, donde se anula, el cuerpo se despega y sigue como proyectil
- surface(path=[(100,150), (400,400), arc(500,300, 400,200), arc(300,300, 400,400), (800,400)])
- RIZO: rampa que baja al fondo de un círculo cerrado por DOS arcos (el que sube y el que baja) y sale por un piso. Con on(bola, pista, at=0) en lo alto de la rampa, al reproducir la esfera completa la vuelta si parte de h ≥ 2.5·R (con R el radio del rizo), se despega antes de la cima si no llega, y sube y vuelve si no pasa de la horizontal; el ⓘ predice cuál de los tres. El mismo perfil recorrido por FUERA (una loma) se despega después de la cima
- ceiling()
- Techo
- wall(left)
- Pared izquierda o derecha
- anchor(techo, at=0.3)
- Punto de anclaje sobre techo, superficie o barra
Conectores y fuerzas
- rope()
- Cuerda. Compacta: rope(from=A.top, via=[over(P)], to=B.top)
- rope(orientation=vertical)
- Eje declarado para el motor: vertical, horizontal, along_surface (sigue la tangente del apoyo) o free. El cálculo cree la declaración, no el trazo. Sin declararla, usa la dirección del trazo en cada extremo y el ⓘ de la reproducción dice cuál tomó
- spring(k=200, rest=120)
- Resorte. Como la cuerda, ata sus dos extremos (si no, se rechaza)
- spring(k=200, orientation=horizontal)
- Eje del resorte, horizontal o vertical: su extremo en una pared, un techo o un piso va donde ese eje lo toca. Sin declararlo, horizontal contra una pared (a la altura del bloque) y vertical colgado; free lo deja en el centro del soporte. Un eje que no llega a su soporte se rechaza
- junction()
- Nudo donde concurren varias cuerdas: sin masa, sus tensiones se equilibran entre sí
- rope(from=V.rightEnd, to=pared, direction=150)
- Dirección de la cuerda, de from= hacia to=, en grados como en force(): el amarre va donde esa recta toca el soporte (pared, techo o superficie) y el cálculo usa ese ángulo. «A 30° con el techo» desde un nudo J: direction=150. Sin via= ni anchor()
- force(50N, direction=down)
- Fuerza externa: right/up/left/down o un ángulo
- force(direction=30)
- Fuerza de magnitud DESCONOCIDA: la despeja equilibrium() (la caja que sube a velocidad constante); sin él se dibuja sin valor y se avisa
Relaciones (la posición sale del grafo)
- on(A, rampa, at=0.55, mu=0.3)
- Apoyo sobre una superficie; mu= añade roce: estático si alcanza para sostener el cuerpo (vale −Fₜ, y si es 0 no se dibuja), si no cinético (µ·N) contra el movimiento. Sale de la cara de contacto
- on(A, rampa, mu=0.3, motion=up)
- Movimiento declarado: up o down (cuesta arriba o abajo), left o right. El roce es cinético y se opone a él; con una fuerza desconocida, equilibrium() da la de velocidad constante
- stack(B, A)
- B apilado sobre A
- contact(b, mesa, at=0.4)
- Contacto genérico cuerpo–superficie
- pin(P1.axle, techo)
- Unión persistente del eje de una polea
- pin(V, pared, at=0)
- Pasador de una barra en un soporte fijo (pared, techo, piso o anchor()); at= entre sus extremos (0 el izquierdo, 1 el derecho; en una pared, el que la toca). La barra gira alrededor de él y el soporte la sostiene con Rx y Ry: las despeja equilibrium() y el DCL las dibuja en el pasador
- attach(c1.a, A.top)
- Terminal de cuerda o resorte a un puerto del cuerpo; los soportes van SIN puerto: attach(c1.b, techo)
- route(c1, [over(P1), over(P2)])
- La cuerda rodea las poleas, en orden. Una polea SIN pin que la cuerda rodea entre una fija y el techo (o entre dos puntos fijos) cuelga en el seno: es MÓVIL, con sus dos tramos verticales; su carga va con attach(c2.a, M.axle), cuya cuerda tira con el doble de la tensión
- apply(F, viga.rightEnd)
- Aplica la fuerza sobre un punto del cuerpo
Vistas y layout
- fbd(A)
- Diagrama de cuerpo libre: las fuerzas se deducen del grafo
- fbd(J)
- DCL de un nudo: solo las tensiones de sus cuerdas, a escala entre sí (un nudo no tiene peso)
- forces(A, B)
- DCL de varios cuerpos a la vez
- fbd(A, weight=20N, normal=10N)
- Magnitudes declaradas en newtons: el largo de cada flecha las respeta (weight, normal, friction, tension)
- fbd(A, weight="Fg", weight_t="Fg·senθ")
- Rótulo por fuerza y por componente de la descomposición (_t tangencial, _n normal)
- fbd_scale(1.5)
- Calibrado global: multiplica el largo de todas las flechas del DCL
- equilibrium()
- ¿El sistema está en equilibrio? El motor resuelve y responde con las tensiones, normales y roces (estático o cinético, con su sentido), la reacción de cada pasador (Rx, Ry, con su sentido) y despeja la fuerza sin magnitud; el DCL los dibuja a escala, vivos al editar. Dice los supuestos que usó
- datos()
- Los valores EN la figura: una ficha arriba de ella con el veredicto, la aceleración, las tensiones, las normales, los roces y las reacciones, que el motor rehace al editar (respeta «decimal: coma»). datos(A), la de un cuerpo. Si el motor no puede resolver la escena, lo dice. Alias info
- note(A, "T = {{tension(c)}} N")
- Texto junto a un objeto, del lado donde no tapa nada, y lo sigue; note((480, 60), "…") en un punto. Medidas vivas entre {{…}}: tension(c), normal(A), roce(A) (normal(A, piso) con dos apoyos), acel(A), reaccion(V) y reaccion(V, x) o (V, y); |1 fija los decimales. Sin respuesta del motor, «—». Alias nota
- axes(A, decompose=on)
- Ejes vivos anclados al cuerpo (rotan con él); decompose descompone los vectores cercanos en componentes (mg·senθ, mg·cosθ). Etiquetas: axes(A, "t", "n")
- angle(rampa, "θ")
- Arco de ángulo sobre la rampa, con símbolo o medida
- label(A, "caja")
- Rótulo del objeto
- place(B, x=380, y=260, rot=15)
- Solo cuerpos que ninguna relación ubica
Vistas de la reproducción (al pulsar ▶)
- velocity(A)
- Flecha de la velocidad del cuerpo mientras la escena corre, con su valor en m/s. Acepta varios: velocity(m1, m2)
- accel(A)
- Flecha de la aceleración, en m/s². En vuelo apunta siempre hacia abajo (vale g); sobre un apoyo recto va a lo largo de él
- trail(A)
- Rastro del camino recorrido, punteado. Se borra al volver al reposo con ↻
Escala y marco (unidades reales)
- gravity(10)
- La g de la escena en m/s² (sin declararla, 9.81): cambia el peso, el equilibrio y la reproducción. Va arriba, antes del primer objeto
- scale(300px, 1m)
- Cuántos píxeles mide una unidad (mm, cm, m, km); es la escala de toda la escena y va arriba, antes de la primera medida con unidad. Sin declararla rige 300 px = 1 m. Caso astronómico: scale(1px, 425km)
- frame(x=100, y=400)
- Origen del marco de referencia, en píxeles del lienzo (la cuadrícula lo muestra); rot= gira +x en grados antihorarios. Es el punto desde el que se miden los metros
- place(B, x=1m, y=0.5m)
- Ubicación en METROS desde el origen de frame(), con y hacia ARRIBA. Las dos coordenadas van en el mismo sistema (píxeles o metros)
- floor(length=3m)
- Toda longitud admite unidad: length=2m, r=10cm, rest=40cm, width=0.5m, y los puntos de path=[(0m,0m), (2m,1m)]
Macros direccionables
- S = atwood(5kg, 3kg)
- Máquina de Atwood; piezas: S.techo, S.polea, S.m1, S.m2, S.cuerda
- W = incline(30, 4kg)
- Plano inclinado con bloque; piezas: W.rampa, W.bloque
Óptica geométrica
- L = lens(convergente, f=2)
- Lente convergente o divergente de distancia focal f (positiva), sobre un eje horizontal; at= la corre sobre el eje (0 por defecto). Las medidas son unidades del banco óptico: sin unidad o todas en cm, m…; el banco se encuadra solo. Crece hasta cubrir los rayos que la tocan, más un 10 %. Alias lente
- L2 = lens(convergente, f=2, at=4.5, abertura=5)
- abertura= fija el alto total del elemento; un rayo que la toca por fuera no entra: no se dibuja y la respuesta lo avisa
- E = mirror(cóncavo, f=3)
- Espejo cóncavo, convexo o plano (sin f); refleja hacia la izquierda. El curvo se dibuja delgado —la recta del vértice con las puntas curvadas— y dobla la luz en ella, así que los rayos concurren en la imagen de la ecuación. Alias espejo
- obj = object(L, at=-5, height=2)
- La flecha-objeto: su posición sobre el eje y su altura (hacia arriba, positiva); sin elemento, object(at=-1.5, height=0.6), la luz entra por la izquierda. Una etiqueta entre comillas («"A"») nombra sus imágenes A′, A″…; sin ella, A. Alias objeto
- rays(obj)
- Los rayos notables, desviados por el motor; también rays(obj, paralelo, focal) para elegirlos. Alias rayos
- img = image(obj)
- La imagen final, que calcula el motor: real o virtual (punteada, con sus prolongaciones), derecha o invertida. Al arrastrar el objeto o un elemento, los rayos y la imagen se rehacen. Alias imagen
- image(obj, L1)
- Con varios elementos, la luz los recorre todos en su orden (un espejo la devuelve) y cada imagen es el objeto del siguiente, real o virtual: image(obj, L1) dibuja la intermedia que forma L1
- cota(obj, L)
- Cota viva bajo el eje: dₒ = 5. También cota(img, L) (dᵢ), cota(L.F, L) (f), cota(E.C, E) (R) o entre dos puntos cualesquiera del banco; cota(obj, altura) y cota(img, altura) dan la altura con signo (h, h′). Un tercer argumento entre comillas cambia el rótulo; con "" queda solo el número. Sigue a la construcción al arrastrar
- note((2, -3), "m = {{aumento(obj)}}")
- Texto en el banco (x sobre el eje, y hacia arriba). Entre {{…}}, medidas vivas: dist(P, Q), height(X), aumento(obj), f(L), do(obj) y di(obj) (con signo: + real); cambian al arrastrar y respetan «decimal: coma» y las unidades. Alias nota
- datos(obj)
- La ficha del objeto, arriba a la izquierda: f, dₒ, dᵢ, el aumento y si la imagen es real o virtual, derecha o invertida, mayor o menor; en un banco, el aumento total. En /qf-style, obj { color: rojo } pinta el objeto, sus rayos y su imagen, e img { color: … }, solo la imagen. Alias info
Refracción: medios y láser
- P = prism(n=1.5)
- Prisma de índice n (1 a 5) o material= de la lista (agua, acrilico, vidrio, flint, diamante); sin ellos, vidrio (1.5). Equilátero de lado 4, vértice arriba y centro en (0, 0): angle= (el del vértice), side=, at=(x, y) y rot= (grados, antihorario). Unidades del banco, y hacia arriba. Alias prisma
- B = slab(n=1.5, width=6, height=2)
- Lámina de caras paralelas (ancho × alto): el rayo sale paralelo y corrido. at= y rot=, como el prisma. Alias lamina
- agua = medium(n=1.33, below=0)
- Un medio que sigue más allá de la figura: todo lo que está bajo y = 0 (above=, sobre ella), sin borde y con su superficie. Alias medio
- M = medium(n=1.5, [(0,0), (4,0), (0,3)])
- Un polígono simple por sus vértices, en cualquier sentido de giro
- S = semicircle(n=1.5, r=2)
- Semicilindro con la cara plana abajo, centro en at= y rot= para girarlo; la cara curva es exacta. laser(S, incidence=45) entra por ella, sin desviarse, al centro de la cara plana: el ángulo crítico. Alias semicirculo
- G = disc(material=agua, r=2)
- Un disco: la gota o un cilindro. laser(G, incidence=59.4) llega horizontal y la toca a r·sen θ de su centro. Alias disco, gota
- D = mirror(plano, at=(0, 3), angle=135)
- Espejo plano suelto, para el láser: at=(x, y) lo saca del eje, angle= inclina la superficie (desde la horizontal; 90, vertical) y mira= elige la cara que refleja (izquierda; arriba si es horizontal). Mide 2,7 (abertura= lo cambia). No convive con un objeto del banco
- l = laser(P, incidence=40)
- El láser, al medio de la cara de P que mira a la luz (o al centro de un espejo plano), con su incidencia (desde la normal, de 0 a 90): el motor pone el origen y la dirección. from= dice de dónde llega (izquierda por defecto; derecha, arriba, abajo); si la cara mira al otro lado, la luz va por dentro del medio (del agua al aire)
- laser(toward=(0, 0), incidence=30)
- A un punto de la cara de un medio, con su incidencia
- laser((-4, 1), angle=-10)
- Desde un punto, con angle= (grados, antihorario desde +x) o toward=(x, y). El motor lo sigue por la escena: Snell en cada cara, reflexión total más allá del ángulo crítico y reflejos parciales más tenues (reflejos=no los apaga); cruza las lentes y rebota en los espejos, que crecen hasta cubrirlo. Si no toca nada, se avisa
- l = laser(P, incidence=50, luz=blanca)
- Luz blanca: siete colores que se separan en un medio que dispersa (el violeta se desvía más). lambda=650nm, un solo color con su índice
- normals(l)
- La normal y los ángulos, desde la normal, en cada cara (hasta seis). Alias normales. l { color: verde } pinta el haz
- note((0, -2.5), "δ = {{desviacion(l)}}°")
- Medidas vivas, en grados (el ° afuera): incidencia(l, k) y refraccion(l, k) en el impacto k (1 si se omite; en un espejo o en la reflexión total, el de reflexión), desviacion(l), critico(P) e indice(P). Se rehacen al mover el láser; un impacto que ya no existe se lee «—»
- datos(l)
- La ficha del láser: llegada y salida en cada impacto (hasta seis), la desviación total y el ángulo crítico de cada medio que cruza, vivos
Estilos (/qf-style)
El aspecto de la figura va aparte de lo que la figura es: al final del script, después de una línea /qf-style, reglas como las de una hoja de estilos —un tipo o un nombre, y entre llaves sus propiedades—. Sirve en las tres gramáticas. Lo que la línea del DSL ya dice (color=, punteado) manda sobre el bloque; lo que nadie dice sale del estilo estándar. Los números van con punto decimal, salvo que el bloque pida coma.
/qf-dsl
window x: [-3, 3], y: [-1, 5]
f = plot(x^2, color=morado)
g = plot(x + 2)
P = intersection(f, g)
A = point(1.5, 2.25, coords)
S = area(f, g, [-1:2], donde g > f)
/qf-style
decimal: coma
curva { grosor: grueso }
g { línea: punto-raya }
punto { marcador: cruz; radio: 5 }
región { relleno: degradado(blanco, celeste, 90) }Bloque y ajustes
- /qf-style
- Abre el bloque al final del script; todo lo que sigue es aspecto. Un /qf-dsl después del bloque es un error. «# » abre un comentario; #dc2626 (tres o seis cifras) es un color.
- decimal: coma
- Coma decimal en todos los números que escribe la figura (ejes, medidas, rótulos, {{valores}}) y punto y coma entre las coordenadas de un par. decimal: punto vuelve al de por defecto.
Reglas
- curva { color: azul }
- Por tipo: punto, segmento, semirrecta, recta, vector, curva, circunferencia, elipse, arco, polígono, región, ángulo, eje, cuadrícula, texto (también en plural). Varias propiedades, con «;» o una por línea; la coma no las separa: «grosor: grueso, color: azul» se lee como un solo valor y da error.
- A, f { color: rojo }
- Por nombre: los del script y los vértices de una figura; un lado (AB) no es un objeto aparte: el borde entero va con el nombre de la figura. Un objeto que se llama como un tipo, su plural o un alias (curva, recta, área, fuerza…) no recibe reglas por su nombre: la regla da error y pide otro nombre. La cascada: lo que la línea del DSL ya dice (color=, punteado, fill=) > regla por nombre > regla por tipo > estilo estándar; entre reglas iguales, la última.
- elipse { relleno: translúcido amarillo }
- Una elipse es una curva cerrada: le llegan las reglas de curva (su trazo) y las de elipse, que además la rellenan como a una circunferencia (relleno, opacidad, borde). En el plano cartesiano todavía no se rellena: avisa y aplica el trazo.
- P { marcador: ninguno; rótulo: no }
- Esconde un punto: sin marca ni nombre, sigue en la figura y construyendo. Con el nombre de una colección del plano, todos sus puntos.
- k, r { oculto: sí }
- Esconde un objeto y lo que lo acompaña: no se dibuja y sigue construyendo. En geometría y física no cuenta para el encuadre. En el plano: puntos, curvas, cónicas, rectas, polígonos, áreas y notas (texto { oculto: sí }); lo que está sobre ellos o los corta sigue en su lugar. La región de una inecuación no: «relleno: ninguno». eje { oculto: sí } quita ejes y números. También visible: no.
Propiedades
- grosor: grueso
- fino, medio, normal, grueso (1 · 1,5 · 2 · 3 px, la escala de TikZ) o un número en px.
- línea: punto-raya
- continua, discontinua, puntos, punto-raya. El patrón se escala con el grosor.
- color: rojo
- Un nombre (rojo, verde, azul, amarillo, naranja, morado, rosa, celeste, gris, negro, blanco, marrón; también en inglés) o un hexadecimal: #dc2626 o dc2626. En un polígono, una circunferencia o una elipse es el borde; en una región, el relleno.
- marcador: cuadrado
- lleno, hueco, cuadrado, cruz o ninguno (sin marca). Solo puntos.
- radio: 5
- El tamaño del punto, en px.
- rótulo: no
- Esconde el nombre del punto; «rótulo: sí» lo devuelve. En el plano, un label() de la línea manda. Solo puntos.
- relleno: translúcido celeste
- ninguno, sólido, translúcido, rayado, puntos (con un color si quieres) o un color solo. Polígonos, circunferencias, elipses y regiones; en el plano cartesiano, polígonos y regiones.
- relleno: degradado(blanco, azul, 90)
- Degradado lineal de un color al otro; el ángulo, en grados, en el sentido de la pantalla: 0, de izquierda a derecha; 90, de arriba hacia abajo.
- relleno: radial(blanco, azul)
- Degradado del centro al borde.
- opacidad: 0.5
- La del relleno (en la cuadrícula, la de sus líneas): de 0 a 1, o un porcentaje (50%). En una región también la de su contorno.
- borde: ninguno
- Sin contorno: polígonos, circunferencias, elipses y regiones de geometría.
/qf-dsl. Cada nombre se define una vez y puede reutilizarse. Escribe /qf-dsl help en el asistente para ver la referencia del lienzo activo.