null+****@clear*****
null+****@clear*****
2011年 9月 24日 (土) 18:09:37 JST
Kouhei Sutou 2011-09-24 09:09:37 +0000 (Sat, 24 Sep 2011)
New Revision: 32433ca22e9cf0a52e6b7b56acaed294a60fb91b
Log:
[geo] export grn_geo_select_in_circle() and grn_geo_select_in_rectangle().
Modified files:
include/groonga.h
lib/expr.c
lib/geo.c
lib/geo.h
test/unit/story/test-taiyaki.c
Modified: include/groonga.h (+59 -5)
===================================================================
--- include/groonga.h 2011-09-17 05:09:38 +0000 (7e4356c)
+++ include/groonga.h 2011-09-24 09:09:37 +0000 (e7987e2)
@@ -1715,6 +1715,65 @@ GRN_API grn_obj *grn_obj_open(grn_ctx *ctx, unsigned char type, grn_obj_flags fl
GRN_API int grn_column_index(grn_ctx *ctx, grn_obj *column, grn_operator op,
grn_obj **indexbuf, int buf_size, int *section);
+/* geo */
+
+typedef struct {
+ int latitude;
+ int longitude;
+} grn_geo_point;
+
+
+/**
+ * grn_geo_select_in_circle:
+ * @index: the index column for TokyoGeoPoint or WGS84GeoPpoint type.
+ * @center_point: the center point of the target circle. (ShortText, Text,
+ * LongText, TokyoGeoPoint or WGS84GeoPoint)
+ * @distance: the radius of the target circle (Int32,
+ * UInt32, Int64, UInt64 or Float) or the point
+ * on the circumference of the target circle. (ShortText, Text, LongText,
+ * TokyoGeoPoint or WGS84GeoPoint)
+ * @res: the table to store found record IDs. It must be
+ * GRN_TABLE_HASH_KEY type table.
+ * @op: the operator for matched records.
+ *
+ * It selects records that are in the circle specified by
+ * @center_point and @distance from @center_point. Records
+ * are search by @index. Found records are added to @res
+ * table with @op operation.
+ **/
+GRN_API grn_rc grn_geo_select_in_circle(grn_ctx *ctx,
+ grn_obj *index,
+ grn_obj *center_point,
+ grn_obj *distance,
+ grn_obj *res,
+ grn_operator op);
+
+/**
+ * grn_geo_select_in_rectangle:
+ * @index: the index column for TokyoGeoPoint or WGS84GeoPpoint type.
+ * @top_left_point: the top left point of the target
+ * rectangle. (ShortText, Text, LongText, TokyoGeoPoint or
+ * WGS84GeoPoint)
+ * @bottom_right_point: the bottom right point of the target
+ * rectangle. (ShortText, Text, LongText, TokyoGeoPoint or
+ * WGS84GeoPoint)
+ * @res: the table to store found record IDs. It must be
+ * GRN_TABLE_HASH_KEY type table.
+ * @op: the operator for matched records.
+ *
+ * It selects records that are in the rectangle specified by
+ * @top_left_point and @bottom_right_point. Records are
+ * search by @index. Found records are added to @res table
+ * with @op operation.
+ **/
+GRN_API grn_rc grn_geo_select_in_rectangle(grn_ctx *ctx,
+ grn_obj *index,
+ grn_obj *top_left_point,
+ grn_obj *bottom_right_point,
+ grn_obj *res,
+ grn_operator op);
+
+
/* query & snippet */
#ifndef GRN_QUERY_AND
@@ -2072,11 +2131,6 @@ GRN_API grn_rc grn_text_otoj(grn_ctx *ctx, grn_obj *bulk, grn_obj *obj,
#define GRN_GEO_MSEC2DEGREE(msec)\
((((int)(msec)) / 3600.0) * 0.001)
-typedef struct {
- int latitude;
- int longitude;
-} grn_geo_point;
-
#define GRN_GEO_POINT_SET(ctx,obj,_latitude,_longitude) do {\
grn_geo_point _val;\
_val.latitude = (int)(_latitude);\
Modified: lib/expr.c (+6 -4)
===================================================================
--- lib/expr.c 2011-09-17 05:09:38 +0000 (97320b4)
+++ lib/expr.c 2011-09-24 09:09:37 +0000 (15ad053)
@@ -4175,12 +4175,14 @@ grn_table_select(grn_ctx *ctx, grn_obj *table, grn_obj *expr,
GRN_TABLE_MAX_KEY_SIZE);
/* geo_in_circle and geo_in_rectangle only */
if (len == 13 && !memcmp(buf, "geo_in_circle", 13)) {
- grn_geo_search_in_circle(ctx, index, si->args, si->nargs, res,
- si->logical_op);
+ /* TODO: error check */
+ grn_selector_geo_in_circle(ctx, index, si->args, si->nargs,
+ res, si->logical_op);
done++;
} else if (len == 16 && !memcmp(buf, "geo_in_rectangle", 16)) {
- grn_geo_search_in_rectangle(ctx, index, si->args, si->nargs,
- res, si->logical_op);
+ /* TODO: error check */
+ grn_selector_geo_in_rectangle(ctx, index, si->args, si->nargs,
+ res, si->logical_op);
done++;
}
}
Modified: lib/geo.c (+201 -121)
===================================================================
--- lib/geo.c 2011-09-17 05:09:38 +0000 (5646aac)
+++ lib/geo.c 2011-09-24 09:09:37 +0000 (1468af7)
@@ -522,75 +522,115 @@ grn_geo_table_sort(grn_ctx *ctx, grn_obj *table, int offset, int limit,
}
grn_rc
-grn_geo_search_in_circle(grn_ctx *ctx, grn_obj *obj, grn_obj **args, int nargs,
+grn_selector_geo_in_circle(grn_ctx *ctx, grn_obj *obj, grn_obj **args, int nargs,
+ grn_obj *res, grn_operator op)
+{
+ if (nargs == 4) {
+ grn_obj *center_point, *distance;
+ center_point = args[2];
+ distance = args[3];
+ grn_geo_select_in_circle(ctx, obj, center_point, distance, res, op);
+ } else {
+ ERR(GRN_INVALID_ARGUMENT,
+ "geo_in_circle(): requires 3 arguments but was <%d> arguments",
+ nargs - 1);
+ }
+ return ctx->rc;
+}
+
+grn_rc
+grn_geo_select_in_circle(grn_ctx *ctx, grn_obj *index,
+ grn_obj *center_point, grn_obj *distance,
grn_obj *res, grn_operator op)
{
grn_id domain;
- double lng0, lat0, lng1, lat1, lng2, lat2, x, y, d;
- grn_obj *proc, *pat, *pos1, *pos2, pos1_, pos2_;
- grn_geo_point *geo_point1, geo_point2;
- if (nargs != 4) { goto exit; }
- pat = grn_ctx_at(ctx, obj->header.domain);
- proc = args[0];
- pos1 = args[2];
- pos2 = args[3];
+ double center_longitude, center_latitude;
+ double on_circle_longitude, on_circle_latitude;
+ double x, y, d;
+ grn_obj *pat, *point_on_circle = NULL, center_point_, point_on_circle_;
+ grn_geo_point *center, on_circle;
+ pat = grn_ctx_at(ctx, index->header.domain);
domain = pat->header.domain;
- if (domain != GRN_DB_TOKYO_GEO_POINT && domain != GRN_DB_WGS84_GEO_POINT) { goto exit; }
- if (pos1->header.domain != domain) {
- GRN_OBJ_INIT(&pos1_, GRN_BULK, 0, domain);
- if (grn_obj_cast(ctx, pos1, &pos1_, 0)) { goto exit; }
- pos1 = &pos1_;
+ if (domain != GRN_DB_TOKYO_GEO_POINT && domain != GRN_DB_WGS84_GEO_POINT) {
+ char name[GRN_TABLE_MAX_KEY_SIZE];
+ int name_size = 0;
+ grn_obj *domain_object;
+ domain_object = grn_ctx_at(ctx, domain);
+ if (domain_object) {
+ name_size = grn_obj_name(ctx, domain_object, name, GRN_TABLE_MAX_KEY_SIZE);
+ grn_obj_unlink(ctx, domain_object);
+ } else {
+ strcpy(name, "(null)");
+ name_size = strlen(name);
+ }
+ ERR(GRN_INVALID_ARGUMENT,
+ "geo_in_circle(): index table must be "
+ "TokyoGeoPoint or WGS84GeoPoint key type table: <%.*s>",
+ name_size, name);
+ goto exit;
}
- geo_point1 = GRN_GEO_POINT_VALUE_RAW(pos1);
- lng1 = GRN_GEO_INT2RAD(geo_point1->longitude);
- lat1 = GRN_GEO_INT2RAD(geo_point1->latitude);
- switch (pos2->header.domain) {
+
+ if (center_point->header.domain != domain) {
+ GRN_OBJ_INIT(¢er_point_, GRN_BULK, 0, domain);
+ if (grn_obj_cast(ctx, center_point, ¢er_point_, 0)) { goto exit; }
+ center_point = ¢er_point_;
+ }
+ center = GRN_GEO_POINT_VALUE_RAW(center_point);
+ center_longitude = GRN_GEO_INT2RAD(center->longitude);
+ center_latitude = GRN_GEO_INT2RAD(center->latitude);
+ switch (distance->header.domain) {
case GRN_DB_INT32 :
- d = GRN_INT32_VALUE(pos2) / (double)GRN_GEO_RADIUS;
- geo_point2.latitude = geo_point1->latitude + GRN_GEO_RAD2INT(d);
- geo_point2.longitude = geo_point1->longitude;
+ d = GRN_INT32_VALUE(distance) / (double)GRN_GEO_RADIUS;
+ on_circle.latitude = center->latitude + GRN_GEO_RAD2INT(d);
+ on_circle.longitude = center->longitude;
d = d * d;
break;
case GRN_DB_UINT32 :
- d = GRN_UINT32_VALUE(pos2) / (double)GRN_GEO_RADIUS;
- geo_point2.latitude = geo_point1->latitude + GRN_GEO_RAD2INT(d);
- geo_point2.longitude = geo_point1->longitude;
+ d = GRN_UINT32_VALUE(distance) / (double)GRN_GEO_RADIUS;
+ on_circle.latitude = center->latitude + GRN_GEO_RAD2INT(d);
+ on_circle.longitude = center->longitude;
d = d * d;
break;
case GRN_DB_INT64 :
- d = GRN_INT64_VALUE(pos2) / (double)GRN_GEO_RADIUS;
- geo_point2.latitude = geo_point1->latitude + GRN_GEO_RAD2INT(d);
- geo_point2.longitude = geo_point1->longitude;
+ d = GRN_INT64_VALUE(distance) / (double)GRN_GEO_RADIUS;
+ on_circle.latitude = center->latitude + GRN_GEO_RAD2INT(d);
+ on_circle.longitude = center->longitude;
d = d * d;
break;
case GRN_DB_UINT64 :
- d = GRN_UINT64_VALUE(pos2) / (double)GRN_GEO_RADIUS;
- geo_point2.latitude = geo_point1->latitude + GRN_GEO_RAD2INT(d);
- geo_point2.longitude = geo_point1->longitude;
+ d = GRN_UINT64_VALUE(distance) / (double)GRN_GEO_RADIUS;
+ on_circle.latitude = center->latitude + GRN_GEO_RAD2INT(d);
+ on_circle.longitude = center->longitude;
d = d * d;
break;
case GRN_DB_FLOAT :
- d = GRN_FLOAT_VALUE(pos2) / (double)GRN_GEO_RADIUS;
- geo_point2.latitude = geo_point1->latitude + GRN_GEO_RAD2INT(d);
- geo_point2.longitude = geo_point1->longitude;
+ d = GRN_FLOAT_VALUE(distance) / (double)GRN_GEO_RADIUS;
+ on_circle.latitude = center->latitude + GRN_GEO_RAD2INT(d);
+ on_circle.longitude = center->longitude;
d = d * d;
break;
case GRN_DB_SHORT_TEXT :
case GRN_DB_TEXT :
case GRN_DB_LONG_TEXT :
- GRN_OBJ_INIT(&pos2_, GRN_BULK, 0, domain);
- if (grn_obj_cast(ctx, pos2, &pos2_, 0)) { goto exit; }
- pos2 = &pos2_;
+ GRN_OBJ_INIT(&point_on_circle_, GRN_BULK, 0, domain);
+ if (grn_obj_cast(ctx, point_on_circle, &point_on_circle_, 0)) { goto exit; }
+ point_on_circle = &point_on_circle_;
/* fallthru */
case GRN_DB_TOKYO_GEO_POINT :
case GRN_DB_WGS84_GEO_POINT :
- if (domain != pos2->header.domain) { /* todo */ goto exit; }
- GRN_GEO_POINT_VALUE(pos2, geo_point2.latitude, geo_point2.longitude);
- lng2 = GRN_GEO_INT2RAD(geo_point2.longitude);
- lat2 = GRN_GEO_INT2RAD(geo_point2.latitude);
- x = (lng2 - lng1) * cos((lat1 + lat2) * 0.5);
- y = (lat2 - lat1);
+ if (domain != distance->header.domain) { /* todo */ goto exit; }
+ if (!point_on_circle) { point_on_circle = distance; }
+ GRN_GEO_POINT_VALUE(point_on_circle,
+ on_circle.latitude, on_circle.longitude);
+ on_circle_longitude = GRN_GEO_INT2RAD(on_circle.longitude);
+ on_circle_latitude = GRN_GEO_INT2RAD(on_circle.latitude);
+ x = (on_circle_longitude - center_longitude) *
+ cos((center_latitude + on_circle_latitude) * 0.5);
+ y = (on_circle_latitude - center_latitude);
d = ((x * x) + (y * y));
+ if (point_on_circle == &point_on_circle_) {
+ grn_obj_unlink(ctx, point_on_circle);
+ }
break;
default :
goto exit;
@@ -602,21 +642,21 @@ grn_geo_search_in_circle(grn_ctx *ctx, grn_obj *obj, grn_obj **args, int nargs,
uint8_t geo_key1[sizeof(grn_geo_point)];
uint8_t geo_key2[sizeof(grn_geo_point)];
- d_far = grn_geo_distance_raw(ctx, geo_point1, &geo_point2);
- grn_gton(geo_key1, geo_point1, sizeof(grn_geo_point));
- grn_gton(geo_key2, &geo_point2, sizeof(grn_geo_point));
+ d_far = grn_geo_distance_raw(ctx, center, &on_circle);
+ grn_gton(geo_key1, center, sizeof(grn_geo_point));
+ grn_gton(geo_key2, &on_circle, sizeof(grn_geo_point));
diff_bit = compute_diff_bit(geo_key1, geo_key2);
#ifdef GEO_DEBUG
- printf("point1: ");
- grn_p_geo_point(ctx, geo_point1);
- printf("point2: ");
- grn_p_geo_point(ctx, &geo_point2);
+ printf("center point: ");
+ grn_p_geo_point(ctx, center);
+ printf("point on circle: ");
+ grn_p_geo_point(ctx, &on_circle);
printf("diff: %d\n", diff_bit);
#endif
if ((diff_bit % 2) == 1) {
diff_bit--;
}
- n_meshes = grn_geo_get_meshes_for_circle(ctx, geo_point1,
+ n_meshes = grn_geo_get_meshes_for_circle(ctx, center,
d_far, diff_bit, GRN_TRUE,
meshes);
while (n_meshes--) {
@@ -630,16 +670,18 @@ grn_geo_search_in_circle(grn_ctx *ctx, grn_obj *obj, grn_obj **args, int nargs,
inspect_mesh_entry(ctx, meshes, n_meshes);
if (tc) {
grn_id tid;
- grn_geo_point pos;
+ grn_geo_point point;
+ double longitude, latitude;
while ((tid = grn_table_cursor_next(ctx, tc))) {
- grn_table_get_key(ctx, pat, tid, &pos, sizeof(grn_geo_point));
- lng0 = GRN_GEO_INT2RAD(pos.longitude);
- lat0 = GRN_GEO_INT2RAD(pos.latitude);
- x = (lng1 - lng0) * cos((lat0 + lat1) * 0.5);
- y = (lat1 - lat0);
+ grn_table_get_key(ctx, pat, tid, &point, sizeof(grn_geo_point));
+ longitude = GRN_GEO_INT2RAD(point.longitude);
+ latitude = GRN_GEO_INT2RAD(point.latitude);
+ x = (center_longitude - longitude) *
+ cos((latitude + center_latitude) * 0.5);
+ y = (center_latitude - latitude);
if (((x * x) + (y * y)) <= d) {
- inspect_tid(ctx, tid, &pos, (x * x) + (y * y));
- grn_ii_at(ctx, (grn_ii *)obj, tid, (grn_hash *)res, op);
+ inspect_tid(ctx, tid, &point, (x * x) + (y * y));
+ grn_ii_at(ctx, (grn_ii *)index, tid, (grn_hash *)res, op);
}
}
grn_table_cursor_close(ctx, tc);
@@ -657,31 +699,69 @@ typedef enum {
} mesh_direction;
grn_rc
-grn_geo_search_in_rectangle(grn_ctx *ctx, grn_obj *obj, grn_obj **args, int nargs,
+grn_selector_geo_in_rectangle(grn_ctx *ctx, grn_obj *obj,
+ grn_obj **args, int nargs,
+ grn_obj *res, grn_operator op)
+{
+ if (nargs == 4) {
+ grn_obj *top_left_point, *bottom_right_point;
+ top_left_point = args[2];
+ bottom_right_point = args[3];
+ grn_geo_select_in_rectangle(ctx, obj,
+ top_left_point, bottom_right_point,
+ res, op);
+ } else {
+ ERR(GRN_INVALID_ARGUMENT,
+ "geo_in_rectangle(): requires 3 arguments but was <%d> arguments",
+ nargs - 1);
+ }
+ return ctx->rc;
+}
+
+grn_rc
+grn_geo_select_in_rectangle(grn_ctx *ctx, grn_obj *index,
+ grn_obj *top_left_point, grn_obj *bottom_right_point,
grn_obj *res, grn_operator op)
{
grn_id domain;
- grn_obj *proc, *pat, *pos1, *pos2, pos1_, pos2_;
- grn_geo_point *geo_point1, *geo_point2;
- if (nargs != 4) { goto exit; }
- pat = grn_ctx_at(ctx, obj->header.domain);
- proc = args[0];
- pos1 = args[2];
- pos2 = args[3];
+ grn_obj *pat, top_left_point_, bottom_right_point_;
+ grn_geo_point *top_left, *bottom_right;
+
+ pat = grn_ctx_at(ctx, index->header.domain);
domain = pat->header.domain;
- if (domain != GRN_DB_TOKYO_GEO_POINT && domain != GRN_DB_WGS84_GEO_POINT) { goto exit; }
- if (pos1->header.domain != domain) {
- GRN_OBJ_INIT(&pos1_, GRN_BULK, 0, domain);
- if (grn_obj_cast(ctx, pos1, &pos1_, 0)) { goto exit; }
- pos1 = &pos1_;
+ if (domain != GRN_DB_TOKYO_GEO_POINT && domain != GRN_DB_WGS84_GEO_POINT) {
+ char name[GRN_TABLE_MAX_KEY_SIZE];
+ int name_size = 0;
+ grn_obj *domain_object;
+ domain_object = grn_ctx_at(ctx, domain);
+ if (domain_object) {
+ name_size = grn_obj_name(ctx, domain_object, name, GRN_TABLE_MAX_KEY_SIZE);
+ grn_obj_unlink(ctx, domain_object);
+ } else {
+ strcpy(name, "(null)");
+ name_size = strlen(name);
+ }
+ ERR(GRN_INVALID_ARGUMENT,
+ "geo_in_rectangle(): index table must be "
+ "TokyoGeoPoint or WGS84GeoPoint key type table: <%.*s>",
+ name_size, name);
+ goto exit;
}
- geo_point1 = GRN_GEO_POINT_VALUE_RAW(pos1);
- if (pos2->header.domain != domain) {
- GRN_OBJ_INIT(&pos2_, GRN_BULK, 0, domain);
- if (grn_obj_cast(ctx, pos2, &pos2_, 0)) { goto exit; }
- pos2 = &pos2_;
+
+ if (top_left_point->header.domain != domain) {
+ GRN_OBJ_INIT(&top_left_point_, GRN_BULK, 0, domain);
+ if (grn_obj_cast(ctx, top_left_point, &top_left_point_, 0)) { goto exit; }
+ top_left_point = &top_left_point_;
+ }
+ top_left = GRN_GEO_POINT_VALUE_RAW(top_left_point);
+ if (bottom_right_point->header.domain != domain) {
+ GRN_OBJ_INIT(&bottom_right_point_, GRN_BULK, 0, domain);
+ if (grn_obj_cast(ctx, bottom_right_point, &bottom_right_point_, 0)) {
+ goto exit;
+ }
+ bottom_right_point = &bottom_right_point_;
}
- geo_point2 = GRN_GEO_POINT_VALUE_RAW(pos2);
+ bottom_right = GRN_GEO_POINT_VALUE_RAW(bottom_right_point);
{
mesh_direction direction;
int distance, latitude_distance, longitude_distance;
@@ -690,65 +770,65 @@ grn_geo_search_in_rectangle(grn_ctx *ctx, grn_obj *obj, grn_obj **args, int narg
uint8_t geo_key_input[sizeof(grn_geo_point)];
uint8_t geo_key_base[sizeof(grn_geo_point)];
- if (geo_point1->latitude < 0 || geo_point1->longitude < 0 ||
- geo_point2->latitude < 0 || geo_point2->longitude < 0) {
+ if (top_left->latitude < 0 || top_left->longitude < 0 ||
+ bottom_right->latitude < 0 || bottom_right->longitude < 0) {
ERR(GRN_FUNCTION_NOT_IMPLEMENTED,
- "geo_in_rectangle() with negative coordinate is not implemented.");
+ "geo_in_rectangle(): negative coordinate is not implemented.");
goto exit;
}
- if (geo_point1->latitude >= GRN_GEO_MAX_LATITUDE) {
+ if (top_left->latitude >= GRN_GEO_MAX_LATITUDE) {
ERR(GRN_INVALID_ARGUMENT,
- "geo_in_rectangle(): geo point1's latitude is too big: <%d>(max:%d): "
- "(%d,%d) (%d,%d)",
- GRN_GEO_MAX_LATITUDE, geo_point1->latitude,
- geo_point1->latitude, geo_point1->longitude,
- geo_point2->latitude, geo_point2->longitude);
+ "geo_in_rectangle(): top left point's latitude is too big: "
+ "<%d>(max:%d): (%d,%d) (%d,%d)",
+ GRN_GEO_MAX_LATITUDE, top_left->latitude,
+ top_left->latitude, top_left->longitude,
+ bottom_right->latitude, bottom_right->longitude);
goto exit;
}
- if (geo_point1->longitude >= GRN_GEO_MAX_LONGITUDE) {
+ if (top_left->longitude >= GRN_GEO_MAX_LONGITUDE) {
ERR(GRN_INVALID_ARGUMENT,
- "geo_in_rectangle(): geo point1's longitude is too big: <%d>(max:%d): "
- "(%d,%d) (%d,%d)",
- GRN_GEO_MAX_LONGITUDE, geo_point1->longitude,
- geo_point1->latitude, geo_point1->longitude,
- geo_point2->latitude, geo_point2->longitude);
+ "geo_in_rectangle(): top left point's longitude is too big: "
+ "<%d>(max:%d): (%d,%d) (%d,%d)",
+ GRN_GEO_MAX_LONGITUDE, top_left->longitude,
+ top_left->latitude, top_left->longitude,
+ bottom_right->latitude, bottom_right->longitude);
goto exit;
}
- if (geo_point2->latitude >= GRN_GEO_MAX_LATITUDE) {
+ if (bottom_right->latitude >= GRN_GEO_MAX_LATITUDE) {
ERR(GRN_INVALID_ARGUMENT,
- "geo_in_rectangle(): geo point2's latitude is too big: <%d>(max:%d): "
- "(%d,%d) (%d,%d)",
- GRN_GEO_MAX_LATITUDE, geo_point2->latitude,
- geo_point1->latitude, geo_point1->longitude,
- geo_point2->latitude, geo_point2->longitude);
+ "geo_in_rectangle(): bottom right point's latitude is too big: "
+ "<%d>(max:%d): (%d,%d) (%d,%d)",
+ GRN_GEO_MAX_LATITUDE, bottom_right->latitude,
+ top_left->latitude, top_left->longitude,
+ bottom_right->latitude, bottom_right->longitude);
goto exit;
}
- if (geo_point2->longitude >= GRN_GEO_MAX_LONGITUDE) {
+ if (bottom_right->longitude >= GRN_GEO_MAX_LONGITUDE) {
ERR(GRN_INVALID_ARGUMENT,
- "geo_in_rectangle(): geo point2's longitude is too big: <%d>(max:%d): "
- "(%d,%d) (%d,%d)",
- GRN_GEO_MAX_LONGITUDE, geo_point2->longitude,
- geo_point1->latitude, geo_point1->longitude,
- geo_point2->latitude, geo_point2->longitude);
+ "geo_in_rectangle(): bottom right point's longitude is too big: "
+ "<%d>(max:%d): (%d,%d) (%d,%d)",
+ GRN_GEO_MAX_LONGITUDE, bottom_right->longitude,
+ top_left->latitude, top_left->longitude,
+ bottom_right->latitude, bottom_right->longitude);
goto exit;
}
- latitude_distance = geo_point1->latitude - geo_point2->latitude;
- longitude_distance = geo_point2->longitude - geo_point1->longitude;
+ latitude_distance = top_left->latitude - bottom_right->latitude;
+ longitude_distance = bottom_right->longitude - top_left->longitude;
if (latitude_distance > longitude_distance) {
direction = MESH_LATITUDE;
- geo_point_input = geo_point2;
- geo_point_base.latitude = geo_point2->latitude;
- geo_point_base.longitude = geo_point2->longitude - longitude_distance;
+ geo_point_input = bottom_right;
+ geo_point_base.latitude = bottom_right->latitude;
+ geo_point_base.longitude = bottom_right->longitude - longitude_distance;
} else {
direction = MESH_LONGITUDE;
- geo_point_input = geo_point1;
- geo_point_base.latitude = geo_point1->latitude - latitude_distance;
- geo_point_base.longitude = geo_point1->longitude;
+ geo_point_input = top_left;
+ geo_point_base.latitude = top_left->latitude - latitude_distance;
+ geo_point_base.longitude = top_left->longitude;
}
grn_gton(geo_key_input, geo_point_input, sizeof(grn_geo_point));
grn_gton(geo_key_base, &geo_point_base, sizeof(grn_geo_point));
@@ -758,11 +838,11 @@ grn_geo_search_in_rectangle(grn_ctx *ctx, grn_obj *obj, grn_obj **args, int narg
if (direction == MESH_LATITUDE) {
distance = geo_point_max.latitude - geo_point_min.latitude + 1;
start = geo_point_min.latitude;
- end = geo_point1->latitude;
+ end = top_left->latitude;
} else {
distance = geo_point_max.longitude - geo_point_min.longitude + 1;
start = geo_point_min.longitude;
- end = geo_point2->longitude;
+ end = bottom_right->longitude;
}
#ifdef GEO_DEBUG
printf("direction: %s\n",
@@ -776,9 +856,9 @@ grn_geo_search_in_rectangle(grn_ctx *ctx, grn_obj *obj, grn_obj **args, int narg
printf("max: ");
grn_p_geo_point(ctx, &geo_point_max);
printf("top-left: ");
- grn_p_geo_point(ctx, geo_point1);
+ grn_p_geo_point(ctx, top_left);
printf("bottom-right: ");
- grn_p_geo_point(ctx, geo_point2);
+ grn_p_geo_point(ctx, bottom_right);
printf("diff-bit: %10d\n", diff_bit);
printf("start: %10d\n", start);
printf("end: %10d\n", end);
@@ -801,14 +881,14 @@ grn_geo_search_in_rectangle(grn_ctx *ctx, grn_obj *obj, grn_obj **args, int narg
inspect_mesh(ctx, &geo_point_base, diff_bit, (i - start) / distance);
if (tc) {
grn_id tid;
- grn_geo_point pos;
+ grn_geo_point point;
while ((tid = grn_table_cursor_next(ctx, tc))) {
- grn_table_get_key(ctx, pat, tid, &pos, sizeof(grn_geo_point));
- if (!grn_geo_in_rectangle_raw(ctx, &pos, geo_point1, geo_point2)) {
+ grn_table_get_key(ctx, pat, tid, &point, sizeof(grn_geo_point));
+ if (!grn_geo_in_rectangle_raw(ctx, &point, top_left, bottom_right)) {
continue;
}
- inspect_tid(ctx, tid, &pos, 0);
- grn_ii_at(ctx, (grn_ii *)obj, tid, (grn_hash *)res, op);
+ inspect_tid(ctx, tid, &point, 0);
+ grn_ii_at(ctx, (grn_ii *)index, tid, (grn_hash *)res, op);
}
grn_table_cursor_close(ctx, tc);
}
Modified: lib/geo.h (+5 -4)
===================================================================
--- lib/geo.h 2011-09-17 05:09:38 +0000 (4d8db3c)
+++ lib/geo.h 2011-09-24 09:09:37 +0000 (c5832e4)
@@ -51,13 +51,14 @@ extern "C" {
_longitude = GRN_GEO_INT2RAD(_val->longitude);\
} while (0)
-grn_rc grn_geo_search_in_circle(grn_ctx *ctx, grn_obj *obj, grn_obj **args,
- int nargs, grn_obj *res, grn_operator op);
-grn_rc grn_geo_search_in_rectangle(grn_ctx *ctx, grn_obj *obj, grn_obj **args,
- int nargs, grn_obj *res, grn_operator op);
int grn_geo_table_sort(grn_ctx *ctx, grn_obj *table, int offset, int limit,
grn_obj *result, grn_table_sort_key *keys, int n_keys);
+grn_rc grn_selector_geo_in_circle(grn_ctx *ctx, grn_obj *obj, grn_obj **args,
+ int nargs, grn_obj *res, grn_operator op);
+grn_rc grn_selector_geo_in_rectangle(grn_ctx *ctx, grn_obj *obj, grn_obj **args,
+ int nargs, grn_obj *res, grn_operator op);
+
grn_bool grn_geo_in_circle(grn_ctx *ctx, grn_obj *point, grn_obj *center,
grn_obj *radius_or_point);
grn_bool grn_geo_in_rectangle(grn_ctx *ctx, grn_obj *point,
Modified: test/unit/story/test-taiyaki.c (+17 -17)
===================================================================
--- test/unit/story/test-taiyaki.c 2011-09-17 05:09:38 +0000 (c924452)
+++ test/unit/story/test-taiyaki.c 2011-09-24 09:09:37 +0000 (0ccc56e)
@@ -26,10 +26,10 @@ void test_in_rectangle_long_latitude(void);
void test_in_rectangle_long_longitude(void);
void test_in_rectangle_same_locations(void);
void test_in_rectangle_over_border(void);
-void test_in_rectangle_over_latitude1(void);
-void test_in_rectangle_over_longitude1(void);
-void test_in_rectangle_over_latitude2(void);
-void test_in_rectangle_over_longitude2(void);
+void test_in_rectangle_over_top_left_latitude(void);
+void test_in_rectangle_over_top_left_longitude(void);
+void test_in_rectangle_over_bottom_right_latitude(void);
+void test_in_rectangle_over_bottom_right_longitude(void);
void test_sort(void);
void test_filter_by_tag_and_sort_by_distance_from_tokyo_tocho(void);
void test_in_circle_and_tag(void);
@@ -230,7 +230,7 @@ test_in_rectangle_over_border(void)
grn_test_assert_send_command_error(
context,
GRN_FUNCTION_NOT_IMPLEMENTED,
- "geo_in_rectangle() with negative coordinate is not implemented.",
+ "geo_in_rectangle(): negative coordinate is not implemented.",
"select Shops "
"--sortby '+name' "
"--output_columns 'name, location' "
@@ -239,14 +239,14 @@ test_in_rectangle_over_border(void)
}
void
-test_in_rectangle_over_latitude1(void)
+test_in_rectangle_over_top_left_latitude(void)
{
grn_test_assert_send_command_error(
context,
GRN_INVALID_ARGUMENT,
- "geo_in_rectangle(): geo point1's latitude is too big: "
+ "geo_in_rectangle(): top left point's latitude is too big: "
"<324000000>(max:324000000): "
- "(324000000,503061840) (128254104,503177040)",
+ "(324000000,503061840) (128254104,50317704",
"select Shops "
"--sortby '+name' "
"--output_columns 'name, location' "
@@ -255,14 +255,14 @@ test_in_rectangle_over_latitude1(void)
}
void
-test_in_rectangle_over_longitude1(void)
+test_in_rectangle_over_top_left_longitude(void)
{
grn_test_assert_send_command_error(
context,
GRN_INVALID_ARGUMENT,
- "geo_in_rectangle(): geo point1's longitude is too big: "
+ "geo_in_rectangle(): top left point's longitude is too big: "
"<648000000>(max:648000000): "
- "(128640960,648000000) (128254104,503177040)",
+ "(128640960,648000000) (128254104,5031770",
"select Shops "
"--sortby '+name' "
"--output_columns 'name, location' "
@@ -271,14 +271,14 @@ test_in_rectangle_over_longitude1(void)
}
void
-test_in_rectangle_over_latitude2(void)
+test_in_rectangle_over_bottom_right_latitude(void)
{
grn_test_assert_send_command_error(
context,
GRN_INVALID_ARGUMENT,
- "geo_in_rectangle(): geo point2's latitude is too big: "
+ "geo_in_rectangle(): bottom right point's latitude is too big: "
"<324000000>(max:324000000): "
- "(128640960,503061840) (324000000,503177040)",
+ "(128640960,503061840) (324000000,5031",
"select Shops "
"--sortby '+name' "
"--output_columns 'name, location' "
@@ -287,14 +287,14 @@ test_in_rectangle_over_latitude2(void)
}
void
-test_in_rectangle_over_longitude2(void)
+test_in_rectangle_over_bottom_right_longitude(void)
{
grn_test_assert_send_command_error(
context,
GRN_INVALID_ARGUMENT,
- "geo_in_rectangle(): geo point2's longitude is too big: "
+ "geo_in_rectangle(): bottom right point's longitude is too big: "
"<648000000>(max:648000000): "
- "(128640960,503061840) (128254104,648000000)",
+ "(128640960,503061840) (128254104,648",
"select Shops "
"--sortby '+name' "
"--output_columns 'name, location' "