Prevent degenerate transforms for zero-size Scene/SubScene

XMLWordPrintable

    • Type: Bug
    • Resolution: Unresolved
    • Priority: P4
    • tbd
    • Affects Version/s: jfx25
    • Component/s: javafx
    • None

      When a Scene or SubScene has its width or height set to 0, coordinate transformations stop working because the transformation matrix contains NaNs. This is a consequence of divisions by zero in both parallel and perspective projections.

      Even though a 0x0 scene is mathematically degenerate, it is still desirable for coordinate transformation APIs to remain numerically well-behaved and return finite results whenever possible, rather than being poisoned by NaN/Infinity.

      Here is an application that demonstrates the failing coordinate transformations. Click on the buttons to resize the SubScene and observe the console output:

      public class ZeroSizeSubScene extends Application {

          @Override
          public void start(Stage stage) {
              var rect = new Rectangle(50, 50, Color.RED);
              var subScene = new SubScene(new Group(rect), 100, 100);
              subScene.setFill(Color.GRAY);

              // Also try a perspective camera:
              //
              // var camera = new PerspectiveCamera();
              // camera.setRotate(45);
              // camera.setTranslateX(-20);
              // camera.setRotationAxis(new Point3D(0, 1, 0));
              // subScene.setCamera(camera);

              class MyButton extends Button {
                  public MyButton(String text, double width, double height) {
                      super(text);
                      setOnAction(_ -> {
                          var timeline = new Timeline(
                              new KeyFrame(Duration.seconds(1), new KeyValue(subScene.widthProperty(), width)),
                              new KeyFrame(Duration.seconds(1), new KeyValue(subScene.heightProperty(), height)));

                          timeline.setOnFinished(_ -> {
                              Point2D p0 = rect.localToScreen(0, 0);
                              System.out.println("rect.localToScreen(0, 0) = " + p0);
                          });

                          timeline.play();
                      });
                  }
              }

              VBox.setMargin(subScene, new Insets(0, 0, 20, 0));

              var root = new VBox(5,
                  subScene,
                  new CheckBox("Rotate SubScene") {{ setOnAction(_ -> subScene.setRotate(isSelected() ? 45 : 0)); }},
                  new MyButton("Size: 100x100", 100, 100),
                  new MyButton("Size: 10x10", 10, 10),
                  new MyButton("Size: 100x0", 100, 0),
                  new MyButton("Size: 0x100", 0, 100),
                  new MyButton("Size: 0x0", 0, 0)
              );

              Scene scene = new Scene(root, 300, 300);
              stage.setScene(scene);
              stage.show();
          }
      }

            Assignee:
            Michael Strauß
            Reporter:
            Michael Strauß
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: