91
Charlie Macleod Understanding the CIM, a Guide for Developers

Understanding the CIM A Guide for Developers

  • Upload
    others

  • View
    3

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Understanding the CIM A Guide for Developers

Charlie Macleod

Understanding the CIM, a Guide for Developers

Page 2: Understanding the CIM A Guide for Developers

Understanding the CIM – A Guide for Developers

- Overview- Definition- How to retrieve and access the CIM- Transactional Model

- Practical Guidelines- Leveraging CIMViewer or CIM Serialization

- Recipe for developing custom CIM Code

Page 3: Understanding the CIM A Guide for Developers

• There are three major patterns within the Pro SDK - QueuedTask with async and await- MVVM (Model, View , View Model)

- …..and

- the CIM

Understanding the CIM

Page 4: Understanding the CIM A Guide for Developers

Understanding the CIM – CIM Definition and Purpose

• CIM or “Cartographic Information Model”:- It is a specification for persisting and transferring the state and

structure of all Pro model entities. Including:- Contents and relationships- Symbolization- Labelling- State: Visible, Editable, Selectable, etc..

- Models include Map, Layer, Layout, Report, Edit Template, etc.

Page 5: Understanding the CIM A Guide for Developers

Understanding the CIM – CIM Definition and Purpose

• Pro model entities provide “convenience” .NET properties for their most commonly used aspects- For the rest, we use the CIM- Much greater level of granularity than the models

- Allows the models to remain “clean”, more streamlined- Must use the CIM to manipulate renderers, symbols, text

- No model wrappers

Page 6: Understanding the CIM A Guide for Developers

Understanding the CIM – CIM Access

• All model entities contain a CIM representation.- Access via GetDefinition()

- Must be on the QueuedTask- Changes applied via SetDefinition()- Changes propagated back to the Pro view models via various internal “sync” events

- i.e. the various project panes and dockpanes

Page 7: Understanding the CIM A Guide for Developers

Understanding the CIM – CIM Characteristics

• The CIM entities themselves:- Reside in ArcGIS.Core.CIM namespace- All derive from CIMObject- Inherit serialize/deserialize to/from XML via CIMObject

- Deserialize to/from JSON available as of 2.4- Thread agnostic (can be manipulated on any thread)

- B-u-t…CIM definitions can only be retrieved/set [from/to models] via the QueuedTask

Page 8: Understanding the CIM A Guide for Developers

Understanding the CIM – Examples

• Transactional pattern for access – Get and Set- For example, accessing the CIM from a layer

- Note: use ToXml() to serialize to XML – useful for debugging

var streets = MapView.Active.Map.FindLayers("streets").First() as FeatureLayer;await QueuedTask.Run(() => {

//Use GetDefinition to retrieve the CIM Definition – ‘CIMFeatureLayer’//in this casevar def = streets.GetDefinition() as CIMFeatureLayer;

var str = def.ToXml();//Get the XML representation for Debug

//TODO Make changes to the CIM

//Commit changes backstreets.SetDefinition(def);

});

Page 9: Understanding the CIM A Guide for Developers

Understanding the CIM – Examples

• Changing feature layer selection color , hiding the legend, adding custom properties

var streets = MapView.Active.Map.FindLayers("streets").First() as FeatureLayer;await QueuedTask.Run(() =>{//access the layer CIM Definitionvar def = streets.GetDefinition() as CIMFeatureLayer;

//make changes - change the selection color, hide the legenddef.SelectionColor = ColorFactory.Instance.RedRGB;def.ShowLegends = false;

//add a custom propertyvar customProperties = new List<CIMStringMap>();customProperties.Add(new CIMStringMap() { Key = "My Property", Value = "My Value" });def.CustomProperties = customProperties.ToArray();

//set the CIM Definition backstreets.SetDefinition(def);

});

Page 10: Understanding the CIM A Guide for Developers

Understanding the CIM – Examples

• Updating Arrays- CIM Objects store their collection properties as arrays

- By product of CIM objects existing in .NET and Native code- Lacking “nice” List semantics for Add, Update, Remove- Many times when editing the CIM we want to update the collections (add, update, remove, etc)

Page 11: Understanding the CIM A Guide for Developers

Understanding the CIM – Examples

