[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 15:05:52 JST 2012


HAYASHI Kentaro	2012-11-02 15:05:52 +0900 (Fri, 02 Nov 2012)

  New Revision: 917759a79dfac0028e8e2fa24c632da9f663151f
  https://github.com/groonga/groonga/commit/917759a79dfac0028e8e2fa24c632da9f663151f

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

  Modified files:
    lib/geo.c

  Modified: lib/geo.c (+98 -1)
===================================================================
--- lib/geo.c    2012-11-02 14:42:21 +0900 (d7fa858)
+++ lib/geo.c    2012-11-02 15:05:52 +0900 (5400bbe)
@@ -1915,6 +1915,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_2ND;
+    } else if (point1->longitude >= 0 && point2->longitude <= 0 &&
+               point1->latitude > 0 && point2->latitude < 0) {
+      return QUADRANT_1ST_TO_3RD;
     } else {
       /* FIXME */
       return QUADRANT_1ST;
@@ -1948,7 +1951,7 @@ grn_geo_distance_rectangle_raw(grn_ctx *ctx,
   double lng1, lat1, lng2, lat2, distance;
   double slope, intercept, longitude_delta, latitude_delta;
   double east_distance, west_distance, intercept_edge;
-  double north_distance, south_distance;
+  double north_distance, south_distance, intermediate_distance, on_equator;
   distance_type dist_type;
   quadrant_type quad_type;
 
@@ -1995,6 +1998,51 @@ 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) {
+        slope = latitude_delta / longitude_delta;
+        intercept = lat1 - slope * lng1;
+        intercept_edge = -intercept / slope;
+        if (intercept_edge > 0) {
+          north_distance = geo_distance_rectangle_square_root(lng1,
+                                                              lat1,
+                                                              intercept_edge,
+                                                              0);
+          intermediate_distance = geo_distance_rectangle_square_root(intercept_edge,
+                                                                     0,
+                                                                     0,
+                                                                     intercept);
+          south_distance = geo_distance_rectangle_square_root(0,
+                                                              intercept,
+                                                              lng2,
+                                                              lat2);
+          distance = (north_distance + intermediate_distance +
+                      south_distance) * GRN_GEO_RADIUS;
+        } else if (intercept_edge < 0) {
+          north_distance = geo_distance_rectangle_square_root(lng1,
+                                                              lat1,
+                                                              0,
+                                                              intercept);
+          intermediate_distance = geo_distance_rectangle_square_root(0,
+                                                                     intercept,
+                                                                     intercept_edge,
+                                                                     0);
+          south_distance = geo_distance_rectangle_square_root(intercept_edge,
+                                                              0,
+                                                              lng2,
+                                                              lat2);
+          distance = (north_distance + intermediate_distance +
+                      south_distance) * GRN_GEO_RADIUS;
+        } else {
+          north_distance = geo_distance_rectangle_square_root(lng1,
+                                                              lat1,
+                                                              intercept_edge,
+                                                              0);
+          south_distance = geo_distance_rectangle_square_root(intercept_edge,
+                                                              0,
+                                                              lng2,
+                                                              lat2);
+          distance = (north_distance + south_distance) * GRN_GEO_RADIUS;
+        }
       } else {
         slope = latitude_delta / longitude_delta;
         intercept = lat1 - slope * lng1;
@@ -2041,6 +2089,55 @@ 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;
+        slope = latitude_delta / longitude_delta;
+        intercept = lat1 - slope * lng1;
+        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,
+                                                              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,
+                                                              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,
+                                                              on_equator,
+                                                              0);
+          intermediate_distance = geo_distance_rectangle_square_root(on_equator,
+                                                                     0,
+                                                                     M_PI,
+                                                                     intercept_edge);
+          south_distance = geo_distance_rectangle_square_root(-M_PI,
+                                                              intercept_edge,
+                                                              lng2,
+                                                              lat2);
+          distance = (north_distance + intermediate_distance +
+                      south_distance) * GRN_GEO_RADIUS;
+        } else {
+          north_distance = geo_distance_rectangle_square_root(lng1,
+                                                              lat1,
+                                                              M_PI,
+                                                              0);
+          south_distance = geo_distance_rectangle_square_root(-M_PI,
+                                                              0,
+                                                              lng2,
+                                                              lat2);
+          distance = (north_distance + south_distance) * GRN_GEO_RADIUS;
+        }
       } else {
         distance = geo_distance_rectangle_square_root(lng1,
                                                       lat1,
-------------- next part --------------
HTML����������������������������...
Download 



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