sp_key.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:7k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB & Ramil Kalimullin
  2.    
  3.    This program is free software; you can redistribute it and/or modify
  4.    it under the terms of the GNU General Public License as published by
  5.    the Free Software Foundation; either version 2 of the License, or
  6.    (at your option) any later version.
  7.    
  8.    This program is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.    GNU General Public License for more details.
  12.    
  13.    You should have received a copy of the GNU General Public License
  14.    along with this program; if not, write to the Free Software
  15.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  16. #include "myisamdef.h"
  17. #ifdef HAVE_SPATIAL
  18. #include "sp_defs.h"
  19. static int sp_add_point_to_mbr(uchar *(*wkb), uchar *end, uint n_dims, 
  20.                              uchar byte_order, double *mbr);
  21. static int sp_get_point_mbr(uchar *(*wkb), uchar *end, uint n_dims, 
  22.                            uchar byte_order, double *mbr);
  23. static int sp_get_linestring_mbr(uchar *(*wkb), uchar *end, uint n_dims, 
  24.                                 uchar byte_order, double *mbr);
  25. static int sp_get_polygon_mbr(uchar *(*wkb), uchar *end, uint n_dims, 
  26.                              uchar byte_order, double *mbr);
  27. static int sp_get_geometry_mbr(uchar *(*wkb), uchar *end, uint n_dims, 
  28.                               double *mbr, int top);
  29. static int sp_mbr_from_wkb(uchar (*wkb), uint size, uint n_dims, double *mbr);
  30. static void get_double(double *d, const byte *pos)
  31. {
  32.   float8get(*d, pos);
  33. }
  34.   
  35. uint sp_make_key(register MI_INFO *info, uint keynr, uchar *key,
  36.  const byte *record, my_off_t filepos)
  37. {
  38.   HA_KEYSEG *keyseg;
  39.   MI_KEYDEF *keyinfo = &info->s->keyinfo[keynr];
  40.   uint len = 0;
  41.   byte *pos;
  42.   uint dlen;
  43.   uchar *dptr;
  44.   double mbr[SPDIMS * 2];
  45.   uint i;
  46.   
  47.   keyseg = &keyinfo->seg[-1];
  48.   pos = (byte*)record + keyseg->start;
  49.   
  50.   dlen = _mi_calc_blob_length(keyseg->bit_start, pos);
  51.   memcpy_fixed(&dptr, pos + keyseg->bit_start, sizeof(char*));
  52.   if (!dptr)
  53.   {
  54.     my_errno= HA_ERR_NULL_IN_SPATIAL;
  55.     return 0;
  56.   }
  57.   sp_mbr_from_wkb(dptr + 4, dlen - 4, SPDIMS, mbr); /* SRID */
  58.   
  59.   for (i = 0, keyseg = keyinfo->seg; keyseg->type; keyseg++, i++)
  60.   {
  61.     uint length = keyseg->length;
  62.     
  63.     pos = ((byte*)mbr) + keyseg->start;
  64.     if (keyseg->flag & HA_SWAP_KEY)
  65.     {
  66. #ifdef HAVE_ISNAN
  67.       if (keyseg->type == HA_KEYTYPE_FLOAT)
  68.       {
  69. float nr;
  70. float4get(nr, pos);
  71. if (isnan(nr))
  72. {
  73.   /* Replace NAN with zero */
  74.     bzero(key, length);
  75.   key+= length;
  76.   continue;
  77. }
  78.       }
  79.       else if (keyseg->type == HA_KEYTYPE_DOUBLE)
  80.       {
  81. double nr;
  82. get_double(&nr, pos);
  83. if (isnan(nr))
  84. {
  85.     bzero(key, length);
  86.   key+= length;
  87.   continue;
  88. }
  89.       }
  90. #endif
  91.       pos += length;
  92.       while (length--)
  93.       {
  94.         *key++ = *--pos;
  95.       }
  96.     }
  97.     else
  98.     {
  99.       memcpy((byte*)key, pos, length);
  100.       key += keyseg->length;
  101.     }
  102.     len += keyseg->length;
  103.   }
  104.   _mi_dpointer(info, key, filepos);
  105.   return len;
  106. }
  107. /*
  108. Calculate minimal bounding rectangle (mbr) of the spatial object
  109. stored in "well-known binary representation" (wkb) format.
  110. */
  111. static int sp_mbr_from_wkb(uchar *wkb, uint size, uint n_dims, double *mbr)
  112. {
  113.   uint i;
  114.   for (i=0; i < n_dims; ++i)
  115.   {
  116.     mbr[i * 2] = DBL_MAX;
  117.     mbr[i * 2 + 1] = -DBL_MAX;
  118.   }
  119.   return sp_get_geometry_mbr(&wkb, wkb + size, n_dims, mbr, 1);
  120. }
  121. /*
  122.   Add one point stored in wkb to mbr
  123. */
  124. static int sp_add_point_to_mbr(uchar *(*wkb), uchar *end, uint n_dims, 
  125.        uchar byte_order __attribute__((unused)),
  126.        double *mbr)
  127. {
  128.   double ord;
  129.   double *mbr_end= mbr + n_dims * 2;
  130.   while (mbr < mbr_end)
  131.   {
  132.     if ((*wkb) > end - 8)
  133.       return -1;
  134.     get_double(&ord, *wkb);
  135.     (*wkb)+= 8;
  136.     if (ord < *mbr)
  137.       float8store((char*) mbr, ord);
  138.     mbr++;
  139.     if (ord > *mbr)
  140.       float8store((char*) mbr, ord);
  141.     mbr++;
  142.   }
  143.   return 0;
  144. }
  145. static int sp_get_point_mbr(uchar *(*wkb), uchar *end, uint n_dims, 
  146.                            uchar byte_order, double *mbr)
  147. {
  148.   return sp_add_point_to_mbr(wkb, end, n_dims, byte_order, mbr);
  149. }
  150. static int sp_get_linestring_mbr(uchar *(*wkb), uchar *end, uint n_dims, 
  151.                                   uchar byte_order, double *mbr)
  152. {
  153.   uint n_points;
  154.   n_points = uint4korr(*wkb);
  155.   (*wkb) += 4;
  156.   for (; n_points > 0; --n_points)
  157.   {
  158.     /* Add next point to mbr */
  159.     if (sp_add_point_to_mbr(wkb, end, n_dims, byte_order, mbr))
  160.       return -1;
  161.   }
  162.   return 0;
  163. }
  164. static int sp_get_polygon_mbr(uchar *(*wkb), uchar *end, uint n_dims, 
  165.                                uchar byte_order, double *mbr)
  166. {
  167.   uint n_linear_rings;
  168.   uint n_points;
  169.   n_linear_rings = uint4korr((*wkb));
  170.   (*wkb) += 4;
  171.   for (; n_linear_rings > 0; --n_linear_rings)
  172.   {
  173.     n_points = uint4korr((*wkb));
  174.     (*wkb) += 4;
  175.     for (; n_points > 0; --n_points)
  176.     {
  177.       /* Add next point to mbr */
  178.       if (sp_add_point_to_mbr(wkb, end, n_dims, byte_order, mbr))
  179.         return -1;
  180.     }
  181.   }
  182.   return 0;
  183. }
  184. static int sp_get_geometry_mbr(uchar *(*wkb), uchar *end, uint n_dims,
  185.                               double *mbr, int top)
  186. {
  187.   int res;
  188.   uchar byte_order;
  189.   uint wkb_type;
  190.   byte_order = *(*wkb);
  191.   ++(*wkb);
  192.   wkb_type = uint4korr((*wkb));
  193.   (*wkb) += 4;
  194.   switch ((enum wkbType) wkb_type)
  195.   {
  196.     case wkbPoint:
  197.       res = sp_get_point_mbr(wkb, end, n_dims, byte_order, mbr);
  198.       break;
  199.     case wkbLineString:
  200.       res = sp_get_linestring_mbr(wkb, end, n_dims, byte_order, mbr);
  201.       break;
  202.     case wkbPolygon:
  203.       res = sp_get_polygon_mbr(wkb, end, n_dims, byte_order, mbr);
  204.       break;
  205.     case wkbMultiPoint:
  206.     {
  207.       uint n_items;
  208.       n_items = uint4korr((*wkb));
  209.       (*wkb) += 4;
  210.       for (; n_items > 0; --n_items)
  211.       {
  212.         byte_order = *(*wkb);
  213.         ++(*wkb);
  214.         (*wkb) += 4;
  215.         if (sp_get_point_mbr(wkb, end, n_dims, byte_order, mbr))
  216.           return -1;
  217.       }
  218.       res = 0;
  219.       break;
  220.     }
  221.     case wkbMultiLineString:
  222.     {
  223.       uint n_items;
  224.       n_items = uint4korr((*wkb));
  225.       (*wkb) += 4;
  226.       for (; n_items > 0; --n_items)
  227.       {
  228.         byte_order = *(*wkb);
  229.         ++(*wkb);
  230.         (*wkb) += 4;
  231.         if (sp_get_linestring_mbr(wkb, end, n_dims, byte_order, mbr))
  232.           return -1;
  233.       }
  234.       res = 0;
  235.       break;
  236.     }
  237.     case wkbMultiPolygon:
  238.     {
  239.       uint n_items;
  240.       n_items = uint4korr((*wkb));
  241.       (*wkb) += 4;
  242.       for (; n_items > 0; --n_items)
  243.       {
  244.         byte_order = *(*wkb);
  245.         ++(*wkb);
  246.         (*wkb) += 4;
  247.         if (sp_get_polygon_mbr(wkb, end, n_dims, byte_order, mbr))
  248.           return -1;
  249.       }
  250.       res = 0;
  251.       break;
  252.     }
  253.     case wkbGeometryCollection:
  254.     {
  255.       uint n_items;
  256.       if (!top)
  257.         return -1;
  258.       n_items = uint4korr((*wkb));
  259.       (*wkb) += 4;
  260.       for (; n_items > 0; --n_items)
  261.       {
  262.         if (sp_get_geometry_mbr(wkb, end, n_dims, mbr, 0))
  263.           return -1;
  264.       }
  265.       res = 0;
  266.       break;
  267.     }
  268.     default:
  269.       res = -1;
  270.   }
  271.   return res;
  272. }
  273. #endif /*HAVE_SPATIAL*/