/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package Chapter15.EndofChapter15.Exerc15dot17;
/**
*
* @author Rogerio Biscaia
*/
/*
(Geometry: find the bounding rectangle)
Write a program that enables the user
to add and remove points in a
two-dimensional plane dynamically, as shown
in Figure.
A minimum bounding rectangle is updated as the
points are added and removed.
Assume that the radius of each point is 10 pixels.
*/
import java.util.ArrayList;
import javafx.collections.ObservableList;
import javafx.event.Event;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.control.Label;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.input.MouseButton;
import javafx.scene.paint.Color;
import javafx.scene.layout.Pane;
import javafx.scene.layout.BorderPane;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.stage.Stage;
public class GetBoundingRectangle extends Application {
private ArrayList <Circle> allCircles = new ArrayList<>();
private Circle newCircle;
private ArrayList <Line> boundRectangleLines;
private ObservableList <Node> listNodes;
/*
Create the pane for the points
*/
private Pane pointsPane = new Pane();
@Override
public void start(Stage primaryStage) throws Exception {
double initialSceneW;
double initialSceneH;
initialSceneW = 400;
initialSceneH = 320;
/*
Create the Border pane
*/
BorderPane mainPane = new BorderPane();
/*
Create the label with instructions
*/
Label lblInstructions = new Label("INSTRUCTIONS\n" + "Add: Left Click\n" + "Remove: Right Click");
/*
Create the handler
*/
pointsPane.setOnMouseClicked( e -> {
int i;
int indexClickedNode;
double getX;
double getY;
double newCircleX;
double newCircleY;
double incrementXY;
double circleRadius;
/*
Variables to update the
Width and Height of the
PointsPane
*/
double incrementWH;
incrementWH = 40;
double newPointsPaneW;
double newPointsPaneH;
boolean nodeIsCircle;
boolean pointsPaneUpdated;
pointsPaneUpdated = false;
indexClickedNode = -1;
getX = e.getX();
getY = e.getY();
incrementXY = 5;
circleRadius = 10;
String nodeName;
String circle;
circle = "Circle";
double currentNodeListCircleX;
currentNodeListCircleX = 0;
double currentNodeListCircleY;
currentNodeListCircleY = 0;
Node currentNodeList;
Circle currentNodeListCircle;
double[][] minMax;
//listNodes = pane.getChildren();
/*
Display all the nodes
*/
System.out.println("");
System.out.println("Displaying all the Nodes:" );
for(i = 0; i < listNodes.size(); i++) {
System.out.println( listNodes.get(i) );
}
System.out.println( "Button: " + e.getButton() );
System.out.println("Event To String: " + e.toString() );
nodeName = e.getTarget() + "";
System.out.println( "Event Target: " + e.getTarget() );
nodeIsCircle = nodeName.matches(circle + ".*");
System.out.println( "The Clicked Node is a Circle: " + nodeIsCircle );
if( e.getButton() == MouseButton.PRIMARY ) {
if(nodeIsCircle == false) {
if( getX <= circleRadius + incrementXY ) {
newCircleX = circleRadius + incrementXY;
} else {
newCircleX = getX;
} //end of if else if( getX <= circleRadius )
if( getY <= circleRadius + incrementXY ) {
newCircleY = circleRadius + incrementXY;
} else {
newCircleY = getY;
} //end of if else if( getY <= circleRadius )
newCircle = new Circle( newCircleX, newCircleY, circleRadius);
newCircle.setFill( Color.WHITE );
newCircle.setStroke( Color.BLACK );
allCircles.add(newCircle);
//listNodes.add( newCircle );
pointsPaneUpdated = true;
System.out.println( "Added New Circle x: " + getX + " y: " + getY + " and radius: " + circleRadius );
} //end of if(nodeIsCircle == false)
} else if( e.getButton() == MouseButton.SECONDARY ) {
if(nodeIsCircle) {
for(i = 0; i < listNodes.size(); i++) {
currentNodeList = listNodes.get(i);
if( currentNodeList instanceof Circle ) {
currentNodeListCircle = (Circle) currentNodeList;
if( currentNodeListCircle.contains(getX, getY) ) {
indexClickedNode = i;
}
} //end of if( currentNodeList instanceof Circle )
} //end of for loop for(j = 0; j < listNodes.size(); j++)
System.out.println( "The index for the clicked Circle is " + indexClickedNode );
if(indexClickedNode >= 0) {
System.out.println("Removing the circle " + nodeName );
//listNodes.remove( indexClickedNode );
allCircles.remove( indexClickedNode );
pointsPaneUpdated = true;
} //end of if(indexClickedNode >= 0)
} //end of if(nodeIsCircle)
} //end of if else if if( e.getButton() == MouseButton.PRIMARY )
if(allCircles.size() > 0 && pointsPaneUpdated ) {
minMax = getMinAndMaxXY(allCircles);
/*
Remove all the nodes
*/
listNodes.clear();
/*
Add all the Circles
*/
for(i = 0; i < allCircles.size(); i++) {
listNodes.add( allCircles.get(i) );
}
/*
Add all the
lines in the Array List
of Lines
*/
boundRectangleLines = getBoundingLines(minMax);
for(i = 0; i < boundRectangleLines.size(); i++) {
listNodes.add( boundRectangleLines.get(i) );
}
newPointsPaneW = minMax[1][0] + incrementWH;
newPointsPaneH = minMax[1][1] + incrementWH;
//pointsPane.setMinSize(newPointsPaneW, newPointsPaneH);
mainPane.setMinSize(newPointsPaneW, newPointsPaneH);
} else if( allCircles.size() == 0 && pointsPaneUpdated ) {
listNodes.clear();
} //end of if else if(allCircles.size() > 0 )
} ); //end of pane.setOnMouseClicked( e -> {} );
pointsPane.getChildren().clear();
listNodes = pointsPane.getChildren();
mainPane.getChildren().clear();
mainPane.setLeft(lblInstructions);
mainPane.setCenter(pointsPane);
BorderPane.setAlignment( lblInstructions , Pos.TOP_CENTER);
/*
Create a scene and
place it in the stage
*/
Scene scene = new Scene(mainPane, initialSceneW, initialSceneH);
primaryStage.setResizable(true);
primaryStage.setTitle("Display Points in Pane");
primaryStage.setScene(scene);
primaryStage.show();
} //end of the method public void start(Stage primaryStage)
/*
The main method is only needed for the IDE with
limited JavaFX support.
Not needed for running from the
command line
*/
public static void main(String[] args) {
try {
Application.launch(args);
} catch(Exception ex1) {
System.out.println("Exception in the main in the " +
"class GetBoundingRectangle");
System.out.println( ex1.toString() );
}
} //end of main
/*
Method to get the
MinX and MaxX
and
MinY and MaxY
from an
Array List of circles
*/
public double[][] getMinAndMaxXY(ArrayList <Circle> circles) {
int i;
double circleRadius;
double currentX;
double currentY;
double minX, maxX;
double minY, maxY;
ArrayList<Double> allX;
ArrayList<Double> allY;
allX = new ArrayList<>();
allY = new ArrayList<>();
double[][] minMax;
minMax = new double[2][2];
if( circles.size() > 0) {
circleRadius = circles.get(0).getRadius();
for(i = 0; i < circles.size(); i++) {
currentX = circles.get(i).getCenterX();
currentY = circles.get(i).getCenterY();
allX.add(currentX);
allY.add(currentY);
}
minX = java.util.Collections.min(allX);
minY = java.util.Collections.min(allY);
maxX = java.util.Collections.max(allX);
maxY = java.util.Collections.max(allY);
minMax[0][0] = minX - circleRadius;
minMax[0][1] = minY - circleRadius;
minMax[1][0] = maxX + circleRadius;
minMax[1][1] = maxY + circleRadius;
} //end of if( circles.size() >= 0)
return minMax;
} //end of the method public double [][] getMinAndMaxXY(ArrayList <Circle> circles)
/*
Method to get tha
4 Lines that define the
bounding rectangle
*/
public ArrayList<Line> getBoundingLines( double[][] minMaxXY ) {
int i;
double minX, maxX;
double minY, maxY;
double incrementXY;
Line newLine;
incrementXY = 2;
ArrayList<Line> allBoundRectangleLines = new ArrayList<>();
if( minMaxXY.length == 2 ) {
minX = minMaxXY[0][0] - incrementXY;
minY = minMaxXY[0][1] - incrementXY;
maxX = minMaxXY[1][0] + incrementXY;
maxY = minMaxXY[1][1] + incrementXY;
/*
Line 1 - Between (minX, minY) and (maxX, minY)
*/
newLine = new Line(minX, minY, maxX, minY);
allBoundRectangleLines.add(newLine);
/*
Line 2 - Between (maxX, minY) and (maxX, maxY)
*/
newLine = new Line(maxX, minY, maxX, maxY);
allBoundRectangleLines.add(newLine);
/*
Line 3 - Between (minX, maxY) and (maxX, maxY)
*/
newLine = new Line(minX, maxY, maxX, maxY);
allBoundRectangleLines.add(newLine);
/*
Line 4 - Between (minX, minY) and (minX, maxY)
*/
newLine = new Line(minX, minY, minX, maxY);
allBoundRectangleLines.add(newLine);
} //end of if(allCircles.size() > 0 )
for(i = 0; i < allBoundRectangleLines.size(); i++ ) {
allBoundRectangleLines.get(i).setStroke( Color.BLACK );
allBoundRectangleLines.get(i).setStrokeWidth( 2 );
}
return allBoundRectangleLines;
} //end of the method public ArrayList<Line> getBoundingLines( double[][] minMaxXY )
} //end of the class GetBoundingRectangle