顺时针路径排序

This commit is contained in:
2023-03-09 11:48:10 +08:00
parent 7f21dd5016
commit 822fc341a4
3 changed files with 79 additions and 56 deletions

View File

@ -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
View 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())
})
}

View File

@ -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);
} }