14
2023
05

GEOHASH_ENCODE

Oracle GEOHASH_ENCODE 实现

CREATE OR REPLACE FUNCTION GEOHASH_ENCODE (latitude in number, longitude in number, precision in number:=5) RETURN VARCHAR2 AS 
  even    boolean := true;
  bit     number  := 0;
  ch      number  := 0;
  mid     number  := 0.0;
  geohash varchar2(20)  := '';
  
  TYPE varchar2_table IS TABLE OF VARCHAR2(12);
  Base32 varchar2_table;
  
  TYPE number_table IS TABLE OF NUMBER;
  lat number_table;
  lon number_table;
  Bits number_table;
  
  FUNCTION bitor( x IN NUMBER, y IN NUMBER ) RETURN NUMBER  AS
  BEGIN
    RETURN x + y - bitand(x,y);
  END;
            
BEGIN
  lat     := number_table(-90.0, 90.0);
  lon     := number_table(-180.0, 180.0);
  Bits    := number_table(16, 8, 4, 2, 1);
  Base32  := varchar2_table('0','1','2','3','4','5','6','7','8','9','b','c','d','e','f','g','h','j','k','m','n','p','q','r','s','t','u','v','w','x','y','z');
  
  while (nvl(length(geohash),0) < precision) loop
    if (even) then
        mid := (lon(0+1) + lon(1+1)) / 2;
        if (longitude > mid) then
            ch := bitor(ch, Bits(bit+1));
            lon(0+1) := mid;
          else
            lon(1+1) := mid;
        end if;
    else
      mid := (lat(0+1) + lat(1+1)) / 2;
        if (latitude > mid) then
            ch := bitor(ch, Bits(bit+1));
            lat(0+1) := mid;
          else
            lat(1+1) := mid;
        end if;
    end if;
    
    even:=not even;
    
    if (bit<4) then
      bit:=bit+1;
    else
      geohash:=geohash||Base32(ch+1);
      bit:=0;
      ch:=0;
    end if;
    
  end loop;
  
  RETURN geohash;
END GEOHASH_ENCODE;


« 上一篇

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。