Skip to content

Commit

Permalink
Small refactor to toggle map spatial filter [WIP]
Browse files Browse the repository at this point in the history
- Add Geohash model & collection - use in both the SpatialFilter and CesiumGeohash
- Move logic from SpatialFilter and CesiumGeohash to Geohash model/collection
- Ensure that mapModel is always added as a property of new layers (e.g. new geohash layers)
- Fix a small SolrResults bug with facetting

Relates to #2069
  • Loading branch information
robyngit committed Mar 31, 2023
1 parent d7e2557 commit 14bbfd6
Show file tree
Hide file tree
Showing 13 changed files with 520 additions and 214 deletions.
2 changes: 2 additions & 0 deletions src/js/collections/SolrResults.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ define(['jquery', 'underscore', 'backbone', 'models/SolrHeader', 'models/SolrRes
//Get the facet counts and store them in this model
if( solr.facet_counts ){
this.facetCounts = solr.facet_counts.facet_fields;
} else {
this.facetCounts = "nothing";
}

//Cache this set of results
Expand Down
163 changes: 163 additions & 0 deletions src/js/collections/maps/Geohashes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
"use strict";

define([
"jquery",
"underscore",
"backbone",
"nGeohash",
"models/maps/Geohash",
], function ($, _, Backbone, nGeohash, Geohash) {
/**
* @classdesc A Geohashes Collection represents a collection of Geohash models.
* @classcategory Collections/Geohashes
* @class Geohashes
* @name Geohashes
* @extends Backbone.Collection
* @since x.x.x
* @constructor
*/
var Geohashes = Backbone.Collection.extend(
/** @lends Geohashes.prototype */ {
/**
* The name of this type of collection
* @type {string}
*/
type: "Geohashes",

/**
* The model class for this collection
* @type {Geohash}
*/
model: Geohash,

getLevelHeightMap: function () {
return {
1: 6800000,
2: 2400000,
3: 550000,
4: 120000,
5: 7000,
6: 0,
};
},

/**
* Get the geohash level to use for a given height.
*
* @param {number} [height] - Altitude to use to calculate the geohash
* level/precision.
*/
heightToLevel: function (height) {
try {
const levelHeightMap = this.getLevelHeightMap();
return Object.keys(levelHeightMap).find(
(key) => height >= levelHeightMap[key]
);
} catch (e) {
console.log("Failed to get geohash level, returning 1" + e);
return 1;
}
},

/**
* Retrieves the geohash IDs for the provided bounding boxes and level.
*
* @param {Object} bounds - Bounding box with north, south, east, and west
* properties.
* @param {number} level - Geohash level.
* @returns {string[]} Array of geohash IDs.
*/
getGeohashIDs: function (bounds, level) {
let geohashIDs = [];
bounds = this.splitBoundingBox(bounds);
bounds.forEach(function (bb) {
geohashIDs = geohashIDs.concat(
nGeohash.bboxes(bb.south, bb.west, bb.north, bb.east, level)
);
});
return geohashIDs;
},

/**
* Splits the bounding box if it crosses the prime meridian. Returns an
* array of bounding boxes.
*
* @param {Object} bounds - Bounding box object with north, south, east,
* and west properties.
* @returns {Array<Object>} Array of bounding box objects.
* @since x.x.x
*/
splitBoundingBox: function (bounds) {
if (!bounds) return [];
const { north, south, east, west } = bounds;

if (east < west) {
return [
{ north, south, east: 180, west },
{ north, south, east, west: -180 },
];
} else {
return [{ north, south, east, west }];
}
},

/**
* Add geohashes to the collection based on a bounding box and height.
* @param {Object} bounds - Bounding box with north, south, east, and west
* properties.
* @param {number} height - Altitude to use to calculate the geohash
* level/precision.
* @param {boolean} [overwrite=false] - Whether to overwrite the current
* collection.
*/
addGeohashesByExtent: function (bounds, height, overwrite = false) {
const level = this.heightToLevel(height);
const geohashIDs = this.getGeohashIDs(bounds, level);
this.addGeohashesById(geohashIDs, overwrite);
},

/**
* Add geohashes to the collection based on an array of geohash IDs.
* @param {string[]} geohashIDs - Array of geohash IDs.
* @param {boolean} [overwrite=false] - Whether to overwrite the current
* collection.
*/
addGeohashesById: function (geohashIDs, overwrite = false) {
if (overwrite) this.reset();
this.add(geohashIDs.map((id) => ({ geohash: id })));
},

/**
* Get the unique geohash levels for all geohashes in the collection.
*/
getLevels: function () {
return _.uniq(this.pluck("level"));
},

/**
* Return the geohashes as a GeoJSON FeatureCollection, where each
* geohash is represented as a GeoJSON Polygon (rectangle).
* @returns {Object} GeoJSON FeatureCollection.
*/
toGeoJSON: function () {
return {
type: "FeatureCollection",
features: this.map(function (geohash) {
return geohash.toGeoJSON();
}),
};
},
}
);

return Geohashes;
});

// TODO: consider adding this back in to optionally limit the number of geohashes
// const limit = this.get("maxGeohashes");
// if (limit && geohashIDs.length > limit && level > 1) {
// while (geohashIDs.length > limit && level > 1) {
// level--;
// geohashIDs = this.getGeohashIDs(bounds, level);
// }
// }
30 changes: 16 additions & 14 deletions src/js/collections/maps/MapAssets.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,22 +192,24 @@ define([
},

/**
* Add a new Geohash layer to the collection.
* @param {MapConfig#MapAssetConfig} assetConfig - Configuration object
* for the Geohash layer (optional).
* Add a new MapAsset model to this collection. This is useful if adding
* the collection from a Map model, since this method will attach the Map
* model to the MapAsset model.
* @param {MapConfig#MapAssetConfig | MapAsset } asset - The configuration
* object for the MapAsset model, or the MapAsset model itself.
* @param {MapModel} [mapModel] - The Map model that contains this
* collection. This is optional, but if provided, it will be attached to
* the MapAsset model.
* @returns {MapAsset} - Returns the MapAsset model that was added to the
* collection.
*/
addGeohashLayer: function (assetConfig) {
addAsset: function (asset, mapModel) {
try {
const config = Object.assign({}, assetConfig, {
type: "CesiumGeohash",
});
return this.add(config);
} catch (error) {
console.log(
"Failed to add a geohash layer to a MapAssets collection" +
". Error details: " +
error
);
const newModel = this.add(asset);
if (mapModel) newModel.set("mapModel", mapModel);
return newModel;
} catch (e) {
console.log("Failed to add a layer to a MapAssets collection", e);
}
},
}
Expand Down
35 changes: 19 additions & 16 deletions src/js/models/connectors/Filters-Map.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@
define([
"backbone",
"collections/Filters",
"models/filters/SpatialFilter",
"models/maps/Map",
], function (Backbone, Filters, SpatialFilter, Map) {
], function (Backbone, Filters, Map) {
"use strict";

/**
Expand Down Expand Up @@ -38,7 +37,6 @@ define([
*/
defaults: function () {
return {
filtersList: [],
filters: new Filters([], { catalogSearch: true }),
spatialFilters: [],
map: new Map(),
Expand All @@ -59,24 +57,13 @@ define([
*/
initialize: function (attr, options) {
try {
this.addFiltersList();
const add = options?.addSpatialFilter ?? true;
this.findAndSetSpatialFilters(add);
} catch (e) {
console.log("Error initializing Filters-Map connector: ", e);
}
},

/**
* Adds the filter models from filtersList to the Filters collection if
* filtersList is not empty.
*/
addFiltersList: function () {
if (this.get("filtersList")?.length) {
this.get("filters").add(this.get("filtersList"));
}
},

/**
* Finds and sets the spatial filters within the Filters collection. Stops
* any existing listeners, adds a new listener for collection updates, and
Expand Down Expand Up @@ -128,10 +115,26 @@ define([
addSpatialFilterIfNeeded: function (add) {
const spatialFilters = this.get("spatialFilters");
if (!spatialFilters?.length && add) {
this.get("filters").add(new SpatialFilter({
this.get("filters").add({
filterType: "SpatialFilter",
isInvisible: true,
}));
});
}
},

/**
* Removes all SpatialFilter models from the Filters collection and
* destroys them.
*/
removeSpatialFilter: function () {
const spatialFilters = this.get("spatialFilters");
if (spatialFilters?.length) {
spatialFilters.forEach((filter) => {
filter.collection.remove(filter);
filter.destroy();
});
}
this.set("spatialFilters", []);
},

/**
Expand Down
1 change: 0 additions & 1 deletion src/js/models/connectors/Filters-Search.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ define([
*/
connect: function () {
this.disconnect();
const model = this;
const filters = this.get("filters");
const searchResults = this.get("searchResults");
// Listen to changes in the Filters to trigger a search
Expand Down
7 changes: 7 additions & 0 deletions src/js/models/connectors/Map-Search-Filters.js
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,13 @@ define([
const connectors = this.getConnectors();
return connectors.every((connector) => connector.get("isConnected"));
},

/**
* Remove the spatial filter from the Filters model.
*/
removeSpatialFilter: function () {
this.get("filtersMapConnector").removeSpatialFilter();
}
}
);
});
9 changes: 5 additions & 4 deletions src/js/models/connectors/Map-Search.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ define([
* there is no Map model set on this model.
*/
findLayers: function () {
const model = this;
const map = this.get("map");
if (!map) return null;
return map.get("layers");
Expand All @@ -97,9 +96,8 @@ define([
* @fires Layers#add
*/
createGeohash() {
const layers = this.get("layers");
if (!layers) return null;
return layers.addGeohashLayer();
const map = this.get("map");
return map.addLayer({ type: "CesiumGeohash" });
},

/**
Expand Down Expand Up @@ -140,6 +138,9 @@ define([
this.disconnect();
const searchResults = this.get("searchResults");
this.listenTo(searchResults, "reset", this.updateGeohashCounts);
// TODO: ‼️ The map needs to send the height/geohash level to the search.
// and set the facet (so that the results include counts for each
// geohash at the current level). ‼️
this.set("isConnected", true);
},

Expand Down
Loading

0 comments on commit 14bbfd6

Please sign in to comment.