为什么Shape.intersect产生的形状出现在错误的位置? [英] Why does the resulting shape from Shape.intersect appear at an incorrect position?

查看:195
本文介绍了为什么Shape.intersect产生的形状出现在错误的位置?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于我目前的一个javafx项目,我正在与Venn Diagrams合作。我想利用Shape.intersect来减轻我必须亲自完成的数学计算量(并避免使用Path对象)。 Shape.intersect产生一个完美的形状,但它被翻译/移动了一点,我无法弄清楚要多少钱。理想情况下,我希望交叉区域恰好出现在两个原始形状相交的位置 - 即新交叉点与原始形状无缝匹配。

For one of my current javafx projects I'm working with Venn Diagrams. I'd like to take advantage of Shape.intersect to ease the amount of math calculations I'd have to personally work through (and avoid working with Path objects). Shape.intersect produces a perfect shape, but it is translated / moved a bit and I can't figure out how much to put it back. Ideally, I'd like to have the intersection area occur exactly where the two original shapes intersect - i.e. the new intersection would fit seamlessly with the original shapes.

目前,我的代码产生了一个三维的Venn图,可以随窗口缩放。我可以访问圆圈的3个中心点以及其他重要交叉点的粗略近似值。这些其他点是近似的,因为它们依赖于sin和cos值来确保所有三个圆都是相同的大小并且是对称的。

At the moment, my code produces a triple Venn Diagram that scales with the window. I have access to the 3 center points of the circles as well as rough approximations of other important points of intersection. These other points are approximated because they rely on sin and cos values to make sure all three circles are the same size and symmetrical.

我模拟了下面的图像(点/字母在外部添加了油漆,但底层图像是我的应用程序现在生成的内容):

I mocked up the following image (the points/letters were added externally in paint but the underlying image is what my app produces now):

正如您所看到的,A和B的圆圈(以蓝色显示)不在标记处。

As you can see, the intersection of circles A and B (shown in blue) is off the mark.

为了生成这个,我的代码将底层画布缩放到窗口大小,计算放置圆心的位置,然后绘制具有相同半径的全部3。删除所有额外的绒毛,我的代码基本上是这样的:

To produce this, my code scales the underlying canvas to the window size, calculates where to place the centers of the circles, and then draws all 3 with the same radius. Cutting out all the extra fluff, my code essentially looks like this:

// Constructor creates 3 circles and adds to canvas
Circle a = new Circle();
canvas.getChildren().add(a);
// etc. for the other two circles

// And also makes a Shape object to hold the intersection
Shape ab = Shape.intersect(a,b); // initially empty
canvas.getChildren().add(ab);

稍后......

// Resizing the window calls an update function
// which recalculates the circles' centers and 
// radii and then updates them. Since circles are
// drawn from upper left corner, the relocate call 
// makes sure to subtract the radius to center it
a.setRadius(radius);
a.relocate(acx-radius,acy-radius);

交叉逻辑(也在更新函数中):

And the intersection logic (also in the update function):

canvas.getChildren().remove(ab);
ab = Shape.intersect(a,b);

// Can relocate to point c, but this doesn't do the job either (see below)
ab.relocate(pcx,pcy);

// Add the new intersection back to the canvas
canvas.getChildren().add(ab);

我尝试将生成的交叉点形状重新定位到C点,但我不是确定我对这一点的近似是否过于圆滑,因为它仍未正确对齐:

I've tried doing a relocate on the resulting intersection shape to point C, but I'm not sure if my approximation of that point is just rounded too much because it still isn't properly aligned:

我猜这个偏移可能与布局边界/视觉边界有关,或者在调整大小时被改变并且从未正确更新的东西,但我花了很长时间看在文档上并且无法弄明白。

I'm guessing this offset might have something to do with layout bounds / visual bounds or something that gets altered on a resize and never properly updated, but I spent a long term looking at the docs and couldn't figure it out.

