Skip to content

Commit

Permalink
Merge pull request #67 from HarryDulaney/hg-new-solutions
Browse files Browse the repository at this point in the history
Add many new solutions
  • Loading branch information
HarryDulaney authored Nov 18, 2023
2 parents 86d7208 + c9d8f95 commit 6d0cf89
Show file tree
Hide file tree
Showing 12 changed files with 1,669 additions and 0 deletions.
116 changes: 116 additions & 0 deletions ch_15/Exercise15_21.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package ch_15;


import javafx.application.Application;
import javafx.geometry.Point2D;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.scene.text.Text;
import javafx.stage.Stage;

/**
* 15.21 (Drag points) Draw a circle with three random points on the circle. Connect
* the points to form a triangle. Display the angles in the triangle. Use the mouse
* to drag a point along the perimeter of the circle. As you drag it, the triangle and
* angles are redisplayed dynamically, as shown in Figure 15.30b. For computing
* angles in a triangle, see Listing 4.1.
* <p>
* The parametric equation for a circle is
* x = cx + r * cos(a)
* y = cy + r * sin(a)
* where r is the radius, (cx, cy) the center of the circle, and a, an angle in radians.
*/
public class Exercise15_21 extends Application {
private double radius = 10;
private int centerX = 200;
private int centerY = 125;
private int radiusMainCircle = 100;
private Pane pane = new Pane();
private Circle outlineCircle = new Circle(centerX, centerY, radiusMainCircle);
private Circle[] points = new Circle[3];
private Line line1 = new Line();
private Line line2 = new Line();
private Line line3 = new Line();
private Text[] text = {new Text(), new Text(), new Text()};

@Override
public void start(Stage primaryStage) {
draw();
pane.getChildren().addAll(points[0], points[1], points[2],
line1, line2, line3, text[0], text[1], text[2]);
Scene scene = new Scene(pane, 400, 250);
primaryStage.setTitle(getClass().getName());
primaryStage.setScene(scene);
primaryStage.show();

points[0].setOnMouseDragged(e -> {
if (points[0].contains(e.getX(), e.getY())) {
// Recompute and display angles
points[0].setCenterX(e.getX());
points[0].setCenterY(e.getY());
setLines();
}
});

points[1].setOnMouseDragged(e -> {
if (points[1].contains(e.getX(), e.getY())) {
// Recompute and display angles
points[1].setCenterX(e.getX());
points[1].setCenterY(e.getY());
setLines();
}
});

points[2].setOnMouseDragged(e -> {
if (points[2].contains(e.getX(), e.getY())) {
// Recompute and display angles
points[2].setCenterX(e.getX());
points[2].setCenterY(e.getY());
setLines();
}
});
}


void draw() {
points[0] = new Circle(40, 40, 10);
points[1] = new Circle(140, 40, 10);
points[2] = new Circle(60, 140, 10);
setLines();
}

private void setLines() {
line1.setStartX(points[0].getCenterX());
line1.setStartY(points[0].getCenterY());
line1.setEndX(points[1].getCenterX());
line1.setEndY(points[1].getCenterY());
line2.setStartX(points[0].getCenterX());
line2.setStartY(points[0].getCenterY());
line2.setEndX(points[2].getCenterX());
line2.setEndY(points[2].getCenterY());
line3.setStartX(points[1].getCenterX());
line3.setStartY(points[1].getCenterY());
line3.setEndX(points[2].getCenterX());
line3.setEndY(points[2].getCenterY());

// Compute angles
double a = new Point2D(points[2].getCenterX(), points[2].getCenterY()).
distance(points[1].getCenterX(), points[1].getCenterY());
double b = new Point2D(points[2].getCenterX(), points[2].getCenterY()).
distance(points[0].getCenterX(), points[0].getCenterY());
double c = new Point2D(points[1].getCenterX(), points[1].getCenterY()).
distance(points[0].getCenterX(), points[0].getCenterY());
double[] angle = new double[3];
angle[0] = Math.acos((a * a - b * b - c * c) / (-2 * b * c));
angle[1] = Math.acos((b * b - a * a - c * c) / (-2 * a * c));
angle[2] = Math.acos((c * c - b * b - a * a) / (-2 * a * b));

for (int i = 0; i < 3; i++) {
text[i].setX(points[i].getCenterX());
text[i].setY(points[i].getCenterY() - radius);
text[i].setText(String.format("%.2f", Math.toDegrees(angle[i])));
}
}
}
163 changes: 163 additions & 0 deletions ch_15/Exercise15_29.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
package ch_15;

