Retrieving symbology info from ArcMap document (.mxd)

1782
4
Jump to solution
02-23-2021 01:29 PM
HannahBernal
New Contributor II

Hello,

I wish to retrieve symbology information from a mxd file I created from ArcMap 10.6.2 using the ArcGIS Pro API. Since I want to do this when the Pro application is not running, I cannot access the classes or interfaces under the ArcGIS.Desktop namespace.

Arc objects equivalent to what is needed would be the IMapDocument and IMapReader objects that allowed a map object to be created from the the mxd file path that has symbology information for every feature layer.

Would it be possible to retrieve this kind of information from the mxd file, or would the mxd file need to be converted to another type of file to be useable outside of Pro? From what I've researched so far, the .mapx file seems to have the symbology info I'm looking for. If it's possible to convert mxd to mapx, how would the mapx file be parsed through to get and save its symbology?

Thank you in advance,

Hannah

1 Solution

Accepted Solutions
KirkKuykendall1
Occasional Contributor III

Do you have access to the ArcObjects SDK?

If so, it might be easier to write an ArcObjects app that translates renderers, symbols etc. from ArcObjects into CIM objects.  Esri seems to be using CIM as the common foundation across all apps - except for Arcmap.

All CIM objects can be serialized to json.  A symbology translator could read from mxds (using ArcObjects) and write json files (using ArcGIS.Core.CIM).  You could then have a Pro Addin to deserialize the json to display it in Pro.  I suspect it would take a lot of tweaking to make it look right.

In the code below I created a new ArcObjects console app, changed the target framework to 4.8, and added a reference to C:\Program Files\ArcGIS\Pro\bin\ArcGIS.Core.dll, which fortunately is compatible with 32 bit.

 

using ESRI.ArcGIS.esriSystem;
using System;
using System.Collections.Generic;
using System.Text;
using ArcGIS.Core.CIM;
using System.Diagnostics;

namespace ArcObjectsConsoleApplication1
{
    class Program
    {
        private static LicenseInitializer m_AOLicenseInitializer = 
            new ArcObjectsConsoleApplication1.LicenseInitializer();

        [STAThread()]
        static void Main(string[] args)
        {
            //ESRI License Initializer generated code.
            m_AOLicenseInitializer.InitializeApplication(
                new esriLicenseProductCode[] 
                { 
                    esriLicenseProductCode.esriLicenseProductCodeAdvanced 
                },
                new esriLicenseExtensionCode[] { }
                );
            // todo: open mxd and read ISymbol stuff...

            //todo: populate CIM objects using ArcObjects ISymbol stuff.
            var renderer = new CIMSimpleRenderer()
            {
                Patch = PatchShape.Default,
                Symbol = new CIMSymbolReference()
                {
                    Symbol = new CIMPointSymbol()
                }
            };
            // serialize out to a file...
            Debug.Print(renderer.ToJson());

            //ESRI License Initializer generated code.
            //Do not make any call to ArcObjects after ShutDownApplication()
            m_AOLicenseInitializer.ShutdownApplication();
        }
    }
}

 

 

Output: 

 

{
  "type": "CIMSimpleRenderer",
  "patch": "Default",
  "symbol": {
    "type": "CIMSymbolReference",
    "symbol": {
      "type": "CIMPointSymbol",
      "haloSize": 1,
      "scaleX": 1,
      "angleAlignment": "Display"
    }
  }
}

 

 

View solution in original post

0 Kudos
4 Replies
KirkKuykendall1
Occasional Contributor III

Do you have access to the ArcObjects SDK?

If so, it might be easier to write an ArcObjects app that translates renderers, symbols etc. from ArcObjects into CIM objects.  Esri seems to be using CIM as the common foundation across all apps - except for Arcmap.

All CIM objects can be serialized to json.  A symbology translator could read from mxds (using ArcObjects) and write json files (using ArcGIS.Core.CIM).  You could then have a Pro Addin to deserialize the json to display it in Pro.  I suspect it would take a lot of tweaking to make it look right.

In the code below I created a new ArcObjects console app, changed the target framework to 4.8, and added a reference to C:\Program Files\ArcGIS\Pro\bin\ArcGIS.Core.dll, which fortunately is compatible with 32 bit.

 

