通过交互禁用图形更新我有一个包含 ox、oy、dx 和 dy 列的数据表。 出于演示目的,您可以假设所有列都是随机的,公式为:Random Normal(0, 10)。 真正的问题是具有坐标列表的网络。
我想在 (ox, oy) 和 (dx, dy) 之间画线,我可以使用 Graph Builder 或 Graph Box 来做到这一点(下面的示例)。 但是,每次交互时,JMP 都会重新绘制线条,这使我的可视化速度非常慢(我在数据表中有 >10 000 行)。 我通过在图形脚本中的原点和目标坐标中添加一个小的随机部分来测试这一点,并且只要有任何交互(例如,使用 Grabber 工具并拖动画布、调整轴、调整图形大小、调整窗口大小),线条确实发生了变化。 有没有办法停止 JMP 更新图表并重新运行脚本?
我在 Graph Builder(我更喜欢使用这个平台)或 Graph Box 中找不到方法。 我找到了
<< Graph Updating( Per Mouse Up );
消息,但它只有两个选项;据我所知,没有“不更新”选项。 另外,我认为该消息无论如何都不适用于 Graph Box。
这是一个最小的 Graph Box 示例,它可以绘制线条,但线条会随着每次交互而更新:
New Window( "Example",
Graph Box(
Frame Size( 300, 300 ),
Pen Color( "Blue" );
o_x = :ox << Get Values();
o_y = :oy << Get Values();
d_x = :dx << Get Values();
d_y = :dy << Get Values();
For( i=1, i<=N Items(o_x), i++,
origin = Eval List({o_x[i]*Random Normal( 1, 0.1 ), o_y[i]*Random Normal( 1, 0.1 )});
destination = Eval List({d_x[i]*Random Normal( 1, 0.1 ), d_y[i]*Random Normal( 1, 0.1 )});
Line(origin, destination);
);
);
);提醒一下,我只在该 Graph Box 脚本中添加了随机法线,只是为了查看是否正在重新计算线条。 真正的问题是固定坐标。
额外的问题:有没有办法在图表框构建后添加线条? 我在示例中找不到它。 我推测它们可能不会随着每次鼠标交互而更新,但无法对其进行测试。
图形脚本回复:通过交互禁用图形更新我认为问题在于框架框会在有变化时自动更新,所以最好在渲染之前进行所有更改。 此外,您也可以对操作进行矢量化以提高速度,而不是使用 For() 函数显式迭代。 图形段也提供了一些优势,但目前它们的文档记录很差。
请参阅此方法:
Names Default to Here( 1 );
// origin
o_x = :ox << Get As Matrix;
o_y = :oy << Get As Matrix;
// destination
d_x = :dx << Get As Matrix;
d_y = :dy << Get As Matrix;
n = N Items( o_x );
// vectorize for line segments
seg = (o_x :*</img> J( n, 1, Random Normal( 1, 0.1 ))) || (o_y f:* J( n, 1, Random Normal( 1, 0.1 ))) ||
(d_x :*</img> J( n, 1, Random Normal( 1, 0.1 ))) || (d_y f:* J( n, 1, Random Normal( 1, 0.1 )));
// plot segments
New Window( "Example",
gb = Graph Box(
Frame Size( 300, 300 ),
Pen Color( "Blue" );
Line Seg( seg );
)
);
// later, update seg, then send gb << Reshow message to graph box
(我没有您的数据表,因此无法对其进行测试,但它仍应说明该方法。)
回复:通过交互禁用图形更新恕我直言,JMP 真的非常_非常_需要更新此功能。我多次遇到这个问题,很简单,没有有效的解决方法。JMP 仅应在发生某些变化(例如图形大小)时重新运行图形脚本,而不仅仅是在滚动/更改窗口大小时。
话虽如此,我发现执行此类操作的最快方法如下所示。我创建了一个 SVG 路径(根据我的经验,这是在 JMP 中渲染复杂路径的最快方法)并有一个哨兵来确定是否重建路径。我已经包含了一个按钮来强制重建路径,只是作为一个例子。
希望这会有所帮助,但更好的是 JMP 开发人员提供的系统与所有其他显示管理器系统(包括多线程、信号/插槽、回调等)一样。
我也尝试过使用这种方法来获取所需渲染的图像,检查图形框的大小,如果大小没有改变,则使用保存的图像作为要显示的东西。这就是 JMP 应该做的事情,而且永远不应该被设置为在每一个可能的机会中积极地执行图形脚本。但是,我对这种方法不太满意,因为 JMP 没有提供必要的工具来使其正常工作
self = New Namespace();
self:table = Current Data Table();
self:redraw = 1;
self:path = "";
self:build path = Function( {},
{Default Local},
self:path = "";
For Each Row( self:table,
self:path ||= Eval Insert( "\[M^:ox * Random Normal( 1, 0.1 )^,^oy * Random Normal( 1, 0.1)^ L^dx * Random Normal( 1, 0.1 )^,^:dy * Random Normal( 1, 0.1 )^]\" )
);
);
Eval( Eval Expr(
New Window( "Example",
<<ON close=""></ON>
回复:通过交互禁用图形更新我不知道我可以在 JSL 中进行这样的矢量化。 所以谢谢你教我这个方法!
一旦我将随机性计算移出图形框,数字就不会更新,但这是一种误导。 我只是把随机性放进去让自己相信 JMP 正在重绘图表。 因此,虽然这种方法有效,但它并没有完全达到我想要做的效果。 一旦我将随机性计算拉到图表框中,所有的线都在移动。 但我确实在此过程中学到了一些东西。 谢谢!
此外,我仍然不得不循环绘制线条,因为我的线条不应该是连接的路径。 所以,我不能只创建一对 x 和 y 矩阵并将它们传递给 Line 或 Line Seg。
我使用您的代码使其与我的数据表一起使用,如下所示。 如果其他人需要此解决方案,我会将表格附加到此消息中。
Names Default To Here( 1 );
// origin
o_x = :ox << Get As Matrix;
o_y = :oy << Get As Matrix;
// destination
d_x = :dx << Get As Matrix;
d_y = :dy << Get As Matrix;
n = N Items( o_x );
// plot segments
New Window( "Example",
gb = Graph Box(
Frame Size( 300, 300 ),
Pen Color( "Blue" );
seg_x = (o_x :*</img> J( n, 1, Random Normal( 1, 0.1 ) )) || (d_x :*</img> J( n, 1, Random Normal( 1, 0.1 ) ));
seg_y = (o_y :*</img> J( n, 1, Random Normal( 1, 0.1 ) )) || (d_y :*</img> J( n, 1, Random Normal( 1, 0.1 ) ));
For( i=1, i<=n, i++,
Line( seg_x[i, -1], seg_y[i, -1] )
)
)
);