• Updating Arrays- Simplest approach is to use LINQ to convert array to List (“array.ToList()”)- Modify the list- Set the list back to the array property using “list.ToArray()”

- Also use list.ToArray() to assign a collection when the property is null

Page 12: Understanding the CIM A Guide for Developers

Understanding the CIM – CIM Viewer

• Diagnostic tool for examining CIM definitions:- Available on Github

https://github.com/esri/arcgis-pro-sdk-cim-viewer

- Leverages the XML nature of the CIM to view structure and values

Page 13: Understanding the CIM A Guide for Developers

Understanding the CIM – CIM Characteristics

• Demo

Page 14: Understanding the CIM A Guide for Developers

Understanding the CIM – Practical Guidelines

• When to use the CIM?- Model properties are insufficient

- You need to modify a setting not exposed on the model- You want to make multiple changes as a single transaction

- i.e. GetDefinition….changes….SetDefinition- There is no corresponding model

- Eg Renderers, Labelling, Symbology

Page 15: Understanding the CIM A Guide for Developers

Understanding the CIM – A Generic Approach

• Assume we need to update the CIM• Two common challenges:

- Which aspects of the CIM do we need to modify?- Translating that into our .NET code

- Can be tricky to figure out the right casts and assignments

- Toward deriving a generic or repeatable approach…we will use two examples….

Page 16: Understanding the CIM A Guide for Developers

Understanding the CIM – Usage Scenarios

- Mapping- Modify a (Unique Value) Renderer

- Add total counts per subtype for each legend class

Page 17: Understanding the CIM A Guide for Developers

Understanding the CIM – Usage Scenarios

- Layout- Customize a Layout map frame

- Use a polygon feature(s) as the map frame outline

Page 18: Understanding the CIM A Guide for Developers

Understanding the CIM – A Practical Approach

• How can we resolve what aspect of the CIM to modify?- 1. SDK Resources

- https://github.com/esri/arcgis-pro-sdk/wiki- https://github.com/Esri/arcgis-pro-sdk-community-samples/tree/master/Map-Authoring- https://community.esri.com/groups/arcgis-pro-sdk- https://pro.arcgis.com/en/pro-app/sdk/api-reference- https://github.com/esri/cim-spec

- Snippets, Samples, Geonet, API Reference

Page 19: Understanding the CIM A Guide for Developers

Understanding the CIM – A Practical Approach

• How can we resolve what aspect of the CIM to modify?- 2. Leverage the CIM Serialization to XML

- Allows us to examine the CIM for a given model- CIMViewer for “interactive” investigation or use XML Viewer of Visual Studio

- Edit the CIM, observe the changes on the UI

- “Translate” observations of the CIM XML back into code

Page 20: Understanding the CIM A Guide for Developers

Understanding the CIM – A Practical Approach

• Scenario 1- Customize the layer legend labels (UV Renderer)…assume SDK resources have been

consulted

• Select the layer (with the renderer)• Observe the layer definition in the CIM Viewer or in code (using “def.ToXml()”)

Page 21: Understanding the CIM A Guide for Developers

Understanding the CIM – Using the CIM Viewer

• Hone in on the top-level CIM characteristic you wish to modify.- The Renderer in this case

- eg “Ctrl + F” search for “Renderer”

Page 22: Understanding the CIM A Guide for Developers

Understanding the CIM – CIM Xml Elements

- Xml Element names correspond to the names of the CIM properties*- The “typens:” value gives you their (.NET) type.

- *Array properties identify the name. Each Child element identifies the type

Page 23: Understanding the CIM A Guide for Developers

Understanding the CIM – CIM Xml Elements

- Based on the XML “Build up” corresponding CIM “dot” property hierarchy based on the Xml in your code

var def = crimes.GetDefinition() as CIMFeatureLayer;var uvr = def.Renderer as CIMUniqueValueRenderer;

Page 24: Understanding the CIM A Guide for Developers

Understanding the CIM – A Practical Approach

• Find the value field(s) for which we want counts

Page 25: Understanding the CIM A Guide for Developers

Understanding the CIM – A Practical Approach

• Find where the labels are stored that we need to update

Page 26: Understanding the CIM A Guide for Developers

