# Compress/Expand data visualization



## susieferrari (23. Jul 2012)

Hi all,

having a XY chart I would like compress/expand data visualization both for X and Y axis by left mouse click, keep pressed and drag

Here is a chart example (picture A01973 attached) and here is the code to plot sample data


```
public class BaseXYChart extends Application {
 
    @Override
    public void start(Stage stage) {
       stage.setTitle("Linear plot");
         
       final CategoryAxis xAxis = new CategoryAxis();
       final NumberAxis yAxis = new NumberAxis(1, 22, 0.5);
         
       yAxis.setTickLabelFormatter(new NumberAxis.DefaultFormatter(yAxis){
            @Override
        public String toString(Number object){
            return String.format("%7.2f", object);
        }
    });
final LineChart<String, Number>lineChart = new LineChart<String, Number>(xAxis, yAxis);
 
       lineChart.setCreateSymbols(false);
       lineChart.setAlternativeRowFillVisible(false);
       lineChart.setLegendVisible(false);
                
       XYChart.Series series1 = new XYChart.Series();
         
        series1.getData().add(new XYChart.Data("Jan", 1));
        series1.getData().add(new XYChart.Data("Feb", 1.5));
        series1.getData().add(new XYChart.Data("Mar", 2));
        series1.getData().add(new XYChart.Data("Apr", 2.5));
        series1.getData().add(new XYChart.Data("May", 3));
        series1.getData().add(new XYChart.Data("Jun", 4));
        series1.getData().add(new XYChart.Data("Jul", 6));
        series1.getData().add(new XYChart.Data("Aug", 9));
        series1.getData().add(new XYChart.Data("Sep", 12));
        series1.getData().add(new XYChart.Data("Oct", 15));
        series1.getData().add(new XYChart.Data("Nov", 20));
        series1.getData().add(new XYChart.Data("Dec", 22));
  
        BorderPane pane = new BorderPane();
        pane.setCenter(lineChart);          
        Scene scene = new Scene(pane, 800, 600);
        lineChart.getData().addAll(series1);
          
        stage.setScene(scene);
        stage.show();
    }
 
    public static void main(String[] args) {
        launch(args);
    }   
}
```

This is the expected result after left mouse click, keep pressed and dragged from top to bottom on Y Axis

(picture A01955 attached)

The same is expected for X Axis, by dragging lef/right data should compress or expand.

How can I accomplish this? Haven't found any examples anywhere!

Thanks.

Susie


----------



## susieferrari (23. Jul 2012)

Question closed, solved right now.

Thanks

Susie


----------



## Gast2 (23. Jul 2012)

You do know how a forum works, don't you? 

The most important aspect is sharing information with each other! So please tell us *how* you solved this issue...


----------



## susieferrari (23. Jul 2012)

Yes, of course, I am still working to fine tuning the code to fix all minor problems, once done I will share it.

I thought none was interested since I've got only one reply in my previous post, and it doesn't help at all.

I know how a forum works and that's the reason for posting here, asking help and hoping to find support in sharing help and information.

But maybe I am wrong, so let's test it with another question I have to solve:

This problem is about draw on a chart + zoom (= magnify).

the code below performs a zoom by left mouse click & drag on the chart (from up left to down right) and restore back form down right to up left.

Right mouse click and drag performs a free hand draw: the problem is that if I draw then zoom, what drawn is displaced, it is no longer where I previously drawn.

How to fix this?
And, how perform the same by using Category Axis on X axis instead of Number, Number as my example?

Sample code below


```
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 CategoryAxis xAxis = new CategoryAxis();
    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);
 
    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(lineChart, 800, 600);
    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);
 
    //root.getChildren().add(lineChart);
    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();
}
// sum layout shift against parent until we ascend to scene
 
 
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);
 
 
                        //System.out.println("(a) rectinitY.get() "+rectinitY.get()+" rectY.get() "+rectY.get());
                        //System.out.println("(a) Tgap "+Tgap+" axisShift "+axisShift+" yAxis.getLowerBound() " + yAxis.getLowerBound()+ " " + yAxis.getUpperBound());
 
                        if (newUpperBound > yAxis.getUpperBound())
                            newUpperBound = yAxis.getUpperBound();
 
                        yScaleFactor = (yAxis.getUpperBound() - yAxis.getLowerBound())/(newUpperBound - newLowerBound);
                        yAxis.setLowerBound(newLowerBound);
                        yAxis.setUpperBound(newUpperBound);
 
                        //System.out.println("(b) yAxis.getLowerBound() " + yAxis.getLowerBound()+ " " + yAxis.getUpperBound());
 
                        // Zoom in X-axis by removing first and last data values.
                        // Note: Maybe better if categoryaxis is replaced by numberaxis then setting the
                        // LowerBound and UpperBound will be avaliable.
                        /*
                        XYChart.Series series1 = lineChart.getData().get(0);
                        if (!series1.getData().isEmpty()) {
                            series1.getData().remove(0);
                            series1.getData().remove(series1.getData().size() - 1);
                        }
                        */
 
                        NumberAxis xAxis = (NumberAxis) lineChart.getXAxis();
 
                        //System.out.println("(a) xAxis.getLowerBound() " + xAxis.getLowerBound()+ " " + xAxis.getUpperBound());            
 
                        Tgap = xAxis.getWidth()/(xAxis.getUpperBound() - xAxis.getLowerBound());            
            //            newXlower = (rectinitX.get()/Tgap) + xAxis.getLowerBound();
            //            newXupper = (rectX.get()/Tgap)+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 );
 
 
 
                        //System.out.println("(b) xAxis.getLowerBound() "+xAxis.getLowerBound()+" "+xAxis.getUpperBound());
                        
                        ZoomFreeHand(path, xScaleFactor, yScaleFactor, xaxisShift, yaxisShift);
                    }
                    // Hide the rectangle
                    rectX.set(0);
                    rectY.set(0);
                }
        }// end if (mouseEvent.getButton() == MouseButton.PRIMARY)
        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()));
            }
        } //end if (mouseEvent.getButton() == MouseButton.SECONDARY)
    }
   };
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) {
    /*
    ObservableList<PathElement> ListPath = path.getElements();
    
    if (ListPath.size() != 0)
    {
        MoveTo moveto;
        ((MoveTo)(ListPath.get(0))).setX(0-axisShiftX);    
        ((MoveTo)(ListPath.get(0))).setY(0-axisShiftY);
    }
    */
    
    path.setScaleX(xScaleFactor);
    path.setScaleY(yScaleFactor);
    path.setTranslateX(xaxisShift);
    path.setTranslateY(yaxisShift);
}
 
    public static void main(String[] args) {
        launch(args);
    }
        
}
```

Thanks all!

Susie


----------

