Go to content Go to navigation and search

Home

Current Oracle Spatial Blog Articles


Search

Browse

RSS / Atom

Email me

textpattern

Creative Commons License
All Blog Articles, Data Models and Free Source Code by Simon Greener, The SpatialDB Advisor is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.

Implementing a Scale/ST_Scale function for Oracle Spatial

Tuesday February 03 2009 at 19:20

The tools in Locator and Spatial do not include translate, 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.

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.

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.

Creative Commons License

post this at del.icio.uspost this at Diggpost this at Technoratipost this at Redditpost this at Farkpost this at Yahoo! my webpost this at Windows Livepost this at Google Bookmarkspost this to Twitter

Comment