Центр тяжести формы Явафа - PullRequest
1 голос
/ 31 марта 2020

Как найти центр тяжести объекта javafx Shape?

Более длинная история : я выделяю пересечения 2 или более фигур, и мне нужно расположить текст поверх этого пересечения - в идеале центрировать текст по центроиду. Учитывая вероятность того, что эти пересечения будут нерегулярными, использование центра макета границ пересечения для вычислений довольно часто приводит к неправильному позиционированию текста. Например, построение приведенного ниже кода приводит к центральной точке, которая смещена относительно концептуального центра:

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();
    } 
}

Я бы предпочел полагаться на API javafx, чтобы сделать это (совместим с java 8), если вообще возможно.

Один из вариантов , который я рассмотрел, заключается в оценке центроида путем выборки с использованием API формы и расчета центроида точек, попадающих в данный 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;

Проблема с этим методом заключается в том, что он не является детерминированным c, может быть неточным для меньшего числа итераций, и достаточно интенсивным и трудоемким для большего числа фигур (и / или более точного измерения)

...