using ESRI.ArcGIS.esriSystem;
using System;
using System.Collections.Generic;
using System.Text;
using ArcGIS.Core.CIM;
using System.Diagnostics;

namespace ArcObjectsConsoleApplication1
{
    class Program
    {
        private static LicenseInitializer m_AOLicenseInitializer = 
            new ArcObjectsConsoleApplication1.LicenseInitializer();

        [STAThread()]
        static void Main(string[] args)
        {
            //ESRI License Initializer generated code.
            m_AOLicenseInitializer.InitializeApplication(
                new esriLicenseProductCode[] 
                { 
                    esriLicenseProductCode.esriLicenseProductCodeAdvanced 
                },
                new esriLicenseExtensionCode[] { }
                );
            // todo: open mxd and read ISymbol stuff...

            //todo: populate CIM objects using ArcObjects ISymbol stuff.
            var renderer = new CIMSimpleRenderer()
            {
                Patch = PatchShape.Default,
                Symbol = new CIMSymbolReference()
                {
                    Symbol = new CIMPointSymbol()
                }
            };
            // serialize out to a file...
            Debug.Print(renderer.ToJson());

            //ESRI License Initializer generated code.
            //Do not make any call to ArcObjects after ShutDownApplication()
            m_AOLicenseInitializer.ShutdownApplication();
        }
    }
}

 

 

Output: 

 

{
  "type": "CIMSimpleRenderer",
  "patch": "Default",
  "symbol": {
    "type": "CIMSymbolReference",
    "symbol": {
      "type": "CIMPointSymbol",
      "haloSize": 1,
      "scaleX": 1,
      "angleAlignment": "Display"
    }
  }
}

 

 

0 Kudos
HannahBernal
New Contributor II

Thank you very much for your response, Kirk. The application I'm working on is using the ArcGIS Pro SDK. Would it still be possible to use ArcObjects in this case? If not, is there an equivalent way to do this just in the Pro SDK?

0 Kudos
KirkKuykendall1
Occasional Contributor III

ArcGIS Pro and ArcMap can be installed "side by side" -  they are different applications entirely.  Same with the SDKs.  I've got SDKs for both ArcObjects and Pro installed with VS2019.

That being said, it seems like ItemFactory would use some subset of ArcObjects behind the scenes to import mxds, but I don't see any methods ItemFactory exposes that would let you get at the internals.

Since you said "I want to do this when the Pro application is not running", I take that to mean you'd like to write a standalone app.  I'm not certain, but I don't think lyrx files can be generated from a CoreHost app.

Arcmap is only slightly CIM-aware.  When I use the Create Runtime Content tool from within Arcmap, it creates a folder that contains a sqlite geodatabase.  Within that geodatabase is a table for each layer with an AdvancedDrawingInfo column.  The json in that table looks like this:

{
   "drawingInfo":{
      "renderer":{
         "type":"simple",
         "symbol":{
            "type":"CIMSymbolReference",
            "symbol":{
               "type":"CIMLineSymbol",
               "symbolLayers":[
                  {
                     "type":"CIMFilledStroke",
                     "enable":true,
                     "colorLocked":false,
                     "capStyle":"Round",
                     "pattern":{
                        "type":"CIMSolidPattern",
                        "color":[
                           140,
                           0,
                           16,
                           255
                        ]
                     },
                     "width":1,
                     "lineStyle3D":"Strip",
                     "alignment":"Center",
                     "joinStyle":"Round",
                     "miterLimit":10,
                     "patternFollowsStroke":true
                  }
               ]
            },
            "symbolName":"Symbol_1"
         },
         "label":"",
         "description":""
      },
      "transparency":0,
      "labelingInfo":null
   }
}

 

So maybe there would be some way to use Runtime Content as a way to migrate symbology.  I suspect it's only capable of very simple symbols, but might be worth a try.

0 Kudos
HannahBernal
New Contributor II

Hi Kirk,

We decided to use the mapx file instead of the mxd file to retrieve the symbology info from our map. Your example solution did help me understand the JSON format that the data comes in, in which I found can be easily used to create CIM objects.

Thank you for your help and response,

Hannah

0 Kudos