Understanding the CIM – A Practical Approach

Page 27: Understanding the CIM A Guide for Developers

Understanding the CIM – A Practical Approach

Page 28: Understanding the CIM A Guide for Developers

Understanding the CIM – A Practical Approach

Page 29: Understanding the CIM A Guide for Developers

Understanding the CIM – A Practical Approach

Page 30: Understanding the CIM A Guide for Developers

Understanding the CIM – A Practical Approach

Page 31: Understanding the CIM A Guide for Developers

Understanding the CIM – A Practical Approach

Page 32: Understanding the CIM A Guide for Developers

Understanding the CIM – A Practical Approach

Page 33: Understanding the CIM A Guide for Developers

Understanding the CIM – A Practical Approach

Page 34: Understanding the CIM A Guide for Developers

Understanding the CIM – A Practical Approach

Page 35: Understanding the CIM A Guide for Developers

Understanding the CIM – A Practical Approach

Page 36: Understanding the CIM A Guide for Developers

Understanding the CIM – A Practical Approach

Page 37: Understanding the CIM A Guide for Developers

Understanding the CIM – A Practical Approach

Page 38: Understanding the CIM A Guide for Developers

Understanding the CIM – CIM Scenario 1

• Demo

Page 39: Understanding the CIM A Guide for Developers

Understanding the CIM – A Practical Approach

• Scenario 2- Customize the layout mapframe shape. Customize the border symbol

• Scenario 2- Change the shape- Change the symbol

Page 40: Understanding the CIM A Guide for Developers

Understanding the CIM – A Practical Approach

• Assume SDK Resources have been consulted…

• Select the layout• Observe the layout definition in the CIM Viewer or in code (using “def.ToXml()”)

Page 41: Understanding the CIM A Guide for Developers

Understanding the CIM – A Practical Approach

• Hone in on the top-level CIM characteristic you wish to modify.- The layout MapFrame in this case

Page 42: Understanding the CIM A Guide for Developers

Understanding the CIM – A Practical Approach

- Based on the XML “Build up” corresponding CIM “dot” property hierarchy based on the Xml in your code

Page 43: Understanding the CIM A Guide for Developers

Understanding the CIM – A Practical Approach

• Within the MapFrame we are looking for its border/frame and whatever symbol it is using…

Page 44: Understanding the CIM A Guide for Developers

Understanding the CIM – A Practical Approach

Page 45: Understanding the CIM A Guide for Developers

Understanding the CIM – A Practical Approach

Page 46: Understanding the CIM A Guide for Developers

Understanding the CIM – A Practical Approach

Page 47: Understanding the CIM A Guide for Developers

Understanding the CIM – A Practical Approach

Page 48: Understanding the CIM A Guide for Developers

Understanding the CIM – CIM Scenario 2

• Demo

Page 49: Understanding the CIM A Guide for Developers

Understanding the CIM – A Developer’s Guide

• Summary- Definition- Transactional Model for Get/Set- Hands-on Techniques for Developing Custom CIM code

- Covered use of CIM Viewer and/or Serialization to:- Examine the CIM- “Construct” our code (“transferring” the xml hierarchy to “dot” property notation)

Page 50: Understanding the CIM A Guide for Developers

ArcGIS Pro SDK for .NET – Technical Sessions

Date Time Session Location

Mon, Nov 04 1:00 pm – 1:45 pm Learning Customization and Extensibility Salon Durieux

Tue, Nov 05

9:00 am – 9:45 am Understanding the CIM, a Guide for Developers Salon Humboldt

2:00 pm – 2:45 pm Intermediate Editing Salon Durieux

4:00 pm – 4:45 pm Advanced Customization Patterns Salon Durieux

Wed, Nov 06 2:00 pm – 2:45 pm Learning Customization and Extensibility Salon Humboldt

Page 51: Understanding the CIM A Guide for Developers

Understanding the CIM – A Developer’s Guide

• Questions?

- https://github.com/esri/arcgis-pro-sdk/wiki/tech-sessions#2019-berlin

Page 52: Understanding the CIM A Guide for Developers

Complete answersand select “Submit”

Scroll down to find the feedback section

Select the session you attended

Download the Esri Events app and find your event

Please Take Our Survey on the App

Page 53: Understanding the CIM A Guide for Developers
Page 54: Understanding the CIM A Guide for Developers

Understanding the CIM – CIM Persistence

• Revisit CIMObject and Serialization/Deserialization to/from Xml, JSON- Already leveraged xml serialization in our debugging

- CIMViewer and/or Visual Studio Xml Viewer- Examine leveraging deserialization to complete persistence pattern:

- Cautionary notes regarding URIs

Page 55: Understanding the CIM A Guide for Developers

Understanding the CIM – CIMObject ToXml, FromXML(), ReadXml()

• Xml- All CIM classes derive from CIMObject

- Serialization via ToXml()- Deserialization either via ReadXml(XmlReader reader) or…- Concrete CIM classes have a static FromXml(string xml) method

Page 56: Understanding the CIM A Guide for Developers

Understanding the CIM –ToXML, FromXml()

• Xml Serialization, Deserialization

//Serialization / Deserialization with JSONvar mapframe = def.Elements.OfType<CIMMapFrame>().First();var xml = mapframe.ToXml();

//Deserialize using instance ReadXml method var mapframe2 = new CIMMapFrame();mapframe2.ReadXml(new XmlTextReader(new StringReader(xml)));

// Deserialize using matching concrete class “FromXml”var mapframe2 = CIMMapFrame.FromXml(xml);

Page 57: Understanding the CIM A Guide for Developers

Understanding the CIM –ToJson, FromJson()

• Json- All CIM classes derive from CIMObject

- Serialization via ToJSON()- Deserialization via concrete class static FromJson(string json) method only

Page 58: Understanding the CIM A Guide for Developers

Understanding the CIM –ToJson, FromJson()

• Json Serialization, Deserialization

//Serialization / Deserialization with JSONvar mapframe = def.Elements.OfType<CIMMapFrame>().First();

var settings = new JsonSerializationSettings() {PrettyPrint = true

};var json = mapframe.ToJson(settings);//Deserialize using matching concrete class “FromJson”var mapframe2 = CIMMapFrame.FromJson(json);

Page 59: Understanding the CIM A Guide for Developers

Understanding the CIM – A Practical Approach

• Demo

Page 60: Understanding the CIM A Guide for Developers

Understanding the CIM – CIM Serialization/Deserialization

• Caveats or “Fine Print”:- Avoid using CIM persistence to copy model object definition when there is a URI

- Primary examples are Maps, Layers, Layouts, Reports- Contain URIs which will be duplicated in the deserialized instances

- URIs are a primary key into the project- Duplicating URIs can have unintended consequences

- Use supported export format instead – map file, layer files, report files, etc

Page 61: Understanding the CIM A Guide for Developers

Understanding the CIM – A Developer’s Guide

• Summary- Definition- Transactional Model for Get/Set- Hands-on Techniques for Developing Custom CIM code

- Covered use of CIM Viewer and/or Serialization to:- Examine the CIM- “Construct” our code (“transferring” the xml hierarchy to “dot” property notation)

- CIM Persistence- ToXml and ReadXml, FromXml- ToJson and FromJson- Cautionary notes on CIM Uris and copying

Page 62: Understanding the CIM A Guide for Developers
Page 63: Understanding the CIM A Guide for Developers
Page 64: Understanding the CIM A Guide for Developers

Understanding the CIM – CIM Deserialization - Xml

• Deserialization via ReadXml(XmlReader reader) or static FromXML(xml)- Use a matching CIM type instance to consume the XML

- Use a map frame to deserialize a map frame- Use a scale bar to deserialize a scale bar- Use a renderer to deserialize a renderer- …etc

Page 65: Understanding the CIM A Guide for Developers

Understanding the CIM – CIM Serialization ToXml()

• Serialization via ToXml()- “regular” XML string (compatible with .NET xml apis).

Page 66: Understanding the CIM A Guide for Developers

Understanding the CIM – CIM Deserialization - Xml

• If we don’t know the type to use, examine “xsi:type=typens:CIMXyztype” attribute

- identifies “the” type to instantiate- For ReadXML:

- Use new + default ctor()- Call ReadXML on the newly constructed instance

- For static FromXML:- Call (static) FromXml directly on the appropriate type

Page 67: Understanding the CIM A Guide for Developers

Understanding the CIM – CIM Deserialization - Xml

Page 68: Understanding the CIM A Guide for Developers

Understanding the CIM – CIM Deserialization - Xml

• Optionally:- Use reflection to create the correct instance rather than new.

- Does allow for a more “generic” approach…suitable for “utility method” but….- Cast to the correct concrete type will most likely still be required at some point…

Page 69: Understanding the CIM A Guide for Developers

Understanding the CIM – Toward Copy or “Clone”

• Can leverage serialize/deserialization for purposes of Copy or Clone- Serialize the CIM Object to be cloned/copied via ToXml()- Deserialize it into a new instance using ReadXml(…)

Page 70: Understanding the CIM A Guide for Developers

Understanding the CIM – Toward Copy or “Clone”

- Use reflection to create the correct instance- .NET Extension method can add some additional syntactic “sugar”

Page 71: Understanding the CIM A Guide for Developers

Understanding the CIM – CIM Serialization/Deserialization

• Caveats or “Fine Print”:- Avoid CIM persistence/clone on the entire model object definition when there is a

URI- Primary examples are Maps, Layers, Layouts, Reports- Contain URIs which will be duplicated in the deserialized instances

- URIs are a primary key into the project- Duplicating URIs can have unintended consequences

- For persistence, use the supported export format instead – map file, layer files, report files, etc.

- Persistence, if done at all, is best suited to individual model object aspects like:- Renderers, Elements, Symbology, etc.

Page 72: Understanding the CIM A Guide for Developers

Understanding the CIM – Toward Clone

• Ideally, we can identify the CIM instance type we need from the xml- Instantiate that type auto-magically without the need to hardcode

Page 73: Understanding the CIM A Guide for Developers

Understanding the CIM – Toward Clone

• All serialized CIM objects carry a “xsi:type=typens:CIMXyztype” attribute

• Use that “typens:” type to identify the correct instance- Instantiate the new CIM instance using reflection- Eg System.Activator.CreateInstance(string assemblyName, string typeName)

Page 74: Understanding the CIM A Guide for Developers

Understanding the CIM – Toward Clone

• Example:

Page 75: Understanding the CIM A Guide for Developers

Understanding the CIM – A Practical Approach

Page 76: Understanding the CIM A Guide for Developers

Understanding the CIM – Symbology

• One of the primary uses of the CIM is in defining symbology:- Coarse-grained API available via SymbolFactory (ColorFactory for colors)- Creates a variety of “pre-cooked” symbols- Requires use of the CIM to create more specialized varieties

- As well as modify “pre-cooked” ones*

*Lots of code examples at https://github.com/esri/arcgis-pro-sdk/wiki/ProSnippets-Symbology

Page 77: Understanding the CIM A Guide for Developers

Understanding the CIM – Symbology

• Points, Lines, Polygons follow a very uniform structure:- Derive from CIMMultiLayerSymbol -> CIMSymbol

- Consists of one or more Symbol Layers - CIMSymbolLayer

