Centroid of a javafx Shape

Viewed 83

How can one find the centroid of a javafx Shape object?

Longer story: I am highlighting the intersections of 2 or more shapes, and need to position text over this intersection - ideally centering the text at the centroid. Given the potential for these intersections to be irregular, using the center of the intersection's layout bounds for calculations quite often result in mis-positioning of the text. For example, constructing the code below results in the center point that is offset relative to the conceptual center:

public class Test extends Application{

    public static void main(String[] args) {
        launch(args);
    }
    public void start(Stage primaryStage){
        /*
         * Create shapes
         */
        Circle s1 = new Circle(100, 100, 75);
        s1.setFill(new Color(1, 0, 0, 0.25));
        Circle s2 = new Circle(200, 100, 75);
        s2.setFill(new Color(0, 1, 0, 0.25));
        Circle s3 = new Circle(150, 125, 50); 
        s3.setFill(new Color(0, 0, 1, 0.25));
        /*
         * Create the intersection
         */
        Shape intersection = Shape.intersect(s3, s2);
        intersection = Shape.subtract(intersection, s1);
        intersection.setStroke(Color.RED);

        /*
         * Create a point that shows the layout bounds center
         */
        Circle boundsCenter = new Circle();
        boundsCenter.setRadius(2d);
        boundsCenter.setCenterX(intersection.getLayoutBounds().getMinX() + intersection.getLayoutBounds().getWidth()/2);
        boundsCenter.setCenterY(intersection.getLayoutBounds().getMinY() + intersection.getLayoutBounds().getHeight()/2);
        boundsCenter.setFill(Color.RED);
        intersection.setFill(null);


        Pane pane = new Pane();
        pane.getChildren().addAll(s1, s2, s3, intersection, boundsCenter);
        Scene scene = new Scene(pane);
        primaryStage.setScene(scene);
        primaryStage.sizeToScene();
        primaryStage.show();
    } 
}

I would prefer to rely on the javafx API to do so (java 8 compatible), if at all possible.

One Option I have considered is to estimate the centroid by sampling using the Shape API and calculating the centroid of Points that fall within the given Shape:

//estimate the centroid by random sampling 
int maxEstimate = 100;
double x = 0; double y = 0; double count = 0;
while(count < maxEstimate) {
    double randomX = intersection.getLayoutBounds().getMinX() + Math.random() * intersection.getLayoutBounds().getWidth();
    double randomY = intersection.getLayoutBounds().getMinY() + Math.random() * intersection.getLayoutBounds().getHeight();
    Circle test = new Circle(randomX, randomY, 1d);
    Shape isInside = Shape.intersect(c, intersection);
    if ( isInside.getLayoutBounds().getWidth() > 0 || isInside.getLayoutBounds().getHeight() > 0 ) {
        x += randomX;
        y += randomY;
        count++;
    }
}
double centroidX = x / count;
double centroidY = y / count;

The problem with this method is that it is non-deterministic, can be inaccurate for smaller number of iterations, and quite intensive and time consuming for a larger number of shapes (and/or a more accurate measurement)

0 Answers
Related