aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/map.js103
-rw-r--r--src/popover.js11
2 files changed, 109 insertions, 5 deletions
diff --git a/src/map.js b/src/map.js
new file mode 100644
index 0000000..5a751e6
--- /dev/null
+++ b/src/map.js
@@ -0,0 +1,103 @@
+/***********************************************************************
+ * Copyright © 2024-2025 Guilhem Moulin <info@guilhem.se>
+ * Map base setup
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ **********************************************************************/
+
+import Map from 'ol/Map.js';
+import View from 'ol/View.js';
+import TileLayer from 'ol/layer/Tile.js';
+
+import WMTS from 'ol/source/WMTS.js';
+import WMTSTileGrid from 'ol/tilegrid/WMTS.js';
+
+import proj4 from 'proj4';
+import { get as getProjection } from 'ol/proj.js';
+import { register as registerProjection } from 'ol/proj/proj4.js';
+
+proj4.defs('EPSG:3006', '+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs +type=crs');
+registerProjection(proj4);
+
+export const projection = getProjection('EPSG:3006');
+
+/* Lantmäteriet uses a tile-scheme where the origin (upper-left corner) is at
+ * N8500000 E-1200000 (SWEREF99 TM), where each tile is 256×256 pixels, and where
+ * the resolution at level 0 is 4096m per pixel (each side is 1048.576km long).
+ *
+ * https://www.lantmateriet.se/globalassets/geodata/geodatatjanster/tb_twk_visning_cache_v1.1.0.pdf
+ * https://www.lantmateriet.se/globalassets/geodata/geodatatjanster/tb_twk_visning-oversiktlig_v1.0.3.pdf
+ *
+ * We set the extent to a 4×4 tiles square at level 2 (1024px = 1048.576km per
+ * side) somehow centered on Norrbotten and Västerbotten, and zoom in from there.
+ * This represent a TILEROW (x) offset of 5, and a TILECOL (y) offset of 2.
+ */
+export const extent = [110720, 6927136, 1159296, 7975712];
+
+/* XXX using the topowebbcache WMTS is fine for testing (as it doesn't require
+ * authentication) but not in production in a public instance as doing so would
+ * violate its current terms of use (as of January 2024 it's not CC0 open data).
+ * See
+ *
+ * https://www.lantmateriet.se/sv/om-lantmateriet/Rattsinformation/upphovsratt-och-publicering-av-lantmateriets-geografiska-information/
+ * https://www.lantmateriet.se/sv/kartor/vara-karttjanster/min-karta/#anchor-2
+ * https://help.locusmap.eu/topic/support-for-swedish-lantmateriets-min-karta-wms
+ *
+ * More precise background maps might be available in the future as open data,
+ * though:
+ *
+ * https://www.lantmateriet.se/sv/om-lantmateriet/press/nyheter/lantmateriets-arbete-mot-oppna-data-i-full-gang/
+ * https://ext-geodatakatalog.lansstyrelsen.se/GeodataKatalogen/srv/swe/catalog.search#/map uses
+ * https://api.lantmateriet.se/open/topowebb-ccby/v1/wmts/token/3c3a9cf47e7cb5ea24542d40d19698/?layer=topowebb&style=default&tilematrixset=3006&Service=WMTS&Request=GetTile&Version=1.0.0&Format=image/png&TileMatrix=7&TileCol=237&TileRow=155
+ */
+export const baseMapSource = new WMTS({
+ url: undefined,
+ version: '1.0.0',
+ style: 'default',
+ matrixSet: '3006',
+ format: 'image/png',
+ tileGrid: new WMTSTileGrid({
+ extent: extent,
+ // https://www.lantmateriet.se/globalassets/geodata/geodatatjanster/tb_twk_visning-oversiktlig_v1.0.3.pdf
+ tileSize: 256,
+ origin: [-1200000, 8500000],
+ resolutions: [4096, 2048, 1024, 512, 256, 128, 64, 32, 16, 8],
+ matrixIds: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
+ }),
+ projection: projection,
+ wrapX: false,
+ crossOrigin: 'anonymous',
+});
+
+const view = new View({
+ projection: projection,
+ extent: extent,
+ showFullExtent: true,
+ /* center of the bbox of the Norrbotten and Västerbotten geometries */
+ center: [694767.48, 7338176.57],
+ zoom: 1,
+ enableRotation: false,
+ resolutions: [1024, 512, 256, 128, 64, 32, 16, 8],
+ constrainResolution: false,
+});
+
+export const map = new Map({
+ controls: [],
+ view: view,
+ layers: [
+ new TileLayer({
+ source: baseMapSource
+ }),
+ ],
+});
diff --git a/src/popover.js b/src/popover.js
index 74e79d6..7080711 100644
--- a/src/popover.js
+++ b/src/popover.js
@@ -23,6 +23,7 @@ import VectorTileLayer from 'ol/layer/VectorTile.js';
import { Popover } from 'bootstrap';
+import { map } from './map.js';
/* return an <a> tag with the given URL and optional text */
const reURL = new RegExp('^https?://', 'i');
@@ -989,13 +990,13 @@ const formatFeaturePropertiesToHTML = function(properties) {
/* Initialize popup overlay with the give map and HTML element */
let popupOverlay = null;
-export const initPopupOverLay = function(map, element) {
+(function() {
popupOverlay = new Overlay({
stopEvent: true,
- element: element,
+ element: document.getElementById('popup'),
});
map.addOverlay(popupOverlay);
-};
+})();
let featureOverlayLayer = null;
let overlayAttributes = [],
@@ -1023,7 +1024,7 @@ export const disposePopover = function() {
};
/* Initialize popover on the given map */
-export const initPopover = function(map) {
+(function() {
featureOverlayLayer = new VectorTileLayer({
zIndex: 65535,
declutter: false,
@@ -1344,4 +1345,4 @@ export const initPopover = function(map) {
document.body.classList.remove('inprogress');
});
});
-};
+})();