import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Polygon;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;

/**
* **15.29 (Racing car) Write a program that simulates car racing, as shown in
* Figure 15.34a. The car moves from left to right. When it hits the right end, it
* restarts from the left and continues the same process. You can use a timer to
* control animation. Redraw the car with a new base coordinates (x, y), as shown
* in Figure 15.34b. Also let the user pause/resume the animation with a
* button press/release and increase/decrease the car speed by pressing the UP and
* DOWN arrow keys.
*/
public class Exercise15_29 extends Application {

private final double WIDTH = 600;
private final double HEIGHT = 100;

@Override
public void start(Stage primaryStage) throws Exception {
RacingPane pane = new RacingPane(WIDTH, HEIGHT);
pane.start();
pane.setOnMousePressed(e -> pane.pause());
pane.setOnMouseReleased(e -> pane.play());

pane.setOnKeyPressed(e -> {
if (e.getCode() == KeyCode.UP) {
pane.increaseSpeed();
} else if (e.getCode() == KeyCode.DOWN) {
pane.decreaseSpeed();
}
});

Scene scene = new Scene(pane, WIDTH, HEIGHT);
primaryStage.setTitle(getClass().getName());
primaryStage.setScene(scene);
primaryStage.show();

pane.requestFocus();
}

}

class RacingPane extends Pane {
private double x;
private double y;
private CarShape car;
private Timeline animation;

/**
* Construct and animate a default CarPane
*/
RacingPane(double width, double height) {
setHeight(height);
setWidth(width);
car = new CarShape(x, y, 5, this);
x = 0;
y = 100;
animation = new Timeline(
new KeyFrame(Duration.millis(50), e -> car.moveCar(x, y, this)));
animation.setCycleCount(Timeline.INDEFINITE);
}


void start() {
animation.play();
}


/**
* Pause animation
*/
public void pause() {
animation.pause();
}

/**
* Play animation
*/
public void play() {
animation.play();
}

/**
* Increase rate by 1
*/
public void increaseSpeed() {
animation.setRate(animation.getRate() + 1);
}

/**
* decrease rate by 1
*/
public void decreaseSpeed() {
animation.setRate(animation.getRate() > 0 ? animation.getRate() - 1 : 0);
}

class CarShape {
private double wheelRadius;
private Rectangle lowerBody;
private Polygon topBody;
private Circle wheel1;
private Circle wheel2;

public CarShape(double x, double y, double wheelRadius, Pane pane) {
this.wheelRadius = wheelRadius;
drawAndRender(x, y, pane);
}

void drawAndRender(double x, double y, Pane pane) {
if (!pane.getChildren().isEmpty()) {
pane.getChildren().clear();
}

lowerBody = new Rectangle(x, y - 20, 50, 10);
topBody = new Polygon(x + 10, y - 20, x + 20, y - 30, x + 30,
y - 30, x + 40, y - 20);
wheel1 = new Circle(x + 15, y - 5, wheelRadius);
wheel2 = new Circle(x + 35, y - 5, wheelRadius);
pane.getChildren().addAll(getLowerBody(), getWheel1(), getWheel2(), getTopBody());
}

/**
* Calculate new x position and draw car
*
* @param x the current x position
* @param y the current y position
* @param pane the pane to render the car on
*/
protected void moveCar(double x, double y, Pane pane) {
x += 1;


drawAndRender(x, y, pane);
}

public Rectangle getLowerBody() {
return lowerBody;
}

public Polygon getTopBody() {
return topBody;
}

public Circle getWheel1() {
return wheel1;
}

public Circle getWheel2() {
return wheel2;
}
}
}
Loading

0 comments on commit 6d0cf89

Please sign in to comment.