Polygon

A Polygon is a two-dimensional surface stored as a sequence of points defining an exterior bounding ring and zero or more interior rings.

Polygon instances

A Polygon instance can be formed from a ring that has at least three distinct points. A Polygon instance can also be empty.

The exterior and any interior rings of a Polygon define its boundary. The space within the rings defines the interior of the Polygon.

The illustration below shows examples of Polygon instances.

Examples of geometry Polygon instances

As shown in the illustration:

  1. Figure 1 is a Polygon instance whose boundary is defined by an exterior ring.

  2. Figure 2 is a Polygon instance whose boundary is defined by an exterior ring and two interior rings. The area inside the interior rings is part of the exterior of the Polygon instance.

  3. Figure 3 is a valid Polygon instance because its interior rings intersect at a single tangent point.

Accepted instances

Accepted Polygon instances are instances that can be stored in a geometry or geography variable without throwing an exception. The following are accepted Polygon instances for the geometry type:

  • An Empty Polygon instance

  • A Polygon instance that has an acceptable exterior ring and zero or more acceptable interior rings

The following criteria are needed for a ring to be acceptable.

  • The LineString instance must be accepted.

  • The LineString instance must have at least four points that include three distinct points.

  • The starting and ending points of the LineString instance must have the same X and Y values.

    Note

    Z and M values are ignored.

A Polygon instance of a geography type is accepted only if the instance is valid. For more information on valid Polygon instances for geography type, see BkmkValidGeographyPolygons.

The following example shows accepted Polygon instances.

DECLARE @g1 geometry = 'POLYGON EMPTY';
DECLARE @g2 geometry = 'POLYGON((1 1, 3 3, 3 1, 1 1))';
DECLARE @g3 geometry = 'POLYGON((-5 -5, -5 5, 5 5, 5 -5, -5 -5),(0 0, 3 0, 3 3, 0 3, 0 0))';
DECLARE @g4 geometry = 'POLYGON((-5 -5, -5 5, 5 5, 5 -5, -5 -5),(3 0, 6 0, 6 3, 3 3, 3 0))';

As @g4 shows an accepted Polygon instance may not be a valid Polygon instance. The following examples throw a System.FormatException because the Polygon instances are not accepted.

DECLARE @g1 geometry = 'POLYGON((1 1, 3 3, 1 1))';
DECLARE @g2 geometry = 'POLYGON((1 1, 3 3, 3 1, 1 5))';

@g1 is not accepted because the LineString instance for the exterior ring does not contain enough points. @g2 is not accepted because the starting point of the exterior ring LineString instance is not the same as the ending point. The following example has an acceptable exterior ring, but the interior ring is not acceptable. This also throws a System.FormatException.

DECLARE @g geometry = 'POLYGON((-5 -5, -5 5, 5 5, 5 -5, -5 -5),(0 0, 3 0, 0 0))';

Valid instances

The interior rings of a Polygon can touch both themselves and each other at single tangent points, but if the interior rings of a Polygon cross, the instance is not valid.

The following example shows valid Polygon instances.

DECLARE @g1 geometry = 'POLYGON((-20 -20, -20 20, 20 20, 20 -20, -20 -20))';
DECLARE @g2 geometry = 'POLYGON((-20 -20, -20 20, 20 20, 20 -20, -20 -20), (10 0, 0 10, 0 -10, 10 0))';
DECLARE @g3 geometry = 'POLYGON((-20 -20, -20 20, 20 20, 20 -20, -20 -20), (10 0, 0 10, 0 -10, 10 0), (-10 0, 0 10, -5 -10, -10 0))';
SELECT @g1.STIsValid(), @g2.STIsValid(), @g3.STIsValid();

@g3 is valid because the two interior rings touch at a single point and do not cross each other. The following example shows Polygon instances that are not valid.

DECLARE @g1 geometry = 'POLYGON((-20 -20, -20 20, 20 20, 20 -20, -20 -20), (20 0, 0 10, 0 -20, 20 0))';
DECLARE @g2 geometry = 'POLYGON((-20 -20, -20 20, 20 20, 20 -20, -20 -20), (10 0, 0 10, 0 -10, 10 0), (5 0, 1 5, 1 -5, 5 0))';
DECLARE @g3 geometry = 'POLYGON((-20 -20, -20 20, 20 20, 20 -20, -20 -20), (10 0, 0 10, 0 -10, 10 0), (-10 0, 0 10, 0 -10, -10 0))';
DECLARE @g4 geometry = 'POLYGON((-20 -20, -20 20, 20 20, 20 -20, -20 -20), (10 0, 0 10, 0 -10, 10 0), (-10 0, 1 5, 0 -10, -10 0))';
SELECT @g1.STIsValid(), @g2.STIsValid(), @g3.STIsValid(), @g4.STIsValid();

@g1 is not valid because the inner ring touches the exterior ring in two places. @g2 is not valid because the second inner ring in within the interior of the first inner ring. @g3 is not valid because the the two inner rings touch at multiple consecutive points. @g4 is not valid because the interiors of the two inner rings overlap.

