Centroid Package now supports Y ordinate seeding

The populate CENTROID package has been modified. It now allows the caller of the CENTROID_A function to invoke Y ordinate seeding.

   /* ----------------------------------------------------------------------------------------
   * @function   : centroid_a
   * @precis     : Generates centroid for a polygon.
   * @version    : 1.3
   * @description: The standard mdsys.sdo_geom.sdo_centroid function does not guarantee
   *               that the centroid it generates falls inside the polygon.
   *               This function ensures that the centroid of any arbitrary polygon falls within the polygon.
   * @param      : p_geometry   : MDSYS.SDO_GEOMETRY : The geometry object.
   * @param      : P_Method     : pls_integer
   /** @param    : p_method     : number : 0 = use average of all Area's X Ordinates for starting centroid Calculation
   *                                      10 = use average of all Area's Y Ordinates for starting centroid Calculation
   *                                       1 = Use centre X Ordinate of geometry MBR
   *                                      11 = Use centre Y Ordinate of geometry MBR
   *                                       2 = User supplied starting seed X ordinate value
   *                                      12 = User supplied starting seed Y ordinate value
   *                                       3 = Use Standard Oracle centroid function
   *                                       4 = Use Oracle implementation of PointOnSurface
   ** @param     : p_Seed_Value : Number : Starting ordinate X/Y for which a Y/X that is inside the polygon is returned.
   * @param      : P_Dec_Places : pls_integer : Ordinate rounding precision for X, Y ordinates.
   * @param      : P_Tolerance  : number      : Tolerance for Oracle functions.
   * @param      : p_loops      : pls_integer : Number of attempts to find centroid based on small changes to seed
   * @return     : centroid     : MDSYS.SDO_GEOMETRY : The centroid.
   * @requires   : GetVector()
   * @history    : Simon Greener - Jul 2008 - Original coding of centroid_a as internal function
   * @history    : Simon Greener - Jan 2012 - Exposed internal function. Added p_seed_x support.
   * @copyright  : Free for public use
   **/
   FUNCTION Centroid_A(P_Geometry   IN Mdsys.Sdo_Geometry,
                       P_method     IN Pls_Integer DEFAULT 1,
                       P_Seed_Value IN NUMBER      DEFAULT NULL,
                       P_Dec_Places IN Pls_Integer DEFAULT 3,
                       P_Tolerance  IN Pls_Integer DEFAULT 0.05,
                       p_loops      IN pls_integer DEFAULT 10)
     RETURN MDSYS.SDO_GEOMETRY DETERMINISTIC;
 --
 -- Example
 --
 WITH poly AS (
 SELECT SDO_GEOMETRY(2003,NULL,NULL,SDO_ELEM_INFO_ARRAY(1,1003,1),
                     SDO_ORDINATE_ARRAY(1458.776,1513.583, 1230.558,1614.423, 1156.254,1656.883, 1060.721,1667.497,
                                        997.032,1662.19, 943.958,1640.96, 890.884,1603.809, 837.81,1545.427,
                                        779.428,1497.66, 763.506,1418.049, 758.199,1354.361, 752.891,1285.364,
                                        747.584,1189.831, 731.662,1094.298, 821.888,489.254, 1050.106,-147.635,
                                        1315.476,-407.698, 1442.854,207.961, 1644.535,430.872, 1055.414,982.842,
                                        2095.665,1327.824, 1878.061,1433.972, 1458.776,1513.583)) AS geom
   FROM dual
 )
 SELECT CASE LEVEL WHEN 1 THEN 'X' ELSE 'Y' END AS ord,
        CODESYS.centroid.centroid_a(p_geometry   => a.geom,
                                             p_method     => CASE LEVEL WHEN 1 THEN 0 ELSE 10 END,
                                             p_seed_value => NULL,
                                             p_dec_places => 3,
                                             p_tolerance  => 0.005,
                                             p_loops      => 2) AS centroid
   FROM poly a
   CONNECT BY level < 3;
 --
 -- Result
 --
 ORD CENTROID
 --- -----------------------------------------------------------------------
 X   SDO_GEOMETRY(2001,NULL,SDO_POINT_TYPE(1124.871,348.43,NULL),NULL,NULL)
 Y   SDO_GEOMETRY(2001,NULL,SDO_POINT_TYPE(1158.87,1155.448,NULL),NULL,NULL)

This is what it looks like.

I hope this enhancement is of use to someone.

Leave a Reply

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