fixed dependencies

This commit is contained in:
nuknal
2024-10-24 15:46:01 +08:00
parent d16a5bd9c0
commit 1161e8d054
2005 changed files with 690883 additions and 0 deletions

176
vendor/github.com/paulmach/orb/CHANGELOG.md generated vendored Normal file
View File

@@ -0,0 +1,176 @@
# Changelog
All notable changes to this project will be documented in this file.
## [v0.11.1](https://github.com/paulmach/orb/compare/v0.11.0...v0.11.1) - 2024-01-29
### Fixed
- geojson: `null` json into non-pointer Feature/FeatureCollection will set them to empty by [@paulmach](https://github.com/paulmach)in https://github.com/paulmach/orb/pull/145
## [v0.11.0](https://github.com/paulmach/orb/compare/v0.10.0...v0.11.0) - 2024-01-11
### Fixed
- quadtree: InBoundMatching does not properly accept passed-in buffer by [@nirmal-vuppuluri](https://github.com/nirmal-vuppuluri) in https://github.com/paulmach/orb/pull/139
- mvt: Do not swallow error cause by [@m-pavel](https://github.com/m-pavel) in https://github.com/paulmach/orb/pull/137
### Changed
- simplify: Visvalingam, by default, keeps 3 points for "areas" by [@paulmach](https://github.com/paulmach) in https://github.com/paulmach/orb/pull/140
- encoding/mvt: skip encoding of features will nil geometry by [@paulmach](https://github.com/paulmach) in https://github.com/paulmach/orb/pull/141
- encoding/wkt: improve unmarshalling performance by [@paulmach](https://github.com/paulmach) in https://github.com/paulmach/orb/pull/142
## [v0.10.0](https://github.com/paulmach/orb/compare/v0.9.2...v0.10.0) - 2023-07-16
### Added
- add ChildrenInZoomRange method to maptile.Tile by [@peitili](https://github.com/peitili) in https://github.com/paulmach/orb/pull/133
## [v0.9.2](https://github.com/paulmach/orb/compare/v0.9.1...v0.9.2) - 2023-05-04
### Fixed
- encoding/wkt: better handling/validation of missing parens by [@paulmach](https://github.com/paulmach) in https://github.com/paulmach/orb/pull/131
## [v0.9.1](https://github.com/paulmach/orb/compare/v0.9.0...v0.9.1) - 2023-04-26
### Fixed
- Bump up mongo driver to 1.11.4 by [@m-pavel](https://github.com/m-pavel) in https://github.com/paulmach/orb/pull/129
- encoding/wkt: split strings with regexp by [@m-pavel](https://github.com/m-pavel) in https://github.com/paulmach/orb/pull/128
## [v0.9.0](https://github.com/paulmach/orb/compare/v0.8.0...v0.9.0) - 2023-02-19
### Added
- geojson: marshal/unmarshal BSON [@paulmach](https://github.com/paulmach) in https://github.com/paulmach/orb/pull/123
## [v0.8.0](https://github.com/paulmach/orb/compare/v0.7.1...v0.8.0) - 2023-01-05
### Fixed
- quadtree: fix bad sort due to pointer allocation issue by [@paulmach](https://github.com/paulmach) in https://github.com/paulmach/orb/pull/115
- geojson: ensure geometry unmarshal errors get returned by [@paulmach](https://github.com/paulmach) in https://github.com/paulmach/orb/pull/117
- encoding/mvt: remove use of crypto/md5 to compare marshalling in tests by [@paulmach](https://github.com/paulmach) in https://github.com/paulmach/orb/pull/118
- encoding/wkt: fix panic for some invalid wkt data by [@paulmach](https://github.com/paulmach) in https://github.com/paulmach/orb/pull/119
### Other
- fix typo by [@rubenpoppe](https://github.com/rubenpoppe) in https://github.com/paulmach/orb/pull/107
- Fixed a small twister in README.md by [@Timahawk](https://github.com/Timahawk) in https://github.com/paulmach/orb/pull/108
- update github ci to use go 1.19 by [@paulmach](https://github.com/paulmach) in https://github.com/paulmach/orb/pull/116
## [v0.7.1](https://github.com/paulmach/orb/compare/v0.7.0...v0.7.1) - 2022-05-16
No changes
The v0.7.0 tag was updated since it initially pointed to the wrong commit. This is causing caching issues.
## [v0.7.0](https://github.com/paulmach/orb/compare/v0.6.0...v0.7.0) - 2022-05-10
This tag is broken, please use v0.7.1 instead.
### Breaking Changes
- tilecover now returns an error (vs. panicing) on non-closed 2d geometry by [@paulmach](https://github.com/paulmach) in https://github.com/paulmach/orb/pull/87
This changes the signature of many of the methods in the [maptile/tilecover](https://github.com/paulmach/orb/tree/master/maptile/tilecover) package.
To emulate the old behavior replace:
tiles := tilecover.Geometry(poly, zoom)
with
tiles, err := tilecover.Geometry(poly, zoom)
if err != nil {
panic(err)
}
## [v0.6.0](https://github.com/paulmach/orb/compare/v0.5.0...v0.6.0) - 2022-05-04
### Added
- geo: add correctly spelled LengthHaversine by [@paulmach](https://github.com/paulmach) in https://github.com/paulmach/orb/pull/97
- geojson: add support for "external" json encoders/decoders by [@paulmach](https://github.com/paulmach) in https://github.com/paulmach/orb/pull/98
- Add ewkb encoding/decoding support by [@paulmach](https://github.com/paulmach) in https://github.com/paulmach/orb/pull/88
## [v0.5.0](https://github.com/paulmach/orb/compare/v0.4.0...v0.5.0) - 2022-04-06
### Added
- encoding/mvt: stable marshalling by [@travisgrigsby](https://github.com/travisgrigsby) in https://github.com/paulmach/orb/pull/93
- encoding/mvt: support mvt marshal for GeometryCollection by [@dadadamarine](https://github.com/dadadamarine) in https://github.com/paulmach/orb/pull/89
### Fixed
- quadtree: fix cleanup of nodes during removal by [@paulmach](https://github.com/paulmach) in https://github.com/paulmach/orb/pull/94
### Other
- encoding/wkt: various code improvements by [@paulmach](https://github.com/paulmach) in https://github.com/paulmach/orb/pull/95
- update protoscan to 0.2.1 by [@paulmach](https://github.com/paulmach) in https://github.com/paulmach/orb/pull/83
## [v0.4.0](https://github.com/paulmach/orb/compare/v0.3.0...v0.4.0) - 2021-11-11
### Added
- geo: Add functions to calculate points based on distance and bearing by [@thzinc](https://github.com/thzinc) in https://github.com/paulmach/orb/pull/76
### Fixed
- encoding/mvt: avoid reflect nil value by [@nicklasaven](https://github.com/nicklasaven) in https://github.com/paulmach/orb/pull/78
## [v0.3.0](https://github.com/paulmach/orb/compare/v0.2.2...v0.3.0) - 2021-10-16
### Changed
- quadtree: sort KNearest results closest first by [@paulmach](https://github.com/paulmach) in https://github.com/paulmach/orb/pull/75
- ring: require >=4 points to return true when calling Closed() by [@missinglink](https://github.com/missinglink) in https://github.com/paulmach/orb/pull/70
### Fixed
- encoding/mvt: verify tile coord does not overflow for z > 20 by [@paulmach](https://github.com/paulmach) in https://github.com/paulmach/orb/pull/74
- quadtree: Address panic-ing quadtree.Matching(…) method when finding no closest node by [@willsalz](https://github.com/willsalz) in https://github.com/paulmach/orb/pull/73
## [v0.2.2](https://github.com/paulmach/orb/compare/v0.2.1...v0.2.2) - 2021-06-05
### Fixed
- Dependency resolution problems in some cases, issue https://github.com/paulmach/orb/issues/65, pr https://github.com/paulmach/orb/pull/66
## [v0.2.1](https://github.com/paulmach/orb/compare/v0.2.0...v0.2.1) - 2021-01-16
### Changed
- encoding/mvt: upgrade protoscan v0.1 -> v0.2 [`ad31566`](https://github.com/paulmach/orb/commit/ad31566942027c1cd30dd341f35123fb54676599)
- encoding/mvt: remove github.com/pkg/errors as a dependency [`d2e235`](https://github.com/paulmach/orb/commit/d2e23529a295a0d973cc787ad2742cb6ccbd5306)
## v0.2.0 - 2021-01-16
### Breaking Changes
- Foreign Members in Feature Collections
Extra attributes in a feature collection object will now be put into `featureCollection.ExtraMembers`.
Similarly, stuff in `ExtraMembers will be marshalled into the feature collection base.
The break happens if you were decoding these foreign members using something like
```go
type MyFeatureCollection struct {
geojson.FeatureCollection
Title string `json:"title"`
}
```
**The above will no longer work** in this release and it never supported marshalling. See https://github.com/paulmach/orb/pull/56 for more details.
- Features with nil/missing geometry will no longer return an errors
Previously missing or invalid geometry in a feature collection would return a `ErrInvalidGeometry` error.
However missing geometry is compliant with [section 3.2](https://tools.ietf.org/html/rfc7946#section-3.2) of the spec.
See https://github.com/paulmach/orb/issues/38 and https://github.com/paulmach/orb/pull/58 for more details.
### Changed
- encoding/mvt: faster unmarshalling for Mapbox Vector Tiles (MVT) see https://github.com/paulmach/orb/pull/57

20
vendor/github.com/paulmach/orb/LICENSE.md generated vendored Normal file
View File

@@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2017 Paul Mach
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

181
vendor/github.com/paulmach/orb/README.md generated vendored Normal file
View File

@@ -0,0 +1,181 @@
# orb [![CI](https://github.com/paulmach/orb/workflows/CI/badge.svg)](https://github.com/paulmach/orb/actions?query=workflow%3ACI+event%3Apush) [![codecov](https://codecov.io/gh/paulmach/orb/branch/master/graph/badge.svg?token=NuuTjLVpKW)](https://codecov.io/gh/paulmach/orb) [![Go Report Card](https://goreportcard.com/badge/github.com/paulmach/orb)](https://goreportcard.com/report/github.com/paulmach/orb) [![Go Reference](https://pkg.go.dev/badge/github.com/paulmach/orb.svg)](https://pkg.go.dev/github.com/paulmach/orb)
Package `orb` defines a set of types for working with 2d geo and planar/projected geometric data in Golang.
There are a set of sub-packages that use these types to do interesting things.
They each provide their own README with extra info.
## Interesting features
- **Simple types** - allow for natural operations using the `make`, `append`, `len`, `[s:e]` builtins.
- **GeoJSON** - support as part of the [`geojson`](geojson) sub-package.
- **Mapbox Vector Tile** - encoding and decoding as part of the [`encoding/mvt`](encoding/mvt) sub-package.
- **Direct to type from DB query results** - by scanning WKB data directly into types.
- **Rich set of sub-packages** - including [`clipping`](clip), [`simplifing`](simplify), [`quadtree`](quadtree) and more.
## Type definitions
```go
type Point [2]float64
type MultiPoint []Point
type LineString []Point
type MultiLineString []LineString
type Ring LineString
type Polygon []Ring
type MultiPolygon []Polygon
type Collection []Geometry
type Bound struct { Min, Max Point }
```
Defining the types as slices allows them to be accessed in an idiomatic way
using Go's built-in functions such at `make`, `append`, `len`
and with slice notation like `[s:e]`. For example:
```go
ls := make(orb.LineString, 0, 100)
ls = append(ls, orb.Point{1, 1})
point := ls[0]
```
### Shared `Geometry` interface
All of the base types implement the `orb.Geometry` interface defined as:
```go
type Geometry interface {
GeoJSONType() string
Dimensions() int // e.g. 0d, 1d, 2d
Bound() Bound
}
```
This interface is accepted by functions in the sub-packages which then act on the
base types correctly. For example:
```go
l := clip.Geometry(bound, geom)
```
will use the appropriate clipping algorithm depending on if the input is 1d or 2d,
e.g. a `orb.LineString` or a `orb.Polygon`.
Only a few methods are defined directly on these type, for example `Clone`, `Equal`, `GeoJSONType`.
Other operation that depend on geo vs. planar contexts are defined in the respective sub-package.
For example:
- Computing the geo distance between two point:
```go
p1 := orb.Point{-72.796408, -45.407131}
p2 := orb.Point{-72.688541, -45.384987}
geo.Distance(p1, p2)
```
- Compute the planar area and centroid of a polygon:
```go
poly := orb.Polygon{...}
centroid, area := planar.CentroidArea(poly)
```
## GeoJSON
The [geojson](geojson) sub-package implements Marshalling and Unmarshalling of GeoJSON data.
Features are defined as:
```go
type Feature struct {
ID interface{} `json:"id,omitempty"`
Type string `json:"type"`
Geometry orb.Geometry `json:"geometry"`
Properties Properties `json:"properties"`
}
```
Defining the geometry as an `orb.Geometry` interface along with sub-package functions
accepting geometries allows them to work together to create easy to follow code.
For example, clipping all the geometries in a collection:
```go
fc, err := geojson.UnmarshalFeatureCollection(data)
for _, f := range fc {
f.Geometry = clip.Geometry(bound, f.Geometry)
}
```
The library supports third party "encoding/json" replacements
such [github.com/json-iterator/go](https://github.com/json-iterator/go).
See the [geojson](geojson) readme for more details.
The types also support BSON so they can be used directly when working with MongoDB.
## Mapbox Vector Tiles
The [encoding/mvt](encoding/mvt) sub-package implements Marshalling and
Unmarshalling [MVT](https://www.mapbox.com/vector-tiles/) data.
This package uses sets of `geojson.FeatureCollection` to define the layers,
keyed by the layer name. For example:
```go
collections := map[string]*geojson.FeatureCollection{}
// Convert to a layers object and project to tile coordinates.
layers := mvt.NewLayers(collections)
layers.ProjectToTile(maptile.New(x, y, z))
// In order to be used as source for MapboxGL geometries need to be clipped
// to max allowed extent. (uncomment next line)
// layers.Clip(mvt.MapboxGLDefaultExtentBound)
// Simplify the geometry now that it's in tile coordinate space.
layers.Simplify(simplify.DouglasPeucker(1.0))
// Depending on use-case remove empty geometry, those too small to be
// represented in this tile space.
// In this case lines shorter than 1, and areas smaller than 2.
layers.RemoveEmpty(1.0, 2.0)
// encoding using the Mapbox Vector Tile protobuf encoding.
data, err := mvt.Marshal(layers) // this data is NOT gzipped.
// Sometimes MVT data is stored and transfered gzip compressed. In that case:
data, err := mvt.MarshalGzipped(layers)
```
## Decoding WKB/EWKB from a database query
Geometries are usually returned from databases in WKB or EWKB format. The [encoding/ewkb](encoding/ewkb)
sub-package offers helpers to "scan" the data into the base types directly.
For example:
```go
db.Exec(
"INSERT INTO postgis_table (point_column) VALUES (ST_GeomFromEWKB(?))",
ewkb.Value(orb.Point{1, 2}, 4326),
)
row := db.QueryRow("SELECT ST_AsBinary(point_column) FROM postgis_table")
var p orb.Point
err := row.Scan(ewkb.Scanner(&p))
```
For more information see the readme in the [encoding/ewkb](encoding/ewkb) package.
## List of sub-package utilities
- [`clip`](clip) - clipping geometry to a bounding box
- [`encoding/mvt`](encoding/mvt) - encoded and decoding from [Mapbox Vector Tiles](https://www.mapbox.com/vector-tiles/)
- [`encoding/wkb`](encoding/wkb) - well-known binary as well as helpers to decode from the database queries
- [`encoding/ewkb`](encoding/ewkb) - extended well-known binary format that includes the SRID
- [`encoding/wkt`](encoding/wkt) - well-known text encoding
- [`geojson`](geojson) - working with geojson and the types in this package
- [`maptile`](maptile) - working with mercator map tiles and quadkeys
- [`project`](project) - project geometries between geo and planar contexts
- [`quadtree`](quadtree) - quadtree implementation using the types in this package
- [`resample`](resample) - resample points in a line string geometry
- [`simplify`](simplify) - linear geometry simplifications like Douglas-Peucker

172
vendor/github.com/paulmach/orb/bound.go generated vendored Normal file
View File

@@ -0,0 +1,172 @@
package orb
import (
"math"
)
var emptyBound = Bound{Min: Point{1, 1}, Max: Point{-1, -1}}
// A Bound represents a closed box or rectangle.
// To create a bound with two points you can do something like:
// orb.MultiPoint{p1, p2}.Bound()
type Bound struct {
Min, Max Point
}
// GeoJSONType returns the GeoJSON type for the object.
func (b Bound) GeoJSONType() string {
return "Polygon"
}
// Dimensions returns 2 because a Bound is a 2d object.
func (b Bound) Dimensions() int {
return 2
}
// ToPolygon converts the bound into a Polygon object.
func (b Bound) ToPolygon() Polygon {
return Polygon{b.ToRing()}
}
// ToRing converts the bound into a loop defined
// by the boundary of the box.
func (b Bound) ToRing() Ring {
return Ring{
b.Min,
Point{b.Max[0], b.Min[1]},
b.Max,
Point{b.Min[0], b.Max[1]},
b.Min,
}
}
// Extend grows the bound to include the new point.
func (b Bound) Extend(point Point) Bound {
// already included, no big deal
if b.Contains(point) {
return b
}
return Bound{
Min: Point{
math.Min(b.Min[0], point[0]),
math.Min(b.Min[1], point[1]),
},
Max: Point{
math.Max(b.Max[0], point[0]),
math.Max(b.Max[1], point[1]),
},
}
}
// Union extends this bound to contain the union of this and the given bound.
func (b Bound) Union(other Bound) Bound {
if other.IsEmpty() {
return b
}
b = b.Extend(other.Min)
b = b.Extend(other.Max)
b = b.Extend(other.LeftTop())
b = b.Extend(other.RightBottom())
return b
}
// Contains determines if the point is within the bound.
// Points on the boundary are considered within.
func (b Bound) Contains(point Point) bool {
if point[1] < b.Min[1] || b.Max[1] < point[1] {
return false
}
if point[0] < b.Min[0] || b.Max[0] < point[0] {
return false
}
return true
}
// Intersects determines if two bounds intersect.
// Returns true if they are touching.
func (b Bound) Intersects(bound Bound) bool {
if (b.Max[0] < bound.Min[0]) ||
(b.Min[0] > bound.Max[0]) ||
(b.Max[1] < bound.Min[1]) ||
(b.Min[1] > bound.Max[1]) {
return false
}
return true
}
// Pad extends the bound in all directions by the given value.
func (b Bound) Pad(d float64) Bound {
b.Min[0] -= d
b.Min[1] -= d
b.Max[0] += d
b.Max[1] += d
return b
}
// Center returns the center of the bounds by "averaging" the x and y coords.
func (b Bound) Center() Point {
return Point{
(b.Min[0] + b.Max[0]) / 2.0,
(b.Min[1] + b.Max[1]) / 2.0,
}
}
// Top returns the top of the bound.
func (b Bound) Top() float64 {
return b.Max[1]
}
// Bottom returns the bottom of the bound.
func (b Bound) Bottom() float64 {
return b.Min[1]
}
// Right returns the right of the bound.
func (b Bound) Right() float64 {
return b.Max[0]
}
// Left returns the left of the bound.
func (b Bound) Left() float64 {
return b.Min[0]
}
// LeftTop returns the upper left point of the bound.
func (b Bound) LeftTop() Point {
return Point{b.Left(), b.Top()}
}
// RightBottom return the lower right point of the bound.
func (b Bound) RightBottom() Point {
return Point{b.Right(), b.Bottom()}
}
// IsEmpty returns true if it contains zero area or if
// it's in some malformed negative state where the left point is larger than the right.
// This can be caused by padding too much negative.
func (b Bound) IsEmpty() bool {
return b.Min[0] > b.Max[0] || b.Min[1] > b.Max[1]
}
// IsZero return true if the bound just includes just null island.
func (b Bound) IsZero() bool {
return b.Max == Point{} && b.Min == Point{}
}
// Bound returns the the same bound.
func (b Bound) Bound() Bound {
return b
}
// Equal returns if two bounds are equal.
func (b Bound) Equal(c Bound) bool {
return b.Min == c.Min && b.Max == c.Max
}

56
vendor/github.com/paulmach/orb/clone.go generated vendored Normal file
View File

@@ -0,0 +1,56 @@
package orb
import (
"fmt"
)
// Clone will make a deep copy of the geometry.
func Clone(g Geometry) Geometry {
if g == nil {
return nil
}
switch g := g.(type) {
case Point:
return g
case MultiPoint:
if g == nil {
return nil
}
return g.Clone()
case LineString:
if g == nil {
return nil
}
return g.Clone()
case MultiLineString:
if g == nil {
return nil
}
return g.Clone()
case Ring:
if g == nil {
return nil
}
return g.Clone()
case Polygon:
if g == nil {
return nil
}
return g.Clone()
case MultiPolygon:
if g == nil {
return nil
}
return g.Clone()
case Collection:
if g == nil {
return nil
}
return g.Clone()
case Bound:
return g
}
panic(fmt.Sprintf("geometry type not supported: %T", g))
}

10
vendor/github.com/paulmach/orb/codecov.yml generated vendored Normal file
View File

@@ -0,0 +1,10 @@
coverage:
status:
project: off
patch: off
precision: 2
round: down
range: "70...90"
comment: false

44
vendor/github.com/paulmach/orb/define.go generated vendored Normal file
View File

@@ -0,0 +1,44 @@
package orb
// EarthRadius is the radius of the earth in meters. It is used in geo distance calculations.
// To keep things consistent, this value matches WGS84 Web Mercator (EPSG:3857).
const EarthRadius = 6378137.0 // meters
// DefaultRoundingFactor is the default rounding factor used by the Round func.
var DefaultRoundingFactor = 1e6 // 6 decimal places
// Orientation defines the order of the points in a polygon
// or closed ring.
type Orientation int8
// Constants to define orientation.
// They follow the right hand rule for orientation.
const (
// CCW stands for Counter Clock Wise
CCW Orientation = 1
// CW stands for Clock Wise
CW Orientation = -1
)
// A DistanceFunc is a function that computes the distance between two points.
type DistanceFunc func(Point, Point) float64
// A Projection a function that moves a point from one space to another.
type Projection func(Point) Point
// Pointer is something that can be represented by a point.
type Pointer interface {
Point() Point
}
// A Simplifier is something that can simplify geometry.
type Simplifier interface {
Simplify(g Geometry) Geometry
LineString(ls LineString) LineString
MultiLineString(mls MultiLineString) MultiLineString
Ring(r Ring) Ring
Polygon(p Polygon) Polygon
MultiPolygon(mp MultiPolygon) MultiPolygon
Collection(c Collection) Collection
}

51
vendor/github.com/paulmach/orb/equal.go generated vendored Normal file
View File

@@ -0,0 +1,51 @@
package orb
import (
"fmt"
)
// Equal returns if the two geometrires are equal.
func Equal(g1, g2 Geometry) bool {
if g1 == nil || g2 == nil {
return g1 == g2
}
if g1.GeoJSONType() != g2.GeoJSONType() {
return false
}
switch g1 := g1.(type) {
case Point:
return g1.Equal(g2.(Point))
case MultiPoint:
return g1.Equal(g2.(MultiPoint))
case LineString:
return g1.Equal(g2.(LineString))
case MultiLineString:
return g1.Equal(g2.(MultiLineString))
case Ring:
g2, ok := g2.(Ring)
if !ok {
return false
}
return g1.Equal(g2)
case Polygon:
g2, ok := g2.(Polygon)
if !ok {
return false
}
return g1.Equal(g2)
case MultiPolygon:
return g1.Equal(g2.(MultiPolygon))
case Collection:
return g1.Equal(g2.(Collection))
case Bound:
g2, ok := g2.(Bound)
if !ok {
return false
}
return g1.Equal(g2)
}
panic(fmt.Sprintf("geometry type not supported: %T", g1))
}

60
vendor/github.com/paulmach/orb/geo/README.md generated vendored Normal file
View File

@@ -0,0 +1,60 @@
# orb/geo [![Godoc Reference](https://pkg.go.dev/badge/github.com/paulmach/orb)](https://pkg.go.dev/github.com/paulmach/orb/geo)
The geometries defined in the `orb` package are generic 2d geometries.
Depending on what projection they're in, e.g. lon/lat or flat on the plane,
area and distance calculations are different. This package implements methods
that assume the lon/lat or WGS84 projection.
## Examples
Area of the [San Francisco Main Library](https://www.openstreetmap.org/way/24446086):
```go
poly := orb.Polygon{
{
{ -122.4163816, 37.7792782 },
{ -122.4162786, 37.7787626 },
{ -122.4151027, 37.7789118 },
{ -122.4152143, 37.7794274 },
{ -122.4163816, 37.7792782 },
},
}
a := geo.Area(poly)
fmt.Printf("%f m^2", a)
// Output:
// 6073.368008 m^2
```
Distance between two points:
```go
oakland := orb.Point{-122.270833, 37.804444}
sf := orb.Point{-122.416667, 37.783333}
d := geo.Distance(oakland, sf)
fmt.Printf("%0.3f meters", d)
// Output:
// 13042.047 meters
```
Circumference of the [San Francisco Main Library](https://www.openstreetmap.org/way/24446086):
```go
poly := orb.Polygon{
{
{ -122.4163816, 37.7792782 },
{ -122.4162786, 37.7787626 },
{ -122.4151027, 37.7789118 },
{ -122.4152143, 37.7794274 },
{ -122.4163816, 37.7792782 },
},
}
l := geo.Length(poly)
fmt.Printf("%0.0f meters", l)
// Output:
// 325 meters
```

112
vendor/github.com/paulmach/orb/geo/area.go generated vendored Normal file
View File

@@ -0,0 +1,112 @@
// Package geo computes properties on geometries assuming they are lon/lat data.
package geo
import (
"fmt"
"math"
"github.com/paulmach/orb"
)
// Area returns the area of the geometry on the earth.
func Area(g orb.Geometry) float64 {
if g == nil {
return 0
}
switch g := g.(type) {
case orb.Point, orb.MultiPoint, orb.LineString, orb.MultiLineString:
return 0
case orb.Ring:
return math.Abs(ringArea(g))
case orb.Polygon:
return polygonArea(g)
case orb.MultiPolygon:
return multiPolygonArea(g)
case orb.Collection:
return collectionArea(g)
case orb.Bound:
return Area(g.ToRing())
}
panic(fmt.Sprintf("geometry type not supported: %T", g))
}
// SignedArea will return the signed area of the ring.
// Will return negative if the ring is in the clockwise direction.
// Will implicitly close the ring.
func SignedArea(r orb.Ring) float64 {
return ringArea(r)
}
func ringArea(r orb.Ring) float64 {
if len(r) < 3 {
return 0
}
var lo, mi, hi int
l := len(r)
if r[0] != r[len(r)-1] {
// if not a closed ring, add an implicit calc for that last point.
l++
}
// To support implicit closing of ring, replace references to
// the last point in r to the first 1.
area := 0.0
for i := 0; i < l; i++ {
if i == l-3 { // i = N-3
lo = l - 3
mi = l - 2
hi = 0
} else if i == l-2 { // i = N-2
lo = l - 2
mi = 0
hi = 0
} else if i == l-1 { // i = N-1
lo = 0
mi = 0
hi = 1
} else { // i = 0 to N-3
lo = i
mi = i + 1
hi = i + 2
}
area += (deg2rad(r[hi][0]) - deg2rad(r[lo][0])) * math.Sin(deg2rad(r[mi][1]))
}
return -area * orb.EarthRadius * orb.EarthRadius / 2
}
func polygonArea(p orb.Polygon) float64 {
if len(p) == 0 {
return 0
}
sum := math.Abs(ringArea(p[0]))
for i := 1; i < len(p); i++ {
sum -= math.Abs(ringArea(p[i]))
}
return sum
}
func multiPolygonArea(mp orb.MultiPolygon) float64 {
sum := 0.0
for _, p := range mp {
sum += polygonArea(p)
}
return sum
}
func collectionArea(c orb.Collection) float64 {
area := 0.0
for _, g := range c {
area += Area(g)
}
return area
}

97
vendor/github.com/paulmach/orb/geo/bound.go generated vendored Normal file
View File

@@ -0,0 +1,97 @@
package geo
import (
"math"
"github.com/paulmach/orb"
)
// NewBoundAroundPoint creates a new bound given a center point,
// and a distance from the center point in meters.
func NewBoundAroundPoint(center orb.Point, distance float64) orb.Bound {
radDist := distance / orb.EarthRadius
radLat := deg2rad(center[1])
radLon := deg2rad(center[0])
minLat := radLat - radDist
maxLat := radLat + radDist
var minLon, maxLon float64
if minLat > minLatitude && maxLat < maxLatitude {
deltaLon := math.Asin(math.Sin(radDist) / math.Cos(radLat))
minLon = radLon - deltaLon
if minLon < minLongitude {
minLon += 2 * math.Pi
}
maxLon = radLon + deltaLon
if maxLon > maxLongitude {
maxLon -= 2 * math.Pi
}
} else {
minLat = math.Max(minLat, minLatitude)
maxLat = math.Min(maxLat, maxLatitude)
minLon = minLongitude
maxLon = maxLongitude
}
return orb.Bound{
Min: orb.Point{rad2deg(minLon), rad2deg(minLat)},
Max: orb.Point{rad2deg(maxLon), rad2deg(maxLat)},
}
}
// BoundPad expands the bound in all directions by the given amount of meters.
func BoundPad(b orb.Bound, meters float64) orb.Bound {
dy := meters / 111131.75
dx := dy / math.Cos(deg2rad(b.Max[1]))
dx = math.Max(dx, dy/math.Cos(deg2rad(b.Min[1])))
b.Min[0] -= dx
b.Min[1] -= dy
b.Max[0] += dx
b.Max[1] += dy
b.Min[0] = math.Max(b.Min[0], -180)
b.Min[1] = math.Max(b.Min[1], -90)
b.Max[0] = math.Min(b.Max[0], 180)
b.Max[1] = math.Min(b.Max[1], 90)
return b
}
// BoundHeight returns the approximate height in meters.
func BoundHeight(b orb.Bound) float64 {
return 111131.75 * (b.Max[1] - b.Min[1])
}
// BoundWidth returns the approximate width in meters
// of the center of the bound.
func BoundWidth(b orb.Bound) float64 {
c := (b.Min[1] + b.Max[1]) / 2.0
s1 := orb.Point{b.Min[0], c}
s2 := orb.Point{b.Max[0], c}
return Distance(s1, s2)
}
//MinLatitude is the minimum possible latitude
var minLatitude = deg2rad(-90)
//MaxLatitude is the maxiumum possible latitude
var maxLatitude = deg2rad(90)
//MinLongitude is the minimum possible longitude
var minLongitude = deg2rad(-180)
//MaxLongitude is the maxiumum possible longitude
var maxLongitude = deg2rad(180)
func deg2rad(d float64) float64 {
return d * math.Pi / 180.0
}
func rad2deg(r float64) float64 {
return 180.0 * r / math.Pi
}

119
vendor/github.com/paulmach/orb/geo/distance.go generated vendored Normal file
View File

@@ -0,0 +1,119 @@
package geo
import (
"math"
"github.com/paulmach/orb"
)
// Distance returns the distance between two points on the earth.
func Distance(p1, p2 orb.Point) float64 {
dLat := deg2rad(p1[1] - p2[1])
dLon := deg2rad(p1[0] - p2[0])
dLon = math.Abs(dLon)
if dLon > math.Pi {
dLon = 2*math.Pi - dLon
}
// fast way using pythagorean theorem on an equirectangular projection
x := dLon * math.Cos(deg2rad((p1[1]+p2[1])/2.0))
return math.Sqrt(dLat*dLat+x*x) * orb.EarthRadius
}
// DistanceHaversine computes the distance on the earth using the
// more accurate haversine formula.
func DistanceHaversine(p1, p2 orb.Point) float64 {
dLat := deg2rad(p1[1] - p2[1])
dLon := deg2rad(p1[0] - p2[0])
dLat2Sin := math.Sin(dLat / 2)
dLon2Sin := math.Sin(dLon / 2)
a := dLat2Sin*dLat2Sin + math.Cos(deg2rad(p2[1]))*math.Cos(deg2rad(p1[1]))*dLon2Sin*dLon2Sin
return 2.0 * orb.EarthRadius * math.Atan2(math.Sqrt(a), math.Sqrt(1-a))
}
// Bearing computes the direction one must start traveling on earth
// to be heading from, to the given points.
func Bearing(from, to orb.Point) float64 {
dLon := deg2rad(to[0] - from[0])
fromLatRad := deg2rad(from[1])
toLatRad := deg2rad(to[1])
y := math.Sin(dLon) * math.Cos(toLatRad)
x := math.Cos(fromLatRad)*math.Sin(toLatRad) - math.Sin(fromLatRad)*math.Cos(toLatRad)*math.Cos(dLon)
return rad2deg(math.Atan2(y, x))
}
// Midpoint returns the half-way point along a great circle path between the two points.
func Midpoint(p, p2 orb.Point) orb.Point {
dLon := deg2rad(p2[0] - p[0])
aLatRad := deg2rad(p[1])
bLatRad := deg2rad(p2[1])
x := math.Cos(bLatRad) * math.Cos(dLon)
y := math.Cos(bLatRad) * math.Sin(dLon)
r := orb.Point{
deg2rad(p[0]) + math.Atan2(y, math.Cos(aLatRad)+x),
math.Atan2(math.Sin(aLatRad)+math.Sin(bLatRad), math.Sqrt((math.Cos(aLatRad)+x)*(math.Cos(aLatRad)+x)+y*y)),
}
// convert back to degrees
r[0] = rad2deg(r[0])
r[1] = rad2deg(r[1])
return r
}
// PointAtBearingAndDistance returns the point at the given bearing and distance in meters from the point
func PointAtBearingAndDistance(p orb.Point, bearing, distance float64) orb.Point {
aLat := deg2rad(p[1])
aLon := deg2rad(p[0])
bearingRadians := deg2rad(bearing)
distanceRatio := distance / orb.EarthRadius
bLat := math.Asin(math.Sin(aLat)*math.Cos(distanceRatio) + math.Cos(aLat)*math.Sin(distanceRatio)*math.Cos(bearingRadians))
bLon := aLon +
math.Atan2(
math.Sin(bearingRadians)*math.Sin(distanceRatio)*math.Cos(aLat),
math.Cos(distanceRatio)-math.Sin(aLat)*math.Sin(bLat),
)
return orb.Point{rad2deg(bLon), rad2deg(bLat)}
}
func PointAtDistanceAlongLine(ls orb.LineString, distance float64) (orb.Point, float64) {
if len(ls) == 0 {
panic("empty LineString")
}
if distance < 0 || len(ls) == 1 {
return ls[0], 0.0
}
var (
travelled = 0.0
from, to orb.Point
)
for i := 1; i < len(ls); i++ {
from, to = ls[i-1], ls[i]
actualSegmentDistance := DistanceHaversine(from, to)
expectedSegmentDistance := distance - travelled
if expectedSegmentDistance < actualSegmentDistance {
bearing := Bearing(from, to)
return PointAtBearingAndDistance(from, bearing, expectedSegmentDistance), bearing
}
travelled += actualSegmentDistance
}
return to, Bearing(from, to)
}

26
vendor/github.com/paulmach/orb/geo/length.go generated vendored Normal file
View File

@@ -0,0 +1,26 @@
package geo
import (
"github.com/paulmach/orb"
"github.com/paulmach/orb/internal/length"
)
// Length returns the length of the boundary of the geometry
// using the geo distance function.
func Length(g orb.Geometry) float64 {
return length.Length(g, Distance)
}
// LengthHaversign returns the length of the boundary of the geometry
// using the geo haversine formula
//
// Deprecated: misspelled, use correctly spelled `LengthHaversine` instead.
func LengthHaversign(g orb.Geometry) float64 {
return length.Length(g, DistanceHaversine)
}
// LengthHaversine returns the length of the boundary of the geometry
// using the geo haversine formula
func LengthHaversine(g orb.Geometry) float64 {
return length.Length(g, DistanceHaversine)
}

132
vendor/github.com/paulmach/orb/geojson/README.md generated vendored Normal file
View File

@@ -0,0 +1,132 @@
# orb/geojson [![Godoc Reference](https://pkg.go.dev/badge/github.com/paulmach/orb)](https://pkg.go.dev/github.com/paulmach/orb/geojson)
This package **encodes and decodes** [GeoJSON](http://geojson.org/) into Go structs
using the geometries in the [orb](https://github.com/paulmach/orb) package.
Supports both the [json.Marshaler](https://pkg.go.dev/encoding/json#Marshaler) and
[json.Unmarshaler](https://pkg.go.dev/encoding/json#Unmarshaler) interfaces.
The package also provides helper functions such as `UnmarshalFeatureCollection` and `UnmarshalFeature`.
The types also support BSON via the [bson.Marshaler](https://pkg.go.dev/go.mongodb.org/mongo-driver/bson#Marshaler) and
[bson.Unmarshaler](https://pkg.go.dev/go.mongodb.org/mongo-driver/bson#Unmarshaler) interfaces.
These types can be used directly when working with MongoDB.
## Unmarshalling (JSON -> Go)
```go
rawJSON := []byte(`
{ "type": "FeatureCollection",
"features": [
{ "type": "Feature",
"geometry": {"type": "Point", "coordinates": [102.0, 0.5]},
"properties": {"prop0": "value0"}
}
]
}`)
fc, _ := geojson.UnmarshalFeatureCollection(rawJSON)
// or
fc := geojson.NewFeatureCollection()
err := json.Unmarshal(rawJSON, &fc)
// Geometry will be unmarshalled into the correct geo.Geometry type.
point := fc.Features[0].Geometry.(orb.Point)
```
## Marshalling (Go -> JSON)
```go
fc := geojson.NewFeatureCollection()
fc.Append(geojson.NewFeature(orb.Point{1, 2}))
rawJSON, _ := fc.MarshalJSON()
// or
blob, _ := json.Marshal(fc)
```
## Foreign/extra members in a feature collection
```go
rawJSON := []byte(`
{ "type": "FeatureCollection",
"generator": "myapp",
"timestamp": "2020-06-15T01:02:03Z",
"features": [
{ "type": "Feature",
"geometry": {"type": "Point", "coordinates": [102.0, 0.5]},
"properties": {"prop0": "value0"}
}
]
}`)
fc, _ := geojson.UnmarshalFeatureCollection(rawJSON)
fc.ExtraMembers["generator"] // == "myApp"
fc.ExtraMembers["timestamp"] // == "2020-06-15T01:02:03Z"
// Marshalling will include values in `ExtraMembers` in the
// base featureCollection object.
```
## Performance
For performance critical applications, consider a
third party replacement of "encoding/json" like [github.com/json-iterator/go](https://github.com/json-iterator/go)
This can be enabled with something like this:
```go
import (
jsoniter "github.com/json-iterator/go"
"github.com/paulmach/orb"
)
var c = jsoniter.Config{
EscapeHTML: true,
SortMapKeys: false,
MarshalFloatWith6Digits: true,
}.Froze()
CustomJSONMarshaler = c
CustomJSONUnmarshaler = c
```
The above change can have dramatic performance implications, see the benchmarks below
on a 100k feature collection file:
```
benchmark old ns/op new ns/op delta
BenchmarkFeatureMarshalJSON-12 2694543 733480 -72.78%
BenchmarkFeatureUnmarshalJSON-12 5383825 2738183 -49.14%
BenchmarkGeometryMarshalJSON-12 210107 62789 -70.12%
BenchmarkGeometryUnmarshalJSON-12 691472 144689 -79.08%
benchmark old allocs new allocs delta
BenchmarkFeatureMarshalJSON-12 7818 2316 -70.38%
BenchmarkFeatureUnmarshalJSON-12 23047 31946 +38.61%
BenchmarkGeometryMarshalJSON-12 2 3 +50.00%
BenchmarkGeometryUnmarshalJSON-12 2042 18 -99.12%
benchmark old bytes new bytes delta
BenchmarkFeatureMarshalJSON-12 794088 490251 -38.26%
BenchmarkFeatureUnmarshalJSON-12 766354 1068497 +39.43%
BenchmarkGeometryMarshalJSON-12 24787 18650 -24.76%
BenchmarkGeometryUnmarshalJSON-12 79784 51374 -35.61%
```
## Feature Properties
GeoJSON features can have properties of any type. This can cause issues in a statically typed
language such as Go. Included is a `Properties` type with some helper methods that will try to
force convert a property. An optional default, will be used if the property is missing or the wrong
type.
```go
f.Properties.MustBool(key string, def ...bool) bool
f.Properties.MustFloat64(key string, def ...float64) float64
f.Properties.MustInt(key string, def ...int) int
f.Properties.MustString(key string, def ...string) string
```

38
vendor/github.com/paulmach/orb/geojson/bbox.go generated vendored Normal file
View File

@@ -0,0 +1,38 @@
package geojson
import "github.com/paulmach/orb"
// BBox is for the geojson bbox attribute which is an array with all axes
// of the most southwesterly point followed by all axes of the more northeasterly point.
type BBox []float64
// NewBBox creates a bbox from a a bound.
func NewBBox(b orb.Bound) BBox {
return []float64{
b.Min[0], b.Min[1],
b.Max[0], b.Max[1],
}
}
// Valid checks if the bbox is present and has at least 4 elements.
func (bb BBox) Valid() bool {
if bb == nil {
return false
}
return len(bb) >= 4 && len(bb)%2 == 0
}
// Bound returns the orb.Bound for the BBox.
func (bb BBox) Bound() orb.Bound {
if !bb.Valid() {
return orb.Bound{}
}
mid := len(bb) / 2
return orb.Bound{
Min: orb.Point{bb[0], bb[1]},
Max: orb.Point{bb[mid], bb[mid+1]},
}
}

138
vendor/github.com/paulmach/orb/geojson/feature.go generated vendored Normal file
View File

@@ -0,0 +1,138 @@
package geojson
import (
"bytes"
"fmt"
"github.com/paulmach/orb"
"go.mongodb.org/mongo-driver/bson"
)
// A Feature corresponds to GeoJSON feature object
type Feature struct {
ID interface{} `json:"id,omitempty"`
Type string `json:"type"`
BBox BBox `json:"bbox,omitempty"`
Geometry orb.Geometry `json:"geometry"`
Properties Properties `json:"properties"`
}
// NewFeature creates and initializes a GeoJSON feature given the required attributes.
func NewFeature(geometry orb.Geometry) *Feature {
return &Feature{
Type: "Feature",
Geometry: geometry,
Properties: make(map[string]interface{}),
}
}
// Point implements the orb.Pointer interface so that Features can be used
// with quadtrees. The point returned is the center of the Bound of the geometry.
// To represent the geometry with another point you must create a wrapper type.
func (f *Feature) Point() orb.Point {
return f.Geometry.Bound().Center()
}
var _ orb.Pointer = &Feature{}
// MarshalJSON converts the feature object into the proper JSON.
// It will handle the encoding of all the child geometries.
// Alternately one can call json.Marshal(f) directly for the same result.
func (f Feature) MarshalJSON() ([]byte, error) {
return marshalJSON(newFeatureDoc(&f))
}
// MarshalBSON converts the feature object into the proper JSON.
// It will handle the encoding of all the child geometries.
// Alternately one can call json.Marshal(f) directly for the same result.
func (f Feature) MarshalBSON() ([]byte, error) {
return bson.Marshal(newFeatureDoc(&f))
}
func newFeatureDoc(f *Feature) *featureDoc {
doc := &featureDoc{
ID: f.ID,
Type: "Feature",
Properties: f.Properties,
BBox: f.BBox,
Geometry: NewGeometry(f.Geometry),
}
if len(doc.Properties) == 0 {
doc.Properties = nil
}
return doc
}
// UnmarshalFeature decodes the data into a GeoJSON feature.
// Alternately one can call json.Unmarshal(f) directly for the same result.
func UnmarshalFeature(data []byte) (*Feature, error) {
f := &Feature{}
err := f.UnmarshalJSON(data)
if err != nil {
return nil, err
}
return f, nil
}
// UnmarshalJSON handles the correct unmarshalling of the data
// into the orb.Geometry types.
func (f *Feature) UnmarshalJSON(data []byte) error {
if bytes.Equal(data, []byte(`null`)) {
*f = Feature{}
return nil
}
doc := &featureDoc{}
err := unmarshalJSON(data, &doc)
if err != nil {
return err
}
return featureUnmarshalFinish(doc, f)
}
// UnmarshalBSON will unmarshal a BSON document created with bson.Marshal.
func (f *Feature) UnmarshalBSON(data []byte) error {
doc := &featureDoc{}
err := bson.Unmarshal(data, &doc)
if err != nil {
return err
}
return featureUnmarshalFinish(doc, f)
}
func featureUnmarshalFinish(doc *featureDoc, f *Feature) error {
if doc.Type != "Feature" {
return fmt.Errorf("geojson: not a feature: type=%s", doc.Type)
}
var g orb.Geometry
if doc.Geometry != nil {
if doc.Geometry.Coordinates == nil && doc.Geometry.Geometries == nil {
return ErrInvalidGeometry
}
g = doc.Geometry.Geometry()
}
*f = Feature{
ID: doc.ID,
Type: doc.Type,
Properties: doc.Properties,
BBox: doc.BBox,
Geometry: g,
}
return nil
}
type featureDoc struct {
ID interface{} `json:"id,omitempty" bson:"id"`
Type string `json:"type" bson:"type"`
BBox BBox `json:"bbox,omitempty" bson:"bbox,omitempty"`
Geometry *Geometry `json:"geometry" bson:"geometry"`
Properties Properties `json:"properties" bson:"properties"`
}

View File

@@ -0,0 +1,197 @@
/*
Package geojson is a library for encoding and decoding GeoJSON into Go structs
using the geometries in the orb package. Supports both the json.Marshaler and
json.Unmarshaler interfaces as well as helper functions such as
`UnmarshalFeatureCollection` and `UnmarshalFeature`.
*/
package geojson
import (
"bytes"
"fmt"
"go.mongodb.org/mongo-driver/bson"
)
const featureCollection = "FeatureCollection"
// A FeatureCollection correlates to a GeoJSON feature collection.
type FeatureCollection struct {
Type string `json:"type"`
BBox BBox `json:"bbox,omitempty"`
Features []*Feature `json:"features"`
// ExtraMembers can be used to encoded/decode extra key/members in
// the base of the feature collection. Note that keys of "type", "bbox"
// and "features" will not work as those are reserved by the GeoJSON spec.
ExtraMembers Properties `json:"-"`
}
// NewFeatureCollection creates and initializes a new feature collection.
func NewFeatureCollection() *FeatureCollection {
return &FeatureCollection{
Type: featureCollection,
Features: []*Feature{},
}
}
// Append appends a feature to the collection.
func (fc *FeatureCollection) Append(feature *Feature) *FeatureCollection {
fc.Features = append(fc.Features, feature)
return fc
}
// MarshalJSON converts the feature collection object into the proper JSON.
// It will handle the encoding of all the child features and geometries.
// Alternately one can call json.Marshal(fc) directly for the same result.
// Items in the ExtraMembers map will be included in the base of the
// feature collection object.
func (fc FeatureCollection) MarshalJSON() ([]byte, error) {
m := newFeatureCollectionDoc(fc)
return marshalJSON(m)
}
// MarshalBSON converts the feature collection object into a BSON document
// represented by bytes. It will handle the encoding of all the child features
// and geometries.
// Items in the ExtraMembers map will be included in the base of the
// feature collection object.
func (fc FeatureCollection) MarshalBSON() ([]byte, error) {
m := newFeatureCollectionDoc(fc)
return bson.Marshal(m)
}
func newFeatureCollectionDoc(fc FeatureCollection) map[string]interface{} {
var tmp map[string]interface{}
if fc.ExtraMembers != nil {
tmp = fc.ExtraMembers.Clone()
} else {
tmp = make(map[string]interface{}, 3)
}
tmp["type"] = featureCollection
delete(tmp, "bbox")
if fc.BBox != nil {
tmp["bbox"] = fc.BBox
}
if fc.Features == nil {
tmp["features"] = []*Feature{}
} else {
tmp["features"] = fc.Features
}
return tmp
}
// UnmarshalJSON decodes the data into a GeoJSON feature collection.
// Extra/foreign members will be put into the `ExtraMembers` attribute.
func (fc *FeatureCollection) UnmarshalJSON(data []byte) error {
if bytes.Equal(data, []byte(`null`)) {
*fc = FeatureCollection{}
return nil
}
tmp := make(map[string]nocopyRawMessage, 4)
err := unmarshalJSON(data, &tmp)
if err != nil {
return err
}
*fc = FeatureCollection{}
for key, value := range tmp {
switch key {
case "type":
err := unmarshalJSON(value, &fc.Type)
if err != nil {
return err
}
case "bbox":
err := unmarshalJSON(value, &fc.BBox)
if err != nil {
return err
}
case "features":
err := unmarshalJSON(value, &fc.Features)
if err != nil {
return err
}
default:
if fc.ExtraMembers == nil {
fc.ExtraMembers = Properties{}
}
var val interface{}
err := unmarshalJSON(value, &val)
if err != nil {
return err
}
fc.ExtraMembers[key] = val
}
}
if fc.Type != featureCollection {
return fmt.Errorf("geojson: not a feature collection: type=%s", fc.Type)
}
return nil
}
// UnmarshalBSON will unmarshal a BSON document created with bson.Marshal.
// Extra/foreign members will be put into the `ExtraMembers` attribute.
func (fc *FeatureCollection) UnmarshalBSON(data []byte) error {
tmp := make(map[string]bson.RawValue, 4)
err := bson.Unmarshal(data, &tmp)
if err != nil {
return err
}
*fc = FeatureCollection{}
for key, value := range tmp {
switch key {
case "type":
fc.Type, _ = bson.RawValue(value).StringValueOK()
case "bbox":
err := value.Unmarshal(&fc.BBox)
if err != nil {
return err
}
case "features":
err := value.Unmarshal(&fc.Features)
if err != nil {
return err
}
default:
if fc.ExtraMembers == nil {
fc.ExtraMembers = Properties{}
}
var val interface{}
err := value.Unmarshal(&val)
if err != nil {
return err
}
fc.ExtraMembers[key] = val
}
}
if fc.Type != featureCollection {
return fmt.Errorf("geojson: not a feature collection: type=%s", fc.Type)
}
return nil
}
// UnmarshalFeatureCollection decodes the data into a GeoJSON feature collection.
// Alternately one can call json.Unmarshal(fc) directly for the same result.
func UnmarshalFeatureCollection(data []byte) (*FeatureCollection, error) {
fc := &FeatureCollection{}
err := fc.UnmarshalJSON(data)
if err != nil {
return nil, err
}
return fc, nil
}

586
vendor/github.com/paulmach/orb/geojson/geometry.go generated vendored Normal file
View File

@@ -0,0 +1,586 @@
package geojson
import (
"errors"
"github.com/paulmach/orb"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/bsontype"
)
// ErrInvalidGeometry will be returned if a the json of the geometry is invalid.
var ErrInvalidGeometry = errors.New("geojson: invalid geometry")
// A Geometry matches the structure of a GeoJSON Geometry.
type Geometry struct {
Type string `json:"type"`
Coordinates orb.Geometry `json:"coordinates,omitempty"`
Geometries []*Geometry `json:"geometries,omitempty"`
}
// NewGeometry will create a Geometry object but will convert
// the input into a GoeJSON geometry. For example, it will convert
// Rings and Bounds into Polygons.
func NewGeometry(g orb.Geometry) *Geometry {
jg := &Geometry{}
switch g := g.(type) {
case orb.Ring:
jg.Coordinates = orb.Polygon{g}
case orb.Bound:
jg.Coordinates = g.ToPolygon()
case orb.Collection:
for _, c := range g {
jg.Geometries = append(jg.Geometries, NewGeometry(c))
}
jg.Type = g.GeoJSONType()
default:
jg.Coordinates = g
}
if jg.Coordinates != nil {
jg.Type = jg.Coordinates.GeoJSONType()
}
return jg
}
// Geometry returns the orb.Geometry for the geojson Geometry.
// This will convert the "Geometries" into a orb.Collection if applicable.
func (g *Geometry) Geometry() orb.Geometry {
if g.Coordinates != nil {
return g.Coordinates
}
c := make(orb.Collection, 0, len(g.Geometries))
for _, geom := range g.Geometries {
c = append(c, geom.Geometry())
}
return c
}
// MarshalJSON will marshal the geometry into the correct JSON structure.
func (g *Geometry) MarshalJSON() ([]byte, error) {
if g.Coordinates == nil && len(g.Geometries) == 0 {
return []byte(`null`), nil
}
ng := newGeometryMarshallDoc(g)
return marshalJSON(ng)
}
// MarshalBSON will convert the geometry into a BSON document with the structure
// of a GeoJSON Geometry. This function is used when the geometry is the top level
// document to be marshalled.
func (g *Geometry) MarshalBSON() ([]byte, error) {
ng := newGeometryMarshallDoc(g)
return bson.Marshal(ng)
}
// MarshalBSONValue will marshal the geometry into a BSON value
// with the structure of a GeoJSON Geometry.
func (g *Geometry) MarshalBSONValue() (bsontype.Type, []byte, error) {
// implementing MarshalBSONValue allows us to marshal into a null value
// needed to match behavior with the JSON marshalling.
if g.Coordinates == nil && len(g.Geometries) == 0 {
return bsontype.Null, nil, nil
}
ng := newGeometryMarshallDoc(g)
return bson.MarshalValue(ng)
}
func newGeometryMarshallDoc(g *Geometry) *geometryMarshallDoc {
ng := &geometryMarshallDoc{}
switch g := g.Coordinates.(type) {
case orb.Ring:
ng.Coordinates = orb.Polygon{g}
case orb.Bound:
ng.Coordinates = g.ToPolygon()
case orb.Collection:
ng.Geometries = make([]*Geometry, 0, len(g))
for _, c := range g {
ng.Geometries = append(ng.Geometries, NewGeometry(c))
}
ng.Type = g.GeoJSONType()
default:
ng.Coordinates = g
}
if ng.Coordinates != nil {
ng.Type = ng.Coordinates.GeoJSONType()
}
if len(g.Geometries) > 0 {
ng.Geometries = g.Geometries
ng.Type = orb.Collection{}.GeoJSONType()
}
return ng
}
// UnmarshalGeometry decodes the JSON data into a GeoJSON feature.
// Alternately one can call json.Unmarshal(g) directly for the same result.
func UnmarshalGeometry(data []byte) (*Geometry, error) {
g := &Geometry{}
err := unmarshalJSON(data, g)
if err != nil {
return nil, err
}
return g, nil
}
// UnmarshalJSON will unmarshal the correct geometry from the JSON structure.
func (g *Geometry) UnmarshalJSON(data []byte) error {
jg := &jsonGeometry{}
err := unmarshalJSON(data, jg)
if err != nil {
return err
}
switch jg.Type {
case "Point":
p := orb.Point{}
err = unmarshalJSON(jg.Coordinates, &p)
if err != nil {
return err
}
g.Coordinates = p
case "MultiPoint":
mp := orb.MultiPoint{}
err = unmarshalJSON(jg.Coordinates, &mp)
if err != nil {
return err
}
g.Coordinates = mp
case "LineString":
ls := orb.LineString{}
err = unmarshalJSON(jg.Coordinates, &ls)
if err != nil {
return err
}
g.Coordinates = ls
case "MultiLineString":
mls := orb.MultiLineString{}
err = unmarshalJSON(jg.Coordinates, &mls)
if err != nil {
return err
}
g.Coordinates = mls
case "Polygon":
p := orb.Polygon{}
err = unmarshalJSON(jg.Coordinates, &p)
if err != nil {
return err
}
g.Coordinates = p
case "MultiPolygon":
mp := orb.MultiPolygon{}
err = unmarshalJSON(jg.Coordinates, &mp)
if err != nil {
return err
}
g.Coordinates = mp
case "GeometryCollection":
g.Geometries = jg.Geometries
default:
return ErrInvalidGeometry
}
g.Type = g.Geometry().GeoJSONType()
return nil
}
// UnmarshalBSON will unmarshal a BSON document created with bson.Marshal.
func (g *Geometry) UnmarshalBSON(data []byte) error {
bg := &bsonGeometry{}
err := bson.Unmarshal(data, bg)
if err != nil {
return err
}
switch bg.Type {
case "Point":
p := orb.Point{}
err = bg.Coordinates.Unmarshal(&p)
if err != nil {
return err
}
g.Coordinates = p
case "MultiPoint":
mp := orb.MultiPoint{}
err = bg.Coordinates.Unmarshal(&mp)
if err != nil {
return err
}
g.Coordinates = mp
case "LineString":
ls := orb.LineString{}
err = bg.Coordinates.Unmarshal(&ls)
if err != nil {
return err
}
g.Coordinates = ls
case "MultiLineString":
mls := orb.MultiLineString{}
err = bg.Coordinates.Unmarshal(&mls)
if err != nil {
return err
}
g.Coordinates = mls
case "Polygon":
p := orb.Polygon{}
err = bg.Coordinates.Unmarshal(&p)
if err != nil {
return err
}
g.Coordinates = p
case "MultiPolygon":
mp := orb.MultiPolygon{}
err = bg.Coordinates.Unmarshal(&mp)
if err != nil {
return err
}
g.Coordinates = mp
case "GeometryCollection":
g.Geometries = bg.Geometries
default:
return ErrInvalidGeometry
}
g.Type = g.Geometry().GeoJSONType()
return nil
}
// A Point is a helper type that will marshal to/from a GeoJSON Point geometry.
type Point orb.Point
// Geometry will return the orb.Geometry version of the data.
func (p Point) Geometry() orb.Geometry {
return orb.Point(p)
}
// MarshalJSON will convert the Point into a GeoJSON Point geometry.
func (p Point) MarshalJSON() ([]byte, error) {
return marshalJSON(&Geometry{Coordinates: orb.Point(p)})
}
// MarshalBSON will convert the Point into a BSON value following the GeoJSON Point structure.
func (p Point) MarshalBSON() ([]byte, error) {
return bson.Marshal(&Geometry{Coordinates: orb.Point(p)})
}
// UnmarshalJSON will unmarshal the GeoJSON Point geometry.
func (p *Point) UnmarshalJSON(data []byte) error {
g := &Geometry{}
err := unmarshalJSON(data, &g)
if err != nil {
return err
}
point, ok := g.Coordinates.(orb.Point)
if !ok {
return errors.New("geojson: not a Point type")
}
*p = Point(point)
return nil
}
// UnmarshalBSON will unmarshal GeoJSON Point geometry.
func (p *Point) UnmarshalBSON(data []byte) error {
g := &Geometry{}
err := bson.Unmarshal(data, &g)
if err != nil {
return err
}
point, ok := g.Coordinates.(orb.Point)
if !ok {
return errors.New("geojson: not a Point type")
}
*p = Point(point)
return nil
}
// A MultiPoint is a helper type that will marshal to/from a GeoJSON MultiPoint geometry.
type MultiPoint orb.MultiPoint
// Geometry will return the orb.Geometry version of the data.
func (mp MultiPoint) Geometry() orb.Geometry {
return orb.MultiPoint(mp)
}
// MarshalJSON will convert the MultiPoint into a GeoJSON MultiPoint geometry.
func (mp MultiPoint) MarshalJSON() ([]byte, error) {
return marshalJSON(&Geometry{Coordinates: orb.MultiPoint(mp)})
}
// MarshalBSON will convert the MultiPoint into a GeoJSON MultiPoint geometry BSON.
func (mp MultiPoint) MarshalBSON() ([]byte, error) {
return bson.Marshal(&Geometry{Coordinates: orb.MultiPoint(mp)})
}
// UnmarshalJSON will unmarshal the GeoJSON MultiPoint geometry.
func (mp *MultiPoint) UnmarshalJSON(data []byte) error {
g := &Geometry{}
err := unmarshalJSON(data, &g)
if err != nil {
return err
}
multiPoint, ok := g.Coordinates.(orb.MultiPoint)
if !ok {
return errors.New("geojson: not a MultiPoint type")
}
*mp = MultiPoint(multiPoint)
return nil
}
// UnmarshalBSON will unmarshal the GeoJSON MultiPoint geometry.
func (mp *MultiPoint) UnmarshalBSON(data []byte) error {
g := &Geometry{}
err := bson.Unmarshal(data, &g)
if err != nil {
return err
}
multiPoint, ok := g.Coordinates.(orb.MultiPoint)
if !ok {
return errors.New("geojson: not a MultiPoint type")
}
*mp = MultiPoint(multiPoint)
return nil
}
// A LineString is a helper type that will marshal to/from a GeoJSON LineString geometry.
type LineString orb.LineString
// Geometry will return the orb.Geometry version of the data.
func (ls LineString) Geometry() orb.Geometry {
return orb.LineString(ls)
}
// MarshalJSON will convert the LineString into a GeoJSON LineString geometry.
func (ls LineString) MarshalJSON() ([]byte, error) {
return marshalJSON(&Geometry{Coordinates: orb.LineString(ls)})
}
// MarshalBSON will convert the LineString into a GeoJSON LineString geometry.
func (ls LineString) MarshalBSON() ([]byte, error) {
return bson.Marshal(&Geometry{Coordinates: orb.LineString(ls)})
}
// UnmarshalJSON will unmarshal the GeoJSON MultiPoint geometry.
func (ls *LineString) UnmarshalJSON(data []byte) error {
g := &Geometry{}
err := unmarshalJSON(data, &g)
if err != nil {
return err
}
lineString, ok := g.Coordinates.(orb.LineString)
if !ok {
return errors.New("geojson: not a LineString type")
}
*ls = LineString(lineString)
return nil
}
// UnmarshalBSON will unmarshal the GeoJSON MultiPoint geometry.
func (ls *LineString) UnmarshalBSON(data []byte) error {
g := &Geometry{}
err := bson.Unmarshal(data, &g)
if err != nil {
return err
}
lineString, ok := g.Coordinates.(orb.LineString)
if !ok {
return errors.New("geojson: not a LineString type")
}
*ls = LineString(lineString)
return nil
}
// A MultiLineString is a helper type that will marshal to/from a GeoJSON MultiLineString geometry.
type MultiLineString orb.MultiLineString
// Geometry will return the orb.Geometry version of the data.
func (mls MultiLineString) Geometry() orb.Geometry {
return orb.MultiLineString(mls)
}
// MarshalJSON will convert the MultiLineString into a GeoJSON MultiLineString geometry.
func (mls MultiLineString) MarshalJSON() ([]byte, error) {
return marshalJSON(&Geometry{Coordinates: orb.MultiLineString(mls)})
}
// MarshalBSON will convert the MultiLineString into a GeoJSON MultiLineString geometry.
func (mls MultiLineString) MarshalBSON() ([]byte, error) {
return bson.Marshal(&Geometry{Coordinates: orb.MultiLineString(mls)})
}
// UnmarshalJSON will unmarshal the GeoJSON MultiPoint geometry.
func (mls *MultiLineString) UnmarshalJSON(data []byte) error {
g := &Geometry{}
err := unmarshalJSON(data, &g)
if err != nil {
return err
}
multilineString, ok := g.Coordinates.(orb.MultiLineString)
if !ok {
return errors.New("geojson: not a MultiLineString type")
}
*mls = MultiLineString(multilineString)
return nil
}
// UnmarshalBSON will unmarshal the GeoJSON MultiPoint geometry.
func (mls *MultiLineString) UnmarshalBSON(data []byte) error {
g := &Geometry{}
err := bson.Unmarshal(data, &g)
if err != nil {
return err
}
multilineString, ok := g.Coordinates.(orb.MultiLineString)
if !ok {
return errors.New("geojson: not a MultiLineString type")
}
*mls = MultiLineString(multilineString)
return nil
}
// A Polygon is a helper type that will marshal to/from a GeoJSON Polygon geometry.
type Polygon orb.Polygon
// Geometry will return the orb.Geometry version of the data.
func (p Polygon) Geometry() orb.Geometry {
return orb.Polygon(p)
}
// MarshalJSON will convert the Polygon into a GeoJSON Polygon geometry.
func (p Polygon) MarshalJSON() ([]byte, error) {
return marshalJSON(&Geometry{Coordinates: orb.Polygon(p)})
}
// MarshalBSON will convert the Polygon into a GeoJSON Polygon geometry.
func (p Polygon) MarshalBSON() ([]byte, error) {
return bson.Marshal(&Geometry{Coordinates: orb.Polygon(p)})
}
// UnmarshalJSON will unmarshal the GeoJSON Polygon geometry.
func (p *Polygon) UnmarshalJSON(data []byte) error {
g := &Geometry{}
err := unmarshalJSON(data, &g)
if err != nil {
return err
}
polygon, ok := g.Coordinates.(orb.Polygon)
if !ok {
return errors.New("geojson: not a Polygon type")
}
*p = Polygon(polygon)
return nil
}
// UnmarshalBSON will unmarshal the GeoJSON Polygon geometry.
func (p *Polygon) UnmarshalBSON(data []byte) error {
g := &Geometry{}
err := bson.Unmarshal(data, &g)
if err != nil {
return err
}
polygon, ok := g.Coordinates.(orb.Polygon)
if !ok {
return errors.New("geojson: not a Polygon type")
}
*p = Polygon(polygon)
return nil
}
// A MultiPolygon is a helper type that will marshal to/from a GeoJSON MultiPolygon geometry.
type MultiPolygon orb.MultiPolygon
// Geometry will return the orb.Geometry version of the data.
func (mp MultiPolygon) Geometry() orb.Geometry {
return orb.MultiPolygon(mp)
}
// MarshalJSON will convert the MultiPolygon into a GeoJSON MultiPolygon geometry.
func (mp MultiPolygon) MarshalJSON() ([]byte, error) {
return marshalJSON(&Geometry{Coordinates: orb.MultiPolygon(mp)})
}
// MarshalBSON will convert the MultiPolygon into a GeoJSON MultiPolygon geometry.
func (mp MultiPolygon) MarshalBSON() ([]byte, error) {
return bson.Marshal(&Geometry{Coordinates: orb.MultiPolygon(mp)})
}
// UnmarshalJSON will unmarshal the GeoJSON MultiPolygon geometry.
func (mp *MultiPolygon) UnmarshalJSON(data []byte) error {
g := &Geometry{}
err := unmarshalJSON(data, &g)
if err != nil {
return err
}
multiPolygon, ok := g.Coordinates.(orb.MultiPolygon)
if !ok {
return errors.New("geojson: not a MultiPolygon type")
}
*mp = MultiPolygon(multiPolygon)
return nil
}
// UnmarshalBSON will unmarshal the GeoJSON MultiPolygon geometry.
func (mp *MultiPolygon) UnmarshalBSON(data []byte) error {
g := &Geometry{}
err := bson.Unmarshal(data, &g)
if err != nil {
return err
}
multiPolygon, ok := g.Coordinates.(orb.MultiPolygon)
if !ok {
return errors.New("geojson: not a MultiPolygon type")
}
*mp = MultiPolygon(multiPolygon)
return nil
}
type bsonGeometry struct {
Type string `json:"type" bson:"type"`
Coordinates bson.RawValue `json:"coordinates" bson:"coordinates"`
Geometries []*Geometry `json:"geometries,omitempty" bson:"geometries"`
}
type jsonGeometry struct {
Type string `json:"type"`
Coordinates nocopyRawMessage `json:"coordinates"`
Geometries []*Geometry `json:"geometries,omitempty"`
}
type geometryMarshallDoc struct {
Type string `json:"type" bson:"type"`
Coordinates orb.Geometry `json:"coordinates,omitempty" bson:"coordinates,omitempty"`
Geometries []*Geometry `json:"geometries,omitempty" bson:"geometries,omitempty"`
}

74
vendor/github.com/paulmach/orb/geojson/json.go generated vendored Normal file
View File

@@ -0,0 +1,74 @@
package geojson
import "encoding/json"
// CustomJSONMarshaler can be set to have the code use a different
// json marshaler than the default in the standard library.
// One use case in enabling `github.com/json-iterator/go`
// with something like this:
//
// import (
// jsoniter "github.com/json-iterator/go"
// "github.com/paulmach/orb"
// )
//
// var c = jsoniter.Config{
// EscapeHTML: true,
// SortMapKeys: false,
// MarshalFloatWith6Digits: true,
// }.Froze()
//
// orb.CustomJSONMarshaler = c
// orb.CustomJSONUnmarshaler = c
//
// Note that any errors encountered during marshaling will be different.
var CustomJSONMarshaler interface {
Marshal(v interface{}) ([]byte, error)
} = nil
// CustomJSONUnmarshaler can be set to have the code use a different
// json unmarshaler than the default in the standard library.
// One use case in enabling `github.com/json-iterator/go`
// with something like this:
//
// import (
// jsoniter "github.com/json-iterator/go"
// "github.com/paulmach/orb"
// )
//
// var c = jsoniter.Config{
// EscapeHTML: true,
// SortMapKeys: false,
// MarshalFloatWith6Digits: true,
// }.Froze()
//
// orb.CustomJSONMarshaler = c
// orb.CustomJSONUnmarshaler = c
//
// Note that any errors encountered during unmarshaling will be different.
var CustomJSONUnmarshaler interface {
Unmarshal(data []byte, v interface{}) error
} = nil
func marshalJSON(v interface{}) ([]byte, error) {
if CustomJSONMarshaler == nil {
return json.Marshal(v)
}
return CustomJSONMarshaler.Marshal(v)
}
func unmarshalJSON(data []byte, v interface{}) error {
if CustomJSONUnmarshaler == nil {
return json.Unmarshal(data, v)
}
return CustomJSONUnmarshaler.Unmarshal(data, v)
}
type nocopyRawMessage []byte
func (m *nocopyRawMessage) UnmarshalJSON(data []byte) error {
*m = data
return nil
}

112
vendor/github.com/paulmach/orb/geojson/properties.go generated vendored Normal file
View File

@@ -0,0 +1,112 @@
package geojson
import "fmt"
// Properties defines the feature properties with some helper methods.
type Properties map[string]interface{}
// MustBool guarantees the return of a `bool` (with optional default).
// This function useful when you explicitly want a `bool` in a single
// value return context, for example:
// myFunc(f.Properties.MustBool("param1"), f.Properties.MustBool("optional_param", true))
// This function will panic if the value is present but not a bool.
func (p Properties) MustBool(key string, def ...bool) bool {
v := p[key]
if b, ok := v.(bool); ok {
return b
}
if v != nil {
panic(fmt.Sprintf("not a bool, but a %T: %v", v, v))
}
if len(def) > 0 {
return def[0]
}
panic("property not found")
}
// MustInt guarantees the return of an `int` (with optional default).
// This function useful when you explicitly want a `int` in a single
// value return context, for example:
// myFunc(f.Properties.MustInt("param1"), f.Properties.MustInt("optional_param", 123))
// This function will panic if the value is present but not a number.
func (p Properties) MustInt(key string, def ...int) int {
v := p[key]
if i, ok := v.(int); ok {
return i
}
if f, ok := v.(float64); ok {
return int(f)
}
if v != nil {
panic(fmt.Sprintf("not a number, but a %T: %v", v, v))
}
if len(def) > 0 {
return def[0]
}
panic("property not found")
}
// MustFloat64 guarantees the return of a `float64` (with optional default)
// This function useful when you explicitly want a `float64` in a single
// value return context, for example:
// myFunc(f.Properties.MustFloat64("param1"), f.Properties.MustFloat64("optional_param", 10.1))
// This function will panic if the value is present but not a number.
func (p Properties) MustFloat64(key string, def ...float64) float64 {
v := p[key]
if f, ok := v.(float64); ok {
return f
}
if i, ok := v.(int); ok {
return float64(i)
}
if v != nil {
panic(fmt.Sprintf("not a number, but a %T: %v", v, v))
}
if len(def) > 0 {
return def[0]
}
panic("property not found")
}
// MustString guarantees the return of a `string` (with optional default)
// This function useful when you explicitly want a `string` in a single
// value return context, for example:
// myFunc(f.Properties.MustString("param1"), f.Properties.MustString("optional_param", "default"))
// This function will panic if the value is present but not a string.
func (p Properties) MustString(key string, def ...string) string {
v := p[key]
if s, ok := v.(string); ok {
return s
}
if v != nil {
panic(fmt.Sprintf("not a string, but a %T: %v", v, v))
}
if len(def) > 0 {
return def[0]
}
panic("property not found")
}
// Clone returns a shallow copy of the properties.
func (p Properties) Clone() Properties {
n := make(Properties, len(p)+3)
for k, v := range p {
n[k] = v
}
return n
}

11
vendor/github.com/paulmach/orb/geojson/types.go generated vendored Normal file
View File

@@ -0,0 +1,11 @@
package geojson
// A list of the geojson types that are currently supported.
const (
TypePoint = "Point"
TypeMultiPoint = "MultiPoint"
TypeLineString = "LineString"
TypeMultiLineString = "MultiLineString"
TypePolygon = "Polygon"
TypeMultiPolygon = "MultiPolygon"
)

146
vendor/github.com/paulmach/orb/geometry.go generated vendored Normal file
View File

@@ -0,0 +1,146 @@
package orb
// Geometry is an interface that represents the shared attributes
// of a geometry.
type Geometry interface {
GeoJSONType() string
Dimensions() int // e.g. 0d, 1d, 2d
Bound() Bound
// requiring because sub package type switch over all possible types.
private()
}
// compile time checks
var (
_ Geometry = Point{}
_ Geometry = MultiPoint{}
_ Geometry = LineString{}
_ Geometry = MultiLineString{}
_ Geometry = Ring{}
_ Geometry = Polygon{}
_ Geometry = MultiPolygon{}
_ Geometry = Bound{}
_ Geometry = Collection{}
)
func (p Point) private() {}
func (mp MultiPoint) private() {}
func (ls LineString) private() {}
func (mls MultiLineString) private() {}
func (r Ring) private() {}
func (p Polygon) private() {}
func (mp MultiPolygon) private() {}
func (b Bound) private() {}
func (c Collection) private() {}
// AllGeometries lists all possible types and values that a geometry
// interface can be. It should be used only for testing to verify
// functions that accept a Geometry will work in all cases.
var AllGeometries = []Geometry{
nil,
Point{},
MultiPoint{},
LineString{},
MultiLineString{},
Ring{},
Polygon{},
MultiPolygon{},
Bound{},
Collection{},
// nil values
MultiPoint(nil),
LineString(nil),
MultiLineString(nil),
Ring(nil),
Polygon(nil),
MultiPolygon(nil),
Collection(nil),
// Collection of Collection
Collection{Collection{Point{}}},
}
// A Collection is a collection of geometries that is also a Geometry.
type Collection []Geometry
// GeoJSONType returns the geometry collection type.
func (c Collection) GeoJSONType() string {
return "GeometryCollection"
}
// Dimensions returns the max of the dimensions of the collection.
func (c Collection) Dimensions() int {
max := -1
for _, g := range c {
if d := g.Dimensions(); d > max {
max = d
}
}
return max
}
// Bound returns the bounding box of all the Geometries combined.
func (c Collection) Bound() Bound {
if len(c) == 0 {
return emptyBound
}
var b Bound
start := -1
for i, g := range c {
if g != nil {
start = i
b = g.Bound()
break
}
}
if start == -1 {
return emptyBound
}
for i := start + 1; i < len(c); i++ {
if c[i] == nil {
continue
}
b = b.Union(c[i].Bound())
}
return b
}
// Equal compares two collections. Returns true if lengths are the same
// and all the sub geometries are the same and in the same order.
func (c Collection) Equal(collection Collection) bool {
if len(c) != len(collection) {
return false
}
for i, g := range c {
if !Equal(g, collection[i]) {
return false
}
}
return true
}
// Clone returns a deep copy of the collection.
func (c Collection) Clone() Collection {
if c == nil {
return nil
}
nc := make(Collection, len(c))
for i, g := range c {
nc[i] = Clone(g)
}
return nc
}

View File

@@ -0,0 +1,71 @@
package length
import (
"fmt"
"github.com/paulmach/orb"
)
// Length returns the length of the boundary of the geometry
// using 2d euclidean geometry.
func Length(g orb.Geometry, df orb.DistanceFunc) float64 {
if g == nil {
return 0
}
switch g := g.(type) {
case orb.Point:
return 0
case orb.MultiPoint:
return 0
case orb.LineString:
return lineStringLength(g, df)
case orb.MultiLineString:
sum := 0.0
for _, ls := range g {
sum += lineStringLength(ls, df)
}
return sum
case orb.Ring:
return lineStringLength(orb.LineString(g), df)
case orb.Polygon:
return polygonLength(g, df)
case orb.MultiPolygon:
sum := 0.0
for _, p := range g {
sum += polygonLength(p, df)
}
return sum
case orb.Collection:
sum := 0.0
for _, c := range g {
sum += Length(c, df)
}
return sum
case orb.Bound:
return Length(g.ToRing(), df)
}
panic(fmt.Sprintf("geometry type not supported: %T", g))
}
func lineStringLength(ls orb.LineString, df orb.DistanceFunc) float64 {
sum := 0.0
for i := 1; i < len(ls); i++ {
sum += df(ls[i], ls[i-1])
}
return sum
}
func polygonLength(p orb.Polygon, df orb.DistanceFunc) float64 {
sum := 0.0
for _, r := range p {
sum += lineStringLength(orb.LineString(r), df)
}
return sum
}

40
vendor/github.com/paulmach/orb/line_string.go generated vendored Normal file
View File

@@ -0,0 +1,40 @@
package orb
// LineString represents a set of points to be thought of as a polyline.
type LineString []Point
// GeoJSONType returns the GeoJSON type for the object.
func (ls LineString) GeoJSONType() string {
return "LineString"
}
// Dimensions returns 1 because a LineString is a 1d object.
func (ls LineString) Dimensions() int {
return 1
}
// Reverse will reverse the line string.
// This is done inplace, ie. it modifies the original data.
func (ls LineString) Reverse() {
l := len(ls) - 1
for i := 0; i <= l/2; i++ {
ls[i], ls[l-i] = ls[l-i], ls[i]
}
}
// Bound returns a rect around the line string. Uses rectangular coordinates.
func (ls LineString) Bound() Bound {
return MultiPoint(ls).Bound()
}
// Equal compares two line strings. Returns true if lengths are the same
// and all points are Equal.
func (ls LineString) Equal(lineString LineString) bool {
return MultiPoint(ls).Equal(MultiPoint(lineString))
}
// Clone returns a new copy of the line string.
func (ls LineString) Clone() LineString {
ps := MultiPoint(ls)
return LineString(ps.Clone())
}

58
vendor/github.com/paulmach/orb/multi_line_string.go generated vendored Normal file
View File

@@ -0,0 +1,58 @@
package orb
// MultiLineString is a set of polylines.
type MultiLineString []LineString
// GeoJSONType returns the GeoJSON type for the object.
func (mls MultiLineString) GeoJSONType() string {
return "MultiLineString"
}
// Dimensions returns 1 because a MultiLineString is a 2d object.
func (mls MultiLineString) Dimensions() int {
return 1
}
// Bound returns a bound around all the line strings.
func (mls MultiLineString) Bound() Bound {
if len(mls) == 0 {
return emptyBound
}
bound := mls[0].Bound()
for i := 1; i < len(mls); i++ {
bound = bound.Union(mls[i].Bound())
}
return bound
}
// Equal compares two multi line strings. Returns true if lengths are the same
// and all points are Equal.
func (mls MultiLineString) Equal(multiLineString MultiLineString) bool {
if len(mls) != len(multiLineString) {
return false
}
for i, ls := range mls {
if !ls.Equal(multiLineString[i]) {
return false
}
}
return true
}
// Clone returns a new deep copy of the multi line string.
func (mls MultiLineString) Clone() MultiLineString {
if mls == nil {
return nil
}
nmls := make(MultiLineString, 0, len(mls))
for _, ls := range mls {
nmls = append(nmls, ls.Clone())
}
return nmls
}

56
vendor/github.com/paulmach/orb/multi_point.go generated vendored Normal file
View File

@@ -0,0 +1,56 @@
package orb
// A MultiPoint represents a set of points in the 2D Eucledian or Cartesian plane.
type MultiPoint []Point
// GeoJSONType returns the GeoJSON type for the object.
func (mp MultiPoint) GeoJSONType() string {
return "MultiPoint"
}
// Dimensions returns 0 because a MultiPoint is a 0d object.
func (mp MultiPoint) Dimensions() int {
return 0
}
// Clone returns a new copy of the points.
func (mp MultiPoint) Clone() MultiPoint {
if mp == nil {
return nil
}
points := make([]Point, len(mp))
copy(points, mp)
return MultiPoint(points)
}
// Bound returns a bound around the points. Uses rectangular coordinates.
func (mp MultiPoint) Bound() Bound {
if len(mp) == 0 {
return emptyBound
}
b := Bound{mp[0], mp[0]}
for _, p := range mp {
b = b.Extend(p)
}
return b
}
// Equal compares two MultiPoint objects. Returns true if lengths are the same
// and all points are Equal, and in the same order.
func (mp MultiPoint) Equal(multiPoint MultiPoint) bool {
if len(mp) != len(multiPoint) {
return false
}
for i := range mp {
if !mp[i].Equal(multiPoint[i]) {
return false
}
}
return true
}

56
vendor/github.com/paulmach/orb/multi_polygon.go generated vendored Normal file
View File

@@ -0,0 +1,56 @@
package orb
// MultiPolygon is a set of polygons.
type MultiPolygon []Polygon
// GeoJSONType returns the GeoJSON type for the object.
func (mp MultiPolygon) GeoJSONType() string {
return "MultiPolygon"
}
// Dimensions returns 2 because a MultiPolygon is a 2d object.
func (mp MultiPolygon) Dimensions() int {
return 2
}
// Bound returns a bound around the multi-polygon.
func (mp MultiPolygon) Bound() Bound {
if len(mp) == 0 {
return emptyBound
}
bound := mp[0].Bound()
for i := 1; i < len(mp); i++ {
bound = bound.Union(mp[i].Bound())
}
return bound
}
// Equal compares two multi-polygons.
func (mp MultiPolygon) Equal(multiPolygon MultiPolygon) bool {
if len(mp) != len(multiPolygon) {
return false
}
for i, p := range mp {
if !p.Equal(multiPolygon[i]) {
return false
}
}
return true
}
// Clone returns a new deep copy of the multi-polygon.
func (mp MultiPolygon) Clone() MultiPolygon {
if mp == nil {
return nil
}
nmp := make(MultiPolygon, 0, len(mp))
for _, p := range mp {
nmp = append(nmp, p.Clone())
}
return nmp
}

40
vendor/github.com/paulmach/orb/planar/README.md generated vendored Normal file
View File

@@ -0,0 +1,40 @@
# orb/planar [![Godoc Reference](https://pkg.go.dev/badge/github.com/paulmach/orb)](https://pkg.go.dev/github.com/paulmach/orb/planar)
The geometries defined in the `orb` package are generic 2d geometries.
Depending on what projection they're in, e.g. lon/lat or flat on the plane,
area and distance calculations are different. This package implements methods
that assume the planar or Euclidean context.
## Examples
Area of 3-4-5 triangle:
```go
r := orb.Ring{{0, 0}, {3, 0}, {0, 4}, {0, 0}}
a := planar.Area(r)
fmt.Println(a)
// Output:
// 6
```
Distance between two points:
```go
d := planar.Distance(orb.Point{0, 0}, orb.Point{3, 4})
fmt.Println(d)
// Output:
// 5
```
Length/circumference of a 3-4-5 triangle:
```go
r := orb.Ring{{0, 0}, {3, 0}, {0, 4}, {0, 0}}
l := planar.Length(r)
fmt.Println(l)
// Output:
// 12
```

284
vendor/github.com/paulmach/orb/planar/area.go generated vendored Normal file
View File

@@ -0,0 +1,284 @@
// Package planar computes properties on geometries assuming they are
// in 2d euclidean space.
package planar
import (
"fmt"
"math"
"github.com/paulmach/orb"
)
// Area returns the area of the geometry in the 2d plane.
func Area(g orb.Geometry) float64 {
// TODO: make faster non-centroid version.
_, a := CentroidArea(g)
return a
}
// CentroidArea returns both the centroid and the area in the 2d plane.
// Since the area is need for the centroid, return both.
// Polygon area will always be >= zero. Ring area my be negative if it has
// a clockwise winding orider.
func CentroidArea(g orb.Geometry) (orb.Point, float64) {
if g == nil {
return orb.Point{}, 0
}
switch g := g.(type) {
case orb.Point:
return multiPointCentroid(orb.MultiPoint{g}), 0
case orb.MultiPoint:
return multiPointCentroid(g), 0
case orb.LineString:
return multiLineStringCentroid(orb.MultiLineString{g}), 0
case orb.MultiLineString:
return multiLineStringCentroid(g), 0
case orb.Ring:
return ringCentroidArea(g)
case orb.Polygon:
return polygonCentroidArea(g)
case orb.MultiPolygon:
return multiPolygonCentroidArea(g)
case orb.Collection:
return collectionCentroidArea(g)
case orb.Bound:
return CentroidArea(g.ToRing())
}
panic(fmt.Sprintf("geometry type not supported: %T", g))
}
func multiPointCentroid(mp orb.MultiPoint) orb.Point {
if len(mp) == 0 {
return orb.Point{}
}
x, y := 0.0, 0.0
for _, p := range mp {
x += p[0]
y += p[1]
}
num := float64(len(mp))
return orb.Point{x / num, y / num}
}
func multiLineStringCentroid(mls orb.MultiLineString) orb.Point {
point := orb.Point{}
dist := 0.0
if len(mls) == 0 {
return orb.Point{}
}
validCount := 0
for _, ls := range mls {
c, d := lineStringCentroidDist(ls)
if d == math.Inf(1) {
continue
}
dist += d
validCount++
if d == 0 {
d = 1.0
}
point[0] += c[0] * d
point[1] += c[1] * d
}
if validCount == 0 {
return orb.Point{}
}
if dist == math.Inf(1) || dist == 0.0 {
point[0] /= float64(validCount)
point[1] /= float64(validCount)
return point
}
point[0] /= dist
point[1] /= dist
return point
}
func lineStringCentroidDist(ls orb.LineString) (orb.Point, float64) {
dist := 0.0
point := orb.Point{}
if len(ls) == 0 {
return orb.Point{}, math.Inf(1)
}
// implicitly move everything to near the origin to help with roundoff
offset := ls[0]
for i := 0; i < len(ls)-1; i++ {
p1 := orb.Point{
ls[i][0] - offset[0],
ls[i][1] - offset[1],
}
p2 := orb.Point{
ls[i+1][0] - offset[0],
ls[i+1][1] - offset[1],
}
d := Distance(p1, p2)
point[0] += (p1[0] + p2[0]) / 2.0 * d
point[1] += (p1[1] + p2[1]) / 2.0 * d
dist += d
}
if dist == 0 {
return ls[0], 0
}
point[0] /= dist
point[1] /= dist
point[0] += ls[0][0]
point[1] += ls[0][1]
return point, dist
}
func ringCentroidArea(r orb.Ring) (orb.Point, float64) {
centroid := orb.Point{}
area := 0.0
if len(r) == 0 {
return orb.Point{}, 0
}
// implicitly move everything to near the origin to help with roundoff
offsetX := r[0][0]
offsetY := r[0][1]
for i := 1; i < len(r)-1; i++ {
a := (r[i][0]-offsetX)*(r[i+1][1]-offsetY) -
(r[i+1][0]-offsetX)*(r[i][1]-offsetY)
area += a
centroid[0] += (r[i][0] + r[i+1][0] - 2*offsetX) * a
centroid[1] += (r[i][1] + r[i+1][1] - 2*offsetY) * a
}
if area == 0 {
return r[0], 0
}
// no need to deal with first and last vertex since we "moved"
// that point the origin (multiply by 0 == 0)
area /= 2
centroid[0] /= 6 * area
centroid[1] /= 6 * area
centroid[0] += offsetX
centroid[1] += offsetY
return centroid, area
}
func polygonCentroidArea(p orb.Polygon) (orb.Point, float64) {
if len(p) == 0 {
return orb.Point{}, 0
}
centroid, area := ringCentroidArea(p[0])
area = math.Abs(area)
if len(p) == 1 {
if area == 0 {
c, _ := lineStringCentroidDist(orb.LineString(p[0]))
return c, 0
}
return centroid, area
}
holeArea := 0.0
weightedHoleCentroid := orb.Point{}
for i := 1; i < len(p); i++ {
hc, ha := ringCentroidArea(p[i])
ha = math.Abs(ha)
holeArea += ha
weightedHoleCentroid[0] += hc[0] * ha
weightedHoleCentroid[1] += hc[1] * ha
}
totalArea := area - holeArea
if totalArea == 0 {
c, _ := lineStringCentroidDist(orb.LineString(p[0]))
return c, 0
}
centroid[0] = (area*centroid[0] - weightedHoleCentroid[0]) / totalArea
centroid[1] = (area*centroid[1] - weightedHoleCentroid[1]) / totalArea
return centroid, totalArea
}
func multiPolygonCentroidArea(mp orb.MultiPolygon) (orb.Point, float64) {
point := orb.Point{}
area := 0.0
for _, p := range mp {
c, a := polygonCentroidArea(p)
point[0] += c[0] * a
point[1] += c[1] * a
area += a
}
if area == 0 {
return orb.Point{}, 0
}
point[0] /= area
point[1] /= area
return point, area
}
func collectionCentroidArea(c orb.Collection) (orb.Point, float64) {
point := orb.Point{}
area := 0.0
max := maxDim(c)
for _, g := range c {
if g.Dimensions() != max {
continue
}
c, a := CentroidArea(g)
point[0] += c[0] * a
point[1] += c[1] * a
area += a
}
if area == 0 {
return orb.Point{}, 0
}
point[0] /= area
point[1] /= area
return point, area
}
func maxDim(c orb.Collection) int {
max := 0
for _, g := range c {
if d := g.Dimensions(); d > max {
max = d
}
}
return max
}

122
vendor/github.com/paulmach/orb/planar/contains.go generated vendored Normal file
View File

@@ -0,0 +1,122 @@
package planar
import (
"math"
"github.com/paulmach/orb"
)
// RingContains returns true if the point is inside the ring.
// Points on the boundary are considered in.
func RingContains(r orb.Ring, point orb.Point) bool {
if !r.Bound().Contains(point) {
return false
}
c, on := rayIntersect(point, r[0], r[len(r)-1])
if on {
return true
}
for i := 0; i < len(r)-1; i++ {
inter, on := rayIntersect(point, r[i], r[i+1])
if on {
return true
}
if inter {
c = !c
}
}
return c
}
// PolygonContains checks if the point is within the polygon.
// Points on the boundary are considered in.
func PolygonContains(p orb.Polygon, point orb.Point) bool {
if !RingContains(p[0], point) {
return false
}
for i := 1; i < len(p); i++ {
if RingContains(p[i], point) {
return false
}
}
return true
}
// MultiPolygonContains checks if the point is within the multi-polygon.
// Points on the boundary are considered in.
func MultiPolygonContains(mp orb.MultiPolygon, point orb.Point) bool {
for _, p := range mp {
if PolygonContains(p, point) {
return true
}
}
return false
}
// Original implementation: http://rosettacode.org/wiki/Ray-casting_algorithm#Go
func rayIntersect(p, s, e orb.Point) (intersects, on bool) {
if s[0] > e[0] {
s, e = e, s
}
if p[0] == s[0] {
if p[1] == s[1] {
// p == start
return false, true
} else if s[0] == e[0] {
// vertical segment (s -> e)
// return true if within the line, check to see if start or end is greater.
if s[1] > e[1] && s[1] >= p[1] && p[1] >= e[1] {
return false, true
}
if e[1] > s[1] && e[1] >= p[1] && p[1] >= s[1] {
return false, true
}
}
// Move the y coordinate to deal with degenerate case
p[0] = math.Nextafter(p[0], math.Inf(1))
} else if p[0] == e[0] {
if p[1] == e[1] {
// matching the end point
return false, true
}
p[0] = math.Nextafter(p[0], math.Inf(1))
}
if p[0] < s[0] || p[0] > e[0] {
return false, false
}
if s[1] > e[1] {
if p[1] > s[1] {
return false, false
} else if p[1] < e[1] {
return true, false
}
} else {
if p[1] > e[1] {
return false, false
} else if p[1] < s[1] {
return true, false
}
}
rs := (p[1] - s[1]) / (p[0] - s[0])
ds := (e[1] - s[1]) / (e[0] - s[0])
if rs == ds {
return false, true
}
return rs <= ds, false
}

21
vendor/github.com/paulmach/orb/planar/distance.go generated vendored Normal file
View File

@@ -0,0 +1,21 @@
package planar
import (
"math"
"github.com/paulmach/orb"
)
// Distance returns the distance between two points in 2d euclidean geometry.
func Distance(p1, p2 orb.Point) float64 {
d0 := (p1[0] - p2[0])
d1 := (p1[1] - p2[1])
return math.Sqrt(d0*d0 + d1*d1)
}
// DistanceSquared returns the square of the distance between two points in 2d euclidean geometry.
func DistanceSquared(p1, p2 orb.Point) float64 {
d0 := (p1[0] - p2[0])
d1 := (p1[1] - p2[1])
return d0*d0 + d1*d1
}

173
vendor/github.com/paulmach/orb/planar/distance_from.go generated vendored Normal file
View File

@@ -0,0 +1,173 @@
package planar
import (
"fmt"
"math"
"github.com/paulmach/orb"
)
// DistanceFromSegment returns the point's distance from the segment [a, b].
func DistanceFromSegment(a, b, point orb.Point) float64 {
return math.Sqrt(DistanceFromSegmentSquared(a, b, point))
}
// DistanceFromSegmentSquared returns point's squared distance from the segement [a, b].
func DistanceFromSegmentSquared(a, b, point orb.Point) float64 {
x := a[0]
y := a[1]
dx := b[0] - x
dy := b[1] - y
if dx != 0 || dy != 0 {
t := ((point[0]-x)*dx + (point[1]-y)*dy) / (dx*dx + dy*dy)
if t > 1 {
x = b[0]
y = b[1]
} else if t > 0 {
x += dx * t
y += dy * t
}
}
dx = point[0] - x
dy = point[1] - y
return dx*dx + dy*dy
}
// DistanceFrom returns the distance from the boundary of the geometry in
// the units of the geometry.
func DistanceFrom(g orb.Geometry, p orb.Point) float64 {
d, _ := DistanceFromWithIndex(g, p)
return d
}
// DistanceFromWithIndex returns the minimum euclidean distance
// from the boundary of the geometry plus the index of the sub-geometry
// that was the match.
func DistanceFromWithIndex(g orb.Geometry, p orb.Point) (float64, int) {
if g == nil {
return math.Inf(1), -1
}
switch g := g.(type) {
case orb.Point:
return Distance(g, p), 0
case orb.MultiPoint:
return multiPointDistanceFrom(g, p)
case orb.LineString:
return lineStringDistanceFrom(g, p)
case orb.MultiLineString:
dist := math.Inf(1)
index := -1
for i, ls := range g {
if d, _ := lineStringDistanceFrom(ls, p); d < dist {
dist = d
index = i
}
}
return dist, index
case orb.Ring:
return lineStringDistanceFrom(orb.LineString(g), p)
case orb.Polygon:
return polygonDistanceFrom(g, p)
case orb.MultiPolygon:
dist := math.Inf(1)
index := -1
for i, poly := range g {
if d, _ := polygonDistanceFrom(poly, p); d < dist {
dist = d
index = i
}
}
return dist, index
case orb.Collection:
dist := math.Inf(1)
index := -1
for i, ge := range g {
if d, _ := DistanceFromWithIndex(ge, p); d < dist {
dist = d
index = i
}
}
return dist, index
case orb.Bound:
return DistanceFromWithIndex(g.ToRing(), p)
}
panic(fmt.Sprintf("geometry type not supported: %T", g))
}
func multiPointDistanceFrom(mp orb.MultiPoint, p orb.Point) (float64, int) {
dist := math.Inf(1)
index := -1
for i := range mp {
if d := DistanceSquared(mp[i], p); d < dist {
dist = d
index = i
}
}
return math.Sqrt(dist), index
}
func lineStringDistanceFrom(ls orb.LineString, p orb.Point) (float64, int) {
dist := math.Inf(1)
index := -1
for i := 0; i < len(ls)-1; i++ {
if d := segmentDistanceFromSquared(ls[i], ls[i+1], p); d < dist {
dist = d
index = i
}
}
return math.Sqrt(dist), index
}
func polygonDistanceFrom(p orb.Polygon, point orb.Point) (float64, int) {
if len(p) == 0 {
return math.Inf(1), -1
}
dist, index := lineStringDistanceFrom(orb.LineString(p[0]), point)
for i := 1; i < len(p); i++ {
d, i := lineStringDistanceFrom(orb.LineString(p[i]), point)
if d < dist {
dist = d
index = i
}
}
return dist, index
}
func segmentDistanceFromSquared(p1, p2, point orb.Point) float64 {
x := p1[0]
y := p1[1]
dx := p2[0] - x
dy := p2[1] - y
if dx != 0 || dy != 0 {
t := ((point[0]-x)*dx + (point[1]-y)*dy) / (dx*dx + dy*dy)
if t > 1 {
x = p2[0]
y = p2[1]
} else if t > 0 {
x += dx * t
y += dy * t
}
}
dx = point[0] - x
dy = point[1] - y
return dx*dx + dy*dy
}

12
vendor/github.com/paulmach/orb/planar/length.go generated vendored Normal file
View File

@@ -0,0 +1,12 @@
package planar
import (
"github.com/paulmach/orb"
"github.com/paulmach/orb/internal/length"
)
// Length returns the length of the boundary of the geometry
// using 2d euclidean geometry.
func Length(g orb.Geometry) float64 {
return length.Length(g, Distance)
}

51
vendor/github.com/paulmach/orb/point.go generated vendored Normal file
View File

@@ -0,0 +1,51 @@
package orb
// A Point is a Lon/Lat 2d point.
type Point [2]float64
var _ Pointer = Point{}
// GeoJSONType returns the GeoJSON type for the object.
func (p Point) GeoJSONType() string {
return "Point"
}
// Dimensions returns 0 because a point is a 0d object.
func (p Point) Dimensions() int {
return 0
}
// Bound returns a single point bound of the point.
func (p Point) Bound() Bound {
return Bound{p, p}
}
// Point returns itself so it implements the Pointer interface.
func (p Point) Point() Point {
return p
}
// Y returns the vertical coordinate of the point.
func (p Point) Y() float64 {
return p[1]
}
// X returns the horizontal coordinate of the point.
func (p Point) X() float64 {
return p[0]
}
// Lat returns the vertical, latitude coordinate of the point.
func (p Point) Lat() float64 {
return p[1]
}
// Lon returns the horizontal, longitude coordinate of the point.
func (p Point) Lon() float64 {
return p[0]
}
// Equal checks if the point represents the same point or vector.
func (p Point) Equal(point Point) bool {
return p[0] == point[0] && p[1] == point[1]
}

55
vendor/github.com/paulmach/orb/polygon.go generated vendored Normal file
View File

@@ -0,0 +1,55 @@
package orb
// Polygon is a closed area. The first LineString is the outer ring.
// The others are the holes. Each LineString is expected to be closed
// ie. the first point matches the last.
type Polygon []Ring
// GeoJSONType returns the GeoJSON type for the object.
func (p Polygon) GeoJSONType() string {
return "Polygon"
}
// Dimensions returns 2 because a Polygon is a 2d object.
func (p Polygon) Dimensions() int {
return 2
}
// Bound returns a bound around the polygon.
func (p Polygon) Bound() Bound {
if len(p) == 0 {
return emptyBound
}
return p[0].Bound()
}
// Equal compares two polygons. Returns true if lengths are the same
// and all points are Equal.
func (p Polygon) Equal(polygon Polygon) bool {
if len(p) != len(polygon) {
return false
}
for i := range p {
if !p[i].Equal(polygon[i]) {
return false
}
}
return true
}
// Clone returns a new deep copy of the polygon.
// All of the rings are also cloned.
func (p Polygon) Clone() Polygon {
if p == nil {
return p
}
np := make(Polygon, 0, len(p))
for _, r := range p {
np = append(np, r.Clone())
}
return np
}

75
vendor/github.com/paulmach/orb/ring.go generated vendored Normal file
View File

@@ -0,0 +1,75 @@
package orb
// Ring represents a set of ring on the earth.
type Ring LineString
// GeoJSONType returns the GeoJSON type for the object.
func (r Ring) GeoJSONType() string {
return "Polygon"
}
// Dimensions returns 2 because a Ring is a 2d object.
func (r Ring) Dimensions() int {
return 2
}
// Closed will return true if the ring is a real ring.
// ie. 4+ points and the first and last points match.
// NOTE: this will not check for self-intersection.
func (r Ring) Closed() bool {
return (len(r) >= 4) && (r[0] == r[len(r)-1])
}
// Reverse changes the direction of the ring.
// This is done inplace, ie. it modifies the original data.
func (r Ring) Reverse() {
LineString(r).Reverse()
}
// Bound returns a rect around the ring. Uses rectangular coordinates.
func (r Ring) Bound() Bound {
return MultiPoint(r).Bound()
}
// Orientation returns 1 if the the ring is in couter-clockwise order,
// return -1 if the ring is the clockwise order and 0 if the ring is
// degenerate and had no area.
func (r Ring) Orientation() Orientation {
area := 0.0
// This is a fast planar area computation, which is okay for this use.
// implicitly move everything to near the origin to help with roundoff
offsetX := r[0][0]
offsetY := r[0][1]
for i := 1; i < len(r)-1; i++ {
area += (r[i][0]-offsetX)*(r[i+1][1]-offsetY) -
(r[i+1][0]-offsetX)*(r[i][1]-offsetY)
}
if area > 0 {
return CCW
}
if area < 0 {
return CW
}
// degenerate case, no area
return 0
}
// Equal compares two rings. Returns true if lengths are the same
// and all points are Equal.
func (r Ring) Equal(ring Ring) bool {
return MultiPoint(r).Equal(MultiPoint(ring))
}
// Clone returns a new copy of the ring.
func (r Ring) Clone() Ring {
if r == nil {
return nil
}
ps := MultiPoint(r)
return Ring(ps.Clone())
}

100
vendor/github.com/paulmach/orb/round.go generated vendored Normal file
View File

@@ -0,0 +1,100 @@
package orb
import (
"fmt"
"math"
)
// Round will round all the coordinates of the geometry to the given factor.
// The default is 6 decimal places.
func Round(g Geometry, factor ...int) Geometry {
if g == nil {
return nil
}
f := float64(DefaultRoundingFactor)
if len(factor) > 0 {
f = float64(factor[0])
}
switch g := g.(type) {
case Point:
return Point{
math.Round(g[0]*f) / f,
math.Round(g[1]*f) / f,
}
case MultiPoint:
if g == nil {
return nil
}
roundPoints([]Point(g), f)
return g
case LineString:
if g == nil {
return nil
}
roundPoints([]Point(g), f)
return g
case MultiLineString:
if g == nil {
return nil
}
for _, ls := range g {
roundPoints([]Point(ls), f)
}
return g
case Ring:
if g == nil {
return nil
}
roundPoints([]Point(g), f)
return g
case Polygon:
if g == nil {
return nil
}
for _, r := range g {
roundPoints([]Point(r), f)
}
return g
case MultiPolygon:
if g == nil {
return nil
}
for _, p := range g {
for _, r := range p {
roundPoints([]Point(r), f)
}
}
return g
case Collection:
if g == nil {
return nil
}
for i := range g {
g[i] = Round(g[i], int(f))
}
return g
case Bound:
return Bound{
Min: Point{
math.Round(g.Min[0]*f) / f,
math.Round(g.Min[1]*f) / f,
},
Max: Point{
math.Round(g.Max[0]*f) / f,
math.Round(g.Max[1]*f) / f,
},
}
}
panic(fmt.Sprintf("geometry type not supported: %T", g))
}
func roundPoints(ps []Point, f float64) {
for i := range ps {
ps[i][0] = math.Round(ps[i][0]*f) / f
ps[i][1] = math.Round(ps[i][1]*f) / f
}
}