diff --git a/client/src/components/map/MapComponent.tsx b/client/src/components/map/MapComponent.tsx index becf884..1d40248 100644 --- a/client/src/components/map/MapComponent.tsx +++ b/client/src/components/map/MapComponent.tsx @@ -6,15 +6,14 @@ import Feature from 'ol/Feature' import { getCenter } from 'ol/extent' import { highlightStyleRed, highlightStyleYellow } from './MapStyles' import { customMapSource, googleMapsSatelliteSource, yandexMapsSatelliteSource } from './MapSources' -import { Geometry, Point } from 'ol/geom' +import { Geometry } from 'ol/geom' import { fromExtent } from 'ol/geom/Polygon' import { Coordinate } from 'ol/coordinate' -import { addInteractions, getFeatureByEntityId, handleImageDrop, loadFeatures, processFigure, processLine, zoomToFeature } from './mapUtils' +import { addFigures, addInteractions, addLines, getCitySettings, getFeatureByEntityId, handleImageDrop, loadFeatures, loadRegionBounds, loadRegionCapitals, zoomToFeature } from './mapUtils' import useSWR, { SWRConfiguration } from 'swr' import { fetcher } from '../../http/axiosInstance' import { BASE_URL } from '../../constants' import { IconBoxPadding, IconChevronLeft, } from '@tabler/icons-react' -import { ICitySettings, IFigure, ILine } from '../../interfaces/gis' import axios from 'axios' import MapToolbar from './MapToolbar/MapToolbar' import MapStatusbar from './MapStatusbar/MapStatusbar' @@ -32,8 +31,7 @@ import { Button, Divider, Spinner, Portal, Tooltip, Drawer } from '@fluentui/rea import { useAppStore } from '../../store/app' import { setDistrictsData, setRegionsData } from '../../store/regions' import View from 'ol/View' -import { Icon, Style } from 'ol/style' -import { fromLonLat } from 'ol/proj' +import { Style } from 'ol/style' import MapRegionSelect from './MapRegionSelect/MapRegionSelect' import MapLayersSelect from './MapLayers/MapLayersSelect' import MapObjectSearch from './MapObjectSearch/MapObjectSearch' @@ -42,19 +40,6 @@ const swrOptions: SWRConfiguration = { revalidateOnFocus: false } -// City settings mockup -function getCitySettings() { - return { - city_id: 0, - image_width: 8500, - image_height: 12544, - scale: 9000, - offset_x: 0,//14442665.697619518, - offset_y: 0,//8884520.63524492, - rotation: 0 - } as ICitySettings -} - const MapComponent = ({ id, active = false @@ -122,17 +107,7 @@ const MapComponent = ({ // First step: On region bounds loaded useEffect(() => { if (regionsLayer && regionBoundsData) { - if (Array.isArray(regionBoundsData)) { - regionBoundsData.map(bound => { - const geoJson = new GeoJSON() //new GeoJSON({ featureProjection: 'EPSG:3857' }) - const geometry = geoJson.readGeometry(bound) as Geometry - - const feature = new Feature(geometry) - feature.setProperties(bound.properties) - - regionsLayer.getSource()?.addFeature(feature) - }) - } + loadRegionBounds(regionBoundsData, regionsLayer) } return () => { @@ -144,35 +119,13 @@ const MapComponent = ({ useEffect(() => { if (regionsData && Array.isArray(regionsData) && capitalsLayer) { - regionsData.map((region) => { - const lon = region.capital_longitude - const lat = region.capital_latitude + loadRegionCapitals(regionsData, capitalsLayer) + } - if (lon != null && lat != null) { - const marker = new Feature({ - geometry: new Point(fromLonLat([lon, lat], 'EPSG:3857')), - regionId: region.id, // optional, useful for interactivity - }); - - marker.setStyle(new Style({ - image: new Icon({ - src: '/map_pin_icon.svg', - scale: 0.2 - }) - })) - - if (region.capital) { - marker.setProperties({ - entity_id: region.capital - }) - } - - // Optional styling for capital marker - - capitalsLayer.getSource()?.addFeature(marker); - } - - }) + return () => { + if (capitalsLayer) { + capitalsLayer.getSource()?.clear() + } } }, [regionsData, capitalsLayer]) @@ -254,7 +207,6 @@ const MapComponent = ({ // Satellite tiles setting useEffect(() => { - console.log("Setting satLayer", satMapsProvider) if (satLayer) { if (satMapsProvider === 'google') { satLayer.setSource(googleMapsSatelliteSource) @@ -383,52 +335,16 @@ const MapComponent = ({ useEffect(() => { const districtBoundSource = districtBoundLayer.getSource() - if (selectedDistrict && districtBoundSource && districtBoundSource.getFeatures().length > 0) { + if (map && selectedDistrict && districtBoundSource && districtBoundSource.getFeatures().length > 0) { const center: Coordinate = getCenter(districtBoundSource.getExtent()) const settings = getCitySettings() - if (Array.isArray(figuresData)) { - figuresLayer.getSource()?.clear() - if (figuresData.length > 0) { - const geoJsonObject = { - type: "FeatureCollection", - features: figuresData.map((figure: IFigure) => processFigure( - figure, - settings.scale, - [center[0], center[1]] - )), - } + addFigures(center, figuresData, figuresLayer, settings, map) - const features = new GeoJSON().readFeatures(geoJsonObject) - - figuresLayer.getSource()?.addFeatures(features) - - if (map) { - const extent = figuresLayer.getSource()?.getExtent() - - if (extent) { - map.getView().fit(fromExtent(extent), { duration: 500 }) - } - } - } - } - - if (Array.isArray(linesData)) { - linesLayer.getSource()?.clear() - if (linesData.length > 0) { - const geoJsonObject = { - type: "FeatureCollection", - features: linesData.map((line: ILine) => processLine(line, settings.scale, [center[0], center[1]])), - } - - const features = new GeoJSON().readFeatures(geoJsonObject) - - linesLayer.getSource()?.addFeatures(features) - } - } + addLines(center, linesData, linesLayer, settings) } - }, [figuresData, linesData, selectedDistrict, selectedYear, districtBoundLayer]) + }, [map, figuresData, linesData, selectedDistrict, selectedYear, districtBoundLayer]) useEffect(() => { if (selectedDistrict && districtData) { diff --git a/client/src/components/map/mapUtils.ts b/client/src/components/map/mapUtils.ts index 29aceb3..c398035 100644 --- a/client/src/components/map/mapUtils.ts +++ b/client/src/components/map/mapUtils.ts @@ -4,7 +4,7 @@ import Feature from "ol/Feature"; import GeoJSON from "ol/format/GeoJSON"; import { Circle, Geometry, LineString, Point, Polygon, SimpleGeometry } from "ol/geom"; import VectorLayer from "ol/layer/Vector"; -import { addCoordinateTransforms, addProjection, get, getTransform, Projection, ProjectionLike, transform } from "ol/proj"; +import { addCoordinateTransforms, addProjection, fromLonLat, get, getTransform, Projection, ProjectionLike, transform } from "ol/proj"; import proj4 from "proj4"; import { Type } from "ol/geom/Geometry"; import { Draw, Modify, Snap, Translate } from "ol/interaction"; @@ -12,7 +12,7 @@ import { never, noModifierKeys, platformModifierKeyOnly, primaryAction } from "o import { IGeometryType } from "../../interfaces/map"; import { uploadCoordinates } from "../../actions/map"; import { ImageStatic } from "ol/source"; -import { IFigure, ILine } from "../../interfaces/gis"; +import { ICitySettings, IFigure, ILine } from "../../interfaces/gis"; import { fromCircle, fromExtent } from "ol/geom/Polygon"; import { measureStyleFunction, modifyStyle } from "./Measure/MeasureStyles"; import { getCurrentTool, getDraw, getDrawingLayerSource, getImageLayer, getMap, getMeasureClearPrevious, getMeasureDraw, getMeasureModify, getMeasureSource, getMeasureType, getOverlayLayerSource, getSnap, getTipPoint, getTranslate, PrintOrientation, setDraw, setFile, setMeasureDraw, setPolygonExtent, setRectCoords, setSnap, setTranslate, useMapStore } from "../../store/map"; @@ -20,6 +20,122 @@ import Collection from "ol/Collection"; import { SketchCoordType } from "ol/interaction/Draw"; import VectorImageLayer from "ol/layer/VectorImage"; import VectorSource from "ol/source/Vector"; +import Map from "ol/Map"; +import { Icon, Style } from "ol/style"; + +export function getCitySettings() { + return { + city_id: 0, + image_width: 8500, + image_height: 12544, + scale: 9000, + offset_x: 0,//14442665.697619518, + offset_y: 0,//8884520.63524492, + rotation: 0 + } as ICitySettings +} + +export const loadRegionCapitals = (regionsData: any, capitalsLayer: VectorLayer, any>) => { + if (Array.isArray(regionsData)) { + regionsData.map((region) => { + const lon = region.capital_longitude + const lat = region.capital_latitude + + if (lon != null && lat != null) { + const marker = new Feature({ + geometry: new Point(fromLonLat([lon, lat], 'EPSG:3857')), + regionId: region.id, // optional, useful for interactivity + }); + + marker.setStyle(new Style({ + image: new Icon({ + src: '/map_pin_icon.svg', + scale: 0.2 + }) + })) + + if (region.capital) { + marker.setProperties({ + entity_id: region.capital + }) + } + + // Optional styling for capital marker + + capitalsLayer.getSource()?.addFeature(marker); + } + }) + } +} + +export const loadRegionBounds = (regionBoundsData: any, regionsLayer: VectorImageLayer, VectorSource>>) => { + if (Array.isArray(regionBoundsData)) { + regionBoundsData.map(bound => { + const geoJson = new GeoJSON() //new GeoJSON({ featureProjection: 'EPSG:3857' }) + const geometry = geoJson.readGeometry(bound) as Geometry + + const feature = new Feature(geometry) + feature.setProperties(bound.properties) + + regionsLayer.getSource()?.addFeature(feature) + }) + } +} + +export const addFigures = ( + center: Coordinate, + figuresData: any, + figuresLayer: VectorLayer>, Feature>, + settings: ICitySettings, + map: Map +) => { + if (Array.isArray(figuresData)) { + figuresLayer.getSource()?.clear() + if (figuresData.length > 0) { + const geoJsonObject = { + type: "FeatureCollection", + features: figuresData.map((figure: IFigure) => processFigure( + figure, + settings.scale, + [center[0], center[1]] + )), + } + + const features = new GeoJSON().readFeatures(geoJsonObject) + + figuresLayer.getSource()?.addFeatures(features) + + if (map) { + const extent = figuresLayer.getSource()?.getExtent() + + if (extent) { + map.getView().fit(fromExtent(extent), { duration: 500 }) + } + } + } + } +} + +export const addLines = ( + center: Coordinate, + linesData: any, + linesLayer: VectorLayer>, Feature>, + settings: ICitySettings +) => { + if (Array.isArray(linesData)) { + linesLayer.getSource()?.clear() + if (linesData.length > 0) { + const geoJsonObject = { + type: "FeatureCollection", + features: linesData.map((line: ILine) => processLine(line, settings.scale, [center[0], center[1]])), + } + + const features = new GeoJSON().readFeatures(geoJsonObject) + + linesLayer.getSource()?.addFeatures(features) + } + } +} export const calculateAngle = (coords: [number, number][]) => { const [start, end] = coords;