Position infoWindow away from overlapping polyline - android

I'm developing an Android application which contains an activity with google maps where I plot a path between two location with polylines. I have added markers at source and destination with infowindow showing some data, but these infowindow blocks the polyline and makes user zoom the map to see the path. Is there a way to move infowindow similar to how Uber does?
Any help will be appreciated.
Thank you.

There are really two parts to this problem: (1) establishing where you want the info window and (2) how to get it there. I will be focusing mostly on (1) and try to help with references for (2).
(Note also there is a third problem which can be inferred from the animated gif: the infowindow for "Home" is adjusted because it is clipped in the final view - I've added an approach to this at the end.)
One approach to (1) is to create a bounding rectangle around the path from Point A to Point B. This is a simplification of the problem which has shortcomings to be shown but is a good initial approach. There are optimizations which I think you'll soon realize to better fit the location in extreme cases.
Use this bounding rectangle (R) to determine the minimum dimension relative to the marker anchor of interest (d1 vs d2).
Using the mininimum dimension you can then compute a screen distance from anchor to nearest side of info window (f). From this nearest point you can then determine the anchor offset of the info window.
First some pictures which serve several purposes: (a) identify key locations by label and (b) to start considering more complex problems:
The simplest case is pictured here...:
...but the the labels are bit crammed so a second looser case is pictured here:
Determining the bounding rectangle is straight forward albeit inefficient. Loop over the points of the path (from My Location to Home) and maintain the maximums and minimums of latitude and longitude (note that the -180 to 180 longitude crossover is a pervasive complexity not addressed here - just keep it in mind). This yields:
LatLng upperLeft (maxLat, minLng)
LatLng lowerRight (minLat, maxLng)
So establishing the location of the info window of A is then:
Compute the length (in meters) from A to side of rectangle by using Point A to (A lat, M lng) and Point A to (M lat, A Lng). (Use `SphericalUtil.distanceBetween`)
Determine the lesser of the two measurements, L.
Use L (distance in meters) to compute a screen pixel equivalent S.
Adjust S to offset from edge of BR (Sadj)
Use Sadj (in screen pixels) to compute the Info Window offset (in screen pixels) taking into account the Info Window anchor point and the dimension of the Info Window.
Set the info window anchor (which is relative to the marker coordinate system) and render.
Optimization: Let's say you prefer the location of 'Home' in the 2nd picture to be something like:
Then the optimization would be to consider a smaller bounding rectangle using only some subset of the closer segments of path. So this leads to the next problem of determining when to optimize using thresholds for d1/d2. This same optimization would be used when the zoom level does not include both points; just use the points on screen to compute the bounding rectangle.
For the third problem where "Home" is clipped after the zoom is to account for the dimensions of the infowindow when applying the bounding rectangle - this way the minimum dimension will always include the corresponding extent of the info window.

Related

Using hand drawn map in android application

In my android application I want to use "handmade" maps. It's an artistic map image, based on a real map, so it's geographically accurate. The map cover a relatively small, walkable area (like a neighborhood in a city). The map is bigger than the screen size, so the user will drag the map (but always at the same scale, so no zooming). The application has to work offline, with no Internet connection, but I want to show the user's current (possibly moving) GPS position on this map. Is there any way to do this?
Yes this is possible, and in your case not so difficult.
Measure 3 reference point;
1. near or at left upper corner (NW)
2. near or at right upper corner (NE)
3. near or lef middle or right lower corner (S).
next step is to map the 3 points to pixel and screen coordinates.
Then you need to do an linear interpolation for latitude (between y/lat coordinate of Point 1 and 3)
And an separate linear interpolation between Point1 and 2 for longitude /x value of your GPS coordinate.
With this knowledge, you search further and read some poste here, etc.
You may want to look into OpenStreetMap for your mapping. It allows you to specify a custom tile source for the map. Here is a related SO question.
You will need to break your image up into pieces, this site gives a good explanation on how the tiles are formatted.

Android Google map with inset overview when zoomed in

I am developing an android application using Google maps with clustering of markers. The application works fine however once you zoom into a specific area and all the clusters expand to individual markers I would like to also show a small view that represents the entire map, where you are, and where all the markers are, to enable the user to navigate round the map while zoomed in. Ive Googled and searched SO, but not found anything. Is there any "off the shelf" solution? Or am I going to have to code this all myself? The type of solution I am looking for is the type of small window that many games use to show an overview of where the player is and all the points of interest are within the current level.
I haven't seen any "off the shelf" solutions, but here is what I would do here:
1) Create an additional fragment of the map. Place it in one of corners like games do
2) Here is where all the magic should happen. You need to synchronize these 2 maps. Map's Projection lets you to translate geo coordinates into XY coordinates within the view. That's being said you can get lat/lng of your top-left and bottom-right corners on the main map and translate these 2 corners into top-left and bottom-right XY coordinates of the mini-map's view. Now, when you have XY coordinates, the only thing you need to do - is to draw a rect on top of the mini map.
There is even easier and more native solution - since you have top-left and bottom-right lat/lng coordinates - you can draw a set of polylines on a minimap to get a rect. But in this case it will be hard to move it around (with your finger) in case you want to change current main map location using mini-map

Android google maps zoom to fit mark and current position

I'm trying to create a custom "my location" button for my app using Google Maps.
What I'm trying to do is to center the map around the location of the user, which is already done and working flawlessly, but also want to zoom in just enough to see a marker of my choice (this is actually the closest of a set of markers I have in memory, but that's not important now).
I haven't been able to find how the zoom variable works here. If I know the marker I want to show is 0.5 GPS units away from me, how can I center the map around me in a way that includes that marker on its boundaries? I'd also use a padding to make sure it perfectly fits in the map.
LatLng my_coordinates = ...;
LatLng closest_mark = ...;
map.animateCamera(CameraUpdateFactory.newLatLng(my_coordinates));
So now I want to modify that code to not only center the position to my_coordinates but also make sure zoom will make closest_mark fit in the viewport
CameraUpdateFactory.newLatLngBounds( ?? , /*padding*/);
I don't think there is a specific zoom variable in the api you can control along with the points in the map. (And LatLngBounds just takes in the upper right and lower left bounds and gets you a view accordingly).
I believe what you could do is with a little geometry. If your marker is very close to your location (you can consider it a rectangle), get the distance between the two and extrapolate that on the opposite direction with the same distance (multiple by a small factor if you want some padding) to get the other coordinates, and then you can get the upper right and lower left coordinates (simple geometry).
If your marker is quite far and the surface of the earth comes into picture, you may have to use the haversine formula (great circle distance).
Hope this helps.

Android: How To: display a map (still image file) with a moving current location pointer

I am trying to create a prototype that could guide a person to his destination place.
place is a wide building with several floors.
i can obtain/retrieve the maps (still images). e.g. current:1F destination:5F; so I can get the still images of 1st,2nd...5th floors (5 image files).
Scenario:
start the application
input the current location (or may automatically set using current location) & destination
click the search route button to search the maps to use (still images) & mark the current location & destination
update the current location upon moving/going to destination
Problem:
I just need to display 1 image file (each floor) at a time then move to other floor by using scroll bar. But.. don't know how to display it.
I can get the current location coordinate via WiFi but don't know how to put it into still image to mark the current location.
For sure there is already look a like sample application available.
Could you share the concepts/ideas or would you include the code snippets. Big Help with my thesis.
Any guidance on the right direction is appreciated.
You have a couple possibilities, create your own MapView like object to provide scrolling ot overlay your map on the Google Api. Example usage of the MapView Api is available through the Location dev guide.
To do this via your own View will be easier if you understand basic graphics programming and transformations for zoom and pan. (If you're good at math it will be no trouble to learn). Use an ImageView with android:scaleType="matrix" override the MotionEvent handler to get the touches then process them into a tranlation and zoom matrix.
To associate the indicator to the image make two pixels into anchor points that coorespond to a real life lat/long. Usually its (0,0) and (width,height) of a rectangular image. Make your life easier and make sure the images are to scale. Then using a second ImageView (for the indicator) draw it on top and move it to the correct place on the screen and make sure the background in this View is transparent as well as the background of your indicator or you'll have a rectangular block "halo".
Be sure to check the accuracies of each location given by the LocationManager.
Additional Content
onCurrentPosition(Location current){
double hypotenuse = upperLeft.distanceTo(current);
double bearing = upperLeft.bearingTo(current);
double currentDistanceX = Math.cos(bearing) * hypotenuse;
// "percentage to mark the position"
double currentPixelX = (currentDistanceX / upperLeft.distanceTo(lowerRight) * Math.cos(upperLeft.bearingTo(lowerRight))) * mapWidth;
moveIndicatorX(currentPixelX);
}

Take all screen coordinates

Assume that my current point is lat = 50.000 and long = 50.000 and I want to show some bus stations on these location but my limit should depends on zoom level.
So far, for that aim I find a way: If a can take left-up corner and right-down corners lat's long's ; I will find stations between these locations.
Do you know how can I take these points or any different idea about this situation?
Thanks in advance..
Well you can easily get the top left and bottom right lat/lon coordinates using
GeoPoint tlGpt; // Top left
GeoPoint brGpt; // Bottom right
tlGpt = mapView.getProjection().fromPixels(0, 0);
brGpt = mapView.getProjection().fromPixels(mapView.getWidth(), mapView.getHeight());
At any zoom level where you could actually see the bus stations on the map, then the top left longitude could be considered the same as the bottom left longitude, similarly bottom left long would be approx = bottom right long. Thus you could consider the bounding box as a rectangle, rather than an isosceles trapezium (trapezoid in US English)
If you just want a rough measure to pick up a reasonable sample of objects, then lat/long "distance" is good enough. Just make sure you divide the latitude range by the cosine of the latitude, to get the longitude range (i.e., ∆long = ∆lat/cos(lat)). This is to compensate for the contraction of longitude lines as you approach the poles. You use ∆lat as the basis because latitude lines have the same distance between them everywhere on the globe.
For a more accurate measure, there are some complicated functions that allow you to compute great circle distances from lat/long pairs, but it is conceptually much easier to convert lat/long pairs into 3-D coordinates, and use a simple pythagorean distance to approximate the great circle distance. You could use 2*r*acos(d/(2*r)) (if my whiteboard geometry serves me well), where r is the nominal radius of the earth, to get the exact great circle. But if all you want is to get objects within a range, you can invert the formula to get the pythagorean-distance equivalent of the great-circle limit. This can also be used to derive a 3-D bounding box to speed up the search. If your database supports R-trees, then you're laughing! SQLite supports R*Trees, but they are disabled in the default build, so I don't know if they're available on Android (it seems that it isn't).

Categories

Resources