Dart Documentationsimple_featuresPolygon

Polygon class

A Polygon is a planar Surface defined by 1 exterior boundary and 0 or more interior boundaries. Each interior boundary defines a hole in the Polygon.

class Polygon extends Surface {

 LineString _exterior;
 List<LineString> _interiors;

 /**
  * Creates a new polygon.
  *
  * [exteriorRing] must not be null. If [exteriorRing] is empty,
  * [interiorRings] must be null, the empty list, or consist of
  * empty [LinearRing]s only.
  *
  * [interiorRings] can be null. If it is a non-empty list, then it
  * must not contain null values.
  *
  * Note: According to the SFS, both the exterior and the interior must
  * be valid [LinearRing]s, i.e. they must be simple, closed [LineString]s.
  * Exterior and interior rings must not cross and a polygon must not have
  * cuts, spikes, punctures (see the SFS for examples). These restrictions
  * are currently not enforced when a [Polygon] is created.
  *
  * Throws [ArgumentError] if one of the preconditions is violated.
  */
 Polygon(LineString exteriorRing, Iterable<LineString> interiorRings) {
   _require(exteriorRing != null);
   //TODO: valdiate that exteriorRing is indeed a ring
   if (interiorRings == null) interiorRings = [];
   _require(interiorRings.every((r) => r != null),
       "interior rings must not be null"
   );
   if (exteriorRing.isEmpty) {
     _require(interiorRings.every((r) => r.isEmpty),
         "exterior ring is empty => all interior rings must be empty"
     );
     _exterior = null;
     _interiors = null;
     return;
   }
   _exterior = exteriorRing;
   _interiors = new List.from(interiorRings, growable: false);
   //TODO: check geometry of interiors. Must be valid rings, mutually not
   // intersection
   //TODO: check geometry of overall polygon. SFS mentions a set of edge
   // cases like spikes, cuts or punctures which are not allowed
 }

 /**
  * Creates a new empty polygon.
  */
 Polygon.empty(): _exterior=null, _interiors = null;

 /**
  * Creates a new point from the WKT string [wkt].
  *
  * Throws a [WKTError] if [wkt] isn't a valid representation of
  * a [Polygon].
  */
 factory Polygon.wkt(String wkt) {
   var g = parseWKT(wkt);
   if (g is! Polygon) {
     throw new WKTError("WKT string doesn't represent a Polygon");
   }
 }

 /**
  * Creates a triangle with the [exterior].
  *
  * [exterior] must be a non-null, closed linestring with exactly three
  * distinct, non-colienar points.
  *
  * Throws [ArgumentError] if the preconditions aren't met.
  */
 Polygon.triangle(LineString exterior){
   _require(exterior != null);
   _require(
     exterior.map((p) => new DirectPosition2D(p.x, p.y)).toSet().length == 3,
     "a triangle must consist of three non-colinear nodes"
   );
   _require(exterior.isClosed, "the exterior of a triangle must be closed");
   //TODO: check for colienarity of the three points

   _exterior = exterior;
 }

 /**
  * The exterior ring of this polygon.
  *
  * Replies an empty linestring if this polygon is empty.
  */
 @specification(name:"exteriorRing()")
 LineString get exteriorRing => _exterior == null
   ? new LineString.empty()
   : _exterior;

 /**
  * The interior rings. Replies an empty iterable, if
  * this polygon doesn't have interior rings.
  */
 Iterable<LineString> get interiorRings => _interiors== null
     ? []
     : _interiors;

 /// the number of interior rings
 @specification(name:"numInteriorRing()")
 int get numInteriorRing => _interiors == null
   ? 0
   : _interiors.length;

 /**
  * Replies the n-th interior ring.
  *
  * Throws a [RangeError] if [n] is out of range
  */
 @specification(name:"interiorRingN()")
 LineString interiorRingN(int n) => interiorRings.elementAt(n);

 @override String get geometryType => "Polygon";

 /**
  * Replies true if this polygon isn't empty and if both the
  * exterior and each of the interior rings are 3D.
  */
 @override bool get is3D {
   bool ret = _exterior == null ? false : _exterior.is3D;
   if (interiorRings.length == 0) return ret;
   ret = ret && interiorRings.every((r) => r.is3D);
   return ret;
 }

