-
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
Conversation
Please submit an issue for this: https://github.com/AnalyticalGraphicsInc/cesium/tree/master/Documentation/Contributors/CodingGuide#deprecation-and-breaking-changes |
bboxDegrees = resultObject.boundingbox; | ||
return { | ||
displayName: resultObject.display_name, | ||
bbox: { |
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.
bbox
is part of the new public Cesium API, right? This is part of the "class" a geocode implementation returns.
It should following Cesium conventions:
- Avoid abbreviations, probably call it
rectangle
- Use a Cesium type, probably
Rectangle
- Use radians. This will likely require most users to convert, e.g., using
fromDegrees
, but it will be consistent with the rest of the API.
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.
Thanks for the review @pjcozzi. Yes, bbox
will be part of the public API, I'll have this fixed.
@erikmaarten this is a great start, but I think there are a few changes we can make here to improve the API.
This will make it really easy to plug in different services in the future. For example, I know people on the forum were asking how to use the Mapbox geocoder as well. We could eventually add Also, if you could, it would be better to make the custom geocoder changes and the autocomplete changes in separate PRs so we can review each individually |
…ults that destinations of type Rectangle or Cartesian3
@hpinkos Ready for review. |
) | ||
}; | ||
}); | ||
}) |
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.
Missing semicolon
|
||
* Deprecated | ||
* 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 comment
The reason will be displayed to describe this comment to others. Learn more.
Add a #
before 4723
/** | ||
* Provides geocoding through Bing Maps. | ||
* @alias BingMapsGeocoderService | ||
* |
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.
Add @params
doc
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 comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be defaultValue(options.url, url)
?
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.
I'm not sure it should be possible to supply a different URL, because then it's not really the same geocoder service anymore
* | ||
*/ | ||
displayName : { | ||
get : DeveloperError.throwInstantiationError |
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.
Should this be here? It doesn't look like BingMapsGeocoderService
uses this property
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.
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 comment
The 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
@mramato ready for another review. I fix the problem you found, and also re-did the way the @erikmaarten you should review the changes I made in f10c75f with regards to promises to see how I changed them together. Your use of |
Thanks @mramato for reviewing. @hpinkos that's a nice refactor, but the functionality is not what I intended, if I'm reading the code correctly. It's good to avoid superfluous requests, but now users will be forced to wait for requests to start and fail in turn. If a more specifically scoped geocoder (like a geocoder with radio station codes as mentioned in the forums) is higher in priority, which I think would be normal, than a general geocoder, then users of that app would often have to wait for one extra network request (slow in the context of users interacting with the geocoder search bar), or more if more geocoders are used. So while it makes technical sense to avoid requests that aren't necessary, doing the extra network requests upfront makes for better UX. A middle ground might also be sensible if we anticipate large numbers of geocoders in the same app: chaining the requests, but with chunks of five requests each time or something like that. |
Is this ready? If we want to ship this in 1.29, we should merge it this week. |
@mramato had some comments on the interface design that I've replied to, and @hpinkos asked him for a follow-up review of the last changes, but since he's out for the holidays we won't be able to get any updates from him there. @hpinkos have you seen my comments? Would like to hear what you think. Also, since my comments don't affect the interface, we could just settle with the current functionality and see how people actually use and then adapt to that. |
I get what you're saying here. I did make it a bit more synchronous by waiting for the previous call to complete before making the next one. I was thinking the first one would often be the geocode that we ended up using, so I didn't see the point of making calls to the other geocoders and waiting for them all to either resolve or fail. I'm really not sure which is best, so I'll wait to hear what @mramato thinks before changing things more |
What is the plan with this pull request? |
@mramato can you take a look at this? |
On my list for later today. |
If you click inside the text field at any point, autocomplete starts to work as expected. |
} | ||
//>>includeEnd('debug'); | ||
|
||
try { |
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.
Sorry if this has been covered, but what part of this try block can cause an exception?
|
||
var that = this; | ||
|
||
this._suggestionsVisible = knockout.pureComputed(function () { | ||
var suggestions = knockout.getObservable(that, '_suggestions'); |
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.
My knockout-es5 is a little rusty, but is this knockout.getObservable
needed here? I think you can just use that._suggestions
directly and everything will work. CC @shunter
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.
I wasn't sure it would trigger the pureComputed
properly otherwise, but I didn't test it to see
*/ | ||
this.autoComplete = defaultValue(options.autocomplete, true); | ||
|
||
this._focusTextbox = false; |
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.
This shouldn't be private if it's used in the bindings.
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.
Every other thing we're binding to below is privage
} | ||
}); | ||
|
||
GeocoderViewModel.prototype.destroy = function() { |
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.
Add documentation.
viewModel._geocodePromise = promise; | ||
promise | ||
.then(function (result) { | ||
if (promise.cancel || promise !== viewModel._geocodePromise) { |
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.
I don't think the second condition here can ever be true, since it's impossible to start a second geocode while a current geocode is in process.
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.
That would be for if the geocode
was triggered again before the first geocode resolved
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.
Maybe I'm missing something, but how is that possible with the code as currently written?
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.
True. I was thinking it would happen if you hit the geocode button a few times, but in that case promise.cancel
would be true. I just kept this here because that's how it was working before, but I agree that it doesn't seem necessary.
nextPromise.otherwise(function (err) { | ||
return {state: 'rejected', reason: err}; | ||
}); | ||
} else if (defined(nextPromise.catch)) { |
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.
I assume you are doing this to try and handle multiple promise implementations, but I think we should just simplify the code and always assume the promise was created with our version of when. Otherwise bad things can happen anyway, for example Bluebird promises have a cancel
function, which would end up making your code think that cancel
has been called on successful geocodes because you glob your own cancel
onto the promise as a boolean. (hopefully that make sense).
We we upgrade to bluebird, these problems should go away, but we should just assume everyone is using Cesium's own when
library for the time being.
@@ -2,7 +2,13 @@ Change Log | |||
========== | |||
|
|||
### 1.29 - 2017-01-02 | |||
|
|||
* Deprecated |
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.
Merge in master and move this to 1.30.
Thanks again @erikmaarten, I don't want to bikeshed this too much since it clearly works well (except in the couple cases I mentioned). Once my last round of comments are addressed we can merge this up to master. |
@erikmaarten I'll take care of cleaning this up |
# Conflicts: # CHANGES.md
@mramato ready |
Thanks @hpinkos for taking care of this. @mramato do you have any opinion on #4723 (comment)? I updated the release numbers here to deprecate those properties in 1.30 and remove them in 1.31 since we didn't make it in time for the 1.29 release. I also updated the deprecation issue. |
Ultimately, I think the use of multiple geocoders will be uncommon, so the point is probably moot. However, I agree that having a slow geocoder first could end up slowing down the entire operation in that use case, so firing multiple requests and letting the first one that returns "win" may be a good idea. We should probably also make the limit of 5 an option in the view model so that users can allow more returns if desired. I'm going to merge this as-is for now since it's in good shape, but if you (@erikmaarten) want to open another PR right away to add back the gecode "race" then we'll merge that too (and it will be easier to review since it will be a smaller change). Thanks again! |
Adresses parts of #1262.
Something I haven't quite decided on is whether there should be different methods for getting geocoder search suggestions and the actual geocoding. This would be necessary if a certain service has different API endpoints for this, or if they otherwise need to be handled differently. It would probably be better to keep this separate.
A custom geocoder is expected to look like:
The default geocoder in Cesium remains largely unchanged in this PR.
I've marked the
GeocoderViewModel
propertieskey
andurl
for deprecation. I think these don't make sense to expose as public properties since they are implementation details (and may not exist) of the custom geocoder provided.