[Groonga-commit] groonga/groonga [master] search also missing small meshes.

Back to archive index

null+****@clear***** null+****@clear*****
2010年 7月 28日 (水) 17:24:12 JST


Kouhei Sutou	2010-07-28 08:24:12 +0000 (Wed, 28 Jul 2010)

  New Revision: 07590da9b3b7d74a2a39082314de2135b96d40e3

  Log:
    search also missing small meshes.

  Modified files:
    lib/db.c

  Modified: lib/db.c (+90 -32)
===================================================================
--- lib/db.c    2010-07-28 03:37:41 +0000 (c2153d4)
+++ lib/db.c    2010-07-28 08:24:12 +0000 (1953fea)
@@ -6570,43 +6570,52 @@ grn_table_sort_geo_detect_mesh(grn_ctx *ctx, grn_obj *table,
 {
   int i;
   int diff_bit_mask = 0;
-  uint8_t geo_key_base[4], geo_key_far[4], geo_key_min[4], geo_key_max[4];
+  uint8_t geo_key_base[sizeof(grn_geo_point)];
+  uint8_t geo_key_far[sizeof(grn_geo_point)];
+  uint8_t geo_key_min[sizeof(grn_geo_point)];
+  uint8_t geo_key_max[sizeof(grn_geo_point)];
   grn_geo_point point;
 
-  grn_gton(geo_key_base, base_point, 4);
+  grn_gton(geo_key_base, base_point, sizeof(grn_geo_point));
   point.latitude = lat_far;
   point.longitude = lng_far;
-  grn_gton(geo_key_far, &point, 4);
-  for (i = 0; i < 4; i++) {
+  grn_gton(geo_key_far, &point, sizeof(grn_geo_point));
+  for (i = 0; i < sizeof(grn_geo_point); i++) {
     if (((geo_key_base[i] >> 6) & 3) != ((geo_key_far[i] >> 6) & 3)) {
       *diff_bit = 0;
-      diff_bit_mask = 0xff >> 2;
+      diff_bit_mask = 0xff >> 0;
       break;
     } else if (((geo_key_base[i] >> 4) & 3) != ((geo_key_far[i] >> 4) & 3)) {
       *diff_bit = 2;
-      diff_bit_mask = 0xff >> 4;
+      diff_bit_mask = 0xff >> 2;
       break;
     } else if (((geo_key_base[i] >> 2) & 3) != ((geo_key_far[i] >> 2) & 3)) {
       *diff_bit = 4;
-      diff_bit_mask = 0xff >> 6;
+      diff_bit_mask = 0xff >> 4;
       break;
     } else if (((geo_key_base[i] >> 0) & 3) != ((geo_key_far[i] >> 0) & 3)) {
       *diff_bit = 6;
-      diff_bit_mask = 0xff >> 8;
+      diff_bit_mask = 0xff >> 6;
       break;
     }
   }
   *diff_byte = i;
   memcpy(geo_key_min, geo_key_base, i + 1);
   geo_key_min[i] &= ~diff_bit_mask;
-  memset(geo_key_min + i + 1, 0, 4 - i - 1);
+  memset(geo_key_min + i + 1, 0, sizeof(grn_geo_point) - i - 1);
   memcpy(geo_key_max, geo_key_base, i + 1);
   geo_key_max[i] |= diff_bit_mask;
-  memset(geo_key_max + i + 1, 0xff, 4 - i - 1);
-  grn_ntog((uint8_t *)geo_min, geo_key_min, 4);
-  grn_ntog((uint8_t *)geo_max, geo_key_max, 4);
+  memset(geo_key_max + i + 1, 0xff, sizeof(grn_geo_point) - i - 1);
+  grn_ntog((uint8_t *)geo_min, geo_key_min, sizeof(grn_geo_point));
+  grn_ntog((uint8_t *)geo_max, geo_key_max, sizeof(grn_geo_point));
 }
 
+typedef struct
+{
+  grn_geo_point key;
+  int key_size;
+} mesh_entry;
+
 static void
 grn_table_sort_geo_collect_points(grn_ctx *ctx, grn_obj *table, grn_obj *index,
                                   grn_pat *pat,
@@ -6615,12 +6624,12 @@ grn_table_sort_geo_collect_points(grn_ctx *ctx, grn_obj *table, grn_obj *index,
                                   int lng_far, int lat_far, double d_far,
                                   geo_entry **entries, int *n_entries)
 {
-  int e;
-  uint8_t geos[4][4];
-  grn_geo_point geo_min, geo_max, geo_base, keys[4];
+  int n_meshes, e;
+  grn_geo_point geo_min, geo_max, geo_base;
+  mesh_entry meshes[20];
   int diff_byte = 0, diff_bit = 0, key_size;
   int lat_diff, lng_diff;
-  double lng1, lat1;
+  double lng1, lat1, lng2, lat2, x, y, d;
   geo_entry *ep, *p;
 
   grn_table_sort_geo_detect_mesh(ctx, table, base_point, lng_far, lat_far, d_far,
@@ -6645,27 +6654,76 @@ grn_table_sort_geo_collect_points(grn_ctx *ctx, grn_obj *table, grn_obj *index,
       geo_base.longitude = geo_min.longitude;
     }
   }
-  keys[0].latitude = geo_base.latitude + lat_diff;
-  keys[0].longitude = geo_base.longitude + lng_diff;
-  keys[1].latitude = geo_base.latitude + lat_diff;
-  keys[1].longitude = geo_base.longitude - lng_diff;
-  keys[2].latitude = geo_base.latitude - lat_diff;
-  keys[2].longitude = geo_base.longitude - lng_diff;
-  keys[3].latitude = geo_base.latitude - lat_diff;
-  keys[3].longitude = geo_base.longitude + lng_diff;
-  grn_gton(geos[0], keys + 0, 4);
-  grn_gton(geos[1], keys + 1, 4);
-  grn_gton(geos[2], keys + 2, 4);
-  grn_gton(geos[3], keys + 3, 4);
+
+  n_meshes = 0;
+
+#define add_mesh(lat_diff_,lng_diff_,key_size_)\
+  meshes[n_meshes].key.latitude = geo_min.latitude + lat_diff_;\
+  meshes[n_meshes].key.longitude = geo_min.longitude + lng_diff_;\
+  meshes[n_meshes].key_size = key_size_;\
+  n_meshes++;
+
+  add_mesh(0, 0, key_size);
+  add_mesh(0, -lng_diff, key_size);
+  add_mesh(-lat_diff, -lng_diff, key_size);
+  add_mesh(-lat_diff, 0, key_size);
+
+#define add_sub_mesh(lat_diff_cmp,lng_diff_cmp,lat_diff_base,lng_diff_base)\
+  lat2 = geo_base.latitude + lat_diff_cmp;\
+  lng2 = geo_base.longitude + lng_diff_cmp;\
+  x = (lng2 - lng1) * cos((lat1 + lat2) * 0.5);\
+  y = (lat2 - lat1);\
+  d = ((x * x) + (y * y));\
+  if (d > d_far) {\
+    add_mesh(lat_diff_base, lng_diff_base, key_size + 2);\
+  }
+
+  add_sub_mesh(lat_diff + 1, -lng_diff / 2,
+               lat_diff + 1, -lng_diff);
+  add_sub_mesh(lat_diff + 1, 0,
+               lat_diff + 1, -lng_diff / 2);
+  add_sub_mesh(lat_diff + 1, 0,
+               lat_diff + 1, 0);
+  add_sub_mesh(lat_diff + 1, lng_diff / 2 + 1,
+               lat_diff + 1, lng_diff / 2 + 1);
+
+  add_sub_mesh(lat_diff / 2 + 1, lng_diff + 1,
+               lat_diff / 2 + 1, lng_diff + 1);
+  add_sub_mesh(0, lng_diff + 1,
+               0, lng_diff + 1);
+  add_sub_mesh(0, lng_diff + 1,
+               -lat_diff / 2, lng_diff + 1);
+  add_sub_mesh(-lat_diff / 2, lng_diff + 1,
+               -lat_diff, lng_diff + 1);
+
+  add_sub_mesh(-lat_diff, lng_diff / 2,
+               -lat_diff * 2, lng_diff / 2 + 1);
+  add_sub_mesh(-lat_diff, 0,
+               -lat_diff * 2, 0);
+  add_sub_mesh(-lat_diff, 0,
+               -lat_diff * 2, -lng_diff / 2);
+  add_sub_mesh(-lat_diff, -lng_diff / 2,
+               -lat_diff * 2, -lng_diff);
+
+  add_sub_mesh(-lat_diff / 2, -lng_diff,
+               -lat_diff, -lng_diff * 2);
+  add_sub_mesh(0, -lng_diff,
+               -lat_diff / 2, -lng_diff * 2);
+  add_sub_mesh(0, -lng_diff,
+               0, -lng_diff * 2);
+  add_sub_mesh(lat_diff / 2 + 1, -lng_diff,
+               lat_diff / 2 + 1, -lng_diff * 2);
+
+#undef add_sub_mesh
+#undef add_mesh
 
   e = 0;
   if ((ep = *entries = GRN_MALLOC(sizeof(geo_entry) * (n + 1)))) {
-    int i;
     grn_id tid;
-    double lng2, lat2, x, y, d;
-    for (i = 0; i < 4; i++) {
+    while (n_meshes--) {
       grn_pat_cursor *pc = grn_pat_cursor_open(ctx, pat,
-                                               keys + i, key_size,
+                                               &(meshes[n_meshes].key),
+                                               meshes[n_meshes].key_size,
                                                NULL, 0,
                                                0, -1,
                                                GRN_CURSOR_PREFIX|GRN_CURSOR_SIZE_BY_BIT);




Groonga-commit メーリングリストの案内
Back to archive index