Re: [問題] 有關疊加圖的問題
※ 引述《huangcooly (弱小豪)》之銘言:
: 哇哇~多謝L大你的解釋
: 不過你上面所提供的做法
: 小弟我也嘗試過
: 不過做法大概是這樣
: Do[
: a^i=Plot[t,{t,i,i+1}];
: AppendTo[g,a^i];
: ,{i,0,n}]
: Show[g];
: 這樣的做法大概也與你的類似
: 將圖集中在g裡面
: 最後再一起show出來
: 可是當我的g裡面有很多圖的時候
: 似乎會相當讓耗費記憶體空間
: 例如當我n取到一萬時
: 我的g裡面就會出現一萬張圖
: 我改用累加圖的做法時
: 似乎不太會耗用我記憶體
: 所以我才會改此做法
: 會用此方法小弟曾做個小嘗試
: t = {};
: a = Plot[t, {t, 0, 1}];
: b = Plot[t, {t, 1, 2}];
: AppendTo[t, a];
: AppendTo[t, b];
: 此時去跑t
: 應該會跑出a,b兩張圖
: g = Show[t, PlotRange -> All]
: 接下來去跑g
: 應該會跑出一張a,b圖合起來的樣子
: 再來再跑
: t={};
: 此時t裡面應該空了
: 此時再去跑一次g
: 卻仍然可跑出a,b所合起來的圖
: 因此若g仍為Show[t,PlotRange -> All]的話
: 應該會畫不出圖來
: 所以我認為g是儲存一個圖檔下來
: 但是這樣似乎不會產生L大所說的Show太多次的問題
: 所以我也搞不懂哪裡怪怪的= =
OK, 我用 Short 和 [[ ]] 去查過它的內部結構了
上篇文的結構敘述雖然是錯的但是重點大概有到
詳細說明是這樣子的:
首先, 在我用的六版上 Plot 產生的圖內部是這個樣子的:
這些是 Plot 所產生用來畫出這個 Plot 的 primitive
│
┌──────────┴──────────┐
Graphics[{{{},{},{Hue[0.67,0.6,0.6],Line[{<<..>>}]}}},<<其他選項>>]
↑
這個是 Plot 預設的那個藍線顏色
雖然我不清楚是什麼時候會在前面那些 list 裡放東西
但它的內部的確是這種樣子的
然後 當 Show 吃許多個圖進來時
它只會單純的把所有 Graphics 裡的 primitive 用個 List 包起來
再生成一個新的 Graphics
那麼你的寫法
第一圈時 g = {Graphics[<<P#1>>,...],{}}
這裡我用 <<P#1>> 代寫第一圈的 Plot 所產生的 primitive 以下 <<P#2>> 等類推
所以 a1 = Graphics[{<<P#1>>},...]
第二圈時 g = {Graphics[<<P#2>>,...],Graphics[{<<P#1>>},...]}
所以 a1 = Graphics[{<<P#2>>,{<<P#1>>}},...]
第三圈時 g = {Graphics[<<P#3>>,...],Graphics[{<<P#2>>,{<<P#1>>}},...]}
所以 a1 = Graphics[{<<P#3>>,{<<P#2>>,{<<P#1>>}}},...]
注意到了嗎 因為 Show 每次都會多包一層的關係
所以最後堆起來的那個 a1 裡 你跑幾圈 <<P#1>> 就會被包到第幾層深
深到超過 $RecursionLimit 之後
這時還不會有事 因為 List 包起來時不會去運算內層的 List
然後 Graphics 因為還沒顯示一樣沒事
最後你叫它顯示出來 它才去當中一層一層呼叫來畫
這時就會呼叫到超過層數 就出現「呼叫層數超過 $RecursionLimit」的訊息
上面這個行為其實不需要用到你這個例子就可以證實了:
故意製造一個 4100 層深的 List 包著一個 primitive
┌───────┴────────┐
直接輸入 Graphics[Nest[List,Line[{{0,0},{1,1}}],4100]];
加了分號只把結果存起來 於是不會有錯誤訊息出現
緊接著再輸入 Show[%] 或直接 % 叫出來畫就會發現它跳錯誤訊息出來了
也就是說我先前的文章雖然弄錯結構
但每一次 Show 就包一層的事實卻是正確的
(想想也是, 不然它要怎麼簡單的合併圖案呢 XD)
(其實我在 PO 上一篇文章時就已經有去查那個 a1 的結構了
只是沒有仔細看過它到底是怎麼回事就 PO 文了....XD)
這個問題如果要從你那裡修改的話 目前我只有想到這一個解法:
如上所說所有事情要到 a1 叫出來畫時才會出事
那我們只要想辦法在畫它之前把它解決掉就好了
把很深的 List 給攤平相信你也知道是用 Flatten
那麼我們只要在畫圖前加入這一行:
a1[[1]] = Flatten[a1[[1]]];
這樣就把 a1 這張圖的 primitive 區的那深得可以的 List 給攤開
這樣再畫時就不會有錯誤訊息了
話說回來 說到你提到的記憶體用量問題
看到 Show 這樣的行為其實你應該也會了解到一件事
其實 Show 只是單純的把兩張圖的資訊合起來而已
即使到最後每張圖在總圖中的份量少之又少
當初所畫出來的東西還是不會丟掉
因此即使像是你這樣的寫法 最後所使用的記憶體量還是那麼多張 Plot 的資料量
那還不如就直接把它一個一個收集起來再一次 Show 出來
記憶體使用量還是那麼多 但卻避免掉了這個問題
那如果要真正減少資料量的話就只能從 Plot 下手了
Plot 有一個參數叫做 PlotPoints 它指定了一開始的 sample 點數
還有另一個參數是 MaxRecursion 它指定為了畫得平順可以遞迴多取點多少層
可以比較一下這些 Plot 指令所畫出來的 primitive 點數:
Plot[t,{t,0,1},PlotPoints->50] [[1]] // Short
{{{},{},{Hue[0.67,0.6,0.6],Line[{<<78>>}]}}}
Plot[t,{t,0,1},PlotPoints->30] [[1]] // Short
{{{},{},{Hue[0.67,0.6,0.6],Line[{<<48>>}]}}}
Plot[t,{t,0,1},PlotPoints->10] [[1]] // Short
{{{},{},{Hue[0.67,0.6,0.6],Line[{<<38>>}]}}}
Plot[t,{t,0,1},PlotPoints->40,MaxRecursion->5] [[1]] // Short
{{{},{},{Hue[0.67,0.6,0.6],Line[{<<61>>}]}}}
Plot[t,{t,0,1},PlotPoints->40,MaxRecursion->2] [[1]] // Short
{{{},{},{Hue[0.67,0.6,0.6],Line[{<<46>>}]}}}
Plot[t,{t,0,1},PlotPoints->40,MaxRecursion->0] [[1]] // Short
{{{},{},{Hue[0.67,0.6,0.6],Line[{<<41>>}]}}}
這就能有效的減少你的資料量了
那就看你的圖需要畫到多精細 適當的減少這兩個參數就行了
(其實主要火力放在 PlotPoints 就行了, MaxRecursion 影響稍微小一點
不過 PlotPoints 減少到一定程度後 MaxRecursion 的影響會慢慢變大)
而且減少這些資料量在最後畫圖時也會快一點
(78 個點連線 * 4000 張圖 和 38 個點連線 * 4000 張圖 哪個快相信很明顯)
--
◢ ˊ_▂▃▄▂_ˋ. ◣ ▅▅ ▅▅ ι●╮ █▄▄▄▄▄
▍./◤_▂▃▄▂_◥ \'▊ HARUHI █████ <■┘ ▄▄▄▄▄▄▄
▎⊿ ◤◤◥█◥◥█Δ ISM By-gamejye ¢|\ ▌▌▌▌▌▄▌▌
▏ζ(▏●‵◥′●▊)Ψ ▏ █ ⊿Δ ▄▄▄ ▄▄▄▄
█/|▊ 〃 、 〃▋ |\ ▎ ハルヒ主義 █▄▄▄█▄▄
◥◥|◣ ‵′ ◢/'◢◢S.O.S 世界を大いに盛り上げるための涼宮ハルヒの団
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.112.28.91
推
12/23 23:25, , 1F
12/23 23:25, 1F
→
12/23 23:27, , 2F
12/23 23:27, 2F
→
12/23 23:29, , 3F
12/23 23:29, 3F
→
12/23 23:30, , 4F
12/23 23:30, 4F
討論串 (同標題文章)