1

マップ オーバーレイとして表示される米国全体の気温のビットマップがあります。その部分は正常に機能します。ビットマップ温度オーバーレイは、境界線と地理的ポイントに対してマップ上に完全に配置されます.

私の目標は、この温度ビットマップをタップして、そのピクセルの色に基づいて温度を出力できるようにすることです。ビットマップ オーバーレイは、現在の地図投影に基づいてスケーリングおよび配置されています。タップされたときにビットマップ ピクセルを取得するための私の解決策では、ジオポイントを使用して逆戻りし、スケーリングを考慮してから、元のビットマップ イメージからタップされたポイントを取得する必要があります。

タッピングは正常に機能しますが、どのピクセルが取得されるかについては不正確であることに気付きました。たとえば、ビットマップの可視部分の下をタップしても (メキシコのように)、色付きのピクセルを返すことができます. これは、返されたピクセル値がすべて南に約 50 マイルずれているようなものです。ズームアウトすると、エラーは大きくも明白でもありませんが、ズームインすると、明らかに間違ったピクセル (温度) 値が返されるため、明らかになります。

私の方法は健全だと思いますが、私が扱っている大きな数が「倍精度」で問題を引き起こしているのではないかと思っています。BigDecimal (経験なし) またはその他の数値形式に切り替える必要がありますか? これを行うより良い方法はありますか?

以下のコード>>>>

public class BitmapOverlay extends Overlay {

Bitmap bmp;
Bitmap bmp2;
Context mContext;
GeoPoint upperLeft;
GeoPoint lowerRight;
Paint paint;
Paint lpaint;
Point ppupperLeft;
Point pplowerRight;
Rect src;
Rect src2;
Rect dst;
int frame;
int complete=100;

boolean shadow;
AnimationDrawable animation;
ImageView radarView;

Double W=(-129.357400913)* 1E6;
Double S=(23.560962423770285)* 1E6;
Double E=(-64.6787004566)* 1E6;
Double N=(50.3092170302897)* 1E6;

Projection currentProjection;

boolean mExternalStorageAvailable = false;
String fullPath;

boolean running;

public BitmapOverlay (Context freshContext){

    paint = new Paint(Paint.FILTER_BITMAP_FLAG);

    paint.setAntiAlias(true);
    paint.setFilterBitmap(true);
    paint.setDither(true);



    String state = Environment.getExternalStorageState();

    if (Environment.MEDIA_MOUNTED.equals(state)) {
    // We can read and write the media
    mExternalStorageAvailable = true;

    Log.i("isSdReadable", "External storage card is readable.");

    } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
    // We can only read the media
    Log.i("isSdReadable", "External storage card is readable.");
    mExternalStorageAvailable = true;
    } else {
    // Something else is wrong. It may be one of many other
    // states, but all we need to know is we can neither read nor write
    mExternalStorageAvailable = false;
    }








    upperLeft=new GeoPoint(N.intValue(),W.intValue());
    lowerRight=new GeoPoint(S.intValue(),E.intValue());


    ppupperLeft = new Point();
    pplowerRight = new Point();



    mContext=freshContext;




}






public void UpdateFrame(int sentframe , String ET){
    frame=sentframe;
//  complete=sentcomplete;




    if ( mExternalStorageAvailable == true) {

    //  Log.i("MyRadarOverlay", "got BMP Frame="+frame);

        //have to convert complete to frame to sequence... otherwise it gets to 5     
and stops..
        //might need to figure better wayt o tell when bmp is done
        //complete=frame-1;

        if (ET.equals("temp")){fullPath =  
Environment.getExternalStorageDirectory().getAbsolutePath() +  
                "/Pictures/ti0.png";}

        if (ET.equals("radar")){fullPath = 
Environment.getExternalStorageDirectory().getAbsolutePath() +  
                "/Pictures/ri"+frame+".png";}



        // Look for the file on the external storage
        try {



        bmp = BitmapFactory.decodeFile(fullPath);
        //}
        } catch (Exception e) {
        Log.e("getThumbnail() on external storage", e.getMessage());
        }


        if (ET.equals("radar")){    
        fullPath = Environment.getExternalStorageDirectory().getAbsolutePath() +  
                "/Pictures/si"+frame+".png";

    //  Log.i("MyRadarOverlay", "sifile path="+fullPath);

        // Look for the file on the external storage
        try {
        //if (tools.isSdReadable() == true) {

        bmp2 = BitmapFactory.decodeFile(fullPath);
        //}
        } catch (Exception e) {
        Log.e("getThumbnail() on external storage", e.getMessage());
        }
        //end of second if et == radar
 }

    }



}




  public void draw(Canvas canvas, MapView mapView, boolean shadow) {



    currentProjection=mapView.getProjection();

    currentProjection.toPixels(upperLeft, ppupperLeft);
    currentProjection.toPixels(lowerRight, pplowerRight);



    dst = new Rect( ppupperLeft.x, ppupperLeft.y, pplowerRight.x, pplowerRight.y );

    if (bmp2 != null ){

        src = new Rect( 0,0, bmp2.getWidth() , bmp2.getHeight()  );

        canvas.drawBitmap(bmp2, src, dst, paint);


      } 



  if (bmp != null ){


    src = new Rect( 0,0, bmp.getWidth() , bmp.getHeight()  );

    canvas.drawBitmap(bmp, src, dst, paint);



  } 



}




