How to Scale a Dataset
This VBA code demonstrates
how to scale an ArcGIS Shapefile dataset and re-center it on the original
dataset.
Eicher GIS, LLC
Option Explicit
Const SCALE_FACTOR = 5
Sub ScalePolygons()
' .mxd setup:
' First layer should be original
poly shapes
' Second layer empty poly shape file
where scaled shapes will be stored
' ----------------------------------------------------------------------
' logic:
' 1) TRANSLATE to set false origin at lower left of extent
of all polys
'
' 2) apply SCALE transformation to every x, y point
(locations
' based on false origin
'
' 3) TRANSLATE all points by fixed x and y shift so that
' center of new dataset extent
equals center of
' orig dataset extent
'
' 4) TRANSLATE to undo 1)
'
' ----------------------------------------------------------------------
Dim pMxDoc As IMxDocument
Set pMxDoc = ThisDocument
Dim pOriginalLayer As IFeatureLayer
Set pOriginalLayer =
pMxDoc.ActiveView.FocusMap.Layer(0)
Dim pGeoDataset As IGeoDataset
Set pGeoDataset = pOriginalLayer
' get envelope of orig dataset
Dim pOrigEnv As IEnvelope
Set pOrigEnv = pGeoDataset.Extent
' get coordinates of lower left corner of dataset
Dim dblDSLowerLeftX As Double
dblDSLowerLeftX = pOrigEnv.LowerLeft.X
Dim dblDSLowerLeftY As Double
dblDSLowerLeftY = pOrigEnv.LowerLeft.Y
' calc width and height of scaled dataset
Dim dblNewDSHeight As Double
Dim dblNewDSWidth As Double
dblNewDSHeight = pOrigEnv.Height * SCALE_FACTOR
dblNewDSWidth = pOrigEnv.Width * SCALE_FACTOR
' calc x and y translation distances to move scaled
' dataset points so that scaled dataset
is
' centered on orig dataset
Dim dblXAdjust As Double
Dim dblYAdjust As Double
dblXAdjust = (dblNewDSWidth - pOrigEnv.Width) / 2
dblYAdjust = (dblNewDSHeight - pOrigEnv.Height) / 2
' setup output feature class for writing
Dim pOutFeatLayer As IFeatureLayer
Set pOutFeatLayer =
pMxDoc.ActiveView.FocusMap.Layer(1)
Dim pOutFeatClass As IFeatureClass
Set pOutFeatClass = pOutFeatLayer.FeatureClass
Dim pInsertCursor As IFeatureCursor
Set pInsertCursor = pOutFeatClass.Insert(True)
Dim pFeatBuf As IFeatureBuffer
Set pFeatBuf = pOutFeatClass.CreateFeatureBuffer
' declare variables that we'll use in the loop
Dim pPoint As IPoint
Dim pPoly As IPolygon
Dim pPolyPointColl As IPointCollection
Dim i As Integer
Dim p
Dim pNewPoly As IPolygon
Dim pNewPolyPointColl As IPointCollection
Dim pNewPolyTopoOper As ITopologicalOperator
' query orig features
Dim pQF As IQueryFilter
Set pQF = New QueryFilter
pQF.WhereClause = "" ' to get all features
Dim pFeatCursor As IFeatureCursor
Set pFeatCursor =
pOriginalLayer.FeatureClass.Search(pQF, False)
Dim pFeat As IFeature
Set pFeat = pFeatCursor.NextFeature
Dim iFIDField As Integer
iFIDField = pFeat.Fields.FindField("FID")
Dim iFID As Integer
' loop through all orig features...
Do While Not pFeat Is Nothing
iFID = pFeat.Value(iFIDField)
Set pPoly = pFeat.ShapeCopy
Set pPolyPointColl = pPoly
Set pNewPoly = New Polygon
Set pNewPolyPointColl =
pNewPoly
' loop through all points in
feature polygon
For i = 0 To
pPolyPointColl.PointCount - 1
Set
pPoint = pPolyPointColl.Point(i)
' 1) TRANSLATE to set false origin at lower left of extent of all
polys
pPoint.X = pPoint.X - dblDSLowerLeftX
pPoint.Y = pPoint.Y - dblDSLowerLeftY
' 2) apply SCALE transformation to every x, y point (locations
' based on false origin
'
multiplication is straightforward in our case because
' x scaling = y scaling = SCALE_FACTOR
pPoint.X = pPoint.X * SCALE_FACTOR
pPoint.Y = pPoint.Y * SCALE_FACTOR
' 3) TRANSLATE all points by fixed x and y shift so that
' center of new dataset extent equals
center of
' orig dataset extent
pPoint.X = pPoint.X - dblXAdjust
pPoint.Y = pPoint.Y - dblYAdjust
' 4) TRANSLATE to reset origin (i.e. undo 1)
pPoint.X = pPoint.X + dblDSLowerLeftX
pPoint.Y = pPoint.Y + dblDSLowerLeftY
'
output scaled point
Debug.Print "Shape " + Str(iFID) + ": " + Str(pPoint.X) +
"," + Str(pPoint.Y)
' add
point to new poly
pNewPolyPointColl.AddPoint pPoint
Next i ' get next point
in polygon
' simplify poly to close
polygon
Set pNewPolyTopoOper =
pNewPoly
pNewPolyTopoOper.Simplify
' create new feature (with
scaled shape) and insert into output feature class
Set pFeatBuf.Shape = pNewPoly
pInsertCursor.InsertFeature
pFeatBuf
' get next poly feature
Set pFeat =
pFeatCursor.NextFeature
End Sub
Eicher GIS, LLC