Marker Icons position offset - android

I have a pin which has a arrowed-tip. When placed a marker, the tip is not actually pointing accurately to the tap location. It seems my pins are being positioned base on their center. I want to move this center by a particular offset.
Here is what I am currently using (among many other custom pins I have). These are sized at 250x250:
This is a circular button. Notice it has a arrow on the bottom-most part (pointing downwards).
Now, lets place this pin on mapbox:
#Override
public void onMapClicked(#NonNull LatLng point)
{
mPopularView.showPinSelectedPopup(false);
if(!mIsOnMyRecommendationMode)
return;
IconFactory iconFactory = IconFactory.getInstance(getContext());
Drawable iconDrawable = ContextCompat.getDrawable(getContext(), R.drawable.ic_map_bank_blue_pin);
Icon icon = iconFactory.fromDrawable(iconDrawable);
MarkerOptions markerOption = new MarkerOptions();
markerOption.setPosition(point);
markerOption.title("Just a I don't know where I am!");
markerOption.setSnippet("Hello World! I don't know where I am!");
markerOption.setIcon(icon);
mPopularView.getMapboxMap().addMarker(markerOption);
mIsOnMyRecommendationMode = false;
}
Fairly simple, just like in the docs. It works very well. Look at the following pic:
I hope this pic will paint a thousand words. Please do not suggest of adjusting the LatLang to account for the offset. That will be incorrect on my use case. It has to be the pixel position of the icon itself. MapBox should have accounted for this when they allowed devs to develop their own custom pins (WE ARE GOING TO PUT ARROWS ON OUR PINS!).
Currently, I set the height of the custom pin icon with double the height. But one caveat I found is that I can actually select the bottom half of the now longer pin icon. For example:
Notice the image above. The height of that image has been doubled. When I placed this, now the arrow correctly points to the area I tapped. One caveat is that, when you pressed below the pin, it still detects click callback. Guess why... because the bounds (specifically the height) of the custom icon is longer and so does its click boundaries. Thus, I cannot put pins below it as it detects it as onMarkerClicked().
How can I get around this? Any ideas?
Thanks!
Not So Elegant Solution
Just wanted to post this as answer in case somebody else is experiencing the same. My situation is kind of extreme and I really need to load the bitmap on the pin instead of some other method proposed by cammace. I use the old fashioned pixel-positioning to get exactly what I wanted. Fortunately, MapBox is equipped with transforming screen coordinates to map coordinates and vice-versa.
I tested this on both tablet and a mobile phone and it doesn't seem to get affected by the screen size. Its pointy edge now actually points at my designated target:
LatLng position = new LatLng();
position.setLatitude(lat);
position.setLongitude(long);
PointF pointF = mMapboxMap.getProjection().toScreenLocation(position);
pointF.offset(0f, -(icon.getBitmap().getHeight() / 2.0f));
position = mMapboxMap.getProjection().fromScreenLocation(pointF);
This is not the most elegant solution. I hope this helps anyone who are in similar situation like me. Nudging the pin upward is only representational, I still read the original latlong values of pins from our homebrew server as is, I just placed the latlong values a little bit off upwards during marker placement.
Zooming also doesn't seem to be affected by this, I tried both not placing it by pixels and one with using this solution.
As I have said, if this is totally wrong. Let me know.
If there are some caveats on this approach. Please do let me know.

With the release of 4.2.0 last week, we have three ways of adding markers. The current way you are adding them will indeed mean that you will need to add padding to your image so that the image is centered (this is what we are doing with the default marker).
The second option you have is using MarkerViews. Simply replace this line:
MarkerOptions markerOption = new MarkerOptions();
to this:
MarkerViewOptions markerOption = new MarkerViewOptions();
this will expose a few more options including an anchoring option. Marker views have one issue which is performance, so if you are adding an abundance of markers or don't like them being slightly out of sync with the map, you have a third option.
The third option will be using Runtime Styling to create a symbol layer and making use of the offset property found in the style spec. Have a look at this example found in our demo app for better understanding of the potential of using runtime styling.

Related

Generate "out of view" markers indicators on a map with React Native

For a project, I have to indicate, with colored arrows, in which direction are the markers that aren't shown in the visible region.
When the user scrolls, or zoom on the map, the arrows move accordingly to where the not visible markers are compared to the current center of the visible region.
Here is a picture that demonstrate what is needed :
I am using react-native-mapview and added regular views over the map to show the indicators.
I've started working on this by comparing the coordinates and calculating the point of intersection between lines (border lines and line made by the 2 coordinates) at each frame. It works fine on iOS but is pretty laggy on Android, especially chan there are a lot of markers involved.
What would be the best and optimized way to do this ?
Maybe you could try using Animated.View instead regular view. It may render more fluently?
pass tracksViewChanges={false} to Markers https://github.com/react-native-community/react-native-maps/blob/master/docs/marker.md

Draw a line away from "google map navigation path" at fixed distance on both the side, so it will create box like view around navigation path

How can we Draw a line away from "google map navigation path" at fixed distance on both the side, so it will create box like view around navigation path. is it possible?
Please check the attached image to be more clear with requirement, where blue line is my navigation path between two point & red line is that suppose to be plot around the path at fix distance
[]
Also I have use 'https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=-33.8670522,151.1957362&radius=500&type=restaurant&name=cruise&key=Key' to get place list around selected location. But is it possible to get all place detail for whole path, like all the restaurant that are 1KM away from displayed navigation path. is it possible?
For the "box like view around the navigation path", it's possible by using the Google Maps API - Shapes - Polygon. From the doc:
...polygons are designed to define regions within a closed loop with the interior filled in.
You just have to define the points for the outline of the polygon. I think here, you can use the location of the navigation path as center, to be the basis of where you'll put the polygon points.
While for the "is it possible to get all place detail for whole path, like all the restaurant that are 1KM away from displayed navigation path", yes, it's possible. As seen in the sample URL you provided on your post:
https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=-33.8670522,151.1957362&radius=500&type=restaurant&name=cruise&key=Key
-- you are already defining the radius(500m) and the type(restaurants). What you could do is do a request for each points you think is relevant in the navigation path then consolidate the necessary data from the response. You can see the Place Details docs for more details.
I think it'll be easier if you just choose the center of the navigation path, then provide the radius that will cover it all, but I guess you still prefer the way I mentioned above. Anyways, all formulas and calculations will be up to you. Hope this helps. Good luck.

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 Dynamically-Drawn, Clickable Map Overlay?

I'm trying to write an Android app that will allow a user to search for a generic destination (e.g., "gas station") and be presented with up to ~5 nearby locations to choose from. The screen results would display the user location in the center, and possible destination options would be indicated by markers.
The trick is that I don't want to rescale the map from its starting scale, and so some of the possible destinations may not be visible on the screen. I want to dynamically draw a clickable direction indicator (such as an arrow) that emanates from the user location and points to any off-screen destination. If there are multiple off-screen destinations, I'd probably want to scale the arrow lengths to indicate relative distances. If the user clicks on the arrow, they should be "teleported" to the off-screen location.
Any thoughts on how to best implement this? The only information I've found on overlays uses static files (Most overlays seem to be just .PNG files for markers; one example had a route that was drawn from an XML file). I'd need to calculate the arrow based on direction
to the destination (direction the arrow points) and the relative distance to that location (arrow length), so the overlay is something I'd have to come up with at run time.
I think the main challenge is drawing the clickable arrows, but another question that comes to mind is, should I search using the Google Maps API, or is this job more suited to the Google Places API?
Thanks!
I guess we should put the teleportation on hold until the problem of a dynamically-drawn, clickable overlay is solved then!
A dynamically-drawn, clickable overlay is merely a subclass of Overlay. You will override one or both of the draw() methods to render your arrows using the Canvas 2D drawing API. You will override onTap() to be notified of taps on the map, to see if they tapped on an arrow. You add the overlay to the MapView via addOverlays().add().
Most overlays seem to be just .PNG files for markers
Those are usually ItemizedOverlay classes. That's much simpler to implement, particularly if you are one of those developers (like me) who is all thumbs when it comes to Canvas. However, you cannot achieve what you want with an ItemizedOverlay, in all likelihood.
I'd need to calculate the arrow based on direction to the destination (direction the arrow points) and the relative distance to that location (arrow length), so the overlay is something I'd have to come up with at run time.
Correct. You can use a Projection to help convert between pixel space and geo-space (latitude and longitude), if needed.
Note that this all assumes you are trying to use MapActivity and MapView. You are also welcome to use WebView or a plain browser to bring up your own JavaScript-based maps, if you prefer.

Android custom GPS map application

I want to build an app that uses GPS data and a building map I provide to show the user where in the building on the map they are. This will be done in a specific building that i already know gets GPS and cell service.
At first I thought the easiest way to do this was to see if I could use Google maps to plot the users location and then just "overlay" my custom building map on top of the Google map so that I wouldnt have to deal with any of the gps information or the complexities of the mapping I would just have to scale my "overlay" to fit properly on top of the Google map so that the user was shown in the correct room in a building. I'm wondering if anyone can provide me any information on how to do this or if there is an easier way to accomplish my map. Any information at all is helpful!
You want...
Google Map View
...and more specifically you will probably want to read the subsection appropriately titled: "Part 2: Adding Overlay Items"
EDIT: Whoops! Nevermind! I misread your question... that is only if you want to overlay an item on the map. Sorry...
There is no possibility to use closer zoom level than that you can see on standard GMap i.e. in browser. Other problem is that google uses GeoPoint class based on cardinal microdegrees to draw overlays, and it's accuracy is to low.
You can look on jGarminImg - it's java library - unfortunately written for using with swing, but it should be relatively easy to make it work with android. On the other hand - you have to make your own map.
You can use standard overlays, or you can make your map in kml format and use this example to display it.
You may be able to achieve this with a custom view that displays your building plan and knows the precise co-ordinates of each corner of the building.
When you receive your location updates you can add a marker to your custom view by translating the real world position into a position in the image using something along the lines of:
pseudocode:
markerX = realWorldX - mapStartX;
markerY = realWorldY - mapStartY;
if( isOnMap( markerX, markerY ) )
{
drawMarker( markerX, markerY );
}
Yes you can overlay bitmap images on top of the Google MapView.
All you have to do is subclass the Overlay class, override the draw method, and draw on the canvas. You have to provide a rectangle of GeoPoints (probably the top left and the bottom right corners) to anchor the building bitmap on top of the MapView. You use mapView.getProjection() to translate the latitude and longitude into xy coordinates on the canvas.
I assume drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) will be useful here. Bear in mind that src and paint can be null. If the GeoPoints you used are accurate, the bitmap will adjust automatically to pans and zooms, although it might get pixelated if the user zooms in too much.
edit: I am not so confident that Google Maps will have your building stays at the exact same GeoPoints in different zoom levels, so you might have to adjust those values for different zoom levels
If you need only the map of the building, it should not be too difficult to plot the location on an image without using Google Maps, provided that you can determine your location as coordinates inside the building.
You need to know two coordinates: north-west and south-east corners of the building map you are using. When you get GPS location updates, the correct location on the map image can be easily calculated based on these corner coordinates.
I would do it like this,
Place a marker on the google map to indicate the position of the building
Drilling down on the building would load your building map as a custom view. Plot the user location on the custom view
I think trying to overlay your building map on a google map while possible will be more complex to code than doing it via a custom view.
Also overlaying the lowest zoom level with your building map is not going to give you enough resolution unless you have a thumping big building. Whole blocks are pretty small
One issue you have probably already considered is the device will revert to cell tower and wifi for it's location when inside the building giving you a less accurate location fix.

Categories

Resources