Muestra las diferencias entre dos versiones de la página.
| Ambos lados, revisión anterior Revisión previa Próxima revisión | Revisión previa | ||
|
numbers:graphics [2010/04/03 17:58] alfred |
numbers:graphics [2020/05/09 09:25] (actual) |
||
|---|---|---|---|
| Línea 1: | Línea 1: | ||
| ====== Gráficos ====== | ====== Gráficos ====== | ||
| + | |||
| ===== Geometría ===== | ===== Geometría ===== | ||
| - | ===== Transformaciones ===== | ||
| + | |||
| + | |||
| + | ==== Problemas geométricos comunes ==== | ||
| + | * [[http://www.devmag.org.za/articles/245-BASIC-VECTOR-RECIPES/#topall]] | ||
| + | Ampliaremos la siguiente clase en [[highlevel:processing|Processing]]: | ||
| + | <code java> | ||
| + | class Point { | ||
| + | int x, y; | ||
| + | Point (int x, int y) { | ||
| + | this.x = x; | ||
| + | this.y = y; | ||
| + | } | ||
| + | void draw () { | ||
| + | point (x, y); | ||
| + | } | ||
| + | } | ||
| + | class Line { | ||
| + | Point p1, p2; | ||
| + | Line (Point p1, Point p2) { | ||
| + | this.p1 = new Point(p1.x, p1.y); | ||
| + | this.p2 = new Point(p2.x, p2.y); | ||
| + | } | ||
| + | void draw () { | ||
| + | line(p1.x, p1.y, p2.x, p2.y); | ||
| + | } | ||
| + | } | ||
| + | </code> | ||
| + | * **Distancia entre dos puntos**. //En la clase Point//: | ||
| + | <code java> | ||
| + | float distance (Point p) { | ||
| + | // Resta y magnitud de dos vectores | ||
| + | int subX = this.x - p.x; | ||
| + | int subY = this.y - p.y; | ||
| + | return sqrt(pow(subX,2) + pow(subY,2)); | ||
| + | } | ||
| + | </code> | ||
| + | * **Distancia entre un punto y una línea**, el siguiente código devuelve la distancia entre un punto P a la lína que pasa entre A y B: | ||
| + | <code java> | ||
| + | public double pointToLineDistance(Point A, Point B, Point P) | ||
| + | { | ||
| + | double normalLength = Math.sqrt((B.x - A.x) * (B.x - A.x) + (B.y - A.y) * (B.y - A.y)); | ||
| + | return Math.abs((P.x - A.x) * (B.y - A.y) - (P.y - A.y) * (B.x - A.x)) / normalLength; | ||
| + | } | ||
| + | </code> | ||
| + | **Saber si dos líneas son paralelas** | ||
| + | **Saber si dos líneas son perpendiculares** \\ | ||
| + | **Teniendo dos puntos y una línea, están los puntos al mismo lado de la línea?** \\ | ||
| + | **Está la línea sobre dos puntos?** \\ | ||
| + | **Un punto está en el ángulo de visión?** \\ | ||
| + | |||
| + | |||
| + | ===== Transformaciones ===== | ||
| + | |||
| + | ==== Traslación ==== | ||
| + | {{numbers:graf:translacion.png?300|}} | ||
| + | === Por suma === | ||
| + | Trasladaremos la posición (20, 30) unas (50, -100) posiciones: \\ | ||
| + | {{numbers:graf:translacion_por_suma.png|}} | ||
| + | === Por multiplicación === | ||
| + | Trasladaremos la posición (20, 30) unas (50, -100) veces: \\ | ||
| + | {{numbers:graf:translacion_por_multiplicacion.png|}} | ||
| Línea 11: | Línea 72: | ||
| + | ==== Rotación ==== | ||
| + | === Rotación 2d === | ||
| + | La multiplicación de un vector 2d por la siguiente matriz: \\ | ||
| + | <m> | ||
| + | delim{[} { matrix{2}{2}{{cos(alpha)} {-sen(alpha)} {sen(alpha)} {cos(alpha)} } } {]} | ||
| + | </m> \\ | ||
| + | devolverá otro vector 2d que será el equivalente al primero pero rotado //alpha// radianes. | ||
| + | === Rotación 3d (X, Y, Z) === | ||
| + | Se utilizarán vectores de 3 dimensiones (o de cuatro con el último término a 0). \\ | ||
| + | :?: No tengo claro cual es cual: \\ | ||
| + | <m> | ||
| + | delim{[} { matrix{4}{4}{ 1 0 0 0 0 {cos(alpha)} {-sen(alpha)} 0 0 {sen(alpha)} {cos(alpha)} 0 0 0 0 1 } } {]} | ||
| + | </m> \\ | ||
| + | <m> | ||
| + | delim{[} { matrix{4}{4}{ {cos(alpha)} 0 {sen(alpha)} 0 0 1 0 0 {-sen(alpha)} 0 {cos(alpha)} 0 0 0 0 1 } } {]} | ||
| + | </m> \\ | ||
| + | <m> | ||
| + | delim{[} { matrix{4}{4}{ {cos(alpha)} {-sen(alpha)} 0 0 {sen(alpha)} {cos(alpha)} 0 0 0 0 0 1 } } {]} | ||
| + | </m> | ||
| + | ==== Escalado ==== | ||
| ===== Animaciones ===== | ===== Animaciones ===== | ||
| + | |||
| + | ==== Aceleración mediante vectores ==== | ||
| + | * [[numbers:maths#vectores|Operaciones con vectores]] | ||
| + | Para los ejemplos se ha utilizado el lenguaje [[highlevel:processing|Processing]] y la [[highlevel:processing#otras_clases|clase PVector]], utilizaremos tres vectores: uno para la posición, otro para la velocidad y otro para la aceleración. \\ | ||
| + | La parte más importante del código es la clase ''Mover'', esta tiene cuatro métodos: el constructor que inicializa los vectores e indica un máximo de velocidad, ''update'' que es con la que jugaremos para modificar la velocidad, ''display'' que mostrará la pelota según la posición actualy ''checkEdges'' que se encarga de controlar cuando la pelota sale de los bordes. La función ''setup'' inicializa la vista y el objeto ''Mover'' y la función ''update'' actualiza la vista. \\ \\ | ||
| + | Para crear una **aceleración constante** simplemente debemos ir sumando la aceleración a la velocidad y la velocidad a la posición. Limitaremos la velocidad a ''maxSpeed''. | ||
| + | <code java> | ||
| + | Mover mover; | ||
| + | |||
| + | void setup() { | ||
| + | size(200,200); | ||
| + | smooth(); | ||
| + | background(255); | ||
| + | mover = new Mover(); | ||
| + | } | ||
| + | |||
| + | void draw() { | ||
| + | clean(); | ||
| + | mover.update(); | ||
| + | mover.checkEdges(); | ||
| + | mover.display(); | ||
| + | } | ||
| + | |||
| + | void clean () { | ||
| + | noStroke(); | ||
| + | fill(255,10); | ||
| + | rect(0,0,width,height); | ||
| + | } | ||
| + | |||
| + | class Mover { | ||
| + | PVector location; | ||
| + | PVector velocity; | ||
| + | PVector acceleration; | ||
| + | float maxSpeed; | ||
| + | |||
| + | Mover() { | ||
| + | location = new PVector(width/2,height/2); | ||
| + | velocity = new PVector(0, 0); | ||
| + | acceleration = new PVector(-0.001,0.01); | ||
| + | maxSpeed = 10.0; | ||
| + | } | ||
| + | |||
| + | void update() { | ||
| + | velocity.add(acceleration); | ||
| + | velocity.limit(maxSpeed); | ||
| + | location.add(velocity); | ||
| + | } | ||
| + | |||
| + | void display() { | ||
| + | stroke(0); | ||
| + | fill(175); | ||
| + | ellipse(location.x,location.y,16,16); | ||
| + | } | ||
| + | |||
| + | void checkEdges() { | ||
| + | if (location.x > width) { | ||
| + | location.x = 0; | ||
| + | } else if (location.x < 0) { | ||
| + | location.x = width; | ||
| + | } | ||
| + | if (location.y > height) { | ||
| + | location.y = 0; | ||
| + | } else if (location.y < 0) { | ||
| + | location.y = height; | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | </code> | ||
| + | Crear una **aceleración aleatoria** es muy sencillo, en el ''update'' crearemos un nuevo vector con valores aleatorios y que asignaremos a la aceleración. | ||
| + | <code java> | ||
| + | acceleration = new PVector(random(-1,1),random(-1,1)); | ||
| + | </code> | ||
| + | Para realizar una aceleración condicionada por la distancia a la que se encuentra la pelota del mouse necesitamos un nuevo vector que nos indique la dirección hacia donde está el mouse, este nuevo vector será ''dir'' y lo creamos a partir de restar la posición del ratón y la posición de la bola. Luego normalizaremos el vector (esto nos creará un vector "proporcional" a la distancia) y lo multiplicaremos por un escalar (''0.2'' en nuestro caso). | ||
| + | <code java> | ||
| + | maxSpeed = 4.0; | ||
| + | |||
| + | void update() { | ||
| + | PVector mouse = new PVector(mouseX,mouseY); | ||
| + | PVector dir = PVector.sub(mouse,location); | ||
| + | dir.normalize(); | ||
| + | dir.mult(0.2); | ||
| + | acceleration = dir; | ||
| + | |||
| + | velocity.add(acceleration); | ||
| + | velocity.limit(maxSpeed); | ||
| + | location.add(velocity); | ||
| + | } | ||
| + | </code> | ||
| Línea 114: | Línea 283: | ||
| * [[http://freespace.virgin.net/hugo.elias/models/m_perlin.htm]] | * [[http://freespace.virgin.net/hugo.elias/models/m_perlin.htm]] | ||
| * [[http://devmag.org.za/articles/48-HOW-TO-USE-PERLIN-NOISE-IN-YOUR-GAMES/2/#top1]] | * [[http://devmag.org.za/articles/48-HOW-TO-USE-PERLIN-NOISE-IN-YOUR-GAMES/2/#top1]] | ||
| + | |||
| + | ===== Ecuaciones de formas ===== | ||
| + | ==== Elipse ==== | ||
| + | <code python> | ||
| + | import pygame | ||
| + | from pygame.locals import * | ||
| + | import sys | ||
| + | import math | ||
| + | w = 640 | ||
| + | h = 489 | ||
| + | screen = pygame.display.set_mode((w,h)) | ||
| + | |||
| + | sampling = 50 | ||
| + | r1 = 100 | ||
| + | r2 = 160 | ||
| + | |||
| + | def drawPoint (x,y, c=(255,0,0)): | ||
| + | centX = w/2 | ||
| + | centY = h/2 | ||
| + | nx = centX + x | ||
| + | ny = centY + y | ||
| + | pygame.draw.circle(screen, c, (int(nx), int(ny)), 1) | ||
| + | |||
| + | for i in range(sampling): | ||
| + | theta = i * (2. * 3.1421)/sampling | ||
| + | cosTheta = math.cos(theta) | ||
| + | sinTheta = math.sin(theta) | ||
| + | tmp1 = (cosTheta*cosTheta)/(r2*r2) | ||
| + | tmp2 = (sinTheta * sinTheta)/(r1*r1) | ||
| + | tmp = math.sqrt(tmp1+tmp2) | ||
| + | drawPoint(cosTheta/tmp, sinTheta/tmp) | ||
| + | |||
| + | pygame.display.flip() | ||
| + | |||
| + | while True: | ||
| + | for event in pygame.event.get(): | ||
| + | if event.type == QUIT: | ||
| + | sys.exit() | ||
| + | pygame.display.update() | ||
| + | </code> | ||