出于某种原因,需要把百度地图中的聚合方法在java中实现,自己写了一份。
当时做的功能是把聚合后的点存入数据库中,并且需要计算的数值比较多,因此显得麻烦些,我已经把代码进行了一些删减。(本来是想提供一个更纯净的版本的,但是这个两年前的代码,实在是有点忘了,并且现在也并不需要使用,不打算再读一遍。等真正需要的时候再重写一份吧。)
其中DaoHelper是调用sql的公共方法,IClusterOpt 存储一些配置信息,比如地图缩放比等等。
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import com.DaoHelper;
import com.util.bean.IClusterOpt;
import com.XUtils;
/**
* 基于半径的点聚合
* @author Administrator
*/
public class MarkerClusterUtil {
//[1:20米,50米,100米,200米,500米,1公里,2公里,5公里,10公里,20公里,25公里,50公里,100公里,200公里,500公里,1000公里,2000公里,5000公里,10000公里]
//[19级, 18级,17级, 16级, 15级, 14级, 13级, 12级, 11级, 10级, 9级, 8级, 7级, 6级, 5级, 4级, 3级, 2级, 1级]
@SuppressWarnings("unchecked")
private Map<String, Double> zoomRadius = new HashMap(){
{
// this.put("18", 30d);
// this.put("17", 60d);
// this.put("16", 120d);
// this.put("15", 300d);
// this.put("14", 600d);
// this.put("13", 1200d);
// this.put("12", 3000d);
// this.put("11", 6000d);
// this.put("10", 12000d);
// this.put("9", 15000d);
this.put("18", 62.5d);
this.put("17", 125d);
this.put("16", 250d);
this.put("15", 625d);
this.put("14", 1250d);
this.put("13", 2500d); //12500d
this.put("12", 6250d);
this.put("11", 12500d);
this.put("10", 25000d);
this.put("9", 31250d);
}
};
private List<Map<String, String>> markers = new ArrayList<Map<String,String>>();
private List<Cluster> clusters = new ArrayList(2048);
private String[] zooms;
private String sql;
private DaoHelper daoHelper = XUtils.getDaoHelper();
/**
* select '20171212', '2101', '17',
*/
private StringBuffer aSql;
public void createCluster(List<Map<String, String>> markers, IClusterOpt opt) throws Exception{
this.clusters = new ArrayList(2048);
this.markers = markers;
this.zooms = opt.getZooms();
//check
if(markers == null || markers.size() == 0){
throw new Exception("markers null");
}
for(String tz : zooms){
if(!zoomRadius.containsKey(tz)){
throw new Exception("zoom undefined");
}
}
//check
StringBuffer sb = new StringBuffer(" select '" + “” + "', '");
for(String zoom : this.zooms){
aSql = new StringBuffer(sb.toString() + "'" + zoom + "', ");
Double radius = this.zoomRadius.get(zoom);
this.clusters = this.doCluster(markers, radius);
this.thisClustersToDb();
this.clusters = new ArrayList(2048);
}
}
private void thisClustersToDb(){
int cacheNum = 20;
List<Cluster> cacheClusters = new ArrayList(22);
for(int i = 0; i < this.clusters.size(); i++){
cacheClusters.add(this.clusters.get(i));
if(i % cacheNum == (cacheNum - 1)){
this.doInsert(cacheClusters);
cacheClusters = new ArrayList(cacheNum + 5);
}
}
this.doInsert(cacheClusters);
cacheClusters = new ArrayList(22);
}
private void doInsert(List<Cluster> cl){
if(cl == null || cl.size() == 0)
return;
StringBuffer sb = new StringBuffer();
sb.append(" insert into map_cluster(id, zoom, cluster_num, lng, lat, ");
sb.append(" gh1_num, kd2_num, gh3_num, kd4_num, ");
sb.append(" gh5_num, kd6_num, gh7_fee_a, kd8_fee_a) ");
sb.append(" select seq_cluster.nextval, t1.* from ( ");
for(int i = 0; i < cl.size(); i++){
Cluster cluster = cl.get(i);
sb.append(this.aSql);
sb.append("" + cluster.getExtInfo().get("cNum") + " c , ");
sb.append("" + cluster.getCenter().getLng() + " a , ");
sb.append("" + cluster.getCenter().getLat() + " b , ");
sb.append("" + cluster.getExtInfo().get("a") + " d , ");
sb.append("" + cluster.getExtInfo().get("b") + " e , ");
sb.append("" + cluster.getExtInfo().get("c") + " f , ");
sb.append("" + cluster.getExtInfo().get("d") + " g , ");
sb.append("" + cluster.getExtInfo().get("e") + " h , ");
sb.append("" + cluster.getExtInfo().get("f") + " i , ");
sb.append("" + cluster.getExtInfo().get("g") + " j , ");
sb.append("" + cluster.getExtInfo().get("h") + " k ");
sb.append(" from dual ");
if(i != cl.size() - 1){
sb.append(" union all ");
}
}
sb.append(" ) t1 ");
Map daoMap = new HashMap(2);
daoMap.put("sql", sb.toString());
System.out.println(daoMap.get("sql"));
daoHelper.insert("clusterer.map.cacheSql", daoMap);
sb = null;
}
private List<Cluster> doCluster(List<Map<String, String>> markers, Double radius){
this.clusters = new ArrayList(2048);
for(int i = 0; i < markers.size(); i++){
int cIndex = -1;
Double distance = 99999999d;
Point tempMarkerPoint =
new Point(Double.valueOf(markers.get(i).get("m")), Double.valueOf(markers.get(i).get("l")));
for(int j = 0; j < this.clusters.size(); j++){
Double tempDistince = this.clusters.get(j).getDistance(tempMarkerPoint);
if(tempDistince < distance){
distance = tempDistince;
cIndex = j;
}
}
if(cIndex == -1 || distance > radius){
Cluster cluster = new Cluster(tempMarkerPoint, radius, markers.get(i));
this.clusters.add(cluster);
}else {
this.clusters.get(cIndex).addMarker(markers.get(i), tempMarkerPoint);
}
if(i % 1000 == 0){
System.out.println(i);
}
}
for(int i = 0; i < this.clusters.size(); i++){
this.clusters.get(i).finish();
}
return this.clusters;
}
static class Cluster{
Point center;
//String text;
Double r;
private List<Map<String, String>> markers = new ArrayList<Map<String,String>>(50);
Map<String, String> extInfo = new HashMap(16);
Cluster(Point center, Double r){
this.center = center;
this.r = r;
}
Cluster(Point center, Double r, Map<String, String> marker){
this.center = center;
this.r = r;
this.markers.add(marker);
}
private void updateCenter(Point point){
this.center.setLng(this.center.getLng() * this.markers.size() / (this.markers.size() + 1) +
point.getLng() / (this.markers.size() + 1));
this.center.setLat(this.center.getLat() * this.markers.size() / (this.markers.size() + 1) +
point.getLat() / (this.markers.size() + 1));
}
public void finish(){
Double a = 0d;
Double b = 0d;
Double c = 0d;
Double d = 0d;
Double e = 0d;
Double f = 0d;
Double g = 0d;
Double h = 0d;
for(int i = 0; i < this.markers.size(); i++){
a += Double.valueOf(this.markers.get(i).get("A"));
b += Double.valueOf(this.markers.get(i).get("B"));
c += Double.valueOf(this.markers.get(i).get("C"));
d += Double.valueOf(this.markers.get(i).get("D"));
e += Double.valueOf(this.markers.get(i).get("E"));
f += Double.valueOf(this.markers.get(i).get("F"));
g += Double.valueOf(this.markers.get(i).get("G"));
h += Double.valueOf(this.markers.get(i).get("H"));
}
this.extInfo.put("cNum", this.markers.size() + "");
this.extInfo.put("a", a + "");
this.extInfo.put("b", b + "");
this.extInfo.put("c", c + "");
this.extInfo.put("d", d + "");
this.extInfo.put("e", e + "");
this.extInfo.put("f", f + "");
this.extInfo.put("g", g + "");
this.extInfo.put("h", h + "");
this.markers = null;
}
public void addMarker(Map<String, String> allInfo, Point point){
this.updateCenter(point);
this.markers.add(allInfo);
}
public boolean isPointContains(Point point){
return getDistance(point) < r ? true : false;
}
public Double getDistance(Point point){
return MapUtil.getDistance(center.getLat(), center.getLng(), point.getLat(), point.getLng());
}
// public void addExtInfo(String key, String value){
// if(this.extNumInfo.containsKey(key))
// this.extNumInfo.put(key, this.extNumInfo.get(key) + value);
// else
// this.extNumInfo.put(key, value);
// }
public Point getCenter() {
return center;
}
public void setCenter(Point center) {
this.center = center;
}
// public String getText() {
// return text;
// }
// public void setText(String text) {
// this.text = text;
// }
public double getR() {
return r;
}
public void setR(Double r) {
this.r = r;
}
public Map<String, String> getExtInfo() {
return extInfo;
}
}
static class Point{
double lng;
double lat;
Point(double lng, double lat){
this.lng = lng;
this.lat = lat;
}
public double getLng() {
return lng;
}
public void setLng(double lng) {
this.lng = lng;
}
public double getLat() {
return lat;
}
public void setLat(double lat) {
this.lat = lat;
}
}
public String getSql() {
return sql;
}
}