Implementing a Scale/ST_Scale function for Oracle Spatial

The tools in Locator and Spatial do not include translate (move)rotate and scale functions. I have developed the first two of these and have written about them in the referenced articles. In this article I show how to use the last of these, a Scale function, which I have just developed.

Here is the function’s descriptive header and the public function declarations from my GEOM package.

 /* ----------------------------------------------------------------------------------------
 * function   : SCALE
 * precis     : Function which updates all coordinates in a shape by applying an x/y/z factor.
 * version    : 1.0
 * description: As against, move, which adds a supplied delta to existing coords, Scale multiplies
 *               existing coordinates by the supplied factors. Rounding is applied to the result using
 *               the supplied tolerances.
 * usage      : Function Scale( p_geometry IN MDSYS.SDO_GEOMETRY,
 *                               p_diminfo IN MDSYS.SDO_DIM_ARRAY,
 *                               p_deltaX IN number,
 *                               p_deltaY IN number,
 *                               p_deltaY IN number,
 *                             )
 *                 Return MDSYS.SDO_GEOMETRY DETERMINISTIC;
 *               eg fixedShape := CODESYS.geom.tolerance(shape,diminfo);
 * param      : p_geometry    : The shape to move.
 * paramtype  : p_geomery     : MDSYS.SDO_GEOMETRY
 * param      : p_diminfo     : Tolerance used to round x/y/z values after scaling
 * param      : p_diminfo     : SDO_DIM_ARRAY
 * param      : p_XFactor     : Factor to be applied to the X coordinate.
 * paramtype  : p_XFactor     : number
 * param      : p_YFactor     : Factor to be applied to the Y coordinate.
 * paramtype  : p_YFactor     : number
 * param      : p_ZFactor     : Factpr to be applied to the Z coordinate.
 * paramtype  : p_ZFactor     : number
 * requires   : CODESYS.GEOM.isMeasure and CODESYS.GEOM.ADD_Coordinate
 * return     : newShape      : Shape whose coordinates have been scaled.
 * rtnType    : newShape      : MDSYS.SDO_GEOMETRY
 * history    : Simon Greener - Jan 2008 - Original coding.
 * copyright  : Licensed under a Creative Commons Attribution-Share Alike 2.5 Australia License. (http://creativecommons.org/licenses/by-sa/2.5/au/)
 **/
 FUNCTION Scale( p_geometry    IN MDSYS.SDO_GEOMETRY,
                  p_diminfo     IN MDSYS.SDO_DIM_ARRAY,
                  p_XFactor     IN NUMBER,
                  p_YFactor     IN NUMBER,
                  p_ZFactor     IN NUMBER := NULL
                )
   Return MDSYS.SDO_GEOMETRY Deterministic;
  
 /* Wrapper functions */
 FUNCTION Scale( p_geometry    IN MDSYS.SDO_GEOMETRY,
                  p_tolerance   IN NUMBER,
                  p_XFactor     IN NUMBER,
                  p_YFactor     IN NUMBER,
                  p_ZFactor     IN NUMBER := NULL
                )
   Return MDSYS.SDO_GEOMETRY Deterministic;
  
 FUNCTION ST_Scale( p_geometry    IN MDSYS.ST_GEOMETRY,
                     p_tolerance   IN NUMBER,
                     p_XFactor     IN NUMBER,
                     p_YFactor     IN NUMBER,
                     p_ZFactor     IN NUMBER := NULL )
   Return MDSYS.ST_GEOMETRY DETERMINISTIC;

First, let’s scale a 2D ST_LINESTRING using one of the wrapper functions:

 SELECT GEOM.ST_Scale(MDSYS.ST_GEOMETRY.FROM_WKT('LINESTRING(1 2, 1 1)'), 0.005, 0.5, 0.75).Get_WKT() as GEOM
   FROM DUAL;
  
 GEOM
 ------------------------------
 LINESTRING (0.5 1.5, 0.5 0.75)
  
 1 rows selected

The result is as follows.

!http://www.spatialdbadvisor.com/images/41.png (Scale simple, vertical, line.)!

Now, let’s test it using the two 2.5D test cases from the PostGIS online help for its ST_Scale function.

First, scale all three ordinates.

 -- Scale X, Y, Z
 SELECT GEOM.AsEWKT(GEOM.Scale(SDO_GEOMETRY(3002,null,null,sdo_elem_info_array(1,2,1),sdo_ordinate_array(1,2,3,1,1,1)), 0.005, 0.5, 0.75, 0.8)) as Geom
   FROM DUAL;
  
 GEOM
 ---------------------------------------------------------------------------------------
 LINESTRING XYZ ( LINESTRING(0.5 1.5 2.3999999999999999, 0.5 0.75 0.80000000000000004) )
  
 1 rows selected

Then scale only the X,Y coords of a 2.5D geometry.

 -- Scale X Y for a 2.5D geometry
 SELECT GEOM.AsEWKT(GEOM.Scale(SDO_GEOMETRY(3002,null,null,sdo_elem_info_array(1,2,1),sdo_ordinate_array(1,2,3,1,1,1)), 0.005, 0.5, 0.75)) as GEOM
   FROM DUAL;
  
 GEOM
 --------------------------------------------------------
 LINESTRING XYZ ( LINESTRING(0.5 1.5 3.0, 0.5 0.75 1.0) )
  
 1 rows selected

The result, graphically, in both cases is the same as in the 2D graphic above.

Finally, let’s scale a simple polygon’s X and Y coordinates by 2.

 SELECT GEOM.AsEWKT(GEOM.Scale(MDSYS.SDO_GEOMETRY(2003,null,null,sdo_elem_info_array(1,1003,4),sdo_ordinate_array(1,1,2,2,3,1)), 0.005, 2, 2)) as Geom
   FROM DUAL;
  
 GEOM
 ------------------------------------------------------
 POLYGON XY ( CURVEPOLYGON(2.0 2.0, 4.0 4.0, 6.0 2.0) )
  
 1 rows selected

The result is as shown.

!http://www.spatialdbadvisor.com/images/42.png (Scale simple 2D polygon by 2)!

The Scale/ST_Scale functions are a useful, final, complement to the Translate/ST_Translate and Rotate/ST_Rotate functions I have written previous.

All functions are available in my free GEOM PL/SQL package.
I hope this is of use to someone.

Leave a Reply

Your email address will not be published. Required fields are marked *