 /**
  * Replies true if this polygon isn't empty and if both the
  * exterior and each of the interior rings are measured.
  */
 @override bool get isMeasured {
   bool ret = _exterior == null ? false : _exterior.isMeasured;
   if (interiorRings.length == 0) return ret;
   ret = ret && interiorRings.every((r) => r.isMeasured);
   return ret;
 }

 @override bool get isEmpty => _exterior == null;

 @override Geometry get boundary {
   if (isEmpty) return new MultiLineString.empty();
   if (interiorRings.isEmpty) return exteriorRing;
   var rings = [];
   rings.add(exteriorRing);
   rings.addAll(interiorRings);
   return new MultiLineString(rings);
 }


 @override
 _writeTaggedWKT(writer, {bool withZ: false, bool withM: false}) {
   writer.write("POLYGON");
   writer.blank();
   if (!isEmpty) {
     writer.ordinateSpecification(withZ: is3D, withM: isMeasured);
   }
   _writeWKT(writer, withZ: withZ, withM: withM);
 }

 _writeWKT(writer, {bool withZ: false, bool withM: false}) {
   if (this.isEmpty){
     writer.empty();
   } else {
     writer..lparen()..newline();
     writer..incIdent()..ident();
     _exterior._writeWKT(writer, withZ: withZ, withM: withM);
     if (!_interiors.isEmpty) writer..comma()..newline();
     for(int i=0; i< _interiors.length; i++) {
       if (i > 0) writer..comma()..newline()..ident();
       _interiors[i]._writeWKT(writer, withZ: withZ, withM: withM);
     }
     writer..newline();
     writer..decIdent()..ident()..rparen();
   }
 }
}

Extends

Geometry > Surface > Polygon

Subclasses

Triangle

Constructors

new Polygon(LineString exteriorRing, Iterable<LineString> interiorRings) #

Creates a new polygon.

exteriorRing must not be null. If exteriorRing is empty, interiorRings must be null, the empty list, or consist of empty LinearRings only.

interiorRings can be null. If it is a non-empty list, then it must not contain null values.

Note: According to the SFS, both the exterior and the interior must be valid LinearRings, i.e. they must be simple, closed LineStrings. Exterior and interior rings must not cross and a polygon must not have cuts, spikes, punctures (see the SFS for examples). These restrictions are currently not enforced when a Polygon is created.

Throws ArgumentError if one of the preconditions is violated.

Polygon(LineString exteriorRing, Iterable<LineString> interiorRings) {
 _require(exteriorRing != null);
 //TODO: valdiate that exteriorRing is indeed a ring
 if (interiorRings == null) interiorRings = [];
 _require(interiorRings.every((r) => r != null),
     "interior rings must not be null"
 );
 if (exteriorRing.isEmpty) {
   _require(interiorRings.every((r) => r.isEmpty),
       "exterior ring is empty => all interior rings must be empty"
   );
   _exterior = null;
   _interiors = null;
   return;
 }
 _exterior = exteriorRing;
 _interiors = new List.from(interiorRings, growable: false);
 //TODO: check geometry of interiors. Must be valid rings, mutually not
 // intersection
 //TODO: check geometry of overall polygon. SFS mentions a set of edge
 // cases like spikes, cuts or punctures which are not allowed
}

new Polygon.empty() #

Creates a new empty polygon.

Polygon.empty(): _exterior=null, _interiors = null;

new Polygon.triangle(LineString exterior) #

Creates a triangle with the exterior.

exterior must be a non-null, closed linestring with exactly three distinct, non-colienar points.

Throws ArgumentError if the preconditions aren't met.

Polygon.triangle(LineString exterior){
 _require(exterior != null);
 _require(
   exterior.map((p) => new DirectPosition2D(p.x, p.y)).toSet().length == 3,
   "a triangle must consist of three non-colinear nodes"
 );
 _require(exterior.isClosed, "the exterior of a triangle must be closed");
 //TODO: check for colienarity of the three points

 _exterior = exterior;
}

factory Polygon.wkt(String wkt) #

