Introducción a PiQ Lang
PiQ Lang es el lenguaje en el que se escriben los diseños de ParametrIQ. Un dibujo de ParametrIQ CAD es un programa
de PiQ Lang: el archivo .piq es una lista de líneas de PiQ Lang, y todo lo que se dibuja con el ratón se guarda como
tales líneas. Esta introducción recorre el lenguaje desde el principio. No es una referencia completa: cada sección
enlaza con las páginas que sí lo son.
Dónde ejecutarlo
- El Playground: escriba un programa y ejecútelo. Cada instrucción se ejecuta por orden, y el
Playground muestra el valor de cada una o qué ha fallado. Un programa que dibuja puede descargarse como archivo
.piqy abrirse en ParametrIQ CAD. - La ventana Interactiva de ParametrIQ CAD: escriba una línea, pulse Enter y se ejecutará sobre el dibujo que tenga abierto.
- Un archivo
.piq: ParametrIQ CAD lo ejecuta, instrucción por instrucción, al abrirlo.
Cada uno de los ejemplos siguientes es un programa independiente. Después de cada uno se muestra lo que presenta el Playground al ejecutarlo.
Líneas y comentarios
Un programa es una lista de instrucciones: asignaciones, comandos y expresiones. Se ejecutan de arriba abajo, cada una
cuando se llega a ella. Normalmente cada instrucción ocupa su propia línea; para poner varias en una misma línea,
sepárelas con ;.
Una instrucción continúa más allá del final de la línea mientras quede abierto un paréntesis, corchete o llave ((,
[ o {). Así, una instrucción larga puede dividirse después de una coma, dentro de sus paréntesis.
// inicia un comentario, que llega hasta el final de la línea y se omite. Un comentario puede ocupar toda la línea o
seguir a una instrucción. Un // dentro de las comillas de una cadena forma parte de la cadena.
// The length of the lid
LID=120 // in millimetres
FLAP=40; TUCK=FLAP/2
SIZES={"A4":210,
"A3":297}
LID
SIZES["A3"]
LID → 120
SIZES["A3"] → 297
Escribir una expresión sola, como en las dos últimas líneas, la muestra con su valor. PRINT
muestra varios valores a la vez, cada uno con su expresión tal como la vuelve a leer el Playground (así, 7/2 se
muestra como 3 1/2).
Valores
Números
Un número puede escribirse como número entero, decimal, fracción, número mixto o en pies y pulgadas.
12
0.5
1/4
2 1/4
3'6"
12 → 12
0.5 → 0.5
1/4 → 1/4
2 1/4 → 2 1/4
3'6" → 3'6"
Las fracciones se mantienen exactas mientras se trabaja con fracciones y números enteros, y se muestran como números
mixtos; lo mismo ocurre con las funciones que pueden mantenerlas exactas (ABS, MIN, ROUND, SQRT(9/16) …). En
cuanto interviene un decimal, el resultado es decimal:
1/3 + 1/6
1/3 + 1
7/2
7.0/2
1/3 + 1/6 → 1/2
1/3 + 1 → 1 1/3
7/2 → 3 1/2
7.0/2 → 3.5
Los pies y pulgadas siguen siendo pies y pulgadas al sumarles pies y pulgadas, y al multiplicarlos o dividirlos por un número entero o una fracción; divididos por pies y pulgadas, dan cuántas veces cabe uno en el otro. Un decimal los convierte a las unidades del dibujo (milímetros en el Playground), y también lo hace un número simple sumado a ellos en un dibujo en milímetros (en un dibujo en pulgadas, el número son pulgadas). TOMM y TOIN convierten entre milímetros y pulgadas.
1'6" + 6"
2 * 1'
3' / 4
3' / 6"
2.5 * 1'
TOMM(1)
TOIN(25.4)
1'6" + 6" → 2'
2 * 1' → 2'
3' / 4 → 9"
3' / 6" → 6
2.5 * 1' → 762
TOMM(1) → 25.4
TOIN(25.4) → 1
Consulte Números para ver todas las formas de escribirlos.
Texto
El texto (una cadena) se escribe entre comillas dobles. + une textos, y un número unido a un texto se convierte en
texto. Dentro de las comillas, \n inicia una nueva línea, \" es una comilla y \\ una barra invertida.
"Panel " + "A"
"W=" + 5
"Panel " + "A" → "Panel A"
"W=" + 5 → "W=5"
TRUE y FALSE
Los dos valores lógicos, escritos TRUE y FALSE (en mayúsculas o minúsculas: true es TRUE). Las comparaciones
los producen, y &&, || y ! los combinan.
5 > 3
1 == 1.0
TRUE && !FALSE
5 > 3 → TRUE
1 == 1.0 → TRUE
TRUE && !FALSE → TRUE
Posiciones
Una posición es una X y una Y entre corchetes: [250,200]. Las posiciones pueden sumarse y restarse, multiplicarse
por un número y medirse. .X e .Y las descomponen.
[3,4] + [1,1]
2 * [3,4]
DISTANCE([0,0],[3,4])
[3,4].Y
[3,4] + [1,1] → [4,5]
2 * [3,4] → [6,8]
DISTANCE([0,0],[3,4]) → 5
[3,4].Y → 4
Una posición restada de otra es el desplazamiento entre ambas: una dirección. ANGLE da el ángulo de una dirección, y NORMALIZE hace que mida 1.
Variables
Una variable es un nombre para un valor, creado con =:
WIDTH=50
DEPTH=WIDTH/2
PRINT WIDTH, DEPTH
WIDTH → 50
DEPTH → 25
Definiciones, no copias
Una variable conserva su definición, no el valor que tenía cuando se creó. DEPTH=WIDTH/2 significa «la mitad de
WIDTH», siempre. Si cambia WIDTH, DEPTH se ajusta:
WIDTH=50
DEPTH=WIDTH/2
WIDTH=80
DEPTH
DEPTH → 40
Esto es lo que hace que un diseño sea paramétrico: todo un dibujo se define a partir de unas pocas variables, y al cambiarlas se vuelve a dibujar. A una variable se le puede dar una nueva definición en cualquier momento, incluso de otro tipo (texto donde había un número).
Como las líneas se ejecutan en orden, un nombre debe definirse antes de que una línea lo use. Y una definición no puede
ser circular (A=B+1 cuando B se define a partir de A): se rechaza, y la variable conserva su definición anterior.
B=A+1
A Not Defined
Nombres
Un nombre está formado por letras, dígitos y _, y empieza por una letra o _. Los nombres no distinguen mayúsculas
de minúsculas y se muestran en mayúsculas: width y WIDTH son la misma variable.
Un nombre no puede ser una de las palabras propias del lenguaje. Algunas son cortas y fáciles de elegir por accidente:
X e Y (las partes de una posición), y todos los nombres de comandos y funciones (LINE, ARC, SIN, LEFT,
SCALE, TEXT …). Elija nombres que digan lo que son (FLAP, LID_DEPTH, X1) y no tendrá este problema.
y=2
line 1:1 unexpected token
Etiquetas
Una variable puede tener una etiqueta, que indica para qué sirve, después de una coma. ParametrIQ CAD la muestra en el panel Variables y la pide por ese nombre.
FLAP=40,"Tuck flap depth"
LABEL cambia una etiqueta más adelante, y RENAME cambia el nombre de una variable en todos los lugares donde se usa.
Variables de tamaño y del sistema
Todo dibujo empieza con el tamaño de la caja, L, W y D (longitud, anchura y profundidad: variables normales que
puede cambiar), y con las variables del sistema, cuyos nombres empiezan por #: configuraciones como las unidades
(#U) y la capa actual, constantes (#PI) y los valores predeterminados de las cotas. Se enumeran en
Variables.
L
W
D
#U
#PI
L → 500
W → 400
D → 300
#U → MILLIMETERS
#PI → 3.141593
Operadores y funciones
La aritmética habitual, con *, / y % antes que + y -, y los paréntesis primero. % es el resto de la
división. Tiene el signo del divisor, de modo que A % 360 es un ángulo entre 0 y 360 sea cual sea A.
2+3*4
(2+3)*4
-2*3
17 % 5
-30 % 360
2+3*4 → 14
(2+3)*4 → 20
-2*3 → -6
17 % 5 → 2
-30 % 360 → 330
No hay operador de potencia: use POW (^ significa uno u otro, pero no ambos, para TRUE y
FALSE).
Las comparaciones (<, <=, >, >=, ==, !=) dan TRUE o FALSE. Después de operar, los decimales rara vez son
exactamente iguales, así que ~= los compara con un margen mínimo:
0.1+0.2 == 0.3
0.1+0.2 ~= 0.3
0.1+0.2 == 0.3 → FALSE
0.1+0.2 ~= 0.3 → TRUE
Elegir
test ? a : b es a cuando la condición es TRUE, y b en caso contrario. SWITCH busca un
valor en un diccionario o una lista, con un valor para cuando no está.
SIZE=7
SIZE > 5 ? "large" : "small"
SWITCH(SIZE,{1:"one",7:"seven"},"other")
SWITCH(1,{"zero","one","two"},"other")
SIZE > 5 ? "large" : "small" → "large"
SWITCH(SIZE,{1:"one",7:"seven"},"other") → "seven"
SWITCH(1,{"zero","one","two"},"other") → "one"
Listas y diccionarios
Una lista son valores entre llaves, {10,20,40}; sus elementos se numeran desde 0, así que WIDTHS[0] es el primero.
Un diccionario son claves y valores, {"A4":210,"A3":297}, y PAPER["A3"] es el valor de una clave. .COUNT indica
cuántos hay.
WIDTHS={10,20,40}
WIDTHS[2]
WIDTHS.COUNT
PAPER={"A4":210,"A3":297}
PAPER["A3"]
PAPER.KEYS
WIDTHS[2] → 40
WIDTHS.COUNT → 3
PAPER["A3"] → 297
PAPER.KEYS → {"A4","A3"}
Funciones
Una función se llama con sus argumentos entre paréntesis: SQRT(2), MAX(A,B). Hay funciones para números
(ROUND, MIN, CLAMP …), para ángulos y
trigonometría, para posiciones y direcciones, y para puntos sobre elementos. Las funciones trigonométricas trabajan en
radianes; DTOR y RTOD convierten desde y hacia grados.
SQRT(2)
MAX(3,7)
ROUND(3.5)
SIN(DTOR(30))
RTOD(ANGLE([1,1]))
SQRT(2) → 1.414214
MAX(3,7) → 7
ROUND(3.5) → 4
SIN(DTOR(30)) → 0.5
RTOD(ANGLE([1,1])) → 45
Todas las funciones se enumeran, con ejemplos, en Expresiones. También puede escribir sus propias funciones: consulte Funciones propias, más abajo.
Puntos
Un dibujo se construye sobre puntos, cuyo nombre es P y un número. Todo dibujo empieza con cuatro, las esquinas
de la caja: P0 en el origen, P1 a L a su derecha, P2 a W por encima de P1, y P3 a la izquierda de P2.
P0
P1
P2
P3
P0 → [0,0]
P1 → [500,0]
P2 → [500,400]
P3 → [0,400]
Un punto nuevo se crea como una variable y, como una variable, conserva su definición. Si se define a partir de otros puntos, los sigue:
P4=RIGHT(P0,100)
P5=UP(P4,W/2)
P6=POLAR(P5,45,50)
P7=ALONG(P0,P2,100)
L=600
P1
P5
P1 → [600,0]
P5 → [100,200]
LEFT, RIGHT, UP y DOWN avanzan en horizontal o en vertical; POLAR
avanza con un ángulo (en grados) y una distancia; ALONG avanza una distancia hacia otro punto;
LERP, una fracción del camino. Al establecer L se movió P1, ya que la definición de P1 es
RIGHT(P0,L).
A un punto se le puede dar una posición fija, P4=[100,0], pero un diseño solo es paramétrico donde sus puntos se
definen a partir de otros. Las herramientas de ParametrIQ CAD crean los puntos así por usted: consulte
Modos de forzado de cursor.
Dibujar
Los comandos añaden elementos al dibujo: líneas, arcos, curvas, texto, cotas … Cada uno se dibuja sobre puntos, de modo que se mueve cuando ellos se mueven.
FLAP=60,"Flap"
P4=UP(P3,FLAP)
P5=UP(P2,FLAP)
POLYLINE @1,[P0,P1,P2,P3],TRUE
LINE @2,P3,P4
LINE @3,P4,P5
LINE @4,P5,P2
P6=[250,200]
P7=LEFT(P6,50)
CIRCLE @5,P7,P6,TRUE
P8=[220,430]
TEXT @6,P8,"Lid",20,0
DIMHORIZONTAL @7,P0,P1,RIGHT
LENGTHOF(@3)
PERIMETEROF(@1)
AREAOF(@5)
LENGTHOF(@3) → 500
PERIMETEROF(@1) → 1800
AREAOF(@5) → 7853.981634
Un comando es una palabra clave seguida de sus argumentos, separados por comas. @1, @2 … dan nombre a los
elementos, para que las líneas posteriores puedan usarlos; si se omite el nombre, se elige uno automáticamente. Después
de los argumentos puede ir un número de capa (LINE P3,P4,1 dibuja en la capa 1, Hendido). Donde un comando admite un punto, admite el nombre de un punto: defina primero
el punto (P7=LEFT(P6,50)) y luego dibuje sobre él.
Los elementos pueden medirse, y pueden definirse puntos sobre ellos, de modo que un punto puede permanecer en el centro de una línea o donde se cruzan dos líneas: LENGTHOF, ONELEMENT, CROSSING, CENTEROF y el resto de Puntos sobre elementos.
P4=[250,0]
P5=[250,400]
LINE @1,P0,P2
LINE @2,P4,P5
P6=CROSSING(@1,@2,0)
P6
ONELEMENT(@1,0.5)
@1.END
P6 → [250,200]
ONELEMENT(@1,0.5) → [250,200]
@1.END → [500,400]
Todos los comandos se enumeran en Interactiva, y la configuración que puede tener cualquier elemento (capa, grosor de línea, oculto …) en Configuración de elementos.
Un diseño completo
En conjunto, unas pocas variables definen una pieza completa. Esta es la plancha de una bandeja: una base de L por
W, con hendidos, con una pared de altura WALL en cada lado y el contorno cortado. Al cambiar cualquier medida, la
plancha se vuelve a dibujar en consecuencia: aquí, la longitud.
WALL=40,"Wall height"
// the outer corners of the four walls
P4=DOWN(P0,WALL)
P5=DOWN(P1,WALL)
P6=RIGHT(P1,WALL)
P7=RIGHT(P2,WALL)
P8=UP(P2,WALL)
P9=UP(P3,WALL)
P10=LEFT(P3,WALL)
P11=LEFT(P0,WALL)
// the base, on the Crease layer (1); the outline, on the Cut layer (0)
POLYLINE @1,[P0,P1,P2,P3],TRUE,1
POLYLINE @2,[P0,P4,P5,P1,P6,P7,P2,P8,P9,P3,P10,P11],TRUE,0
L=300
PERIMETEROF(@1)
PERIMETEROF(@2)
PERIMETEROF(@1) → 1400
PERIMETEROF(@2) → 1720
Nada está en una posición fija excepto P0: cada esquina se calcula a partir del tamaño de la caja y de WALL, así que
la plancha es correcta para cualquier bandeja.
Mover puntos
TRANSFORM mueve puntos mediante una transformación: un desplazamiento, un giro, un cambio de escala, una simetría. Los puntos se redefinen a partir de donde estaban, así que siguen dependiendo de aquello a partir de lo cual se definieron.
P4=[100,100]
P5=[200,100]
TRANSFORM [P4,P5],TRANSLATE([0,50])
P4
P5
P4 → [100,150]
P5 → [200,150]
Bucles y condiciones
FOR, FOREACH y WHILE repiten un bloque de
instrucciones, entre BEGIN y END, e IF elige uno. Dentro de un bloque, las instrucciones se
ejecutan una tras otra, y cada elemento se crea a partir de los puntos tal como están en ese momento, de modo que un
bucle puede dibujar una fila de objetos sobre un punto que se mueve en cada vuelta. Un bloque sigue siendo paramétrico:
se vuelve a ejecutar cada vez que cambia el dibujo, así que aquí una caja más larga tiene más agujeros.
// a hole every 60 along the middle of the box, as many as fit
FOR I = 30 TO L - 30 STEP 60 BEGIN
P10 = [I, W/2]
P11 = RIGHT(P10, 10)
CIRCLE P11, P10, TRUE
END
IF L > 400 THEN BEGIN
LINE P0, P2
END
Lo que un bloque establece le pertenece (su P10 no es el del dibujo), y lo que crea pertenece al bloque. Consulte Bloques y control de flujo.
Funciones propias
FUNCTION define una función propia. La más sencilla es una sola expresión de sus argumentos, y se usa como cualquier otra función, en cualquier lugar donde vaya una expresión:
FUNCTION HYPOT(A,B) = SQRT(A*A+B*B)
HYPOT(3,4)
DIAGONAL=HYPOT(L,W)
DIAGONAL
HYPOT(3,4) → 5
DIAGONAL → 640.312424
DIAGONAL se define mediante la función, así que sigue a la caja cuando cambian L y W.
Una función también puede tener un bloque, entre BEGIN y END, que ejecuta una instrucción tras otra: puede
establecer sus propias variables, elegir con IF, repetir en bucle, llamar a otras funciones o a sí misma, y devolver
su valor con RETURN:
FUNCTION FACTORIAL(N) BEGIN
IF N <= 1 THEN BEGIN RETURN 1 END
RETURN N*FACTORIAL(N-1)
END
FACTORIAL(6)
FACTORIAL(6) → 720
Una función también puede crear geometría. Sus puntos y variables le pertenecen (su P1 no es el P1 del dibujo), y CALL dibuja lo que crea, de nuevo cada vez que cambia el dibujo. Esta dibuja una cruz que sigue a P2 allá donde se mueva:
FUNCTION MARK(C,S) BEGIN
P1 = C+[-S,0] ; P2 = C+[S,0] ; P3 = C+[0,-S] ; P4 = C+[0,S]
LINE P1, P2
LINE P3, P4
END
CALL MARK(P2,20)
Una función ve las variables del dibujo (L, W …) tal como están cuando se la llama, y las demás funciones. Puede
usarse antes de definirse, y definirla de nuevo con el mismo nombre la reemplaza.
Funciones de JavaScript
Una función también puede escribirse en JavaScript, entre <<< y >>>, para cálculos y
geometría que resultan más sencillos en un lenguaje de uso general. Se llama, se dibuja con CALL y se guarda igual que
cualquier otra función, y recibe las variables y los puntos del dibujo, y funciones para crear elementos:
FUNCTION RECTAREA(a,b) JAVASCRIPT <<< return a * b >>>
RECTAREA(L,W)
RECTAREA(L,W) → 200000
El Playground tiene ejemplos más extensos de ambas: Funciones propias y Funciones de JavaScript.
Dibujos dentro de dibujos
Un dibujo puede incluir otro como pieza: IMPORT lee un archivo .piq y lo coloca, y el
dibujo lo conserva como una PART. Las variables propias de la pieza que tienen el mismo nombre que
las del dibujo, como L, toman los valores del dibujo, de modo que una tapa dibujada para cualquier caja encaja en
esta. Un SWITCHPART contiene varias piezas y muestra la que elige una variable.
Siguientes pasos
- Expresiones: todos los operadores y funciones, con ejemplos.
- Interactiva: todos los comandos.
- ParametrIQ CAD: dibujar con el ratón, en el mismo lenguaje.