Răsfoiți Sursa

经纬度和距离转换、添加自定义初始化参数设置、噪声数据(有bug)

Rmengdi 2 luni în urmă
părinte
comite
6d01734929
1 a modificat fișierele cu 300 adăugiri și 50 ștergeri
  1. 300 50
      uavps-web/src/views/uavps/parameter/index.vue

+ 300 - 50
uavps-web/src/views/uavps/parameter/index.vue

@@ -337,19 +337,13 @@
                   placeholder="中心点-纬度"
                 ></el-input>
               </el-form-item>
-              <el-form-item label="长距离" prop="longSideDistance">
-                <el-input
-                  v-model="canvasInfo.longSideDistance"
-                  placeholder="长距离"
-                >
+              <el-form-item label="长距离" prop="widthKm">
+                <el-input v-model="canvasInfo.widthKm" placeholder="长距离">
                   <template slot="append">km</template>
                 </el-input>
               </el-form-item>
-              <el-form-item label="宽距离" prop="wideSideDistance">
-                <el-input
-                  v-model="canvasInfo.wideSideDistance"
-                  placeholder="宽距离"
-                >
+              <el-form-item label="宽距离" prop="heightKm">
+                <el-input v-model="canvasInfo.heightKm" placeholder="宽距离">
                   <template slot="append">km</template>
                 </el-input>
               </el-form-item>
@@ -368,20 +362,138 @@
               justify-content: space-between;
             "
           >
-            <div ref="pixiCanvas" class="left" style="width: 80%"></div>
             <div
-              class="right"
-              style="width: 19%; background-color: aquamarine"
-            ></div>
+              ref="pixiCanvas"
+              class="left"
+              style="width: 80%; position: relative"
+            >
+              <div style="position: absolute; top: 5px; left: 5px">
+                <span>经度:{{ nowlongitude }}</span
+                ><br />
+                <span>经度:{{ nowlatitude }}</span>
+              </div>
+            </div>
+            <div class="right" style="width: 19%; height: 600px">
+              <el-divider content-position="left">编队信息</el-divider>
+              <div style="overflow-y: scroll; width: 100%; height: 550px">
+                <li v-for="(item, index) in formationInfoList" :key="index">
+                  <div style="cursor: pointer">
+                    <div>
+                      <span>编号:&nbsp;&nbsp;</span
+                      ><label>{{ item.number }}</label>
+                    </div>
+                    <div>
+                      <span>经度:&nbsp;&nbsp;</span
+                      ><label>{{ item.longitude }}</label>
+                    </div>
+                    <div>
+                      <span>纬度:&nbsp;&nbsp;</span
+                      ><label>{{ item.latitude }}</label>
+                    </div>
+                  </div>
+                </li>
+              </div>
+            </div>
           </div>
         </div>
       </el-form>
       <div slot="footer" class="dialog-footer">
-        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button
+          type="primary"
+          :disabled="this.formationInfoList.length == 0"
+          @click="submitForm"
+          >确 定</el-button
+        >
         <el-button @click="cancel">取 消</el-button>
       </div>
     </el-dialog>
 
