Skip to content

Commit

Permalink
Merge pull request #1171 from dbauszus-glx/mvt-snap-issue
Browse files Browse the repository at this point in the history
Fix issue snapping to mvt
  • Loading branch information
dbauszus-glx authored Mar 12, 2024
2 parents b175047 + 3f899e8 commit 44c3af3
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 19 deletions.
97 changes: 95 additions & 2 deletions lib/layer/format/mvt.mjs
Original file line number Diff line number Diff line change
@@ -1,9 +1,34 @@
/**
### mapp.layer.formats.mvt()
This module defines the MVT (MapBox Vector Tile) format for map layers.
@module /layer/formats/mvt
*/

/**
* Configures the MVT format for a map layer.
@function mvt
@param {Object} layer - The layer object.
@param {string} [layer.srid='3857'] - The spatial reference system identifier (SRID) for the layer.
@param {Object} [layer.style={}] - The style object for the layer.
@param {Object} [layer.params={}] - Additional parameters for the layer.
@param {boolean} [layer.mvt_cache] - Flag indicating whether to use MVT caching (deprecated).
@param {string[]} [layer.tables] - An array of table names for the layer.
@param {string[]} [layer.wkt_properties] - An array of properties to be retrieved as WKT (Well-Known Text) format.
@param {number} [layer.transition] - The transition duration for the layer.
@param {number} [layer.cacheSize] - The cache size for the layer.
@param {Object} layer.mapview - The mapview object.
@param {string} layer.mapview.host - The host URL for the API.
@param {Object} layer.mapview.locale - The locale object.
@param {string} layer.mapview.locale.key - The key for the locale.
@param {string} layer.mapview.srid - The SRID for the mapview.
@param {ol.Map} layer.mapview.Map - The OpenLayers map object.
@param {Object} layer.filter - The filter object for the layer.
@param {function} layer.filter.current - The current filter function for the layer.
@param {function} layer.tableCurrent - A function that returns the current table for the layer.
@param {function} layer.geomCurrent - A function that returns the current geometry for the layer.
@param {ol.layer.VectorTile} layer.L - The OpenLayers vector tile layer.
@returns {void}
*/
export default layer => {

// Assign default SRID if nullish.
Expand Down Expand Up @@ -72,7 +97,7 @@ export default layer => {
}),
transition: 0,
cacheSize: 0,
tileUrlFunction
tileUrlFunction: tileUrlFunction(layer)
})

// Define source for mvt layer.
Expand Down Expand Up @@ -102,6 +127,22 @@ export default layer => {
})
}

