Skip to content

Commit daf8d77

Browse files
committed
Update Search for boundaries.html
Update sample to use latest geocoding and boundary polygon services.
1 parent ad3c8e0 commit daf8d77

1 file changed

Lines changed: 136 additions & 52 deletions

File tree

Samples/Services Module/Search for boundaries/Search for boundaries.html

Lines changed: 136 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
<script src="https://samples.azuremaps.com/lib/azure-maps/azure-maps-helper.min.js"></script>
2222

2323
<script>
24-
var map, datasource, layer, popup;
24+
var map, datasource, layer, popup, displayedLocation;
2525

2626
// Your Azure Maps client id for accessing your Azure Maps account.
2727
var azureMapsClientId = 'e6b6ab59-eb5d-4d25-aa57-581135b927f0';
@@ -30,10 +30,18 @@
3030
var tokenServiceUrl = 'https://samples.azuremaps.com/api/GetAzureMapsToken';
3131

3232
// URL for the Azure Maps Search Geocoder API.
33-
var geocodeUrl = 'https://{azMapsDomain}/search/address/json?api-version=1.0&query={query}';
33+
var geocodeUrl = 'https://{azMapsDomain}/geocode?api-version=2023-06-01&top=10&view=Auto&query={query}';
3434

3535
// URL for the Azure Maps Search Polygon API.
36-
var polygonUrl = 'https://{azMapsDomain}/search/polygon/json?api-version=1.0&geometries={geometries}';
36+
var polygonUrl = 'https://{azMapsDomain}/search/polygon?api-version=2023-06-01&coordinates={coordinates}&view=Auto&resultType={resultType}&resolution={resolution}';
37+
38+
//A list of entity types that the boundary service supports.
39+
var boundaryEntityTypes = ['adminDistrict', 'adminDistrict2', 'countryRegion', 'locality', 'neighborhood', 'postalCode', 'postalCode2', 'postalCode3', 'postalCode4'];
40+
41+
//A simple local-cache to store information about boundaries for this sample.
42+
// Format: { id: { position: [], entityType: '', bbox: [] } } where the id is a pipe delimited formatted address and entity type since many places could have the same formatted address.
43+
//Not caching boundary polygon for this sample as we want to be able to switch between resolutions.
44+
var boundaryCache = {};
3745

3846
// Function to retrieve an Azure Maps access token.
3947
function getToken(resolve, reject, map) {
@@ -61,8 +69,8 @@
6169
// Alternatively, use an Azure Maps key.
6270
// Get an Azure Maps key at https://azure.com/maps.
6371
// NOTE: The primary key should be used as the key.
64-
//authType: 'subscriptionKey',
65-
//subscriptionKey: '[YOUR_AZURE_MAPS_KEY]'
72+
// authType: 'subscriptionKey',
73+
// subscriptionKey: '[YOUR_AZURE_MAPS_KEY]'
6674
}
6775
});
6876

@@ -101,77 +109,145 @@
101109
var geocodeRequestUrl = geocodeUrl
102110
.replace('{query}', encodeURIComponent(query));
103111

