2525// Package geographiclib is a wrapper around the GeographicLib library.
2626package geographiclib
2727
28- // #cgo CXXFLAGS: -std=c++14
29- // #cgo LDFLAGS: -lm
30- //
31- // #include "geodesic.h"
32- // #include "geographiclib.h"
33- import "C"
34-
35- import (
36- "math"
37-
38- "github.com/golang/geo/s1"
39- "github.com/golang/geo/s2"
40- )
41-
4228var (
4329 // WGS84Spheroid represents the default WGS84 ellipsoid.
4430 WGS84Spheroid = NewSpheroid (6378137 , 1 / 298.257223563 )
4733// Spheroid is an object that can perform geodesic operations
4834// on a given spheroid.
4935type Spheroid struct {
50- cRepr C.struct_geod_geodesic
5136 Radius float64
5237 Flattening float64
5338 SphereRadius float64
@@ -61,90 +46,5 @@ func NewSpheroid(radius float64, flattening float64) *Spheroid {
6146 Flattening : flattening ,
6247 SphereRadius : (radius * 2 + minorAxis ) / 3 ,
6348 }
64- C .geod_init (& s .cRepr , C .double (radius ), C .double (flattening ))
6549 return s
6650}
67-
68- // Inverse solves the geodetic inverse problem on the given spheroid
69- // (https://en.wikipedia.org/wiki/Geodesy#Geodetic_problems).
70- // Returns s12 (distance in meters), az1 (azimuth at point 1) and az2 (azimuth at point 2).
71- func (s * Spheroid ) Inverse (a , b s2.LatLng ) (s12 , az1 , az2 float64 ) {
72- var retS12 , retAZ1 , retAZ2 C.double
73- C .geod_inverse (
74- & s .cRepr ,
75- C .double (a .Lat .Degrees ()),
76- C .double (a .Lng .Degrees ()),
77- C .double (b .Lat .Degrees ()),
78- C .double (b .Lng .Degrees ()),
79- & retS12 ,
80- & retAZ1 ,
81- & retAZ2 ,
82- )
83- return float64 (retS12 ), float64 (retAZ1 ), float64 (retAZ2 )
84- }
85-
86- // InverseBatch computes the sum of the length of the lines represented
87- // by the line of points.
88- // This is intended for use for LineStrings. LinearRings/Polygons should use "AreaAndPerimeter".
89- // Returns the sum of the s12 (distance in meters) units.
90- func (s * Spheroid ) InverseBatch (points []s2.Point ) float64 {
91- lats := make ([]C.double , len (points ))
92- lngs := make ([]C.double , len (points ))
93- for i , p := range points {
94- latlng := s2 .LatLngFromPoint (p )
95- lats [i ] = C .double (latlng .Lat .Degrees ())
96- lngs [i ] = C .double (latlng .Lng .Degrees ())
97- }
98- var result C.double
99- C .CR_GEOGRAPHICLIB_InverseBatch (
100- & s .cRepr ,
101- & lats [0 ],
102- & lngs [0 ],
103- C .int (len (points )),
104- & result ,
105- )
106- return float64 (result )
107- }
108-
109- // AreaAndPerimeter computes the area and perimeter of a polygon on a given spheroid.
110- // The points must never be duplicated (i.e. do not include the "final" point of a Polygon LinearRing).
111- // Area is in meter^2, Perimeter is in meters.
112- func (s * Spheroid ) AreaAndPerimeter (points []s2.Point ) (area float64 , perimeter float64 ) {
113- lats := make ([]C.double , len (points ))
114- lngs := make ([]C.double , len (points ))
115- for i , p := range points {
116- latlng := s2 .LatLngFromPoint (p )
117- lats [i ] = C .double (latlng .Lat .Degrees ())
118- lngs [i ] = C .double (latlng .Lng .Degrees ())
119- }
120- var areaDouble , perimeterDouble C.double
121- C .geod_polygonarea (
122- & s .cRepr ,
123- & lats [0 ],
124- & lngs [0 ],
125- C .int (len (points )),
126- & areaDouble ,
127- & perimeterDouble ,
128- )
129- return float64 (areaDouble ), float64 (perimeterDouble )
130- }
131-
132- // Project returns computes the location of the projected point.
133- //
134- // Using the direct geodesic problem from GeographicLib (Karney 2013).
135- func (s * Spheroid ) Project (point s2.LatLng , distance float64 , azimuth s1.Angle ) s2.LatLng {
136- var lat , lng C.double
137-
138- C .geod_direct (
139- & s .cRepr ,
140- C .double (point .Lat .Degrees ()),
141- C .double (point .Lng .Degrees ()),
142- C .double (azimuth * 180.0 / math .Pi ),
143- C .double (distance ),
144- & lat ,
145- & lng ,
146- nil ,
147- )
148-
149- return s2 .LatLngFromDegrees (float64 (lat ), float64 (lng ))
150- }
0 commit comments