Geometry to wkt curve polygon
From WickyWiki
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;
/