Как найти центр тяжести объекта 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, может быть неточным для меньшего числа итераций, и достаточно интенсивным и трудоемким для большего числа фигур (и / или более точного измерения)