First note that you are falling into a very common mistake in using integer division and expecting it to result in a double. The expression
72/5000
evaluates to zero, so you have a zero scale, with which you will obviously not see anything at all. You need
double scale = 72.0/5000;
Also note that there is no need to assume the resolution of the screeen; you can use the Screen
API to determine it at runtime. So, as a simple example (which assumes the stage is displayed on the primary screen; it is not too hard to find the "current" screen dynamically) you can do
double scale = Screen.getPrimary().getDpi() / 5000;
Basically, your transforms are reversed; but I will step through this piece by piece:
I think the intention of your first transform is to move the coordinate system so the origin is at the center. At this point the pane is still in "pixel units", so one unit is one pixel, and the origin is in the top left. So to move the origin to the center, you need
pane.getTransforms().add(new Translate(320, 240));
Note the top left corner of the rectangle is at the origin, so this puts the top left corner of the rectangle at the center of the screen.
Now you do the scale, which scales about the origin (the origin remains fixed):
pane.getTransforms().add(new Scale(scale, scale));
Note that because the origin stays fixed, the top left of the rectangle is at the center of the screen at this point. The scale means that the "units" are now "world units", so the pane width is 640/scale=44444.44
and the height is 480/scale=33333.33
, though this isn't too important.
Now, since the rectangle has its top left corner at the center, and the units are "world units", to center it move it left by half its width and up by half its height:
pane.getTransforms().add(new Translate(-5000, -7500));
You can check the position of the rectangle in the units of the scene (pixels) with
System.out.println(rectangle.getLocalToSceneTransform().transform(rectangle.getBoundsInLocal()));
The following gives the desired outcome:
public void start(Stage primaryStage) {
double sceneWidth = 640;
double sceneHeight = 480;
double rectangleWidth = 10000;
double rectangleHeight = 15000;
double scale = Screen.getPrimary().getDpi()/5000;
Pane pane = new Pane();
Scene scene = new Scene(pane, sceneWidth, sceneHeight);
Rectangle rectangle = new Rectangle(rectangleWidth, rectangleHeight);
pane.getChildren().add(rectangle);
primaryStage.setScene(scene);
primaryStage.show();
pane.getTransforms().clear();
pane.getTransforms().add(new Translate(320, 240));
pane.getTransforms().add(new Scale(scale, scale));
pane.getTransforms().add(new Translate(-5000, -7500));
System.out.println(rectangle.getLocalToSceneTransform().transform(rectangle.getBoundsInLocal()));
}
With the original code you posted, you start with a 10000 by 15000 pixel rectangle with top left at 0,0 (which is the top left of the pane).
You then translate 5000 pixels left and 7500 pixels up.
This leaves the origin of the pane, and the top left of the rectangle, at (-5000, -7500)
in scene coordinates, and the rectangle extends to (5000, 7500)
in scene coordinates (so at this point it covers the scene).
Then you scale by a factor 72.0/5000
(after correcting the aforementioned error). This makes the rectangle width 144 and height 216 in scene coordinates, and since the origin is fixed in a scale transformation it extends from (-5000, -7500)
to (-4856, -7284)
, again in scene coordinates. This of course places it well outside the visible area of the scene.
Finally you translate by (320, 240)
in world coordinates (the coordinates of the pane, since that's the node to which the translation is applied). These equate to 320*scale = 4.608
horizontally and 240*scale = 3.456
vertically in scene coordinates, shifting the rectangle so it spans from (-4995.392, -7496.544)
to (-4851.392 ,-7280.544)
in scene coordinates (still far from the visible portion of the scene).
You can use the same debugging line as above to see where the rectangle lies in scene coordinates.