github.com/pavlo67/common@v0.5.3/common/geolib/point.go (about)

     1  package geolib
     2  
     3  import (
     4  	"math"
     5  
     6  	"github.com/pavlo67/common/common/mathlib"
     7  
     8  	geo "github.com/kellydunn/golang-geo"
     9  	"github.com/pavlo67/common/common/mathlib/plane"
    10  	// geo "github.com/billups/golang-geo"
    11  )
    12  
    13  const DistanceEps = 1.
    14  
    15  type Point struct {
    16  	Lat, Lon Degrees
    17  }
    18  
    19  type Direction struct {
    20  	Bearing
    21  	Distance float64
    22  }
    23  
    24  func (dir Direction) Moving() plane.Point2 {
    25  	return dir.Bearing.Point(dir.Distance)
    26  }
    27  
    28  const StepDistanceEps = 1e-2
    29  
    30  // https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
    31  
    32  func (p Point) Tile(zoom int) Tile {
    33  	// TODO!!! check zoom
    34  
    35  	tile := Tile{Zoom: zoom}
    36  
    37  	n := math.Exp2(float64(zoom))
    38  
    39  	tile.X = int(math.Floor(float64((p.Lon+180.0)/360.0) * n))
    40  	if float64(tile.X) >= n {
    41  		tile.X = int(n - 1)
    42  	}
    43  
    44  	latAngle := float64(p.Lat) * math.Pi / 180
    45  	tile.Y = int(math.Floor(n * (1 - math.Log(math.Tan(latAngle)+1/math.Cos(latAngle))/math.Pi) / 2))
    46  
    47  	// log.Print(p, zoom, tile)
    48  
    49  	return tile
    50  }
    51  
    52  func (p Point) MovedBeared(bearing Bearing, moving plane.Point2) Point {
    53  	var geoPointStepped Point
    54  
    55  	if moving.Radius() <= StepDistanceEps {
    56  		geoPointStepped = p
    57  
    58  	} else {
    59  		stepBeared := moving.RotateByAngle(bearing.XToYAngleFromOy())
    60  		geoPointStepped = p.MovedAt(stepBeared)
    61  
    62  	}
    63  
    64  	return Point{
    65  		Degrees(mathlib.Round(float64(geoPointStepped.Lat), 6)),
    66  		Degrees(mathlib.Round(float64(geoPointStepped.Lon), 6))}
    67  }
    68  
    69  func (p Point) Geo() geo.Point {
    70  	return *geo.NewPoint(float64(p.Lat), float64(p.Lon))
    71  }
    72  
    73  func (p Point) MovedAt(moving plane.Point2) Point {
    74  	if moving.X == 0 && moving.Y == 0 {
    75  		return p
    76  	}
    77  
    78  	dxKm, dyKm := moving.X*0.001, moving.Y*0.001
    79  
    80  	bearing := BearingFromPoint(plane.Point2{dxKm, dyKm})
    81  
    82  	geoPoint := p.Geo()
    83  
    84  	// geoPoint.PointAtDistanceAndBearing() requires distance in kilometers
    85  	geoPointNew := geoPoint.PointAtDistanceAndBearing(math.Sqrt(dxKm*dxKm+dyKm*dyKm), float64(bearing))
    86  
    87  	return Point{Degrees(geoPointNew.Lat()), Degrees(geoPointNew.Lng())}
    88  }
    89  
    90  func (p Point) PointAtDirection(dir Direction) Point {
    91  	geoPoint := p.Geo()
    92  
    93  	// geoPoint.PointAtDistanceAndBearing() requires distance in kilometers
    94  	geoPointNew := geoPoint.PointAtDistanceAndBearing(dir.Distance*0.001, float64(dir.Bearing))
    95  
    96  	return Point{Degrees(geoPointNew.Lat()), Degrees(geoPointNew.Lng())}
    97  }
    98  
    99  func (p Point) BearingTo(p1 Point) Bearing {
   100  	geoPoint, geoPoint1 := p.Geo(), p1.Geo()
   101  	return Bearing(geoPoint.BearingTo(&geoPoint1))
   102  }
   103  
   104  func (p Point) DistanceTo(p1 Point) float64 {
   105  	geoPoint, geoPoint1 := p.Geo(), p1.Geo()
   106  
   107  	// geoPoint.GreatCircleDistance(&geoPoint1) returns distance in kilometers
   108  	return 1000 * geoPoint.GreatCircleDistance(&geoPoint1)
   109  }
   110  
   111  func (p Point) DirectionTo(p1 Point) Direction {
   112  	geoPoint, geoPoint1 := p.Geo(), p1.Geo()
   113  	return Direction{
   114  		Bearing(geoPoint.BearingTo(&geoPoint1)),
   115  		1000 * geoPoint.GreatCircleDistance(&geoPoint1),
   116  	}
   117  }
   118  
   119  func (geoPoint Point) MissFrom(geoPointReal Point) (missPoint plane.Point2, miss float64, bearing Bearing) {
   120  	missDirection := geoPointReal.DirectionTo(geoPoint)
   121  
   122  	return missDirection.Moving(), missDirection.Distance, missDirection.Bearing
   123  }