+    <el-drawer
+      title="设置参数"
+      size="20%"
+      :visible.sync="drawerOpen"
+      direction="rtl"
+      :show-close="false"
+      :wrapperClosable="false"
+    >
+      <div class="demo-drawer__content" style="width: 80%; margin-left: 20px">
+        <el-form
+          label-width="80px"
+          ref="formationInfoRef"
+          :rules="formationInfoRules"
+          :model="formationInfoForm"
+        >
+          <el-form-item label="编号" prop="number">
+            <el-input
+              v-model="formationInfoForm.number"
+              placeholder="请输入编号"
+            />
+          </el-form-item>
+          <el-form-item label="经度" prop="longitude">
+            <el-input
+              v-model="formationInfoForm.longitude"
+              placeholder="请输入经度"
+            />
+          </el-form-item>
+          <el-form-item label="纬度" prop="latitude">
+            <el-input
+              v-model="formationInfoForm.latitude"
+              placeholder="请输入纬度"
+            />
+          </el-form-item>
+          <el-form-item label="海拔" prop="altitude">
+            <el-input
+              v-model="formationInfoForm.altitude"
+              placeholder="请输入海拔"
+            />
+          </el-form-item>
+          <el-form-item label="东向速度" prop="eastSpeed">
+            <el-input
+              v-model="formationInfoForm.eastSpeed"
+              placeholder="请输入东向速度"
+            >
+              <template slot="append">m/s</template>
+            </el-input>
+          </el-form-item>
+          <el-form-item label="北向速度" prop="northSpeed">
+            <el-input
+              v-model="formationInfoForm.northSpeed"
+              placeholder="请输入北向速度"
+            >
+              <template slot="append">m/s</template>
+            </el-input>
+          </el-form-item>
+          <el-form-item label="天向速度" prop="skySpeed">
+            <el-input
+              v-model="formationInfoForm.skySpeed"
+              placeholder="请输入天向速度"
+            >
+              <template slot="append">m/s</template>
+            </el-input>
+          </el-form-item>
+          <el-form-item label="航线类型" prop="flightPathType">
+            <el-select
+              v-model="formationInfoForm.flightPathType"
+              placeholder="航线类型"
+            >
+              <el-option label="直线" value="直线"></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item label="噪声" prop="positionNoise">
+            <el-input
+              v-model="formationInfoForm.positionNoise"
+              placeholder="请输入噪声"
+            />
+          </el-form-item>
+        </el-form>
+        <div class="demo-drawer__footer">
+          <el-button type="primary" @click="handleDrawerSubmit"
+            >确 定</el-button
+          >
+        </div>
+      </div>
+    </el-drawer>
+
     <!-- 飞行轨迹展示对话框 -->
     <el-dialog
       :title="title"
@@ -514,6 +626,7 @@ import {
   updateParameter,
 } from "@/api/uavps/parameter";
 import * as PIXI from "pixi.js";
