Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 如何在百度地圖上畫镂空圓 Android

如何在百度地圖上畫镂空圓 Android

編輯:關於Android編程

首先我發現API還提供一個畫多邊形的類。而一個镂空圓分解成兩個多邊形,即橫著一刀切在這個镂空圓上,上下兩部分各為一個多邊形。

但實現上述镂空圓時我的思路還是講經緯度看出笛卡爾坐標系上的x,y,然而經緯度在並不是均勻分布的,這也導致了用上述方法畫出的圓一旦離開了赤道就會變成橢圓。

這個問題很棘手,首先我們分析問題,圓的失真是由於經緯度分布不均勻導致的,所以我們不能用笛卡爾坐標系來思考問題,而應該將經緯度轉換成球坐標系。維度的范圍是大於-90度而小於90度,而球坐標系中的φ的范圍是0到180,同理,經度的范圍是-180,180,而θ的范圍是0,360。很容易找到他們的關系,即φ = 90-維度,

θ = 180-經度;轉換公式:(維度,經度) = (φ,θ,R)其中R = 地球半徑;

但是得到球坐標系坐標之後分析問題還是十分困難,我們應該將問題轉換成我們熟悉的,即將球坐標系轉換吃笛卡爾坐標系:

公式如下:

r = √(x2+y2+z2)

θ = arccos[z/√(x2+y2+z2)]

φ = arctan(y/x)

代碼實現:

static V3 changeToXyz(LatLng lng){  
         V3 v = new V3();  
        if (lng.latitude<0){  
            v.var1 = 90 + Math.abs(lng.latitude);  
        }else {  
            v.var1 = 90 - lng.latitude ;  
         }  
         if(lng.longitude<0){  
             v.var2 = 180 + Math.abs(lng.longitude);  
         }else {  
             v.var2 = 180 - lng.longitude;  
         }  
         v.var3 = R;  
         V3 temp = new V3();  
         temp.var1 = v.var3*Math.sin(Math.PI*v.var1/180)*Math.cos(Math.PI*v.var2/180);  
         temp.var2 = v.var3*Math.sin(Math.PI*v.var1/180)*Math.sin(Math.PI*v.var2/180);  
         temp.var3 = v.var3*Math.cos(Math.PI*v.var1/180);  
         return temp;  
    }
V3類是我實現vector3的類(即3維向量)

代碼如下:

static class V3 {  
        double var1 = 0.0;  
        double var2 = 0.0;  
        double var3 = 0.0;  
        V3(){  
  
        }  
        V3(Double var1,Double var2, Double var3){  
            this.var1 = var1;  
            this.var2 = var2;  
            this.var3 = var3;  
        }  
        public static V3 add(V3 v1, V3 v2){  
            return new V3(v1.var1+v2.var1,v1.var2+v2.var2,v1.var3+v2.var3);  
        }  
  
  
    }
得到笛卡爾坐標系之後我們終於可以分析問題了,在地圖上畫圓實際上就是在球體上畫圓,我們可以令vector1為地圖上的球心(0,0,0)到圓心center的向量,我們在vector1上任意取一點half,過這點垂直於vector1的平面與球面相交的部分我們要求的圓形,而這個圓形正是以half為圓心的圓形,我們設這個圓形的半徑是r。通過r我們能求出half的坐標。
Double rate =  Math.sqrt(R*R-r*r)/R;
V3 half = new V3(rate*center.var1,rate*center.var2,rate*center.var3);
我們知道這個圓任意一條半徑都是和vector1垂直的,即我們只要知道任意一條半徑所在的向量的表達式遍可以通過旋轉角θ1求出所有半徑所在的向量的表達式。為了方便我們選擇一條在x,y平面上的向量作為這個起始向量vector2(這樣的目的是為了讓起始映射到經緯度坐標系之後與精度軸平行).

公式:

(x,y,z) = (1,-center.x/center.y,0)

然後我們讓這條向量繞著center旋轉,向量旋轉公式:

 

\
  ax,ay,az為center的x,y,z,I是單位矩陣,θ 是旋轉角度,P是需要選擇的向量即vector2;(注意這裡必須將center的變成膜為1的單位向量)

代碼如下

