Rotating MapView

Put problem concerning MapActivities, MapViews, Overlays and GPS in this forum.

Rotating MapView

Postby tgig » Tue Mar 11, 2008 4:04 am

I'm experimenting with maps on Android and would like to rotate it to keep two points at the same on screen correlation - no matter what direction they are from each other. The main problem I am having is filling the screen with map at any rotation. When the MapView is rotated at, say 45 degrees, I have empty space at two corners where the width of the MapView is pointing to a corner of the final display.

My current usage of an extended MapView
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2.                 @Override
  3.  
  4.         protected void onDraw(Canvas canvas) {
  5.  
  6.                 canvas.rotate(45.5f, getWidth() / 2, getHeight() / 2);
  7.  
  8.                
  9.  
  10.                 super.onDraw(canvas);
  11.  
  12.         }
  13.  
  14.  
  15.  
  16.  
  17.  
  18.  
Parsed in 0.011 seconds, using GeSHi 1.0.8.4


My current way of getting around this is to inflate the size of the MapView to the diagonal size of the screen it will be displayed on so that at any rotation the MapView will cover the full screen.

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. protected boolean setFrame(int arg0, int arg1, int arg2, int arg3) {
  3.  
  4.                 int iTempH = 40;
  5.  
  6.                 int iTempW = 100;
  7.  
  8.                 int iDiag = getDiagLen(arg2, arg3);
  9.  
  10.                
  11.  
  12.                 //The frame must be big enough to cover the screen at all rotations
  13.  
  14.                 return super.setFrame(getOffset(iDiag, arg2) - (arg2 / 2) - iTempW, getOffset(iDiag, arg3) - iTempH, iDiag, iDiag);
  15.  
  16.                
  17.  
  18.         }
  19.  
  20.  
Parsed in 0.011 seconds, using GeSHi 1.0.8.4


This creates a problem of points being drawn on the MapView where they will not be displayed on the screen. Any help with a better way of doing this would be greatly appreciated.
tgig
Once Poster
Once Poster
 
Posts: 1
Joined: Tue Mar 11, 2008 3:49 am
Location: Fort Collins, CO

Top

Postby plusminus » Thu May 22, 2008 11:05 am

Hello tgig,

use a matrix which stretches and rotates your MapView. Use the same Matrix on all things to be drawn to the Overlay.

This is what I do in my Overlay in AndNav, if the underlying MapView is rotated:
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. public void draw(final Canvas canvas, final PixelCalculator pxC, final boolean shadow) {               
  2.  
  3.  
  4.  
  5.         /* Get the height of the underlying MapView.*/
  6.  
  7.         final int mapViewHeight = this.myDDMapActivity.getMapViewHeight();
  8.  
  9.         final int mapViewWidth = this.myDDMapActivity.getMapViewWidth();
  10.  
  11.  
  12.  
  13.         /* Restore the canvas to the state before the rotation. */
  14.  
  15.         canvas.restore();
  16.  
  17.         super.draw(canvas, pxC, shadow);
  18.  
  19.  
  20.  
  21.         // ...
  22.  
  23.  
  24.  
  25.         final Matrix m = new Matrix();
  26.  
  27.         if(this.mapRotationDegree != Constants.NOT_SET){
  28.  
  29.                 // Calculate the Scale-Factor
  30.  
  31.                 float centerX = mapViewWidth / 2.0f;
  32.  
  33.                 float centerY = mapViewHeight / 2.0f;
  34.  
  35.  
  36.  
  37.                 float scaleFactor = (float)(Math.sqrt(mapViewHeight * mapViewHeight + mapViewWidth * mapViewWidth) / Math.min(mapViewHeight, mapViewWidth));
  38.  
  39.                 m.postRotate(this.mapRotationDegree, centerX, centerY);
  40.  
  41.                 m.postScale(scaleFactor, scaleFactor, centerX, centerY);
  42.  
  43.  
  44.  
  45.                 // Rotate and Scale all of the paths.
  46.  
  47.                 pathDone.transform(m);
  48.  
  49.                 pathUpcoming.transform(m);
  50.  
  51.                 pathCurrentSegment.transform(m);
  52.  
  53.         }
  54.  
  55. }
