Filtering boundary tilesets by ISO 3166-1 alpha-3 country code - mapbox

Is it possible to filter boundary tilesets by ISO 3166-1 alpha-3 country code? And if yes, then how? I've searched in the documentation, but haven't found anything. This is how I currently filter the tileset by 2 characters country code iso_3166_1. I've tried to change it from 'iso_3166_1' to 'iso_3166_1_alpha_3', as found in reference to something different, but it doesn't work.
mapBox.on('load', () => {
mapBox.addSource('admin-1', {
type: 'vector',
url: 'mapbox://mapbox.boundaries-adm1-v3'
});
var countriesToDisplay: Array<string> = ['US', 'NZ']
countriesToDisplay.forEach((countryCode: string) => {
mapBox.addLayer({
id: 'admin-1-fill-' + countryCode,
type: 'fill',
source: 'admin-1',
'source-layer': 'boundaries_admin_1',
filter: ['any', ['all', ['==', ['get', 'iso_3166_1'], countryCode]]],
paint: { 'fill-color': '#044e9c' }
}, 'waterway-label');
});
});

Mapbox Boundaries v3 tileset only has a few features in the actual tiles, for polygons they are:
id
iso_3166_1
worldview
Checkout the full reference documentation here: https://docs.mapbox.com/vector-tiles/reference/mapbox-boundaries-v3/#polygon-tileset-reference
The rest of the data is stored in the supplemental look up tables that you are sent when you purchase the tileset. You can see all the properties available here: https://docs.mapbox.com/help/tutorials/get-started-mapbox-boundaries/#feature-lookup-tables
You will need to perform a data join to make the data from these lookup tables accessible to you in your javascript. There is a tutorial that walks you through that here: https://docs.mapbox.com/help/tutorials/data-joins-with-mapbox-boundaries/

Related

Mapbox js - tileset colors assignment

I am trying to create a colored uk areas map - I need the colors to be driven by local data (say for example sales by postcode), which will always change depending on user selections like report date ranges etc. I have a tileset source which I am assigning to a layer, as in the following (sensitive values blanked out):
this.map.addLayer({
"id": "uk-pc-data",
"type": "fill",
"source-layer": "***",
"source": {
type: 'vector',
url: '***'
}
});
I am then able to style the postcode areas within the tileset by addressing a name property on the tileset features, like so:
"paint": {
"fill-color": [
"match",
["get", "name", [{name: "PR"}, {name: "CH"}, {name: "LN"}]],
[
"PR",
"DD",
"AL",
"PO"
],
"hsla(344, 84%, 29%, 0.37)",
"hsla(131, 94%, 34%, 0)"
]
}
The above will assign one color to the matched areas, and a default to all the other (the non matched ones); What I would like to do, is computing the colour value locally (so based on data constantly changing) based on the feature name, like so
"paint": {
"fill-color": function (feature = {}) {
return localSalesByArea(feature.name)
}
}
This though does not seem to be possible: any help or pointers appreciated; I have been through examples from Mapbox
such as choroplet, heatmaps, expressions but these seem to rely on values delivered via the dataset itself (i.e Population), in my case the values which determine the color scale are separated (they come from an internal reporting api)
If the data on which the colours are determined does not exist in the tileset, you basically have to do a gigantic lookup by name.
You will have a function that generates the fill-color expression, something like:
function makeFillExpression(valuesByName) {
function valueToColor(value) {
return /* insert your choroplething special sauce here */;
}
return ret = [
"match",
["get", "name"],
Object.keys(valuesByName).map(name => valueToColor(valuesByName[name])),
'black'
];
}
Yes, it will be a very large and unwieldy expression.

mapbox gl data driven styles (choropleth maps)