+// import { BlurFilter } from "@pixi/filter-blur";
 
 export default {
   name: "Parameter",
@@ -600,13 +713,40 @@ export default {
         centerLatitude: [
           { required: true, message: "纬度不能为空", trigger: "blur" },
         ],
-        longSideDistance: [
+        widthKm: [
           { required: true, message: "长距离不能为空", trigger: "blur" },
         ],
-        wideSideDistance: [
+        heightKm: [
           { required: true, message: "宽距离不能为空", trigger: "blur" },
         ],
       },
+      formationInfoRules: {
+        number: [{ required: true, message: "编号不能为空", trigger: "blur" }],
+        longitude: [
+          { required: true, message: "经度不能为空", trigger: "blur" },
+        ],
+        latitude: [
+          { required: true, message: "纬度不能为空", trigger: "blur" },
+        ],
+        altitude: [
+          { required: true, message: "海拔不能为空", trigger: "blur" },
+        ],
+        eastSpeed: [
+          { required: true, message: "东向速度不能为空", trigger: "blur" },
+        ],
+        northSpeed: [
+          { required: true, message: "北向速度不能为空", trigger: "blur" },
+        ],
+        skySpeed: [
+          { required: true, message: "天向速度不能为空", trigger: "blur" },
+        ],
+        flightPathType: [
+          { required: true, message: "航线类型不能为空", trigger: "change" },
+        ],
+        positionNoise: [
+          { required: true, message: "噪音不能为空", trigger: "blur" },
+        ],
+      },
       // 是否显示轨迹
       showTrajectory: false,
       pixiApp: null,
@@ -666,11 +806,30 @@ export default {
       canvasInfo: {
         centerLongitude: null,
         centerLatitude: null,
-        longSideDistance: null,
-        wideSideDistance: null,
+        widthKm: null,
+        heightKm: null,
       },
+      // 编辑编队信息的画布
+      pixiCanvas: null,
       // 是否提交了编队信息
       submitInfoFlag: false,
+      // 编队信息
+      formationInfoList: [],
+      formationInfoForm: {
+        number: null,
+        longitude: 100.0,
+        latitude: 100.0,
+        altitude: 100.0,
+        eastSpeed: 100.0,
+        northSpeed: 100.0,
+        skySpeed: 100.0,
+        flightPathType: "直线",
+        positionNoise: 18.2,
+      },
+      drawerOpen: false,
+      // 鼠标当前的经纬度
+      nowlongitude: null,
+      nowlatitude: null,
     };
   },
   created() {
@@ -732,6 +891,7 @@ export default {
     /** 新增按钮操作 */
     handleAdd() {
       this.reset();
+      this.form.formationType = "1";
       this.open = true;
       this.title = "添加算法参数信息";
     },
@@ -747,23 +907,29 @@ export default {
     },
     /** 提交按钮 */
     submitForm() {
-      this.$refs["form"].validate((valid) => {
-        if (valid) {
-          if (this.form.id != null) {
-            updateParameter(this.form).then((response) => {
-              this.$modal.msgSuccess("修改成功");
-              this.open = false;
-              this.getList();
-            });
-          } else {
-            addParameter(this.form).then((response) => {
-              this.$modal.msgSuccess("新增成功");
-              this.open = false;
-              this.getList();
-            });
+      console.log("this.formationType", this.formationType);
+      if (this.formationType == "2") {
+        // 自由编队
+        // 清空画布
+      } else {
+        this.$refs["form"].validate((valid) => {
+          if (valid) {
+            if (this.form.id != null) {
+              updateParameter(this.form).then((response) => {
+                this.$modal.msgSuccess("修改成功");
+                this.open = false;
+                this.getList();
+              });
+            } else {
+              addParameter(this.form).then((response) => {
+                this.$modal.msgSuccess("新增成功");
+                this.open = false;
+                this.getList();
+              });
+            }
           }
-        }
-      });
+        });
+      }
     },
     /** 删除按钮操作 */
     handleDelete(row) {
@@ -792,6 +958,34 @@ export default {
       this.title = "回放";
     },
 
+    handleDrawerSubmit() {
+      this.$refs["formationInfoRef"].validate((valid) => {
+        if (valid) {
+          let index = this.formationInfoList.findIndex(
+            (item) => item.number == this.formationInfoForm.number
+          );
+          if (index !== -1) {
+            this.$message.warning("该编号已存在,请重新输入");
+            return;
+          } else {
+            this.drawerOpen = false;
+            this.formationInfoList.push(this.formationInfoForm);
+            this.formationInfoForm = {
+              number: null,
+              longitude: 100.0,
+              latitude: 100.0,
+              altitude: 100.0,
+              eastSpeed: 100.0,
+              northSpeed: 100.0,
+              skySpeed: 100.0,
+              flightPathType: "直线",
+              positionNoise: 18.2,
+            };
+          }
+        }
+      });
+    },
+
     // 选择编队类型
     typeChange(val) {
       if (val == "2") {
@@ -814,19 +1008,29 @@ export default {
 
     // 初始化编队的画布
     initFormationApp() {
-      const pixiCanvas = this.$refs.pixiCanvas;
-      if (!pixiCanvas) return;
+      this.pixiCanvas = this.$refs.pixiCanvas;
+      if (!this.pixiCanvas) return;
       // 创建Pixi应用
       this.formationAirPiXiApp = new PIXI.Application({
-        width: pixiCanvas.clientWidth,
-        height: pixiCanvas.clientHeight,
+        width: this.pixiCanvas.clientWidth,
+        height: this.pixiCanvas.clientHeight,
         antialias: true,
         transparent: false,
         resolution: 1,
         backgroundAlpha: 0,
       });
       this.formationAirPiXiApp.renderer.backgroundColor = 0x1099bb;
-      pixiCanvas.appendChild(this.formationAirPiXiApp.view);
+      this.pixiCanvas.appendChild(this.formationAirPiXiApp.view);
+      // 绘制中心点
+      const graphics = new PIXI.Graphics();
+      graphics.beginFill(0xe53f32);
+
+      // 绘制一个圆形,半径为 5 像素
+      const centerX = this.pixiCanvas.clientWidth / 2;
+      const centerY = this.pixiCanvas.clientHeight / 2;
+      graphics.drawCircle(centerX, centerY, 3);
+      graphics.endFill();
+      this.formationAirPiXiApp.stage.addChild(graphics);
     },
 
     // 增加飞机编队
@@ -852,6 +1056,15 @@ export default {
       this.formationAirPiXiApp.view.addEventListener("pointermove", (e) => {
         airSprite.x = e.offsetX;
         airSprite.y = e.offsetY;
+        const { clientX, clientY } = e;
+        const rect = this.formationAirPiXiApp.view.getBoundingClientRect();
+        const mouseX = clientX - rect.left;
+        const mouseY = clientY - rect.top;
+
+        // 计算对应经纬度
+        const { lat, lng } = this.calculateLatLng(mouseX, mouseY);
+        this.nowlongitude = lng;
+        this.nowlatitude = lat;
       });
       this.formationAirPiXiApp.view.addEventListener("dblclick", (e) => {
         // 创建新精灵
@@ -860,10 +1073,45 @@ export default {
         newSprite.scale.set(0.04);
         newSprite.x = e.offsetX;
         newSprite.y = e.offsetY;
+        const { clientX, clientY } = e;
+        const rect = this.formationAirPiXiApp.view.getBoundingClientRect();
+        const mouseX = clientX - rect.left;
+        const mouseY = clientY - rect.top;
+
+        // 计算对应经纬度
+        const { lat, lng } = this.calculateLatLng(mouseX, mouseY);
+        this.formationInfoForm.longitude = lng;
+        this.formationInfoForm.latitude = lat;
+        this.drawerOpen = true;
         this.formationAirPiXiApp.stage.addChild(newSprite);
       });
     },
 
+    calculateLatLng(x, y) {
+      // 计算鼠标相对于画布中心的偏移量(单位:像素)
+      const offsetX = x - this.pixiCanvas.clientWidth / 2;
+      const offsetY = y - this.pixiCanvas.clientHeight / 2;
+
+      // 将像素偏移量转换为实际距离(单位:公里)
+      const kmPerPixelX = this.canvasInfo.widthKm / this.pixiCanvas.clientWidth;
+      const kmPerPixelY =
+        this.canvasInfo.heightKm / this.pixiCanvas.clientHeight;
+      const deltaX = offsetX * kmPerPixelX;
+      const deltaY = -offsetY * kmPerPixelY; // 注意 y 轴方向相反
+
+      // 将实际距离转换为经纬度差值
+      const deltaLat = deltaY / 111; // 每纬度约 111 公里
+      const deltaLng =
+        deltaX /
+        (111 * Math.cos((this.canvasInfo.centerLatitude * Math.PI) / 180)); // 每经度约 111 * cos(lat) 公里
+
+      // 计算最终经纬度
+      const lat = Number(this.canvasInfo.centerLatitude) + Number(deltaLat);
+      const lng = Number(this.canvasInfo.centerLongitude) + Number(deltaLng);
+
+      return { lat, lng };
+    },
+
     /** 导出按钮操作 */
     handleExport() {
       this.download(
@@ -962,6 +1210,7 @@ export default {
           const dude = new PIXI.Sprite(this.targetTexture);
           dude.anchor.set(0.5, 0.5);
           dude.scale.set(0.04);
+
           dude.x = data.targetAircraft[0].aircrafts[i].coordinateX;
           dude.y = data.targetAircraft[0].aircrafts[i].coordinateY;
           const eastSpeed = data.targetAircraft[0].aircrafts[i].eastSpeed;
@@ -969,10 +1218,13 @@ export default {
           dude.rotation = Math.atan2(northSpeed, eastSpeed);
 
           dude.id = data.targetAircraft[0].aircrafts[i].aircraftNumber; // 分配唯一编号
-
           this.targetUavAry.push(dude);
+
+          // 创建模糊滤镜
+          const blurFilter = new PIXI.filters.BlurFilter();
+          blurFilter.blur = 20;
+          dude.filters = [blurFilter];
           group.addChild(dude);
-          // this.pixiApp.stage.addChild(group);
 
           // 创建圆圈
           // 圆圈相对于飞机的位置
@@ -1168,11 +1420,7 @@ export default {
     },
     // 更新飞行路径
     updatePath() {
-      // console.log("this.targetUavPath", this.targetUavPath);
-      // this.pathGraphics.clear();
       this.pathGraphics.lineStyle(1, 0xeeee00, 1);
-      // debugger;
-      // const simplifiedPath = douglasPeucker(this.targetUavPath, 5);
       if (this.targetUavPath.length <= 1) {
         const firstData = this.targetUavPath[this.targetUavPath.length - 1];
         this.lastPosition = firstData;
@@ -1336,12 +1584,16 @@ export default {
       this.canvasInfo = {
         centerLongitude: null,
         centerLatitude: null,
-        longSideDistance: null,
-        wideSideDistance: null,
+        widthKm: null,
+        heightKm: null,
       };
       this.submitInfoFlag = false;
       this.formationAirPiXiApp = null;
       this.formationType = "1";
+      this.pixiCanvas = null;
+      (this.nowlongitude = null),
+        (this.nowlatitude = null),
+        (this.formationInfoList = []);
       this.reset();
     },
     destroyTormationInfo() {
@@ -1376,8 +1628,6 @@ export default {
         this.curAltitude;
       console.info("transFormation", msg);
       this.webSocket.send(msg);
-      // this.pixiApp.stage.removeChildren();
-      // this.clearAllAry();
     },
     clearAllAry() {
       this.targetLblAry = [];