-
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
Adding support for WMS-T Time parameter to WebMapServiceImageryProvider #6348
Conversation
@@ -13,7 +13,8 @@ define([ | |||
'../Core/WebMercatorTilingScheme', | |||
'../ThirdParty/Uri', | |||
'./GetFeatureInfoFormat', | |||
'./UrlTemplateImageryProvider' | |||
'./UrlTemplateImageryProvider', | |||
'../Scene/TimeDynamicImagery' |
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.
TimeDynamicImagery.js
is in the same directory. No need to the ../Scene
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, will make this change
}); | ||
} | ||
|
||
if (defined(options.clock)) { |
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.
Why is the time
parameter a special case? Can't the dynamic properties remain generic like WMTS?
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.
The user can pass any parameters they want, but in this case we are building a time parameter out of the time intervals / clock information.
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 have made changes, but I still get the current time from the clock and create a time parameter if it does not exist in the parameters from the interval.
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.
We shouldn't be hard coding that time
parameter. When I hooked it up into WMTS, there were many different ways server used this parameter. For instance some of them expected TIME
as the parameter. Others had a parameter epoch
, and time
was the offset from this time or some expected time
to be a range in the format start
/end
. In these cases, this code wouldn't work. We don't do this in WMTS and I don't think we should do it here. This needs to be generic and not specific to your use case.
|
||
if (defined(dynamicIntervalData)) { | ||
if (!isNaN(dynamicIntervalData)){ | ||
parameters['time'] = interval.start.toString(); |
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.
Not exactly sure what is going on here? If dynamicIntervalData
is a number, we just use the start time? Why is that?
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.
Ah, that may have been specific to my use case. Let me look further. Good catch, thanks.
I have made some updates based on your feedback, and expanded the test suite. Can you take a look? I think it makes more sense now. Thanks. |
if (defined(dynamicIntervalData)) { | ||
if (dynamicIntervalData instanceof Object){ | ||
try { | ||
Object.keys(dynamicIntervalData).forEach(function (key, index) { |
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 is just copying dynamicIntervalData
. We can just pass that directly into setQueryParameters
.
}); | ||
} catch (err){ | ||
// Warn the user, this may not be a problem | ||
console.warn('Data from interval has problems.', err); |
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.
In Cesium we don't output errors to the console if its a error by the developer. We occasionally use it if there is an error from a remote server. You can search for DeveloperError to see how we use it and also remove it from the minified build. Although I anticipate that this try/catch will go away.
} | ||
} | ||
} | ||
if (!('time' in keys)){ |
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 should be removed like above.
Thanks for the continued feedback, @tfili, I'll review and update. |
Will you be adding support for other dimensions as was done for WMTS, including the predefined "elevation"? I use a WMS for weather forecast data that has additional dimensions "run" and "forecast". |
Hi @GatorScott you can add any parameters you want via the data in your TimeInterval. |
Ok @tfili your suggestions are implemented; please especially review the code I changed in the constructor, the pushing of parameters here might be redundant as the timeDynamicImagery may automagically handle this on first load? Not sure. |
|
if (defined(options.clock)) { | ||
if (defined(options.parameters)) { | ||
options.parameters['time'] = options.clock.currentTime.toString(); | ||
if (defined(options.clock)){ |
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 doesn't need to be done in the constructor, you are always setting them in requestImage
var resource = imageryProvider._tileProvider._resource; // We actually want to set the time parameter within the tile provider. | ||
var parameters = {}; | ||
var keys = []; | ||
var resource = imageryProvider._tileProvider._resource; // We actually want to set the query parameters within the tile provider. |
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.
Since we can have multiple images in flight, including some for a future time with different dynamic data, you want something like this, that will clone the resource but merge in the dynamic query parameters. Also, you don't need to check if dynamicIntervalData
is an object.
You want to do something like
var resource = imageryProvider._tileProvider._resource;
if (defined(dynamicIntervalData)) {
resource = resource.getDerivedResource({
queryParameters: objectToLowercase(dynamicIntervalData)
});
}
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.
The reason why I am updating the parameters on the resource in the tile provider is because it is the one that is using them. If I make a copy of the resource as you suggest, then I have no way of setting that as the resource in the tile provider (in this case the UrlTemplateImageryProvider). It doesn't feel right to update the parameters on the resource in the tile provider, but the API for requestImage does not allow for passing the parameters any other way. Thoughts?
I've pushed the code cleanup; I am still setting the query parameters on the resource within the tile provider. .. |
Hi @tfili any chance you might review this soon? Thanks a ton. |
@tamarmot, sorry for the delay. It’s been on my list all week. I’ve been swamped. I’ll hopefully get to it tomorrow or early next week. |
@@ -27,7 +28,8 @@ define([ | |||
WebMercatorTilingScheme, | |||
Uri, | |||
GetFeatureInfoFormat, | |||
UrlTemplateImageryProvider) { | |||
TimeDynamicImagery, | |||
UrlTemplateImageryProvider ) { |
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.
Fix white space
@@ -67,6 +69,9 @@ define([ | |||
* @param {String|String[]} [options.subdomains='abc'] The subdomains to use for the <code>{s}</code> placeholder in the URL template. | |||
* If this parameter is a single string, each character in the string is a subdomain. If it is | |||
* an array, each element in the array is a subdomain. | |||
* @param {Clock} [options.clock] A Clock instance that is used when determining the value for the time dimension. Required when options.times is specified. | |||
* @param {TimeIntervalCollection} [options.times] TimeIntervalCollection with its data property being an object containing time dynamic dimension and their values. | |||
* |
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.
Remove extra blank line.
} | ||
|
||
if (defined(options.proxy)) { | ||
deprecationWarning('WebMapServiceImageryProvider.proxy', 'The options.proxy parameter has been deprecated. Specify options.url as a Resource instance and set the proxy property there.'); |
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 deprecation was removed in the master for our release next week. deprecationWarning
isn't included in this file anymore.
done, thanks!
…On Tue, Apr 3, 2018 at 7:32 AM, Tom Fili ***@***.***> wrote:
Looking at issue, I was able to create this example that seems to work
correctly.
var viewer = new Cesium.Viewer('cesiumContainer');
function dataCallback(interval, index) {
var time;
if (index === 0) { // leading
time = Cesium.JulianDate.toIso8601(interval.stop);
} else {
time = Cesium.JulianDate.toIso8601(interval.start);
}
return {
Time: time
};
}
var times = Cesium.TimeIntervalCollection.fromIso8601({
iso8601: '2014-06-30/2017-06-16/P1D',
leadingInterval: true,
trailingInterval: true,
isStopIncluded: false, // We want stop time to be part of the trailing interval
dataCallback: dataCallback
});
var imageryLayers = viewer.imageryLayers;var provider = new Cesium.WebMapServiceImageryProvider({
url: "http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0q-t.cgi?",
layers: "nexrad-n0q-wmst",
parameters: {
format: 'image/png',
transparent: 'true'
},
times: times,
clock: viewer.clock
});imageryLayers.addImageryProvider(provider);
provider.readyPromise
.then(function() {
var start = Cesium.JulianDate.fromIso8601('2014-06-30');
var end = Cesium.JulianDate.fromIso8601('2017-06-16');
viewer.timeline.zoomTo(start, end);
var clock = viewer.clock;
clock.startTime = start;
clock.endTime = end;
clock.currentTime = start;
clock.clockRange = Cesium.ClockRange.LOOP_STOP;
clock.multiplier = 86400;
});
@tamarmot <https://github.com/tamarmot> Can you merge in master to
resolve the conflict.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#6348 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AFgK8Ha7kHaFN13Yf8K23gZ-VyVHk6eGks5tk4f2gaJpZM4Swmjr>
.
|
@tfili bump Are we waiting on anything else? |
var currentInterval; | ||
|
||
if (!defined(timeDynamicImagery)){ | ||
return this._tileProvider.requestImage(x, y, level, request); |
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 should be requestImage(this, x, y, level, request)
, just like below but without the interval.
CHANGES.md
Outdated
@@ -57,8 +60,14 @@ Change Log | |||
* Fixed improper zoom during model load failure. [#6305](https://github.com/AnalyticalGraphicsInc/cesium/pull/6305) | |||
* Fixed rendering vector tiles when using `invertClassification`. [#6349](https://github.com/AnalyticalGraphicsInc/cesium/pull/6349) | |||
* Fixed occlusion when `globe.show` is `false`. [#6374](https://github.com/AnalyticalGraphicsInc/cesium/pull/6374) | |||
<<<<<<< HEAD |
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 merge has a conflict.
Yeah, I dropped the ball on merging this. Besides the bad merge in CHANGES and the one small tweak, I'm fine with merging this. |
Thanks all. I am on vacation now back in July...
… On Jun 20, 2018, at 7:27 PM, Tom Fili ***@***.***> wrote:
Yeah, I dropped the ball on merging this. Besides the bad merge in CHANGES and the one small tweak, I'm fine with merging this.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
|
@tamarmot hop you had a good vacation! Let us know when this is ready for another look =) |
Hi. I've been using the updated code successfully - it works great thank you thank you. However, I don't think the GetFeatureInfo request has been updated - I don't see the time param in querystrings. |
I think I fixed this - used same approach as @tamarmot in WebMapServiceImageryProvider.js, changed/added following:
Look Ok? |
@gadew64 yes, that looks fine to me. Are you interested in opening a pull request to finish this up? |
I'd be delighted if someone else could finish up the integration, clearly I
no longer have time :)
…On Thu, Aug 23, 2018 at 8:57 AM Hannah ***@***.***> wrote:
@gadew64 <https://github.com/gadew64> yes, that looks fine to me. Are you
interested in opening a pull request to finish this up?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#6348 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AFgK8ChieSejZULj4g16RbzLeyiYcbOdks5uTqaxgaJpZM4Swmjr>
.
|
@tamarmot I've finished up the last changes for you. Thanks again and sorry for it taking so long. @gadew64 I put in the code for time dynamic pickFeature. Stepping through the code, it seems to work as intended but I don't have a server to test with. Could you give me one to use or can you test this branch as-is to make sure it works for you? |
Any idea if and when this PR might be merged? This feature is very important for us. Thus I would highly appreciate the merge. |
@heinerlamprecht Do you have a server that has time-dynamic feature picking to test it? Otherwise I can probably just merge it. |
@tfili No I haven't. I need this feature, because our WMS provides frequently updated data, and the viewport needs to refresh the display accordingly. At the moment, the map is only updated if the user pans or zooms enough. Feature picking is currently not implemented (and for this specific service not needed at all). |
In case it helps, here's a WMS server with a time dimension and time-dynamic GetFeatureInfo: And here it is working in TerriaJS (but using our own WMS-T support): |
Thanks again @tamarmot |
*/ | ||
clock : { | ||
get : function() { | ||
return this._timeDynamicImagery.clock; |
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 know this is already merged, but there's a bug here. If times
isn't passed in the constructor, this._timeDynamicImagery
is undefined so this (and all other such references in the getters/setters below) will throw. Once a WMSImageryProvider is initialized as "non-dynamic" it's impossible to make it dynamic, so any references to dynamic properties should return undefined.
Hi @kring @tfili @tamarmot , I may have found a deeper issue here, with the design of TimeDynamicImagery / TimeIntervalCollection. I hope I'm just using it wrong. I can open a separate issue if need be, but the short version is: I found this sample data in a related ticket, I think. I'm working on a simple parser for the Capabilities document, so that I can advertise layers to the user and automatically configure the supported time parameters. To that end, I'm looking at the On this server, the value of that tag is Is there another way to handle this? The 8601 Interval spec allows a single, simple string to specify an effectively unlimited number of intervals ( |
@thw0rted can you please open a new issue? It'll be easier to discuss everything there. A lot of the team is off for Thanksgiving this week, but we'll try to get back to you next week. Thanks! |
OK, no problem. I'll leave a trackback so it shows up here. Also, as an experiment, I'm designing a class that implements the TimeIntervalCollection interface but works the way I described (keeping only a start, stop, and period) to see if it works for my current needs. If it does, maybe I can clean it up to share. |
Implementing a fix for #2581 as I also needed this functionality to work with lunaserv.
Please review specifically line 211 in WebMapServiceImageryProvider.js
Also I wasn't sure if I had to do something else to support the pickFeatures in this case.
Happy for any feedback, thanks!
Tamar