如何在GraphStream视图中进行缩放?

4

在GraphStream可视化中,图形可能非常密集。 enableAutoLayout 方法提供了全局的图形可视化,因此需要进行缩放。如何缩放GraphStream视图?

Graph go=...;
Viewer viewer = new Viewer(go, Viewer.ThreadingModel.GRAPH_IN_ANOTHER_THREAD);
viewer.enableAutoLayout();
View view = viewer.addDefaultView(false); 
swingNode.setContent((JComponent) view);

更多内容请点击这里 - trashgod
4个回答

6
我尝试寻找一种使用鼠标滚轮缩放到鼠标光标的方法,并偶然间发现了这个帖子,希望能找到答案。最终我通过GraphStream解决了如何缩放到鼠标光标的问题:
在我的情况下,每次鼠标滚轮旋转的缩放因子为1.25(或者在缩小时为0.8)。该代码基于图形的原始中心、图形中的点击点、缩放以及最终可以从相机中检索到的Px和Gu之间的比率来计算图形的新中心。
final Viewer viewer = new Viewer(graph, Viewer.ThreadingModel.GRAPH_IN_ANOTHER_THREAD);
viewer.enableAutoLayout();
final View view = viewer.addDefaultView(false);
view.getCamera().setViewPercent(1);
((Component) view).addMouseWheelListener(new MouseWheelListener() {
    @Override
    public void mouseWheelMoved(MouseWheelEvent e) {
        e.consume();
        int i = e.getWheelRotation();
        double factor = Math.pow(1.25, i);
        Camera cam = view.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;
        double x = guClicked.x + (pxCenter.x - e.getX())/newRatioPx2Gu;
        double y = guClicked.y - (pxCenter.y - e.getY())/newRatioPx2Gu;
        cam.setViewCenter(x, y, 0);
        cam.setViewPercent(zoom);
    }
});

2

这只是将比例尺更改为中心。我的问题是关于缩放到视图的任何点,而不仅仅是中心。 - AbdelKh
1
根据同一文档页面的说明,您可以先将视图中心更改为任意点,然后进行缩放 view.getCamera().setViewCenter(2, 3, 4); - Yoann

1

这里有一个简单的代码,展示了如何缩放图表:

public class zoomGraph{

   public zoomGraph(){
   }
   //the methode that will zoom the graph
   public static void zoomGraphMouseWheelMoved(MouseWheelEvent mwe, ViewPanel view_panel){
        if (Event.ALT_MASK != 0) {            
            if (mwe.getWheelRotation() > 0) {
                double new_view_percent = view_panel.getCamera().getViewPercent() + 0.05;
                view_panel.getCamera().setViewPercent(new_view_percent);               
            } else if (mwe.getWheelRotation() < 0) {
                double current_view_percent = view_panel.getCamera().getViewPercent();
                if(current_view_percent > 0.05){
                    view_panel.getCamera().setViewPercent(current_view_percent - 0.05);                
                }
            }
        }                     
    }

    public static void main(String[] args) {

        JFrame frame = new JFrame();
        frame.setLayout(new GridLayout());
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);        
        frame.setBounds(0, 0, 700, 500);
        frame.setPreferredSize(new Dimension(700, 500));


        //Components
        JPanel panel = new JPanel();
        panel.setLayout(new GridLayout());
        frame.add(panel);

        //create a simple graph
        Graph graph = new SingleGraph("tuto_zoom", false, true);
        graph.addNode("node_1");
        graph.addNode("node_2");
        graph.addEdge("edge_1_2", "node_1","node_2");

        //show the graph in the panel
        Viewer viewer = new Viewer(graph, Viewer.ThreadingModel.GRAPH_IN_ANOTHER_THREAD);
        viewer.enableAutoLayout();
        ViewPanel view_panel = viewer.addDefaultView(false); 
        Rectangle rec = panel.getBounds();
        view_panel.setBounds(0, 0, rec.width, rec.height);
        view_panel.setPreferredSize(new Dimension(rec.width, rec.height));
        panel.add(view_panel);


        //add a mouse wheel listener to the ViewPanel for zooming the graph
        view_panel.addMouseWheelListener(new MouseWheelListener() {
            @Override
            public void mouseWheelMoved(MouseWheelEvent mwe) {
                zoomGraph.zoomGraphMouseWheelMoved(mwe, view_panel);
            }
        });


        frame.setVisible(true);
    }

}

0

这不是一个新的答案,而是对 @MichaG 的回答(https://dev59.com/A6Lia4cB1Zd3GeqPoch0#52929241)的改进。感谢你的出色工作!

在实现时,我意识到当图形旋转时,缩放中心是偏移的。下面是我的更新版本,它也适用于旋转后的图形:

@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);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接