How to build a polygon using segments and points


Building a polygon using segments and points

The following code example shows how to build multipart polygons in two ways:
  • The first polygon is built segment by segment.
  • The second polygon is built by defining its vertices as an array of WKSPoint structures.
The first approach gives you the most control if you're using advanced construction techniques or curved segments (circular arcs, Bézier curves, and so on). The first polygon should look something like the following illustration:
The second approach 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.
[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 to build another polygon. 
    //These 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 an _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 in this 
    //way, be sure 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, etc.
    //When you use certain methods on the top-level geometry implementation of the 
    //IGeometryCollection interface, such as AddGeometry, it automatically invalidates 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();

    //Add arrays of points to a geometry using 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 to build another polygon.
    'These 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 an _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 in this
    'way, be sure 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, etc.
    'When you use certain methods on the top-level geometry implementation of the
    'IGeometryCollection interface, such as AddGeometry, it automatically invalidates 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()
    
    'Add arrays of points to a geometry using 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






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):
Development licensing Deployment licensing
ArcView ArcView
ArcEditor ArcEditor
ArcInfo ArcInfo
Engine Developer Kit Engine Runtime