Skip to content
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

Feature/70 add wcslayer #204

Merged
merged 42 commits into from
Aug 7, 2023
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
8d35418
initial razor page build
seahro Jul 18, 2023
dbbc0c2
build out interop file
seahro Jul 19, 2023
2b0522c
working on class
seahro Jul 19, 2023
dfa1c77
Merge branch 'develop' into feature/70_add_wcslayer
seahro Jul 21, 2023
5a47c3f
razor pg working
seahro Jul 21, 2023
db3c255
working
seahro Jul 21, 2023
3312ec2
update branch
seahro Jul 21, 2023
4766c02
working
seahro Jul 24, 2023
aac38d7
Merge branch 'develop' into feature/70_add_wcslayer
seahro Jul 24, 2023
a2956e7
raster stretch renderer added, multi dimensionaldefinition next
seahro Jul 24, 2023
54525e2
dimensiondefinition class in place working on methods
seahro Jul 24, 2023
4648a5a
dimensiondefinition added to builder and definitions
seahro Jul 24, 2023
87fddb5
add color ramp class working on definitions
seahro Jul 24, 2023
d3e154c
working
seahro Jul 25, 2023
1eba18c
rasterstretch converter in place and child component registration in …
seahro Jul 25, 2023
2812782
working on razor display
seahro Jul 25, 2023
b252340
initial render working color blend only black n white currently still…
seahro Jul 25, 2023
4a617db
multicolorramp and algorithmic color ramps in place working on wrappi…
seahro Jul 26, 2023
e57049f
dimensionaldefinition and renderer added to razor sample page
seahro Jul 26, 2023
8b7df91
layer properties set up for rendering on razor page
seahro Jul 26, 2023
23bf08d
adjusting rgb list to map color property in js/ts
seahro Jul 27, 2023
34bba50
refactoring color objects
seahro Jul 27, 2023
496554c
build without errors, markup kick back raster exception error. add wc…
seahro Jul 27, 2023
d7779bc
razor page working no color works correctly color loads but colors st…
seahro Jul 28, 2023
0090d1a
interop refactor working
seahro Jul 31, 2023
3826a2e
working
seahro Jul 31, 2023
27120e6
working wcs in jsinterop
seahro Jul 31, 2023
2ada0a3
major adjustments to jsbuilder, interop, and the classes. both layer…
seahro Aug 2, 2023
30241bf
refactor rasterstretchrenderer out of renderer
seahro Aug 2, 2023
44e6d7f
color ramps rendering correctly and cleanup complete
seahro Aug 2, 2023
2e00b1b
remove commented out code items
seahro Aug 2, 2023
08f4674
working on corrections
seahro Aug 2, 2023
2024863
corrected layer.cs to add wcs layer and added additional dimensional …
seahro Aug 3, 2023
8c8e89a
refactors complete and rendering correctly
seahro Aug 3, 2023
15ebcbf
corrections complete
seahro Aug 3, 2023
160b292
pr review 2 refactors and succesfully tested
seahro Aug 7, 2023
118a10f
merge from develop
TimPurdum Aug 7, 2023
03dd90e
starting corrections for warnings
seahro Aug 7, 2023
9391fa3
working on corrections
seahro Aug 7, 2023
23be778
warnings as errors "issues" corrected
seahro Aug 7, 2023
a197586
realigned branch with remote
seahro Aug 7, 2023
4825b16
Tested, cleanup
TimPurdum Aug 7, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 132 additions & 0 deletions samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/WCSLayers.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
@page "/wcslayers"
@using dymaptic.GeoBlazor.Core.Components.Renderers.ColorRamps;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move this to _Imports.razor


<h3>WCS Layers</h3>

<div class="links-div">
<a class="btn btn-secondary" target="_blank" href="https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-WCSLayer.html">ArcGIS API for JavaScript</a>
<a class="btn btn-primary" target="_blank" href="something">NOAA Sea Surface Temperature Charts</a>
</div>
<Label>Add the sample WCS Layer URL to see a visualization of global sea surface temperature data:</Label>
<InputText @bind-Value="_wcsLayerUrl"></InputText>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know that we really need this input field. I doubt anyone is going to test their own layers in our samples page.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed. I think for some samples it makes sense to have the input field, others really dont need it.