public static V3 getTemp(V3 center,Double ang){  
        center = getmR(center,1.0);  
        Double x = center.var1;  
        Double y = center.var2;  
        Double z = center.var3;  
        Matrix a = new Matrix(3,3);  
        Matrix b = new Matrix(3,3);  
        Matrix i = new Matrix(3,3);  
        double[][] A = new double[3][3];  
        A[0][0] = x * x;    A[0][1] = x * y;    A[0][2] = x * z;  
        A[1][0] = y * x;    A[1][1] = y * y;    A[1][2] = y * z;  
        A[2][0] = z * x;    A[2][1] = z * y;    A[2][2] = z * z;  
        double[][] B = new double[3][3];  
        B[0][0] =  0;       B[0][1] = -z;       B[0][2] = y;  
        B[1][0] =  z;       B[1][1] =  0;       B[1][2] = -x;  
        B[2][0] = -y;       B[2][1] =  x;       B[2][2] =  0;  
        double[][] I = new double[3][3];  
        I[0][0] =  1;       I[0][1] =  0;       I[0][2] = 0;  
        I[1][0] =  0;       I[1][1] =  1;       I[1][2] = 0;  
        I[2][0] =  0;       I[2][1] =  0;       I[2][2] =  1;  
        a.init(A);  
        b.init(B);  
        i.init(I);  
        Matrix m = new Matrix(3,3);  
        m = i.Minus(a);  
        m = m.mMultiply(Math.cos(ang));  
        Matrix t = new Matrix(3,3);  
        t = b;  
        t = t.mMultiply(Math.sin(ang));  
        m = m.Plus(t);  
        m = m.Plus(a);  
        m = m.Trans();  
        t = new Matrix(3,1);  
        double[][] T = new double[3][1];  
        T[0][0] = 1.0;T[1][0] =-1*center.var1/center.var2;T[2][0] =0.0;  
        t.init(T);  
        m = m.Multiply(t);  
        m = m.Trans();  
        return new V3(m.mat[0][0],m.mat[0][1],m.mat[0][2]);  
  
    }
介紹一下用到的Matrix 類

import java.util.Random;  
public class Matrix {  
    public  int row;  
    public  int rank;  
    public  double[][] mat;  
  
    public Matrix(int a, int b) {  
        row = a;  
        rank = b;  
        mat = new double[row][rank];  
    }  
    public void New(){  
        Random rand=new Random();  
        for (int i = 0; i < row; i++)  
            for (int j = 0; j < rank; j++)  
                mat[i][j]=rand.nextInt(100);  
    }  
    public void init(double[][] in){  
        mat = in;  
    }  
    public void Output() {  
        System.out.println("Matrix=:");  
        for (int i = 0; i < row; i++) {  
            for (int j = 0; j < rank; j++)  
                System.out.print(mat[i][j] + " ");  
            System.out.println();  
        }  
        System.out.println();  
    }  
  
    public  Matrix Plus(Matrix a) {  
        Matrix c=new Matrix(row,rank);  
        if (a.row == row && a.rank == rank) {  
            for (int i = 0; i < row; i++)  
                for (int j = 0; j < rank; j++)  
                    c.mat[i][j] = mat[i][j] + a.mat[i][j];  
        } else {  
            System.out.println("matrixAdd error!");  
        }  
        return c;  
    }  
  
    public  Matrix Minus(Matrix a) {  
        Matrix c=new Matrix(row,rank);  
        if (a.row == row && a.rank == rank) {  
            for (int i = 0; i <row; i++)  
                for (int j = 0; j <rank; j++)  
                    c.mat[i][j] = mat[i][j] - a.mat[i][j];  
        } else {  
            System.out.println("matrixMinus error!");  
        }  
        return c;  
    }  
    public Matrix mMultiply(double a){  
        for(int i=0;i<row;i++){  
            for(int j=0;j<rank;j++){  
                mat[i][j] *= a;  
            }  
        }  
        return this;  
    }  
    public Matrix Multiply(Matrix a) {  
        Matrix c = new Matrix(row, a.rank);  
        if (rank == a.row) {  
            for (int i = 0; i < c.row; i++)  
                for (int j = 0; j < c.rank; j++) {  
                    double sum = 0;  
                    for (int k = 0; k < rank; k++)  
                        sum += mat[i][k] * a.mat[k][j];  
                    c.mat[i][j] = sum;  
                }  
        } else {  
            System.out.println("matrix Multiply errors!");  
        }  
        return c;  
    }  
  
    public Matrix Trans() {  
        Matrix c = new Matrix(rank,row);  
        for (int i = 0; i < c.row; i++)  
            for (int j = 0; j < c.rank; j++)  
                c.mat[i][j] = mat[j][i];  
        return c;  
    }  
  
