通過交互禁用圖形更新我有一個包含 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);
);
);
);提醒一下,我只在該圖形框腳本中添加了隨機法線,只是為了查看是否正在重新計算線條。 真正的問題是固定坐標。
額外的問題:有沒有辦法在圖錶框構建後添加線條? 我在示例中找不到它。 我推測它們可能不會隨著每次鼠標交互而更新,但無法對其進行測試。
圖形腳本回复:通過交互禁用圖形更新我認為問題在於框架框會在有變化時自動更新,所以最好在渲染之前進行所有更改。 此外,您也可以對操作進行矢量化以提高速度,而不是使用 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] )
)
)
);