I'm trying to create a choropleth map using mapbox-gl. In the example choropleth maps, it looks like they set the feature's paint fill colour based on the properties of the feature. Is there a way to set the colour by accessing a map?
ie. I have tiles each with a unique id in the feature property called id. I also have a json which maps each id with a value and would like to access those values to set the colour.
Is this possible? or am i limited to only being able to access values in the feature properties?
I'm not entirely sure if I understood your question correctly. But I think what you are trying to achieve can be done with expressions:
const geojson = {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
properties: {
id: 'foo'
},
geometry: {
/* */
}
}
]
};
const values = {
foo: 'green',
bar: 'red',
baz: 'blue'
};
map.addLayer({
// ...
paint: {
'fill-color': [
[
'get',
// get the id property and use it as a key into "values"
['get', 'id'],
values
]
]
}
});
See the get expression: https://www.mapbox.com/mapbox-gl-js/style-spec#expressions-get
Update from 04.2018:
Since some moment constructions like
[
'get',
// get the id property and use it as a key into "values"
['get', 'id'],
values
]
stopped to work. The following exception occures: 'Bare objects invalid. Use ["literal", {...}]'. Now it is necessary to use type expressions, like this:
[
'get',
['string', ['get', 'id'],
['literal', values]
]
See this and this for reference.

geojson as url source + turf.js + manipulation of subset of features' properties

mapbox-gl-js version: >=0.27.0 <=0.38.0
(1) I have a Feature geojson type of a single polygon adding to my map from a url source.
(2) I also have a FeatureCollection geojson type of ~4k polygons adding to the map also from a url source.
I use turf.intersect between (1) and (2) to select the intersecting polygons of (2).
I then store the intersecting polygons [a sub-set of (2)] to an array.
I then manipulate the values of some properties of those intersecting polygons
with simple math.
I now want to update (2) with the resulting values of the array.
I would love to use something like setData to update (2), but that is not possible for a subset which also is not (a) a geojson data object or (b) a url to one as specified in the docs.
Hopefully I have explained this sufficiently. If so, what is the suggested workflow in this case?
Mapbox is not good at sharing if you let it load the GeoJSON; see https://github.com/mapbox/mapbox-gl-js/issues/1762 If you want to manipulate the data yourself, you should load it yourself, then pass it to Mapbox. For example:
// load your data via ajax however you want
const promises = {
polygon: $.get('.../geojson.json'),
collection: $.get('.../feature-collection.json'),
};
// setup your map
const map = new mapboxgl.Map({...});
map.on('load', () => {
RSVP.hash(promises).then((data) => {
map.addSource('my-data', {
type: 'geojson',
// transform does intersection and updates,
// then outputs a GeoJSON formatted object
data: transform(data.polygon, data.collection),
});
});
});

Exclude Filters Using InstantSearch.js?

We are using Algolia to index content from a variety of sources and for a dozen different products. Right now I have one index and product is a configured facet.
I need to find a way to restrict searches to only those products the user owns.
I'm using the InstantSearch library and I've been reading through the documentation and various online forums for information on how to accomplish this.
Here is the code I'm trying to get working.
var client = algoliasearch("myAppId", "myApiKey")
var index = client.initIndex('myIndex');
var search = instantsearch({
appId: 'myAppId',
apiKey: 'myApiKey',
indexName: 'myIndex',
urlSync: {},
attributesToHighlight: 'full'
});
search.addWidget(
instantsearch.widgets.refinementList({
container: '#products',
attributeName: 'products',
operator: 'or',
limit: 100,
sortBy: ['name:asc'],
templates: {
}
})
);
search.addWidget({
init: function (options) {
options.helper.addFacetRefinement('products', 'Product A');
}
});
search.start();
But when I execute this I get an error stating "Uncaught Error: products is not defined in the facets attribute of the helper configuration".
What step am I missing? Or am I approaching this in the wrong way?
Any guidance appreciated.
~ Greg
I found an answer to my needs. I had to add a searchParameters option to the instantsearch configuration call. And I had to write some code to hide the unwanted products from my refinementlist widget.
First step is to create an array of the products I want to hide.
var productsToExclude = ['product-a','product-b'];
I had to pass this list of items to hide via the "searchParameters" instantsearch configuration option.
var search = instantsearch({
appId: 'myAppId',
apiKey: 'myApiKey',
indexName: 'myIndex',
urlSync: {},
attributesToHighlight: 'full',
searchParameters: { facetsExcludes: { "products": productsToExclude}}
});
And I also had to write a bit of code to hide the items in the refinementList widget.
var onRenderHandler = function () {
for (var p in productsToExclude) {
$("input[type=checkbox][value='" + productsToExclude[p] + "']").parent().hide();
}
};
search.on('render', onRenderHandler);

Calling Mapquest with an address

I'm looking for a simple way to bring up a MapQuest map with something like:
http://mkapquestapi.com?address=123 Mapel St. Mytown, CA&diameter=20 miles
All the MapQuest documentation I've found tries to put me through hundreds of pages that do much more than I want.
I came across the example below in another StackOverflow question:
$.ajax({
url: "http://www.mapquestapi.com/geocoding/v1/address?key=",
dataType: 'json',
type: 'POST',
contentType:'json',
data: {location: { "postalCode": "98765"}, options: { thumbMaps: false} },
success: function(data) { log( data ) },
error: function(data) { log( 'error occurred - ' + zipCode + ' - ' + data ) }
});
I could handle something like that if someone could point me to where MapQuest explains what it wants in the parameters.
Thanks for any help.
So you want to open MapQuest with an address, rather than lat/long coordinates?
The parameter options are defined in the MapQuest geocoding parameters section. Try this:
http://www.mapquestapi.com/geocoding/#parameters
Disclaimer: I work at MapQuest.
What exactly are you looking to do --- are you looking to generate an image of a map with an address marked on it?
If so, you can use the Static Map API. Here's an example: http://www.mapquestapi.com/staticmap/v4/getplacemap?key=YOUR_KEY_HERE&location=1555 Blake St, Denver, CO&size=400,200&type=map&zoom=13&imagetype=jpeg&showicon=red_1-1
More documentation is here: http://www.mapquestapi.com/staticmap/
If you are looking to make a link that opens MapQuest.com and displays an address, you can link to it this way: http://mapq.st/map?q=1555 Blake St Denver CO 80202&maptype=map
More documentation is here: http://www.mapquestapi.com/link-to-mapquest/
Let me know if this helps. Sounds like you're looking for a map or a map image and not a geocoding result.