----------------------------------------------------------------------------------------------------- -- PL/SQL function: get_csq -- -- Written by: Tony Rees, CSIRO Australia (Tony.Rees@csiro.au) -- -- Date Created: January, 2003 -- -- Description: gets c-squares code for a supplied lat/long coordinate pair; rewritten as a -- -- recursive function (cf original "get_csquare"), to cope with any supplied resolution -- -- Inputs: nlat: latitude in decimal degrees (number) -- -- nlong: longitude in decimal degrees (number) -- -- resolution: square size in decimal degrees (number) -- -- Output: code as varchar2 -- -- Remarks: resolution expected as one of the following: 10, 5, 1, 0.5, 0.1 etc. [degrees], -- -- **now extensible (cf original "get_csquare" code)** -- -- 0 deg latitude/longitude is treated as positive -- -- 90 deg latitude is treated as 89.99999, -90 deg latitude is treated as -89.99999 -- -- 180 deg longitude is treated as 179.99999, -180 deg longitude is treated as -179.99999 -- ----------------------------------------------------------------------------------------------------- function get_csq(nlat number :=null, nlong number :=null, resolution number) return varchar2 is code_char1 varchar2 (1) :=null; code_char2 varchar2 (1) :=null; code_chars34 varchar2 (2) :=null; csq_str varchar2 (20000) :=null; next_triplet varchar2 (3) :=null; lat_remainder number :=null; long_remainder number :=null; cycles_required number :=null; proc_start integer; -- process timer in seconds proc_end integer; -- process timer in seconds function get_triplet (xLat number :=null, xLong number :=null) return varchar2 is digit1 number :=null; digit2 number :=null; digit3 number :=null; begin --get the second digit digit2 := trunc(xLat); --get the third digit digit3 := trunc(xLong); --get the first digit if digit2 between 0 and 4 and digit3 between 0 and 4 then digit1 := 1; elsif digit2 between 0 and 4 and digit3 between 5 and 9 then digit1 := 2; elsif digit2 between 5 and 9 and digit3 between 0 and 4 then digit1 := 3; elsif digit2 between 5 and 9 and digit3 between 5 and 9 then digit1 := 4; end if; return to_char(digit1)||to_char(digit2)||to_char(digit3); end get_triplet; begin ------------------------------- if global_debug then proc_start := to_number(to_char(sysdate,'SSSSS'));end if; ------------------------------- --get the global quadrant if nlat>=0 then if nlong>=0 then code_char1 :='1'; elsif nlong<0 then code_char1 :='7'; end if; elsif nlat<0 then if nlong>=0 then code_char1 :='3'; elsif nlong<0 then code_char1 :='5'; end if; end if; --get the next digit (tens of degrees latitude) if abs(nlat) >=90 then --special case for +90, -90 degrees code_char2 := '8'; lat_remainder := 9.99999; else code_char2 := to_char(trunc(abs(nlat/10))); lat_remainder := abs(nlat) - (to_number(code_char2)*10); end if; --get the next 2 digits (tens of degrees longitude) if abs(nlong) >=180 then --special case for +180, -180 degrees code_chars34 := '17'; long_remainder := 9.99999; else code_chars34 := substr('00'||to_char(trunc(abs(nlong/10))), -2); long_remainder := abs(nlong) - (to_number(code_chars34)*10); end if; csq_str := code_char1||code_char2||code_chars34; -- convert resolution to a number of times to process remainder if resolution = 10 then cycles_required := 0; else -- assign cycles_required to value 1 for resolution >=1, 2 for resolution >=0.1, -- 3 for resolution >=0.01, etc. cycles_required := length(to_char(resolution - trunc(resolution))); end if; while cycles_required >0 loop next_triplet := get_triplet(lat_remainder, long_remainder); csq_str := csq_str||':'||next_triplet; lat_remainder := (lat_remainder - (to_number(substr(next_triplet,2,1))))*10; long_remainder := (long_remainder - (to_number(substr(next_triplet,3,1))))*10; cycles_required := cycles_required - 1; end loop; -- remove last two characters for a resolution whose last digit is a five, according to c-squares spec if substr(to_char(resolution),-1)='5' then csq_str := substr(csq_str,1,length(csq_str)-2); end if; return csq_str; ------------------------------- if global_debug then proc_end := to_number(to_char(sysdate,'SSSSS'));htp.print('function get_csq : '||' Start sec: '||proc_start||' Finish sec: '||proc_end||' Total time: '|| to_char(proc_end -proc_start));htp.br;end if; ------------------------------- end get_csq;