Skip to content

Commit a0eeb5d

Browse files
sim51jacomyal
authored andcommitted
front: editor - fix null_geometry and improve mouse hover due to maplibre migration
1 parent 9f92d43 commit a0eeb5d

File tree

5 files changed

+64
-42
lines changed

5 files changed

+64
-42
lines changed

front/src/applications/editor/Map.tsx

+42-27
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import maplibregl from 'maplibre-gl';
44
import ReactMapGL, { AttributionControl, ScaleControl } from 'react-map-gl';
55
import { withTranslation } from 'react-i18next';
66
import { TFunction } from 'i18next';
7-
87
import VirtualLayers from 'applications/osrd/views/OSRDSimulation/VirtualLayers';
98
import colors from 'common/Map/Consts/colors';
109
import 'common/Map/Map.scss';
@@ -17,6 +16,7 @@ import Platforms from '../../common/Map/Layers/Platforms';
1716
import osmBlankStyle from '../../common/Map/Layers/osmBlankStyle';
1817
import OrthoPhoto from '../../common/Map/Layers/OrthoPhoto';
1918
import { Viewport } from '../../reducers/map';
19+
import { getMapMouseEventNearestFeature } from '../../utils/mapboxHelper';
2020
import EditorContext from './context';
2121
import {
2222
CommonToolState,
@@ -99,26 +99,39 @@ const MapUnplugged: FC<PropsWithChildren<MapProps>> = ({
9999
onMove={(e) => setViewport(e.viewState)}
100100
onMoveStart={() => setMapState((prev) => ({ ...prev, isDragging: true }))}
101101
onMoveEnd={() => setMapState((prev) => ({ ...prev, isDragging: false }))}
102-
onMouseEnter={(e) => {
103-
setMapState((prev) => ({ ...prev, isHovering: true }));
104-
const feature = (e.features || [])[0];
105-
if (activeTool.onHover) {
106-
activeTool.onHover(e, extendedContext);
107-
} else if (feature && feature.properties) {
108-
const entity = feature?.properties?.id
109-
? editorState.entitiesIndex[feature.properties.id]
110-
: undefined;
111-
setToolState({
112-
...toolState,
113-
hovered: entity || null,
114-
});
102+
onMouseMove={(e) => {
103+
const nearestResult = getMapMouseEventNearestFeature(e);
104+
const partialToolState: Partial<CommonToolState> = {
105+
hovered: null,
106+
mousePosition: [e.lngLat.lng, e.lngLat.lat],
107+
};
108+
const partialMapState: Partial<MapState> = { isHovering: false };
109+
110+
// if we hover something
111+
if (nearestResult) {
112+
const { feature } = nearestResult;
113+
const eventWithFeature = {
114+
...e,
115+
preventDefault: e.preventDefault,
116+
features: [feature],
117+
};
118+
partialMapState.isHovering = true;
119+
if (activeTool.onHover) {
120+
activeTool.onHover(eventWithFeature, extendedContext);
121+
} else if (feature && feature.properties) {
122+
const entity = feature?.properties?.id
123+
? editorState.entitiesIndex[feature.properties.id]
124+
: undefined;
125+
partialToolState.hovered = entity || null;
126+
}
115127
} else {
116-
setToolState({ ...toolState, hovered: null });
128+
if (activeTool.onMove) {
129+
activeTool.onMove(e, extendedContext);
130+
}
117131
}
118-
}}
119-
onMouseLeave={() => {
120-
setMapState((prev) => ({ ...prev, isHovering: false }));
121-
setToolState({ ...toolState, mousePosition: null, hovered: null });
132+
133+
setToolState({ ...toolState, ...partialToolState });
134+
setMapState((prev) => ({ ...prev, ...partialMapState }));
122135
}}
123136
onLoad={(e) => {
124137
// need to call resize, otherwise sometime the canvas doesn't take 100%
@@ -140,17 +153,19 @@ const MapUnplugged: FC<PropsWithChildren<MapProps>> = ({
140153
}
141154
cursor={cursor}
142155
onClick={(e) => {
156+
const nearestResult = getMapMouseEventNearestFeature(e);
157+
const eventWithFeature = nearestResult
158+
? {
159+
...e,
160+
preventDefault: e.preventDefault,
161+
features: [nearestResult.feature],
162+
}
163+
: e;
143164
if (toolState.hovered && activeTool.onClickFeature) {
144-
activeTool.onClickFeature(toolState.hovered, e, extendedContext);
165+
activeTool.onClickFeature(toolState.hovered, eventWithFeature, extendedContext);
145166
}
146167
if (activeTool.onClickMap) {
147-
activeTool.onClickMap(e, extendedContext);
148-
}
149-
}}
150-
onMouseMove={(e) => {
151-
setToolState({ ...toolState, mousePosition: [e.lngLat.lng, e.lngLat.lat] });
152-
if (activeTool.onMove) {
153-
activeTool.onMove(e, extendedContext);
168+
activeTool.onClickMap(eventWithFeature, extendedContext);
154169
}
155170
}}
156171
>

front/src/applications/editor/tools/pointEdition/components.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ export const PointEditionMessages: FC = () => {
217217
PointEditionState<EditorEntity>
218218
>;
219219

220-
if (!state.entity.geometry) {
220+
if (!state.entity.geometry || isEqual(state.entity.geometry, NULL_GEOMETRY)) {
221221
return state.nearestPoint
222222
? t(`Editor.tools.point-edition.help.stop-dragging-on-line`)
223223
: t(`Editor.tools.point-edition.help.stop-dragging-no-line`);

front/src/applications/editor/tools/pointEdition/tool-factory.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,8 @@ The entity ${entity.properties.id} position computed by Turf.js does not match t
189189
return ['editor/geo/track-main', POINT_LAYER_ID];
190190
},
191191
getCursor({ state }, { isDragging }) {
192-
if (isDragging || !state.entity.geometry) return 'move';
192+
if (isDragging || !state.entity.geometry || isEqual(state.entity.geometry, NULL_GEOMETRY))
193+
return 'move';
193194
if (state.isHoveringTarget) return 'pointer';
194195
return 'default';
195196
},

front/src/types/mapbox-gl.ts

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
} from 'mapbox-gl';
1313

1414
export type {
15+
MapboxGeoJSONFeature,
1516
MapLayerMouseEvent,
1617
AnyPaint,
1718
CirclePaint,

front/src/utils/mapboxHelper.ts

+18-13
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import nearestPointOnLine from '@turf/nearest-point-on-line';
2222
import nearestPoint, { NearestPoint } from '@turf/nearest-point';
2323
import fnDistance from '@turf/distance';
2424
import fnExplode from '@turf/explode';
25-
import { Zone, MapLayerMouseEvent } from '../types';
25+
import { Zone, MapLayerMouseEvent, MapboxGeoJSONFeature } from '../types';
2626
import { getAngle } from '../applications/editor/data/utils';
2727

2828
/**
@@ -290,30 +290,35 @@ export function getNearestPoint(lines: Feature<LineString>[], coord: Coord): Nea
290290
*/
291291
export function getMapMouseEventNearestFeature(
292292
e: MapLayerMouseEvent,
293-
opts?: { layersId?: string[]; tolerance: number }
294-
): { feature: Feature; nearest: number[]; distance: number } | null {
293+
opts?: { layersId?: string[]; tolerance: number; excludeOsm: boolean }
294+
): { feature: MapboxGeoJSONFeature; nearest: number[]; distance: number } | null {
295295
const layers = opts?.layersId;
296-
const tolerance = opts?.tolerance || 30;
296+
const tolerance = opts?.tolerance || 15;
297+
const excludeOsm = opts?.excludeOsm || true;
297298
const { target: map, point } = e;
298299
const coord = e.lngLat.toArray();
299300

300-
const features = map.queryRenderedFeatures(
301-
[
302-
[point.x - tolerance / 2, point.y - tolerance / 2],
303-
[point.x + tolerance / 2, point.y + tolerance / 2],
304-
],
305-
{ layers }
306-
);
301+
const features = map
302+
.queryRenderedFeatures(
303+
[
304+
[point.x - tolerance / 2, point.y - tolerance / 2],
305+
[point.x + tolerance / 2, point.y + tolerance / 2],
306+
],
307+
{ layers }
308+
)
309+
.filter((f) => (excludeOsm ? !f.layer.id.startsWith('osm') : true));
307310

308311
const result = head(
309312
sortBy(
310-
features.map((feature: Feature) => {
313+
features.map((feature) => {
311314
let distance = Infinity;
312315
let nearestFeaturePoint: Feature<Point> | null = null;
313316
switch (feature.geometry.type) {
314317
case 'Point': {
315318
nearestFeaturePoint = feature as Feature<Point>;
316-
distance = fnDistance(coord, nearestFeaturePoint.geometry.coordinates);
319+
// we boost point, otherwise when a point is on line,
320+
// it's too easy to find a point of line closest
321+
distance = 0.7 * fnDistance(coord, nearestFeaturePoint.geometry.coordinates);
317322
break;
318323
}
319324
case 'LineString': {

0 commit comments

Comments
 (0)