Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

isValid2DBoundingBox #6

Closed
M-Scott-Lassiter opened this issue May 23, 2022 · 2 comments
Closed

isValid2DBoundingBox #6

M-Scott-Lassiter opened this issue May 23, 2022 · 2 comments

Comments

@M-Scott-Lassiter
Copy link
Owner

M-Scott-Lassiter commented May 23, 2022

Description

Bounding boxes are an optional GeoJSON property that describe a box of longitude boundaries that run along meridians and latitude boundaries that are parallel to the equator. A 2D Bounding Box only describes longitude and latitude boundaries, whereas a 3D BBox describes an additional min and max altitude/depth value.

A GeoJSON object MAY have a member named "bbox" to include information on the coordinate range for its Geometries, Features, or FeatureCollections. The value of the bbox member MUST be an array of length 2*n where n is the number of dimensions represented in the contained geometries, with all axes of the most southwesterly point followed by all axes of the more northeasterly point. The axes order of a bbox follows the axes order of geometries.

The "bbox" values define shapes with edges that follow lines of constant longitude, latitude, and elevation.
~ https://datatracker.ietf.org/doc/html/rfc7946#section-5

Format

The values of a "bbox" array are [west, south, east, north], not [minx, miny, maxx, maxy].
~https://datatracker.ietf.org/doc/html/rfc7946#appendix-B.1

The Antimeridian

In the case of objects spanning the antimeridian, a bounding box becomes required.

Consider a set of point Features within the Fiji archipelago, straddling the antimeridian between 16 degrees S and 20 degrees S. The southwest corner of the box containing these Features is at 20 degrees S and 177 degrees E, and the northwest corner is at 16 degrees S and 178 degrees W. The antimeridian-spanning GeoJSON bounding box for this FeatureCollection is

"bbox": [177.0, -20.0, -178.0, -16.0]

and covers 5 degrees of longitude. The complementary bounding box for the same latitude band, not crossing the antimeridian, is

"bbox": [-178.0, -20.0, 177.0, -16.0]

and covers 355 degrees of longitude.

The latitude of the northeast corner is always greater than the latitude of the southwest corner, but bounding boxes that cross the antimeridian have a northeast corner longitude that is less than the longitude of the southwest corner.
~https://datatracker.ietf.org/doc/html/rfc7946#section-5.2

The Poles

An area that encompasses either the north or south pole will also require a bounding box that meets special use cases.

A bounding box that contains the North Pole extends from a southwest corner of "minlat" degrees N, 180 degrees W to a northeast corner of 90 degrees N, 180 degrees E. Viewed on a globe, this bounding box approximates a spherical cap bounded by the "minlat" circle of latitude.

"bbox": [-180.0, minlat, 180.0, 90.0]

A bounding box that contains the South Pole extends from a southwest corner of 90 degrees S, 180 degrees W to a northeast corner of "maxlat" degrees S, 180 degrees E.

"bbox": [-180.0, -90.0, 180.0, maxlat]

A bounding box that just touches the North Pole and forms a slice of an approximate spherical cap when viewed on a globe extends from a southwest corner of "minlat" degrees N and "westlon" degrees E to a northeast corner of 90 degrees N and "eastlon" degrees E.

"bbox": [westlon, minlat, eastlon, 90.0]

Similarly, a bounding box that just touches the South Pole and forms a slice of an approximate spherical cap when viewed on a globe has the following representation in GeoJSON.

"bbox": [westlon, -90.0, eastlon, maxlat]

Implementers MUST NOT use latitude values greater than 90 or less than -90 to imply an extent that is not a spherical cap.
~https://datatracker.ietf.org/doc/html/rfc7946#section-5.3

Boundaries

Any values outside of the WGS-84 standards should fail.

WGS84 Bounds: -180.0000, -90.0000, 180.0000, 90.0000
Projected Bounds: -180.0000, -90.0000, 180.0000, 90.0000
~ https://spatialreference.org/ref/epsg/wgs-84/
Also, see https://datatracker.ietf.org/doc/html/rfc7946#section-4

Although not explicitly stated, it can be inferred that the north value must be larger than the south value.

Valid GeoJSON Examples

Example of a 2D bbox member on a Feature:

{
    "type": "Feature",
    "bbox": [-10.0, -10.0, 10.0, 10.0],
    "geometry": {
        "type": "Polygon",
        "coordinates": [
            [
                [-10.0, -10.0],
                [10.0, -10.0],
                [10.0, 10.0],
                [-10.0, -10.0]
            ]
        ]
    }
}