Creates a new point from the WKT string wkt.

Throws a WKTError if wkt isn't a valid representation of a Polygon.

factory Polygon.wkt(String wkt) {
 var g = parseWKT(wkt);
 if (g is! Polygon) {
   throw new WKTError("WKT string doesn't represent a Polygon");
 }
}

Properties

final double area #

inherited from Surface

The area of this Surface, as measured in the spatial reference system of this Surface.

@specification(name:"area()")
double get area;

final String asText #

inherited from Geometry

A WKT representation of the geometry

@specification(name:"asText()")
String get asText {
 var buffer = new StringBuffer();
 var writer = new _WKTWriter(buffer);
 _writeTaggedWKT(writer, withZ: is3D, withM: isMeasured);
 return buffer.toString();
}

final Geometry boundary #

Returns the closure of the combinatorial boundary of this geometric object

docs inherited from Geometry
@override Geometry get boundary {
 if (isEmpty) return new MultiLineString.empty();
 if (interiorRings.isEmpty) return exteriorRing;
 var rings = [];
 rings.add(exteriorRing);
 rings.addAll(interiorRings);
 return new MultiLineString(rings);
}

final Point centroid #

inherited from Surface

The mathematical centroid for this Surface as a Point. The result is not guaranteed to be on this Surface.

@specification(name:"centroid()")
Point get centroid;

final dimension #

inherited from Surface

The inherent dimension of this geometric object, which must be less than or equal to the coordinate dimension. In non-homogeneous collections, this will return the largest topological dimension of the contained objects.

docs inherited from Geometry
@override get dimension => 2;

final LineString exteriorRing #

The exterior ring of this polygon.

Replies an empty linestring if this polygon is empty.

@specification(name:"exteriorRing()")
LineString get exteriorRing => _exterior == null
 ? new LineString.empty()
 : _exterior;

final String geometryType #

Returns the name of the instantiable subtype of Geometry of which this geometric object is an instantiable member. The name of the subtype of Geometry is returned as a string.

docs inherited from Geometry
@override String get geometryType => "Polygon";

final Iterable<LineString> interiorRings #

The interior rings. Replies an empty iterable, if this polygon doesn't have interior rings.

Iterable<LineString> get interiorRings => _interiors== null
   ? []
   : _interiors;

final bool is3D #

Replies true if this polygon isn't empty and if both the exterior and each of the interior rings are 3D.

@override bool get is3D {
 bool ret = _exterior == null ? false : _exterior.is3D;
 if (interiorRings.length == 0) return ret;
 ret = ret && interiorRings.every((r) => r.is3D);
 return ret;
}

final bool isEmpty #

Returns 1 true if this geometric object is the empty Geometry.

docs inherited from Geometry
@override bool get isEmpty => _exterior == null;

final bool isMeasured #

Replies true if this polygon isn't empty and if both the exterior and each of the interior rings are measured.

@override bool get isMeasured {
 bool ret = _exterior == null ? false : _exterior.isMeasured;
 if (interiorRings.length == 0) return ret;
 ret = ret && interiorRings.every((r) => r.isMeasured);
 return ret;
}

final bool isSimple #

inherited from Geometry

Returns true if this geometric object has no anomalous geometric points, such as self intersection or self tangency.

@specification(name:"isSimple()")
bool get isSimple;

final int numInteriorRing #

the number of interior rings

@specification(name:"numInteriorRing()")
int get numInteriorRing => _interiors == null
 ? 0
 : _interiors.length;

final Point pointOnSurface #

inherited from Surface

A Point guaranteed to be on this Surface.

@specification(name:"pointOnSurface()")
Point get pointOnSurface;

int get SRID #

inherited from Geometry

Returns the Spatial Reference System ID for this geometric object.

@specification(name:"srid()")
int get SRID => _srid;

dynamic set SRID(int value) #

inherited from Geometry

the Spatial Reference System ID for this geometric object.

set SRID(int value) => _srid = value;

Methods

LineString interiorRingN(int n) #

Replies the n-th interior ring.

Throws a RangeError if n is out of range

@specification(name:"interiorRingN()")
LineString interiorRingN(int n) => interiorRings.elementAt(n);