生成直角拐点改为后端定义变量值,根据贝塞尔曲线的偏移量动态改变弧度

增加等距复制点的弹窗
This commit is contained in:
yyy 2025-07-02 17:01:22 +08:00
parent cd17472173
commit 709df94ff3
3 changed files with 175 additions and 18 deletions

View File

@ -7,7 +7,17 @@
class="batch-copying-dialog-form"
@close="dialogClose"
>
<el-form :model="batchCopyingForm" label-width="120" ref="BatchCopyingFormRef" :rules="rules">
<el-form :model="batchCopyingForm" label-width="110" ref="BatchCopyingFormRef" :rules="rules">
<el-form-item label="偏移距离(米)" prop="distance" required>
<el-input-number
v-model="batchCopyingForm.distance"
placeholder="请输入距离"
controls-position="right"
style="width: 100%"
:min="0"
precision="2"
/>
</el-form-item>
<el-form-item label="方向(弧度)" prop="radian" required>
<el-input-number
v-model="batchCopyingForm.radian"
@ -20,16 +30,20 @@
precision="4"
/>
</el-form-item>
<el-form-item label="偏移距离(米)" prop="distance" required>
<el-input-number
v-model="batchCopyingForm.distance"
placeholder="请输入距离"
controls-position="right"
style="width: 100%"
:min="0"
precision="2"
/>
</el-form-item>
<div class="tips">
<div class="mb-1">
<el-text>向上弧度 1.57079</el-text>
</div>
<div class="mb-1">
<el-text>向左弧度 3.141592</el-text>
</div>
<div class="mb-1">
<el-text>向下弧度 -1.57079</el-text>
</div>
<div class="mb-1">
<el-text>向右弧度 0</el-text>
</div>
</div>
</el-form>
<template #footer>
<div class="dialog-footer">
@ -127,5 +141,9 @@ defineExpose({ open }) // 提供 open 方法,用于打开弹窗
padding: 0px 20px 20px 0;
border-top: none !important;
}
.tips {
padding-left: 110px;
}
}
</style>

View File

@ -0,0 +1,102 @@
<template>
<!-- 新增设备 -->
<Dialog
v-model="dialogFormVisible"
title="等距复制"
width="540"
class="isometric-replication-dialog"
@close="dialogClose"
>
<el-form :model="form" label-width="110" ref="ruleFormRef" :rules="rules">
<el-form-item label="间隔距离/米" prop="distance" required>
<el-input-number
v-model="form.distance"
:min="0"
:precision="2"
placeholder="请输入"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="复制数量" prop="number" required>
<el-input-number
v-model="form.number"
:min="0"
:precision="2"
placeholder="请输入"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="复制角度" prop="angle" required>
<el-input-number
v-model="form.angle"
:min="0"
:precision="2"
placeholder="请输入"
style="width: 100%"
/>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="dialogFormVisible = false">取消</el-button>
<el-button type="primary" @click="submitForm(ruleFormRef)"> 确定 </el-button>
</div>
</template>
</Dialog>
</template>
<script setup>
import { reactive, ref } from 'vue'
import * as MapApi from '@/api/map/map'
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
const message = useMessage() //
const ruleFormRef = ref()
const dialogFormVisible = ref(false) //
const rules = reactive({
distance: [{ required: true, message: '请输入间隔距离', trigger: 'blur' }],
number: [{ required: true, message: '请输入复制数量', trigger: 'blur' }],
angle: [{ required: true, message: '请输入复制角度', trigger: 'blur' }]
})
//
const form = ref({
positionMapId: '',
skuInfo: '', //
areaName: '', //
areaNumber: 0,
mapItemIds: []
})
const open = (list) => {
dialogFormVisible.value = true
}
const emit = defineEmits(['addEventListener', 'itemAreaSettingSubmitSuccess'])
const dialogClose = () => {
emit('addEventListener')
}
const submitForm = async (formEl) => {
if (!formEl) return
await formEl.validate(async (valid, fields) => {
if (valid) {
}
})
}
defineExpose({ open }) // open
</script>
<style lang="scss">
.isometric-replication-dialog {
padding: 0px;
.el-dialog__footer {
padding: 0px 20px 20px 0;
border-top: none !important;
}
}
</style>

View File

