So width is a slightly ambiguous term. If you mean the width of the line symbol being used then the answer is it depends. If your features are being symbolized with a "simple" line symbol, then yes. Simply access the stroke layer(s) and retrieve the (max) width. The width will be in points and will need to be converted to the units of the map if you want the width in map units. For more complicated line symbology with multiple layers and various geometric offsets applied, visual variables, etc, etc then it could be much more difficult.
So, this is the simple case, assuming a UVR and we are retrieving the overall max width - u will need to modify if u are interested in just the max width of a particular class (or group):
//access the layer CIM Definition
//QTR.Run(()=> ...
var def = featLayer.GetDefinition() as CIMFeatureLayer;
var uvr = def.Renderer as CIMUniqueValueRenderer;
double maxWidth = 0.0;
foreach (var group in uvr.Groups) {
foreach (var valclass in group.Classes) {
var symbol = valclass.Symbol as CIMLineSymbol;
if (symbol == null) continue;
var sym_layers = ((CIMLineSymbol)symbol).SymbolLayers.ToList();
foreach (var sl in sym_layers) {
//assuming no offsets, etc.
if (sl is CIMStroke stroke) {
maxWidth = Math.Max(maxWidth, stroke.GetWidth());
//TODO - convert width in points to map units as needed
public static class CIMStrokeExtensions {
public static double GetWidth(this CIMStroke cimstroke) {
if (cimstroke is CIMSolidStroke)
return ((CIMSolidStroke) cimstroke).Width;
else if (cimstroke is CIMPictureStroke)
return ((CIMPictureStroke)cimstroke).Width;
else if (cimstroke is CIMGradientStroke)
return ((CIMGradientStroke)cimstroke).Width;
return 0;
}
You could also attempt to calculate the width using the graphic outline - a polygon generated from the feature and its renderer that "matches" the graphical outline of the given feature (whether point, line, poly, or anno). Essentially, the outline polygon is equivalent to the masking polygon for "that" feature. The mask polygon will take into consideration all aspects of the renderer + visual variables, etc. so it is much more sophisticated but...it is a polygon and it is not necessarily straightforward to derive the feature "width" depending on the underlying shape/curvature of a particular line.
To retrieve the graphical outline of a feature: featLayer.GetDrawingOutline(....) (note: this was QueryDrawingOutline at 2.x but the usage was the same)
//QTR.Run(()=> ..
var outline = featLayer.QueryDrawingOutline(oid, MapView.Active,
DrawingOutlineType.Exact) as Polygon;
So width is a slightly ambiguous term. If you mean the width of the line symbol being used then the answer is it depends. If your features are being symbolized with a "simple" line symbol, then yes. Simply access the stroke layer(s) and retrieve the (max) width. The width will be in points and will need to be converted to the units of the map if you want the width in map units. For more complicated line symbology with multiple layers and various geometric offsets applied, visual variables, etc, etc then it could be much more difficult.
So, this is the simple case, assuming a UVR and we are retrieving the overall max width - u will need to modify if u are interested in just the max width of a particular class (or group):
//access the layer CIM Definition
//QTR.Run(()=> ...
var def = featLayer.GetDefinition() as CIMFeatureLayer;
var uvr = def.Renderer as CIMUniqueValueRenderer;
double maxWidth = 0.0;
foreach (var group in uvr.Groups) {
foreach (var valclass in group.Classes) {
var symbol = valclass.Symbol as CIMLineSymbol;
if (symbol == null) continue;
var sym_layers = ((CIMLineSymbol)symbol).SymbolLayers.ToList();
foreach (var sl in sym_layers) {
//assuming no offsets, etc.
if (sl is CIMStroke stroke) {
maxWidth = Math.Max(maxWidth, stroke.GetWidth());
//TODO - convert width in points to map units as needed
public static class CIMStrokeExtensions {
public static double GetWidth(this CIMStroke cimstroke) {
if (cimstroke is CIMSolidStroke)
return ((CIMSolidStroke) cimstroke).Width;
else if (cimstroke is CIMPictureStroke)
return ((CIMPictureStroke)cimstroke).Width;
else if (cimstroke is CIMGradientStroke)
return ((CIMGradientStroke)cimstroke).Width;
return 0;
}
You could also attempt to calculate the width using the graphic outline - a polygon generated from the feature and its renderer that "matches" the graphical outline of the given feature (whether point, line, poly, or anno). Essentially, the outline polygon is equivalent to the masking polygon for "that" feature. The mask polygon will take into consideration all aspects of the renderer + visual variables, etc. so it is much more sophisticated but...it is a polygon and it is not necessarily straightforward to derive the feature "width" depending on the underlying shape/curvature of a particular line.
To retrieve the graphical outline of a feature: featLayer.GetDrawingOutline(....) (note: this was QueryDrawingOutline at 2.x but the usage was the same)
//QTR.Run(()=> ..
var outline = featLayer.QueryDrawingOutline(oid, MapView.Active,
DrawingOutlineType.Exact) as Polygon;
Hi, thank you very much for the advice, it helped me a lot.
You can also use the CIMViewer add-in to inspect the composition of your layer symbology. A download for 3.0 is available here: Release ArcGIS Pro 3.0 SDK for .NET · Esri/arcgis-pro-sdk-cim-viewer (github.com)
If you run ArcGIS Pro 2.x you have to clone the CIMViewer repo's source code and build the 2.x esriaddinx. The 2.x CIMViewer solution is called: CIMViewer.sln in the same GitHub repo.