//---------------------------------------------------------------------------------------------
// Facultad de Informatica. Universidad Politecnica de Madrid
// Trabajo de Fin de Carrera. Diciembre de 2000
// Autor: Juan Carlos Ferreras Ferreras
// Tutor: Manuel Abellanas Oar
// Voronoi.java : Simulacion del Algoritmo de Fortune para el Calculo de D. Voronoi en Internet
// Tambien calcula T. Delaunay y Cierre Convexo
//---------------------------------------------------------------------------------------------
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.lang.*;
public class voronoi extends Applet {
int DIM_APPLET_X; //Ancho en Pixels del Applet según el TAG html
int DIM_APPLET_Y; //Alto en Pixels del Applet según el TAG html
int BALDOSA_X=20; //Coordenada x de la posicion del canvas en la pantalla
int BALDOSA_Y=40; //Coordenada Y de la posicion del canvas en la pantalla
int TAMANO_BALDOSA_X; //Tamaño en pixels de la baldosa gráfica
int TAMANO_BALDOSA_Y; //Tamaño en pixels de la baldosa gráfica
int MAX_VERTICES=2000;//Maximo numero de vertices
int MAX_LADOS=12000; //Maximo numero de lados
int MAX_CARAS=4000; //Maximo numero de caras
Color COLOR_FONDO_BALDOSA = Color.white; //Color de fondo de la baldosa
Color COLOR_LINEAS = Color.blue.darker().darker(); //Color de lineas
Color COLOR_PUNTOS = Color.red; //Color de los puntos
Color COLOR_PLAYA = new Color((float)0.5783256,
(float)0.77211806,
(float)0.99363103); //Color de la playa
matriz_puntos m_puntos; //Array que comprueba si el punto ya esta insertado
lista_vertices V; //Lista de vertices
lista_lados L; //Lista de lados
lista_caras C; //Lista de caras
inserta_punto accion_pulsar_punto; //Evento de pulsar el canvas
hacer_drag_sweep drag_sweep; //Evento para hacer drag en sweep
hacer_click_sweep click_sweep; //Evento para hacer click en sweep
Image fondo; //Se guarda el fondo del applet
Image baldosa_buffer=null; //Imagen de la baldosa
Image baldosa_color; //Imagen de la baldosa color aleatorio
Image cierre_convexo; //Imagen del cierre convexo
Image i_voronoi; //Imagen de Voronoi
Image i_voronoi_color; //Imagen de Voronoi Color
Image sweep; //Imagen del Sweep
Image sweep_color; //Imagen del Sweep
Image cir_dela; //Imagen para circunferencia y Delone
Graphics contexto_baldosa_buffer; //contexto gráfico de baldosa_buffer
Graphics contexto_baldosa_color; //contexto gráfico de baldosa color aleatorio
Graphics contexto_cierre_convexo; //contexto gráfico del cierre convexo
Graphics contexto_i_voronoi; //contexto voronoi
Graphics contexto_i_voronoi_color; //contexto voronoi color
Graphics contexto_sweep; //contexto sweep
Graphics contexto_sweep_color; //contexto sweep color
Graphics contexto_cir_dela; // conteto para circunferenca y delanuay
micanvas baldosa; //Canvas que contiene la baldosa inicial
Button boton_insertar_puntos; //Comienzo de inserción de puntos
Choice seleccion; //Choice para Voronoi, Triangulación, cierre convexo
Choice velocidad; //Choice para la velocidad de la simulacion automatica
CheckboxGroup grupo_check; //Para agrupar los tres check
Checkbox check_b_n; //Checkbox b/n
Checkbox check_color; //Checkbox para color
Checkbox check_circulos; //Checkbox para circ
Checkbox check_voro; //Checkbox para voro
Button boton_nuevo; //Boton nuevo
Button boton_simula; //Boton Simulacion Sweep Line
Button boton_cambiar_color;//Boton para cambiar botones
Button boton_manual; //Boton manual sweep
Button boton_automatico; //Boton automatico sweep
Button boton_volver; //Boton volver
Button boton_comenzar; //Boton para comenzar la simulacion automatica
Label titulo; //String de sweep line
boolean pinta_delaunay = true; //Por defecto Delaunay
boolean pinta_cierre_convexo=false; //Por defecto Cierre Convexo
boolean pinta_voronoi=false; //Por defecto Voronoi
boolean pinta_b_n=true; //Por defecto b/n
boolean pinta_color=false; //Por defecto color a false
boolean pinta_sweep=false; //Por defecto sweep line a false
boolean pinta_sweep_automatico=false; //Por defecto sweep line a false
boolean mostrar_voro_dela=false; //Por defecto voro_dela a false
boolean mostrar_circulos_dela=false; //Por defecto cir_dela a false
int posicion_x_linea=0; //Posicion de la linea de barrido
int incremento=1; //Incremento de la linea de barrido
Polygon l_polig[]; //Para guardar los voronoi de todos los puntos
Polygon lista_voronoi_camb_color[]; // Lista de los poligonos de Voronoi
class micanvas extends Canvas {
public void update(Graphics g) {
paint(g);
}
public void paint (Graphics g) {
if (baldosa_buffer != null) {
if (pinta_delaunay &&
pinta_b_n &&
!(mostrar_voro_dela || mostrar_circulos_dela)) {
g.drawImage(baldosa_buffer, 0, 0, null);
}
if (pinta_delaunay && pinta_b_n && (mostrar_voro_dela || mostrar_circulos_dela)) {
Polygon p;
Polygon l_p[];
double centro_x[];
double centro_y[];
int n_p=0;
l_p=new Polygon[C.num_caras];
centro_x=new double[C.num_caras];
centro_y=new double[C.num_caras];
for (int i=1; i<C.num_caras;i++) {
p = new Polygon();
p.addPoint(C.l_caras[i].lado_interno.origen.punto.x,
C.l_caras[i].lado_interno.origen.punto.y);
p.addPoint(C.l_caras[i].lado_interno.next.origen.punto.x,
C.l_caras[i].lado_interno.next.origen.punto.y);
p.addPoint(C.l_caras[i].lado_interno.prev.origen.punto.x,
C.l_caras[i].lado_interno.prev.origen.punto.y);
if (!(((p.xpoints[0]==V.l_vertices[0].punto.x) &&
(p.ypoints[0]==V.l_vertices[0].punto.y)) ||
((p.xpoints[0]==V.l_vertices[1].punto.x) &&
(p.ypoints[0]==V.l_vertices[1].punto.y)) ||
((p.xpoints[0]==V.l_vertices[2].punto.x) &&
(p.ypoints[0]==V.l_vertices[2].punto.y)) ||
((p.xpoints[1]==V.l_vertices[0].punto.x) &&
(p.ypoints[1]==V.l_vertices[0].punto.y)) ||
((p.xpoints[1]==V.l_vertices[1].punto.x) &&
(p.ypoints[1]==V.l_vertices[1].punto.y)) ||
((p.xpoints[1]==V.l_vertices[2].punto.x) &&
(p.ypoints[1]==V.l_vertices[2].punto.y)) ||
((p.xpoints[2]==V.l_vertices[0].punto.x) &&
(p.ypoints[2]==V.l_vertices[0].punto.y)) ||
((p.xpoints[2]==V.l_vertices[1].punto.x) &&
(p.ypoints[2]==V.l_vertices[1].punto.y)) ||
((p.xpoints[2]==V.l_vertices[2].punto.x) &&
(p.ypoints[2]==V.l_vertices[2].punto.y)))) {
l_p[n_p]=p;
centro_x[n_p]=C.l_caras[0].circun_x(C.l_caras[i]);
centro_y[n_p]=C.l_caras[0].circun_y(C.l_caras[i]);
n_p++;
}//del if
}//del for
if (mostrar_circulos_dela && (!mostrar_voro_dela)) {
contexto_cir_dela.setColor(COLOR_FONDO_BALDOSA);
contexto_cir_dela.fillRect(0,0,TAMANO_BALDOSA_X, TAMANO_BALDOSA_Y);
contexto_cir_dela.setColor(Color.green.brighter().brighter());
int distancia=0;
for (int n=0; n<n_p; n++) {
distancia=(int)V.l_vertices[0].distancia(centro_x[n],
centro_y[n],
l_p[n].xpoints[0],
l_p[n].ypoints[0]);
contexto_cir_dela.drawOval((int)centro_x[n]-distancia,
(int)centro_y[n]-distancia,
(int)2 * distancia,
(int)2 * distancia);
} //del for
contexto_cir_dela.setColor(Color.red);
for (int j=0; j<n_p; j++) contexto_cir_dela.drawPolygon(l_p[j]);
if (V.num_vertices==5) contexto_cir_dela.drawLine(V.l_vertices[3].punto.x,
V.l_vertices[3].punto.y,
V.l_vertices[4].punto.x,
V.l_vertices[4].punto.y);
}
if (mostrar_voro_dela && (!mostrar_circulos_dela)) {
contexto_cir_dela.drawImage(i_voronoi, 0, 0, null);
contexto_cir_dela.setColor(Color.red);
for (int j=0; j<n_p; j++) contexto_cir_dela.drawPolygon(l_p[j]);
if (V.num_vertices==5) contexto_cir_dela.drawLine(V.l_vertices[3].punto.x,
V.l_vertices[3].punto.y,
V.l_vertices[4].punto.x,
V.l_vertices[4].punto.y);
} //de mostrar_voro_dela
if (mostrar_circulos_dela && mostrar_voro_dela) {
contexto_cir_dela.drawImage(i_voronoi, 0, 0, null);
contexto_cir_dela.setColor(Color.green.brighter().brighter());
int distancia=0;
for (int n=0; n<n_p; n++) {
distancia=(int)V.l_vertices[0].distancia(centro_x[n],
centro_y[n],
l_p[n].xpoints[0],
l_p[n].ypoints[0]);
contexto_cir_dela.drawOval((int)centro_x[n]-distancia,
(int)centro_y[n]-distancia,
(int)2 * distancia,
(int)2 * distancia);
} //del for
contexto_cir_dela.setColor(Color.red);
for (int j=0; j<n_p; j++) contexto_cir_dela.drawPolygon(l_p[j]);
if (V.num_vertices==5) contexto_cir_dela.drawLine(V.l_vertices[3].punto.x,
V.l_vertices[3].punto.y,
V.l_vertices[4].punto.x,
V.l_vertices[4].punto.y);
} //de mostrar_circulos_dela
contexto_cir_dela.setColor(COLOR_PUNTOS);
for (int l=0; l<V.num_vertices; l++) {
contexto_cir_dela.fillOval( V.l_vertices[l].punto.x-2,
V.l_vertices[l].punto.y-2,
5,
5);
}
g.drawImage(cir_dela, 0, 0, null);
}
if (pinta_delaunay && pinta_color) {
g.drawImage(baldosa_color, 0, 0, null);
}
if (pinta_cierre_convexo) {
g.drawImage(cierre_convexo, 0, 0, null);
}
if (pinta_voronoi && pinta_b_n) {
g.drawImage(i_voronoi, 0, 0, null);
}
if (pinta_voronoi && pinta_color) {
g.drawImage(i_voronoi_color, 0, 0, null);
}
if (pinta_sweep) {
Polygon parabola;
parabola =new Polygon();
int max_valor=-1;
int valor; //valor
int valor_aux=20000;
valor=valor_aux;
for (int k=-1; k<TAMANO_BALDOSA_Y+1; k++) {
for (int t=3; t<V.num_vertices; t++) {
if (V.l_vertices[t].punto.x > posicion_x_linea) {
valor_aux = (int)((0.5*(k*k-2.0*V.l_vertices[t].punto.y*k+V.l_vertices[t].punto.y * V.l_vertices[t].punto.y +V.l_vertices[t].punto.x * V.l_vertices[t].punto.x-posicion_x_linea*posicion_x_linea))/(V.l_vertices[t].punto.x-posicion_x_linea));
if (valor_aux<valor) valor=valor_aux;
} //del if
} //del for
if (valor < posicion_x_linea) {
valor = posicion_x_linea;
parabola.addPoint(valor,k-1);
parabola.addPoint(valor,k+1);
} else {
parabola.addPoint(valor,k);
}
if (valor > max_valor) max_valor=valor;
valor=20000;
valor_aux=20000;
} //del for
parabola.addPoint(TAMANO_BALDOSA_X+2,TAMANO_BALDOSA_Y+2);
parabola.addPoint(-2,TAMANO_BALDOSA_Y+2);
parabola.addPoint(-2,-2);
parabola.addPoint(TAMANO_BALDOSA_X+2,-2);
if (pinta_color) {
contexto_sweep.drawImage(i_voronoi_color, 0, 0, null);
} else {
contexto_sweep.drawImage(i_voronoi, 0, 0, null);
}
contexto_sweep.setColor(COLOR_PLAYA);
contexto_sweep.fillRect(0,0,posicion_x_linea,TAMANO_BALDOSA_Y);
contexto_sweep.fillPolygon(parabola);
contexto_sweep.setColor(COLOR_LINEAS);
contexto_sweep.drawPolygon(parabola);
for (int i=0; i<TAMANO_BALDOSA_Y; i++) {
if ((posicion_x_linea>=0) && (posicion_x_linea < TAMANO_BALDOSA_X))
if (m_puntos.esta(posicion_x_linea,i))
contexto_sweep.drawLine(posicion_x_linea,i,parabola.xpoints[i],i);
}
// Y los puntos
contexto_sweep.setColor(COLOR_PUNTOS);
for (int l=0; l<V.num_vertices; l++) {
contexto_sweep.fillOval( V.l_vertices[l].punto.x-2,
V.l_vertices[l].punto.y-2,
5,
5);
}
contexto_sweep.setColor(Color.white);
contexto_sweep.fillRect(posicion_x_linea-1,-1,
2,TAMANO_BALDOSA_Y+1);
contexto_sweep.setColor(Color.black);
contexto_sweep.drawLine(posicion_x_linea, -1,
posicion_x_linea, TAMANO_BALDOSA_Y+1);
g.drawImage(sweep, 0, 0, null);
if (pinta_sweep_automatico && (max_valor > -1)) {
posicion_x_linea= posicion_x_linea - incremento;
baldosa.repaint();
}
if ((pinta_sweep_automatico) && (max_valor <= -1))
boton_comenzar.setEnabled(true);
}
} //del if
} //de paint
} // de micanvas
//Mantiene una matriz booleana con los puntos que se han pulsado
public class matriz_puntos {
public int num_puntos;
public boolean array_puntos [][]; //Array que comprueba si el punto ya está.
// Constructores
public matriz_puntos (int x, int y) { //lo crea nuevo
array_puntos=new boolean[x][y]; //array del tamaño del canvas
num_puntos=0;
for (int i=0; i<x; i++) {
for (int j=0; j<y; j++) {
array_puntos[i][j] = false;
}
}
}
//Metodos
public boolean esta (int x, int y) {
return (array_puntos[x][y] == true); // Porque no estan a false
}
public void inserta (int x, int y) {
array_puntos[x][y]=true;
num_puntos++;
}
public void inicializa (int x, int y) { // Inicializa la matriz de boolean
num_puntos=0;
for (int i=0; i<x; i++) {
for (int j=0; j<y; j++) {
array_puntos[i][j] = false;
}
}
}
} // De la clase matriz_puntos
public class vertice {
public Point punto;
public lado lado_incidente;
public Color color_vertice;
//Constructores
public vertice (Point p, lado l) {
punto = new Point(p);
lado_incidente=l;
color_vertice = new Color((float)Math.random(),
(float)Math.random(),
(float)Math.random());
}
public vertice (int x, int y, lado l) {
punto = new Point(x, y);
lado_incidente=l;
color_vertice = new Color((float)Math.random(),
(float)Math.random(),
(float)Math.random());
}
public vertice () {
punto = null;
lado_incidente = null;
color_vertice = new Color((float)Math.random(),
(float)Math.random(),
(float)Math.random());
}
// Metodos
public double distancia_2 (int x1, int y1, int x2, int y2) {
// Devuelve la distancia al cuadrado de dos puntos
return Math.pow((double)x1 - (double)x2, 2) +
Math.pow((double)y1 - (double)y2, 2);
}
public double distancia_2 (double x1, double y1, double x2, double y2) {
// Devuelve la distancia al cuadrado de dos puntos
return Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2);
}
public double distancia (int x1, int y1, int x2, int y2) {
// Devuelve la distancia de dos puntos
return Math.sqrt (distancia_2(x1, y1, x2, y2));
}
public double distancia (double x1, double y1, double x2, double y2) {
// Devuelve la distancia de dos puntos
return Math.sqrt (distancia_2(x1, y1, x2, y2));
}
} // de vertice
public class lista_vertices {
public vertice l_vertices[];
public int num_vertices;
// Constructor
public lista_vertices(int i) {
l_vertices = new vertice[i];
num_vertices = 0;
}
// Métodos
public void inserta (vertice v, lado l) {
l_vertices[num_vertices] = v;
num_vertices++;
}
public void inserta (Point p, lado l) {
l_vertices[num_vertices] = new vertice(p, l);
num_vertices++;
}
public void inserta (int x, int y, lado l) {
l_vertices[num_vertices] = new vertice(x, y, l);
num_vertices++;
}
public Point ultimo () {
return l_vertices[num_vertices-1].punto;
}
public Point punto (int index) {
return l_vertices[index].punto;
}
public void inicializa() {
// Inicializa
num_vertices = 0;
}
}
public class lado { //Del triángulo
public vertice origen;
public lado twin;
public lado next;
public lado prev;
public cara cara_incidente;
// Constructor
public lado(vertice or, lado tw, lado nx, lado pr, cara c_i) {
origen=or;
twin=tw;
next=nx;
prev=pr;
cara_incidente=c_i;
}
// Metodos
public boolean ilegal (vertice v, lado l) {
vertice p0;
vertice p1; // vertices del triangulo externo
vertice p2;
vertice v0;
vertice v1; // vertices de los 2 triangulos
vertice v2;
vertice v3;
p0 = new vertice();
p1 = new vertice();
p2 = new vertice();
v0 = new vertice();
v1 = new vertice();
v2 = new vertice();
v3 = new vertice();
p0 = V.l_vertices[0];
p1 = V.l_vertices[1];
p2 = V.l_vertices[2];
v0 = v;
v1 = l.origen;
v2 = l.twin.prev.origen;
v3 = l.twin.origen;
// Empezamos con los casos
// i y j son negativos
if (((v1==p0) ||
(v1==p1) ||
(v1==p2)) &&
((v3==p0) ||
(v3==p1) ||
(v3==p2)) ) {
return false;
} // son todos positivos
if ((v0!=p0) && (v0!=p1) && (v0!=p2) &&
(v1!=p0) && (v1!=p1) && (v1!=p2) &&
(v2!=p0) && (v2!=p1) && (v2!=p2) &&
(v3!=p0) && (v3!=p1) && (v3!=p2) ) {
double c_x;
double c_y;
c_x = l.cara_incidente.circun_x(l.cara_incidente);
c_y = l.cara_incidente.circun_y(l.cara_incidente);
if (v0.distancia_2 (c_x, c_y, (double)v0.punto.x, (double)v0.punto.y) >
v0.distancia_2 (c_x, c_y, (double)v2.punto.x, (double)v2.punto.y))
return true;
else return false;
}
// Solo 1 negativo
int cuantos = 0;
int cuales [];
cuales = new int[4];
for (int i=0; i<4; i++) cuales[i]= -1;
if (v0==p0){
cuales[0] = 0;
cuantos++;
}
if (v0==p1){
cuales[0] = 1;
cuantos++;
}
if (v0==p2){
cuales[0] = 2;
cuantos++;
}
if (v1==p0){
cuales[1] = 0;
cuantos++;
}
if (v1==p1){
cuales[1] = 1;
cuantos++;
}
if (v1==p2){
cuales[1] = 2;
cuantos++;
}
if (v2==p0){
cuales[2] = 0;
cuantos++;
}
if (v2==p1){
cuales[2] = 1;
cuantos++;
}
if (v2==p2){
cuales[2] = 2;
cuantos++;
}
if (v3==p0){
cuales[3] = 0;
cuantos++;
}
if (v3==p1){
cuales[3] = 1;
cuantos++;
}
if (v3==p2){
cuales[3] = 2;
cuantos++;
}
// 1 Negativo
if (cuantos == 1) {
if ((cuales[1]!= -1)||
(cuales[3]!= -1)) {
if ((l.cara_incidente.left_no_colineal(v0.punto, v1.punto, v2.punto)) &&
(l.cara_incidente.left_no_colineal(v2.punto, v3.punto, v0.punto))) {
return true;
}
} else {
return false;
}
}
// 2 Negativos
if (cuantos == 2) {
if ((cuales[0] + cuales[2]) >
(cuales[1] + cuales[3])) {
return false;
} else {
if ((l.cara_incidente.left_no_colineal(v0.punto, v1.punto, v2.punto)) &&
(l.cara_incidente.left_no_colineal(v2.punto, v3.punto, v0.punto))) {
return true;
}
}
}
// Fin de solo 1 negativo
return false;
} //de ilegal
public void legaliza_lado(vertice v, lado l) {
lado aux1;
lado aux2;
lado aux3;
lado aux4;
lado aux5;
lado aux6;
cara caraaux1;
cara caraaux2;
if (ilegal(v,l)) {
aux1 = new lado(null, null, null, null, null);
aux2 = new lado(null, null, null, null, null);
aux3 = new lado(null, null, null, null, null);
aux4 = new lado(null, null, null, null, null);
aux5 = new lado(null, null, null, null, null);
aux6 = new lado(null, null, null, null, null);
caraaux1 = new cara(null);
caraaux2 = new cara(null);
aux1 = l;
aux2 = l.next;
aux3 = l.prev;
aux4 = l.twin;
aux5 = l.twin.next;
aux6 = l.twin.prev;
caraaux1 = aux1.cara_incidente;
caraaux2 = aux4.cara_incidente;
//los origenes
aux1.origen = aux3.origen;
aux4.origen = aux6.origen;
//Los twin
// No es necesario
// Los next
aux1.next = aux6;
aux2.next = aux1;
aux3.next = aux5;
aux4.next = aux3;
aux5.next = aux4;
aux6.next = aux2;
// Los prev
aux1.prev = aux2;
aux2.prev = aux6;
aux3.prev = aux4;
aux4.prev = aux5;
aux5.prev = aux3;
aux6.prev = aux1;
// Las cara_incidente
aux1.cara_incidente = caraaux1;
aux2.cara_incidente = caraaux1;
aux3.cara_incidente = caraaux2;
aux4.cara_incidente = caraaux2;
aux5.cara_incidente = caraaux2;
aux6.cara_incidente = caraaux1;
//Lados internos de las caras
caraaux1.lado_interno = aux1;
caraaux2.lado_interno = aux4;
//Los vertices
aux2.origen.lado_incidente = aux2;
aux3.origen.lado_incidente = aux3;
aux5.origen.lado_incidente = aux5;
aux6.origen.lado_incidente = aux6;
// Y legalizo los nuevos lados
legaliza_lado(v, aux5);
legaliza_lado(v, aux6);
} // del if
} // del metodo legaliza_lado
}
public class lista_lados {
public lado l_lados[];
public int num_lados;
public lista_lados(int i) {
l_lados = new lado[i];
num_lados = 0;
}
public void inicializa() {
// Inicializa
num_lados = 0;
}
}
public class cara {
public lado lado_interno;
public Color color_cara;
//Constructor
public cara (lado l) {
lado_interno = l;
color_cara = new Color((float)Math.random(),
(float)Math.random(),
(float)Math.random());
}
//Metodos
public int area2 (Point p1, Point p2, Point p3) {
//2 veces el area
return (p1.x * p2.y - p1.y * p2.x +
p1.y * p3.x - p1.x * p3.y +
p2.x * p3.y - p3.x * p2.y);
}
public boolean colineal (Point p1, Point p2, Point p3) {
// true si son colineales
return (area2(p1, p2, p3)==0);
}
public boolean left_no_colineal (Point p1, Point p2, Point p3) {
// true si son colineales
return (area2(p1, p2, p3)<0);
}
public boolean left (Point p1, Point p2, Point p3) {
// true si p3 a la izqda. de p1---p2
return (area2(p1, p2, p3)<=0);
}
public boolean en_triangulo(cara c, Point p) {
if (
left(c.lado_interno.origen.punto, c.lado_interno.next.origen.punto, p) &&
left(c.lado_interno.prev.origen.punto, c.lado_interno.origen.punto, p) &&
left(c.lado_interno.next.origen.punto, c.lado_interno.prev.origen.punto, p)
) return true;
else return false;
}
public boolean interior_estricto_al_triangulo (cara c, Point p) {
if (
left_no_colineal(c.lado_interno.origen.punto, c.lado_interno.next.origen.punto, p) &&
left_no_colineal(c.lado_interno.prev.origen.punto, c.lado_interno.origen.punto, p) &&
left_no_colineal(c.lado_interno.next.origen.punto, c.lado_interno.prev.origen.punto, p)
) return true;
else return false;
}
public lado lado_interseccion (cara c, Point p) {
if (colineal(c.lado_interno.origen.punto, c.lado_interno.next.origen.punto, p))
return c.lado_interno;
else if (colineal(c.lado_interno.prev.origen.punto, c.lado_interno.origen.punto, p))
return (c.lado_interno.prev);
else if (colineal(c.lado_interno.next.origen.punto, c.lado_interno.prev.origen.punto, p))
return (c.lado_interno.next);
else return null; // Nunca se da el caso
}
public cara encuentra_triangulo (Point p) {
int i;
for (i=1; i<C.num_caras; i++) { //nos saltamos la cara 0 pq es la del triangulo externo
if (en_triangulo (C.l_caras[i], p)) break;
}
return C.l_caras[i];
} // del metodo
public double circun_x (cara c) {
double x1;
double y1;
double x2;
double y2;
double x3;
double y3;
x1= (double)c.lado_interno.origen.punto.x;
y1= (double)c.lado_interno.origen.punto.y;
x2= (double)c.lado_interno.next.origen.punto.x;
y2= (double)c.lado_interno.next.origen.punto.y;
x3= (double)c.lado_interno.prev.origen.punto.x;
y3= (double)c.lado_interno.prev.origen.punto.y;
return (y3*x2*x2-y1*x2*x2+y2*y2*y3+y1*x3*x3+y3*y3*y1+
y2*x1*x1-y1*y2*y2-x1*x1*y3-x3*x3*y2-y2*y3*y3+
y1*y1*y2-y3*y1*y1)/
((double)2.0*(x1*y2-x1*y3-x3*y2-x2*y1+y1*x3+y3*x2));
}
public float circun_x_float (cara c) {
float x1;
float y1;
float x2;
float y2;
float x3;
float y3;
x1= (float)c.lado_interno.origen.punto.x;
y1= (float)c.lado_interno.origen.punto.y;
x2= (float)c.lado_interno.next.origen.punto.x;
y2= (float)c.lado_interno.next.origen.punto.y;
x3= (float)c.lado_interno.prev.origen.punto.x;
y3= (float)c.lado_interno.prev.origen.punto.y;
return (y3*x2*x2-y1*x2*x2+y2*y2*y3+y1*x3*x3+y3*y3*y1+
y2*x1*x1-y1*y2*y2-x1*x1*y3-x3*x3*y2-y2*y3*y3+
y1*y1*y2-y3*y1*y1)/
((float)2.0*(x1*y2-x1*y3-x3*y2-x2*y1+y1*x3+y3*x2));
}
public double circun_y (cara c) {
double x1;
double y1;
double x2;
double y2;
double x3;
double y3;
x1= (double)c.lado_interno.origen.punto.x;
y1= (double)c.lado_interno.origen.punto.y;
x2= (double)c.lado_interno.next.origen.punto.x;
y2= (double)c.lado_interno.next.origen.punto.y;
x3= (double)c.lado_interno.prev.origen.punto.x;
y3= (double)c.lado_interno.prev.origen.punto.y;
return (-x2*x2*x1-y2*y2*x1+x1*x3*x3+x1*y3*y3+x3*x2*x2+
x3*y2*y2+x2*x1*x1-x1*x1*x3+x2*y1*y1-y1*y1*x3-
x3*x3*x2-y3*y3*x2)/
((double)-2.0*(x1*y2-x1*y3-x3*y2-x2*y1+y1*x3+y3*x2));
}
public float circun_y_float (cara c) {
float x1;
float y1;
float x2;
float y2;
float x3;
float y3;
x1= (float)c.lado_interno.origen.punto.x;
y1= (float)c.lado_interno.origen.punto.y;
x2= (float)c.lado_interno.next.origen.punto.x;
y2= (float)c.lado_interno.next.origen.punto.y;
x3= (float)c.lado_interno.prev.origen.punto.x;
y3= (float)c.lado_interno.prev.origen.punto.y;
return (-x2*x2*x1-y2*y2*x1+x1*x3*x3+x1*y3*y3+x3*x2*x2+
x3*y2*y2+x2*x1*x1-x1*x1*x3+x2*y1*y1-y1*y1*x3-
x3*x3*x2-y3*y3*x2)/
((float)-2.0*(x1*y2-x1*y3-x3*y2-x2*y1+y1*x3+y3*x2));
}
} //de la clase
public class lista_caras {
public cara l_caras[];
public int num_caras;
//Constructores
public lista_caras(int i) {
l_caras=new cara[i];
num_caras=0;
}
public void inserta (cara c) {
num_caras++;
}
public void inicializa() {
// Inicializa
num_caras = 0;
}
}
public void inserta_triangulo_externo () {
V.inserta(TAMANO_BALDOSA_X/2, -2 * TAMANO_BALDOSA_Y, null);
V.inserta(-TAMANO_BALDOSA_X, 2* TAMANO_BALDOSA_Y, null);
V.inserta( 2 * TAMANO_BALDOSA_X, 2 * TAMANO_BALDOSA_Y, null);
//Estrutura total del triangulo inicial
L.num_lados=L.num_lados + 6;
L.l_lados[0] = new lado(V.l_vertices[1], null, null, null, null);
L.l_lados[1] = new lado(V.l_vertices[0], null, null, null, null);
L.l_lados[2] = new lado(V.l_vertices[2], null, null, null, null);
L.l_lados[3] = new lado(V.l_vertices[0], null, null, null, null);
L.l_lados[4] = new lado(V.l_vertices[1], null, null, null, null);
L.l_lados[5] = new lado(V.l_vertices[2], null, null, null, null);
//
C.num_caras = C.num_caras + 2;
C.l_caras[0] = new cara (L.l_lados[0]); // Externo
C.l_caras[1] = new cara (L.l_lados[3]); // Interno
//
L.l_lados[0].twin = L.l_lados[3];
L.l_lados[1].twin = L.l_lados[5];
L.l_lados[2].twin = L.l_lados[4];
L.l_lados[3].twin = L.l_lados[0];
L.l_lados[4].twin = L.l_lados[2];
L.l_lados[5].twin = L.l_lados[1];
//
L.l_lados[0].next = L.l_lados[1];
L.l_lados[1].next = L.l_lados[2];
L.l_lados[2].next = L.l_lados[0];
L.l_lados[3].next = L.l_lados[4];
L.l_lados[4].next = L.l_lados[5];
L.l_lados[5].next = L.l_lados[3];
//
L.l_lados[0].prev = L.l_lados[2];
L.l_lados[1].prev = L.l_lados[0];
L.l_lados[2].prev = L.l_lados[1];
L.l_lados[3].prev = L.l_lados[5];
L.l_lados[4].prev = L.l_lados[3];
L.l_lados[5].prev = L.l_lados[4];
//
L.l_lados[0].cara_incidente = C.l_caras[0];
L.l_lados[1].cara_incidente = C.l_caras[0];
L.l_lados[2].cara_incidente = C.l_caras[0];
L.l_lados[3].cara_incidente = C.l_caras[1];
L.l_lados[4].cara_incidente = C.l_caras[1];
L.l_lados[5].cara_incidente = C.l_caras[1];
//
V.l_vertices[0].lado_incidente = L.l_lados[3];
V.l_vertices[1].lado_incidente = L.l_lados[4];
V.l_vertices[2].lado_incidente = L.l_lados[5];
} // Fin inserta_triangulo_externo
public Polygon transforma_poligono (Polygon pol) {
Polygon paux;
int MAX_CORD = 29000; //10000;
double new_x, new_y;
paux = new Polygon();
for (int i=0; i<pol.npoints; i++) {
if ((Math.abs(pol.xpoints[i]) <= MAX_CORD) &&
(Math.abs(pol.ypoints[i]) <= MAX_CORD)) { //Es dibujable
paux.addPoint (pol.xpoints[i], pol.ypoints[i]);
if ((Math.abs(pol.xpoints[(i + 1 + pol.npoints) % pol.npoints]) > MAX_CORD) ||
(Math.abs(pol.ypoints[(i + 1 + pol.npoints) % pol.npoints]) > MAX_CORD)) { //No es dibujable el sig.
new_x = pol.xpoints[i] + 2000 *
(pol.xpoints[(i + 1 + pol.npoints) % pol.npoints] - pol.xpoints[i]) /
V.l_vertices[0].distancia(pol.xpoints[(i + 1 + pol.npoints) % pol.npoints],
pol.ypoints[(i + 1 + pol.npoints) % pol.npoints],
pol.xpoints[i],
pol.ypoints[i]);
new_y = pol.ypoints[i] + 2000 *
(pol.ypoints[(i + 1 + pol.npoints) % pol.npoints] - pol.ypoints[i]) /
V.l_vertices[0].distancia(pol.xpoints[(i + 1 + pol.npoints) % pol.npoints],
pol.ypoints[(i + 1 + pol.npoints) % pol.npoints],
pol.xpoints[i],
pol.ypoints[i]);
paux.addPoint ((int)Math.round(new_x ),(int)Math.round(new_y));
} //fin del if interno
} // Fin de punto i dentro
//Ahora le punto i esta fuera de la zona dibujable
if ((Math.abs(pol.xpoints[i]) > MAX_CORD) ||
(Math.abs(pol.ypoints[i]) > MAX_CORD)) {
new_x = V.l_vertices[V.num_vertices-1].punto.x + 2000 *
(pol.xpoints[i] - V.l_vertices[V.num_vertices-1].punto.x) /
V.l_vertices[0].distancia(V.l_vertices[V.num_vertices-1].punto.x,
V.l_vertices[V.num_vertices-1].punto.y,
pol.xpoints[i],
pol.ypoints[i]);
new_y = V.l_vertices[V.num_vertices-1].punto.y + 2000 *
(pol.ypoints[i] - V.l_vertices[V.num_vertices-1].punto.y) /
V.l_vertices[0].distancia(V.l_vertices[V.num_vertices-1].punto.x,
V.l_vertices[V.num_vertices-1].punto.y,
pol.xpoints[i],
pol.ypoints[i]);
paux.addPoint ((int)Math.round(new_x ),(int)Math.round(new_y));
//Añado tb el punto intermedio entre los 2
if ((Math.abs(pol.xpoints[(i + 1 + pol.npoints) % pol.npoints]) > MAX_CORD) ||
(Math.abs(pol.ypoints[(i + 1 + pol.npoints) % pol.npoints]) > MAX_CORD)) {
new_x = V.l_vertices[V.num_vertices-1].punto.x + 2000 *
((pol.xpoints[i]+pol.xpoints[(i + 1 + pol.npoints) % pol.npoints])/2 - V.l_vertices[V.num_vertices-1].punto.x /
V.l_vertices[0].distancia((pol.xpoints[i]+pol.xpoints[(i + 1 + pol.npoints) % pol.npoints])/2,
(pol.ypoints[i]+pol.ypoints[(i + 1 + pol.npoints) % pol.npoints])/2,
V.l_vertices[V.num_vertices-1].punto.x,
V.l_vertices[V.num_vertices-1].punto.y));
new_y = V.l_vertices[V.num_vertices-1].punto.y + 2000 *
((pol.ypoints[i]+pol.ypoints[(i + 1 + pol.npoints) % pol.npoints])/2 - V.l_vertices[V.num_vertices-1].punto.y /
V.l_vertices[0].distancia((pol.xpoints[i]+pol.xpoints[(i + 1 + pol.npoints) % pol.npoints])/2,
(pol.ypoints[i]+pol.ypoints[(i + 1 + pol.npoints) % pol.npoints])/2,
V.l_vertices[V.num_vertices-1].punto.x,
V.l_vertices[V.num_vertices-1].punto.y));
paux.addPoint ((int)Math.round(new_x ),(int)Math.round(new_y));
}
// Si el siguiente esta dentro
if ((Math.abs(pol.xpoints[(i + 1 + pol.npoints) % pol.npoints]) <= MAX_CORD) &&
(Math.abs(pol.ypoints[(i + 1 + pol.npoints) % pol.npoints]) <= MAX_CORD)) {
new_x = pol.xpoints[(i + 1 + pol.npoints) % pol.npoints] + 2000 *
(pol.xpoints[i] - pol.xpoints[(i + 1 + pol.npoints) % pol.npoints]) /
V.l_vertices[0].distancia(pol.xpoints[(i + 1 + pol.npoints) % pol.npoints],
pol.ypoints[(i + 1 + pol.npoints) % pol.npoints],
pol.xpoints[i],
pol.ypoints[i]);
new_y = pol.ypoints[(i + 1 + pol.npoints) % pol.npoints] + 2000 *
(pol.ypoints[i] - pol.ypoints[(i + 1 + pol.npoints) % pol.npoints]) /
V.l_vertices[0].distancia(pol.xpoints[(i + 1 + pol.npoints) % pol.npoints],
pol.ypoints[(i + 1 + pol.npoints) % pol.npoints],
pol.xpoints[i],
pol.ypoints[i]);
paux.addPoint ((int)Math.round(new_x ),(int)Math.round(new_y));
} // Fin del sihuiente dentro
// Y si el sihuiente esta fuera de la zona dibujable pero corta la parte del applet
if ((Math.abs(pol.xpoints[(i + 1 + pol.npoints) % pol.npoints]) > MAX_CORD) ||
(Math.abs(pol.ypoints[(i + 1 + pol.npoints) % pol.npoints]) > MAX_CORD)) {
System.out.println("Ha ocurrido..... ¡OJO!");
} // el siguiente fuera pero cortando la zona visible
} // Fin de i fuera de la zona dibujable
} //del for
return paux;
} // de transforma_poligono
public void dibuja_voronoi_vertice(vertice v) {
lado lado_aux1;
lado lado_aux2;
Polygon p_v;
boolean es_interno=true;
boolean circuncentro_fuera=false;
float cx, cy;
Point vector_director;
double dist;
double punto_medio_x;
double punto_medio_y;
double posible_circun_x;
double posible_circun_y;
boolean dibujable = true;
p_v = new Polygon();
lado_aux1 = new lado(null, null, null, null, null);
lado_aux2 = new lado(null, null, null, null, null);
lado_aux1 = v.lado_incidente;
cx= (C.l_caras[0].circun_x_float(lado_aux1.cara_incidente));
cy= (C.l_caras[0].circun_y_float(lado_aux1.cara_incidente));
p_v.addPoint( (int)Math.round(cx), (int)Math.round(cy));
lado_aux2 = lado_aux1.prev.twin;
while ( lado_aux2 != lado_aux1 ) {
cx= (C.l_caras[0].circun_x_float(lado_aux2.cara_incidente));
cy= (C.l_caras[0].circun_y_float(lado_aux2.cara_incidente));
p_v.addPoint( (int)Math.round(cx), (int)Math.round(cy));
lado_aux2 = lado_aux2.prev.twin;
}
for (int g=0; g<p_v.npoints; g++) {
if ((p_v.xpoints[g]>30000) ||
(p_v.xpoints[g]<-30000) ||
(p_v.ypoints[g]>30000) ||
(p_v.ypoints[g]<-30000)) {
dibujable =false;
break;
}
}
if (dibujable) {
lista_voronoi_camb_color[V.num_vertices-1]= p_v;
contexto_i_voronoi.setColor(COLOR_FONDO_BALDOSA);
contexto_i_voronoi.fillPolygon(p_v);
contexto_i_voronoi.setColor(COLOR_LINEAS);
contexto_i_voronoi.drawPolygon(p_v);
contexto_i_voronoi_color.setColor(v.color_vertice);
contexto_i_voronoi_color.fillPolygon(p_v);
//El de color con lineas
contexto_i_voronoi_color.setColor(COLOR_LINEAS);
contexto_i_voronoi_color.drawPolygon(p_v);
} else { //No lo puedo dibujar pq se sale de la zona dibujable
Polygon p_v_new;
p_v_new = new Polygon();
p_v_new = transforma_poligono (p_v);
lista_voronoi_camb_color[V.num_vertices-1]= p_v_new;
contexto_i_voronoi.setColor(COLOR_FONDO_BALDOSA);
contexto_i_voronoi.fillPolygon(p_v_new);
contexto_i_voronoi.setColor(COLOR_LINEAS);
contexto_i_voronoi.drawPolygon(p_v_new);
contexto_i_voronoi_color.setColor(v.color_vertice);
contexto_i_voronoi_color.fillPolygon(p_v_new);
//El de color con lineas
contexto_i_voronoi_color.setColor(COLOR_LINEAS);
contexto_i_voronoi_color.drawPolygon(p_v_new);
} //del else
contexto_i_voronoi.setColor(Color.red);
contexto_i_voronoi_color.setColor(Color.red);
for (int j=0; j<V.num_vertices; j++) {
contexto_i_voronoi.fillOval( V.l_vertices[j].punto.x-2,
V.l_vertices[j].punto.y-2,
5,
5);
contexto_i_voronoi_color.fillOval( V.l_vertices[j].punto.x-2,
V.l_vertices[j].punto.y-2,
5,
5);
} //del for
}
public void dibuja_voronoi() {
dibuja_voronoi_vertice(V.l_vertices[V.num_vertices-1]);
for (int m=1; m<C.num_caras; m++){
if (C.l_caras[0].colineal(C.l_caras[m].lado_interno.origen.punto,
C.l_caras[m].lado_interno.next.origen.punto,
C.l_caras[m].lado_interno.prev.origen.punto)) {
break;
}
}
for (int b=3; b<V.num_vertices; b++) {
if ( C.l_caras[0].colineal(V.l_vertices[b].lado_incidente.origen.punto,
V.l_vertices[b].lado_incidente.next.origen.punto,
V.l_vertices[b].lado_incidente.prev.origen.punto)) {
break;
}
}
contexto_i_voronoi.setColor(Color.red);
contexto_i_voronoi_color.setColor(Color.red);
for (int j=0; j<V.num_vertices; j++) {
contexto_i_voronoi.fillOval( V.l_vertices[j].punto.x-2,
V.l_vertices[j].punto.y-2,
5,
5);
contexto_i_voronoi_color.fillOval( V.l_vertices[j].punto.x-2,
V.l_vertices[j].punto.y-2,
5,
5);
}
}
public void dibuja_cierre_convexo (){
// Dibuja el cierre convexo, solo cuando se pide, no siempre
Polygon c_c;
vertice first;
lado aux1;
c_c = new Polygon();
contexto_cierre_convexo.setColor(COLOR_FONDO_BALDOSA); //FONDO_BALDOSA);
contexto_cierre_convexo.fillRect(0,0,TAMANO_BALDOSA_X, TAMANO_BALDOSA_Y);
aux1 = L.l_lados[0].twin.prev;
first= L.l_lados[0].twin.prev.origen;
c_c.addPoint(aux1.origen.punto.x, aux1.origen.punto.y);
do {
if ((aux1.twin.prev.origen == V.l_vertices[0]) ||
(aux1.twin.prev.origen == V.l_vertices[1]) ||
(aux1.twin.prev.origen == V.l_vertices[2])) {
aux1 = aux1.twin.next;
} else {
aux1 = aux1.twin.prev;
}
c_c.addPoint(aux1.origen.punto.x, aux1.origen.punto.y);
} while (aux1.origen != first);
if (!pinta_color) {
contexto_cierre_convexo.setColor(COLOR_LINEAS);
contexto_cierre_convexo.drawPolygon(c_c);
} else {
contexto_cierre_convexo.setColor(C.l_caras[0].color_cara);
contexto_cierre_convexo.fillPolygon(c_c);
// Y la linea de fuera
contexto_cierre_convexo.setColor(COLOR_LINEAS);
contexto_cierre_convexo.drawPolygon(c_c);
}
if (m_puntos.num_puntos==2) {
if (!pinta_color) {
contexto_cierre_convexo.setColor(COLOR_LINEAS);
contexto_cierre_convexo.drawLine(V.l_vertices[V.num_vertices-1].punto.x,
V.l_vertices[V.num_vertices-1].punto.y,
V.l_vertices[V.num_vertices-2].punto.x,
V.l_vertices[V.num_vertices-2].punto.y);
} else {
contexto_cierre_convexo.setColor(C.l_caras[0].color_cara);
contexto_cierre_convexo.drawLine(V.l_vertices[V.num_vertices-1].punto.x,
V.l_vertices[V.num_vertices-1].punto.y,
V.l_vertices[V.num_vertices-2].punto.x,
V.l_vertices[V.num_vertices-2].punto.y);
}
}
contexto_cierre_convexo.setColor(COLOR_PUNTOS);
for (int l=0; l<V.num_vertices; l++) {
contexto_cierre_convexo.fillOval( V.l_vertices[l].punto.x-2,
V.l_vertices[l].punto.y-2,
5,
5);
}
baldosa.repaint();
}
public void repintar_triangulacion_color () {
contexto_baldosa_color.setColor(COLOR_FONDO_BALDOSA);
contexto_baldosa_color.fillRect(0,0,TAMANO_BALDOSA_X, TAMANO_BALDOSA_Y);
Polygon pol;
// si solo son dos puntos a color dibujo una linea
if (m_puntos.num_puntos == 2) {
contexto_baldosa_color.setColor(C.l_caras[1].color_cara);
contexto_baldosa_color.drawLine(V.l_vertices[3].punto.x,
V.l_vertices[3].punto.y,
V.l_vertices[4].punto.x,
V.l_vertices[4].punto.y);
}
for (int j=0; j<C.num_caras; j++) {
if ((C.l_caras[j].lado_interno.origen!=V.l_vertices[0]) &&
(C.l_caras[j].lado_interno.origen!=V.l_vertices[1]) &&
(C.l_caras[j].lado_interno.origen!=V.l_vertices[2]) &&
(C.l_caras[j].lado_interno.next.origen!=V.l_vertices[0]) &&
(C.l_caras[j].lado_interno.next.origen!=V.l_vertices[1]) &&
(C.l_caras[j].lado_interno.next.origen!=V.l_vertices[2]) &&
(C.l_caras[j].lado_interno.prev.origen!=V.l_vertices[0]) &&
(C.l_caras[j].lado_interno.prev.origen!=V.l_vertices[1]) &&
(C.l_caras[j].lado_interno.prev.origen!=V.l_vertices[2])) {
pol = new Polygon();
pol.addPoint(C.l_caras[j].lado_interno.origen.punto.x,
C.l_caras[j].lado_interno.origen.punto.y);
pol.addPoint(C.l_caras[j].lado_interno.next.origen.punto.x,
C.l_caras[j].lado_interno.next.origen.punto.y);
pol.addPoint(C.l_caras[j].lado_interno.prev.origen.punto.x,
C.l_caras[j].lado_interno.prev.origen.punto.y);
contexto_baldosa_color.setColor(C.l_caras[j].color_cara);
contexto_baldosa_color.fillPolygon(pol);
// Para la triangulacion en color
contexto_baldosa_color.setColor(COLOR_LINEAS);
contexto_baldosa_color.drawPolygon(pol);
} // del if
} // del for
contexto_baldosa_color.setColor(COLOR_PUNTOS);
for (int l=0; l<V.num_vertices; l++) {
contexto_baldosa_color.fillOval( V.l_vertices[l].punto.x-2,
V.l_vertices[l].punto.y-2,
5,
5);
}
}
class pulsar_boton_nuevo implements ActionListener {
public void actionPerformed (ActionEvent e) {
remove(titulo);
remove(boton_automatico);
remove(boton_manual);
contexto_baldosa_buffer.setColor(COLOR_FONDO_BALDOSA);
contexto_baldosa_buffer.fillRect(0, 0,
TAMANO_BALDOSA_X, TAMANO_BALDOSA_Y);
contexto_baldosa_color.setColor(COLOR_FONDO_BALDOSA);
contexto_baldosa_color.fillRect(0, 0,
TAMANO_BALDOSA_X, TAMANO_BALDOSA_Y);
contexto_i_voronoi.setColor(COLOR_FONDO_BALDOSA);
contexto_i_voronoi.fillRect(0, 0,
TAMANO_BALDOSA_X, TAMANO_BALDOSA_Y);
contexto_i_voronoi_color.setColor(COLOR_FONDO_BALDOSA);
contexto_i_voronoi_color.fillRect(0, 0,
TAMANO_BALDOSA_X, TAMANO_BALDOSA_Y);
m_puntos.inicializa(TAMANO_BALDOSA_X, TAMANO_BALDOSA_Y);
V.inicializa();
L.inicializa();
C.inicializa();
inserta_triangulo_externo();
if (pinta_cierre_convexo) dibuja_cierre_convexo();
baldosa.repaint();
}
}
class pulsar_boton_insertar_puntos implements ActionListener {
// Cuando se pulsa dicho botón para empezar a introducir puntos
public void actionPerformed (ActionEvent e) {
baldosa.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
add(boton_nuevo); // estan por debajo
add(seleccion); // estan por debajo
remove(boton_insertar_puntos);
add(check_b_n);
add(check_color);
add(check_circulos);
add(check_voro);
inserta_triangulo_externo();
baldosa.addMouseListener (accion_pulsar_punto); //estaba parado en el init
contexto_baldosa_buffer.setColor(COLOR_FONDO_BALDOSA);
contexto_baldosa_buffer.fillRect(0,0,TAMANO_BALDOSA_X, TAMANO_BALDOSA_Y);
baldosa.repaint();
}
} // Fin de evento de pulsación de ratón en le botón
class pulsar_boton_cambiar_color implements ActionListener {
public void actionPerformed (ActionEvent e) {
COLOR_PLAYA = new Color((float)Math.random(),
(float)Math.random(),
(float)Math.random());
for (int i=0; i<C.num_caras; i++) {
C.l_caras[i].color_cara = new Color((float)Math.random(),
(float)Math.random(),
(float)Math.random());
}
for (int j=0; j<V.num_vertices; j++) {
V.l_vertices[j].color_vertice = new Color((float)Math.random(),
(float)Math.random(),
(float)Math.random());
}
if (pinta_delaunay) repintar_triangulacion_color();
if (pinta_cierre_convexo) dibuja_cierre_convexo();
if (pinta_voronoi||pinta_sweep) { // Para que repinte todo el voronoi color
for (int p=3; p < V.num_vertices; p++ ) {
contexto_i_voronoi_color.setColor(V.l_vertices[p].color_vertice);
contexto_i_voronoi_color.fillPolygon(lista_voronoi_camb_color[p]);
//El de color con lineas
contexto_i_voronoi_color.setColor(COLOR_LINEAS);
contexto_i_voronoi_color.drawPolygon(lista_voronoi_camb_color[p]);
}
contexto_i_voronoi_color.setColor(COLOR_PUNTOS);
for (int l=0; l<V.num_vertices; l++) {
contexto_i_voronoi_color.fillOval( V.l_vertices[l].punto.x-2,
V.l_vertices[l].punto.y-2,
5,
5);
}
}
baldosa.repaint();
}
}
class pulsar_boton_manual implements ActionListener {
public void actionPerformed (ActionEvent e) {
baldosa.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
posicion_x_linea=TAMANO_BALDOSA_X /2;
seleccion.setEnabled(false); // deja disbale el menu
pinta_sweep=true;
pinta_voronoi=false;
pinta_sweep_automatico=false;
boton_manual.setEnabled(false);
boton_nuevo.setEnabled(false);
boton_automatico.setEnabled(false);
//Esto crea todos los poligonos en l_polig
l_polig = new Polygon[V.num_vertices];
Polygon voro;
voro = new Polygon();
lado lado_aux1;
lado lado_aux2;
float cx;
float cy;
for (int j=3; j<V.num_vertices; j++) {
voro = new Polygon();
lado_aux1 = new lado(null, null, null, null, null);
lado_aux2 = new lado(null, null, null, null, null);
lado_aux1 = V.l_vertices[j].lado_incidente;
cx= (C.l_caras[0].circun_x_float(lado_aux1.cara_incidente));
cy= (C.l_caras[0].circun_y_float(lado_aux1.cara_incidente));
voro.addPoint( (int)Math.round(cx), (int)Math.round(cy));
lado_aux2 = lado_aux1.prev.twin;
while ( lado_aux2 != lado_aux1 ) {
cx= (C.l_caras[0].circun_x_float(lado_aux2.cara_incidente));
cy= (C.l_caras[0].circun_y_float(lado_aux2.cara_incidente));
voro.addPoint( (int)Math.round(cx), (int)Math.round(cy));
lado_aux2 = lado_aux2.prev.twin;
}
l_polig[j]=new Polygon();
l_polig[j]=voro;
} // Fin de todos los voronois
baldosa.removeMouseListener(accion_pulsar_punto);
baldosa.addMouseMotionListener( drag_sweep = new hacer_drag_sweep());
baldosa.addMouseListener( click_sweep = new hacer_click_sweep());
add(boton_volver);
pinta_sweep=true; //solo para la primera vez
baldosa.repaint(); //solo util la primera vez que se pulsa
}
}
class pulsar_boton_automatico implements ActionListener {
public void actionPerformed (ActionEvent e) {
baldosa.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
baldosa.removeMouseListener(accion_pulsar_punto);
boton_automatico.setEnabled(false);
boton_nuevo.setEnabled(false);
boton_manual.setEnabled(false);
seleccion.setEnabled(false);
add(boton_comenzar);
add(velocidad);
add(boton_volver);
}
}
class pulsar_boton_comenzar implements ActionListener {
//Es el del comienzo de la simulacion automatica
public void actionPerformed (ActionEvent e) {
boton_comenzar.setEnabled(false);
pinta_sweep=true;
pinta_sweep_automatico=true;
pinta_voronoi=false;
boton_automatico.setEnabled(false);
boton_manual.setEnabled(false);
seleccion.setEnabled(false);
boton_nuevo.setEnabled(false);
baldosa.removeMouseListener(accion_pulsar_punto);
posicion_x_linea=TAMANO_BALDOSA_X;
baldosa.repaint();
}
}
class pulsar_boton_volver implements ActionListener {
public void actionPerformed (ActionEvent e) {
boton_comenzar.setEnabled(true);
posicion_x_linea=TAMANO_BALDOSA_X /2;
seleccion.setEnabled(true); // deja disbale el menu
pinta_sweep=false;
pinta_voronoi=true;
boton_manual.setEnabled(true);
boton_automatico.setEnabled(true);
boton_nuevo.setEnabled(true);
remove(boton_volver);
remove(velocidad);
remove(boton_comenzar);
baldosa.removeMouseMotionListener(drag_sweep);
baldosa.removeMouseListener(click_sweep);
baldosa.addMouseListener( accion_pulsar_punto);
baldosa.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
baldosa.repaint();
}
}
class pulsar_velocidad implements ItemListener {
public void itemStateChanged (ItemEvent e) {
if (e.getItem().equals(" Muy Lento")) {
incremento=1;
}
if (e.getItem().equals(" Lento")) {
incremento=2;
}
if (e.getItem().equals(" Medio")) {
incremento=3;
}
if (e.getItem().equals(" Rápido")) {
incremento=4;
}
if (e.getItem().equals(" Muy Rápido")) {
incremento=5;
}
}
}
class pulsar_seleccion implements ItemListener {
// Evento de pulsacion del Choice
public void itemStateChanged (ItemEvent e) {
if (e.getItem().equals(" Cierre Convexo")) {
remove(titulo);
remove(boton_automatico);
remove(boton_manual);
if (check_voro.isShowing()){
remove(check_voro);
remove(check_circulos);
}
if (pinta_sweep) {
baldosa.addMouseListener(accion_pulsar_punto);
baldosa.removeMouseMotionListener(drag_sweep);
baldosa.removeMouseListener(click_sweep);
if (pinta_color) add(boton_cambiar_color);
}
pinta_cierre_convexo=true;
pinta_delaunay=false;
pinta_voronoi=false;
pinta_sweep=false;
dibuja_cierre_convexo();
}
if (e.getItem().equals(" Triangulación de Delaunay")) {
remove(titulo);
remove(boton_automatico);
remove(boton_manual);
if (!check_voro.isShowing() && !pinta_color){
add(check_voro);
add(check_circulos);
}
if (pinta_sweep) {
baldosa.addMouseListener(accion_pulsar_punto);
baldosa.removeMouseMotionListener(drag_sweep);
baldosa.removeMouseListener(click_sweep);
if (pinta_color) add(boton_cambiar_color);
}
pinta_delaunay=true;
pinta_voronoi=false;
pinta_cierre_convexo=false;
pinta_sweep=false;
}
if (e.getItem().equals(" Diagrama de Voronoi")) {
if (check_voro.isShowing()){
remove(check_voro);
remove(check_circulos);
}
if ((!pinta_voronoi)&&(V.num_vertices>3)) {
if (!titulo.isShowing()) add(titulo);
if (!boton_automatico.isShowing()) add(boton_automatico);
if (!boton_manual.isShowing()) add(boton_manual);
}
if (pinta_sweep) {
baldosa.addMouseListener(accion_pulsar_punto);
baldosa.removeMouseMotionListener(drag_sweep);
baldosa.removeMouseListener(click_sweep);
if (pinta_color) add(boton_cambiar_color);
}
pinta_voronoi=true;
pinta_delaunay=false;
pinta_cierre_convexo=false;
pinta_sweep=false;
}
baldosa.repaint();
}
}
class pulsar_check_circulos implements ItemListener {
public void itemStateChanged (ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED)
mostrar_circulos_dela=true;
if (e.getStateChange() == ItemEvent.DESELECTED)
mostrar_circulos_dela=false;
baldosa.repaint();
}
}
class pulsar_check_voro implements ItemListener {
public void itemStateChanged (ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED)
mostrar_voro_dela=true;
if (e.getStateChange() == ItemEvent.DESELECTED)
mostrar_voro_dela=false;
baldosa.repaint();
}
}
class pulsar_check_b_n implements ItemListener {
// Evento de pulsacion del Check B-N
public void itemStateChanged (ItemEvent e) {
if (pinta_delaunay && !check_voro.isShowing()){
add(check_voro);
add(check_circulos);
}
pinta_b_n = true;
pinta_color = false;
remove(boton_cambiar_color);
if (pinta_cierre_convexo) dibuja_cierre_convexo();
baldosa.repaint();
}
}
class pulsar_checkcolor implements ItemListener {
// Evento de pulsacion del Check Color
public void itemStateChanged (ItemEvent e) {
if (pinta_delaunay && check_voro.isShowing()){
remove(check_voro);
remove(check_circulos);
}
pinta_b_n = false;
pinta_color = true;
add(boton_cambiar_color);
if (pinta_cierre_convexo) dibuja_cierre_convexo();
baldosa.repaint();
}
}
class hacer_click_sweep extends MouseAdapter {
// Click en el canvas para colocar la linea de barrido
public void mousePressed (MouseEvent e) {
baldosa.setCursor(new Cursor(Cursor.W_RESIZE_CURSOR));
posicion_x_linea=e.getPoint().x;
baldosa.repaint();
}
public void mouseReleased (MouseEvent e) {
baldosa.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
}
class hacer_drag_sweep extends MouseMotionAdapter {
// Click en el canvas para colocar la linea de barrido
public void mouseDragged (MouseEvent e) { //Esto esta en prueba para mover la linea de barrido
baldosa.setCursor(new Cursor(Cursor.W_RESIZE_CURSOR));
posicion_x_linea=e.getPoint().x;
baldosa.repaint();
}
public void mouseMoved (MouseEvent e) { //Esto esta en prueba para mover la linea de barrido
if ((e.getPoint().x<=posicion_x_linea+3) &&
(e.getPoint().x>=posicion_x_linea-3)) {
baldosa.setCursor(new Cursor(Cursor.W_RESIZE_CURSOR));
} else {
baldosa.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
}
}
class inserta_punto extends MouseAdapter {
/* Click realizado sobre el Canvas de la baldosa inicial */
//Variables
Point punto;
cara triangulo;
lado lado_i;
lado aux1;
lado aux2;
lado aux3;
lado aux4;
lado aux5;
lado aux6;
lado aux7;
lado aux8;
lado aux9;
lado aux10;
lado aux11;
lado aux12;
lado lado1;
lado lado2;
lado lado3;
cara caraaux1;
cara caraaux2;
cara caraaux3;
cara triangulo_twin;
public void mousePressed (MouseEvent e) {
//Al loro con esto, paro la escucha de la insercion de puntos
baldosa.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
baldosa.removeMouseListener (accion_pulsar_punto);
punto=e.getPoint();
if (m_puntos.esta(punto.x, punto.y) ||
(V.num_vertices == MAX_VERTICES)) {
} else { // No estaba
m_puntos.inserta (punto.x, punto.y); // Lo mete en la matriz booleana
V.inserta(punto, null); // Insertamos el punto en la la lista de vertices
triangulo= new cara(null);
triangulo = triangulo.encuentra_triangulo(V.l_vertices[V.num_vertices-1].punto);
if (triangulo.interior_estricto_al_triangulo(triangulo,
V.l_vertices[V.num_vertices-1].punto)) { //Estamos dentro del triangulo
L.l_lados[L.num_lados] = new lado(null, null, null, null, null);
L.num_lados++;
L.l_lados[L.num_lados] = new lado(null, null, null, null, null);
L.num_lados++;
L.l_lados[L.num_lados] = new lado(null, null, null, null, null);
L.num_lados++;
L.l_lados[L.num_lados] = new lado(null, null, null, null, null);
L.num_lados++;
L.l_lados[L.num_lados] = new lado(null, null, null, null, null);
L.num_lados++;
L.l_lados[L.num_lados] = new lado(null, null, null, null, null);
L.num_lados++;
aux1 = new lado(null, null, null, null, null);
aux2 = new lado(null, null, null, null, null);
aux3 = new lado(null, null, null, null, null);
aux4 = new lado(null, null, null, null, null);
aux5 = new lado(null, null, null, null, null);
aux6 = new lado(null, null, null, null, null);
lado1 = new lado(null, null, null, null, null);
lado2 = new lado(null, null, null, null, null);
lado3 = new lado(null, null, null, null, null);
lado1 = triangulo.lado_interno;
lado2 = triangulo.lado_interno.next;
lado3 = triangulo.lado_interno.prev;
caraaux2 = new cara(null);
caraaux3 = new cara(null);
aux6 = L.l_lados[L.num_lados-1];
aux5 = L.l_lados[L.num_lados-2];
aux4 = L.l_lados[L.num_lados-3];
aux3 = L.l_lados[L.num_lados-4];
aux2 = L.l_lados[L.num_lados-5];
aux1 = L.l_lados[L.num_lados-6];
//Los origenes
aux1.origen = lado2.origen;
aux2.origen = V.l_vertices[V.num_vertices-1];
aux3.origen = lado1.origen;
aux4.origen = V.l_vertices[V.num_vertices-1];
aux5.origen = lado3.origen;
aux6.origen = V.l_vertices[V.num_vertices-1];
//los twin
aux1.twin = aux6;
aux2.twin = aux3;
aux3.twin = aux2;
aux4.twin = aux5;
aux5.twin = aux4;
aux6.twin = aux1;
//los next
aux1.next = aux2;
aux2.next = lado1;
aux3.next = aux4;
aux4.next = lado3;
aux5.next = aux6;
aux6.next = lado2;
//los prev
aux1.prev = lado1;
aux2.prev = aux1;
aux3.prev = lado3;
aux4.prev = aux3;
aux5.prev = lado2;
aux6.prev = aux5;
//Ok el punto insertado
V.l_vertices[V.num_vertices-1].lado_incidente = aux2; //por ejemplo
// Ahora empiezo con las caras
C.l_caras[C.num_caras] = new cara (null);
caraaux2 = C.l_caras[C.num_caras];
caraaux2.lado_interno = lado2;
C.num_caras++;
C.l_caras[C.num_caras] = new cara (null);
caraaux3 = C.l_caras[C.num_caras];
caraaux3.lado_interno = lado3;
C.num_caras++;
//Vamos con las cara_incidente de los nuevos lados
aux1.cara_incidente = triangulo;
aux2.cara_incidente = triangulo;
aux3.cara_incidente = caraaux3;
aux4.cara_incidente = caraaux3;
aux5.cara_incidente = caraaux2;
aux6.cara_incidente = caraaux2;
lado1.cara_incidente = triangulo;
lado2.cara_incidente = caraaux2;
lado3.cara_incidente = caraaux3;
// lados
lado1.next = aux1;
lado2.next = aux5;
lado3.next = aux3;
lado1.prev = aux2;
lado2.prev = aux6;
lado3.prev = aux4;
//
lado1.origen.lado_incidente = lado1;
lado2.origen.lado_incidente = lado2;
lado3.origen.lado_incidente = lado3;
aux6.origen.lado_incidente = aux6;
// Y legalizo los lados
L.l_lados[L.num_lados-1].legaliza_lado(V.l_vertices[V.num_vertices-1],
lado1);
L.l_lados[L.num_lados-1].legaliza_lado(V.l_vertices[V.num_vertices-1],
lado2);
L.l_lados[L.num_lados-1].legaliza_lado(V.l_vertices[V.num_vertices-1],
lado3);
} else { // El punto esta justamente sobre el lado (=0)
//vemaos cual es el lado
lado_i = new lado(null, null, null, null, null);
lado_i = triangulo.lado_interseccion(triangulo,V.l_vertices[V.num_vertices-1].punto);
aux1 = new lado(null, null, null, null, null);
aux2 = new lado(null, null, null, null, null);
aux3 = new lado(null, null, null, null, null);
aux4 = new lado(null, null, null, null, null);
aux5 = new lado(null, null, null, null, null);
aux6 = new lado(null, null, null, null, null);
aux7 = new lado(null, null, null, null, null);
aux8 = new lado(null, null, null, null, null);
aux9 = new lado(null, null, null, null, null);
aux10 = new lado(null, null, null, null, null);
aux11 = new lado(null, null, null, null, null);
aux12 = new lado(null, null, null, null, null);
triangulo_twin = new cara(null);
caraaux1 = new cara (null);
caraaux2 = new cara (null);
aux1 = lado_i;
aux2 = lado_i.next;
aux3 = lado_i.prev;
aux4 = lado_i.twin;
aux5 = lado_i.twin.next;
aux6 = lado_i.twin.prev;
triangulo_twin = aux4.cara_incidente;
//Empezamos con los nuevos lados
L.l_lados[L.num_lados] = new lado (aux3.origen, null, null, null, null);
aux7 = L.l_lados[L.num_lados];
L.num_lados++;
L.l_lados[L.num_lados] = new lado (V.l_vertices[V.num_vertices-1], null, null, null, null);
aux8 = L.l_lados[L.num_lados];
L.num_lados++;
L.l_lados[L.num_lados] = new lado (aux5.origen, null, null, null, null);
aux9 = L.l_lados[L.num_lados];
L.num_lados++;
L.l_lados[L.num_lados] = new lado (V.l_vertices[V.num_vertices-1], null, null, null, null);
aux10 = L.l_lados[L.num_lados];
L.num_lados++;
L.l_lados[L.num_lados] = new lado (aux6.origen, null, null, null, null);
aux11 = L.l_lados[L.num_lados];
L.num_lados++;
L.l_lados[L.num_lados] = new lado (V.l_vertices[V.num_vertices-1], null, null, null, null);
aux12 = L.l_lados[L.num_lados];
L.num_lados++;
//El origen de aux1 ok
aux1.origen = V.l_vertices[V.num_vertices-1];
// Los twin
aux7.twin = aux8;
aux8.twin = aux7;
aux9.twin = aux10;
aux10.twin = aux9;
aux11.twin = aux12;
aux12.twin = aux11;
//Los next
aux1.next = aux2;
aux2.next = aux7;
aux3.next = aux9;
aux4.next = aux12;
aux5.next = aux11;
aux6.next = aux4;
aux7.next = aux1;
aux8.next = aux3;
aux9.next = aux8;
aux10.next = aux5;
aux11.next = aux10;
aux12.next = aux6;
//Los prev
aux1.prev = aux7;
aux2.prev = aux1;
aux3.prev = aux8;
aux4.prev = aux6;
aux5.prev = aux10;
aux6.prev = aux12;
aux7.prev = aux2;
aux8.prev = aux9;
aux9.prev = aux3;
aux10.prev = aux11;
aux11.prev = aux5;
aux12.prev = aux4;
// 2 nuevas caras
C.l_caras[C.num_caras] = new cara (null);
caraaux1 = C.l_caras[C.num_caras];
C.num_caras++;
C.l_caras[C.num_caras] = new cara (null);
caraaux2 = C.l_caras[C.num_caras];
C.num_caras++;
caraaux1.lado_interno = aux9;
caraaux2.lado_interno = aux10;
triangulo.lado_interno = aux1;
triangulo_twin.lado_interno = aux4;
// Las caras incidentes
aux1.cara_incidente = triangulo;
aux2.cara_incidente = triangulo;
aux3.cara_incidente = caraaux1;
aux4.cara_incidente = triangulo_twin;
aux5.cara_incidente = caraaux2;
aux6.cara_incidente = triangulo_twin;
aux7.cara_incidente = triangulo;
aux8.cara_incidente = caraaux1;
aux9.cara_incidente = caraaux1;
aux10.cara_incidente = caraaux2;
aux11.cara_incidente = caraaux2;
aux12.cara_incidente = triangulo_twin;
//Los lado_incidente de los puntos
aux2.origen.lado_incidente = aux2;
aux3.origen.lado_incidente = aux3;
aux5.origen.lado_incidente = aux5;
aux6.origen.lado_incidente = aux6;
V.l_vertices[V.num_vertices-1].lado_incidente = aux1;
// Legalizacion de lados
//
L.l_lados[L.num_lados-1].legaliza_lado(V.l_vertices[V.num_vertices-1], aux2);
L.l_lados[L.num_lados-1].legaliza_lado(V.l_vertices[V.num_vertices-1], aux3);
L.l_lados[L.num_lados-1].legaliza_lado(V.l_vertices[V.num_vertices-1], aux5);
L.l_lados[L.num_lados-1].legaliza_lado(V.l_vertices[V.num_vertices-1], aux6);
// Fin
}
//Vamos a intentar dibujar de manera eficiente
Polygon P;
Polygon tri;
Color colores[];
colores=new Color[MAX_CARAS];
P = new Polygon();
lado l_i;
lado l_ax;
l_i=new lado(null,null,null,null,null);
l_i=V.l_vertices[V.num_vertices-1].lado_incidente;
P.addPoint(l_i.next.origen.punto.x,
l_i.next.origen.punto.y);
colores[0]=l_i.cara_incidente.color_cara;
l_ax=l_i.next.next.twin;
while (l_ax != l_i) {
P.addPoint(l_ax.next.origen.punto.x,
l_ax.next.origen.punto.y);
colores[P.npoints-1]=l_ax.cara_incidente.color_cara;
l_ax=l_ax.next.next.twin;
}
for (int c=0; c<P.npoints; c++){
if ((P.xpoints[c]!=V.l_vertices[0].punto.x) &&
(P.ypoints[c]!=V.l_vertices[0].punto.y) &&
(P.xpoints[c]!=V.l_vertices[1].punto.x) &&
(P.ypoints[c]!=V.l_vertices[1].punto.y) &&
(P.xpoints[c]!=V.l_vertices[2].punto.x) &&
(P.ypoints[c]!=V.l_vertices[2].punto.y) &&
(P.xpoints[(c+1)%P.npoints]!=V.l_vertices[0].punto.x) &&
(P.ypoints[(c+1)%P.npoints]!=V.l_vertices[0].punto.y) &&
(P.xpoints[(c+1)%P.npoints]!=V.l_vertices[1].punto.x) &&
(P.ypoints[(c+1)%P.npoints]!=V.l_vertices[1].punto.y) &&
(P.xpoints[(c+1)%P.npoints]!=V.l_vertices[2].punto.x) &&
(P.ypoints[(c+1)%P.npoints]!=V.l_vertices[2].punto.y)) {
tri= new Polygon();
tri.addPoint(P.xpoints[c], P.ypoints[c]);
tri.addPoint(P.xpoints[(c+1)%P.npoints], P.ypoints[(c+1)%P.npoints]);
tri.addPoint(V.l_vertices[V.num_vertices-1].punto.x,
V.l_vertices[V.num_vertices-1].punto.y);
contexto_baldosa_buffer.setColor(COLOR_FONDO_BALDOSA);
contexto_baldosa_buffer.fillPolygon(tri);
contexto_baldosa_color.setColor(colores[c]);
contexto_baldosa_color.fillPolygon(tri);
contexto_baldosa_buffer.setColor(COLOR_LINEAS);
contexto_baldosa_color.setColor(COLOR_LINEAS);
contexto_baldosa_buffer.drawPolygon(tri);
contexto_baldosa_color.drawPolygon(tri);
}
}
if (m_puntos.num_puntos==2) {
contexto_baldosa_buffer.setColor(COLOR_LINEAS);
contexto_baldosa_buffer.drawLine(V.l_vertices[V.num_vertices-1].punto.x,
V.l_vertices[V.num_vertices-1].punto.y,
V.l_vertices[V.num_vertices-2].punto.x,
V.l_vertices[V.num_vertices-2].punto.y);
contexto_baldosa_color.setColor(C.l_caras[C.num_caras-1].color_cara);
contexto_baldosa_color.drawLine(V.l_vertices[V.num_vertices-1].punto.x,
V.l_vertices[V.num_vertices-1].punto.y,
V.l_vertices[V.num_vertices-2].punto.x,
V.l_vertices[V.num_vertices-2].punto.y);
}
contexto_baldosa_buffer.setColor(COLOR_PUNTOS);
contexto_baldosa_color.setColor(COLOR_PUNTOS);
for (int h=0; h<P.npoints; h++) {
contexto_baldosa_color.fillOval( P.xpoints[h]-2,
P.ypoints[h]-2,
5,
5);
contexto_baldosa_buffer.fillOval( P.xpoints[h]-2,
P.ypoints[h]-2,
5,
5);
}
contexto_baldosa_color.fillOval( V.l_vertices[V.num_vertices-1].punto.x-2,
V.l_vertices[V.num_vertices-1].punto.y-2,
5,
5);
contexto_baldosa_buffer.fillOval( V.l_vertices[V.num_vertices-1].punto.x-2,
V.l_vertices[V.num_vertices-1].punto.y-2,
5,
5);
// Ahora si es necesario llamo a dibuja_cierre_convexo
if (pinta_cierre_convexo) dibuja_cierre_convexo();
} //del else (el punto no existia)
dibuja_voronoi_vertice(V.l_vertices[V.num_vertices-1]);
baldosa.repaint();
baldosa.addMouseListener (accion_pulsar_punto);
if ((pinta_voronoi)&&(V.num_vertices>3)) {
if (!titulo.isShowing()) add(titulo);
if (!boton_automatico.isShowing()) add(boton_automatico);
if (!boton_manual.isShowing()) add(boton_manual);
}
} //Del metodo Mousepressed
} // De la clase inserta_punto
public Image dibuja_fondo(Image img) {
// Dibuja una imagen con forma de ventana Windows
Graphics g;
int ancho, alto;
g = img.getGraphics();
ancho = img.getWidth(null); // Tamaño en pixels ancho imagen
alto = img.getHeight(null); // Tamaño en pixels alto imagen
g.setColor(Color.lightGray);
g.fillRect(0, 0, ancho, alto); // Cubre todo de gris claro
g.setColor(Color.white.darker()); //Para el rectángulo de abajo gris claro
g.fillRect(4, BALDOSA_Y + TAMANO_BALDOSA_Y + 11, ancho, alto); //Lo dibuja
g.setColor(Color.black); //Sombra negra
g.drawRect(ancho-1,0,ancho-1,alto-1); //rectangulo negro
g.drawLine(0,alto-1,ancho-1,alto-1); // abajo
g.setColor(Color.gray); //Vamos al gris
g.drawLine(1,alto-2,ancho -2,alto-2); //abajo
g.drawLine(ancho-2,1,ancho-2,alto-2); //derecha
g.setColor(Color.white); //ahora banco
g.drawLine(1,1,ancho-3,1); // arriba
g.drawLine(1,1,1,alto-3); // izqda.
g.setColor(Color.blue.darker().darker()); //Azul Oscuro para el titulo
g.fillRect(4,4,ancho-8,18);
g.setColor(Color.gray); //Gris otra vez para linea de separacion
g.drawLine(4,23,ancho-5,23); // Linea de separaci¢n
g.setColor(Color.white); //idem
g.drawLine(4,24,ancho-5,24); //idem
g.setColor(Color.white); //Gris otra vez para linea de separacion abajo
g.drawLine(4,BALDOSA_Y + TAMANO_BALDOSA_Y + 9,
ancho-5,BALDOSA_Y + TAMANO_BALDOSA_Y + 9); // Linea de separaci¢n
g.setColor(Color.gray); //idem
g.drawLine(4,BALDOSA_Y + TAMANO_BALDOSA_Y + 10,
ancho-5,BALDOSA_Y + TAMANO_BALDOSA_Y + 10); //idem
g.setColor(Color.red); //Para el nombre de la ventana
g.setFont(new Font("Sanserif",Font.BOLD,17)); //Tipo de letra
g.drawString("V",10,19);
g.setColor(Color.green); //Para el nombre de la ventana
g.setFont(new Font("Sanserif",Font.BOLD,15)); //Tipo de letra
g.drawString("V",13,19);
g.setColor(Color.yellow); //Para el nombre de la ventana
g.setFont(new Font("Sanserif",Font.BOLD,12)); //Tipo de letra
g.drawString("V",18,19);
g.setColor(Color.white.brighter()); //Para el nombre de la ventana
g.setFont(new Font("Sanserif",Font.BOLD,12)); //Tipo de letra
g.drawString("Delaunay/Voronoi/Simulación Sweep Line", 37,17); // Título
g.setColor(Color.green);
g.setFont(new Font("Sanserif",Font.PLAIN,11));
g.drawString("Versión 9.3.7",DIM_APPLET_X-120, 17);
// Para poner icono a la derecha arriba
g.setColor(Color.green);
g.setFont(new Font("Sanserif",Font.BOLD,17));
g.drawString("o",DIM_APPLET_X-17 ,17);
g.setColor(Color.red);
g.drawString("V",DIM_APPLET_X-21 ,19);
g.drawString("V",DIM_APPLET_X-22 ,19);
g.setColor(Color.yellow);
g.setFont(new Font("Sanserif",Font.BOLD,16));
g.drawString("o",DIM_APPLET_X-25 ,20);
// Ahora pongo el reborde 3D al Panel de dibujo alrededor de la baldosa
g.setColor(Color.gray);
g.drawLine(BALDOSA_X - 1,
BALDOSA_Y - 1,
BALDOSA_X + TAMANO_BALDOSA_X,
BALDOSA_Y - 1);
g.drawLine(BALDOSA_X - 1,
BALDOSA_Y - 1,
BALDOSA_X - 1,
BALDOSA_Y + TAMANO_BALDOSA_Y);
g.setColor(Color.white);
g.drawLine(BALDOSA_X - 1,
BALDOSA_Y + TAMANO_BALDOSA_Y + 1,
BALDOSA_X + TAMANO_BALDOSA_X + 1,
BALDOSA_Y + TAMANO_BALDOSA_Y + 1);
g.drawLine(BALDOSA_X + TAMANO_BALDOSA_X +1,
BALDOSA_Y - 1,
BALDOSA_X + TAMANO_BALDOSA_X + 1,
BALDOSA_Y + TAMANO_BALDOSA_Y+ 1);
g.drawLine(BALDOSA_X - 4,
BALDOSA_Y - 4,
BALDOSA_X + TAMANO_BALDOSA_X + 3,
BALDOSA_Y - 4);
g.drawLine(BALDOSA_X - 4,
BALDOSA_Y - 4,
BALDOSA_X - 4,
BALDOSA_Y + TAMANO_BALDOSA_Y + 3);
g.setColor(Color.gray);
g.drawLine(BALDOSA_X - 4,
BALDOSA_Y + TAMANO_BALDOSA_Y + 4,
BALDOSA_X + TAMANO_BALDOSA_X + 4,
BALDOSA_Y + TAMANO_BALDOSA_Y + 4);
g.drawLine(BALDOSA_X + TAMANO_BALDOSA_X + 4,
BALDOSA_Y - 4,
BALDOSA_X + TAMANO_BALDOSA_X + 4,
BALDOSA_Y + TAMANO_BALDOSA_Y + 4);
g.setColor(Color.black);
g.drawLine(BALDOSA_X + TAMANO_BALDOSA_X + 5,
BALDOSA_Y - 5,
BALDOSA_X + TAMANO_BALDOSA_X + 5,
BALDOSA_Y + TAMANO_BALDOSA_Y + 5);
g.drawLine(BALDOSA_X - 5,
BALDOSA_Y + TAMANO_BALDOSA_Y + 5,
BALDOSA_X + TAMANO_BALDOSA_X + 5,
BALDOSA_Y + TAMANO_BALDOSA_Y + 5);
return img;
}
public void init() {
V = new lista_vertices(MAX_VERTICES); // Lista de vertices
L = new lista_lados(MAX_LADOS); // Lista de lados
C = new lista_caras(MAX_CARAS); // Lista de caras
lista_voronoi_camb_color = new Polygon[MAX_VERTICES]; //Lista de voronois
//repintar color
this.setLayout(null); //Coloco manualmente los componentes
DIM_APPLET_X = this.getSize().width;
DIM_APPLET_Y = this.getSize().height;
// Tamaño de la baldosa en el init en relación al tamaño del applet
// Aquí se cambian las relaciones de tamaño de la baldosa de dibujo
TAMANO_BALDOSA_X = DIM_APPLET_X - 2 * BALDOSA_X; //Tamaño en pixels de la baldosa gráfica (Image)(Coord X)
TAMANO_BALDOSA_Y = DIM_APPLET_Y - BALDOSA_Y - 70; //Tamaño en pixels de la baldosa gr fica (Image)(Coord Y)
// Creo la matriz booleana que indica si el punto está o no insertado
m_puntos= new matriz_puntos(TAMANO_BALDOSA_X, TAMANO_BALDOSA_Y);
// Creo la imagen del tamaño del applet para dibujar el fondo
fondo=this.createImage(DIM_APPLET_X, DIM_APPLET_Y);
fondo=dibuja_fondo(fondo); //Dibujamos el fondo
// Creo el doble buffer de la baldosa inicial
baldosa_buffer=this.createImage( TAMANO_BALDOSA_X, TAMANO_BALDOSA_Y);
contexto_baldosa_buffer=baldosa_buffer.getGraphics();
contexto_baldosa_buffer.setColor(COLOR_FONDO_BALDOSA);
contexto_baldosa_buffer.fillRect(0,0,TAMANO_BALDOSA_X, TAMANO_BALDOSA_Y);
contexto_baldosa_buffer.setColor(Color.black);
// Baldosa color
baldosa_color=this.createImage( TAMANO_BALDOSA_X, TAMANO_BALDOSA_Y);
contexto_baldosa_color=baldosa_color.getGraphics();
contexto_baldosa_color.setColor(COLOR_FONDO_BALDOSA);
contexto_baldosa_color.fillRect(0,0,TAMANO_BALDOSA_X, TAMANO_BALDOSA_Y);
contexto_baldosa_color.setColor(Color.black);
// Baldosa cierre convexo
cierre_convexo=this.createImage( TAMANO_BALDOSA_X, TAMANO_BALDOSA_Y);
contexto_cierre_convexo=cierre_convexo.getGraphics();
contexto_cierre_convexo.setColor(COLOR_FONDO_BALDOSA); //FONDO_BALDOSA);
contexto_cierre_convexo.fillRect(0,0,TAMANO_BALDOSA_X, TAMANO_BALDOSA_Y);
contexto_cierre_convexo.setColor(Color.black);
// Baldosa voronoi
i_voronoi=this.createImage( TAMANO_BALDOSA_X, TAMANO_BALDOSA_Y);
contexto_i_voronoi=i_voronoi.getGraphics();
contexto_i_voronoi.setColor(COLOR_FONDO_BALDOSA); //FONDO_BALDOSA);
contexto_i_voronoi.fillRect(0,0,TAMANO_BALDOSA_X, TAMANO_BALDOSA_Y);
contexto_i_voronoi.setColor(Color.black);
// Baldosa voronoi color
i_voronoi_color=this.createImage( TAMANO_BALDOSA_X, TAMANO_BALDOSA_Y);
contexto_i_voronoi_color=i_voronoi_color.getGraphics();
contexto_i_voronoi_color.setColor(COLOR_FONDO_BALDOSA); //FONDO_BALDOSA);
contexto_i_voronoi_color.fillRect(0,0,TAMANO_BALDOSA_X, TAMANO_BALDOSA_Y);
contexto_i_voronoi_color.setColor(Color.black);
// Baldosa para dibujar la evolucion de la linea de barrido
sweep=this.createImage( TAMANO_BALDOSA_X, TAMANO_BALDOSA_Y);
contexto_sweep=sweep.getGraphics();
// Baldosa para dibujar circunferencia y Voronoi en delaunay
cir_dela=this.createImage( TAMANO_BALDOSA_X, TAMANO_BALDOSA_Y);
contexto_cir_dela = cir_dela.getGraphics();
// Creo la imagen del tamaño del applet para dibujar el fondo
baldosa = new micanvas();
baldosa.setBounds( BALDOSA_X, BALDOSA_Y,
TAMANO_BALDOSA_X, TAMANO_BALDOSA_Y);
//No escucha eventos el canvas hasta que pulse el botón
//baldosa.addMouseListener(accion_pulsar_punto = new inserta_punto());
add(baldosa); //Añado el Canvas baldosa
// Añado el botón para empezar a insertar puntos
String s;
s="¡¡ Pulsar aquí para iniciar la Aplicación !!";
boton_insertar_puntos = new Button(s);
FontMetrics fm;
Font f;
f=new Font("Sanserif",Font.BOLD,15);
fm=boton_insertar_puntos.getFontMetrics(f);
int tam=0;
tam=fm.stringWidth(s);
boton_insertar_puntos.setFont(f);
boton_insertar_puntos.setForeground(Color.black);
boton_insertar_puntos.setBounds((DIM_APPLET_X-tam)/2-30,
BALDOSA_Y + TAMANO_BALDOSA_Y + 15,
tam+60,
DIM_APPLET_Y -
(BALDOSA_Y + TAMANO_BALDOSA_Y + 15) - 10 );
boton_insertar_puntos.addActionListener(new pulsar_boton_insertar_puntos());
boton_insertar_puntos.setBackground(Color.lightGray);
add(boton_insertar_puntos);
// Esto va en pruebas para la caratula inicial
contexto_baldosa_buffer.setColor(Color.black);
contexto_baldosa_buffer.fillRect(0,0,TAMANO_BALDOSA_X, TAMANO_BALDOSA_Y);
f=new Font("Sanserif",Font.BOLD,30);
fm=this.getFontMetrics(f);
s="FACULTAD DE INFORMATICA - U.P.M.";
tam=fm.stringWidth(s);
contexto_baldosa_buffer.setFont(f);
contexto_baldosa_buffer.setColor(Color.blue);
contexto_baldosa_buffer.drawString(s,
(TAMANO_BALDOSA_X-tam)/2,
TAMANO_BALDOSA_Y/5);
f=new Font("Sanserif",Font.ITALIC,25);
fm=this.getFontMetrics(f);
s="VISUALIZACION INTERACTIVA DEL ALGORITMO";
tam=fm.stringWidth(s);
contexto_baldosa_buffer.setFont(f);
contexto_baldosa_buffer.setColor(Color.white);
contexto_baldosa_buffer.drawString(s,
(TAMANO_BALDOSA_X-tam)/2,
TAMANO_BALDOSA_Y*2/5);
contexto_baldosa_buffer.drawLine((TAMANO_BALDOSA_X-tam)/2,
TAMANO_BALDOSA_Y*2/5+1,
TAMANO_BALDOSA_X-(TAMANO_BALDOSA_X-tam)/2,
TAMANO_BALDOSA_Y*2/5+1);
contexto_baldosa_buffer.drawLine((TAMANO_BALDOSA_X-tam)/2,
TAMANO_BALDOSA_Y*2/5+2,
TAMANO_BALDOSA_X-(TAMANO_BALDOSA_X-tam)/2,
TAMANO_BALDOSA_Y*2/5+2);
s="DE FORTUNE EN INTERNET";
tam=fm.stringWidth(s);
contexto_baldosa_buffer.drawString(s,
(TAMANO_BALDOSA_X-tam)/2,
TAMANO_BALDOSA_Y*2/5 + fm.getHeight());
contexto_baldosa_buffer.drawLine((TAMANO_BALDOSA_X-tam)/2,
TAMANO_BALDOSA_Y*2/5 + fm.getHeight()+1,
TAMANO_BALDOSA_X-(TAMANO_BALDOSA_X-tam)/2,
TAMANO_BALDOSA_Y*2/5 + fm.getHeight()+1);
contexto_baldosa_buffer.drawLine((TAMANO_BALDOSA_X-tam)/2,
TAMANO_BALDOSA_Y*2/5 + fm.getHeight()+2,
TAMANO_BALDOSA_X-(TAMANO_BALDOSA_X-tam)/2,
TAMANO_BALDOSA_Y*2/5 + fm.getHeight()+2);
s="TUTOR: Manuel Abellanas Oar";
f=new Font("Sanserif",Font.PLAIN,18);
fm=this.getFontMetrics(f);
tam=fm.stringWidth(s);
contexto_baldosa_buffer.setFont(f);
contexto_baldosa_buffer.setColor(Color.gray);
contexto_baldosa_buffer.drawString(s,
(TAMANO_BALDOSA_X-tam)/2,
TAMANO_BALDOSA_Y*8/10);
s="AUTOR: Juan Carlos Ferreras Ferreras";
tam=fm.stringWidth(s);
contexto_baldosa_buffer.drawString(s,
(TAMANO_BALDOSA_X-tam)/2,
TAMANO_BALDOSA_Y*8/10+fm.getHeight());
s="Diciembre de 2000";
f=new Font("Sanserif",Font.ITALIC,16);
fm=this.getFontMetrics(f);
tam=fm.stringWidth(s);
contexto_baldosa_buffer.setFont(f);
contexto_baldosa_buffer.drawString(s,
(TAMANO_BALDOSA_X-tam)/2,
TAMANO_BALDOSA_Y*8/10+5*fm.getHeight()/2);
//Añado el evento al canvas y lo paro después
baldosa.addMouseListener(accion_pulsar_punto = new inserta_punto());
baldosa.removeMouseListener (accion_pulsar_punto);
// Al loro
seleccion = new Choice();
seleccion.add(" Triangulación de Delaunay");
seleccion.add(" Diagrama de Voronoi");
seleccion.add(" Cierre Convexo");
seleccion.setBounds(BALDOSA_X,
BALDOSA_Y + TAMANO_BALDOSA_Y + 20,
(TAMANO_BALDOSA_X + 11)/3 ,
19);
seleccion.addItemListener(new pulsar_seleccion());
velocidad = new Choice();
velocidad.add(" Muy Lento");
velocidad.add(" Lento");
velocidad.add(" Medio");
velocidad.add(" Rápido");
velocidad.add(" Muy Rápido");
velocidad.setBounds(5*(TAMANO_BALDOSA_X + 11)/12+2*(TAMANO_BALDOSA_X + 11)/12+7,
DIM_APPLET_Y - 22,
2*(TAMANO_BALDOSA_X + 11)/12+3,
19);
velocidad.addItemListener(new pulsar_velocidad());
// Check para triangulacion circilos y voronoi En pruebas
check_circulos = new Checkbox("Mostrar Círculos");
check_voro = new Checkbox("Mostrar Voronoi");
check_voro.setBounds(5*(TAMANO_BALDOSA_X + 11)/12 ,
DIM_APPLET_Y - 52,
2*(TAMANO_BALDOSA_X + 11)/12+13,
19);
check_voro.setBackground(Color.white.darker());
check_voro.addItemListener(new pulsar_check_voro());
check_circulos.setBounds(5*(TAMANO_BALDOSA_X + 11)/12 ,
DIM_APPLET_Y - 32,
2*(TAMANO_BALDOSA_X + 11)/12+13,
19);
check_circulos.setBackground(Color.white.darker());
check_circulos.addItemListener(new pulsar_check_circulos());
//grupo de checks
grupo_check = new CheckboxGroup();
check_b_n = new Checkbox( "B/N", grupo_check, true);
check_b_n.setBackground(Color.white.darker());
check_b_n.setBounds(BALDOSA_X ,
DIM_APPLET_Y - 22,
(TAMANO_BALDOSA_X + 11)/12-5,
19);
check_b_n.addItemListener(new pulsar_check_b_n());
check_color = new Checkbox( "Color", grupo_check, false);
check_color.setBackground(Color.white.darker());
check_color.setBounds((TAMANO_BALDOSA_X + 11)/12+15,
DIM_APPLET_Y - 22,
52,
19);
check_color.addItemListener(new pulsar_checkcolor());
//boton para cambiar el color
boton_cambiar_color = new Button( "Cambiar colores");
boton_cambiar_color.setBackground(Color.lightGray);
boton_cambiar_color.setBounds(BALDOSA_X +(TAMANO_BALDOSA_X + 11)/6,
DIM_APPLET_Y - 22,
2*(TAMANO_BALDOSA_X + 11)/12+3,
19);
boton_cambiar_color.addActionListener(new pulsar_boton_cambiar_color());
//Boton manual sweep
boton_manual = new Button("Manual");
boton_manual.setBounds(5*(TAMANO_BALDOSA_X + 11)/12,
DIM_APPLET_Y - 42,
2*(TAMANO_BALDOSA_X + 11)/12+3,
19);
boton_manual.setForeground(Color.blue.darker().darker());
boton_manual.addActionListener(new pulsar_boton_manual());
//Boton volver
boton_volver = new Button("Volver");
boton_volver.setBounds(5*(TAMANO_BALDOSA_X + 11)/12+2*(TAMANO_BALDOSA_X + 11)/12+7,
DIM_APPLET_Y - 42,
2*(TAMANO_BALDOSA_X + 11)/12+3,
19);
boton_volver.setFont(new Font("Sanserif",Font.BOLD,14));
boton_volver.setForeground(Color.red);
boton_volver.addActionListener(new pulsar_boton_volver());
boton_comenzar = new Button("Start");
boton_comenzar.setBounds((5*(TAMANO_BALDOSA_X + 11)/12+2*(TAMANO_BALDOSA_X + 11)/12+7)+(2*(TAMANO_BALDOSA_X + 11)/12+3)+3,
DIM_APPLET_Y - 42,
(2*(TAMANO_BALDOSA_X + 11)/12+3)/2+3,
40);
boton_comenzar.setFont(new Font("Sanserif",Font.BOLD,15));
boton_comenzar.setForeground(Color.blue.darker().darker());
boton_comenzar.addActionListener(new pulsar_boton_comenzar());
//Boton automatico sweep
boton_automatico = new Button("Automático");
boton_automatico.setBounds(5*(TAMANO_BALDOSA_X + 11)/12,
DIM_APPLET_Y - 22,
2*(TAMANO_BALDOSA_X + 11)/12+3,
19);
boton_automatico.setForeground(Color.blue.darker().darker());
boton_automatico.addActionListener(new pulsar_boton_automatico());
// Esto es para cargar las clases de drag y sweep y no ralenticen la carga
drag_sweep = new hacer_drag_sweep();
click_sweep = new hacer_click_sweep();
// El titulo del Sweep
titulo =new Label("SIMULACION SWEEP LINE",Label.CENTER);
titulo.setBounds(5*(TAMANO_BALDOSA_X + 11)/12-17,
DIM_APPLET_Y - 58,
2*(TAMANO_BALDOSA_X + 11)/12+35,
16);
titulo.setFont(new Font("Sanserif",Font.BOLD,11));
titulo.setBackground(Color.white.darker());
titulo.setForeground(Color.blue.darker().darker());
boton_nuevo = new Button("Nuevo");
boton_nuevo.setBounds(BALDOSA_X + 5 * (TAMANO_BALDOSA_X + 11)/6,
BALDOSA_Y + TAMANO_BALDOSA_Y + 15,
(TAMANO_BALDOSA_X + 11) / 6 - 4,
DIM_APPLET_Y -
(BALDOSA_Y + TAMANO_BALDOSA_Y + 15) - 10 );
boton_nuevo.addActionListener(new pulsar_boton_nuevo());
boton_nuevo.setBackground(Color.lightGray);
} //del init()
public void update(Graphics g) {
paint(g);
}
public void paint(Graphics g) {
g.drawImage(fondo,0,0,null,null);
}
} //De Voronoi