How to build a polygon using segments and points


Development licensing Deployment licensing
ArcView ArcView
ArcEditor ArcEditor
ArcInfo ArcInfo
Engine Developer Kit Engine Runtime

Additional Requirements
  • This article assumes your project includes references to the ESRI Geometry assembly.

Building a polygon using segments and points

This example builds two multipart polygons in two different ways:
 
The first way gives you the most control if you are using advanced construction techniques or curved segments (circular arcs, Bézier curves, and so on).
 
The second way is recommended for efficiently building polygons from bulk coordinate data that have vertices connected only with straight lines. The techniques shown here can also be applied to polyline construction. The first polygon should look something like the following illustration:
 
 
See the following code example:
 

[C#]
public void ConstructPolygons()
{
//Build a polygon segment by segment.
//Create the segments and rings. If this is a single-part polygon you can add
//segments directly to the polygon and it creates the ring internally.
//You cannot reuse the same ring object. Also, when rings are added to the polygon 
//it takes ownership of them. You cannot reuse a ring for building another polygon. 
//These same restrictions also apply to segments.

ICircularArc circularArc = new CircularArcClass();
IBezierCurveGEN bezierCurve = new BezierCurveClass();
ISegmentCollection ring1 = new RingClass();
ISegmentCollection ring2 = new RingClass();
object missing = Type.Missing;
ring1.AddSegment(circularArc as ISegment, ref missing, ref missing);
ring2.AddSegment(bezierCurve as ISegment, ref missing, ref missing);

IPolygon polygon = new PolygonClass();
//Always define the spatial reference of new top-level geometries.
//polygon.SpatialReference = ... code skipped.
IGeometryCollection geometryCollection = polygon as IGeometryCollection;
geometryCollection.AddGeometry(ring1 as IGeometry, ref missing, ref missing);
geometryCollection.AddGeometry(ring2 as IGeometry, ref missing, ref missing);

//At this point, you have constructed a _shell_ geometry. It consists of one 
//polygon containing two rings, each of which contains one segment. 
//However, the coordinates of those segments have not been defined. 
//Because you still have references to those segments, you can define their 
//coordinates now.
//Circular arc.
IPoint centerPoint = new PointClass();
centerPoint.X = -10;
centerPoint.Y = 0;
circularArc.PutCoordsByAngle(centerPoint, 0, 2 * Math.PI, 10);

//Bézier curve.
IPoint[] controlPoints = new IPoint[4];
for (int i = 0; i < controlPoints.Length; i++)
{
controlPoints[i] = new PointClass();
}
controlPoints[0].X = 10;
controlPoints[0].Y = 0;
controlPoints[1].X = 10;
controlPoints[1].Y = 10;
controlPoints[2].X = 20;
controlPoints[2].Y = 10;
controlPoints[3].X = 10;
controlPoints[3].Y = 0;
bezierCurve.PutCoords(ref controlPoints);

//The polygon has now been defined. When changing segment coordinates directly 
//like this, you need to 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 might be maintaining, such as envelope, length, area, etc.
//When you use certain methods on the top-level geometry implementation 
//of IGeometryCollection interface, like AddGeometry, it will automatically
//invalidate any cached properties.
geometryCollection.GeometriesChanged();

//Build another polygon from a bunch of points. As before, assume that 
//two parts (rings) need to be created. If the polygon is a single part, you can
//add the points directly to the polygon without creating a ring.
IGeometryCollection pointPolygon = new PolygonClass();

//Define the spatial reference of the new pointPolygon here, code skipped.
//As previously stated, the rings used for the first polygon cannot be reused.
ring1 = new RingClass();
ring2 = new RingClass();

//At 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 geometryBridge = new GeometryEnvironmentClass();

WKSPoint[] wksPoints1 = new WKSPoint[ring1.SegmentCount];
geometryBridge.SetWKSPoints(ring1 as IPointCollection4, ref wksPoints1);
WKSPoint[] wksPoints2 = new WKSPoint[ring2.SegmentCount];
geometryBridge.SetWKSPoints(ring2 as IPointCollection4, ref wksPoints2);

pointPolygon.AddGeometry(ring1 as IGeometry, ref missing, ref missing);
pointPolygon.AddGeometry(ring2 as IGeometry, ref missing, ref missing);
//The point polygon is now defined.
}

[VB.NET]
Public Sub ConstructPolygons()
  'Build a polygon segment by segment
  'Create the segments and rings. If this is a single-part polygon you can add
  'segments directly to the polygon and it creates the ring internally.
  'You cannot reuse the same ring object. Also, when rings are added to the polygon 
  'it takes ownership of them. You cannot reuse a ring for building another polygon. 
  'These same restrictions also apply to segments.
  Dim circularArc As ICircularArc = New CircularArcClass()
  Dim bezierCurve As IBezierCurveGEN = New BezierCurveClass()
  Dim ring1 As ISegmentCollection = New RingClass()
  Dim ring2 As ISegmentCollection = New RingClass()
  Dim missing As Object = Type.Missing
  ring1.AddSegment(circularArc, missing, missing)
  ring2.AddSegment(bezierCurve, missing, missing)
  Dim polygon As IPolygon = New PolygonClass()

  'Always define the spatial reference of new top-level geometries.
  'polygon.SpatialReference = ... code skipped.
  Dim geometryCollection As IGeometryCollection = CType(polygon, IGeometryCollection)
  geometryCollection.AddGeometry(ring1, missing, missing)
  geometryCollection.AddGeometry(ring2, missing, missing)
  
  'At this point, you have constructed a _shell_ geometry. It consists of one 
  'polygon containing two rings, each of which contains one segment. 
  'However, the coordinates of those segments have not been defined. 
  'Because you still have references to those segments, you can define their 
  'coordinates now.

  'Circular Arc
  Dim centerPoint As IPoint = New PointClass()
  centerPoint.X = -10
  centerPoint.Y = 0
  circularArc.PutCoordsByAngle(centerPoint, 0, 2 * Math.PI, 10)

  'Bézier curve.
  Dim controlPoints(3) As IPoint
  controlPoints(0) = New PointClass()
  controlPoints(0).X = 10
  controlPoints(0).X = 0
  controlPoints(1) = New PointClass()
  controlPoints(1).X = 10
  controlPoints(1).X = 10
  controlPoints(2) = New PointClass()
  controlPoints(2).X = 20
  controlPoints(2).X = 10
  controlPoints(3) = New PointClass()
  controlPoints(3).X = 10
  controlPoints(3).X = 0
  bezierCurve.PutCoords(controlPoints)

  'The polygon has now been defined. When changing segment coordinates directly  
  'like this, you need to 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 might be maintaining, such as envelope, length, area, etc.
  'When you use certain methods on the top-level geometry implementation 
  'of IGeometryCollection interface, like AddGeometry, it will automatically
  'invalidate any cached properties.
  geometryCollection.GeometriesChanged()
 
  'Build another polygon from a bunch of points. As before, assume that 
  'two parts (rings) need to be created. If the polygon is a single part, you can
  'add the points directly to the polygon without creating a ring.
  Dim pointPolygon As IGeometryCollection = New PolygonClass()

  'Define the spatial reference of the new pointPolygon here, code skipped.
  'As previously stated, the rings used for the first polygon cannot be reused.
  ring1 = New RingClass()
  ring2 = New RingClass()

  'At 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 geometryBridge As IGeometryBridge2 = New GeometryEnvironmentClass()
  Dim segCount As Integer = ring1.SegmentCount
  Dim wksPoints1(ring1.SegmentCount) As WKSPoint 
  geometryBridge.SetWKSPoints(ring1, wksPoints1) 
  Dim wksPoints2(ring2.SegmentCount) As WKSPoint
  geometryBridge.SetWKSPoints(ring2, wksPoints2) 
  pointPolygon.AddGeometry(ring1, missing, missing)
  pointPolygon.AddGeometry(ring2, missing, missing)

  'The point polygon is now defined.
End Sub