## Wednesday, 28 December 2016

### Chapter 16 Exercise 9, Introduction to Java Programming, Tenth Edition Y. Daniel LiangY.

16.9 (Geometry: two rectangles intersect?)
Write a program that enables the user to specify the location and
size of the rectangles and displays whether the two rec- tangles
intersect, as shown in Figure 16.39b. Enable the user to point
the mouse inside a rectangle and drag it. As the rectangle is
being dragged, the rectangle’s center coordinates in the text
fields are updated.

import javafx.scene.shape.Rectangle;

public class MyRectangle2D extends GeometricObject {

private static final int X = 0;
private static final int Y = 1;

public double centerX;
public double centerY;

public double width;
public double height;

public MyRectangle2D(double centerX, double centerY, double width, double height) {
this.centerX = centerX;
this.centerY = centerY;
this.width = width;
this.height = height;
}

public MyRectangle2D(MyPoint centerPoint, double width, double height) {
this(centerPoint.x, centerPoint.y, width, height);
}

public MyRectangle2D(Rectangle rectangle) {
this(rectangle.getX(), rectangle.getY(), rectangle.getWidth(), rectangle.getHeight());
}

public MyRectangle2D() {
this(0, 0, 1, 1);
}

public MyPoint getCenterP() {
return new MyPoint(centerX, centerY);
}
public MyPoint getP1() {
return new MyPoint(centerX - width / 2, centerY + height / 2);
}

public MyPoint getP2() {
return new MyPoint(centerX + width / 2, centerY + height / 2);
}

public MyPoint getP3() {
return new MyPoint(centerX - width / 2, centerY - height / 2);
}

public MyPoint getP4() {
return new MyPoint(centerX + width / 2, centerY - height / 2);
}

public double getCenterX() {
return centerX;
}

public void setCenterX(double centerX) {
this.centerX = centerX;
}

public double getCenterY() {
return centerY;
}

public void setCenterY(double centerY) {
this.centerY = centerY;
}

public double getWidth() {
return width;
}

public void setWidth(double width) {
this.width = width;
}

public double getHeight() {
return height;
}

public void setHeight(double height) {
this.height = height;
}

/** returns the perimeter of the rectangle. **/
@Override
public double getPerimeter() {

return width * 2 + height * 2;
}

/** returns the area of the rectangle **/
@Override
public double getArea() {
return width * height;
}

public boolean contains(double x, double y) {

// Get max X & Y
double maxX = getMax(getP1().x, getP2().x, getP3().x, getP4().x);
double maxY = getMax(getP1().y, getP2().y, getP3().y, getP4().y);
// Get min X & Y
double minX = getMin(getP1().x, getP2().x, getP3().x, getP4().x);
double minY = getMin(getP1().y, getP2().y, getP3().y, getP4().y);

if (x < minX || x > maxX || y < minY || y > maxY)  return false;

return true;

}

public boolean contains(MyRectangle2D r2) {
double xDistance = (r2.centerX > centerX) ? r2.centerX - centerX : centerX - r2.centerX;
double yDistance = (r2.centerY > centerY) ? r2.centerY - centerY : centerY - r2.centerY;

// if the r2 is inside this rectangle
// this is only valid if the rectangles are parallel
return (xDistance <= (width - r2.width) / 2 && yDistance <= (height - r2.height) / 2);

}

public boolean overlaps(MyRectangle2D r2) {
// subtract from the highest number
double xDistance = (r2.centerX > centerX) ? r2.centerX - centerX : centerX - r2.centerX;
double yDistance = (r2.centerY > centerY) ? r2.centerY - centerY : centerY - r2.centerY;

// if the r2 overlaps this rectangle
// this is only valid if the rectangles are parallel
return (xDistance <= (width + r2.width) / 2 && yDistance <= (height + r2.height) / 2);

}

public static boolean r1OverLapsR2(Rectangle r1, Rectangle r2) {
return r1.intersects(r2.getBoundsInLocal()) || r2.intersects(r1.getBoundsInLocal());
}

public javafx.scene.shape.Rectangle getRectangle() {
return new Rectangle(centerX, centerY, width, height);
}
public boolean contains(MyPoint[] points) {

for (MyPoint p : points) {
if (!contains(p)) return false;
}
return true;
}

public boolean contains(MyPoint point) {
return contains(point.x, point.y);
}

public static MyRectangle2D getRectangle(double[][] points) {

// find leftLowestPoint

// find rightMostPoint

// find the center from highest and lowest point

// x distance = width

// y distance = height
MyPoint[] myPoints = new MyPoint[points.length];
for (int i = 0; i < points.length; i++) {
myPoints[i] = new MyPoint(points[i][0], points[i][1]);
}

return getRectangle(myPoints);
}

public static MyRectangle2D getRectangle(MyPoint[] points) {

MyPoint leftMost = getLeftMostPoint(points);
MyPoint rightMost = getRighMostPoint(points);
double width = Math.abs(rightMost.x - leftMost.x);

MyPoint highest = getHighestPoint(points);
MyPoint lowest = getLowestPoint(points);
double height = Math.abs(highest.y - lowest.y);

double centerX = highest.getCenterPoint(lowest).x;
double centerY = leftMost.getCenterPoint(rightMost).y;

return new MyRectangle2D(centerX, centerY, width, height);
}

private static MyPoint getLeftMostPoint(MyPoint[] points) {

MyPoint leftMost = points[0];
for (int i = 0; i < points.length; i++) {
if (leftMost.x > points[i].x) {
leftMost = points[i];
}
}
return leftMost;
}

private static MyPoint getRighMostPoint(MyPoint[] points) {

MyPoint rightMost = points[0];
for (int i = 0; i < points.length; i++) {
if (rightMost.x < points[i].x) {
rightMost = points[i];
}
}
return rightMost;
}

private static MyPoint getHighestPoint(MyPoint[] points) {

MyPoint highest = points[0];
for (int i = 0; i < points.length; i++) {
if (highest.y < points[i].y) {
highest = points[i];
}
}
return highest;
}

private static MyPoint getLowestPoint(MyPoint[] points) {

MyPoint lowest = points[0];
for (int i = 0; i < points.length; i++) {
if (lowest.y > points[i].y) {
lowest = points[i];
}
}
return lowest;
}

private double getMax(double... n) {
double max = n[0];
for (int i = 1; i < n.length; i++) {
if (max < n[i]) {
max = n[i];
}
}
return max;
}
private double getMin(double... n) {
double min = n[0];
for (int i = 1; i < n.length; i++) {
if (min > n[i]) {
min = n[i];
}
}
return min;
}

@Override
public String toString() {
return "MyRectangle2D{" +
"centerX=" + centerX +
", centerY=" + centerY +
", width=" + width +
", height=" + height +
'}';
}
}


import javafx.application.Application;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class Exercise_09 extends Application {
@Override
public void start(Stage primaryStage) throws Exception {

RectanglePane cPane = new RectanglePane();

primaryStage.setScene(new Scene(cPane));
primaryStage.setTitle("Circle Stage");
primaryStage.show();

}

private class RectanglePane extends GridPane {

Label lblIsIntersect; // Tells whether the circles intersect
String intersectString = "Two rectangle Intersect? ";

Rectangle[] rectangles = new Rectangle[2]; // convenience array
RectangleInfoPane[] rInfoPane = new RectangleInfoPane[2];
Rectangle r1;
Rectangle r2;

private RectanglePane() {

// Label and circle's default values
lblIsIntersect = new Label("Two Circles Intersect? No");
r1 = new Rectangle(30,30,60,45);
r2 = new Rectangle(60,30,60,45);
rectangles[0] = r1;
rectangles[1] = r2;
// Connect the circles with the text fields;
for (int i = 0; i < rectangles.length; i++) {
rInfoPane[i] = new RectangleInfoPane(
"MyRec2 Info " + (i + 1) + ":", rectangles[i]);
rectangles[i].setFill(Color.TRANSPARENT);
rectangles[i].setStroke(Color.BLACK);

}
// Create Pane to hold the two circles
Pane cPane = new Pane(rectangles);
cPane.setStyle("-fx-border-color: green");

// Create Hbox to hold lblIsIntersect and make it center
HBox topLabelPane = new HBox(lblIsIntersect);
topLabelPane.setAlignment(Pos.CENTER);

// add listeners to c1, c2
for (int i = 0; i < 2; i++) {
final int index = i;
rectangles[i].setOnMouseDragged(e -> {
rectangles[index].setX(e.getX() - rectangles[index].getWidth() / 2);
rectangles[index].setY(e.getY() - rectangles[index].getHeight() / 2);
rInfoPane[index].update();
});
}

// add nodes to this pane

HBox hBoxInfo = new HBox(rInfoPane);
hBoxInfo.setSpacing(10);

setVgap(5);
setHgap(10);

GridPane.setHalignment(topLabelPane, HPos.CENTER);
GridPane.setHalignment(hBoxInfo, HPos.CENTER);
autosize();

}
// Updates textfields when circles are moved
lblIsIntersect.setText(
(MyRectangle2D.r1OverLapsR2(r1,r2)) ? intersectString + "Yes" : intersectString + "No");
}

private class RectangleInfoPane extends VBox {

TextField[] mTextFields = new TextField[4];
private TextField tfX;
private Label lblX;

private TextField tfY;
private Label lblY;

private TextField tfRecW;
private Label lblRecW;

private TextField tfRecH;
private Label lblRecH;

Rectangle mRectangle;
private RectangleInfoPane(String title, Rectangle r) {

mRectangle = r;
Label lblTitle = new Label(title);
HBox titlePane = new HBox(lblTitle);
titlePane.setAlignment(Pos.CENTER);

tfX = new TextField();
mTextFields[0] = tfX;
tfX.setPrefColumnCount(4);
tfX.setText(Double.toString(r.getX()));

lblX = new Label("x:", tfX);
lblX.setContentDisplay(ContentDisplay.RIGHT);
HBox xPane = new HBox(lblX);

tfY = new TextField();
mTextFields[1] = tfY;
tfY.setPrefColumnCount(4);
tfY.setText(Double.toString(r.getY()));
lblY = new Label("y:", tfY);
lblY.setContentDisplay(ContentDisplay.RIGHT);
HBox yPane = new HBox(lblY);

tfRecW = new TextField();
mTextFields[2] = tfRecW;
tfRecW.setPrefColumnCount(4);
tfRecW.setText(Double.toString(r.getWidth()));
lblRecW = new Label("width:", tfRecW);
lblRecW.setContentDisplay(ContentDisplay.RIGHT);
HBox wPane = new HBox(lblRecW);

tfRecH = new TextField();
mTextFields[3] = tfRecH;
tfRecH.setPrefColumnCount(4);
tfRecH.setText(Double.toString(r.getWidth()));
lblRecH = new Label("height:", tfRecH);
lblRecH.setContentDisplay(ContentDisplay.RIGHT);
HBox hPane = new HBox(lblRecH);

setStyle("-fx-border-color: black;");

// set listeners
for (TextField tf : mTextFields) {
tf.setOnAction(e -> updateRecStats());
}
}

private void updateRecStats(){
mRectangle.setX(Double.parseDouble(tfX.getText()));
mRectangle.setY(Double.parseDouble(tfY.getText()));
mRectangle.setWidth(Double.parseDouble(tfRecW.getText()));
mRectangle.setHeight(Double.parseDouble(tfRecH.getText()));
}

private void update() {
tfX.setText(mRectangle.getX() + "");
tfY.setText(mRectangle.getY() + "");
tfRecW.setText(mRectangle.getWidth() + "");
tfRecH.setText(mRectangle.getHeight() + "");
}
}
}

public static void main(String[] args) {
Application.launch(args);
}
}