0 Replies Latest reply: Nov 21, 2012 11:38 AM by famedoro RSS

    Zoom as axis rescaling

    famedoro
      Hi all,

      I would like to zoom in ( no magnify) a selected part of a chart: to zoom I mean a change for axis scale while the image should not be magnified.

      I was able to zoom by pixel resolution, but it is not what I would like to achieve: as from these links,
      first picture [http://postimage.org/image/ritfwispt/] show a freehand draw by right mouse click and drag, and picture 2 [http://postimage.org/image/kh76iqw87/] shows same freehand draw displaced and magnified once double click and drag with left mouse click.

      Does anybody can help me ?
      import javafx.application.Application;
      import javafx.beans.property.SimpleDoubleProperty;
      import javafx.collections.ObservableList;
      import javafx.event.EventHandler;
      import javafx.scene.Node;
      import javafx.scene.chart.NumberAxis;
      import javafx.scene.chart.XYChart;
      import javafx.stage.Stage;
      import javafx.scene.Scene;
      import javafx.scene.chart.LineChart;
      import javafx.scene.input.MouseButton;
      import javafx.scene.input.MouseEvent;
      import javafx.scene.layout.BorderPane;
      import javafx.scene.paint.Color;
      import javafx.scene.shape.*;
      
      
      public class Zoom extends Application {
      
      Path path;//Add path for freehand
      BorderPane pane;
      Rectangle rect;
      SimpleDoubleProperty rectinitX = new SimpleDoubleProperty();
      SimpleDoubleProperty rectinitY = new SimpleDoubleProperty();
      SimpleDoubleProperty rectX = new SimpleDoubleProperty();
      SimpleDoubleProperty rectY = new SimpleDoubleProperty();
      
      double initXLowerBound = 0, initXUpperBound = 0, initYLowerBound = 0, initYUpperBound = 0;
      @Override
      public void start(Stage stage) {
      
          stage.setTitle("Lines plot");
      
          final NumberAxis xAxis = new NumberAxis(1, 12, 1);
          final NumberAxis yAxis = new NumberAxis(0.53000, 0.53910, 0.0005);
      
          yAxis.setTickLabelFormatter(new NumberAxis.DefaultFormatter(yAxis) {
      
              @Override
              public String toString(Number object) {
                  return String.format("%7.5f", object);
              }
          });
      
          final LineChart<Number, Number> lineChart = new LineChart<Number, Number>(xAxis, yAxis);
      
          lineChart.setCreateSymbols(false);
          lineChart.setAlternativeRowFillVisible(false);
          lineChart.setAnimated(true);
          lineChart.setLegendVisible(false);
      
          XYChart.Series series1 = new XYChart.Series();
          
          series1.getData().add(new XYChart.Data(1, 0.53185));
          series1.getData().add(new XYChart.Data(2, 0.532235));
          series1.getData().add(new XYChart.Data(3, 0.53234));
          series1.getData().add(new XYChart.Data(4, 0.538765));
          series1.getData().add(new XYChart.Data(5, 0.53442));
          series1.getData().add(new XYChart.Data(6, 0.534658));
          series1.getData().add(new XYChart.Data(7, 0.53023));
          series1.getData().add(new XYChart.Data(8, 0.53001));
          series1.getData().add(new XYChart.Data(9, 0.53589));
          series1.getData().add(new XYChart.Data(10, 0.53476));
          series1.getData().add(new XYChart.Data(11, 0.530123));
          series1.getData().add(new XYChart.Data(12, 0.53035));
      
      
          pane = new BorderPane();
          pane.setCenter(lineChart);
          Scene scene = new Scene(pane, 800, 600);
          lineChart.getData().addAll(series1);
          
          initXLowerBound = ((NumberAxis) lineChart.getXAxis()).getLowerBound();
          initXUpperBound = ((NumberAxis) lineChart.getXAxis()).getUpperBound();
          initYLowerBound = ((NumberAxis) lineChart.getYAxis()).getLowerBound();
          initYUpperBound = ((NumberAxis) lineChart.getYAxis()).getUpperBound();
      
          stage.setScene(scene);        
          
          path = new Path();
          path.setStrokeWidth(1);
          path.setStroke(Color.BLACK);
      
          scene.setOnMouseClicked(mouseHandler);
          scene.setOnMouseDragged(mouseHandler);
          scene.setOnMouseEntered(mouseHandler);
          scene.setOnMouseExited(mouseHandler);
          scene.setOnMouseMoved(mouseHandler);
          scene.setOnMousePressed(mouseHandler);
          scene.setOnMouseReleased(mouseHandler);
      
          pane.getChildren().add(path);
      
          rect = new Rectangle();
          rect.setFill(Color.web("blue", 0.1));
          rect.setStroke(Color.BLUE);
          rect.setStrokeDashOffset(50);
      
          rect.widthProperty().bind(rectX.subtract(rectinitX));
          rect.heightProperty().bind(rectY.subtract(rectinitY));
          pane.getChildren().add(rect);
      
          stage.show();
      }
      
      
      EventHandler<MouseEvent> mouseHandler = new EventHandler<MouseEvent>() {
      
          @Override
          public void handle(MouseEvent mouseEvent) {
              if (mouseEvent.getButton() == MouseButton.PRIMARY)
              {
                      if (mouseEvent.getEventType() == MouseEvent.MOUSE_PRESSED) {
                          rect.setX(mouseEvent.getX());
                          rect.setY(mouseEvent.getY());
                          rectinitX.set(mouseEvent.getX());
                          rectinitY.set(mouseEvent.getY());
                      } else if (mouseEvent.getEventType() == MouseEvent.MOUSE_DRAGGED) {
                          rectX.set(mouseEvent.getX());
                          rectY.set(mouseEvent.getY());
                      } else if (mouseEvent.getEventType() == MouseEvent.MOUSE_RELEASED) {
      
                          if ((rectinitX.get() >= rectX.get())&&(rectinitY.get() >= rectY.get()))
                          {
                              //Condizioni Iniziali
                              LineChart<Number, Number> lineChart = (LineChart<Number, Number>) pane.getCenter();
      
                              ((NumberAxis) lineChart.getXAxis()).setLowerBound(initXLowerBound);
                              ((NumberAxis) lineChart.getXAxis()).setUpperBound(initXUpperBound);
      
                              ((NumberAxis) lineChart.getYAxis()).setLowerBound(initYLowerBound);
                              ((NumberAxis) lineChart.getYAxis()).setUpperBound(initYUpperBound);
                              
                              ZoomFreeHand(path, 1.0, 1.0, 0, 0);
      
                          }
                          else
                          {
                              //Zoom In
      
                              double Tgap = 0;
                              double newLowerBound, newUpperBound, axisShift;
                              double xScaleFactor, yScaleFactor;
                              double xaxisShift, yaxisShift;
                              //System.out.println("Zoom bounds : [" + rectinitX.get()+", "+rectinitY.get()+"] ["+ rectX.get()+", "+rectY.get()+"]");                
                              //System.out.println("TODO: Determine bound ranges according these zoom coordinates.\n");
      
                              // TODO: Determine bound ranges according this zoom coordinates.
                              //LineChart<String, Number> lineChart = (LineChart<String, Number>) pane.getCenter();
                              LineChart<Number, Number> lineChart = (LineChart<Number, Number>) pane.getCenter();
      
                              // Zoom in Y-axis by changing bound range.            
                              NumberAxis yAxis = (NumberAxis) lineChart.getYAxis();
                              Tgap = yAxis.getHeight()/(yAxis.getUpperBound() - yAxis.getLowerBound());
                              axisShift = getSceneShiftY(yAxis);
                              yaxisShift = axisShift;
                              
                              newUpperBound = yAxis.getUpperBound() - ((rectinitY.get() - axisShift) / Tgap);
                              newLowerBound = yAxis.getUpperBound() - (( rectY.get() - axisShift) / Tgap);
      
                             if (newUpperBound > yAxis.getUpperBound())
                                  newUpperBound = yAxis.getUpperBound();
      
                              yScaleFactor = (yAxis.getUpperBound() - yAxis.getLowerBound())/(newUpperBound - newLowerBound);
                              yAxis.setLowerBound(newLowerBound);
                              yAxis.setUpperBound(newUpperBound);
      
                              // Zoom in X-axis by removing first and last data values.
      
                              NumberAxis xAxis = (NumberAxis) lineChart.getXAxis();
      
      
                              Tgap = xAxis.getWidth()/(xAxis.getUpperBound() - xAxis.getLowerBound());            
                              axisShift = getSceneShiftX(xAxis);                        
                              xaxisShift = axisShift;
                                      
                              
                              
                              newLowerBound = ((rectinitX.get() - axisShift) / Tgap) + xAxis.getLowerBound();
                              newUpperBound = ((rectX.get() - axisShift) / Tgap) + xAxis.getLowerBound();                
      
                              if (newUpperBound > xAxis.getUpperBound())
                                  newUpperBound = xAxis.getUpperBound();
      
                              xScaleFactor = (xAxis.getUpperBound() - xAxis.getLowerBound())/(newUpperBound - newLowerBound);
                              xAxis.setLowerBound( newLowerBound );
                              xAxis.setUpperBound( newUpperBound );
      
      
                              ZoomFreeHand(path, xScaleFactor, yScaleFactor, xaxisShift, yaxisShift);
                          }
                          // Hide the rectangle
                          rectX.set(0);
                          rectY.set(0);
                      }
              }
              else if (mouseEvent.getButton() == MouseButton.SECONDARY) //free hand graphics
              {
                  if(mouseEvent.getEventType() == MouseEvent.MOUSE_PRESSED){
                      path.getElements().clear();
                      path.getElements().add(new MoveTo(mouseEvent.getX(), mouseEvent.getY()));
                  }
                  else if(mouseEvent.getEventType()==MouseEvent.MOUSE_DRAGGED){
                      path.getElements().add(new LineTo(mouseEvent.getX(), mouseEvent.getY()));
                  }
              } 
          }
         };
      private static double getSceneShiftX(Node node) {
          double shift = 0;
          do { 
              shift += node.getLayoutX(); 
              node = node.getParent();
          } while (node != null);
          return shift;
      }
      private static double getSceneShiftY(Node node) {
          double shift = 0;
          do { 
              shift += node.getLayoutY(); 
              node = node.getParent();
          } while (node != null);
          return shift;
      }
      private static void ZoomFreeHand(Path path, double xScaleFactor, double yScaleFactor, double xaxisShift, double yaxisShift) {    
          path.setScaleX(xScaleFactor);
          path.setScaleY(yScaleFactor);
          path.setTranslateX(xaxisShift);
          path.setTranslateY(yaxisShift);
      }
      
          public static void main(String[] args) {
              launch(args);
          }
          
          
      }