geohash.go 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. // Copyright 2021 EMQ Technologies Co., Ltd.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package main
  15. import (
  16. "fmt"
  17. "github.com/lf-edge/ekuiper/pkg/api"
  18. "github.com/mmcloughlin/geohash"
  19. )
  20. type geohashEncode struct {
  21. }
  22. type geohashEncodeInt struct {
  23. }
  24. type geohashDecode struct {
  25. }
  26. type geohashDecodeInt struct {
  27. }
  28. type geohashBoundingBox struct {
  29. }
  30. type geohashBoundingBoxInt struct {
  31. }
  32. type geohashNeighbor struct {
  33. }
  34. type geohashNeighborInt struct {
  35. }
  36. type geohashNeighbors struct {
  37. }
  38. type geohashNeighborsInt struct {
  39. }
  40. type position struct {
  41. Longitude float64
  42. Latitude float64
  43. }
  44. var (
  45. GeohashEncode geohashEncode
  46. GeohashEncodeInt geohashEncodeInt
  47. GeohashDecode geohashDecode
  48. GeohashDecodeInt geohashDecodeInt
  49. GeohashBoundingBox geohashBoundingBox
  50. GeohashBoundingBoxInt geohashBoundingBoxInt
  51. GeohashNeighbor geohashNeighbor
  52. GeohashNeighborInt geohashNeighborInt
  53. GeohashNeighbors geohashNeighbors
  54. GeohashNeighborsInt geohashNeighborsInt
  55. g_direction = map[string]geohash.Direction{
  56. "North": geohash.North,
  57. "NorthEast": geohash.NorthEast,
  58. "East": geohash.East,
  59. "SouthEast": geohash.SouthEast,
  60. "South": geohash.South,
  61. "SouthWest": geohash.SouthWest,
  62. "West": geohash.West,
  63. "NorthWest": geohash.NorthWest}
  64. )
  65. func (r *geohashEncode) IsAggregate() bool {
  66. return false
  67. }
  68. func (r *geohashEncodeInt) IsAggregate() bool {
  69. return false
  70. }
  71. func (r *geohashDecode) IsAggregate() bool {
  72. return false
  73. }
  74. func (r *geohashDecodeInt) IsAggregate() bool {
  75. return false
  76. }
  77. func (r *geohashBoundingBox) IsAggregate() bool {
  78. return false
  79. }
  80. func (r *geohashBoundingBoxInt) IsAggregate() bool {
  81. return false
  82. }
  83. func (r *geohashNeighbor) IsAggregate() bool {
  84. return false
  85. }
  86. func (r *geohashNeighborInt) IsAggregate() bool {
  87. return false
  88. }
  89. func (r *geohashNeighbors) IsAggregate() bool {
  90. return false
  91. }
  92. func (r *geohashNeighborsInt) IsAggregate() bool {
  93. return false
  94. }
  95. func (r *geohashEncode) Validate(args []interface{}) error {
  96. if len(args) != 2 {
  97. return fmt.Errorf("The geohashEncode function supports 2 parameters, but got %d", len(args))
  98. }
  99. return nil
  100. }
  101. func (r *geohashEncodeInt) Validate(args []interface{}) error {
  102. if len(args) != 2 {
  103. return fmt.Errorf("The geohashEncodeInt function supports 2 parameters, but got %d", len(args))
  104. }
  105. return nil
  106. }
  107. func (r *geohashDecode) Validate(args []interface{}) error {
  108. if len(args) != 1 {
  109. return fmt.Errorf("The geohashDecode function supports 1 parameters, but got %d", len(args))
  110. }
  111. return nil
  112. }
  113. func (r *geohashDecodeInt) Validate(args []interface{}) error {
  114. if len(args) != 1 {
  115. return fmt.Errorf("The geohashDecodeInt function supports 1 parameters, but got %d", len(args))
  116. }
  117. return nil
  118. }
  119. func (r *geohashBoundingBox) Validate(args []interface{}) error {
  120. if len(args) != 1 {
  121. return fmt.Errorf("The geohashBoundingBox function supports 1 parameters, but got %d", len(args))
  122. }
  123. return nil
  124. }
  125. func (r *geohashBoundingBoxInt) Validate(args []interface{}) error {
  126. if len(args) != 1 {
  127. return fmt.Errorf("The geohashBoundingBoxInt function supports 1 parameters, but got %d", len(args))
  128. }
  129. return nil
  130. }
  131. func (r *geohashNeighbor) Validate(args []interface{}) error {
  132. if len(args) != 2 {
  133. return fmt.Errorf("The geohashNeighbor function supports 2 parameters, but got %d", len(args))
  134. }
  135. return nil
  136. }
  137. func (r *geohashNeighborInt) Validate(args []interface{}) error {
  138. if len(args) != 2 {
  139. return fmt.Errorf("The geohashNeighborInt function supports 2 parameters, but got %d", len(args))
  140. }
  141. return nil
  142. }
  143. func (r *geohashNeighbors) Validate(args []interface{}) error {
  144. if len(args) != 1 {
  145. return fmt.Errorf("The geohashNeighbors function supports 1 parameters, but got %d", len(args))
  146. }
  147. return nil
  148. }
  149. func (r *geohashNeighborsInt) Validate(args []interface{}) error {
  150. if len(args) != 1 {
  151. return fmt.Errorf("The geohashNeighborsInt function supports 1 parameters, but got %d", len(args))
  152. }
  153. return nil
  154. }
  155. func (r *geohashEncode) Exec(args []interface{}, _ api.FunctionContext) (interface{}, bool) {
  156. la, ok := args[0].(float64)
  157. if !ok {
  158. return fmt.Errorf("arg[0] is not a float, got %v", args[0]), false
  159. }
  160. lo, ok := args[1].(float64)
  161. if !ok {
  162. return fmt.Errorf("arg[1] is not a float, got %v", args[1]), false
  163. }
  164. return geohash.Encode(la, lo), true
  165. }
  166. func (r *geohashEncodeInt) Exec(args []interface{}, _ api.FunctionContext) (interface{}, bool) {
  167. la, ok := args[0].(float64)
  168. if !ok {
  169. return fmt.Errorf("arg[0] is not a float, got %v", args[0]), false
  170. }
  171. lo, ok := args[1].(float64)
  172. if !ok {
  173. return fmt.Errorf("arg[1] is not a float, got %v", args[1]), false
  174. }
  175. return geohash.EncodeInt(la, lo), true
  176. }
  177. func (r *geohashDecode) Exec(args []interface{}, _ api.FunctionContext) (interface{}, bool) {
  178. hash, ok := args[0].(string)
  179. if !ok || 0 == len(hash) {
  180. return fmt.Errorf("arg[0] is not a string, got %v", args[0]), false
  181. }
  182. if err := geohash.Validate(hash); nil != err {
  183. return err, false
  184. }
  185. la, lo := geohash.Decode(hash)
  186. return position{Longitude: lo, Latitude: la}, true
  187. }
  188. func (r *geohashDecodeInt) Exec(args []interface{}, _ api.FunctionContext) (interface{}, bool) {
  189. hash, ok := args[0].(uint64)
  190. if !ok || 0 > hash {
  191. return fmt.Errorf("arg[0] is not a bigint, got %v", args[0]), false
  192. }
  193. la, lo := geohash.DecodeInt(hash)
  194. return position{Longitude: lo, Latitude: la}, true
  195. }
  196. func (r *geohashBoundingBox) Exec(args []interface{}, _ api.FunctionContext) (interface{}, bool) {
  197. hash, ok := args[0].(string)
  198. if !ok || 0 == len(hash) {
  199. return fmt.Errorf("arg[0] is not a string, got %v", args[0]), false
  200. }
  201. if err := geohash.Validate(hash); nil != err {
  202. return err, false
  203. }
  204. return geohash.BoundingBox(hash), true
  205. }
  206. func (r *geohashBoundingBoxInt) Exec(args []interface{}, _ api.FunctionContext) (interface{}, bool) {
  207. hash, ok := args[0].(uint64)
  208. if !ok || 0 > hash {
  209. return fmt.Errorf("arg[0] is not a bigint, got %v", args[0]), false
  210. }
  211. return geohash.BoundingBoxInt(hash), true
  212. }
  213. func (r *geohashNeighbor) Exec(args []interface{}, _ api.FunctionContext) (interface{}, bool) {
  214. hash, ok := args[0].(string)
  215. if !ok || 0 == len(hash) {
  216. return fmt.Errorf("arg[0] is not a string, got %v", args[0]), false
  217. }
  218. if err := geohash.Validate(hash); nil != err {
  219. return err, false
  220. }
  221. var directionCode geohash.Direction
  222. direction, ok := args[1].(string)
  223. if !ok || 0 == len(direction) {
  224. return fmt.Errorf("arg[1] is not a string, got %v", args[1]), false
  225. } else {
  226. directionCode, ok = g_direction[direction]
  227. if !ok {
  228. return fmt.Errorf("arg[1] is valid, got %v", args[1]), false
  229. }
  230. }
  231. return geohash.Neighbor(hash, directionCode), true
  232. }
  233. func (r *geohashNeighborInt) Exec(args []interface{}, _ api.FunctionContext) (interface{}, bool) {
  234. hash, ok := args[0].(uint64)
  235. if !ok || 0 > hash {
  236. return fmt.Errorf("arg[0] is not a bigint, got %v", args[0]), false
  237. }
  238. var directionCode geohash.Direction
  239. direction, ok := args[1].(string)
  240. if !ok || 0 == len(direction) {
  241. return fmt.Errorf("arg[1] is not a string, got %v", args[1]), false
  242. } else {
  243. directionCode, ok = g_direction[direction]
  244. if !ok {
  245. return fmt.Errorf("arg[1] is valid, got %v", args[1]), false
  246. }
  247. }
  248. return geohash.NeighborInt(hash, directionCode), true
  249. }
  250. func (r *geohashNeighbors) Exec(args []interface{}, _ api.FunctionContext) (interface{}, bool) {
  251. hash, ok := args[0].(string)
  252. if !ok || 0 == len(hash) {
  253. return fmt.Errorf("arg[0] is not a string, got %v", args[0]), false
  254. }
  255. if err := geohash.Validate(hash); nil != err {
  256. return err, false
  257. }
  258. return geohash.Neighbors(hash), true
  259. }
  260. func (r *geohashNeighborsInt) Exec(args []interface{}, _ api.FunctionContext) (interface{}, bool) {
  261. hash, ok := args[0].(uint64)
  262. if !ok || 0 > hash {
  263. return fmt.Errorf("arg[0] is not a bigint, got %v", args[0]), false
  264. }
  265. return geohash.NeighborsInt(hash), true
  266. }