@ -966,6 +966,12 @@
:imgBgObj="imgBgObj"
@submit-batch-copying-form-success="submitBatchCopyingFormSuccess"
/>
<!-- 等距复制 -->
<IsometricReplicationDialog
ref="IsometricReplicationDialogRef"
@add-event-listener="addEventListener"
/>
<!-- 节点右击菜单 -->
<div
v-if="state.contextMenu.visible"
@ -975,6 +981,7 @@
>
<div class="context-menu-item" @click="deleteSingleNode">删除</div>
<div class="context-menu-item" @click="contextMenuEditNode">编辑节点</div>
<div class="context-menu-item" @click="isometricReplication">等距复制</div>
<div
class="context-menu-item"
@click="generateDetectionPoint"
@ -1016,6 +1023,7 @@ import BatchCopyingDialogForm from './components-tool/BatchCopyingDialogForm.vue
import lineLibrarySettingDialog from './components-tool/lineLibrarySettingDialog.vue'
import layerSelectionToolDialog from './components-tool/layerSelectionToolDialog.vue'
import itemAreaManagementDialog from './components-tool/itemAreaManagementDialog.vue'
import IsometricReplicationDialog from './components-tool/IsometricReplicationDialog.vue'
import lineLibraryManagementDialog from './components-tool/lineLibraryManagementDialog.vue'
import GenerateStraightLinesDialog from './components-tool/GenerateStraightLinesDialog.vue'
import mapScaleTool from './components-tool/map-scale-tool.vue'
@ -1028,6 +1036,7 @@ defineOptions({ name: 'EditMapPageRealTimeMap' })
const GenerateStraightLinesDialogRef = ref() //线
const lineLibraryManagementDialogRef = ref() //线
const IsometricReplicationDialogRef = ref() //
const itemAreaManagementDialogRef = ref() //
const lineLibrarySettingDialogRef = ref() //线
const itemAreaSettingDialogRef = ref() //
@ -1775,7 +1784,9 @@ const state = reactive({
y: 0,
currentCurve: null,
currentIndex: -1
}
},
checkPointDistance: 0,
curveOffsetValue: 0
})
const getRefLineParams = (params) => {
@ -2194,6 +2205,13 @@ const contextMenuEditNode = () => {
}
}
//
const isometricReplication = () => {
// IsometricReplicationDialogRef.value.open()
// hideContextMenu()
message.warning('规则暂未制定')
}
//
const generateDetectionPoint = async () => {
if (state.contextMenu.currentIndex === -1) return
@ -2205,8 +2223,7 @@ const generateDetectionPoint = async () => {
state.contextMenu.currentItem
const newId = await MapApi.getNodeId()
const distance = await MapApi.getCheckDistance()
const distanceValue = Number(distance) / Number(imgBgObj.resolution) //
const distanceValue = Number(state.checkPointDistance) / Number(imgBgObj.resolution) //
// 使
const angle = locationYaw * (180 / Math.PI)
@ -3962,6 +3979,14 @@ const saveNodeList = async () => {
throw new Error('节点保存失败:' + (error?.message || '未知错误'))
}
}
//
const getCheckDistance = async () => {
const res = await MapApi.getCheckDistance()
state.checkPointDistance = Number(res.mapCheckDistance)
state.curveOffsetValue = Number(res.mapArcOffset)
}
//线
const saveMapRoute = async () => {
try {
@ -4289,6 +4314,7 @@ onBeforeRouteLeave((to, from) => {
onMounted(() => {
getMapList()
getCheckDistance()
window.addEventListener('keydown', handleKeyDown)
})
@ -4420,8 +4446,9 @@ window.addEventListener('click', (e) => {
})
//
function getRightAngleControlPoints(direction, start, end, offset = 0) {
function getRightAngleControlPoints(direction, start, end) {
let corner
let offset = -state.curveOffsetValue || 0
if (direction === 'leftTop') {
corner = { x: Math.min(start.x, end.x), y: Math.min(start.y, end.y) }
} else if (direction === 'rightBottom') {
@ -4440,11 +4467,21 @@ function getRightAngleControlPoints(direction, start, end, offset = 0) {
const len = Math.sqrt(dx * dx + dy * dy) || 1
return { x: dx / len, y: dy / len }
}
// /offset
//
const distance = Math.sqrt((start.x - end.x) ** 2 + (start.y - end.y) ** 2) || 1
// offset100
const normalizedOffset = offset * (distance / 100)
// /normalizedOffset
const u1 = getUnit(corner, start)
const u2 = getUnit(corner, end)
const beginControl = { x: corner.x + u1.x * offset, y: corner.y + u1.y * offset }
const endControl = { x: corner.x + u2.x * offset, y: corner.y + u2.y * offset }
const beginControl = {
x: corner.x + u1.x * normalizedOffset,
y: corner.y + u1.y * normalizedOffset
}
const endControl = {
x: corner.x + u2.x * normalizedOffset,
y: corner.y + u2.y * normalizedOffset
}
return { beginControl, endControl }
}
// 线