-
Notifications
You must be signed in to change notification settings - Fork 121
ProSnippets StreamLayers
uma2526 edited this page Nov 10, 2021
·
2 revisions
Language: C#
Subject: StreamLayers
Contributor: ArcGIS Pro SDK Team <[email protected]>
Organization: esri, http://www.esri.com
Date: 1/10/2020
ArcGIS Pro: 2.4
Visual Studio: 2017, 2019
.NET Target Framework: 4.6.1
//Must be on the QueuedTask
var url = "https://geoeventsample1.esri.com:6443/arcgis/rest/services/AirportTraffics/StreamServer";
var createParam = new FeatureLayerCreationParams(new Uri(url))
{
IsVisible = false //turned off by default
};
var streamLayer = LayerFactory.Instance.CreateLayer<StreamLayer>(createParam, map);
//or use "original" create layer (will be visible by default)
Uri uri = new Uri(url);
streamLayer = LayerFactory.Instance.CreateLayer(uri, map) as StreamLayer;
streamLayer.SetVisibility(false);//turn off
//Must be on the QueuedTask
var url = "https://geoeventsample1.esri.com:6443/arcgis/rest/services/AirportTraffics/StreamServer";
var lyrCreateParam = new FeatureLayerCreationParams(new Uri(url))
{
IsVisible = true,
DefinitionFilter = new CIMDefinitionFilter()
{
DefinitionExpression = "RWY = '29L'",
Name = "Runway"
}
};
var streamLayer = LayerFactory.Instance.CreateLayer<StreamLayer>(lyrCreateParam, map);
var url = @"https://geoeventsample1.esri.com:6443/arcgis/rest/services/LABus/StreamServer";
var uri = new Uri(url, UriKind.Absolute);
//Must be on QueuedTask!
var createParams = new FeatureLayerCreationParams(uri)
{
RendererDefinition = new SimpleRendererDefinition()
{
SymbolTemplate = SymbolFactory.Instance.ConstructPointSymbol(
ColorFactory.Instance.BlueRGB,
12,
SimpleMarkerStyle.Pushpin).MakeSymbolReference()
}
};
var streamLayer = LayerFactory.Instance.CreateLayer<StreamLayer>(
createParams, map);
var url = @"https://geoeventsample1.esri.com:6443/arcgis/rest/services/AirportTraffics/StreamServer";
var uri = new Uri(url, UriKind.Absolute);
//Must be on QueuedTask!
var createParams = new FeatureLayerCreationParams(uri)
{
IsVisible = false
};
var streamLayer = LayerFactory.Instance.CreateLayer<StreamLayer>(
createParams, map);
//Define the unique values by hand
var uvr = new CIMUniqueValueRenderer()
{
Fields = new string[] { "ACTYPE" },
UseDefaultSymbol = true,
DefaultLabel = "Others",
DefaultSymbol = SymbolFactory.Instance.ConstructPointSymbol(
CIMColor.CreateRGBColor(185, 185, 185), 8, SimpleMarkerStyle.Hexagon).MakeSymbolReference()
};
var classes = new List<CIMUniqueValueClass>();
//add in classes - one for ACTYPE of 727, one for DC 9
classes.Add(
new CIMUniqueValueClass() {
Values = new CIMUniqueValue[] {
new CIMUniqueValue() { FieldValues = new string[] { "B727" } } },
Visible = true,
Label = "Boeing 727",
Symbol = SymbolFactory.Instance.ConstructPointSymbol(
ColorFactory.Instance.RedRGB, 10, SimpleMarkerStyle.Hexagon).MakeSymbolReference()
});
classes.Add(
new CIMUniqueValueClass()
{
Values = new CIMUniqueValue[] {
new CIMUniqueValue() { FieldValues = new string[] { "DC9" } } },
Visible = true,
Label = "DC 9",
Symbol = SymbolFactory.Instance.ConstructPointSymbol(
ColorFactory.Instance.GreenRGB, 10, SimpleMarkerStyle.Hexagon).MakeSymbolReference()
});
//add the classes to a group
var groups = new List<CIMUniqueValueGroup>()
{
new CIMUniqueValueGroup() {
Classes = classes.ToArray()
}
};
//add the groups to the renderer
uvr.Groups = groups.ToArray();
//Apply the renderer (for current observations)
streamLayer.SetRenderer(uvr);
streamLayer.SetVisibility(true);//turn on the layer
var trackAwareLayers = MapView.Active.Map.GetLayersAsFlattenedList()
.OfType<StreamLayer>().Where(sl => sl.IsTrackAware)?.ToList();
//spatial or non-spatial?
if (streamLayer.TrackType == TrackType.AttributeOnly)
{
//this is a non-spatial stream layer
}
else
{
//this must be a spatial stream layer
}
if (!streamLayer.IsStreamingConnectionOpen)
//Must be on QueuedTask!
streamLayer.StartStreaming();
//Must be on QueuedTask!
//Start...
streamLayer.StartStreaming();
//Stop...
streamLayer.StopStreaming();
//Must be on QueuedTask!
//Must be called on the feature class
using(var rfc = streamLayer.GetFeatureClass())
rfc.Truncate();
if (streamLayer.IsTrackAware)
{
var trackField = streamLayer.TrackIdFieldName;
//TODO use the field name
}
var trackType = streamLayer.TrackType;
switch(trackType)
{
//TODO deal with tracktype
case TrackType.None:
case TrackType.AttributeOnly:
case TrackType.Spatial:
break;
}
//Must be on QueuedTask
//Set Expiration Method and Max Expiration Count
if (streamLayer.GetExpirationMethod() != FeatureExpirationMethod.MaximumFeatureCount)
streamLayer.SetExpirationMethod(FeatureExpirationMethod.MaximumFeatureCount);
streamLayer.SetExpirationMaxCount(15);
//FYI
if (streamLayer.IsTrackAware)
{
//MaxCount is per track! otherwise for the entire layer
}
//Must be on QueuedTask
//Set Expiration Method and Max Expiration Age
if (streamLayer.GetExpirationMethod() != FeatureExpirationMethod.MaximumFeatureAge)
streamLayer.SetExpirationMethod(FeatureExpirationMethod.MaximumFeatureAge);
//set to 12 hours (max is 24 hours)
streamLayer.SetExpirationMaxAge(new TimeSpan(12,0,0));
//FYI
if (streamLayer.IsTrackAware)
{
//MaxAge is per track! otherwise for the entire layer
}
//The layer must be track aware and spatial
if (streamLayer.TrackType != TrackType.Spatial)
return;
//Must be on QueuedTask
//get the CIM Definition
var def = streamLayer.GetDefinition() as CIMFeatureLayer;
//set the number of previous observations,
def.PreviousObservationsCount = (int)streamLayer.GetExpirationMaxCount() - 1;
//set show previous observations and track lines to true
def.ShowPreviousObservations = true;
def.ShowTracks = true;
//commit the changes
streamLayer.SetDefinition(def);
var uvrDef = new UniqueValueRendererDefinition()
{
ValueFields = new string[] { "ACTYPE" },
SymbolTemplate = SymbolFactory.Instance.ConstructPointSymbol(
ColorFactory.Instance.RedRGB, 10, SimpleMarkerStyle.Hexagon)
.MakeSymbolReference(),
ValuesLimit = 5
};
//Note: CreateRenderer can only create value classes based on
//the current events it has received
streamLayer.SetRenderer(streamLayer.CreateRenderer(uvrDef));
//Define the classes by hand to avoid using CreateRenderer(...)
CIMUniqueValueClass uvcB727 = new CIMUniqueValueClass()
{
Values = new CIMUniqueValue[] { new CIMUniqueValue() { FieldValues = new string[] { "B727" } } },
Visible = true,
Label = "Boeing 727",
Symbol = SymbolFactory.Instance.ConstructPointSymbol(CIMColor.CreateRGBColor(255, 0, 0), 8, SimpleMarkerStyle.Hexagon).MakeSymbolReference()
};
CIMUniqueValueClass uvcD9 = new CIMUniqueValueClass()
{
Values = new CIMUniqueValue[] { new CIMUniqueValue() { FieldValues = new string[] { "DC9" } } },
Visible = true,
Label = "DC 9",
Symbol = SymbolFactory.Instance.ConstructPointSymbol(CIMColor.CreateRGBColor(0, 255, 0), 8, SimpleMarkerStyle.Hexagon).MakeSymbolReference()
};
//Assign the classes to a group
CIMUniqueValueGroup uvGrp = new CIMUniqueValueGroup()
{
Classes = new CIMUniqueValueClass[] { uvcB727, uvcD9 }
};
//assign the group to the renderer
var UVrndr = new CIMUniqueValueRenderer()
{
Fields = new string[] { "ACTYPE" },
Groups = new CIMUniqueValueGroup[] { uvGrp },
UseDefaultSymbol = true,
DefaultLabel = "Others",
DefaultSymbol = SymbolFactory.Instance.ConstructPointSymbol(
CIMColor.CreateRGBColor(185, 185, 185), 8, SimpleMarkerStyle.Hexagon).MakeSymbolReference()
};
//set the renderer. Depending on the current events recieved, the
//layer may or may not have events for each of the specified
//unique value classes
streamLayer.SetRenderer(UVrndr);
//The layer must be track aware and spatial
if (streamLayer.TrackType != TrackType.Spatial)
return;
//Must be on QueuedTask!
//Define unique value classes same as we do for current observations
//or use "CreateRenderer(...)" to assign them automatically
CIMUniqueValueClass uvcB727Prev = new CIMUniqueValueClass()
{
Values = new CIMUniqueValue[] { new CIMUniqueValue() {
FieldValues = new string[] { "B727" } } },
Visible = true,
Label = "Boeing 727",
Symbol = SymbolFactory.Instance.ConstructPointSymbol(
CIMColor.CreateRGBColor(255, 0, 0), 4, SimpleMarkerStyle.Hexagon)
.MakeSymbolReference()
};
CIMUniqueValueClass uvcD9Prev = new CIMUniqueValueClass()
{
Values = new CIMUniqueValue[] { new CIMUniqueValue() {
FieldValues = new string[] { "DC9" } } },
Visible = true,
Label = "DC 9",
Symbol = SymbolFactory.Instance.ConstructPointSymbol(
CIMColor.CreateRGBColor(0, 255, 0), 4, SimpleMarkerStyle.Hexagon)
.MakeSymbolReference()
};
CIMUniqueValueGroup uvGrpPrev = new CIMUniqueValueGroup()
{
Classes = new CIMUniqueValueClass[] { uvcB727Prev, uvcD9Prev }
};
var UVrndrPrev = new CIMUniqueValueRenderer()
{
Fields = new string[] { "ACTYPE" },
Groups = new CIMUniqueValueGroup[] { uvGrpPrev },
UseDefaultSymbol = true,
DefaultLabel = "Others",
DefaultSymbol = SymbolFactory.Instance.ConstructPointSymbol(
CIMColor.CreateRGBColor(185, 185, 185), 4, SimpleMarkerStyle.Hexagon)
.MakeSymbolReference()
};
//The layer must be track aware and spatial
if (streamLayer.TrackType != TrackType.Spatial)
return;
//Must be on QueuedTask!
//Note: only a simple renderer with solid line symbol is supported for track
//line renderer
var trackRenderer = new SimpleRendererDefinition()
{
SymbolTemplate = SymbolFactory.Instance.ConstructLineSymbol(
ColorFactory.Instance.BlueRGB, 2, SimpleLineStyle.Solid)
.MakeSymbolReference()
};
streamLayer.SetRenderer(
streamLayer.CreateRenderer(trackRenderer),
FeatureRendererTarget.TrackLines);
//The layer must be track aware and spatial for these settings
//to have an effect
if (streamLayer.TrackType != TrackType.Spatial)
return;
//Must be on QueuedTask
if (!streamLayer.AreTrackLinesVisible)
streamLayer.SetTrackLinesVisibility(true);
if (!streamLayer.ArePreviousObservationsVisible)
streamLayer.SetPreviousObservationsVisibility(true);
//The layer must be track aware and spatial for these settings
//to have an effect
if (streamLayer.TrackType != TrackType.Spatial)
return;
//Must be on QueuedTask
//Note: Setting PreviousObservationsCount larger than the
//"SetExpirationMaxCount()" has no effect
streamLayer.SetPreviousObservationsCount(6);
if (!streamLayer.AreTrackLinesVisible)
streamLayer.SetTrackLinesVisibility(true);
if (!streamLayer.ArePreviousObservationsVisible)
streamLayer.SetPreviousObservationsVisibility(true);
//Must be on QueuedTask!
var renderer = streamLayer.GetRenderer();
//The layer must be track aware and spatial
if (streamLayer.TrackType != TrackType.Spatial)
return;
//Must be on QueuedTask!
var prev_renderer = streamLayer.GetRenderer(
FeatureRendererTarget.PreviousObservations);
//The layer must be track aware and spatial
if (streamLayer.TrackType != TrackType.Spatial)
return;
//Must be on QueuedTask!
var track_renderer = streamLayer.GetRenderer(
FeatureRendererTarget.TrackLines);
await QueuedTask.Run(async () =>
{
//query filter can be null to search and retrieve all rows
//true means recycling cursor
using (var rc = streamLayer.SearchAndSubscribe(qfilter, true))
{
//waiting for new features to be streamed
//default is no cancellation
while (await rc.WaitForRowsAsync())
{
while (rc.MoveNext())
{
//determine the origin of the row event
switch (rc.Current.GetRowSource())
{
case RealtimeRowSource.PreExisting:
//pre-existing row at the time of subscribe
continue;
case RealtimeRowSource.EventInsert:
//row was inserted after subscribe
continue;
case RealtimeRowSource.EventDelete:
//row was deleted after subscribe
continue;
}
}
}
}//row cursor is disposed. row cursor is unsubscribed
//....or....
//Use the feature class instead of the layer
using(var rfc = streamLayer.GetFeatureClass())
{
//non-recycling cursor - 2nd param "false"
using(var rc = rfc.SearchAndSubscribe(qfilter, false))
{
//waiting for new features to be streamed
//default is no cancellation
while (await rc.WaitForRowsAsync())
{
//etc
}
}
}
});
await QueuedTask.Run(async () =>
{
//Recycling cursor - 2nd param "true"
//or streamLayer.Subscribe(qfilter, true) to just subscribe
using (var rc = streamLayer.SearchAndSubscribe(qfilter, true))
{
//auto-cancel after 20 seconds
var cancel = new CancellationTokenSource(new TimeSpan(0, 0, 20));
//catch TaskCanceledException
try
{
while (await rc.WaitForRowsAsync(cancel.Token))
{
//check for row events
while (rc.MoveNext())
{
//etc
}
}
}
catch (TaskCanceledException tce)
{
//Handle cancellation as needed
}
cancel.Dispose();
}
});
//somewhere in our code we create a CancellationTokenSource
var cancel = new CancellationTokenSource();
//...
//call cancel on the CancellationTokenSource anywhere in
//the add-in, assuming the CancellationTokenSource is in scope
if (SomeConditionForCancel)
cancel.Cancel();//<-- will cancel the token
//Within QueuedTask we are subscribed! streamLayer.Subscribe() or SearchAndSubscribe()
try
{
//TaskCanceledException will be thrown when the token is cancelled
while (await rc.WaitForRowsAsync(cancel.Token))
{
//check for row events
while (rc.MoveNext())
{
//etc
}
}
}
catch (TaskCanceledException tce)
{
//Handle cancellation as needed
}
cancel.Dispose();
var url = "https://geoeventsample1.esri.com:6443/arcgis/rest/services/AirportTraffics/StreamServer";
await QueuedTask.Run(() =>
{
var realtimeServiceConProp = new RealtimeServiceConnectionProperties(
new Uri(url),
RealtimeDatastoreType.StreamService
);
using (var realtimeDatastore = new RealtimeDatastore(realtimeServiceConProp))
{
//A Realtime data store only contains **one** Realtime feature class (or table)
var name = realtimeDatastore.GetTableNames().First();
using (var realtimeFeatureClass = realtimeDatastore.OpenTable(name) as RealtimeFeatureClass)
{
//feature class, by default, is not streaming (opposite of the stream layer)
realtimeFeatureClass.StartStreaming();
//TODO use the feature class
//...
}
}
});
using (var rfc = streamLayer.GetFeatureClass())
using (var rfc_def = rfc.GetDefinition())
{
if (rfc_def.HasTrackIDField())
{
//Track aware
}
}
//Must be on QueuedTask
using (var rfc = streamLayer.GetFeatureClass())
using (var rfc_def = rfc.GetDefinition())
{
if (rfc_def.HasTrackIDField())
{
var fld_name = rfc_def.GetTrackIDField();
}
}
//Note: with feature class we can also use a System Task to subscribe and
//process rows
await QueuedTask.Run(async () =>
{
// or var rfc = realtimeDatastore.OpenTable(name) as RealtimeFeatureClass
using (var rfc = streamLayer.GetFeatureClass())
{
//non-recycling cursor - 2nd param "false"
//subscribe, pre-existing rows are not searched
using (var rc = rfc.Subscribe(qfilter, false))
{
SpatialQueryFilter spatialFilter = new SpatialQueryFilter();
//waiting for new features to be streamed
//default is no cancellation
while (await rc.WaitForRowsAsync())
{
while(rc.MoveNext())
{
switch (rc.Current.GetRowSource())
{
case RealtimeRowSource.EventInsert:
//getting geometry from new events as they arrive
Polygon poly = ((RealtimeFeature)rc.Current).GetShape() as Polygon;
//using the geometry to select features from another feature layer
spatialFilter.FilterGeometry = poly;//project poly if needed...
countyFeatureLayer.Select(spatialFilter);
continue;
default:
continue;
}
}
}
}//row cursor is disposed. row cursor is unsubscribed
}
});
//Note we can use System Task with the Realtime feature class
//for subscribe
await System.Threading.Tasks.Task.Run(async () =>
// or use ... QueuedTask.Run()
{
using (var rfc = streamLayer.GetFeatureClass())
{
//non-recycling cursor - 2nd param "false"
using (var rc = rfc.SearchAndSubscribe(qfilter, false))
{
//waiting for new features to be streamed
//default is no cancellation
while (await rc.WaitForRowsAsync())
{
//pre-existing rows will be retrieved that were searched
while (rc.MoveNext())
{
var row = rc.Current;
var row_source = row.GetRowSource();
switch (row_source)
{
case RealtimeRowSource.EventDelete:
//TODO - handle deletes
break;
case RealtimeRowSource.EventInsert:
//TODO handle inserts
break;
case RealtimeRowSource.PreExisting:
//TODO handle pre-existing rows
break;
}
}
}
}//row cursor is disposed. row cursor is unsubscribed
}
});
await System.Threading.Tasks.Task.Run(async () =>
// or use ... QueuedTask.Run()
{
using (var rfc = streamLayer.GetFeatureClass())
{
//Recycling cursor - 2nd param "true"
using (var rc = rfc.SearchAndSubscribe(qfilter, true))
{
//auto-cancel after 20 seconds
var cancel = new CancellationTokenSource(new TimeSpan(0, 0, 20));
//catch TaskCanceledException
try
{
while (await rc.WaitForRowsAsync(cancel.Token))
{
//check for row events
while (rc.MoveNext())
{
//etc
}
}
}
catch(TaskCanceledException tce)
{
//Handle cancellation as needed
}
cancel.Dispose();
}
}
});
Home | API Reference | Requirements | Download | Samples
- Overview of the ArcGIS Pro SDK
- What's New for Developers at 3.5
- Installing ArcGIS Pro SDK for .NET
- Release notes
- Resources
- Pro SDK Videos
- ProSnippets
- ArcGIS Pro API
- ProGuide: ArcGIS Pro Extensions NuGet
Migration
- ProConcepts: Framework
- ProConcepts: Asynchronous Programming in ArcGIS Pro
- ProConcepts: Advanced topics
- ProGuide: How to Increment Addin Version Number
- ProGuide: Custom settings
- ProGuide: Command line switches for ArcGISPro.exe
- ProGuide: Reusing ArcGIS Pro Commands
- ProGuide: Licensing
- ProGuide: Digital signatures
- ProGuide: Command Search
- ProGuide: Keyboard shortcuts
- ProSnippets: Framework
- ProSnippets: DAML
Add-ins
- ProConcepts: Localization
- ProGuide: Installation and Upgrade
- ProGuide: Your first add-in
- ProGuide: ArcGIS AllSource Project Template
- ProGuide: Content and Image Resources
- ProGuide: Embedding Toolboxes
- ProGuide: Diagnosing ArcGIS Pro Add-ins
- ProGuide: Regression Testing
Configurations
Customization
- ProGuide: The Ribbon, Tabs and Groups
- ProGuide: Buttons
- ProGuide: Label Controls
- ProGuide: Checkboxes
- ProGuide: Edit Boxes
- ProGuide: Combo Boxes
- ProGuide: Context Menus
- ProGuide: Palettes and Split Buttons
- ProGuide: Galleries
- ProGuide: Dockpanes
- ProGuide: Code Your Own States and Conditions
- ProGuide: Command Filter
Styling
- ProConcepts: Project Content and Items
- ProConcepts: Custom Items
- ProGuide: Custom Items
- ProGuide: Custom browse dialog filters
- ProSnippets: Content
- ProSnippets: Browse Dialog Filters
- ArcGIS Pro TypeID Reference
- ProConcepts: Editing
- ProConcepts: COGO
- ProConcepts: Annotation Editing
- ProConcepts: Dimension Editing
- ProGuide: Editing Tool
- ProGuide: Sketch Tool With Halo
- ProGuide: Construction Tools with Options
- ProGuide: Annotation Construction Tools
- ProGuide: Annotation Editing Tools
- ProGuide: Knowledge Graph Construction Tools
- ProGuide: Templates
- ProSnippets: Editing
3D Analyst Data
Plugin Datasources
Topology
Linear Referencing
Object Model Diagram
- ProConcepts: Geometry
- ProConcepts: Multipatches
- ProGuide: Building Multipatches
- ProSnippets: Geometry
- ProSnippets: Geometry Engine
Relational Operations
- ProConcepts: Knowledge Graph
- ProGuide: Knowledge Graph Construction Tools
- ProSnippets: Knowledge Graph
Reports
Presentations
- ProConcepts: Map Authoring
- ProConcepts: Annotation
- ProConcepts: Dimensions
- ProGuide: Tray buttons
- ProGuide: Custom Dictionary Style
- ProGuide: Geocoding
- ProSnippets: Map Authoring
- ProSnippets: Annotation
- ProSnippets: Charts
- ProSnippets: Labeling
- ProSnippets: Renderers
- ProSnippets: Symbology
- ProSnippets: Text Symbols
3D Analyst
CIM
Graphics
Scene
Stream
Voxel
- ProConcepts: Map Exploration
- ProGuide: Map Pane Impersonation
- ProGuide: TableControl
- ProSnippets: Map Exploration
- ProSnippets: Custom Pane with Contents
Map Tools
- ProGuide: Feature Selection
- ProGuide: Identify
- ProGuide: MapView Interaction
- ProGuide: Embeddable Controls
- ProGuide: Custom Pop-ups
- ProGuide: Dynamic Pop-up Menu
Network Diagrams
- ProConcepts: Workflow Manager
- ProSnippets: Workflow Manager
- ProConcepts: Workflow Manager Classic (deprecated)
- ArcGIS Pro API Reference Guide
- ArcGIS Pro SDK (pro.arcgis.com)
- arcgis-pro-sdk-community-samples
- ArcGISPro Registry Keys
- ArcGIS Pro DAML ID Reference
- ArcGIS Pro Icon Reference
- ArcGIS Pro TypeID Reference
- ProConcepts: Distributing Add-Ins Online
- ProConcepts: Migrating to ArcGIS Pro
- FAQ
- Archived ArcGIS Pro API Reference Guides
- Dev Summit Tech Sessions