最近希望在android上实现在百度地图绘制重力异常图(地形图),查了一下官方提供了一个热力图绘制方法,效果很好,但只能显示官方提供的人员流量数据,所以退一步试着实现简单的等值线图绘制,不难,着急的朋友完全可以仿照下例修改使用:
主要方法:
①对离散点构造矩形区域并插值:
insertValue(List longitude,List latitude ,List value,int row ,int col);
参数含义:longitude/latitdue/value测点经、纬度和测值列表,顺序依次对应,row/col目标插值矩阵行列数;
②对插值矩阵实现等值线算法 :
createContour(float[ ][ ] data,int ilb,int iub, int jlb, int jub,float[ ] insert_longitude,float[ ] insert_latitude,int n ,float[ ] z);
参数含义:data经插值后得到的矩阵,ilb/iub/jlb/jub很多时候我们仅需要对一部分区域绘制等值线,这四个参数决定了取data矩阵中哪部分计算等值线,取值0~(row-1)或者0~(col-1),insert_longitude/latitude插值后对应矩阵点横纵坐标值(经纬度),n测线的数量,越大等值线越密,z的长度与n对应,指示每段等值线间要间隔的数值;
③在BaiduMap上绘制等值线:
drawCoutour(float longitude1,float latitude1,float longitude2,float latitude2,Baidumap);
前四个参数指示了要绘制直线的起始位置,并传入一个发生绘制的地图组件;
public void insertValue(List longitude,List latitude,List value,int row_latitude,int col_longitude,int n) {
float max_longitude,min_longitude,max_latitude,min_latitude,add_longitude,add_latitude;
float insert_longitude[]=new float[col_longitude];
float insert_latitude[]=new float[row_latitude];
float insert_value[][]=new float[row_latitude][col_longitude];
max_longitude=Collections.max(longitude);
min_longitude=Collections.min(longitude);
max_latitude=Collections.max(latitude);
min_latitude=Collections.min(latitude);
add_longitude=(max_longitude-min_longitude)/col_longitude;
add_latitude=(max_latitude-min_latitude)/row_latitude;
for(int i=0;imax) {
max=insert_value[i][j];
}
}}
float z[]=new float[n];
float add_z=(max-min)/n;
for(int i=0;i
public void createContour(float[][] data, int ilb, int iub, int jlb, int jub, float [] x, float [] y, int nc, float [] z){
double x1 = 0.0;
double x2 = 0.0;
double y1 = 0.0;
double y2 = 0.0;
int i,j,k,m;
int [] im = {0,1,1,0};
int [] jm = {0,0,1,1};
int [][][] castab=
{
{
{0,0,8},{0,2,5},{7,6,9}
},
{
{0,3,4},{1,3,1},{4,3,0}
},
{
{9,6,7},{5,2,0},{8,0,0}
}
};
for (j=(jub-1);j>=jlb;j--) {
for (i=ilb;i<=iub-1;i++) {
double temp1,temp2;
temp1 = Math.min(d[i][j],d[i][j+1]);
temp2 = Math.min(d[i+1][j],d[i+1][j+1]);
dmin= Math.min(temp1,temp2);
temp1 = Math.max(d[i][j],d[i][j+1]);
temp2 = Math.max(d[i+1][j],d[i+1][j+1]);
dmax= Math.max(temp1,temp2);
if (dmax>=z[0]&&dmin<=z[nc-1]) {
for (k=0;k=dmin&&z[k]<=dmax) {
for (m=4;m>=0;m--) {
if (m>0) {
h[m] = d[i+im[m-1]][j+jm[m-1]]-z[k];
xh[m] = x[i+im[m-1]];
yh[m] = y[j+jm[m-1]];
} else {
h[0] = 0.25*(h[1]+h[2]+h[3]+h[4]);
xh[0]=0.5*(x[i]+x[i+1]);
yh[0]=0.5*(y[j]+y[j+1]);
}
if (h[m]>0.0) {
sh[m] = 1;
} else if (h[m]<0.0) {
sh[m] = -1;
} else
sh[m] = 0;
}
for (m=1;m<=4;m++) {
m1 = m;
m2 = 0;
if (m!=4) {
m3 = m+1;
} else {
m3 = 1;
}
case_value = castab[sh[m1]+1][sh[m2]+1][sh[m3]+1];
if (case_value!=0) {
switch (case_value) {
case 1: // Line between vertices 1 and 2
x1=xh[m1];
y1=yh[m1];
x2=xh[m2];
y2=yh[m2];
break;
case 2: // Line between vertices 2 and 3
x1=xh[m2];
y1=yh[m2];
x2=xh[m3];
y2=yh[m3];
break;
case 3: // Line between vertices 3 and 1
x1=xh[m3];
y1=yh[m3];
x2=xh[m1];
y2=yh[m1];
break;
case 4: // Line between vertex 1 and side 2-3
x1=xh[m1];
y1=yh[m1];
x2=xsect(m2,m3);
y2=ysect(m2,m3);
break;
case 5: // Line between vertex 2 and side 3-1
x1=xh[m2];
y1=yh[m2];
x2=xsect(m3,m1);
y2=ysect(m3,m1);
break;
case 6: //Line between vertex 3 and side 1-2
x1=xh[m3];
y1=yh[m3];
x2=xsect(m1,m2);
y2=ysect(m1,m2);
break;
case 7: // Line between sides 1-2 and 2-3
x1=xsect(m1,m2);
y1=ysect(m1,m2);
x2=xsect(m2,m3);
y2=ysect(m2,m3);
break;
case 8: // Line between sides 2-3 and 3-1
x1=xsect(m2,m3);
y1=ysect(m2,m3);
x2=xsect(m3,m1);
y2=ysect(m3,m1);
break;
case 9: // Line between sides 3-1 and 1-2
x1=xsect(m3,m1);
y1=ysect(m3,m1);
x2=xsect(m1,m2);
y2=ysect(m1,m2);
break;
default:
break;
}
this.drawContour((float)x1, (float)y1, (float)x2, (float)y2, baidumap);//注意在此调用drawContour绘制等值线
//System.out.println("绘制线段,从点("+x1+","+y1+")到("+x2+","+y2+")");
}}}}}}}}
public void drawContour(float long1,float lat1,float long2,float lat2,BaiduMap baodumap) {
LatLng p1 = new LatLng(long1, lat1);
LatLng p2 = new LatLng(long2, lat2);
List points = new ArrayList();
points.add(p1);
points.add(p2);
//绘制折线
OverlayOptions ooPolyline = new PolylineOptions().width(10)
.color(0xAAFF0000).points(points);
Polyline mPolyline = (Polyline)baidumap.addOverlay(ooPolyline);
}
//几个辅助方法
public float distance2(float insert_longitude,float insert_latitude,float longitude,float latitude) {
return (float) (Math.pow((float) Math.pow((longitude-insert_longitude),2)+Math.pow((latitude-insert_latitude),2),1)) ;}
private double xsect(int p1, int p2){
return(h[p2]*xh[p1]-h[p1]*xh[p2])/(h[p2]-h[p1]);
}
private double ysect(int p1, int p2){
return (h[p2]*yh[p1]-h[p1]*yh[p2])/(h[p2]-h[p1]);
}
1.以下是不同测线数量的显示效果(用java graphics简单绘制),可以看到在要求精度不高的情况下可以有效实现等值线的绘制:
2.第一个方法中List的使用例子:
List
List
List
longitude.add((float) 100);//继续添加坐标值...
latitude.add((float) 110); //继续添加坐标值...
value.add((float) 50); //继续添加测点值...
希望能帮到有需要的人。