/**
* Returns a function that generates the tile URL for a WKT-based layer.
@function wktTileUrlFunction
@param {Object} layer - The layer object.
@param {string} layer.mapview.host - The host URL for the API.
@param {Object} layer.mapview.locale - The locale object.
@param {string} layer.mapview.locale.key - The key for the locale.
@param {string} layer.mapview.srid - The SRID for the mapview.
@param {string} layer.key - The key for the layer.
@param {function} layer.tableCurrent - A function that returns the current table for the layer.
@param {function} layer.geomCurrent - A function that returns the current geometry for the layer.
@param {boolean} layer.display - A flag indicating whether the layer is displayed.
@param {Set} [layer.clones] - A set of cloned layers.
@param {ol.source.VectorTile} layer.source - The OpenLayers vector tile source.
@returns {function} A function that generates the tile URL for the given tile coordinate.
*/
function wktTileUrlFunction(layer) {

return tileCoord => {
Expand Down Expand Up @@ -138,6 +179,30 @@ function wktTileUrlFunction(layer) {
}
}

/**
* Returns a function that generates the tile URL for an MVT layer.
@function tileUrlFunction
@param {Object} layer - The layer object.
@param {string} layer.mapview.host - The host URL for the API.
@param {Object} layer.mapview.locale - The locale object.
@param {string} layer.mapview.locale.key - The key for the locale.
@param {string} layer.key - The key for the layer.
@param {function} layer.tableCurrent - A function that returns the current table for the layer.
@param {function} layer.geomCurrent - A function that returns the current geometry for the layer.
@param {boolean} layer.display - A flag indicating whether the layer is displayed.
@param {Set} [layer.clones] - A set of cloned layers.
@param {Object} [layer.params] - Additional parameters for the layer.
@param {Object} [layer.style] - The style object for the layer.
@param {Object} [layer.style.theme] - The theme style object.
@param {string|string[]} [layer.style.theme.fields] - The field(s) for the theme style.
@param {string} [layer.style.theme.field] - The field for the theme style.
@param {Object} [layer.style.label] - The label style object.
@param {string} [layer.style.label.field] - The field for the label style.
@param {Object} [layer.filter] - The filter object for the layer.
@param {function} [layer.filter.current] - The current filter function for the layer.
@param {ol.source.VectorTile} layer.source - The OpenLayers vector tile source.
@returns {function} A function that generates the tile URL for the given tile coordinate.
*/
function tileUrlFunction(layer) {

return tileCoord => {
Expand Down Expand Up @@ -184,6 +249,34 @@ function tileUrlFunction(layer) {

}

/**
* Loads the layer features and updates the layer display on map view change.
@function changeEndLoad
@param {Object} layer - The layer object.
@param {XMLHttpRequest} [layer.xhr] - The XMLHttpRequest object used for fetching data.
@param {function} layer.tableCurrent - A function that returns the current table for the layer.
@param {boolean} layer.display - A flag indicating whether the layer is displayed.
@param {Set} [layer.clones] - A set of cloned layers.
@param {function} layer.geomCurrent - A function that returns the current geometry for the layer.
@param {Object} [layer.params] - Additional parameters for the layer.
@param {Object} [layer.style] - The style object for the layer.
@param {Object} [layer.style.theme] - The theme style object.
@param {string|string[]} [layer.style.theme.fields] - The field(s) for the theme style.
@param {string} [layer.style.theme.field] - The field for the theme style.
@param {Object} [layer.style.label] - The label style object.
@param {string} [layer.style.label.field] - The field for the label style.
@param {Object} layer.mapview - The mapview object.
@param {string} layer.mapview.host - The host URL for the API.
@param {Object} layer.mapview.locale - The locale object.
@param {string} layer.mapview.locale.key - The key for the locale.
@param {string} layer.mapview.srid - The SRID for the mapview.
@param {ol.Map} layer.mapview.Map - The OpenLayers map object.
@param {Object} layer.filter - The filter object for the layer.
@param {function} [layer.filter.current] - The current filter function for the layer.
@param {Object} [layer.featuresObject] - An object to store layer features.
@param {ol.layer.VectorTile} layer.L - The OpenLayers vector tile layer.
@returns {void}
*/
function changeEndLoad(layer) {

layer.xhr?.abort()
Expand Down
66 changes: 49 additions & 17 deletions lib/mapview/interactions/snap.mjs
Original file line number Diff line number Diff line change
@@ -1,18 +1,44 @@
/**
@module /mapview/interactions/snap
*/

export default function(mapview) {
* ### mapview.interactions.snap()
* This module sets up the snap interaction for the mapview.
* @module /mapview/interactions/snap
*/

/**
* Sets up the snap interaction for the mapview.
* @function snap
* @param {Object} mapview - The mapview object.
* @param {ol.Map} mapview.Map - The OpenLayers map object.
* @param {Object} mapview.interaction - The interaction object.
* @param {boolean|Object} mapview.interaction.snap - The snap interaction configuration.
* @param {string} [mapview.interaction.snap.layer] - The key of the layer to snap to.
* @param {ol.layer.Layer} mapview.interaction.layer - The interaction layer.
* @param {Object} mapview.layers - The map layers object.
*/
export default function (mapview) {
// The current draw/modify interaction doesn't snap.
if (!mapview.interaction.snap) return;

if (mapview.interaction.snap === true) {
// Assign the interaction layer as snap layer if snap is true.
mapview.interaction.snap = {
layer: mapview.interaction.layer.key
}
}

if (typeof (mapview.interaction.snap) === 'string') {
// Assign the interaction layer as snap layer if snap is a string.
mapview.interaction.snap = {
layer: mapview.interaction.snap
}
}
// Assign mapview and interaction to be _this.
mapview.interaction.snap = {
remove: ()=>{

/**
* Removes the snap interaction and related resources.
*/
remove: () => {
if (mapview.interaction.layer.featureSource) {

// Detach tile load event,
mapview.interaction.layer.featureSource.un('tileloadend', tileloadend)

Expand All @@ -31,8 +57,8 @@ export default function(mapview) {

// Check if snap layer exists in mapview.layers.
if (!mapview.layers[mapview.interaction.snap.layer]) {
console.warn(`Unable to snap to layer:${mapview.interaction.snap.layer} as it is not found in mapview.layers.`)
return;
console.warn(`Unable to snap to layer:${mapview.interaction.snap.layer} as it is not found in mapview.layers.`)
return;
}

// Assign snap layer from key if defined.
Expand All @@ -41,15 +67,23 @@ export default function(mapview) {
// Assign interaction as snap layer if undefined.
mapview.interaction.snap.layer ??= mapview.interaction.layer

mapview.interaction.snap.layer.show()

/**
* Callback function for the `tileloadend event of the feature source.
* Adds features from the loaded tile to the snap source.
* @param {ol.TileLoadEvent} e - The tile load event.
*/
function tileloadend(e) {
const features = e.tile.getFeatures()

// Add features from tile to the snap.source.
mapview.interaction.snap.source.addFeatures(e.tile.getFeatures())
// Try adding features to prevent a crash adding the same feature twice.
try {
mapview.interaction.snap.source.addFeatures(features)
} catch { }
}

// Only MVT layer have a snapSource.
if (mapview.interaction.snap.layer.featureSource) {

// Create new Vector source for snap features.
mapview.interaction.snap.source = new ol.source.Vector()

Expand All @@ -60,12 +94,10 @@ export default function(mapview) {
source: mapview.interaction.snap.layer.featureSource,
opacity: 0
})

// Add invisible tile layer for the featureSource to trigger tile loads.
mapview.Map.addLayer(mapview.interaction.snap.vectorTileLayer)

} else {

// Assign vector source as snap source for vector layer.
mapview.interaction.snap.source = mapview.interaction.snap.layer.L.getSource()
}
Expand All @@ -74,7 +106,7 @@ export default function(mapview) {
mapview.interaction.snap.interaction = new ol.interaction.Snap({
source: mapview.interaction.snap.source
})

// Add snap.interaction to mapview.Map
mapview.Map.addInteraction(mapview.interaction.snap.interaction)
}

0 comments on commit 44c3af3

Please sign in to comment.