Geometría Computacional La geometrı́a computacional es una rama de ciencia de la computación que estudia algoritmos para resolver problemas geométricos. Nos concetraremos en la representación y programación de algunos objetos y algoritmos en el plano cartesiano. Un punto sólo tiene posición y se representa con un par de coordenadas (x, y). Una lı́nea está definida por todos los puntos que satisfacen la ecuación ax + by + c = 0. Formas alternativas de escribir la ecuación: y = mx + n, donde m se conoce como la pendiente de la recta, y (0, n) es un punto de la recta. Jorge Baier Aranda, PUC 68 La misma ecuación se puede escribir dado un punto (x1, y1) y la pendiente: y − y1 = m(x − x1). Dado dos puntos (x1, y1) y (x2, y2), la ecuación es: y1 − y2 (x − x1). y − y1 = x1 − x2 o (y2 − y1)x + (x1 − x2)y + x2y1 − x1y2 = 0. También es frecuente escribir la ecuación de la forma x y + = 1, a b donde (a, 0) y (0, b) son puntos de la recta. El punto de intersección de dos rectas l1 : y = m1x + n1 y l2 : y = m2x + n2 es n2 − n1 n2 − n1 , m1 + n1 m1 − m2 m1 − m2 Jorge Baier Aranda, PUC 69 El ángulo que forman dos rectas no paralelas l1 : a1x + b1y + c1 y l2 : a2x + b2y + c2 = 0 está dado por a1b2 − a2b1 arctan a1a2 + b1b2 en caso de usar rectas con pendientes, el ángulo es el siguiente: 1 Si m es la pendiente de una recta, entonces − m es la pendiente de una recta perpendicular a ella. Jorge Baier Aranda, PUC 70 Segmentos, vectores y producto cruz Un segmento es un subconjunto de una lı́nea recta comprendido entre dos puntos de ella. Un vector es un segmento dirigido entre el origen y un punto del plano. Si p0 = (0, 0) y p1 = (x, y), entonces usamos la notación p~1 (o simplemente p1) → para hablar del segmento dirigido − p− 0 p1 . Jorge Baier Aranda, PUC 71 El producto cruz entre dos vectores p1 = (x, y) y p2 se define por x1 x2 p1 × p2 = y1 y2 y representa el área (con signo) del paralelógramo de la figura. y p1 + p2 p1 sentido horario p2 x Si p1 está en sentido horario desde p2 con respecto al origen, entonces p1 × p2 > 0. Si p1 × p2 = 0, entonces p1 y p2 son colineales con el origen. Jorge Baier Aranda, PUC 72 Pregunta: ¿cómo determinar si al recorrer los segmentos p0p1 y p1p2, desde p0 se debe doblar a la izquierda o a la derecha? p está en sentido horario desde − p−→ p , Respuesta: el giro será a la izquierda ssi − p−→ 1 2 1 0 es decir, ssi (p2 − p1) × (p0 − p1) > 0 Jorge Baier Aranda, PUC 73 Intersección de dos segmentos Es muy sencillo usar el producto cruz para determinar si dos segmentos se intersectan. La prueba se realiza en dos fases. En la primera (rechazo rápido) se revisa si los rectángulos más pequeños que contienen a los segmentos se intersectan. Si tenemos un segmento p1p2 (con p1 = (x1, y1), p2 = (x2, y2), entonces el rectángulo más pequeño que lo contiene es el de esquina inferior izquierda pI = (xI , yI ), donde xI = mı́n{x1, x2} y yI = mı́n{y1, y2}, y de esquina superior derecha pS = (xS , yS ), donde xS = máx{x1, x2} y yS = máx{y1, y2}. Jorge Baier Aranda, PUC 74 Dos rectángulos, representados por sus esquinas superior derecha e inferior izquierda, (p1I , p1S ) y (p2I , p2S ), se intersectan ssi (mı́n{x1S , x2S } ≥ máx{x1I , x2I }) ∧ (mı́n{yS1 , yS2 } ≥ máx{yI1, yI2}) Jorge Baier Aranda, PUC 75 La segunda fase consiste en determiar si los extremos del primer segmento quedan a lados opuestos del primero y vice versa. Esto se puede hacer fácilmente usando el producto cruz. Mirando la siguiente figura: p3 p2 p4 p1 Sabemos que para que los extremos de p3p4 queden a lados diferentes de p1p2, se tiene que dar que p3 − p1 y p4 − p1 estén en sentidos horarios distintos con respecto a p2 − p1. Ası́, basta con chequear que: ((p3 − p1) × (p2 − p1))((p4 − p1) × (p2 − p1)) ≤ 0 Jorge Baier Aranda, PUC 76 Para asegurarse que los segmentos se intersectan hay que verificar la misma condición, pero con respecto al otro segmento. ¿Como verificar si una secuencia de puntos hp0, . . . , pn−1i son los vértices de un polı́gono convexo? Respuesta: verificando que al recorrer los vértices no hayan vueltas a la derecha y a la izquierda, simultáneamente. Esto se puede hacer usando el producto cruz. Jorge Baier Aranda, PUC 77 Rayos horizontales Un rayo horizontal hacia la derecha desde p0 = (x0, y0) es el conjunto de puntos con coordenadas (x, y0), con x ≤ x0. La interesección entre un rayo horizontal hacia la derecha desde p0 y un segmento p1p2, con p1 = (x1, y1), p2 = (x2, y2) se puede haciendo la interesección entre el segmento p1p2 y el segmento p0p3 con p3 = (x0, máx{y0, y1, y2}) Jorge Baier Aranda, PUC 78 ¿Pertenece p a P ? Preguntarse si un punto p pertenece a un polı́gono P = hp0, . . . , pni es un problema sencillo si P es convexo. ¿Cómo lo hacemos? En un caso más general, tal vez no lo es tanto... El problema se puede enfrentar usando el teorema de la curva de Jordan, que simplemente dice que un polı́gono divide al plano en dos regiones, la interior y la exterior. Jorge Baier Aranda, PUC 79 Ası́, si dibujamos algún rayo que salga desde el punto, si éste atraviesa el borde un número impar de veces, entonces el punto está dentro del polı́gono. Al programar una rutina que verfifique esto, hay que tener en cuenta que el rayo podrı́a pasar por un vértice... Jorge Baier Aranda, PUC 80 Área de un Polígono Es sorprendentemente sencillo calcular el área de un polı́gono usando el producto cruz. La idea es elegir un punto arbitrario y sumar las áreas con signo de todos los triángulos definidos entre el punto arbitrario y una arista del polı́gono (se debe recorrer los vertices del polı́gono en orden horario o antihorario). Ası́ si P = hp0, . . . , pni es un polı́gono cualquiera, entonces n−1 1X A(P ) = (xiyi+1 − xi+1yi). 2 i=0 Jorge Baier Aranda, PUC 81 Triangulación de polígonos Aún cuando el área de un polı́gono cualquiera puede ser fácil de calcular, el problema de triangular un polı́gono puede ser relevante. El algoritmo de Van Gogh ataca este problema cortando orejas al polı́gono. Una oreja es un triángulo formado por dos aristas contiguas del polı́gono u una cuerda de éste. Para encontrar una oreja, basta con recorrer el polı́gono en sentido horario y encontrar un giro a la izquierda (esto se puede determinar con el producto cruz). Una vez encontrada la oreja, se eliminan las aristas del polı́gono y se agrega a la cuerda como una nueva arista. Jorge Baier Aranda, PUC 82