104-
processRequest(geocodeRequestUrl).then(geocode => {
105-
var r = geocode.results;
106-
var geomIds = [];
112+
processRequest(geocodeRequestUrl).then(fc => {
113+
var r = fc.features;
107114
var html = ['<h3>Results</h3><ol>'];
115+
var hasBoundaries = false;
116+
var firstResult;
108117

109-
// Loop through the results and extract the ones that have boundaries.
118+
// Loop through the results and extract the ones that might have boundaries.
110119
for (var i = 0; i < r.length; i++) {
111-
if (r[i].dataSources && r[i].dataSources.geometry && r[i].dataSources.geometry.id) {
112-
// Store the bounady id.
113-
geomIds.push(r[i].dataSources.geometry.id);
114-
115-
// Create a link to select and zoom into the boundary.
116-
html.push(`<li><a href="javascript:void(0)" onclick="viewPolygon('${r[i].dataSources.geometry.id}');">${r[i].address.freeformAddress}</a><br/>${r[i].entityType}</li>`);
120+
var t = r[i].properties.type;
121+
122+
//Convert the type property to a boundary Entity type value as it seems these values differ between services.
123+
switch (t) {
124+
case 'CountryRegion':
125+
t = 'countryRegion';
126+
break;
127+
case 'AdminDivision1':
128+
t = 'adminDistrict';
129+
break;
130+
case 'AdminDivision2':
131+
t = 'adminDistrict2';
132+
break;
133+
case 'Postcode1':
134+
t = 'postalCode';
135+
break;
136+
case 'Postcode2':
137+
t = 'postalCode2';
138+
break;
139+
case 'Postcode3':
140+
t = 'postalCode3';
141+
break;
142+
case 'Postcode4':
143+
t = 'postalCode4';
144+
break;
145+
case 'PopulatedPlace':
146+
t = 'locality';
147+
break;
148+
case 'Neighborhood':
149+
t = 'neighborhood';
150+
break;
117151
}
118-
}
119152

120-
html.push('</ol>');
121153

122-
if (geomIds.length > 0) {
123-
// Filter the polygon layer to the first polygon.
124-
layer.setOptions({ filter: ['==', ['get', 'providerID'], geomIds[0]] });
154+
//Check to see if the search result could have a boundary.
155+
if (boundaryEntityTypes.indexOf(t) != -1) {
156+
var id = `${r[i].properties.address.formattedAddress}|${t}`;
125157

126-
// Retrieve the boudary polygons. The response may be large, so allow a longer abort time.
127-
var polygonRequestUrl = polygonUrl
128-
.replace('{geometries}', geomIds.join());
158+
//Cache some basic information about the location.
159+
boundaryCache[id] = {
160+
position: r[i].geometry.coordinates,
161+
entityType: t
162+
};
129163

130-
processRequest(polygonRequestUrl).then(boundaries => {
131-
html.push(`Response size: ${Math.round(JSON.stringify(boundaries).length / 1024 / 1024 * 100) / 100}MB`);
164+
if (!firstResult) {
165+
firstResult = id;
166+
}
132167

133-
// Get the results in GeoJSON format and add it to the data source.
134-
for (var j = 0; j < boundaries.additionalData.length; j++) {
135-
var geojson = boundaries.additionalData[j].geometryData;
136-
for (var f = 0; f < geojson.features.length; f++) {
137-
geojson.features[f].properties.providerID = geojson.features[f].id;
138-
}
168+
// Create a link to select and zoom into the boundary.
169+
html.push(`<li><a href="javascript:void(0)" onclick="getPolygon('${id}');">${r[i].properties.address.formattedAddress}</a> (${t}, Confidence: ${r[i].properties.confidence})</li>`);
139170

140-
datasource.add(geojson);
141-
}
171+
hasBoundaries = true;
172+
}
173+
}
174+
175+
html.push('</ol>');
142176

143-
// Focus on the first polygon in the list.
144-
viewPolygon(boundaries.additionalData[0].geometryData.features[0].id);
177+
if (hasBoundaries) {
178+
// Focus on the first polygon in the list.
179+
getPolygon(firstResult);
145180

146-
// Display the list of boundaries.
147-
document.getElementById('resultList').innerHTML = html.join('');
181+
// Display the list of results.
182+
document.getElementById('resultList').innerHTML = html.join('');
148183

149-
// Hide the loading icon.
150-
document.getElementById('loadingIcon').style.display = 'none';
151-
});
184+
// Hide the loading icon.
185+
document.getElementById('loadingIcon').style.display = 'none';
152186
} else {
153-
alert('No boundary found.');
187+
document.getElementById('resultList').innerHTML = 'No boundary found.';
154188

155189
// Hide the loading icon.
156190
document.getElementById('loadingIcon').style.display = 'none';
157191
}
158192
});
159193
}
160194

161-
function viewPolygon(geomId) {
195+
function getPolygon(id) {
162196
popup.close();
163197

164-
// Filter the polygon layer to only display the boundary with the specified geometry id.
165-
layer.setOptions({ filter: ['==', ['get', 'providerID'], geomId] });
198+
//Make sure we have information in the cache for the provided ID.
199+
if (boundaryCache[id]) {
200+
displayedLocation = id;
166201

167-
// Retrieve the boundary shape from the data source that has the required geometry id.
168-
var s = datasource.getShapes().find(x => x.getProperties().providerID === geomId);
202+
var b = boundaryCache[id];
169203

170-
// Update the map camera so that it focuses on the geometry.
171-
map.setCamera({
172-
bounds: atlas.data.BoundingBox.fromData(s),
173-
padding: 40
174-
});
204+
//Get the selected resolution type.
205+
var resolution = document.getElementById('resolutionSelector').value;
206+
207+
//Retrieve the boundary from Azure Maps.
208+
209+
// Show the loading icon.
210+
document.getElementById('loadingIcon').style.display = '';
211+
212+
// Retrieve the boudary polygons. The response may be large, so allow a longer abort time.
213+
var polygonRequestUrl = polygonUrl
214+
.replace('{coordinates}', b.position.join(','))
215+
.replace('{resultType}', b.entityType)
216+
.replace('{resolution}', resolution);
217+
218+
processRequest(polygonRequestUrl).then(f => {
219+
console.log(`Response size for '${id}' boundary: ${Math.round(JSON.stringify(f).length / 1024 / 1024 * 100) / 100}MB`);
220+
221+
//Cache the boundary.
222+
b.boundary = f;
223+
224+
//Add the boundary to the map.
225+
datasource.setShapes(f);
226+
227+
//Caclaulte and cache the bounding box of the boundary.
228+
b.bbox = atlas.data.BoundingBox.fromData(f);
229+
230+
//Update the map camera so that it focuses on the geometry.
231+
map.setCamera({ bounds: b.bbox, padding: 40 });
232+
233+
// Hide the loading icon.
234+
document.getElementById('loadingIcon').style.display = 'none';
235+
}, e => {
236+
//An error occurred, clear the data source.
237+
alert('Unable to retrieve boundary for this location.');
238+
239+
datasource.clear();
240+
241+
// Hide the loading icon.
242+
document.getElementById('loadingIcon').style.display = 'none';
243+
});
244+
}
245+
}
246+
247+
function reloadBoundary() {
248+
if (displayedLocation) {
249+
getPolygon(displayedLocation);
250+
}
175251
}
176252

177253
function layerClicked(e) {
@@ -220,9 +296,17 @@
220296
<div id="myMap" style="position:relative;width:100%;min-width:290px;height:600px;"></div>
221297

222298
<div style="position:absolute;top:15px;left:15px;background-color:white;padding:10px;border-radius:10px;">
223-
<input type="text" id="input" value="Sydney, NSW" />
299+
<input type="text" id="input" value="London" />
224300
<input type="button" onClick="search()" value="Search" />
225301

302+
Resolution:
303+
<select id="resolutionSelector" onchange="reloadBoundary()">
304+
<option value="small">Small</option>
305+
<option value="medium" selected>Medium</option>
306+
<option value="large">Large</option>
307+
<option value="huge">Huge</option>
308+
</select>
309+
226310
<div id="resultList"></div>
227311
</div>
228312

0 commit comments

Comments
 (0)