About adjusting features using spatial adjustment methods
In the ArcMap user interface (UI), spatial adjustments are performed by defining displacement links, the features that will be adjusted, and the transformation method that will be applied.
In the application programming interface (API), you define the links as two point arrays representing the from and to ends of displacement links. The number of required displacement links is based on the type of transformation to be applied. Each transformation defines this number, which can be accessed via ITransformationMethod.MinNumDisplacementPoints.
The transformation is then defined by the methods and properties on ITransformationMethod. To perform the transformation, call ITransformationMethod.Transform passing a feature cursor of the features you want to adjust.
The following transformations are supported in ArcGIS:
- AffineTransformationMethod
- ConformalTransformationMethod (similarity transformation)
- EdgeSnapTransformationMethod
- PiecewiseTransformationMethod (used for rubber sheeting)
- ProjectiveTransformationMethod
The following code shows an example of these steps:
Make sure to change the x,y coordinates for the control points and the query filter's WHERE clause based on your data.
// This method performs an affine transformation on features.
//Create control points for the transformation.
//Normally, these come from the from/to ends of displacement links.
List < IPoint > fromPoints = new List < IPoint > ();
fromPoints.Add(CreatePoint(5566626.728, 4948245.103));
fromPoints.Add(CreatePoint(5566858.655, 4948246.713));
fromPoints.Add(CreatePoint(5566686.32, 4948088.874));
IPoint[] fromPointsArray = fromPoints.ToArray();
List < IPoint > toPoints = new List < IPoint > ();
toPoints.Add(CreatePoint(5566895.699, 4948111.423));
toPoints.Add(CreatePoint(5566744.302, 4947960.026));
toPoints.Add(CreatePoint(5567013.273, 4947989.017));
IPoint[] toPointsArray = toPoints.ToArray();
//Define control points.
ITransformationMethodGEN transformMethod = new AffineTransformationMethodClass();
IMxDocument mxDoc = m_application.Document as IMxDocument;
try
{
transformMethod.DefineFromControlPoints(ref fromPointsArray, ref toPointsArray,
null, mxDoc.ActiveView.Extent);
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("Define Control Points failed.");
}
//Create a feature cursor based on the predefined query.
IFeatureLayer featureLayer = mxDoc.FocusMap.get_Layer(0)as IFeatureLayer;
if (featureLayer == null)
{
System.Windows.Forms.MessageBox.Show(
"Please load a feature layer as the first layer in TOC.");
return ;
}
IFeatureClass featureClass = featureLayer.FeatureClass;
IQueryFilter queryFilter = new QueryFilterClass();
queryFilter.WhereClause = "diameter = 10";
IFeatureCursor featureCursor = featureClass.Search(queryFilter, false);
//Transform features.
IWorkspaceEdit workspaceEdit = featureClass.FeatureDataset.Workspace as
IWorkspaceEdit;
workspaceEdit.StartEditOperation();
transformMethod.Transform(featureCursor, null);
workspaceEdit.StopEditOperation();
//Refresh the active view.
mxDoc.ActiveView.Refresh();
private IPoint CreatePoint(double xVal, double yVal)
{
//This function creates a point.
IPoint point = new PointClass();
point.X = xVal;
point.Y = yVal;
return point;
}
[VB.NET]
'Perform an affine transformation on features.
'Create control points for the transformation.
'Normally, these come from the from/to ends of displacement links.
Dim fromPoints As List(Of IPoint) = New List(Of IPoint)
fromPoints.Add(CreatePoint(5566626.728, 4948245.103))
fromPoints.Add(CreatePoint(5566858.655, 4948246.713))
fromPoints.Add(CreatePoint(5566686.32, 4948088.874))
Dim fromPointsArray() As IPoint = fromPoints.ToArray()
Dim toPoints As List(Of IPoint) = New List(Of IPoint)
toPoints.Add(CreatePoint(5566895.699, 4948111.423))
toPoints.Add(CreatePoint(5566744.302, 4947960.026))
toPoints.Add(CreatePoint(5567013.273, 4947989.017))
Dim toPointsArray() As IPoint = toPoints.ToArray()
'Define control points.
Dim transformMethod As ITransformationMethodGEN = New AffineTransformationMethodClass()
Dim mxDoc As IMxDocument = TryCast(m_application.Document, IMxDocument)
Try
transformMethod.DefineFromControlPoints(fromPointsArray, _
toPointsArray, Nothing, mxDoc.ActiveView.Extent)
Catch ex As Exception
System.Windows.Forms.MessageBox.Show("Define Control Points failed.")
End Try
'Create a feature cursor based on the predefined query.
Dim featureLayer As IFeatureLayer = TryCast(mxDoc.FocusMap.Layer(0), IFeatureLayer)
If (featureLayer Is Nothing) Then
System.Windows.Forms.MessageBox.Show("Please load a feature layer as the first layer in TOC.")
Return
End If
Dim featureClass As IFeatureClass = featureLayer.FeatureClass
Dim queryFilter As IQueryFilter = New QueryFilterClass()
queryFilter.WhereClause = "diameter = 10"
Dim featureCursor As IFeatureCursor = featureClass.Search(queryFilter, False)
'Transform features.
Dim workspaceEdit As IWorkspaceEdit = TryCast(featureClass.FeatureDataset.Workspace, IWorkspaceEdit)
workspaceEdit.StartEditOperation()
transformMethod.Transform(featureCursor, Nothing)
workspaceEdit.StopEditOperation()
'Refresh the active view.
mxDoc.ActiveView.Refresh()
Private Function CreatePoint(ByVal xVal As Double, ByVal yVal As Double) As IPoint
'This function creates a point.
Dim point As IPoint = New PointClass()
point.X = xVal
point.Y = yVal
Return point
End Function
Creating displacement links
In some cases, it might be advantageous when working with large numbers of known coordinates to define displacement links programmatically rather than manually entering a pair of coordinates.
The following code example shows how to create displacement links:
[C#]
public void CreateDisplacementLink()
{
//Create a displacement link from two points.
//Get the map and reset graphics container.
IMxDocument mxDocument = m_application.Document as IMxDocument;
IMap map = mxDocument.FocusMap;
IGraphicsContainer graphicsContainer = map as IGraphicsContainer;
graphicsContainer.Reset();
//Get the link symbol from the adjustment extension.
IAdjustment adjustment = m_application.FindExtensionByName(
"ESRI Adjustment Tools")as IAdjustment;
IAdjustProperties adjustmentProperties = adjustment as IAdjustProperties;
ILineSymbol linkSymbol = adjustmentProperties.DisplacementLinkSymbol;
//Create the polyline from two points.
IPoint fromPoint = new PointClass();
fromPoint.PutCoords(115, - 32);
IPoint toPoint = new PointClass();
toPoint.PutCoords(116, - 31);
IPolyline polyLine = new PolylineClass();
polyLine.FromPoint = fromPoint;
polyLine.ToPoint = toPoint;
//Instantiate a new displacement link and set symbology.
IDisplacementLinkElement link = new DisplacementLinkElementClass();
link.Symbol = linkSymbol;
IElement element = link as IElement;
//Set the geometry and add to the graphics container.
element.Geometry = polyLine;
graphicsContainer.AddElement(element, 0);
//Refresh the graphics.
mxDocument.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null,
null);
}
[VB.NET]
'Create a displacement link from two points
'Get the map and graphics container
Dim pMxDoc As IMxDocument = My.ArcMap.Document
Dim pMap As IMap = pMxDoc.FocusMap
Dim pGraCon As IGraphicsContainer = pMap
pGraCon.Reset()
'Get the link symbol from the adjustment extension
Dim pAdjust As IAdjustment = My.ArcMap.Application.FindExtensionByName("ESRI Adjustment Tools")
Dim pAdjustProp As IAdjustProperties = pAdjust
Dim pLinkSymbol As ILineSymbol = pAdjustProp.DisplacementLinkSymbol
'Create the polyline from two points
Dim pFromPoint As IPoint
pFromPoint = New Point
pFromPoint.PutCoords(115, -32)
Dim pToPoint As IPoint
pToPoint = New Point
pToPoint.PutCoords(116, -31)
Dim pPolyLine As IPolyline
pPolyLine = New Polyline
pPolyLine.FromPoint = pFromPoint
pPolyLine.ToPoint = pToPoint
'Instantiate a new displacement link and set symbology
Dim pLink As IDisplacementLinkElement
pLink = New DisplacementLinkElement
pLink.Symbol = pLinkSymbol
Dim pElement As IElement = pLink
'Set the geometry and add to the graphics container
pElement.Geometry = pPolyLine
pGraCon.AddElement(pElement, 0)
'Refresh the graphics
pMxDoc.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, Nothing, Nothing)
To use the code in this topic, reference the following assemblies in your Visual Studio project. In the code files, you will need using (C#) or Imports (VB .NET) directives for the corresponding namespaces (given in parenthesis below if different from the assembly name):
ESRI.ArcGIS.Framework ESRI.ArcGIS.ArcMapUI ESRI.ArcGIS.Geodatabase ESRI.ArcGIS.Carto ESRI.ArcGIS.Geometry ESRI.ArcGIS.EditorExt System.Collections.Generic
Development licensing | Deployment licensing |
---|---|
ArcGIS for Desktop Basic | ArcGIS for Desktop Basic |
ArcGIS for Desktop Standard | ArcGIS for Desktop Standard |
ArcGIS for Desktop Advanced | ArcGIS for Desktop Advanced |