Monday, January 17, 2011

Your First Map Application

Guidebee Map API has support for almost every platform you can find in the market, both on desktop and on moble platforms. I'll use Java ME as a start ,because it's simple . And the main concepts apply to other platform also. if you are not familiar with Java ME Midlet, only pay attention to the code in blue. The other parts are just the skeleton code for Java ME, just like Form_Load, Form_Close on .Net framework.
The following code display map of Perth, Australia.



//--------------------------------- IMPORTS -------------------------------
import javax.microedition.midlet.MIDlet;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.Display;

import com.mapdigit.gis.MapLayer;
import com.mapdigit.gis.drawing.IGraphics;
import com.mapdigit.gis.drawing.IImage;
import com.mapdigit.gis.geometry.GeoLatLng;
import com.mapdigit.gis.raster.IMapDrawingListener;
import com.mapdigit.gis.raster.IReaderListener;
import com.mapdigit.gis.raster.MapTileDownloadManager;
import com.mapdigit.gis.raster.MapType;
import com.mapdigit.gis.raster.RasterMap;

import com.mapdigit.licence.LicenceManager;

import com.pstreets.gisengine.demo.midp.drawing.MIDPGraphicsFactory;


//[------------------------------ MAIN CLASS -----------------------------]
/**
 * Hello China demo.
 *

© Copyright 2011 Guidebee, Inc. All Rights Reserved.
 * @version     1.00, 04/01/11
 * @author      Guidebee Pty Ltd.
 */
