3

I have created this post -> plot a real world lat lon into different angle still image map

from that, I can successfully mark the given lat&lon given the two (2) coordinates (upper left, lower right) but due to incorrect angle of the still image map compare to real world map angle, my mark was displaced.

Now, I am thinking of using four (4) coordinates (upper left, lower left, upper right, lower right) of the image. So that, I could plot the given lat&lon without considering the angle.

I think, even without Android experience could answer this question. I just kinda slow with Mathematics matter.

It is possible to implement it? if yes, any guidance & code snippets are appreciated.

UPDATES1 Main goal is to mark the given lat&lon into image map which has different angle against to real world map.

UPDATES2 I am using the below codes to compute my angle. Would you check it if it is reliable for getting the angle. Then convert it to pixel. NOTE: this codes are using only two coordinates of the image plus target coordinate.

public static double[] calc_xy (double imageSize, Location target, Location upperLeft, Location upperRight) {
    double newAngle = -1;
    try {
        double angle = calc_radian(upperRight.getLongitude(), upperRight.getLatitude(), 
                upperLeft.getLongitude(), upperLeft.getLatitude(), 
                target.getLongitude(), target.getLatitude());
        newAngle = 180-angle;

    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    double upperLeft_Target_dist = upperLeft.distanceTo(target);

    double upperLeft_Right_dist = upperLeft.distanceTo(upperRight);
    double distancePerPx = imageSize /upperLeft_Right_dist;

    double distance = upperLeft_Target_dist * distancePerPx;

    double radian = newAngle * Math.PI/180;

    double[] result = radToPixel(distance, radian);
    return result;
}

public static double[] radToPixel(double distance, double radian) {
    double[] result = {-1,-1};
    result[Functions.Location.PIXEL_X_LON] = distance * Math.cos(radian);
    result[Functions.Location.PIXEL_Y_LAT] = distance * Math.sin(radian);
    return result;
}

public static double calc_radian(Double x1, Double y1, Double x2, Double y2, Double x3, Double y3)
    throws Exception{

    double rad = 0.0;

    if((Double.compare(x1, x2) == 0 && Double.compare(y1, y2) == 0) ||
            (Double.compare(x3, x2) == 0 && Double.compare(y3, y2) == 0))
    {
        Log.d(tag, "Same place") ;
        return rad;
    }

    /* compute vector */
    double BAx = x2 - x1;
    double BAy = y2 - y1;

    double BCx = x3 - x2;
    double BCy = y3 - y2;

    double cosA =  BAx / Math.sqrt( BAx * BAx + BAy * BAy ) ;
    double cosC =  BCx / Math.sqrt( BCx * BCx + BCy * BCy ) ;

    double radA = Math.acos( cosA ) * 180.0 / Math.PI ;
    double radC = Math.acos( cosC ) * 180.0 / Math.PI ;
    if( BAy < 0.0 )
    {
        radA = radA * -1.0 ;
    }
    if( BCy < 0.0 )
    {
        radC = radC * -1.0 ;
    }

    rad = radC - radA ;


    if( rad > 180.0 )
    {
        rad = rad - 360;
    }

    if( rad < -180.0 )
    {
        rad = rad + 360;
    }

    return rad ;
}
Community
  • 1
  • 1
eros
  • 4,946
  • 18
  • 53
  • 78
  • It looks like the angle might be constant. If that is the case you could simply apply a transform to each lat/lon point. – John J Smith Sep 21 '11 at 08:54
  • Actually, I think it might be better to keep the point stationary and rotate your image. You could rotate it consistent with the direction the device is held. – John J Smith Sep 21 '11 at 19:35
  • @John J Smith , 1) angle is constant. would you assist me to have applied a transformation of lat/lon point? 2) rotation approach seems the best way. If we can't able to transform the lat/lon, i'll try this one... it seems these are the answer for my post. would you post it as answer. So that, people can vote on. – eros Sep 26 '11 at 00:20
  • Anyone ever get these methods to work properly using a custom map? – James andresakis Oct 30 '13 at 04:34

3 Answers3

2

This looks like you want to plot the user's current geo-location on an image of, say a building or campus. Assuming this, my approach would be to 'map' the still image to the screen which is likely to require a translation transform, a rotation transform and a scaling transform. In addition, you will need to know the actual geo-location coordinates of at least two points on your image. Given the image in your previous post, I would assume you have the geo coordinates of the bottom left corner and the bottom right corner. You already have the information to convert a geo coordinate into a screen coordinate so the image can be drawn matching up the bottom left corner of your image with the pixel coordinate which you've calculated. I will call this point your anchor point.

At this stage you probably have an image with one corner at the correct location but now it needs to be scaled down or up and then rotated about your anchor point. You can get the current zoom level from your mapView or you can get the latitudeSpan and you can calculate the scale factor to be applied to your image.

Lastly, if you have the geo coordinates of the two corners of the image, you can calculate the angle the image should be rotated. This can be calculated using pythagoras or you can convert from Cartesian coordinates to polar coordinates see here. This calculation doesn't have to be done by your app - it can be calculated separately and put in as a constant. Now you can apply the rotation transform around your fixed anchor point.

You may also want to make use of handy built-in functions such as mapController.zoomInFixing() which takes pixel coordinates or one of the other zoomTo() or animateTo() functions.

Edit: If you're not using a mapview to manage your geo-coordinates then you can apply the image transformations using code like this:

// create a matrix for the manipulation
    Matrix matrix = new Matrix();
    // resize the bit map
    matrix.postScale(scaleWidth, scaleHeight);
    // rotate the Bitmap
    matrix.postRotate(angle);

// recreate the new Bitmap
    Bitmap resizedBitmap = Bitmap.createBitmap(bitmapOrg, 0, 0, 
                      width, height, matrix, true); 

    // make a Drawable from Bitmap to allow to set the BitMap 
    // to the ImageView, ImageButton or what ever
    BitmapDrawable bmd = new BitmapDrawable(resizedBitmap);

    ImageView imageView = new ImageView(this);

    // set the Drawable on the ImageView
    imageView.setImageDrawable(bmd);

Edit: With the upper left and lower right coordinates, you can calculate the angle as follows:

angle = sin-1((right.x - left.y)/sqrt((right.x - left.x)sq + (right.y - left.y)sq))

[Where sqrt = square root; sq = squared

John J Smith
  • 11,435
  • 9
  • 53
  • 72
  • I am not using any MapController or MapView rather simple ImageSwitcher & ImageView. So I need to compute it manually. – eros Sep 27 '11 at 06:28
  • any other idea? would you give samples? – eros Sep 27 '11 at 10:53
  • If you have the geo location coordinates of two points of the image, you can calculate the angle. – John J Smith Sep 27 '11 at 11:44
  • (1) what is the two points? (2) how can I calculate the angle with two points of the image? – eros Sep 28 '11 at 06:58
  • Any two points on your image - ideally, the geo-location coordinates of the bottom left corner and the bottom right corner. Then you can use Pythagoras to calculate the angle. If you have these two coordinates I'll calculate it for you. – John J Smith Sep 28 '11 at 14:32
  • let say I have the upper left and lower right coordinates. May I know the formula on how to calculate the angle? – eros Sep 29 '11 at 00:03
  • Cool formula~ Thanks. How about using upperLeft and upperRight coordinates. Is it the same formula? I am thinking of getting the angle,distance then compute it proportionate to image size (pixel). Are you referring to X as Lon? and Y as Lat? – eros Sep 30 '11 at 02:43
  • Yes, same formula for upper left and upper right. X can be either x pixels or latitude; y can be either y pixels or longitude. However, you can have problems with negative lat/lon values and the sin function. It is also more accurate to convert lat/lon to screen pixels and then use these in the formula. – John J Smith Sep 30 '11 at 08:20
1

If you know what is the angle, it is a simple Cartesian rotation of the axis.

Let x be the old longitude, y be the old latitude, and b be the angle

The new longitude x' = x*cos(b) - y*sin(b)

The new latitude y' = x*sin(b) + y*cos(b)

Sherif elKhatib
  • 45,786
  • 16
  • 89
  • 106
0

I'm not sure I understand but it seems to me like you want to calculate the angle of the image that you want using two points then rotate it and resize it based on the number of pixels between point a and b (two corners) using the method of changing from lat lon to pixels and the distance formula

ghostbust555
  • 2,040
  • 16
  • 29
  • >want to calculate the angle -> yes but i am thinking of alternative solution by compute it using 4 coordinates (upper left, lower left, upper right, lower right). – eros Sep 15 '11 at 02:07