This is not supposed to be a new answer, but rather an improvement of @MichaG 's answer (https://stackoverflow.com/a/52929241/5036964). Thanks for the great work!
When implementing this I realized, that the zoom center is off, when the graph is rotated. Below is my updated version, that also works when the graph was rotated:
@Override
public void mouseWheelMoved(MouseWheelEvent e) {
e.consume();
int i = e.getWheelRotation();
double factor = Math.pow(1.25, i);
Camera cam = viewPanel.getCamera();
double zoom = cam.getViewPercent() * factor;
Point2 pxCenter = cam.transformGuToPx(cam.getViewCenter().x, cam.getViewCenter().y, 0);
Point3 guClicked = cam.transformPxToGu(e.getX(), e.getY());
double newRatioPx2Gu = cam.getMetrics().ratioPx2Gu/factor;
/*
* patch begins here.
* the offset is calculated as before, but afterwards rotated according to
* the current rotation of the view.
*/
Point2 offset = new Point2();
offset.x = (pxCenter.x - e.getX()) / newRatioPx2Gu;
offset.y = (pxCenter.y - e.getY()) / newRatioPx2Gu;
Point2 rotatedOffset = rotateOffset(offset, -cam.getViewRotation());
double x = guClicked.x + rotatedOffset.x;
double y = guClicked.y - rotatedOffset.y;
cam.setViewCenter(x, y, 0);
cam.setViewPercent(zoom);
}
/**
* Rotates a given offset by the supplied angle in degrees.
*
* @param offset the offset that needs to be rotated
* @param degrees the degree in angles of the rotation
* @return rotated offset
*/
private Point2 rotateOffset(Point2 offset, double degrees) {
double sin = Math.sin(Math.toRadians(degrees));
double cos = Math.cos(Math.toRadians(degrees));
double rotOffsetX = offset.x * cos - offset.y * sin;
double rotOffsetY = offset.x * sin + offset.y * cos;
return new Point2(rotOffsetX, rotOffsetY);
}