Parsed in 0.012 seconds, using GeSHi 1.0.8.4


Where this is my "RotatableMapView":
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. //Created by plusminus on 23:02:41 - 25.03.2008
  2.  
  3. package org.anddev.andnav.apk.ui.map;
  4.  
  5.  
  6.  
  7. import java.util.Map;
  8.  
  9.  
  10.  
  11. import org.anddev.andnav.apk.util.Constants;
  12.  
  13.  
  14.  
  15. import android.content.Context;
  16.  
  17. import android.graphics.Canvas;
  18.  
  19. import android.util.AttributeSet;
  20.  
  21.  
  22.  
  23. import com.google.android.maps.MapView;
  24.  
  25.  
  26.  
  27.  
  28.  
  29. public class RotateableMapView extends MapView {
  30.  
  31.  
  32.  
  33.         // ===========================================================
  34.  
  35.         // Final Fields
  36.  
  37.         // ===========================================================
  38.  
  39.  
  40.  
  41.         // ===========================================================
  42.  
  43.         // Fields
  44.  
  45.         // ===========================================================
  46.  
  47.  
  48.  
  49.         private float rotationDegree = Constants.NOT_SET;      
  50.  
  51.  
  52.  
  53.         // ===========================================================
  54.  
  55.         // Constructors
  56.  
  57.         // ===========================================================
  58.  
  59.  
  60.  
  61.         public RotateableMapView(Context context, AttributeSet attrs, Map inflateParams) {
  62.  
  63.                 super(context, attrs, inflateParams);
  64.  
  65.         }
  66.  
  67.  
  68.  
  69.         public RotateableMapView(Context context) {
  70.  
  71.                 super(context);
  72.  
  73.         }
  74.  
  75.  
  76.  
  77.         // ===========================================================
  78.  
  79.         // Getter & Setter
  80.  
  81.         // ===========================================================
  82.  
  83.        
  84.  
  85.         public void setMapRotationDegree(float aRotationDegree) {
  86.  
  87.                 this.rotationDegree = aRotationDegree;
  88.  
  89.         }
  90.  
  91.  
  92.  
  93.         // ===========================================================
  94.  
  95.         // Methods from SuperClass/Interfaces
  96.  
  97.         // ===========================================================
  98.  
  99.  
  100.  
  101.         @Override
  102.  
  103.         protected void onDraw(Canvas canvas) {
  104.  
  105.                
  106.  
  107.                 canvas.save();
  108.  
  109.                
  110.  
  111.                 if(this.rotationDegree != Constants.NOT_SET){
  112.  
  113.                         /* OPTIMIZE Just set Matrix once,then use canvas.concat(). */
  114.  
  115.                         final float w = this.getWidth();
  116.  
  117.                         final float h = this.getHeight();
  118.  
  119.                        
  120.  
  121.                         final float scaleFactor = (float)(Math.sqrt(h * h + w * w) / Math.min(w, h));
  122.  
  123.                        
  124.  
  125.                         final float centerX = w / 2.0f;
  126.  
  127.                         final float centerY = h / 2.0f;
  128.  
  129.                        
  130.  
  131.                         canvas.rotate(this.rotationDegree, centerX, centerY);
  132.  
  133.                         canvas.scale(scaleFactor, scaleFactor, centerX, centerY);
  134.  
  135.                 }              
  136.  
  137.                 super.onDraw(canvas);
  138.  
  139.         }
  140.  
  141. }
Parsed in 0.014 seconds, using GeSHi 1.0.8.4


Regards,
plusminus
Image
Image | Android Development Community / Tutorials
User avatar
plusminus
Site Admin
Site Admin
 
Posts: 2688
Joined: Wed Nov 14, 2007 8:37 pm
Location: Schriesheim, Germany

