顺时针路径排序
This commit is contained in:
@ -18,6 +18,8 @@
|
|||||||
"@amap/amap-jsapi-loader": "^1.0.1",
|
"@amap/amap-jsapi-loader": "^1.0.1",
|
||||||
"@element-plus/icons-vue": "2.0.10",
|
"@element-plus/icons-vue": "2.0.10",
|
||||||
"@highlightjs/vue-plugin": "^2.1.0",
|
"@highlightjs/vue-plugin": "^2.1.0",
|
||||||
|
"@turf/center": "^6.5.0",
|
||||||
|
"@turf/helpers": "^6.5.0",
|
||||||
"@vueuse/core": "9.5.0",
|
"@vueuse/core": "9.5.0",
|
||||||
"@wangeditor/editor": "^5.1.23",
|
"@wangeditor/editor": "^5.1.23",
|
||||||
"@wangeditor/editor-for-vue": "^5.1.12",
|
"@wangeditor/editor-for-vue": "^5.1.12",
|
||||||
|
15
src/utils/geoUtils.js
Normal file
15
src/utils/geoUtils.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import {points} from "@turf/helpers";
|
||||||
|
import center from "@turf/center";
|
||||||
|
|
||||||
|
// [[-97.522259, 35.4691],
|
||||||
|
// [-97.502754, 35.463455],
|
||||||
|
// [-97.508269, 35.463245]]
|
||||||
|
export const pointSortClockwise = (coordinates) => {
|
||||||
|
const centerCoor = center(points(coordinates)).geometry.coordinates;
|
||||||
|
return coordinates.sort((a, b) => {
|
||||||
|
// 转换为以 centerCoor 为原点的坐标
|
||||||
|
const point_a = [a[0] - centerCoor[0], a[1] - centerCoor[1]]
|
||||||
|
const point_b = [b[0] - centerCoor[0], b[1] - centerCoor[1]]
|
||||||
|
return Math.atan2(...point_b.reverse()) - Math.atan2(...point_a.reverse())
|
||||||
|
})
|
||||||
|
}
|
@ -3,82 +3,85 @@
|
|||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="18">
|
<el-col :span="18">
|
||||||
<div
|
<div
|
||||||
:style="{
|
:style="{
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<div class="search-bar">
|
<div class="search-bar">
|
||||||
<el-row :gutter="10">
|
<el-row :gutter="10">
|
||||||
<!-- <el-col :span="7"> -->
|
<!-- <el-col :span="7"> -->
|
||||||
<el-button type="info" size="small" @click="back"
|
<el-button size="small" type="info" @click="back"
|
||||||
>返回上层</el-button
|
>返回上层
|
||||||
|
</el-button
|
||||||
>
|
>
|
||||||
<!-- </el-col> -->
|
<!-- </el-col> -->
|
||||||
<el-col :span="10">
|
<el-col :span="10">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="searchKeyword"
|
v-model="searchKeyword"
|
||||||
size="small"
|
placeholder="请输入地名或点击地图选点"
|
||||||
@keypress.enter="searchPoint"
|
size="small"
|
||||||
placeholder="请输入地名或点击地图选点"
|
@keypress.enter="searchPoint"
|
||||||
></el-input>
|
></el-input>
|
||||||
</el-col>
|
</el-col>
|
||||||
<!-- <el-col :span="7"> -->
|
<!-- <el-col :span="7"> -->
|
||||||
<el-button
|
<el-button
|
||||||
type="primary"
|
icon="search"
|
||||||
size="small"
|
size="small"
|
||||||
icon="search"
|
type="primary"
|
||||||
@click="searchPoint"
|
@click="searchPoint"
|
||||||
>搜索</el-button
|
>搜索
|
||||||
|
</el-button
|
||||||
>
|
>
|
||||||
<!-- </el-col> -->
|
<!-- </el-col> -->
|
||||||
<el-button
|
<el-button
|
||||||
type="primary"
|
plain
|
||||||
plain
|
size="small"
|
||||||
size="small"
|
type="primary"
|
||||||
@click="switchMapLayer"
|
@click="switchMapLayer"
|
||||||
>{{ isSatelliteMode ? "标准模式" : "卫星模式" }}</el-button
|
>{{ isSatelliteMode ? "标准模式" : "卫星模式" }}
|
||||||
|
</el-button
|
||||||
>
|
>
|
||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
<div id="map-container"></div>
|
<div id="map-container"></div>
|
||||||
<el-button
|
<el-button
|
||||||
:style="{
|
:style="{
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
right: '20px',
|
right: '20px',
|
||||||
top: '20px',
|
top: '20px',
|
||||||
}"
|
}"
|
||||||
@click="
|
circle
|
||||||
|
icon="refresh"
|
||||||
|
type="primary"
|
||||||
|
@click="
|
||||||
map.clearMap();
|
map.clearMap();
|
||||||
form.fencePath = [];
|
form.fencePath = [];
|
||||||
"
|
"
|
||||||
type="primary"
|
|
||||||
icon="refresh"
|
|
||||||
circle
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-card class="fence-form-card">
|
<el-card class="fence-form-card">
|
||||||
<el-scrollbar
|
<el-scrollbar
|
||||||
:wrap-style="{
|
:wrap-style="{
|
||||||
height: 'calc(100vh - 84px - 35px)',
|
height: 'calc(100vh - 84px - 35px)',
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<el-form
|
<el-form
|
||||||
ref="fenceRef"
|
ref="fenceRef"
|
||||||
:model="form"
|
:model="form"
|
||||||
:rules="rules"
|
:rules="rules"
|
||||||
label-width="80px"
|
label-position="top"
|
||||||
label-position="top"
|
label-width="80px"
|
||||||
>
|
>
|
||||||
<el-form-item label="围栏名称" prop="fenceName">
|
<el-form-item label="围栏名称" prop="fenceName">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="form.fenceName"
|
v-model="form.fenceName"
|
||||||
placeholder="请输入围栏名称"
|
placeholder="请输入围栏名称"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="限速(km/h)" prop="speed">
|
<el-form-item label="限速(km/h)" prop="speed">
|
||||||
<el-input v-model="form.speed" placeholder="请输入限速(km/h)" />
|
<el-input v-model="form.speed" placeholder="请输入限速(km/h)"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="报警类型" prop="reportType">
|
<el-form-item label="报警类型" prop="reportType">
|
||||||
<el-radio-group v-model="form.reportType" class="ml-4">
|
<el-radio-group v-model="form.reportType" class="ml-4">
|
||||||
@ -90,8 +93,8 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="报警时段" prop="reportTime">
|
<el-form-item label="报警时段" prop="reportTime">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="form.reportTime"
|
v-model="form.reportTime"
|
||||||
placeholder="请输入报警时段"
|
placeholder="请输入报警时段"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- <el-form-item label="围栏地图数据" prop="fencePath">
|
<!-- <el-form-item label="围栏地图数据" prop="fencePath">
|
||||||
@ -104,13 +107,14 @@
|
|||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<el-button
|
<el-button
|
||||||
:style="{
|
:style="{
|
||||||
width: '100%',
|
width: '100%',
|
||||||
}"
|
}"
|
||||||
@click="submitForm"
|
size="small"
|
||||||
type="primary"
|
type="primary"
|
||||||
size="small"
|
@click="submitForm"
|
||||||
>保存</el-button
|
>保存
|
||||||
|
</el-button
|
||||||
>
|
>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@ -127,17 +131,17 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup name="AddFence">
|
<script name="AddFence" setup>
|
||||||
import tab from "@/plugins/tab";
|
import tab from "@/plugins/tab";
|
||||||
import { onMounted } from "vue";
|
import {onMounted} from "vue";
|
||||||
import { useRoute } from "vue-router";
|
import {useRoute} from "vue-router";
|
||||||
import { loadAMap } from "@/utils/map";
|
import {loadAMap} from "@/utils/map";
|
||||||
import markBsPng from "@/assets/images/mark_bs.png";
|
import markBsPng from "@/assets/images/mark_bs.png";
|
||||||
import mapPinPng from "@/assets/images/map-pin.png";
|
import mapPinPng from "@/assets/images/map-pin.png";
|
||||||
import { addFence, updateFence, getFence } from "@/api/fence";
|
import {addFence, getFence, updateFence} from "@/api/fence";
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { proxy } = getCurrentInstance();
|
const {proxy} = getCurrentInstance();
|
||||||
const AMap = shallowRef(null);
|
const AMap = shallowRef(null);
|
||||||
const map = shallowRef(null);
|
const map = shallowRef(null);
|
||||||
const placeSearch = shallowRef(null);
|
const placeSearch = shallowRef(null);
|
||||||
@ -169,7 +173,7 @@ const data = reactive({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const { form, rules } = toRefs(data);
|
const {form, rules} = toRefs(data);
|
||||||
|
|
||||||
const addFencePath = (lnglat) => {
|
const addFencePath = (lnglat) => {
|
||||||
if (map.value.getAllOverlays("polygon").length === 0) {
|
if (map.value.getAllOverlays("polygon").length === 0) {
|
||||||
@ -177,10 +181,10 @@ const addFencePath = (lnglat) => {
|
|||||||
}
|
}
|
||||||
form.value.fencePath.push(lnglat);
|
form.value.fencePath.push(lnglat);
|
||||||
turningPointMarker.value.push(
|
turningPointMarker.value.push(
|
||||||
new AMap.value.Marker({
|
new AMap.value.Marker({
|
||||||
map: map.value,
|
map: map.value,
|
||||||
position: lnglat,
|
position: lnglat,
|
||||||
content: `
|
content: `
|
||||||
<div
|
<div
|
||||||
style="
|
style="
|
||||||
background-image: url(${mapPinPng});
|
background-image: url(${mapPinPng});
|
||||||
@ -195,8 +199,8 @@ const addFencePath = (lnglat) => {
|
|||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
`,
|
`,
|
||||||
anchor: "bottom-right",
|
anchor: "bottom-right",
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
if (form.value.fencePath.length > 2) {
|
if (form.value.fencePath.length > 2) {
|
||||||
turningPointMarker.value.forEach((el) => {
|
turningPointMarker.value.forEach((el) => {
|
||||||
@ -327,7 +331,7 @@ function reset() {
|
|||||||
|
|
||||||
function back() {
|
function back() {
|
||||||
reset();
|
reset();
|
||||||
tab.closeOpenPage({ path: "/basic/fence" });
|
tab.closeOpenPage({path: "/basic/fence"});
|
||||||
}
|
}
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
@ -355,16 +359,16 @@ onMounted(() => {
|
|||||||
map.value.add(fencePolygon.value);
|
map.value.add(fencePolygon.value);
|
||||||
map.value.addControl(new AMap.value.Scale());
|
map.value.addControl(new AMap.value.Scale());
|
||||||
if (route.query.fenceId && route.query.uuid) {
|
if (route.query.fenceId && route.query.uuid) {
|
||||||
const routerObj = Object.assign({}, route, { title: "修改电子围栏" });
|
const routerObj = Object.assign({}, route, {title: "修改电子围栏"});
|
||||||
tab.updatePage(routerObj);
|
tab.updatePage(routerObj);
|
||||||
getFence(route.query.fenceId, route.query.uuid).then((resp) => {
|
getFence(route.query.fenceId, route.query.uuid).then((resp) => {
|
||||||
form.value = {
|
form.value = {
|
||||||
...resp.data,
|
...resp.data,
|
||||||
fencePath: resp.data.fencePath
|
fencePath: resp.data.fencePath
|
||||||
? JSON.parse(resp.data.fencePath).map(
|
? JSON.parse(resp.data.fencePath).map(
|
||||||
(el) => new AMap.value.LngLat(...el)
|
(el) => new AMap.value.LngLat(...el)
|
||||||
)
|
)
|
||||||
: [],
|
: [],
|
||||||
};
|
};
|
||||||
fencePolygon.value.setPath(form.value.fencePath);
|
fencePolygon.value.setPath(form.value.fencePath);
|
||||||
map.value.setFitView([fencePolygon.value]);
|
map.value.setFitView([fencePolygon.value]);
|
||||||
@ -382,10 +386,12 @@ onMounted(() => {
|
|||||||
left: 20px;
|
left: 20px;
|
||||||
top: 20px;
|
top: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#map-container {
|
#map-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: calc(100vh - 84px);
|
height: calc(100vh - 84px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.fence-form-card {
|
.fence-form-card {
|
||||||
height: calc(100vh - 84px);
|
height: calc(100vh - 84px);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user