RDM_RTREE_NEAREST

Specifying RDM_RTREE_NEAREST for the type in the RDM_RTREE_KEY structure will return a cursor that contains the nearest X neighbors in the R-tree to the specified bounding box. The engine uses the Euclidean distance for calculating how near objects are to each other.

The calculation of distance uses the center points of the objects defined in the rows.

In the above image, the center point of the MBRClosed minimum bounding rectangle in Row B is closest to the center point of the bounding box and will be the first row returned in the result followed by Row A and then Row C.

The nearest neighbor query calculates the nearest neighbors when the cursor is created. Therefore, it is not considered a ‘live’ cursor and the results will stay constant regardless if rows are inserted, updated or deleted. As long as a lock on the table is maintained the cursor is guaranteed to be current. The cursor will be ordered on the Euclidean distance of the rows.

Here is an example of finding rows that are contained by a bounding box using a R-tree index.

static RDM_RETCODE retrieveNearestZipCode (RDM_DB db)
{
    RDM_RETCODE rc = sOKAY;
    RDM_CURSOR cursor = NULL;
    POINTSOFINTEREST poi = {0};
    POINTSOFINTEREST_LOCATION_KEY keyVal = {0};
    RDM_RTREE_KEY key = {0};

    /* Set the key value for the lookup */
    keyVal.location[0] = -180.0;    /* Longitude is the 'x' value */
    keyVal.location[1] = 43.601772; /* Latitude is the 'y' value */
    keyVal.location[2] = 180.0;     /* Longitude is the 'x' value */
    keyVal.location[3] = 47.432251; /* Latitude is the 'y' value */

    /* Set key lookup information */
    key.type =
        RDM_RTREE_NEAREST; /* Find rows in the order of nearest to farthest */
    key.value = &keyVal;
    key.bytesIn = sizeof (POINTSOFINTEREST_LOCATION_KEY);

    /* Start an update transaction */
    rc = rdm_dbStartRead (db, RDM_LOCK_ALL, 0, NULL);
    if (rc == sOKAY)
    {
        /* Get a cursor based on the r-tree key information */
        rc = rdm_dbGetRowsByKeyInRtreeKeyRange (
            db, KEY_POINTSOFINTEREST_LOCATION, &key, &cursor);
        if (rc == sOKAY)
        {
            /* Move to the first row in the cursor */
            rc = rdm_cursorMoveToFirst (cursor);
            while (rc == sOKAY)
            {
                /* Read the entire row */
                rc = rdm_cursorReadRow (
                    cursor, &poi, sizeof (POINTSOFINTEREST), NULL);

                /* Move to the next result row */
                if (rc == sOKAY)
                {
                    rc = rdm_cursorMoveToNext (cursor);
                }
            }

            /* We expect to break out of the loop with sENDOFCURSOR */
            if (rc == sENDOFCURSOR)
            {
                rc = sOKAY;
            }

            /* Free the cursor */
            (void) rdm_cursorFree (cursor);
        }

        /* End the read transaction (free locks) */
        (void) rdm_dbEnd (db);
    }

    return rc;
}