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.
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