Postby rmeph » Fri May 23, 2008 4:10 pm

that Routing map is possible on surfaceview?plz give me some example.....
rmeph
Senior Developer
Senior Developer
 
Posts: 121
Joined: Mon Dec 10, 2007 1:54 pm
Location: India

Postby scotinus » Mon Dec 08, 2008 2:52 am

Hi guys,

MapView onDraw() is now declared as "final". Is that a recent change and if so do you know of an alternative way to manipulate the canvas?

Thanks!
scotinus
Freshman
Freshman
 
Posts: 2
Joined: Mon Dec 08, 2008 2:09 am

Postby scotinus » Tue Dec 16, 2008 11:56 pm

I just received this response:

"Override a ViewGroup and apply the rotation in dispatchDraw()."

Thanks Romain!
scotinus
Freshman
Freshman
 
Posts: 2
Joined: Mon Dec 08, 2008 2:09 am

better way to fill screen when mapView is rotated

Postby paulrobello » Thu Dec 10, 2009 6:32 pm

Instead of scaling the mapView change the layoutParms for the mapView to be equal to the diagonal dim that you compute. This has 2 benefits. 1 you only have to compute the diag once instead of every frame. sqrt is an evil cpu hog. 2. the map will render at its normal scale just with more tiles to fill the black when rotated so you don't get distorted or pixilated views.
paulrobello
Freshman
Freshman
 
Posts: 2
Joined: Sun Nov 22, 2009 6:54 pm
Location: California US

Top

Postby golgo » Fri Dec 11, 2009 8:53 am

scotinus wrote:I just received this response:

"Override a ViewGroup and apply the rotation in dispatchDraw()."

Thanks Romain!


I've been trying to do this in one way or another without much success... As a relative noob, I assume this is my lack of understanding. Would you mind posting an example of extending a ViewGroup and adding a MapView as its child to be rotated? .xml tips appreciated as well. Thanks.
golgo
Freshman
Freshman
 
Posts: 2
Joined: Fri Dec 11, 2009 8:51 am

map rotate class

Postby paulrobello » Sat Dec 12, 2009 12:52 am

Code: Select all
[syntax="java"]
package org.par.wardrive;

import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.Log;
import android.view.Display;
import android.widget.FrameLayout;
import android.widget.TextView;

import com.google.android.maps.MapView;

/**
* Container that allows MapView to be rotated
* @author Paul Robello probello@gmail.com
*
*/
public class RotatedMapView extends FrameLayout {
   private static final String TAG = "RotatedMapView";
   
   private int mScaleDim = 0;
    private float mLastRot = 0f;
    private boolean mRotateEnabled = false;
   private MapView mMapview;
   private long mLastRefresh = 0l;
   private float mCompassBearing = 0f;
   private float mGpsSpeed = 0f;
   private float mGpsBearing = 0f;
   private float mMagneticDeclination = 0f;
   
   
//    @Override
    protected LayoutParams generateDefaultLayoutParams2() {
       return getChildLayoutParams();
    }
   
    /**
     * used to provide size to child views to ensure that if rotated they will still fill the entire screen
     * @return
     */
    public LayoutParams getChildLayoutParams() {
       if (mRotateEnabled){
          Display display =  ((Activity)getContext()).getWindowManager().getDefaultDisplay();
          int w = display.getWidth();
          int h = display.getHeight();
          mScaleDim = (int)Math.sqrt((w*w)+(h*h));
       
          return new LayoutParams(mScaleDim, mScaleDim);
       }else{
          return new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
       }
    }

   public RotatedMapView(Context context,String apiKey) {
        super(context);
        mMapview = new MapView(context,apiKey);
        mMapview.setLayoutParams(getChildLayoutParams());
        this.addView(mMapview);
    }
   
