为什么 Shape.intersect 生成的形状出现在错误的位置?
Why does the resulting shape from Shape.intersect appear at an incorrect position?
对于我当前的一个 javafx 项目,我正在使用维恩图。我想利用 Shape.intersect 来减轻我必须亲自完成的数学计算量(并避免使用 Path 对象)。 Shape.intersect 产生了一个完美的形状,但它被平移/移动了一点,我不知道要放回去多少。理想情况下,我希望交叉区域恰好出现在两个原始形状相交的位置 - 即新交叉点将与原始形状无缝贴合。
目前,我的代码生成了一个与 window 成比例的三重维恩图。我可以访问圆的 3 个中心点以及其他重要交点的粗略近似值。这些其他点是近似值,因为它们依赖 sin 和 cos 值来确保所有三个圆的大小相同且对称。
我模拟了下图(points/letters 是在画图外部添加的,但底层图像是我的应用程序现在生成的):
如您所见,圆 A 和圆 B 的交点(以蓝色显示)偏离了标记。
为此,我的代码将基础 canvas 缩放到 window 大小,计算放置圆心的位置,然后绘制所有 3 个具有相同半径的圆心。去掉所有多余的绒毛,我的代码基本上是这样的:
// 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);
和交集逻辑(也在更新函数中):
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,但我不确定我对该点的近似值是否四舍五入太多,因为它仍然没有正确对齐:
我猜这个偏移量可能与布局边界/视觉边界或在调整大小时发生变化并且从未正确更新的东西有关,但我花了很长时间查看文档并且无法理解出来了。
理想情况下,我想避免手动计算 C 点,因为圆本身是通过近似/舍入生成的,这使得 C 点几乎不可能精确。我希望有人能给我指出一个只能使用原始圆圈的解决方案,但我会采取任何使交叉点出现在正确位置的方法,而不管当前 canvas.
的大小
总结:如何使 Shape.intersect 返回的形状出现在创建它的两个形状的中心?感谢您的宝贵时间。
我设法弄清楚了这个问题。我正在使用一个 auto-resizing canvas 对象,其灵感来自于我在 Whosebug 上找到的 。以防 link 发生变化,我从那里借用的关键代码如下所示:
// 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 的 class 中,它扩展了 Pane。
我发现了什么
当您还将像 Circles 这样的对象添加到 Canvas 窗格的 children() 时,上面的代码会出现问题。我的 redraw() 方法只移动了圆心并调整了半径。 我从未更新过 .setLayoutX() 和 .setLayoutY() 函数,就像我为实际圆圈的实际 canvas 对象所做的那样。因此,调整 Canvas 窗格的大小会不一致地更新布局信息,并且所有圆圈的底层布局位置将不同步。
因此,此处的解决方法是将“更新布局”部分更改为以下内容:
// Update the layout
for (Node n : getChildren()) {
n.setLayoutX(left);
n.setLayoutY(top);
}
这会更新圆圈的布局位置以及添加到 Canvas 窗格的任何其他对象(不仅仅是我原来的 canvas),使生成的交叉部分实际上在右侧位置。
事后看来,我绝对应该在我原来的问题中包含更多代码,以便其他人可以提供帮助。希望有一天有人会遇到与我相同的问题并能够找到这个答案。
对于我当前的一个 javafx 项目,我正在使用维恩图。我想利用 Shape.intersect 来减轻我必须亲自完成的数学计算量(并避免使用 Path 对象)。 Shape.intersect 产生了一个完美的形状,但它被平移/移动了一点,我不知道要放回去多少。理想情况下,我希望交叉区域恰好出现在两个原始形状相交的位置 - 即新交叉点将与原始形状无缝贴合。
目前,我的代码生成了一个与 window 成比例的三重维恩图。我可以访问圆的 3 个中心点以及其他重要交点的粗略近似值。这些其他点是近似值,因为它们依赖 sin 和 cos 值来确保所有三个圆的大小相同且对称。
我模拟了下图(points/letters 是在画图外部添加的,但底层图像是我的应用程序现在生成的):
如您所见,圆 A 和圆 B 的交点(以蓝色显示)偏离了标记。
为此,我的代码将基础 canvas 缩放到 window 大小,计算放置圆心的位置,然后绘制所有 3 个具有相同半径的圆心。去掉所有多余的绒毛,我的代码基本上是这样的:
// 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);
和交集逻辑(也在更新函数中):
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,但我不确定我对该点的近似值是否四舍五入太多,因为它仍然没有正确对齐:
我猜这个偏移量可能与布局边界/视觉边界或在调整大小时发生变化并且从未正确更新的东西有关,但我花了很长时间查看文档并且无法理解出来了。
理想情况下,我想避免手动计算 C 点,因为圆本身是通过近似/舍入生成的,这使得 C 点几乎不可能精确。我希望有人能给我指出一个只能使用原始圆圈的解决方案,但我会采取任何使交叉点出现在正确位置的方法,而不管当前 canvas.
的大小总结:如何使 Shape.intersect 返回的形状出现在创建它的两个形状的中心?感谢您的宝贵时间。
我设法弄清楚了这个问题。我正在使用一个 auto-resizing canvas 对象,其灵感来自于我在 Whosebug 上找到的
// 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 的 class 中,它扩展了 Pane。
我发现了什么 当您还将像 Circles 这样的对象添加到 Canvas 窗格的 children() 时,上面的代码会出现问题。我的 redraw() 方法只移动了圆心并调整了半径。 我从未更新过 .setLayoutX() 和 .setLayoutY() 函数,就像我为实际圆圈的实际 canvas 对象所做的那样。因此,调整 Canvas 窗格的大小会不一致地更新布局信息,并且所有圆圈的底层布局位置将不同步。
因此,此处的解决方法是将“更新布局”部分更改为以下内容:
// Update the layout
for (Node n : getChildren()) {
n.setLayoutX(left);
n.setLayoutY(top);
}
这会更新圆圈的布局位置以及添加到 Canvas 窗格的任何其他对象(不仅仅是我原来的 canvas),使生成的交叉部分实际上在右侧位置。
事后看来,我绝对应该在我原来的问题中包含更多代码,以便其他人可以提供帮助。希望有一天有人会遇到与我相同的问题并能够找到这个答案。