HAYASHI Kentaro
null+****@clear*****
Mon Nov 5 19:10:25 JST 2012
HAYASHI Kentaro 2012-11-05 19:10:25 +0900 (Mon, 05 Nov 2012) New Revision: 443e8d3e3899e323f7e218934c49b57fbdd51c73 https://github.com/groonga/groonga/commit/443e8d3e3899e323f7e218934c49b57fbdd51c73 Log: geo: return the value of correct distance according to quadrant type Support to calculate the value of distance across the equator in eastern/western hemisphere. (2nd quadrant to 4th one) refs #1534 Modified files: lib/geo.c Modified: lib/geo.c (+67 -1) =================================================================== --- lib/geo.c 2012-11-05 19:05:35 +0900 (7ac0bdf) +++ lib/geo.c 2012-11-05 19:10:25 +0900 (933a3c5) @@ -1921,6 +1921,9 @@ geo_quadrant_type(grn_geo_point *point1, grn_geo_point *point2) } else if (point1->longitude <= 0 && point2->longitude >= 0 && point1->latitude < 0 && point2->latitude > 0) { return QUADRANT_3RD_TO_1ST; + } else if (point1->longitude <= 0 && point2->longitude >= 0 && + point1->latitude > 0 && point2->latitude < 0) { + return QUADRANT_2ND_TO_4TH; } else { /* FIXME */ return QUADRANT_1ST; @@ -1956,6 +1959,7 @@ grn_geo_distance_rectangle_raw(grn_ctx *ctx, double east_distance, west_distance, intercept_edge; double north_distance, south_distance, intermediate_distance, on_equator; double first_longitude, first_latitude, third_longitude, third_latitude; + double middle1_longitude, middle1_latitude, middle2_longitude, middle2_latitude; distance_type dist_type; quadrant_type quad_type; @@ -2003,7 +2007,8 @@ grn_geo_distance_rectangle_raw(grn_ctx *ctx, } distance = (north_distance + south_distance) * GRN_GEO_RADIUS; } else if (quad_type == QUADRANT_1ST_TO_3RD || - quad_type == QUADRANT_3RD_TO_1ST) { + quad_type == QUADRANT_3RD_TO_1ST || + quad_type == QUADRANT_2ND_TO_4TH) { slope = latitude_delta / longitude_delta; intercept = lat1 - slope * lng1; intercept_edge = -intercept / slope; @@ -2152,6 +2157,67 @@ grn_geo_distance_rectangle_raw(grn_ctx *ctx, third_latitude); distance = (north_distance + south_distance) * GRN_GEO_RADIUS; } + } else if (quad_type == QUADRANT_2ND_TO_4TH) { + first_longitude = lng2; + first_latitude = lat2; + third_longitude = lng1; + third_latitude = lat1; + longitude_delta = third_longitude + M_2PI - first_longitude; + latitude_delta = third_latitude - first_latitude; + slope = latitude_delta / longitude_delta; + intercept = first_latitude - slope * first_longitude; + intercept_edge = slope * M_PI + intercept; + if (intercept_edge > 0) { + on_equator = M_2PI - (-intercept / slope); + middle1_longitude = on_equator; + middle1_latitude = 0; + middle2_longitude = M_PI; + middle2_latitude = intercept_edge; + north_distance = geo_distance_rectangle_square_root(first_longitude, + first_latitude, + middle1_longitude, + middle1_latitude); + intermediate_distance = geo_distance_rectangle_square_root(middle1_longitude, + middle1_latitude, + middle2_longitude, + middle2_latitude); + south_distance = geo_distance_rectangle_square_root(middle2_longitude, + middle2_latitude, + -third_longitude, + third_latitude); + distance = (north_distance + intermediate_distance + + south_distance) * GRN_GEO_RADIUS; + } else if (intercept_edge < 0) { + on_equator = -intercept / slope; + middle1_longitude = M_PI; + middle1_latitude = intercept_edge; + middle2_longitude = M_2PI - on_equator; + middle2_latitude = 0; + north_distance = geo_distance_rectangle_square_root(first_longitude, + first_latitude, + middle1_longitude, + middle1_latitude); + intermediate_distance = geo_distance_rectangle_square_root(middle1_longitude, + middle1_latitude, + middle2_longitude, + middle2_latitude); + south_distance = geo_distance_rectangle_square_root(middle2_longitude, + middle2_latitude, + -third_longitude, + third_latitude); + distance = (north_distance + intermediate_distance + + south_distance) * GRN_GEO_RADIUS; + } else { + north_distance = geo_distance_rectangle_square_root(first_longitude, + first_latitude, + M_PI, + 0); + south_distance = geo_distance_rectangle_square_root(-M_PI, + 0, + third_longitude, + third_latitude); + distance = (north_distance + south_distance) * GRN_GEO_RADIUS; + } } else { distance = geo_distance_rectangle_square_root(lng1, lat1, -------------- next part -------------- HTML����������������������������...Télécharger