forked from VinokurovVE/tests
Map testing, custom table based on Tanstack Table
This commit is contained in:
@ -11,26 +11,29 @@ import { Type } from 'ol/geom/Geometry'
|
||||
import { click, never, noModifierKeys, platformModifierKeyOnly, primaryAction, shiftKeyOnly } from 'ol/events/condition'
|
||||
import Feature from 'ol/Feature'
|
||||
import { SatelliteMapsProvider } from '../../interfaces/map'
|
||||
import { containsExtent, Extent, getCenter, getHeight, getWidth } from 'ol/extent'
|
||||
import { containsExtent, Extent } from 'ol/extent'
|
||||
import { drawingLayerStyle, regionsLayerStyle, selectStyle } from './MapStyles'
|
||||
import { googleMapsSatelliteSource, regionsLayerSource, yandexMapsSatelliteSource } from './MapSources'
|
||||
import { mapCenter } from './MapConstants'
|
||||
import ImageLayer from 'ol/layer/Image'
|
||||
import VectorImageLayer from 'ol/layer/VectorImage'
|
||||
import { LineString, MultiPoint, Point, Polygon, SimpleGeometry } from 'ol/geom'
|
||||
import { fromExtent } from 'ol/geom/Polygon'
|
||||
import { Circle, LineString, MultiPoint, Point, Polygon, SimpleGeometry } from 'ol/geom'
|
||||
import { fromCircle, fromExtent } from 'ol/geom/Polygon'
|
||||
import Collection from 'ol/Collection'
|
||||
import { Coordinate } from 'ol/coordinate'
|
||||
import { Stroke, Fill, Circle as CircleStyle, Style } from 'ol/style'
|
||||
import { calculateExtent, calculateRotationAngle, rotateProjection } from './mapUtils'
|
||||
import { Stroke, Fill, Circle as CircleStyle, Style, Text } from 'ol/style'
|
||||
import { calculateCenter, calculateExtent, calculateRotationAngle, rotateProjection } from './mapUtils'
|
||||
import MapBrowserEvent from 'ol/MapBrowserEvent'
|
||||
import { fromLonLat, get } from 'ol/proj'
|
||||
import { fromLonLat, get, transform } from 'ol/proj'
|
||||
import { useCities } from '../../hooks/swrHooks'
|
||||
import useSWR from 'swr'
|
||||
import { fetcher } from '../../http/axiosInstance'
|
||||
import { BASE_URL } from '../../constants'
|
||||
import { Accordion, ActionIcon, Box, Flex, Select as MantineSelect, MantineStyleProp, rem, Slider, useMantineColorScheme } from '@mantine/core'
|
||||
import { Accordion, ActionIcon, Box, Button, Flex, Select as MantineSelect, MantineStyleProp, rem, Slider, useMantineColorScheme } from '@mantine/core'
|
||||
import { IconApi, IconArrowBackUp, IconArrowsMove, IconCircle, IconExclamationCircle, IconLine, IconPlus, IconPoint, IconPolygon, IconRuler, IconTable, IconUpload } from '@tabler/icons-react'
|
||||
import { getGridCellPosition } from './mapUtils'
|
||||
import { IFigure, ILine } from '../../interfaces/gis'
|
||||
import { Height } from '@mui/icons-material'
|
||||
|
||||
const MapComponent = () => {
|
||||
const { cities } = useCities(100, 1)
|
||||
@ -97,6 +100,10 @@ const MapComponent = () => {
|
||||
source: new VectorSource()
|
||||
}))
|
||||
|
||||
const figuresLayer = useRef<VectorLayer>(new VectorLayer({
|
||||
source: new VectorSource()
|
||||
}))
|
||||
|
||||
const regionsLayer = useRef<VectorImageLayer>(new VectorImageLayer({
|
||||
source: regionsLayerSource,
|
||||
style: regionsLayerStyle
|
||||
@ -208,49 +215,7 @@ const MapComponent = () => {
|
||||
}),
|
||||
});
|
||||
|
||||
function calculateCenter(geometry: SimpleGeometry) {
|
||||
let center, coordinates, minRadius;
|
||||
const type = geometry.getType();
|
||||
if (type === 'Polygon') {
|
||||
let x = 0;
|
||||
let y = 0;
|
||||
let i = 0;
|
||||
coordinates = (geometry as Polygon).getCoordinates()[0].slice(1);
|
||||
coordinates.forEach(function (coordinate) {
|
||||
x += coordinate[0];
|
||||
y += coordinate[1];
|
||||
i++;
|
||||
});
|
||||
center = [x / i, y / i];
|
||||
} else if (type === 'LineString') {
|
||||
center = (geometry as LineString).getCoordinateAt(0.5);
|
||||
coordinates = geometry.getCoordinates();
|
||||
} else {
|
||||
center = getCenter(geometry.getExtent());
|
||||
}
|
||||
let sqDistances;
|
||||
if (coordinates) {
|
||||
sqDistances = coordinates.map(function (coordinate: Coordinate) {
|
||||
const dx = coordinate[0] - center[0];
|
||||
const dy = coordinate[1] - center[1];
|
||||
return dx * dx + dy * dy;
|
||||
});
|
||||
minRadius = Math.sqrt(Math.max.apply(Math, sqDistances)) / 3;
|
||||
} else {
|
||||
minRadius =
|
||||
Math.max(
|
||||
getWidth(geometry.getExtent()),
|
||||
getHeight(geometry.getExtent()),
|
||||
) / 3;
|
||||
}
|
||||
return {
|
||||
center: center,
|
||||
coordinates: coordinates,
|
||||
minRadius: minRadius,
|
||||
sqDistances: sqDistances,
|
||||
};
|
||||
}
|
||||
|
||||
// tile processing
|
||||
const handleImageDrop = useCallback((event: any) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
@ -398,10 +363,10 @@ const MapComponent = () => {
|
||||
const tileWidth = mapWidth / (Math.sqrt(Math.pow(4, zoomLevel)))
|
||||
const tileHeight = mapHeight / (Math.sqrt(Math.pow(4, zoomLevel)))
|
||||
|
||||
let minPosX = minX - (tilesH / 2)
|
||||
let maxPosX = maxX - (tilesH / 2) + 1
|
||||
let minPosY = -(minY - (tilesH / 2))
|
||||
let maxPosY = -(maxY - (tilesH / 2) + 1)
|
||||
const minPosX = minX - (tilesH / 2)
|
||||
const maxPosX = maxX - (tilesH / 2) + 1
|
||||
const minPosY = -(minY - (tilesH / 2))
|
||||
const maxPosY = -(maxY - (tilesH / 2) + 1)
|
||||
console.log(`tileWidth: ${tileWidth} minPosX: ${minPosX} maxPosX: ${maxPosX} minPosY: ${minPosY} maxPosY: ${maxPosY}`)
|
||||
|
||||
const newMinX = tileWidth * minPosX
|
||||
@ -551,36 +516,6 @@ const MapComponent = () => {
|
||||
})
|
||||
}
|
||||
|
||||
function getTilesPerSide(zoom: number) {
|
||||
return Math.pow(2, zoom)
|
||||
}
|
||||
|
||||
function normalize(value: number, min: number, max: number) {
|
||||
return (value - min) / (max - min)
|
||||
}
|
||||
|
||||
function getTileIndex(normalized: number, tilesPerSide: number) {
|
||||
return Math.floor(normalized * tilesPerSide)
|
||||
}
|
||||
|
||||
function getGridCellPosition(x: number, y: number, extent: Extent, zoom: number) {
|
||||
const tilesPerSide = getTilesPerSide(zoom);
|
||||
const minX = extent[0]
|
||||
const minY = extent[1]
|
||||
const maxX = extent[2]
|
||||
const maxY = extent[3]
|
||||
|
||||
// Normalize the coordinates
|
||||
const xNormalized = normalize(x, minX, maxX);
|
||||
const yNormalized = normalize(y, minY, maxY);
|
||||
|
||||
// Get tile indices
|
||||
const tileX = getTileIndex(xNormalized, tilesPerSide);
|
||||
const tileY = getTileIndex(1 - yNormalized, tilesPerSide);
|
||||
|
||||
return { tileX, tileY };
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
drawingLayer.current = new VectorLayer({
|
||||
source: drawingLayerSource.current,
|
||||
@ -641,11 +576,11 @@ const MapComponent = () => {
|
||||
|
||||
map.current = new Map({
|
||||
controls: [],
|
||||
layers: [baseLayer.current, satLayer.current, regionsLayer.current, citiesLayer.current, drawingLayer.current, imageLayer.current, overlayLayer.current, nodeLayer.current],
|
||||
layers: [baseLayer.current, satLayer.current, regionsLayer.current, citiesLayer.current, figuresLayer.current, drawingLayer.current, imageLayer.current, overlayLayer.current, nodeLayer.current],
|
||||
target: mapElement.current as HTMLDivElement,
|
||||
view: new View({
|
||||
center: mapCenter,//center: fromLonLat([130.401113, 67.797368]),
|
||||
zoom: 16,
|
||||
center: transform([129.7659541, 62.009504], 'EPSG:4326', 'EPSG:3857'),//center: fromLonLat([130.401113, 67.797368]),
|
||||
zoom: 17,
|
||||
maxZoom: 21,
|
||||
//extent: mapExtent,
|
||||
}),
|
||||
@ -729,7 +664,7 @@ const MapComponent = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const [satelliteOpacity, setSatelliteOpacity] = useState<number>(0)
|
||||
const [satelliteOpacity, setSatelliteOpacity] = useState<number>(1)
|
||||
|
||||
const [statusText, setStatusText] = useState('')
|
||||
|
||||
@ -797,7 +732,7 @@ const MapComponent = () => {
|
||||
if (Array.isArray(nodes)) {
|
||||
nodes.map(node => {
|
||||
if (node.shape_type === 'LINE') {
|
||||
let coordinates: Coordinate[] = []
|
||||
const coordinates: Coordinate[] = []
|
||||
if (Array.isArray(node.shape)) {
|
||||
node.shape.map((point: any) => {
|
||||
const coordinate = [point.x as number, point.y as number] as Coordinate
|
||||
@ -811,6 +746,102 @@ const MapComponent = () => {
|
||||
}
|
||||
}, [nodes])
|
||||
|
||||
function styleFunction(feature: Feature) {
|
||||
return [
|
||||
new Style({
|
||||
fill: new Fill({
|
||||
color: 'rgba(255,255,255,0.4)'
|
||||
}),
|
||||
stroke: new Stroke({
|
||||
color: '#3399CC',
|
||||
width: 1.25
|
||||
}),
|
||||
text: new Text({
|
||||
font: '12px Calibri,sans-serif',
|
||||
fill: new Fill({ color: '#000' }),
|
||||
stroke: new Stroke({
|
||||
color: '#fff', width: 2
|
||||
}),
|
||||
// get the text from the feature - `this` is ol.Feature
|
||||
// and show only under certain resolution
|
||||
text: feature.get('object_id')
|
||||
})
|
||||
})
|
||||
];
|
||||
}
|
||||
|
||||
function fourthStyleFunction(feature: Feature) {
|
||||
return [
|
||||
new Style({
|
||||
fill: new Fill({
|
||||
color: 'rgba(255,255,255,0.4)'
|
||||
}),
|
||||
stroke: new Stroke({
|
||||
color: '#3399CC',
|
||||
width: 1.25
|
||||
}),
|
||||
text: new Text({
|
||||
font: '12px Calibri,sans-serif',
|
||||
fill: new Fill({ color: '#000' }),
|
||||
stroke: new Stroke({
|
||||
color: '#fff', width: 2
|
||||
}),
|
||||
// get the text from the feature - `this` is ol.Feature
|
||||
// and show only under certain resolution
|
||||
text: `${feature.get('object_id')}\n ${feature.get('angle')}`
|
||||
})
|
||||
})
|
||||
];
|
||||
}
|
||||
|
||||
function thirdStyleFunction(feature: Feature) {
|
||||
return [
|
||||
new Style({
|
||||
fill: new Fill({
|
||||
color: 'rgba(255,255,255,0.4)'
|
||||
}),
|
||||
stroke: new Stroke({
|
||||
color: '#33ccb3',
|
||||
width: 1.25
|
||||
}),
|
||||
text: new Text({
|
||||
font: '12px Calibri,sans-serif',
|
||||
fill: new Fill({ color: '#000' }),
|
||||
stroke: new Stroke({
|
||||
color: '#fff', width: 2
|
||||
}),
|
||||
// get the text from the feature - `this` is ol.Feature
|
||||
// and show only under certain resolution
|
||||
text: feature.get('object_id')
|
||||
})
|
||||
})
|
||||
];
|
||||
}
|
||||
|
||||
function firstStyleFunction(feature: Feature) {
|
||||
return [
|
||||
new Style({
|
||||
fill: new Fill({
|
||||
color: 'rgba(255,255,255,0.4)'
|
||||
}),
|
||||
stroke: new Stroke({
|
||||
color: 'red',
|
||||
width: 1.25
|
||||
}),
|
||||
text: new Text({
|
||||
font: '12px Calibri,sans-serif',
|
||||
fill: new Fill({ color: '#000' }),
|
||||
stroke: new Stroke({
|
||||
color: '#fff', width: 2
|
||||
}),
|
||||
// get the text from the feature - `this` is ol.Feature
|
||||
// and show only under certain resolution
|
||||
text: feature.get('object_id')
|
||||
})
|
||||
})
|
||||
];
|
||||
}
|
||||
|
||||
return (
|
||||
<Box w={'100%'} h={'calc(100% - 64px)'} mah={'100%'} flex={'1'} pos={'relative'}>
|
||||
<ActionIcon.Group orientation='vertical' pos='absolute' top='8px' right='8px' style={{ zIndex: 1, backdropFilter: 'blur(8px)', backgroundColor: colorScheme === 'light' ? '#FFFFFFAA' : '#000000AA', borderRadius: '4px' }}>
|
||||
@ -918,7 +949,160 @@ const MapComponent = () => {
|
||||
<Accordion variant='filled' style={{ backgroundColor: 'transparent' }} defaultValue='Объекты'>
|
||||
<Accordion.Item key={'s'} value={'Объекты'}>
|
||||
<Accordion.Control icon={<IconTable />}>{'Объекты'}</Accordion.Control>
|
||||
<Accordion.Panel>{'ASd'}</Accordion.Panel>
|
||||
<Accordion.Panel>
|
||||
<Button
|
||||
onClick={async () => {
|
||||
//open()
|
||||
|
||||
const city_id = 145
|
||||
const year = 2023
|
||||
|
||||
const figuresLimit = 10000
|
||||
const linesLimit = 10000
|
||||
|
||||
figuresLayer.current.getSource()?.clear()
|
||||
|
||||
try {
|
||||
// const response = await fetch(`${import.meta.env.VITE_API_EMS_URL}/gis/images/all?city_id=${city_id}`, {
|
||||
// method: 'GET',
|
||||
// headers: {
|
||||
// 'Content-Type': 'application/json',
|
||||
// },
|
||||
// })
|
||||
|
||||
//const responseData = await response.json()
|
||||
|
||||
const scaling = {
|
||||
w: 10000, // responseData[0].width
|
||||
h: 10000 // responseData[0].width
|
||||
}
|
||||
|
||||
const figuresResponse = await fetch(`${import.meta.env.VITE_API_EMS_URL}/gis/figures/all?city_id=${city_id}&year=${year}&offset=0&limit=${figuresLimit}`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
|
||||
const linesResponse = await fetch(`${import.meta.env.VITE_API_EMS_URL}/gis/lines/all?city_id=${city_id}&year=${year}&offset=0&limit=${linesLimit}`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
|
||||
await linesResponse.json().then(linesData => {
|
||||
linesData.map((line: ILine) => {
|
||||
const x1 = line.x1 * scaling.w
|
||||
const y1 = line.y1 * scaling.h
|
||||
const x2 = line.x2 * scaling.w
|
||||
const y2 = line.y2 * scaling.h
|
||||
|
||||
const center = [mapCenter[0], mapCenter[1]]
|
||||
|
||||
const testCoords = [
|
||||
[center[0] + x1, center[1] - y1],
|
||||
[center[0] + x2, center[1] - y2],
|
||||
]
|
||||
|
||||
const feature = new Feature(new LineString(testCoords))
|
||||
feature.setStyle(styleFunction(feature))
|
||||
feature.set('object_id', line.object_id)
|
||||
|
||||
figuresLayer.current?.getSource()?.addFeature(feature)
|
||||
})
|
||||
})
|
||||
|
||||
await figuresResponse.json().then(figuresData => {
|
||||
figuresData.map((figure: IFigure) => {
|
||||
if (figure.figure_type_id == 1) {
|
||||
const width = figure.width * scaling.w
|
||||
const height = figure.height * scaling.h
|
||||
|
||||
const left = figure.left * scaling.w
|
||||
const top = figure.top * scaling.h
|
||||
|
||||
const centerX = mapCenter[0] + left + (width / 2)
|
||||
const centerY = mapCenter[1] - top - (height / 2)
|
||||
|
||||
const radius = width / 2;
|
||||
const circleGeom = new Circle([centerX, centerY], radius)
|
||||
|
||||
const ellipseGeom = fromCircle(circleGeom, 64)
|
||||
ellipseGeom.scale(1, height / width)
|
||||
|
||||
const feature = new Feature(ellipseGeom)
|
||||
|
||||
feature.setStyle(firstStyleFunction(feature))
|
||||
feature.set('object_id', figure.object_id)
|
||||
figuresLayer.current?.getSource()?.addFeature(feature)
|
||||
}
|
||||
|
||||
if (figure.figure_type_id == 3) {
|
||||
const x = figure.left * scaling.w
|
||||
const y = figure.top * scaling.h
|
||||
|
||||
const center = [mapCenter[0] + x, mapCenter[1] - y]
|
||||
|
||||
const coords = figure.points?.split(' ').map(pair => {
|
||||
const [x, y] = pair.split(';').map(Number)
|
||||
return [
|
||||
center[0] + (x * scaling.w),
|
||||
center[1] - (y * scaling.h)
|
||||
]
|
||||
})
|
||||
|
||||
if (coords) {
|
||||
const polygon = new Polygon([coords])
|
||||
|
||||
const feature = new Feature({
|
||||
geometry: polygon
|
||||
})
|
||||
|
||||
feature.set('object_id', figure.object_id)
|
||||
feature.setStyle(thirdStyleFunction(feature))
|
||||
figuresLayer.current?.getSource()?.addFeature(feature)
|
||||
}
|
||||
}
|
||||
|
||||
if (figure.figure_type_id == 4) {
|
||||
const width = figure.width * scaling.w
|
||||
const height = figure.height * scaling.h
|
||||
const left = figure.left * scaling.w
|
||||
const top = figure.top * scaling.h
|
||||
|
||||
const halfWidth = width / 2
|
||||
const halfHeight = height / 2
|
||||
|
||||
const center = [mapCenter[0] + left + halfWidth, mapCenter[1] - top - halfHeight]
|
||||
|
||||
const testCoords = [
|
||||
[center[0] - halfWidth, center[1] - halfHeight],
|
||||
[center[0] - halfWidth, center[1] + halfHeight],
|
||||
[center[0] + halfWidth, center[1] + halfHeight],
|
||||
[center[0] + halfWidth, center[1] - halfHeight],
|
||||
[center[0] - halfWidth, center[1] - halfHeight]
|
||||
]
|
||||
|
||||
const geometry1 = new Polygon([testCoords])
|
||||
const anchor1 = center
|
||||
geometry1.rotate(-figure.angle * Math.PI / 180, anchor1)
|
||||
const feature1 = new Feature(geometry1)
|
||||
feature1.set('object_id', figure.object_id)
|
||||
feature1.set('angle', figure.angle)
|
||||
feature1.setStyle(fourthStyleFunction(feature1))
|
||||
figuresLayer.current?.getSource()?.addFeature(feature1)
|
||||
}
|
||||
})
|
||||
})
|
||||
} catch (err) {
|
||||
console.error('No data')
|
||||
}
|
||||
}}
|
||||
>
|
||||
Test
|
||||
</Button>
|
||||
</Accordion.Panel>
|
||||
</Accordion.Item>
|
||||
</Accordion>
|
||||
</Flex>
|
||||
@ -956,7 +1140,7 @@ const MapComponent = () => {
|
||||
}}
|
||||
>
|
||||
</div>
|
||||
</Box>
|
||||
</Box >
|
||||
);
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user