我在美国有一个温度位图,可以显示为地图叠加层。该部分工作正常 - 位图温度叠加完美地位于地图上相对于边界和地理点。
我的目标是能够点击此温度位图,然后根据该像素颜色输出温度。位图叠加层将根据当前地图投影进行缩放和定位。我在点击时获取位图像素的解决方案要求我使用地理点向后移动,考虑缩放,然后从原始位图图像中检索点击点。
点击工作正常,但我注意到哪些像素被检索不准确。例如,我可以点击位图的可见部分下方(如墨西哥)并仍然返回彩色像素 - 相反,在地图的顶部(加拿大附近),我可以点击可见的位图而不返回任何像素。就好像返回的像素值都向南移动了大约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
}
}
答案 0 :(得分:0)
如果其他人偶然发现了这一点 - 我找到了解决方案。显然,错误是由于发生了web mercator映射转换。我覆盖在地图上的位图只能在远北和南边界准确。那是错误为零的地方。我越接近我的位图相对于纬度的中点,误差就越大。我能够通过在位图上绘制一组像素然后将它们与已知的lat线进行比较来量化中点处的误差。在这种特殊情况下,误差在中点处约为54个像素。我还在已知的纬度上测试了南北方的一些其他点,以便创建错误数据集。现在,我知道我的错误,我可以插入一个修正,以应用于每个特定的纬度。为了准确插值,我正在使用Cubic插值。