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

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)
}