Geometry data type

For a Polygon instance of a geometry type to be valid, it needs to meet the following criteria:

  1. The first ring is the exterior ring.

  2. All interior rings lie within the exterior ring.

  3. No interior ring lies within another interior ring.

  4. No ring crosses itself or another ring.

  5. No two rings can share the same edge.

  6. The interior of an interior ring cannot overlap the interior of another interior ring.

  7. All rings can only touch themselves or another ring at zero or a finite number of tangent points.

  8. The interior of the Polygon instance is connected. There must exist at least one path between any two interior points of the instance that is completely inside the instance.

The following example shows valid Polygon instances.

DECLARE @g1 geometry = 'POLYGON((-20 -20, -20 20, 20 20, 20 -20, -20 -20))';
DECLARE @g2 geometry = 'POLYGON((-20 -20, -20 20, 20 20, 20 -20, -20 -20), (10 0, 0 10, 0 -10, 10 0))';
DECLARE @g3 geometry = 'POLYGON((-20 -20, -20 20, 20 20, 20 -20, -20 -20), (10 0, 0 10, 0 -10, 10 0), (-10 0, 0 10, -5 -10, -10 0))';
SELECT @g1.STIsValid(), @g2.STIsValid(), @g3.STIsValid();

@g3 is valid because the two interior rings touch at a single point and do not cross each other. The following example shows Polygon instances that are not valid.

DECLARE @g1 geometry = 'POLYGON((-20 -20, -20 20, 20 20, 20 -20, -20 -20), (20 0, 0 10, 0 -20, 20 0))';
DECLARE @g2 geometry = 'POLYGON((-20 -20, -20 20, 20 20, 20 -20, -20 -20), (10 0, 0 10, 0 -10, 10 0), (5 0, 1 5, 1 -5, 5 0))';
DECLARE @g3 geometry = 'POLYGON((-20 -20, -20 20, 20 20, 20 -20, -20 -20), (10 0, 0 10, 0 -10, 10 0), (-10 0, 0 10, 0 -10, -10 0))';
DECLARE @g4 geometry = 'POLYGON((-20 -20, -20 20, 20 20, 20 -20, -20 -20), (10 0, 0 10, 0 -10, 10 0), (-10 0, 1 5, 0 -10, -10 0))';
DECLARE @g5 geometry = 'POLYGON((10 0, 0 10, 0 -10, 10 0), (-20 -20, -20 20, 20 20, 20 -20, -20 -20) )';
SELECT @g1.STIsValid(), @g2.STIsValid(), @g3.STIsValid(), @g4.STIsValid(), @g5.STIsValid();

@g1 is not valid because the inner ring touches the exterior ring in two places. @g2 is not valid because the second inner ring in within the interior of the first inner ring. @g3 is not valid because the the two inner rings touch at multiple consecutive points. @g4 is not valid because the interiors of the two inner rings overlap. @g5 is not valid because the first ring is an interior ring and the second ring is an exterior ring.

Geography data type

For a Polygon instance of a geography type to be valid, it must meet the following criteria:

  1. The instance must meet all of the rules required to be an accepted Polygon instance of geometry type.

  2. The interior of the instance is connected using a left-hand rule.

  3. The instance can fit in a hemisphere.

  4. No ring crosses itself or any other ring.

  5. All rings can only touch themselves or any other ring at zero or a finite number of tangent points.

The following example throws a Microsoft.SqlServer.Types.GLArgumentException because the Polygon instance exceeds a hemisphere.

DECLARE @g geography = 'POLYGON((-122.358 47.653, 122.348 47.649, 122.348 47.658, 122.358 47.658, -122.358 47.653))';

The following example shows a valid Polygon instance for the geography type.

DECLARE @g geography = 'POLYGON((-122.358 47.653, -122.348 47.649, -122.348 47.658, -122.358 47.658, -122.358 47.653))';

Examples

The following example creates a simple geometryPolygon instance with a hole and SRID 10.

DECLARE @g geometry;
SET @g = geometry::STPolyFromText('POLYGON((0 0, 0 3, 3 3, 3 0, 0 0), (1 1, 1 2, 2 1, 1 1))', 10);

Aninstance that is not valid may be entered and converted to a valid geometry instance. In the following example of a Polygon, the interior and exterior rings overlap and the instance is not valid.

DECLARE @g geometry;
SET @g = geometry::Parse('POLYGON((1 0, 0 1, 1 2, 2 1, 1 0), (2 0, 1 1, 2 2, 3 1, 2 0))');

In the following example, the invalid instance is made valid with MakeValid().

SET @g = @g.MakeValid();
SELECT @g.ToString();

The geometry instance returned from the above example is a MultiPolygon.

MULTIPOLYGON (((2 0, 3 1, 2 2, 1.5 1.5, 2 1, 1.5 0.5, 2 0)), ((1 0, 1.5 0.5, 1 1, 1.5 1.5, 1 2, 0 1, 1 0)))