I am working on a project with a feature of animating a path with a line. So when I press a button, a line goes through all the circles in the canvas. But I see that there is a slight difference in my path and the strokeline. It doesnt go through the circles. Please kindly advice thank you. This is my code:
import java.util.ArrayList;
import java.util.Random;
import javafx.animation.Animation;
import javafx.animation.PathTransition;
import javafx.animation.PathTransition.OrientationType;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.CubicCurveTo;
import javafx.scene.shape.LineTo;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.Path;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class PathVisualization extends Application {
private static double SCENE_WIDTH = 1000;
private static double SCENE_HEIGHT = 500;
private Canvas canvas;
private GraphicsContext gc;
private Button clear;
private Animation animation;
private ArrayList<Circle> num;
@Override
public void start(Stage primaryStage) throws Exception {
BorderPane bp = new BorderPane();
Pane root = new Pane();
root.setMaxSize(800,500);
// path = new Path();
canvas = new Canvas(SCENE_WIDTH,SCENE_HEIGHT);
TextField no = new TextField();
Button add = new Button("Add Circle");
Button playAnimation = new Button("Play");
clear = new Button("Clear");
Button pause = new Button("Pause");
VBox control = new VBox();
control.getChildren().add(no);
control.getChildren().add(add);
control.getChildren().add(playAnimation);
control.getChildren().add(clear);
control.getChildren().add(pause);
root.getChildren().add(canvas);
bp.setCenter(root);
bp.setLeft(control);
num = new ArrayList<Circle>();
clear.setOnMouseClicked(event->{
num.clear();
gc.clearRect(0, 0, gc.getCanvas().getWidth(), gc.getCanvas().getHeight());
root.getChildren().clear();
root.getChildren().add(canvas);
});
add.setOnMouseClicked(event->{
int cirNum = Integer.parseInt(no.getText());
Random rand = new Random();
for (int j=0;j<cirNum;j++) {
int x = rand.nextInt((int)root.getMaxWidth()-1);
int y = rand.nextInt((int)root.getMaxHeight()-1);
Circle circle = new Circle(x,y,10);
num.add(circle);
root.getChildren().add(circle);
}
//Heuristic Change
Path path = new Path();
path.setStroke(Color.RED);
path.getElements().add(new MoveTo(num.get(0).getCenterX(),num.get(0).getCenterY()));
path.setStrokeWidth(1);
for (int i=0;i<num.size();i++) {
try {
path.getElements().addAll(new LineTo(num.get(i).getCenterX(),num.get(i).getCenterY()));
}catch(IndexOutOfBoundsException e) {
path.getElements().addAll(new LineTo(num.get(0).getCenterX(),num.get(0).getCenterY()));
}
}
root.getChildren().addAll(path);
//create animation
animation = createPathAnimation(path, Duration.seconds(num.size()/4));
});
playAnimation.setOnMouseClicked(e ->{
animation.play();
});
pause.setOnMouseClicked(e->{
animation.pause();
});
primaryStage.setScene(new Scene(bp, SCENE_WIDTH, SCENE_HEIGHT));
primaryStage.show();
}
private Animation createPathAnimation(Path path, Duration duration) {
gc = canvas.getGraphicsContext2D();
// move a node along a path. we want its position
Circle pen = new Circle(0,0,0);
// create path transition
PathTransition pathTransition = new PathTransition(duration, path, pen);
pathTransition.currentTimeProperty().addListener( new ChangeListener<Duration>() {
Location oldLocation = null;
/**
* Draw a line from the old location to the new location
*/
@Override
public void changed(ObservableValue<? extends Duration> observable, Duration oldValue, Duration newValue) {
// skip starting at 0/0
if( oldValue == Duration.ZERO)
return;
// get current location
double x = pen.getTranslateX();
double y = pen.getTranslateY();
// initialize the location
if( oldLocation == null) {
oldLocation = new Location();
oldLocation.x = x;
oldLocation.y = y;
return;
}
// draw line
gc.setStroke(Color.GREENYELLOW);
gc.setLineWidth(5);
gc.strokeLine(oldLocation.x, oldLocation.y, x, y);
// update old location with current one
oldLocation.x = x;
oldLocation.y = y;
}
});
pathTransition.setOrientation(OrientationType.ORTHOGONAL_TO_TANGENT);
return pathTransition;
}
public static class Location {
double x;
double y;
}
public static void main(String[] args) {
launch(args);
}
}
This is the issue. At certain corners, the strokeline does not go through the circle and makes a weird cut.