SpatialDB Advisor
I often have need to convert 2D geometry objects from 2D to 3D and have wrote a function that was part of my free PL/SQL packages that did this. That function depended on another package.
Just this week I had need of a standalone version, so I went back to my old function and removed all dependencies on any other package.
This function, called TO_3D, actually does a number of things:
Here is the function.
/*
--
function To_3D
-- precis Converts a 2D or 4D geometry to a 3D geometry
-- version 1.0
-- usage v_3D_geom := geom.To_3D(MDSYS.SDO_Geometry(2001,....),50)
-- history Simon Greener, May 2007 Original coding
-- history Simon Greener, Aug 2009 Added support for interpolating Z values
*/
Function To_3D( p_geom IN MDSYS.SDO_Geometry,
p_start_z IN NUMBER,
p_end_z IN NUMBER := NULL,
p_tolerance IN NUMBER := 0.05)
Return MDSYS.SDO_Geometry Deterministic
Is
v_sign PLS_INTEGER := SIGN(p_end_z - p_start_z);
v_isMeasured BOOLEAN;
v_gtype INTEGER; -- geometry type (single digit)
v_dim INTEGER;
v_npoints INTEGER;
v_i PLS_INTEGER;
v_j PLS_INTEGER;
v_offset PLS_INTEGER;
v_length NUMBER := 0;
v_cumulative_length NUMBER := 0;
v_round_factor NUMBER := case when p_tolerance is null
then null
else round(log(10,(1/p_tolerance)/2))
end;
v_3D_geom MDSYS.SDO_Geometry;
Now let’s test it by building a 3D geometry from a 2D one with full Z interpolation.
select geom.to_3d( a.original_geom, -1, -200, 0.05) as threed_geom
from ( select mdsys.sdo_geometry(2002,null,null,sdo_elem_info_array(1,2,1),sdo_ordinate_array(0,0,5,5,10,10)) as original_geom
from dual
) a;
Now, take the above and push it into a function to add measure information to the new 3D geometry.
select MDSYS.SDO_LRS.CONVERT_TO_LRS_GEOM( threed_geom, 1, 10) as lrs_geom, threed_geom
from (select geom.to_3d( a.original_geom, -1, -200, 0.05) as threed_geom
from ( select mdsys.sdo_geometry(2002,null,null,sdo_elem_info_array(1,2,1),sdo_ordinate_array(0,0,5,5,10,10)) as original_geom
from dual
) a
) b;
Now let’s strip the measure information off the geometry to return our 3D geometry of above.
select geom.to_3d(c.lrs_geom,null,null,0.05) as geom_3d, c.threed_geom
from (select MDSYS.SDO_LRS.CONVERT_TO_LRS_GEOM( threed_geom, 1, 10) as lrs_geom, threed_geom
from (select geom.to_3d( a.original_geom, -1, -200, 0.05) as threed_geom
from ( select mdsys.sdo_geometry(2002,null,null,sdo_elem_info_array(1,2,1),sdo_ordinate_array(0,0,5,5,10,10)) as original_geom
from dual
) a
) b
) c;
Finally, let’s check the validity of the final geometry which should be the same as the original.
select sdo_geom.validate_geometry(d.geom_3d,0.05)
from (select geom.to_3d(c.lrs_geom,null,null,0.05) as geom_3d, c.threed_geom
from (select MDSYS.SDO_LRS.CONVERT_TO_LRS_GEOM( threed_geom, 1, 10) as lrs_geom, threed_geom
from (select geom.to_3d( a.original_geom, -1, -200, 0.05) as threed_geom
from ( select mdsys.sdo_geometry(2002,null,null,sdo_elem_info_array(1,2,1),sdo_ordinate_array(0,0,5,5,10,10)) as original_geom
from dual
) a
) b
) c
) d;
Finally, let’s reduce the 3D geometry back to a 2D geometry using a TO_2D function to see if we get the same geometry.
select sdo_geom.relate(geom.to_2D(d.geom_3d),'DETERMINE',mdsys.sdo_geometry(2002,null,null,sdo_elem_info_array(1,2,1),sdo_ordinate_array(0,0,5,5,10,10)),0.05) as relate
from (select geom.to_3d(c.lrs_geom,null,null,0.05) as geom_3d, c.threed_geom
from (select MDSYS.SDO_LRS.CONVERT_TO_LRS_GEOM( threed_geom, 1, 10) as lrs_geom, threed_geom
from (select geom.to_3d( a.original_geom, -1, -200, 0.05) as threed_geom
from ( select mdsys.sdo_geometry(2002,null,null,sdo_elem_info_array(1,2,1),sdo_ordinate_array(0,0,5,5,10,10)) as original_geom
from dual
) a
) b
) c
) d;
I hope this function is of use to someone as it certainly is useful to me!


















<<Extend (Reduce/Contract/Skrink) Function for Oracle >>Swapping Ordinates in an SDO_GEOMETRY object