[Groonga-commit] groonga/groonga [master] work for long latitude rectangle.

Back to archive index

null+****@clear***** null+****@clear*****
2010年 8月 12日 (木) 17:20:13 JST


Kouhei Sutou	2010-08-12 08:20:13 +0000 (Thu, 12 Aug 2010)

  New Revision: 70f65fc8098689cdf99cf2947607540b4ea087b8

  Log:
    work for long latitude rectangle.

  Modified files:
    lib/geo.c
    test/unit/story/test-taiyaki.c

  Modified: lib/geo.c (+45 -42)
===================================================================
--- lib/geo.c    2010-08-12 02:48:01 +0000 (a152e94)
+++ lib/geo.c    2010-08-12 08:20:13 +0000 (11fdae8)
@@ -31,24 +31,16 @@ typedef struct {
 static int
 compute_diff_bit(uint8_t *geo_key1, uint8_t *geo_key2)
 {
-  int i, diff_bit = 0;
+  int i, j, diff_bit = 0;
 
   for (i = 0; i < sizeof(grn_geo_point); i++) {
-    if (geo_key1[i] == geo_key2[i]) {
-      continue;
-    }
-
-    if ((geo_key1[i] & 0xc0) != (geo_key2[i] & 0xc0)) {
-      diff_bit = 0;
-      break;
-    } else if ((geo_key1[i] & 0x30) != (geo_key2[i] & 0x30)) {
-      diff_bit = 2;
-      break;
-    } else if ((geo_key1[i] & 0x0c) != (geo_key2[i] & 0x0c)) {
-      diff_bit = 4;
-      break;
-    } else if ((geo_key1[i] & 0x03) != (geo_key2[i] & 0x03)) {
-      diff_bit = 6;
+    if (geo_key1[i] != geo_key2[i]) {
+      for (j = 0; j < 8; j++) {
+        if ((geo_key1[i] & (1 << (7 - j))) != (geo_key2[i] & (1 << (7 - j)))) {
+          diff_bit = j + 1;
+          break;
+        }
+      }
       break;
     }
   }
@@ -120,6 +112,9 @@ grn_geo_table_sort_detect_far_point(grn_ctx *ctx, grn_obj *table, grn_obj *index
 
       diff_bit_prev = diff_bit_current;
       diff_bit_current = compute_diff_bit(geo_key_curr, geo_key_prev);
+      if ((diff_bit_current % 2) == 1) {
+        diff_bit_current--;
+      }
       if (diff_bit_current < diff_bit_prev && *diff_bit > diff_bit_current) {
         if (i == n) {
           break;
@@ -581,6 +576,9 @@ grn_geo_search_in_circle(grn_ctx *ctx, grn_obj *obj, grn_obj **args, int nargs,
     grn_gton(geo_key1, geo_point1, sizeof(grn_geo_point));
     grn_gton(geo_key2, &geo_point2, sizeof(grn_geo_point));
     diff_bit = compute_diff_bit(geo_key1, geo_key2);
+    if ((diff_bit % 2) == 1) {
+      diff_bit--;
+    }
     n_meshes = grn_geo_get_meshes_for_circle(ctx, geo_point1,
                                              d_far, diff_bit, GRN_TRUE,
                                              meshes);
@@ -651,35 +649,38 @@ grn_geo_search_in_rectangle(grn_ctx *ctx, grn_obj *obj, grn_obj **args, int narg
     mesh_direction direction;
     int distance, latitude_distance, longitude_distance;
     int i, start, end, diff_bit;
-    grn_geo_point geo_point_base, geo_point_min, geo_point_max;
-    uint8_t geo_key1[sizeof(grn_geo_point)];
+    grn_geo_point *geo_point_input, geo_point_base, geo_point_min, geo_point_max;
+    uint8_t geo_key_input[sizeof(grn_geo_point)];
     uint8_t geo_key_base[sizeof(grn_geo_point)];
 
     latitude_distance = geo_point1->latitude - geo_point2->latitude;
     longitude_distance = geo_point2->longitude - geo_point1->longitude;
     if (latitude_distance > longitude_distance) {
       direction = MESH_LATITUDE;
-      distance = latitude_distance;
-      geo_point_base.latitude = geo_point1->latitude;
-      geo_point_base.longitude = geo_point1->longitude + distance;
-      end = geo_point2->latitude;
+      geo_point_input = geo_point2;
+      geo_point_base.latitude = geo_point2->latitude;
+      geo_point_base.longitude = geo_point2->longitude - longitude_distance;
     } else {
       direction = MESH_LONGITUDE;
-      distance = longitude_distance;
-      geo_point_base.latitude = geo_point1->latitude + distance;
+      geo_point_input = geo_point1;
+      geo_point_base.latitude = geo_point1->latitude + latitude_distance;
       geo_point_base.longitude = geo_point1->longitude;
-      end = geo_point2->longitude;
     }
-    grn_gton(geo_key1, geo_point1, sizeof(grn_geo_point));
+    grn_gton(geo_key_input, geo_point_input, sizeof(grn_geo_point));
     grn_gton(geo_key_base, &geo_point_base, sizeof(grn_geo_point));
-    diff_bit = compute_diff_bit(geo_key1, geo_key_base);
-    compute_min_and_max(geo_point1, diff_bit + 2, &geo_point_min, &geo_point_max);
+    diff_bit = compute_diff_bit(geo_key_input, geo_key_base);
+    compute_min_and_max(geo_point_input, diff_bit,
+                        &geo_point_min, &geo_point_max);
     if (direction == MESH_LATITUDE) {
-      start = geo_point_max.latitude;
+      start = geo_point2->latitude;
+      end = geo_point_max.latitude;
+      distance = geo_point_max.latitude - geo_point_min.latitude + 1;
     } else {
-      start = geo_point_max.longitude;
+      start = geo_point_min.longitude;
+      end = geo_point2->longitude;
+      distance = geo_point_max.longitude - geo_point_min.longitude + 1;
     }
-    memcpy(&geo_point_base, &geo_point_max, sizeof(grn_geo_point));
+    memcpy(&geo_point_base, &geo_point_min, sizeof(grn_geo_point));
 #ifdef GEO_DEBUG
     printf("direction: %s\n",
            direction == MESH_LATITUDE ? "latitude" : "longitude");
@@ -689,17 +690,15 @@ grn_geo_search_in_rectangle(grn_ctx *ctx, grn_obj *obj, grn_obj **args, int narg
     grn_p_geo_point(ctx, geo_point1);
     printf("bottom-right: ");
     grn_p_geo_point(ctx, geo_point2);
+    printf("start:    %10d\n", start);
+    printf("end:      %10d\n", end);
+    printf("distance: %10d\n", distance);
 #endif
 
     for (i = start; i < end + distance; i += distance) {
       grn_table_cursor *tc;
-      if (direction == MESH_LATITUDE) {
-        geo_point_base.latitude += direction;
-      } else {
-        geo_point_base.longitude += direction;
-      }
       tc = grn_table_cursor_open(ctx, pat,
-                                 &geo_point_base, diff_bit + 1,
+                                 &geo_point_base, diff_bit,
                                  NULL, 0,
                                  0, -1,
                                  GRN_CURSOR_PREFIX|GRN_CURSOR_SIZE_BY_BIT);
@@ -708,16 +707,20 @@ grn_geo_search_in_rectangle(grn_ctx *ctx, grn_obj *obj, grn_obj **args, int narg
         grn_id tid;
         grn_geo_point pos;
         while ((tid = grn_table_cursor_next(ctx, tc))) {
-          if (i == start || end < i) {
-            grn_table_get_key(ctx, pat, tid, &pos, sizeof(grn_geo_point));
-            if (!grn_geo_in_rectangle_raw(ctx, &pos, geo_point1, geo_point2)) {
-              continue;
-            }
+          grn_table_get_key(ctx, pat, tid, &pos, sizeof(grn_geo_point));
+          if (!grn_geo_in_rectangle_raw(ctx, &pos, geo_point1, geo_point2)) {
+            continue;
           }
+          inspect_tid(ctx, tid, &pos, 0);
           grn_ii_at(ctx, (grn_ii *)obj, tid, (grn_hash *)res, op);
         }
         grn_table_cursor_close(ctx, tc);
       }
+      if (direction == MESH_LATITUDE) {
+        geo_point_base.latitude += distance;
+      } else {
+        geo_point_base.longitude += distance;
+      }
     }
   }
 exit :

  Modified: test/unit/story/test-taiyaki.c (+40 -7)
===================================================================
--- test/unit/story/test-taiyaki.c    2010-08-12 02:48:01 +0000 (b5b40b4)
+++ test/unit/story/test-taiyaki.c    2010-08-12 08:20:13 +0000 (3925a75)
@@ -22,7 +22,8 @@
 #include "../lib/grn-assertions.h"
 
 void test_in_circle(void);
-void test_in_rectangle(void);
+void test_in_rectangle_long_longitude(void);
+void test_in_rectangle_long_latitude(void);
 void test_sort(void);
 void test_filter_by_tag_and_sort_by_distance_from_tokyo_tocho(void);
 void test_but_white(void);
@@ -123,7 +124,7 @@ test_in_circle(void)
 }
 
 void
-test_in_rectangle(void)
+test_in_rectangle_long_longitude(void)
 {
   gdouble takada_no_baba_latitude = 35.7121;
   gdouble takada_no_baba_longitude = 139.7038;
@@ -134,16 +135,17 @@ test_in_rectangle(void)
 
   cut_assert_equal_string(
     "[[[3],"
-    "[[\"name\",\"ShortText\"],[\"_score\",\"Int32\"]],"
-    "[\"たいやき神田達磨 八重洲店\",3273],"
-    "[\"銀座 かずや\",3713],"
-    "[\"たい焼き鉄次 大丸東京店\",3732]"
+    "[[\"name\",\"ShortText\"],[\"_score\",\"Int32\"],"
+     "[\"location\",\"WGS84GeoPoint\"]],"
+    "[\"たいやき神田達磨 八重洲店\",3273,\"130094061x505025099\"],"
+    "[\"銀座 かずや\",3713,\"130055008x504968095\"],"
+    "[\"たい焼き鉄次 大丸東京店\",3732,\"130089012x505045070\"]"
     "]]",
     send_command(
       cut_take_printf(
         "select Shops "
         "--sortby '+_score, +name' "
-        "--output_columns 'name, _score' "
+        "--output_columns 'name, _score, location' "
         "--filter 'geo_in_rectangle(location, \"%s\", \"%s\")' "
         "--scorer '_score=geo_distance(location, \"%s\")'",
         grn_test_location_string(takada_no_baba_latitude,
@@ -153,6 +155,37 @@ test_in_rectangle(void)
 }
 
 void
+test_in_rectangle_long_latitude(void)
+{
+  gdouble sugamo_latitude = 35.73360;
+  gdouble sugamo_longitude = 139.7394;
+  gdouble daiba_latitude = 35.62614;
+  gdouble daiba_longitude = 139.7714;
+  gdouble budoukan_latitude = 35.69328;
+  gdouble budoukan_longitude = 139.74968;
+
+  cut_assert_equal_string(
+    "[[[4],"
+    "[[\"name\",\"ShortText\"],[\"_score\",\"Int32\"],"
+     "[\"location\",\"WGS84GeoPoint\"]],"
+    "[\"たいやき神田達磨 八重洲店\",3273,\"130094061x505025099\"],"
+    "[\"銀座 かずや\",3713,\"130055008x504968095\"],"
+    "[\"根津のたいやき\",4754,\"130322053x504985073\"],"
+    "[\"築地 さのきや\",5244,\"130019020x505027021\"]"
+    "]]",
+    send_command(
+      cut_take_printf(
+        "select Shops "
+        "--sortby '+_score, +name' "
+        "--output_columns 'name, _score, location' "
+        "--filter 'geo_in_rectangle(location, \"%s\", \"%s\")' "
+        "--scorer '_score=geo_distance(location, \"%s\")'",
+        grn_test_location_string(sugamo_latitude, sugamo_longitude),
+        grn_test_location_string(daiba_latitude, daiba_longitude),
+        grn_test_location_string(budoukan_latitude, budoukan_longitude))));
+}
+
+void
 test_sort(void)
 {
   gdouble yurakucho_latitude = 35.67487;




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