    public Matrix Invs() {  
        int rw = row, rk = rank;  
        Matrix imat = new Matrix(rw, rk);  
        Matrix jmat = new Matrix(rw, rk);  
        for (int i = 0; i < rw; i++)  
            for (int j = 0; j < rw; j++)  
                jmat.mat[i][j] = mat[i][j];  
        for (int i = 0; i < rw; i++)  
            for (int j = 0; j < rw; j++)  
                imat.mat[i][j] = 0;  
        for (int i = 0; i < rw; i++)  
            imat.mat[i][i] = 1;  
  
        for (int i = 0; i < rw; i++) {  
            for (int j = 0; j < rw; j++) {  
                if (i != j) {  
                    double t = jmat.mat[j][i] / jmat.mat[i][i];  
                    for (int k = 0; k < rw; k++) {  
                        jmat.mat[j][k] -= jmat.mat[i][k] * t;  
                        imat.mat[j][k] -= imat.mat[i][k] * t;  
                    }  
                }  
            }  
        }  
        for (int i = 0; i < rw; i++)  
            if (jmat.mat[i][i] != 1) {  
                double t = jmat.mat[i][i];  
                for (int j = 0; j < rw; j++) {  
                    jmat.mat[i][j] = jmat.mat[i][j] / t;  
                    imat.mat[i][j] = imat.mat[i][j] / t;  
                }  
            }  
        return imat;  
    }  
}

好了,既然已經求到了每一個半徑向量,那麼我們用這個向量轉換成膜為1的向量,然後加上half就能求出對應的點,把點連起來就是一個圓了。

以下是源碼:

package com.example.administrator.pass.tools;  
  
import com.baidu.mapapi.map.OverlayOptions;  
import com.baidu.mapapi.map.PolygonOptions;  
import com.baidu.mapapi.map.Stroke;  
import com.baidu.mapapi.model.LatLng;  
  
import java.util.ArrayList;  
import java.util.List;  
  
/** 
 * Created by Administrator on 11/10 0010. 
 */  
  
public class smoke  {  
  
    static Double  R = 6371004.0;  
  
     static V3 changeToXyz(LatLng lng){  
         V3 v = new V3();  
        if (lng.latitude<0){  
            v.var1 = 90 + Math.abs(lng.latitude);  
        }else {  
            v.var1 = 90 - lng.latitude ;  
         }  
         if(lng.longitude<0){  
             v.var2 = 180 + Math.abs(lng.longitude);  
         }else {  
             v.var2 = 180 - lng.longitude;  
         }  
         v.var3 = R;  
         V3 temp = new V3();  
         temp.var1 = v.var3*Math.sin(Math.PI*v.var1/180)*Math.cos(Math.PI*v.var2/180);  
         temp.var2 = v.var3*Math.sin(Math.PI*v.var1/180)*Math.sin(Math.PI*v.var2/180);  
         temp.var3 = v.var3*Math.cos(Math.PI*v.var1/180);  
         return temp;  
    }  
    static LatLng getLatLng(V3 in){  
        Double x = in.var1;  
        Double y = in.var2;  
        Double z = in.var3;  
        Double r = Math.sqrt(x*x+y*y+z*z);  
        Double ceta =    Math.atan(y/x);//x  
        Double gama = Math.acos(z/r); //z  
        if (x==0.0&&y==0.0){  
            ceta = 0.0;  
        }  
        ceta = Math.abs(ceta);  
        if(x>0&&y>=0){  
            ceta  = ceta;  
        }  
        if(x<=0&&y>0){  
            ceta = Math.PI/2-ceta;  
            ceta += Math.PI/2;  
        }  
        if(x<0&&y<=0){  
            ceta += Math.PI;  
        }  
        if(x>=0&&y<0){  
            ceta = Math.PI/2-ceta;  
            ceta += Math.PI/2*3;  
        }  
        Double latitude = (gama/Math.PI)*180;  
        Double longitude = (ceta/Math.PI)*180;  
        if (latitude >= 90){  
            latitude = -1*(latitude-90);  
        }else {  
            latitude = 90 - latitude;  
        }  
        if (longitude >=180){  
            longitude = -1*(longitude-180);  
        }else {  
            longitude = 180 - longitude;  
        }  
        return new LatLng(latitude,longitude);  
  
    }  
    V3 test(V3 in){  
        Double x = in.var1;  
        Double y = in.var2;  
        Double z = in.var3;  
        Double r = Math.sqrt(x*x+y*y+z*z);  
        Double ceta =   Math.PI/2 + Math.atan(y/x);  
        Double gama = Math.acos(z/r);  
        return (new V3(ceta,gama,r));  
    }  
  
  
  
