Skip to content
Snippets Groups Projects
Commit 73105c10 authored by Tam Minh Le's avatar Tam Minh Le
Browse files

Merge branch 'ValueLimits' into 'dev'

Added limits to the values

See merge request !39
parents e699f1ce 6e1832eb
No related branches found
No related tags found
2 merge requests!54Final release,!39Added limits to the values
Showing
with 171 additions and 64 deletions
......@@ -13,6 +13,13 @@ import java.util.List;
public class GameController {
public void updateCanvasCoordinates(Vector2D minCoords, Vector2D maxCoords) {
ChaosGameDescription description = ChaosGame.getInstance().getDescription();
description.setMaxCoords(maxCoords);
description.setMinCoords(minCoords);
ChaosGame.getInstance().setDescription(description);
}
public int getCurrentSteps() {
return ChaosGame.getInstance().getSteps();
}
......@@ -43,6 +50,14 @@ public class GameController {
ChaosGame.getInstance().setCanvas(width, height);
}
public int getHeight() {
return ChaosGame.getInstance().getCanvas().getHeight();
}
public int getWidth() {
return ChaosGame.getInstance().getCanvas().getWidth();
}
public void setChaosGameSteps(int steps) {
ChaosGame.getInstance().setSteps(steps);
}
......@@ -51,6 +66,10 @@ public class GameController {
ChaosGame.getInstance().runSteps();
}
public int getOutOfBoundsCount() {
return ChaosGame.getInstance().getOutOfBoundsCount();
}
public void setJuliaTransformation(Complex point, Vector2D minCoords, Vector2D maxCoords) {
List<Transform2D> transforms = new ArrayList<>();
transforms.add(new JuliaTransform(point, -1));
......@@ -98,4 +117,8 @@ public class GameController {
public List<String> listTransformationFileNames() {
return ChaosGameFileHandler.listTransformationFileNames();
}
public void emptyChaosGame() {
ChaosGame.getInstance().setDescription(null);
}
}
\ No newline at end of file
......@@ -76,14 +76,15 @@ public class ChaosCanvas{
* @param point the point at which to put the pixel
*/
public void putPixel(Vector2D point) {
public boolean putPixel(Vector2D point) {
Vector2D indices = transformCoordsToIndices.transform(point);
int x = (int) indices.getX0();
int y = (int) indices.getX1();
if (x >= 0 && x < width && y >= 0 && y < height) {
canvas[x][y] += 1;
return true;
} else {
System.out.println("Indices out of bounds");
return false;
}
}
/**
......
......@@ -26,6 +26,7 @@ public class ChaosGame {
private int steps;
private Vector2D currentPoint;
private Random random;
private int outOfBoundsCount = 0;
private List<ChaosGameObserver> observers;
......@@ -106,9 +107,13 @@ public class ChaosGame {
public int getSteps() {
return steps;
}
public int getOutOfBoundsCount() {
return outOfBoundsCount;
}
public void runSteps() {
ChaosGameDescription description = ChaosGame.getInstance().getDescription();
outOfBoundsCount = 0;
if (description.isWeighted()) {
List<Pair<Transform2D, Double>> weightedTransforms = description.getWeightedTransforms();
......@@ -122,7 +127,9 @@ public class ChaosGame {
break;
}
}
canvas.putPixel(currentPoint);
if (!canvas.putPixel(currentPoint)) {
outOfBoundsCount++;
}
}
} else {
List<Transform2D> transforms = description.getTransforms();
......@@ -130,7 +137,9 @@ public class ChaosGame {
int randomIndex = random.nextInt(transforms.size());
Transform2D transform = transforms.get(randomIndex);
currentPoint = transform.transform(currentPoint);
canvas.putPixel(currentPoint);
if (!canvas.putPixel(currentPoint)) {
outOfBoundsCount++;
}
}
}
notifyChaosGameUpdated();
......
......@@ -94,7 +94,9 @@ public class AffineDialog {
Button editButton = new Button(isEditMode ? "Edit Fractal" : "Display Fractal");
editButton.setOnAction(event -> {
if (validateInputs(stepsField, minCoordsFieldX, minCoordsFieldY, maxCoordsFieldX, maxCoordsFieldY, transformationFields)) {
displayFractal(stepsField, minCoordsFieldX, minCoordsFieldY, maxCoordsFieldX, maxCoordsFieldY, transformationFields);
}
});
HBox buttonBox = new HBox(10);
......@@ -124,57 +126,79 @@ public class AffineDialog {
}
private void displayFractal(TextField stepsField, TextField minCoordsFieldX, TextField minCoordsFieldY, TextField maxCoordsFieldX, TextField maxCoordsFieldY, List<Node[]> transformationFields) {
if (stepsField.getText().isEmpty() || minCoordsFieldX.getText().isEmpty() ||
minCoordsFieldY.getText().isEmpty() || maxCoordsFieldX.getText().isEmpty() ||
maxCoordsFieldY.getText().isEmpty()) {
UserFeedback.showErrorPopup("Input Error", "All primary transformation fields must be filled out.");
return;
}
for (Node[] fields : transformationFields) {
TextField matrixField = (TextField) fields[0];
TextField vectorField = (TextField) fields[1];
if (matrixField.getText().isEmpty() || vectorField.getText().isEmpty()) {
UserFeedback.showErrorPopup("Input Error", "All matrix and vector fields must be filled out. Use the add and remove transformation buttons if necessary.");
return;
}
}
try {
int steps = Integer.parseInt(stepsField.getText());
if (steps <= 0) {
UserFeedback.showErrorPopup("Input Error", "Number of steps must be above zero.");
return;
}
double minX = Double.parseDouble(minCoordsFieldX.getText());
double minY = Double.parseDouble(minCoordsFieldY.getText());
double maxX = Double.parseDouble(maxCoordsFieldX.getText());
double maxY = Double.parseDouble(maxCoordsFieldY.getText());
gameController.setChaosGameSteps(steps);
List<Transform2D> transforms = new ArrayList<>();
for (Node[] fields : transformationFields) {
TextField matrixField = (TextField) fields[0];
TextField vectorField = (TextField) fields[1];
double[][] matrixValues = parseMatrix(matrixField.getText());
double[] vectorValues = parseVector(vectorField.getText());
Matrix2x2 matrix = new Matrix2x2(matrixValues[0][0], matrixValues[0][1], matrixValues[1][0], matrixValues[1][1]);
Vector2D vector = new Vector2D(vectorValues[0], vectorValues[1]);
transforms.add(new AffineTransform2D(matrix, vector));
}
gameController.setChaosGameSteps(steps);
gameController.setAffineTransformation(transforms, new Vector2D(minX, minY), new Vector2D(maxX, maxY));
gameController.setChaosCanvasSize(200, 200);
gameController.runTransformation();
dialog.close();
if (gameController.getOutOfBoundsCount() > 0) {
UserFeedback.showErrorPopup("Error", gameController.getOutOfBoundsCount() + " points were out of bounds. Try adjusting the max and min coordinates.");
}
}
private boolean validateInputs(TextField stepsField, TextField minCoordsFieldX, TextField minCoordsFieldY, TextField maxCoordsFieldX, TextField maxCoordsFieldY, List<Node[]> transformationFields) {
try {
// Validate step count
int steps = Integer.parseInt(stepsField.getText());
if (steps <= 0 || steps > 1_000_000) {
throw new IllegalArgumentException("Steps must be between 1 and 1,000,000.");
}
// Validate coordinate bounds
double minX = Double.parseDouble(minCoordsFieldX.getText());
double minY = Double.parseDouble(minCoordsFieldY.getText());
double maxX = Double.parseDouble(maxCoordsFieldX.getText());
double maxY = Double.parseDouble(maxCoordsFieldY.getText());
if (minX >= maxX || minY >= maxY) {
throw new IllegalArgumentException("Minimum coordinates must be less than maximum coordinates.");
}
// Validate matrix and vector entries
for (Node[] fields : transformationFields) {
TextField matrixField = (TextField) fields[0];
TextField vectorField = (TextField) fields[1];
double[][] matrix = parseMatrix(matrixField.getText());
double[] vector = parseVector(vectorField.getText());
for (double[] row : matrix) {
for (double value : row) {
if (value < -2.0 || value > 2.0) {
throw new IllegalArgumentException("Matrix values must be between -2 and 2.");
}
}
}
for (double value : vector) {
if (value < -2.0 || value > 2.0) {
throw new IllegalArgumentException("Vector values must be between -2 and 2.");
}
}
}
} catch (NumberFormatException e) {
UserFeedback.showErrorPopup("Input Error", "Please enter valid numbers for all fields.");
UserFeedback.showErrorPopup("Input Error", "Please enter valid numbers.");
return false;
} catch (IllegalArgumentException e) {
UserFeedback.showErrorPopup("Input Error", e.getMessage());
return false;
}
return true;
}
private void addTransformationFields(GridPane grid, AffineTransform2D transform, int rowIndex, List<Node[]> fieldList) {
TextField matrixField = new TextField("[" + transform.getMatrix().getA00() + ", " + transform.getMatrix().getA01() + "; " + transform.getMatrix().getA10() + ", " + transform.getMatrix().getA11() + "]");
TextField vectorField = new TextField("[" + transform.getVector().getX0() + ", " + transform.getVector().getX1() + "]");
......
package edu.ntnu.idatt2003.mappevurderingprog2.views.Components;
import edu.ntnu.idatt2003.mappevurderingprog2.controllers.GameController;
import edu.ntnu.idatt2003.mappevurderingprog2.utils.Size;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
......@@ -22,9 +23,11 @@ public class ExtraUserOptions extends VBox {
private final Node node;
private final RotationButton rotationButton;
private final InformationButton informationButton;
private GameController gameController;
public ExtraUserOptions(Node node) {
public ExtraUserOptions(Node node, GameController gameController) {
this.node = node;
this.gameController = gameController;
resetViewButton = new Button("Reset View");
clearCanvasButton = new Button("Clear Canvas");
rotationButton = new RotationButton(node);
......@@ -111,6 +114,7 @@ public class ExtraUserOptions extends VBox {
GraphicsContext gc = ((Canvas) node).getGraphicsContext2D();
gc.clearRect(0, 0, ((Canvas) node).getWidth(), ((Canvas) node).getHeight());
}
gameController.emptyChaosGame();
node.getTransforms().clear();
node.setTranslateX(0);
node.setTranslateY(0);
......
......@@ -59,7 +59,11 @@ public class JuliaDialog {
grid.add(imagField, 1, 4);
Button editButton = new Button("Display Fractal");
editButton.setOnAction(event -> displayFractal(stepsField, minCoordsFieldX, minCoordsFieldY, maxCoordsFieldX, maxCoordsFieldY, realField, imagField));
editButton.setOnAction(event -> {
if (validateInputs(stepsField, minCoordsFieldX, minCoordsFieldY, maxCoordsFieldX, maxCoordsFieldY, realField, imagField)) {
displayFractal(stepsField, minCoordsFieldX, minCoordsFieldY, maxCoordsFieldX, maxCoordsFieldY, realField, imagField);
}
});
grid.add(editButton, 1, 5);
dialog.getDialogPane().setContent(grid);
......@@ -67,20 +71,7 @@ public class JuliaDialog {
}
private void displayFractal(TextField stepsField, TextField minCoordsFieldX, TextField minCoordsFieldY, TextField maxCoordsFieldX, TextField maxCoordsFieldY, TextField realField, TextField imagField) {
if (stepsField.getText().isEmpty() || minCoordsFieldX.getText().isEmpty() ||
minCoordsFieldY.getText().isEmpty() || maxCoordsFieldX.getText().isEmpty() ||
maxCoordsFieldY.getText().isEmpty() || realField.getText().isEmpty() ||
imagField.getText().isEmpty()) {
UserFeedback.showErrorPopup("Input Error", "All fields must be filled out.");
return;
}
try {
int steps = Integer.parseInt(stepsField.getText());
if (steps <= 0) {
UserFeedback.showErrorPopup("Input Error", "Number of steps must be above zero.");
return;
}
double minX = Double.parseDouble(minCoordsFieldX.getText());
double minY = Double.parseDouble(minCoordsFieldY.getText());
double maxX = Double.parseDouble(maxCoordsFieldX.getText());
......@@ -89,14 +80,53 @@ public class JuliaDialog {
double imag = Double.parseDouble(imagField.getText());
Complex newPoint = new Complex(real, imag);
gameController.setChaosGameSteps(steps);
gameController.setJuliaTransformation(newPoint, new Vector2D(minX, minY), new Vector2D(maxX, maxY));
gameController.setChaosCanvasSize(200, 200);
gameController.runTransformation();
dialog.close();
if (gameController.getOutOfBoundsCount() > 0) {
UserFeedback.showErrorPopup("Error", gameController.getOutOfBoundsCount() + " points were out of bounds. Try adjusting the max and min coordinates.");
}
}
private boolean validateInputs(TextField stepsField, TextField minFieldX, TextField minFieldY, TextField maxFieldX, TextField maxFieldY, TextField realField, TextField imagField) {
try {
if (stepsField.getText().isEmpty() || minFieldX.getText().isEmpty() ||
minFieldY.getText().isEmpty() || maxFieldX.getText().isEmpty() ||
maxFieldY.getText().isEmpty() || realField.getText().isEmpty() ||
imagField.getText().isEmpty()) {
throw new IllegalArgumentException("All fields must be filled out.");
}
int steps = Integer.parseInt(stepsField.getText());
if (steps <= 0 || steps > 1_000_000) {
throw new IllegalArgumentException("Steps must be between 1 and 1,000,000.");
}
double minX = Double.parseDouble(minFieldX.getText());
double minY = Double.parseDouble(minFieldY.getText());
double maxX = Double.parseDouble(maxFieldX.getText());
double maxY = Double.parseDouble(maxFieldY.getText());
if (minX >= maxX || minY >= maxY) {
throw new IllegalArgumentException("Minimum coordinates must be less than maximum coordinates.");
}
double real = Double.parseDouble(realField.getText());
double imag = Double.parseDouble(imagField.getText());
if (real < -2 || real > 2 || imag < -2 || imag > 2) {
throw new IllegalArgumentException("Real and imaginary parts must be within [-2, 2].");
}
} catch (NumberFormatException e) {
UserFeedback.showErrorPopup("Input Error", "Please enter valid numbers for all fields.");
UserFeedback.showErrorPopup("Input Error", "Please enter valid numbers.");
return false;
} catch (IllegalArgumentException e) {
UserFeedback.showErrorPopup("Input Error", e.getMessage());
return false;
}
return true;
}
public void showDialog() {
......
......@@ -17,7 +17,7 @@ public class Menu extends VBox {
existingFractalsMenu = new ExistingFractalsMenu(view, gameController);
createFractalMenu = new CreateFractalMenu(view, gameController);
editFractalMenu = new CurrentFractalMenu(view, gameController);
extraUserOptions = new ExtraUserOptions(view.getMainCanvas());
extraUserOptions = new ExtraUserOptions(view.getMainCanvas(), gameController);
initializeMenu();
}
......
......@@ -34,6 +34,9 @@ public abstract class TransformationButton extends Button {
gameController.setChaosGameDescription(chaosGameDescription);
gameController.setChaosCanvasSize(width, height);
gameController.runTransformation();
if (gameController.getOutOfBoundsCount() > 0) {
UserFeedback.showErrorPopup("Error", gameController.getOutOfBoundsCount() + " points were out of bounds. Try adjusting the max and min coordinates.");
}
});
}
}
package edu.ntnu.idatt2003.mappevurderingprog2.views.Components;
import edu.ntnu.idatt2003.mappevurderingprog2.controllers.GameController;
import javafx.scene.Node;
import javafx.scene.control.Slider;
import javafx.scene.transform.Scale;
......@@ -7,9 +8,11 @@ import javafx.scene.transform.Scale;
public class Zoom {
private double mouseX, mouseY;
private GameController gameController;
private Slider zoomSlider;
public Zoom(Node node) {
public Zoom(Node node, GameController gameController) {
this.gameController = gameController;
zoomSlider = new Slider(0.5, 4.0, 1.0);
setUpZoomSlider();
setUpZoomAndMovement(node);
......
......@@ -27,16 +27,14 @@ public class View extends BorderPane implements ChaosGameObserver {
private Canvas mainCanvas;
private GameController gameController;
private Menu menu;
private ExtraUserOptions extraUserOptions;
private int greenThreshold, blueThreshold, redThreshold;
private Zoom zoom;
public View(GameController gameController) {
this.gameController = gameController;
this.mainCanvas = new Canvas(600, 400);
this.zoom = new Zoom(mainCanvas);
this.zoom = new Zoom(mainCanvas, gameController);
zoom.setUpZoomAndMovement(mainCanvas);
this.extraUserOptions = new ExtraUserOptions(mainCanvas);
}
public Canvas getMainCanvas() {
......
Affine2D
0.0, 0.0
1.0, 1.0
0.500000, 0.000000, 0.000000, 0.500000, 0.0, 0.0
0.500000, 0.000000, 0.000000, 0.500000, 2.0, 0.0
0.500000, 0.000000, 0.000000, 0.500000, 0.25, 0.5
Affine2D
0.0, 0.0
1.0, 1.0
0.500000, 0.000000, 0.000000, 0.400000, 0.0, 0.0
0.500000, 0.000000, 0.000000, 0.500000, 0.5, 0.0
0.500000, 0.000000, 0.000000, 0.500000, 0.25, 0.5
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment