三維流體模組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
      );
    }
  );
}
Copyright © NCHC 2022 Version:13.0 all right reserved,powered by Gitbook修訂時間: 2024-12-02 15:55:11