三維流體模組API開發-以流體、箭頭展示
[info] 小提示:
程式碼連結:https://doc-3dgdp.colife.org.tw/samplecode/#src/testweb/fluid/
初始化三維流體模組
三維流體模組需使用WebGL2,注意圖台初始化時要在參數中設定 requestWebGL2: true
。
index.html
:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Military Demo</title>
<meta charset="utf-8" />
<!-- 引用 js -->
<script src="PGWeb3D.min.js"></script>
<!-- 引用 style -->
<link rel="stylesheet" type="text/css" href="PGWeb3D.css" />
</head>
<body>
<!-- 參數控制面板 -->
<div id="MyControl" style="position: absolute;z-index:1;">
<table style="background-color: black; color: white;">
<tr>
<td>Mode</td>
<td>
<table>
<tr>
<td><input type="checkbox" id="is3D" checked></td>
<td style="color: white;">3D</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>Shape</td>
<td id="shape">
<Input type="radio" name="shapeRadio" value="line" checked>Line</Input>
<Input type="radio" name="shapeRadio" value="arrow">Arrow</Input>
</td>
</tr>
<tr>
<td>Data</td>
<td>
<select id="changedata">
<option value="9">3D Water</option>
<option value="10">3D WaterSurface</option>
</select>
</td>
</tr>
<tr>
<td>MinSpeed</td>
<td><input type="number" id="minSpeed" style="width: 118px" step="0.1"></td>
</tr>
<tr>
<td>Speed Factor</td>
<td><input type="number" id="speedFactor" style="width: 118px"></td>
</tr>
<tr>
<td>Lift</td>
<td><input type="number" id="lift" style="width: 118px"></td>
</tr>
<tr>
<td>ArrowScale</td>
<td><input type="number" id="arrowScale" style="width: 118px"></td>
</tr>
</table>
</div>
<!-- 圖台初始化 -->
<div id="MyMap" style="width:100%;height:100%;position:absolute;top:0;left:0"></div>
<!-- 引用主要 js,邏輯會寫在這個檔案 -->
<script src="main.js"></script>
</body>
</html>
main.js
:
// 初始化圖台, 記得傳入 requestWebGL2: true 參數
var terrainview = new ov.TerrainView("MyMap", { requestWebGL2: true });
// 取得三維流體模組
var fluidModule = terrainview.getModule("fluid");
// 預先建立三維流體模組的參數物件
var fluidParam = {};
// 在使用其他圖層前必須要先讀入地形 其他圖層的新增都會在callback中
terrainview.openTerrain(
{
url: 'https://data-3dgdp.colife.org.tw/Sample_src/PGWebJS/13.0/oviewRP.ashx', // 或您自己的O'View MapServer服務
identifier: "範例地形圖",
callback: openCallback,
}
);
// 地形讀取完成後的callback
function openCallback(result) {
// 設定底圖
terrainview.setBaseLayer({
url: "BING_MAP",
identifier: "IMAGE"
});
// 建立三維流體
createFluid(9);
}
// 參數面板 INPUT 事件-3D檢查
document.getElementById("is3D").addEventListener("change", function (evt) {
if (document.getElementById("changedate").value < 9) {
fluidParam.is3D = evt.target.checked;
fluidModule.removeFluidData();
fluidModule.setFluidDataByParam(fluidParam);
}
});
// 參數面板 INPUT 事件-最小速度
document.getElementById("minSpeed").addEventListener("input", function (evt) {
let minSpeed = parseFloat(evt.target.value);
if (!isNaN(minSpeed)) {
fluidModule.setFluidDataByParam({ minSpeed });
}
});
// 參數面板 INPUT 事件-速度倍率
document
.getElementById("speedFactor")
.addEventListener("input", function (evt) {
let speedFactor = parseFloat(evt.target.value);
if (!isNaN(speedFactor)) {
fluidModule.speedFactor = speedFactor;
}
});
// 參數面板 INPUT 事件-垂直速度
document.getElementById("lift").addEventListener("input", function (evt) {
let lift = parseFloat(evt.target.value);
if (!isNaN(lift)) {
fluidModule.lift = lift;
}
});
// 參數面板 INPUT 事件-箭頭大小
document.getElementById("arrowScale").addEventListener("input", (evt) => {
let arrowScale = parseFloat(evt.target.value);
if (!isNaN(arrowScale)) {
fluidModule.arrowScale = arrowScale;
}
});
// 參數面板 INPUT 事件-切換資料
document
.getElementById("changedata")
.addEventListener("change", function (evt) {
var v = evt.target.value;
if (v < 9) updateWind(dictionary[v]);
else if (terrainview._TerrainEngine.Device.GetWebGLVersion() > 1) {
createFluid(v);
}
});
// 參數面板 INPUT 事件-切換形狀
document.getElementById("shape").addEventListener("change", () => {
let elements = document.getElementsByName("shapeRadio");
for (let element of elements) {
if (element.checked) {
switch (element.value) {
case "line":
fluidModule.mode = ov.FLUID_MODE.LINE;
break;
case "arrow":
fluidModule.mode = ov.FLUID_MODE.ARROW;
break;
}
}
}
});
// 建立三維流體
function createFluid(v) {
// 讀取三維流體資料
new CFileLoader(1).GetText(
v == 9
? "https://sample.pilotgaea.com.tw/demo/index/src/testweb/fluid_fluid/Water.csv"
: "https://sample.pilotgaea.com.tw/demo/index/src/testweb/fluid_fluid/Water_Surface.csv",
function (rtn) {
let lines = rtn
.split("\r\n")
.map(function (line) {
return line.split(",").map(function (l) {
return l.trim();
});
})
.filter(function (l) {
return !isNaN(parseFloat(l[0]));
});
let xs = lines.map(function (l) {
return parseFloat(l[0]);
});
let ys = lines.map(function (l) {
return parseFloat(l[1]);
});
let zs = lines.map(function (l) {
return parseFloat(l[2]);
});
let max = [xs[0], ys[0], zs[0]];
let min = [xs[0], ys[0], zs[0]];
xs.forEach(function (a) {
if (a > max[0]) max[0] = a;
else if (a < min[0]) min[0] = a;
});
ys.forEach(function (a) {
if (a > max[1]) max[1] = a;
else if (a < min[1]) min[1] = a;
});
zs.forEach(function (a) {
if (a > max[2]) max[2] = a;
else if (a < min[2]) min[2] = a;
});
let row = Math.ceil((max[0] - min[0]) * 3);
let col = Math.ceil((max[1] - min[1]) * 3);
let level = Math.ceil((max[2] - min[2]) * 3);
// 設定中心點
let center = new Geo3DPoint(120, 24.3, 3);
let centerWorldMap = new Geo3DPoint(center);
terrainview._TerrainEngine.MapToWorldMap_3DPointSelf(centerWorldMap);
let lt = new Geo3DPoint(min[0], max[1], 0).Plus(centerWorldMap);
let rt = new Geo3DPoint(max[0], max[1], 0).Plus(centerWorldMap);
let lb = new Geo3DPoint(min[0], min[1], 0).Plus(centerWorldMap);
let rb = new Geo3DPoint(max[0], min[1], 0).Plus(centerWorldMap);
terrainview._TerrainEngine.WorldMapToMap_3DPointSelf(lt);
terrainview._TerrainEngine.WorldMapToMap_3DPointSelf(rt);
terrainview._TerrainEngine.WorldMapToMap_3DPointSelf(lb);
terrainview._TerrainEngine.WorldMapToMap_3DPointSelf(rb);
let uData = new Array(row * col * level).fill(0);
let vData = new Array(row * col * level).fill(0);
let zData = new Array(row * col * level).fill(0);
// 資料預處理
for (let i = 0; i < lines.length; i++) {
let x = Math.min(
Math.round(((xs[i] - min[0]) / (max[0] - min[0])) * row),
row
);
let y = Math.min(
Math.round(((max[1] - ys[i]) / (max[1] - min[1])) * col),
col
);
let z = Math.min(
Math.round(((zs[i] - min[2]) / (max[2] - min[2])) * level),
level
);
let index = (z * col + y) * row + x;
uData[index] = parseFloat(lines[i][4]);
vData[index] = parseFloat(lines[i][5]);
zData[index] = parseFloat(lines[i][6]);
}
// 設定三維流體資料
fluidModule.setFluidDataByUVData({
uData,
vData,
zData,
width: row,
height: col,
depth: level,
lift: -1,
boundary: new GeoBoundary(
Math.min(lt.x, lb.x),
Math.min(lb.y, rb.y),
Math.max(rt.x, rb.x),
Math.max(lt.y, rt.y)
),
offset: [
min[0],
max[0] - min[0],
min[1],
max[1] - min[1],
min[2],
max[2] - min[2]
],
speedFactor: 50,
center
});
// 設定預設參數
fluidModule.arrowScale = 1;
// 取得預設參數
document.getElementById("speedFactor").value = fluidModule.speedFactor;
document.getElementById("minSpeed").value = fluidModule._module.MinSpeed;
document.getElementById("lift").value = fluidModule.lift;
document.getElementById("arrowScale").value = fluidModule.arrowScale;
// 定位到中心點
terrainview.gotoCamera(
new ov.Camera(
new GeoPoint(120.00038429381732, 24.300468756933427, 70),
new GeoPoint(0, 0, -1),
new GeoPoint(0, 1, 0)
),
false
);
}
);
}