Rotate marker to point to device heading when rotating map and place the marker to specific point on the map when map is dragged

1,111 views
Skip to first unread message

Himal Rai

unread,
Jun 14, 2015, 4:46:57 AM6/14/15
to mapsfo...@googlegroups.com

Using new version of mapsforge 0.5.1, map rotates fine with onSensorChanged event. I have added a custom GPS location marker at GPS point on onLocationChanged event. When the map rotates, the marker is also rotated to point towards the device heading like in google maps overriding the marker's draw method.

android.graphics.Canvas androidCanvas = AndroidGraphicFactory.getCanvas(canvas);
androidCanvas.save();
Float px = (float) canvas.getWidth()/2;
Float py = (float) canvas.getHeight()/2;
androidCanvas.rotate(degree, px, py);
canvas.drawBitmap(bitmap, left, top);
androidCanvas.restore();



However when the map is dgragged, the marker's position disorients from the previous point of the GPS location.



How do I calculate the px and py value to keep the marker at the precise point of GPS location on map even when the map is rotating.

Emux

unread,
Jun 14, 2015, 9:51:14 AM6/14/15
to mapsfo...@googlegroups.com
You need to perform the calculations for each component in its units system.

i.e. a marker is to be rotated with pivot point its pin point on map.

Take a look at Marker.draw method to find the needed info for that.

--
Emux
Cruiser - Atlas

Himal Rai

unread,
Jun 15, 2015, 4:31:48 AM6/15/15
to mapsfo...@googlegroups.com
Hi Emux, thanks for the reply. I am trying to achieve the feature of rotating the marker like in the Cruiser app. The location marker rotates smoothly at the GPS location and stays at its position even when the map is dragged. Can you please guide me on how can this be achieved (calculation for each component in its unit system) ? Here is my RotatingMarker class. 

class RotatingMarker extends Marker {

    private Bitmap bitmap;
    private int horizontalOffset;
    private LatLong latLong;
    private int verticalOffset;

    protected float degree = 0.0f;
    protected float px = 0.0f;
    protected float py = 0.0f;

    public RotatingMarker(LatLong latLong, Bitmap bitmap, int horizontalOffset, int verticalOffset) {
        super(latLong, bitmap, horizontalOffset, verticalOffset);

        this.latLong = latLong;
        this.bitmap = bitmap;
        this.horizontalOffset = horizontalOffset;
        this.verticalOffset = verticalOffset;
    }

    @Override
    public synchronized void draw(BoundingBox boundingBox, byte zoomLevel, Canvas canvas, Point topLeftPoint) {
        if (this.latLong == null || this.bitmap == null) {
            return;
        }
        long mapSize = MercatorProjection.getMapSize(zoomLevel, this.displayModel.getTileSize());
        double pixelX = MercatorProjection.longitudeToPixelX(this.latLong.longitude, mapSize);
        double pixelY = MercatorProjection.latitudeToPixelY(this.latLong.latitude, mapSize);

        int halfBitmapWidth = this.bitmap.getWidth() / 2;
        int halfBitmapHeight = this.bitmap.getHeight() / 2;

        int left = (int) (pixelX - topLeftPoint.x - halfBitmapWidth + this.horizontalOffset);
        int top = (int) (pixelY - topLeftPoint.y - halfBitmapHeight + this.verticalOffset);
        int right = left + this.bitmap.getWidth();
        int bottom = top + this.bitmap.getHeight();

        Rectangle bitmapRectangle = new Rectangle(left, top, right, bottom);
        Rectangle canvasRectangle = new Rectangle(0, 0, canvas.getWidth(), canvas.getHeight());
        if (!canvasRectangle.intersects(bitmapRectangle)) {
            return;
        }

        android.graphics.Canvas androidCanvas = AndroidGraphicFactory.getCanvas(canvas);
        androidCanvas.save();
        // How is the pivot value calculated ?
        this.px = (float) canvas.getWidth()/2;
        this.py = (float) canvas.getHeight()/2;
        androidCanvas.rotate(this.degree, this.px, this.py);
        canvas.drawBitmap(this.bitmap, left, top);
        androidCanvas.restore();
    }

    public RotatingMarker setDegree(float degree) {
        this.degree = degree;

        return this;
    }

    public RotatingMarker setPivotPoint(float px, float py) {
        this.px = px;
        this.py = py;

        return this;
    }
}
Screenshot_2015-06-15-14-13-10.png

Emux

unread,
Jun 15, 2015, 4:50:57 AM6/15/15
to mapsfo...@googlegroups.com
On 15/06/2015 11:31 πμ, Himal Rai wrote:
        // How is the pivot value calculated ?
        this.px = (float) canvas.getWidth()/2;
        this.py = (float) canvas.getHeight()/2;
        androidCanvas.rotate(this.degree, this.px, this.py);
        canvas.drawBitmap(this.bitmap, left, top);


If you study carefully the Marker code, you'll see that you need the marker's point where it pins the map and is actually its rotation pivot:

androidCanvas.rotate(degree, (float) (pixelX - topLeftPoint.x), (float) (pixelY - topLeftPoint.y));

Try that way.

Himal Rai

unread,
Jun 15, 2015, 5:52:29 AM6/15/15
to mapsfo...@googlegroups.com
Thanks Emux, You saved my day 
"If you study carefully the Marker code, you'll see that you need the marker's point where it pins the map and is actually its rotation pivot:
androidCanvas.rotate(degree, (float) (pixelX - topLeftPoint.x), (float) (pixelY - topLeftPoint.y));"

 It worked great.


Reply all
Reply to author
Forward
0 new messages