Sunday 25 December 2016

Chapter 15 Exercise 17, Introduction to Java Programming, Tenth Edition Y. Daniel LiangY.

15.17 (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 15.29a.
A minimum bounding rectangle is updated as the points are added and
removed. Assume that the radius of each point is 10 pixels.


import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.input.MouseButton;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

import java.util.ArrayList;

public class Exercise_17 extends Application {

    Pane pane = new Pane();
    ArrayList<Circle> mCircles = new ArrayList<>();
    @Override
    public void start(Stage primaryStage) {

        double width = 600;
        double height = 400;
        // VBox
        VBox infoVBox = new VBox();
        infoVBox.setPadding(new Insets(5, 5, 5, 5));
        infoVBox.setStyle("-fx-border-color: black");

        Label info1 = new Label("INSTRUCTION");
        Label info2 = new Label("Add: Left Click");
        Label info3 = new Label("Remove: Right Click");

        infoVBox.getChildren().addAll(info1, info2, info3);
        Pane infoPane = new Pane(infoVBox);
        infoPane.setPadding(new Insets(10, 10, 10, 10));

        // Pane
        pane.getChildren().addAll(infoPane);
        infoVBox.setLayoutX(10);
        infoVBox.setLayoutY(10);

        pane.setOnMouseClicked(e-> {
            double x = e.getX();
            double y = e.getY();
            if (infoPane.contains(x, y)) return;

            if (e.getButton() == MouseButton.PRIMARY) {
                Circle c = drawPoint(x,y);
                mCircles.add(c);
                pane.getChildren().add(c);
                drawMinBoundingRec();

            } else if (e.getButton() == MouseButton.SECONDARY) {
                removePoint(x, y);
                drawMinBoundingRec();

            }

        });

        Scene scene = new Scene(pane, width, height);
        primaryStage.setScene(scene);
        primaryStage.setTitle("click to draw circle");
        primaryStage.show();
    }

    private Circle drawPoint(double x, double y) {
        Circle c = new Circle(x, y, 10, Color.TRANSPARENT);
        c.setStroke(Color.BLACK);
        return c;
    }

    private void drawMinBoundingRec() {

        removeRec(); // removes old rec

        if (mCircles.size() == 0) return;

        // assume first circle is the current bounding limit
        Circle top = mCircles.get(0);
        Circle bottom = mCircles.get(0);
        Circle right = mCircles.get(0);
        Circle left = mCircles.get(0);
        // get lowest x,y and get highest x,y
        for (Circle c : mCircles) {
            if (c.getCenterX() < left.getCenterX()) left = c;
            if (c.getCenterX() > right.getCenterX()) right = c;
            if (c.getCenterY() > bottom.getCenterY()) bottom = c;
            if (c.getCenterY() < top.getCenterY()) top = c;
        }
        // all circles have the same radius
        double width = right.getCenterX() - left.getCenterX() +  top.getRadius() * 2;
        double height = bottom.getCenterY() - top.getCenterY() +  top.getRadius() * 2;
        double centerX = (right.getCenterX() + left.getCenterX()) / 2;
        double centerY = (top.getCenterY() + bottom.getCenterY()) / 2;

        Rectangle rec = new Rectangle(centerX - width / 2, centerY - height / 2, width, height);
        rec.setStroke(Color.BLACK);
        rec.setFill(Color.TRANSPARENT);
        pane.getChildren().add(rec);

    }
    private void removePoint(double x, double y) {
        ObservableList<Node> list = pane.getChildren();
        for (int i = list.size() - 1; i >= 0; i--) {
            Node c = list.get(i);

            if (c instanceof Circle && c.contains(x, y)) {
                pane.getChildren().remove(c);
                mCircles.remove(c);

                break;
            }
        }
    }

    private void removeRec(){
        ObservableList<Node> list = pane.getChildren();

        for (Node c : list) {
            if (c instanceof Rectangle) {
                pane.getChildren().remove(c);

                break;
            }
        }

    }

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

No comments :

Post a Comment