/*****************************************************************************
**
** Function name:
**
** MyShapeContains
**
** Description:
**
** Entrypoint for the SQL routine "Contains (MyShape,MyShape) returns
** boolean". This is an Rtree strategy function.
**
** 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 spatially compared.
** MI_FPARAM *fp UDR function parameter & state info.
**
** Return value:
**
** mi_boolean True if shape2 is completely inside
** shape1. If shape1 is a non-region
** subtype (e.g. a point), returns NULL.
**
*****************************************************************************/
UDREXPORT mi_boolean
MyShapeContains (mi_lvarchar *shape1,
mi_lvarchar *shape2,
MI_FPARAM *fp)
{
mi_boolean bbox_overlap;
mi_boolean retval;
MyShape *s1 = (MyShape *) mi_get_vardata (shape1);
MyShape *s2 = (MyShape *) mi_get_vardata (shape2);
SHAPE_TRACE_ENTER (MyShapeContains);
CheckVersion (s1->hdr.version);
CheckVersion (s2->hdr.version);
/*
* If shape1 is a non-region shape (e.g. point) it is not
* possible for shape1 to contain shape2 so return NULL.
*/
switch (s1->hdr.tag)
{
case MyHeaderTag:
case MyBoxTag:
case MyCircleTag:
break;
case MyPointTag:
default:
mi_fp_setreturnisnull((fp), 0, MI_TRUE);
retval = MI_FALSE;
goto ContainsDone;
}
bbox_overlap = (s1->hdr.xmin <= s2->hdr.xmax &&
s2->hdr.xmin <= s1->hdr.xmax &&
s1->hdr.ymin <= s2->hdr.ymax &&
s2->hdr.ymin <= s1->hdr.ymax);
/*
* If bounding boxes do not overlap then it is not possible for
* shape1 to contain shape2.
*/
if (!bbox_overlap)
{
retval = MI_FALSE;
goto ContainsDone;
}
/*
* If bounding boxes overlap, and one or both objects are internal
* index nodes, we cannot rule out the possibility that objects
* in the subtree below this node satisfy the spatial test,
* so return true.
*/
if (s1->hdr.tag == MyHeaderTag || s2->hdr.tag == MyHeaderTag)
{
retval = MI_TRUE;
goto ContainsDone;
}
/*
* Both objects are actual shapes so perform an exact geometric test.
* Note operand order is reversed so we can simply use the insideTable.
*/
retval = Dispatch(insideTable, MI_FALSE, s2, s1);
ContainsDone:
SHAPE_TRACE_EXIT (MyShapeContains);
return retval;
}