Skip to content

Commit

Permalink
Merge indexing prevention (#181)
Browse files Browse the repository at this point in the history
* AB#25225: Remove point property from restroom query (#175)

* better marker for mapillary

* clean up

* use camera angle to filter initial pictures

* Bump hsl-map-style version to 1.1.3 (#178)

* AB#48697: Prevent search engine indexing (#180)

* AB#48634: Update hsl-map-style dependency to 1.2.0 (#182)

* AB#39612: Remove unrealistic durations from stop list (#179)

* AB#39612: Remove unrealistic durations from stop list

* Tweak styles

---------

Co-authored-by: Anton Jyrkiäinen <anton.jyrkiainen@helsinki.fi>
  • Loading branch information
e-halinen and ahjyrkia authored Dec 20, 2024
1 parent 6f7c674 commit 1fd63f7
Show file tree
Hide file tree
Showing 9 changed files with 122 additions and 68 deletions.
1 change: 1 addition & 0 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta name="robots" content="noindex,nofollow" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
Expand Down
13 changes: 8 additions & 5 deletions src/components/MapillaryViewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { getClosestMapillaryImage } from "../utils/mapUtils";
import styles from "./mapillaryViewer.module.css";

const MapillaryViewer = observer(
({ location, elementId, onNavigation, className, onCloseViewer }) => {
({ location, elementId, onNavigation, className, onCloseViewer, selectedRoutes }) => {
const [error, setError] = useState(null);
const mly = useRef(null);
const resizeListener = useRef(null);
Expand Down Expand Up @@ -44,9 +44,10 @@ const MapillaryViewer = observer(

window.addEventListener("resize", currentResizeListener);
resizeListener.current = currentResizeListener;

currentMly.setFilter(["==", "organizationKey", "227572519135262"]);
currentMly.on("image", (evt) => onNavigation(evt.image.lngLat));
currentMly.on("image", (evt) => {
onNavigation({latlng: evt.image.lngLat, computedCompassAngle: evt.image.computedCompassAngle})
});
mly.current = currentMly;
}, [mly.current, resizeListener.current]);

Expand All @@ -57,19 +58,21 @@ const MapillaryViewer = observer(
const closest = await getClosestMapillaryImage({
lat: location.lat,
lng: location.lng,
selectedRoutes
});
if (closest && closest.id) {
mly.current
.moveTo(closest.id)
.then((node) => {
onNavigation(node.lngLat);
.then((image) => {
onNavigation({latlng: image.lngLat, computedCompassAngle: image.computedCompassAngle});
})
.catch((error) => console.warn(error));
setError(null);
} else {
setError("Katukuvia ei löytynyt.");
}
} catch (e) {
console.log(e)
setError("Katunäkymän haku epäonnistui.");
}
}
Expand Down
88 changes: 43 additions & 45 deletions src/components/mapLeaflet.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import locationIconOffline from "../icons/icon-location-offline.svg";
import fullScreenEnterIcon from "../icons/icon-fullscreen-enter.svg";
import fullScreenExitIcon from "../icons/icon-fullscreen-exit.svg";
import restroomIcon from "../icons/restroom-solid.svg";
import { mapillaryImageMargerIcon } from '../icons/mapillaryImageMargerIcon.js';
import styles from "./mapLeaflet.module.css";
import MapillaryViewer from "./MapillaryViewer.js";
import { isMobile } from "../utils/browser";
Expand Down Expand Up @@ -83,11 +84,11 @@ const addMarkersToLayer = (stops, direction, map, restrooms) => {
}
closeByRestrooms.forEach((closeByRestroom) => {
let icon = mapIcon(restroomIcon);
const markerr = L.marker([closeByRestroom.lat, closeByRestroom.lon], { icon });
markerr.bindTooltip(`${closeByRestroom.nameFi}, ${closeByRestroom.addressFi}`, {
const marker = L.marker([closeByRestroom.lat, closeByRestroom.lon], { icon });
marker.bindTooltip(`${closeByRestroom.nameFi}, ${closeByRestroom.addressFi}`, {
direction: "top",
});
markerr.addTo(map);
marker.addTo(map);
});
};

Expand Down Expand Up @@ -296,18 +297,6 @@ class MapLeaflet extends React.Component {
}

componentDidUpdate(prevProps, prevState) {
// All layers except the base layer and mapillary features are removed when the component is updated
this.map.eachLayer((layer) => {
if (!layer.options.baseLayer) {
if (
layer.options.type !== "mapillaryGeoJsonLayer" &&
layer.options.type !== "mapillaryImageMarker" &&
layer.options.type !== "mapillaryHighlightMarker"
) {
this.map.removeLayer(layer);
}
}
});
// Leaflet map is updated once geometry and stop data has been fetched
// The view (bounding box) is set only the first time the route stops are recieved
if (
Expand Down Expand Up @@ -468,6 +457,12 @@ class MapLeaflet extends React.Component {
drawControl: true,
});

if (this.map) {
this.map.createPane('imageMarkerPane');
this.map.getPane('imageMarkerPane').style.zIndex = 650;
this.map.getPane('imageMarkerPane').style.pointerEvents = 'none';
}

const baseMaps = {
Aerial: aerialTileLayer,
Digitransit: digitransitTileLayer,
Expand Down Expand Up @@ -524,44 +519,43 @@ class MapLeaflet extends React.Component {
if (!this.state.showMapillaryLayer) {
return;
}
for (const key in e.target._layers) {
const layer = e.target._layers[key];
if (layer) {
if (layer.options.type === "mapillaryHighlightMarker") {
this.setState({ mapillaryLocation: layer._latlng });
}
e.target.eachLayer(layer => {
if (layer.options && layer.options.type === "mapillaryHighlightMarker") {
const latLng = layer.getLatLng();
this.setState({ mapillaryLocation: latLng });
}
}
});
}

setMapillaryLocation(position, playService) {
if (!this.state.mapillaryLocation) {
if (playService) {
playService.stop();
}
return;


setMapillaryLocation({latlng, computedCompassAngle = 0}) {
function createRotatedIcon(computedCompassAngle) {
const svgIconHtml = mapillaryImageMargerIcon(computedCompassAngle);

const svgIcon = L.divIcon({
className: 'custom-div-icon',
html: svgIconHtml,
iconSize: [15, 15],
iconAnchor: [7.5, 7.5]
});

return svgIcon;
}
if (this.imageMarker) {
this.imageMarker.remove();
this.imageMarker = null;
}
if (this.map && position) {
const marker = this.createMarker({
position: position,
opacity: 1,
type: "mapillaryImageMarker",
color: "red",
});
if (!this.imageMarker) {
this.imageMarker = marker;
this.imageMarker.addTo(this.map);
} else {
this.imageMarker.setLatLng(position);
}
} else if (!position) {

if (this.map && latlng) {
const marker = L.marker(latlng, {
icon: createRotatedIcon(computedCompassAngle)
}).addTo(this.map);

this.imageMarker = marker;
} else if (!latlng) {
this.removeMarker();
}
this.setState({ mapillaryImageLocation: { lat: position.lat, lng: position.lon } });
this.setState({ mapillaryImageLocation: { lat: latlng.lat, lng: latlng.lng } });
}

onHover = (e) => {
Expand Down Expand Up @@ -597,6 +591,7 @@ class MapLeaflet extends React.Component {
radius: 4,
color: options.color,
opacity: options.opacity,
pane: 'imageMarkerPane',
});
};

Expand Down Expand Up @@ -628,8 +623,10 @@ class MapLeaflet extends React.Component {
});
this.setState({ mapillaryLocation: null });
};

render() {
const selectedRouteObjects = this.props.routes.filter(route =>
this.props.selectedRoutes.includes(route.id)
);
return (
<div
className={classNames(styles.container, {
Expand All @@ -655,6 +652,7 @@ class MapLeaflet extends React.Component {
elementId="mly"
onNavigation={this.setMapillaryLocation}
location={this.state.mapillaryLocation}
selectedRoutes={selectedRouteObjects}
/>
)}
</div>
Expand Down
11 changes: 1 addition & 10 deletions src/components/stop.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,7 @@ import styles from "./stop.module.css";
import PropTypes from "prop-types";
import timeIcon2 from "../icons/icon-time2.svg";

const Stop = ({
shortId,
stopNameFi,
stopNameSv,
duration,
platform,
onClick,
timingStopType,
}) => (
const Stop = ({ shortId, stopNameFi, stopNameSv, platform, onClick, timingStopType }) => (
<button className={styles.root} onClick={onClick}>
<p className={styles.textTitle}>{shortId}</p>
<div className={styles.infoContainer}>
Expand All @@ -21,7 +13,6 @@ const Stop = ({
</div>
<div className={styles.additionalInfoContainer}>
<div className={styles.textAdditional}>{stopNameSv}</div>
<div className={styles.textDuration}>{duration} min</div>
</div>
</div>
{timingStopType > 0 && (
Expand Down
2 changes: 1 addition & 1 deletion src/components/stop.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
.textTitle {
font-size: var(--mainTextSize);
font-weight: 600;
width: 68px;
width: 100px;
flex-wrap: wrap;
}

Expand Down
1 change: 0 additions & 1 deletion src/components/stopList.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ const renderStops = (routeStops, isFullScreen, setMapCenter) =>
shortId={stop.shortId}
stopNameFi={stop.nameFi}
stopNameSv={stop.nameSe}
duration={stop.duration}
timingStopType={stop.timingStopType}
platform={stop.platform}
onClick={() => setMapCenter({ lat: stop.lat, lng: stop.lon, stopId: stop.stopId })}
Expand Down
7 changes: 7 additions & 0 deletions src/icons/mapillaryImageMargerIcon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

export function mapillaryImageMargerIcon(angle) {
const correctedAngle = angle - 90;
return `<svg fill="red" width="15px" height="15px" viewBox="-96 0 512 512" xmlns="http://www.w3.org/2000/svg" style="transform: rotate(${correctedAngle}deg); transform-origin: center;">` +
`<path d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"/>` +
`</svg>`;
}
63 changes: 59 additions & 4 deletions src/utils/mapUtils.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import * as turf from "@turf/turf";

const IMAGE_COMPASS_ANGLE_THRESHOLD = 20;

const wait = async (delay) => {
return new Promise((resolve) => setTimeout(resolve, delay));
};
Expand All @@ -18,12 +20,63 @@ const fetchRetry = async (url, delay, tries, fetchOptions = {}) => {
return res;
};

export async function getClosestMapillaryImage({ lat, lng }) {

const bearingToCompassAngle = (bearing) => {
const compassAngle = (bearing + 360) % 360;
return compassAngle;
};

export async function getCompassAngle({ closestCoordinate, nextCoordinate }) {
const startPoint = turf.point(closestCoordinate);
const endPoint = turf.point(nextCoordinate);

const bearing = turf.bearing(startPoint, endPoint);

const compassAngle = bearingToCompassAngle(bearing);

return compassAngle;
}

export async function getClosestMapillaryImage({ lat, lng, selectedRoutes }) {

const p = turf.point([lng, lat]);
const buffer = turf.buffer(p, 0.05, { units: "kilometers" });
const bbox = turf.bbox(buffer);

const url = `https://graph.mapillary.com/images?fields=id,geometry&bbox=${bbox}&limit=100`;
const pointsWithGeometry = [];

selectedRoutes.forEach((route) => {
route.geometries.nodes[0].geometry.coordinates.forEach((coord) => {
pointsWithGeometry.push({
point: turf.point(coord),
geometry: route.geometries.nodes[0].geometry.coordinates,
});
});
});

const pointsCollection = turf.featureCollection(pointsWithGeometry.map(pg => pg.point));

const nearest = turf.nearestPoint(p, pointsCollection);

const nearestGeometry = pointsWithGeometry.find(pg =>
pg.point.geometry.coordinates[0] === nearest.geometry.coordinates[0] &&
pg.point.geometry.coordinates[1] === nearest.geometry.coordinates[1]
).geometry;

let nextCoordinate;
const nearestCoordIndex = nearestGeometry.findIndex(coord =>
coord[0] === nearest.geometry.coordinates[0] &&
coord[1] === nearest.geometry.coordinates[1]
);

if (nearestCoordIndex >= 0 && nearestCoordIndex < nearestGeometry.length - 5) {
nextCoordinate = nearestGeometry[nearestCoordIndex + 5];
} else {
nextCoordinate = nearest.geometry.coordinates;
}

const closestCoordinateCompassAngle = await getCompassAngle({closestCoordinate: nearest.geometry.coordinates, nextCoordinate})
const url = `https://graph.mapillary.com/images?fields=id,geometry,compass_angle,detection&bbox=${bbox}&limit=100`;
const delay = 500;
const tries = 3;

Expand Down Expand Up @@ -52,18 +105,20 @@ export async function getClosestMapillaryImage({ lat, lng }) {
if (!json.data) {
return null;
}

let closest;
json.data.forEach((feature) => {
const coordinates = feature.geometry.coordinates;
let distance = Math.hypot(
Math.abs(lat - coordinates[1]),
Math.abs(lng - coordinates[0])
);
if (!closest || distance < closest.distance) {
const angleDifference = Math.abs(feature.compass_angle - closestCoordinateCompassAngle);
const angleOffBy = Math.min(angleDifference, 360 - angleDifference);
if ((!closest || distance < closest.distance) && angleOffBy <= IMAGE_COMPASS_ANGLE_THRESHOLD) {
closest = feature;
closest.distance = distance;
}
});

return closest;
}
4 changes: 2 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6439,8 +6439,8 @@ hpack.js@^2.1.6:
wbuf "^1.1.0"

"hsl-map-style@https://github.com/HSLdevcom/hsl-map-style":
version "1.1.2"
resolved "https://github.com/HSLdevcom/hsl-map-style#207a8de2664c9a50b5a5f886d30f5b1628f995c7"
version "1.2.0"
resolved "https://github.com/HSLdevcom/hsl-map-style#68b1642ce364ebcea115bc3f20465d3c2ee83c0d"
dependencies:
lodash "^4.17.4"

Expand Down

0 comments on commit 1fd63f7

Please sign in to comment.