I've been working on this for a while now, but I still have not gotten the result I'm looking for. I'm trying to create an app to display our mountain bike trails so you can see where you are when you're on them. I started by manually copying coordinates from my kml file and pasting them as Geopoints with this code which worked until I got to point 80. Then the LogCat gave an error rejecting large method, and I still have hundreds more to go:
import java.util.List;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.Projection;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.os.Bundle;
public class TrailMaps extends MapActivity {
private List mapOverlays;
private Projection projection;
private MapController mc;
private MapView mapView;
private GeoPoint gP;
private MyOverlay myoverlay;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mapView = (MapView) findViewById(R.id.mapview);//Creating an instance of MapView
mapView.setBuiltInZoomControls(true);//Enabling the built-in Zoom Controls
gP = new GeoPoint(43311836,-91777756);//Creating a GeoPoint
mc = mapView.getController();
mc.setCenter(gP);
mc.setZoom(15);//Initializing the MapController and setting the map to center at the
mapOverlays = mapView.getOverlays();
projection = mapView.getProjection();
myoverlay = new MyOverlay();
mapOverlays.add(myoverlay);
}
class MyOverlay extends Overlay{
public MyOverlay(){
}
public void draw(Canvas canvas, MapView mapView, boolean shadow) {
super.draw(canvas, mapView, shadow);
Paint paint;
paint = new Paint();
paint.setDither(true);
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(2);
GeoPoint gp1 = new GeoPoint(43311836,-91777756);
GeoPoint gp2 = new GeoPoint(43311718,-91777699);
GeoPoint gp3 = new GeoPoint(43311718,-91777699);
GeoPoint gp4 = new GeoPoint(43311666,-91777627);
GeoPoint gp5 = new GeoPoint(43311624,-91777541);
Point pt1 = new Point();
Point pt2 = new Point();
Point pt3 = new Point();
Point pt4 = new Point();
Point pt5 = new Point();
Path path1 = new Path();
Path path2 = new Path();
Path path3 = new Path();
projection.toPixels(gp1,pt1);
projection.toPixels(gp2, pt2);
projection.toPixels(gp3, pt3);
projection.toPixels(gp4, pt4);
projection.toPixels(gp5, pt5);
path1.moveTo(pt1.x, pt1.y);
path1.lineTo(pt2.x, pt2.y);
path2.moveTo(pt3.x,pt3.y);
path2.lineTo(pt4.x, pt4.y);
path3.moveTo(pt4.x,pt4.y);
path3.lineTo(pt5.x,pt5.y);
canvas.drawPath(path1, paint);
canvas.drawPath(path2, paint);
canvas.drawPath(path3, paint);
}
}
#Override
protected boolean isRouteDisplayed() {
return false;
}
}
Then I tried to parse the kml file as in this example: How to draw a path on a map using kml file?
But this is taking my coordinates and finding the nearest streets and overlaying a route. My coordinates are not along the street they are in a park off road, so how else should I do it?
Right now I'm open to any suggestions. Is there a better way to parse the kml file, do it locally vs going to http://maps.google.com/maps?, overlaying it as an image, or a whole new direction completely... Any suggestions would be much appreciated.
Thanks
Related
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I want to generate map link and want send mail of that link. when user will click on that link map should be opened in the browser with that location.I have generated the link and also it shows the location but problem is it does not shows the pin for current location.How to modify the link so that i can get the pin on map. The link which i have generated is as follows,
https://www.google.com/maps/preview/#"+latitude+","+longitude+",16z
http://www.openstreetmap.org/?mlat=latitude&mlon=longitude#map=zoom/latitude/longitude
where mlat and mlon specifiy the position of the marker.
Create a GIF image containing a pushpin (called pushpin) and copy it into the res/drawable-mdpi
folder of the existing project
import java.util.List;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Point;
import android.os.Bundle;
import android.view.KeyEvent;
public classLBSActivity extendsMapActivity {
MapView mapView;
MapController mc;
GeoPoint p;
private classMapOverlay extendscom.google.android.maps.Overlay
{
#Override
public booleandraw(Canvas canvas, MapView mapView,
booleanshadow, longwhen)
{
super.draw(canvas, mapView, shadow);
//---translate the GeoPoint to screen pixels---Point screenPts = newPoint();
mapView.getProjection().toPixels(p, screenPts);
//---add the marker---FIGURE 9-10
Displaying Maps
❘ 367
Bitmap bmp = BitmapFactory.decodeResource(
getResources(), R.drawable.pushpin);
canvas.drawBitmap(bmp, screenPts.x, screenPts.y-50, null);
return true;
}
}
/** Called when the activity is first created. */
#Override
public voidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mapView= (MapView) findViewById(R.id.mapView);
mapView.setBuiltInZoomControls(true);
mapView.setSatellite(true);
mapView.setTraffic(true);
mc= mapView.getController();
String coordinates[] = {“1.352566007”, “103.78921587”};
doublelat = Double.parseDouble(coordinates[0]);
doublelng = Double.parseDouble(coordinates[1]);
p= newGeoPoint(
(int) (lat * 1E6),
(int) (lng * 1E6));
mc.animateTo(p);
mc.setZoom(13);
//---Add a location marker---MapOverlay mapOverlay = newMapOverlay();
List<Overlay> listOfOverlays = mapView.getOverlays();
listOfOverlays.clear();
listOfOverlays.add(mapOverlay);
mapView.invalidate();
}
public booleanonKeyDown(intkeyCode, KeyEvent event)
{
//...
}
#Override
protected booleanisRouteDisplayed() {
//...
}
}
I have some a shape file which I have converted to a KML file that I wish to read coordinates from and then draw paths between the coordinates on a MapView. With the help of this great post: How to draw a path on a map using kml file? I have been able to read the the KML into an ArrayList of "Placemarks". This great blog post then showed how to take a list of GeoPoints and draw a path: http://djsolid.net/blog/android---draw-a-path-array-of-points-in-mapview
The example in the above post only draws one path between some points however and since I have many more paths than that I am running into some performance problems. I'm currently adding a new RouteOverlay for each of the separate paths. This results in me having over 800 overlays when they have all been added. This has a performance hit and I would love some input on what I can do to improve it.
Here are some options I have considered:
Try to add all the points to a List which then can be passed into a class that will extend Overlay. In that new class perhaps it would be possible to add and draw the paths in a single Overlay layer? I'm not sure on how to implement this though since the paths are not always intersecting and they have different start and end points. At the moment I'm adding each path which has several points to it's own list and then I add that to an Overlay. That results in over 700 overlays...
Simplify the KML or SHP. Instead of having over 700 different paths, perhaps there is someway to merge them into perhaps 100 paths or less? Since alot of paths are intersected at some point it should be possible to modify the original SHP file so that it merges all intersections. Since I have never worked with these kinds of files before I have not been able to find a way to do this in GQIS. If someone knows how to do this I would love for some input on that. Here is a link to the group of shape files if you are interested:
http://danielkvist.net/cprg_bef_cbana_polyline.shp
http://danielkvist.net/cprg_bef_cbana_polyline.shx
http://danielkvist.net/cprg_bef_cbana_polyline.dbf
http://danielkvist.net/cprg_bef_cbana_polyline.prj
Anyway, here is the code I'm using to add the Overlays. Many thanks in advance.
RoutePathOverlay.java
package net.danielkvist;
import java.util.List;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.RectF;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.Projection;
public class RoutePathOverlay extends Overlay
{
private int _pathColor;
private final List<GeoPoint> _points;
private boolean _drawStartEnd;
public RoutePathOverlay(List<GeoPoint> points)
{
this(points, Color.RED, false);
}
public RoutePathOverlay(List<GeoPoint> points, int pathColor, boolean drawStartEnd)
{
_points = points;
_pathColor = pathColor;
_drawStartEnd = drawStartEnd;
}
private void drawOval(Canvas canvas, Paint paint, Point point)
{
Paint ovalPaint = new Paint(paint);
ovalPaint.setStyle(Paint.Style.FILL_AND_STROKE);
ovalPaint.setStrokeWidth(2);
int _radius = 6;
RectF oval = new RectF(point.x - _radius, point.y - _radius, point.x + _radius, point.y + _radius);
canvas.drawOval(oval, ovalPaint);
}
public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when)
{
Projection projection = mapView.getProjection();
if (shadow == false && _points != null)
{
Point startPoint = null, endPoint = null;
Path path = new Path();
// We are creating the path
for (int i = 0; i < _points.size(); i++)
{
GeoPoint gPointA = _points.get(i);
Point pointA = new Point();
projection.toPixels(gPointA, pointA);
if (i == 0)
{ // This is the start point
startPoint = pointA;
path.moveTo(pointA.x, pointA.y);
}
else
{
if (i == _points.size() - 1)// This is the end point
endPoint = pointA;
path.lineTo(pointA.x, pointA.y);
}
}
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(_pathColor);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(3);
paint.setAlpha(90);
if (getDrawStartEnd())
{
if (startPoint != null)
{
drawOval(canvas, paint, startPoint);
}
if (endPoint != null)
{
drawOval(canvas, paint, endPoint);
}
}
if (!path.isEmpty())
canvas.drawPath(path, paint);
}
return super.draw(canvas, mapView, shadow, when);
}
public boolean getDrawStartEnd()
{
return _drawStartEnd;
}
public void setDrawStartEnd(boolean markStartEnd)
{
_drawStartEnd = markStartEnd;
}
}
MyMapActivity
package net.danielkvist;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapView;
public class MyMapActivity extends MapActivity
{
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
MapView mapView = (MapView) findViewById(R.id.mapview);
mapView.setBuiltInZoomControls(true);
String url = "http://danielkvist.net/cprg_bef_cbana_polyline_simp1600.kml";
NavigationDataSet set = MapService.getNavigationDataSet(url);
drawPath(set, Color.parseColor("#6C8715"), mapView);
}
/**
* Does the actual drawing of the route, based on the geo points provided in
* the nav set
*
* #param navSet
* Navigation set bean that holds the route information, incl.
* geo pos
* #param color
* Color in which to draw the lines
* #param mMapView01
* Map view to draw onto
*/
public void drawPath(NavigationDataSet navSet, int color, MapView mMapView01)
{
ArrayList<GeoPoint> geoPoints = new ArrayList<GeoPoint>();
Collection overlaysToAddAgain = new ArrayList();
for (Iterator iter = mMapView01.getOverlays().iterator(); iter.hasNext();)
{
Object o = iter.next();
Log.d(BikeApp.APP, "overlay type: " + o.getClass().getName());
if (!RouteOverlay.class.getName().equals(o.getClass().getName()))
{
overlaysToAddAgain.add(o);
}
}
mMapView01.getOverlays().clear();
mMapView01.getOverlays().addAll(overlaysToAddAgain);
int totalNumberOfOverlaysAdded = 0;
for(Placemark placemark : navSet.getPlacemarks())
{
String path = placemark.getCoordinates();
if (path != null && path.trim().length() > 0)
{
String[] pairs = path.trim().split(" ");
String[] lngLat = pairs[0].split(","); // lngLat[0]=longitude
// lngLat[1]=latitude
// lngLat[2]=height
try
{
if(lngLat.length > 1 && !lngLat[0].equals("") && !lngLat[1].equals(""))
{
GeoPoint startGP = new GeoPoint(
(int) (Double.parseDouble(lngLat[1]) * 1E6),
(int) (Double.parseDouble(lngLat[0]) * 1E6));
GeoPoint gp1;
GeoPoint gp2 = startGP;
geoPoints = new ArrayList<GeoPoint>();
geoPoints.add(startGP);
for (int i = 1; i < pairs.length; i++)
{
lngLat = pairs[i].split(",");
gp1 = gp2;
if (lngLat.length >= 2 && gp1.getLatitudeE6() > 0
&& gp1.getLongitudeE6() > 0
&& gp2.getLatitudeE6() > 0
&& gp2.getLongitudeE6() > 0)
{
// for GeoPoint, first:latitude, second:longitude
gp2 = new GeoPoint(
(int) (Double.parseDouble(lngLat[1]) * 1E6),
(int) (Double.parseDouble(lngLat[0]) * 1E6));
if (gp2.getLatitudeE6() != 22200000)
{
geoPoints.add(gp2);
}
}
}
totalNumberOfOverlaysAdded++;
mMapView01.getOverlays().add(new RoutePathOverlay(geoPoints));
}
}
catch (NumberFormatException e)
{
Log.e(BikeApp.APP, "Cannot draw route.", e);
}
}
}
Log.d(BikeApp.APP, "Total overlays: " + totalNumberOfOverlaysAdded);
mMapView01.setEnabled(true);
}
#Override
protected boolean isRouteDisplayed()
{
// TODO Auto-generated method stub
return false;
}
}
Edit: There are of course some more files I'm using but that I have not posted. You can download the complete Eclipse project here: http://danielkvist.net/se.zip
Have you considered rendering all the paths to a bitmap and then use that as a overlay, and of-course you would need to render it again if the user zooms in or out or moves the map alot. Making the bitmap 2 or 4 times as large as the screen (be care-full not to use up all memory here) you should be able to get some zooming in and out a-swell as allow for a bit of panning until you need to render it again.
Rendering it like a quad-tree (with week references to the bitmaps in the tree) would allow for some caching and possibly big performance improvements.
Going with a quad-tree is not an easy approach but might be worth the effort if you have the time and knowledge for it. I believe this roughly is how the google maps handles its map tiles.
I am getting different x,y value for a specific lat,long. I wonder why it is happening. May be I lack knowledge. So, if you anyone can explain by observing the following code snippet then it would be a great help.
import java.util.List;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;
import com.google.android.maps.Projection;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;
public class MaopaoActivity extends MapActivity {
MapView FMmapview;
GeoPoint fm_gp;
Button bt;
int lat,lng;
List<Overlay> mapOverlays;
Drawable drawable;
CustomItemizedOverlay itemizedoverlay;
OverlayItem overlayitem;
String RASTA="";
String [] pairs;
int EndLat,EndLng;
String kotha;
TextView tv;
double startlat,startlong;
double endlat,endlong;
double midlat,midlong;
int startlatE6,startlongE6;
int endlatE6,endlongE6;
int midlatE6,midlongE6;
GeoPoint StartGp,EndGp,midGp1,midGp2;
Integer x1,y1,x2,y2,x3,y3;
Double x4,y4;
Point StartPoint;
Point EndPoint;
Point MidPoint1;
Point MidPoint2;
String abc;
double w,T,G;
Integer Tint,Gint;
#Override
protected void onCreate(Bundle icicle)
{
// TODO Auto-generated method stub
super.onCreate(icicle);
setContentView(R.layout.fullmap);
StartPoint = new Point();
EndPoint = new Point();
MidPoint1 = new Point();
MidPoint2 = new Point();
tv=(TextView)findViewById(R.id.fm_tv1);
startlat=34.123018;
startlatE6=(int)(startlat*1E6);
startlong=-118.146278;
startlongE6=(int)(startlong*1E6);
endlat=34.122525;
endlatE6=(int)(endlat*1000000);
endlong=-118.146241;
endlongE6=(int)(endlong*1000000);
midlat=34.122724;
midlatE6=(int)(midlat*1000000);
midlong=-118.146106;
midlongE6=(int)(midlong*1000000);
EndGp=new GeoPoint(endlatE6,endlongE6);
midGp1=new GeoPoint(midlatE6,midlongE6);
StartGp=new GeoPoint(startlatE6,startlongE6);
FMmapview=(MapView)findViewById(R.id.MapViewFM123);
Projection projection = FMmapview.getProjection();
FMmapview.getController().setCenter(StartGp);
FMmapview.getController().setZoom(18);
FMmapview.getProjection().toPixels(EndGp,EndPoint);
FMmapview.getProjection().toPixels(midGp1,MidPoint1);
FMmapview.getProjection().toPixels(StartGp,StartPoint);
x1=StartPoint.x;
y1=StartPoint.y;
x2=EndPoint.x;
y2=EndPoint.y;
x3=MidPoint1.x;
y3=MidPoint1.y;
w=(y2-y1)/(x2-x1);
T=((x3+(w*w*x1)+(w*y3)-(w*x1))/(w*w+1));
G=w*(T-x1)+y1;
Tint=(int) Math.ceil(T);
Gint=(int)Math.ceil(G);
mapOverlays = FMmapview.getOverlays();
drawable = this.getResources().getDrawable(R.drawable.blue);
itemizedoverlay = new CustomItemizedOverlay(drawable,this);
overlayitem = new OverlayItem(midGp1, "Your are at","hello motttto");
itemizedoverlay.addOverlay(overlayitem);
mapOverlays.add(itemizedoverlay);
midGp2=FMmapview.getProjection().fromPixels(Tint,Gint);
//x4=(midGp2.getLatitudeE6())/(1E6);
//y4=(midGp2.getLongitudeE6())/(1E6);
abc="A="+x1.toString()+','+y1.toString()+" B="+x2.toString()+","+y2.toString()+" C="+x3.toString()+","+y3.toString()+" D="+Tint.toString()+","+Gint.toString();
tv.setText(abc);
//midGp2=new GeoPoint(34048039,-118140655);
mapOverlays = FMmapview.getOverlays();
drawable = this.getResources().getDrawable(R.drawable.blue);
itemizedoverlay = new CustomItemizedOverlay(drawable,this);
overlayitem = new OverlayItem(midGp2, "Your are at","hello motttto");
itemizedoverlay.addOverlay(overlayitem);
mapOverlays.add(itemizedoverlay);
FMmapview.getController().animateTo(StartGp);
FMmapview.getController().setCenter(StartGp);
FMmapview.getController().setZoom(18);
FMmapview.getOverlays().add(new MyOverLay(StartGp,EndGp,2,Color.BLUE));
}
#Override
protected boolean isRouteDisplayed()
{
// TODO Auto-generated method stub
return false;
}
}
Here I get x,y=0,0 for the geopoint 34.123018,-118.146278;
and again I get x,y=240,340 when I re-run the app.
If I clear data, I get x,y=0,0
and then When I re-run I get different value for the same aforementioned lat/long.
It would be a great help if anyone can clear my conception
EDITED:
I have found the reason, which is totally unusual to me.
The projection value to pixel may vary.
as http://code.google.com/android/add-ons/google-apis/reference/com/google/android/maps/MapView.html#getProjection%28%29 says that
"The Projection of the map in its current state. You should not hold on to this object for more than one draw, since the projection of the map could change."
So, x,y can be 0,0 or can be anything. Whatever might be the projected x,y value is, it will always represent same lat,long.
The problem that leads me to such thinking unfortunately was the following line:
T=((x3+(w*w*x1)+(w*y3)-(w*x1))/(w*w+1));
It provides different value. If I break this into 3 lines then T provides correct result. Though, I never had to face such situation in C++. This is something weird.
Anyway, I would still want to know the reason behind the value of the projection being different.
I believe the answer to your question is that the zoom function in MapView is animated, that means it doesn’t complete immediately. So, the different projections you are getting results from them being taken during the zoom animation where the locations in the map are changing at the same time you are taking them.
To confirm that, you can make a delay of a couple of seconds between the map center/zoom change and taking the projections and you should always get the same projection values.
Good luck,
Luis
I am using the osmdroid-android 3.0.5.jar instead of Google map api to show the location in map by using geo-coordinate.
Well i am able to get map in android emulator but the problem is the overlay i am using to point to location is wrong.
Here's my code :
public class MainActivity extends Activity {
/** Called when the activity is first created. */
private MapView osmMapView;
private MapController controller;
private Projection projection;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
osmMapView = (MapView) findViewById(R.id.osm_map_view);
this.osmMapView.setTileSource(TileSourceFactory.MAPNIK);
this.osmMapView.setBuiltInZoomControls(true);
this.osmMapView.setMultiTouchControls(true);
this.projection = this.osmMapView.getProjection();
this.controller = this.osmMapView.getController();
this.controller.setZoom(5);
List<Overlay> overLayList = osmMapView.getOverlays();
overLayList.add(new ScaleBarOverlay(this));
overLayList.add(new PutOverLayOnMap(this));
}
private class PutOverLayOnMap extends Overlay {
public PutOverLayOnMap(Context ctx) {
super(ctx);
}
#Override
protected void draw(Canvas c, MapView osmv, boolean shadow) {
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setDither(true);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeWidth(10);
Point point = new Point();
GeoPoint geoPoint = new GeoPoint((int)(41.057121 * 1E6), (int)(-73.561867 * 1E6));
projection.toPixels(geoPoint, point);
c.drawPoint(point.x, point.y, paint);
System.out.println("GeoPoint(OSM) : "+geoPoint.getLatitudeE6()+" #### "+geoPoint.getLongitudeE6());
}
}
The following is my main.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<org.osmdroid.views.MapView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_centerInParent="true"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true"
android:id="#+id/osm_map_view"
renderer="CloudMadeStandardTiles"
cloudmadeStyle="1"
/>
</LinearLayout>
As you can see I am using
GeoPoint geoPoint = new GeoPoint((int)(41.057121 * 1E6), (int)(-73.561867 * 1E6));
which is the geo-coordinate of Stamford US Now the red dot is showing somewhere Africa, center of the map (intersection of latitude & longitude).
What i am doing wrong?
You need to get the projection in the draw method. The javadocs for getProjection tell you
public MapView.Projection getProjection()
Get a projection for converting between screen-pixel coordinates and latitude/longitude coordinates. You should not hold on to this object for more than one draw, since the projection of the map could change.
So in your draw method, insert the line as shown below
....
paint.setStrokeWidth(10);
Point point = new Point();
projection = osmMapView.getProjection(); // <<<<<<<<<<<<<<<<< ADD THIS LINE
GeoPoint geoPoint = new GeoPoint((int) (41.057121 * 1E6),
(int) (-73.561867 * 1E6));
projection.toPixels(geoPoint, point);
.....
This should fix it.
I want to overlay a map image (.jpg) over the Google Maps mapview.
The problem is: The overlay image is not showing, who knows what's the
problem?
There is no error in logcat and the MapView is working.
The code:
package nl.ultimo.android.skikaart;
import java.util.List;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Bundle;
public class MapsActivity extends MapActivity
{
Bitmap bmp; //Loaded bitmap in memory
GeoPoint min; //Top left corner (lat/long)
GeoPoint max; //Right bottom corner (lat/long)
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
float lat1 = 45.19775f;
float lng1 = 6.28418333f;
float lat2 = 45.2636667f;
float lng2 = 6.17431667f;
min = new GeoPoint((int)(lat1 * 1E6), (int)(lng1 * 1E6)); // bounding rectangle
max = new GeoPoint((int)(lat2 * 1E6), (int)(lng2 * 1E6));
MapView mapView = (MapView) findViewById(R.id.mapView);
MapController ctrl = mapView.getController();
int x = (min.getLongitudeE6() + max.getLongitudeE6())/ 2; //Select map center
int y = (min.getLatitudeE6() + max.getLatitudeE6())/ 2;
ctrl.setCenter(new GeoPoint(y,x));
ctrl.setZoom(12); //Set scale
mapView.setBuiltInZoomControls(true); //Enable zoom controls
//Add overlay
MapOverlay mapOverlay = new MapOverlay();
List<Overlay> listOfOverlays = mapView.getOverlays();
listOfOverlays.clear();
listOfOverlays.add(mapOverlay);
mapView.invalidate();
}
class MapOverlay extends com.google.android.maps.Overlay
{
#Override
public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when)
{
super.draw(canvas, mapView, shadow);
//Translate the GeoPoint to screen pixels
Point screenPts = new Point();
mapView.getProjection().toPixels(min, screenPts);
//The overlay image
Bitmap bmp = BitmapFactory.decodeResource(getResources(),R.drawable.skikaart);
//Prepare two rectangles (pixels)
Point top_left = new Point();
mapView.getProjection().toPixels(min, top_left);
Point bottom_right = new Point();
mapView.getProjection().toPixels(max, bottom_right);
Rect src = new Rect( 0,0,bmp.getWidth() - 1, bmp.getHeight() - 1 );
Rect dst = new Rect( top_left.x, bottom_right.y,bottom_right.x,top_left.y );
canvas.drawBitmap(bmp, src, dst, null);
return true;
}
}
#Override
protected boolean isRouteDisplayed() {
return false;
}
}
to see marker you need to do next
Drawable drawable = ...set your marker drawable
drawable.setBounds(-drawable.getIntrinsicWidth() / 2, -drawable.getIntrinsicHeight(), drawable.getIntrinsicWidth() / 2, 0);
overlayitem.setMarker(drawable);
Just to make things clear here is a quote from reference
"The setBounds(Rect) method must be called to tell the Drawable where it is drawn and how large it should be."
Your code has one minor mistake.
Change
Rect dst = new Rect( top_left.x, bottom_right.y,bottom_right.x,top_left.y );
to
Rect dst = new Rect( top_left.x, top_left.y,bottom_right.x,bottom_right.y );
and you should be good.
Remember that draw() is called each time the overlay needs to be rendered. When the map is being moved by the user, this could happen multiple times per second!!
You need to load the resource only ONCE, then only draw the bitmap onto the canvas during the draw invocation.
Also, your current implementation is highly coupled with the actual Activity.
in your activity
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
...
map.getOverlays().add(new PNGMapOverlay(getResources(), R.drawable.bitmap_id));
}
// allows re-factoring into separate class/file
class MapOverlay extends com.google.android.maps.Overlay
{
private Bitmap bitmap;
public MapOverlay(Resources resources, int resourceId) {
bitmap = BitmapFactory.decodeResource(resources, resourceId);
}
#Override
public void draw(Canvas canvas, MapView mapView, boolean shadow) {
...
canvas.drawBitmap(bmp, src, dst, null);
}
}
Change this code
min = new GeoPoint((int)(lat1 * 1E6), (int)(lng2 * 1E6)); // bounding rectangle
max = new GeoPoint((int)(lat2 * 1E6), (int)(lng1 * 1E6));
instead of
min = new GeoPoint((int)(lat1 * 1E6), (int)(lng1 * 1E6)); // bounding rectangle
max = new GeoPoint((int)(lat2 * 1E6), (int)(lng2 * 1E6));
and try its working.
You have to add overlays into your listOfOverlays. Then only it will be shown on the map. For that you have to create an overlayitem using ur geopoint and then add it to the list of overlays.
For eg:
GeoPoint point = new GeoPoint((int) (latitude * 1E6), (int) (longitude * 1E6));
OverlayItem overlayItem = new OverlayItem(point, "", "");
listOfOverlays.addOverlay(overlayItem);
mapView.invalidate();
Try and see. If you face any issue, please add as comments.
I just spent ages pulling my hair out with the same problem as you. Turned out removing android:layout_weight="1" from my MapView declaration resolved the problem. Don't ask me why!