-
Notifications
You must be signed in to change notification settings - Fork 3.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve geocoder #4723
Improve geocoder #4723
Changes from 19 commits
89fcd98
6bfbc9d
60db026
fb19346
9f84da3
bc8ed9a
da2b6cb
202eee3
d2ef80c
7680bdc
8d04944
9124a6b
ba11113
48111c6
3d4071f
b94d7be
9152955
4e58f4b
a68cbc5
93876bc
2849a18
1fc73d4
b06cfa1
e99f838
0846a89
b72ae90
94eecbf
1b66af9
2659c7f
f10c75f
ff5b0ea
7d52c00
1d34c97
97f10a7
7c8f5f4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="utf-8"> | ||
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"> | ||
<meta name="description" content="Cluster labels, billboards and points."> | ||
<meta name="cesium-sandcastle-labels" content="Tutorials,Showcases"> | ||
<title>Cesium Demo</title> | ||
<script type="text/javascript" src="../Sandcastle-header.js"></script> | ||
<script type="text/javascript" src="../../../ThirdParty/requirejs-2.1.20/require.js"></script> | ||
<script type="text/javascript"> | ||
require.config({ | ||
baseUrl : '../../../Source', | ||
waitSeconds : 60 | ||
}); | ||
</script> | ||
</head> | ||
<body class="sandcastle-loading" data-sandcastle-bucket="bucket-requirejs.html"> | ||
<style> | ||
@import url(../templates/bucket.css); | ||
#toolbar { | ||
background: rgba(42, 42, 42, 0.8); | ||
padding: 4px; | ||
border-radius: 4px; | ||
} | ||
#toolbar input { | ||
vertical-align: middle; | ||
padding-top: 2px; | ||
padding-bottom: 2px; | ||
} | ||
</style> | ||
<div id="cesiumContainer" class="fullSize"></div> | ||
<div id="loadingOverlay"><h1>Loading...</h1></div> | ||
<script id="cesium_sandcastle_script"> | ||
function startup(Cesium) { | ||
'use strict'; | ||
//Sandcastle_Begin | ||
|
||
var viewer = new Cesium.Viewer('cesiumContainer', { | ||
geocoder: new Cesium.OpenStreetMapNominatimGeocoderService() | ||
}); | ||
|
||
//Sandcastle_End | ||
Sandcastle.finishedLoading(); | ||
} | ||
if (typeof Cesium !== "undefined") { | ||
startup(Cesium); | ||
} else if (typeof require === "function") { | ||
require(["Cesium"], startup); | ||
} | ||
</script> | ||
</body> | ||
</html> |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,7 +2,9 @@ Change Log | |
========== | ||
|
||
### 1.29 - 2017-01-02 | ||
|
||
* Deprecated | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Merge in master and move this to 1.30. |
||
* The properties `url` and `key` will be removed from `GeocoderViewModel` in 1.30. This properties will be available on geocoder services that support them, like `BingMapsGeocoderService`; | ||
* Added support for custom geocoder services [4723](https://github.com/AnalyticalGraphicsInc/cesium/pull/4723). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add a |
||
* Added the ability to blend a `Model` with a color/translucency. Added `color`, `colorBlendMode`, and `colorBlendAmount` properties to `Model`, `ModelGraphics`, and CZML. Added `ColorBlendMode` enum. [#4547](https://github.com/AnalyticalGraphicsInc/cesium/pull/4547) | ||
* Fixed tooltips for gallery thumbnails in Sandcastle [#4702](https://github.com/AnalyticalGraphicsInc/cesium/pull/4702) | ||
* Fixed texture rotation for `RectangleGeometry` [#2737](https://github.com/AnalyticalGraphicsInc/cesium/issues/2737) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
/*global define*/ | ||
define([ | ||
'./BingMapsApi', | ||
'./defaultValue', | ||
'./defineProperties', | ||
'./loadJsonp', | ||
'./Rectangle', | ||
], function( | ||
BingMapsApi, | ||
defaultValue, | ||
defineProperties, | ||
loadJsonp, | ||
Rectangle) { | ||
'use strict'; | ||
|
||
var url = 'https://dev.virtualearth.net/REST/v1/Locations'; | ||
|
||
/** | ||
* Provides geocoding through Bing Maps. | ||
* @alias BingMapsGeocoderService | ||
* | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add |
||
*/ | ||
function BingMapsGeocoderService(options) { | ||
options = defaultValue(options, defaultValue.EMPTY_OBJECT); | ||
this._canceled = false; | ||
|
||
this._url = 'https://dev.virtualearth.net/REST/v1/Locations'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure it should be possible to supply a different URL, because then it's not really the same geocoder service anymore |
||
this._key = BingMapsApi.getKey(options.key); | ||
|
||
this.autoComplete = defaultValue(options.autoComplete, false); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this a Geocoder option instead of a widget-level option? It seems odd to make the decision at the low-level, non-UX part. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Even if a particular In the case of So my intention was that the widget-level |
||
} | ||
|
||
defineProperties(BingMapsGeocoderService.prototype, { | ||
/** | ||
* The URL endpoint for the Bing geocoder service | ||
* @type {String} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This and below need to be marked |
||
*/ | ||
url : { | ||
get : function () { | ||
return this._url; | ||
} | ||
}, | ||
|
||
/** | ||
* The key for the Bing geocoder service | ||
* @type {String} | ||
*/ | ||
key : { | ||
get : function () { | ||
return this._key; | ||
} | ||
} | ||
}); | ||
|
||
BingMapsGeocoderService.prototype.cancel = function() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing documentation. |
||
this._canceled = true; | ||
}; | ||
|
||
/** | ||
* @function | ||
* | ||
* @param {String} query The query to be sent to the geocoder service | ||
* @returns {Promise<GeocoderResult[]>} | ||
*/ | ||
BingMapsGeocoderService.prototype.geocode = function(query) { | ||
this._canceled = false; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From an interface standpoint, this is kind of odd. If I do There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It probably makes more sense to pull the cancel functionality out of the geocode function and into the widget (since cancel doesn't really make sense for non-UX usage. |
||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a reason we don't check that query is defined and throw a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missed it |
||
var key = this.key; | ||
var promise = loadJsonp(url, { | ||
parameters : { | ||
query : query, | ||
key : key | ||
}, | ||
callbackParameterName : 'jsonp' | ||
}); | ||
|
||
var that = this; | ||
|
||
return promise.then(function(result) { | ||
if (that._canceled) { | ||
return; | ||
} | ||
if (result.resourceSets.length === 0) { | ||
return []; | ||
} | ||
|
||
var results = result.resourceSets[0].resources; | ||
|
||
return results.map(function (resource) { | ||
var bbox = resource.bbox; | ||
var south = bbox[0]; | ||
var west = bbox[1]; | ||
var north = bbox[2]; | ||
var east = bbox[3]; | ||
return { | ||
displayName: resource.name, | ||
destination: Rectangle.fromDegrees(west, south, east, north) | ||
}; | ||
}); | ||
}); | ||
}; | ||
|
||
return BingMapsGeocoderService; | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
/*global define*/ | ||
define([ | ||
'./defineProperties', | ||
'./DeveloperError' | ||
], function( | ||
defineProperties, | ||
DeveloperError) { | ||
'use strict'; | ||
|
||
/** | ||
* @typedef {Object} GeocoderResult | ||
* @property {String} displayName The display name for a location | ||
* @property {Rectangle|Cartesian3} destination The bounding box for a location | ||
*/ | ||
|
||
/** | ||
* Provides geocoding through an external service. This type describes an interface and | ||
* is not intended to be used. | ||
* @alias GeocoderService | ||
* @constructor | ||
* | ||
* @see BingMapsGeocoderService | ||
*/ | ||
function GeocoderService () { | ||
/** | ||
* Indicates whether this geocoding service is to be used for autocomplete. | ||
* | ||
* @type {boolean} | ||
* @default false | ||
*/ | ||
this.autoComplete = false; | ||
} | ||
|
||
defineProperties(GeocoderService.prototype, { | ||
/** | ||
* The name of this service to be displayed next to suggestions | ||
* in case more than one geocoder is in use | ||
* @type {String} | ||
* | ||
*/ | ||
displayName : { | ||
get : DeveloperError.throwInstantiationError | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this be here? It doesn't look like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This isn't actually being used at the moment, so perhaps I should remove it, but I thought it would be useful to have a name for each service for the case where somebody wanted to show to end users which results come from which geocoders. But that may be a premature consideration since it's not actually used... what do you think, should I just get rid of it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If this isn't being used, you should get rid of it. Thanks |
||
} | ||
}); | ||
|
||
/** | ||
* @function | ||
* | ||
* @param {String} query The query to be sent to the geocoder service | ||
* @returns {Promise<GeocoderResult[]>} | ||
*/ | ||
GeocoderService.prototype.geocode = DeveloperError.throwInstantiationError; | ||
|
||
return GeocoderService; | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/*global define*/ | ||
define([ | ||
'./Cartesian3', | ||
'./defaultValue', | ||
'../ThirdParty/when' | ||
], function( | ||
Cartesian3, | ||
defaultValue, | ||
when) { | ||
'use strict'; | ||
|
||
/** | ||
* Provides geocoding through Bing Maps. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Update doc. |
||
* @alias LongLatGeocoderService | ||
* | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I realized options aren't actually used for this service, so I just removed them instead |
||
*/ | ||
function LongLatGeocoderService(options) { | ||
options = defaultValue(options, defaultValue.EMPTY_OBJECT); | ||
this.autoComplete = false; | ||
} | ||
|
||
LongLatGeocoderService.prototype.cancel = function() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add this function to the |
||
}; | ||
|
||
/** | ||
* @function | ||
* | ||
* @param {String} query The query to be sent to the geocoder service | ||
* @returns {Promise<GeocoderResult[]>} | ||
*/ | ||
LongLatGeocoderService.prototype.geocode = function(query, callback) { | ||
try { | ||
var splitQuery = query.match(/[^\s,\n]+/g); | ||
if ((splitQuery.length === 2) || (splitQuery.length === 3)) { | ||
var longitude = +splitQuery[0]; | ||
var latitude = +splitQuery[1]; | ||
var height = (splitQuery.length === 3) ? +splitQuery[2] : 300.0; | ||
|
||
if (!isNaN(longitude) && !isNaN(latitude) && !isNaN(height)) { | ||
var result = { | ||
displayName: query, | ||
destination: Cartesian3.fromDegrees(longitude, latitude, height) | ||
}; | ||
return when.resolve([result]); | ||
} | ||
} | ||
return when.resolve([]); | ||
} catch (e) { | ||
when.reject(e); | ||
} | ||
}; | ||
|
||
return LongLatGeocoderService; | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
/*global define*/ | ||
define([ | ||
'./Cartesian3', | ||
'./defaultValue', | ||
'./loadJson', | ||
'./Rectangle' | ||
], function( | ||
Cartesian3, | ||
defaultValue, | ||
loadJson, | ||
Rectangle) { | ||
'use strict'; | ||
|
||
/** | ||
* Provides geocoding through OpenStreetMap Nominatim. | ||
* @alias OpenStreetMapNominatimGeocoder | ||
* | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
*/ | ||
function OpenStreetMapNominatimGeocoder(options) { | ||
options = defaultValue(options, defaultValue.EMPTY_OBJECT); | ||
this.displayName = defaultValue(options.displayName, 'Nominatim'); | ||
this._canceled = false; | ||
this.autoComplete = defaultValue(options.autoComplete, true); | ||
} | ||
|
||
OpenStreetMapNominatimGeocoder.prototype.cancel = function() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. doc |
||
this._canceled = true; | ||
}; | ||
|
||
/** | ||
* @function | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You probably don't need |
||
* | ||
* @param {String} query The query to be sent to the geocoder service | ||
* @returns {Promise<GeocoderResult[]>} | ||
*/ | ||
OpenStreetMapNominatimGeocoder.prototype.geocode = function (input) { | ||
var endpoint = 'http://nominatim.openstreetmap.org/search?'; | ||
var query = 'format=json&q=' + input; | ||
var requestString = endpoint + query; | ||
return loadJson(requestString) | ||
.then(function (results) { | ||
var bboxDegrees; | ||
return results.map(function (resultObject) { | ||
bboxDegrees = resultObject.boundingbox; | ||
return { | ||
displayName: resultObject.display_name, | ||
destination: Rectangle.fromDegrees( | ||
bboxDegrees[2], | ||
bboxDegrees[0], | ||
bboxDegrees[3], | ||
bboxDegrees[1] | ||
) | ||
}; | ||
}); | ||
}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing semicolon |
||
}; | ||
|
||
return OpenStreetMapNominatimGeocoder; | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we sure about including this in core Cesium? Are people asking for it? Is it just increasing the API surface area? Would it be better suited as an example of a custom geocoder in this Sandcastle example as this name states?