<button disabled="@(!_mapRendered)" @onclick="(()=>AddRemoveWCSLayer())">Add the WCS Layer with color ramp enabled</button>
<button disabled="@(!_mapRendered)" @onclick="(()=>_markup = !_markup)">Add new WCS Layer in Markup without colorizing</button>

<MapView @ref="_view" class="map-view" OnMapRendered="OnMapRendered" Scale="0">
<Map ArcGISDefaultBasemap="arcgis-light-gray">
@if (_markup)
{
<WCSLayer Url="https://sampleserver6.arcgisonline.com/arcgis/services/ScientificData/SeaTemperature/ImageServer/WCSServer?request=GetCapabilities&service=WCS"></WCSLayer>
}


</Map>
</MapView>

@code {



private void OnMapRendered() => _mapRendered = true;

public async Task AddRemoveWCSLayer()
{
WCSLayer wcsSampleLayer = new()
{
Url = _wcsLayerUrl,
Renderer = CreateRenderer(),
MultidimensionalDefinition = CreateDimensionalDefinition(),
Opacity = 0.5
};

if (!_view.Map.Layers.Any())
{
await _view.AddLayer(wcsSampleLayer);
}
else
{
_view.Map.Layers.Clear();
}
_view.Refresh();

}

public DimensionalDefinition CreateDimensionalDefinition()
{
// initializes the dimensional filter for the raster display
DimensionalDefinition? multidimensionalDefinition = new DimensionalDefinition()
{
VariableName = "water_temp", // water temp at sea level
DimensionName = "StdZ",
Values = new List<int>(0)
};
return multidimensionalDefinition;
}


public RasterStretchRenderer CreateRenderer()
{
// This initializes the renderer as a standard deviation type
var displayRenderer = new RasterStretchRenderer
{
StretchType = StretchType.StandardDeviation,
Statistics = new List<int>{-3, 37, 1, 1}
};

var toFromColor1 = new AlgorithmicColorRamp
{
FromColor = new MapColor( 0, 0, 255 ),
ToColor = new MapColor ( 0, 255, 255 )
};
//multipartColorRamp.ColorRamps?.Append(toFromColor1);
var toFromColor2 = new AlgorithmicColorRamp
{
FromColor = new MapColor ( 0, 255, 255 ),
ToColor = new MapColor ( 255, 255, 0 )
};
//multipartColorRamp.ColorRamps?.Append(toFromColor2);
var toFromColor3 = new AlgorithmicColorRamp
{
FromColor = new MapColor ( 255, 255, 0 ),
ToColor = new MapColor ( 255, 0, 0 )
};
//multipartColorRamp.ColorRamps?.Append(toFromColor3);

// Builds the multipart color ramp
MultipartColorRamp? multipartColorRamp = new()
{
AlgorithmicColorRamps = new AlgorithmicColorRamp[]
{
toFromColor1,
toFromColor2,
toFromColor3
}
};

// initializes the colorRamp for the renderer, the color ramp contains the type and specific colorizing details from the MultipartColorRamp collection for the renderer
var colorRamp = new ColorRamp
{
Type = "multipart",
MultipartColorRamps = multipartColorRamp

};
//finalizes the renderer with all the color ramp values
displayRenderer.ColorRamps = colorRamp;
return displayRenderer;
}

private AlgorithmicColorRamp[]? _colorRampsList;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not used. I'll stop harping, but please check for unused variables when cleaning up code.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, and no worries.

private MultipartColorRamp? multipartColorRamp;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not used.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

corrected




private MapView _view;
private bool _markup = false;
private bool _visible = false;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not used

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

corrected

private bool _mapRendered = false;


//private string _wcsLayerUrl = "https://sampleserver6.arcgisonline.com/arcgis/rest/services/WCS/SeaTemperature/ImageServer";
private string _wcsLayerUrl2 = "https://sampleserver6.arcgisonline.com/arcgis/services/ScientificData/SeaTemperature/ImageServer/WCSServer";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This variable is never used and can be deleted.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

an oversight while I was cleaning up the file...corrected.

private string _wcsLayerUrl = "https://sampleserver6.arcgisonline.com/arcgis/services/ScientificData/SeaTemperature/ImageServer/WCSServer?request=GetCapabilities&service=WCS";
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
new("kmllayers", "KML Layers", "oi-excerpt"),
new("georss-layer", "GeoRSS Layer", "oi-rss"),
new("osm-layer", "OpenStreetMaps Layer", "oi-envelope-open"),
new("wcslayers", "WCS Layers", "oi-project"),
new("web-map", "Web Map", "oi-browser"),
new("web-scene", "Web Scene", "oi-box"),
new("events", "Events", "oi-flash"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,20 @@
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<UserSecretsId>0d722028-1f33-4f5f-829c-e1333fd73878</UserSecretsId>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

user secrets do not work AFAIK in wasm, hence why these were not here before.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually, they do work in both server and wasm.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

both references are now removed from csproj files

</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.5"/>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.5" PrivateAssets="all"/>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.5" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.5" PrivateAssets="all" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\dymaptic.GeoBlazor.Core.Sample.Shared\dymaptic.GeoBlazor.Core.Sample.Shared.csproj"/>
<ProjectReference Include="..\dymaptic.GeoBlazor.Core.Sample.Shared\dymaptic.GeoBlazor.Core.Sample.Shared.csproj" />
</ItemGroup>

<ItemGroup>
<Content Remove="staticwebapp.config.json"/>
<Content Remove="staticwebapp.config.json" />
</ItemGroup>

</Project>
4 changes: 3 additions & 1 deletion src/dymaptic.GeoBlazor.Core/Components/Layers/Layer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ internal override void ValidateRequiredChildren()
/// </param>
internal virtual Task UpdateFromJavaScript(Layer renderedLayer)
{
if (renderedLayer.FullExtent is not null)
if (renderedLayer?.FullExtent is not null)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this ? should not be necessary based on the non-null nature of the method parameter. However, if null is sneaking in here from JS, we should back up and check that before this method is called.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was corrected by adding "wcs" as a layer type to the layerConverter in layer.cs

{
FullExtent = renderedLayer.FullExtent;
}
Expand Down Expand Up @@ -276,6 +276,8 @@ internal class LayerConverter : JsonConverter<Layer>
return JsonSerializer.Deserialize<CSVLayer>(ref cloneReader, newOptions);
case "kml":
return JsonSerializer.Deserialize<KMLLayer>(ref cloneReader, newOptions);
//case "wcs":
// return JsonSerializer.Deserialize<WCSLayer>(ref cloneReader, newOptions);
}
}

Expand Down
132 changes: 132 additions & 0 deletions src/dymaptic.GeoBlazor.Core/Components/Layers/WCSLayer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
using dymaptic.GeoBlazor.Core.Components.Renderers;
using dymaptic.GeoBlazor.Core.Exceptions;
using Microsoft.AspNetCore.Components;
using System.Text.Json.Serialization;


namespace dymaptic.GeoBlazor.Core.Components.Layers;

/// <summary>
/// WCS presents raster data from a OGC Web Coverage Service. Raster data are projected and rendered on the client-side.
/// It supports versions 1.0.0, 1.1.0, 1.1.1, 1.1.2 and 2.0.1. For version 2.0.1, it supports servers that support
/// GEOTIFF coverage and implements the following extensions: Scaling, Interpolation, Range Subsetting, CRS, and KVP/Get.
/// <a target="_blank" href="https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-WCSLayer.html">
/// ArcGIS
/// JS API
/// </a>
/// </summary>
public class WCSLayer : Layer
{
/// <inheritdoc />
[JsonPropertyName("type")]
public override string LayerType => "wcs";

/// <summary>
/// Constructor for use as a razor component
/// </summary>
public WCSLayer()
{
}
/// <summary>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there should be a space before these comments, and not one after them, for consistency.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected across all the class files.

/// Constructor for use in code
/// </summary>
/// <param name="url">
/// The url for the WCS Layer source data.
/// </param>

public WCSLayer(string? url = null, PortalItem? portalItem = null)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add List<DimensionalDefinition> multidimensionalDefinition, RasterStretchRenderer renderer, double opacity, string title to this constructor. Use the constructor in your WCSLayers.razor samples page instead of setting these properties directly. In fact, I think we should make these private set; properties (only for the ones that are not also [Parameter]), because if you set them after the layer is rendered, it will break.

{
if (url is null && portalItem is null)
{
throw new MissingRequiredOptionsChildElementException(nameof(WCSLayer),
new[] {nameof(Url), nameof(PortalItem)});
}
Url = url;
PortalItem = portalItem;
}

[Parameter]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[RequiredProperty(nameof(PortalItem))]
public string? Url { get; set; }

/// <summary>
/// The portal item for the KML Layer source data.
/// </summary>
[RequiredProperty(nameof(Url))]
public PortalItem? PortalItem { get; set; }
/// <summary>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

always have a space between properties and/or xml comments

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

corrected

/// The multidimensional definitions associated with the layer.
/// </summary>
public DimensionalDefinition? MultidimensionalDefinition { get; set; }
/// <summary>
/// The renderer assigned to the layer.
/// </summary>
public RasterStretchRenderer Renderer { get; set; }

/// <inheritdoc />
public override async Task RegisterChildComponent(MapComponent child)
{
switch (child)
{
case PortalItem portalItem:
if (!portalItem.Equals(PortalItem))
{
PortalItem = portalItem;
LayerChanged = true;
}
break;
case DimensionalDefinition dimensionalDefinition:
if (!dimensionalDefinition.Equals(MultidimensionalDefinition))
{
MultidimensionalDefinition = dimensionalDefinition;
LayerChanged = true;
}
break;
case RasterStretchRenderer rasterStretchRenderer:
if (!rasterStretchRenderer.Equals(Renderer))
{
Renderer = rasterStretchRenderer;
LayerChanged = true;
}
break;
default:
await base.RegisterChildComponent(child);

break;
}
}
/// <inheritdoc />
public override async Task UnregisterChildComponent(MapComponent child)
{
switch (child)
{
case PortalItem _:
PortalItem = null;
LayerChanged = true;
break;
case DimensionalDefinition _:
MultidimensionalDefinition = null;
LayerChanged = true;
break;
case RasterStretchRenderer _:
Renderer = null;
LayerChanged = true;
break;
default:
await base.UnregisterChildComponent(child);

break;
}
}
/// <inheritdoc />
internal override void ValidateRequiredChildren()
{
PortalItem?.ValidateRequiredChildren();
MultidimensionalDefinition?.ValidateRequiredChildren();
Renderer?.ValidateRequiredChildren();
base.ValidateRequiredChildren();
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using dymaptic.GeoBlazor.Core.Extensions;
using dymaptic.GeoBlazor.Core.Objects;
using dymaptic.GeoBlazor.Core.Serialization;
using Microsoft.AspNetCore.Components;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;

namespace dymaptic.GeoBlazor.Core.Components.Renderers.ColorRamps;

/// <summary>
/// Creates a color ramp for use in a raster renderer. The algorithmic color ramp is defined by specifying two colors and the
/// algorithm used to traverse the intervening color spaces.
/// <a target="_blank" href="https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-AlgorithmicColorRamp.html">
/// ArcGIS
/// JS API
/// </a>
/// </summary>
public class AlgorithmicColorRamp : ColorRamp
{
public AlgorithmicColorRamp() { }
/// <summary>
/// A string value representing the color ramp type.
/// </summary>
//[JsonPropertyName("type")]
//public string? Type { get; set; }

/// <summary>
/// The algorithm used to generate the colors between the fromColor and toColor.
/// </summary>

public Algorithm Algorithm { get; set; }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To support inheriting from MapComponent

  1. Make all public properties here [Parameter]
  2. Add two constructors, the empty one, and one that sets all the properties. Use that one for C# construction.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parameters and constructors are now included

/// <summary>
/// The first color in the color ramp.
/// </summary>
public MapColor? FromColor { get; set; }
/// <summary>
/// The last color in the color ramp.
/// </summary>
public MapColor? ToColor { get; set; }
}
/// <summary>
/// The algorithm used to generate the colors between the fromColor and toColor. Each algorithm uses different methods for generating the intervening colors.
/// </summary>
[JsonConverter(typeof(EnumToKebabCaseStringConverter<Algorithm>))]
public enum Algorithm
{
CieLab,
LabLch,
Hsv
}

//internal class AlgorithmConverter : JsonConverter<Algorithm>
//{
// public override Algorithm Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
// {
// throw new NotImplementedException();
// }

// public override void Write(Utf8JsonWriter writer, Algorithm value, JsonSerializerOptions options)
// {
// string? stringVal = Enum.GetName(typeof(Algorithm), value);
// string resultString = stringVal!.ToKebabCase();
// writer.WriteRawValue($"\"{resultString}\"");
// }
//}
Loading