ProConcepts Editing Dimensions - Esri/arcgis-pro-sdk GitHub Wiki
This concepts document covers special considerations for authors of editing tools for dimensions. It augments the overall dimension concepts covered in ProConcepts Dimensions.
ArcGIS.Core.dll
ArcGIS.Desktop.Editing.dll
Language: C#
Subject: Dimensions
Contributor: ArcGIS Pro SDK Team <[email protected]>
Organization: Esri, http://www.esri.com
Date: 10/06/2024
ArcGIS Pro: 3.4
Visual Studio: 2022
This concepts document augments the overall dimension concepts covered in ProConcepts Dimensions. Dimension features differ from other geodatabase features in a few small but fundamental ways. It is important to keep these in mind when developing custom dimension editing tools.
Similar to annotation feature classes, the dimension feature class stores polygon geometry. This polygon is the boundary of the dimension feature. It is automatically updated by the application each time the dimension attributes are modified. You should never need to access or modify a dimension feature's polygon shape.
A dimension feature requires that a specific number of points be entered into the edit sketch to describe it's geometry. The key coordinates for a dimension feature are the begin and end points, the dimension line point and the text point. These are stored as groups of x and y fields on the feature class itself. To modify the shape of a dimension feature, you must modify one or more of these x and y field pairs.
The begin and end dimension points define the dimension's measurement points. The dimension line point determines the height of the dimension line above the baseline. And the text point defines a custom text location. In many situations the text point x and y are null, meaning that the text is at it's default location - the midpoint of the baseline.
A dimension feature class has a collection of one or more styles associated with it. These styles are defined when the feature class is created. Every time you create a new dimension feature, you assign it one of these predefined styles. The style contains properties that describe how the dimension feature is displayed, such as the start point and end point symbols, the dimension line symbol and the text font, style and size.
You can retrieve the style classes for a dimension feature class by accessing its DimensionFeatureClassDefinition. This can be achieved using code similar to the following:
// must be executed on the MCT - wrap in a QueuedTask.Run
// get the dimension layer
DimensionLayer dimLayer = CurrentTemplate.Layer as DimensionLayer;
if (dimLayer == null)
return false;
// get the dimension feature class
var fc = dimLayer.GetTable() as ArcGIS.Core.Data.Mapping.DimensionFeatureClass;
if (fc == null)
return false;
// get the featureclass definition which contains the style collections
var cimDefinition = fc.GetDefinition() as ArcGIS.Core.Data.Mapping.DimensionFeatureClassDefinition;
var styles = cimDefinition.GetDimensionStyles();
Use a value in this collection to set the StyleID field when creating or modifying dimension features.
If you find over time, that the styles created do not contain the properties you need for additional dimension features, you must create a new style with the new properties, then assign the new style to the dimension features. You cannot overwrite individual properties on the style on a feature-by-feature basis like you can with annotation symbols.
By default, dimension feature classes are created with a predefined set of system fields. These fields are guaranteed to exist in the physical schema and cannot be deleted by the user. Because of this, it is possible to use the Inspector object to access or modify dimension features as you would with standard geodatabase features.
Writing a construction tool for dimension features is very similar to writing a construction tool for point, line or polygon data. Use the ArcGIS Pro Construction Tool template in Visual Studio to create a construction tool. Configure the categoryRefID tag in the config.daml file for your tool to be esri_editing_construction_dimension
. Dimension features are required to be created using a multipoint geometry so set the SketchType
property in the constructor code to be SketchGeometryType.Multipoint.
<tool id="DimensionTools_MyDimConstructionTool"
categoryRefID="esri_editing_construction_dimension"
caption="MyDimConstructionTool" className="MyDimConstructionTool"
loadOnClick="true"
smallImage="Images\GenericButtonRed16.png"
largeImage="Images\GenericButtonRed32.png">
<tooltip heading="Tooltip Heading">dimension<disabledText /></tooltip>
</tool>
public MyDimConstructionTool()
{
IsSketchTool = true;
UseSnapping = true;
// Select the type of construction tool you wish to implement.
SketchType = SketchGeometryType.Multipoint;
}
The most important part of a dimension construction tool is determining when to finish the sketch. As previously mentioned, even though the shape of a dimension feature is a polygon, a multipoint is required to be passed to the EditOperation.Create method. Dimension features can be created with 2, 3 or 4 points within the multipoint. Two points specify the Begin and End dimension points with a null dimension Line point and a null Text point. Three points means defining the dimension Line point in addition to the Begin and End points. Finally with four points; you have the Begin and End dimension points, Line Point and Text Point defined.
As the construction tool author, you decide how many points your tool requires. This is accomplished by overriding the OnSketchModifiedAsync
method and forcing the sketch to finish when it matches the required number of points. Here is an example of how to force the sketch to finish after the user clicks 2 times.
protected override async Task<bool> OnSketchModifiedAsync()
{
// restrict the sketch to 2 points
bool finish = await QueuedTask.Run(async () =>
{
// get the current sketch
var geometry = await base.GetCurrentSketchAsync();
// cast to a Multipoint
var geom = geometry as ArcGIS.Core.Geometry.Multipoint;
// check the point count
return geom?.PointCount >= 2;
});
// call FinishSketchAsync if we have 2 points
if (finish)
finish = await base.FinishSketchAsync();
return finish;
}
The OnSketchCompleteAsync method as defined by the Visual Studio template wizard does not require any additional modifications in order for the construction tool to be completed. An edit operation is created, the Create method is called using the CurrentTemplate and sketch geometry (restricted to a 2 point multipoint as per the OnSketchModifiedAsync method) and then finally the ExecuteAsync method is called.
/// <summary>
/// Called when the sketch finishes. This is where we will create the sketch operation and then execute it.
/// </summary>
/// <param name="geometry">The geometry created by the sketch.</param>
/// <returns>A Task returning a Boolean indicating if the sketch complete event was successfully handled.</returns>
protected override Task<bool> OnSketchCompleteAsync(Geometry geometry)
{
if (CurrentTemplate == null || geometry == null)
return false;
// Create an edit operation
var createOperation = new EditOperation();
createOperation.Name = string.Format("Create {0}", CurrentTemplate.Layer.Name);
createOperation.SelectNewFeatures = true;
// Queue feature creation
createOperation.Create(CurrentTemplate, geometry);
// Execute the operation
return createOperation.ExecuteAsync();
}
Modifying dimension features should follow similar patterns to modifying point, line or polygon features. That is; create an Inspector object, load the appropriate feature, modify the necessary attributes, then call EditOperation.Modify passing the updated Inspector object. Here is an example showing how to update the StyleID of a dimension feature
// must be executed on the MCT - wrap in a QueuedTask.Run
// get the dimension feature class
var fc = dimLayer.GetTable() as ArcGIS.Core.Data.Mapping.DimensionFeatureClass;
if (fc == null)
return;
// get the featureclass definition which contains the style collections
var cimDefinition = fc.GetDefinition() as ArcGIS.Core.Data.Mapping.DimensionFeatureClassDefinition;
var styles = cimDefinition.GetDimensionStyles();
// make sure there are styles
if (styles.Count == 0)
return;
// load the inspector with a feature
var insp = new Inspector();
insp.Load(dimLayer, oids);
string oldStyleID = insp["styleID"].ToString();
int int_styleID = Convert.ToInt32(styleID);
int newStyleID = -1;
foreach (var style in styles)
{
// if it's different
if (style.ID != int_styleID)
newStyleID = style.ID;
}
if (newStyleID == -1)
{
// the dimension feature class requires more than 1 style in
// order to assign a new style
return;
}
insp["styleID"] = newStyleID;
var op = new EditOperation();
op.Modify(insp);
bool result = op.Execute();
If you are interested in displaying a custom length rather than the dimension length, modify the UseCustomLength and CustomLength fields. To change the dimension display, modify the DimDisplay (are dimension lines displayed?), MarkerDisplay (are dimension symbols displayed?) or ExtDisplay (are the extension lines displayed?) fields. All three fields have a range of 0-3 indicating Both (0), Begin (1), End (2), None (3). The coordinates of the dimension components are represented by the BeginX, BeginY, EndX, EndY, DimX, DimY and TextX and TextY fields. Finally modify the ExtAngle field to change the extension line angle (stored in radians). And the TextAngle field to change the dimension text angle (stored in radians).
Similar to editing of other geometry types, you can load multiple dimension features into the inspector, assign values via the Inspector class and have those values be applied to all features loaded in the inspector.
The Inspector class is also the recommended pattern for creating dimension templates. Rather than dealing directly with the CIM as in previous releases, the CreateTemplate method facilitates template creation with a populated Inspector object. You can also easily assign the template name, description, tags, default tool and tool filter with the same call.
// must be executed on the MCT - wrap in a QueuedTask.Run
// load the schema
insp = new Inspector();
insp.LoadSchema(dimLayer);
// set up the StyleID field - required field
// ok to access the field this way - it is guaranteed to exist
insp["StyleID"] = style.ID;
// set default values for other dimension fields as necessary using Inspector
// set up tags
var tags = new[] { "Dimension", "tag1", "tag2" };
// set up default tool - use daml-id rather than guid
string defaultTool = "esri_editing_AlignedDimensionTool";
// create a new CIM template - new extension method
var newTemplate = dimLayer.CreateTemplate("My new template", "sample description",
insp, defaultTool, tags);