Example of a 2D bbox member on a FeatureCollection:

{
    "type": "FeatureCollection",
    "bbox": [100.0, 0.0, 105.0, 1.0],
         "features": [
             ...
         ]
}

Example of a 2D bbox on a feature with a FeatureCollection that also has a bounding box:

{
    "type": "FeatureCollection",
    "bbox": [-100.0, -10, 10, 49.5],
         "features": [
             {
                 "type": "Feature",
                 "bbox": [-10.0, -10.0, 10.0, 10.0],
                 "geometry": {
                     ...
                 }
             },
             ...
         ]
}

Example of a 2D bbox that crosses the antimeridian:

{
    "type": "FeatureCollection",
    "bbox": [177.0, -20.0, -178.0, -16.0],
         "features": [
             ...
         ]
}

Example Matcher Usage

expect([-10.0, -10.0, 10.0, 10.0]).isValid2DBoundingBox()
expect([100.0, 0.0, 105.0, 1.0]).isValid2DBoundingBox()
expect([177.0, -20.0, -178.0, -16.0]).isValid2DBoundingBox() // Crosses antimeridian and spans 5 degrees

expect([-10.0, -10.0, 10.0, 100.0]).not.isValid2DBoundingBox() // North out of bounds
expect([100.0, 0.0, -100.0, 105.0, 1.0, 0.0]).not.isValid2DCoordinate() // 3D bounding box
expect({ bbox: [-10.0, -10.0, 10.0, 10.0] }).not.isValid2DCoordinate() // Object instead of bbox array

Passing Tests

Values in Range

  • Each quadrant
    • NW: [-20, 10, -10, 20]
    • NE: [10, 10, 20, 20]
    • SW: [-20, -20, -10, -10]
    • SE: [10, -20, 20, -10]
  • Spanning all quadrants
    • Prime meridian: [-10, -20, 20, 10]
    • Antimeridian: [170, -20, -170, 20]

Values at Edge Cases

  • Longitude Boundaries:
    • West: [-180, 10, 20, 20]
    • North: [10, 10, 180, 20]
  • Poles with Cap
    • North: [-180.0, 80, 180.0, 90.0]
    • South: [-180.0, -90, 180.0, -80.0]
  • Poles not Including Cap
    • North: [10, 80, 20, 90.0]
    • South: [-45, -90, -80, -80.0]
  • Spanning all longitudes
    • All longitudes: [-180, 10, 180, 20]
    • All latitudes: [-10, -90, 10, 90]
    • Whole Earth: [-180, -90, 180, 90]
  • Northern Boundary Equals Southern:
    • [-10, -20, 10, -20]
    • [-10, 20, 10, 20]
  • Eastern Boundary Equals Western
    • [-10, -20, -10, 20]
    • [10, -20, 10, 20]
  • All zeros
    • [0, 0, 0, 0]

Failing Tests

Bbox input not an array

  • undefined
  • null
  • Booleans: true, false
  • Numbers: 200, -200, Infinity, -Infinity, NaN
  • Objects: { bbox: [10, 10, 20, 20] }
  • Strings: '', 'Random Coordinate', '[10, 10, 20, 20]'

Incorrect number of array elements

  • [ ], [20], [20, 10], [20, 30, 0], [20, 30, 0, 0, 10], [20, 30, 0, 20, 30, 0], [20, 30, 0, 20, 30, 0, 20, 30, 0]

Coordinates out of range

  • Latitude: [-10, -90.0000001, 10, 0], [-10, 0, 10, 90.0000001], [-10, -90000, 10, 0], [-10, 0, 10, 90000]
  • Longitude: [-180.0000001, -10, -160, 10], [160, -10, 180.0000001, 10], [-1800000, -10, -160, 10], [160, -10, 1800000, 10]
  • Combination:
    • [-181, -10, 181, 10]
    • [-10, -91, 10, 91]
    • [-181, -91, 10, 10]
    • [-10, -10, 181, 91]
    • [-181, -91, 181, 91]

Illogical BBox

  • Northern Boundary Less Than Southern: [-10, 20, 10, -20]

BBox has non-numeric values

  • Each of the values in "Bbox input not an array" paired with valid inputs:
    • [<value>, -10, 10, 10]
    • [-10, <value>, 10, 10]
    • [-10, -10, <value>, 10]
    • [-10, -10, 10, <value>]
    • [<value>, <value>, <value>, <value>]

BBox values are arrays of numbers

[[-20], [10], [-10], [20]]

@M-Scott-Lassiter M-Scott-Lassiter added the new matcher proposal Proposal for a new GeoJSON matcher label May 23, 2022
@M-Scott-Lassiter M-Scott-Lassiter added this to To do in Bounding Boxes via automation May 23, 2022
@M-Scott-Lassiter M-Scott-Lassiter self-assigned this May 23, 2022
This was referenced May 23, 2022
@M-Scott-Lassiter M-Scott-Lassiter changed the title [New Matcher]: isValid2DBoundingBox isValid2DBoundingBox May 24, 2022
@M-Scott-Lassiter M-Scott-Lassiter moved this from To do to In progress in Bounding Boxes May 24, 2022
M-Scott-Lassiter added a commit that referenced this issue May 25, 2022
This matcher verifies a two dimensional bounding box meets WGS-84 and GeoJSON validity requirements.
This is the first matcher in the boundingBoxes category. Added the new folders, setup files, and
scripts.

Resolves: #6
github-actions bot pushed a commit that referenced this issue May 25, 2022
## [1.0.0-beta.4](v1.0.0-beta.3...v1.0.0-beta.4) (2022-05-25)

### 🏗️ Build Changes

* **package:** add entry points for all, boundingboxes, and coordinates ([8c1d312](8c1d312))

### 🎁 Feature Changes

* **isValid2DBoundingBox:** add new matcher function ([7fe56f3](7fe56f3)), closes [#6](#6)
* **isValid3DBoundingBox:** add new matcher ([6ee8cc6](6ee8cc6)), closes [#7](#7)

### 🎯 Test Changes

* **isValid2DBoundingBox:** fix typo in test descriptions ([df94c27](df94c27))

### 🧭 API Documentation Changes

* update JSDoc organization ([7ab7eca](7ab7eca))
@M-Scott-Lassiter
Copy link
Owner Author

🎉 This issue has been resolved in version 1.0.0-beta.4 🎉

The release is available on:

Your semantic-release bot 📦🚀

Bounding Boxes automation moved this from In progress to Done May 25, 2022
github-actions bot pushed a commit that referenced this issue Jun 2, 2022
## 1.0.0 (2022-06-02)

### 🧭 API Documentation Changes

* **toBeMultiLineStringGeometry:** add the min point count error to the JSDoc API ([01f6c4b](01f6c4b))
* change JSDoc param types to avoid using GeoJSON unknown types ([06ac03a](06ac03a))
* **all:** cleanup JSDoc formatting and standardize API examples ([300a96d](300a96d))
* update JSDoc descriptions of coordinate core functions ([f5658f3](f5658f3))
* update JSDoc organization ([7ab7eca](7ab7eca))
* **isValidCoordinate:** update returns description ([70bd43e](70bd43e))
* **isValidCoordinate:** update the error and parameter descriptions ([7e3e8ed](7e3e8ed))

### 🐞 Bug Fixes

* add bounding box validity checking to geometry core functions and matchers ([ac6a9a1](ac6a9a1)), closes [/datatracker.ietf.org/doc/html/rfc7946#section-5](https://github.com/M-Scott-Lassiter//datatracker.ietf.org/doc/html/rfc7946/issues/section-5) [#9](#9) [#10](#10) [#11](#11) [#12](#12) [#13](#13) [#14](#14) [#16](#16) [#29](#29)
* **toBeLineStringGeometry:** prohibit single coordinate in "coordinates" member ([ee5de52](ee5de52)), closes [/datatracker.ietf.org/doc/html/rfc7946#section-3](https://github.com/M-Scott-Lassiter//datatracker.ietf.org/doc/html/rfc7946/issues/section-3) [#11](#11)

### 🎯 Test Changes

* add 'Feature' and 'FeatureCollection' to test list of disallowed geometry type values ([f139a09](f139a09))
* **toBeLineStringGeometry:** add a stress test with many points ([22df5c7](22df5c7))
* **toBeGeometryCollection:** add an unrecognizable geometry to the invalid tests ([5c041c6](5c041c6))
* **toBeGeometryCollection:** add robust snapshot tests, verify coordinates treated as foreign member ([472d12d](472d12d)), closes [#32](#32) [#33](#33)
* **isValid2DBoundingBox:** add robust snapshot tests ([4363710](4363710)), closes [#32](#32)
* **isValid2DCoordinate:** add robust snapshot tests ([ae92f67](ae92f67)), closes [#32](#32)
* **isValid3DBoundingBox:** add robust snapshot tests ([a37ec48](a37ec48)), closes [#32](#32)
* **isValid3DCoordinate:** add robust snapshot tests ([56fbf92](56fbf92)), closes [#32](#32)
* **isValidBoundingBox:** add robust snapshot tests ([063b94e](063b94e)), closes [#32](#32)
* **isValidCoordinate:** add robust snapshot tests ([7b4a804](7b4a804)), closes [#32](#32)
* **toBeAnyGeometry:** add robust snapshot tests ([8a6e611](8a6e611)), closes [#32](#32)
* **toBeLineStringGeometry:** add robust snapshot tests ([cfaed46](cfaed46)), closes [#32](#32)
* **toBeMultiLineStringGeometry:** add robust snapshot tests ([57dc767](57dc767)), closes [#32](#32)
* **toBeMultiPointGeometry:** add robust snapshot tests ([36013e1](36013e1)), closes [#32](#32)
* **toBeMultiPolygonGeometry:** add robust snapshot tests ([df1c23a](df1c23a)), closes [#32](#32)
* **toBePointGeometry:** add robust snapshot tests ([fd5c516](fd5c516)), closes [#32](#32)
* **toBePolygonGeometry:** add robust snapshot tests ([1c9df69](1c9df69)), closes [#32](#32)
* **toBeMultiLineStringGeometry:** fix coordinate out of range test that ([d6fe2ac](d6fe2ac))
* **toBeMultiPointGeometry:** fix typo in test and core function that was omitting coverage ([bc10f4e](bc10f4e))
* **isValid2DBoundingBox:** fix typo in test descriptions ([df94c27](df94c27))
* setup the project testing framework ([6a95c37](6a95c37))

### 🎁 Feature Changes

* **isValid2DBoundingBox:** add new matcher function ([7fe56f3](7fe56f3)), closes [#6](#6)
* **isValid2DCoordinate:** add new matcher function ([527bbc4](527bbc4)), closes [#1](#1)
* **isValid3DCoordinate:** add new matcher function ([0329231](0329231)), closes [#2](#2)
* **isValidCoordinate:** add new matcher function ([d7e5b70](d7e5b70)), closes [#4](#4)
* **isValid3DBoundingBox:** add new matcher ([6ee8cc6](6ee8cc6)), closes [#7](#7)
* **isValidBoundingBox:** add new matcher ([9a8b7ed](9a8b7ed)), closes [#8](#8)
* **toBeAnyGeometry:** add new matcher ([ed7c3eb](ed7c3eb)), closes [#15](#15)
* **toBeFeature:** add new matcher ([551aa7f](551aa7f)), closes [#32](#32) [#24](#24)
* **toBeFeatureCollection:** add new matcher ([21fe044](21fe044)), closes [#25](#25)
* **toBeGeometryCollection:** add new matcher ([63cc919](63cc919)), closes [#16](#16)
* **toBeLineStringGeometry:** add new matcher ([54416a5](54416a5)), closes [#11](#11)
* **toBeMultiLineStringGeometry:** add new matcher ([3d3a15e](3d3a15e)), closes [#12](#12)
* **toBeMultiPointGeometry:** add new matcher ([9a12752](9a12752)), closes [#10](#10)
* **toBeMultiPolygonGeometry:** add new matcher ([41fef3a](41fef3a)), closes [#14](#14)
* **toBePointGeometry:** add new matcher ([9973afa](9973afa)), closes [#9](#9)
* **toBePolygonGeometry:** add new matcher ([3b9d18d](3b9d18d)), closes [#13](#13)
* split package exports into matcher and core functionality ([a7340d9](a7340d9)), closes [#5](#5)

### 🏗️ Build Changes

* add conventional-changelog-conventionalcommits as dev dependency ([7361d79](7361d79)), closes [#3](#3)
* **package:** add entry points for all, boundingboxes, and coordinates ([8c1d312](8c1d312))
* move release configuration into a separate shareable file ([fa6e50d](fa6e50d))
* **package:** rename matcher loader entry script ([5221d6d](5221d6d))
* setup initial project environment ([b468a41](b468a41))
* **package:** update the commitizen config for customized scopes ([ac05626](ac05626))
* **devDependencies:** upgrade Jest to v28.1, specify peerDependency at >v24.0.0 ([22d1614](22d1614)), closes [#30](#30)
* **package:** upgrade min required Node version to 16 ([58a9824](58a9824))
* **package:** upgrade minimum required node version from 10 to 14 to match LTS schedule ([1e8a8bb](1e8a8bb))
@M-Scott-Lassiter
Copy link
Owner Author

🎉 This issue has been resolved in version 1.0.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Development

No branches or pull requests

1 participant