I was wondering if anyone had any experience or examples rendering raster functions as a raster layer.
Every time I pass a raster function with the mask_function the whole raster isn't shown.
I use a function of the following
{ "raster_function":{"type":"Mask_function"}, "raster_function_arguments": { "nodata_values":{"double_array":["0.0","1.0","2.0","3.0","4.0","5.0","6.0","7.0","8.0","9.0","10.0","11.0","12.0","13.0","14.0","15.0","16.0","17.0","18.0","19.0","20.0","21.0","22.0","23.0","24.0","25.0","26.0","27.0","28.0","29.0","30.0","31.0","32.0","33.0","34.0","35.0","36.0","37.0","38.0","39.0","40.0","41.0","42.0","43.0","44.0","45.0","46.0","47.0","48.0","49.0","50.0"],"type":"Raster_function_variable"}, "nodata_interpretation":{"nodata_interpretation":"all","type":"Raster_function_variable"}, "raster":{"name":"raster","is_raster":true,"type":"Raster_function_variable"}, "type":"Raster_function_arguments" },"type":"Raster_function_template"}
I have also tried using instead of string values just regular values in the form of [0.0, 1.0, 2.0, ...]
My code looks like the following
class func loadOnlineRasterImage(function: String, complete: @escaping (AGSRasterLayer) ->()) {
let x = URL.init(string: "https://utility.arcgis.com/usrsvcs/servers/11e0cb598d77463cbe3b90d5e53f37d6/rest/services/WorldEleva...")
let imageServiceRaster = AGSImageServiceRaster.init(url: x!)
let serviceInfo = imageServiceRaster.serviceInfo
let renderingRule = AGSRenderingRule(renderingRuleJSON: [
"rasterFunction": function,
"format":"jpg"
])
imageServiceRaster.renderingRule = renderingRule
imageServiceRaster.load { (error) in
if let error = error {
print(error)
return
}
let rasterFunction = self.setRasterfunction(raster: imageServiceRaster)
let finalRaster = AGSRaster.init(rasterFunction: rasterFunction)
print("nardo")
print(error)
let rasterLayer = AGSRasterLayer(raster: finalRaster)
complete(rasterLayer)
}
}
class func setRasterfunction(raster: AGSImageServiceRaster) -> AGSRasterFunction{
var x: [Double] = []
for index in 0...50 {
x.append(Double(index))
}
var xx = x.map({abc -> String in "\(abc)"}).joined(separator: ",")
var content = "{ \"raster_function\":{\"type\":\"Mask_function\"}, \"raster_function_arguments\": { \"nodata_values\":{\"double_array\":[{{replace}}],\"type\":\"Raster_function_variable\"}, \"nodata_interpretation\":{\"nodata_interpretation\":\"all\",\"type\":\"Raster_function_variable\"}, \"raster\":{\"name\":\"raster\",\"is_raster\":true,\"type\":\"Raster_function_variable\"}, \"type\":\"Raster_function_arguments\" },\"type\":\"Raster_function_template\"}".replacingOccurrences(of: "{{replace}}", with: xx )
print(content)
FileUtil.writefile(name: "hi.json", content: content )
let docDir = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
let mapUrl = docDir.appendingPathComponent("hi.json")
let rasterFunction = AGSRasterFunction(fileURL: mapUrl)
// initialize the arguments of the raster function
let rasterFunctionArguments = rasterFunction.arguments
print(rasterFunctionArguments.debugDescription)
let rasterNames = rasterFunctionArguments!.rasterNames
// assuming rasterNames has 2 entries, set the 2 rasters
rasterFunctionArguments!.setRaster(raster, withName: rasterNames[0])
return rasterFunction
}
The first function uses the second function to create a raster function and load it into a new agsraster which is then placed in a layer. I know that the file is properly being written as I've checked it. I'm not sure what I'm doing wrong : \
Does anyone have any working examples or advice?
Solved! Go to Solution.
In the loadOnlineRasterImage function, imageServiceRaster is going out of scope. The call to load is asynchronous; when the completion block is executed and tries to use imageServiceRaster, it has gone out of scope. With that fixed, your code is working for me. I made two other minor changes. I wasn't sure why you were setting the renderingRule so I removed that code. And instead of writing the JSON to disk and reading it back, I changed it to use the fromJSON method, like this:
let rasterFunction = AGSRasterFunction.fromJSON(content, error: nil) as? AGSRasterFunction
I hope that helps.
Phil
So I managed to get the raster function working with a saved raster file. However when I try to apply a raster function to a AGSImageServiceRaster the raster never gets rendered. When checking the web requests that go out, there are none that go out to the export service that are used to populate the raster : \
Has anyone ever used an AGSImageServiceRaster with a raster function?
In the loadOnlineRasterImage function, imageServiceRaster is going out of scope. The call to load is asynchronous; when the completion block is executed and tries to use imageServiceRaster, it has gone out of scope. With that fixed, your code is working for me. I made two other minor changes. I wasn't sure why you were setting the renderingRule so I removed that code. And instead of writing the JSON to disk and reading it back, I changed it to use the fromJSON method, like this:
let rasterFunction = AGSRasterFunction.fromJSON(content, error: nil) as? AGSRasterFunction
I hope that helps.
Phil
Hi,
Confirming this works in the following example (C# WPF):
async Task AddRasterAndSetBackgroundColorValue()
{
try
{
// Create a raster dataset from a local file raster.
Raster raster = new Raster(@"..\FileRaster.tif");
// Await the Load to catch any errors.
await raster.LoadAsync();
// Create a raster function from the JSON string using the static/Shared method called: RasterFunction.FromJson(json as String)
RasterFunction rasterFunction = RasterFunction.FromJson(jsonFunction);
// Get the raster function arguments
RasterFunctionArguments rasterFunctionArguments = rasterFunction.Arguments;
// Get the list of raster names from the raster function arguments.
IReadOnlyList<string> rasterNames = rasterFunctionArguments.GetRasterNames();
// Set the local file raster as a raster name argument.
rasterFunctionArguments.SetRaster(rasterNames[0], raster);
// Create a new raster based on the raster function.
Raster rasterWithFunction = new Raster(rasterFunction);
// Create a new raster layer from the raster with function applied.
RasterLayer rasterLayer = new RasterLayer(rasterWithFunction);
// Add RasterLayer with function to Map OperationalLayers collection.
Map.OperationalLayers.Add(rasterLayer);
}
catch (Exception ex)
{
// TODO : Handle Errors
}
}
string jsonFunction =
@"{
""raster_function"":{""type"":""Mask_function""},
""raster_function_arguments"":
{
""nodata_values"":{""double_array"":[0],""type"":""Raster_function_variable""},
""nodata_interpretation"":{""nodata_interpretation"":""all"",""type"":""Raster_function_variable""},
""raster"":{""name"":""raster"",""is_raster"":true,""type"":""Raster_function_variable""},
""type"":""Raster_function_arguments""
},
""type"":""Raster_function_template""
}";
Mike