add selection tool

This commit is contained in:
2025-10-20 17:52:50 +09:00
parent 6d31e1f37a
commit 2180afa529
4 changed files with 50 additions and 33 deletions

View File

@ -4,7 +4,7 @@ import { saveFeatures } from '../mapUtils';
import { Button, Tooltip } from '@fluentui/react-components';
import { useAppStore } from '../../../store/app';
import { useObjectsStore } from '../../../store/objects';
import { AddFilled, RulerRegular, SubtractFilled } from '@fluentui/react-icons';
import { AddFilled, RulerRegular, SelectObjectRegular, SelectObjectSkewEditRegular, SubtractFilled } from '@fluentui/react-icons';
const MapToolbar = ({
map_id
@ -25,11 +25,17 @@ const MapToolbar = ({
</Tooltip>
<Tooltip content={"Редактировать"} relationship='label' hideDelay={0} showDelay={0} withArrow>
<Button icon={<IconTransformPoint />} appearance={currentTool === 'Edit' ? 'primary' : 'transparent'} onClick={() => {
<Button icon={<SelectObjectSkewEditRegular />} appearance={currentTool === 'Edit' ? 'primary' : 'transparent'} onClick={() => {
setCurrentTool(map_id, 'Edit')
}} />
</Tooltip>
<Tooltip content={"Выделение"} relationship='label' hideDelay={0} showDelay={0} withArrow>
<Button icon={<SelectObjectRegular />} appearance={currentTool === 'Selection' ? 'primary' : 'transparent'} onClick={() => {
setCurrentTool(map_id, 'Selection')
}} />
</Tooltip>
<Tooltip content={"Точка"} relationship='label' hideDelay={0} showDelay={0} withArrow>
<Button icon={<IconPoint />} appearance={currentTool === 'Point' ? 'primary' : 'transparent'} onClick={() => {
setCurrentTool(map_id, 'Point')

View File

@ -15,13 +15,13 @@ import { ImageStatic } from "ol/source";
import { 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 } from "../../store/map";
import { getCurrentTool, getDraw, getDrawingLayerSource, getImageLayer, getMap, getMeasureClearPrevious, getMeasureDraw, getMeasureModify, getMeasureSource, getMeasureType, getOverlayLayerSource, getSelectionDragBox, getSnap, getTipPoint, getTranslate, PrintOrientation, setDraw, setFile, setMeasureDraw, setPolygonExtent, setRectCoords, setSnap, setTranslate, useMapStore } from "../../store/map";
import Collection from "ol/Collection";
import { SketchCoordType } from "ol/interaction/Draw";
import VectorImageLayer from "ol/layer/VectorImage";
import VectorSource from "ol/source/Vector";
const calculateAngle = (coords: [number, number][]) => {
export const calculateAngle = (coords: [number, number][]) => {
const [start, end] = coords;
const dx = end[0] - start[0];
const dy = end[1] - start[1];
@ -390,7 +390,9 @@ export const addInteractions = (
const map = getMap(map_id)
const measureModify = getMeasureModify(map_id)
if (currentTool !== 'Measure' && currentTool !== 'Mover' && currentTool !== 'Edit') {
if (currentTool !== 'Measure' && currentTool !== 'Mover' && currentTool !== 'Edit' && currentTool !== 'Selection') {
map?.getInteractions().clear()
setDraw(map_id, new Draw({
source: getDrawingLayerSource(map_id),
type: currentTool as Type,
@ -430,6 +432,8 @@ export const addInteractions = (
}
if (currentTool == 'Measure') {
map?.getInteractions().clear()
const drawType = measureType;
const activeTip =
'Кликните, чтобы продолжить рисовать ' +
@ -474,6 +478,7 @@ export const addInteractions = (
const translate = getTranslate(map_id)
if (translate) {
map?.getInteractions().clear()
map?.addInteraction(translate)
}
}
@ -482,6 +487,17 @@ export const addInteractions = (
//const modify = new Modify()
//map?.current?.addInteraction(translate.current)
}
if (currentTool == 'Selection') {
console.log("Selection tool selected")
map?.getInteractions().clear()
const selectionDragBox = useMapStore.getState().id[map_id].selectionDragBox
if (selectionDragBox) {
map?.addInteraction(selectionDragBox)
}
}
}
export const zoomToFeature = (map_id: string, feature: Feature | undefined) => {
@ -525,7 +541,7 @@ export const loadFeatures = (map_id: string) => {
}
}
function rotateProjection(projection: ProjectionLike, angle: number, extent: Extent) {
export function rotateProjection(projection: ProjectionLike, angle: number, extent: Extent) {
function rotateCoordinate(coordinate: Coordinate, angle: number, anchor: Coordinate) {
const coord = rotate(
[coordinate[0] - anchor[0], coordinate[1] - anchor[1]],
@ -606,13 +622,13 @@ function rotateProjection(projection: ProjectionLike, angle: number, extent: Ext
}
}
const calculateCentroid = (bottomLeft: Coordinate, topLeft: Coordinate, topRight: Coordinate, bottomRight: Coordinate) => {
export const calculateCentroid = (bottomLeft: Coordinate, topLeft: Coordinate, topRight: Coordinate, bottomRight: Coordinate) => {
const x = (bottomLeft[0] + topLeft[0] + topRight[0] + bottomRight[0]) / 4;
const y = (bottomLeft[1] + topLeft[1] + topRight[1] + bottomRight[1]) / 4;
return [x, y];
}
function calculateRotationAngle(bottomLeft: Coordinate, bottomRight: Coordinate) {
export function calculateRotationAngle(bottomLeft: Coordinate, bottomRight: Coordinate) {
// Calculate the difference in x and y coordinates between bottom right and bottom left
const deltaX = bottomRight[0] - bottomLeft[0];
const deltaY = bottomRight[1] - bottomLeft[1];
@ -623,7 +639,7 @@ function calculateRotationAngle(bottomLeft: Coordinate, bottomRight: Coordinate)
return angle;
}
function calculateExtent(bottomLeft: Coordinate, topLeft: Coordinate, topRight: Coordinate, bottomRight: Coordinate) {
export function calculateExtent(bottomLeft: Coordinate, topLeft: Coordinate, topRight: Coordinate, bottomRight: Coordinate) {
const width = distance(bottomLeft, bottomRight);
const height = distance(bottomLeft, topLeft);
@ -641,19 +657,19 @@ function calculateExtent(bottomLeft: Coordinate, topLeft: Coordinate, topRight:
return extent;
}
function getTilesPerSide(zoom: number) {
export function getTilesPerSide(zoom: number) {
return Math.pow(2, zoom)
}
function normalize(value: number, min: number, max: number) {
export function normalize(value: number, min: number, max: number) {
return (value - min) / (max - min)
}
function getTileIndex(normalized: number, tilesPerSide: number) {
export function getTileIndex(normalized: number, tilesPerSide: number) {
return Math.floor(normalized * tilesPerSide)
}
function getGridCellPosition(x: number, y: number, extent: Extent, zoom: number) {
export function getGridCellPosition(x: number, y: number, extent: Extent, zoom: number) {
const tilesPerSide = getTilesPerSide(zoom);
const minX = extent[0]
const minY = extent[1]
@ -671,7 +687,7 @@ function getGridCellPosition(x: number, y: number, extent: Extent, zoom: number)
return { tileX, tileY };
}
function calculateTransformations(alignPoints: Coordinate[]) {
export function calculateTransformations(alignPoints: Coordinate[]) {
const [P1, P2, P3, P4] = alignPoints;
// Translation vector (move P1 to P3)
@ -690,7 +706,7 @@ function calculateTransformations(alignPoints: Coordinate[]) {
return { translation, scale, rotation };
}
function calculateCenter(geometry: SimpleGeometry) {
export function calculateCenter(geometry: SimpleGeometry) {
let center, coordinates, minRadius;
const type = geometry.getType();
if (type === 'Polygon') {
@ -733,7 +749,7 @@ function calculateCenter(geometry: SimpleGeometry) {
};
}
function applyTransformations(
export function applyTransformations(
layer: VectorLayer,
transformations: {
translation: number[];
@ -763,18 +779,4 @@ function applyTransformations(
});
console.log("Transformations applied to figuresLayer");
}
export {
rotateProjection,
calculateTransformations,
calculateRotationAngle,
calculateExtent,
calculateCentroid,
getTilesPerSide,
normalize,
getTileIndex,
getGridCellPosition,
calculateCenter,
applyTransformations
}

View File

@ -8,7 +8,7 @@ import { TypeRole } from '../interfaces/gis';
import VectorSource from 'ol/source/Vector';
import Feature from 'ol/Feature';
import { containsExtent, Extent } from 'ol/extent';
import { Draw, Modify, Select, Snap, Translate } from 'ol/interaction';
import { DragBox, Draw, Modify, Select, Snap, Translate } from 'ol/interaction';
import TileLayer from 'ol/layer/Tile';
import { v4 as uuidv4 } from 'uuid';
import { googleMapsSatelliteSource } from '../components/map/MapSources';
@ -18,7 +18,7 @@ import ImageLayer from 'ol/layer/Image';
import { drawingLayerStyle, figureStyle, highlightStyleRed, highlightStyleYellow, lineStyle, overlayStyle, regionsLayerStyle, selectStyle } from '../components/map/MapStyles';
import { Fill, Stroke, Style } from 'ol/style';
import { VectorImage } from 'ol/layer';
import { click, pointerMove } from 'ol/events/condition';
import { click, noModifierKeys, pointerMove } from 'ol/events/condition';
import { measureStyleFunction, modifyStyle } from '../components/map/Measure/MeasureStyles';
import MapBrowserEvent from 'ol/MapBrowserEvent';
import { get, transform } from 'ol/proj';
@ -96,6 +96,7 @@ interface MapState {
printOrientation: PrintOrientation;
printScale: PrintScale;
printScaleLine: boolean;
selectionDragBox: DragBox;
}>;
}
@ -267,6 +268,10 @@ export const initializeMapState = (
}
})
const selectionDragBox = new DragBox({
condition: noModifierKeys
})
const map = new Map({
controls: [],
layers: [
@ -476,13 +481,16 @@ export const initializeMapState = (
printOrientation: 'horizontal',
printRes: 72,
printScale: '250',
printScaleLine: true
printScaleLine: true,
selectionDragBox: selectionDragBox
}
}
}
})
}
export const getSelectionDragBox = (id: string) => useMapStore.getState().id[id].selectionDragBox
export const setPrintOrientation = (id: string, orientation: PrintOrientation) => useMapStore.setState((state) => {
return {
id: {

View File

@ -11,4 +11,5 @@ export type ToolType =
"Measure" |
"Mover" |
"Edit" |
"Selection" |
null