0

我有一个渲染 SVGDiagram 的 JPanel,设置为 JScrollPane 的视口视图。滚动窗格似乎工作正常,我也可以放大和缩小图表;并给定一个 MouseEvent,我可以使用“pick”方法找到附近的 SVGElements。

我希望能够使滚动窗格在给定的 ShapeElement 上居中,但我遇到了麻烦。我认为元素边界框的中心将是图表坐标系中形状的中心,但这似乎是错误的:

ShapeElement c;
Rectangle2D bounds = c.getBoundingBox();
Point center = new Point((int) bounds.getCenterX(), (int) bounds.getCenterY());

返回的中心似乎 (a) 将 Y 坐标偏移超过图表的高度(图表底部附近的元素似乎具有带有小的负 Y 值的“中心”,图表顶部附近的元素似乎具有“中心”具有较大的负 Y 值),以及 (b) 缩放 X 坐标(没有缩放,图表左边缘附近的元素似乎具有 X 值接近零的中心,而图表右边缘附近的元素似乎有 X 值大致接近图表宽度的 1/2 的中心)。

显然,当 svgSalamander 将 Shapes 渲染到屏幕上时,它会将它们放在“正确的位置”——但它使用的任何变换都只有在渲染到屏幕时才可用,这无助于我找到元素不在屏幕上时的中心。

有没有人有运气尝试将给定的 ShapeElement 居中?

4

1 回答 1

0

再一次,只是花时间写下这个问题,就把我推向了答案的方向。

关键是“pick”还必须将图表的坐标系与每个 Shape 的坐标系联系起来。在代码之后,SVGRoot.pick 创建一个标识 AffineTransform,然后依次连接到它,SVGRoot 的 viewXForm,然后是它遇到的每个 TransformableElement 的 xform,直到它到达一个 ShapeElement;在那里,ShapeElement.pick 检查给定的 Rectangle 是否与其通过 AffineTransforms 的串联变换的 Shape 相交。

因此,要找到给定 ShapeElement 的中心,只需要沿着其父元素向上走,收集任何 TransformableElement.getXForm() 结果,附加根元素的 viewXForm,创建从根元素向下的所有这些变换的串联,并将该变换应用于目标 ShapeElement 边界框的中心:

        synchronized Point2D getCenter(ShapeElement e) throws SVGException {
            List<AffineTransform> ats = new ArrayList<>();
            for (SVGElement el = e; el != null; el = el.getParent())
                if (el instanceof TransformableElement) {
                    AffineTransform a = ((TransformableElement) el).getXForm();
                    if (a != null)
                        ats.add(a);
                }
            ats.add(diagram.getRoot().getViewXform());
            AffineTransform xform = new AffineTransform();
            for (AffineTransform a : <an Iterable that iterates over ats in reverse> )
                xform.concatenate(a);
            return xform.transform(
                    new Point2D.Double(
                            e.getBoundingBox().getCenterX(),
                            e.getBoundingBox().getCenterY()
                    ), null);
        }

我确实必须添加(一个微不足道的)SVGRoot.getViewXform(),但仅此而已。

于 2022-02-26T23:05:31.087 回答