Union support function

/*****************************************************************************
**
** Function name:
**
**      MyShapeUnion
**
** Description:
**
**      This is an R-Tree support function which enables
**      the server to maintain an R-Tree index.  It computes the
**      union of two objects' bounding boxes.
**
** Special Comments:
**
**      Because MyShape and its subtypes are variable length opaque 
**      datatypes, the UDT instances are passed in from the server 
**      wrapped in mi_lvarchars.
**
** Parameters:
**
**      mi_lvarchar *in1, *in2   UDT instances to be unioned together.
**      mi_lvarchar *out         Resulting union.
**      MI_FPARAM   *fp          UDR function parameter & state info.
**
** Return value:
**
**      mi_integer               MI_OK if success, MI_ERROR if problems.
**
*****************************************************************************/

UDREXPORT mi_integer
MyShapeUnion (mi_lvarchar *shape_in1,
              mi_lvarchar *shape_in2,
              mi_lvarchar *shape_out,
              MI_FPARAM   *fp)
{
    MyShapeHdr *h1;
    MyShapeHdr *h2;
    MyShapeHdr *h3;

    SHAPE_TRACE_ENTER (MyShapeUnion);

    h1 = (MyShapeHdr *) mi_get_vardata (shape_in1);
    h2 = (MyShapeHdr *) mi_get_vardata (shape_in2);
    h3 = (MyShapeHdr *) mi_get_vardata (shape_out);

    CheckVersion (h1->version);
    CheckVersion (h2->version);
 
    if (h1 == h2)
    {
        /*
         * This is a 'self-union', which is how the R-Tree determines how
         * big your header structure is.  This situation will occur just
         * once, on the first index insert operation.
         */
        h3->version = SHAPE_VERSION;
        h3->tag     = MyHeaderTag;
        h3->xmin    = h1->xmin;
        h3->ymin    = h1->ymin;
        h3->xmax    = h1->xmax;
        h3->ymax    = h1->ymax;
    }
    else
    {
        /*
         * CAUTION!  h1 and h3 may both reference the same structure!
         * Likewise, h2 and h3 may both reference the same structure!
         * This is because the R-Tree reuses variables to save memory.
         * This means we have to be careful not to prematurely overwrite
         * any elements of h1 or h2 as we assign values to h3.
         * The following algorithm is safe in this regard.
         */
        h3->version = SHAPE_VERSION;
        h3->tag     = MyHeaderTag;
        h3->xmin    = (h1->xmin < h2->xmin) ? h1->xmin : h2->xmin;
        h3->ymin    = (h1->ymin < h2->ymin) ? h1->ymin : h2->ymin;
        h3->xmax    = (h1->xmax > h2->xmax) ? h1->xmax : h2->xmax;
        h3->ymax    = (h1->ymax > h2->ymax) ? h1->ymax : h2->ymax;
    }

    /*
     * Set the size of the mi_lvarchar to tell the R-Tree how 
     * big each element to be stored on internal node pages will be.
     * IMPORTANT NOTE: You must do this in every Union() call,
     * not just the first one (where h1 == h2).
     */
    mi_set_varlen (shape_out, sizeof(MyShapeHdr));

    SHAPE_TRACE_EXIT (MyShapeUnion);

    return MI_OK;
}