軍事模組API開發
[info] 小提示:
程式碼連結:https://doc-3dgdp.colife.org.tw/samplecode/#src/testweb/military_2525b/
初始化軍事模組
軍事模組需要額外引入PGWeb3DMilitary.min.js,並使用terrainview.getModule取得軍事模組。
下面的範例可以用來建立一個附帶參數設定面板的軍事模組圖台
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>
<script src="PGWeb3DMilitary.min.js"></script>
<!-- 引用 style -->
<link rel="stylesheet" type="text/css" href="PGWeb3D.css" />
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<!-- 圖台初始化 -->
<div id="MyMap">
<!-- 數量控制面板 -->
<div id="MyControl">
<select id="totalnumber" onchange="insert2525b()">
<option value="0">----</option>
<option value="100" selected="selected">100</option>
<option value="200">200</option>
<option value="500">500</option>
<option value="1000">1000</option>
<option value="2000">2000</option>
<option value="5000">5000</option>
</select>
<span id="FpsSpan"></span>
</div>
<!-- 自訂參數面板 -->
<div style="position: absolute; z-index: 1; top: 30px; left: 0;">
<details class="ov-widget-details" style="width: 270px;">
<summary class="ov-widget-summary ov-widget-unselectable">
<div class="ov-widget-summary-title">自訂</div>
</summary>
<div class="ov-widget-scrollBar">
<table>
<tr>
<td>中心點位置</td>
<td>
<div class="degree">
<input type="number" id="lng" step="0.01" value="121.23" />
</div>
<div class="degree">
<input type="number" id="lat" step="0.01" value="23.42" />
</div>
<div class="meter">
<input type="number" id="height" value="3000.0" />
</div>
</td>
</tr>
<tr>
<td>
<div>
<span>編碼</span><span class="SIDCHint" onclick="toggleSIDCHint()">❔</span>
</div>
</td>
<td>
<div class="megahertz">
<input type="text" id="code" value="sfgpewrh--mt" />
</div>
</td>
</tr>
<tr>
<td>尺寸</td>
<td>
<div class="dBW">
<input type="number" id="size" value="64.0" />
</div>
</td>
</tr>
<tr>
<td>時間</td>
<td>
<div class="megahertz">
<input type="text" id="dtg" value="30140000ZSEP97" />
</div>
</td>
</tr>
<tr>
<td>位置</td>
<td>
<div class="megahertz">
<input type="text" id="location" value="0900000.0E570306.0N" />
</div>
</td>
</tr>
<tr>
<td>移動方向</td>
<td>
<div class="megahertz">
<input type="number" id="direction" value="45" />
</div>
</td>
</tr>
<tr>
<td>種類</td>
<td>
<div class="megahertz">
<input type="text" id="type" value="MACHINE GUN" />
</div>
</td>
</tr>
<tr>
<td>數量</td>
<td>
<div class="megahertz">
<input type="number" id="quantity" value="200" />
</div>
</td>
</tr>
<tr>
<td>人員說明</td>
<td>
<div class="megahertz">
<input type="text" id="staffComments" value="FOR REINFORCEMENTS" />
</div>
</td>
</tr>
<tr>
<td>追加資訊</td>
<td>
<div class="megahertz">
<input type="text" id="additionalInformation" value="ADDED SUPPORT FOR JJ" />
</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="megahertz">
<input type="button" id="cbMoveToClick" value="移動到滑鼠點擊座標" onclick="clickToMove()" />
</div>
</td>
</tr>
</table>
<!-- 資訊提示面板 -->
<div id="SIDC_HINT_PANEL" draggable="true">
<table>
<span class="panelCloseButton" onclick="toggleSIDCHint()">✖</span>
<caption>
提供 2525C-Coding Scheme:WARFIGHTING
的基本符號表供參考,需要進一步符號定義請參閱
<a href="https://quicksearch.dla.mil/qsDocDetails.aspx?ident_number=114934" target="_blank">MIL-STD-2525
Spec</a>
</caption>
<tr>
<th>Coding Scheme<br />(字母1)</th>
<th>
AFFILIATION / EXERCISE <br />AMPLIFYING DESCRIPTOR<br />(字母2)
</th>
<th>BATTLE DIMENSION<br />(字母3)</th>
<th>STATUS<br />(字母4)</th>
</tr>
<tr>
<td>S - WARFIGHTING</td>
<td>
P - PENDING<br />
U - UNKNOWN<br />
A - ASSUME FRIEND<br />
F - FRIEND<br />
N - NEUTRAL<br />
S - SUSPECT<br />
H - HOSTILE
</td>
<td>
P - SPACE<br />
A - AIR<br />
G - GROUND<br />
S - SEA SURFACE<br />
U - SEA SUBSURFACE<br />
</td>
<td>
A - ANTICIPATED/PLANNED<br />
P - PRESENT
</td>
</tr>
<tr>
<th>FUNCTION ID<br />(字母5~10)</th>
<th>SYMBOL MODIFIER<br />(字母11~12)</th>
<th>COUNTRY CODE<br />(字母13~14)</th>
<th>ORDER OF BATTLE<br />(字母15)</th>
</tr>
<tr>
<td>詳請參見 2525C SPEC A-III</td>
<td>詳請參見 2525C SPEC A-III</td>
<td>詳請參見 FIPS Pub 10 系列</td>
<td>
A - AIR OB<br />
E - ELECTRONIC OB<br />
C - CIVILIAN OB<br />
G - GROUND OB<br />
N - MARITIME OB<br />
S - STRATEGIC FORCE RELATED
</td>
</tr>
</table>
</div>
</div>
</details>
</div>
</div>
<!-- 引用主要 js,邏輯會寫在這個檔案 -->
<script src="main.js"></script>
</body>
</html>
main.js
:
// 初始化圖台
var terrainview = new ov.TerrainView("MyMap");
// 載入軍事模組,需要PGWeb3DMilitary.min.js
var militaryModule = terrainview.getModule("military");
// 軍事符號單元集合
var military2525BEntitys = [];
// 自訂符號單元
var customEntity = null;
// 記錄上次更新時間, 用來計算移動距離模擬符號移動
var lastTime = 0;
// 2525B符號代碼集合 (此範例提供 50 個不同的符號代碼, 需要更多符號代碼請參考MIL-STD-2525B)
var Code2525BCollection = [
"SFAPM-----*****", "SHAPM-----*****", "SFAPMFF---*****", "SHAPMFF---*****", "SFAPMFFI--*****", "SUAP------*****", "SFAPMF----*****", "IFAPSCO-----***", "IHAPSCO-----***", "IFAPSRE-----***",
"IHAPSRE-----***", "IUSPSCP-----***", "IUSPSRU-----***", "IFGPSCP-----***", "IHGPSCP-----***", "IFGPSRE-----***", "IHGPSRE-----***", "SUSP------*****", "SUSPCLBB--*****", "SUSPXM----*****",
"SHSPXM----*****", "SFSPXM----*****", "SNSPXM----*****", "SUSPXF----*****", "SHSPXF----*****", "SHSPXF----*****", "SFSPXF----*****", "SFSPXF----*****", "SFSPXF----*****", "SFSPXF----*****",
"SFSPXF----*****", "SFSPXF----*****", "SUUP------*****", "SHUP------*****", "SFUP------*****", "SNUP------*****", "SUAPMFF---*****", "SNAPMFF---*****", "SUAPC-----*****", "SHAPC-----*****",
"SFAPC-----*****", "SNAPC-----*****", "IFSPSCP-----***", "IHSPSCP-----***", "IFSPSRE-----***", "IHSPSRE-----***", "SFSPG-------***", "SHSPG-------***", "SHAPMF----*****", "SFUPWT------***"
];
// 自訂符號-點擊移動模式
var isDragging;
var isMoveToClickMode = false;
// 在使用其他圖層前必須要先讀入地形 其他圖層的新增都會在callback中
terrainview.openTerrain({
url: "http://127.0.0.1:8080",
identifier: "範例地形圖",
callback: openCallback,
urlTemplate: "https://sample.pilotgaea.com.tw/Oview.aspx?{URL}"
});
// 地形讀取完成後的callback
function openCallback(result) {
// 設定底圖
terrainview.setBaseLayer({
url: "BING_MAP",
identifier: "VECTOR",
urlTemplate: "https://sample.pilotgaea.com.tw/Oview.aspx?{URL}"
});
// 設定初始位置
let initialPos = new GeoPoint(121.2347878442796, 23.427553934089445, 900000);
let initialV = new Geo3DPoint(0, 0, -1);
let initialUp = new Geo3DPoint(0, 1, 0);
let initialCamera = new ov.Camera(initialPos, initialV, initialUp);
terrainview.gotoCamera(initialCamera, false);
// 設定滑鼠點擊事件(自訂符號-點擊移動模式)
document.querySelector("#MyMap canvas").addEventListener("mousedown", () => {
isMoveToClickMode && (isDragging = false);
});
document.querySelector("#MyMap canvas").addEventListener("mousemove", () => {
isMoveToClickMode && (isDragging = true);
});
document.querySelector("#MyMap canvas").addEventListener("mouseup", () => {
isMoveToClickMode && setCustomEntityGeo();
});
// 插入軍事符號
insert2525b();
// 更新畫面
updateScreen();
// 設定自訂參數面板的的input事件
var allInput = document.getElementsByTagName("input");
for (var i = 0; i < allInput.length; i++) {
allInput[i].addEventListener("input", updateCustomEntity);
}
// 更新自訂符號
updateCustomEntity();
}
// 更新自訂符號
function updateCustomEntity() {
// 取得自訂符號參數
var lat = Number(document.getElementById("lat").value);
var lng = Number(document.getElementById("lng").value);
var height = Number(document.getElementById("height").value);
var code = document.getElementById("code").value;
var size = Number(document.getElementById("size").value);
var dtg = document.getElementById("dtg").value;
var location = document.getElementById("location").value;
var direction = document.getElementById("direction").value;
var type = document.getElementById("type").value;
var quantity = document.getElementById("quantity").value;
var staffComments = document.getElementById("staffComments").value;
var additionalInformation = document.getElementById("additionalInformation")
.value;
// 建立自訂符號參數物件
var parameter = {
code,
geo: new GeoPoint(lng, lat, height),
size,
extra: {
dtg,
location,
direction,
type,
quantity,
staffComments,
additionalInformation
}
};
// 如果已經有自訂符號就更新, 沒有就新增
if (customEntity) {
customEntity.update(parameter);
} else {
customEntity = militaryModule.add2525BEntity(parameter);
}
}
// 更新軍事符號
function update2525B(time) {
// 檢查時間參數
if (time === undefined) time = 0;
// 計算時間差
let delta = time - lastTime;
// 更新軍事符號位置
for (var i = 0; i < military2525BEntitys.length; i++) {
var course = military2525BEntitys[i].course;
var speed = military2525BEntitys[i].speed;
var geo = military2525BEntitys[i].geo;
var updateFlag = military2525BEntitys[i].updateFlag++;
var code = undefined;
geo.x += Math.sin(course * Math.PI * 2) * speed * delta * 0.001;
geo.y += Math.cos(course * Math.PI * 2) * speed * delta * 0.001;
if (updateFlag % 60 === 0) {
military2525BEntitys[i].course += Math.random() - 0.5;
}
if (updateFlag % 20 === 0) {
code = Code2525BCollection[Math.floor(Math.random() * 50) % 50];
}
military2525BEntitys[i].entity.update({ geo: geo, code: code });
}
// 更新上次更新時間
lastTime = time;
}
// 自訂符號-點擊移動模式
function setCustomEntityGeo() {
if (isDragging) return;
const { x: lng, y: lat } = terrainview.mousePos;
document.getElementById("lat").value = lat;
document.getElementById("lng").value = lng;
isMoveToClickMode = false;
terrainview.cursor = "default";
updateCustomEntity();
}
// 切換軍事符號提示面板顯示
function toggleSIDCHint() {
var SIDC_HINT_PANEL = document.getElementById("SIDC_HINT_PANEL");
var currentDisplay = SIDC_HINT_PANEL.style.display;
SIDC_HINT_PANEL.style.display =
currentDisplay == "none" || currentDisplay == "" ? "block" : "none";
}
// 開始點擊移動模式
function clickToMove() {
terrainview.cursor = "alias"; // 設定滑鼠游標
isMoveToClickMode = true;
}
// 更新畫面
function updateScreen(time) {
terrainview.updateScreen(); // 更新圖台畫面
update2525B(time); // 更新軍事符號位置
updateFPS(); // 更新FPS
requestAnimationFrame(updateScreen); // 設定下一次更新畫面
}
// 設定FPS顯示
function updateFPS() {
document.getElementById("FpsSpan").innerHTML =
"Fps: " + terrainview.getFPS().toFixed(0);
}
// 插入軍事符號
function insert2525b() {
// 取得軍事符號數量
let iconcount = document.getElementById("totalnumber").value;
// 檢查軍事模組是否存在, 如果存在就移除所有軍事符號重新插入
if (militaryModule !== null) {
militaryModule.removeAllEntity(); // 移除所有軍事符號
military2525BEntitys = []; // 重置軍事符號集合
// 按照軍事符號數量插入軍事符號
for (var i = 0; i < iconcount; i++) {
// 隨機取得軍事符號代碼
var codeString = Code2525BCollection[i % 50];
// 隨機取得軍事符號位置
var geo = new GeoPoint(
119 + Math.random() * 10,
21 + Math.random() * 10,
Math.random() * 5000 + 8000
);
// 插入軍事符號
var entity = militaryModule.add2525BEntity({
code: codeString,
geo: geo,
size: 32
});
// 將軍事符號加入軍事符號集合
military2525BEntitys.push({
geo: geo,
entity: entity,
course: Math.random(),
speed: Math.random(),
updateFlag: i
});
}
// 重置自訂符號
customEntity = null;
// 更新自訂符號
updateCustomEntity();
}
}
style.css
:
#MyMap {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
#MyControl {
position: absolute;
z-index: 1;
color: white;
background-color: black;
}
#SIDC_HINT_PANEL {
position: absolute;
top: 0px;
left: 270px;
padding: 2px;
width: 700px;
background-color: snow;
color: #333;
z-index: 10;
font-size: 8px;
margin: auto;
border: 1px solid #ccc;
border-radius: 4px;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
padding: 16px;
display: none;
}
#SIDC_HINT_PANEL table {
width: 100%;
border-collapse: collapse;
margin-bottom: 16px;
}
#SIDC_HINT_PANEL th,
#SIDC_HINT_PANEL td {
border: 1px solid #ddd;
text-align: left;
padding: 8px;
}
#SIDC_HINT_PANEL th {
background-color: #207523;
color: white;
}
#SIDC_HINT_PANEL caption {
font-size: 14px;
margin-bottom: 2px;
}
#SIDC_HINT_PANEL caption a {
text-decoration: underline;
color: royalblue;
}
.SIDCHint {
background-color: silver;
border-radius: 50%;
margin-right: 5px;
font-size: 8px;
padding: 2px;
position: relative;
cursor: pointer;
margin-left: 5px;
top: -2px;
}
.SIDCHint:hover::after {
content: "點擊顯示編碼提示";
position: absolute;
width: 100px;
background-color: white;
border: 1px solid black;
color: black;
font-size: 12px;
top: 25px;
transform: translateX(-50%);
cursor: pointer;
}
.panelCloseButton {
position: absolute;
top: 5px;
right: 5px;
color: gray;
z-index: 10;
border-radius: 4px;
cursor: pointer;
}
DEMO 簡介
操作說明
- 藍色箭頭處下拉式選單可設定畫面上要生成的符號數量
- 紅色箭頭處點擊後可顯示符號提示面板
- 綠色箭頭處點擊後再點擊地圖上任意位置可移動自訂符號