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
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)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue