ajantha-bhat commented on a change in pull request #3481: 
[CARBONDATA-3548]Geospatial Support: add hash id create,query condition analyze 
and generate hash id list
URL: https://github.com/apache/carbondata/pull/3481#discussion_r356550716
 
 

 ##########
 File path: geo/src/main/java/org/apache/carbondata/geo/GeoHashImpl.java
 ##########
 @@ -168,20 +238,151 @@ public String generate(List<?> sources) throws 
Exception {
     if (!(sources.get(0) instanceof Long) || !(sources.get(1) instanceof 
Long)) {
       throw new RuntimeException("Source columns must be of Long type.");
     }
-    //TODO: generate geohashId
-    return String.valueOf(0);
+    Long longitude = (Long) sources.get(0);
+    Long latitude  = (Long) sources.get(1);
+    // generate the hash code
+    int[] gridPoint = calculateID(longitude, latitude);
+    Long hashId = createHashID(gridPoint[0], gridPoint[1]);
+    return String.valueOf(hashId);
   }
 
   /**
    * Query processor for GeoHash.
-   * @param polygon
+   * example: (`LONGITUDE`, `LATITUDE`, '116270714,40112476;116217155,40028403;
+   * 
116337318,39927378;116459541,39966859;116447868,40076233;116385384,40129279;')
+   * @param polygon a group of pints, close out to form an area
    * @return Returns list of ranges of GeoHash IDs
    * @throws Exception
    */
   @Override
   public List<Long[]> query(String polygon) throws Exception {
-    List<Long[]> rangeList = new ArrayList<Long[]>();
-    // TODO: process the polygon coordinates and generate the list of ranges 
of GeoHash IDs
-    return rangeList;
+    String[] pointList = polygon.split(";");
+    if (3  > pointList.length) {
+      throw new RuntimeException("polygon need at least 3 points, really has " 
+ pointList.length);
+    } else {
+      List<double[]> queryList = new ArrayList<>();
+      for (String str: pointList) {
+        String[] points = str.split(",");
+        if (2 != points.length) {
+          throw new RuntimeException("longitude and latitude is a pair need 2 
data");
+        } else {
+          try {
+            queryList.add(new double[] {Double.valueOf(points[0]), 
Double.valueOf(points[1])});
+          } catch (NumberFormatException e) {
+            throw new RuntimeException("can not covert the string data to 
double", e);
+          }
+        }
+      }
+      if (3 > queryList.size()) {
+        throw new RuntimeException("polygon list size" + queryList.size() + " 
less than three");
+      } else {
+        List<Long[]> rangeList = getPolygonRangeList(queryList);
+        return rangeList;
+      }
+    }
+  }
+
+  /**
+   * use query polygon condition to get the hash id list, the list is merged 
and sorted.
+   * @param queryList polygon points close out to form an area
+   * @return hash id list
+   * @throws Exception
+   */
+  private  List<Long[]> getPolygonRangeList(List<double[]> queryList) throws 
Exception {
+    QuadTreeCls qTreee = new QuadTreeCls(userDefineMinLongitude, 
userDefineMinLatitude,
+        CalculateMaxLongitude, CalculateMaxLatitude, cutLevel);
+    qTreee.insert(queryList);
+    return qTreee.getNodesData();
+  }
+
+  /**
+   *  After necessary attributes, perform necessary calculation
+   * @throws Exception
+   */
+  private void calculateData() throws Exception {
+    // Angular to radian, radians = (Math.PI / 180) * degrees
+    // Cosine value of latitude angle of origin
+    this.mCos = Math.cos(this.oriLatitude / this.conversionRatio * Math.PI / 
CONVERT_FACTOR);
+    // get δx=L∗360/(2πR∗cos(lat))
+    this.deltaX = (this.gridSize * 360) / (2 * Math.PI * EARTH_RADIUS * 
this.mCos);
+    this.deltaXByRatio = this.deltaX * this.conversionRatio;
+    // get δy=L∗360/2πR
+    this.deltaY = (this.gridSize * 360) / (2 * Math.PI * EARTH_RADIUS);
+    this.deltaYByRatio = this.deltaY * this.conversionRatio;
+    LOGGER.info("after spatial calculate delta X is: " + String.format("%f", 
this.deltaX)
+                    + "the delta Y is: " + String.format("%f", this.deltaY));
+    LOGGER.info("after spatial calculate X ByRatio is: " + String.format("%f", 
this.deltaXByRatio)
+                    + "the Y ByRatio is: " + String.format("%f", 
this.deltaYByRatio));
+    // Calculate the complement area and grid i,j for grid number
+    // Xmax = x0+(2^n∗δx) Ymax = y0+(2^n∗δx) Where n is the number of cut
+    // Where x0, Y0 are the minimum x, y coordinates of a given region,
+    // Xmax >= maxLongitude Ymax >= maxLatitude
+    // In the calculation process, first substitute maxlongitude and 
maxlatitude to calculate n.
+    // if n is not an integer, then take the next integer of N, and then 
substitute to find
+    // xmax and ymax。
+    this.calculateArea();
+  }
+
+  /**
+   * Calculate the complement area, including the range of the complement 
area, t
+   * he number of knives cut and the depth of the quad tree
+   */
+  private void calculateArea() {
+    // step 1 calculate xn, yn by using maxLongitude, maxLatitude, 
minLongitude, minLatitude
+    // substitution formula
+    // Here, the user's given area is mostly rectangle, which needs to be 
extended to
+    // square processing to find the maximum value of XN and yn
+    // n=log_2 (Xmax−X0)/δx, log_2 (Ymax−Y0)/δy
+    double Xn = Math.log((userDefineMaxLongitude - userDefineMinLongitude) / 
deltaX)
+                    / Math.log(2);
+    double Yn = Math.log((userDefineMaxLatitude - userDefineMinLatitude) / 
deltaY)
+                    / Math.log(2);
+    double doubleMax = Math.max(Xn, Yn);
+    this.cutLevel = doubleMax % 1 == 0 ? (int) doubleMax : (int) (doubleMax + 
1);
+    // setep 2 recalculate the region according to the number of segmentation
+    this.CalculateMaxLongitude = userDefineMinLongitude + Math.pow(2, 
this.cutLevel)
+                                                              * deltaX;
+    this.CalculateMaxLatitude = userDefineMinLatitude + Math.pow(2, 
this.cutLevel)
+                                                            * deltaY;
+    LOGGER.info("After spatial calculate the cut level is: " + 
String.format("%d", this.cutLevel));
+    LOGGER.info("the min longitude is: " + String.format("%f", 
this.userDefineMinLongitude) +
+                    " the max longitude is: " + String.format("%f", 
this.CalculateMaxLongitude));
+    LOGGER.info("the min latitude is: " + String.format("%f", 
this.userDefineMinLatitude) +
+                    " the max latitude is: " + String.format("%f", 
this.CalculateMaxLatitude));
+  }
+
+  /**
+   * Through grid index coordinates and calculation of hashid, grid latitude 
and longitude
+   * coordinates can be transformed by latitude and longitude
+   * @param longitude Longitude, the actual longitude and latitude are 
processed by * coefficient,
+   *                  and the floating-point calculation is converted to 
integer calculation
+   * @param latitude Latitude, the actual longitude and latitude are processed 
by * coefficient,
+   *                 and the floating-point calculation is converted to 
integer calculation.
+   * @return Grid ID value [row, column] column starts from 1
+   */
+  private int[] calculateID(long longitude, long latitude) throws Exception {
+    try {
+      int row = (int) ((longitude - this.lon0ByRation) / this.deltaXByRatio);
+      int column = (int) ((latitude - this.lat0ByRation) / this.deltaYByRatio);
+      return new int[]{row, column};
+    } catch (ArithmeticException  e) {
+      throw new RuntimeException("can not divide by zero.");
+    }
+  }
+
+  /**
+   * Calculate the corresponding hashid value from the grid coordinates
+   * @param row Gridded row index
+   * @param column Gridded column index
+   * @return hash id
+   */
+  private long createHashID(long row, long column) {
+    long index = 0L;
+    for (int i = 0; i < cutLevel + 1; i++) {
+      long x = (row >> i) & 1;    //取第i位
 
 Review comment:
   please use english comment

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
[email protected]


With regards,
Apache Git Services

Reply via email to