49 compute_diff_bit(uint8_t *geo_key1, uint8_t *geo_key2)
51 int i, j, diff_bit = 0;
54 if (geo_key1[i] != geo_key2[i]) {
56 for (j = 0; j < 8; j++) {
57 if ((geo_key1[i] & (1 << (7 - j))) != (geo_key2[
i] & (1 << (7 - j)))) {
66 return i * 8 + diff_bit;
70 compute_min_and_max_key(uint8_t *key_base,
int diff_bit,
71 uint8_t *key_min, uint8_t *key_max)
73 int diff_byte, diff_bit_mask;
75 diff_byte = diff_bit / 8;
76 diff_bit_mask = 0xff >> (diff_bit % 8);
79 if (key_min) { memcpy(key_min, key_base, diff_byte); }
80 if (key_max) { memcpy(key_max, key_base, diff_byte); }
83 memcpy(key_min, key_base, diff_byte + 1);
84 key_min[diff_byte] &= ~diff_bit_mask;
85 memset(key_min + diff_byte + 1, 0,
90 memcpy(key_max, key_base, diff_byte + 1);
91 key_max[diff_byte] |= diff_bit_mask;
92 memset(key_max + diff_byte + 1, 0xff,
107 compute_min_and_max_key(geo_key_base, diff_bit,
108 geo_min ? geo_key_min : NULL,
109 geo_max ? geo_key_max : NULL);
128 printf(
"mesh: %d:%d\n", n, key_size);
133 compute_min_and_max(key, key_size, &min, &max);
152 printf(
"tid: %d:%g", tid, d);
160 for (i = 0; i < 8; i++) {
162 for (j = 0; j < 8; j++) {
163 printf(
"%d", (key[i] & (1 << (7 - j))) >> (7 - j));
175 for (i = 0; i < target_bit; i++) {
177 if (i > 0 && i % 8 == 0) {
181 if (i > 0 && i % 8 == 0) {
198 printf(
" target bit: %d\n", entry->
target_bit);
200 #define INSPECT_STATUS_FLAG(name) \
201 ((entry->status_flags & GRN_GEO_CURSOR_ENTRY_STATUS_ ## name) ? "true" : "false")
203 printf(
" top included: %s\n", INSPECT_STATUS_FLAG(TOP_INCLUDED));
204 printf(
"bottom included: %s\n", INSPECT_STATUS_FLAG(BOTTOM_INCLUDED));
205 printf(
" left included: %s\n", INSPECT_STATUS_FLAG(LEFT_INCLUDED));
206 printf(
" right included: %s\n", INSPECT_STATUS_FLAG(RIGHT_INCLUDED));
207 printf(
" latitude inner: %s\n", INSPECT_STATUS_FLAG(LATITUDE_INNER));
208 printf(
"longitude inner: %s\n", INSPECT_STATUS_FLAG(LONGITUDE_INNER));
210 #undef INSPECT_STATUS_FLAG
215 uint8_t *top_left_key, uint8_t *bottom_right_key,
221 printf(
"top-left: ");
223 printf(
"bottom-right: ");
225 printf(
"next-entry-0: ");
227 printf(
"next-entry-1: ");
233 # define inspect_mesh(...)
234 # define inspect_mesh_entry(...)
235 # define inspect_tid(...)
236 # define inspect_key(...)
237 # define print_key_mark(...)
238 # define inspect_cursor_entry(...)
239 # define inspect_cursor_entry_targets(...)
248 double *d_far,
int *diff_bit)
250 int i = 0, diff_bit_prev, diff_bit_current;
275 diff_bit_prev = diff_bit_current;
276 diff_bit_current = compute_diff_bit(geo_key_curr, geo_key_prev);
278 printf(
"diff: %d:%d:%d\n", *diff_bit, diff_bit_prev, diff_bit_current);
280 if ((diff_bit_current % 2) == 1) {
283 if (diff_bit_current < diff_bit_prev && *diff_bit > diff_bit_current) {
288 *diff_bit = diff_bit_current;
299 for (p = ep; entries < p && p[-1].
d > d; p--) {
332 double d_far,
int diff_bit,
333 int include_base_point_mesh,
338 int lat_diff, lng_diff;
342 compute_min_and_max(base_point, diff_bit - 2, &geo_min, &geo_max);
389 printf(
"diff: %d (%d, %d)\n", diff_bit, lat_diff, lng_diff);
392 printf(
"position: left-top\n");
395 printf(
"position: right-top\n");
398 printf(
"position: right-bottom\n");
401 printf(
"position: left-bottom\n");
408 #define add_mesh(lat_diff_,lng_diff_,key_size_) do {\
409 meshes[n_meshes].key.latitude = geo_base.latitude + (lat_diff_);\
410 meshes[n_meshes].key.longitude = geo_base.longitude + (lng_diff_);\
411 meshes[n_meshes].key_size = key_size_;\
425 add_mesh(-lat_diff, -lng_diff, diff_bit);
458 int i, j, n_sub_meshes, lat, lat_min, lat_max, lng, lng_min, lng_max;
460 for (i = -5; i < 5; i++) {
461 lat_min = ((lat_diff + 1) / 2) *
i;
462 lat_max = ((lat_diff + 1) / 2) * (i + 1) - 1;
463 for (j = -5; j < 5; j++) {
464 if (-3 < i && i < 2 && -3 < j && j < 2) {
467 lng_min = ((lng_diff + 1) / 2) * j;
468 lng_max = ((lng_diff + 1) / 2) * (j + 1) - 1;
471 }
else if (geo_base.
latitude + lat_max < base_point->latitude) {
478 }
else if (geo_base.
longitude + lng_max < base_point->longitude) {
486 &(meshes[n_meshes].key));
489 printf(
"sub-mesh: %d: (%d,%d): (%d,%d;%d,%d)\n",
497 meshes[n_meshes].
key_size = diff_bit + 2;
516 double d_far,
int diff_bit)
522 n_meshes = grn_geo_get_meshes_for_circle(ctx, base_point, d_far, diff_bit,
525 ep = entries + n_entries;
529 &(meshes[n_meshes].key),
530 meshes[n_meshes].key_size,
550 for (p = ep; entries < p && p[-1].
d > d; p--) {
587 if (!accessor->
next) {
599 grn_geo_table_sort_by_distance(
grn_ctx *ctx,
610 int n_entries = 0, e = offset + limit;
620 n = grn_geo_table_sort_detect_far_point(ctx, table, index, pat,
621 entries, pc, e, accessorp,
625 n = grn_geo_table_sort_collect_points(ctx, table, index, pat,
626 entries, n, e, accessorp,
627 base_point, d_far, diff_bit);
629 need_not_indexed_records = offset + limit > n;
630 if (need_not_indexed_records) {
634 for (ep = entries + offset;
635 n_entries < limit && ep < entries + n;
639 if (indexed_records) {
641 indexed_records = NULL;
646 if (indexed_records) {
652 if (indexed_records) {
660 if (n_entries == limit) {
677 int i = 0, e = offset + limit;
679 if (n_keys == 2 && (index = find_geo_sort_index(ctx, keys->
key))) {
706 i = grn_geo_table_sort_by_distance(ctx, table, index, pat,
707 pc, accessorp, base_point,
708 offset, limit, result);
730 if ((strncmp(
"rectangle", name, size) == 0) ||
731 (strncmp(
"rect", name, size) == 0)) {
733 }
else if ((strncmp(
"sphere", name, size) == 0) ||
734 (strncmp(
"sphr", name, size) == 0)) {
736 }
else if ((strncmp(
"ellipsoid", name, size) == 0) ||
737 (strncmp(
"ellip", name, size) == 0)) {
741 "geo distance approximate type must be one of "
742 "[rectangle, rect, sphere, sphr, ellipsoid, ellip]"
763 if (!(nargs == 4 || nargs == 5)) {
765 "geo_in_circle(): requires 3 or 4 arguments but was <%d> arguments",
773 int column_name_size;
774 point_column = args[1];
778 "geo_in_circle(): index for <%.*s> is missing",
779 column_name_size, column_name);
790 grn_obj *center_point, *distance;
791 center_point = args[2];
800 grn_geo_resolve_distance_raw_func (
grn_ctx *ctx,
806 switch (approximate_type) {
824 return distance_raw_func;
834 double center_longitude, center_latitude;
836 grn_obj *pat, *point_on_circle = NULL, center_point_, point_on_circle_;
850 strcpy(name,
"(null)");
851 name_size = strlen(name);
854 "geo_in_circle(): index table must be "
855 "TokyoGeoPoint or WGS84GeoPoint key type table: <%.*s>",
863 center_point = ¢er_point_;
869 distance_raw_func = grn_geo_resolve_distance_raw_func(ctx,
872 if (!distance_raw_func) {
874 "unknown approximate type: <%d>", approximate_type);
909 point_on_circle = &point_on_circle_;
914 if (!point_on_circle) { point_on_circle = distance; }
917 d = distance_raw_func(ctx, center, &on_circle);
918 if (point_on_circle == &point_on_circle_) {
926 int n_meshes, diff_bit;
935 diff_bit = compute_diff_bit(geo_key1, geo_key2);
937 printf(
"center point: ");
939 printf(
"point on circle: ");
941 printf(
"diff: %d\n", diff_bit);
943 if ((diff_bit % 2) == 1) {
946 n_meshes = grn_geo_get_meshes_for_circle(ctx, center,
952 &(meshes[n_meshes].key),
953 meshes[n_meshes].key_size,
962 double point_distance;
964 point_distance = distance_raw_func(ctx, &point, center);
965 if (point_distance <= d) {
985 grn_obj *top_left_point, *bottom_right_point;
986 top_left_point = args[2];
987 bottom_right_point = args[3];
989 top_left_point, bottom_right_point,
993 "geo_in_rectangle(): requires 3 arguments but was <%d> arguments",
1003 const char *process_name,
1020 if (domain_object) {
1024 strcpy(name,
"(null)");
1025 name_size = strlen(name);
1028 "%s: index table must be "
1029 "TokyoGeoPoint or WGS84GeoPoint key type table: <%.*s>",
1030 process_name, name_size, name);
1063 "%s: negative coordinate is not implemented.", process_name);
1069 "%s: top left point's latitude is too big: "
1070 "<%d>(max:%d): (%d,%d) (%d,%d)",
1080 "%s: top left point's longitude is too big: "
1081 "<%d>(max:%d): (%d,%d) (%d,%d)",
1091 "%s: bottom right point's latitude is too big: "
1092 "<%d>(max:%d): (%d,%d) (%d,%d)",
1102 "%s: bottom right point's longitude is too big: "
1103 "<%d>(max:%d): (%d,%d) (%d,%d)",
1113 int latitude_distance, longitude_distance;
1127 longitude_distance = bottom_right->
longitude - top_left->longitude;
1128 if (latitude_distance > longitude_distance) {
1129 geo_point_input = bottom_right;
1133 geo_point_input = top_left;
1134 base.
latitude = top_left->latitude - latitude_distance;
1139 diff_bit = compute_diff_bit(geo_key_input, geo_key_base);
1140 compute_min_and_max(&base, diff_bit, &(data->
min), &(data->
max));
1145 compute_diff_bit(geo_key_top_left, geo_key_bottom_right) - 1;
1156 printf(
"top-left: ");
1158 printf(
"bottom-right: ");
1161 printf(
"distance(latitude): %10d\n", latitude_distance);
1162 printf(
"distance(longitude): %10d\n", longitude_distance);
1170 #define SAME_BIT_P(a, b, n_bit)\
1171 ((((uint8_t *)(a))[(n_bit) / 8] & (1 << (7 - ((n_bit) % 8)))) ==\
1172 (((uint8_t *)(b))[(n_bit) / 8] & (1 << (7 - ((n_bit) % 8)))))
1174 #define CURSOR_ENTRY_UPDATE_STATUS(entry, name, other_key) do {\
1175 if (SAME_BIT_P((entry)->key, (other_key), (entry)->target_bit)) {\
1176 (entry)->status_flags |= GRN_GEO_CURSOR_ENTRY_STATUS_ ## name;\
1178 (entry)->status_flags &= ~GRN_GEO_CURSOR_ENTRY_STATUS_ ## name;\
1182 #define CURSOR_ENTRY_CHECK_STATUS(entry, name)\
1183 ((entry)->status_flags & GRN_GEO_CURSOR_ENTRY_STATUS_ ## name)
1184 #define CURSOR_ENTRY_IS_INNER(entry)\
1185 (((entry)->status_flags &\
1186 (GRN_GEO_CURSOR_ENTRY_STATUS_LATITUDE_INNER |\
1187 GRN_GEO_CURSOR_ENTRY_STATUS_LONGITUDE_INNER)) ==\
1188 (GRN_GEO_CURSOR_ENTRY_STATUS_LATITUDE_INNER |\
1189 GRN_GEO_CURSOR_ENTRY_STATUS_LONGITUDE_INNER))
1190 #define CURSOR_ENTRY_INCLUDED_IN_LATITUDE_DIRECTION(entry)\
1191 ((entry)->status_flags &\
1192 (GRN_GEO_CURSOR_ENTRY_STATUS_LATITUDE_INNER |\
1193 GRN_GEO_CURSOR_ENTRY_STATUS_TOP_INCLUDED |\
1194 GRN_GEO_CURSOR_ENTRY_STATUS_BOTTOM_INCLUDED))
1195 #define CURSOR_ENTRY_INCLUDED_IN_LONGITUDE_DIRECTION(entry)\
1196 ((entry)->status_flags &\
1197 (GRN_GEO_CURSOR_ENTRY_STATUS_LONGITUDE_INNER |\
1198 GRN_GEO_CURSOR_ENTRY_STATUS_LEFT_INCLUDED |\
1199 GRN_GEO_CURSOR_ENTRY_STATUS_RIGHT_INCLUDED))
1201 #define SET_N_BIT(a, n_bit)\
1202 (((uint8_t *)(a))[((n_bit) / 8)] ^= (1 << (7 - ((n_bit) % 8))))
1204 #define N_BIT(a, n_bit)\
1205 ((((uint8_t *)(a))[((n_bit) / 8)] &\
1206 (1 << (7 - ((n_bit) % 8)))) >> (1 << (7 - ((n_bit) % 8))))
1222 if (in_rectangle_data_prepare(ctx, index, top_left_point, bottom_right_point,
1223 "geo_in_rectangle()", &data)) {
1230 "[geo][cursor][in-rectangle] failed to allocate memory for geo cursor");
1243 cursor->
rest = limit;
1267 const char *minimum_reduce_bit_env;
1269 minimum_reduce_bit_env = getenv(
"GRN_GEO_IN_RECTANGLE_MINIMUM_REDUCE_BIT");
1270 if (minimum_reduce_bit_env) {
1295 grn_geo_cursor_entry_next_push(
grn_ctx *ctx,
1325 grn_geo_cursor_entry_next(
grn_ctx *ctx,
1410 printf(
"%d: force stopping to reduce a mesh\n", entry->
target_bit);
1417 printf(
"%d: inner entries\n", entry->
target_bit);
1430 &next_entry0, &next_entry1);
1456 if (grn_geo_cursor_entry_next_push(ctx, cursor, &next_entry1)) {
1459 printf(
"%d: latitude: push 1\n", next_entry1.
target_bit);
1464 if (grn_geo_cursor_entry_next_push(ctx, cursor, &next_entry0)) {
1467 printf(
"%d: latitude: push 0\n", next_entry0.
target_bit);
1494 if (grn_geo_cursor_entry_next_push(ctx, cursor, &next_entry1)) {
1497 printf(
"%d: longitude: push 1\n", next_entry1.
target_bit);
1502 if (grn_geo_cursor_entry_next_push(ctx, cursor, &next_entry0)) {
1505 printf(
"%d: longitude: push 0\n", next_entry0.
target_bit);
1519 stack_entry = &(cursor->
entries[
i]);
1530 printf(
"%d: pop entry\n", entry->
target_bit);
1561 if (cursor->
rest == 0) {
1577 if (!grn_geo_cursor_entry_next(ctx, cursor, &entry)) {
1619 if (cursor->
offset == 0) {
1621 keep_each = callback(ctx, posting, user_data);
1622 if (cursor->
rest > 0) {
1623 if (--(cursor->
rest) == 0) {
1647 *return_posting = posting;
1655 grn_geo_cursor_each(ctx, geo_cursor, grn_geo_cursor_next_callback, &posting);
1699 top_left_point, bottom_right_point,
1705 grn_geo_cursor_each(ctx, cursor, grn_geo_select_in_rectangle_callback,
1738 memcpy(geo_point, key, key_size);
1761 if (in_rectangle_data_prepare(ctx, index, top_left_point, bottom_right_point,
1762 "grn_geo_estimate_in_rectangle()", &data)) {
1768 if (total_records > 0) {
1770 int select_latitude_distance, select_longitude_distance;
1771 int total_latitude_distance, total_longitude_distance;
1772 double select_ratio;
1773 double estimated_n_records;
1795 if (select_latitude_distance < total_latitude_distance) {
1796 select_ratio *= ((double)select_latitude_distance /
1797 (
double)total_latitude_distance);
1799 if (select_longitude_distance < total_longitude_distance) {
1800 select_ratio *= ((double)select_longitude_distance /
1801 (
double)total_longitude_distance);
1803 estimated_n_records = ceil(total_records * select_ratio);
1804 n = (int)estimated_n_records;
1819 grn_obj center_, radius_or_point_;
1830 distance_raw_func = grn_geo_resolve_distance_raw_func(ctx,
1833 if (!distance_raw_func) {
1835 "unknown approximate type: <%d>", approximate_type);
1838 d = distance_raw_func(ctx,
1862 radius_or_point = &radius_or_point_;
1866 if (domain != radius_or_point->
header.
domain) {
goto exit; }
1867 r = d <= distance_raw_func(ctx,
1896 grn_obj top_left_, bottom_right_;
1902 top_left = &top_left_;
1907 bottom_right = &bottom_right_;
1945 geo_longitude_distance_type(
int start_longitude,
int end_longitude)
1950 if (start_longitude >= 0) {
1951 diff_longitude = abs(start_longitude - end_longitude);
1953 diff_longitude = abs(end_longitude - start_longitude);
1955 east_to_west = start_longitude > 0 && end_longitude < 0;
1956 west_to_east = start_longitude < 0 && end_longitude > 0;
1957 if (start_longitude != end_longitude &&
1958 (east_to_west || west_to_east) &&
1969 #define QUADRANT_1ST_WITH_AXIS(point) \
1970 (point->longitude >= 0) && (point->latitude >= 0)
1971 #define QUADRANT_2ND_WITH_AXIS(point) \
1972 (point->longitude <= 0) && (point->latitude >= 0)
1973 #define QUADRANT_3RD_WITH_AXIS(point) \
1974 (point->longitude <= 0) && (point->latitude <= 0)
1975 #define QUADRANT_4TH_WITH_AXIS(point) \
1976 (point->longitude >= 0) && (point->latitude <= 0)
2028 #undef QUADRANT_1ST_WITH_AXIS
2029 #undef QUADRANT_2ND_WITH_AXIS
2030 #undef QUADRANT_3RD_WITH_AXIS
2031 #undef QUADRANT_4TH_WITH_AXIS
2034 static inline double
2035 geo_distance_rectangle_square_root(
double start_longitude,
double start_latitude,
2036 double end_longitude,
double end_latitude)
2038 double diff_longitude;
2041 diff_longitude = end_longitude - start_longitude;
2042 x = diff_longitude * cos((start_latitude + end_latitude) * 0.5);
2043 y = end_latitude - start_latitude;
2044 return sqrt((x * x) + (y * y));
2047 static inline double
2048 geo_distance_rectangle_short_dist_type(
quadrant_type quad_type,
2049 double lng1,
double lat1,
2050 double lng2,
double lat2)
2053 double longitude_delta, latitude_delta;
2059 longitude_delta = lng2 - lng1;
2060 if (longitude_delta > 0 || longitude_delta < 0) {
2062 distance = geo_distance_rectangle_square_root(lng1,
2067 distance = geo_distance_rectangle_square_root(lng2,
2073 latitude_delta = fabs(lat1) + fabs(lat2);
2074 distance = sqrt(latitude_delta * latitude_delta) *
GRN_GEO_RADIUS;
2078 distance = geo_distance_rectangle_square_root(lng1,
2084 distance = geo_distance_rectangle_square_root(lng2,
2093 distance = geo_distance_rectangle_square_root(lng1,
2097 }
else if (lat2 < lat1) {
2098 distance = geo_distance_rectangle_square_root(lng2,
2103 longitude_delta = lng2 - lng1;
2104 distance = longitude_delta * cos(lat1);
2108 distance = geo_distance_rectangle_square_root(lng1,
2116 static inline double
2117 geo_distance_rectangle_long_dist_type(
quadrant_type quad_type,
2118 double lng1,
double lat1,
2119 double lng2,
double lat2)
2121 #define M_2PI 6.28318530717958647692
2128 distance = geo_distance_rectangle_square_root(lng2 + M_2PI,
2133 distance = geo_distance_rectangle_square_root(lng1,
2141 distance = geo_distance_rectangle_square_root(lng2,
2146 distance = geo_distance_rectangle_square_root(lng1 + M_2PI,
2152 distance = geo_distance_rectangle_square_root(lng2 + M_2PI,
2157 distance = geo_distance_rectangle_square_root(lng1 + M_2PI,
2162 distance = geo_distance_rectangle_square_root(lng2,
2167 distance = geo_distance_rectangle_square_root(lng1,
2173 distance = geo_distance_rectangle_square_root(lng1,
2178 distance = geo_distance_rectangle_square_root(lng2,
2193 double lng1, lat1, lng2, lat2, distance;
2201 quad_type = geo_quadrant_type(point1, point2);
2203 distance = geo_distance_rectangle_square_root(lng1,
2208 dist_type = geo_longitude_distance_type(point1->
longitude,
2211 distance = geo_distance_rectangle_short_dist_type(quad_type,
2215 distance = geo_distance_rectangle_long_dist_type(quad_type,
2227 double lng1, lat1, lng2, lat2, x, y;
2233 x = sin(fabs(lng2 - lng1) * 0.5);
2234 y = sin(fabs(lat2 - lat1) * 0.5);
2235 return asin(sqrt((y * y) + cos(lat1) * cos(lat2) * x * x)) * 2 *
GRN_GEO_RADIUS;
2241 int c1,
int c2,
double c3)
2243 double lng1, lat1, lng2, lat2, p, q, r, m, n, x, y;
2249 p = (lat1 + lat2) * 0.5;
2250 q = (1 - c3 * sin(p) * sin(p));
2254 x = n * cos(p) * fabs(lng1 - lng2);
2255 y = m * fabs(lat1 - lat2);
2256 return sqrt((x * x) + (y * y));
2314 if (domain1 != domain2) {
2344 if (point1_initialized) {
2347 if (point2_initialized) {
2374 if (point2_initialized) {
2407 if (point2_initialized) {