I am trying to use the dimensions in ArcMap but after I dimension a map then close and reopen the map the dimensions are gone and I get a COM error, cannot initialize COM component when I try to edit the properties of the dimension feature class in ArcCatalog. Is there a way to save the dimensions so they do not disappear?
I created a button to recreate the dim style with arcobjects, now I don't get COM initialize error but when I close and reopen arcmap, instead of dimension there are red polygons.
Here is the code I use to create the dimension feature class,
IFeatureLayer pFeatureLayer = (IFeatureLayer)pBoundaryLayer;
IFeatureClass pFeatureClass = pFeatureLayer.FeatureClass;
string strCatalogPath = GetCatalogPath(pFeatureClass);
IWorkspace pWorkspace = FileGDBWorkspaceFromPropertySet(strCatalogPath);
IObjectClassDescription ocDescription = new DimensionClassDescription();
IFields pRequiredFields = ocDescription.RequiredFields;
int intShapeFieldPosition = pRequiredFields.FindField("Shape");
IField pShapeField = pRequiredFields.get_Field(intShapeFieldPosition);
IGeometryDef pGeomDef = pShapeField.GeometryDef;
IGeometryDefEdit pGeomDefEdit = (IGeometryDefEdit)pGeomDef;
ISpatialReferenceFactory3 pSpatRefFac = new SpatialReferenceEnvironmentClass();
ISpatialReference pSpatRef = pSpatRefFac.CreateSpatialReference(6578);
IProjectedCoordinateSystem pProSpatRef = (IProjectedCoordinateSystem)pSpatRef;
ILinearUnit linUnit = pProSpatRef.CoordinateUnit;
pGeomDefEdit.SpatialReference_2 = pSpatRef;
IFeatureWorkspace pFeatWorkspace = (IFeatureWorkspace)pWorkspace;
string pName = "DIM";
IFeatureClass pNewFeatureClass = pFeatWorkspace.CreateFeatureClass(pName.ToString(), pRequiredFields, ocDescription.InstanceCLSID, ocDescription.ClassExtensionCLSID, esriFeatureType.esriFTDimension, "Shape", "");
ISchemaLock schemaLock = (ISchemaLock)pNewFeatureClass;
try
{
schemaLock.ChangeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock);
IDimensionClassExtension dimExtension = (IDimensionClassExtension)pNewFeatureClass.Extension;
dimExtension.ReferenceScale = 12000;
dimExtension.ReferenceScaleUnits = esriUnits.esriFeet;
IDimensionStyle dimensionStyle = new DimensionStyleClass();
dimensionStyle.Name = "BEARING_DISTANCE";
IDimensionStyleText dimText = (IDimensionStyleText)dimensionStyle;
string expression = "def FindLabel ( [DIMLENGTH], [BEGINX] , [BEGINY] , [ENDX] , [ENDY] ):" + Environment.NewLine +
" import math" + Environment.NewLine +
" dY = float([ENDY]) -float( [BEGINY])" + Environment.NewLine +
" dX = float( [ENDX])-float( [BEGINX])" + Environment.NewLine +
" azimuth = math.atan2(dX, dY) * 180 / math.pi" + Environment.NewLine +
" if azimuth < 0:" + Environment.NewLine +
" azimuth = azimuth + 360" + Environment.NewLine +
" if azimuth > 270 and azimuth<= 360:" + Environment.NewLine +
" bearing = 360 - azimuth" + Environment.NewLine +
" minutes,seconds = divmod(bearing * 3600, 60)" + Environment.NewLine +
" degrees,minutes = divmod(minutes, 60)" + Environment.NewLine +
" dmsBearing = \"N \" + str(int(degrees)) + \"°\" + str(int(minutes)) + \"'\" + str(round(seconds, 2)) + \" W\"" + Environment.NewLine +
" return dmsBearing + \" \" + str(round(float( [DIMLENGTH]), 2))+\"'\"" + Environment.NewLine +
" if azimuth > 180 and azimuth<= 270:" + Environment.NewLine +
" bearing = azimuth - 180" + Environment.NewLine +
" minutes,seconds = divmod(bearing * 3600, 60)"+ Environment.NewLine +
" degrees,minutes = divmod(minutes, 60)"+ Environment.NewLine +
" dmsBearing = \"S \" + str(int(degrees)) + \"°\" + str(int(minutes)) + \"'\" + str(round(seconds, 2)) + \" W\"" + Environment.NewLine +
" return dmsBearing + \" \" + str(round(float( [DIMLENGTH]), 2))+\"'\"" + Environment.NewLine +
" if azimuth > 90 and azimuth<= 180:" + Environment.NewLine +
" bearing = 180 - azimuth" + Environment.NewLine +
" minutes,seconds = divmod(bearing * 3600, 60)" + Environment.NewLine +
" degrees,minutes = divmod(minutes, 60)" + Environment.NewLine +
" dmsBearing = \"S \" + str(int(degrees)) + \"°\" + str(int(minutes)) + \"'\" + str(round(seconds, 2)) + \" E\"" + Environment.NewLine +
" return dmsBearing + \" \" + str(round(float( [DIMLENGTH]), 2))+\"'\"" + Environment.NewLine +
" if azimuth >= 0 and azimuth<= 90:" + Environment.NewLine +
" minutes,seconds = divmod(azimuth * 3600, 60)" + Environment.NewLine +
" degrees,minutes = divmod(minutes, 60)" + Environment.NewLine +
" dmsBearing = \"N \" + str(int(degrees)) + \"°\" + str(int(minutes)) + \"'\" + str(round(seconds, 2)) + \" E\"" + Environment.NewLine +
" return dmsBearing + \" \" + str(round(float( [DIMLENGTH]), 2))+\"'\"" + Environment.NewLine +
" else:" + Environment.NewLine +
" if azimuth > 270 and azimuth<= 360:" + Environment.NewLine +
" bearing = 360 - azimuth" + Environment.NewLine +
" minutes,seconds = divmod(bearing * 3600, 60)" + Environment.NewLine +
" degrees,minutes = divmod(minutes, 60)" + Environment.NewLine +
" dmsBearing = \"N \" + str(int(degrees)) + \"°\" + str(int(minutes)) + \"'\" + str(round(seconds, 2)) + \" W\"" + Environment.NewLine +
" return dmsBearing + \" \" + str(round(float( [DIMLENGTH]), 2))+\"'\"" + Environment.NewLine +
" if azimuth > 180 and azimuth<= 270:" + Environment.NewLine +
" bearing = azimuth - 180" + Environment.NewLine +
" minutes,seconds = divmod(bearing * 3600, 60)" + Environment.NewLine +
" degrees,minutes = divmod(minutes, 60)" + Environment.NewLine +
" dmsBearing = \"S \" + str(int(degrees)) + \"°\" + str(int(minutes)) + \"'\" + str(round(seconds, 2)) + \" W\"" + Environment.NewLine +
" return dmsBearing + \" \" + str(round(float( [DIMLENGTH]), 2))+\"'\"" + Environment.NewLine +
" if azimuth > 90 and azimuth<= 180:" + Environment.NewLine +
" bearing = 180 - azimuth" + Environment.NewLine +
" minutes,seconds = divmod(bearing * 3600, 60)" + Environment.NewLine +
" degrees,minutes = divmod(minutes, 60)" + Environment.NewLine +
" dmsBearing = \"S \" + str(int(degrees)) + \"°\" + str(int(minutes)) + \"'\" + str(round(seconds, 2)) + \" E\"" + Environment.NewLine +
" return dmsBearing + \" \" + str(round(float( [DIMLENGTH]), 2))+\"'\"" + Environment.NewLine +
" if azimuth >= 0 and azimuth<= 90:" + Environment.NewLine +
" minutes,seconds = divmod(azimuth * 3600, 60)" + Environment.NewLine +
" degrees,minutes = divmod(minutes, 60)" + Environment.NewLine +
" dmsBearing = \"N \" + str(int(degrees)) + \"°\" + str(int(minutes)) + \"'\" + str(round(seconds, 2)) + \" E\"" + Environment.NewLine +
" return dmsBearing + \" \" + str(round(float( [DIMLENGTH]), 2))+\"'\"";
dimText.Expression = expression;
dimText.ExpressionSimple = false;
dimText.ExpressionParserName = "Python";
dimText.TextDisplay = esriDimensionTextDisplay.esriDimensionTDExpression;
dimText.ExtendLineOnFit = false;
stdole.IFontDisp iFont = new stdole.StdFontClass() as stdole.IFontDisp;
iFont.Name = "Arial";
iFont.Size = 8;
ITextSymbol txtSymbol = new TextSymbol();
txtSymbol.Font = iFont;
dimText.TextSymbol = txtSymbol;
IDimensionStyleDisplay dimDisplay = (IDimensionStyleDisplay)dimensionStyle;
dimDisplay.MarkerDisplay = esriDimensionDisplay.esriDimensionDisplayBoth;
IArrowMarkerSymbol mrkrSym = new ArrowMarkerSymbolClass();
mrkrSym.Size = 6;
IMarkerSymbol newMrkrSym = (IMarkerSymbol)mrkrSym;
dimDisplay.BeginMarkerSymbol = newMrkrSym;
dimDisplay.EndMarkerSymbol = newMrkrSym;
dimDisplay.MarkerFit = esriDimensionMarkerFit.esriDimensionMarkerFitText;
IDimensionStyles dimensionStyles = dimExtension.DimensionStyles;
dimensionStyles.AddStyle(dimensionStyle);
}
catch(COMException comExcept)
{
MessageBox.Show(comExcept.StackTrace.ToString());
}
finally
{
schemaLock.ChangeSchemaLock(esriSchemaLock.esriSharedSchemaLock);
}
Update: I am still trying to persist the dimensions in arcmap I am now using the PersistenceHelper I am having some success persisting the shape but the text expression and line style are not persisting, to persist the DimensionStyleText and DimensionStyleDisplay do I add them to the struct and how do I do that since they are interfaces?
namespace CreateDimensions
{
public class PersistExtension: ESRI.ArcGIS.Desktop.AddIns.Extension
{
private DimStyleStruct dimStyleClass;
[Serializable()]
public struct DimStyleStruct
{
public DimensionStyleClass dimStyle;
}
public PersistExtension()
{
}
protected override void OnSave(Stream outStrm)
{
dimStyleClass = new DimStyleStruct();
dimStyleClass.dimStyle = PersistDimClass.DimStyleClass;
PersistenceHelper.Save<DimStyleStruct>(outStrm, dimStyleClass);
}
protected override void OnLoad(Stream inStrm)
{
dimStyleClass.dimStyle = new DimensionStyleClass();
PersistenceHelper.Load<DimStyleStruct>(inStrm, ref dimStyleClass);
}
}
}
I have made a little more progress and I have rewritten my add-in as arcobjects extension, I use the load and save methods to write to the document stream and I am getting the style I want back in the map but the only thing missing is the custom expression to display bearing and distance.
public void Save(IVariantStream Stream)
{
//TODO: Save extension related data to document stream
if (DimStyleModel.Name != "")
{
Stream.Write(DimStyleModel.Name.ToString());
MessageBox.Show(DimStyleModel.Name.ToString());
Stream.Write(DimStyleModel.RefScale);
Stream.Write(DimStyleModel.Expression);
Stream.Write(DimStyleModel.TextSymbol);
Stream.Write(DimStyleModel.LineSymbol);
Stream.Write(DimStyleModel.MrkrSymbol);
}
Marshal.ReleaseComObject(Stream);
}
public void Load(IVariantStream Stream)
{
//TODO: Load persisted data from document stream
if(Stream!=null)
{
string sName = "";
int iRefScale = 0;
string sExpression = "";
ITextSymbol pTextSymbol = null;
ILineSymbol pLineSymbol = null;
IMarkerSymbol pMrkrSymbol = null;
sName = (string)Stream.Read();
iRefScale = (int)Stream.Read();
sExpression = (string)Stream.Read();
pTextSymbol = (ITextSymbol)Stream.Read();
pLineSymbol = (ILineSymbol)Stream.Read();
pMrkrSymbol = (IMarkerSymbol)Stream.Read();
ILayer pLayer = ReturnLayerByName("DIM");
IFeatureLayer pFeatureLayer = (IFeatureLayer)pLayer;
IFeatureClass pFeatureClass = pFeatureLayer.FeatureClass;
ISchemaLock pSchemaLock = (ISchemaLock)pFeatureClass;
try
{
pSchemaLock.ChangeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock);
IDimensionClassExtension pDimExt = (IDimensionClassExtension)pFeatureClass.Extension;
pDimExt.ReferenceScale = iRefScale;
pDimExt.ReferenceScaleUnits = esriUnits.esriFeet;
IDimensionStyle pDimStyle = new DimensionStyleClass
{
Name = sName
};
IDimensionStyleDisplay pNewDimDisplay = (IDimensionStyleDisplay)pDimStyle;
pNewDimDisplay.MarkerDisplay = esriDimensionDisplay.esriDimensionDisplayBoth;
pNewDimDisplay.DimensionLineSymbol = pLineSymbol;
pNewDimDisplay.BeginMarkerSymbol = pMrkrSymbol;
pNewDimDisplay.EndMarkerSymbol = pMrkrSymbol;
pNewDimDisplay.MarkerFit = esriDimensionMarkerFit.esriDimensionMarkerFitText;
pNewDimDisplay.MarkerDisplay = esriDimensionDisplay.esriDimensionDisplayBoth;
pNewDimDisplay.DrawLineOnFit = false;
IDimensionStyleText pNewDimText = (IDimensionStyleText)pDimStyle;
pNewDimText.Expression = sExpression;
pNewDimText.ExpressionParserName = "Python";
pNewDimText.TextDisplay = esriDimensionTextDisplay.esriDimensionTDExpression;
pNewDimText.TextSymbol = pTextSymbol;
pDimExt.UpdateProperties();
IDimensionStyles pDimStyles = pDimExt.DimensionStyles;
pDimStyles.AddStyle(pDimStyle);
}
catch (COMException comExcept)
{
MessageBox.Show(comExcept.StackTrace.ToString());
}
finally
{
pSchemaLock.ChangeSchemaLock(esriSchemaLock.esriSharedSchemaLock);
}
}
Marshal.ReleaseComObject(Stream);
}
Next step I am going to tyr and add the expression in the load method,