2023-11-08 15:31:53 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<n-grid style="width: 96vw;" class="mx-auto" :cols="2">
|
2023-11-29 16:08:12 +08:00
|
|
|
|
<n-gi style="padding-top: 1.5vh; padding-bottom: 0;" class="w-h-full p">
|
|
|
|
|
|
<n-scrollbar style="max-height: 48vh; border: 1px solid #eee">
|
2023-11-08 15:31:53 +08:00
|
|
|
|
<n-dynamic-input
|
|
|
|
|
|
v-model:value="geodata"
|
|
|
|
|
|
:on-create="onCreate"
|
|
|
|
|
|
:on-remove="onRemove"
|
|
|
|
|
|
>
|
2023-11-29 16:08:12 +08:00
|
|
|
|
<template #default="{ value, index }">
|
2023-11-08 15:31:53 +08:00
|
|
|
|
<div style="display: flex; align-items: flex-start; width: 100%">
|
|
|
|
|
|
<div style="width: 50%">
|
|
|
|
|
|
<n-input maxlength="13" clearable v-model:value="value.lat" type="text" placeholder="经度" @input="handleInput" :status="value.latStatus" />
|
|
|
|
|
|
<n-gradient-text :size="12" type="error" v-show="value.latCheck">
|
2023-11-29 16:08:12 +08:00
|
|
|
|
<div v-html="value.latErrMsg"></div>
|
2023-11-08 15:31:53 +08:00
|
|
|
|
</n-gradient-text>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div style="width: 50%">
|
|
|
|
|
|
<n-input maxlength="12" clearable v-model:value="value.lng" type="text" placeholder="纬度" @input="handleInput" :status="value.lngStatus" />
|
|
|
|
|
|
<n-gradient-text :size="12" type="error" v-show="value.lngCheck">
|
2023-11-29 16:08:12 +08:00
|
|
|
|
<div v-html="value.lngErrMsg"></div>
|
2023-11-08 15:31:53 +08:00
|
|
|
|
</n-gradient-text>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2023-11-29 16:08:12 +08:00
|
|
|
|
<n-button style="padding: 0 5px;font-size: 24px;" @click="move('up', index)">
|
|
|
|
|
|
<n-icon>
|
|
|
|
|
|
<UpIcon />
|
|
|
|
|
|
</n-icon>
|
|
|
|
|
|
</n-button>
|
|
|
|
|
|
<n-button style="padding: 0 5px;font-size: 24px;" @click="move('down', index)">
|
|
|
|
|
|
<n-icon>
|
|
|
|
|
|
<DownIcon />
|
|
|
|
|
|
</n-icon>
|
|
|
|
|
|
</n-button>
|
2023-11-08 15:31:53 +08:00
|
|
|
|
</template>
|
|
|
|
|
|
</n-dynamic-input>
|
|
|
|
|
|
</n-scrollbar>
|
2023-11-29 16:08:12 +08:00
|
|
|
|
<v-chart style="max-height: 38vh; border: 1px solid #eee" class="chart" id="chart" :option="option" />
|
2023-11-08 15:31:53 +08:00
|
|
|
|
<div style="margin-top: 1vh;" class="w-full flex flex-1">
|
|
|
|
|
|
<n-button class="mx-auto" :disabled="geodata.length == 0 ? true : false" size="large" type="primary" @click="calculation">计 算</n-button>
|
|
|
|
|
|
<n-button class="mx-auto" :disabled="geodata.length == 0 ? true : false" size="large" type="error" @click="delgeo">清空输入</n-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</n-gi>
|
2023-11-29 16:08:12 +08:00
|
|
|
|
<n-gi style="padding-top: 1.5vh; padding-bottom: 0;" class="w-h-full p">
|
|
|
|
|
|
<n-data-table :columns="columns" :data="data" :single-line="false" :pagination="pagination" :style="{ height: '86vh' }" flex-height />
|
2023-11-08 15:31:53 +08:00
|
|
|
|
<div style="margin-top: 1vh;" class="w-full flex flex-1">
|
|
|
|
|
|
<div style="width: 128px" class="mx-auto">
|
|
|
|
|
|
<n-select v-model:value="unit" :options="options" />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<n-button class="mx-auto" :disabled="data.length == 0 ? true : false" size="large" type="error" @click="delall">清除数据</n-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</n-gi>
|
|
|
|
|
|
</n-grid>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
|
|
import { ref, h, watch, reactive } from "vue"
|
|
|
|
|
|
import * as echarts from "echarts"
|
|
|
|
|
|
import { use, registerMap } from "echarts/core"
|
|
|
|
|
|
import { CanvasRenderer } from 'echarts/renderers'
|
|
|
|
|
|
import { MapChart, ScatterChart } from 'echarts/charts'
|
|
|
|
|
|
import VChart from "vue-echarts"
|
2023-11-29 16:08:12 +08:00
|
|
|
|
import { NGi, NGrid, NButton, NDynamicInput, NDataTable, NScrollbar, NInput, NGradientText, NIcon, NSelect, useMessage, useDialog } from "naive-ui"
|
|
|
|
|
|
import { KeyboardArrowUpRound as UpIcon, KeyboardArrowDownRound as DownIcon } from '@vicons/material'
|
2023-11-08 15:31:53 +08:00
|
|
|
|
|
|
|
|
|
|
const message = useMessage()
|
|
|
|
|
|
|
|
|
|
|
|
const dialog = useDialog()
|
|
|
|
|
|
|
|
|
|
|
|
const geodata = ref([
|
|
|
|
|
|
{
|
|
|
|
|
|
lat: "",
|
|
|
|
|
|
latStatus: "",
|
|
|
|
|
|
latCheck: "",
|
2023-11-29 16:08:12 +08:00
|
|
|
|
latErrMsg:"",
|
2023-11-08 15:31:53 +08:00
|
|
|
|
lng: "",
|
|
|
|
|
|
lngStatus: "",
|
2023-11-29 16:08:12 +08:00
|
|
|
|
lngCheck: "",
|
|
|
|
|
|
lngErrMsg:""
|
2023-11-08 15:31:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
|
|
const onCreate = () => {
|
|
|
|
|
|
return {
|
|
|
|
|
|
lat: "",
|
|
|
|
|
|
latStatus: "",
|
|
|
|
|
|
latCheck: "",
|
2023-11-29 16:08:12 +08:00
|
|
|
|
latErrMsg:"",
|
2023-11-08 15:31:53 +08:00
|
|
|
|
lng: "",
|
|
|
|
|
|
lngStatus: "",
|
2023-11-29 16:08:12 +08:00
|
|
|
|
lngCheck: "",
|
|
|
|
|
|
lngErrMsg:""
|
2023-11-08 15:31:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const unit = ref('平方米/m²')
|
|
|
|
|
|
|
|
|
|
|
|
const options = [
|
|
|
|
|
|
{
|
|
|
|
|
|
label:"平方米/m²",
|
|
|
|
|
|
value:'平方米/m²'
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label:"平方千米/km²",
|
|
|
|
|
|
value:'平方千米/km²'
|
|
|
|
|
|
}]
|
2023-11-29 16:08:12 +08:00
|
|
|
|
|
|
|
|
|
|
const move = (updown, index) => {
|
|
|
|
|
|
let moveit
|
|
|
|
|
|
if(updown == 'up'){
|
|
|
|
|
|
if(index !== 0){
|
|
|
|
|
|
moveit = geodata.value[index]
|
|
|
|
|
|
geodata.value[index] = geodata.value[index - 1]
|
|
|
|
|
|
geodata.value[index - 1] = moveit
|
|
|
|
|
|
moveit = null
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if(updown == 'down'){
|
|
|
|
|
|
if(index !== geodata.value.length-1){
|
|
|
|
|
|
moveit = geodata.value[index]
|
|
|
|
|
|
geodata.value[index] = geodata.value[index + 1]
|
|
|
|
|
|
geodata.value[index + 1] = moveit
|
|
|
|
|
|
moveit = null
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-11-08 15:31:53 +08:00
|
|
|
|
|
|
|
|
|
|
const columns = ref([
|
|
|
|
|
|
{
|
|
|
|
|
|
title: '经纬度数据',
|
|
|
|
|
|
key: 'latandlng',
|
|
|
|
|
|
render (row) {
|
|
|
|
|
|
const tags = row.latandlng.map((DataTag) => {
|
|
|
|
|
|
return h(
|
|
|
|
|
|
NScrollbar,
|
|
|
|
|
|
{
|
|
|
|
|
|
style: {
|
|
|
|
|
|
whiteSpace: 'pre-wrap'
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
default: () => `经度:${DataTag[0]}\n纬度:${DataTag[1]}\n\n`
|
|
|
|
|
|
}
|
|
|
|
|
|
)
|
|
|
|
|
|
})
|
|
|
|
|
|
return tags
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
title: `面积(单位:${ unit.value })`,
|
|
|
|
|
|
key: 'area'
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
title: '轮廓',
|
|
|
|
|
|
key: 'operate',
|
|
|
|
|
|
fixed: 'right',
|
|
|
|
|
|
align: 'center',
|
|
|
|
|
|
render (row) {
|
|
|
|
|
|
return h(
|
|
|
|
|
|
NButton,
|
|
|
|
|
|
{
|
|
|
|
|
|
strong: true,
|
|
|
|
|
|
tertiary: true,
|
|
|
|
|
|
size: 'large',
|
|
|
|
|
|
type: 'info',
|
|
|
|
|
|
onClick: () => drawContour(row)
|
|
|
|
|
|
},
|
|
|
|
|
|
{ default: () => '生成轮廓' }
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
title: '操作',
|
|
|
|
|
|
key: 'operate',
|
|
|
|
|
|
fixed: 'right',
|
|
|
|
|
|
align: 'center',
|
|
|
|
|
|
render (row) {
|
|
|
|
|
|
return h(
|
|
|
|
|
|
NButton,
|
|
|
|
|
|
{
|
|
|
|
|
|
strong: true,
|
|
|
|
|
|
tertiary: true,
|
|
|
|
|
|
size: 'large',
|
|
|
|
|
|
type: 'error',
|
|
|
|
|
|
onClick: () => deldata(row)
|
|
|
|
|
|
},
|
|
|
|
|
|
{ default: () => '删除' }
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|
|
|
|
|
|
}])
|
|
|
|
|
|
|
|
|
|
|
|
const data = ref([])
|
|
|
|
|
|
|
|
|
|
|
|
const geoObj = reactive({
|
|
|
|
|
|
"type":"FeatureCollection",
|
|
|
|
|
|
"features":[{
|
|
|
|
|
|
"type":"Feature",
|
|
|
|
|
|
"properties":{
|
|
|
|
|
|
"adcode":0,
|
|
|
|
|
|
"name":"经纬度数据",
|
|
|
|
|
|
"center":[0,0],
|
|
|
|
|
|
"centroid":[0,0],
|
|
|
|
|
|
"cp":[15,12],
|
|
|
|
|
|
"childrenNum":0,
|
|
|
|
|
|
"level":"city",
|
|
|
|
|
|
"acroutes":[0,0],
|
|
|
|
|
|
"parent":{"adcode":0}
|
|
|
|
|
|
},
|
|
|
|
|
|
"geometry":{
|
|
|
|
|
|
"type":"MultiPolygon",
|
|
|
|
|
|
"coordinates":[[[[15,30],[0,0],[15,10],[30,0]]]]
|
|
|
|
|
|
}
|
|
|
|
|
|
}]
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
use([ CanvasRenderer, MapChart, ScatterChart ])
|
|
|
|
|
|
registerMap('nowin',geoObj)
|
|
|
|
|
|
const option = reactive({
|
|
|
|
|
|
geo: [
|
|
|
|
|
|
{
|
|
|
|
|
|
zlevel:3,
|
|
|
|
|
|
map: 'nowin',
|
|
|
|
|
|
label: {
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
color: 'black',
|
|
|
|
|
|
fontSize: 18
|
|
|
|
|
|
},
|
|
|
|
|
|
itemStyle: {
|
|
|
|
|
|
normal: {
|
|
|
|
|
|
areaColor: '#26c4eb',
|
|
|
|
|
|
shadowColor:"#01273F",
|
|
|
|
|
|
shadowOffsetX: 0,
|
|
|
|
|
|
shadowOffsetY: 0,
|
|
|
|
|
|
borderWidth:0.5,
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
],
|
|
|
|
|
|
series: [{
|
|
|
|
|
|
//设置为分散点
|
|
|
|
|
|
type: 'scatter',
|
|
|
|
|
|
//series坐标系类型
|
|
|
|
|
|
coordinateSystem: 'geo',
|
|
|
|
|
|
//设置图形 'circle', 'rect', 'roundRect', 'triangle', 'diamond', 'pin', 'arrow'
|
|
|
|
|
|
symbol: 'pin',
|
|
|
|
|
|
// //标记的大小,可以设置成诸如 10 这样单一的数字,也可以用数组分开表示宽和高,例如 [20, 10] 表示标记宽为20,高为10
|
|
|
|
|
|
symbolSize: [40,40],
|
|
|
|
|
|
//气泡字体设置
|
|
|
|
|
|
label: {
|
|
|
|
|
|
normal: {
|
|
|
|
|
|
show: false,//是否显示
|
|
|
|
|
|
textStyle: {
|
|
|
|
|
|
color: '#000',//字体颜色
|
|
|
|
|
|
fontSize: 8,//字体大小
|
|
|
|
|
|
},
|
|
|
|
|
|
//返回气泡数据
|
|
|
|
|
|
formatter (value){
|
|
|
|
|
|
return value.data.value[2]
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
itemStyle: {
|
|
|
|
|
|
normal: {
|
|
|
|
|
|
color: '#1E90FF', //标志颜色
|
|
|
|
|
|
areaColor: '#26c4eb',
|
|
|
|
|
|
borderWidth: 0.5,
|
|
|
|
|
|
borderColor: "#ffffff",
|
|
|
|
|
|
shadowColor:"#01273F",
|
|
|
|
|
|
shadowBlur: 6
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
// //给区域赋值
|
|
|
|
|
|
data: [],
|
|
|
|
|
|
showEffectOn: 'render',//配置何时显示特效。可选:'render' 绘制完成后显示特效。'emphasis' 高亮(hover)的时候显示特效。
|
|
|
|
|
|
rippleEffect: {//涟漪特效相关配置。
|
|
|
|
|
|
brushType: 'stroke'//波纹的绘制方式,可选 'stroke' 和 'fill'
|
|
|
|
|
|
},
|
|
|
|
|
|
hoverAnimation: true,//是否开启鼠标 hover 的提示动画效果。
|
|
|
|
|
|
zlevel: 3//所属图形的 zlevel 值
|
|
|
|
|
|
}]
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
window.addEventListener('resize', () => {
|
|
|
|
|
|
let chart = echarts.init(document.getElementById('chart'))
|
|
|
|
|
|
chart.resize()
|
|
|
|
|
|
})
|
|
|
|
|
|
|
2023-11-29 16:08:12 +08:00
|
|
|
|
const rerender = (mapName,mapArea,mapGeo,initialize) => {
|
2023-11-08 15:31:53 +08:00
|
|
|
|
if(mapGeo){
|
2023-11-29 16:08:12 +08:00
|
|
|
|
if(initialize){
|
|
|
|
|
|
geoObj.features[0].properties.cp = [15,12]
|
|
|
|
|
|
}
|
|
|
|
|
|
else{
|
|
|
|
|
|
geoObj.features[0].properties.cp = centerPoint(mapGeo)
|
|
|
|
|
|
}
|
2023-11-08 15:31:53 +08:00
|
|
|
|
geoObj.features[0].geometry.coordinates[0][0] = mapGeo
|
|
|
|
|
|
}
|
|
|
|
|
|
geoObj.features[0].properties.name = mapArea
|
|
|
|
|
|
registerMap(mapName, geoObj)
|
|
|
|
|
|
option.geo[0].map = mapName
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const onRemove = () => {
|
|
|
|
|
|
if(geodata.value.length < 3){
|
2023-11-29 16:08:12 +08:00
|
|
|
|
rerender('nowin','经纬度数据',[[15,30],[0,0],[15,10],[30,0]],true)
|
2023-11-08 15:31:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const inputFilter = (inputData) => {
|
|
|
|
|
|
let infilter = []
|
|
|
|
|
|
let beffilter = [...inputData]
|
|
|
|
|
|
beffilter.forEach(item => {
|
|
|
|
|
|
if(item !== '\u00A0' && item !== '\u0020' && item !== '\u3000'){
|
|
|
|
|
|
if(!isNaN(Number(item))){
|
|
|
|
|
|
infilter.push(item)
|
2023-11-29 16:08:12 +08:00
|
|
|
|
}
|
|
|
|
|
|
else if(item == '.'){
|
2023-11-08 15:31:53 +08:00
|
|
|
|
if(infilter.indexOf('.') == '-1'){
|
|
|
|
|
|
infilter.push(item)
|
|
|
|
|
|
}
|
2023-11-29 16:08:12 +08:00
|
|
|
|
}
|
|
|
|
|
|
else if(item == '-'){
|
2023-11-08 15:31:53 +08:00
|
|
|
|
if(infilter.indexOf('-') == '-1'){
|
|
|
|
|
|
infilter.push(item)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
return infilter.join('')
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-11-29 16:08:12 +08:00
|
|
|
|
const stuck = (dataObj,dataItem,Status,Check,ErrMsg,throwMsg) => {
|
|
|
|
|
|
dataObj[dataItem + 'Status'] = Status
|
|
|
|
|
|
dataObj[dataItem + 'Check'] = Check
|
|
|
|
|
|
dataObj[dataItem + 'ErrMsg'] = ErrMsg
|
|
|
|
|
|
if(throwMsg){
|
|
|
|
|
|
message.error(ErrMsg)
|
|
|
|
|
|
throw new Error(ErrMsg)
|
|
|
|
|
|
}
|
2023-11-08 15:31:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-11-29 16:08:12 +08:00
|
|
|
|
const judgment = (dataObj,dataItem,ErrMsg,throwMsg) => {
|
|
|
|
|
|
let toJudgment
|
|
|
|
|
|
if(dataItem == 'lat'){
|
|
|
|
|
|
toJudgment = Number(dataObj[dataItem]).toFixed(8) > 180 || Number(dataObj[dataItem]).toFixed(8) < -180
|
2023-11-08 15:31:53 +08:00
|
|
|
|
}
|
2023-11-29 16:08:12 +08:00
|
|
|
|
else if(dataItem == "lng"){
|
|
|
|
|
|
toJudgment = Number(dataObj[dataItem]).toFixed(8) > 90 || Number(dataObj[dataItem]).toFixed(8) < -90
|
2023-11-08 15:31:53 +08:00
|
|
|
|
}
|
2023-11-29 16:08:12 +08:00
|
|
|
|
if(dataObj[dataItem] == ''){
|
|
|
|
|
|
stuck(dataObj,dataItem,'error',true,ErrMsg+'不能为空',throwMsg)
|
2023-11-08 15:31:53 +08:00
|
|
|
|
}
|
2023-11-29 16:08:12 +08:00
|
|
|
|
else if(dataObj[dataItem].indexOf('-') !== -1 && dataObj[dataItem].indexOf('-') !== 0 || dataObj[dataItem].indexOf('.') == dataObj[dataItem].length-1 || dataObj[dataItem].indexOf('-')+1 == dataObj[dataItem].indexOf('.')){
|
|
|
|
|
|
stuck(dataObj,dataItem,'error',true,ErrMsg+'数据格式错误',throwMsg)
|
2023-11-08 15:31:53 +08:00
|
|
|
|
}
|
2023-11-29 16:08:12 +08:00
|
|
|
|
else if(toJudgment){
|
|
|
|
|
|
stuck(dataObj,dataItem,'error',true,'非法的'+ErrMsg+'数据',throwMsg)
|
2023-11-08 15:31:53 +08:00
|
|
|
|
}
|
2023-11-29 16:08:12 +08:00
|
|
|
|
else{
|
|
|
|
|
|
stuck(dataObj,dataItem,'success',false,'',false)
|
|
|
|
|
|
if(throwMsg){
|
|
|
|
|
|
dataObj[dataItem] = Number(dataObj[dataItem]).toString()
|
|
|
|
|
|
}
|
2023-11-08 15:31:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-11-29 16:08:12 +08:00
|
|
|
|
const handleInput = () => {
|
|
|
|
|
|
geodata.value.forEach((element,index) => {
|
|
|
|
|
|
element.lat = inputFilter(element.lat)
|
|
|
|
|
|
element.lng = inputFilter(element.lng)
|
|
|
|
|
|
judgment(element,'lat','经度',false)
|
|
|
|
|
|
judgment(element,'lng','纬度',false)
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-11-08 15:31:53 +08:00
|
|
|
|
//地球赤道半径 6378.137
|
|
|
|
|
|
//地球平均半径 6371.004
|
|
|
|
|
|
//弧度转角度 Math.PI / 180.0
|
|
|
|
|
|
//角度转弧度 180.0 / Math.PI
|
|
|
|
|
|
//米转角度 2.0 * Math.PI * 6371.004 / 360.0
|
|
|
|
|
|
|
|
|
|
|
|
//需求决定了输入的经纬度距离不会太远,近似为求平面多边形的面积
|
|
|
|
|
|
const calculationArea = (points) => {
|
|
|
|
|
|
let area = 0
|
|
|
|
|
|
//将多边形分解为三角形
|
|
|
|
|
|
points.forEach((item,index) => {
|
|
|
|
|
|
let j = (index + 1) % points.length
|
|
|
|
|
|
let xi = points[index][0] * (2.0 * Math.PI * 6371004.0 / 360.0) * Math.cos(points[index][1] * (Math.PI / 180.0))
|
|
|
|
|
|
let yi = points[index][1] * (2.0 * Math.PI * 6371004.0 / 360.0)
|
|
|
|
|
|
let xj = points[j][0] * (2.0 * Math.PI * 6371004.0 / 360.0) * Math.cos(points[j][1] * (Math.PI / 180.0))
|
|
|
|
|
|
let yj = points[j][1] * (2.0 * Math.PI * 6371004.0 / 360.0)
|
|
|
|
|
|
area += xi * yj - xj * yi
|
|
|
|
|
|
})
|
|
|
|
|
|
//计算结果为平方米
|
|
|
|
|
|
if(unit.value == '平方米/m²'){
|
|
|
|
|
|
return Math.abs(area / 2).toFixed(4) + unit.value
|
|
|
|
|
|
}
|
|
|
|
|
|
else{
|
|
|
|
|
|
return (Math.abs(area / 2) / 1000000).toFixed(9) + unit.value
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const centerPoint = (allPoint) => {
|
|
|
|
|
|
let averagelat = 0
|
|
|
|
|
|
let averagelng = 0
|
|
|
|
|
|
allPoint.forEach(item => {
|
|
|
|
|
|
averagelat = Number(item[0]) + averagelat
|
|
|
|
|
|
averagelng = Number(item[1]) + averagelng
|
|
|
|
|
|
})
|
|
|
|
|
|
return [averagelat/allPoint.length,averagelng/allPoint.length]
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const diffData = (areaResult) => {
|
|
|
|
|
|
let allowCalaulation = true
|
|
|
|
|
|
data.value.forEach(items => {
|
|
|
|
|
|
if(items.latandlng.join(';') == areaResult.latandlng.join(';')){
|
|
|
|
|
|
allowCalaulation = false
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
if(allowCalaulation){
|
|
|
|
|
|
data.value.push(areaResult)
|
2023-11-29 16:08:12 +08:00
|
|
|
|
rerender('nowin','经纬度数据',[[15,30],[0,0],[15,10],[30,0]],true)
|
|
|
|
|
|
rerender('updataGeo',data.value[data.value.length-1].area,data.value[data.value.length-1].latandlng,false)
|
2023-11-08 15:31:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const calculation = () => {
|
|
|
|
|
|
if(geodata.value.length <= 2){
|
|
|
|
|
|
message.error('经纬度数据对的数量不能满足运算')
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
let pointArr = []
|
|
|
|
|
|
geodata.value.forEach((element,index) => {
|
2023-11-29 16:08:12 +08:00
|
|
|
|
judgment(element,'lat','经度',true)
|
|
|
|
|
|
judgment(element,'lng','纬度',true)
|
|
|
|
|
|
pointArr.push([element.lat.length>8?Number(element.lat).toFixed(8):Number(element.lat), element.lng.length>8?Number(element.lng).toFixed(8):Number(element.lng)])
|
2023-11-08 15:31:53 +08:00
|
|
|
|
})
|
|
|
|
|
|
let areaData = {
|
|
|
|
|
|
latandlng: pointArr,
|
|
|
|
|
|
area: calculationArea(pointArr)
|
|
|
|
|
|
}
|
|
|
|
|
|
diffData(areaData)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const delgeo = () => {
|
|
|
|
|
|
dialog.warning({
|
|
|
|
|
|
title: '警告',
|
|
|
|
|
|
content: '确定要清除全部输入吗?',
|
|
|
|
|
|
positiveText: '确定',
|
|
|
|
|
|
negativeText: '返回',
|
|
|
|
|
|
onPositiveClick: () => {
|
|
|
|
|
|
geodata.value = [
|
|
|
|
|
|
{
|
|
|
|
|
|
lat: "",
|
|
|
|
|
|
latStatus: "",
|
|
|
|
|
|
latCheck: "",
|
|
|
|
|
|
lng: "",
|
|
|
|
|
|
lngStatus: "",
|
|
|
|
|
|
lngCheck: ""
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
2023-11-29 16:08:12 +08:00
|
|
|
|
rerender('nowin','经纬度数据',[[15,30],[0,0],[15,10],[30,0]],true)
|
2023-11-08 15:31:53 +08:00
|
|
|
|
},
|
|
|
|
|
|
onNegativeClick: () => {
|
|
|
|
|
|
message.error('已返回')
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const drawContour = (row) => {
|
2023-11-29 16:08:12 +08:00
|
|
|
|
rerender('nowin','经纬度数据',[[15,30],[0,0],[15,10],[30,0]],true)
|
|
|
|
|
|
rerender('updataGeo',row.area,row.latandlng,false)
|
2023-11-08 15:31:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const deldata = (row) => {
|
|
|
|
|
|
data.value.filter((item,index,array)=>{
|
|
|
|
|
|
if(item == row){
|
|
|
|
|
|
array.splice(index,1)
|
|
|
|
|
|
if(data.value.length == 0){
|
2023-11-29 16:08:12 +08:00
|
|
|
|
rerender('nowin','经纬度数据',[[15,30],[0,0],[15,10],[30,0]],true)
|
2023-11-08 15:31:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const delall = () => {
|
|
|
|
|
|
dialog.warning({
|
|
|
|
|
|
title: '警告',
|
|
|
|
|
|
content: '确定要清除全部数据吗?',
|
|
|
|
|
|
positiveText: '确定',
|
|
|
|
|
|
negativeText: '返回',
|
|
|
|
|
|
onPositiveClick: () => {
|
|
|
|
|
|
data.value = []
|
2023-11-29 16:08:12 +08:00
|
|
|
|
rerender('nowin','经纬度数据',[[15,30],[0,0],[15,10],[30,0]],true)
|
2023-11-08 15:31:53 +08:00
|
|
|
|
},
|
|
|
|
|
|
onNegativeClick: () => {
|
|
|
|
|
|
message.error('已返回')
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
watch(unit,(value) => {
|
|
|
|
|
|
columns.value[1].title = `面积(单位:${ value })`
|
|
|
|
|
|
if(data.value.length !== 0){
|
|
|
|
|
|
data.value.forEach(element => {
|
|
|
|
|
|
if(value == '平方米/m²'){
|
|
|
|
|
|
rerender('updataGeo',element.area)
|
|
|
|
|
|
element.area = (element.area.slice(0,element.area.length-8) * 1000000).toFixed(4) + value
|
|
|
|
|
|
rerender('change',element.area)
|
|
|
|
|
|
}else{
|
|
|
|
|
|
rerender('updataGeo',element.area)
|
|
|
|
|
|
element.area = (element.area.slice(0,element.area.length-6) / 1000000).toFixed(9) + value
|
|
|
|
|
|
rerender('change',element.area)
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped lang="less">
|
|
|
|
|
|
.n-grid {
|
|
|
|
|
|
place-items: center
|
|
|
|
|
|
}
|
|
|
|
|
|
.p {
|
|
|
|
|
|
padding: 1%;
|
|
|
|
|
|
padding-top: 2%
|
|
|
|
|
|
}
|
|
|
|
|
|
.mt {
|
|
|
|
|
|
margin-top:2%
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|