Extending ArcGIS Pro with .NET and Python: Interactive ... Extending ArcGIS Pro with .NET and...

download Extending ArcGIS Pro with .NET and Python: Interactive ... Extending ArcGIS Pro with .NET and Python:

If you can't read please download the document

  • date post

    22-Jun-2020
  • Category

    Documents

  • view

    4
  • download

    0

Embed Size (px)

Transcript of Extending ArcGIS Pro with .NET and Python: Interactive ... Extending ArcGIS Pro with .NET and...

  • Extending ArcGIS Pro with .NET and

    Python: Interactive Analytics

    Carlos A. Osorio-Murillo

    Mark Janikas

  • Introduction

    • ArcGIS Pro is highly customizable. From an application perspective, .NET can be used to

    construct buttons, ribbons and tool specific user interfaces. Through the use of Python and

    Geoprocessing, your desired functionality can run both in demand and interactively with

    the .NET extension you created. This session introduces the key concepts necessary to

    get started with extending your ArcGIS Pro Application and provides a clear case study of

    interactive analytics to show you the power of the strategies outlined.

  • Objectives .Net & Python

    • Integrate .Net and Python for improving workflows

    • Powering a Density-Based Clustering method (OPTICS) through an Add-in

    • Quick demo how to create an Add-in Visual Studio

  • Unsupervised learning methods

    Density-Based

    Clustering

    DBSCAN OPTICS HDBSCAN

    Find representavives groups

    Which criteria depends of user

    Partition

    (Kmean)

    Spatially constrain

    (SKATER)

  • Density-based Clustering

    Three clustering algorithms

    Fast

    Automatic Detection

    Interactive

  • OPTICS Process

    • Produce a special order of the database with a density-base clustering structure

    • God for both automatic and interactive cluster analysis, including finding intrinsic

    clustering structure

    • Can be represented graphically (Plot)

    arcpy.DensityBasedClustering_stats()

  • OPTICS Process arcpy.DensityBasedClustering_stats()

    (Generate Reachability information)

    Cluster detection

    Map clustering

    (Applying color

    exclusion schema)

  • Python Tool for Detecting cluster

    def execute(self, parameters, messages): import SSCluster as SSC import SSDataObject as SSDO import numpy as NUM

    #### Get Parameters #### inputFC = parameters[0].valueAsText minPoints = int(parameters[1].valueAsText) tolerance = int(parameters[2].valueAsText) threshold = int(parameters[3].valueAsText)

    #### Allow overwrite Output ### ARCPY.env.overwriteOutput = True

    #### Load Data #### ssdo = SSDO.SSDataObject(inputFC) ssdo.obtainData(fields = ["REACHORDER","REACHDIST"])

    #### Sort Reachability Order ### ord = ssdo.fields["REACHORDER"].data

    #### Get Reachability Distances #### reachValues = ssdo.fields["REACHDIST"].data

    #### Sorting by Index #### data = NUM.zeros((len(reachValues), 2), dtype= float) data[:, 0] = reachValues data[:, 1] = ord odata = data[data[:,1].argsort()]

  • OPTICS as an

    extension of DBSCAN

    Distance Threshold

    Not enough minimum number

    of points to be considered

    Clusters

    #### Function to get DBSCAN Clusters #### def getDBSCAN(distances, threshold, minPoints, orderValues):

    clusterArr = NUM.ones(len(distances), dtype = int)*-1 indices = distances = minPoints-1:

    clusterArr[ini:end+1] = clusterIndex clusterIndex += 1 ini = end = 0 c = 1

    return clusterArr[orderValues]

  • OPTICS Tolerance

    Merged clusters

    Cluster shape

    import SSCluster as SSC #### Initialize Detect Zone Class #### zones = SSC.DetectZones()

    #### Get Cluster By Tolerance ### idClusters, idColor = zones.getClusters(reachValues,

    orderValues, minPoints, tolerance)

    Arcgis Pro Python Module

  • Interactive Clustering detection

    through Add-in

    and Python

  • Addin

    Demo Detecting clusters

    https://github.com/Esri/ExampleDotNetAndPythonForAnalytics

  • Add-in Creation using Visual Studio

    Resources

    https://github.com/Esri/arcgis-pro-sdk/wiki/ProGuide-

    Build-Your-First-Add-in

  • Add-in Creation using Visual Studio

  • Creating an Add-in Demo

  • Design Control WPF ComboBox

    Slider

    TextBox

    …..

    Dockpanel

  • Add-in Events

    Add-In UI App

    GetLayersInMap()

    Geoprocessing Toolbox/Tool

    UpdateClusters()

    Python

    Update Dataset

    Update Simbology()

    Async method

    Time line

  • GetLayersInMap()

    internal async void GetLayersInMap() {

    if (MapView.Active == null) return;

    var currentMap = MapView.Active.Map; var layers = currentMap.GetLayersAsFlattenedList(); List featureLayers = new List(); foreach (Layer lyr in layers) {

    if (lyr is FeatureLayer) { FeatureLayer flyr = lyr as FeatureLayer; bool check = true; check = (flyr.ShapeType == esriGeometryType.esriGeometryPoint); if (check) {

    /// Layer should contain Reachability distance field int hasClusteredOpticLayer = await QueuedTask.Run(() => { return flyr.GetTable().GetDefinition().FindField("REACHDIST");

    });

    if (hasClusteredOpticLayer >= 0) featureLayers.Add(flyr);

    } }

    } _layers = featureLayers; NotifyPropertyChanged(() => Layers);

    }

    Obtain Point Layers with

    a specific field

    await QueuedTask.Run(() => {

    return flyr.GetTable().GetDefinition().FindField("REACHDIST"); });

    check = (flyr.ShapeType == esriGeometryType.esriGeometryPoint);

  • UpdateClusters()

    internal async void UpdateCluster(bool isTolerance) {

    if (MapView.Active == null) return;

    // Get Layer Name string inputFC = SelectedLayer.Name; int minPoints = 2; bool parsed = Int32.TryParse(MinPoints, out minPoints); // Set PYT path string tool_path ="C:\\PATH\\UpdateCluster.pyt\\UpdateClusterTool"; IReadOnlyList args= null; if (isTolerance) {

    /// Arguments for executing process using Tolerance args = Geoprocessing.MakeValueArray(inputFC, minPoints, ValueSlider, -1);

    } else {

    /// Arguments for executing process using Threshold args = Geoprocessing.MakeValueArray(inputFC, minPoints, -1, ValueThreshold);

    }

    Task task; /// Execute the Tool in the python toolbox task = Geoprocessing.ExecuteToolAsync(tool_path, args, flags: GPExecuteToolFlags.AddToHistory);

    task = Geoprocessing.ExecuteToolAsync(tool_path, args, flags: GPExecuteToolFlags.AddToHistory);

    string tool_path ="C:\\PATH\\UpdateCluster.pyt\\UpdateClusterTool";

  • Update Simbology

    await QueuedTask.Run( () => { /// Search for a specific Symbol /// Other styles Arcgis/Resouces/Styles/Styles.stylx SQLite DB SymbolStyleItem symbolStyleItem = (SymbolStyleItem)style.LookupItem(StyleItemType.PointSymbol, "Circle 1_Shapes_3"); pointSymbol = (CIMPointSymbol)symbolStyleItem.Symbol;

    /// Cluster Ids based in Color Schema int[] ids = new int[] { -1, 1, 2, 3, 4, 5, 6, 7, 8 };

    /// Set Colors string[] colors = new string[]{ "156,156,156", "166,206,227", "31,120,180", "178,223,138",

    "51,160,44", "251,154,153", "227,26,28", "253,191,111", "255,127,0" };

    /// Color Field String[] fields = new string[] { "COLOR_ID" };

    /// Make a reference of the point symbol CIMSymbolReference symbolPointTemplate = pointSymbol.MakeSymbolReference();

    /// Get definition of type symbology unique values UniqueValueRendererDefinition uniqueValueRendererDef = new UniqueValueRendererDefinition(fields, symbolPointTemplate, null, symbolPointTemplate, false);

    /// Get Current renderer of the Selected Layer CIMUniqueValueRenderer renderer = (CIMUniqueValueRenderer)SelectedLayer.CreateRenderer(uniqueValueRendererDef); CIMUniqueValueClass[] newClasses = new CIMUniqueValueClass[colors.Count()];

    /// Get Point Symbol as string for creating other point colors string point = pointSymbol.ToXml();

    /// Create Each Color for (int i = 0; i < ids.Length; i++) { CIMPointSymbol npoint = CIMPointSymbol.FromXml(point); if (ids[i] == -1) { npoint.SetSize(4);

    } else { npoint.SetSize(6);

    } CIMSymbolReference symbolPointTemplatei = npoint.MakeSymbolReference(); newClasses[i] = new CIMUniqueValueClass(); newClasses[i].Values = new CIMUniqueValue[1]; newClasses[i].Values[0] = new CIMUniqueValue(); newClasses[i].Values[0].FieldValues = new string[1]; newClasses[i].Values[0].FieldValues[0] = ids[i].ToString(); newClasses[i].Label = ids[i].ToString(); newClasses[i].Symbol = symbolPointTemplatei; var color = colors[i].Split(','); double r = Convert.ToDouble(color[0]); double g = Convert.ToDouble(color[1]); double b = Convert.ToDouble(color[2]); newClasses[i].Symbol.Symbol.SetColor(CIMColor.CreateRGBColor(r, g, b));

    } /// Add Colors into the renderer renderer.Groups[0].Classes = newClasses;

    /// Apply new renderer in the layer SelectedLayer.SetRenderer(renderer);

    //SelectedLayer.RecalculateRenderer(); });

    UniqueValueRendererDefinition uniqueValueRendererDef = new UniqueValueRendererDefinition(fields, symbolPointTemplate, null, symbolPointTemplate, false);

    CIMUniqueValueRenderer renderer = (CIMUniqueValueRenderer)SelectedLayer.CreateRenderer(uniqueValueRendererDef);

    SymbolStyleItem symbolStyleItem = (SymbolStyleItem)style.LookupItem(StyleItemType.PointSymbol, "Circle 1_Shapes_3");

    renderer.Groups[0].Classes = newClasses; SelectedLayer.SetRenderer(renderer);

  • Conclusions

    - Add-in can improve Geoprocessing Tools (Density-Based Clustering)

    - Easy way to join Python Scripts and .Net through an Add-in

    - ArcGIS Pro SDK Ex