public abstract class CIMMultiLayerSymbol : CIMSymbol {public CIMSymbolLayer[] SymbolLayers { get; set; }

Page 78: Understanding the CIM A Guide for Developers

Understanding the CIM – Symbology

• CIMSymbolLayer classes represent the Strokes, Fills, Markers that comprise the symbol- In simple cases, the symbol has a single layer

- Build more complex symbols using multiple layers- Can combine effects with a layer to create dots, dashes, offsets, etc.- Various options for line endings, joins, miter, etc,etc

var stroke = new CIMSolidStroke() { Color = ColorFactory.Instance.RedRGB, Width = 2 };var lineSymbol = new CIMLineSymbol() { SymbolLayers = new CIMSymbolLayer[1] { stroke } };

Page 79: Understanding the CIM A Guide for Developers

Understanding the CIM – Symbology

- Build more complex symbols using multiple layers- Can combine effects with a layer to create dots, dashes, offsets, etc.

- Various options for line endings, joins, miter, etc,etc

var stroke = new CIMSolidStroke() { Color = ColorFactory.Instance.RedRGB, Width = 2 };stroke.Effects = new CIMGeometricEffect[] {

new CIMGeometricEffectOffset() {Method = GeometricEffectOffsetMethod.Mitered, Offset = -3}};

var stroke2 = new CIMSolidStroke() { Color = ColorFactory.Instance.BlueRGB, Width = 1 };stroke2.Effects = new CIMGeometricEffect[] {new CIMGeometricEffectOffset() {Method = GeometricEffectOffsetMethod.Mitered, Offset = 3},new CIMGeometricEffectArrow() { ArrowType = GeometricEffectArrowType.Block, Width = 4}

};

var lineSymbol = new CIMLineSymbol() { SymbolLayers = new CIMSymbolLayer[] { stroke, stroke2 } };

Page 80: Understanding the CIM A Guide for Developers

Understanding the CIM – Symbology

• Points, Lines, Polygons follow a very uniform structure:- Derive from CIMMultiLayerSymbol -> CIMSymbol

- Consists of one or more Symbol Layers – CIMSymbolLayer- Layers represent the Strokes, Fills, Markers that comprise the symbol

- Consists of one or more Geometric Effects – CIMGeometricEffect- Effects are dashes, dots, line endings, offsets

- The layers represent the “primitives” used to represent the symbols- Strokes, fills, markers, etc. - CIMStroke, CIMFill, CIMMarker

- All* symbols use the same (mix of) layers- “Simple” symbols have a single layer- More complex symbols use multiple layers. Layers can be of different types

- For example – a line symbol can consist of: - A stroke, a circle marker, and a square marker

public abstract class CIMMultiLayerSymbol : CIMSymbol {public CIMGeometricEffect[] Effects { get; set; }

Page 81: Understanding the CIM A Guide for Developers

Understanding the CIM – Symbology

• Simple example:

Page 82: Understanding the CIM A Guide for Developers

Understanding the CIM – Symbology

• CIMSymbolLayer:- Marker, Stroke, Fill- Geometryic effects- To create a symbol create one or more layers- Use CIM Viewer to analyze existing symbols to “reverse engineer” how they are

created- Every CIM Symbol consists of one or more Symbol Layers - CIMSymbolLayer

- The layers represent the “primitives” used to represent the symbols- Strokes, fills, markers, etc.

- All symbols use the same (mix of) layers (Points, Lines, Polygons, Text*)- “Simple” symbols have a single layer- More complex symbols use multiple layers

- *Text can consist of multiple symbols – text itself, callout, halo, etc.

Page 83: Understanding the CIM A Guide for Developers

Understanding the CIM – Symbology

• Simple example

Page 84: Understanding the CIM A Guide for Developers

Understanding the CIM – Symbology

• Multi layer example

Page 85: Understanding the CIM A Guide for Developers

Understanding the CIM – Symbology

• Graphic- Combines symbol with a geometry- Use to place on the map in the overlay

- Points, lines, polygons, text

Page 86: Understanding the CIM A Guide for Developers

Understanding the CIM – Symbology

• Demo

Page 87: Understanding the CIM A Guide for Developers

Understanding the CIM – Symbology

- Clone- Deserialize from XML- Dealing with URI

Page 88: Understanding the CIM A Guide for Developers

Understanding the CIM – Symbology

- Demo

Page 89: Understanding the CIM A Guide for Developers

Understanding the CIM – Symbology

- Versioning- Typens in root elements

Page 90: Understanding the CIM A Guide for Developers

Understanding the CIM – CIM Access

• It is a transactional pattern- Retrieve the model’s CIM definition [Get]- Change the desired properties- Apply the changes back to the model [Set]

var def = layout.GetDefinition();//Change definition as needed//Commit changes backlayout.SetDefinition(def);

SymbolStyleItem si = . . .var symbol = si.Symbol;si.Symbol = symbol;

var renderer = ((FeatureLayer) layer).GetRenderer();((FeatureLayer)layer).SetRenderer(renderer);

AnnotationFeature feature = . . .var graphic = feature.GetGraphic();

Page 91: Understanding the CIM A Guide for Developers

Understanding the CIM

• Accessing the CIM:

public abstract class CIMMultiLayerSymbol : CIMSymbol {public CIMGeometricEffect[] Effects { get; set; }public CIMSymbolLayer[] SymbolLayers { get; set; }