diff --git a/src/cl/cromer/estructuras/Arbol.java b/src/cl/cromer/estructuras/Arbol.java index 80787da..6d64c75 100644 --- a/src/cl/cromer/estructuras/Arbol.java +++ b/src/cl/cromer/estructuras/Arbol.java @@ -55,6 +55,7 @@ public class Arbol { niveles.add(new ArrayList<>()); } calcularNiveles(arbol, 0); + niveles.remove(niveles.size() - 1); return true; } @@ -76,6 +77,7 @@ public class Arbol { niveles.add(new ArrayList<>()); } calcularNiveles(arbol, 0); + niveles.remove(niveles.size() - 1); return true; } @@ -123,7 +125,6 @@ public class Arbol { public void calcularNiveles(ArbolNodo nodo, int nivel) { try { if (nodo != null) { - nodo.setNivel(nivel); niveles.get(nivel).add(nodo); nivel++; calcularNiveles(nodo.getIzquerda(), nivel); diff --git a/src/cl/cromer/estructuras/ArbolController.java b/src/cl/cromer/estructuras/ArbolController.java index f2852e8..243174a 100644 --- a/src/cl/cromer/estructuras/ArbolController.java +++ b/src/cl/cromer/estructuras/ArbolController.java @@ -2,7 +2,6 @@ package cl.cromer.estructuras; import javafx.fxml.FXML; import javafx.fxml.Initializable; -import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.layout.GridPane; import javafx.scene.text.Text; @@ -79,14 +78,25 @@ public class ArbolController implements Initializable { arbol.insertar(15);*/ arbol.insertar(5); - arbol.insertar(4); arbol.insertar(3); + arbol.insertar(4); + arbol.insertar(2); + arbol.insertar(1); + arbol.insertar(8); + arbol.insertar(7); + arbol.insertar(6); + arbol.insertar(9); + //arbol.insertar(7); + + /*arbol.insertar(5); + arbol.insertar(3); + arbol.insertar(4); arbol.insertar(2); arbol.insertar(1); arbol.insertar(6); arbol.insertar(7); arbol.insertar(8); - arbol.insertar(9); + arbol.insertar(9);*/ } /** @@ -102,7 +112,7 @@ public class ArbolController implements Initializable { /*String codigoTexto = new Scanner(getClass().getResourceAsStream("/cl/cromer/estructuras/code/array" + tipo + "/insertar")).useDelimiter("\\Z").next(); codigoArray.setText(codigoTexto);*/ - /*if (valorArbol.getText() != null && ! valorArbol.getText().trim().equals("")) { + if (valorArbol.getText() != null && ! valorArbol.getText().trim().equals("")) { try { boolean exito = arbol.insertar(Integer.valueOf(valorArbol.getText())); if (exito) { @@ -120,17 +130,52 @@ public class ArbolController implements Initializable { } else { Main.mostrarError(resourceBundle.getString("arbolNoValor"), resourceBundle); - }*/ + } generarGrafico(); } + /** + * Eliminar un valor del arbol y mostrar el codigo en la pantalla. + */ + /*@FXML + protected void botonEliminar() { + if (scene == null) { + initializeArbol(); + } + + // Mostrar el codigo + String codigoTexto = new Scanner(getClass().getResourceAsStream("/cl/cromer/estructuras/code/array" + tipo + "/insertar")).useDelimiter("\\Z").next(); + codigoArray.setText(codigoTexto); + + if (valorArbol.getText() != null && ! valorArbol.getText().trim().equals("")) { + try { + boolean exito = arbol.eliminar(Integer.valueOf(valorArbol.getText())); + if (exito) { + valorArbol.setText(""); + generarGrafico(); + } + else { + Main.mostrarError(resourceBundle.getString("arbolValorExiste"), resourceBundle); + } + } + catch (NumberFormatException exception) { + // El error no es fatal, sigue + Main.mostrarError(resourceBundle.getString("arbolNoValor"), resourceBundle); + } + } + else { + Main.mostrarError(resourceBundle.getString("arbolNoValor"), resourceBundle); + } + generarGrafico(); + }*/ + /** * Crear un arbol nuevo. */ private void initializeArbol() { scene = contenidoArbol.getScene(); // TODO: remove this - contenidoArbol.setGridLinesVisible(true); + //contenidoArbol.setGridLinesVisible(true); grafico = new Grafico(scene); //this.arbol = new Arbol(); Arbol.Tipos tipos = (Arbol.Tipos) scene.getUserData(); @@ -138,9 +183,11 @@ public class ArbolController implements Initializable { private void generarGrafico() { grafico.removerDestacar(); - Node node = contenidoArbol.getChildren().get(0); + + // Node 0 contains the grid + //Node node = contenidoArbol.getChildren().get(0); contenidoArbol.getChildren().clear(); - contenidoArbol.getChildren().add(0, node); + //contenidoArbol.getChildren().add(0, node); List> niveles = arbol.getNiveles(); @@ -161,90 +208,60 @@ public class ArbolController implements Initializable { } Colores colores = new Colores(); + int k; + int l = 0; for (int i = niveles.size() - 1; i >= 0 ; i--) { + k = l; for (int j = 0; j < niveles.get(i).size(); j++) { - contenidoArbol.add(Grafico.crearCirculo(colores, j + "_" + i), j, i); - colores.siguinteColor(); if (niveles.get(i).get(j) != null) { + niveles.get(i).get(j).setX(k); + if (niveles.get(i).get(j).getIzquerda() != null) { + k = niveles.get(i).get(j).getIzquerda().getX() + 1; + niveles.get(i).get(j).setX(k); + contenidoArbol.add(Grafico.crearCirculo(colores, j + "_" + i), niveles.get(i).get(j).getIzquerda().getX() + 1, i); + } + else if (niveles.get(i).get(j).getDerecha() != null) { + k = niveles.get(i).get(j).getDerecha().getX() - 1; + niveles.get(i).get(j).setX(k); + contenidoArbol.add(Grafico.crearCirculo(colores, j + "_" + i), niveles.get(i).get(j).getDerecha().getX() - 1, i); + } + else { + contenidoArbol.add(Grafico.crearCirculo(colores, j + "_" + i), k, i); + } + + // Check the right for visual conflicts + if (niveles.get(i).get(j).getDerecha() != null && niveles.get(i).get(j).getDerecha().getX() > k + 1) { + int parentX = niveles.get(i).get(j).getX(); + int childX = niveles.get(i).get(j).getDerecha().getX(); + for (int m = parentX + 1; m < childX; m++) { + contenidoArbol.add(Grafico.crearLineaHorizontal(), m, i); + } + } + + // Check the left for visual conflicts + + colores.siguinteColor(); text = (Text) scene.lookup("#texto_" + j + "_" + i); text.setText(String.valueOf(niveles.get(i).get(j).getValor())); - } - } - } - } - /** - * Poner los valores en el grafico. - */ - /*private void generarGrafico() { - grafico.removerDestacar(); - ArbolNodo node = contenidoArbol.getChildren().get(0); - contenidoArbol.getChildren().clear(); - contenidoArbol.getChildren().add(0, node); - - Text text; - - int ancho = arbol.getAncho(); - if (ancho % 2 == 0) { - ancho++; - } - for (int i = 0; i < arbol.getAltura(); i++) { - contenidoArbol.addRow(i); - for (int j = 0; j < ancho; j++) { - contenidoArbol.addColumn(j); - text = new Text(); - text.setText(" "); - text.setId(j + "_" + i); - contenidoArbol.add(text, j, i); - } - } - - int medio = ancho / 2; - - ArbolNodo tempArbol = this.arbol.getArbol(); - Stack globalStack = new Stack(); - globalStack.push(tempArbol); - boolean filaVacio = false; - int x = medio; - int y = 0; - Colores colores = new Colores(); - while (!filaVacio) { - Stack localStack = new Stack(); - filaVacio = true; - - text = new Text(); - text.setText(" "); - text.setId(x + "_" + y); - contenidoArbol.add(text, x, y); - - while (!globalStack.isEmpty()) { - ArbolNodo temp = (ArbolNodo) globalStack.pop(); - if (temp != null) { - //System.out.print(temp.iData); - text = new Text(); - text.setText(String.valueOf(temp.getValor())); - text.setId(x + "_" + y); - contenidoArbol.add(Grafico.crearCirculo(colores, x + "_" + y), x, y); - colores.siguinteColor(); - localStack.push(temp.getIzquerda()); - localStack.push(temp.getDerecha()); - - if(temp.getIzquerda() != null || - temp.getDerecha() != null) - filaVacio = false; + if (i != 0) { + if (niveles.get(i).get(j).getPadre().getIzquerda() == niveles.get(i).get(j)) { + // El hijo está a la izquerda + contenidoArbol.add(Grafico.crearEsquinaDerecha(), k, i - 1); + } + else { + // El hijo está a la derecha + contenidoArbol.add(Grafico.crearEsquinaIzquerda(), k, i - 1); + } + } + k++; } else { - System.out.print("--"); - localStack.push(null); - localStack.push(null); + k++; } - x++; + k++; } - y++; - x = 0; - // Next level - while(!localStack.isEmpty()) - globalStack.push( localStack.pop() ); + l++; } - }*/ + } } \ No newline at end of file diff --git a/src/cl/cromer/estructuras/ArbolNodo.java b/src/cl/cromer/estructuras/ArbolNodo.java index 43c9455..70a3136 100644 --- a/src/cl/cromer/estructuras/ArbolNodo.java +++ b/src/cl/cromer/estructuras/ArbolNodo.java @@ -5,14 +5,14 @@ final public class ArbolNodo { private ArbolNodo izquerda; private ArbolNodo derecha; private int valor; - private int nivel; + private int x; public ArbolNodo(int valor, ArbolNodo padre) { this.padre = padre; this.izquerda = null; this.derecha = null; this.valor = valor; - this.nivel = 1; + this.x=0; } public ArbolNodo getPadre() { @@ -43,11 +43,11 @@ final public class ArbolNodo { return valor; } - public int getNivel() { - return nivel; + public int getX() { + return x; } - public void setNivel(int nivel) { - this.nivel = nivel; + public void setX(int x) { + this.x = x; } } diff --git a/src/cl/cromer/estructuras/Colores.java b/src/cl/cromer/estructuras/Colores.java index b069fc9..0a3a7ba 100644 --- a/src/cl/cromer/estructuras/Colores.java +++ b/src/cl/cromer/estructuras/Colores.java @@ -2,6 +2,8 @@ package cl.cromer.estructuras; import javafx.scene.paint.Color; +import java.util.Random; + /** * Rotación de colores. * @@ -71,7 +73,7 @@ public class Colores { break; case 5: color = 6; - texto = Color.BLACK; + texto = Color.WHITE; fondo = Color.GREEN; border = Color.BLACK; break; @@ -87,6 +89,20 @@ public class Colores { fondo = Color.BLUE; border = Color.BLACK; } + + } + + public void randomColor() { + int r = (int)(Math.random() * 256); + int g = (int)(Math.random() * 256); + int b = (int)(Math.random() * 256); + fondo = Color.rgb(r, g, b); + + // Generate a text color that doesn't conflict + double a = 1 - (0.299 * r + 0.587 * g + 0.114 * b) / 255; + texto = (a > 0.5)?Color.WHITE: Color.BLACK; + + border = Color.BLACK; } /** diff --git a/src/cl/cromer/estructuras/Grafico.java b/src/cl/cromer/estructuras/Grafico.java index e967c08..6766d46 100644 --- a/src/cl/cromer/estructuras/Grafico.java +++ b/src/cl/cromer/estructuras/Grafico.java @@ -83,6 +83,70 @@ public class Grafico { return stackPane; } + /** + * Crear una linea horizontal para conecatar nodos de arboles. + * + * @return Pane: Devolver el pane que contiene la linea. + */ + public static Pane crearEsquinaDerecha() { + Line right = new Line(); + right.setStartY(21); + right.setEndY(21); + right.setStartX(20); + right.setEndX(40); + + Line up = new Line(); + up.setStartY(21); + up.setEndY(40); + up.setStartX(20); + up.setEndX(20); + + Pane stackPane = new Pane(); + stackPane.getChildren().addAll(right, up); + return stackPane; + } + + /** + * Crear una linea para conectar arboles. + * + * @return Pane: Devolver el pane que contiene las lienas. + */ + public static Pane crearEsquinaIzquerda() { + Line left = new Line(); + left.setStartY(21); + left.setEndY(21); + left.setStartX(0); + left.setEndX(20); + + Line up = new Line(); + up.setStartY(21); + up.setEndY(40); + up.setStartX(20); + up.setEndX(20); + + Pane stackPane = new Pane(); + stackPane.getChildren().addAll(left, up); + return stackPane; + } + + /** + * Crear una linea para conectar arboles. + * + * @return StackPane: Devolver el pane que contiene las lienas. + */ + public static StackPane crearLineaHorizontal() { + Line line = new Line(); + line.setStrokeWidth(1.5); + line.setStartY(20); + line.setEndY(20); + line.setStartX(0); + line.setEndX(40); + + StackPane stackPane = new StackPane(); + stackPane.getChildren().addAll(line); + return stackPane; + } + /** * Crear una flecha que apunta por arriba. * diff --git a/src/cl/cromer/estructuras/GrafoController.java b/src/cl/cromer/estructuras/GrafoController.java index 4a0bf20..859c6eb 100644 --- a/src/cl/cromer/estructuras/GrafoController.java +++ b/src/cl/cromer/estructuras/GrafoController.java @@ -873,6 +873,8 @@ public class GrafoController implements Initializable { ); graphicsContext.restore(); } + + // Todo: make this more effecient by removing the extra line draws that overlap } } } diff --git a/src/cl/cromer/estructuras/fxml/arbol.fxml b/src/cl/cromer/estructuras/fxml/arbol.fxml index 31a96b9..706be32 100644 --- a/src/cl/cromer/estructuras/fxml/arbol.fxml +++ b/src/cl/cromer/estructuras/fxml/arbol.fxml @@ -17,8 +17,7 @@