Compare commits
5 Commits
main
...
2b639ea0f3
| Author | SHA1 | Date | |
|---|---|---|---|
| 2b639ea0f3 | |||
| 0aecd99d65 | |||
| 04f23de755 | |||
| 7dca973b3b | |||
| 31f8c849b8 |
@ -4,5 +4,6 @@
|
|||||||
"semi": false,
|
"semi": false,
|
||||||
"singleQuote": true,
|
"singleQuote": true,
|
||||||
"trailingComma": "es5",
|
"trailingComma": "es5",
|
||||||
"bracketSpacing": false
|
"bracketSpacing": false,
|
||||||
|
"printWidth": 120
|
||||||
}
|
}
|
||||||
|
|||||||
28
README.md
28
README.md
@ -1,3 +1,29 @@
|
|||||||
# kxfx
|
# kxfx
|
||||||
|
|
||||||
## 机动路线规划
|
## Project setup
|
||||||
|
|
||||||
|
```
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compiles and hot-reloads for development
|
||||||
|
|
||||||
|
```
|
||||||
|
npm run serve
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compiles and minifies for production
|
||||||
|
|
||||||
|
```
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Lints and fixes files
|
||||||
|
|
||||||
|
```
|
||||||
|
npm run lint
|
||||||
|
```
|
||||||
|
|
||||||
|
### Customize configuration
|
||||||
|
|
||||||
|
See [Configuration Reference](https://cli.vuejs.org/config/).
|
||||||
|
|||||||
421
package-lock.json
generated
421
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
|||||||
[http]
|
[http]
|
||||||
port=8083
|
port=8081
|
||||||
address=127.0.0.1
|
address=127.0.0.1
|
||||||
|
|
||||||
[title]
|
[title]
|
||||||
|
|||||||
@ -17,7 +17,7 @@ export default {
|
|||||||
return {
|
return {
|
||||||
routerMap: {
|
routerMap: {
|
||||||
1: '/',
|
1: '/',
|
||||||
2: '/residentAnalysis',
|
// 2: '/residentAnalysis ',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -6,13 +6,13 @@ import residentAnalysis from '@/views/residentAnalysis/index.vue'
|
|||||||
Vue.use(VueRouter)
|
Vue.use(VueRouter)
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
|
// {
|
||||||
|
// path: '/',
|
||||||
|
// name: 'home',
|
||||||
|
// component: HomeView,
|
||||||
|
// },
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
name: 'home',
|
|
||||||
component: HomeView,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/residentAnalysis',
|
|
||||||
name: 'residentAnalysis',
|
name: 'residentAnalysis',
|
||||||
component: residentAnalysis,
|
component: residentAnalysis,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -22,8 +22,8 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
tabList: [
|
tabList: [
|
||||||
{id: 1, label: '机动路线规划'},
|
// {id: 1, label: '机动路线规划'},
|
||||||
// {id: 2, label: '临时部署驻地分析'},
|
{id: 1, label: '临时部署驻地分析'},
|
||||||
],
|
],
|
||||||
activeIndex: 1,
|
activeIndex: 1,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -81,21 +81,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<input
|
<input type="file" ref="fileInput" @change="handleFileUpload" style="display: none" />
|
||||||
type="file"
|
|
||||||
ref="fileInput"
|
|
||||||
@change="handleFileUpload"
|
|
||||||
style="display: none"
|
|
||||||
/>
|
|
||||||
<div class="importJson" @click="triggerFileUpload">导入json文件</div>
|
<div class="importJson" @click="triggerFileUpload">导入json文件</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="control-panel">
|
<div class="control-panel">
|
||||||
<div class="title">隐蔽添加</div>
|
<div class="title">隐蔽添加</div>
|
||||||
<el-form
|
<el-form label-width="120px" label-position="left" size="mini">
|
||||||
label-width="120px"
|
|
||||||
label-position="left"
|
|
||||||
size="mini"
|
|
||||||
>
|
|
||||||
<el-form-item label="缓冲半径(m)">
|
<el-form-item label="缓冲半径(m)">
|
||||||
<el-input v-model="hideform.radius"></el-input>
|
<el-input v-model="hideform.radius"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -112,12 +103,7 @@
|
|||||||
<span>参与路线规划</span>
|
<span>参与路线规划</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<el-form
|
<el-form @submit.native.prevent="calculateShortestPath" label-width="120px" label-position="left" size="mini">
|
||||||
@submit.native.prevent="calculateShortestPath"
|
|
||||||
label-width="120px"
|
|
||||||
label-position="left"
|
|
||||||
size="mini"
|
|
||||||
>
|
|
||||||
<el-form-item label="宽度">
|
<el-form-item label="宽度">
|
||||||
<el-input v-model="inputform.width"></el-input>
|
<el-input v-model="inputform.width"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -125,10 +111,7 @@
|
|||||||
<el-input v-model="inputform.load" placeholder=""></el-input>
|
<el-input v-model="inputform.load" placeholder=""></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="最小转弯半径">
|
<el-form-item label="最小转弯半径">
|
||||||
<el-input
|
<el-input v-model="inputform.minTurnRadius" placeholder=""></el-input>
|
||||||
v-model="inputform.minTurnRadius"
|
|
||||||
placeholder=""
|
|
||||||
></el-input>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<div class="importJson" @click="openDialog">数据选择</div>
|
<div class="importJson" @click="openDialog">数据选择</div>
|
||||||
@ -156,7 +139,7 @@
|
|||||||
inputform.minTurnRadius || 0
|
inputform.minTurnRadius || 0
|
||||||
}},最大车辆载重{{ inputform.load || 0 }}吨
|
}},最大车辆载重{{ inputform.load || 0 }}吨
|
||||||
</div>
|
</div>
|
||||||
<vxe-table ref="xTable" :data="infoList" style="max-height: 50vh;overflow: hidden;overflow-y: auto;">
|
<vxe-table ref="xTable" :data="infoList" style="max-height: 50vh; overflow: hidden; overflow-y: auto">
|
||||||
<vxe-column field="编码" title="编码" width="65px"></vxe-column>
|
<vxe-column field="编码" title="编码" width="65px"></vxe-column>
|
||||||
<vxe-column field="名称" title="名称" width="80px"></vxe-column>
|
<vxe-column field="名称" title="名称" width="80px"></vxe-column>
|
||||||
<vxe-column field="宽度" title="路宽"></vxe-column>
|
<vxe-column field="宽度" title="路宽"></vxe-column>
|
||||||
@ -165,23 +148,23 @@
|
|||||||
<vxe-column field="水深" title="水深"></vxe-column>
|
<vxe-column field="水深" title="水深"></vxe-column>
|
||||||
<vxe-column field="净空高" title="净空高" width="65px"></vxe-column>
|
<vxe-column field="净空高" title="净空高" width="65px"></vxe-column>
|
||||||
</vxe-table>
|
</vxe-table>
|
||||||
<vxe-table :data="factoriesWithVehicles" style="margin-top: 10px;">
|
<vxe-table :data="factoriesWithVehicles" style="margin-top: 10px">
|
||||||
<vxe-column field="options.style.properties.FID_1" title="厂房id"></vxe-column>
|
<vxe-column field="options.style.properties.FID_1" title="厂房id"></vxe-column>
|
||||||
<vxe-column field="area" title="面积(㎡)">
|
<vxe-column field="area" title="面积(㎡)">
|
||||||
<template v-slot="{ row }">
|
<template v-slot="{row}">
|
||||||
{{ row.area.toFixed(2)}}
|
{{ row.area.toFixed(2) }}
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="vehicles" title="车辆">
|
<vxe-column field="vehicles" title="车辆">
|
||||||
<template v-slot="{ row }">
|
<template v-slot="{row}">
|
||||||
{{ (row.vehicles.map(item => item.name)).join(',')}}
|
{{ row.vehicles.map((item) => item.name).join(',') }}
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
</vxe-table>
|
</vxe-table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<el-dialog :visible.sync="dialogVisible" title="车辆选择" width="800px">
|
<el-dialog :visible.sync="dialogVisible" title="车辆选择" width="800px">
|
||||||
<div style="margin-bottom: 10px;">
|
<div style="margin-bottom: 10px">
|
||||||
<el-button type="primary" size="mini" @click="handleAdd">新增</el-button>
|
<el-button type="primary" size="mini" @click="handleAdd">新增</el-button>
|
||||||
</div>
|
</div>
|
||||||
<vxe-table
|
<vxe-table
|
||||||
@ -197,37 +180,37 @@
|
|||||||
>
|
>
|
||||||
<vxe-column type="checkbox" width="50"></vxe-column>
|
<vxe-column type="checkbox" width="50"></vxe-column>
|
||||||
<vxe-column field="name" title="名称" width="100">
|
<vxe-column field="name" title="名称" width="100">
|
||||||
<template v-slot="{ row }">
|
<template v-slot="{row}">
|
||||||
<el-input v-if="row.editing" v-model="row.name" size="mini"></el-input>
|
<el-input v-if="row.editing" v-model="row.name" size="mini"></el-input>
|
||||||
<span v-else>{{ row.name }}</span>
|
<span v-else>{{ row.name }}</span>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="long" title="长度" width="100">
|
<vxe-column field="long" title="长度" width="100">
|
||||||
<template v-slot="{ row }">
|
<template v-slot="{row}">
|
||||||
<el-input v-if="row.editing" v-model="row.long" size="mini"></el-input>
|
<el-input v-if="row.editing" v-model="row.long" size="mini"></el-input>
|
||||||
<span v-else>{{ row.long }}</span>
|
<span v-else>{{ row.long }}</span>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="width" title="宽度" width="100">
|
<vxe-column field="width" title="宽度" width="100">
|
||||||
<template v-slot="{ row }">
|
<template v-slot="{row}">
|
||||||
<el-input v-if="row.editing" v-model="row.width" size="mini"></el-input>
|
<el-input v-if="row.editing" v-model="row.width" size="mini"></el-input>
|
||||||
<span v-else>{{ row.width }}</span>
|
<span v-else>{{ row.width }}</span>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="load" title="载重(吨)" width="100">
|
<vxe-column field="load" title="载重(吨)" width="100">
|
||||||
<template v-slot="{ row }">
|
<template v-slot="{row}">
|
||||||
<el-input v-if="row.editing" v-model="row.load" size="mini"></el-input>
|
<el-input v-if="row.editing" v-model="row.load" size="mini"></el-input>
|
||||||
<span v-else>{{ row.load }}</span>
|
<span v-else>{{ row.load }}</span>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="minTurnRadius" title="最小转弯半径">
|
<vxe-column field="minTurnRadius" title="最小转弯半径">
|
||||||
<template v-slot="{ row }">
|
<template v-slot="{row}">
|
||||||
<el-input v-if="row.editing" v-model="row.minTurnRadius" size="mini"></el-input>
|
<el-input v-if="row.editing" v-model="row.minTurnRadius" size="mini"></el-input>
|
||||||
<span v-else>{{ row.minTurnRadius }}</span>
|
<span v-else>{{ row.minTurnRadius }}</span>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column title="操作" width="100">
|
<vxe-column title="操作" width="100">
|
||||||
<template v-slot="{ row }">
|
<template v-slot="{row}">
|
||||||
<el-button v-if="!row.editing" type="text" size="mini" @click="handleEdit(row)">编辑</el-button>
|
<el-button v-if="!row.editing" type="text" size="mini" @click="handleEdit(row)">编辑</el-button>
|
||||||
<el-button v-else type="text" size="mini" @click="handleSave(row)">保存</el-button>
|
<el-button v-else type="text" size="mini" @click="handleSave(row)">保存</el-button>
|
||||||
<el-button type="text" size="mini" @click="handleDelete(row)">删除</el-button>
|
<el-button type="text" size="mini" @click="handleDelete(row)">删除</el-button>
|
||||||
@ -248,7 +231,7 @@
|
|||||||
import Cookies from 'js-cookie'
|
import Cookies from 'js-cookie'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import iniParser from 'ini-parser'
|
import iniParser from 'ini-parser'
|
||||||
import configIni from '/config.ini';
|
import configIni from '/public/config.ini'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
@ -321,7 +304,7 @@ export default {
|
|||||||
.catch((error) => {})
|
.catch((error) => {})
|
||||||
},
|
},
|
||||||
async initMap() {
|
async initMap() {
|
||||||
const parsedData = iniParser.parse(configIni);
|
const parsedData = iniParser.parse(configIni)
|
||||||
this.viewer = new window.mars3d.Map(
|
this.viewer = new window.mars3d.Map(
|
||||||
'map',
|
'map',
|
||||||
{
|
{
|
||||||
@ -356,7 +339,7 @@ export default {
|
|||||||
|
|
||||||
this.shortestPathLayer = new window.mars3d.layer.GraphicLayer()
|
this.shortestPathLayer = new window.mars3d.layer.GraphicLayer()
|
||||||
this.viewer.addLayer(this.shortestPathLayer)
|
this.viewer.addLayer(this.shortestPathLayer)
|
||||||
|
|
||||||
this.accordFactoryLayer = new window.mars3d.layer.GraphicLayer()
|
this.accordFactoryLayer = new window.mars3d.layer.GraphicLayer()
|
||||||
this.viewer.addLayer(this.accordFactoryLayer)
|
this.viewer.addLayer(this.accordFactoryLayer)
|
||||||
this.loadShapefile() // 拿到路网数据
|
this.loadShapefile() // 拿到路网数据
|
||||||
@ -450,7 +433,7 @@ export default {
|
|||||||
outline: false,
|
outline: false,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
this.graphicLayer.addGraphic(graphicLine);
|
this.graphicLayer.addGraphic(graphicLine)
|
||||||
})
|
})
|
||||||
this.roadNetworkGeoJSONBuild = this.buildGraph(this.roadNetworkGeoJSON)
|
this.roadNetworkGeoJSONBuild = this.buildGraph(this.roadNetworkGeoJSON)
|
||||||
this.loadFactoryGeoJson() // 拿到厂房数据
|
this.loadFactoryGeoJson() // 拿到厂房数据
|
||||||
@ -500,7 +483,7 @@ export default {
|
|||||||
this.accordPoint = graphic
|
this.accordPoint = graphic
|
||||||
try {
|
try {
|
||||||
// 创建缓冲区的宽度
|
// 创建缓冲区的宽度
|
||||||
const bufferWidth = this.hideform.radius; // 避让区的宽度(单位:米)
|
const bufferWidth = this.hideform.radius // 避让区的宽度(单位:米)
|
||||||
// 获取绘制的点的坐标
|
// 获取绘制的点的坐标
|
||||||
const pointCoordinates = [
|
const pointCoordinates = [
|
||||||
graphic.toGeoJSON().geometry.coordinates[0],
|
graphic.toGeoJSON().geometry.coordinates[0],
|
||||||
@ -514,12 +497,12 @@ export default {
|
|||||||
coordinates: pointCoordinates,
|
coordinates: pointCoordinates,
|
||||||
},
|
},
|
||||||
properties: {},
|
properties: {},
|
||||||
};
|
}
|
||||||
// 使用 Turf.js 计算缓冲区
|
// 使用 Turf.js 计算缓冲区
|
||||||
let buffered = turf.buffer(pointFeature, bufferWidth / 1000, { units: 'kilometers' });
|
let buffered = turf.buffer(pointFeature, bufferWidth / 1000, {units: 'kilometers'})
|
||||||
|
|
||||||
// 将缓冲区存储到数组中
|
// 将缓冲区存储到数组中
|
||||||
this.bufferLayerList.push(buffered);
|
this.bufferLayerList.push(buffered)
|
||||||
const polygon = new window.mars3d.graphic.PolygonEntity({
|
const polygon = new window.mars3d.graphic.PolygonEntity({
|
||||||
positions: buffered.geometry.coordinates[0],
|
positions: buffered.geometry.coordinates[0],
|
||||||
style: {
|
style: {
|
||||||
@ -529,19 +512,19 @@ export default {
|
|||||||
outlineWidth: 1,
|
outlineWidth: 1,
|
||||||
outlineColor: '#ffffff',
|
outlineColor: '#ffffff',
|
||||||
},
|
},
|
||||||
time: new Date().getTime()
|
time: new Date().getTime(),
|
||||||
})
|
})
|
||||||
this.accordFactoryLayer.addGraphic(polygon);
|
this.accordFactoryLayer.addGraphic(polygon)
|
||||||
// 检查缓冲区内的厂房
|
// 检查缓冲区内的厂房
|
||||||
this.checkFactoryInBuffer('point', pointCoordinates);
|
this.checkFactoryInBuffer('point', pointCoordinates)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("缓冲区生成或检查异常:", error);
|
console.error('缓冲区生成或检查异常:', error)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
// 获取当前路线的缓冲区
|
// 获取当前路线的缓冲区
|
||||||
hadBuffer () {
|
hadBuffer() {
|
||||||
if (this.shortestPathList.length == 0) {
|
if (this.shortestPathList.length == 0) {
|
||||||
this.$message.warning('请先进行路线规划')
|
this.$message.warning('请先进行路线规划')
|
||||||
return
|
return
|
||||||
@ -551,34 +534,34 @@ export default {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
// =======检查几何对象的类型 缓冲区========
|
// =======检查几何对象的类型 缓冲区========
|
||||||
for (const feature of this.shortestPathList[0]) {
|
for (const feature of this.shortestPathList[0]) {
|
||||||
// this.shortestPathList[0].forEach((feature) => {
|
// this.shortestPathList[0].forEach((feature) => {
|
||||||
// 创建缓冲区的宽度
|
// 创建缓冲区的宽度
|
||||||
const bufferWidth = this.hideform.radius; // 避让区的宽度(单位:米)
|
const bufferWidth = this.hideform.radius // 避让区的宽度(单位:米)
|
||||||
if (feature.geometry.type === 'LineString') {
|
if (feature.geometry.type === 'LineString') {
|
||||||
const positions = feature.geometry.coordinates[0];
|
const positions = feature.geometry.coordinates[0]
|
||||||
// 确保每条线至少有 2 个点
|
// 确保每条线至少有 2 个点
|
||||||
if (positions.length < 2) {
|
if (positions.length < 2) {
|
||||||
console.warn('无效的线,跳过:', feature);
|
console.warn('无效的线,跳过:', feature)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
// 使用 Turf.js 计算缓冲区
|
// 使用 Turf.js 计算缓冲区
|
||||||
var buffered = turf.buffer(feature, bufferWidth / 1000, { units: 'kilometers' });
|
var buffered = turf.buffer(feature, bufferWidth / 1000, {units: 'kilometers'})
|
||||||
|
|
||||||
// 将缓冲区存储到数组中
|
// 将缓冲区存储到数组中
|
||||||
this.bufferLayerList.push(buffered);
|
this.bufferLayerList.push(buffered)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("缓冲分析异常:", error);
|
console.error('缓冲分析异常:', error)
|
||||||
}
|
}
|
||||||
} else if (feature.geometry.type === 'MultiLineString') {
|
} else if (feature.geometry.type === 'MultiLineString') {
|
||||||
// 遍历每个线段
|
// 遍历每个线段
|
||||||
feature.geometry.coordinates.forEach((lineCoordinates) => {
|
feature.geometry.coordinates.forEach((lineCoordinates) => {
|
||||||
// 检查每个线段是否有效
|
// 检查每个线段是否有效
|
||||||
if (lineCoordinates.length < 2) {
|
if (lineCoordinates.length < 2) {
|
||||||
console.warn('多线段中的无效的线段,跳过:', lineCoordinates);
|
console.warn('多线段中的无效的线段,跳过:', lineCoordinates)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建单个线段的 GeoJSON 特征
|
// 创建单个线段的 GeoJSON 特征
|
||||||
@ -588,27 +571,27 @@ export default {
|
|||||||
type: 'LineString',
|
type: 'LineString',
|
||||||
coordinates: lineCoordinates,
|
coordinates: lineCoordinates,
|
||||||
},
|
},
|
||||||
properties: feature.properties
|
properties: feature.properties,
|
||||||
};
|
}
|
||||||
try {
|
try {
|
||||||
// 使用 Turf.js 计算缓冲区
|
// 使用 Turf.js 计算缓冲区
|
||||||
var buffered = turf.buffer(lineFeature, bufferWidth / 1000, { units: 'kilometers' });
|
var buffered = turf.buffer(lineFeature, bufferWidth / 1000, {units: 'kilometers'})
|
||||||
|
|
||||||
// 将缓冲区存储到数组中
|
// 将缓冲区存储到数组中
|
||||||
this.bufferLayerList.push(buffered);
|
this.bufferLayerList.push(buffered)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("缓冲分析异常:", error);
|
console.error('缓冲分析异常:', error)
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
} else {
|
} else {
|
||||||
console.warn('不支持的几何类型:', feature.geometry.type);
|
console.warn('不支持的几何类型:', feature.geometry.type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 去筛选在缓存区的厂房
|
// 去筛选在缓存区的厂房
|
||||||
this.checkFactoryInBuffer('line');
|
this.checkFactoryInBuffer('line')
|
||||||
}catch (error) {
|
} catch (error) {
|
||||||
console.error("处理路径列表时发生错误:", error);
|
console.error('处理路径列表时发生错误:', error)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
checkFactoryInBuffer(type, pointInfo) {
|
checkFactoryInBuffer(type, pointInfo) {
|
||||||
@ -629,106 +612,106 @@ export default {
|
|||||||
// 检查几何对象的类型
|
// 检查几何对象的类型
|
||||||
if (factory.geometry.type === 'MultiPolygon') {
|
if (factory.geometry.type === 'MultiPolygon') {
|
||||||
// 创建多边形集合(MultiPolygon)
|
// 创建多边形集合(MultiPolygon)
|
||||||
const factoryMultiPoly = turf.multiPolygon(factory.geometry.coordinates);
|
const factoryMultiPoly = turf.multiPolygon(factory.geometry.coordinates)
|
||||||
// 计算整个多边形集合的面积
|
// 计算整个多边形集合的面积
|
||||||
const area = turf.area(factoryMultiPoly);
|
const area = turf.area(factoryMultiPoly)
|
||||||
// 计算工厂多边形集合的边界框
|
// 计算工厂多边形集合的边界框
|
||||||
const [minX, minY, maxX, maxY] = turf.bbox(factoryMultiPoly);
|
const [minX, minY, maxX, maxY] = turf.bbox(factoryMultiPoly)
|
||||||
|
|
||||||
// 筛选与工厂边界框相交的缓冲区
|
// 筛选与工厂边界框相交的缓冲区
|
||||||
const candidates = this.bufferLayerList.filter((buffer) => {
|
const candidates = this.bufferLayerList.filter((buffer) => {
|
||||||
const [bminX, bminY, bmaxX, bmaxY] = turf.bbox(buffer);
|
const [bminX, bminY, bmaxX, bmaxY] = turf.bbox(buffer)
|
||||||
return !(bmaxX < minX || bminX > maxX || bmaxY < minY || bminY > maxY);
|
return !(bmaxX < minX || bminX > maxX || bmaxY < minY || bminY > maxY)
|
||||||
});
|
})
|
||||||
// 精确相交检测
|
// 精确相交检测
|
||||||
let isInside = false;
|
let isInside = false
|
||||||
for (const buffer of candidates) {
|
for (const buffer of candidates) {
|
||||||
if (turf.booleanIntersects(factoryMultiPoly, buffer)) {
|
if (turf.booleanIntersects(factoryMultiPoly, buffer)) {
|
||||||
// 如果工厂在缓冲区内,绘制所有多边形
|
// 如果工厂在缓冲区内,绘制所有多边形
|
||||||
isInside = true;
|
isInside = true
|
||||||
this.drawFactory(factory.geometry.coordinates, factory, area, pointInfo);
|
this.drawFactory(factory.geometry.coordinates, factory, area, pointInfo)
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 如果工厂不在任何缓冲区内
|
// 如果工厂不在任何缓冲区内
|
||||||
resolve();
|
resolve()
|
||||||
} else {
|
} else {
|
||||||
reject(new Error('不支持的几何类型'));
|
reject(new Error('不支持的几何类型'))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
});
|
})
|
||||||
// 确保所有工厂处理完成后进行排序
|
// 确保所有工厂处理完成后进行排序
|
||||||
Promise.allSettled(factoryPromises)
|
Promise.allSettled(factoryPromises)
|
||||||
.then(async (results) => {
|
.then(async (results) => {
|
||||||
// 只有路线隐蔽规划需要塞入车辆 点的不需要
|
// 只有路线隐蔽规划需要塞入车辆 点的不需要
|
||||||
// 所有工厂处理完成,进行排序 按照距离近到远
|
// 所有工厂处理完成,进行排序 按照距离近到远
|
||||||
this.accordFactoryInfo.sort((a, b) => a.distance - b.distance);
|
this.accordFactoryInfo.sort((a, b) => a.distance - b.distance)
|
||||||
// 拿到当前的车队车辆信息 并且算出面积 按照从大到小排序
|
// 拿到当前的车队车辆信息 并且算出面积 按照从大到小排序
|
||||||
const areaList = JSON.parse(Cookies.get('minTurnRadius'))
|
const areaList = JSON.parse(Cookies.get('minTurnRadius'))
|
||||||
areaList.map((item) => {
|
areaList.map((item) => {
|
||||||
item.area = Number(item.long) * Number(item.width)
|
item.area = Number(item.long) * Number(item.width)
|
||||||
})
|
})
|
||||||
areaList.sort((a, b) => b.area - a.area);
|
areaList.sort((a, b) => b.area - a.area)
|
||||||
// 初始化每个工厂的剩余面积
|
// 初始化每个工厂的剩余面积
|
||||||
this.accordFactoryInfo.forEach(factory => {
|
this.accordFactoryInfo.forEach((factory) => {
|
||||||
factory.remainingArea = factory.area; // 记录每个工厂的剩余可用面积
|
factory.remainingArea = factory.area // 记录每个工厂的剩余可用面积
|
||||||
factory.vehicles = []; // 确保每个工厂都有一个 vehicles 属性
|
factory.vehicles = [] // 确保每个工厂都有一个 vehicles 属性
|
||||||
});
|
})
|
||||||
// 遍历每个车辆,尝试塞入工厂
|
// 遍历每个车辆,尝试塞入工厂
|
||||||
areaList.forEach((vehicle) => {
|
areaList.forEach((vehicle) => {
|
||||||
let isPlaced = false;
|
let isPlaced = false
|
||||||
|
|
||||||
// 遍历每个工厂,尝试塞入车辆
|
// 遍历每个工厂,尝试塞入车辆
|
||||||
for (let i = 0; i < this.accordFactoryInfo.length; i++) {
|
for (let i = 0; i < this.accordFactoryInfo.length; i++) {
|
||||||
const factory = this.accordFactoryInfo[i];
|
const factory = this.accordFactoryInfo[i]
|
||||||
|
|
||||||
// 检查工厂是否还有剩余面积
|
// 检查工厂是否还有剩余面积
|
||||||
if (factory.remainingArea >= vehicle.area) {
|
if (factory.remainingArea >= vehicle.area) {
|
||||||
// 塞入车辆
|
// 塞入车辆
|
||||||
factory.vehicles.push({
|
factory.vehicles.push({
|
||||||
...vehicle,
|
...vehicle,
|
||||||
remainingArea: factory.remainingArea - vehicle.area // 记录车辆塞入后的工厂剩余面积
|
remainingArea: factory.remainingArea - vehicle.area, // 记录车辆塞入后的工厂剩余面积
|
||||||
});
|
})
|
||||||
|
|
||||||
// 更新工厂的剩余面积
|
// 更新工厂的剩余面积
|
||||||
factory.remainingArea -= vehicle.area;
|
factory.remainingArea -= vehicle.area
|
||||||
|
|
||||||
// 标记车辆已放置
|
// 标记车辆已放置
|
||||||
isPlaced = true;
|
isPlaced = true
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果车辆没有被放置,可以在这里处理(例如记录日志或显示警告)
|
// 如果车辆没有被放置,可以在这里处理(例如记录日志或显示警告)
|
||||||
if (!isPlaced) {
|
if (!isPlaced) {
|
||||||
console.warn(`车辆 ${vehicle.id} 无法放置在任何工厂中`);
|
console.warn(`车辆 ${vehicle.id} 无法放置在任何工厂中`)
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
// 更新 this.accordFactoryInfo
|
// 更新 this.accordFactoryInfo
|
||||||
this.accordFactoryInfo = this.accordFactoryInfo.map(factory => {
|
this.accordFactoryInfo = this.accordFactoryInfo.map((factory) => {
|
||||||
// 确保每个工厂都有 vehicles 属性
|
// 确保每个工厂都有 vehicles 属性
|
||||||
if (!factory.vehicles) {
|
if (!factory.vehicles) {
|
||||||
factory.vehicles = [];
|
factory.vehicles = []
|
||||||
}
|
}
|
||||||
// 确保 remainingArea 是一个数字且大于 0
|
// 确保 remainingArea 是一个数字且大于 0
|
||||||
factory.area = factory.area > 0 ? factory.area : 0;
|
factory.area = factory.area > 0 ? factory.area : 0
|
||||||
return factory;
|
return factory
|
||||||
});
|
})
|
||||||
// 过滤出有车辆的工厂
|
// 过滤出有车辆的工厂
|
||||||
const factoriesWithVehicles = this.accordFactoryInfo.filter(factory => factory.vehicles.length > 0);
|
const factoriesWithVehicles = this.accordFactoryInfo.filter((factory) => factory.vehicles.length > 0)
|
||||||
this.factoriesWithVehicles = factoriesWithVehicles
|
this.factoriesWithVehicles = factoriesWithVehicles
|
||||||
await this.showAreaInfoDialog(factoriesWithVehicles);
|
await this.showAreaInfoDialog(factoriesWithVehicles)
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error('数据有问题', error)
|
console.error('数据有问题', error)
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
drawFactory(factoryMultiPoly, factory, area, pointInfo) {
|
drawFactory(factoryMultiPoly, factory, area, pointInfo) {
|
||||||
// 获取当前多边形集合的中心点
|
// 获取当前多边形集合的中心点
|
||||||
const center = turf.center(turf.multiPolygon(factory.geometry.coordinates));
|
const center = turf.center(turf.multiPolygon(factory.geometry.coordinates))
|
||||||
// 将中心点转换为 Mars3D 的 LngLatPoint 对象
|
// 将中心点转换为 Mars3D 的 LngLatPoint 对象
|
||||||
const popupPosition = new mars3d.LngLatPoint(center.geometry.coordinates[0], center.geometry.coordinates[1]);
|
const popupPosition = new mars3d.LngLatPoint(center.geometry.coordinates[0], center.geometry.coordinates[1])
|
||||||
// 遍历每个多边形集合
|
// 遍历每个多边形集合
|
||||||
factory.geometry.coordinates[0].forEach((coordGroup) => {
|
factory.geometry.coordinates[0].forEach((coordGroup) => {
|
||||||
// 创建一个多边形图形
|
// 创建一个多边形图形
|
||||||
@ -740,35 +723,39 @@ export default {
|
|||||||
outline: true,
|
outline: true,
|
||||||
outlineWidth: 1,
|
outlineWidth: 1,
|
||||||
outlineColor: '#ffffff',
|
outlineColor: '#ffffff',
|
||||||
properties: { ...factory.properties },
|
properties: {...factory.properties},
|
||||||
},
|
},
|
||||||
time: new Date().getTime()
|
time: new Date().getTime(),
|
||||||
})
|
})
|
||||||
this.accordFactoryLayer.addGraphic(graphic);
|
this.accordFactoryLayer.addGraphic(graphic)
|
||||||
// 计算多边形中心与参考点的距离
|
// 计算多边形中心与参考点的距离
|
||||||
const point = pointInfo && pointInfo.length > 0 ? pointInfo : this.form.endPoint.split(',').map(Number)
|
const point = pointInfo && pointInfo.length > 0 ? pointInfo : this.form.endPoint.split(',').map(Number)
|
||||||
const distance = turf.distance(center.geometry.coordinates, point, { units: 'kilometers' }) * 1000; // 米
|
const distance = turf.distance(center.geometry.coordinates, point, {units: 'kilometers'}) * 1000 // 米
|
||||||
// 将多边形图形添加到地图层
|
// 将多边形图形添加到地图层
|
||||||
this.accordFactoryInfo.push({
|
this.accordFactoryInfo.push({
|
||||||
...graphic,
|
...graphic,
|
||||||
distance: distance,
|
distance: distance,
|
||||||
popupPosition: popupPosition,
|
popupPosition: popupPosition,
|
||||||
area: this.hideform.redundancy && this.hideform.redundancy != 0 && area > 0
|
area:
|
||||||
? area * (100 - this.hideform.redundancy) * 0.01
|
this.hideform.redundancy && this.hideform.redundancy != 0 && area > 0
|
||||||
: area > 0
|
? area * (100 - this.hideform.redundancy) * 0.01
|
||||||
? area
|
: area > 0
|
||||||
: 0, // 如果 area 不是有效值,设置为 0 或其他默认值
|
? area
|
||||||
|
: 0, // 如果 area 不是有效值,设置为 0 或其他默认值
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
// 显示面积信息弹框的方法
|
// 显示面积信息弹框的方法
|
||||||
async showAreaInfoDialog(info) {
|
async showAreaInfoDialog(info) {
|
||||||
const graphics = this.accordFactoryLayer.getGraphics();
|
const graphics = this.accordFactoryLayer.getGraphics()
|
||||||
const promises = [];
|
const promises = []
|
||||||
info.forEach((item) => {
|
info.forEach((item) => {
|
||||||
graphics.forEach((ele) => {
|
graphics.forEach((ele) => {
|
||||||
if (ele.options.time === item.options.time && ele.options.style.properties.FID_1 === item.options.style.properties.FID_1) {
|
if (
|
||||||
const textInfo = `${item.area.toFixed(2)}㎡ \n(${item.vehicles.map(e => e.name).join(',')})`
|
ele.options.time === item.options.time &&
|
||||||
|
ele.options.style.properties.FID_1 === item.options.style.properties.FID_1
|
||||||
|
) {
|
||||||
|
const textInfo = `${item.area.toFixed(2)}㎡ \n(${item.vehicles.map((e) => e.name).join(',')})`
|
||||||
const labelGraphic = new window.mars3d.graphic.LabelEntity({
|
const labelGraphic = new window.mars3d.graphic.LabelEntity({
|
||||||
id: 'label',
|
id: 'label',
|
||||||
position: item.popupPosition,
|
position: item.popupPosition,
|
||||||
@ -781,34 +768,34 @@ export default {
|
|||||||
outlineColor: '#000000',
|
outlineColor: '#000000',
|
||||||
background: true,
|
background: true,
|
||||||
backgroundColor: '#2f705f',
|
backgroundColor: '#2f705f',
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
// 使用 Promise 确保标签添加完成后继续执行
|
// 使用 Promise 确保标签添加完成后继续执行
|
||||||
const promise = new Promise((resolve, reject) => {
|
const promise = new Promise((resolve, reject) => {
|
||||||
this.accordFactoryLayer.addGraphic(labelGraphic, () => {
|
this.accordFactoryLayer.addGraphic(labelGraphic, () => {
|
||||||
resolve();
|
resolve()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|
||||||
promises.push(promise);
|
promises.push(promise)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
this.$message.success("路线隐蔽规划成功")
|
this.$message.success('路线隐蔽规划成功')
|
||||||
const popupPositionList = info.map(item => item.popupPosition)
|
const popupPositionList = info.map((item) => item.popupPosition)
|
||||||
let minLng = Infinity;
|
let minLng = Infinity
|
||||||
let maxLng = -Infinity;
|
let maxLng = -Infinity
|
||||||
let minLat = Infinity;
|
let minLat = Infinity
|
||||||
let maxLat = -Infinity;
|
let maxLat = -Infinity
|
||||||
|
|
||||||
popupPositionList.forEach(point => {
|
popupPositionList.forEach((point) => {
|
||||||
if (point.lng < minLng) minLng = point.lng;
|
if (point.lng < minLng) minLng = point.lng
|
||||||
if (point.lng > maxLng) maxLng = point.lng;
|
if (point.lng > maxLng) maxLng = point.lng
|
||||||
if (point.lat < minLat) minLat = point.lat;
|
if (point.lat < minLat) minLat = point.lat
|
||||||
if (point.lat > maxLat) maxLat = point.lat;
|
if (point.lat > maxLat) maxLat = point.lat
|
||||||
});
|
})
|
||||||
// 创建一个矩形区域,包含所有点
|
// 创建一个矩形区域,包含所有点
|
||||||
const rectangle = Cesium.Rectangle.fromDegrees(minLng, minLat, maxLng, maxLat);
|
const rectangle = Cesium.Rectangle.fromDegrees(minLng, minLat, maxLng, maxLat)
|
||||||
|
|
||||||
this.viewer.scene.camera.flyTo({
|
this.viewer.scene.camera.flyTo({
|
||||||
destination: Cesium.Cartesian3.fromDegrees(
|
destination: Cesium.Cartesian3.fromDegrees(
|
||||||
@ -819,29 +806,29 @@ export default {
|
|||||||
orientation: {
|
orientation: {
|
||||||
heading: Cesium.Math.toRadians(0), // 方位角
|
heading: Cesium.Math.toRadians(0), // 方位角
|
||||||
pitch: Cesium.Math.toRadians(-90), // 俯仰角
|
pitch: Cesium.Math.toRadians(-90), // 俯仰角
|
||||||
roll: 0.0 // 翻滚角
|
roll: 0.0, // 翻滚角
|
||||||
},
|
},
|
||||||
duration: 2 // 飞行动画持续时间,单位为秒
|
duration: 2, // 飞行动画持续时间,单位为秒
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
// 弹框
|
// 弹框
|
||||||
async openDialog() {
|
async openDialog() {
|
||||||
this.multipleSelection = []
|
this.multipleSelection = []
|
||||||
await fetch('./data/minTurnRadius.json')
|
await fetch('./data/minTurnRadius.json')
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
return response.json()
|
return response.json()
|
||||||
})
|
})
|
||||||
.then(async (data) => {
|
.then(async (data) => {
|
||||||
this.dialogVisible = true;
|
this.dialogVisible = true
|
||||||
this.tableData = data
|
this.tableData = data
|
||||||
await this.$nextTick(() => {
|
await this.$nextTick(() => {
|
||||||
this.multipleSelection = JSON.parse(Cookies.get('minTurnRadius'))
|
this.multipleSelection = JSON.parse(Cookies.get('minTurnRadius'))
|
||||||
this.multipleSelection.forEach((item) => {
|
this.multipleSelection.forEach((item) => {
|
||||||
this.$refs.vxeTable.setCheckboxRowKey(item.id, true)
|
this.$refs.vxeTable.setCheckboxRowKey(item.id, true)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
.catch((error) => {})
|
||||||
.catch((error) => {})
|
|
||||||
},
|
},
|
||||||
handleSelectionChange({records}) {
|
handleSelectionChange({records}) {
|
||||||
this.multipleSelection = records
|
this.multipleSelection = records
|
||||||
@ -879,35 +866,39 @@ export default {
|
|||||||
load: null,
|
load: null,
|
||||||
minTurnRadius: null,
|
minTurnRadius: null,
|
||||||
editing: true,
|
editing: true,
|
||||||
};
|
}
|
||||||
this.tableData.push(newRow);
|
this.tableData.push(newRow)
|
||||||
},
|
},
|
||||||
handleDelete(row) {
|
handleDelete(row) {
|
||||||
const index = this.tableData.findIndex(item => item.id === row.id);
|
const index = this.tableData.findIndex((item) => item.id === row.id)
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
this.tableData.splice(index, 1);
|
this.tableData.splice(index, 1)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleEdit(row) {
|
handleEdit(row) {
|
||||||
this.$set(row, 'editing', true);
|
this.$set(row, 'editing', true)
|
||||||
},
|
},
|
||||||
handleSave(row) {
|
handleSave(row) {
|
||||||
this.$set(row, 'editing', false);
|
this.$set(row, 'editing', false)
|
||||||
},
|
},
|
||||||
// 保存列表数据
|
// 保存列表数据
|
||||||
suerCofirm() {
|
suerCofirm() {
|
||||||
const parsedData = iniParser.parse(configIni);
|
const parsedData = iniParser.parse(configIni)
|
||||||
axios.post(`http://${parsedData.http.address}:${parsedData.http.port}/api/equpment`, JSON.stringify(this.tableData), {
|
axios
|
||||||
headers: {
|
.post(
|
||||||
'Authorization': 'Bearer your_token_here',
|
`http://${parsedData.http.address}:${parsedData.http.port}/api/equpment`,
|
||||||
'Content-Type': 'application/json'
|
JSON.stringify(this.tableData),
|
||||||
}
|
{
|
||||||
})
|
headers: {
|
||||||
.then(response => {
|
Authorization: 'Bearer your_token_here',
|
||||||
this.$message.success('保存成功')
|
'Content-Type': 'application/json',
|
||||||
})
|
},
|
||||||
.catch(error => {
|
}
|
||||||
});
|
)
|
||||||
|
.then((response) => {
|
||||||
|
this.$message.success('保存成功')
|
||||||
|
})
|
||||||
|
.catch((error) => {})
|
||||||
},
|
},
|
||||||
// 导入json文件
|
// 导入json文件
|
||||||
triggerFileUpload() {
|
triggerFileUpload() {
|
||||||
@ -974,21 +965,12 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
addPointToMap(type, point, time) {
|
addPointToMap(type, point, time) {
|
||||||
const coords = time
|
const coords = time ? point.points.split(',').map(Number) : point.split(',').map(Number)
|
||||||
? point.points.split(',').map(Number)
|
|
||||||
: point.split(',').map(Number)
|
|
||||||
const graphic = new window.mars3d.graphic.PointEntity({
|
const graphic = new window.mars3d.graphic.PointEntity({
|
||||||
position: new window.mars3d.LngLatPoint(coords[0], coords[1]),
|
position: new window.mars3d.LngLatPoint(coords[0], coords[1]),
|
||||||
style: {
|
style: {
|
||||||
pixelSize: 10,
|
pixelSize: 10,
|
||||||
color:
|
color: type === 'startPoint' ? 'red' : type === 'endPoint' ? 'red' : type === 'viaPoints' ? 'blue' : 'orange',
|
||||||
type === 'startPoint'
|
|
||||||
? 'red'
|
|
||||||
: type === 'endPoint'
|
|
||||||
? 'red'
|
|
||||||
: type === 'viaPoints'
|
|
||||||
? 'blue'
|
|
||||||
: 'orange',
|
|
||||||
label: {
|
label: {
|
||||||
text:
|
text:
|
||||||
type === 'startPoint'
|
type === 'startPoint'
|
||||||
@ -1022,9 +1004,7 @@ export default {
|
|||||||
addPolygonToMap(type, area, time) {
|
addPolygonToMap(type, area, time) {
|
||||||
const coords = JSON.parse(area.points)
|
const coords = JSON.parse(area.points)
|
||||||
const graphic = new window.mars3d.graphic.PolygonEntity({
|
const graphic = new window.mars3d.graphic.PolygonEntity({
|
||||||
positions: coords.map(
|
positions: coords.map((coord) => new window.mars3d.LngLatPoint(coord[0], coord[1])),
|
||||||
(coord) => new window.mars3d.LngLatPoint(coord[0], coord[1])
|
|
||||||
),
|
|
||||||
style: {
|
style: {
|
||||||
color: 'red',
|
color: 'red',
|
||||||
opacity: 0.4,
|
opacity: 0.4,
|
||||||
@ -1079,94 +1059,55 @@ export default {
|
|||||||
}
|
}
|
||||||
} else if (type === 'viaPoints') {
|
} else if (type === 'viaPoints') {
|
||||||
if (!row.points) {
|
if (!row.points) {
|
||||||
const graphic = this.viaPoints.find(
|
const graphic = this.viaPoints.find((viaPoint) => viaPoint.style.time === row.time)
|
||||||
(viaPoint) => viaPoint.style.time === row.time
|
if (this.form.viaPoints.length === 1 && this.form.viaPoints[0].points === '') {
|
||||||
)
|
|
||||||
if (
|
|
||||||
this.form.viaPoints.length === 1 &&
|
|
||||||
this.form.viaPoints[0].points === ''
|
|
||||||
) {
|
|
||||||
// 如果只剩下一个空项,不删除图形,清空输入框值
|
// 如果只剩下一个空项,不删除图形,清空输入框值
|
||||||
this.form.viaPoints[0].points = ''
|
this.form.viaPoints[0].points = ''
|
||||||
graphic?.remove()
|
graphic?.remove()
|
||||||
this.viaPoints = this.viaPoints.filter(
|
this.viaPoints = this.viaPoints.filter((viaPoint) => viaPoint.style.time !== row.time)
|
||||||
(viaPoint) => viaPoint.style.time !== row.time
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
this.form.viaPoints = this.form.viaPoints.filter(
|
this.form.viaPoints = this.form.viaPoints.filter((viaPoint) => viaPoint.time !== row.time)
|
||||||
(viaPoint) => viaPoint.time !== row.time
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
graphic?.remove()
|
graphic?.remove()
|
||||||
this.viaPoints = this.viaPoints.filter(
|
this.viaPoints = this.viaPoints.filter((viaPoint) => viaPoint.style.time !== row.time)
|
||||||
(viaPoint) => viaPoint.style.time !== row.time
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
const graphic = this.viaPoints.find(
|
const graphic = this.viaPoints.find((viaPoint) => viaPoint.style.time === row.time)
|
||||||
(viaPoint) => viaPoint.style.time === row.time
|
|
||||||
)
|
|
||||||
this.updatePointPosition(graphic, row.points)
|
this.updatePointPosition(graphic, row.points)
|
||||||
}
|
}
|
||||||
} else if (type === 'avoidPoints') {
|
} else if (type === 'avoidPoints') {
|
||||||
if (!row.points) {
|
if (!row.points) {
|
||||||
const graphic = this.avoidPoints.find(
|
const graphic = this.avoidPoints.find((avoidPoint) => avoidPoint.style.time === row.time)
|
||||||
(avoidPoint) => avoidPoint.style.time === row.time
|
if (this.form.avoidPoints.length === 1 && this.form.avoidPoints[0].points === '') {
|
||||||
)
|
|
||||||
if (
|
|
||||||
this.form.avoidPoints.length === 1 &&
|
|
||||||
this.form.avoidPoints[0].points === ''
|
|
||||||
) {
|
|
||||||
// 如果只剩下一个空项,不删除图形,清空输入框值
|
// 如果只剩下一个空项,不删除图形,清空输入框值
|
||||||
this.form.avoidPoints[0].points = ''
|
this.form.avoidPoints[0].points = ''
|
||||||
} else {
|
} else {
|
||||||
this.form.avoidPoints = this.form.avoidPoints.filter(
|
this.form.avoidPoints = this.form.avoidPoints.filter((avoidPoint) => avoidPoint.time !== row.time)
|
||||||
(avoidPoint) => avoidPoint.time !== row.time
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
graphic?.remove()
|
graphic?.remove()
|
||||||
this.avoidPoints = this.avoidPoints.filter(
|
this.avoidPoints = this.avoidPoints.filter((avoidPoint) => avoidPoint.style.time !== row.time)
|
||||||
(avoidPoint) => avoidPoint.style.time !== row.time
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
const graphic = this.avoidPoints.find(
|
const graphic = this.avoidPoints.find((avoidPoint) => avoidPoint.style.time === row.time)
|
||||||
(avoidPoint) => avoidPoint.style.time === row.time
|
|
||||||
)
|
|
||||||
this.updatePointPosition(graphic, row.points)
|
this.updatePointPosition(graphic, row.points)
|
||||||
}
|
}
|
||||||
} else if (type === 'avoidAreas') {
|
} else if (type === 'avoidAreas') {
|
||||||
if (!row.points) {
|
if (!row.points) {
|
||||||
const graphic = this.avoidAreas.find(
|
const graphic = this.avoidAreas.find((avoidArea) => avoidArea.style.time === row.time)
|
||||||
(avoidArea) => avoidArea.style.time === row.time
|
if (this.form.avoidAreas.length === 1 && this.form.avoidAreas[0].points === '') {
|
||||||
)
|
|
||||||
if (
|
|
||||||
this.form.avoidAreas.length === 1 &&
|
|
||||||
this.form.avoidAreas[0].points === ''
|
|
||||||
) {
|
|
||||||
// 如果只剩下一个空项,不删除图形,清空输入框值
|
// 如果只剩下一个空项,不删除图形,清空输入框值
|
||||||
this.form.avoidAreas[0].points = ''
|
this.form.avoidAreas[0].points = ''
|
||||||
} else {
|
} else {
|
||||||
this.form.avoidAreas = this.form.avoidAreas.filter(
|
this.form.avoidAreas = this.form.avoidAreas.filter((avoidArea) => avoidArea.time !== row.time)
|
||||||
(avoidArea) => avoidArea.time !== row.time
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
graphic?.remove()
|
graphic?.remove()
|
||||||
this.avoidAreas = this.avoidAreas.filter(
|
this.avoidAreas = this.avoidAreas.filter((avoidArea) => avoidArea.style.time !== row.time)
|
||||||
(avoidArea) => avoidArea.style.time !== row.time
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
const graphic = this.avoidAreas.find(
|
const graphic = this.avoidAreas.find((avoidArea) => avoidArea.style.time === row.time)
|
||||||
(avoidArea) => avoidArea.style.time === row.time
|
|
||||||
)
|
|
||||||
this.updatePolygonPosition(graphic, row.points)
|
this.updatePolygonPosition(graphic, row.points)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleEmptyArray(type) {
|
handleEmptyArray(type) {
|
||||||
if (
|
if (type === 'viaPoints' && this.form.viaPoints.length === 1 && this.form.viaPoints[0].points === '') {
|
||||||
type === 'viaPoints' &&
|
|
||||||
this.form.viaPoints.length === 1 &&
|
|
||||||
this.form.viaPoints[0].points === ''
|
|
||||||
) {
|
|
||||||
this.form.viaPoints = []
|
this.form.viaPoints = []
|
||||||
} else if (
|
} else if (
|
||||||
type === 'avoidPoints' &&
|
type === 'avoidPoints' &&
|
||||||
@ -1174,11 +1115,7 @@ export default {
|
|||||||
this.form.avoidPoints[0].points === ''
|
this.form.avoidPoints[0].points === ''
|
||||||
) {
|
) {
|
||||||
this.form.avoidPoints = []
|
this.form.avoidPoints = []
|
||||||
} else if (
|
} else if (type === 'avoidAreas' && this.form.avoidAreas.length === 1 && this.form.avoidAreas[0].points === '') {
|
||||||
type === 'avoidAreas' &&
|
|
||||||
this.form.avoidAreas.length === 1 &&
|
|
||||||
this.form.avoidAreas[0].points === ''
|
|
||||||
) {
|
|
||||||
this.form.avoidAreas = []
|
this.form.avoidAreas = []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1193,9 +1130,7 @@ export default {
|
|||||||
if (!graphic) return
|
if (!graphic) return
|
||||||
try {
|
try {
|
||||||
const coords = JSON.parse(pointsStr)
|
const coords = JSON.parse(pointsStr)
|
||||||
graphic.positions = coords.map(
|
graphic.positions = coords.map((coord) => new window.mars3d.LngLatPoint(coord[0], coord[1]))
|
||||||
(coord) => new window.mars3d.LngLatPoint(coord[0], coord[1])
|
|
||||||
)
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
graphic.remove()
|
graphic.remove()
|
||||||
}
|
}
|
||||||
@ -1350,9 +1285,7 @@ export default {
|
|||||||
success: (graphic) => {
|
success: (graphic) => {
|
||||||
this.avoidAreas.push(graphic)
|
this.avoidAreas.push(graphic)
|
||||||
const avoidAreasGeoJSON = graphic.toGeoJSON()
|
const avoidAreasGeoJSON = graphic.toGeoJSON()
|
||||||
const points = JSON.stringify(
|
const points = JSON.stringify(avoidAreasGeoJSON.geometry.coordinates[0])
|
||||||
avoidAreasGeoJSON.geometry.coordinates[0]
|
|
||||||
)
|
|
||||||
if (
|
if (
|
||||||
this.form.avoidAreas.length == 1 &&
|
this.form.avoidAreas.length == 1 &&
|
||||||
this.form.avoidAreas[0].points == '' &&
|
this.form.avoidAreas[0].points == '' &&
|
||||||
@ -1385,11 +1318,8 @@ export default {
|
|||||||
}
|
}
|
||||||
// 计算边权重(距离,单位:米)
|
// 计算边权重(距离,单位:米)
|
||||||
const distance =
|
const distance =
|
||||||
turf.distance(
|
turf.distance(turf.point(coords[0][0]), turf.point(coords[coords.length - 1][0]), {units: 'kilometers'}) *
|
||||||
turf.point(coords[0][0]),
|
1000
|
||||||
turf.point(coords[coords.length - 1][0]),
|
|
||||||
{units: 'kilometers'}
|
|
||||||
) * 1000
|
|
||||||
|
|
||||||
// 构建邻接表(双向图)
|
// 构建邻接表(双向图)
|
||||||
graph[startNode] = graph[startNode] || {}
|
graph[startNode] = graph[startNode] || {}
|
||||||
@ -1418,22 +1348,17 @@ export default {
|
|||||||
return nearestNode
|
return nearestNode
|
||||||
},
|
},
|
||||||
// 3. 路径规划主函数(经纬度坐标输入) - 支持途经点 + 避让点/区域
|
// 3. 路径规划主函数(经纬度坐标输入) - 支持途经点 + 避让点/区域
|
||||||
async planRoute(
|
async planRoute(startCoord, endCoord, viaPoints = [], avoidObstacles = null) {
|
||||||
startCoord,
|
|
||||||
endCoord,
|
|
||||||
viaPoints = [],
|
|
||||||
avoidObstacles = null
|
|
||||||
) {
|
|
||||||
const {graph, nodeCoords} = this.roadNetworkGeoJSONBuild
|
const {graph, nodeCoords} = this.roadNetworkGeoJSONBuild
|
||||||
|
|
||||||
// 按顺序组合点:起点 -> 途经点 -> 终点
|
// 按顺序组合点:起点 -> 途经点 -> 终点
|
||||||
const points = [startCoord];
|
const points = [startCoord]
|
||||||
if (viaPoints && viaPoints.length > 0) {
|
if (viaPoints && viaPoints.length > 0) {
|
||||||
viaPoints.forEach((viaPoint) => {
|
viaPoints.forEach((viaPoint) => {
|
||||||
points.push(viaPoint.geometry.coordinates);
|
points.push(viaPoint.geometry.coordinates)
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
points.push(endCoord);
|
points.push(endCoord)
|
||||||
const fullPath = []
|
const fullPath = []
|
||||||
const infoList = []
|
const infoList = []
|
||||||
for (let i = 0; i < points.length - 1; i++) {
|
for (let i = 0; i < points.length - 1; i++) {
|
||||||
@ -1457,8 +1382,7 @@ export default {
|
|||||||
for (const [node, coord] of Object.entries(nodeCoords)) {
|
for (const [node, coord] of Object.entries(nodeCoords)) {
|
||||||
const pt = turf.point(coord)
|
const pt = turf.point(coord)
|
||||||
avoidObstacles.features.forEach((ob) => {
|
avoidObstacles.features.forEach((ob) => {
|
||||||
if (turf.booleanPointInPolygon(pt.geometry, ob.geometry))
|
if (turf.booleanPointInPolygon(pt.geometry, ob.geometry)) obstacleNodes.push(node)
|
||||||
obstacleNodes.push(node)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
obstacleNodes.forEach((node) => delete tempGraph[node])
|
obstacleNodes.forEach((node) => delete tempGraph[node])
|
||||||
@ -1471,10 +1395,7 @@ export default {
|
|||||||
delete tempGraph[node][targetNode]
|
delete tempGraph[node][targetNode]
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
const line = turf.lineString([
|
const line = turf.lineString([nodeCoords[node], nodeCoords[targetNode]])
|
||||||
nodeCoords[node],
|
|
||||||
nodeCoords[targetNode],
|
|
||||||
])
|
|
||||||
avoidObstacles.features.forEach((area) => {
|
avoidObstacles.features.forEach((area) => {
|
||||||
if (turf.booleanCrosses(line, area)) {
|
if (turf.booleanCrosses(line, area)) {
|
||||||
delete tempGraph[node][targetNode]
|
delete tempGraph[node][targetNode]
|
||||||
@ -1500,21 +1421,17 @@ export default {
|
|||||||
if (!this.join) {
|
if (!this.join) {
|
||||||
segment = this.roadNetworkGeoJSON.features.find(
|
segment = this.roadNetworkGeoJSON.features.find(
|
||||||
(f) =>
|
(f) =>
|
||||||
(f.properties.FNODE_ == currentNode &&
|
(f.properties.FNODE_ == currentNode && f.properties.TNODE_ == nextNode) ||
|
||||||
f.properties.TNODE_ == nextNode) ||
|
(f.properties.FNODE_ == nextNode && f.properties.TNODE_ == currentNode)
|
||||||
(f.properties.FNODE_ == nextNode &&
|
|
||||||
f.properties.TNODE_ == currentNode)
|
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
segment = this.roadNetworkGeoJSON.features.find(
|
segment = this.roadNetworkGeoJSON.features.find(
|
||||||
(f) =>
|
(f) =>
|
||||||
((f.properties.FNODE_ == currentNode &&
|
((f.properties.FNODE_ == currentNode && f.properties.TNODE_ == nextNode) ||
|
||||||
f.properties.TNODE_ == nextNode) ||
|
(f.properties.FNODE_ == nextNode && f.properties.TNODE_ == currentNode)) &&
|
||||||
(f.properties.FNODE_ == nextNode &&
|
f.properties.载重吨 >= this.inputform.load &&
|
||||||
f.properties.TNODE_ == currentNode) ) &&
|
f.properties.宽度 >= this.inputform.width &&
|
||||||
f.properties.载重吨 >= this.inputform.load &&
|
f.properties.曲率半 <= this.inputform.minTurnRadius
|
||||||
f.properties.宽度 >= this.inputform.width &&
|
|
||||||
f.properties.曲率半 <= this.inputform.minTurnRadius
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (segment) {
|
if (segment) {
|
||||||
@ -1534,20 +1451,13 @@ export default {
|
|||||||
this.shortestPathLayer.clear()
|
this.shortestPathLayer.clear()
|
||||||
this.shortestPathList = []
|
this.shortestPathList = []
|
||||||
this.infoList = []
|
this.infoList = []
|
||||||
const startPoint = turf.point(
|
const startPoint = turf.point(this.pointQD.toGeoJSON().geometry.coordinates).geometry.coordinates // 起点
|
||||||
this.pointQD.toGeoJSON().geometry.coordinates
|
const endPoint = turf.point(this.pointZD.toGeoJSON().geometry.coordinates).geometry.coordinates // 终点
|
||||||
).geometry.coordinates // 起点
|
|
||||||
const endPoint = turf.point(this.pointZD.toGeoJSON().geometry.coordinates)
|
|
||||||
.geometry.coordinates // 终点
|
|
||||||
// 途经点
|
// 途经点
|
||||||
const viaPointsGeoJSON =
|
const viaPointsGeoJSON = this.viaPoints.map((point) => point.toGeoJSON()) || []
|
||||||
this.viaPoints.map((point) => point.toGeoJSON()) || []
|
const viaPointsTurf = viaPointsGeoJSON.map((p) => turf.point(p.geometry.coordinates))
|
||||||
const viaPointsTurf = viaPointsGeoJSON.map((p) =>
|
|
||||||
turf.point(p.geometry.coordinates)
|
|
||||||
)
|
|
||||||
// 避让点
|
// 避让点
|
||||||
const avoidPointsGeoJSON =
|
const avoidPointsGeoJSON = this.avoidPoints.map((point) => point.toGeoJSON()) || []
|
||||||
this.avoidPoints.map((point) => point.toGeoJSON()) || []
|
|
||||||
const avoidPointsPolygons = avoidPointsGeoJSON.map((point) => {
|
const avoidPointsPolygons = avoidPointsGeoJSON.map((point) => {
|
||||||
return turf.circle(
|
return turf.circle(
|
||||||
turf.point(point.geometry.coordinates),
|
turf.point(point.geometry.coordinates),
|
||||||
@ -1556,18 +1466,9 @@ export default {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
// 避让区域
|
// 避让区域
|
||||||
const avoidAreasGeoJSON =
|
const avoidAreasGeoJSON = this.avoidAreas.map((area) => area.toGeoJSON({closure: true})) || []
|
||||||
this.avoidAreas.map((area) => area.toGeoJSON({closure: true})) || []
|
const obstaclesGeoJSON = turf.featureCollection([...avoidPointsPolygons, ...avoidAreasGeoJSON])
|
||||||
const obstaclesGeoJSON = turf.featureCollection([
|
const route = await this.planRoute(startPoint, endPoint, viaPointsTurf, obstaclesGeoJSON)
|
||||||
...avoidPointsPolygons,
|
|
||||||
...avoidAreasGeoJSON,
|
|
||||||
])
|
|
||||||
const route = await this.planRoute(
|
|
||||||
startPoint,
|
|
||||||
endPoint,
|
|
||||||
viaPointsTurf,
|
|
||||||
obstaclesGeoJSON
|
|
||||||
)
|
|
||||||
this.drawPath(route)
|
this.drawPath(route)
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1588,9 +1489,7 @@ export default {
|
|||||||
this.infoList = path.infoList.map((item) => item.properties)
|
this.infoList = path.infoList.map((item) => item.properties)
|
||||||
},
|
},
|
||||||
/** 隐蔽规划 */
|
/** 隐蔽规划 */
|
||||||
concealed() {
|
concealed() {},
|
||||||
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@ -1664,14 +1563,14 @@ export default {
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
.control-panel .title .joinCheck {
|
.control-panel .title .joinCheck {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #555;
|
color: #555;
|
||||||
}
|
}
|
||||||
.el-checkbox {
|
.el-checkbox {
|
||||||
margin-right: 5px!important;
|
margin-right: 5px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.importJson {
|
.importJson {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@ -1721,6 +1620,4 @@ export default {
|
|||||||
.popDiloag .popDiloag-title {
|
.popDiloag .popDiloag-title {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
.popDiloag .popDiloag-p {
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user