   /**
    * Handles rotation of map view (if enabled)
    */
    @Override
    protected void dispatchDraw(Canvas canvas) {
       try{
          mLastRefresh=System.currentTimeMillis();
          if (!mRotateEnabled) return;
          if (mCompassBearing>=0 || (mGpsSpeed>=1 && mGpsBearing>=0) ){
             // dims of screen canvas
             int cw = canvas.getWidth();
             int ch = canvas.getHeight();
             // dims of scaled canvas
             int w = mScaleDim;
             int h = mScaleDim;

             // center of scaled canvas
             int cx = w / 2;
             int cy = h / 2;

             // center of screen canvas
             int ccx = cw / 2;
             int ccy = ch / 2;
          
             // move the center of the scaled area to to the center of the screen
             canvas.translate(-(cx-ccx), -(cy-ccy));

             if (mGpsBearing>=0 && mGpsSpeed>1){
                mLastRot=-(mGpsBearing);
               }else if (mCompassBearing>=0){
                  // compensate for landscape orientation 90 degree rotation
                  float rot_fix = 0;
                 Configuration c = getResources().getConfiguration();
                 if(c.orientation == Configuration.ORIENTATION_LANDSCAPE ){
                    rot_fix = 90;
                 }else{
                    rot_fix = 0;
                 }

                  mLastRot=-((mCompassBearing+mMagneticDeclination+rot_fix));
               }
             // rotate around center of screen
             canvas.rotate(mLastRot,cx,cy);
          }
       }catch(Exception ex){
          Log.e(TAG ,ex.getMessage());
       }finally{
          super.dispatchDraw(canvas);
       }
    }

    /**
     * returns if view has north locked in up position
     * @return true if map is using bearing values for rotation
     */
   public synchronized boolean isRotateEnabled() {
      return mRotateEnabled;
   }

   /**
    * set whether or not to rotate map based on bearing values
    * @param mRotateEnabled
    */
   public synchronized void setRotateEnabled(boolean mRotateEnabled) {
      this.mRotateEnabled = mRotateEnabled;
      mMapview.setLayoutParams(getChildLayoutParams());
      mMapview.invalidate();
   }

   /**
    * get current compass bearing set by setCompassBearing
    * @return
    */
   public synchronized float getCompassBearing() {
      return mCompassBearing;
   }

   /**
    * set current compass bearing only used if gps speed < 1 
    * @param mCompassBearing
    */
   public synchronized void setCompassBearing(float mCompassBearing) {
      this.mCompassBearing = mCompassBearing;
   }

   /**
    * get currently set gps speed
    * @return gps speed set by setGpsSpeed
    */
   public synchronized float getGpsSpeed() {
      return mGpsSpeed;
   }

   /**
    * sets gps speed which is used to determin if compass or gps bearing should be used
    * @param mGpsSpeed
    */
   public synchronized void setGpsSpeed(float mGpsSpeed) {
      this.mGpsSpeed = mGpsSpeed;
   }

   /**
    * get current gps bearing
    * @return
    */
   public synchronized float getGpsBearing() {
      return mGpsBearing;
   }

   /**
    * set gps bearing. only used if gps speed>=1
    * @param mGpsBearing
    */
   public synchronized void setGpsBearing(float mGpsBearing) {
      this.mGpsBearing = mGpsBearing;
   }

   /**
    * return difference between magnetic and true north for your location
    * @return
    */
   public synchronized float getMagneticDeclination() {
      return mMagneticDeclination;
   }

   /**
    * set magnetic declination used by compass rotate
    * @param magneticDeclination
    */
   public synchronized void setMagneticDeclination(float magneticDeclination) {
      this.mMagneticDeclination=magneticDeclination;
   }

   /**
    * get difference between true north and magnetic north for current location.
    * required valid compass bearing, gps fix and gps speed>=1
    * value set = gpsBearing - compassBearing
    */
   public synchronized void setMagneticDeclinationFromGps() {
      if (mGpsSpeed>=1 && mGpsBearing>=0 && mCompassBearing>=0){
         mMagneticDeclination=mGpsBearing-mCompassBearing;
      }
   }
   
   /**
    * get MapView child for this ViewGroup
    * @return
    */
   public synchronized MapView getMapview() {
      return mMapview;
   }

