Update
This commit is contained in:
@ -8,11 +8,11 @@ import { Tile as TileLayer, VectorImage, Vector as VectorLayer } from 'ol/layer'
|
||||
import { click, never, platformModifierKeyOnly, primaryAction, shiftKeyOnly } from 'ol/events/condition'
|
||||
import Feature from 'ol/Feature'
|
||||
import { IRectCoords, SatelliteMapsProvider } from '../../interfaces/map'
|
||||
import { Extent } from 'ol/extent'
|
||||
import { drawingLayerStyle, highlightStyleRed, highlightStyleYellow, overlayStyle, regionsLayerStyle } from './MapStyles'
|
||||
import { Extent, getCenter } from 'ol/extent'
|
||||
import { drawingLayerStyle, figureStyle, highlightStyleRed, highlightStyleYellow, lineStyle, overlayStyle, regionsLayerStyle } from './MapStyles'
|
||||
import { customMapSource, googleMapsSatelliteSource, regionsLayerSource, yandexMapsSatelliteSource } from './MapSources'
|
||||
import ImageLayer from 'ol/layer/Image'
|
||||
import { LineString, Point, SimpleGeometry } from 'ol/geom'
|
||||
import { Geometry, LineString, Point, SimpleGeometry } from 'ol/geom'
|
||||
import { fromExtent } from 'ol/geom/Polygon'
|
||||
import Collection from 'ol/Collection'
|
||||
import { Coordinate } from 'ol/coordinate'
|
||||
@ -23,14 +23,14 @@ import useSWR, { SWRConfiguration } from 'swr'
|
||||
import { fetcher } from '../../http/axiosInstance'
|
||||
import { BASE_URL } from '../../constants'
|
||||
import { ActionIcon, Autocomplete, Box, CloseButton, Flex, Select as MantineSelect, MantineStyleProp, rem, useMantineColorScheme, Portal, Menu, Button, Group, Divider, LoadingOverlay } from '@mantine/core'
|
||||
import { IconBoxMultiple, IconChevronDown, IconPlus, IconSearch, IconUpload } from '@tabler/icons-react'
|
||||
import { IconBoxMultiple, IconBoxPadding, IconChevronDown, IconPlus, IconSearch, IconUpload } from '@tabler/icons-react'
|
||||
import { getGridCellPosition } from './mapUtils'
|
||||
import { IFigure, ILine } from '../../interfaces/gis'
|
||||
import axios from 'axios'
|
||||
import MapToolbar from './MapToolbar/MapToolbar'
|
||||
import MapStatusbar from './MapStatusbar/MapStatusbar'
|
||||
import { measureStyleFunction, modifyStyle } from './Measure/MeasureStyles'
|
||||
import { setCurrentCoordinate, setCurrentX, setCurrentY, setCurrentZ, setSatMapsProvider, useMapStore } from '../../store/map'
|
||||
import { setCurrentCoordinate, setCurrentX, setCurrentY, setCurrentZ, setAlignMode, setSatMapsProvider, useMapStore, getAlignMode } from '../../store/map'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { useThrottle } from '@uidotdev/usehooks'
|
||||
import ObjectTree from '../Tree/ObjectTree'
|
||||
@ -38,7 +38,9 @@ import { setCurrentObjectId, setSelectedDistrict, setSelectedRegion, setSelected
|
||||
import MapLayers from './MapLayers/MapLayers'
|
||||
import ObjectParameters from './ObjectParameters/ObjectParameters'
|
||||
import TabsPane, { ITabsPane } from './TabsPane/TabsPane'
|
||||
import Link from 'ol/interaction/Link'
|
||||
import { useSearchParams } from 'react-router-dom'
|
||||
import GeoJSON from 'ol/format/GeoJSON'
|
||||
import { Stroke, Style } from 'ol/style'
|
||||
|
||||
const swrOptions: SWRConfiguration = {
|
||||
revalidateOnFocus: false
|
||||
@ -98,7 +100,6 @@ const citySettings: ICitySettings[] = [
|
||||
city_id: 145,
|
||||
image_width: 8500,
|
||||
image_height: 12544,
|
||||
// scale: 10000,
|
||||
scale: 9000,
|
||||
offset_x: 14442665.697619518,
|
||||
offset_y: 8884520.63524492,
|
||||
@ -109,7 +110,6 @@ const citySettings: ICitySettings[] = [
|
||||
city_id: 146,
|
||||
image_width: 8500,
|
||||
image_height: 12544,
|
||||
// scale: 10000,
|
||||
scale: 8000,
|
||||
offset_x: 14416475.697619518,
|
||||
offset_y: 8889280.63524492,
|
||||
@ -124,10 +124,10 @@ function getCitySettings(
|
||||
const settings = citySettings.find(el => el.city_id === city_id)
|
||||
|
||||
if (settings) {
|
||||
console.log("City settings found")
|
||||
//console.log("City settings found")
|
||||
return settings
|
||||
} else {
|
||||
console.log("City settings NOT found")
|
||||
//console.log("City settings NOT found")
|
||||
return {
|
||||
city_id: 0,
|
||||
image_width: 8500,
|
||||
@ -145,7 +145,7 @@ const MapComponent = () => {
|
||||
|
||||
// States
|
||||
const { selectedYear, currentObjectId, selectedRegion, selectedDistrict } = useObjectsStore()
|
||||
const { currentTool, satMapsProvider, selectedObjectType } = useMapStore()
|
||||
const { currentTool, satMapsProvider, selectedObjectType, alignMode } = useMapStore()
|
||||
///
|
||||
|
||||
const [file, setFile] = useState<File | null>(null)
|
||||
@ -169,6 +169,65 @@ const MapComponent = () => {
|
||||
}
|
||||
}))
|
||||
|
||||
const alignModeLayer = useRef(new VectorLayer({
|
||||
source: new VectorSource(),
|
||||
properties: {
|
||||
id: uuidv4(),
|
||||
type: 'align',
|
||||
name: 'Подгонка'
|
||||
}
|
||||
}))
|
||||
|
||||
function calculateTransformations(alignPoints: Coordinate[]) {
|
||||
const [P1, P2, P3, P4] = alignPoints;
|
||||
|
||||
// Translation vector (move P1 to P3)
|
||||
const translation = [P3[0] - P1[0], P3[1] - P1[1]];
|
||||
|
||||
// Scaling factor (distance between P3 and P4 divided by P1 and P2)
|
||||
const distanceLayer = Math.sqrt((P2[0] - P1[0]) ** 2 + (P2[1] - P1[1]) ** 2);
|
||||
const distanceMap = Math.sqrt((P4[0] - P3[0]) ** 2 + (P4[1] - P3[1]) ** 2);
|
||||
const scale = distanceMap / distanceLayer;
|
||||
|
||||
// Rotation angle (difference in angles between the two lines)
|
||||
const angleLayer = Math.atan2(P2[1] - P1[1], P2[0] - P1[0]);
|
||||
const angleMap = Math.atan2(P4[1] - P3[1], P4[0] - P3[0]);
|
||||
const rotation = angleMap - angleLayer;
|
||||
|
||||
return { translation, scale, rotation };
|
||||
}
|
||||
|
||||
function applyTransformations(figuresLayer: React.MutableRefObject<VectorLayer>, transformations: {
|
||||
translation: number[];
|
||||
scale: number;
|
||||
rotation: number;
|
||||
}, origin: Coordinate) {
|
||||
const { translation, scale, rotation } = transformations;
|
||||
|
||||
const source = figuresLayer.current.getSource();
|
||||
if (!source) return;
|
||||
|
||||
source.getFeatures().forEach((feature) => {
|
||||
const geometry = feature.getGeometry();
|
||||
|
||||
if (geometry) {
|
||||
// Translate
|
||||
geometry.translate(translation[0], translation[1]);
|
||||
|
||||
// Scale (around the origin)
|
||||
geometry.scale(scale, scale, origin);
|
||||
|
||||
// Rotate (around the origin)
|
||||
geometry.rotate(rotation, origin);
|
||||
}
|
||||
});
|
||||
|
||||
console.log("Transformations applied to figuresLayer");
|
||||
}
|
||||
|
||||
|
||||
const alignPoints = useRef<Coordinate[]>([])
|
||||
|
||||
const measureDraw = useRef<Draw | null>(null)
|
||||
|
||||
const mapElement = useRef<HTMLDivElement | null>(null)
|
||||
@ -192,7 +251,7 @@ const MapComponent = () => {
|
||||
|
||||
const selectFeature = useRef<Select>(new Select({
|
||||
condition: function (mapBrowserEvent) {
|
||||
return click(mapBrowserEvent) && shiftKeyOnly(mapBrowserEvent);
|
||||
return click(mapBrowserEvent) && shiftKeyOnly(mapBrowserEvent)
|
||||
},
|
||||
}))
|
||||
|
||||
@ -220,6 +279,10 @@ const MapComponent = () => {
|
||||
id: uuidv4(),
|
||||
type: 'figures',
|
||||
name: 'Фигуры'
|
||||
},
|
||||
style: function (feature) {
|
||||
figureStyle.getText()?.setText(feature.get('object_id'))
|
||||
return figureStyle
|
||||
}
|
||||
}))
|
||||
|
||||
@ -230,6 +293,12 @@ const MapComponent = () => {
|
||||
id: uuidv4(),
|
||||
type: 'lines',
|
||||
name: 'Линии'
|
||||
},
|
||||
style: function (feature) {
|
||||
//lineStyle.getText()?.setText('11,4')//(feature.get('object_id'))
|
||||
lineStyle.getText()?.setRotation(feature.get('rotation'))
|
||||
lineStyle.getText()?.setOffsetY(-8)
|
||||
return lineStyle
|
||||
}
|
||||
}))
|
||||
|
||||
@ -243,6 +312,33 @@ const MapComponent = () => {
|
||||
}
|
||||
}))
|
||||
|
||||
const districtBoundLayer = useRef<VectorImage>(new VectorImage({
|
||||
style: new Style({
|
||||
stroke: new Stroke({
|
||||
color: 'red',
|
||||
width: 2,
|
||||
}),
|
||||
})
|
||||
}))
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedDistrict && selectedYear) {
|
||||
const bounds = new VectorSource({
|
||||
url: `bounds/cities/${selectedDistrict}.geojson`,
|
||||
format: new GeoJSON(),
|
||||
})
|
||||
|
||||
districtBoundLayer.current.setSource(bounds)
|
||||
|
||||
bounds.on('featuresloadend', function () {
|
||||
// map.current?.setView(new View({
|
||||
// extent: bounds.getExtent()
|
||||
// }))
|
||||
console.log(bounds.getFeatures().length)
|
||||
})
|
||||
}
|
||||
}, [selectedDistrict, selectedYear])
|
||||
|
||||
const selectedArea = useRef<Feature | null>(null)
|
||||
|
||||
const baseLayer = useRef<TileLayer>(new TileLayer({
|
||||
@ -450,6 +546,7 @@ const MapComponent = () => {
|
||||
satLayer.current,
|
||||
staticMapLayer.current,
|
||||
regionsLayer.current,
|
||||
districtBoundLayer.current,
|
||||
citiesLayer.current,
|
||||
linesLayer.current,
|
||||
figuresLayer.current,
|
||||
@ -457,7 +554,8 @@ const MapComponent = () => {
|
||||
imageLayer.current,
|
||||
overlayLayer.current,
|
||||
nodeLayer.current,
|
||||
measureLayer.current
|
||||
measureLayer.current,
|
||||
alignModeLayer.current
|
||||
],
|
||||
target: mapElement.current as HTMLDivElement,
|
||||
view: new View({
|
||||
@ -481,19 +579,43 @@ const MapComponent = () => {
|
||||
if (pixel) {
|
||||
map.current?.forEachFeatureAtPixel(pixel, function (feature) {
|
||||
if (feature.get('geometry_type') === 'line') {
|
||||
console.log(feature.getProperties())
|
||||
//console.log(feature.getProperties())
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
map.current.on('click', function (e: MapBrowserEvent<UIEvent>) {
|
||||
const pixel = map.current?.getEventPixel(e.originalEvent)
|
||||
if (getAlignMode()) {
|
||||
if (alignPoints.current.length < 4) {
|
||||
alignPoints.current.push(e.coordinate)
|
||||
alignModeLayer.current.getSource()?.addFeature(new Feature(new Point(e.coordinate)))
|
||||
if (alignPoints.current.length === 4) {
|
||||
console.log("collected 4 points, now can align")
|
||||
console.log(alignPoints.current)
|
||||
const transformations = calculateTransformations(alignPoints.current);
|
||||
console.log(transformations)
|
||||
|
||||
if (pixel) {
|
||||
map.current?.forEachFeatureAtPixel(pixel, function (feature) {
|
||||
setCurrentObjectId(feature.get('object_id'))
|
||||
})
|
||||
// Use the first map point (P3) as the origin for scaling and rotation
|
||||
const origin = alignPoints.current[2];
|
||||
console.log(origin)
|
||||
|
||||
applyTransformations(figuresLayer, transformations, origin);
|
||||
applyTransformations(linesLayer, transformations, origin);
|
||||
console.log("Figures layer aligned!")
|
||||
|
||||
alignPoints.current = []
|
||||
alignModeLayer.current.getSource()?.clear()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const pixel = map.current?.getEventPixel(e.originalEvent)
|
||||
|
||||
if (pixel) {
|
||||
map.current?.forEachFeatureAtPixel(pixel, function (feature) {
|
||||
setCurrentObjectId(feature.get('object_id'))
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@ -706,30 +828,92 @@ const MapComponent = () => {
|
||||
swrOptions
|
||||
)
|
||||
|
||||
const link = useRef<Link>(new Link())
|
||||
const { data: districtData } = useSWR(
|
||||
selectedDistrict ? `/gis/images/all?city_id=${selectedDistrict}` : null,
|
||||
(url) => axios.get(url, {
|
||||
baseURL: BASE_URL.ems
|
||||
}).then((res) => Array.isArray(res.data) ? res.data[0] : null),
|
||||
swrOptions
|
||||
)
|
||||
|
||||
const [searchParams, setSearchParams] = useSearchParams()
|
||||
|
||||
useEffect(() => {
|
||||
if (link.current) {
|
||||
if (selectedRegion) {
|
||||
link.current.update('r', selectedRegion?.toString())
|
||||
}
|
||||
if (selectedRegion) {
|
||||
setSearchParams((params) => {
|
||||
params.set('r', selectedRegion.toString());
|
||||
return params
|
||||
})
|
||||
}
|
||||
|
||||
if (selectedDistrict) {
|
||||
link.current.update('d', selectedDistrict?.toString())
|
||||
}
|
||||
if (selectedDistrict) {
|
||||
setSearchParams((params) => {
|
||||
params.set('d', selectedDistrict?.toString());
|
||||
return params
|
||||
})
|
||||
}
|
||||
|
||||
if (selectedYear) {
|
||||
link.current.update('y', selectedYear?.toString())
|
||||
}
|
||||
if (selectedYear) {
|
||||
setSearchParams((params) => {
|
||||
params.set('y', selectedYear?.toString());
|
||||
return params
|
||||
})
|
||||
}
|
||||
|
||||
if (currentObjectId) {
|
||||
link.current.update('o', currentObjectId?.toString())
|
||||
if (currentObjectId) {
|
||||
setSearchParams((params) => {
|
||||
params.set('o', currentObjectId?.toString());
|
||||
return params
|
||||
})
|
||||
}
|
||||
}, [selectedRegion, selectedDistrict, selectedYear, currentObjectId, setSearchParams])
|
||||
|
||||
useEffect(() => {
|
||||
if (Array.isArray(regionsData)) {
|
||||
const region = searchParams.get('r')
|
||||
|
||||
if (searchParams.get('r')) {
|
||||
setSelectedRegion(Number(region))
|
||||
}
|
||||
}
|
||||
}, [link, selectedRegion, selectedDistrict, selectedYear, currentObjectId])
|
||||
}, [searchParams, regionsData])
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedDistrict) {
|
||||
if (Array.isArray(regionsData)) {
|
||||
const district = searchParams.get('d')
|
||||
|
||||
if (Array.isArray(districtsData)) {
|
||||
if (district) {
|
||||
setSelectedDistrict(Number(district))
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [searchParams, regionsData, districtsData])
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (Array.isArray(regionsData)) {
|
||||
const year = searchParams.get('y')
|
||||
|
||||
if (year) {
|
||||
setSelectedYear(Number(year))
|
||||
}
|
||||
}
|
||||
}, [searchParams, regionsData])
|
||||
|
||||
useEffect(() => {
|
||||
const object = searchParams.get('o')
|
||||
|
||||
if (figuresData && linesData && object) {
|
||||
setCurrentObjectId(object)
|
||||
}
|
||||
}, [searchParams, figuresData, linesData])
|
||||
|
||||
useEffect(() => {
|
||||
const districtBoundSource: VectorSource<Feature<Geometry>> | null = districtBoundLayer.current.getSource()
|
||||
|
||||
if (selectedDistrict && districtBoundSource && districtBoundSource.getFeatures().length > 0) {
|
||||
const center: Coordinate = getCenter(districtBoundSource.getExtent())
|
||||
const settings = getCitySettings(selectedDistrict)
|
||||
|
||||
if (Array.isArray(figuresData)) {
|
||||
@ -739,7 +923,7 @@ const MapComponent = () => {
|
||||
processFigure(
|
||||
figure,
|
||||
settings.scale,
|
||||
[settings.offset_x, settings.offset_y],
|
||||
[center[0], center[1]],
|
||||
figuresLayer
|
||||
)
|
||||
})
|
||||
@ -758,16 +942,23 @@ const MapComponent = () => {
|
||||
linesLayer.current.getSource()?.clear()
|
||||
if (linesData.length > 0) {
|
||||
linesData.map((line: ILine) => {
|
||||
processLine(line, settings.scale, [settings.offset_x, settings.offset_y], linesLayer)
|
||||
processLine(line, settings.scale, [center[0], center[1]], linesLayer)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}, [figuresData, linesData, selectedDistrict, selectedYear])
|
||||
}, [figuresData, linesData, selectedDistrict, selectedYear, districtBoundLayer])
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedDistrict) {
|
||||
if (!selectedRegion) {
|
||||
setSelectedDistrict(null)
|
||||
setSelectedYear(null)
|
||||
}
|
||||
}, [selectedRegion, selectedDistrict])
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedDistrict && districtData) {
|
||||
const settings = getCitySettings(selectedDistrict)
|
||||
|
||||
const imageUrl = `${import.meta.env.VITE_API_EMS_URL}/static/${selectedDistrict}`;
|
||||
@ -775,14 +966,13 @@ const MapComponent = () => {
|
||||
img.src = imageUrl;
|
||||
img.onload = () => {
|
||||
if (map.current) {
|
||||
console.log(districtData)
|
||||
|
||||
const width = img.naturalWidth
|
||||
const height = img.naturalHeight
|
||||
console.log(width, height)
|
||||
//const k = (width < height ? width / height : height / width)
|
||||
const k = settings.image_scale
|
||||
|
||||
console.log(k)
|
||||
|
||||
const wk = width * k
|
||||
const hk = height * k
|
||||
|
||||
@ -806,7 +996,7 @@ const MapComponent = () => {
|
||||
}
|
||||
};
|
||||
}
|
||||
}, [selectedDistrict])
|
||||
}, [selectedDistrict, districtData])
|
||||
|
||||
useEffect(() => {
|
||||
if (baseLayer.current) {
|
||||
@ -869,6 +1059,13 @@ const MapComponent = () => {
|
||||
data={regionsData ? regionsData.map((item: { name: string, id: number }) => ({ label: item.name, value: item.id.toString() })) : []}
|
||||
onChange={(value) => setSelectedRegion(Number(value))}
|
||||
clearable
|
||||
onClear={() => {
|
||||
setSelectedRegion(null)
|
||||
setSearchParams((params) => {
|
||||
params.delete('r')
|
||||
return params
|
||||
})
|
||||
}}
|
||||
searchable
|
||||
value={selectedRegion ? selectedRegion.toString() : null}
|
||||
/>
|
||||
@ -879,6 +1076,13 @@ const MapComponent = () => {
|
||||
data={districtsData ? districtsData.map((item: { name: string, id: number, district_name: string }) => ({ label: [item.name, item.district_name].join(' - '), value: item.id.toString() })) : []}
|
||||
onChange={(value) => setSelectedDistrict(Number(value))}
|
||||
clearable
|
||||
onClear={() => {
|
||||
setSelectedDistrict(null)
|
||||
setSearchParams((params) => {
|
||||
params.delete('d')
|
||||
return params
|
||||
})
|
||||
}}
|
||||
searchable
|
||||
value={selectedDistrict ? selectedDistrict.toString() : null}
|
||||
/>
|
||||
@ -888,12 +1092,27 @@ const MapComponent = () => {
|
||||
w='92px'
|
||||
data={['2018', '2019', '2020', '2021', '2022', '2023', '2024'].map(el => ({ label: el, value: el }))}
|
||||
onChange={(e) => {
|
||||
setSelectedYear(Number(e))
|
||||
if (e) {
|
||||
setSelectedYear(Number(e))
|
||||
} else {
|
||||
setSelectedYear(null)
|
||||
}
|
||||
}}
|
||||
defaultValue={selectedYear?.toString()}
|
||||
allowDeselect={false}
|
||||
onClear={() => {
|
||||
setSelectedYear(null)
|
||||
setSearchParams((params) => {
|
||||
params.delete('y')
|
||||
return params
|
||||
})
|
||||
}}
|
||||
value={selectedYear ? selectedYear?.toString() : null}
|
||||
clearable
|
||||
/>
|
||||
|
||||
<Button variant={alignMode ? 'filled' : 'transparent'} onClick={() => setAlignMode(!alignMode)}>
|
||||
<IconBoxPadding style={{ width: rem(20), height: rem(20) }} />
|
||||
</Button>
|
||||
|
||||
<Menu
|
||||
position="bottom-end"
|
||||
transitionProps={{ transition: 'pop-top-right' }}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import Feature, { FeatureLike } from "ol/Feature";
|
||||
import { FeatureLike } from "ol/Feature";
|
||||
import { Text } from "ol/style";
|
||||
import Fill from "ol/style/Fill";
|
||||
import { FlatStyleLike } from "ol/style/flat";
|
||||
@ -90,101 +90,42 @@ export function overlayStyle(feature: FeatureLike) {
|
||||
return styles
|
||||
}
|
||||
|
||||
export 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')
|
||||
})
|
||||
const figureStyle = 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
|
||||
})
|
||||
];
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
export 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')
|
||||
})
|
||||
})
|
||||
];
|
||||
}
|
||||
|
||||
export 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')
|
||||
})
|
||||
})
|
||||
];
|
||||
}
|
||||
|
||||
export 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')}`
|
||||
})
|
||||
})
|
||||
];
|
||||
}
|
||||
const lineStyle = 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
|
||||
}),
|
||||
placement: 'line',
|
||||
overflow: true,
|
||||
//declutterMode: 'obstacle'
|
||||
})
|
||||
})
|
||||
|
||||
const drawingLayerStyle: FlatStyleLike = {
|
||||
'fill-color': 'rgba(255, 255, 255, 0.2)',
|
||||
@ -218,5 +159,7 @@ const regionsLayerStyle = new Style({
|
||||
export {
|
||||
drawingLayerStyle,
|
||||
selectStyle,
|
||||
regionsLayerStyle
|
||||
regionsLayerStyle,
|
||||
lineStyle,
|
||||
figureStyle
|
||||
}
|
@ -9,7 +9,7 @@ import Map from "ol/Map";
|
||||
import { addCoordinateTransforms, addProjection, get, getTransform, Projection, ProjectionLike, transform } from "ol/proj";
|
||||
import VectorSource from "ol/source/Vector";
|
||||
import proj4 from "proj4";
|
||||
import { firstStyleFunction, fourthStyleFunction, selectStyle, styleFunction, thirdStyleFunction } from "./MapStyles";
|
||||
import { selectStyle } from "./MapStyles";
|
||||
import { Type } from "ol/geom/Geometry";
|
||||
import { Draw, Modify, Snap, Translate } from "ol/interaction";
|
||||
import { noModifierKeys } from "ol/events/condition";
|
||||
@ -24,6 +24,13 @@ import { getCurrentTool, getMeasureClearPrevious, getMeasureType, getTipPoint, s
|
||||
import { MutableRefObject } from "react";
|
||||
import { getSelectedCity, getSelectedYear, setSelectedRegion } from "../../store/objects";
|
||||
|
||||
const calculateAngle = (coords: [number, number][]) => {
|
||||
const [start, end] = coords;
|
||||
const dx = end[0] - start[0];
|
||||
const dy = end[1] - start[1];
|
||||
return Math.atan2(dy, dx); // Angle in radians
|
||||
}
|
||||
|
||||
export function processLine(
|
||||
line: ILine,
|
||||
scaling: number,
|
||||
@ -37,18 +44,18 @@ export function processLine(
|
||||
|
||||
const center = [mapCenter[0], mapCenter[1]]
|
||||
|
||||
const testCoords = [
|
||||
const testCoords: [number, number][] = [
|
||||
[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('type', line.type)
|
||||
feature.set('geometry_type', 'line')
|
||||
feature.set('planning', line.planning)
|
||||
feature.set('object_id', line.object_id)
|
||||
feature.set('rotation', calculateAngle(testCoords))
|
||||
|
||||
linesLayer.current?.getSource()?.addFeature(feature)
|
||||
}
|
||||
@ -77,7 +84,6 @@ export function processFigure(
|
||||
|
||||
const feature = new Feature(ellipseGeom)
|
||||
|
||||
feature.setStyle(firstStyleFunction(feature))
|
||||
feature.set('type', figure.type)
|
||||
feature.set('object_id', figure.object_id)
|
||||
feature.set('planning', figure.planning)
|
||||
@ -108,7 +114,6 @@ export function processFigure(
|
||||
feature.set('object_id', figure.object_id)
|
||||
feature.set('planning', figure.planning)
|
||||
feature.set('type', figure.type)
|
||||
feature.setStyle(thirdStyleFunction(feature))
|
||||
figuresLayer.current?.getSource()?.addFeature(feature)
|
||||
}
|
||||
}
|
||||
@ -140,7 +145,6 @@ export function processFigure(
|
||||
feature1.set('planning', figure.planning)
|
||||
feature1.set('type', figure.type)
|
||||
feature1.set('angle', figure.angle)
|
||||
feature1.setStyle(fourthStyleFunction(feature1))
|
||||
figuresLayer.current?.getSource()?.addFeature(feature1)
|
||||
}
|
||||
}
|
||||
@ -277,12 +281,11 @@ export function regionsInit(
|
||||
regionsLayer: React.MutableRefObject<VectorImageLayer<Feature<Geometry>, VectorSource<Feature<Geometry>>>>,
|
||||
) {
|
||||
regionsLayer.current.once('change', function () {
|
||||
if (getSelectedCity() === null || getSelectedYear() === null) {
|
||||
const extent = regionsLayer.current.getSource()?.getExtent()
|
||||
if (getSelectedCity() || getSelectedYear()) return
|
||||
const extent = regionsLayer.current.getSource()?.getExtent()
|
||||
|
||||
if (extent && !extent?.every(val => Math.abs(val) === Infinity)) {
|
||||
map.current?.getView().fit(fromExtent(extent) as SimpleGeometry, { duration: 500, maxZoom: 18, padding: [60, 60, 60, 60] })
|
||||
}
|
||||
if (extent && !extent?.every(val => Math.abs(val) === Infinity)) {
|
||||
map.current?.getView().fit(fromExtent(extent) as SimpleGeometry, { duration: 500, maxZoom: 18, padding: [60, 60, 60, 60] })
|
||||
}
|
||||
})
|
||||
|
||||
|
Reference in New Issue
Block a user