Geometry to wkt curve polygon: Difference between revisions
From WickyWiki
Created page with "Category:Oracle Category:Oracle PL/SQL Category:Oracle Spatial In Oracle Spatial the conversion of arc's to WKT seems not supported as it is not part of the simple f..." |
No edit summary |
||
| Line 2: | Line 2: | ||
[[Category:Oracle PL/SQL]] | [[Category:Oracle PL/SQL]] | ||
[[Category:Oracle Spatial]] | [[Category:Oracle Spatial]] | ||
[[Category:201202]] | |||
In Oracle Spatial the conversion of arc's to WKT seems not supported as it is not part of the simple feature specification. On this page you will find: | In Oracle Spatial the conversion of arc's to WKT seems not supported as it is not part of the simple feature specification. On this page you will find: | ||
Revision as of 09:00, 14 February 2012
In Oracle Spatial the conversion of arc's to WKT seems not supported as it is not part of the simple feature specification. On this page you will find:
- a spatial function to stroke the arc's
- a custom function to output polygons with arc's
SQL arc stroking with Oracle Spatial:
select SDO_UTIL.TO_WKTGEOMETRY( SDO_GEOM.SDO_ARC_DENSIFY(geom, 0.0005, 'arc_tolerance=0.01'))
from (select MDSYS.SDO_GEOMETRY(2003, 90112, NULL,
MDSYS.SDO_ELEM_INFO_ARRAY(1,1005,3,1,2,1,3,2,2,7,2,1)
, MDSYS.SDO_ORDINATE_ARRAY(161312.26, 383399.949, 161312.42, 383399.78
, 161315.461, 383401.401, 161317.344, 383404.288, 161317.296, 383404.342
, 161312.26, 383399.949)) as geom from dual)
;
Result:
POLYGON ((161312.26 383399.949, 161312.42 383399.78, 161313.087535512 383399.978123147 , 161313.731792268 383400.242300498, 161314.346252635 383400.569859498 , 161314.924700414 383400.957486391, 161315.461283728 383401.401259743 , 161315.950574223 383401.896690114, 161316.387621984 383402.438765474 , 161316.76800561 383403.022001908, 161317.087876943 383403.640499096 , 161317.344 383404.288, 161317.296 383404.342, 161312.26 383399.949))
SQL curve WKT with custom function:
select GEOMETRY_TO_CURVEPOLYGON_WKT(geom)
from (select MDSYS.SDO_GEOMETRY(2003, 90112, NULL,
MDSYS.SDO_ELEM_INFO_ARRAY(1,1005,3,1,2,1,3,2,2,7,2,1)
, MDSYS.SDO_ORDINATE_ARRAY(161312.26, 383399.949, 161312.42, 383399.78
, 161315.461, 383401.401, 161317.344, 383404.288, 161317.296, 383404.342
, 161312.26, 383399.949)) as geom from dual)
;
Result:
CURVEPOLYGON(COMPOUNDCURVE((161312.26 383399.949,161312.42 383399.78) ,CIRCULARSTRING(161312.42 383399.78,161315.461 383401.401,161317.344 383404.288) ,(161317.344 383404.288,161317.296 383404.342,161312.26 383399.949)))
PL/SQL curve polygon function:
create or replace FUNCTION GEOMETRY_TO_CURVEPOLYGON_WKT( geom IN mdsys.Sdo_geometry ) RETURN CLOB is
-- FUNCTION geometry --> curvepolygon wkt
-- (c) 2012-01 Synaxion Urbidata
-- exception voor foutieve of niet-ondersteunde geometrie, ondersteund zijn:
-- - (curve)polygon, optioneel met 1 of meer gaten
elem_info_i PLS_INTEGER;
start_index PLS_INTEGER;
until_index PLS_INTEGER;
geometry_type VARCHAR2(12) := 'POLYGON';
element_type PLS_INTEGER;
element_interpretation PLS_INTEGER;
subelements_num PLS_INTEGER;
subelements_type PLS_INTEGER;
ring CLOB;
exterior CLOB;
interiors CLOB;
function num_to_char(n number) return varchar2 is
begin
if trunc(n)=n then
return trim(to_char(n,'9999999999.0'));
else
return to_char(n);
end if;
end;
function read_elem_info(i PLS_INTEGER) return PLS_INTEGER is
begin
IF i+2 > geom.sdo_elem_info.COUNT THEN
raise_application_error(-20002, 'The elemtinfo count ('||to_char(geom.sdo_elem_info.COUNT)||') is not a multitude of 3');
END IF;
start_index:=geom.sdo_elem_info( i );
element_type := geom.sdo_elem_info( i+1 );
element_interpretation:=geom.sdo_elem_info( i+2 );
-- next start index: 'until_index'
IF i+3 <= geom.sdo_elem_info.COUNT THEN
until_index:=geom.sdo_elem_info(i+3);
ELSE
until_index:=geom.Sdo_ordinates.COUNT+1;
END IF;
RETURN i+3;
end;
function read_ring(start_index PLS_INTEGER, until_index PLS_INTEGER) return clob is
begin
declare
j PLS_INTEGER;
r clob;
begin
r:=null;
-- check index, create ring
IF start_index<=geom.Sdo_ordinates.COUNT
and start_index > 0
and until_index+1-2<=geom.Sdo_ordinates.COUNT
and until_index-2>0
and start_index<until_index-1
THEN
j:=start_index;
WHILE j < until_index LOOP
IF not r is NULL THEN
r := r||',';
END IF;
r := r || num_to_char( geom.sdo_ordinates(j+0) ) || ' ' || num_to_char( geom.sdo_ordinates(j+1) );
j:=j+2;
END LOOP;
ELSE
raise_application_error(-20003, 'GEOMETRY_TO_CURVEPOLYGON_WKT: the offset does not point to any coordinates');
END IF;
return r;
end;
end;
BEGIN
IF geom is NULL THEN
RETURN NULL;
ELSIF NOT geom.sdo_elem_info IS NULL THEN
IF geom.sdo_gtype = 2003 THEN
exterior:=NULL;
interiors:=NULL;
elem_info_i:=1;
WHILE elem_info_i <= geom.sdo_elem_info.COUNT LOOP
elem_info_i:=read_elem_info(elem_info_i);
-- curve polygons
IF element_type in (1005,2005) THEN
geometry_type:='CURVEPOLYGON';
subelements_num:=element_interpretation;
subelements_type:=element_type;
ring:=NULL;
WHILE subelements_num>0 LOOP
subelements_num:=subelements_num-1;
elem_info_i:=read_elem_info(elem_info_i);
IF NOT ring is NULL THEN
ring:=ring||',';
END IF;
-- if not last segment then add first point of next segment
IF subelements_num>0 AND until_index<geom.sdo_ordinates.COUNT+1 THEN
until_index:=until_index+2;
END IF;
IF element_interpretation=1 THEN
ring:=ring||'('||read_ring(start_index,until_index)||')';
ELSIF element_interpretation=2 THEN
ring:=ring||'CIRCULARSTRING('||read_ring(start_index,until_index)||')';
ELSE
raise_application_error(-20003, 'GEOMETRY_TO_CURVEPOLYGON_WKT: the interpretation of subelement ('||to_char(element_interpretation)||') should be 1 (straight) or 2 (curve)');
END IF;
END LOOP;
IF subelements_type=1005 AND exterior is NULL THEN
exterior:='COMPOUNDCURVE('||ring||')';
ELSIF subelements_type=2005 THEN
interiors:=interiors || ',' || 'COMPOUNDCURVE('||ring||')';
ELSE
raise_application_error(-20004, 'GEOMETRY_TO_CURVEPOLYGON_WKT: unsupported coumpound geometry');
END IF;
ELSIF element_type=1003 AND exterior is NULL THEN
exterior:='(' || read_ring(start_index,until_index) || ')';
ELSIF element_type=2003 THEN
interiors:=interiors || ',' || '(' || read_ring(start_index,until_index) || ')';
ELSE
raise_application_error(-20005, 'GEOMETRY_TO_CURVEPOLYGON_WKT: unsupported geometry');
END IF;
END LOOP;
RETURN geometry_type || '(' || exterior || interiors || ')';
ELSE
raise_application_error(-20006, 'GEOMETRY_TO_CURVEPOLYGON_WKT: unsupported geometry');
END IF; -- geom.sdo_gtype = 2003
ELSE
raise_application_error(-20006, 'GEOMETRY_TO_CURVEPOLYGON_WKT: unsupported geometry');
END IF; -- NOT geom.sdo_elem_info IS NULL
EXCEPTION WHEN OTHERS THEN
--RETURN NULL;
RETURN DBMS_UTILITY.FORMAT_ERROR_BACKTRACE || SQLERRM;
END;
/