    public static OverlayOptions getOverlayOptions(LatLng Center, Double r, int acc){  
        List<LatLng> pts = new ArrayList<LatLng>();  
        getLatLng(changeToXyz(new LatLng(0.0,0.0)));  
        V3 center = changeToXyz(Center);  
        Double rate =  Math.sqrt(R*R-r*r)/R;  
        V3 half = new V3(rate*center.var1,rate*center.var2,rate*center.var3);  
        V3 temp = new V3();  
        V3 mR = new V3();  
        LatLng lat = new LatLng(0.0,0.0);  
        for(int i=0;i<acc/2+1;i++){  
  
//              temp = new V3(R*Math.cos((2*Math.PI)/acc*i),R*Math.sin((2*Math.PI)/acc*i),0.0);  
                temp = getTemp(center,(2*Math.PI)/acc*i);  
//              mR = getvertical(center,temp,r);  
                mR = getmR(temp,r);  
//          System.out.println(mR.var1+"%%%%%%%"+mR.var2+"%%%%%%%%"+mR.var3);  
                mR = V3.add(mR,half);  
                lat = getLatLng(mR);  
                System.out.println(lat.latitude+"**********"+lat.longitude);  
                pts.add(lat);  
  
        }  
  
  
        LatLng pt1 = new LatLng(lat.latitude,180);  
        pts.add(pt1);  
        LatLng pt2 = new LatLng(90,180);  
        pts.add(pt2);  
        LatLng pt3 = new LatLng(90,-180);  
        pts.add(pt3);  
        LatLng pt4 = new LatLng( getPoint(center,acc,0,r,half).latitude,-180);  
        pts.add(pt4);  
        for(int i=acc/2;i<acc+1;i++){  
  
                temp = getTemp(center,(2*Math.PI)/acc*i);  
//              mR = getvertical(center,temp,r);  
                mR = getmR(temp,r);  
  
                mR = V3.add(mR,half);  
//          System.out.println(mR.var1+"%%%%%%%"+mR.var2+"%%%%%%%%"+mR.var3);  
                lat = getLatLng(mR);  
                System.out.println(lat.latitude+"**********"+lat.longitude);  
                pts.add(lat);  
        }  
  
        pt1 = new LatLng(lat.latitude,180);  
        pts.add(pt1);  
        pt2 = new LatLng(-90,180);  
        pts.add(pt2);  
        pt3 = new LatLng(-90,-180);  
        pts.add(pt3);  
        pt4 = new LatLng(getPoint(center,acc,acc/2,r,half).latitude,-180);  
        pts.add(pt4);  
        OverlayOptions polygonOption = new PolygonOptions()  
                .points(pts)  
                .stroke(new Stroke(4,0))  
                .fillColor(0x99999900);  
        return polygonOption;  
    }  
  
    public static OverlayOptions hhh(){  
        List<LatLng> pts = new ArrayList<LatLng>();  
        LatLng p = new LatLng(20.0,30.0);  
        pts.add(p);  
        p = new LatLng(30.0,45.0);  
        pts.add(p);  
        p = new LatLng(40.0,20.0);  
        pts.add(p);  
        p = new LatLng(40.0,20.0);  
        pts.add(p);  
        p = new LatLng(40.0,20.0);  
        pts.add(p);  
        OverlayOptions polygonOption = new PolygonOptions()  
                .points(pts)  
                .stroke(new Stroke(4,0))  
                .fillColor(0x99999900);  
        return polygonOption;  
    }  
  
  
  
