mirror of
https://github.com/Luzifer/staticmap.git
synced 2024-12-30 01:31:18 +00:00
172 lines
4.9 KiB
Go
172 lines
4.9 KiB
Go
// Copyright 2016 Florian Pigorsch. All rights reserved.
|
|
//
|
|
// Use of this source code is governed by a MIT-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// Package coordsparser is a library for parsing (geographic) coordinates in various string formats
|
|
package coordsparser
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
"strconv"
|
|
)
|
|
|
|
// Parse parses a coordinate string and returns a lat/lng pair or an error
|
|
func Parse(s string) (float64, float64, error) {
|
|
lat, lng, err := ParseD(s)
|
|
if err == nil {
|
|
return lat, lng, nil
|
|
}
|
|
|
|
lat, lng, err = ParseHD(s)
|
|
if err == nil {
|
|
return lat, lng, nil
|
|
}
|
|
|
|
lat, lng, err = ParseHDM(s)
|
|
if err == nil {
|
|
return lat, lng, nil
|
|
}
|
|
|
|
lat, lng, err = ParseHDMS(s)
|
|
if err == nil {
|
|
return lat, lng, nil
|
|
}
|
|
|
|
return 0, 0, fmt.Errorf("Cannot parse coordinates: %s", s)
|
|
}
|
|
|
|
// ParseD parses a coordinate string of the form "D.DDDD D.DDDD" and returns a lat/lng pair or an error
|
|
func ParseD(s string) (float64, float64, error) {
|
|
re := regexp.MustCompile(`^\s*([+-]?[\d\.]+)\s*(,|;|:|\s)\s*([+-]?[\d\.]+)\s*$`)
|
|
|
|
matches := re.FindStringSubmatch(s)
|
|
if matches == nil {
|
|
return 0, 0, fmt.Errorf("Cannot parse 'D' string: %s", s)
|
|
}
|
|
|
|
lat, err := strconv.ParseFloat(matches[1], 64)
|
|
if err != nil || lat < -90 || lat > 90 {
|
|
return 0, 0, fmt.Errorf("Cannot parse 'D' string: %s", s)
|
|
}
|
|
|
|
lng, err := strconv.ParseFloat(matches[3], 64)
|
|
if err != nil || lng < -180 || lng > 180 {
|
|
return 0, 0, fmt.Errorf("Cannot parse 'D' string: %s", s)
|
|
}
|
|
|
|
return lat, lng, nil
|
|
}
|
|
|
|
// ParseHD parses a coordinate string of the form "H D.DDDD H D.DDDD" and returns a lat/lng pair or an error
|
|
func ParseHD(s string) (float64, float64, error) {
|
|
re := regexp.MustCompile(`^\s*([NnSs])\s*([\d\.]+)\s+([EeWw])\s*([\d\.]+)\s*$`)
|
|
|
|
matches := re.FindStringSubmatch(s)
|
|
if matches == nil {
|
|
return 0, 0, fmt.Errorf("Cannot parse 'HD' string: %s", s)
|
|
}
|
|
|
|
lat, err := strconv.ParseFloat(matches[2], 64)
|
|
if err != nil || lat > 90 {
|
|
return 0, 0, fmt.Errorf("Cannot parse 'HD' string: %s", s)
|
|
}
|
|
if matches[1] == "S" || matches[1] == "s" {
|
|
lat = -lat
|
|
}
|
|
|
|
lng, err := strconv.ParseFloat(matches[4], 64)
|
|
if err != nil || lng > 180 {
|
|
return 0, 0, fmt.Errorf("Cannot parse 'HD' string: %s", s)
|
|
}
|
|
if matches[3] == "W" || matches[3] == "w" {
|
|
lng = -lng
|
|
}
|
|
|
|
return lat, lng, nil
|
|
}
|
|
|
|
// ParseHDM parses a coordinate string of the form "H D M.MMM H D M.MMM" and returns a lat/lng pair or an error
|
|
func ParseHDM(s string) (float64, float64, error) {
|
|
re := regexp.MustCompile(`^\s*([NnSs])\s*([\d]+)\s+([\d.]+)\s+([EeWw])\s*([\d]+)\s+([\d.]+)\s*$`)
|
|
|
|
matches := re.FindStringSubmatch(s)
|
|
if matches == nil {
|
|
return 0, 0, fmt.Errorf("Cannot parse 'HDM' string: %s", s)
|
|
}
|
|
|
|
latDeg, err := strconv.ParseFloat(matches[2], 64)
|
|
if err != nil || latDeg > 90 {
|
|
return 0, 0, fmt.Errorf("Cannot parse 'HDM' string: %s", s)
|
|
}
|
|
latMin, err := strconv.ParseFloat(matches[3], 64)
|
|
if err != nil || latMin >= 60 {
|
|
return 0, 0, fmt.Errorf("Cannot parse 'HDM' string: %s", s)
|
|
}
|
|
lat := latDeg + latMin/60.0
|
|
if matches[1] == "S" || matches[1] == "s" {
|
|
lat = -lat
|
|
}
|
|
|
|
lngDeg, err := strconv.ParseFloat(matches[5], 64)
|
|
if err != nil || lngDeg > 180 {
|
|
return 0, 0, fmt.Errorf("Cannot parse 'HDM' string: %s", s)
|
|
}
|
|
lngMin, err := strconv.ParseFloat(matches[6], 64)
|
|
if err != nil || lngMin >= 60 {
|
|
return 0, 0, fmt.Errorf("Cannot parse 'HDM' string: %s", s)
|
|
}
|
|
lng := lngDeg + lngMin/60.0
|
|
if matches[4] == "W" || matches[4] == "w" {
|
|
lng = -lng
|
|
}
|
|
|
|
return lat, lng, nil
|
|
}
|
|
|
|
// ParseHDMS parses a coordinate string of the form "H D M S.SSS H D M S.SSS" and returns a lat/lng pair or an error
|
|
func ParseHDMS(s string) (float64, float64, error) {
|
|
re := regexp.MustCompile(`^\s*([NnSs])\s*([\d]+)\s+([\d]+)\s+([\d.]+)\s+([EeWw])\s*([\d]+)\s+([\d]+)\s+([\d.]+)\s*$`)
|
|
|
|
matches := re.FindStringSubmatch(s)
|
|
if matches == nil {
|
|
return 0, 0, fmt.Errorf("Cannot parse 'HDMS' string: %s", s)
|
|
}
|
|
|
|
latDeg, err := strconv.ParseFloat(matches[2], 64)
|
|
if err != nil || latDeg > 90 {
|
|
return 0, 0, fmt.Errorf("Cannot parse 'HDMS' string: %s", s)
|
|
}
|
|
latMin, err := strconv.ParseFloat(matches[3], 64)
|
|
if err != nil || latMin >= 60 {
|
|
return 0, 0, fmt.Errorf("Cannot parse 'HDMS' string: %s", s)
|
|
}
|
|
latSec, err := strconv.ParseFloat(matches[4], 64)
|
|
if err != nil || latSec >= 60 {
|
|
return 0, 0, fmt.Errorf("Cannot parse 'HDMS' string: %s", s)
|
|
}
|
|
lat := latDeg + latMin/60.0 + latSec/3600.0
|
|
if matches[1] == "S" || matches[1] == "s" {
|
|
lat = -lat
|
|
}
|
|
|
|
lngDeg, err := strconv.ParseFloat(matches[6], 64)
|
|
if err != nil || lngDeg > 180 {
|
|
return 0, 0, fmt.Errorf("Cannot parse 'HDMS' string: %s", s)
|
|
}
|
|
lngMin, err := strconv.ParseFloat(matches[7], 64)
|
|
if err != nil || lngMin >= 60 {
|
|
return 0, 0, fmt.Errorf("Cannot parse 'HDMS' string: %s", s)
|
|
}
|
|
lngSec, err := strconv.ParseFloat(matches[8], 64)
|
|
if err != nil || lngSec >= 60 {
|
|
return 0, 0, fmt.Errorf("Cannot parse 'HDMS' string: %s", s)
|
|
}
|
|
lng := lngDeg + lngMin/60.0 + lngSec/3600.0
|
|
if matches[5] == "W" || matches[5] == "w" {
|
|
lng = -lng
|
|
}
|
|
|
|
return lat, lng, nil
|
|
}
|