bx-865-apps #1
|
@ -3,6 +3,9 @@ const menu = [{
|
||||||
label: 'Создать план помещения',
|
label: 'Создать план помещения',
|
||||||
to: '/plan'
|
to: '/plan'
|
||||||
}]
|
}]
|
||||||
|
|
||||||
|
const point_array = useState('point_array', () => [[]])
|
||||||
|
point_array.value = [[]]
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="grid grid-cols-12 gap-4">
|
<div class="grid grid-cols-12 gap-4">
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
const point_array = useState<number[][] | undefined>('point_array', () => undefined)
|
||||||
|
|
||||||
|
const canvasElement: Ref<HTMLCanvasElement | undefined> = ref();
|
||||||
|
const context: Ref<CanvasRenderingContext2D | undefined> = ref();
|
||||||
|
|
||||||
|
const props = defineProps(['cw', 'ch'])
|
||||||
|
const nextFrame = () => new Promise(resolve => requestAnimationFrame(resolve));
|
||||||
|
|
||||||
|
const newDraw = async () => {
|
||||||
|
context.value = canvasElement.value?.getContext('2d') || undefined;
|
||||||
|
const lines = point_array.value
|
||||||
|
if (!lines) return;
|
||||||
|
|
||||||
|
context.value?.clearRect(0, 0, props.cw, props.ch)
|
||||||
|
await nextFrame()
|
||||||
|
|
||||||
|
for (let indexY = 0; indexY < lines.length; indexY++) {
|
||||||
|
const line = lines[indexY];
|
||||||
|
|
||||||
|
const drawLine = () => {
|
||||||
|
line.forEach((point, indexX) => {
|
||||||
|
if (canvasElement.value && context.value && point > 0) {
|
||||||
|
context.value.fillStyle = 'rgba(70, 0, 70, 0.5)'
|
||||||
|
context.value.fillRect(indexX, indexY, 1, 1)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
drawLine()
|
||||||
|
if (indexY % 10 == 0) await nextFrame()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
watch(point_array, (newStatus) => {
|
||||||
|
newDraw()
|
||||||
|
})
|
||||||
|
onMounted(() => {
|
||||||
|
newDraw()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<canvas :width="props.cw" :height="props.ch" ref="canvasElement" style="position: absolute; z-index: -1;"></canvas>
|
||||||
|
</template>
|
|
@ -0,0 +1,86 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { chunks } from '~/helpers';
|
||||||
|
|
||||||
|
const point_array = useState<number[][] | undefined>('point_array', () => undefined)
|
||||||
|
const chunk_size = useState<number>('chunk_size', () => 8)
|
||||||
|
const threshold = useState<number>('chunk_size', () => 20)
|
||||||
|
|
||||||
|
const paths_array = ref<{ path: string, unwalkable: boolean, x: number, y: number }[]>()
|
||||||
|
|
||||||
|
const props = defineProps(['cw', 'ch'])
|
||||||
|
|
||||||
|
const sampling_data = () => {
|
||||||
|
const points = point_array.value
|
||||||
|
const chunk = chunk_size.value
|
||||||
|
if (!points) return
|
||||||
|
const prepared_array = [...chunks(points, chunk)].map(line => {
|
||||||
|
const line_data = [] as any[][]
|
||||||
|
line.map((item: any) => [...chunks(item, chunk)]).map((item) => {
|
||||||
|
item.map((one_line, k) => {
|
||||||
|
if (!line_data[k]) line_data[k] = []
|
||||||
|
line_data[k].push(...one_line)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return line_data.map(el => {
|
||||||
|
return el.filter(e => e > 0).length > threshold.value ? 1 : 0
|
||||||
|
})
|
||||||
|
});
|
||||||
|
const res: any[] = []
|
||||||
|
prepared_array.forEach((line, indexY) => {
|
||||||
|
line.forEach((point, indexX) => {
|
||||||
|
const targetX = indexX * chunk
|
||||||
|
const targetY = indexY * chunk
|
||||||
|
res.push({
|
||||||
|
path: `M${targetX} ${targetY} ${targetX + chunk} ${targetY} ${targetX + chunk} ${targetY + chunk} ${targetX} ${targetY + chunk}Z`,
|
||||||
|
unwalkable: !!point,
|
||||||
|
x: indexX,
|
||||||
|
y: indexY,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
paths_array.value = res
|
||||||
|
}
|
||||||
|
watch(point_array, (newStatus) => {
|
||||||
|
sampling_data()
|
||||||
|
})
|
||||||
|
onMounted(() => {
|
||||||
|
sampling_data()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<svg ref="svgElement" :width="props.cw" :height="props.ch">
|
||||||
|
<path v-for="item in paths_array" :d="item.path" :class="[
|
||||||
|
{ 'unwalkable': item.unwalkable },
|
||||||
|
// { 'endPoint': (endPoint && item.x == endPoint.x && item.y == endPoint.y) },
|
||||||
|
// { 'startPoint': (startPoint && item.x == startPoint.x && item.y == startPoint.y) },
|
||||||
|
// { 'pathPoint': (startToEndPath && startToEndPath.find((el: number[]) => el[0] == item.x && el[1] == item.y)) },
|
||||||
|
]">
|
||||||
|
</path>
|
||||||
|
</svg>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
svg path {
|
||||||
|
fill: transparent
|
||||||
|
}
|
||||||
|
|
||||||
|
svg path:hover {
|
||||||
|
fill: red
|
||||||
|
}
|
||||||
|
|
||||||
|
svg path.unwalkable {
|
||||||
|
fill: rgba(70, 70, 0, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
svg path.endPoint {
|
||||||
|
fill: blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg path.startPoint {
|
||||||
|
fill: lawngreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg path.pathPoint {
|
||||||
|
fill: gold;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -4,7 +4,10 @@ import PF, { Grid } from 'pathfinding'
|
||||||
import { chunks } from '~/helpers';
|
import { chunks } from '~/helpers';
|
||||||
|
|
||||||
const config = useRuntimeConfig()
|
const config = useRuntimeConfig()
|
||||||
const point_array = ref<number[][]>()
|
const point_array = useState('point_array', () => [[]])
|
||||||
|
const chunk_size = useState('chunk_size', () => 8)
|
||||||
|
const threshold = useState('chunk_size', () => 20)
|
||||||
|
|
||||||
const paths_array = ref<{ path: string, unwalkable: boolean, x: number, y: number }[]>()
|
const paths_array = ref<{ path: string, unwalkable: boolean, x: number, y: number }[]>()
|
||||||
const loading = ref<boolean>(false)
|
const loading = ref<boolean>(false)
|
||||||
|
|
||||||
|
@ -33,9 +36,6 @@ const onUpload = (event: FileUploadUploadEvent) => {
|
||||||
try {
|
try {
|
||||||
const data = JSON.parse(event.xhr.response)
|
const data = JSON.parse(event.xhr.response)
|
||||||
point_array.value = data.response.np_field
|
point_array.value = data.response.np_field
|
||||||
paths_array.value = sampling_data(data.response.np_field, 8, 20)
|
|
||||||
|
|
||||||
newDraw()
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error)
|
||||||
}
|
}
|
||||||
|
@ -46,73 +46,23 @@ const selectFileEvent = async () => {
|
||||||
const res = await fetch(`${config.public.apiBase}/api/floorplan/${selectFile.value}`)
|
const res = await fetch(`${config.public.apiBase}/api/floorplan/${selectFile.value}`)
|
||||||
const data = await res.json()
|
const data = await res.json()
|
||||||
point_array.value = data.np_field
|
point_array.value = data.np_field
|
||||||
paths_array.value = sampling_data(data.np_field, 8, 20)
|
|
||||||
|
|
||||||
newDraw()
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error)
|
||||||
}
|
}
|
||||||
loadingFile.value = false
|
loadingFile.value = false
|
||||||
}
|
}
|
||||||
|
const loadFiles = async () => {
|
||||||
const sampling_data = (np_field: number[][], chunkSize: number, threshold: number) => {
|
try {
|
||||||
const prepared_array = [...chunks(np_field, chunkSize)].map(line => {
|
loadingFile.value = true
|
||||||
const line_data = [] as any[][]
|
const res = await fetch(`${config.public.apiBase}/api/floorplan/`)
|
||||||
line.map((item: any) => [...chunks(item, chunkSize)]).map((item) => {
|
const data = await res.json()
|
||||||
item.map((one_line, k) => {
|
files.value = data
|
||||||
if (!line_data[k]) line_data[k] = []
|
} catch (error) {
|
||||||
line_data[k].push(...one_line)
|
console.log(error)
|
||||||
})
|
|
||||||
})
|
|
||||||
return line_data.map(el => {
|
|
||||||
return el.filter(e => e > 0).length > threshold ? 1 : 0
|
|
||||||
})
|
|
||||||
});
|
|
||||||
const res: any[] = []
|
|
||||||
prepared_array.forEach((line, indexY) => {
|
|
||||||
line.forEach((point, indexX) => {
|
|
||||||
const targetX = indexX * chunkSize
|
|
||||||
const targetY = indexY * chunkSize
|
|
||||||
res.push({
|
|
||||||
path: `M${targetX} ${targetY} ${targetX + chunkSize} ${targetY} ${targetX + chunkSize} ${targetY + chunkSize} ${targetX} ${targetY + chunkSize}Z`,
|
|
||||||
unwalkable: !!point,
|
|
||||||
x: indexX,
|
|
||||||
y: indexY,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
const newDraw = async () => {
|
|
||||||
startPoint.value = undefined
|
|
||||||
endPoint.value = undefined
|
|
||||||
startToEndPath.value = undefined
|
|
||||||
|
|
||||||
context.value = canvasElement.value?.getContext('2d') || undefined;
|
|
||||||
const lines = point_array.value
|
|
||||||
if (!lines) return;
|
|
||||||
|
|
||||||
context.value?.clearRect(0, 0, cw, ch)
|
|
||||||
await nextFrame()
|
|
||||||
|
|
||||||
for (let indexY = 0; indexY < lines.length; indexY++) {
|
|
||||||
const line = lines[indexY];
|
|
||||||
|
|
||||||
const drawLine = () => {
|
|
||||||
line.forEach((point, indexX) => {
|
|
||||||
if (canvasElement.value && context.value && point > 0) {
|
|
||||||
context.value.fillStyle = 'crimson'
|
|
||||||
context.value.fillRect(indexX, indexY, 1, 1)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
drawLine()
|
|
||||||
await nextFrame()
|
|
||||||
}
|
}
|
||||||
grid.value = new PF.Grid(lines.map(y => y.map(x => x > 0 ? 1 : 0)))
|
loadingFile.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const toggleBlock = (name: string) => {
|
const toggleBlock = (name: string) => {
|
||||||
if (openBlocks.value.includes(name)) {
|
if (openBlocks.value.includes(name)) {
|
||||||
openBlocks.value.splice(openBlocks.value.indexOf(name), 1)
|
openBlocks.value.splice(openBlocks.value.indexOf(name), 1)
|
||||||
|
@ -131,17 +81,6 @@ const fileBtnClick = async () => {
|
||||||
}
|
}
|
||||||
toggleBlock('upload_file')
|
toggleBlock('upload_file')
|
||||||
}
|
}
|
||||||
const loadFiles = async () => {
|
|
||||||
try {
|
|
||||||
loadingFile.value = true
|
|
||||||
const res = await fetch(`${config.public.apiBase}/api/floorplan/`)
|
|
||||||
const data = await res.json()
|
|
||||||
files.value = data
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error)
|
|
||||||
}
|
|
||||||
loadingFile.value = false
|
|
||||||
}
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await loadFiles()
|
await loadFiles()
|
||||||
})
|
})
|
||||||
|
@ -169,45 +108,15 @@ onMounted(async () => {
|
||||||
chooseLabel="Выберите файл" :disabled="loading" />
|
chooseLabel="Выберите файл" :disabled="loading" />
|
||||||
</Panel>
|
</Panel>
|
||||||
|
|
||||||
|
<Panel header="Данные для работы">
|
||||||
|
|
||||||
|
</Panel>
|
||||||
|
|
||||||
<Panel :header="loading ? `Идет отрисовка` : `Обработанный план здания`">
|
<Panel :header="loading ? `Идет отрисовка` : `Обработанный план здания`">
|
||||||
<div style=" max-width: 100%; overflow: auto; position: relative;">
|
<div style=" max-width: 100%; overflow: auto; position: relative;">
|
||||||
<canvas ref="canvasElement" :width="cw" :height="ch" style="position: absolute; z-index: -1;"></canvas>
|
<FloorplanCanvas :cw="cw" :ch="ch" />
|
||||||
<svg ref="svgElement" :width="cw" :height="ch">
|
<FloorplanSvg :cw="cw" :ch="ch" />
|
||||||
<path v-for="item in paths_array" :d="item.path" :class="[
|
|
||||||
{ 'unwalkable': item.unwalkable },
|
|
||||||
// { 'endPoint': (endPoint && item.x == endPoint.x && item.y == endPoint.y) },
|
|
||||||
// { 'startPoint': (startPoint && item.x == startPoint.x && item.y == startPoint.y) },
|
|
||||||
// { 'pathPoint': (startToEndPath && startToEndPath.find((el: number[]) => el[0] == item.x && el[1] == item.y)) },
|
|
||||||
]">
|
|
||||||
</path>
|
|
||||||
</svg>
|
|
||||||
</div>
|
</div>
|
||||||
</Panel>
|
</Panel>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
svg path {
|
|
||||||
fill: transparent
|
|
||||||
}
|
|
||||||
|
|
||||||
svg path:hover {
|
|
||||||
fill: red
|
|
||||||
}
|
|
||||||
|
|
||||||
svg path.unwalkable {
|
|
||||||
fill: rgba(0, 0, 0, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
svg path.endPoint {
|
|
||||||
fill: blue;
|
|
||||||
}
|
|
||||||
|
|
||||||
svg path.startPoint {
|
|
||||||
fill: lawngreen;
|
|
||||||
}
|
|
||||||
|
|
||||||
svg path.pathPoint {
|
|
||||||
fill: gold;
|
|
||||||
}
|
|
||||||
</style>
|
|
Loading…
Reference in New Issue