2023-10-31 14:38:43 +00:00
|
|
|
<script setup lang="ts">
|
|
|
|
import { onMounted, onUnmounted, ref, Ref, defineProps, computed } from 'vue';
|
|
|
|
import SectionMain from '@/Components/SectionMain.vue';
|
|
|
|
import { Map } from 'leaflet/src/map/index';
|
|
|
|
import { Rectangle } from 'leaflet';
|
|
|
|
import { canvas } from 'leaflet/src/layer/vector/Canvas';
|
|
|
|
import { svg } from 'leaflet/src/layer/vector/SVG';
|
|
|
|
import axios from 'axios';
|
|
|
|
import { LatLngBoundsExpression } from 'leaflet/src/geo/LatLngBounds';
|
2024-08-07 12:22:36 +00:00
|
|
|
import { tileLayerWMS } from 'leaflet/src/layer/tile/TileLayer.WMS';
|
2024-09-16 15:59:46 +00:00
|
|
|
// import { TileLayer } from 'leaflet/src/layer/tile/TileLayer';
|
2023-10-31 14:38:43 +00:00
|
|
|
import { Attribution } from 'leaflet/src/control/Control.Attribution';
|
|
|
|
import DrawControlComponent from '@/Components/Map/draw.component.vue';
|
|
|
|
import ZoomControlComponent from '@/Components/Map/zoom.component.vue';
|
|
|
|
import { MapService } from '@/Stores/map.service';
|
|
|
|
import { LayerGroup } from 'leaflet/src/layer/LayerGroup';
|
|
|
|
import { OpensearchDocument } from '@/Dataset';
|
|
|
|
|
|
|
|
Map.include({
|
|
|
|
// @namespace Map; @method getRenderer(layer: Path): Renderer
|
|
|
|
// Returns the instance of `Renderer` that should be used to render the given
|
|
|
|
// `Path`. It will ensure that the `renderer` options of the map and paths
|
|
|
|
// are respected, and that the renderers do exist on the map.
|
|
|
|
getRenderer: function (layer) {
|
|
|
|
// @namespace Path; @option renderer: Renderer
|
|
|
|
// Use this specific instance of `Renderer` for this path. Takes
|
|
|
|
// precedence over the map's [default renderer](#map-renderer).
|
|
|
|
var renderer = layer.options.renderer || this._getPaneRenderer(layer.options.pane) || this.options.renderer || this._renderer;
|
|
|
|
|
|
|
|
if (!renderer) {
|
|
|
|
renderer = this._renderer = this._createRenderer();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!this.hasLayer(renderer)) {
|
|
|
|
this.addLayer(renderer);
|
|
|
|
}
|
|
|
|
return renderer;
|
|
|
|
},
|
|
|
|
|
|
|
|
_getPaneRenderer: function (name) {
|
|
|
|
if (name === 'overlayPane' || name === undefined) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
var renderer = this._paneRenderers[name];
|
|
|
|
if (renderer === undefined) {
|
|
|
|
renderer = this._createRenderer({ pane: name });
|
|
|
|
this._paneRenderers[name] = renderer;
|
|
|
|
}
|
|
|
|
return renderer;
|
|
|
|
},
|
|
|
|
|
|
|
|
_createRenderer: function (options) {
|
|
|
|
// @namespace Map; @option preferCanvas: Boolean = false
|
|
|
|
// Whether `Path`s should be rendered on a `Canvas` renderer.
|
|
|
|
// By default, all `Path`s are rendered in a `SVG` renderer.
|
|
|
|
return (this.options.preferCanvas && canvas(options)) || svg(options);
|
|
|
|
},
|
|
|
|
});
|
|
|
|
const DEFAULT_BASE_LAYER_NAME = 'BaseLayer';
|
|
|
|
const DEFAULT_BASE_LAYER_ATTRIBUTION = '© <a target="_blank" href="http://osm.org/copyright">OpenStreetMap</a> contributors';
|
2024-09-16 15:59:46 +00:00
|
|
|
const OPENSEARCH_HOST = 'https://catalog.geosphere.at';
|
|
|
|
// const OPENSEARCH_HOST = `${process.env.OPENSEARCH_HOST}`;
|
2023-11-22 16:06:55 +00:00
|
|
|
// const OPENSEARCH_HOST = `http://${process.env.OPENSEARCH_PUBLIC_HOST}`;
|
2023-10-31 14:38:43 +00:00
|
|
|
let map: Map;
|
|
|
|
|
|
|
|
const props = defineProps({
|
|
|
|
dheckable: Boolean,
|
|
|
|
datasets: {
|
|
|
|
type: Array<OpensearchDocument>,
|
|
|
|
default: () => [],
|
|
|
|
},
|
|
|
|
mapId: {
|
|
|
|
type: String,
|
|
|
|
default: 'map',
|
|
|
|
},
|
|
|
|
mapOptions: {
|
|
|
|
type: Object,
|
|
|
|
default: () => ({
|
|
|
|
center: [48.208174, 16.373819],
|
|
|
|
zoom: 3,
|
|
|
|
zoomControl: false,
|
|
|
|
attributionControl: false,
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
const items = computed({
|
|
|
|
get() {
|
|
|
|
return props.datasets;
|
|
|
|
},
|
|
|
|
// setter
|
|
|
|
set(value) {
|
|
|
|
// Note: we are using destructuring assignment syntax here.
|
|
|
|
|
|
|
|
props.datasets.length = 0;
|
|
|
|
props.datasets.push(...value);
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
const fitBounds: LatLngBoundsExpression = [
|
|
|
|
[46.4318173285, 9.47996951665],
|
|
|
|
[49.0390742051, 16.9796667823],
|
|
|
|
];
|
|
|
|
|
|
|
|
// const mapId = 'map';
|
|
|
|
const drawControl: Ref<DrawControlComponent | null> = ref(null);
|
|
|
|
const southWest = ref(null);
|
|
|
|
const northEast = ref(null);
|
|
|
|
const mapService = MapService();
|
2023-12-29 14:54:49 +00:00
|
|
|
|
2023-10-31 14:38:43 +00:00
|
|
|
const filterLayerGroup = new LayerGroup();
|
|
|
|
// Replace with your actual data
|
|
|
|
// const datasets: Ref<OpensearchDocument[]> = ref([]);
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
initMap();
|
|
|
|
});
|
|
|
|
|
|
|
|
onUnmounted(() => {
|
|
|
|
map.off('zoomend zoomlevelschange');
|
|
|
|
});
|
|
|
|
|
|
|
|
const initMap = async () => {
|
|
|
|
// init leaflet map
|
|
|
|
map = new Map('map', props.mapOptions);
|
|
|
|
mapService.setMap(props.mapId, map);
|
|
|
|
map.scrollWheelZoom.disable();
|
|
|
|
map.fitBounds(fitBounds);
|
|
|
|
drawControl.value?.toggleDraw();
|
|
|
|
|
|
|
|
map.addLayer(filterLayerGroup);
|
|
|
|
|
|
|
|
const attributionControl = new Attribution().addTo(map);
|
|
|
|
attributionControl.setPrefix(false);
|
|
|
|
|
2024-08-07 12:22:36 +00:00
|
|
|
let osmGgray = tileLayerWMS('https://ows.terrestris.de/osm-gray/service', {
|
|
|
|
format: 'image/png',
|
2023-10-31 14:38:43 +00:00
|
|
|
attribution: DEFAULT_BASE_LAYER_ATTRIBUTION,
|
2024-08-07 12:22:36 +00:00
|
|
|
layers: 'OSM-WMS',
|
2023-10-31 14:38:43 +00:00
|
|
|
});
|
|
|
|
|
2024-08-07 12:22:36 +00:00
|
|
|
// let baseAt = new TileLayer('https://{s}.wien.gv.at/basemap/bmapgrau/normal/google3857/{z}/{y}/{x}.png', {
|
|
|
|
// subdomains: ['maps', 'maps1', 'maps2', 'maps3', 'maps4'],
|
|
|
|
// attribution: DEFAULT_BASE_LAYER_ATTRIBUTION,
|
|
|
|
// });
|
|
|
|
|
2023-10-31 14:38:43 +00:00
|
|
|
let layerOptions = {
|
|
|
|
label: DEFAULT_BASE_LAYER_NAME,
|
|
|
|
visible: true,
|
2024-08-07 12:22:36 +00:00
|
|
|
layer: osmGgray,
|
2023-10-31 14:38:43 +00:00
|
|
|
};
|
|
|
|
layerOptions.layer.addTo(map);
|
|
|
|
|
|
|
|
map.on('Draw.Event.CREATED', handleDrawEventCreated);
|
|
|
|
|
|
|
|
// // const query = {
|
|
|
|
// // query: {
|
|
|
|
// // term: {
|
|
|
|
// // id: "103"
|
|
|
|
// // }
|
|
|
|
// // }
|
|
|
|
// // };
|
|
|
|
// // to do : call extra method:
|
|
|
|
// const query = {
|
|
|
|
// // q: 'id:103'
|
|
|
|
// // q: 'author:"Iglseder, Christoph" OR title:"Datensatz"',
|
|
|
|
// // q: 'author:"Iglseder"',
|
|
|
|
// q: '*',
|
|
|
|
// _source: 'author,bbox_xmin,bbox_xmax,bbox_ymin,bbox_ymax,abstract,title',
|
|
|
|
// size: 1000
|
|
|
|
// // qf:"title^3 author^2 subject^1",
|
|
|
|
// }
|
|
|
|
// try {
|
|
|
|
// let response = await axios({
|
|
|
|
// method: 'GET',
|
|
|
|
// url: OPEN_SEARCH_HOST + '/tethys-records/_search',
|
|
|
|
// headers: { 'Content-Type': 'application/json' },
|
|
|
|
// params: query
|
|
|
|
// });
|
|
|
|
// // Loop through the hits in the response
|
|
|
|
// response.data.hits.hits.forEach(hit => {
|
|
|
|
// // Get the geo_location attribute
|
|
|
|
// // var geo_location = hit._source.geo_location;
|
|
|
|
// let xMin = hit._source.bbox_xmin;
|
|
|
|
// let xMax = hit._source.bbox_xmax;
|
|
|
|
// let yMin = hit._source.bbox_ymin;
|
|
|
|
// let yMax = hit._source.bbox_ymax;
|
|
|
|
// var bbox: LatLngBoundsExpression = [[yMin, xMin], [yMax, xMax]];
|
|
|
|
// // Parse the WKT string to get the bounding box coordinates
|
|
|
|
// // var bbox = wktToBbox(geo_location);
|
|
|
|
|
|
|
|
// // // Add the bounding box to the map as a rectangle
|
|
|
|
// new Rectangle(bbox, { color: "#ff7800", weight: 1 }).addTo(map);
|
|
|
|
// // console.log(hit._source);
|
|
|
|
// });
|
|
|
|
// } catch (error) {
|
|
|
|
// console.error(error);
|
|
|
|
// }
|
|
|
|
};
|
|
|
|
|
|
|
|
const handleDrawEventCreated = async (event) => {
|
|
|
|
filterLayerGroup.clearLayers();
|
|
|
|
items.value = [];
|
|
|
|
|
|
|
|
let layer = event.layer;
|
|
|
|
let bounds = layer.getBounds();
|
|
|
|
// coverage.x_min = bounds.getSouthWest().lng;
|
|
|
|
// coverage.y_min = bounds.getSouthWest().lat;
|
|
|
|
// coverage.x_max = bounds.getNorthEast().lng;
|
|
|
|
// coverage.y_max = bounds.getNorthEast().lat;
|
|
|
|
|
|
|
|
try {
|
|
|
|
let response = await axios({
|
|
|
|
method: 'POST',
|
2023-11-22 16:06:55 +00:00
|
|
|
url: OPENSEARCH_HOST + '/tethys-records/_search',
|
2023-10-31 14:38:43 +00:00
|
|
|
headers: { 'Content-Type': 'application/json' },
|
|
|
|
data: {
|
|
|
|
size: 1000,
|
|
|
|
query: {
|
|
|
|
bool: {
|
|
|
|
must: {
|
|
|
|
match_all: {},
|
|
|
|
},
|
|
|
|
filter: {
|
|
|
|
geo_shape: {
|
|
|
|
geo_location: {
|
|
|
|
// replace 'location' with your geo-point field name
|
|
|
|
shape: {
|
|
|
|
type: 'envelope',
|
|
|
|
coordinates: [
|
|
|
|
[bounds.getSouthWest().lng, bounds.getNorthEast().lat],
|
|
|
|
[bounds.getNorthEast().lng, bounds.getSouthWest().lat],
|
|
|
|
],
|
|
|
|
},
|
|
|
|
relation: 'within',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
// _source: 'author,bbox_xmin,bbox_xmax,bbox_ymin,bbox_ymax,abstract,title',
|
|
|
|
// "size": 1000
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
// Loop through the hits in the response
|
|
|
|
response.data.hits.hits.forEach((hit) => {
|
|
|
|
// Get the geo_location attribute
|
|
|
|
// var geo_location = hit._source.geo_location;
|
|
|
|
let xMin = hit._source.bbox_xmin;
|
|
|
|
let xMax = hit._source.bbox_xmax;
|
|
|
|
let yMin = hit._source.bbox_ymin;
|
|
|
|
let yMax = hit._source.bbox_ymax;
|
|
|
|
var bbox: LatLngBoundsExpression = [
|
|
|
|
[yMin, xMin],
|
|
|
|
[yMax, xMax],
|
|
|
|
];
|
|
|
|
// Parse the WKT string to get the bounding box coordinates
|
|
|
|
// var bbox = wktToBbox(geo_location);
|
|
|
|
|
|
|
|
// // Add the bounding box to the map as a rectangle
|
|
|
|
let rect = new Rectangle(bbox, { color: '#ff7800', weight: 1 });
|
|
|
|
filterLayerGroup.addLayer(rect);
|
|
|
|
// add to result list
|
|
|
|
items.value.push(hit._source);
|
|
|
|
});
|
|
|
|
} catch (error) {
|
|
|
|
console.error(error);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<template>
|
2024-01-04 15:40:05 +00:00
|
|
|
<SectionMain>
|
2023-12-29 14:54:49 +00:00
|
|
|
<div id="map" class="map-container mt-6 mb-6 rounded-2xl py-12 px-6 text-center dark:bg-slate-900 bg-white">
|
|
|
|
<ZoomControlComponent ref="zoomControl" :mapId="mapId"></ZoomControlComponent>
|
|
|
|
<DrawControlComponent ref="drawControl" :preserve="false" :mapId="mapId" :southWest="southWest"
|
|
|
|
:northEast="northEast">
|
|
|
|
</DrawControlComponent>
|
2024-01-04 15:40:05 +00:00
|
|
|
</div>
|
|
|
|
</SectionMain>
|
2023-10-31 14:38:43 +00:00
|
|
|
</template>
|
2023-12-29 14:54:49 +00:00
|
|
|
|
|
|
|
|
|
|
|
<style lang="css">
|
|
|
|
/* .leaflet-container {
|
|
|
|
height: 600px;
|
|
|
|
width: 100%;
|
|
|
|
background-color: transparent;
|
|
|
|
outline-offset: 1px;
|
|
|
|
} */
|
|
|
|
.leaflet-container {
|
|
|
|
height: 600px;
|
|
|
|
width: 100%;
|
|
|
|
}
|
|
|
|
|
|
|
|
.leaflet-container .leaflet-pane {
|
|
|
|
z-index: 30!important;
|
|
|
|
}
|
|
|
|
</style>
|