How to efficiently create a polygon


This document was published with and applies to ArcGIS 9.3.
A 10 version also exists. A 9.2 version also exists.
Summary A polygon can be built in numerous ways according to the user's input. This article shows the most commonly used approaches to efficiently create a new polygon.

Additional Requirements
  • The code in this document assumes that references to the following assemblies and their corresponding using (C#) or Imports (VB.NET) statements have been added to your Visual Studio project:
  • ESRI.ArcGIS.Geometry
  • ESRI.ArcGIS.esriSystem

Building a polygon using points

The following code shows how to build a polygon using a collection of points. This approach is preferred when the user has a sequence of vertices as input. The resulting polygon ring will only contain a straight line segment:
 

[VB.NET]
Public Sub CreatePolygonByPoints()
    
    'Build polygon from a sequence of points.
    'At ArcGIS 9.2, the recommended way to add arrays of points to a geometry is to use
    'the IGeometryBridge2 interface on the GeometryEnvironment singleton object.
    Dim geometryBridge2 As IGeometryBridge2 = New GeometryEnvironmentClass
    Dim pointCollection4 As IPointCollection4 = New PolygonClass
    
    'TODO:
    'pointCollection4.SpatialReference = 'Define the spatial reference of the new polygon
    
    Dim aWKSPointBuffer() As WKSPoint
    Dim cPoints As Long = 4 'The number of points in the first part
    ReDim aWKSPointBuffer(0 To CInt(cPoints - 1))
    
    'TODO:
    'aWKSPointBuffer = 'Read cPoints into the point buffer
    
    geometryBridge2.SetWKSPoints(pointCollection4, aWKSPointBuffer)
    
    'pointCollection4 has now been defined
    
End Sub

[C#]
public void CreatePolygonByPoints()
{
  //Build polygon from a sequence of points. 
  //At ArcGIS 9.2, the recommended way to add arrays of points to a geometry is to use
  //the IGeometryBridge2 interface on the GeometryEnvironment singleton object.
  IGeometryBridge2 geometryBridge2 = new GeometryEnvironmentClass();
  IPointCollection4 pointCollection4 = new PolygonClass();

  //TODO:
  //pointCollection4.SpatialReference = 'Define the spatial reference of the new polygon

  WKSPoint[] aWKSPointBuffer = null;
  long cPoints = 4; //The number of points in the first part
  aWKSPointBuffer = new WKSPoint[System.Convert.ToInt32(cPoints - 1) + 1];

  //TODO:
  //aWKSPointBuffer = 'Read cPoints into the point buffer

  geometryBridge2.SetWKSPoints(pointCollection4, ref aWKSPointBuffer);

  //pointCollection4 has now been defined
}

Building a polygon using segments

In this code example, the multipart polygon is built segment–by–segment. It gives the most control if you are using advanced construction techniques or curved segments (circular arcs, Bèzier curves, and so on). See the following:

[VB.NET]
Public Sub CreatePolygonBySegments()
    
    'Build a polygon segment-by-segment.
    Dim polygon As IPolygon = New PolygonClass
    'polygon.SpatialReference = 'Always define the spatial reference of new top-level geometries.
    
    'Create the segments and rings. If this were a single-part polygon, segments can be
    'added directly to the polygon and the ring created internally.
    'You cannot reuse the same ring object. Also, when rings are added to the polygon,
    'the polygon takes ownership of the rings. You cannot reuse a ring for building another polygon.
    'These same restrictions also apply to segments.
    
    Dim circularArc As ICircularArc = New CircularArcClass
    Dim segment1 As ISegment = CType(circularArc, ISegment)
    Dim ring1 As ISegmentCollection = New RingClass
    ring1.AddSegment(segment1)
    
    Dim bezierCurve As IBezierCurve = New BezierCurveClass
    Dim segment2 As ISegment = CType(bezierCurve, ISegment)
    Dim ring2 As ISegmentCollection = New RingClass
    ring2.AddSegment(segment2)
    
    Dim geometryCollection As IGeometryCollection = CType(polygon, IGeometryCollection)
    
    Dim geometry1 As IGeometry = CType(ring1, IGeometry)
    geometryCollection.AddGeometry(geometry1)
    
    Dim geometry2 As IGeometry = CType(ring2, IGeometry)
    geometryCollection.AddGeometry(geometry2)
    
    'At this point, a _shell_geometry has been constructed. The _shell_geometry consists of
    'one polygon containing two rings; each containing one segment.
    'However, the coordinates of those segments have not been defined.
    'Because references to those segments exist, their coordinates can be
    'defined now.
    Dim point As IPoint = New PointClass
    point.X = -10
    point.Y = 0
    
    circularArc.PutCoordsByAngle(point, 0, 2 * 3.14159265358979, 10.0#)
    
    Dim pntArray(0 To 3) As IPoint
    Dim i As Long
    For i = 0 To 3
        pntArray(CInt(i)) = New PointClass
    Next i
    
    pntArray(0).X = 10
    pntArray(0).Y = 0
    pntArray(1).X = 10
    pntArray(1).Y = 10
    pntArray(2).X = 20
    pntArray(2).Y = 10
    pntArray(3).X = 10
    pntArray(3).Y = 0
    bezierCurve.PutCoords(4, pntArray(0))
    
    'polygon has now been defined. When changing segment coordinates directly
    'like this, be careful to let the top-level geometry know that
    'things have changed underneath it so that it can delete any cached properties
    'that it maintains, such as envelope, length, area, and so on.
    'When you use certain methods on the top-level geometry implementation
    'of IGeometryCollection interface, like AddGeometry, it automatically
    'invalidates any cached properties.
    geometryCollection.GeometriesChanged()
    
End Sub

[C#]
public void CreatePolygonBySegments()
{
  //Build a polygon segment-by-segment.
  IPolygon polygon = new PolygonClass();
  //polygon.SpatialReference = 'Always define the spatial reference of new top-level geometries.

  //Create the segments and rings. If this were a single-part polygon, segments can be
  //added directly to the polygon and the ring created internally.
  //You cannot reuse the same ring object. Also, when rings are added to the polygon,
  //the polygon takes ownership of the rings. You cannot reuse a ring for building another polygon.
  //These same restrictions also apply to segments.

  ICircularArc circularArc = new CircularArcClass();
  ISegment segment1 = (ISegment)circularArc;
  ISegmentCollection ring1 = new RingClass();
  object before1 = null;
  object after1 = null;
  ring1.AddSegment(segment1, ref before1, ref after1);

  IBezierCurve bezierCurve = new BezierCurveClass();
  ISegment segment2 = (ISegment)bezierCurve;
  ISegmentCollection ring2 = new RingClass();
  object before2 = null;
  object after2 = null;
  ring2.AddSegment(segment2, ref before2, ref after2);

  IGeometryCollection geometryCollection = (IGeometryCollection)polygon;

  IGeometry geometry1 = (IGeometry)ring1;
  object before1a = null;
  object after1a = null;
  geometryCollection.AddGeometry(geometry1, ref before1a, ref after1a);

  IGeometry geometry2 = (IGeometry)ring2;
  object before2a = null;
  object after2a = null;
  geometryCollection.AddGeometry(geometry2, ref before2a, ref after2a);

  //At this point, a _shell_geometry has been constructed. The _shell_geometry consists of
  //one polygon containing two rings; each containing one segment.
  //However, the coordinates of those segments have not been defined.
  //Because references to those segments exist, their coordinates can be 
  //defined now.
  IPoint point = new PointClass();
  point.X =  - 10;
  point.Y = 0;

  circularArc.PutCoordsByAngle(point, 0, 2 * 3.14159265358979, 10.0);

  IPoint[] pntArray = new IPoint[4];
  long i = 0;
  for (i = 0; i <= 3; i++)
  {
    pntArray[System.Convert.ToInt32(i)] = new PointClass();
  }

  pntArray[0].X = 10;
  pntArray[0].Y = 0;
  pntArray[1].X = 10;
  pntArray[1].Y = 10;
  pntArray[2].X = 20;
  pntArray[2].Y = 10;
  pntArray[3].X = 10;
  pntArray[3].Y = 0;
  bezierCurve.PutCoords(4, ref pntArray[0]);

  //polygon has now been defined. When changing segment coordinates directly
  //like this, be careful to let the top-level geometry know that
  //things have changed underneath it so that it can delete any cached properties
  //that it maintains, such as envelope, length, area, and so on.
  //When you use certain methods on the top-level geometry implementation
  //of IGeometryCollection interface, like AddGeometry, it automatically
  //invalidates any cached properties.
  geometryCollection.GeometriesChanged();
}

Creating a polygon using existing geometries

A polygon can be created based on a topological relationship between existing geometries. In the following code example, a polygon is generated by uniting two existing polygons:

[VB.NET]
Public Sub CreatePolygonFromExistingGeometries(ByRef polygon1 As IPolygon, ByRef polygon2 As IPolygon)
    
    'Build a new polygon by uniting two existing polygons.
    Dim topologicalOperator2 As ITopologicalOperator2 = CType(polygon1, ITopologicalOperator2)
    
    'Simplify.
    topologicalOperator2.IsKnownSimple_2 = False
    topologicalOperator2.Simplify()
    
    Dim geometry As IGeometry = topologicalOperator2.Union(polygon2)
    Dim polygonCombined As IPolygon = CType(geometry, IPolygon)
    
    'polygonCombined is the new generated polygon.
    
End Sub

[C#]
public void CreatePolygonFromExistingGeometries(ref IPolygon polygon1, ref
  IPolygon polygon2)
{
  //Build a new polygon by uniting two existing polygons.
  ITopologicalOperator2 topologicalOperator2 = (ITopologicalOperator2)polygon1;

  //Simplify.
  topologicalOperator2.IsKnownSimple_2 = false;
  topologicalOperator2.Simplify();

  IGeometry geometry = topologicalOperator2.Union(polygon2);
  IPolygon polygonCombined = (IPolygon)geometry;

  //polygonCombined is the new generated polygon.
}