通过交互禁用图形更新我有一个包含列 ox、oy、dx 和 dy 的数据表。 出于演示目的,您可以假设所有列都是随机的,公式为:Random Normal(0, 10)。 真正的问题是具有坐标列表的网络。
我想在 (ox, oy) 和 (dx, dy) 之间画线,我可以使用 Graph Builder 或 Graph Box(下面的示例)来完成此操作。 但是,对于每次交互,JMP 都会重新绘制线条,这使我的可视化速度非常慢(数据表中有 >10000 行)。 我通过向图形脚本中的原点和目标坐标添加一个小的随机部分来测试这一点,一旦有任何交互(例如,使用 Grabber 工具并拖动画布、调整轴、调整图形大小、调整窗口大小),线路确实改变了。 有没有办法阻止 JMP 更新图形并重新运行脚本?
我在 Graph Builder(我更喜欢使用这个平台)或 Graph Box 中找不到方法。 我发现了
<< Graph Updating( Per Mouse Up );
消息,但它只有两个选项;据我所知,没有“不更新”选项。 另外,我认为该消息无论如何都不适用于 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);
);
);
);提醒一下,我只是在该图形框脚本中添加了随机法线,只是为了查看是否正在重新计算线条。 真正的问题有固定的坐标。
奖金问题:在构建图形框后是否有添加线条的方法? 我在示例中找不到它。 我推测它们可能不会随着每次鼠标交互而更新,但无法对其进行测试。
图形脚本回复:通过交互禁用图形更新这是一个非常有趣的想法。 不幸的是,有了 20K 点,路径必须通过移动和线条,图形更加挣扎,甚至更慢。
但我会记住这一点以备将来出现问题,因为我喜欢这样的想法,即从技术上讲这里只有一条路径并且图形代码中不需要循环。
回复:通过交互禁用图形更新我不知道我可以像在 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] )
)
)
);
回复:通过交互禁用图形更新恕我直言,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>
回复:通过交互禁用图形更新我认为问题在于框架框会在发生变化时自动更新,因此最好在渲染之前进行所有更改。 此外,您也可以矢量化操作以提高速度,而不是使用 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
(我没有你的数据表所以我无法测试它,但它应该仍然说明了方法。)