Working auth and photo json endpoint
Signed-off-by: Kris Nóva <kris@nivenly.com>
This commit is contained in:
parent
ef275f97f4
commit
e4323b6047
2032 changed files with 821464 additions and 52 deletions
2
vendor/github.com/google/open-location-code/go/.gitignore
generated
vendored
Normal file
2
vendor/github.com/google/open-location-code/go/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
*.swp
|
||||
olc-fuzz.zip
|
202
vendor/github.com/google/open-location-code/go/LICENSE
generated
vendored
Normal file
202
vendor/github.com/google/open-location-code/go/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,202 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
39
vendor/github.com/google/open-location-code/go/README.md
generated
vendored
Normal file
39
vendor/github.com/google/open-location-code/go/README.md
generated
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
[](http://godoc.org/github.com/google/open-location-code/go)
|
||||
|
||||
# Formatting
|
||||
|
||||
Go files must be formatted with [gofmt](https://golang.org/cmd/gofmt/), and the
|
||||
tests will check that this is the case. If the files are not correctly
|
||||
formatted, the tests will fail.
|
||||
|
||||
You can format your files by running:
|
||||
|
||||
gofmt -w -s .
|
||||
|
||||
# Testing
|
||||
|
||||
Run the unit tests from within the `go` directory with:
|
||||
|
||||
```
|
||||
go test . -v
|
||||
```
|
||||
|
||||
To also run the benchmark tests, run:
|
||||
|
||||
```
|
||||
go test -bench=. . -v
|
||||
```
|
||||
|
||||
## Test with Go-Fuzz
|
||||
|
||||
go get github.com/dvyukov/go-fuzz/...
|
||||
|
||||
go generate github.com/google/open-location-code/go
|
||||
|
||||
go-fuzz-build github.com/google/open-location-code/go
|
||||
go-fuzz -bin=./olc-fuzz.zip -workdir=/tmp/olc-fuzz
|
||||
|
||||
# Install
|
||||
|
||||
go get github.com/google/open-location-code/go
|
||||
|
101
vendor/github.com/google/open-location-code/go/decode.go
generated
vendored
Normal file
101
vendor/github.com/google/open-location-code/go/decode.go
generated
vendored
Normal file
|
@ -0,0 +1,101 @@
|
|||
// Copyright 2015 Tamás Gulácsi. 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 olc
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Decode decodes an Open Location Code into the location coordinates.
|
||||
// Returns a CodeArea object that includes the coordinates of the bounding
|
||||
// box - the lower left, center and upper right.
|
||||
//
|
||||
// To avoid underflow errors, the precision is limited to 15 digits.
|
||||
// Longer codes are allowed, but only the first 15 is decoded.
|
||||
func Decode(code string) (CodeArea, error) {
|
||||
var area CodeArea
|
||||
if err := CheckFull(code); err != nil {
|
||||
return area, err
|
||||
}
|
||||
// Strip out separator character (we've already established the code is
|
||||
// valid so the maximum is one), padding characters and convert to upper
|
||||
// case.
|
||||
code = StripCode(code)
|
||||
if len(code) < 2 {
|
||||
return area, errors.New("code too short")
|
||||
}
|
||||
// Initialise the values for each section. We work them out as integers and
|
||||
// convert them to floats at the end.
|
||||
normalLat := -latMax * pairPrecision
|
||||
normalLng := -lngMax * pairPrecision
|
||||
extraLat := 0
|
||||
extraLng := 0
|
||||
// How many digits do we have to process?
|
||||
digits := pairCodeLen
|
||||
if len(code) < digits {
|
||||
digits = len(code)
|
||||
}
|
||||
// Define the place value for the most significant pair.
|
||||
pv := pairFPV
|
||||
for i := 0; i < digits-1; i += 2 {
|
||||
normalLat += strings.IndexByte(Alphabet, code[i]) * pv
|
||||
normalLng += strings.IndexByte(Alphabet, code[i+1]) * pv
|
||||
if i < digits-2 {
|
||||
pv /= encBase
|
||||
}
|
||||
}
|
||||
// Convert the place value to a float in degrees.
|
||||
latPrecision := float64(pv) / pairPrecision
|
||||
lngPrecision := float64(pv) / pairPrecision
|
||||
// Process any extra precision digits.
|
||||
if len(code) > pairCodeLen {
|
||||
// Initialise the place values for the grid.
|
||||
rowpv := gridLatFPV
|
||||
colpv := gridLngFPV
|
||||
// How many digits do we have to process?
|
||||
digits = maxCodeLen
|
||||
if len(code) < maxCodeLen {
|
||||
digits = len(code)
|
||||
}
|
||||
for i := pairCodeLen; i < digits; i++ {
|
||||
dval := strings.IndexByte(Alphabet, code[i])
|
||||
row := dval / gridCols
|
||||
col := dval % gridCols
|
||||
extraLat += row * rowpv
|
||||
extraLng += col * colpv
|
||||
if i < digits-1 {
|
||||
rowpv /= gridRows
|
||||
colpv /= gridCols
|
||||
}
|
||||
}
|
||||
// Adjust the precisions from the integer values to degrees.
|
||||
latPrecision = float64(rowpv) / finalLatPrecision
|
||||
lngPrecision = float64(colpv) / finalLngPrecision
|
||||
}
|
||||
// Merge the values from the normal and extra precision parts of the code.
|
||||
// Everything is ints so they all need to be cast to floats.
|
||||
lat := float64(normalLat)/pairPrecision + float64(extraLat)/finalLatPrecision
|
||||
lng := float64(normalLng)/pairPrecision + float64(extraLng)/finalLngPrecision
|
||||
// Round everthing off to 14 places.
|
||||
return CodeArea{
|
||||
LatLo: math.Round(lat*1e14) / 1e14,
|
||||
LngLo: math.Round(lng*1e14) / 1e14,
|
||||
LatHi: math.Round((lat+latPrecision)*1e14) / 1e14,
|
||||
LngHi: math.Round((lng+lngPrecision)*1e14) / 1e14,
|
||||
Len: len(code),
|
||||
}, nil
|
||||
}
|
123
vendor/github.com/google/open-location-code/go/encode.go
generated
vendored
Normal file
123
vendor/github.com/google/open-location-code/go/encode.go
generated
vendored
Normal file
|
@ -0,0 +1,123 @@
|
|||
// Copyright 2015 Tamás Gulácsi. 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 olc
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrShort indicates the provided code was a short code.
|
||||
ErrShort = errors.New("short code")
|
||||
// ErrNotShort indicates the provided code was not a short code.
|
||||
ErrNotShort = errors.New("not short code")
|
||||
)
|
||||
|
||||
const (
|
||||
minTrimmableCodeLen = 6
|
||||
)
|
||||
|
||||
// Encode a location into an Open Location Code.
|
||||
//
|
||||
// Produces a code of the specified codeLen, or the default length if
|
||||
// codeLen < 8;
|
||||
// if codeLen is odd, it is incremented to be even.
|
||||
//
|
||||
// latitude is signed decimal degrees. Will be clipped to the range -90 to 90.
|
||||
// longitude is signed decimal degrees. Will be normalised to the range -180 to 180.
|
||||
// The length determines the accuracy of the code. The default length is
|
||||
// 10 characters, returning a code of approximately 13.5x13.5 meters. Longer
|
||||
// codes represent smaller areas, but lengths > 14 are sub-centimetre and so
|
||||
// 11 or 12 are probably the limit of useful codes.
|
||||
func Encode(lat, lng float64, codeLen int) string {
|
||||
if codeLen <= 0 {
|
||||
codeLen = pairCodeLen
|
||||
} else if codeLen < 2 {
|
||||
codeLen = 2
|
||||
} else if codeLen < pairCodeLen && codeLen%2 == 1 {
|
||||
codeLen++
|
||||
} else if codeLen > maxCodeLen {
|
||||
codeLen = maxCodeLen
|
||||
}
|
||||
// Clip the latitude. Normalise the longitude.
|
||||
lat, lng = clipLatitude(lat), normalizeLng(lng)
|
||||
// Latitude 90 needs to be adjusted to be just less, so the returned code
|
||||
// can also be decoded.
|
||||
if lat == latMax {
|
||||
lat = normalizeLat(lat - computeLatPrec(codeLen))
|
||||
}
|
||||
// Use a char array so we can build it up from the end digits, without having
|
||||
// to keep reallocating strings.
|
||||
var code [15]byte
|
||||
|
||||
// Compute the code.
|
||||
// This approach converts each value to an integer after multiplying it by
|
||||
// the final precision. This allows us to use only integer operations, so
|
||||
// avoiding any accumulation of floating point representation errors.
|
||||
|
||||
// Multiply values by their precision and convert to positive.
|
||||
// Note: Go requires rounding before truncating to ensure precision!
|
||||
var latVal int64 = int64(math.Round((lat+latMax)*finalLatPrecision*1e6) / 1e6)
|
||||
var lngVal int64 = int64(math.Round((lng+lngMax)*finalLngPrecision*1e6) / 1e6)
|
||||
|
||||
pos := maxCodeLen - 1
|
||||
// Compute the grid part of the code if necessary.
|
||||
if codeLen > pairCodeLen {
|
||||
for i := 0; i < gridCodeLen; i++ {
|
||||
latDigit := latVal % int64(gridRows)
|
||||
lngDigit := lngVal % int64(gridCols)
|
||||
ndx := latDigit*gridCols + lngDigit
|
||||
code[pos] = Alphabet[ndx]
|
||||
pos -= 1
|
||||
latVal /= int64(gridRows)
|
||||
lngVal /= int64(gridCols)
|
||||
}
|
||||
} else {
|
||||
latVal /= gridLatFullValue
|
||||
lngVal /= gridLngFullValue
|
||||
}
|
||||
pos = pairCodeLen - 1
|
||||
// Compute the pair section of the code.
|
||||
for i := 0; i < pairCodeLen/2; i++ {
|
||||
latNdx := latVal % int64(encBase)
|
||||
lngNdx := lngVal % int64(encBase)
|
||||
code[pos] = Alphabet[lngNdx]
|
||||
pos -= 1
|
||||
code[pos] = Alphabet[latNdx]
|
||||
pos -= 1
|
||||
latVal /= int64(encBase)
|
||||
lngVal /= int64(encBase)
|
||||
}
|
||||
|
||||
// If we don't need to pad the code, return the requested section.
|
||||
if codeLen >= sepPos {
|
||||
return string(code[:sepPos]) + string(Separator) + string(code[sepPos:codeLen])
|
||||
}
|
||||
// Pad and return the code.
|
||||
return string(code[:codeLen]) + strings.Repeat(string(Padding), sepPos-codeLen) + string(Separator)
|
||||
}
|
||||
|
||||
// computeLatPrec computes the precision value for a given code length.
|
||||
// Lengths <= 10 have the same precision for latitude and longitude,
|
||||
// but lengths > 10 have different precisions due to the grid method
|
||||
// having fewer columns than rows.
|
||||
func computeLatPrec(codeLen int) float64 {
|
||||
if codeLen <= pairCodeLen {
|
||||
return math.Pow(float64(encBase), math.Floor(float64(codeLen/-2+2)))
|
||||
}
|
||||
return math.Pow(float64(encBase), -3) / math.Pow(float64(gridRows), float64(codeLen-pairCodeLen))
|
||||
}
|
3
vendor/github.com/google/open-location-code/go/go.mod
generated
vendored
Normal file
3
vendor/github.com/google/open-location-code/go/go.mod
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
module github.com/google/open-location-code/go
|
||||
|
||||
go 1.12
|
0
vendor/github.com/google/open-location-code/go/go.sum
generated
vendored
Normal file
0
vendor/github.com/google/open-location-code/go/go.sum
generated
vendored
Normal file
240
vendor/github.com/google/open-location-code/go/olc.go
generated
vendored
Normal file
240
vendor/github.com/google/open-location-code/go/olc.go
generated
vendored
Normal file
|
@ -0,0 +1,240 @@
|
|||
// Copyright 2015 Tamás Gulácsi. 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 olc implements the Open Location Code algorithm to convert latitude and longitude coordinates
|
||||
// into a shorter sequence of letters and numbers.
|
||||
//
|
||||
// The aim is to provide something that can be used like an address in locations that lack them, because
|
||||
// the streets are unnamed.
|
||||
//
|
||||
// Codes represent areas, and the size of the area depends on the length of the code. The typical code
|
||||
// length is 10 digits, and represents an area of 1/8000 x 1/8000 degrees, or roughly 13.75 x 13.75 meters.
|
||||
//
|
||||
// See https://github.com/google/open-location-code.
|
||||
package olc
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
// Separator is the character that separates the two parts of location code.
|
||||
Separator = '+'
|
||||
// Padding is the optional (left) padding character.
|
||||
Padding = '0'
|
||||
|
||||
// Alphabet is the set of valid encoding characters.
|
||||
Alphabet = "23456789CFGHJMPQRVWX"
|
||||
encBase = len(Alphabet)
|
||||
|
||||
maxCodeLen = 15
|
||||
pairCodeLen = 10
|
||||
gridCodeLen = maxCodeLen - pairCodeLen
|
||||
gridCols = 4
|
||||
gridRows = 5
|
||||
// First place value of the pairs (if the last pair value is 1). encBase^(pairs-1)
|
||||
pairFPV = 160000
|
||||
// Precision of the pair part of the code, in 1/degrees.
|
||||
pairPrecision = 8000
|
||||
// Full value of the latitude grid - gridRows**gridCodeLen.
|
||||
gridLatFullValue = 3125
|
||||
// Full value of the longitude grid - gridCols**gridCodeLen.
|
||||
gridLngFullValue = 1024
|
||||
// First place value of the latitude grid (if the last place is 1). gridRows^(gridCodeLen - 1)
|
||||
gridLatFPV = gridLatFullValue / gridRows
|
||||
// First place value of the longitude grid (if the last place is 1). gridCols^(gridCodeLen - 1)
|
||||
gridLngFPV = gridLngFullValue / gridCols
|
||||
// Latitude precision of a full length code. pairPrecision * gridRows**gridCodeLen
|
||||
finalLatPrecision = pairPrecision * gridLatFullValue
|
||||
// Longitude precision of a full length code. pairPrecision * gridCols**gridCodeLen
|
||||
finalLngPrecision = pairPrecision * gridLngFullValue
|
||||
|
||||
latMax = 90
|
||||
lngMax = 180
|
||||
|
||||
sepPos = 8
|
||||
)
|
||||
|
||||
// CodeArea is the area represented by a location code.
|
||||
type CodeArea struct {
|
||||
LatLo, LngLo, LatHi, LngHi float64
|
||||
Len int
|
||||
}
|
||||
|
||||
// Center returns the (lat,lng) of the center of the area.
|
||||
func (area CodeArea) Center() (lat, lng float64) {
|
||||
return math.Min(area.LatLo+(area.LatHi-area.LatLo)/2, latMax),
|
||||
math.Min(area.LngLo+(area.LngHi-area.LngLo)/2, lngMax)
|
||||
}
|
||||
|
||||
// Check checks whether the passed string is a valid OLC code.
|
||||
// It could be a full code (8FVC9G8F+6W), a padded code (8FVC0000+) or a code fragment (9G8F+6W).
|
||||
func Check(code string) error {
|
||||
if code == "" || len(code) == 1 && code[0] == Separator {
|
||||
return errors.New("empty code")
|
||||
}
|
||||
n := len(code)
|
||||
firstSep, firstPad := -1, -1
|
||||
for i, r := range code {
|
||||
if firstPad != -1 {
|
||||
// Open Location Codes with less than eight digits can be suffixed with zeros with a "+" used as the final character. Zeros may not be followed by any other digit.
|
||||
switch r {
|
||||
case Padding:
|
||||
continue
|
||||
case Separator:
|
||||
if firstSep != -1 {
|
||||
return fmt.Errorf("extraneous separator @%d", i)
|
||||
}
|
||||
firstSep = i
|
||||
if n-1 == i {
|
||||
continue
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("%c after zero @%d", r, i)
|
||||
}
|
||||
|
||||
if '2' <= r && r <= '9' {
|
||||
continue
|
||||
}
|
||||
switch r {
|
||||
case 'C', 'F', 'G', 'H', 'J', 'M', 'P', 'Q', 'R', 'V', 'W', 'X',
|
||||
// Processing of Open Location Codes must be case insensitive.
|
||||
'c', 'f', 'g', 'h', 'j', 'm', 'p', 'q', 'r', 'v', 'w', 'x':
|
||||
continue
|
||||
case Separator:
|
||||
// In addition to the above characters, a full Open Location Code can include a single "+" as a separator after the eighth digit.
|
||||
if firstSep != -1 {
|
||||
return fmt.Errorf("extra separator seen @%d", i)
|
||||
}
|
||||
if i > sepPos || i%2 == 1 {
|
||||
return fmt.Errorf("separator in illegal position @%d", i)
|
||||
}
|
||||
firstSep = i
|
||||
case Padding:
|
||||
if i == 0 {
|
||||
return errors.New("shouldn't start with padding character")
|
||||
}
|
||||
firstPad = i
|
||||
default:
|
||||
return fmt.Errorf("invalid char %c @%d", r, i)
|
||||
}
|
||||
}
|
||||
if firstSep == -1 {
|
||||
return errors.New("missing separator")
|
||||
}
|
||||
if n-firstSep-1 == 1 {
|
||||
return fmt.Errorf("only one char (%q) after separator", code[firstSep+1:])
|
||||
}
|
||||
if firstPad != -1 {
|
||||
if firstSep < sepPos {
|
||||
return errors.New("short codes cannot have padding")
|
||||
}
|
||||
if len(code)-firstPad-1%2 == 1 {
|
||||
return errors.New("odd number of padding chars")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckShort checks whether the passed string is a valid short code.
|
||||
// If it is valid full code, then it returns ErrNotShort.
|
||||
func CheckShort(code string) error {
|
||||
if err := Check(code); err != nil {
|
||||
return err
|
||||
}
|
||||
if i := strings.IndexByte(code, Separator); i >= 0 && i < sepPos {
|
||||
return nil
|
||||
}
|
||||
return ErrNotShort
|
||||
}
|
||||
|
||||
// CheckFull checks whether the passed string is a valid full code.
|
||||
// If it is short, it returns ErrShort.
|
||||
func CheckFull(code string) error {
|
||||
if err := CheckShort(code); err == nil {
|
||||
return ErrShort
|
||||
} else if err != ErrNotShort {
|
||||
return err
|
||||
}
|
||||
if firstLat := strings.IndexByte(Alphabet, upper(code[0])) * encBase; firstLat >= latMax*2 {
|
||||
return errors.New("latitude outside range")
|
||||
}
|
||||
if len(code) == 1 {
|
||||
return nil
|
||||
}
|
||||
if firstLong := strings.IndexByte(Alphabet, upper(code[1])) * encBase; firstLong >= lngMax*2 {
|
||||
return errors.New("longitude outside range")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func upper(b byte) byte {
|
||||
if 'c' <= b && b <= 'x' {
|
||||
return b + 'C' - 'c'
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// StripCode strips the padding and separator characters from the code.
|
||||
//
|
||||
// The code is truncated to the first 15 digits, as Decode won't use more,
|
||||
// to avoid underflow errors.
|
||||
func StripCode(code string) string {
|
||||
code = strings.Map(
|
||||
func(r rune) rune {
|
||||
if r == Separator || r == Padding {
|
||||
return -1
|
||||
}
|
||||
return rune(upper(byte(r)))
|
||||
},
|
||||
code)
|
||||
if len(code) > maxCodeLen {
|
||||
return code[:maxCodeLen]
|
||||
}
|
||||
return code
|
||||
}
|
||||
|
||||
// Because the OLC codes are an area, they can't start at 180 degrees, because they would then have something > 180 as their upper bound.
|
||||
// Basically, what you have to do is normalize the longitude - so you need to change 180 degrees to -180 degrees.
|
||||
func normalize(value, max float64) float64 {
|
||||
for value < -max {
|
||||
value += 2 * max
|
||||
}
|
||||
for value >= max {
|
||||
value -= 2 * max
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
// clipLatitude forces the latitude into the valid range.
|
||||
func clipLatitude(lat float64) float64 {
|
||||
if lat > latMax {
|
||||
return latMax
|
||||
}
|
||||
if lat < -latMax {
|
||||
return -latMax
|
||||
}
|
||||
return lat
|
||||
}
|
||||
|
||||
func normalizeLat(value float64) float64 {
|
||||
return normalize(value, latMax)
|
||||
}
|
||||
|
||||
func normalizeLng(value float64) float64 {
|
||||
return normalize(value, lngMax)
|
||||
}
|
42
vendor/github.com/google/open-location-code/go/olc_gofuzz.go
generated
vendored
Normal file
42
vendor/github.com/google/open-location-code/go/olc_gofuzz.go
generated
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
// +build gofuzz
|
||||
|
||||
// Copyright 2015 Tamás Gulácsi. 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 olc
|
||||
|
||||
//go:generate go run corpus/gen.go -test-data=../test_data -dest=corpus
|
||||
|
||||
// Fuzz usage:
|
||||
// go get github.com/dvyukov/go-fuzz/...
|
||||
//
|
||||
// go-fuzz-build github.com/google/open-location-code/go && go-fuzz -bin=./olc-fuzz.zip -workdir=/tmp/olc-fuzz
|
||||
func Fuzz(data []byte) int {
|
||||
code := string(data)
|
||||
if err := Check(code); err != nil {
|
||||
return 0
|
||||
}
|
||||
area, err := Decode(code)
|
||||
if err != nil {
|
||||
return 2
|
||||
}
|
||||
if _, err = Decode(Encode(area.LatLo, area.LngLo, len(code))); err != nil {
|
||||
return 2
|
||||
}
|
||||
if _, err = Decode(Encode(area.LatHi, area.LngHi, len(code))); err != nil {
|
||||
return 2
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
120
vendor/github.com/google/open-location-code/go/shorten.go
generated
vendored
Normal file
120
vendor/github.com/google/open-location-code/go/shorten.go
generated
vendored
Normal file
|
@ -0,0 +1,120 @@
|
|||
package olc
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// MinTrimmableCodeLen is the minimum length of a code that is able to be shortened.
|
||||
const MinTrimmableCodeLen = 6
|
||||
|
||||
var (
|
||||
pairResolutions = [...]float64{20.0, 1.0, .05, .0025, .000125}
|
||||
)
|
||||
|
||||
// Shorten removes characters from the start of an OLC code.
|
||||
//
|
||||
// This uses a reference location to determine how many initial characters
|
||||
// can be removed from the OLC code. The number of characters that can be
|
||||
// removed depends on the distance between the code center and the reference
|
||||
// location.
|
||||
//
|
||||
// The minimum number of characters that will be removed is four. At most eight
|
||||
// characters will be removed.
|
||||
//
|
||||
// The reference location must be within 50% of the maximum range. This ensures
|
||||
// that the shortened code will be able to be recovered using slightly different
|
||||
// locations.
|
||||
func Shorten(code string, lat, lng float64) (string, error) {
|
||||
if err := CheckFull(code); err != nil {
|
||||
return code, err
|
||||
}
|
||||
if strings.IndexByte(code, Padding) >= 0 {
|
||||
return code, errors.New("cannot shorten padded code")
|
||||
}
|
||||
code = strings.ToUpper(code)
|
||||
area, err := Decode(code)
|
||||
if err != nil {
|
||||
return code, err
|
||||
}
|
||||
if area.Len < MinTrimmableCodeLen {
|
||||
return code, fmt.Errorf("code length must be at least %d", MinTrimmableCodeLen)
|
||||
}
|
||||
|
||||
lat, lng = clipLatitude(lat), normalizeLng(lng)
|
||||
|
||||
// How close are the latitude and longitude to the code center.
|
||||
centerLat, centerLng := area.Center()
|
||||
distance := math.Max(math.Abs(centerLat-lat), math.Abs(centerLng-lng))
|
||||
|
||||
for i := len(pairResolutions) - 2; i >= 1; i-- {
|
||||
// Check if we're close enough to shorten. The range must be less than 1/2
|
||||
// the resolution to shorten at all, and we want to allow some safety, so
|
||||
// use 0.3 instead of 0.5 as a multiplier.
|
||||
if distance < pairResolutions[i]*0.3 {
|
||||
// Trim it.
|
||||
return code[(i+1)*2:], nil
|
||||
}
|
||||
}
|
||||
return code, nil
|
||||
}
|
||||
|
||||
// RecoverNearest recovers the nearest matching code to a specified location.
|
||||
//
|
||||
// Given a short Open Location Code with from four to eight digits missing,
|
||||
// this recovers the nearest matching full code to the specified location.
|
||||
func RecoverNearest(code string, lat, lng float64) (string, error) {
|
||||
// Return uppercased code if a full code was passed.
|
||||
if err := CheckFull(code); err == nil {
|
||||
return strings.ToUpper(code), nil
|
||||
}
|
||||
// Return error if not a short code
|
||||
if err := CheckShort(code); err != nil {
|
||||
return code, ErrNotShort
|
||||
}
|
||||
// Ensure that latitude and longitude are valid.
|
||||
lat, lng = clipLatitude(lat), normalizeLng(lng)
|
||||
|
||||
// Clean up the passed code.
|
||||
code = strings.ToUpper(code)
|
||||
|
||||
// Compute the number of digits we need to recover.
|
||||
padLen := sepPos - strings.IndexByte(code, Separator)
|
||||
|
||||
// The resolution (height and width) of the padded area in degrees.
|
||||
resolution := math.Pow(20, float64(2-(padLen/2)))
|
||||
|
||||
// Distance from the center to an edge (in degrees).
|
||||
halfRes := float64(resolution) / 2
|
||||
|
||||
// Use the reference location to pad the supplied short code and decode it.
|
||||
area, err := Decode(Encode(lat, lng, 0)[:padLen] + code)
|
||||
if err != nil {
|
||||
return code, err
|
||||
}
|
||||
|
||||
// How many degrees latitude is the code from the reference? If it is more
|
||||
// than half the resolution, we need to move it south or north but keep it
|
||||
// within -90 to 90 degrees.
|
||||
centerLat, centerLng := area.Center()
|
||||
if lat+halfRes < centerLat && centerLat-resolution >= -latMax {
|
||||
// If the proposed code is more than half a cell north of the reference location,
|
||||
// it's too far, and the best match will be one cell south.
|
||||
centerLat -= resolution
|
||||
} else if lat-halfRes > centerLat && centerLat+resolution <= latMax {
|
||||
// If the proposed code is more than half a cell south of the reference location,
|
||||
// it's too far, and the best match will be one cell north.
|
||||
centerLat += resolution
|
||||
}
|
||||
|
||||
// How many degrees longitude is the code from the reference?
|
||||
if lng+halfRes < centerLng {
|
||||
centerLng -= resolution
|
||||
} else if lng-halfRes > centerLng {
|
||||
centerLng += resolution
|
||||
}
|
||||
|
||||
return Encode(centerLat, centerLng, area.Len), nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue