diff --git a/geom/type_geometry_collection.go b/geom/type_geometry_collection.go index b29fe65a..0590e163 100644 --- a/geom/type_geometry_collection.go +++ b/geom/type_geometry_collection.go @@ -35,7 +35,8 @@ func NewGeometryCollection(geoms []Geometry, opts ...ConstructorOption) Geometry return GeometryCollection{geoms, ctype} } -// Validate checks if the GeometryCollection is valid. +// Validate checks if the GeometryCollection is valid, by checking that all +// child geometries are valid. func (c GeometryCollection) Validate() error { for i, g := range c.geoms { if err := g.Validate(); err != nil { diff --git a/geom/type_line_string.go b/geom/type_line_string.go index ef7199b1..81031006 100644 --- a/geom/type_line_string.go +++ b/geom/type_line_string.go @@ -11,16 +11,13 @@ import ( // LineString is a linear geometry defined by linear interpolation between a // finite set of points. Its zero value is the empty line string. It is // immutable after creation. -// -// A LineString must consist of either zero points (i.e. it is the empty line -// string), or it must have at least 2 points with distinct XY values. type LineString struct { seq Sequence } -// NewLineString creates a new LineString from a Sequence of points. The -// sequence must contain exactly 0 points, or at least 2 points with distinct -// XY values (otherwise an error is returned). +// NewLineString creates a new LineString from a Sequence of points. An error +// is returned if the LineString would be invalid (see the Validate method for +// details). func NewLineString(seq Sequence, opts ...ConstructorOption) (LineString, error) { ls := LineString{seq} co := newOptionSet(opts) diff --git a/geom/type_multi_line_string.go b/geom/type_multi_line_string.go index 77679127..f3d93b25 100644 --- a/geom/type_multi_line_string.go +++ b/geom/type_multi_line_string.go @@ -20,7 +20,8 @@ type MultiLineString struct { // NewMultiLineString creates a MultiLineString from its constituent // LineStrings. The coordinates type of the MultiLineString is the lowest -// common coordinates type of its LineStrings. +// common coordinates type of its LineStrings. The validity of the input +// LineStrings is not verified. func NewMultiLineString(lines []LineString, opts ...ConstructorOption) MultiLineString { if len(lines) == 0 { return MultiLineString{} @@ -39,7 +40,8 @@ func NewMultiLineString(lines []LineString, opts ...ConstructorOption) MultiLine return MultiLineString{lines, ctype} } -// Validate checks if the MultiLineString is valid. +// Validate checks if the MultiLineString is valid. The only validation rule is +// that each child LineString must be valid. func (m MultiLineString) Validate() error { for i, ls := range m.lines { if err := ls.Validate(); err != nil { diff --git a/geom/type_multi_point.go b/geom/type_multi_point.go index 35a08ff0..f4171a7f 100644 --- a/geom/type_multi_point.go +++ b/geom/type_multi_point.go @@ -17,6 +17,7 @@ type MultiPoint struct { // NewMultiPoint creates a MultiPoint from a list of Points. The coordinate // type of the MultiPoint is the lowest common coordinates type of its Points. +// The validity of the input Points is not verified. func NewMultiPoint(pts []Point, opts ...ConstructorOption) MultiPoint { if len(pts) == 0 { return MultiPoint{} @@ -31,7 +32,8 @@ func NewMultiPoint(pts []Point, opts ...ConstructorOption) MultiPoint { return MultiPoint{forced, ctype} } -// Validate checks if the MultiPoint is valid. +// Validate checks if the MultiPoint is valid. The only validation rule is that +// each child Point is valid. func (m MultiPoint) Validate() error { for i, pt := range m.points { if err := pt.Validate(); err != nil { diff --git a/geom/type_multi_polygon.go b/geom/type_multi_polygon.go index a531b932..e024495f 100644 --- a/geom/type_multi_polygon.go +++ b/geom/type_multi_polygon.go @@ -9,26 +9,19 @@ import ( ) // MultiPolygon is a planar surface geometry that consists of a collection of -// Polygons. The zero value is the empty MultiPolygon (i.e. the collection of -// zero Polygons). It is immutable after creation. -// -// For a MultiPolygon to be valid, the following assertions must hold: -// -// 1. It must be made up of zero or more valid Polygons (any of which may be empty). -// -// 2. The interiors of any two polygons must not intersect. -// -// 3. The boundaries of any two polygons may touch only at a finite number of points. +// (possibly empty) Polygons. The zero value is the empty MultiPolygon (i.e. +// the collection of zero Polygons). It is immutable after creation. type MultiPolygon struct { // Invariant: ctype matches the coordinates type of each polygon. polys []Polygon ctype CoordinatesType } -// NewMultiPolygon creates a MultiPolygon from its constituent Polygons. It -// gives an error if any of the MultiPolygon assertions are not maintained. The +// NewMultiPolygon creates a MultiPolygon from its constituent Polygons. The // coordinates type of the MultiPolygon is the lowest common coordinates type -// its Polygons. +// its Polygons. An error is returned if any of the MultiPolygon constraints +// aren't met (see the Validate method for details). Note that the validity of +// each input Polygon is not verified. func NewMultiPolygon(polys []Polygon, opts ...ConstructorOption) (MultiPolygon, error) { ctype := DimXY if len(polys) > 0 { @@ -53,7 +46,16 @@ func NewMultiPolygon(polys []Polygon, opts ...ConstructorOption) (MultiPolygon, return mp, nil } -// Validate checks if the MultiPolygon is valid. +// Validate checks if the MultiPolygon is valid. MultiPolygons have the +// following constraints: +// +// 1. The interiors of any two child polygons must not intersect. +// +// 2. The boundaries of any two child polygons may touch only at a finite +// number of points. +// +// In addition to these constraints, this method also checks if each child +// Polygon is valid. func (m MultiPolygon) Validate() error { for i, poly := range m.polys { if err := poly.Validate(); err != nil { diff --git a/geom/type_point.go b/geom/type_point.go index 4c9f5b28..11a906b1 100644 --- a/geom/type_point.go +++ b/geom/type_point.go @@ -18,7 +18,8 @@ type Point struct { full bool } -// NewPoint creates a new point given its Coordinates. +// NewPoint creates a new point given its Coordinates. An error is returned for +// invalid points (see the Validate method for details). func NewPoint(c Coordinates, opts ...ConstructorOption) (Point, error) { pt := newUncheckedPoint(c) os := newOptionSet(opts) @@ -31,8 +32,8 @@ func NewPoint(c Coordinates, opts ...ConstructorOption) (Point, error) { return pt, nil } -// Validate checks if the Point is valid. For it to be valid, its coordinates -// must not be NaN or positive or negative Inf. +// Validate checks if the Point is valid. For it to be valid, it must be empty +// or have non-NaN and non-infinite coordinates. func (p Point) Validate() error { if !p.full { return nil diff --git a/geom/type_polygon.go b/geom/type_polygon.go index 764eac3d..c4bc78ee 100644 --- a/geom/type_polygon.go +++ b/geom/type_polygon.go @@ -13,17 +13,6 @@ import ( // It is immutable after creation. When not empty, it is defined by one outer // ring and zero or more interior rings. The outer ring defines the exterior // boundary of the Polygon, and each inner ring defines a hole in the polygon. -// -// For a Polygon to be valid, the following assertions must hold: -// -// 1. The rings (outer and inner) must be valid linear rings. This means that -// they must be non-empty, simple, and closed. -// -// 2. Each pair of rings must only intersect at a single point. -// -// 3. The interior of the polygon must be connected. -// -// 4. The holes must be fully inside the outer ring. type Polygon struct { rings []LineString ctype CoordinatesType @@ -33,6 +22,10 @@ type Polygon struct { // any inner rings follow. If no rings are provided, then the returned Polygon // is the empty Polygon. The coordinate type of the polygon is the lowest // common coordinate type of its rings. +// +// An error is returned if any of the Polygon constraints are not met (see the +// Validate method for details). Note that the validity of each input +// LineString is not verified. func NewPolygon(rings []LineString, opts ...ConstructorOption) (Polygon, error) { ctype := DimXY if len(rings) > 0 { @@ -68,6 +61,10 @@ func NewPolygon(rings []LineString, opts ...ConstructorOption) (Polygon, error) // 3. The interior of the polygon must be connected. // // 4. The holes must be fully inside the outer ring. +// +// In addition to these constraints, this method also verifiers that the rings +// are valid LineStrings (i.e. have at least 2 distinct XY values, and don't +// contain NaN or Infinite values). func (p Polygon) Validate() error { for i, r := range p.rings { if err := r.Validate(); err != nil {