//###################ON TAP#################################   


@Override
public boolean onTap( GeoPoint geoPoint, MapView mapView) {



//  Log.i("My Info", "overlay-on tap called");
     Log.i("BITMAP OVERALY", "TAP at"+geoPoint);     

 //  take left lon add right lon...add basically get a range of lons that the point can  
fall under//
//   if it falls within the range get the percentage ...


 //  the start left most lon is equivalent to 0 the right most is equavalent to the 
width--1600
//   find the relative position on that range

     double xpixel=0;
     double ypixel=0;

     double latgeopoint=geoPoint.getLatitudeE6();
     double longeopoint=geoPoint.getLongitudeE6();


    //find out if it is within longitude range of bitmap
    if (longeopoint>W && longeopoint<E){
        //find out if it is within latitude range of bitmap
        if (latgeopoint>S && latgeopoint<N){

        Log.i("BITMAP OVERALY", "passed if statement- 
lon,lat"+longeopoint+","+latgeopoint);

        //work  on lon side
        double lonrange=W-longeopoint;
        Log.i("BITMAP OVERALY", "lonrange="+lonrange);

        //-64678700456
        double lonratio=lonrange/W-E;
        Log.i("BITMAP OVERALY", "lonratio="+lonratio);

        xpixel=lonratio*bmp.getWidth();
        Log.i("BITMAP OVERALY", "xpixel="+xpixel);

        //work on lat side

        double latrange=N-latgeopoint;
        Log.i("BITMAP OVERALY", "latrange="+latrange);

        //26748254607
        double latratio=latrange/N-S;
        Log.i("BITMAP OVERALY", "latratio="+latratio);

        ypixel=latratio*bmp.getHeight();
        Log.i("BITMAP OVERALY", "ypixel="+ypixel);


        //end if lat
        }
    //end if lon    
    }


     //convert doubles to ints
    int pixelx = (int)xpixel;
    int pixely = (int)ypixel;

    Log.i("BITMAP OVERALY", "pixelx,pixely="+pixelx+","+pixely);



    int pixel = bmp.getPixel(pixelx, pixely);



    int redValue = Color.red(pixel);
    int greenValue = Color.green(pixel);
    int blueValue = Color.blue(pixel);

    float[] hsv = new float[3];
    Color.RGBToHSV(redValue, greenValue, blueValue, hsv);

    String mytemp="";



    if (hsv[0]<5){mytemp="Greater than 110";}
    if (hsv[0]<=20 && hsv[0]>5){mytemp="100 to 110";}
    if (hsv[0]<=45 && hsv[0]>20){mytemp="90 to 100";}
    if (hsv[0]<=60 && hsv[0]>45){mytemp="80 to 90";}
    if (hsv[0]<=80 && hsv[0]>60){mytemp="70 to 80";}
    if (hsv[0]<=120 && hsv[0]>80){mytemp="60 to 70";}
    if (hsv[0]<=150 && hsv[0]>120){mytemp="50 to 60";}







            AlertDialog.Builder dialog = new AlertDialog.Builder(mContext);


              dialog.setNegativeButton("Close",
                      new DialogInterface.OnClickListener() {
                          public void onClick(DialogInterface dialog, int id) {

                                dialog.cancel();

                          }
                      });


              dialog.setTitle("BITMAP TAP hsv=" + hsv[0] + " " + hsv[1] + " " + 
hsv[2] + " TEMP="+mytemp);



              dialog.show();



    return false; 
 //end on tap   
} 



}
4

1 に答える 1

0

他の誰かがこれに出くわした場合に備えて、解決策を見つけました。どうやらエラーは、Web メルカトル マップの変換によるものです。マップにオーバーレイしているビットマップは、北と南の境界でのみ正確です。そこが誤差ゼロです。緯度に対してビットマップの中間点に近づくほど、エラーが大きくなります。ビットマップ上に一連のピクセルを描画し、それらを既知の緯線と比較することで、中間点でのエラーを定量化することができました。この特定のケースでは、エラーは中間点で約 54 ピクセルでした。エラーのデータセットを作成するために、既知の緯度で北と南のいくつかのポイントもテストしました。エラーがわかったので、補正を補間して特定の緯度ごとに適用できます。正確に補間するために、Cubic Interpolation を使用しています。

于 2013-09-24T14:00:31.440 に答える