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.setPadding(new Insets(10));
            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);
                    updateStats();
                    rInfoPane[index].update();
                });
            }

            // add nodes to this pane
            add(topLabelPane, 0, 0, 2, 1);
            add(cPane, 0, 1, 2, 1);

            HBox hBoxInfo = new HBox(rInfoPane);
            hBoxInfo.setSpacing(10);
            add(hBoxInfo, 0, 2, 2, 2);

            setVgap(5);
            setHgap(10);
            setPadding(new Insets(10));

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

        }
        // Updates textfields when circles are moved
        private void updateStats() {
            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);

                getChildren().addAll(titlePane, xPane, yPane, wPane, hPane);

                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);
    }
}

No comments :

Post a Comment