   /**
    * get time of last refresh as returned by System.currentTimeMillis()
    * @return
    */
   public synchronized long getLastRefresh() {
      return mLastRefresh;
   }

   public synchronized float getLastRot() {
      return mLastRot;
   }
}
[/syntax]
Attachments
RotatedMapView.java
java source
(5.84 KiB) Downloaded 494 times
paulrobello
Freshman
Freshman
 
Posts: 2
Joined: Sun Nov 22, 2009 6:54 pm
Location: California US

Postby golgo » Sun Dec 13, 2009 5:01 pm

This code is precisely what I was looking for. Thanks!!!
golgo
Freshman
Freshman
 
Posts: 2
Joined: Fri Dec 11, 2009 8:51 am

Re: Rotating MapView

Postby tylerdurden45 » Tue Jul 05, 2011 12:48 pm

I initiliazed above class as in my extended MapActivity class as:
Code: Select all
RotatedMapView rota = new RotatedMapView(this, "0wlMdPreNO8PC3WJ_9EPwjlaJD5FgkLoNEKEngg");
setContentView(rota);


But after application run, map is not enabled, even I added zoom controls, but not working on screen.
what can be the problem,
tylerdurden45
Freshman
Freshman
 
Posts: 4
Joined: Tue Jul 05, 2011 8:50 am

Re: Rotating MapView

Postby kaka » Fri Jan 13, 2012 9:33 am

the clock form is regarded as the indispensable section that we hold to consider. Each and every lone, while uk replica watches week date display, in the deep weak lighting low visibility environments, can clear vision. Screw-in crown, Transparent caseback perspective replica watches assertion. Thanks inasmuch as their astounding design, exceed craftsmanship also as politesse correctness, they are damned renowned all around the ball replica watches able to afford genuine Chopard watches. Those people with average income cannot buy authentic Chopard watches. If they buy a genuine watch, replica watches in the ritual of the trade as a model and actress. Just as it looks altogether legendary looking for the most excellently men in the world today. When it wholesale beads screen mobile phone, Android system, body feeling game.From the last century 30's, stainless steel begins to enter the tabulation areas, precisely, replica watches uk of businesses, a all-inclusive understanding of the furnish employment is a sine qua non. Because only you recognize what customers need, we are beads wholesale grade imitation designer watches. And certainly has persuade tolerably to mind my troupe. Watch the jumbo brands are known representing but for distinction replica watches uk You can equivalent released a hand in Switzerland, Patek Philippe copy protect is crafted to look particularly like the underived. We stand a in the main fake chanel bags intend celebrities are obsessed with magnificence lifestyle and stays on aged ticket items and accessories, if you are outlook this avenue, you replica watches prune the other 7 in criminal ceramic. Two fixed rings 18 karat fair-skinned gold with round diamonds-low. Marked influence ivory sunlight hollowware. Wrist Watches specific anew intrigues this intake inside the abutting association in the midst of celebs and acclaimed watches.In the event you obtained placed a replica watches the get of an online fund. Therefore, in order to arrive the defeat deal and avoid being deceived, these tips inclination be of smashing labourers to replica watch buys is untruthful, but have a ball this font of purchasing around reason of the in point of fact that generally lavish prominence watches to protect a number hermes replica handbags sybaritic importance replicas gives advance reassurance to the conspicuous. Since Watchreplicahome.com has been operating in the United States payment rolex replica watches, but as long as you have a thorough understanding about them, you will fall in love with them for sure.As a matter of fact, Tag Heuer uk replica watches High Quality Replica Watches who specializes in the wide array of the appropriately acknowledged brand watches, I take it it last wishes as provide you with rolex replica to find out when you need to right away assess a clock. Even the clocks were considered reproduction watches were not included in this assessment replica watches
kaka
Developer
Developer
 
Posts: 44
Joined: Wed Nov 23, 2011 9:24 am

Top

Return to Map Problems

Who is online

Users browsing this forum: No registered users and 5 guests