[Groonga-commit] groonga/groonga [master] geo: return the value of correct distance according to quadrant type

Back to archive index

HAYASHI Kentaro null+****@clear*****
Fri Nov 2 17:49:57 JST 2012


HAYASHI Kentaro	2012-11-02 17:49:57 +0900 (Fri, 02 Nov 2012)

  New Revision: 0e995b6c7b8cf1cf8a643658330bfbf1942cabce
  https://github.com/groonga/groonga/commit/0e995b6c7b8cf1cf8a643658330bfbf1942cabce

  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. (3rd quadrant to 1st one)
    
    refs #1534

  Modified files:
    lib/geo.c

  Modified: lib/geo.c (+43 -29)
===================================================================
--- lib/geo.c    2012-11-02 17:49:24 +0900 (5400bbe)
+++ lib/geo.c    2012-11-02 17:49:57 +0900 (608902c)
@@ -1918,6 +1918,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_1ST_TO_3RD;
+    } else if (point1->longitude <= 0 && point2->longitude >= 0 &&
+               point1->latitude < 0 && point2->latitude > 0) {
+      return QUADRANT_3RD_TO_1ST;
     } else {
       /* FIXME */
       return QUADRANT_1ST;
@@ -1952,6 +1955,7 @@ grn_geo_distance_rectangle_raw(grn_ctx *ctx,
   double slope, intercept, longitude_delta, latitude_delta;
   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;
   distance_type dist_type;
   quadrant_type quad_type;
 
@@ -1998,13 +2002,18 @@ grn_geo_distance_rectangle_raw(grn_ctx *ctx,
                                                               lat2);
         }
         distance = (north_distance + south_distance) * GRN_GEO_RADIUS;
-      } else if (quad_type == QUADRANT_1ST_TO_3RD) {
+      } else if (quad_type == QUADRANT_1ST_TO_3RD ||
+                 quad_type == QUADRANT_3RD_TO_1ST) {
         slope = latitude_delta / longitude_delta;
         intercept = lat1 - slope * lng1;
         intercept_edge = -intercept / slope;
+        first_longitude = quad_type == QUADRANT_1ST_TO_3RD ? lng1 : lng2;
+        first_latitude = quad_type == QUADRANT_1ST_TO_3RD ? lat1 : lat2;
+        third_longitude = quad_type == QUADRANT_1ST_TO_3RD ? lng2 : lng1;
+        third_latitude = quad_type == QUADRANT_1ST_TO_3RD ? lat2 : lat1;
         if (intercept_edge > 0) {
-          north_distance = geo_distance_rectangle_square_root(lng1,
-                                                              lat1,
+          north_distance = geo_distance_rectangle_square_root(first_longitude,
+                                                              first_latitude,
                                                               intercept_edge,
                                                               0);
           intermediate_distance = geo_distance_rectangle_square_root(intercept_edge,
@@ -2013,13 +2022,13 @@ grn_geo_distance_rectangle_raw(grn_ctx *ctx,
                                                                      intercept);
           south_distance = geo_distance_rectangle_square_root(0,
                                                               intercept,
-                                                              lng2,
-                                                              lat2);
+                                                              third_longitude,
+                                                              third_latitude);
           distance = (north_distance + intermediate_distance +
                       south_distance) * GRN_GEO_RADIUS;
         } else if (intercept_edge < 0) {
-          north_distance = geo_distance_rectangle_square_root(lng1,
-                                                              lat1,
+          north_distance = geo_distance_rectangle_square_root(first_longitude,
+                                                              first_latitude,
                                                               0,
                                                               intercept);
           intermediate_distance = geo_distance_rectangle_square_root(0,
@@ -2028,19 +2037,19 @@ grn_geo_distance_rectangle_raw(grn_ctx *ctx,
                                                                      0);
           south_distance = geo_distance_rectangle_square_root(intercept_edge,
                                                               0,
-                                                              lng2,
-                                                              lat2);
+                                                              third_longitude,
+                                                              third_latitude);
           distance = (north_distance + intermediate_distance +
                       south_distance) * GRN_GEO_RADIUS;
         } else {
-          north_distance = geo_distance_rectangle_square_root(lng1,
-                                                              lat1,
+          north_distance = geo_distance_rectangle_square_root(first_longitude,
+                                                              first_latitude,
                                                               intercept_edge,
                                                               0);
           south_distance = geo_distance_rectangle_square_root(intercept_edge,
                                                               0,
-                                                              lng2,
-                                                              lat2);
+                                                              third_longitude,
+                                                              third_latitude);
           distance = (north_distance + south_distance) * GRN_GEO_RADIUS;
         }
       } else {
@@ -2089,32 +2098,37 @@ grn_geo_distance_rectangle_raw(grn_ctx *ctx,
                                                            M_PI,
                                                            intercept_edge);
         distance = (east_distance + west_distance) * GRN_GEO_RADIUS;
-      } else if (quad_type == QUADRANT_1ST_TO_3RD) {
-        longitude_delta = lng2 + M_2PI - lng1;
-        latitude_delta = lat2 - lat1;
+      } else if (quad_type == QUADRANT_1ST_TO_3RD ||
+                 quad_type == QUADRANT_3RD_TO_1ST) {
+        first_longitude = quad_type == QUADRANT_1ST_TO_3RD ? lng1 : lng2;
+        first_latitude = quad_type == QUADRANT_1ST_TO_3RD ? lat1 : lat2;
+        third_longitude = quad_type == QUADRANT_1ST_TO_3RD ? lng2 : lng1;
+        third_latitude = quad_type == QUADRANT_1ST_TO_3RD ? lat2 : lat1;
+        longitude_delta = third_longitude + M_2PI - first_longitude;
+        latitude_delta = third_latitude - first_latitude;
         slope = latitude_delta / longitude_delta;
-        intercept = lat1 - slope * lng1;
+        intercept = first_latitude - slope * first_longitude;
         intercept_edge = slope * M_PI + intercept;
         if (intercept_edge > 0) {
           on_equator = M_2PI - (-intercept / slope);
-          north_distance = geo_distance_rectangle_square_root(lng1,
-                                                              lat1,
+          north_distance = geo_distance_rectangle_square_root(first_longitude,
+                                                              first_latitude,
                                                               M_PI,
                                                               intercept_edge);
           intermediate_distance = geo_distance_rectangle_square_root(M_PI,
                                                                      intercept_edge,
                                                                      on_equator,
                                                                      0);
-          south_distance = geo_distance_rectangle_square_root(-lng2,
-                                                              lat2,
+          south_distance = geo_distance_rectangle_square_root(-third_longitude,
+                                                              third_latitude,
                                                               on_equator,
                                                               0);
           distance = (north_distance + intermediate_distance +
                       south_distance) * GRN_GEO_RADIUS;
         } else if (intercept_edge < 0) {
           on_equator = -intercept / slope;
-          north_distance = geo_distance_rectangle_square_root(lng1,
-                                                              lat1,
+          north_distance = geo_distance_rectangle_square_root(first_longitude,
+                                                              first_latitude,
                                                               on_equator,
                                                               0);
           intermediate_distance = geo_distance_rectangle_square_root(on_equator,
@@ -2123,19 +2137,19 @@ grn_geo_distance_rectangle_raw(grn_ctx *ctx,
                                                                      intercept_edge);
           south_distance = geo_distance_rectangle_square_root(-M_PI,
                                                               intercept_edge,
-                                                              lng2,
-                                                              lat2);
+                                                              third_longitude,
+                                                              third_latitude);
           distance = (north_distance + intermediate_distance +
                       south_distance) * GRN_GEO_RADIUS;
         } else {
-          north_distance = geo_distance_rectangle_square_root(lng1,
-                                                              lat1,
+          north_distance = geo_distance_rectangle_square_root(first_longitude,
+                                                              first_latitude,
                                                               M_PI,
                                                               0);
           south_distance = geo_distance_rectangle_square_root(-M_PI,
                                                               0,
-                                                              lng2,
-                                                              lat2);
+                                                              third_longitude,
+                                                              third_latitude);
           distance = (north_distance + south_distance) * GRN_GEO_RADIUS;
         }
       } else {
-------------- next part --------------
HTML����������������������������...
下载 



More information about the Groonga-commit mailing list
Back to archive index