public class HelloChina extends MIDlet implements IReaderListener,
        IMapDrawingListener {

    protected RasterMap map;
    protected MapTileDownloadManager mapTileDownloadManager;
    protected IImage mapImage;
    protected IGraphics mapGraphics;
    protected MapCanvas canvas;

    public HelloChina() {
        try {
       //setup the licence information
            LicenceManager licenceManager = LicenceManager.getInstance();
            long keys[] = {0x34ba283b8daeb659L, -0x53c811f9da86e998L,
            -0x34ba25c3c581521eL, 0xf15df9fc7e45628L, 0x6a4ece44296c0287L,
            0x4ab0cff532902b1cL,};
            licenceManager.addLicence("GuidebeeMap_JavaME", keys);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

    }

    public void startApp() {
        canvas = new MapCanvas();
        //set the graphics factory
        MapLayer.setAbstractGraphicsFactory(MIDPGraphicsFactory.getInstance());
        mapImage = MapLayer.getAbstractGraphicsFactory().createImage(canvas.getWidth(),
                canvas.getHeight());
        mapGraphics = mapImage.getGraphics();
        //Create the Digital Map objects.
       mapTileDownloadManager = new MapTileDownloadManager(this);
        MapType.updateMapTileUrl();
        map = new RasterMap(1024, 1024, mapTileDownloadManager);
        map.setScreenSize(canvas.getWidth(),
                canvas.getHeight());
      mapTileDownloadManager.start();
        map.setMapDrawingListener(this);
      GeoLatLng center = new GeoLatLng(-31.948275, 115.857562);
        map.setCenter(center, 13, MapType.GOOGLEMAP);        Display.getDisplay(this).setCurrent(canvas);
    }

  

    public void pauseApp() {
    }

    public void destroyApp(boolean unconditional) {
        mapTileDownloadManager.stop();
    }

    public void readProgress(int downloaded, int total) {
        System.out.println(downloaded + "/" + total);
    }


    public void done() {
        if (canvas != null) {
            canvas.repaint();
        }
    }


    /**
     * Map canvas class, a subclass of Canvas.
     */
    protected class MapCanvas extends Canvas {

        private void panMap(float x, float y) {
            float dx = x - oldX;
            float dy = y - oldY;
            if (!(dx == 0 && dy == 0)) {
                map.panDirection((int) dx, (int) dy);
            }

        }
        boolean isPan = false;
        private float oldX = -1;
        private float oldY = -1;

      protected void paint(Graphics g) {
            map.paint(mapGraphics);
            g.drawImage((Image) mapImage.getNativeImage(), 0, 0, 0);
        }

        public void pointerDragged(int x, int y) {
            if (isPan) {
                panMap(x, y);
                oldX = x;
                oldY = y;
            }
        }

        public void pointerPressed(int x, int y) {
            oldX = x;
            oldY = y;
            isPan = true;
        }

        public void pointerReleased(int x, int y) {
            oldX = x;
            oldY = y;
            isPan = false;
        }
    }
}





1.        First is the setup the developer licence, the license information is consist of two part, one the license file (guidebee.lic), is normally put in the root directory. The other part is the license code corresponding to the license file.
2.        As said before, Guidebee Map API internally doesn’t call graphics related methods directly; it uses interfaces defined in Gis.Drawing package. Here’s how you hook up platform dependent implementation to Guidebee Map library. Here for instance on Java ME platform, class MIDPFont MIDPGraphicsMIDPGraphicsFactoryMIDPImage implement those interfaces.  You need to tell the Map API where to look for these classes. 
      MapLayer.setAbstractGraphicsFactory (MIDPGraphicsFactory.getInstance ()) is used to setup the platform dependent GraphicsFactory.
3.        Create an instance of MapTileDownloaderManager; this instance is used to manage all the worker thread. These work threads can download map tiles from server (online map), read map tile from local map file (offline map) or render vector map from vector map data (vector map). After the instance of MapTileDownloaderManager is created, an instance of RasterMap is created also.
RasterMap uses MapTileDownloaderManager to get map tile images to draw on the internal map canvas.
4.        MapTileDownloaderManager.Start starts all worker threads. And remember to stop the worker thread when application exit. Refer to step 6.
5.        Set the center of the map. Here is the latitude, longitude of Perth, Australia. The map type used here is GoogleMap. There are more than 20 different map types you can choose, and you can also define your own map type if needed. The map zoom level here is 13. The maximum zoom level is 17 and the minimum zoom level is 1.
6.        Stop all worker thread when application quits. Otherwise you may have hang threads preventing application exits.
7.        PanDirection(dx,dy) moves map , it’ll explained later.
8.        Display the map on screen. In this application, MapCanvas is used to show the map on screen. These two lines display map on screen.

9.        Asynchronized method is used when download map tiles from map server. i.e. There are worker threads which download map tiles in the background. In this way, the UI can keep responsive. The application can also monitor the download progress uses listener method readProgress, and when each map tile finish downloading, done() is called by the Map library, done is where you update your map on screen.
10.    This is optional. Map Servers like Google, Bing sometime update there map version. The URL may changes for these map server, if may get “image no available” exception if URL is not sync with latest map server. You can call updateMapTileUrl to get the newest URL from our server.






The examples in later chapter will not repeat common code, a base class MapDemoMIDP is used ,it has following definition.



public abstract class MapDemoMIDP extends MIDlet implements IReaderListener,
        IMapDrawingListener {

    protected RasterMap map;
    protected MapTileDownloadManager mapTileDownloadManager;
    protected IImage mapImage;
    protected IGraphics mapGraphics;
    protected MapCanvas canvas;

    public MapDemoMIDP() {
        try {
            LicenceManager licenceManager = LicenceManager.getInstance();
            long keys[]= {-0x8b9d5bd05f46354L,-0x4e41fd81b7d38cc3L,0x5c7addc8022e908aL,
            -0x532dae1d56b062b2L,0x3e18d8181cb217ecL,-0x39a3d8deb40bd92fL,};
            licenceManager.addLicence("GuidebeeMap_JavaME", keys);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

    }

    public void init() {
        canvas = new MapCanvas();
        //set the graphics factory
        MapLayer.setAbstractGraphicsFactory(MIDPGraphicsFactory.getInstance());
        mapImage = MapLayer.getAbstractGraphicsFactory().createImage(canvas.getWidth(),
                canvas.getHeight());
        mapGraphics = mapImage.getGraphics();
        //Create the Digital Map objects.
        mapTileDownloadManager = new MapTileDownloadManager(this);
        map = new RasterMap(1024, 1024, mapTileDownloadManager);
        map.setScreenSize(canvas.getWidth(),
                canvas.getHeight());
        mapTileDownloadManager.start();
        map.setMapDrawingListener(this);

    }

    public void pauseApp() {
    }

    public void destroyApp(boolean unconditional) {
        mapTileDownloadManager.stop();
    }

    public void readProgress(int downloaded, int total) {
        System.out.println(downloaded + "/" + total);
    }

    public void done() {
        if (canvas != null) {
            canvas.repaint();
        }
    }

    /**
     * Map canvas class, a subclass of Canvas.
     */
    protected class MapCanvas extends Canvas {

        private void panMap(float x, float y) {
            float dx = x - oldX;
            float dy = y - oldY;
            if (!(dx == 0 && dy == 0)) {
                map.panDirection((int) dx, (int) dy);
            }

        }
        boolean isPan = false;
        private float oldX = -1;
        private float oldY = -1;

        protected void paint(Graphics g) {
            map.paint(mapGraphics);
            g.drawImage((Image) mapImage.getNativeImage(), 0, 0, 0);
        }

        public void pointerDragged(int x, int y) {
            if (isPan) {
                panMap(x, y);
                oldX = x;
                oldY = y;
            }
        }

        public void pointerPressed(int x, int y) {
            oldX = x;
            oldY = y;
            isPan = true;
        }

        public void pointerReleased(int x, int y) {
            oldX = x;
            oldY = y;
            isPan = false;
        }
    }
}







No comments:

Post a Comment