Options for Raster Graphics in 100.x

902
4
01-09-2019 10:14 AM
DavidMillican
New Contributor II

In 10.2.7 our application accomplished some of our features by extending DynamicMapServiceLayer. It seems that all Layers and Overlays are sealed in 100.x so I'm trying to figure out how to do the same thing that we were doing. So we allow the user to selectively add their data to the map and there could be hundreds of these things to choose from and we dynamically generate the image in the user session as the underlying data can change. And the data is somewhat complex(fairly large matrices). These custom layers are caching the images for performance reasons. The user can toggle visibility of these images in real time once they have been loaded. But basically we extended DynamicMapServiceLayer and override DrawInScreenCoordinates so that we can use the DrawingContext to draw our custom images on the screen. We also override GetImageUriAsync and fake a service call while we are really generating the images locally in the application. I can't see a way to achieve the same level of flexibility given the 100.x framework and how every class seems to be sealed and not extensible.  

I read about GraphicsOverlays which seem to be limited to simple geometry which is great for some of my data but not the scenario that I presented above. I also read about RasterLayers but they seem pretty limited as well. You can create one with a file reference would be too slow for my use. RasterFunction seemed like a promising option but it is sealed as well. Would mocking an ImageRasterService work perhaps? Any other options that I'm not considering?

Thanks for any input that anyone may have.

Tags (2)
0 Kudos
4 Replies
dotMorten_esri
Esri Notable Contributor

Only the tiled layers support custom layer implementations, which could support a workflow like you have. I'm don't really understand how caching dynamic layers worked, as the requests being made are completely different based on the current extent and scale. Users rarely visit the exact same extent and size multiple times? Also I'm not aware what DrawingContext and DrawInScreenCoordinates APIs you were using? (I don't recall us exposing such a thing on the MapView)


Also be aware that Windows automatically caches web requests already as long as the URLs are identical and the server responds that the result is cacheable (it usually is). This cache even works across multiple apps, browser etc, as the shared webbrowser cache is used throughout.

0 Kudos
DavidMillican
New Contributor II

Thanks for the reply Morten!

Ok so I looked back at the solution here(developed by a 3rd party contractor) and there was an intermediate custom layer that provided the DrawingContext to the outermost concrete layers and it defined an abstract DrawInScreenCoordinates method. So please ignore those references. GetImageUriAsync() is what the intermediate layer is overriding from DynamicMapServiceLayer. The caching that I was referring to was done within the layers. It was caching the images that it would create so that it didn't have to create them each time the layer received a request for it. 

But I've pretty much given up on that pattern now as I'm pretty sure I can't reproduce it in 100.x. Now I'm trying to figure out how to accomplish displaying my raster graphics at all.  I tried saving the image being produced to disk and then just added a RasterLayer that referenced the image file to the map's OperationalLayers like the examples do but that didn't seem to work for me for whatever reason. We may not be able to proceed with the upgrade either way as there are just too many things that have fundamentally changed and we have a rather complex implementation in our product today. I know that support is supposed to sunset on 10.2.7 in the near future but it looks like we would have to completely rewrite our mapping feature to do so and lose some features in the process. 

Is the online guide and the API Reference all of the documentation available? Are there any more sample applications? In particular I'd like to see how other people are adding many different rasters at run time.

0 Kudos
dotMorten_esri
Esri Notable Contributor

It would be good to understand your scenario better and why all of this is really necessary, and see if there's a feature we're missing, or just a better way you could do it. Some of it sort of sound like you need to use the MosaicDataSet on a RasterLayer instead. I don't really get how caching on a dynamic layer could/should work as the requests are rarely identical and thus not cacheable (as opposed to tiled layers).

Having said that, it is possible to use the ArGISHttpClientHandler.HttpRequestBegin event to detect any webrequest we make and redirect it to a different URL resource, or completely replace the http handler being used. Just be careful with this one, as anything intensive in that event could significantly reduce performance.

0 Kudos
DavidMillican
New Contributor II

Thanks again Morten. The ArcGISHttpClientHandler may be another option. 

So really my fundamental requirement isn't as technically complex as the current solution was made to be. My user will have a collection of data and they will want to select many items from their collection for display on the map. The application would build an image based on the selection and draw it over the basemap in the correct location.  For some of that data its simple geometry which I'm having no problem accomplishing on the GraphicsOverlay. For other data we are creating bitmaps that have to be drawn on the screen for various reasons. In one case we have very large volumes of 3D data and we want to take one particular horizontal slice of that volume, create a bitmap, and display it on the map. For this one an example might be a high resolution map of all temp values in a state for instance. You'd want to overlay the entire state with a color matching the temp value at that particular pixel for the entire state(assuming you had such detailed measurements all over the state). In another case we are allowing some custom annotation where a point might be represented by one of several symbols depending on the status of that entity and then have user determined labels to the left, right, top, or bottom of the symbol based on fields selected by the user. There is another layer that did some custom annotation where the code is making use of raster graphics to accomplish the goal. I hope this helps explain a bit about what we're trying to do here. I don't think it's incredibly complicated but I am having a hard time converting the existing code to the new runtime. 

I was able to get a sample GeoTIFF and display it on our map just statically referencing it. So the raster feature there works. But when I try to take the MemoryStream that contained the bitmap image that we were generating before, copy it to a FileStream, and then later replace that GeoTIFF with the file on disk it doesn't show up. 

0 Kudos