-
Notifications
You must be signed in to change notification settings - Fork 471
Expand file tree
/
Copy pathGet nearest POIs to a set of addresses.html
More file actions
327 lines (285 loc) · 14.8 KB
/
Get nearest POIs to a set of addresses.html
File metadata and controls
327 lines (285 loc) · 14.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
<!DOCTYPE html>
<html lang="en">
<head>
<title>Get nearest POIs to a set of addresses - Azure Maps Web SDK Samples</title>
<meta charset="utf-8" />
<link rel="shortcut icon" href="/favicon.ico"/>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta name="description" content="This sample shows the nearest POIs to a set of addresses" />
<meta name="keywords" content="Microsoft maps, map, gis, API, SDK, services, module, geolocation, search, fuzzy, geocode, geocoding, points of interest, POI, address, addresses, places, batch, batch geocode" />
<meta name="author" content="Microsoft Azure Maps" /><meta name="version" content="1.0" />
<meta name="screenshot" content="screenshot.jpg" />
<!-- Add references to the Azure Maps Map control JavaScript and CSS files. -->
<link href="https://atlas.microsoft.com/sdk/javascript/mapcontrol/3/atlas.min.css" rel="stylesheet" />
<script src="https://atlas.microsoft.com/sdk/javascript/mapcontrol/3/atlas.min.js"></script>
<!-- Add a reference to the Azure Maps Services Module JavaScript file. -->
<script src="https://atlas.microsoft.com/sdk/javascript/service/2/atlas-service.min.js"></script>
<script>
var map, datasource, poidatasource, searchURL, points;
var results = [];
var maxSearchResults = 300; //The maximum number of points of interests that will be queried on each update.
var searchOptions = {
view: 'Auto',
language: 'Auto',
limit: 1 //Only need one result per address.
};
//Set of addresses to geocode.
var addresses = [
'7014 E Camelback Rd, Scottsdale, AZ, US',
'1640 Redwood Highway, Corte Madera, CA, US',
'3333 Bristol Street, Costa Mesa, CA, US',
'100 West Broadway, Glendale, CA, US',
'10250 Santa Monica Blvd., Los Angeles, CA, US',
'28032 Marguerite Pkwy, Mission Viejo, CA, US',
'186A Stanford Shopping Center, Palo Alto, CA, US',
'7007 Friars Rd, San Diego, CA, US',
'845 Market St, San Francisco, CA, US',
'865 Market Street, San Francisco, CA, US',
'2855 Stevens Creek Blvd., Santa Clara, CA, US',
'3000 East 1st Avenue, Denver, CO, US',
'8505 Park Meadows Center Dr, Lone Tree, CO, US',
'7 Backus Avenue, Danbury, CT, US',
'500 Westfarms Mall, Farmington, CT, US',
'137 Christiana Mall, Newark, DE, US',
'19501 Biscayne Boulevard, Aventura, FL, US',
'7535 Dadeland Mall, Miami, FL, US',
'8001 South Orange Blossom Trail, Orlando, FL, US',
'3393 Peachtree Road NE, Atlanta, GA, US',
'4400 Ashford Dunwoody Road, Atlanta, GA, US',
'520 N Michigan Ave, Chicago, IL, US',
'49 Oakbrook Center, Oak Brook, IL, US',
'J-106 Woodfield Mall, Schaumburg, IL, US',
'8702 Keystone Crossing, Indianapolis, IN, US',
'11467 West 95th Street, Overland Park, KS, US',
'7101 Democracy Boulevard, Bethesda, MD, US',
'10300 Little Patuxent Parkway, Columbia, MD, US',
'800 Boylston Street, Boston, MA, US',
'250 Granite St, Braintree, MA, US',
'1245 Worcester Street, Natick, MA, US',
'2800 West Big Beaver Road, Troy, MI, US',
'162 South Ave, Bloomington, MN, US',
'1155 Saint Louis Galleria, St. Louis, MO, US',
'2417 St Louis Galleria, St. Louis, MO, US',
'3200 Las Vegas Blvd S, Las Vegas, NV, US',
'99 Rockingham Park Blvd, Salem, NH, US',
'400 Commons Way, Bridgewater, NJ, US',
'3710 Route 9 South, Freehold, NJ, US',
'One Garden State Plaza Way, Paramus, NJ, US',
'630 Old Country Rd, Garden City, NY, US',
'160 Walt Whitman Road, Huntington Station, NY, US',
'10 Columbus Circle, New York, NY, US',
'125 Westchester Avenue, White Plains, NY, US',
'4400 Sharon Road, Charlotte, NC, US',
'6910 Fayetteville Road, Durham, NC, US',
'26300 Cedar Rd, Beachwood, OH, US',
'7875 Montgomery Rd, Cincinnati, OH, US',
'1901 Nw Expressway, Oklahoma City, OK, US',
'7021 S Memorial Dr, Tulsa, OK, US',
'330 SW Yamhill Street, Portland, OR, US',
'9585 SW Washington Square Rd, Portland, OR, US',
'2126 Abbott Martin Road, Nashville, TN, US',
'3309 Esperanza Crossing, Austin, TX, US',
'2601 Preston Road, Frisco, TX, US',
'5015 Westheimer Road, Houston, TX, US',
'7400 San Pedro San Antonio, San Antonio, TX, US',
'15900 La Cantera Parkway, San Antonio, TX, US',
'1201 Lake Woodlands Dr, The Woodlands, TX, US',
'51 South Main Street, Salt Lake City, UT, US',
'1100 S Hayes Street, Arlington, VA, US',
'1961 Chain Bridge Road, Tysons Corner, VA, US',
'116 Bellevue Square, Bellevue, WA, US',
'2624 NE University Village Street, Seattle, WA, US'
];
function getMap() {
//Initialize a map instance.
map = new atlas.Map('myMap', {
view: 'Auto',
language: 'Auto',
//Add authentication details for connecting to Azure Maps.
authOptions: {
// Use SAS token for authentication
authType: 'sas',
getToken: function (resolve, reject, map) {
// URL to your authentication service that retrieves a SAS Token
var tokenServiceUrl = 'https://samples.azuremaps.com/api/GetAzureMapsSasToken';
fetch(tokenServiceUrl).then(r => r.text()).then(token => resolve(token));
}
//Alternatively, use an Azure Maps key. Get an Azure Maps key at https://azure.com/maps. NOTE: The primary key should be used as the key.
//authType: 'subscriptionKey',
//subscriptionKey: '<Subscription Key>'
}
});
//Use MapControlCredential to share authentication between a map control and the service module.
var pipeline = atlas.service.MapsURL.newPipeline(new atlas.service.MapControlCredential(map));
//Create an instance of the SearchURL client.
searchURL = new atlas.service.SearchURL(pipeline);
//Wait until the map resources are ready.
map.events.add('ready', function () {
//Create a data source to add your geocode data to.
datasource = new atlas.source.DataSource();
//Create a data source to add your POI data to.
poidatasource = new atlas.source.DataSource();
map.sources.add(datasource);
map.sources.add(poidatasource);
//Add a layer for rendering geocode data.
map.layers.add(new atlas.layer.BubbleLayer(datasource));
//Add a layer for rendering POI data.
var poiLayer = new atlas.layer.BubbleLayer(poidatasource, null, {
//Set the color based on the category code: https://docs.microsoft.com/en-us/azure/azure-maps/supported-search-categories
color: [
'match',
['get', 'code', ['at', 0, ['get', 'classifications', ['get', 'poi']]]],
'SHOP', 'PURPLE',
'RESTAURANT', 'yellow',
'CAFE_PUB', 'green',
'PARKING_GARAGE', 'lightblue',
'CASH_DISPENSER', 'limegreen',
'NIGHTLIFE', 'pink',
//Default color. Set to 'transparent' to hide all other categories.
'gray'
]
});
map.layers.add(poiLayer);
//Create a reusable popup.
popup = new atlas.Popup();
//Add a click event to the poi layer.
map.events.add('click', poiLayer, poiClicked);
});
parallelGeocode();
}
/**
* This method will iterate through all the locations and make multiple parallel requests.
* The browser will limit the number of concurrent requests to the same domain.
*/
async function parallelGeocode() {
var requests = [];
//Create the request promises.
for (var i = 0; i < addresses.length; i++) {
requests.push(searchURL.searchAddress(atlas.service.Aborter.timeout(10000), addresses[i], searchOptions));
}
//Process the promises in parallel.
var responses = await Promise.all(requests);
//Extract the GeoJSON feature results.
responses.forEach(r => {
var fc = r.geojson.getFeatures();
if (fc.features.length > 0) {
results.push(fc.features[0]);
//For each address geocoded it will perform the search of POI that are close to that location.
performPOISearch(fc.features[0].geometry.coordinates, 0);
}
});
//Done.
endSearch();
}
function endSearch() {
datasource.setShapes(results);
//Set the camera to the bounds of the results.
map.setCamera({
bounds: atlas.data.BoundingBox.fromData(results),
padding: 40
});
}
function performPOISearch(center, offset) {
//Make a query for nearby points of interest.
searchURL.searchNearby(atlas.service.Aborter.timeout(3000), center, {
ofs: offset * 100,
limit: 100,
radius: 5000,
view: 'Auto'
}).then(r => {
var data = r.geojson.getFeatures();
//If offset is 0, remove previous data, check the response to see if there are more results to page through.
if (r.summary.offset == 0) {
//Replace all data on the map with the new data.
poidatasource.setShapes(data);
//Calculate the number of pages
var maxPages = Math.ceil(Math.min(maxSearchResults, r.summary.totalResults) / 100);
//Make requests for the other pages.
for (var oft = 1; oft <= maxPages; oft++) {
performPOISearch(center, oft);
}
} else {
//Add the results to the data source.
poidatasource.add(data);
}
});
}
function poiClicked(e) {
//Make sure the event occurred on a point feature.
if (e.shapes && e.shapes.length > 0 && e.shapes[0].getType() === 'Point') {
var properties = e.shapes[0].getProperties();
//Using the properties, create HTML to fill the popup with useful information.
var html = ['<div style="padding:10px;"><span style="font-size:14px;font-weight:bold;">'];
var addressInTitle = false;
if (properties.type === 'POI' && properties.poi && properties.poi.name) {
html.push(properties.poi.name);
} else if (properties.address && properties.address.freeformAddress) {
html.push(properties.address.freeformAddress);
addressInTitle = true;
}
html.push('</span><br/>');
if (!addressInTitle && properties.address && properties.address.freeformAddress) {
html.push(properties.address.freeformAddress, '<br/>');
}
html.push('<b>Type: </b>', properties.type, '<br/>');
if (properties.entityType) {
html.push('<b>Entity Type: </b>', properties.entityType, '<br/>');
}
if (properties.type === 'POI' && properties.poi) {
if (properties.poi.phone) {
html.push('<b>Phone: </b>', properties.poi.phone, '<br/>');
}
if (properties.poi.url) {
html.push('<b>URL: </b>', properties.poi.url, '<br/>');
}
if (properties.poi.classifications) {
html.push('<b>Classifications:</b><br/>');
for (var i = 0; i < properties.poi.classifications.length; i++) {
for (var j = 0; j < properties.poi.classifications[i].names.length; j++) {
html.push(' - ', properties.poi.classifications[i].names[j].name, '<br/>');
}
}
}
}
html.push('</div>');
//Set the popup options.
popup.setOptions({
//Update the content of the popup.
content: html.join(''),
//Update the position of the popup with the pins coordinate.
position: e.shapes[0].getCoordinates()
});
//Open the popup.
popup.open(map);
}
}
</script>
<style>
#myMap {
position: relative;
width: 100%;
min-width: 290px;
height: 600px;
}
.sidePanel {
position: absolute;
top: 10px;
left: 10px;
border-radius: 10px;
background-color: white;
padding: 10px;
}
</style>
</head>
<body onload="getMap()">
<div id="myMap"></div>
<fieldset style="width:calc(100% - 30px);min-width:290px;margin-top:10px;">
<legend>Get the nearest POIs to a set of addresses</legend>
This sample shows how to make multiple parallel requests to the address search service to geocode a set of addresses.
This method generates a high number of queries per second and only recommended when working with a small set of addresses for other methods please refer to <a href="https://docs.microsoft.com/en-us/rest/api/maps/search/post-search-address-batch" target="_blank">the batch search API documentation</a>.
Based on the addresses it loads points of interest data on the map that are nearest to those locations.
Based on the classification code (category), a different color is used to render the point of interest.
The search service returns up to 100 results, but more can be retrieved by paging through the results offset parameter.
</fieldset>
</body>
</html>