<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />故事,第 1 部分
下午早些時候,十月下旬的陽光與男孩和他的朋友們玩耍。這還不可怕。 萬聖節還有幾個小時。
(重新設計的 JMP 用戶社區即將到來!第 2 部分和第 3 部分將在那裡找到您! )
視頻和代碼
此視頻序列顯示了模擬退火,用於在球體周圍均勻放置 3200 個點。最初,這些點被放置在從北極到南極的雙螺旋中。我不是在嘗試雙螺旋;我希望有更多的初始傳播,但無論如何它都有效。顏色僅用於可視化。在初始點之後,退火過程開始。https://en.wikipedia.org/wiki/Annealing_(冶金)描述了一種物理退火過程,其中金屬被加熱以鬆弛結晶結構,使原子移動到不同的關係中。有些材料甚至可能在十月的溫暖陽光下退火。這裡的 JSL 已針對視頻進行了調整,並未針對其他任何內容進行優化……但已經足夠好了。在退火階段,加熱和冷卻的時間表控制著點距離最近的點的距離。因為有很多點在兩極擠在一起,所以時間表需要讓系統保持一段時間,以便這些點有時間遷移出去。在那個“高溫”下,這些點跳得足夠遠,以至於它們經常進入另一個點的附近太遠。時間表的逐漸冷卻階段讓積分穩定下來,移動越來越少。視頻在他們完全安頓下來之前就結束了。
https://www.youtube.com/watch?v=8-Fjw1wD-Oc

nnodes = 3200;
xx = -nnodes * 3 / 2;
nodelocs = J(nnodes, 3, 0); // 每個節點的 x,y,z 點
對於( i = 1, i <= nnodes, i++,
f = i / nnodes; // 0..1
z = Cos( f * Pi() ); // 從上到下
r = Sin( f * Pi() ); // 半徑
x = 罪(10000 * f)* r; // 10,000 弧度
y = Cos( 10000 * f ) * r; // 太多了。但它有效......
節點[i, 1] = x;
節點[i, 2] = y;
節點[i, 3] = z;
);
//nodeobj = 場景顯示列表(); nodeobj<
addnodes = Function( {thisnnodes},
{inode, delta, pos = [0 0 0], result = Scene Display List()},
For( inode = 1, inode <= thisnnodes, inode++,
delta = nodelocs[inode, 0] - pos;
pos = nodelocs[inode, 0];
//顯示(位置,增量);
結果 << 翻譯(增量);
rgb = Color To RGB(Heat Color(inode / nnodes, "spectral") ) * 1;
//顯示(inode/nnodes,rgb);
結果<<顏色(rgb [1],rgb [2],rgb [3]);
結果 << sphere(.005, 3, 3)//calllist(nodeobj);
;
);
結果<<翻譯(-pos); //恢復原始位置
result// 返回顯示列表
;
);
//a=addnodes();
// 將節點動畫成半徑為 1 的球體,大約為 0,0,0
調整 = 函數({d},
{inode,半徑,最近,dist,err,pos,newlocs = J(nnodes,3,.),table = KDTable(nodelocs)},
對於(inode = 1,inode <= nnodes,inode++,
pos = nodelocs[inode, 0];
// 輕推離最近的鄰居
表 << 刪除行(索引節點);
{closest, dist} = table << knearestrows(5, pos);
表<<插入行(inode);
對於(iclose = 1,iclose <= 5,iclose++,
err = pos - nodelocs[closest[iclose], 0] + J( 1, 3, Random Normal( 0, .01 ) ); // [dx dy dz]
//pos = pos + .00991/ 錯誤; // 移開
對於(idim = 1,idim <= 3,idim++,
如果(錯誤[idim] < 0,
pos[idim] -= d / iclose,
pos[idim] += d / iclose
)
);
);
// 向 1.000 微移半徑
半徑 = Sqrt( Sum( pos
位置 ) );
//err = 1.0 - 半徑; // 如果半徑太小,則 err 為正
位置 = 位置 / 半徑; // 大錯誤移動得更快
newlocs[inode, 0] = 位置; // 臨時拷貝
);
nodelocs = newlocs; // 將溫度複製到實際
0 // 虛擬返回值
;
);
角度 = 30;
場景 = 場景框(1924 / 2, 1084 / 2);
構建 = 函數({thisnnodes},
{},
場景<<清晰;
scene << ShowArcBall( never/*always*/ /*During Drag*/ );
場景 << 背景顏色(黑色);
場景 << 透視圖(65, .1, 5);
場景<<翻譯(0.0,0.0,-2.0);
角度 += .1;
場景 << 旋轉(角度 * 0.23, 1, 0, 0);
場景 << 旋轉(角度 * 0.11, 0, 1, 0);
場景 << 旋轉(角度 * 2、0、0、1);
object = addnodes(thisnnodes);
場景<< ArcBall(對象,1);
);
構建(1);
新窗口(“點世界”,場景);
對於( i = 1, i <= 3200, i += 4,
構建(我);
場景<<更新;
等待(0);
// 場景<
);
For( i = 1, i < 5000, i++, // 幾乎在 1000 處完成
vint = 插值(i, 1, .00001, 100, .0005, 200, .001, 4000, .0005, 5000, .00001);
顯示(我,vint);
構建(3200);
場景<<更新;
等待(0);
調整(文特);
//場景<
);
建造();
場景<<更新;
等待(0);