Una de las nociones fundamentales en la geometria computacional es el giro a favor o en contra del reloj (clockwise, counterclockwise). Es decir, dados tres puntos O, A, y B queremos saber si si hubiera un reloj con centro en O, las manecillas rotarian en direccion de A hacia B o de B hacia A.
A --__
/ --
/ \
/ \ El giro de A hacia B es a favor del reloj
/ |
v
O ---------- B
TODO: poner una grafica de verdad (giro a favor del reloj)
Por ejemplo, puede servir para verificar si un punto pertenece a un triangulo. El punto P pertenece a un triangulo ABC si y solo si los tres siguientes giros son en contra del reloj:
B
.
. P2
.
. P1 .
.
C .
. .
.
P3 . A
TODO: poner un grafica de verdad (punto en triangulo)
Aparte, la nocion de giro a favor/en contra del reloj es fundamental para implementar la mayoria de algoritmos de geometria computacional, como los diversos algoritmos que calculan la capsula convexa.
En C++ podemos declarar la funcion con este tipo de datos:
bool cw(pt o, pt a, pt b); // responde si el giro de a hacia b con centro en o es a favor del reloj
bool ccw(pt o, pt a, pt b); // responde si el giro de a hacia b con centro en o es en contra del reloj
Esto nos puede despertar varias preguntas. Por ejemplo, que es el tipo de datos pt
?
struct pt { int x, y; };
pt operator + (pt a, pt b) {
return {a.x + b.x, a.y + b.y}:
}
flecha A
____--->C
B---- ^
^ / flecha B
flecha B / /
/ ____--->A
x----
flecha A
TODO: poner una grafica de verdad (suma de vectores)
pt operator - (pt a, pt b) {
return {a.x - b.x, a.y - b.y}:
}
Interesante porque podemos converir la pregunta ccw(o,a,b)
(una pregunta sobre tres elementos) a una pregunta sobre `foo(o-a,o-b) (una pregunta sobre solo dos elementos)
longitud (pitagores)
double len(pt p) {
return sqrt(p.x*p.x + p.y*p.y);
}
// otra opcion que ofrece C++
double len(pt p) { return hypot(p.x, p.y); }
int dot(pt a, pt b) {
return a.x * b.x + a.y * b.y;
}
Negativo cuando el angulo es mayor a 90
Formula dot(a,b) = len(a) * len(b) * coseno(angulo entre a y b)
pt girar(pt a) {
return {-a.y, a.x};
}
pt det(pt a, pt b) {
return dot(girar(a), b);
}
int det(pt a, pt b) {
return a.x * b.y - a.y * b.x;
}