{"id":1961,"date":"2019-07-10T13:18:16","date_gmt":"2019-07-10T11:18:16","guid":{"rendered":"http:\/\/disseny-test.uoc.edu\/materials\/programacio\/?page_id=1961"},"modified":"2019-08-17T13:35:36","modified_gmt":"2019-08-17T11:35:36","slug":"2-3-3-traslacion-rotacion-y-escala","status":"publish","type":"page","link":"http:\/\/disseny-test.uoc.edu\/materials\/programacio\/es\/2-3-3-traslacion-rotacion-y-escala\/","title":{"rendered":"2.3.3. Traslaci\u00f3n, rotaci\u00f3n y escala"},"content":{"rendered":"<p>Hasta ahora hemos visto c\u00f3mo poner formas gr\u00e1ficas en el <em>canvas <\/em>usando las coordenadas donde las queremos poner. Siempre hemos partido de que el punto (0, 0) (el origen de coordenadas) se encuentra en el v\u00e9rtice superior izquierda, pero con p5.js podemos decidir en qu\u00e9 lugar del <em>canvas<\/em> situamos el punto (0, 0). En el cap\u00edtulo 6 del libro se explica c\u00f3mo podemos mover el origen de coordenadas. Moviendo el origen de coordenadas moveremos las formas que tenemos dibujadas, dado que las habremos dibujado a partir del origen de coordenadas. Por lo tanto, esto ser\u00e1 \u00fatil para mover formas complejas creadas a partir de varias formas simples.<\/p>\n<p>Veremos tres maneras de hacer este cambio del origen de coordenadas.<\/p>\n<h2><strong>Traslaci\u00f3n<\/strong><\/h2>\n<p>La opci\u00f3n m\u00e1s sencilla para mover el origen de coordenadas es la <strong>traslaci\u00f3n<\/strong>. Consiste en desplazarlo un determinado n\u00famero de p\u00edxeles. Estos dos ejemplos son bastante claros:<\/p>\n<p><img loading=\"lazy\" class=\"alignnone size-full wp-image-237\" src=\"http:\/\/disseny-test.uoc.edu\/materials\/programacio\/wp-content\/uploads\/sites\/17\/2019\/07\/PID_00258586_2_019.jpg\" alt=\"\" width=\"634\" height=\"351\" srcset=\"http:\/\/disseny-test.uoc.edu\/materials\/programacio\/wp-content\/uploads\/sites\/17\/2019\/07\/PID_00258586_2_019.jpg 634w, http:\/\/disseny-test.uoc.edu\/materials\/programacio\/wp-content\/uploads\/sites\/17\/2019\/07\/PID_00258586_2_019-300x166.jpg 300w\" sizes=\"(max-width: 634px) 100vw, 634px\" \/><\/p>\n<p>La funci\u00f3n que usamos para determinar d\u00f3nde tenemos el origen de coordenadas es <span style=\"font-family: Courier, Arial;\"><a href=\"https:\/\/p5js.org\/es\/reference\/#\/p5\/translate\" target=\"_blank\" rel=\"noopener\">translate()<\/a><\/span>. Esta instrucci\u00f3n mueve el origen de coordenadas desde la posici\u00f3n actual a la posici\u00f3n indicada en sus par\u00e1metros. As\u00ed:<\/p>\n<pre>translate(40,20);<\/pre>\n<p>Mueve el origen de coordenadas a la posici\u00f3n (40,\u00a0 20).<\/p>\n<p>Atenci\u00f3n, porque, dado que el origen de coordenadas se mueve a partir de su posici\u00f3n actual, si ponemos dos <span style=\"font-family: Courier, Arial;\">translate()<\/span> seguidos el segundo coger\u00e1 como origen de coordenadas el que seleccion\u00f3 el primero.<\/p>\n<p>Y un detalle m\u00e1s. El origen de coordenadas se restablece (vuelve a su lugar) cada vez que se vuelve a ejecutar la funci\u00f3n <span style=\"font-family: Courier, Arial;\">draw()<\/span> (que, como ya sabemos, se ejecuta 50 veces por segundo).<\/p>\n<p>Este ejemplo puede ser bastante aclaratorio:<\/p>\n<pre>function setup() {\r\n  createCanvas(200, 200);\r\n}\r\n\r\nfunction draw() {\r\n  background(220);\r\n    for (var i = 10; i &lt; 400; i += 10){ \/\/ Dibujamos las l\u00edneas\r\n  \t line(i,0,i,height);   \/\/ Verticales\r\n  \t line(0,i,width,i);    \/\/ Horizontales\r\n    }\r\n    fill(255,0,0);\r\n    rect(20,20,20,20);\r\n    translate(20,20);\r\n    fill(0,255,0);\r\n    rect(20,20,20,20);\r\n    fill(0,0,255);\r\n    translate(20,20);\r\n    rect(20,20,20,20);\r\n}\r\n<\/pre>\n<p>Si lo ejecutamos este es el resultado:<\/p>\n<p><img loading=\"lazy\" class=\"alignnone size-full wp-image-242\" src=\"http:\/\/disseny-test.uoc.edu\/materials\/programacio\/wp-content\/uploads\/sites\/17\/2019\/07\/PID_00258586_2_027.jpg\" alt=\"\" width=\"207\" height=\"209\" srcset=\"http:\/\/disseny-test.uoc.edu\/materials\/programacio\/wp-content\/uploads\/sites\/17\/2019\/07\/PID_00258586_2_027.jpg 207w, http:\/\/disseny-test.uoc.edu\/materials\/programacio\/wp-content\/uploads\/sites\/17\/2019\/07\/PID_00258586_2_027-150x150.jpg 150w\" sizes=\"(max-width: 207px) 100vw, 207px\" \/><\/p>\n<p>Si nos fijamos en el c\u00f3digo, el dibujo del rect\u00e1ngulo es siempre el mismo:\u00a0<span style=\"font-family: Courier, Arial;\">rect(20,20,20,20);<\/span> lo que cambiamos es que trasladamos el origen de coordenadas cada vez. Pero, adem\u00e1s, tambi\u00e9n el cambio del origen de coordenadas es siempre el mismo <span style=\"font-family: Courier, Arial;\">translate(20,20);<\/span> porque, como he visto antes, el segundo cambio parte del origen de coordenadas que ha seleccionado primero.<\/p>\n<p>As\u00ed, el primer rect\u00e1ngulo se dibuja en la posici\u00f3n (20, 20), el segundo en la (40, 40) y el tercero en la (60, 60).<\/p>\n<p>Ahora que ya hemos visto c\u00f3mo funciona la funci\u00f3n\u00a0<span style=\"font-family: Courier, Arial;\">translate()<\/span>, ya nos podemos poner con los ejemplos del libro.<\/p>\n<p>El 6-1 es muy sencillo: usamos la posici\u00f3n del rat\u00f3n para determinar el nuevo origen de coordenadas. De este modo, al dibujar el cuadrado, se dibuja all\u00e1 donde est\u00e1 el rat\u00f3n.<\/p>\n<p>En el 6-2 se hacen dos traslaciones, de forma que se dibujan dos cuadrados ligeramente separados. Bien es verdad que una vez tenemos claro el funcionamiento de la funci\u00f3n\u00a0<span style=\"font-family: Courier, Arial;\">translate()<\/span>, estos dos ejemplos son muy f\u00e1ciles de entender.<\/p>\n<h2><strong>Rotaci\u00f3n<\/strong><\/h2>\n<p><strong>Rotar<\/strong> es hacer girar un objeto. En el caso de p5.js, lo que haremos girar es el origen de coordenadas. La funci\u00f3n que usamos para hacer esta rotaci\u00f3n es <span style=\"font-family: Courier, Arial;\"><a href=\"https:\/\/p5js.org\/es\/reference\/#\/p5\/rotate\" target=\"_blank\" rel=\"noopener\">rotate()<\/a><\/span>.<\/p>\n<p>Como estamos hablando de hacer un giro, el par\u00e1metro que le pasaremos a la funci\u00f3n <span style=\"font-family: Courier, Arial;\">rotate()<\/span> ser\u00e1n unos grados, normalmente en radianes, a pesar de que podemos usar grados. En este punto vale la pena revisar, en la gu\u00eda del reto 2, la explicaci\u00f3n de la funci\u00f3n <span style=\"font-family: Courier, Arial;\">arc()<\/span>.<\/p>\n<p>Mirad este ejemplo:<\/p>\n<pre>function setup() {\r\n  createCanvas(200, 200);\r\n}\r\nfunction draw() {\r\n  background(220);\r\n  translate(100,100)\r\n  for (var i=0;i&lt;16;i++){\r\n    line(20, 20, 40, 40);\r\n    rotate(QUARTER_PI\/2.0);\r\n  }\r\n}<\/pre>\n<p>Dibujad esto:<\/p>\n<p><img loading=\"lazy\" class=\"alignnone size-full wp-image-239\" src=\"http:\/\/disseny-test.uoc.edu\/materials\/programacio\/wp-content\/uploads\/sites\/17\/2019\/07\/PID_00258586_2_023.jpg\" alt=\"\" width=\"208\" height=\"207\" srcset=\"http:\/\/disseny-test.uoc.edu\/materials\/programacio\/wp-content\/uploads\/sites\/17\/2019\/07\/PID_00258586_2_023.jpg 208w, http:\/\/disseny-test.uoc.edu\/materials\/programacio\/wp-content\/uploads\/sites\/17\/2019\/07\/PID_00258586_2_023-150x150.jpg 150w\" sizes=\"(max-width: 208px) 100vw, 208px\" \/><\/p>\n<p>Lo primero que hacemos es trasladar el origen de coordenadas al centro del <em>canvas<\/em>.<\/p>\n<p>A continuaci\u00f3n pintamos una l\u00ednea y rotamos, pintamos l\u00ednea y rotamos. As\u00ed 16 veces hasta completar el c\u00edrculo.<\/p>\n<p>Como hab\u00edamos visto en el apartado anterior, los desplazamientos del origen de coordenadas son acumulativos.<\/p>\n<p>Una vez entendido c\u00f3mo funciona la funci\u00f3n <span style=\"font-family: Courier, Arial;\">rotate()<\/span> podemos ver los ejemplos del libro.<\/p>\n<p>El 6-3 hace una rotaci\u00f3n a partir de la posici\u00f3n <strong>x<\/strong> del rat\u00f3n. Dibujamos el cuadrado y empezamos a hacer la rotaci\u00f3n a partir de la posici\u00f3n (0, 0) actual.<\/p>\n<p>En este ejemplo el libro da una explicaci\u00f3n que no es muy real. Dice que <span style=\"font-family: Courier, Arial;\">mouseX<\/span> solo puede tomar valores de 0 a 120 (el tama\u00f1o del <em>canvas<\/em>), pero esto ya hemos visto que no es as\u00ed, pues guarda el valor de la posici\u00f3n\u00a0<strong>x<\/strong> del rat\u00f3n incluso cuando el rat\u00f3n est\u00e1 fuera del <em>canvas<\/em>.<\/p>\n<p>El ejemplo 6-4 es muy parecido. Pero, en este caso, lo que se ha hecho es situar el inicio del cuadrado fuera del <em>canvas<\/em>, de forma que el origen de coordenadas queda en medio del rect\u00e1ngulo. As\u00ed da la sensaci\u00f3n de que el rect\u00e1ngulo gira sobre su eje. Una manera diferente de hacer lo mismo ser\u00eda usando la funci\u00f3n\u00a0<span style=\"font-family: Courier, Arial;\"><a href=\"https:\/\/p5js.org\/es\/reference\/#\/p5\/rectMode\" target=\"_blank\" rel=\"noopener\">rectMode()<\/a><\/span> que nos permite definir c\u00f3mo se dibuja el rect\u00e1ngulo y dibujarlo a partir de su centro.<\/p>\n<p>Modificad este ejemplo para que el origen de coordenadas quede en medio del <em>canvas<\/em>. Usad <span style=\"font-family: Courier, Arial;\">rectMode()<\/span> para dibujar el rect\u00e1ngulo.<\/p>\n<p>El ejemplo 6-5 genera un efecto curioso. El cuadro va rotando continuamente y, a la vez que movemos el rat\u00f3n, vamos dibujando cuadrados. En este caso, la variable <span style=\"font-family: Courier, Arial;\">\u00e1ngulo<\/span> es la que determina el \u00e1ngulo en que se rota el cuadrado. Recordad que cada vez que se ejecuta la funci\u00f3n <span style=\"font-family: Courier, Arial;\">draw()<\/span> se vuelve a poner el origen de coordenadas en su lugar. Por eso necesitamos guardar el \u00e1ngulo en una variable.<\/p>\n<p>En este caso (y lo veremos en el ejemplo siguiente) es importante el orden en que llamamos a las funciones <span style=\"font-family: Courier, Arial;\">translate()<\/span> y <span style=\"font-family: Courier, Arial;\">rotate()<\/span> porque, recordad, dentro de la funci\u00f3n <span style=\"font-family: Courier, Arial;\">draw()<\/span> los cambios en su origen de coordenadas son acumulativos. As\u00ed, al hacer el <span style=\"font-family: Courier, Arial;\">rotate()<\/span> en segundo t\u00e9rmino, lo que hacemos es que el cuadrado est\u00e9 continuamente rotando, pero solo se mueve cuando movemos el rat\u00f3n.<\/p>\n<p>El ejemplo 6-6 cambia el orden, primero hace el <span style=\"font-family: Courier, Arial;\">rotate()<\/span> y despu\u00e9s el <span style=\"font-family: Courier, Arial;\">translate()<\/span>. La diferencia es notable. Ahora el cuadrado se est\u00e1 moviendo continuamente haciendo un c\u00edrculo. Y el movimiento del rat\u00f3n solo determina cu\u00e1n grande es el c\u00edrculo que estamos dibujando.<\/p>\n<p>El ejemplo 6-7 puede parecer complejo, pero en la pr\u00e1ctica solo usa funciones que ya hemos visto. Define tres variables:<\/p>\n<pre>var angle = 0.0;\r\nvar angleDirection = 1;\r\nvar speed = 0.005;<\/pre>\n<p>La variable <span style=\"font-family: Courier, Arial;\">\u00e1ngulo<\/span> determina el \u00e1ngulo que hay que usar en cada momento. Es la misma variable (o al menos se usa por el mismo motivo) que la que ya hab\u00edamos usado en un ejemplo anterior.<\/p>\n<p>La variable <span style=\"font-family: Courier, Arial;\">angleDirection<\/span> se usa para determinar si el brazo va en una direcci\u00f3n o en la contraria. Cambia su valor a -1 cuando se llega al tope determinado.<\/p>\n<p>La variable <span style=\"font-family: Courier, Arial;\">speed<\/span> determina la velocidad a la que se mueve el brazo.<\/p>\n<p>Este ejemplo usa la funci\u00f3n\u00a0<span style=\"font-family: Courier, Arial;\"><a href=\"https:\/\/p5js.org\/es\/reference\/#\/p5\/strokeWeight\" target=\"_blank\" rel=\"noopener\">strokeWeight()<\/a><\/span> que lo que hace es determinar la anchura de la l\u00ednea que se dibujar\u00e1 a continuaci\u00f3n. Y el ejemplo no tiene m\u00e1s misterio.<\/p>\n<h2><strong>Escala<\/strong><\/h2>\n<p>El escalado es el cambio de tama\u00f1o de un objeto. Con la funci\u00f3n <span style=\"font-family: Courier, Arial;\">scale()<\/span> lo que podemos hacer es cambiar el tama\u00f1o de las coordenadas del <em>canvas<\/em>, de forma que no habr\u00e1 una correspondencia entre los p\u00edxeles de la pantalla y los p\u00edxeles del <em>canvas<\/em>.<\/p>\n<p>Recuperamos este ejemplo que hemos visto antes. Pero a\u00f1adimos una nueva variable y una nueva l\u00ednea:<\/p>\n<pre>var escala = 2;  \/\/ <strong>Variable a\u00f1adida<\/strong>\r\n\r\nfunction setup() {\r\n  createCanvas(200, 200);\r\n}\r\n\r\nfunction draw() {\r\n  background(220);\r\n  scale(escala);  \/\/ <strong>Llama a la funci\u00f3n scale<\/strong><strong>()<\/strong>\r\n  for (var i = 10; i &lt; 400; i += 10){ \/\/ Dibujamos las l\u00edneas\r\n    line(i,0,i,height);   \/\/ Verticales\r\n    line(0,i,width,i);    \/\/ Horizontales\r\n  }\r\n  fill(255,0,0);\r\n  rect(20,20,20,20);\r\n  translate(20,20);\r\n  fill(0,255,0);\r\n  rect(20,20,20,20);\r\n  fill(0,0,255);\r\n  translate(20,20);\r\n  rect(20,20,20,20);\r\n}<\/pre>\n<p>Variad el valor de la variable escala y comprobad lo que pasa. A continuaci\u00f3n ten\u00e9is tres capturas de pantalla con tres casos diferentes:<\/p>\n<p><img loading=\"lazy\" class=\"alignnone wp-image-2123 size-full\" src=\"http:\/\/disseny-test.uoc.edu\/materials\/programacio\/wp-content\/uploads\/sites\/17\/2019\/07\/PID_00258586_2_024_2.jpg\" alt=\"\" width=\"727\" height=\"262\" srcset=\"http:\/\/disseny-test.uoc.edu\/materials\/programacio\/wp-content\/uploads\/sites\/17\/2019\/07\/PID_00258586_2_024_2.jpg 727w, http:\/\/disseny-test.uoc.edu\/materials\/programacio\/wp-content\/uploads\/sites\/17\/2019\/07\/PID_00258586_2_024_2-300x108.jpg 300w\" sizes=\"(max-width: 727px) 100vw, 727px\" \/><\/p>\n<p>El ejemplo 6-8 hace tambi\u00e9n escalado, pero usando el rat\u00f3n para controlarlo. Y el ejemplo 6-9 explica qu\u00e9 hay que hacer para evitar que las l\u00edneas tambi\u00e9n se hagan m\u00e1s gruesas.<\/p>\n<p>Con nuestro ejemplo haciendo este cambio (en rojo la l\u00ednea a\u00f1adida):<\/p>\n<pre>scale(escala);  \/\/ <strong>Llama a la funci\u00f3n scale<\/strong><strong>()<\/strong>\r\n<span style=\"color: red;\">strokeWeight(1.0 \/ escala);<\/span>\r\nfor (var i = 10; i &lt; 400; i += 10){ \/\/ Dibujamos las l\u00edneas<\/pre>\n<p><img loading=\"lazy\" class=\"alignnone wp-image-2128 size-full\" src=\"http:\/\/disseny-test.uoc.edu\/materials\/programacio\/wp-content\/uploads\/sites\/17\/2019\/07\/PID_00258586_2_025-1.jpg\" alt=\"\" width=\"727\" height=\"257\" srcset=\"http:\/\/disseny-test.uoc.edu\/materials\/programacio\/wp-content\/uploads\/sites\/17\/2019\/07\/PID_00258586_2_025-1.jpg 727w, http:\/\/disseny-test.uoc.edu\/materials\/programacio\/wp-content\/uploads\/sites\/17\/2019\/07\/PID_00258586_2_025-1-300x106.jpg 300w\" sizes=\"(max-width: 727px) 100vw, 727px\" \/>(con\u00a0<strong>escala = 5<\/strong>)<\/p>\n<h2><span style=\"font-family: Courier, Arial;\">push()<\/span> y <span style=\"font-family: Courier, Arial;\">pop()<\/span><\/h2>\n<p>Estas dos funciones nos permiten guardar la situaci\u00f3n actual del origen de coordenadas. <span style=\"font-family: Courier, Arial;\">push()<\/span> la guarda y <span style=\"font-family: Courier, Arial;\">pop()<\/span> la recupera. Puede ser \u00fatil en programas muy largos para volver a una versi\u00f3n anterior del origen de coordenadas. El ejemplo 6-10 hace una peque\u00f1a demostraci\u00f3n.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hasta ahora hemos visto c\u00f3mo poner formas gr\u00e1ficas en el canvas usando las coordenadas donde las queremos poner. Siempre hemos partido de que el punto (0, 0) (el origen de coordenadas) se encuentra en el v\u00e9rtice superior izquierda, pero con p5.js podemos decidir en qu\u00e9 lugar del canvas situamos el punto (0, 0). En el [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"inline_featured_image":false},"acf":[],"_links":{"self":[{"href":"http:\/\/disseny-test.uoc.edu\/materials\/programacio\/es\/wp-json\/wp\/v2\/pages\/1961"}],"collection":[{"href":"http:\/\/disseny-test.uoc.edu\/materials\/programacio\/es\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"http:\/\/disseny-test.uoc.edu\/materials\/programacio\/es\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"http:\/\/disseny-test.uoc.edu\/materials\/programacio\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/disseny-test.uoc.edu\/materials\/programacio\/es\/wp-json\/wp\/v2\/comments?post=1961"}],"version-history":[{"count":25,"href":"http:\/\/disseny-test.uoc.edu\/materials\/programacio\/es\/wp-json\/wp\/v2\/pages\/1961\/revisions"}],"predecessor-version":[{"id":3742,"href":"http:\/\/disseny-test.uoc.edu\/materials\/programacio\/es\/wp-json\/wp\/v2\/pages\/1961\/revisions\/3742"}],"wp:attachment":[{"href":"http:\/\/disseny-test.uoc.edu\/materials\/programacio\/es\/wp-json\/wp\/v2\/media?parent=1961"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}