2

I have a Path object composed of PathElements

picture

All 5 objects are drawn in the same style. - (MoveTo, LineTo, ArcTo, LineTo, ArcTo)

I need a method that can calculate the center of an entire Path object.

And they can calculate it for all five objects.

The idea is to calculate the center of both arcs (arcTo), to create a Line that connects these centers, and the center of this Line will be the center of an entire Path object.

But, I don't know how to calculate it simply. I got stuck in the calculation of the center of the arc.

I need to calculate it independently of objects creation, but I have access to objects - I can get all the information about them.

Michal Rama
  • 173
  • 1
  • 1
  • 10
  • 1
    Can you supply an [mcve](https://stackoverflow.com/help/minimal-reproducible-example). How did you generate the initial path elements which are being input to this? – jewelsea Jan 03 '20 at 19:54
  • Do you want the center of the entire path, or the center of each path element (other than moveTo)? – VGR Jan 03 '20 at 20:14
  • From the description, he is trying to locate the center of two path elements (arcTo elements). I assume a path element center point is the equidistant point along an arc. Then, he will calculate the midpoint of an imaginary line between those two path element center points. That line midpoint is what Yoda is defining as the center of the path (which is what he ultimately is trying to calculate). – jewelsea Jan 03 '20 at 21:20
  • Yes, when I create a `Line` that connects both `ArcTo` centers, the center of this `Line` is the center of the entire `Path` object. The center `Line` is easy to calculate, but the center of `ArcTo` is more complicated - I found an [article](http://mathcentral.uregina.ca/RR/database/RR.09.10/akulov2.html) how to calculate the center, but I did not understand it. I will not write code for drawing `Path` here. 1. It is too complex. 2. I want to calculate the center independently of the creation of `Path` objects. 3. I have access to objects so I can get all the information they contain. – Michal Rama Jan 03 '20 at 21:59

1 Answers1

4

There will be better ways to do this (by appropriately applying the correct mathematical equations). However, you can lever the path transition system to get the required answers, as is done in the answer to:

The green points are the mid-points of the arcs. The red point is the mid-point of the center of the path.

According to the definition (as I understood it):

From the description, he is trying to locate the center of two path elements (arcTo elements). I assume a path element center point is the equidistant point along an arc. Then, he will calculate the midpoint of an imaginary line between those two path element center points. That line midpoint is what Yoda is defining as the center of the path (which is what he ultimately is trying to calculate).

midpoints

import javafx.animation.Interpolator;
import javafx.animation.PathTransition;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.*;
import javafx.stage.Stage;
import javafx.util.Duration;

public class ArcCenter extends Application {
    @Override
    public void start(Stage stage) {
        Path arcPath1 = new Path(
                new MoveTo(50, 25),
                new ArcTo(30, 15, 0, 100, 50, false, true)
        );
        arcPath1.setStrokeWidth(2);
        arcPath1.setStroke(Color.ORANGE);

        Path arcPath2 = new Path(
                new MoveTo(30, 40),
                new ArcTo(10, 5, 0, 60, 60, false, true)
        );
        arcPath2.setStrokeWidth(2);
        arcPath2.setStroke(Color.HOTPINK);

        Circle arcMidpoint1 = calcMidpoint(arcPath1, Color.FORESTGREEN);
        Circle arcMidpoint2 = calcMidpoint(arcPath2, Color.FORESTGREEN);

        Group group = new Group(
                arcPath1,
                arcPath2,
                arcMidpoint1,
                arcMidpoint2
        );

        arcMidpoint2.translateYProperty().addListener((observable, oldValue, newValue) -> {
            Path line = new Path(
                    new MoveTo(arcMidpoint1.getTranslateX(), arcMidpoint1.getTranslateY()),
                    new LineTo(arcMidpoint2.getTranslateX(), arcMidpoint2.getTranslateY())
            );
            line.setStroke(Color.LIGHTBLUE);
            line.setStrokeWidth(2);
            group.getChildren().add(line);
            line.toBack();

            Circle lineMidpoint = calcMidpoint(line, Color.RED.darker());
            lineMidpoint.translateYProperty().addListener((o, old, newV) -> {
                System.out.println(
                    "Path center point: ( " +
                    lineMidpoint.getTranslateX() + ", " +
                    lineMidpoint.getTranslateY() + " )"
                );
            });
            group.getChildren().add(lineMidpoint);
        });

        group.setScaleX(2);
        group.setScaleY(2);

        stage.setScene(
                new Scene(
                        new StackPane(new Group(group)),
                        300, 200,
                        Color.rgb(35, 39, 50)
                )
        );
        stage.show();
    }

    private Circle calcMidpoint(Path path, Color midpointColor) {
        Circle midpoint = new Circle(3, midpointColor);

        PathTransition pathTransition = new PathTransition(Duration.minutes(10), path, midpoint);
        pathTransition.setOrientation(PathTransition.OrientationType.NONE);
        pathTransition.setInterpolator(Interpolator.LINEAR);
        pathTransition.jumpTo(pathTransition.getDuration().divide(2));
        pathTransition.play();

        midpoint.translateYProperty().addListener((observable, oldValue, newValue) -> {
            pathTransition.stop();
        });

        return midpoint;
    }

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

I make no claims at all that the above proposed solution is actually 100% correct in the values it calculates, but, from a casual glance it looks to be correct (or close enough), that it would seem OK to me for most purposes.

jewelsea
  • 150,031
  • 14
  • 366
  • 406
  • I’m still not clear on the exact problem posed in the question, but using a PathTransition to find the midpoint of an arbitrary Path is a clever idea. – VGR Jan 04 '20 at 03:24
  • Yes. It took me a while to understand and apply the code to my program and it works. Thank you very much. – Michal Rama Jan 05 '20 at 22:24