GroundOverlay image not rotated - android

Regarding positioning an image on a map giving its bounds, Google Maps' documentation states:
When the image is drawn on the map it will be rotated to fit the bounds. If the bounds do not match the original aspect ratio, the image will be skewed.
But in my code I have this:
GroundOverlayOptions goo2 = new GroundOverlayOptions()
.image(BitmapDescriptorFactory.fromResource(imgRes))
.positionFromBounds(new LatLngBounds(
new LatLng(44.415, 8.937),
new LatLng(44.42, 8.942)
));
mMap.addGroundOverlay(goo2);
The image is not rotated, but always drawn straight pointing north, and skewed. Changing the overlay corners just skews more and it never rotates a bit.
How can I set GMaps to rotate it, or does any external tool exist to rotate it?

I solved this by myself.
I think that Google's documentation is not very clear. It states that a GroundOverlay can be positioned using two possible methods:
There are two ways to specify the position of the ground overlay:
Using a LatLng to center the overlay, and dimensions in meters to specify the size of the image.
Using a LatLngBounds to specify the north east and south west corners of the image.
You must specify the position of the ground overlay before it is added to the map.
I was using the second way, or giving it two geo-corners of the image I wanted to apply. What is not clear is that with the second method rotation is not possible, and every discrepancy in proportion will be rendered with a skewed image. Actually the idea I had was exactly that, given two points on a plain, we have exactly one image that can fit those two points without stratching, but just rotating, I was disappointed discovering that does not work.
However, if you have enough patience to calculate by your own size in meters and rotation of your image, you can determine one corner, or the center of the image, and use the first method, using LatLng and explicitly indicate an anchor, for example (0, 0) for upper left corner or (0.5, 0.5) for the center, a height of the picture in meters (here is a good way to find it: How to convert latitude or longitude to meters?), find a rotation by using trigonometry, and that's it.
A way to find the image size in pixels is indicated here.
That's my final code, for memory:
BitmapFactory.Options dimensions = new BitmapFactory.Options();
dimensions.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), imgRes, dimensions);
int imgHeightPixels = dimensions.outHeight;
GroundOverlayOptions goo = new GroundOverlayOptions()
.image(BitmapDescriptorFactory.fromResource(imgRes))
.position(imgBottomLeftCorner, imgHeightInPixels)
.anchor(0, 1)
.bearing(imgRotation);
mMap.addGroundOverlay(goo);
Watch out that the Y coordinates on the map grow bottom up, while on the image grow top down, so the anchor is (0,1).
Given two vectors, here's what I did to find their angle, and consequently the image rotation (using a vector made of two points coordinates on the image versus a vector made of the same two points geographic coordinates):
private static double calcDistance(double x1, double y1, double x2, double y2) {
return (Math.sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1)));
}
private static double calcVectorRotation(double x1, double y1, double x2, double y2) {
return Math.asin( (y1-y2) / calcDistance(x1, y1, x2, y2) );
}

As you've already mentioned and based from the documentation, if the bounds do not match the original aspect ratio, the image will be skewed.
You should try using android:adjustViewBounds to preserve the aspect ratio.
Set this to true if you want the ImageView to adjust its bounds to preserve the aspect ratio of its drawable.
Please try adding the following into your XML:
android:adjustViewBounds="true"
android:scaleType="fitCenter"
You may also try the suggested code implementations in this SO post. Hope that helps!

Related

Want to map zoomed image coordinates with actual image coordinates in android imageview

I am currently using this gitup touchimageview https://github.com/MikeOrtiz/TouchImageView library.... After zoom,based on the zoom percentage I want to map the longpress coordinates to original image coordinates. Any help will be appreciated
Try to get matrix of ImageView:
float[] values = new float[9];
getImageMatrix().getValues(values);
With this array, you have position of top-left corner in terms of image on indexes 2 and 5. For example, when values[2], values[5] is -10,-10 it means, that left top corner of screen is 10,10 pixel of image. So, you can get coordinate of long press:
float imageX = (pressX - values[2])/scale;
float imageY = (pressY - values[5])/scale;
Recently I work with zoomed images, and use this library: https://github.com/chrisbanes/PhotoView
I think its a bit better, it have some predifined touches with image coordinates, and is still improved (last commit ~2 months ago)

Draw Circle in ImageView when getting current location IndoorAtlas SDK

I want to get current location and draw blue dot like picture above. The blue dot is moving when the current location change.
Here is my code :
public void onServiceUpdate(ServiceState state) {
mSharedBuilder.setLength(0);
mSharedBuilder.append("Location: ")
.append(state.getRoundtrip()).append("ms")
.append(state.getGeoPoint().getLatitude())
.append(state.getGeoPoint().getLongitude())
.append(state.getMetricPoint().getX())
.append(state.getMetricPoint().getY())
.append(state.getImagePoint().getI())
.append(state.getImagePoint().getJ())
.append(state.getHeadingDegrees())
.append(state.getUncertainty());
double x1 = state.getMetricPoint().getX();
double y1 = state.getMetricPoint().getY();
float x = (float) x1;
float y = (float) y1;
Paint paint = null;
canvas.drawCircle(x,y,1,paint);
}
Could you help me ? The pictures already in resource folder.
First, in this case it is easier if you use coordinates from ServiceState#getImagePoint() - these (I & J) are coordinates of your location in the original floor plan. I.e. if your original mapped & uploaded floor plan had dimensions 800x600, service might return position I:400,J:300 indicating that you are now in the center of your mapped area.
You cannot however draw a circle like this: canvas.drawCircle(400, 300, radius, paint) - because depending on how your image is currently displayed (e.g. scaled) you might be drawing into incorrect location.
You need to take into account where your image is on the screen and what are it's current dimensions, i.e. scaling ratio. E.g. if you have a display of size 1920x1080 and your floor plan image of size 800x600 is drawn centered and without any scaling into an ImageView that occupies the entire screen real estate (assume full 1920x1080 in portrait here), then you would need to draw your current coordinate (400,300) into canvas at x: ((1080-800)/2)+400, y: ((1920-600/2)+300) = 540,960.
To draw accuracy with the blue dot (the semi-transparent larger circle), use uncertainty to calculate circle radius.

Android Opencv calculate size of rotated image inside rectangle

I want to calculate rotated image size, Image is inside rectangle. I have rectangle width, height and angle of rotated image. Any one tell me
how to calculate rotated image size?
So you have width, height and angle means you already got RotatedRect.
Now using the method
Rect RotatedRect::boundingRect();
you can easly calculate the bounding box for rotated rect.
for more info see RotatedRect.
Edit:
As per your comment below is the way how to find the width and height of rotated rect.
So you know the four corners of rectangle, lets say (x1,y1),(x2,y2),(x3,y3),(x4,y4), now you need to find the transformed point after rotation by the given angle, let it be (xT1,yT1),(xT2,yT2),etc...
where
xT = x0+(x-x0)*cos(theta)+(y-y0)*sin(theta)
yT = y0-(x-x0)*sin(theta)+(y-y0)*cos(theta)
here (x0,y0) is the center around which you are rotating. and theta = angle * CV_PI / 180.0
Using above calculate four transformed points, finally calculate the height and width by finding the distance between transformed points.

Attain maximum zoom on google map showing all markers

i have 5 markers to display on the map, out of which 4 are very near to each other and the fifth one is a little bit distant to these 4. now when i display the map i want all these 5 markers to be shown on map and the with the highest possible zoom. i dont care whether they are on the border of the screen or in the center of the screen.i mean the markers can be scattered on the screen but all i want is that all markers should visible to the user and with the highest possible zoom.
i have tried this Android map v2 zoom to show all the markers . but the result is that it is showing all markers at the center of the map with very little zoom. actually i have calculated screen dimensions using this code.
DisplayMetrics metrics=new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
float height=metrics.heightPixels/metrics.xdpi;
float width=metrics.widthPixels/metrics.ydpi;
but i dont know why there is very little zoom. But wen i saw android documentation, i think the function is doing justice by doing whatever it said it will do.
public static CameraUpdate newLatLngBounds (LatLngBounds bounds, int width, int height, int padding)
Returns a CameraUpdate that transforms the camera such that the specified
latitude/longitude bounds are centered on screen within a bounding box of specified
dimensions at the greatest possible zoom level. You can specify additional padding,
to further restrict the size of the bounding box. The returned CameraUpdate has a
bearing of 0 and a tilt of 0.
Unlike newLatLngBounds(LatLngBounds, int), you can use the CameraUpdate returned by
this method to change the camera prior to the map's the layout phase, because the
arguments specify the desired size of the bounding box.
as it says it keeps all the markers at the center of the map. i do not want that. i want all the markers visible to the user with the maximum possible zoom and markers scattered. can anybody please help me?
Your calculation of float width and height is incorrect.
What your width holds now is inches (value of approx. 2 on phones). You need not to divide pixels width.

Google MapView zoomout to span a circle

I have a MapView centered at point P. The user can't change the MapView center, but he can choose a radius of a circle to be display around point P, and change it dynamically with the map being redrawn at each change to show the new circle.
The thing is, i want the map to zoom in or out as necessary, in order to display the entire circle at the viewable area. I've tried this:
Projection proj = m_Map.getProjection();
Point mapCenterPixles = new Point();
proj.toMapPixels(center, mapCenterPixles);
float radiusPixels = proj.metersToEquatorPixels(newRadius);
IGeoPoint topLeft = proj.fromPixels(mapCenterPixles.x - radiusPixels,
mapCenterPixles.y - radiusPixels);
IGeoPoint bottomRight = proj.fromPixels(mapCenterPixles.x
+ radiusPixels, mapCenterPixles.y + radiusPixels);
m_Map.getController().zoomToSpan(
topLeft.getLatitudeE6() - bottomRight.getLatitudeE6(),
topLeft.getLongitudeE6() - bottomRight.getLongitudeE6());
But it seems i'm missing something, as the values passed to zoomToSpan() cause no chnage, I'm kind of lost here, can someone please shed some light on how to zoom the map to span a bounding box of the circle given its radius in meters, and its center points?
Google Maps zoom levels are defined in powers of two, so MapController#zoomToSpan() also zooms by powers of two.
Ergo, if the span you compute above is already displayable within the current zoom level, it's likely nothing would actually change visually in the map until you need to go to the next larger or smaller zoom level.
This behavior is somewhat vaguely described in the documentation for MapController#zoomToSpan

Categories

Resources