/* This file is part of OpenSatNav. OpenSatNav is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OpenSatNav is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenSatNav. If not, see <http://www.gnu.org/licenses/>. */ package org.andnav.osm.views.overlay; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import org.andnav.osm.util.GeoPoint; import org.andnav.osm.views.OpenStreetMapView; import org.andnav.osm.views.OpenStreetMapView.OpenStreetMapViewProjection; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.Point; /** * * @author Kieran Fleming * */ public class OpenStreetMapViewRouteOverlay extends OpenStreetMapViewOverlay implements Serializable { // =========================================================== // Constants // =========================================================== // =========================================================== // Fields // =========================================================== /** * */ private static final long serialVersionUID = 4352398623624395209L; protected final Paint mPaint = new Paint(); protected List<GeoPoint> route; protected GeoPoint mLocation; protected ArrayList<GeoPoint> pointRoute; protected ArrayList<Point> pixelRoute; protected Point firstPixelPoint, oldFirstPoint, lastPixelPoint, oldLastPixelPoint; protected Path routePath; // =========================================================== // Constructors // =========================================================== public OpenStreetMapViewRouteOverlay(final Context ctx, List<GeoPoint> route) { mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(6); mPaint.setColor(Color.BLUE); mPaint.setAlpha(100); mPaint.setAntiAlias(true); this.route = route; pointRoute = new ArrayList<GeoPoint>(); pixelRoute = new ArrayList<Point>(); routePath = new Path(); for (int i = 0; i < this.route.size(); i++) { GeoPoint nextPoint = this.route.get(i); nextPoint.setCoordsE6(nextPoint.getLatitudeE6(), nextPoint.getLongitudeE6()); pointRoute.add(nextPoint); } } // =========================================================== // Getter & Setter // =========================================================== public void setLocation(final GeoPoint mp) { this.mLocation = mp; } // =========================================================== // Methods from SuperClass/Interfaces // =========================================================== @Override protected void onDrawFinished(Canvas c, OpenStreetMapView osmv) { return; } @Override public void onDraw(final Canvas c, final OpenStreetMapView osmv) { final OpenStreetMapViewProjection pj = osmv.getProjection(); if (this.pointRoute.size() != 0) { if (firstPixelPoint != null) oldFirstPoint = firstPixelPoint; if (lastPixelPoint != null) oldLastPixelPoint = lastPixelPoint; // this is optimisation so the computation from lat/long to pixel // coords // is only done if we need to, as this is expensive // right now this optimises map panning, but can optimise for zoom // as well // get the points firstPixelPoint = pj.toPixels((GeoPoint) pointRoute.get(0), null); lastPixelPoint = pj.toPixels(this.pointRoute.get(this.pointRoute.size() - 1), null); // they panned, don't recompute from lat/long, just move the pixel // route the appropriate amount if ((oldFirstPoint != null) && (oldFirstPoint.x - firstPixelPoint.x) == (oldLastPixelPoint.x - lastPixelPoint.x) && (oldFirstPoint.y - firstPixelPoint.y) == (oldLastPixelPoint.y - lastPixelPoint.y)) { for (int i = 0; i < this.pixelRoute.size(); i++) { this.pixelRoute.set(i, new Point(this.pixelRoute.get(i).x - (oldFirstPoint.x - firstPixelPoint.x), this.pixelRoute.get(i).y - (oldFirstPoint.y - firstPixelPoint.y))); } } // either there is no old point, ergo this is the first time we are // here, // or they have zoomed // if this is false it means the map is still and we don't need to // do anything else if ((oldLastPixelPoint == null) || (oldLastPixelPoint.x != lastPixelPoint.x) || (oldLastPixelPoint.y != lastPixelPoint.y)) { if (pixelRoute != null) pixelRoute.clear(); for (int i = 0; i < pointRoute.size(); i++) { // Point nextScreenCoords = new Point(); pixelRoute.add(pj.toPixels((GeoPoint) pointRoute.get(i), null)); } } // draw the pixel route routePath.rewind(); for (int i = 0; i < this.pixelRoute.size(); i++) { Point current = pixelRoute.get(i); if (i == 0) routePath.moveTo(current.x, current.y); else routePath.lineTo(current.x, current.y); } c.drawPath(routePath, this.mPaint); } } public ArrayList<Point> getPixelRoute() { return this.pixelRoute; } }