I currently need to display a boat/cruise ship route in a MapView, something like this
I started coding my version of it, but since every example that I see of water routes are the same I started wondering if there was a "standard" method of doing it. I have been searching for hours and haven't found anything yet, so I decided to ask here.
Here's what I have so far:
Point point2 = new Point();
projection.toPixels(gp2, point2);
paint.setStrokeWidth(5);
paint.setPathEffect(new DashPathEffect(new float[] {8,12}, 5));
paint.setAlpha(defaultColor==Color.parseColor("#6C8715")?200:100);
canvas.drawLine(point.x, point.y, point2.x,point2.y, paint);
It is working and the only thing left to do is adjust the line every time that the user zooms.
Is this the way to do it, or there's a standard way of doing it?
Any help is appreciated, thank you.
If you move your code to an Overlay then you wouldn't have to worry about adjusting the line when the user zooms/pans. Since you probably have more than two points to draw you can also take advantage of the Path class.
import com.google.android.maps.Overlay;
class PathOverlay extends Overlay {
private void List<GeoPoint>geoPoints;
public PathOverlay(List<GeoPoint> points) {
this.geoPoints = geoPoints;
}
public void draw(Canvas canvas, MapView mapView, boolean shadow) {
super.draw(canvas, mapv, shadow);
Paint paint = new Paint();
paint.setStrokeWidth(5);
paint.setPathEffect(new DashPathEffect(new float[] {8,12}, 5));
paint.setAlpha(defaultColor==Color.parseColor("#6C8715")?200:100);
Path path = new Path();
boolean isFirst = true;
for (GeoPoint geoPoint : this.geoPoints) {
Point point = new Point();
mapView.getProjection().toPixels(geoPoint, point);
if (isFirst) {
isFirst = false;
path.moveTo(point.x, point.y);
}
else {
path.lineTo(point.x,point.y);
}
}
canvas.drawPath(path, paint);
}
}
Extend Overlay and override draw() method in it. Then do the same you did previously. You will get automatic redraw in move/zoom
This one answer will work for you How to draw a path on a map using kml file?
Related
I am trying to draw a filled polygon on a map view in my app. No matter what I have tried it will not draw filled in. I can get the strokes to show up but I can not get it to fill. Below is the draw method of my polygon class. It overrides overlays.
public void draw(Canvas canvas, MapView mapv, boolean shadow) {
super.draw(canvas, mapv, shadow);
Paint mPaint = new Paint();
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.BLACK);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(6);
Paint mPaintFill = new Paint();
mPaintFill.setStyle(Paint.Style.FILL);
mPaintFill.setColor(Color.GREEN);
Path path = new Path();
GeoPoint start = route.get(0);
for (int i = 1; i < route.size(); ++i) {
Point p1 = new Point();
Point p2 = new Point();
Projection projection = mapv.getProjection();
projection.toPixels(start, p1);
projection.toPixels(route.get(i), p2);
path.moveTo(p2.x, p2.y);
path.lineTo(p1.x, p1.y);
start = route.get(i);
}
canvas.drawPath(path, mPaint);
canvas.drawPath(path, mPaintFill);
//canvas.clipPath(path, Op.DIFFERENCE);
}
The above code for me will draw the lines correctly but it doesn't get filled in. Removing canvas.drawPath(path, mPaint); and just leaving the fill one results in nothing showing on the map. I have even tried setting Paint.Style.STROKE to Paint.Style.FILL_AND_STROKE. I am at a complete loss and at this point am thinking it is something simple I am over looking.
public PNGOverlay(Bitmap original, GeoPoint topLeftGeoPoint, GeoPoint bottomRightGeoPoint) {
this.original = Bitmap.createScaledBitmap(original, original.getWidth(), original.getHeight(), true);
...
topGeoPoint = topLeftGeoPoint;
bottomGeoPoint = bottomRightGeoPoint;
}
#Override
public void draw(Canvas canvas, MapView mapView, boolean shadow) {
super.draw(canvas, mapView, false);
Projection projection = mapView.getProjection();
Point leftTop = new Point();
Point rightTop = new Point();
Point rightBottom = new Point();
Point leftBottom = new Point();
projection.toPixels(topGeoPoint, leftTop);
projection.toPixels(new GeoPoint(topGeoPoint.getLatitudeE6(), bottomGeoPoint.getLongitudeE6()), rightTop);
projection.toPixels(bottomGeoPoint, rightBottom);
projection.toPixels(new GeoPoint(bottomGeoPoint.getLatitudeE6(), topGeoPoint.getLongitudeE6()), leftBottom);
....
Paint paint = new Paint();
paint.setFilterBitmap(true);
paint.setAntiAlias(true);
canvas.drawBitmap(original, null, new Rect(leftTop.x, leftTop.y, rightBottom.x, rightBottom.y), paint);
....
}
I have a problem with this code. When I draw the png on the mapView, the png image is showed over the compass and over the GPS position indicatior? Any idea?
From your question is difficult to guess what is exactly your problem, but if you mean that the PNG is being drawn over the other overlays and you want it to be under them, you can solve it by adding the PNG overlay first to the mapview.
MapView calls the draw method from each overlay by the order that you add them:
mapview.getoverlays().add(overlay1);
mapview.getoverlays().add(overlay2);
This results in overlay2 being drawn over overlay1.
mapview.getoverlays().add(overlay2);
mapview.getoverlays().add(overlay1);
This results in overlay1 being drawn over overlay2.
good luck.
I've this custom class that extends the Overlay that is being added into my mapview. i have just one of this class that adds all my polygon and text into this overlay class. However this results in a very slow mapview. I added a draw integer and tested out that this class will draw 84 times each time the ondraw function is being called. Is there any solution that will help to reduce the loading speed of the mapview? Right now the mapview is very slow, each time i move left right or even zoom will be very slow. looking at the android catlog, it seems to me that overlay class ondraw is being called everysecond? should i be looking at another type of layer instead of using overlay?
#Override
public void draw(Canvas canvas, MapView mapView, boolean shadow)
{
shadow=false;
int numberofdraw= 0;
//outline
Paint paint = new Paint();
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStrokeWidth(2);
//paint.setColor(0x10000000);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setAntiAlias(true);
Point point1_draw = new Point();
for (int i =0;i<data.getCustomPolygonList().size();i++)
{
CustomPolygon customPolygon= data.getCustomPolygonList().get(i);
Path path = new Path();
path.setFillType(Path.FillType.EVEN_ODD);
for(int n=0;n<customPolygon.getCorrdinateList().size();n++)
{
GeoPoint sector1 = new GeoPoint((int)(customPolygon.getCorrdinateList().get(n).getLatitude()*1e6), (int)((customPolygon.getCorrdinateList().get(n).getLongitude())*1e6));
if(n==0){
mapView.getProjection().toPixels(sector1, point1_draw);
path.moveTo(point1_draw.x,point1_draw.y);
}else
{
mapView.getProjection().toPixels(sector1, point1_draw);
path.lineTo(point1_draw.x,point1_draw.y);
}
}
path.close();
canvas.drawPath(path, paint);
numberofdraw++;
// canvas.clipPath(path, Op.DIFFERENCE);
}
//inside sector color
for (int i =0;i<data.getCustomPolygonList().size();i++)
{
CustomPolygon customPolygon= data.getCustomPolygonList().get(i);
paint = new Paint();
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStrokeWidth(2);
paint.setColor(0x186666ff);
//paint.setColor(customPolygon.getColor());
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setAntiAlias(true);
point1_draw = new Point();
Path path = new Path();
path.setFillType(Path.FillType.EVEN_ODD);
for(int n=0;n<customPolygon.getCorrdinateList().size();n++)
{
GeoPoint sector1 = new GeoPoint((int)(customPolygon.getCorrdinateList().get(n).getLatitude()*1e6), (int)((customPolygon.getCorrdinateList().get(n).getLongitude())*1e6));
if(n==0){
mapView.getProjection().toPixels(sector1, point1_draw);
path.moveTo(point1_draw.x,point1_draw.y);
}else
{
mapView.getProjection().toPixels(sector1, point1_draw);
path.lineTo(point1_draw.x,point1_draw.y);
}
}
path.close();
numberofdraw++;
canvas.drawPath(path, paint);
}
//inside sector text
for (int i =0;i<data.getCustomPolygonList().size();i++)
{
CustomPolygon customPolygon= data.getCustomPolygonList().get(i);
TextPaint paintText = new TextPaint();
Point point1 = new Point();
String text=customPolygon.getName();
for(int n=0;n<customPolygon.getCorrdinateList().size();n++)
{
if(customPolygon.getTextLocation()!=null)
{
paintText.setTextSize(24);
Rect rect = new Rect();
paintText.getTextBounds(text, 0, text.length(), rect);
paintText.setTextAlign(Paint.Align.CENTER);
paintText.setTypeface(Typeface.DEFAULT_BOLD);
paintText.setColor(Color.BLACK);
GeoPoint sector1 = new GeoPoint((int)(customPolygon.getTextLocation().getLatitude()*1e6), (int)((customPolygon.getTextLocation().getLongitude())*1e6));
mapView.getProjection().toPixels(sector1, point1);
}
}
numberofdraw++;
canvas.drawText(text, point1.x, point1.y, paintText);
}
Log.e(Config.log_id,"draw no. "+ numberofdraw+"");
}
there are many ways you can improve it, I will suggest you one.
Buffering:
For each polygon create a new canvas and a new bitmap
Canvas myBufferCanvas;
Bitmap myBufferBitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
myBufferCanvas = new Canvas(myBufferBitmap);
Then only call draw when the polygon is change, call the draw with myBufferCanvas and then call drawBitmap on the true canvas.
The advantage of this method is performance, it will be extremely fast! The disadvantage is memory, if you have to many polygons, you can kill the device. Just try reusing them some home and you will be fine.
Just remember that you can apply any transformation to your buffered image without redrawing it.
I think you should be using a custom ItemizedOverlay to manage drawing items on your MapView. That aside, there are some changes you can make to your existing code which I'm sure would speed it up. In your draw() method you are creating new Paint objects each time, setting their properties and then disposing of them. Worse still, inside the draw() method you loop through the polygon list twice, creating more Paint objects or TextPaint objects. Instead, you can create one of each Paint object once when the Overlay is initialised and then re-use them in the loop. You may also be able to do everything in one loop.
Process the data, then build the paths and finally paint the paths on the map, see the response from TWiStErRob in this post.
I want to draw Driving direction Route from source geopoints to Destination geopoints. I tried this with the below code but its draw a straight line between the Location not proper shortest route.
#Override
public void draw(Canvas canvas, MapView mapView, boolean shadow) {
// TODO Auto-generated method stub
super.draw(canvas, mapView, shadow);
Projection projection = classMapView.getProjection();
Paint mPaint = new Paint();
mPaint.setDither(true);
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(2);
GeoPoint gP1 = new GeoPoint(22716221,75896816);
GeoPoint gP2 = new GeoPoint(22715212, 75895806);
Point p1 = new Point();
Point p2 = new Point();
Path path = new Path();
projection.toPixels(gP1, p1);
projection.toPixels(gP2, p2);
path.moveTo(p2.x, p2.y);
path.lineTo(p1.x,p1.y);
canvas.drawPath(path, mPaint);
}
Please help and also tell me is it possible to get text of direction as Google Maps provide.
Please go through Google Policies
This states that turn-by-
turn navigation is not allowed using android MapView.
instead you can use intent to do that as follows
Intent intent = new Intent(android.content.Intent.ACTION_VIEW,
Uri.parse("http://maps.google.com/maps?saddr=<start lat>,<start lon>&daddr=<dest lat>,<dest lon>"));
startActivity(intent);
Here is a complete source code at https://github.com/frogermcs/RoutePathExample for how to draw path between two geolocation.
I'm trying to add text labels next to my overlay images. So far the only way I can see to do this would be to use the draw method and draw the text as overlay. I did this, but somehow it isn't showing me the drawn text. My code looks like:
SitesOverlay that extends ItemizedOverlay<OverlayItem>
public void draw(Canvas canvas, MapView mapView,boolean shadow) {
int i;
Paint paint=new Paint();
paint.setStrokeWidth(1);
paint.setARGB(255, 255, 255, 255);
paint.setStyle(Paint.Style.STROKE);
super.draw(canvas, mapView, shadow);
boundCenterBottom(station);
canvas.drawText("hullo",28632877,77219722, paint);
}
My constructor in the SitesOverlay class just adds the images to many different GeoPoints.
Now, in my OnCreate I have this piece of code:
map.getOverlays().add(new SitesOverlay(station));
This is adding the list of images in my constructor - SitesOverlay(station) as overlays.
My question is that since I have added my text in the Draw method of the SitesOverlay class and not in this constructor, is this why the text is not being drawn on the map? If so how do I add the text to the map?
Do the things drawn in the draw() method automatically get added as an overlay? Coz i think thats what is causing the problem here...
Any other way I can add text labels next to my overlay images?
Plz help...
try this..
MyLocationOverlay myTouchOverlay = new MyLocationOverlay ();
List<Overlay> list1 = myMapView.getOverlays();
list1.add(myTouchOverlay);
class MyLocationOverlay extends com.google.android.maps.Overlay {
#Override
public boolean onTap(GeoPoint p, MapView mapView) {
}
#Override
public boolean draw(Canvas canvas, MapView mapView, boolean shadow,
long when) {
super.draw(canvas, mapView, shadow);
Paint paint = new Paint();
// Converts lat/lng-Point to OUR coordinates on the screen.
Point myScreenCoords = new Point();
mapView.getProjection().toPixels(point, myScreenCoords);
paint.setStrokeWidth(1);
paint.setARGB(255, 255, 255, 255);
paint.setStyle(Paint.Style.STROKE);
paint.setTextSize(20);
paint.setColor(Color.RED);
paint.setStrokeWidth(2);
canvas.drawText("Here I am...", myScreenCoords.x-10,myScreenCoords.y-48, paint);
return true;
}
}