mirror of
https://github.com/Luzifer/staticmap.git
synced 2025-01-20 11:31:56 +00:00
Update vendored libraries
Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
2c2b9269d0
commit
3657b6663d
165 changed files with 21402 additions and 5650 deletions
50
Gopkg.lock
generated
50
Gopkg.lock
generated
|
@ -2,10 +2,10 @@
|
|||
|
||||
|
||||
[[projects]]
|
||||
branch = "allow-disable-of-attribution-rendering"
|
||||
branch = "master"
|
||||
name = "github.com/Luzifer/go-staticmaps"
|
||||
packages = ["."]
|
||||
revision = "d701c2c232ad9cbcac3e48e2c34e98544191c2fe"
|
||||
revision = "320790ed53294a789e715b3d0d5da8110efea1a2"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/Luzifer/go_helpers"
|
||||
|
@ -14,8 +14,8 @@
|
|||
"http",
|
||||
"str"
|
||||
]
|
||||
revision = "15199b8e33ca5558e8c58af7924083983eb63ca4"
|
||||
version = "v2.4.0"
|
||||
revision = "b0da2aa67ecc05ee4c8848d679b4a11a2fa578b2"
|
||||
version = "v2.6.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/Luzifer/rconfig"
|
||||
|
@ -23,12 +23,6 @@
|
|||
revision = "7aef1d393c1e2d0758901853b59981c7adc67c7e"
|
||||
version = "v1.2.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/Sirupsen/logrus"
|
||||
packages = ["."]
|
||||
revision = "c155da19408a8799da419ed3eeb0cb5db0ad5dbc"
|
||||
version = "v1.0.5"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/Wessie/appdirs"
|
||||
|
@ -77,25 +71,25 @@
|
|||
"s1",
|
||||
"s2"
|
||||
]
|
||||
revision = "fb250ae94fbe10f86b4f1a9b70a19925da3410b9"
|
||||
revision = "e41ca803f92c4c1770133cfa5b4fc8249a7dbe82"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/gorilla/context"
|
||||
packages = ["."]
|
||||
revision = "1ea25387ff6f684839d82767c1733ff4d4d15d0a"
|
||||
version = "v1.1"
|
||||
revision = "08b5f424b9271eedf6f9f0ce86cb9396ed337a42"
|
||||
version = "v1.1.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/gorilla/mux"
|
||||
packages = ["."]
|
||||
revision = "53c1911da2b537f792e7cafcb446b05ffe33b996"
|
||||
version = "v1.6.1"
|
||||
revision = "e3702bed27f0d39777b0b37b664b6280e8ef8fbf"
|
||||
version = "v1.6.2"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/lucasb-eyer/go-colorful"
|
||||
packages = ["."]
|
||||
revision = "231272389856c976b7500c4fffcc52ddf06ff4eb"
|
||||
revision = "d9cec903b20cbeda6062366e460c2c1bdc717e4d"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/patrickmn/go-cache"
|
||||
|
@ -103,11 +97,17 @@
|
|||
revision = "a3647f8e31d79543b2d0f0ae2fe5c379d72cedc0"
|
||||
version = "v2.1.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/sirupsen/logrus"
|
||||
packages = ["."]
|
||||
revision = "c155da19408a8799da419ed3eeb0cb5db0ad5dbc"
|
||||
version = "v1.0.5"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/spf13/pflag"
|
||||
packages = ["."]
|
||||
revision = "e57e3eeb33f795204c1ca35f56c44f83227c6e66"
|
||||
version = "v1.0.0"
|
||||
revision = "583c0c0531f06d5278b7d917446061adc344b5cd"
|
||||
version = "v1.0.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
|
@ -119,7 +119,7 @@
|
|||
branch = "master"
|
||||
name = "golang.org/x/crypto"
|
||||
packages = ["ssh/terminal"]
|
||||
revision = "b2aa35443fbc700ab74c586ae79b81c171851023"
|
||||
revision = "027cca12c2d63e3d62b670d901e8a2c95854feec"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
|
@ -130,13 +130,13 @@
|
|||
"font/plan9font",
|
||||
"math/fixed"
|
||||
]
|
||||
revision = "f315e440302883054d0c2bd85486878cb4f8572c"
|
||||
revision = "af66defab954cb421ca110193eed9477c8541e2a"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/net"
|
||||
packages = ["context"]
|
||||
revision = "b68f30494add4df6bd8ef5e82803f308e7f7c59c"
|
||||
revision = "db08ff08e8622530d9ed3a0e8ac279f6d4c02196"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
|
@ -145,19 +145,19 @@
|
|||
"unix",
|
||||
"windows"
|
||||
]
|
||||
revision = "378d26f46672a356c46195c28f61bdb4c0a781dd"
|
||||
revision = "6c888cc515d3ed83fc103cf1d84468aad274b0a7"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/time"
|
||||
packages = ["rate"]
|
||||
revision = "26559e0f760e39c24d730d3224364aef164ee23f"
|
||||
revision = "fbb02b2291d28baffd63558aa44b4b56f178d650"
|
||||
|
||||
[[projects]]
|
||||
branch = "v2"
|
||||
name = "gopkg.in/validator.v2"
|
||||
packages = ["."]
|
||||
revision = "59c90c7046f643cbe0d4e7c8776c42a84ce75910"
|
||||
revision = "135c24b11c19e52befcae2ec3fca5d9b78c4e98e"
|
||||
|
||||
[[projects]]
|
||||
name = "gopkg.in/yaml.v2"
|
||||
|
@ -168,6 +168,6 @@
|
|||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "bc8b02eb09921c3dcef7328c41ec92c8442d151672053769293e0c476f4a2188"
|
||||
inputs-digest = "c59f72846eca4898dab7e7c3fc9a28b340f42aafbe4ac4866ad1ae33c382ea76"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
|
||||
[[constraint]]
|
||||
branch = "allow-disable-of-attribution-rendering"
|
||||
branch = "master"
|
||||
name = "github.com/Luzifer/go-staticmaps"
|
||||
|
||||
[[constraint]]
|
||||
|
@ -38,7 +38,7 @@
|
|||
version = "1.2.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/Sirupsen/logrus"
|
||||
name = "github.com/sirupsen/logrus"
|
||||
version = "1.0.5"
|
||||
|
||||
[[constraint]]
|
||||
|
|
2
main.go
2
main.go
|
@ -11,12 +11,12 @@ import (
|
|||
|
||||
httpHelper "github.com/Luzifer/go_helpers/http"
|
||||
"github.com/Luzifer/rconfig"
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/didip/tollbooth"
|
||||
"github.com/didip/tollbooth/limiter"
|
||||
"github.com/golang/geo/s2"
|
||||
"github.com/gorilla/mux"
|
||||
colorful "github.com/lucasb-eyer/go-colorful"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
2
map.go
2
map.go
|
@ -52,7 +52,7 @@ func generateMap(center s2.LatLng, zoom int, marker []marker, x, y int, disableA
|
|||
ctx.SetZoom(zoom)
|
||||
|
||||
if disableAttribution {
|
||||
ctx.ForceNoAttribution()
|
||||
ctx.OverrideAttribution("")
|
||||
}
|
||||
|
||||
if marker != nil {
|
||||
|
|
19
vendor/github.com/Luzifer/go-staticmaps/context.go
generated
vendored
19
vendor/github.com/Luzifer/go-staticmaps/context.go
generated
vendored
|
@ -43,7 +43,7 @@ type Context struct {
|
|||
userAgent string
|
||||
tileProvider *TileProvider
|
||||
|
||||
forceNoAttribution bool
|
||||
overrideAttribution *string
|
||||
}
|
||||
|
||||
// NewContext creates a new instance of Context
|
||||
|
@ -149,12 +149,12 @@ func (m *Context) ClearOverlays() {
|
|||
m.overlays = nil
|
||||
}
|
||||
|
||||
// ForceNoAttribution disables attribution rendering
|
||||
// OverrideAttribution sets a custom attribution string (or none if empty)
|
||||
//
|
||||
// Pay attention you might be violating the terms of usage for the
|
||||
// selected map provider - only use the function if you are aware of this!
|
||||
func (m *Context) ForceNoAttribution() {
|
||||
m.forceNoAttribution = true
|
||||
func (m *Context) OverrideAttribution(attribution string) {
|
||||
m.overrideAttribution = &attribution
|
||||
}
|
||||
|
||||
func (m *Context) determineBounds() s2.Rect {
|
||||
|
@ -390,18 +390,23 @@ func (m *Context) Render() (image.Image, error) {
|
|||
img, image.Point{trans.pCenterX - int(m.width)/2, trans.pCenterY - int(m.height)/2},
|
||||
draw.Src)
|
||||
|
||||
attribution := m.tileProvider.Attribution
|
||||
if m.overrideAttribution != nil {
|
||||
attribution = *m.overrideAttribution
|
||||
}
|
||||
|
||||
// draw attribution
|
||||
if m.tileProvider.Attribution == "" || m.forceNoAttribution {
|
||||
if attribution == "" {
|
||||
return croppedImg, nil
|
||||
}
|
||||
_, textHeight := gc.MeasureString(m.tileProvider.Attribution)
|
||||
_, textHeight := gc.MeasureString(attribution)
|
||||
boxHeight := textHeight + 4.0
|
||||
gc = gg.NewContextForRGBA(croppedImg)
|
||||
gc.SetRGBA(0.0, 0.0, 0.0, 0.5)
|
||||
gc.DrawRectangle(0.0, float64(m.height)-boxHeight, float64(m.width), boxHeight)
|
||||
gc.Fill()
|
||||
gc.SetRGBA(1.0, 1.0, 1.0, 0.75)
|
||||
gc.DrawString(m.tileProvider.Attribution, 4.0, float64(m.height)-4.0)
|
||||
gc.DrawString(attribution, 4.0, float64(m.height)-4.0)
|
||||
|
||||
return croppedImg, nil
|
||||
}
|
||||
|
|
133
vendor/github.com/golang/geo/s2/centroids.go
generated
vendored
Normal file
133
vendor/github.com/golang/geo/s2/centroids.go
generated
vendored
Normal file
|
@ -0,0 +1,133 @@
|
|||
// Copyright 2018 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package s2
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/golang/geo/r3"
|
||||
)
|
||||
|
||||
// There are several notions of the "centroid" of a triangle. First, there
|
||||
// is the planar centroid, which is simply the centroid of the ordinary
|
||||
// (non-spherical) triangle defined by the three vertices. Second, there is
|
||||
// the surface centroid, which is defined as the intersection of the three
|
||||
// medians of the spherical triangle. It is possible to show that this
|
||||
// point is simply the planar centroid projected to the surface of the
|
||||
// sphere. Finally, there is the true centroid (mass centroid), which is
|
||||
// defined as the surface integral over the spherical triangle of (x,y,z)
|
||||
// divided by the triangle area. This is the point that the triangle would
|
||||
// rotate around if it was spinning in empty space.
|
||||
//
|
||||
// The best centroid for most purposes is the true centroid. Unlike the
|
||||
// planar and surface centroids, the true centroid behaves linearly as
|
||||
// regions are added or subtracted. That is, if you split a triangle into
|
||||
// pieces and compute the average of their centroids (weighted by triangle
|
||||
// area), the result equals the centroid of the original triangle. This is
|
||||
// not true of the other centroids.
|
||||
//
|
||||
// Also note that the surface centroid may be nowhere near the intuitive
|
||||
// "center" of a spherical triangle. For example, consider the triangle
|
||||
// with vertices A=(1,eps,0), B=(0,0,1), C=(-1,eps,0) (a quarter-sphere).
|
||||
// The surface centroid of this triangle is at S=(0, 2*eps, 1), which is
|
||||
// within a distance of 2*eps of the vertex B. Note that the median from A
|
||||
// (the segment connecting A to the midpoint of BC) passes through S, since
|
||||
// this is the shortest path connecting the two endpoints. On the other
|
||||
// hand, the true centroid is at M=(0, 0.5, 0.5), which when projected onto
|
||||
// the surface is a much more reasonable interpretation of the "center" of
|
||||
// this triangle.
|
||||
//
|
||||
|
||||
// TrueCentroid returns the true centroid of the spherical triangle ABC
|
||||
// multiplied by the signed area of spherical triangle ABC. The reasons for
|
||||
// multiplying by the signed area are (1) this is the quantity that needs to be
|
||||
// summed to compute the centroid of a union or difference of triangles, and
|
||||
// (2) it's actually easier to calculate this way. All points must have unit length.
|
||||
//
|
||||
// Note that the result of this function is defined to be Point(0, 0, 0) if
|
||||
// the triangle is degenerate.
|
||||
func TrueCentroid(a, b, c Point) Point {
|
||||
// Use Distance to get accurate results for small triangles.
|
||||
ra := float64(1)
|
||||
if sa := float64(b.Distance(c)); sa != 0 {
|
||||
ra = sa / math.Sin(sa)
|
||||
}
|
||||
rb := float64(1)
|
||||
if sb := float64(c.Distance(a)); sb != 0 {
|
||||
rb = sb / math.Sin(sb)
|
||||
}
|
||||
rc := float64(1)
|
||||
if sc := float64(a.Distance(b)); sc != 0 {
|
||||
rc = sc / math.Sin(sc)
|
||||
}
|
||||
|
||||
// Now compute a point M such that:
|
||||
//
|
||||
// [Ax Ay Az] [Mx] [ra]
|
||||
// [Bx By Bz] [My] = 0.5 * det(A,B,C) * [rb]
|
||||
// [Cx Cy Cz] [Mz] [rc]
|
||||
//
|
||||
// To improve the numerical stability we subtract the first row (A) from the
|
||||
// other two rows; this reduces the cancellation error when A, B, and C are
|
||||
// very close together. Then we solve it using Cramer's rule.
|
||||
//
|
||||
// The result is the true centroid of the triangle multiplied by the
|
||||
// triangle's area.
|
||||
//
|
||||
// This code still isn't as numerically stable as it could be.
|
||||
// The biggest potential improvement is to compute B-A and C-A more
|
||||
// accurately so that (B-A)x(C-A) is always inside triangle ABC.
|
||||
x := r3.Vector{a.X, b.X - a.X, c.X - a.X}
|
||||
y := r3.Vector{a.Y, b.Y - a.Y, c.Y - a.Y}
|
||||
z := r3.Vector{a.Z, b.Z - a.Z, c.Z - a.Z}
|
||||
r := r3.Vector{ra, rb - ra, rc - ra}
|
||||
|
||||
return Point{r3.Vector{y.Cross(z).Dot(r), z.Cross(x).Dot(r), x.Cross(y).Dot(r)}.Mul(0.5)}
|
||||
}
|
||||
|
||||
// EdgeTrueCentroid returns the true centroid of the spherical geodesic edge AB
|
||||
// multiplied by the length of the edge AB. As with triangles, the true centroid
|
||||
// of a collection of line segments may be computed simply by summing the result
|
||||
// of this method for each segment.
|
||||
//
|
||||
// Note that the planar centroid of a line segment is simply 0.5 * (a + b),
|
||||
// while the surface centroid is (a + b).Normalize(). However neither of
|
||||
// these values is appropriate for computing the centroid of a collection of
|
||||
// edges (such as a polyline).
|
||||
//
|
||||
// Also note that the result of this function is defined to be Point(0, 0, 0)
|
||||
// if the edge is degenerate.
|
||||
func EdgeTrueCentroid(a, b Point) Point {
|
||||
// The centroid (multiplied by length) is a vector toward the midpoint
|
||||
// of the edge, whose length is twice the sine of half the angle between
|
||||
// the two vertices. Defining theta to be this angle, we have:
|
||||
vDiff := a.Sub(b.Vector) // Length == 2*sin(theta)
|
||||
vSum := a.Add(b.Vector) // Length == 2*cos(theta)
|
||||
sin2 := vDiff.Norm2()
|
||||
cos2 := vSum.Norm2()
|
||||
if cos2 == 0 {
|
||||
return Point{} // Ignore antipodal edges.
|
||||
}
|
||||
return Point{vSum.Mul(math.Sqrt(sin2 / cos2))} // Length == 2*sin(theta)
|
||||
}
|
||||
|
||||
// PlanarCentroid returns the centroid of the planar triangle ABC. This can be
|
||||
// normalized to unit length to obtain the "surface centroid" of the corresponding
|
||||
// spherical triangle, i.e. the intersection of the three medians. However, note
|
||||
// that for large spherical triangles the surface centroid may be nowhere near
|
||||
// the intuitive "center".
|
||||
func PlanarCentroid(a, b, c Point) Point {
|
||||
return Point{a.Add(b.Vector).Add(c.Vector).Mul(1. / 3)}
|
||||
}
|
157
vendor/github.com/golang/geo/s2/contains_point_query.go
generated
vendored
Normal file
157
vendor/github.com/golang/geo/s2/contains_point_query.go
generated
vendored
Normal file
|
@ -0,0 +1,157 @@
|
|||
// Copyright 2018 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package s2
|
||||
|
||||
// VertexModel defines whether shapes are considered to contain their vertices.
|
||||
// Note that these definitions differ from the ones used by BooleanOperation.
|
||||
//
|
||||
// Note that points other than vertices are never contained by polylines.
|
||||
// If you want need this behavior, use ClosestEdgeQuery's IsDistanceLess
|
||||
// with a suitable distance threshold instead.
|
||||
type VertexModel int
|
||||
|
||||
const (
|
||||
// VertexModelOpen means no shapes contain their vertices (not even
|
||||
// points). Therefore Contains(Point) returns true if and only if the
|
||||
// point is in the interior of some polygon.
|
||||
VertexModelOpen VertexModel = iota
|
||||
|
||||
// VertexModelSemiOpen means that polygon point containment is defined
|
||||
// such that if several polygons tile the region around a vertex, then
|
||||
// exactly one of those polygons contains that vertex. Points and
|
||||
// polylines still do not contain any vertices.
|
||||
VertexModelSemiOpen
|
||||
|
||||
// VertexModelClosed means all shapes contain their vertices (including
|
||||
// points and polylines).
|
||||
VertexModelClosed
|
||||
)
|
||||
|
||||
// ContainsPointQuery determines whether one or more shapes in a ShapeIndex
|
||||
// contain a given Point. The ShapeIndex may contain any number of points,
|
||||
// polylines, and/or polygons (possibly overlapping). Shape boundaries may be
|
||||
// modeled as Open, SemiOpen, or Closed (this affects whether or not shapes are
|
||||
// considered to contain their vertices).
|
||||
//
|
||||
// Note that if you need to do a large number of point containment
|
||||
// tests, it is more efficient to re-use the query rather than creating a new
|
||||
// one each time.
|
||||
type ContainsPointQuery struct {
|
||||
model VertexModel
|
||||
index *ShapeIndex
|
||||
iter *ShapeIndexIterator
|
||||
}
|
||||
|
||||
// NewContainsPointQuery creates a new instance of the ContainsPointQuery for the index
|
||||
// and given vertex model choice.
|
||||
func NewContainsPointQuery(index *ShapeIndex, model VertexModel) *ContainsPointQuery {
|
||||
return &ContainsPointQuery{
|
||||
index: index,
|
||||
model: model,
|
||||
iter: index.Iterator(),
|
||||
}
|
||||
}
|
||||
|
||||
// Contains reports whether any shape in the queries index contains the point p
|
||||
// under the queries vertex model (Open, SemiOpen, or Closed).
|
||||
func (q *ContainsPointQuery) Contains(p Point) bool {
|
||||
if !q.iter.LocatePoint(p) {
|
||||
return false
|
||||
}
|
||||
|
||||
cell := q.iter.IndexCell()
|
||||
for _, clipped := range cell.shapes {
|
||||
if q.shapeContains(clipped, q.iter.Center(), p) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// shapeContains reports whether the clippedShape from the iterator's center position contains
|
||||
// the given point.
|
||||
func (q *ContainsPointQuery) shapeContains(clipped *clippedShape, center, p Point) bool {
|
||||
inside := clipped.containsCenter
|
||||
numEdges := clipped.numEdges()
|
||||
if numEdges <= 0 {
|
||||
return inside
|
||||
}
|
||||
|
||||
shape := q.index.Shape(clipped.shapeID)
|
||||
if !shape.HasInterior() {
|
||||
// Points and polylines can be ignored unless the vertex model is Closed.
|
||||
if q.model != VertexModelClosed {
|
||||
return false
|
||||
}
|
||||
|
||||
// Otherwise, the point is contained if and only if it matches a vertex.
|
||||
for _, edgeID := range clipped.edges {
|
||||
edge := shape.Edge(edgeID)
|
||||
if edge.V0 == p || edge.V1 == p {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Test containment by drawing a line segment from the cell center to the
|
||||
// given point and counting edge crossings.
|
||||
crosser := NewEdgeCrosser(center, p)
|
||||
for _, edgeID := range clipped.edges {
|
||||
edge := shape.Edge(edgeID)
|
||||
sign := crosser.CrossingSign(edge.V0, edge.V1)
|
||||
if sign == DoNotCross {
|
||||
continue
|
||||
}
|
||||
if sign == MaybeCross {
|
||||
// For the Open and Closed models, check whether p is a vertex.
|
||||
if q.model != VertexModelSemiOpen && (edge.V0 == p || edge.V1 == p) {
|
||||
return (q.model == VertexModelClosed)
|
||||
}
|
||||
// C++ plays fast and loose with the int <-> bool conversions here.
|
||||
if VertexCrossing(crosser.a, crosser.b, edge.V0, edge.V1) {
|
||||
sign = Cross
|
||||
} else {
|
||||
sign = DoNotCross
|
||||
}
|
||||
}
|
||||
inside = inside != (sign == Cross)
|
||||
}
|
||||
|
||||
return inside
|
||||
}
|
||||
|
||||
// ShapeContains reports whether the given shape contains the point under this
|
||||
// queries vertex model (Open, SemiOpen, or Closed).
|
||||
//
|
||||
// This requires the shape belongs to this queries index.
|
||||
func (q *ContainsPointQuery) ShapeContains(shape Shape, p Point) bool {
|
||||
if !q.iter.LocatePoint(p) {
|
||||
return false
|
||||
}
|
||||
|
||||
clipped := q.iter.IndexCell().findByShapeID(q.index.idForShape(shape))
|
||||
if clipped == nil {
|
||||
return false
|
||||
}
|
||||
return q.shapeContains(clipped, q.iter.Center(), p)
|
||||
}
|
||||
|
||||
// TODO(roberts): Remaining methods from C++
|
||||
// func (q *ContainsPointQuery) ContainingShapes(p Point) []Shape
|
||||
// type shapeVisitorFunc func(shape Shape) bool
|
||||
// func (q *ContainsPointQuery) VisitContainingShapes(p Point, v shapeVisitorFunc) bool
|
||||
// type edgeVisitorFunc func(shape ShapeEdge) bool
|
||||
// func (q *ContainsPointQuery) VisitIncidentEdges(p Point, v edgeVisitorFunc) bool
|
19
vendor/github.com/golang/geo/s2/loop.go
generated
vendored
19
vendor/github.com/golang/geo/s2/loop.go
generated
vendored
|
@ -203,21 +203,16 @@ func (l *Loop) initBound() {
|
|||
l.subregionBound = ExpandForSubregions(l.bound)
|
||||
}
|
||||
|
||||
// IsValid reports whether this is a valid loop or not.
|
||||
func (l *Loop) IsValid() bool {
|
||||
return l.findValidationError() == nil
|
||||
}
|
||||
|
||||
// findValidationError reports whether this is not a valid loop and if so
|
||||
// returns an error describing why. This function requires the Loops ShapeIndex
|
||||
// to have been intialized.
|
||||
func (l *Loop) findValidationError() error {
|
||||
// Validate checks whether this is a valid loop.
|
||||
func (l *Loop) Validate() error {
|
||||
if err := l.findValidationErrorNoIndex(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check for intersections between non-adjacent edges (including at vertices)
|
||||
// TODO(roberts): Once shapeutil gets findAnyCrossing uncomment this.
|
||||
// return findAnyCrossing(l.index)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -476,7 +471,7 @@ func (l *Loop) Edge(i int) Edge {
|
|||
|
||||
// NumChains reports the number of contiguous edge chains in the Loop.
|
||||
func (l *Loop) NumChains() int {
|
||||
if l.isEmptyOrFull() {
|
||||
if l.IsEmpty() {
|
||||
return 0
|
||||
}
|
||||
return 1
|
||||
|
@ -501,12 +496,12 @@ func (l *Loop) ChainPosition(edgeID int) ChainPosition {
|
|||
// dimension returns the dimension of the geometry represented by this Loop.
|
||||
func (l *Loop) dimension() dimension { return polygonGeometry }
|
||||
|
||||
// IsEmpty reports true if this is the special "empty" loop that contains no points.
|
||||
// IsEmpty reports true if this is the special empty loop that contains no points.
|
||||
func (l *Loop) IsEmpty() bool {
|
||||
return l.isEmptyOrFull() && !l.ContainsOrigin()
|
||||
}
|
||||
|
||||
// IsFull reports true if this is the special "full" loop that contains all points.
|
||||
// IsFull reports true if this is the special full loop that contains all points.
|
||||
func (l *Loop) IsFull() bool {
|
||||
return l.isEmptyOrFull() && l.ContainsOrigin()
|
||||
}
|
||||
|
|
190
vendor/github.com/golang/geo/s2/point.go
generated
vendored
190
vendor/github.com/golang/geo/s2/point.go
generated
vendored
|
@ -131,163 +131,6 @@ func (p Point) ApproxEqual(other Point) bool {
|
|||
return p.Vector.Angle(other.Vector) <= s1.Angle(epsilon)
|
||||
}
|
||||
|
||||
// PointArea returns the area on the unit sphere for the triangle defined by the
|
||||
// given points.
|
||||
//
|
||||
// This method is based on l'Huilier's theorem,
|
||||
//
|
||||
// tan(E/4) = sqrt(tan(s/2) tan((s-a)/2) tan((s-b)/2) tan((s-c)/2))
|
||||
//
|
||||
// where E is the spherical excess of the triangle (i.e. its area),
|
||||
// a, b, c are the side lengths, and
|
||||
// s is the semiperimeter (a + b + c) / 2.
|
||||
//
|
||||
// The only significant source of error using l'Huilier's method is the
|
||||
// cancellation error of the terms (s-a), (s-b), (s-c). This leads to a
|
||||
// *relative* error of about 1e-16 * s / min(s-a, s-b, s-c). This compares
|
||||
// to a relative error of about 1e-15 / E using Girard's formula, where E is
|
||||
// the true area of the triangle. Girard's formula can be even worse than
|
||||
// this for very small triangles, e.g. a triangle with a true area of 1e-30
|
||||
// might evaluate to 1e-5.
|
||||
//
|
||||
// So, we prefer l'Huilier's formula unless dmin < s * (0.1 * E), where
|
||||
// dmin = min(s-a, s-b, s-c). This basically includes all triangles
|
||||
// except for extremely long and skinny ones.
|
||||
//
|
||||
// Since we don't know E, we would like a conservative upper bound on
|
||||
// the triangle area in terms of s and dmin. It's possible to show that
|
||||
// E <= k1 * s * sqrt(s * dmin), where k1 = 2*sqrt(3)/Pi (about 1).
|
||||
// Using this, it's easy to show that we should always use l'Huilier's
|
||||
// method if dmin >= k2 * s^5, where k2 is about 1e-2. Furthermore,
|
||||
// if dmin < k2 * s^5, the triangle area is at most k3 * s^4, where
|
||||
// k3 is about 0.1. Since the best case error using Girard's formula
|
||||
// is about 1e-15, this means that we shouldn't even consider it unless
|
||||
// s >= 3e-4 or so.
|
||||
func PointArea(a, b, c Point) float64 {
|
||||
sa := float64(b.Angle(c.Vector))
|
||||
sb := float64(c.Angle(a.Vector))
|
||||
sc := float64(a.Angle(b.Vector))
|
||||
s := 0.5 * (sa + sb + sc)
|
||||
if s >= 3e-4 {
|
||||
// Consider whether Girard's formula might be more accurate.
|
||||
dmin := s - math.Max(sa, math.Max(sb, sc))
|
||||
if dmin < 1e-2*s*s*s*s*s {
|
||||
// This triangle is skinny enough to use Girard's formula.
|
||||
area := GirardArea(a, b, c)
|
||||
if dmin < s*0.1*area {
|
||||
return area
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use l'Huilier's formula.
|
||||
return 4 * math.Atan(math.Sqrt(math.Max(0.0, math.Tan(0.5*s)*math.Tan(0.5*(s-sa))*
|
||||
math.Tan(0.5*(s-sb))*math.Tan(0.5*(s-sc)))))
|
||||
}
|
||||
|
||||
// GirardArea returns the area of the triangle computed using Girard's formula.
|
||||
// All points should be unit length, and no two points should be antipodal.
|
||||
//
|
||||
// This method is about twice as fast as PointArea() but has poor relative
|
||||
// accuracy for small triangles. The maximum error is about 5e-15 (about
|
||||
// 0.25 square meters on the Earth's surface) and the average error is about
|
||||
// 1e-15. These bounds apply to triangles of any size, even as the maximum
|
||||
// edge length of the triangle approaches 180 degrees. But note that for
|
||||
// such triangles, tiny perturbations of the input points can change the
|
||||
// true mathematical area dramatically.
|
||||
func GirardArea(a, b, c Point) float64 {
|
||||
// This is equivalent to the usual Girard's formula but is slightly more
|
||||
// accurate, faster to compute, and handles a == b == c without a special
|
||||
// case. PointCross is necessary to get good accuracy when two of
|
||||
// the input points are very close together.
|
||||
ab := a.PointCross(b)
|
||||
bc := b.PointCross(c)
|
||||
ac := a.PointCross(c)
|
||||
area := float64(ab.Angle(ac.Vector) - ab.Angle(bc.Vector) + bc.Angle(ac.Vector))
|
||||
if area < 0 {
|
||||
area = 0
|
||||
}
|
||||
return area
|
||||
}
|
||||
|
||||
// SignedArea returns a positive value for counterclockwise triangles and a negative
|
||||
// value otherwise (similar to PointArea).
|
||||
func SignedArea(a, b, c Point) float64 {
|
||||
return float64(RobustSign(a, b, c)) * PointArea(a, b, c)
|
||||
}
|
||||
|
||||
// TrueCentroid returns the true centroid of the spherical triangle ABC multiplied by the
|
||||
// signed area of spherical triangle ABC. The result is not normalized.
|
||||
// The reasons for multiplying by the signed area are (1) this is the quantity
|
||||
// that needs to be summed to compute the centroid of a union or difference of triangles,
|
||||
// and (2) it's actually easier to calculate this way. All points must have unit length.
|
||||
//
|
||||
// The true centroid (mass centroid) is defined as the surface integral
|
||||
// over the spherical triangle of (x,y,z) divided by the triangle area.
|
||||
// This is the point that the triangle would rotate around if it was
|
||||
// spinning in empty space.
|
||||
//
|
||||
// The best centroid for most purposes is the true centroid. Unlike the
|
||||
// planar and surface centroids, the true centroid behaves linearly as
|
||||
// regions are added or subtracted. That is, if you split a triangle into
|
||||
// pieces and compute the average of their centroids (weighted by triangle
|
||||
// area), the result equals the centroid of the original triangle. This is
|
||||
// not true of the other centroids.
|
||||
func TrueCentroid(a, b, c Point) Point {
|
||||
ra := float64(1)
|
||||
if sa := float64(b.Distance(c)); sa != 0 {
|
||||
ra = sa / math.Sin(sa)
|
||||
}
|
||||
rb := float64(1)
|
||||
if sb := float64(c.Distance(a)); sb != 0 {
|
||||
rb = sb / math.Sin(sb)
|
||||
}
|
||||
rc := float64(1)
|
||||
if sc := float64(a.Distance(b)); sc != 0 {
|
||||
rc = sc / math.Sin(sc)
|
||||
}
|
||||
|
||||
// Now compute a point M such that:
|
||||
//
|
||||
// [Ax Ay Az] [Mx] [ra]
|
||||
// [Bx By Bz] [My] = 0.5 * det(A,B,C) * [rb]
|
||||
// [Cx Cy Cz] [Mz] [rc]
|
||||
//
|
||||
// To improve the numerical stability we subtract the first row (A) from the
|
||||
// other two rows; this reduces the cancellation error when A, B, and C are
|
||||
// very close together. Then we solve it using Cramer's rule.
|
||||
//
|
||||
// This code still isn't as numerically stable as it could be.
|
||||
// The biggest potential improvement is to compute B-A and C-A more
|
||||
// accurately so that (B-A)x(C-A) is always inside triangle ABC.
|
||||
x := r3.Vector{a.X, b.X - a.X, c.X - a.X}
|
||||
y := r3.Vector{a.Y, b.Y - a.Y, c.Y - a.Y}
|
||||
z := r3.Vector{a.Z, b.Z - a.Z, c.Z - a.Z}
|
||||
r := r3.Vector{ra, rb - ra, rc - ra}
|
||||
|
||||
return Point{r3.Vector{y.Cross(z).Dot(r), z.Cross(x).Dot(r), x.Cross(y).Dot(r)}.Mul(0.5)}
|
||||
}
|
||||
|
||||
// PlanarCentroid returns the centroid of the planar triangle ABC, which is not normalized.
|
||||
// It can be normalized to unit length to obtain the "surface centroid" of the corresponding
|
||||
// spherical triangle, i.e. the intersection of the three medians. However,
|
||||
// note that for large spherical triangles the surface centroid may be
|
||||
// nowhere near the intuitive "center" (see example in TrueCentroid comments).
|
||||
//
|
||||
// Note that the surface centroid may be nowhere near the intuitive
|
||||
// "center" of a spherical triangle. For example, consider the triangle
|
||||
// with vertices A=(1,eps,0), B=(0,0,1), C=(-1,eps,0) (a quarter-sphere).
|
||||
// The surface centroid of this triangle is at S=(0, 2*eps, 1), which is
|
||||
// within a distance of 2*eps of the vertex B. Note that the median from A
|
||||
// (the segment connecting A to the midpoint of BC) passes through S, since
|
||||
// this is the shortest path connecting the two endpoints. On the other
|
||||
// hand, the true centroid is at M=(0, 0.5, 0.5), which when projected onto
|
||||
// the surface is a much more reasonable interpretation of the "center" of
|
||||
// this triangle.
|
||||
func PlanarCentroid(a, b, c Point) Point {
|
||||
return Point{a.Add(b.Vector).Add(c.Vector).Mul(1. / 3)}
|
||||
}
|
||||
|
||||
// ChordAngleBetweenPoints constructs a ChordAngle corresponding to the distance
|
||||
// between the two given points. The points must be unit length.
|
||||
func ChordAngleBetweenPoints(x, y Point) s1.ChordAngle {
|
||||
|
@ -392,39 +235,6 @@ func (p *Point) decode(d *decoder) {
|
|||
p.Z = d.readFloat64()
|
||||
}
|
||||
|
||||
// Angle returns the interior angle at the vertex B in the triangle ABC. The
|
||||
// return value is always in the range [0, pi]. All points should be
|
||||
// normalized. Ensures that Angle(a,b,c) == Angle(c,b,a) for all a,b,c.
|
||||
//
|
||||
// The angle is undefined if A or C is diametrically opposite from B, and
|
||||
// becomes numerically unstable as the length of edge AB or BC approaches
|
||||
// 180 degrees.
|
||||
func Angle(a, b, c Point) s1.Angle {
|
||||
return a.PointCross(b).Angle(c.PointCross(b).Vector)
|
||||
}
|
||||
|
||||
// TurnAngle returns the exterior angle at vertex B in the triangle ABC. The
|
||||
// return value is positive if ABC is counterclockwise and negative otherwise.
|
||||
// If you imagine an ant walking from A to B to C, this is the angle that the
|
||||
// ant turns at vertex B (positive = left = CCW, negative = right = CW).
|
||||
// This quantity is also known as the "geodesic curvature" at B.
|
||||
//
|
||||
// Ensures that TurnAngle(a,b,c) == -TurnAngle(c,b,a) for all distinct
|
||||
// a,b,c. The result is undefined if (a == b || b == c), but is either
|
||||
// -Pi or Pi if (a == c). All points should be normalized.
|
||||
func TurnAngle(a, b, c Point) s1.Angle {
|
||||
// We use PointCross to get good accuracy when two points are very
|
||||
// close together, and RobustSign to ensure that the sign is correct for
|
||||
// turns that are close to 180 degrees.
|
||||
angle := a.PointCross(b).Angle(b.PointCross(c).Vector)
|
||||
|
||||
// Don't return RobustSign * angle because it is legal to have (a == c).
|
||||
if RobustSign(a, b, c) == CounterClockwise {
|
||||
return angle
|
||||
}
|
||||
return -angle
|
||||
}
|
||||
|
||||
// Rotate the given point about the given axis by the given angle. p and
|
||||
// axis must be unit length; angle has no restrictions (e.g., it can be
|
||||
// positive, negative, greater than 360 degrees, etc).
|
||||
|
|
149
vendor/github.com/golang/geo/s2/point_measures.go
generated
vendored
Normal file
149
vendor/github.com/golang/geo/s2/point_measures.go
generated
vendored
Normal file
|
@ -0,0 +1,149 @@
|
|||
// Copyright 2018 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package s2
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/golang/geo/s1"
|
||||
)
|
||||
|
||||
// PointArea returns the area of triangle ABC. This method combines two different
|
||||
// algorithms to get accurate results for both large and small triangles.
|
||||
// The maximum error is about 5e-15 (about 0.25 square meters on the Earth's
|
||||
// surface), the same as GirardArea below, but unlike that method it is
|
||||
// also accurate for small triangles. Example: when the true area is 100
|
||||
// square meters, PointArea yields an error about 1 trillion times smaller than
|
||||
// GirardArea.
|
||||
//
|
||||
// All points should be unit length, and no two points should be antipodal.
|
||||
// The area is always positive.
|
||||
func PointArea(a, b, c Point) float64 {
|
||||
// This method is based on l'Huilier's theorem,
|
||||
//
|
||||
// tan(E/4) = sqrt(tan(s/2) tan((s-a)/2) tan((s-b)/2) tan((s-c)/2))
|
||||
//
|
||||
// where E is the spherical excess of the triangle (i.e. its area),
|
||||
// a, b, c are the side lengths, and
|
||||
// s is the semiperimeter (a + b + c) / 2.
|
||||
//
|
||||
// The only significant source of error using l'Huilier's method is the
|
||||
// cancellation error of the terms (s-a), (s-b), (s-c). This leads to a
|
||||
// *relative* error of about 1e-16 * s / min(s-a, s-b, s-c). This compares
|
||||
// to a relative error of about 1e-15 / E using Girard's formula, where E is
|
||||
// the true area of the triangle. Girard's formula can be even worse than
|
||||
// this for very small triangles, e.g. a triangle with a true area of 1e-30
|
||||
// might evaluate to 1e-5.
|
||||
//
|
||||
// So, we prefer l'Huilier's formula unless dmin < s * (0.1 * E), where
|
||||
// dmin = min(s-a, s-b, s-c). This basically includes all triangles
|
||||
// except for extremely long and skinny ones.
|
||||
//
|
||||
// Since we don't know E, we would like a conservative upper bound on
|
||||
// the triangle area in terms of s and dmin. It's possible to show that
|
||||
// E <= k1 * s * sqrt(s * dmin), where k1 = 2*sqrt(3)/Pi (about 1).
|
||||
// Using this, it's easy to show that we should always use l'Huilier's
|
||||
// method if dmin >= k2 * s^5, where k2 is about 1e-2. Furthermore,
|
||||
// if dmin < k2 * s^5, the triangle area is at most k3 * s^4, where
|
||||
// k3 is about 0.1. Since the best case error using Girard's formula
|
||||
// is about 1e-15, this means that we shouldn't even consider it unless
|
||||
// s >= 3e-4 or so.
|
||||
sa := float64(b.Angle(c.Vector))
|
||||
sb := float64(c.Angle(a.Vector))
|
||||
sc := float64(a.Angle(b.Vector))
|
||||
s := 0.5 * (sa + sb + sc)
|
||||
if s >= 3e-4 {
|
||||
// Consider whether Girard's formula might be more accurate.
|
||||
dmin := s - math.Max(sa, math.Max(sb, sc))
|
||||
if dmin < 1e-2*s*s*s*s*s {
|
||||
// This triangle is skinny enough to use Girard's formula.
|
||||
area := GirardArea(a, b, c)
|
||||
if dmin < s*0.1*area {
|
||||
return area
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use l'Huilier's formula.
|
||||
return 4 * math.Atan(math.Sqrt(math.Max(0.0, math.Tan(0.5*s)*math.Tan(0.5*(s-sa))*
|
||||
math.Tan(0.5*(s-sb))*math.Tan(0.5*(s-sc)))))
|
||||
}
|
||||
|
||||
// GirardArea returns the area of the triangle computed using Girard's formula.
|
||||
// All points should be unit length, and no two points should be antipodal.
|
||||
//
|
||||
// This method is about twice as fast as PointArea() but has poor relative
|
||||
// accuracy for small triangles. The maximum error is about 5e-15 (about
|
||||
// 0.25 square meters on the Earth's surface) and the average error is about
|
||||
// 1e-15. These bounds apply to triangles of any size, even as the maximum
|
||||
// edge length of the triangle approaches 180 degrees. But note that for
|
||||
// such triangles, tiny perturbations of the input points can change the
|
||||
// true mathematical area dramatically.
|
||||
func GirardArea(a, b, c Point) float64 {
|
||||
// This is equivalent to the usual Girard's formula but is slightly more
|
||||
// accurate, faster to compute, and handles a == b == c without a special
|
||||
// case. PointCross is necessary to get good accuracy when two of
|
||||
// the input points are very close together.
|
||||
ab := a.PointCross(b)
|
||||
bc := b.PointCross(c)
|
||||
ac := a.PointCross(c)
|
||||
|
||||
area := float64(ab.Angle(ac.Vector) - ab.Angle(bc.Vector) + bc.Angle(ac.Vector))
|
||||
if area < 0 {
|
||||
area = 0
|
||||
}
|
||||
return area
|
||||
}
|
||||
|
||||
// SignedArea returns a positive value for counterclockwise triangles and a negative
|
||||
// value otherwise (similar to PointArea).
|
||||
func SignedArea(a, b, c Point) float64 {
|
||||
return float64(RobustSign(a, b, c)) * PointArea(a, b, c)
|
||||
}
|
||||
|
||||
// Angle returns the interior angle at the vertex B in the triangle ABC. The
|
||||
// return value is always in the range [0, pi]. All points should be
|
||||
// normalized. Ensures that Angle(a,b,c) == Angle(c,b,a) for all a,b,c.
|
||||
//
|
||||
// The angle is undefined if A or C is diametrically opposite from B, and
|
||||
// becomes numerically unstable as the length of edge AB or BC approaches
|
||||
// 180 degrees.
|
||||
func Angle(a, b, c Point) s1.Angle {
|
||||
// PointCross is necessary to get good accuracy when two of the input
|
||||
// points are very close together.
|
||||
return a.PointCross(b).Angle(c.PointCross(b).Vector)
|
||||
}
|
||||
|
||||
// TurnAngle returns the exterior angle at vertex B in the triangle ABC. The
|
||||
// return value is positive if ABC is counterclockwise and negative otherwise.
|
||||
// If you imagine an ant walking from A to B to C, this is the angle that the
|
||||
// ant turns at vertex B (positive = left = CCW, negative = right = CW).
|
||||
// This quantity is also known as the "geodesic curvature" at B.
|
||||
//
|
||||
// Ensures that TurnAngle(a,b,c) == -TurnAngle(c,b,a) for all distinct
|
||||
// a,b,c. The result is undefined if (a == b || b == c), but is either
|
||||
// -Pi or Pi if (a == c). All points should be normalized.
|
||||
func TurnAngle(a, b, c Point) s1.Angle {
|
||||
// We use PointCross to get good accuracy when two points are very
|
||||
// close together, and RobustSign to ensure that the sign is correct for
|
||||
// turns that are close to 180 degrees.
|
||||
angle := a.PointCross(b).Angle(b.PointCross(c).Vector)
|
||||
|
||||
// Don't return RobustSign * angle because it is legal to have (a == c).
|
||||
if RobustSign(a, b, c) == CounterClockwise {
|
||||
return angle
|
||||
}
|
||||
return -angle
|
||||
}
|
38
vendor/github.com/golang/geo/s2/polygon.go
generated
vendored
38
vendor/github.com/golang/geo/s2/polygon.go
generated
vendored
|
@ -330,18 +330,9 @@ func FullPolygon() *Polygon {
|
|||
return ret
|
||||
}
|
||||
|
||||
// IsValid reports whether this is a valid polygon (including checking whether all
|
||||
// the loops are themselves valid).
|
||||
func (p *Polygon) IsValid() bool {
|
||||
// TODO(roberts): If we want to expose the error, add a Validate() error method.
|
||||
return p.validate() == nil
|
||||
}
|
||||
|
||||
// validate reports any error if this is not a valid polygon.
|
||||
//
|
||||
// Note that in the returned error messages, loops that represent holes have their
|
||||
// edges numbered in reverse order, starting from the last vertex of the loop.
|
||||
func (p *Polygon) validate() error {
|
||||
// Validate checks whether this is a valid polygon,
|
||||
// including checking whether all the loops are themselves valid.
|
||||
func (p *Polygon) Validate() error {
|
||||
for i, l := range p.loops {
|
||||
// Check for loop errors that don't require building a ShapeIndex.
|
||||
if err := l.findValidationErrorNoIndex(); err != nil {
|
||||
|
@ -671,10 +662,6 @@ func (p *Polygon) ReferencePoint() ReferencePoint {
|
|||
|
||||
// NumChains reports the number of contiguous edge chains in the Polygon.
|
||||
func (p *Polygon) NumChains() int {
|
||||
if p.IsFull() {
|
||||
return 0
|
||||
}
|
||||
|
||||
return p.NumLoops()
|
||||
}
|
||||
|
||||
|
@ -687,7 +674,13 @@ func (p *Polygon) Chain(chainID int) Chain {
|
|||
for j := 0; j < chainID; j++ {
|
||||
e += len(p.Loop(j).vertices)
|
||||
}
|
||||
return Chain{e, len(p.Loop(chainID).vertices)}
|
||||
|
||||
// Polygon represents a full loop as a loop with one vertex, while
|
||||
// Shape represents a full loop as a chain with no vertices.
|
||||
if numVertices := p.Loop(chainID).NumVertices(); numVertices != 1 {
|
||||
return Chain{e, numVertices}
|
||||
}
|
||||
return Chain{e, 0}
|
||||
}
|
||||
|
||||
// ChainEdge returns the j-th edge of the i-th edge Chain (loop).
|
||||
|
@ -906,6 +899,16 @@ func (p *Polygon) anyLoopIntersects(o *Loop) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// Area returns the area of the polygon interior, i.e. the region on the left side
|
||||
// of an odd number of loops. The return value is between 0 and 4*Pi.
|
||||
func (p *Polygon) Area() float64 {
|
||||
var area float64
|
||||
for _, loop := range p.loops {
|
||||
area += float64(loop.Sign()) * loop.Area()
|
||||
}
|
||||
return area
|
||||
}
|
||||
|
||||
// Encode encodes the Polygon
|
||||
func (p *Polygon) Encode(w io.Writer) error {
|
||||
e := &encoder{w: w}
|
||||
|
@ -1087,7 +1090,6 @@ func (p *Polygon) decodeCompressed(d *decoder) {
|
|||
}
|
||||
|
||||
// TODO(roberts): Differences from C++
|
||||
// Area
|
||||
// Centroid
|
||||
// SnapLevel
|
||||
// DistanceToPoint
|
||||
|
|
6
vendor/github.com/golang/geo/s2/polyline.go
generated
vendored
6
vendor/github.com/golang/geo/s2/polyline.go
generated
vendored
|
@ -197,6 +197,12 @@ func (p *Polyline) ChainPosition(edgeID int) ChainPosition {
|
|||
// dimension returns the dimension of the geometry represented by this Polyline.
|
||||
func (p *Polyline) dimension() dimension { return polylineGeometry }
|
||||
|
||||
// IsEmpty reports whether this shape contains no points.
|
||||
func (p *Polyline) IsEmpty() bool { return defaultShapeIsEmpty(p) }
|
||||
|
||||
// IsFull reports whether this shape contains all points on the sphere.
|
||||
func (p *Polyline) IsFull() bool { return defaultShapeIsFull(p) }
|
||||
|
||||
// findEndVertex reports the maximal end index such that the line segment between
|
||||
// the start index and this one such that the line segment between these two
|
||||
// vertices passes within the given tolerance of all interior vertices, in order.
|
||||
|
|
53
vendor/github.com/golang/geo/s2/polyline_measures.go
generated
vendored
Normal file
53
vendor/github.com/golang/geo/s2/polyline_measures.go
generated
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
// Copyright 2018 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package s2
|
||||
|
||||
// This file defines various measures for polylines on the sphere. These are
|
||||
// low-level methods that work directly with arrays of Points. They are used to
|
||||
// implement the methods in various other measures files.
|
||||
|
||||
import (
|
||||
"github.com/golang/geo/r3"
|
||||
"github.com/golang/geo/s1"
|
||||
)
|
||||
|
||||
// polylineLength returns the length of the given Polyline.
|
||||
// It returns 0 for polylines with fewer than two vertices.
|
||||
func polylineLength(p []Point) s1.Angle {
|
||||
var length s1.Angle
|
||||
|
||||
for i := 1; i < len(p); i++ {
|
||||
length += p[i-1].Distance(p[i])
|
||||
}
|
||||
return length
|
||||
}
|
||||
|
||||
// polylineCentroid returns the true centroid of the polyline multiplied by the
|
||||
// length of the polyline. The result is not unit length, so you may wish to
|
||||
// normalize it.
|
||||
//
|
||||
// Scaling by the Polyline length makes it easy to compute the centroid
|
||||
// of several Polylines (by simply adding up their centroids).
|
||||
//
|
||||
// Note that for degenerate Polylines (e.g., AA) this returns Point(0, 0, 0).
|
||||
// (This answer is correct; the result of this function is a line integral over
|
||||
// the polyline, whose value is always zero if the polyline is degenerate.)
|
||||
func polylineCentroid(p []Point) Point {
|
||||
var centroid r3.Vector
|
||||
for i := 1; i < len(p); i++ {
|
||||
centroid = centroid.Add(EdgeTrueCentroid(p[i-1], p[i]).Vector)
|
||||
}
|
||||
return Point{centroid}
|
||||
}
|
56
vendor/github.com/golang/geo/s2/shape.go
generated
vendored
56
vendor/github.com/golang/geo/s2/shape.go
generated
vendored
|
@ -59,6 +59,42 @@ func (e edges) Len() int { return len(e) }
|
|||
func (e edges) Swap(i, j int) { e[i], e[j] = e[j], e[i] }
|
||||
func (e edges) Less(i, j int) bool { return e[i].Cmp(e[j]) == -1 }
|
||||
|
||||
// ShapeEdgeID is a unique identifier for an Edge within an ShapeIndex,
|
||||
// consisting of a (shapeID, edgeID) pair.
|
||||
type ShapeEdgeID struct {
|
||||
ShapeID int32
|
||||
EdgeID int32
|
||||
}
|
||||
|
||||
// Cmp compares the two ShapeEdgeIDs and returns
|
||||
//
|
||||
// -1 if s < other
|
||||
// 0 if s == other
|
||||
// +1 if s > other
|
||||
//
|
||||
// The two are compared first by shape id and then by edge id.
|
||||
func (s ShapeEdgeID) Cmp(other ShapeEdgeID) int {
|
||||
switch {
|
||||
case s.ShapeID < other.ShapeID:
|
||||
return -1
|
||||
case s.ShapeID > other.ShapeID:
|
||||
return 1
|
||||
}
|
||||
switch {
|
||||
case s.EdgeID < other.EdgeID:
|
||||
return -1
|
||||
case s.EdgeID > other.EdgeID:
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// ShapeEdge represents a ShapeEdgeID with the two endpoints of that Edge.
|
||||
type ShapeEdge struct {
|
||||
ID ShapeEdgeID
|
||||
Edge Edge
|
||||
}
|
||||
|
||||
// Chain represents a range of edge IDs corresponding to a chain of connected
|
||||
// edges, specified as a (start, length) pair. The chain is defined to consist of
|
||||
// edge IDs {start, start + 1, ..., start + length - 1}.
|
||||
|
@ -179,11 +215,31 @@ type Shape interface {
|
|||
// of edge chains where each chain represents one polygon loop.
|
||||
// Polygons may have degeneracies (e.g., degenerate edges or sibling
|
||||
// pairs consisting of an edge and its corresponding reversed edge).
|
||||
// A polygon loop may also be full (containing all points on the
|
||||
// sphere); by convention this is represented as a chain with no edges.
|
||||
// (See laxPolygon for more details.)
|
||||
//
|
||||
// Note that this method allows degenerate geometry of different dimensions
|
||||
// to be distinguished, e.g. it allows a point to be distinguished from a
|
||||
// polyline or polygon that has been simplified to a single point.
|
||||
dimension() dimension
|
||||
|
||||
// IsEmpty reports whether the Shape contains no points. (Note that the full
|
||||
// polygon is represented as a chain with zero edges.)
|
||||
IsEmpty() bool
|
||||
|
||||
// IsFull reports whether the Shape contains all points on the sphere.
|
||||
IsFull() bool
|
||||
}
|
||||
|
||||
// defaultShapeIsEmpty reports whether this shape contains no points.
|
||||
func defaultShapeIsEmpty(s Shape) bool {
|
||||
return s.NumEdges() == 0 && (!s.HasInterior() || s.NumChains() == 0)
|
||||
}
|
||||
|
||||
// defaultShapeIsFull reports whether this shape contains all points on the sphere.
|
||||
func defaultShapeIsFull(s Shape) bool {
|
||||
return s.NumEdges() == 0 && s.HasInterior() && s.NumChains() > 0
|
||||
}
|
||||
|
||||
// A minimal check for types that should satisfy the Shape interface.
|
||||
|
|
26
vendor/github.com/golang/geo/s2/shapeindex.go
generated
vendored
26
vendor/github.com/golang/geo/s2/shapeindex.go
generated
vendored
|
@ -684,6 +684,22 @@ func (s *ShapeIndex) NumEdges() int {
|
|||
// Shape returns the shape with the given ID, or nil if the shape has been removed from the index.
|
||||
func (s *ShapeIndex) Shape(id int32) Shape { return s.shapes[id] }
|
||||
|
||||
// idForShape returns the id of the given shape in this index, or -1 if it is
|
||||
// not in the index.
|
||||
//
|
||||
// TODO(roberts): Need to figure out an appropriate way to expose this on a Shape.
|
||||
// C++ allows a given S2 type (Loop, Polygon, etc) to be part of multiple indexes.
|
||||
// By having each type extend S2Shape which has an id element, they all inherit their
|
||||
// own id field rather than having to track it themselves.
|
||||
func (s *ShapeIndex) idForShape(shape Shape) int32 {
|
||||
for k, v := range s.shapes {
|
||||
if v == shape {
|
||||
return k
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// Add adds the given shape to the index and returns the assigned ID..
|
||||
func (s *ShapeIndex) Add(shape Shape) int32 {
|
||||
s.shapes[s.nextID] = shape
|
||||
|
@ -696,13 +712,7 @@ func (s *ShapeIndex) Add(shape Shape) int32 {
|
|||
func (s *ShapeIndex) Remove(shape Shape) {
|
||||
// The index updates itself lazily because it is much more efficient to
|
||||
// process additions and removals in batches.
|
||||
// Lookup the id of this shape in the index.
|
||||
id := int32(-1)
|
||||
for k, v := range s.shapes {
|
||||
if v == shape {
|
||||
id = k
|
||||
}
|
||||
}
|
||||
id := s.idForShape(shape)
|
||||
|
||||
// If the shape wasn't found, it's already been removed or was not in the index.
|
||||
if s.shapes[id] == nil {
|
||||
|
@ -723,7 +733,7 @@ func (s *ShapeIndex) Remove(shape Shape) {
|
|||
shapeID: id,
|
||||
hasInterior: shape.HasInterior(),
|
||||
containsTrackerOrigin: shape.ReferencePoint().Contained,
|
||||
edges: make([]Edge, numEdges),
|
||||
edges: make([]Edge, numEdges),
|
||||
}
|
||||
|
||||
for e := 0; e < numEdges; e++ {
|
||||
|
|
7
vendor/github.com/golang/geo/s2/shapeutil.go
generated
vendored
7
vendor/github.com/golang/geo/s2/shapeutil.go
generated
vendored
|
@ -113,7 +113,7 @@ func (r *rangeIterator) refresh() {
|
|||
func referencePointForShape(shape Shape) ReferencePoint {
|
||||
if shape.NumEdges() == 0 {
|
||||
// A shape with no edges is defined to be full if and only if it
|
||||
// contains an empty loop.
|
||||
// contains at least one chain.
|
||||
return OriginReferencePoint(shape.NumChains() > 0)
|
||||
}
|
||||
// Define a "matched" edge as one that can be paired with a corresponding
|
||||
|
@ -156,8 +156,9 @@ func referencePointForShape(shape Shape) ReferencePoint {
|
|||
}
|
||||
}
|
||||
|
||||
// All vertices are balanced, so this polygon is either empty or full. By
|
||||
// convention it is defined to be full if it contains any empty loop.
|
||||
// All vertices are balanced, so this polygon is either empty or full except
|
||||
// for degeneracies. By convention it is defined to be full if it contains
|
||||
// any chain with no edges.
|
||||
for i := 0; i < shape.NumChains(); i++ {
|
||||
if shape.Chain(i).Length == 0 {
|
||||
return OriginReferencePoint(true)
|
||||
|
|
8
vendor/github.com/gorilla/context/.travis.yml
generated
vendored
8
vendor/github.com/gorilla/context/.travis.yml
generated
vendored
|
@ -7,13 +7,13 @@ matrix:
|
|||
- go: 1.4
|
||||
- go: 1.5
|
||||
- go: 1.6
|
||||
- go: 1.7
|
||||
- go: tip
|
||||
allow_failures:
|
||||
- go: tip
|
||||
|
||||
install:
|
||||
- go get golang.org/x/tools/cmd/vet
|
||||
|
||||
script:
|
||||
- go get -t -v ./...
|
||||
- diff -u <(echo -n) <(gofmt -d .)
|
||||
- go tool vet .
|
||||
- go vet $(go list ./... | grep -v /vendor/)
|
||||
- go test -v -race ./...
|
||||
|
|
3
vendor/github.com/gorilla/context/README.md
generated
vendored
3
vendor/github.com/gorilla/context/README.md
generated
vendored
|
@ -4,4 +4,7 @@ context
|
|||
|
||||
gorilla/context is a general purpose registry for global request variables.
|
||||
|
||||
> Note: gorilla/context, having been born well before `context.Context` existed, does not play well
|
||||
> with the shallow copying of the request that [`http.Request.WithContext`](https://golang.org/pkg/net/http/#Request.WithContext) (added to net/http Go 1.7 onwards) performs. You should either use *just* gorilla/context, or moving forward, the new `http.Request.Context()`.
|
||||
|
||||
Read the full documentation here: http://www.gorillatoolkit.org/pkg/context
|
||||
|
|
6
vendor/github.com/gorilla/context/doc.go
generated
vendored
6
vendor/github.com/gorilla/context/doc.go
generated
vendored
|
@ -5,6 +5,12 @@
|
|||
/*
|
||||
Package context stores values shared during a request lifetime.
|
||||
|
||||
Note: gorilla/context, having been born well before `context.Context` existed,
|
||||
does not play well > with the shallow copying of the request that
|
||||
[`http.Request.WithContext`](https://golang.org/pkg/net/http/#Request.WithContext)
|
||||
(added to net/http Go 1.7 onwards) performs. You should either use *just*
|
||||
gorilla/context, or moving forward, the new `http.Request.Context()`.
|
||||
|
||||
For example, a router can set variables extracted from the URL and later
|
||||
application handlers can access those values, or it can be used to store
|
||||
sessions values to be saved at the end of a request. There are several
|
||||
|
|
11
vendor/github.com/gorilla/mux/.travis.yml
generated
vendored
11
vendor/github.com/gorilla/mux/.travis.yml
generated
vendored
|
@ -3,11 +3,12 @@ sudo: false
|
|||
|
||||
matrix:
|
||||
include:
|
||||
- go: 1.5
|
||||
- go: 1.6
|
||||
- go: 1.7
|
||||
- go: 1.8
|
||||
- go: 1.9
|
||||
- go: 1.5.x
|
||||
- go: 1.6.x
|
||||
- go: 1.7.x
|
||||
- go: 1.8.x
|
||||
- go: 1.9.x
|
||||
- go: 1.10.x
|
||||
- go: tip
|
||||
allow_failures:
|
||||
- go: tip
|
||||
|
|
299
vendor/github.com/gorilla/mux/README.md
generated
vendored
299
vendor/github.com/gorilla/mux/README.md
generated
vendored
|
@ -1,5 +1,5 @@
|
|||
gorilla/mux
|
||||
===
|
||||
# gorilla/mux
|
||||
|
||||
[![GoDoc](https://godoc.org/github.com/gorilla/mux?status.svg)](https://godoc.org/github.com/gorilla/mux)
|
||||
[![Build Status](https://travis-ci.org/gorilla/mux.svg?branch=master)](https://travis-ci.org/gorilla/mux)
|
||||
[![Sourcegraph](https://sourcegraph.com/github.com/gorilla/mux/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/mux?badge)
|
||||
|
@ -29,6 +29,7 @@ The name mux stands for "HTTP request multiplexer". Like the standard `http.Serv
|
|||
* [Walking Routes](#walking-routes)
|
||||
* [Graceful Shutdown](#graceful-shutdown)
|
||||
* [Middleware](#middleware)
|
||||
* [Testing Handlers](#testing-handlers)
|
||||
* [Full Example](#full-example)
|
||||
|
||||
---
|
||||
|
@ -178,70 +179,13 @@ s.HandleFunc("/{key}/", ProductHandler)
|
|||
// "/products/{key}/details"
|
||||
s.HandleFunc("/{key}/details", ProductDetailsHandler)
|
||||
```
|
||||
### Listing Routes
|
||||
|
||||
Routes on a mux can be listed using the Router.Walk method—useful for generating documentation:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
func handler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
func main() {
|
||||
r := mux.NewRouter()
|
||||
r.HandleFunc("/", handler)
|
||||
r.HandleFunc("/products", handler).Methods("POST")
|
||||
r.HandleFunc("/articles", handler).Methods("GET")
|
||||
r.HandleFunc("/articles/{id}", handler).Methods("GET", "PUT")
|
||||
r.HandleFunc("/authors", handler).Queries("surname", "{surname}")
|
||||
r.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error {
|
||||
t, err := route.GetPathTemplate()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
qt, err := route.GetQueriesTemplates()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// p will contain regular expression is compatible with regular expression in Perl, Python, and other languages.
|
||||
// for instance the regular expression for path '/articles/{id}' will be '^/articles/(?P<v0>[^/]+)$'
|
||||
p, err := route.GetPathRegexp()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// qr will contain a list of regular expressions with the same semantics as GetPathRegexp,
|
||||
// just applied to the Queries pairs instead, e.g., 'Queries("surname", "{surname}") will return
|
||||
// {"^surname=(?P<v0>.*)$}. Where each combined query pair will have an entry in the list.
|
||||
qr, err := route.GetQueriesRegexp()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m, err := route.GetMethods()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(strings.Join(m, ","), strings.Join(qt, ","), strings.Join(qr, ","), t, p)
|
||||
return nil
|
||||
})
|
||||
http.Handle("/", r)
|
||||
}
|
||||
```
|
||||
|
||||
### Static Files
|
||||
|
||||
Note that the path provided to `PathPrefix()` represents a "wildcard": calling
|
||||
`PathPrefix("/static/").Handler(...)` means that the handler will be passed any
|
||||
request that matches "/static/*". This makes it easy to serve static files with mux:
|
||||
request that matches "/static/\*". This makes it easy to serve static files with mux:
|
||||
|
||||
```go
|
||||