github.com/liucxer/courier@v1.7.1/h3/h3api.go (about) 1 package h3 2 3 import ( 4 "bytes" 5 "fmt" 6 ) 7 8 // Maximum number of cell boundary vertices; worst case is pentagon: 9 // 5 original Verts + 5 edge crossings 10 const MAX_CELL_BNDRY_VERTS = 10 11 12 /** 13 @brief latitude/longitude in radians 14 */ 15 type GeoCoord struct { 16 Lat float64 ///< latitude in radians 17 Lon float64 ///< longitude in radians 18 } 19 20 func (g GeoCoord) String() string { 21 return fmt.Sprintf("%f,%f", g.Lat, g.Lon) 22 } 23 24 func (g GeoCoord) AsDegrees() *GeoCoord { 25 return &GeoCoord{ 26 Lon: normalizeDegree(radsToDegs(g.Lon), -180.0, 180), 27 Lat: normalizeDegree(radsToDegs(g.Lat), -90, 90), 28 } 29 } 30 31 func (g GeoCoord) AsRadians() *GeoCoord { 32 return &GeoCoord{ 33 Lon: radsToDegs(g.Lon), 34 Lat: radsToDegs(g.Lat), 35 } 36 } 37 38 /** 39 @brief cell boundary in latitude/longitude 40 */ 41 type GeoBoundary struct { 42 numVerts int ///< number of vertices 43 Verts []GeoCoord ///< vertices in ccw order 44 } 45 46 func (gb GeoBoundary) String() string { 47 buf := bytes.NewBuffer(nil) 48 buf.WriteRune('[') 49 for i := range gb.Verts { 50 if i != 0 { 51 buf.WriteRune(' ') 52 } 53 buf.WriteString(gb.Verts[i].String()) 54 } 55 buf.WriteRune(']') 56 return buf.String() 57 } 58 59 func (gb GeoBoundary) AsDegrees() *GeoBoundary { 60 list := make([]GeoCoord, len(gb.Verts)) 61 62 for i := range gb.Verts { 63 list[i] = *(gb.Verts[i].AsDegrees()) 64 } 65 66 gb.Verts = list 67 68 return &gb 69 } 70 71 func (gb GeoBoundary) AsRadians() *GeoBoundary { 72 list := make([]GeoCoord, len(gb.Verts)) 73 74 for i := range gb.Verts { 75 list[i] = *(gb.Verts[i].AsDegrees()) 76 } 77 78 gb.Verts = list 79 80 return &gb 81 } 82 83 /** 84 * @brief similar to GeoBoundary, but requires more alloc work 85 */ 86 type Geofence struct { 87 numVerts int 88 verts []GeoCoord 89 } 90 91 func (g *Geofence) IsZero() bool { 92 return g == nil || g.numVerts == 0 93 } 94 95 func (g *Geofence) NewIterate() func(vertexA *GeoCoord, vertexB *GeoCoord) bool { 96 loopIndex := -1 97 98 return func(vertexA *GeoCoord, vertexB *GeoCoord) bool { 99 loopIndex++ 100 101 if loopIndex >= g.numVerts { 102 return false 103 } 104 105 *vertexA = g.verts[loopIndex] 106 *vertexB = g.verts[(loopIndex+1)%g.numVerts] 107 108 return true 109 } 110 } 111 112 /** 113 * @brief Simplified core of GeoJSON Polygon coordinates definition 114 */ 115 type GeoPolygon struct { 116 geofence Geofence ///< exterior boundary of the polygon 117 numHoles int ///< number of elements in the array pointed to by holes 118 holes []Geofence ///< interior boundaries (holes) in the polygon 119 } 120 121 /** 122 * @brief Simplified core of GeoJSON MultiPolygon coordinates definition 123 */ 124 type GeoMultiPolygon struct { 125 numPolygons int 126 polygons []GeoPolygon 127 } 128 129 /** 130 * @brief A coordinate node in a linked geo structure, part of a linked list 131 */ 132 type LinkedGeoCoord struct { 133 vertex GeoCoord 134 next *LinkedGeoCoord 135 } 136 137 /** 138 * @brief A loop node in a linked geo structure, part of a linked list 139 */ 140 type LinkedGeoLoop struct { 141 first *LinkedGeoCoord 142 last *LinkedGeoCoord 143 next *LinkedGeoLoop 144 } 145 146 func (l *LinkedGeoLoop) IsZero() bool { 147 return l == nil || l.first == nil 148 } 149 150 func (l *LinkedGeoLoop) NewIterate() func(vertexA *GeoCoord, vertexB *GeoCoord) bool { 151 var currentCoord, nextCoord *LinkedGeoCoord 152 153 return func(vertexA *GeoCoord, vertexB *GeoCoord) bool { 154 var getNextCoord = func(coordToCheck *LinkedGeoCoord) *LinkedGeoCoord { 155 if coordToCheck == nil { 156 return l.first 157 } 158 return currentCoord.next 159 160 } 161 162 currentCoord = getNextCoord(currentCoord) 163 164 if currentCoord == nil { 165 return false 166 } 167 168 *vertexA = currentCoord.vertex 169 nextCoord = getNextCoord(currentCoord.next) 170 *vertexB = nextCoord.vertex 171 172 return true 173 } 174 } 175 176 /** 177 * @brief A polygon node in a linked geo structure, part of a linked list. 178 */ 179 type LinkedGeoPolygon struct { 180 first *LinkedGeoLoop 181 last *LinkedGeoLoop 182 next *LinkedGeoPolygon 183 } 184 185 /** 186 * @brief IJ hexagon coordinates 187 * 188 * Each axis is spaced 120 degrees apart. 189 */ 190 type CoordIJ struct { 191 i int ///< i component 192 j int ///< j component 193 }