理想情况下,我想避免手动计算C点,因为圈子本身是通过近似生成的/舍入,这使得C几乎不可能准确。我希望有人可以指出我只能使用原始圆圈的解决方案,但无论当前画布的大小如何,我都会采取任何使交叉点出现在正确位置的方法。

Ideally, I'd like to avoid having to calculate point C by hand since the circles themselves are generated through approximation / rounding and this makes C virtually impossible to get exact. I hope someone can point me to a solution that can use the original circles only, but I'll take anything that makes the intersection appear at the right location regardless of the size of the current canvas.

总结:如何使Shape.intersect返回的形状出现在它创建的两个形状的中心?谢谢您的时间。

In summary: how can I make the shape returned by Shape.intersect appear at the center of the two shapes it is created from? Thanks for your time.

推荐答案

我设法找出问题所在。我正在使用自动调整大小的画布对象,该对象受到我在StackOverflow上找到的这篇文章的启发。如果链接发生变化,我从那里借来的代码的关键位如下所示:

I managed to figure out the issue. I was working with an auto-resizing canvas object inspired by this post I found here on StackOverflow. In case that link ever changes, the key bit of code I borrowed from there looked like the following:

// Update function when the window is resized
@Override
protected void layoutChildren() {
    final double top = snappedTopInset();
    final double right = snappedRightInset();
    final double bottom = snappedBottomInset();
    final double left = snappedLeftInset();

    width = getWidth() - left - right;
    height = getHeight() - top - bottom;

    // Update the layout
    canvas.setLayoutX(left);
    canvas.setLayoutY(top);

    if (width != canvas.getWidth() || height != canvas.getHeight()) {
        // Resize
        canvas.setWidth(width);
        canvas.setHeight(height);

        // Determine center
        cx = width / 2;
        cy = height / 2;

        // Determine radius of circles
        radius = 0.25 * Math.min(width, height);

        // Clear and redraw circles
        clear();
        redraw();
    }
}

其中canvas是Canvas的私有实例对象,这整个函数都在一个名为CanvasPane的类中扩展了Pane。

where "canvas" was a private instance of a Canvas object, and this entire function was inside a class called CanvasPane that extended Pane.

我发现了什么
上面的代码有当你还有像Circles这样的对象添加到CanvasPane的children()时。我的redraw()方法只移动了圆的中心并调整了半径。 我从未更新.setLayoutX()和.setLayoutY()函数,就像我为实际圆圈的实际画布对象所做的那样。因此,调整CanvasPane的大小会不一致地更新布局信息,并且所有圆圈的底层布局位置都将不同步。

What I found out The code above has an issue when you also have objects like Circles added to the children() of the CanvasPane. My redraw() method only moved the circle's centers and adjusted the radii. I never updated the .setLayoutX() and .setLayoutY() functions like I did for the actual canvas object for the actual circles. So resizing the CanvasPane would update the layout information inconsistently and all the circles' underlying layout positions would be out of sync.

因此,此处的修复方法是更改​​Update布局部分如下:

So, the fix here is to change the Update layout section to the following:

// Update the layout
for (Node n : getChildren()) {
    n.setLayoutX(left);
    n.setLayoutY(top);
}

这会更新圆圈的布局位置以及添加到CanvasPane的任何其他对象(不仅仅是我原来的画布),使得到的交叉点实际上处于正确的位置。

This updates the layout positions of the circles and any other object added to the CanvasPane (not just the canvas as I had originally), making the resulting intersection piece actually in the right position.

事后来说,我绝对应该在原版中包含更多代码问题所以其他人可以帮忙。希望有一天某人会遇到与我相同的问题,并能够找到这个答案。

In hindsight, I definitely should have included more code in my original question so others could help out. Hopefully though someone someday will have the same issues as me and be able to find this answer.

这篇关于为什么Shape.intersect产生的形状出现在错误的位置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