135 lines
3.2 KiB
Java
135 lines
3.2 KiB
Java
|
package com.anvisics.data;
|
|||
|
|
|||
|
import java.util.ArrayList;
|
|||
|
import java.util.HashMap;
|
|||
|
import java.util.List;
|
|||
|
import java.util.Map;
|
|||
|
|
|||
|
import com.anvisics.NodeUtil;
|
|||
|
|
|||
|
/**
|
|||
|
*
|
|||
|
* @param <T> - object to store in that manager
|
|||
|
*/
|
|||
|
public class DataTileManager<T> {
|
|||
|
|
|||
|
private int zoom = 15;
|
|||
|
|
|||
|
/**
|
|||
|
* map for objects stores as 'xTile_yTile' -> List<T>
|
|||
|
*/
|
|||
|
private Map<String, List<T>> objects = new HashMap<String, List<T>>();
|
|||
|
|
|||
|
public int getZoom() {
|
|||
|
return zoom;
|
|||
|
}
|
|||
|
|
|||
|
public void setZoom(int zoom) {
|
|||
|
// TODO !!! it is required to reindex all stored objects
|
|||
|
if(!objects.isEmpty()){
|
|||
|
throw new UnsupportedOperationException();
|
|||
|
}
|
|||
|
this.zoom = zoom;
|
|||
|
}
|
|||
|
|
|||
|
private void putObjects(int tx, int ty, List<T> r){
|
|||
|
if(objects.containsKey(evTile(tx, ty))){
|
|||
|
r.addAll(objects.get(evTile(tx, ty)));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @depth of the neighbor tile to visit
|
|||
|
* returns not exactly sorted list,
|
|||
|
* however the first objects are from closer tile than last
|
|||
|
*/
|
|||
|
public List<T> getClosestObjects(double latitude, double longitude, int depth){
|
|||
|
int tileX = (int) NodeUtil.getTileNumberX(zoom, longitude);
|
|||
|
int tileY = (int) NodeUtil.getTileNumberY(zoom, latitude);
|
|||
|
List<T> result = new ArrayList<T>();
|
|||
|
|
|||
|
|
|||
|
putObjects(tileX, tileY, result);
|
|||
|
|
|||
|
// that's very difficult way visiting node :
|
|||
|
// similar to visit like spiral
|
|||
|
// however the simplest way could visit by matrix & after that sort tiles by distance (that's less efficient)
|
|||
|
|
|||
|
// go through circle
|
|||
|
for (int i = 1; i <= depth; i++) {
|
|||
|
|
|||
|
// goes <20>
|
|||
|
for (int j = 0; j <= i; j++) {
|
|||
|
// left & right
|
|||
|
int dx = j == 0 ? 0 : -1;
|
|||
|
for (; dx < 1 || (j < i && dx == 1); dx += 2) {
|
|||
|
// north
|
|||
|
putObjects(tileX + dx * j, tileY + i, result);
|
|||
|
// east
|
|||
|
putObjects(tileX + i, tileY - dx * j, result);
|
|||
|
// south
|
|||
|
putObjects(tileX - dx * j, tileY - i, result);
|
|||
|
// west
|
|||
|
putObjects(tileX - i, tileY + dx * j, result);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
private String evTile(int tileX, int tileY){
|
|||
|
return tileX +"_"+tileY;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
public String evaluateTile(double latitude, double longitude){
|
|||
|
int tileX = (int) NodeUtil.getTileNumberX(zoom, longitude);
|
|||
|
int tileY = (int) NodeUtil.getTileNumberY(zoom, latitude);
|
|||
|
return evTile(tileX, tileY);
|
|||
|
}
|
|||
|
|
|||
|
public String registerObject(double latitude, double longitude, T object){
|
|||
|
String tile = evaluateTile(latitude, longitude);
|
|||
|
if(!objects.containsKey(tile)){
|
|||
|
objects.put(tile, new ArrayList<T>());
|
|||
|
}
|
|||
|
objects.get(tile).add(object);
|
|||
|
return tile;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
// testing way to search
|
|||
|
public static void print(int x, int y){
|
|||
|
System.out.println(x + (y-1)*5);
|
|||
|
}
|
|||
|
|
|||
|
public static void main(String[] args) {
|
|||
|
int tileX = 3;
|
|||
|
int tileY = 3;
|
|||
|
int depth = 3;
|
|||
|
for(int i=1; i<=depth; i++){
|
|||
|
|
|||
|
// goes <20>
|
|||
|
for(int j=0; j<=i; j++){
|
|||
|
// left & right
|
|||
|
int dx = j==0 ? 0 : -1;
|
|||
|
for(; dx < 1 || (j < i && dx == 1); dx +=2){
|
|||
|
// north
|
|||
|
print(tileX + dx * j, tileY + i);
|
|||
|
// east
|
|||
|
print(tileX + i, tileY - dx *j);
|
|||
|
// south
|
|||
|
print(tileX - dx * j, tileY - i);
|
|||
|
// west
|
|||
|
print(tileX - i, tileY + dx *j);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
}
|