    static class V3 {  
        double var1 = 0.0;  
        double var2 = 0.0;  
        double var3 = 0.0;  
        V3(){  
  
        }  
        V3(Double var1,Double var2, Double var3){  
            this.var1 = var1;  
            this.var2 = var2;  
            this.var3 = var3;  
        }  
        public static V3 add(V3 v1, V3 v2){  
            return new V3(v1.var1+v2.var1,v1.var2+v2.var2,v1.var3+v2.var3);  
        }  
  
  
    }  
    public static V3 getTemp(V3 center,Double ang){  
        center = getmR(center,1.0);  
        Double x = center.var1;  
        Double y = center.var2;  
        Double z = center.var3;  
        Matrix a = new Matrix(3,3);  
        Matrix b = new Matrix(3,3);  
        Matrix i = new Matrix(3,3);  
        double[][] A = new double[3][3];  
        A[0][0] = x * x;    A[0][1] = x * y;    A[0][2] = x * z;  
        A[1][0] = y * x;    A[1][1] = y * y;    A[1][2] = y * z;  
        A[2][0] = z * x;    A[2][1] = z * y;    A[2][2] = z * z;  
        double[][] B = new double[3][3];  
        B[0][0] =  0;       B[0][1] = -z;       B[0][2] = y;  
        B[1][0] =  z;       B[1][1] =  0;       B[1][2] = -x;  
        B[2][0] = -y;       B[2][1] =  x;       B[2][2] =  0;  
        double[][] I = new double[3][3];  
        I[0][0] =  1;       I[0][1] =  0;       I[0][2] = 0;  
        I[1][0] =  0;       I[1][1] =  1;       I[1][2] = 0;  
        I[2][0] =  0;       I[2][1] =  0;       I[2][2] =  1;  
        a.init(A);  
//      System.out.println("A:");  
//      a.Output();  
        b.init(B);  
//      System.out.println("B:");  
//      b.Output();  
        i.init(I);  
//      System.out.println("I:");  
//      i.Output();  
        Matrix m = new Matrix(3,3);  
        m = i.Minus(a);  
//      m.Output();  
        m = m.mMultiply(Math.cos(ang));  
//      m.Output();  
        Matrix t = new Matrix(3,3);  
        t = b;  
        t = t.mMultiply(Math.sin(ang));  
//      m.Output();  
        m = m.Plus(t);  
//      m.Output();  
        m = m.Plus(a);  
//      m.Output();  
        m = m.Trans();  
//      m.Output();  
        t = new Matrix(3,1);  
        double[][] T = new double[3][1];  
  
//      T[0][0] = 1.0;T[1][0] =1.0;//T[0][2] = -1*(center.var1*center.var2)/center.var3;  
//      T[2][0] = -1*(center.var1*center.var2)/center.var3;  
        T[0][0] = 1.0;T[1][0] =-1*center.var1/center.var2;T[2][0] =0.0;  
                t.init(T);  
        m = m.Multiply(t);  
        m = m.Trans();  
//      m.Output();  
        return new V3(m.mat[0][0],m.mat[0][1],m.mat[0][2]);  
  
    }  
    public static V3 getvertical(V3 v1, V3 v2, Double r){  
        Double a1 = v1.var1;  
        Double a2 = v1.var2;  
        Double a3 = v1.var3;  
        Double b1 = v2.var1;  
        Double b2 = v2.var2;  
        Double b3 = v2.var3;  
        Double dy = (a1*b3-b1*a3)/(b2*a3-b3*a2);  
        Double dz =  (a1*b2-a2*b1)/(a2*b3-a3*b2);  
        Double x = Math.sqrt((r*r)/(1+dy*dy+dz*dz));  
        if ((b2*a3-b3*a2) == 0){  
            x = 0.0;  
            Double z = Math.sqrt((r*r)/((a3*a3)/(a2*a2)+1));  
            Double y = -1*(a3/a2)*z;  
            if(x*a1+y*a2+z*a3 != 0||x*b1+y*b2+z*b3 != 0){  
//              System.out.println("ERROR!");  
            }  
            return new V3(x,y,z);  
        }  
  
        if(x*a1+dy*x*a2+dz*x*a3 != 0||x*b1+dy*x*b2+dz*x*b3 != 0){  
            Double e1 = x*a1+dy*x*a2+dz*x*a3;  
            Double e2 = x*b1+dy*x*b2+dz*x*b3;  
//          System.out.println("ERROR!     "+e1+"    "+"ERROR!     "+e2);  
        }  
  
        return new V3(x,dy*x,dz*x);  
    }  
    public static V3 getmR(V3 v,double r){  
        double x = v.var1;  
        double y = v.var2;  
        double z = v.var3;  
        double sum = x*x + y*y + z*z;  
        double k = Math.sqrt(sum/(r*r));  
        x = x/k;  
        y = y/k;  
        z = z/k;  
        return new V3(x,y,z);  
    }  
    public static LatLng getPoint(V3 center,double acc,int i,double r,V3 half){  
        V3 temp = getTemp(center,(2*Math.PI)/acc*i);  
//              mR = getvertical(center,temp,r);  
        V3 mR = getmR(temp,r);  
//          System.out.println(mR.var1+"%%%%%%%"+mR.var2+"%%%%%%%%"+mR.var3);  
        mR = V3.add(mR,half);  
        LatLng lat = getLatLng(mR);  
        return lat;  
    }  
  
}
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved